// string standard header #if _MSC_VER > 1000 #pragma once #endif #ifndef _GPSTRING_STD_ #define _GPSTRING_STD_ #include #include #ifdef _MSC_VER #pragma pack(push,4) #endif /* _MSC_VER */ #include _STD_BEGIN #define GPSTRING_TRACKING 0 // $ define to 1 to track gpstrings and allow dumping #define GPSTRING_LOG_DELETES 0 // $ define to 1 to track deletions of gpstrings (requires GPSTRING_TRACKING) #if GPSTRING_LOG_DELETES #include #endif // GPSTRING_LOG_DELETES #pragma pack ( push, 1 ) struct StringHeader { size_t m_Length; size_t m_Reserve; unsigned short m_RefCount; }; #pragma pack ( pop ) #if GPSTRING_TRACKING struct TrackingStringHeaderBase { # if GPSTRING_LOG_DELETES template struct OwnedList : std::list { ~OwnedList( void ) { clear(); } void clear( void ) { for ( iterator i = begin() ; i != end() ; ++i ) { delete [] ( *i ); } std::list ::clear(); } }; typedef OwnedList StringAColl; typedef OwnedList StringWColl; static StringAColl& GetRetiredStringsA( void ); static StringWColl& GetRetiredStringsW( void ); static void RetireString( const char * str ); static void RetireString( const wchar_t* str ); # endif // GPSTRING_LOG_DELETES static void Lock ( void ); static void Unlock( void ); }; template struct TrackingStringHeader : T, TrackingStringHeaderBase { typedef TrackingStringHeader ThisType; TrackingStringHeader( void ) { m_Next = m_Prev = this; } const CHAR* c_str( void ) const { return ( (CHAR*)(this + 1) ); } static ThisType& GetRoot( void ) { static ThisType s_Root; return ( s_Root ); } void Link( void ) { Lock(); m_Next = GetRoot().m_Next; m_Prev = &GetRoot(); m_Next->m_Prev = this; m_Prev->m_Next = this; Unlock(); } void Unlink( bool ansi ) { Lock(); m_Next->m_Prev = m_Prev; m_Prev->m_Next = m_Next; Unlock(); # if GPSTRING_LOG_DELETES if ( m_RefCount == 1 ) { RetireString( c_str() ); } # else // GPSTRING_LOG_DELETES UNREFERENCED_PARAMETER( ansi ); # endif // GPSTRING_LOG_DELETES } ThisType* m_Next; ThisType* m_Prev; }; #endif // GPSTRING_TRACKING // TEMPLATE CLASS gp_basic_string template, class _A = allocator<_E> > class gp_basic_string : private _A { public: #if GPSTRING_TRACKING typedef TrackingStringHeader Header; #else // GPSTRING_TRACKING typedef StringHeader Header; #endif // GPSTRING_TRACKING typedef gp_basic_string<_E, _Tr, _A> _Myt; typedef _A::size_type size_type; typedef _A::difference_type difference_type; typedef _A::pointer pointer; typedef _A::const_pointer const_pointer; typedef _A::reference reference; typedef _A::const_reference const_reference; typedef _A::value_type value_type; typedef _A::pointer iterator; typedef _A::const_pointer const_iterator; typedef reverse_iterator const_reverse_iterator; typedef reverse_iterator reverse_iterator; explicit gp_basic_string(const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; } gp_basic_string(const _Myt& _X) : _A(_X) {_Ptr = 0; assign(_X, 0, npos); } gp_basic_string(const _Myt& _X, size_type _P, size_type _M, const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; assign(_X, _P, _M); } gp_basic_string(const _E *_S, size_type _N, const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; assign(_S, _N); } gp_basic_string(const _E *_S, const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; assign(_S); } gp_basic_string(size_type _N, _E _C, const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; assign(_N, _C); } typedef const_iterator _It; gp_basic_string(_It _F, _It _L, const _A& _Al = _A()) : _A(_Al) {_Ptr = 0; assign(_F, _L); } ~gp_basic_string() {_Tidy(); } typedef _Tr traits_type; typedef _A allocator_type; enum _Mref {_FROZEN = 65535}; enum { HEADER_SIZE_ELEMENTS = (sizeof( Header ) / sizeof( _E )) + ((sizeof( Header ) % sizeof( _E )) ? 1 : 0) }; static const size_type npos; _Myt& operator=(const _Myt& _X) {return (assign(_X)); } _Myt& operator=(const _E *_S) {return (assign(_S)); } _Myt& operator=(_E _C) {return (assign(1, _C)); } _Myt& operator+=(const _Myt& _X) {return (append(_X)); } _Myt& operator+=(const _E *_S) {return (append(_S)); } _Myt& operator+=(_E _C) {return (append(1, _C)); } _Myt& append(const _Myt& _X) {return (append(_X, 0, npos)); } _Myt& append(const _Myt& _X, size_type _P, size_type _M) {gpassert(!(_X.size() < _P)); size_type _N = _X.size() - _P; if (_N < _M) _M = _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::copy(_Ptr + length(), &_X.c_str()[_P], _M); _Eos(_N); } return (*this); } _Myt& append(const _E *_S, size_type _M) {size_type _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::copy(_Ptr + length(), _S, _M); _Eos(_N); } return (*this); } _Myt& append(const _E *_S) {return (append(_S, _Tr::length(_S))); } _Myt& append(size_type _M, _E _C) {size_type _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::assign(_Ptr + length(), _M, _C); _Eos(_N); } return (*this); } _Myt& append(_It _F, _It _L) {return (replace(end_split(), end_split(), _F, _L)); } _Myt& assign(const _Myt& _X) {return (assign(_X, 0, npos)); } _Myt& assign( const _Myt& _X, size_type _P, size_type _M ) { gpassert( !(_X.size() < _P) ); size_type _N = _X.size() - _P; if ( _M < _N ) { _N = _M; } if ( this == &_X ) { erase( _P + _N ); erase( 0, _P ); } else if ( (_N > 0) && (_N == _X.size()) && (_Refcnt(_X.c_str()) < _FROZEN - 1) && (get_allocator() == _X.get_allocator()) ) { _Tidy(); _Ptr = _X._Ptr; ++_Refcnt(_Ptr); } else if ( _Grow( _N, true ) ) { _Tr::copy(_Ptr, &_X.c_str()[_P], _N); _Eos(_N); } return ( *this ); } _Myt& assign(const _E *_S, size_type _N) {if (_Grow(_N, true)) {_Tr::copy(_Ptr, _S, _N); _Eos(_N); } return (*this); } _Myt& assign(const _E *_S) {return (assign(_S, _Tr::length(_S))); } _Myt& assign(size_type _N, _E _C) {if (_Grow(_N, true)) {_Tr::assign(_Ptr, _N, _C); _Eos(_N); } return (*this); } _Myt& assign(_It _F, _It _L) {return (replace(begin_split(), end_split(), _F, _L)); } _Myt& insert(size_type _P0, const _Myt& _X) {return (insert(_P0, _X, 0, npos)); } _Myt& insert(size_type _P0, const _Myt& _X, size_type _P, size_type _M) {gpassert(!(length() < _P0 || _X.size() < _P)); size_type _N = _X.size() - _P; if (_N < _M) _M = _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, length() - _P0); _Tr::copy(_Ptr + _P0, &_X.c_str()[_P], _M); _Eos(_N); } return (*this); } _Myt& insert(size_type _P0, const _E *_S, size_type _M) {gpassert(!(length() < _P0)); size_type _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, length() - _P0); _Tr::copy(_Ptr + _P0, _S, _M); _Eos(_N); } return (*this); } _Myt& insert(size_type _P0, const _E *_S) {return (insert(_P0, _S, _Tr::length(_S))); } _Myt& insert(size_type _P0, size_type _M, _E _C) {gpassert(!(length() < _P0)); size_type _N; if (0 < _M && _Grow(_N = length() + _M)) {_Tr::move(_Ptr + _P0 + _M, _Ptr + _P0, length() - _P0); _Tr::assign(_Ptr + _P0, _M, _C); _Eos(_N); } return (*this); } iterator insert(iterator _P, _E _C) {size_type _P0 = _Pdif(_P, begin_split()); insert(_P0, 1, _C); return (begin_split() + _P0); } void insert(iterator _P, size_type _M, _E _C) {size_type _P0 = _Pdif(_P, begin_split()); insert(_P0, _M, _C); } void insert(iterator _P, _It _F, _It _L) {replace(_P, _P, _F, _L); } _Myt& erase(size_type _P0 = 0, size_type _M = npos) {gpassert(!(length() < _P0)); _Split(); if (length() - _P0 < _M) _M = length() - _P0; if (0 < _M) {_Tr::move(_Ptr + _P0, _Ptr + _P0 + _M, length() - _P0 - _M); size_type _N = length() - _M; if (_Grow(_N)) _Eos(_N); } return (*this); } iterator erase(iterator _P) {size_t _M = _Pdif(_P, begin_split()); erase(_M, 1); return (_Psum(_Ptr, _M)); } iterator erase(iterator _F, iterator _L) {size_t _M = _Pdif(_F, begin_split()); erase(_M, _Pdif(_L, _F)); return (_Psum(_Ptr, _M)); } _Myt& replace(size_type _P0, size_type _N0, const _Myt& _X) {return (replace(_P0, _N0, _X, 0, npos)); } _Myt& replace(size_type _P0, size_type _N0, const _Myt& _X, size_type _P, size_type _M) {gpassert(!(length() < _P0 || _X.size() < _P)); if (length() - _P0 < _N0) _N0 = length() - _P0; size_type _N = _X.size() - _P; if (_N < _M) _M = _N; _Split(); size_type _Nm = length() - _N0 - _P0; if (_M < _N0) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); if ((0 < _M || 0 < _N0) && _Grow(_N = length() + _M - _N0)) {if (_N0 < _M) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); _Tr::copy(_Ptr + _P0, &_X.c_str()[_P], _M); _Eos(_N); } return (*this); } _Myt& replace(size_type _P0, size_type _N0, const _E *_S, size_type _M) {gpassert(!(length() < _P0)); if (length() - _P0 < _N0) _N0 = length() - _P0; _Split(); size_type _Nm = length() - _N0 - _P0; if (_M < _N0) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); size_type _N; if ((0 < _M || 0 < _N0) && _Grow(_N = length() + _M - _N0)) {if (_N0 < _M) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); _Tr::copy(_Ptr + _P0, _S, _M); _Eos(_N); } return (*this); } _Myt& replace(size_type _P0, size_type _N0, const _E *_S) {return (replace(_P0, _N0, _S, _Tr::length(_S))); } _Myt& replace(size_type _P0, size_type _N0, size_type _M, _E _C) {gpassert(!(length() < _P0)); if (length() - _P0 < _N0) _N0 = length() - _P0; _Split(); size_type _Nm = length() - _N0 - _P0; if (_M < _N0) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); size_type _N; if ((0 < _M || 0 < _N0) && _Grow(_N = length() + _M - _N0)) {if (_N0 < _M) _Tr::move(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm); _Tr::assign(_Ptr + _P0, _M, _C); _Eos(_N); } return (*this); } _Myt& replace(iterator _F, iterator _L, const _Myt& _X) {return (replace( _Pdif(_F, begin_split()), _Pdif(_L, _F), _X)); } _Myt& replace(iterator _F, iterator _L, const _E *_S, size_type _M) {return (replace( _Pdif(_F, begin_split()), _Pdif(_L, _F), _S, _M)); } _Myt& replace(iterator _F, iterator _L, const _E *_S) {return (replace( _Pdif(_F, begin_split()), _Pdif(_L, _F), _S)); } _Myt& replace(iterator _F, iterator _L, size_type _M, _E _C) {return (replace( _Pdif(_F, begin_split()), _Pdif(_L, _F), _M, _C)); } _Myt& replace(iterator _F1, iterator _L1, _It _F2, _It _L2) {size_type _P0 = _Pdif(_F1, begin_split()); size_type _M = 0; _Distance(_F2, _L2, _M); replace(_P0, _Pdif(_L1, _F1), _M, _E(0)); for (_F1 = begin_split() + _P0; 0 < _M; ++_F1, ++_F2, --_M) *_F1 = *_F2; return (*this); } iterator begin_freeze() {_Freeze(); return (_Ptr); } iterator begin_split() {_Split(); return (_Ptr); } const_iterator begin() const {return (_Ptr); } iterator end_freeze() {_Freeze(); return ((iterator)_Psum(_Ptr, length())); } iterator end_split() {_Split(); return ((iterator)_Psum(_Ptr, length())); } const_iterator end() const {return ((const_iterator)_Psum(_Ptr, length())); } reverse_iterator rbegin_freeze() {return (reverse_iterator(end_freeze())); } reverse_iterator rbegin_split() {return (reverse_iterator(end_split())); } const_reverse_iterator rbegin() const {return (const_reverse_iterator(end())); } reverse_iterator rend_freeze() {return (reverse_iterator(begin_freeze())); } reverse_iterator rend_split() {return (reverse_iterator(begin_split())); } const_reverse_iterator rend() const {return (const_reverse_iterator(begin())); } reference at(size_type _P0) {gpassert(!(length() <= _P0)); _Freeze(); return (_Ptr[_P0]); } const_reference at(size_type _P0) const {gpassert(!(length() <= _P0)); return (_Ptr[_P0]); } reference operator[](size_type _P0) {if (length() < _P0 || _Ptr == 0) return ((reference)*_Nullstr()); _Freeze(); return (_Ptr[_P0]); } const_reference operator[](size_type _P0) const {if (_Ptr == 0) return (*_Nullstr()); else return (_Ptr[_P0]); } const _E *c_str() const {return (_Ptr == 0 ? _Nullstr() : _Ptr); } const _E *data() const {return (c_str()); } size_type length() const {return (_Ptr?(((Header*)_Ptr)[-1].m_Length):0); } size_type size() const {return (length()); } void resize(size_type _N, _E _C) {_N <= length() ? erase(_N) : append(_N - length(), _C); } void resize(size_type _N) {_N <= length() ? erase(_N) : append(_N - length(), _E(0)); } size_type capacity() const {return (_Ptr?(((Header*)_Ptr)[-1].m_Reserve):0); } void reserve(size_type _N = 0) {if (capacity() < _N) _Grow(_N); } bool empty() const {return (length() == 0); } size_type copy(_E *_S, size_type _N, size_type _P0 = 0) const {gpassert(!(length() < _P0)); if (length() - _P0 < _N) _N = length() - _P0; if (0 < _N) _Tr::copy(_S, _Ptr + _P0, _N); return (_N); } void swap(_Myt& _X) {if (get_allocator() == _X.get_allocator()) {std::swap(_Ptr, _X._Ptr); } else {_Myt _Ts = *this; *this = _X, _X = _Ts; }} friend void swap(_Myt& _X, _Myt& _Y) {_X.swap(_Y); } size_type find(const _Myt& _X, size_type _P = 0) const {return (find(_X.c_str(), _P, _X.size())); } size_type find(const _E *_S, size_type _P, size_type _N) const {if (_N == 0 && _P <= length()) return (_P); size_type _Nm; if (_P < length() && _N <= (_Nm = length() - _P)) {const _E *_U, *_V; for (_Nm -= _N - 1, _V = _Ptr + _P; (_U = _Tr::find(_V, _Nm, *_S)) != 0; _Nm -= _U - _V + 1, _V = _U + 1) if (_Tr::compare(_U, _S, _N) == 0) return (_U - _Ptr); } return (npos); } size_type find(const _E *_S, size_type _P = 0) const {return (find(_S, _P, _Tr::length(_S))); } size_type find(_E _C, size_type _P = 0) const {return (find((const _E *)&_C, _P, 1)); } size_type rfind(const _Myt& _X, size_type _P = npos) const {return (rfind(_X.c_str(), _P, _X.size())); } size_type rfind(const _E *_S, size_type _P, size_type _N) const {if (_N == 0) return (_P < length() ? _P : length()); if (_N <= length()) for (const _E *_U = _Ptr + + (_P < length() - _N ? _P : length() - _N); ; --_U) if (_Tr::eq(*_U, *_S) && _Tr::compare(_U, _S, _N) == 0) return (_U - _Ptr); else if (_U == _Ptr) break; return (npos); } size_type rfind(const _E *_S, size_type _P = npos) const {return (rfind(_S, _P, _Tr::length(_S))); } size_type rfind(_E _C, size_type _P = npos) const {return (rfind((const _E *)&_C, _P, 1)); } size_type find_first_of(const _Myt& _X, size_type _P = 0) const {return (find_first_of(_X.c_str(), _P, _X.size())); } size_type find_first_of(const _E *_S, size_type _P, size_type _N) const {if (0 < _N && _P < length()) {const _E *const _V = _Ptr + length(); for (const _E *_U = _Ptr + _P; _U < _V; ++_U) if (_Tr::find(_S, _N, *_U) != 0) return (_U - _Ptr); } return (npos); } size_type find_first_of(const _E *_S, size_type _P = 0) const {return (find_first_of(_S, _P, _Tr::length(_S))); } size_type find_first_of(_E _C, size_type _P = 0) const {return (find((const _E *)&_C, _P, 1)); } size_type find_last_of(const _Myt& _X, size_type _P = npos) const {return (find_last_of(_X.c_str(), _P, _X.size())); } size_type find_last_of(const _E *_S, size_type _P, size_type _N) const {if (0 < _N && 0 < length()) for (const _E *_U = _Ptr + (_P < length() ? _P : length() - 1); ; --_U) if (_Tr::find(_S, _N, *_U) != 0) return (_U - _Ptr); else if (_U == _Ptr) break; return (npos); } size_type find_last_of(const _E *_S, size_type _P = npos) const {return (find_last_of(_S, _P, _Tr::length(_S))); } size_type find_last_of(_E _C, size_type _P = npos) const {return (rfind((const _E *)&_C, _P, 1)); } size_type find_first_not_of(const _Myt& _X, size_type _P = 0) const {return (find_first_not_of(_X.c_str(), _P, _X.size())); } size_type find_first_not_of(const _E *_S, size_type _P, size_type _N) const {if (_P < length()) {const _E *const _V = _Ptr + length(); for (const _E *_U = _Ptr + _P; _U < _V; ++_U) if (_Tr::find(_S, _N, *_U) == 0) return (_U - _Ptr); } return (npos); } size_type find_first_not_of(const _E *_S, size_type _P = 0) const {return (find_first_not_of(_S, _P, _Tr::length(_S))); } size_type find_first_not_of(_E _C, size_type _P = 0) const {return (find_first_not_of((const _E *)&_C, _P, 1)); } size_type find_last_not_of(const _Myt& _X, size_type _P = npos) const {return (find_last_not_of(_X.c_str(), _P, _X.size())); } size_type find_last_not_of(const _E *_S, size_type _P, size_type _N) const {if (0 < length()) for (const _E *_U = _Ptr + (_P < length() ? _P : length() - 1); ; --_U) if (_Tr::find(_S, _N, *_U) == 0) return (_U - _Ptr); else if (_U == _Ptr) break; return (npos); } size_type find_last_not_of(const _E *_S, size_type _P = npos) const {return (find_last_not_of(_S, _P, _Tr::length(_S))); } size_type find_last_not_of(_E _C, size_type _P = npos) const {return (find_last_not_of((const _E *)&_C, _P, 1)); } _Myt substr(size_type _P = 0, size_type _M = npos) const {return (_Myt(*this, _P, _M)); } int compare(const _Myt& _X) const {return (compare(0, length(), _X.c_str(), _X.size())); } int compare(size_type _P0, size_type _N0, const _Myt& _X) const {return (compare(_P0, _N0, _X, 0, npos)); } int compare(size_type _P0, size_type _N0, const _Myt& _X, size_type _P, size_type _M) const {gpassert(!(_X.size() < _P)); if (_X.length() - _P < _M) _M = _X.length() - _P; return (compare(_P0, _N0, _X.c_str() + _P, _M)); } int compare(const _E *_S) const {return (compare(0, length(), _S, _Tr::length(_S))); } int compare(size_type _P0, size_type _N0, const _E *_S) const {return (compare(_P0, _N0, _S, _Tr::length(_S))); } int compare(size_type _P0, size_type _N0, const _E *_S, size_type _M) const {gpassert(!(length() < _P0)); if (length() - _P0 < _N0) _N0 = length() - _P0; size_type _Ans = _Tr::compare(_Psum(_Ptr, _P0), _S, _N0 < _M ? _N0 : _M); return (_Ans != 0 ? _Ans : _N0 < _M ? -1 : _N0 == _M ? 0 : +1); } _A get_allocator() const {return (*this); } private: enum { _MIN_SIZE = 15 }; void _Copy( size_type _N ) { // $$ realloc opportunity if ( _N < _MIN_SIZE ) { _N = _MIN_SIZE; } Header* header = (Header*)allocate( _N + HEADER_SIZE_ELEMENTS + 1, 0 ); header->m_RefCount = 0; header->m_Reserve = _N; _E* _S = (_E*)(header + 1); size_t oldLen = length(); if ( oldLen > 0 ) { if ( oldLen > _N ) { oldLen = _N; } _Tr::copy( _S, _Ptr, oldLen ); } _Tidy(); _Ptr = _S; _Eos( oldLen ); # if GPSTRING_TRACKING header->Link(); # endif // GPSTRING_TRACKING } void _Eos( size_type _N ) { ((Header*)_Ptr)[ -1 ].m_Length = _N; _Tr::assign( _Ptr[ _N ], _E( 0 ) ); } void _Freeze() { if ( _Ptr ) { Header* header = (Header*)_Ptr - 1; if ( (header->m_RefCount != 0) && (header->m_RefCount != _FROZEN) ) { _Grow( header->m_Length ); } } if ( _Ptr ) { _Refcnt( _Ptr ) = _FROZEN; } } bool _Grow( size_type _N, bool _Trim = false ) { if ( _Ptr ) { Header* header = (Header*)_Ptr - 1; if ( (header->m_RefCount != 0) && (header->m_RefCount != _FROZEN) ) { if ( _N == 0 ) { --header->m_RefCount; _Ptr = 0; return ( false ); } else { _Copy( _N ); return ( true ); } } } if ( _N == 0 ) { if ( _Trim ) { _Tidy(); } else if ( _Ptr ) { _Eos( 0 ); } return ( false ); } size_type res = capacity(); if ( _Trim && ((res > _MIN_SIZE) || (res < _N)) ) { // $$ realloc opportunity _Tidy(); _Copy( _N ); } else if ( !_Trim && (res < _N) ) { _Copy( _N ); } return ( true ); } static const _E * __cdecl _Nullstr() {static const _E _C = _E(0); return (&_C); } static size_type _Pdif(const_pointer _P2, const_pointer _P1) {return (_P2 == 0 ? 0 : _P2 - _P1); } static const_pointer _Psum(const_pointer _P, size_type _N) {return (_P == 0 ? 0 : _P + _N); } static pointer _Psum(pointer _P, size_type _N) {return (_P == 0 ? 0 : _P + _N); } unsigned short& _Refcnt(const _E *_U) {return (((Header*)_U)[-1].m_RefCount); } protected: const Header& get_header( void ) const { gpassert( _Ptr != NULL ); return ( ((const Header*)_Ptr)[ -1 ] ); } Header& get_header( void ) { gpassert( _Ptr != NULL ); return ( ((Header*)_Ptr)[ -1 ] ); } int get_ref_count( void ) const { if ( _Ptr == NULL ) { return ( 0 ); } unsigned short refCount = ((Header*)_Ptr)[ -1 ].m_RefCount; return ( (refCount == _FROZEN) ? 1 : (refCount + 1) ); } void _Split() { if ( _Ptr ) { Header* header = (Header*)_Ptr - 1; if ( (header->m_RefCount != 0) && (header->m_RefCount != _FROZEN) ) { _E *_Temp = _Ptr; _Tidy(); assign( _Temp ); } } } void _Tidy() { if ( _Ptr ) { Header* header = (Header*)_Ptr - 1; if ( (header->m_RefCount == 0) || (header->m_RefCount == _FROZEN) ) { # if GPSTRING_TRACKING header->Unlink( sizeof( _E ) == 1 ); # endif // GPSTRING_TRACKING deallocate( header, header->m_Reserve + HEADER_SIZE_ELEMENTS + 1 ); } else { --header->m_RefCount; } _Ptr = 0; } } private: _E *_Ptr; }; template const gp_basic_string<_E, _Tr, _A>::size_type gp_basic_string<_E, _Tr, _A>::npos = (size_type)-1; // gp_basic_string TEMPLATE OPERATORS template inline gp_basic_string<_E, _Tr, _A> __cdecl operator+( const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (gp_basic_string<_E, _Tr, _A>(_L) += _R); } template inline gp_basic_string<_E, _Tr, _A> __cdecl operator+(const _E *_L, const gp_basic_string<_E, _Tr, _A>& _R) {return (gp_basic_string<_E, _Tr, _A>(_L) += _R); } template inline gp_basic_string<_E, _Tr, _A> __cdecl operator+( const _E _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (gp_basic_string<_E, _Tr, _A>(1, _L) += _R); } template inline gp_basic_string<_E, _Tr, _A> __cdecl operator+( const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (gp_basic_string<_E, _Tr, _A>(_L) += _R); } template inline gp_basic_string<_E, _Tr, _A> __cdecl operator+( const gp_basic_string<_E, _Tr, _A>& _L, const _E _R) {return (gp_basic_string<_E, _Tr, _A>(_L) += _R); } template inline bool __cdecl operator==(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_L.compare(_R) == 0); } template inline bool __cdecl operator==(const _E * _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_R.compare(_L) == 0); } template inline bool __cdecl operator==(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (_L.compare(_R) == 0); } template inline bool __cdecl operator!=(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_L == _R)); } template inline bool __cdecl operator!=(const _E *_L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_L == _R)); } template inline bool __cdecl operator!=(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (!(_L == _R)); } template inline bool __cdecl operator<(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_L.compare(_R) < 0); } template inline bool __cdecl operator<(const _E * _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_R.compare(_L) > 0); } template inline bool __cdecl operator<(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (_L.compare(_R) < 0); } template inline bool __cdecl operator>(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_R < _L); } template inline bool __cdecl operator>(const _E * _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (_R < _L); } template inline bool __cdecl operator>(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (_R < _L); } template inline bool __cdecl operator<=(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_R < _L)); } template inline bool __cdecl operator<=(const _E * _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_R < _L)); } template inline bool __cdecl operator<=(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (!(_R < _L)); } template inline bool __cdecl operator>=(const gp_basic_string<_E, _Tr, _A>& _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_L < _R)); } template inline bool __cdecl operator>=(const _E * _L, const gp_basic_string<_E, _Tr, _A>& _R) {return (!(_L < _R)); } template inline bool __cdecl operator>=(const gp_basic_string<_E, _Tr, _A>& _L, const _E *_R) {return (!(_L < _R)); } // gp_basic_string INSERTERS AND EXTRACTORS template inline basic_istream<_E, _Tr>& __cdecl operator>>( basic_istream<_E, _Tr>& _I, gp_basic_string<_E, _Tr, _A>& _X) {typedef ctype<_E> _Ctype; typedef basic_istream<_E, _Tr> _Myis; ios_base::iostate _St = ios_base::goodbit; bool _Chg = false; _X.erase(); const _Myis::sentry _Ok(_I); if (_Ok) {const _Ctype& _Fac = _USE(_I.getloc(), _Ctype); _TRY_IO_BEGIN _A::size_type _N = 0 < _I.width() ? _I.width() : _X.max_size(); _Tr::int_type _C = _I.rdbuf()->sgetc(); for (; 0 < --_N; _C = _I.rdbuf()->snextc()) if(_Tr::eq_int_type(_Tr::eof(), _C)) {_St |= ios_base::eofbit; break; } else if (_Fac.is(_Ctype::space, _Tr::to_char_type(_C))) break; else {_X.append(1, _Tr::to_char_type(_C)); _Chg = true; } _CATCH_IO_(_I); } _I.width(0); if (!_Chg) _St |= ios_base::failbit; _I.setstate(_St); return (_I); } template inline basic_istream<_E, _Tr>& __cdecl getline(basic_istream<_E, _Tr>& _I, gp_basic_string<_E, _Tr, _A>& _X) {return (getline(_I, _X, _I.widen('\n'))); } template inline basic_istream<_E, _Tr>& __cdecl getline(basic_istream<_E, _Tr>& _I, gp_basic_string<_E, _Tr, _A>& _X, const _E _D) {typedef basic_istream<_E, _Tr> _Myis; ios_base::iostate _St = ios_base::goodbit; bool _Chg = false; _X.erase(); const _Myis::sentry _Ok(_I, true); if (_Ok) {_TRY_IO_BEGIN _Tr::int_type _C = _I.rdbuf()->sgetc(); for (; ; _C = _I.rdbuf()->snextc()) if (_Tr::eq_int_type(_Tr::eof(), _C)) {_St |= ios_base::eofbit; break; } else if (_Tr::eq((_E)_C, _D)) {_Chg = true; _I.rdbuf()->sbumpc(); break; } else _X += _Tr::to_char_type(_C), _Chg = true; _CATCH_IO_(_I); } if (!_Chg) _St |= ios_base::failbit; _I.setstate(_St); return (_I); } template inline basic_ostream<_E, _Tr>& __cdecl operator<<( basic_ostream<_E, _Tr>& _O, const gp_basic_string<_E, _Tr, _A>& _X) { _O << _X.c_str(); return (_O); } typedef gp_basic_string, allocator > gp_string; typedef gp_basic_string, allocator > gp_wstring; _STD_END #ifdef _MSC_VER #pragma pack(pop) #endif /* _MSC_VER */ #endif /* _GPSTRING_STD_ */ /* * Copyright (c) 1995 by P.J. Plauger. ALL RIGHTS RESERVED. * Consult your license regarding permissions and restrictions. */