#pragma once
class _String_val //字符串存储,16字节或者大于16字节的堆指针, // base class for basic_string to hold data
{
public:
enum
{ // length of internal buffer, [1, 16],15个字符+\0
_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 */
_