Listing 2 The template class basic_string

template<class _E,
   class _T = string_char_traits<_E>,
   class _A = _ALLOCATOR(_E)>
   class basic_string {
public:
   typedef basic_string(_E, _T, _A> _Myt;
   typedef _T traits_type;
   typedef _SIZ_TYPE(_E, _A)::size_type size_type;
   typedef _SIZ_TYPE(_E, _A)::difference_type difference_type;
   typedef _PTR_TYPE(_E, _A)::pointer pointer;
   typedef _PTR_TYPE(_E, _A)::const_pointer const_pointer;
   typedef _PTR_TYPE(_E, _A)::reference reference;
   typedef _PTR_TYPE(_E, _A)::const_reference const_reference;
   typedef _PTR_TYPE(_E, _A)::value_type value_type;
   typedef _PTR_TYPE(_E, _A)::pointer iterator;
   typedef _PTR_TYPE(_E, _A)::const_pointer const_iterator;
   typedef reverse_iterator<const_iterator, value_type,
      const_reference, difference_type> const_reverse_iterator;
   typedef reverse_iterator<iterator, value_type,
      reference, difference_type> reverse_iterator;
#if _HAS_STATIC_MEMBER_INIT
   static const size_type npos = -1;
#else
   enum _Npos_enum {npos = ~0};   // CAN HAVE WRONG SIZE/TYPE
#endif
   basic_string(_A& _Al = _A())
      : allocator(_Al ) {_Tidy(); }
   basic_string(const _Myt& _X, size_type _P = 0,
      size_type _N = npos, _A& _Al = _A())
      : allocator(_Al) {_Tidy(), assign(_X, _P, _N); }
   basic_string(const _E *_S, size_type _N = npos,
      _A& _Al = _A())
      : allocator(_Al) {_Tidy(), assign(_S, _N); }
   basic_string(size_type _N, _E _C, _A& _Al = _A())
      : allocator(_Al) {_Tidy(), assign(_N, _C); }
#if _HAS_MEMBER_TEMPLATES
   template<class _It>
#else
   typedef const_iterator _It;
#endif
      basic_string(_It _F, _It _L, A& _Al = _A())
      : allocator(_Al) {_Tidy(); assign(_F, _L); }
   ~basic_string()
      {_Tidy(true); }
   _Myt& operator=(const _Mtyt& _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, size_type _P = 0,
      size_type _M = npos)
      {if (_X.size() < _P)
         _Xran();
      size_type _N = _X.size() - _P;
      if (_N < _M)
         _M = _N;
      if (npos - _Len <= _M)
         _Xlen();
      if (0 < _M && _Grow(_N = _Len + _M))
         {_T::copy(_Ptr + _Len, &_X.c_str()[_P],_M);
         _Eos(_N); }
      return (*this); }
   _Myt& append(const _E *_S, size_type _M = npos)
      {if (_M == (size_type)npos)
         _M = _T::length(_S);
      if (npos - _Len <= _M)
         _Xlen();
      size_type _N;
      if (0 < _M && _Grow(_N = _Len + _M))
         {_T::copy(_Ptr + _Len, _S, _M);
         _Eos(_N); }
      return (*this); }
   _Myt& append(size_type _M, _E _C = _T::eos())
      {if (npos - _Len <= _M)
         _Xlen();
      size_type _N;
      if (0 < _M && _Grow(_N = _Len + _M))
         {_Memset(_Ptr + _Len, _C, _M);
         _Eos(_N); }
      return (*this); }
#if _HAS_MEMBER_TEMPLATES
   template<class _It>
#endif
      _Myt& append(_It _F, It _L)
      {insert (end(), _F, _L);
      return (*this); }
   _Myt& assign(const _Myt& _X, size_type _P = 0,
      size_type _M = npos)
      {if (_X.size() < _P)
         _Xran();
      size_type _N = _X.size() - _P;
      if (_M < _N)
         _N = _M;
      if (this == &_X)
         remove(_P + _N), remove(0, _P);
      else if (_Grow(_N, true))
         {_T::copy(_Ptr, &_X.c_str()[_P], _N);
         _Eos(_N); }
      return (*this); }
   _Myt& assign(const _E *_S, size_type _N = npos)
      {if (_N == (size_type)npos)
         _N = _T::length(_S);
      if (_Grow(_N, true))
         {_T::copy(_Ptr, _S, _N);
         _Eos(_N); }
      return (*this); }
   _Myt& assign(size_type _N, _E _C = _T::eos())
      {if (_N == (size_type)npos)
         _Xlen();
      if (_Grow(_N, true))
         {_Memset(_Ptr, _C, _N);
         _Eos(_N); }
      return (*this); }
#if _HAS_MEMBER_TEMPLATES
   template<class _It>
#endif
      _Myt& assign(_It _F, _It _L)
      {return (replace(begin(), end(), _F, _L)); }
   _Myt& insert(size_type _P0, const _Myt& _X, size_type _P = 0,
      size_type _M = npos)
      {if (_Len < _P0 || _X.size() < _P)
         _Xran();
      size_type _N = _X.size() - _P;
      if (_N < _M)
         _M = _N;
      if (npos - _Len <= _M)
         _Xlen();
      if (0 < _M && _Grow(_N = _Len + _M))
         {_Memmove(_Ptr + _P0 + _M, _Ptr + _P0,
            _Len - _P0);
         _T::copy(_Ptr + _P0, &_X.c_str()[_P], M);
         _Eos(_N); }
      return (*this); }
   _Myt& insert(size_type _P0, const _E *_S,
      size_type _M = npos)
      {if (_Len < _P0)
         _Xran();
      if (_M == (size_type)npos)
         _M = _T::length(_S);
      if (npos - _Len <= _M)
         _Xlen();
      size_type _N;
      if (0 < _M && _Grow(_N = _Len + _M))
         {_Memmove(_Ptr + _P0 + _M, _Ptr + _P0,
            _Len - _P0);
         _T::copy(_Ptr + _P0, _S, _M);
         _Eos(_N); }
      return (*this); }
   _Myt& insert(size_type _P0, size_type_M,
      _E _C = _T::eos())
      {if (_Len < _P0)
         _Xran();
      if (npos - _Len <= _M)
         _Xlen();
      size_type _N;
      if (0 < _M && _Grow(_N = _Len + _M))
         {_Memmove(_Ptr + _P0 + _M, _Ptr + _P0,
            _Len - _P0);
         _Memset(_Ptr + _P0, _C, _M);
         _Eos(_N); }
      return (*this); }
   iterator insert(iterator _P, _E _C = _T::eos())
      {size_type _P0 = _P - begin();
      insert(_P0, 1, _C);
      return (begin() + _P0); }
   void insert(iterator _P, size_type _M,
      _E _C = _T::eos())
      {size_type _P0 = _P - begin();
      insert(_P0, _M, _C); }
#if _HAS_MEMBER_TEMPLATES
   template<class _It>
#endif
      void insert(iterator _P, _It _F, _It _L)
      {size_type _M = 0;
      distance(_F, _L, _M);
      insert(size_type(_P - begin()), (const _E *)_F, _M); }
   _Myt& remove(size_type _P0 = 0, size_type_M = npos)
      {if (_Len < _P0)
         _Xran();
      if (_Len - _P0 < _M)
         _M = _Len - _P0;
      if (0 < _M)
         {_Memmove(_Ptr + _P0, _Ptr + _P0 + _M,
            _Len - _P0 - _M);
         size_type _N = _Len - _M;
         if (_Grow(_N))
            _Eos(_N); }
      return (*this); }
   _Myt& remove(iterator _P)
      {return (remove(_P - begin(), 1)); }
   _Myt& remove(iterator _F, iterator _L)
      {return (remove(_F - begin(), _L - _F)); }
   _Myt& replace(size_type _P0, size_type _N0, const _Myt& _X,
      size_type _P = 0, size_type _M = npos)
      {if (_Len < _P0 || _X.size() < _P)
         _Xran();
      size_type _N = _X.size() - _P;
      if (_N < _M)
         _M = _N;
      if (npos - _M <= _Len - _N0)
         _Xlen();
      size_type _Nm = _Len - _N0 - _P0;
      if (_M < _N0)
         _Memmove(_Ptr + _P0 + _M, _PTR + _P0 + _N0, _Nm);
      if ((0 < _M || 0 < _N0) && Grow(_N = _Len + _M - _N0))
         {if (_N0 < _M)
            _Memmove(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
         _T::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 = npos)
      {if (_Len < _P0)
         _Xran();
      if (_M == (size_type)npos)
         _M = _T::length(_S);
      if (npos - _M <= _Len - _N0)
         _Xlen();
      size_type _Nm = _Len - _N0 - _P0;
      if (_M < _N0)
         _Memmove(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
      size_type _N;
      if ((0 < _M || 0 < _N0) && _Grow(_N = _Len +_M - _N0))
         {if (_N0 < _M)
            _Memmove(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
         _T::copy(_Ptr + _P0, _S, _M);
         _Eos(_N); }
      return (*this); }
   _Myt& replace(size_type _P0, size_type _N0,     size_type _M,
      _E _C = _T::eos())
      {if (_Len < _P0)
         _Xran();
      if (_Len - _P0 < _N0)
         _N0 = _Len - _P0;
      if (npos - _M <= _Len - _N0)
         _Xlen();
      size_type _Nm = _Len - _N0 - _P0;
      if (_M < _N0)
         _Memmove(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
      size_type _N;
      if ((0 < _M || 0 < _N0) && _Grow(_N = _Len + _M - _N0))
         {if (_N0 < _M)
            _Memmove(_Ptr + _P0 + _M, _Ptr + _P0 + _N0, _Nm);
         _Memset(_Ptr + _P0, _C,_M);
         _Eos(_N); }
      return (*this); }
   _Myt& replace(iterator _F, iterator _L, const _Myt& _X)
      {return (replace(size_type(_F - begin()),
         size_type(_L - _F), _X)); }
   _Myt& replace(iterator _F, iterator _L, const _E *_S,
      size_type _M = npos)
      {return (replace(size_type(_F - begin()),
         size_type(_L - _F), _S, _M)); }
   _Myt& replace(iterator _F, iterator _L, size_type _M,
      _E _C = _T::eos())
      {return (replace(size_type(_F - begin()),
         size_type(_L - _F), _M, _C)); }
#if _HAS_MEMBER_TEMPLATES
   template<class _It>
#endif
      _Myt& replace(iterator _F1, iterator _L1,
         _It _F2, _It _L2)
      {size_type _M = 0;
      distance(_F2, _L2, _M);
      return (replace(size_type(_F1 - begin()),
         size_type(_L1 - _F1), (const _E *)_F2, _M)); }
   iterator begin()
      {return (_Ptr); }
   const_iterator begin() const
      {return (begin()); }
   iterator end()
      {return (_Ptr == 0 ? 0 : _Ptr + _Len); }
   const_iterator end() const
      {return (end()); }
   reverse_iterator rbegin()
      {return (reverse_iterator(end())); }
   const_reverse_iterator rbegin() const
      {return (const_reverse_iterator(end())); }
   reverse_iterator rend()
      {return (reverse_iterator(begin())); }
   const_reverse_iterator rend() const
      {return (const_reverse_iterator(begin())); }
   const_reference at(size_type _P0) const
      {if (_Len <= _P0)
         _Xran();
      return (_Ptr[_P0]); }
   reference at(size_type _P0)
      {if (_Len <= _P0)
         _Xran();
      return (_Ptr[_P0]); }
   const_reference operator[](size_type _P0) const
      {return (_Ptr[_P0]); }
   reference operator[](size_type _P0)
      {_Grow(_Len);
      return (_Ptr[_P0]); }
   const _E *c_str() const
      {return (_Ptr != 0 ? _Ptr : _Null()); }
   const _E *data() const
      {return (0 < _Len ? _Ptr : 0); }
   size_type length() const
      {return ( _Len); }
   size_type size() const
      {return (_Len); }
   size_type max_size() const
      {size_type _N = _MAX_SIZE(_E, allocator);
      return (_N <= 2 ? 1 : _N - 2); }
   void resize(size_type _N, _E _C = _T::eos())
      {_N <= _Len ? remove(_N) : append(_N - _Len, _C); }
   size_type capacity() const
      {return (_Res); }
   void reserve(size_type _N)
      {if (_Res < _N)
         _Grow(_N), _Eos(_Len); }
   bool empty() const
      {return (_Len == 0); }
   size_type copy(_E *_S, size_type _N,
      size_type _P0 = 0) const
      {if (_Len < _P0)
         _Xran();
      if (_Len - _P0 < _N)
         _N = _Len - _P0;
      _T::copy(_S, _Ptr + _P0, _N);
      return (_N); }
   void swap(_Myt& _X)
      {_E *_Tp = _Ptr; _Ptr = _X._Ptr, _X._Ptr = _Tp;
      size_type _Tl = _Len; _Len = _X._Len, _X._Len = _Tl;
      size_type _Tr = _Res; _Res = _X._Res, _X._Res = _Tr; }
   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 = 0,
      size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      size_type _Nm;
      if (_P < _Len && _N <= (_Nm = _Len - _P))
         {const _E *_U, *_V;
         for (_Nm -=_N - 1, _V = _Ptr + _P;
            (_U = _Memchr(_V, *_S, _Nm)) != 0;
            _Nm -=_U -_V + 1, _V = _U + 1)
            if (_T::compare(_U, _S, _N) == 0)
               return (_U - _Ptr); }
         return (npos); }
   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 = npos,
      size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      if (_N <= _Len)
         for (const _E *_U = _Ptr
            + (_P < _Len - _N ? _P : _Len - _N); ; --_U)
            if (*_U == *_S && _T::compare(_U, _S, _N) == 0)
               return (_U - _Ptr);
            else if (_U == _Ptr)
               break;
      return (npos); }
   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 = 0,
      size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      if (_P < _Len)
         {const _E *const _V = _Ptr + _Len;
         for (const _E *_U = _Ptr + _P; _U < _V; ++_U)
            if (_Memchr(_S, *_U, _N) != 0)
               return (_U - _Ptr); }
         return (npos); }
   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 = npos, size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      if (0 < _Len)
         for (const _E *_U = _Ptr
            + (_P < _Len ? _P : _Len - 1); ; --_U)
            if (_Memchr(_S, *_U, _N) != 0)
               return (_U - _Ptr);
            else if (_U == _Ptr)
               break;
      return (npos); }
   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 = 0,
      size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      if (_P < _Len)
         {const _E *const _V = _Ptr + _Len;
         for (const _E *_U = _Ptr + _P; _U < _V; ++_U)
            if (_Memchr( _S, *_U, _N) == 0)
               return (_U - _Ptr); }
         return (npos); }
   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 = npos,
       size_type _N = npos) const
      {if (_Len0(_N, _S))
         return (0);
      if (0 < _Len)
         for (const _E *_U = _Ptr
            +( _P < _Len ? _P : _Len - 1); ; --_U)
            if (_Memchr( S, *_U, _N) == 0)
               return (_U - _Ptr);
            else if (_U == _Ptr)
               break;
         return (npos); }
   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 _N = npos) const
      {return (_Myt(*this, _P, _N)); }
   int compare(const _Myt& _X, size_type _P = 0,
      size_type _M = npos) const
      {if (_Len < _P)
         _Xran();
      size_type _N = _Len - _P;
      if (_X.size() < _M)
         _M = _X.size();
      size_type _Ans = _T::compare(_Ptr + _P, _X.c_str(),
         _N < _M ? _N : _M);
      return (_Ans != 0 ? _Ans : _N < _M ? -1
         : _N == _M ? 0 : +1); }
   int compare(const _E *_S, size_type _P = 0,
      size_type _M = npos) const
      {if (_Len < _P)
         _Xran();
      size_type _N = _Len - _P;
      if (_M == (size_type)npos)
         _M = _T::length(_S);
      size_type _Ans = _T::compare(_Ptr + _P, _S,
         _N < _M ?_N : _M);
      return (_Ans != 0 ? _Ans : _N < _M ? -1
         : _N ==_M ? 0 : +1); }
protected:
   _A allocator;
private:
   enum {_MIN_SIZE = sizeof (_E) <= 32 ? 31 : 7};
   void _Eos(_N)
      {_T::assign(_Ptr[_Len = _N], _T::eos()); }
   bool _Grow(size_type _N, bool _Trim = false)
      {if (max_size() < _N)
         _Xlen();
      if (_N == 0)
         _Tidy(true);
      else
         {_Res = _N < _Len ? _Len : _N;
         _E *_S = _ALLOCATE(_E, allocator, _Res + 1);
         _Ptr = _T::copy(_S, _Ptr, _Len + 1); }
      size_type _Os = _Ptr == 0 ? 0 : _Res;
      if (_N == 0)
         {if (_Trim && _MIN_SIZE < _Os)
            _Tidy(true);
         else if (_Ptr != 0)
            _Eos(0);
         return (0); }
      else if (_N == _Os || _N < _Os && !_Trim)
         return (1);
      else
         {size_type _Ns = _Ptr == 0 && _N < _Res ? _Res : _N;
         if (max_size() < (_Ns |= _MIN_SIZE))
            _Ns = max_size();
         _E *_S;
         _TRY_BEGIN
            _S = _ALLOCATE(_E, allocator, _Ns + 1);
         _CATCH_ALL
            _Ns = _N;
            _S = _ALLOCATE(_E, allocator, _Ns + 1);
         _CATCH_END
         if (0 < _Len)
            _T::copy(_S, _Ptr, (_Len < _Ns ? Len : _Ns) + 1);
         _DEALLOCATE(_E, allocator, _Ptr);
         _Ptr = _S;
         _Res = _Ns;
         return (1); }}
   static bool _Len0(size_type& _N, const _E *_S)
      {return (_N == 0 || _N == (size_type)npos &&
         (_N = _T::length(_S)) == 0); }
   static const _E *_Null()
      {static const _E _C = _T::eos();
      return (&_C); }
   void _Tidy(bool _Built = false)
      {if (_Built && _Ptr != 0)
         _DEALLOCATE(_E, allocator, _Ptr);
      _Ptr = 0, _Len = 0, _Res = 0; }
   _E *_Ptr;
   size_type _Len, _Res;
   };