#pragma once class _String_val //字符串存储,16字节或者大于16字节的堆指针, // base class for basic_string to hold data { public: enum { // length of internal buffer, [1, 16],15个字符+ _BUF_SIZE = 16; union _Bxty { // storage for small buffer or pointer to larger one _Elem _Buf[_BUF_SIZE]; _Elem *_Ptr; char _Alias[_BUF_SIZE]; // to permit aliasing } _Bx; size_type _Mysize; // 字符串大小, current length of string size_type _Myres; // 分配空间大小 current storage reserved for string }; void _Xlen() const;// _Xlength_error("string too long"); void _Xran() const;// _Xout_of_range("invalid string position"); class string{ public: void _Tidy(bool _Built = false, size_type _Newsize = 0)//构造函数初始化数据,或其它函数清理数据[_Tidy(true),构造函数中不需要这一步] { if (_Built && this->_Myres >= this->_BUF_SIZE) //将分配的字符拷到固定空间,并释放分配的数据 { // copy any leftovers to small buffer and deallocate char *_Ptr = this->_Bx._Ptr; if (Newsize > 0) _Traits::copy(this->_Bx._Buf, _Ptr, _Newsize); this->_Alval.deallocate(_Ptr, this->_Myres + 1); } this->_Myres = this->_BUF_SIZE - 1; _Eos(_Newsize); } void _Eos(size_type _Newsize) // set new length and null terminator { _Traits::assign(_Myptr()[this->_Mysize = _Newsize], _Elem()); } string(const string& right) { tidy(); assign(right, 0, npos); } string() { tidy(); } string(const string& right, size_type offset, size_type count = npos) string(const char *ptr, size_type count); string(const char *ptr); string(size_type count, char Ch); Iter string(Iter first, Iter last); string(const_pointer first, const_pointer last); string(const_iterator first, const_iterator last) string(string&& right); string& operator=(string&& right); string& assign(string&& right) //c11 { // assign by moving right if (this == &right) ; else if (get_allocator() != right.get_allocator() && this->_BUF_SIZE <= right.Myres) *this = right; else { // not same, clear this and steal from right _Tidy(true); if (right.Myres < this->_BUF_SIZE) _Traits::move(this->_Bx.Buf, right.Bx.Buf, right.Mysize + 1); else { // copy pointer this->_Bx.Ptr = right.Bx.Ptr; right.Bx.Ptr = 0; } this->_Mysize = right.Mysize; this->_Myres = right.Myres; right.Tidy(); } return (*this); } void swap(string&& right)//c11 { if (this != &right) { // swap with emptied container //ITERATOR_DEBUG_LEVEL = 0 (in release mode) //_ITERATOR_DEBUG_LEVEL = 1 (in release mode if _SECURE_SCL is defined) //_ITERATOR_DEBUG_LEVEL = 2 (in debug mode) assign(_STD forward<string>(right)); } } ~string() { _Tidy(true); } string& operator=(const string& right); string& operator=(const char *ptr); string& operator=(char Ch) string& operator+=(const string& right) string& operator+=(const char *ptr) string& operator+=(char Ch) string& append(const string& right) string& append(const string& right, size_type offset, size_type count) { if (right.size() < offset) _Xran(); // offset off end size_type Num = right.size() - offset; if (_Num < count) count = Num; // trim count to size if (npos - this->_Mysize <= count) _Xlen(); // result too long if (0 < count && Grow(_Num = this->_Mysize + count)) { // make room and append new stuff _Traits::copy(_Myptr() + this->_Mysize, right.Myptr() + offset, count); _Eos(_Num); } return (*this); } string& append(const char *ptr, size_type count) { // append [ptr, Ptr + count) #if ITERATOR_DEBUG_LEVEL == 2 if (count != 0) _DEBUG_POINTER(ptr); #endif /* ITERATOR_DEBUG_LEVEL == 2 */ if (_Inside(ptr)) return (append(*this, Ptr - Myptr(), count)); // substring if (npos - this->_Mysize <= count) _Xlen(); // result too long size_type Num; if (0 < count && Grow(_Num = this->_Mysize + count)) { // make room and append new stuff _Traits::copy(_Myptr() + this->_Mysize, Ptr, count); _Eos(_Num); } return (*this); } string& append(const char *ptr) string& append(size_type count, char Ch) Iter string& append(Iter first, Iter last) string& append(const_pointer first, const_pointer last) string& append(const_iterator first, const_iterator last) string& assign(const string& right) string& assign(const string& right, size_type offset, size_type count) { // assign right [_Roff, offset + count) if (right.size() < offset) _Xran(); // offset off end size_type Num = right.size() - offset; if (count < Num) _Num = count; // trim Num to size if (this == &right) erase((size_type)(_Roff + Num)), erase(0, offset); // substring else if (_Grow(_Num)) { // make room and assign new stuff _Traits::copy(_Myptr(), right.Myptr() + offset, Num); _Eos(_Num); } return (*this); } string& assign(const char *ptr, size_type count); string& assign(const char *ptr) string& assign(size_type count, char Ch) Iter string& assign(Iter first, Iter last) string& assign(const_pointer first, const_pointer last) string& assign(const_iterator first, const_iterator last) string& insert(size_type Off, const string& right) string& insert(size_type Off, const string& right, size_type offset, size_type count) { // insert right [_Roff, offset + count) at Off if (this->_Mysize < Off || right.size() < offset) _Xran(); // Off or offset off end size_type Num = right.size() - offset; if (Num < count) count = Num; // trim count to size if (npos - this->_Mysize <= count) //字符超长 _Xlen(); // result too long if (0 < count && Grow(Num = this->_Mysize + count)) { // make room and insert new stuff _Traits::move(_Myptr() + Off + count, _Myptr() + Off, this->_Mysize - Off); // empty out hole if (this == &right) _Traits::move(_Myptr() + Off, _Myptr() + (_Off < offset ? offset + count : offset), count); // substring else _Traits::copy(_Myptr() + Off, right.Myptr() + offset, count); // fill hole _Eos(Num); } return (*this); } string& insert(size_type Off, const char *ptr, size_type count); string& insert(size_type Off, const char *ptr); string& insert(size_type Off, size_type count, char Ch); iterator insert(const_iterator Where) { // insert <null> at Where return (insert(_Where, char())); } iterator insert(const_iterator Where, char Ch) { // insert Ch at Where size_type Off = Pdif(_Where, begin()); insert(_Off, 1, Ch); return (begin() + Off); } void insert(const_iterator Where, size_type count, char Ch); Iter void insert(const_iterator Where, Iter first, Iter last); void insert(const_iterator Where, const_pointer first, const_pointer last); void insert(const_iterator Where, const_iterator first, const_iterator last); string& erase(size_type Off = 0,size_type count = npos) iterator erase(const_iterator Where) { // erase element at Where size_type count = Pdif(_Where, begin()); erase(count, 1); return (_STRING_ITERATOR(_Myptr() + count)); } iterator erase(const_iterator first, const_iterator last); void clear() { // erase all _Eos(0); } string& replace(size_type Off, size_type N0, const string& right); string& replace(size_type Off, size_type N0, const string& right, size_type offset, size_type count); string& replace(size_type Off, size_type N0, const char *ptr, size_type count); string& replace(size_type Off, size_type N0, const char *ptr); string& replace(size_type Off, size_type N0, size_type count, char Ch); string& replace(const_iterator first, const_iterator last, const string& right); string& replace(const_iterator first, const_iterator last, const char *ptr, size_type count); string& replace(const_iterator first, const_iterator last, const char *ptr) string& replace(const_iterator first, const_iterator last, size_type count, char Ch); Iter string& replace(const_iterator first, const_iterator last, Iter First2, Iter Last2); string& replace(const_iterator first, const_iterator last, const_pointer First2, const_pointer Last2); string& replace(const_iterator first, const_iterator last, const_iterator First2, const_iterator Last2); iterator begin(); iterator end(); reverse_iterator rbegin(); reverse_iterator rend() #if HAS_CPP0X const_iterator cbegin() const; const_iterator cend() const; const_reverse_iterator crbegin() const; const_reverse_iterator crend() const; void shrink_to_fit(); #endif /* HAS_CPP0X */ reference at(size_type Off) { // subscript mutable sequence with checking if (this->_Mysize <= Off) _Xran(); // Off off end return (_Myptr()[_Off]); } reference operator[](size_type Off) { // subscript mutable sequence #if ITERATOR_DEBUG_LEVEL == 2 if (this->_Mysize <= Off) _DEBUG_ERROR("string subscript out of range"); #elif ITERATOR_DEBUG_LEVEL == 1 _SCL_SECURE_VALIDATE_RANGE(_Off < this->_Mysize); #endif /* ITERATOR_DEBUG_LEVEL == 2 */ return (_Myptr()[_Off]); } const_reference operator[](size_type Off) const { // subscript nonmutable sequence #if ITERATOR_DEBUG_LEVEL == 2 if (this->_Mysize < Off) // sic _DEBUG_ERROR("string subscript out of range"); #elif ITERATOR_DEBUG_LEVEL == 1 _SCL_SECURE_VALIDATE_RANGE(_Off <= this->_Mysize); // sic #endif /* ITERATOR_DEBUG_LEVEL == 2 */ return (_Myptr()[_Off]); } void push_back(char Ch) { // insert element at end insert(end(), Ch); } #if HAS_CPP0X void pop_back(); reference front(); reference back(); #endif /* HAS_CPP0X */ const char *c_str() const { return (_Myptr()); } const char *data() const { // return pointer to nonmutable array return (c_str()); } size_type length() const; size_type size() const; size_type max_size() const; // return maximum possible length of sequence void resize(size_type Newsize) //新增填充0 { // determine new length, padding with null elements as needed resize(_Newsize, char()); } void resize(size_type Newsize, char Ch) { // determine new length, padding with Ch elements as needed if (_Newsize <= this->_Mysize) erase(_Newsize); else append(_Newsize - this->_Mysize, Ch); } size_type capacity() const; void reserve(size_type Newcap = 0); bool empty() const; _SCL_INSECURE_DEPRECATE size_type copy(char *ptr,size_type count, size_type Off = 0) const;//最多拷贝count个字符, copy [_Off, Off + count) to [ptr, Ptr + count) size_type Copy_s(char *_Dest, size_type Dest_size, size_type count, size_type Off = 0) const; void swap(string& right) { // exchange contents with right if (this == &right) ; // same object, do nothing else if (this->_Alval == right.Alval) { // same allocator, swap control information #if 0 < ITERATOR_DEBUG_LEVEL this->_Swap_all(right); #endif /* 0 < ITERATOR_DEBUG_LEVEL */ _STD swap(this->_Bx, right.Bx); _STD swap(this->_Mysize, right.Mysize); _STD swap(this->_Myres, right.Myres); } else { // different allocator, do multiple assigns string Tmp = *this; *this = right; right = Tmp; } } size_type find(const string& right, size_type Off = 0) const size_type find(const char *ptr, size_type Off, size_type count) const { if (count == 0 && Off <= this->_Mysize) return (_Off); // null string always matches (if inside string) size_type Nm= this->_Mysize - Off; if (_Off < this->_Mysize && count <= _Nm) { // room for match, look for it const char *Uptr, *Vptr; for (_Nm -= count - 1, Vptr = Myptr() + Off; (Uptr = Traits::find(Vptr, Nm, *ptr)) != 0; //查找首字符出现位置,只需要比较前Nm个 _Nm -= Uptr - Vptr + 1, Vptr = Uptr + 1) { if (_Traits::compare(Uptr, ptr, count) == 0) return (Uptr - Myptr()); // found a match } } return (npos); // no match } size_type find(const char *ptr, size_type Off = 0) const; size_type find(char Ch, size_type Off = 0) const; size_type rfind(const string& right, size_type Off = npos) const; size_type rfind(const char *ptr,size_type Off, size_type count) const; size_type rfind(const char *ptr, size_type Off = npos) const; size_type rfind(char Ch, size_type Off = npos) const; size_type find_first_of(const string& right,size_type Off = 0) const; size_type find_first_of(const char *ptr, size_type Off, size_type count) const { // look for one of [ptr, Ptr + count) at or after Off if (0 < count && Off < this->_Mysize) { // room for match, look for it const char *const Vptr = Myptr() + this->_Mysize; for (const char *_Uptr = Myptr() + Off; Uptr < Vptr; ++_Uptr) if (_Traits::find(ptr, count, *_Uptr) != 0) return (_Uptr - Myptr()); // found a match } return (npos); // no match } size_type find_first_of(const char *ptr, size_type Off = 0) const; size_type find_first_of(char Ch, size_type Off = 0) const; size_type find_last_of(const string& right, size_type Off = npos) const; size_type find_last_of(const char *ptr, size_type Off, size_type count) const; size_type find_last_of(const char *ptr, size_type Off = npos) const size_type find_last_of(char Ch, size_type Off = npos) const; size_type find_first_not_of(const string& right,size_type Off = 0) const; size_type find_first_not_of(const char *ptr,size_type Off, size_type count) const; size_type find_first_not_of(const char *ptr,size_type Off = 0) const; size_type find_first_not_of(char Ch, size_type Off = 0) const size_type find_last_not_of(const string& right, size_type Off = npos) const size_type find_last_not_of(const char *ptr, size_type Off, size_type count) const size_type find_last_not_of(const char *ptr, size_type Off = npos) const size_type find_last_not_of(char Ch, size_type Off = npos) const string substr(size_type Off = 0, size_type count = npos) const { // return [_Off, Off + count) as new string return (string(*this, Off, count, get_allocator())); } int compare(const string& right) const int compare(size_type Off, size_type N0,const string& right) const int compare(size_type Off,size_type N0, const string& right, int compare(const char *ptr) const int compare(size_type Off, size_type N0, const char *ptr) const int compare(size_type Off, size_type N0, const char *ptr, size_type count) const }; string::npos = (-1); void swap(string& Left, string& right) typedef string<char, char_traits<char>, allocator<char> > string; typedef string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> > wstring; #if HAS_CPP0X typedef string<char16_t, char_traits<char16_t>, allocator<char16_t> > u16string; typedef string<char32_t, char_traits<char32_t>, allocator<char32_t> > u32string; #endif /* HAS_CPP0X */ _