OSDN Git Service

2004-07-08 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / libstdc++-v3 / include / bits / basic_string.h
index 1a534a1..7e6c669 100644 (file)
@@ -1,6 +1,6 @@
 // Components for manipulating sequences of characters -*- C++ -*-
 
-// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
+// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -43,6 +43,7 @@
 #pragma GCC system_header
 
 #include <bits/atomicity.h>
+#include <debug/debug.h>
 
 namespace std
 {
@@ -72,7 +73,7 @@ namespace std
    *                                        [_Rep]
    *                                        _M_length
    *   [basic_string<char_type>]            _M_capacity
-   *   _M_dataplus                          _M_state
+   *   _M_dataplus                          _M_refcount
    *   _M_p ---------------->               unnamed array of char_type
    *  @endcode
    *
@@ -110,30 +111,29 @@ namespace std
     {
       // Types:
     public:
-      typedef _Traits                                      traits_type;
-      typedef typename _Traits::char_type                  value_type;
-      typedef _Alloc                                       allocator_type;
-      typedef typename _Alloc::size_type                   size_type;
-      typedef typename _Alloc::difference_type                     difference_type;
-      typedef typename _Alloc::reference                   reference;
-      typedef typename _Alloc::const_reference                     const_reference;
-      typedef typename _Alloc::pointer                             pointer;
-      typedef typename _Alloc::const_pointer               const_pointer;
+      typedef _Traits                                      traits_type;
+      typedef typename _Traits::char_type                  value_type;
+      typedef _Alloc                                       allocator_type;
+      typedef typename _Alloc::size_type                   size_type;
+      typedef typename _Alloc::difference_type             difference_type;
+      typedef typename _Alloc::reference                   reference;
+      typedef typename _Alloc::const_reference             const_reference;
+      typedef typename _Alloc::pointer                     pointer;
+      typedef typename _Alloc::const_pointer               const_pointer;
       typedef __gnu_cxx::__normal_iterator<pointer, basic_string>  iterator;
       typedef __gnu_cxx::__normal_iterator<const_pointer, basic_string>
                                                             const_iterator;
-      typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;
-      typedef std::reverse_iterator<iterator>              reverse_iterator;
+      typedef std::reverse_iterator<const_iterator>    const_reverse_iterator;
+      typedef std::reverse_iterator<iterator>              reverse_iterator;
 
     private:
       // _Rep: string representation
       //   Invariants:
-      //   1. String really contains _M_length + 1 characters; last is set
-      //      to 0 only on call to c_str().  We avoid instantiating
-      //      _CharT() where the interface does not require it.
+      //   1. String really contains _M_length + 1 characters: due to 21.3.4
+      //      must be kept null-terminated.
       //   2. _M_capacity >= _M_length
-      //      Allocated memory is always _M_capacity + (1 * sizeof(_CharT)).
-      //   3. _M_references has three states:
+      //      Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
+      //   3. _M_refcount has three states:
       //      -1: leaked, one reference, no ref-copies allowed, non-const.
       //       0: one reference, non-const.
       //     n>0: n + 1 references, operations require a lock, const.
@@ -143,9 +143,9 @@ namespace std
 
       struct _Rep_base
       {
-       size_type               _M_length;
-       size_type               _M_capacity;
-       _Atomic_word            _M_references;
+       size_type               _M_length;
+       size_type               _M_capacity;
+       _Atomic_word            _M_refcount;
       };
 
       struct _Rep : _Rep_base
@@ -166,41 +166,37 @@ namespace std
        // Solving for m:
        // m = ((npos - sizeof(_Rep))/sizeof(CharT)) - 1
        // In addition, this implementation quarters this amount.
-       static const size_type  _S_max_size;
-       static const _CharT     _S_terminal;
+       static const size_type  _S_max_size;
+       static const _CharT     _S_terminal;
 
        // The following storage is init'd to 0 by the linker, resulting
         // (carefully) in an empty string with one reference.
         static size_type _S_empty_rep_storage[];
 
-        static _Rep& 
+        static _Rep&
         _S_empty_rep()
         { return *reinterpret_cast<_Rep*>(&_S_empty_rep_storage); }
+
         bool
        _M_is_leaked() const
-        { return this->_M_references < 0; }
+        { return this->_M_refcount < 0; }
 
         bool
        _M_is_shared() const
-        { return this->_M_references > 0; }
+        { return this->_M_refcount > 0; }
 
         void
        _M_set_leaked()
-        { this->_M_references = -1; }
+        { this->_M_refcount = -1; }
 
         void
        _M_set_sharable()
-        { this->_M_references = 0; }
+        { this->_M_refcount = 0; }
 
        _CharT*
        _M_refdata() throw()
        { return reinterpret_cast<_CharT*>(this + 1); }
 
-       _CharT&
-       operator[](size_t __s) throw()
-       { return _M_refdata() [__s]; }
-
        _CharT*
        _M_grab(const _Alloc& __alloc1, const _Alloc& __alloc2)
        {
@@ -210,13 +206,13 @@ namespace std
 
        // Create & Destroy
        static _Rep*
-       _S_create(size_t, const _Alloc&);
+       _S_create(size_type, size_type, const _Alloc&);
 
        void
        _M_dispose(const _Alloc& __a)
        {
          if (__builtin_expect(this != &_S_empty_rep(), false))
-           if (__exchange_and_add(&this->_M_references, -1) <= 0)
+           if (__gnu_cxx::__exchange_and_add(&this->_M_refcount, -1) <= 0)
              _M_destroy(__a);
        }  // XXX MT
 
@@ -227,7 +223,7 @@ namespace std
        _M_refcopy() throw()
        {
          if (__builtin_expect(this != &_S_empty_rep(), false))
-            __atomic_add(&this->_M_references, 1);
+            __gnu_cxx::__atomic_add(&this->_M_refcount, 1);
          return _M_refdata();
        }  // XXX MT
 
@@ -250,11 +246,11 @@ namespace std
       // size that the allocator can hold.
       /// @var
       /// Value returned by various member functions when they fail.
-      static const size_type   npos = static_cast<size_type>(-1);
+      static const size_type   npos = static_cast<size_type>(-1);
 
     private:
       // Data Members (private):
-      mutable _Alloc_hider     _M_dataplus;
+      mutable _Alloc_hider     _M_dataplus;
 
       _CharT*
       _M_data() const
@@ -283,21 +279,20 @@ namespace std
          _M_leak_hard();
       }
 
-      iterator
-      _M_check(size_type __pos) const
+      size_type
+      _M_check(size_type __pos, const char* __s) const
       {
        if (__pos > this->size())
-         __throw_out_of_range(__N("basic_string::_M_check"));
-       return _M_ibegin() + __pos;
+         __throw_out_of_range(__N(__s));
+       return __pos;
       }
 
-      // NB: _M_fold doesn't check for a bad __pos1 value.
-      iterator
-      _M_fold(size_type __pos, size_type __off) const
+      // NB: _M_limit doesn't check for a bad __pos value.
+      size_type
+      _M_limit(size_type __pos, size_type __off) const
       {
        const bool __testoff =  __off < this->size() - __pos;
-       const size_type __newoff = __testoff ? __off : this->size() - __pos;
-       return (_M_ibegin() + __pos + __newoff);
+       return __testoff ? __off : this->size() - __pos;
       }
 
       // _S_copy_chars is a separate template to permit specialization
@@ -378,10 +373,13 @@ namespace std
                   size_type __n, const _Alloc& __a);
 
       /**
-       *  @brief  Construct string as copy of a C substring.
-       *  @param  s  Source C string.
+       *  @brief  Construct string initialized by a character array.
+       *  @param  s  Source character array.
        *  @param  n  Number of characters to copy.
        *  @param  a  Allocator to use (default is default allocator).
+       *
+       *  NB: s must have at least n characters, '\0' has no special
+       *  meaning.
        */
       basic_string(const _CharT* __s, size_type __n,
                   const _Alloc& __a = _Alloc());
@@ -420,14 +418,16 @@ namespace std
        *  @param  str  Source string.
        */
       basic_string&
-      operator=(const basic_string& __str) { return this->assign(__str); }
+      operator=(const basic_string& __str) 
+      { return this->assign(__str); }
 
       /**
        *  @brief  Copy contents of @a s into this string.
        *  @param  s  Source null-terminated string.
        */
       basic_string&
-      operator=(const _CharT* __s) { return this->assign(__s); }
+      operator=(const _CharT* __s) 
+      { return this->assign(__s); }
 
       /**
        *  @brief  Set value to string of length 1.
@@ -437,7 +437,11 @@ namespace std
        *  (*this)[0] == @a c.
        */
       basic_string&
-      operator=(_CharT __c) { return this->assign(1, __c); }
+      operator=(_CharT __c) 
+      { 
+       this->assign(1, __c); 
+       return *this;
+      }
 
       // Iterators:
       /**
@@ -608,7 +612,10 @@ namespace std
        */
       const_reference
       operator[] (size_type __pos) const
-      { return _M_data()[__pos]; }
+      {
+       _GLIBCXX_DEBUG_ASSERT(__pos <= size());
+       return _M_data()[__pos];
+      }
 
       /**
        *  @brief  Subscript access to the data contained in the %string.
@@ -623,6 +630,7 @@ namespace std
       reference
       operator[](size_type __pos)
       {
+       _GLIBCXX_DEBUG_ASSERT(__pos < size());
        _M_leak();
        return _M_data()[__pos];
       }
@@ -729,7 +737,10 @@ namespace std
        */
       basic_string&
       append(const _CharT* __s)
-      { return this->append(__s, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->append(__s, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Append multiple characters.
@@ -740,7 +751,8 @@ namespace std
        *  Appends n copies of c to this string.
        */
       basic_string&
-      append(size_type __n, _CharT __c);
+      append(size_type __n, _CharT __c)
+      { return _M_replace_aux(this->size(), size_type(0), __n, __c); }
 
       /**
        *  @brief  Append a range of characters.
@@ -761,7 +773,7 @@ namespace std
        */
       void
       push_back(_CharT __c)
-      { this->replace(_M_iend(), _M_iend(), 1, __c); }
+      { _M_replace_aux(this->size(), size_type(0), size_type(1), __c); }
 
       /**
        *  @brief  Set value to contents of another string.
@@ -784,7 +796,10 @@ namespace std
        *  of available characters in @a str, the remainder of @a str is used.
        */
       basic_string&
-      assign(const basic_string& __str, size_type __pos, size_type __n);
+      assign(const basic_string& __str, size_type __pos, size_type __n)
+      { return this->assign(__str._M_data()
+                           + __str._M_check(__pos, "basic_string::assign"),
+                           __str._M_limit(__pos, __n)); }
 
       /**
        *  @brief  Set value to a C substring.
@@ -810,7 +825,10 @@ namespace std
        */
       basic_string&
       assign(const _CharT* __s)
-      { return this->assign(__s, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->assign(__s, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Set value to multiple characters.
@@ -823,7 +841,7 @@ namespace std
        */
       basic_string&
       assign(size_type __n, _CharT __c)
-      { return this->replace(_M_ibegin(), _M_iend(), __n, __c); }
+      { return _M_replace_aux(size_type(0), this->size(), __n, __c); }
 
       /**
        *  @brief  Set value to a range of characters.
@@ -858,7 +876,7 @@ namespace std
        *  @brief  Insert a range of characters.
        *  @param p  Iterator referencing location in string to insert at.
        *  @param beg  Start of range.
-       *  @param end  End of range. 
+       *  @param end  End of range.
        *  @throw  std::length_error  If new length exceeds @c max_size().
        *
        *  Inserts characters in range [beg,end).  If adding characters causes
@@ -882,7 +900,7 @@ namespace std
       */
       basic_string&
       insert(size_type __pos1, const basic_string& __str)
-      { return this->insert(__pos1, __str, 0, __str.size()); }
+      { return this->insert(__pos1, __str, size_type(0), __str.size()); }
 
       /**
        *  @brief  Insert a substring.
@@ -904,7 +922,10 @@ namespace std
       */
       basic_string&
       insert(size_type __pos1, const basic_string& __str,
-            size_type __pos2, size_type __n);
+            size_type __pos2, size_type __n)
+      { return this->insert(__pos1, __str._M_data()
+                           + __str._M_check(__pos2, "basic_string::insert"),
+                           __str._M_limit(__pos2, __n)); }
 
       /**
        *  @brief  Insert a C substring.
@@ -914,7 +935,7 @@ namespace std
        *  @return  Reference to this string.
        *  @throw  std::length_error  If new length exceeds @c max_size().
        *  @throw  std::out_of_range  If @a pos is beyond the end of this
-       *  string. 
+       *  string.
        *
        *  Inserts the first @a n characters of @a s starting at @a pos.  If
        *  adding characters causes the length to exceed max_size(),
@@ -942,7 +963,10 @@ namespace std
       */
       basic_string&
       insert(size_type __pos, const _CharT* __s)
-      { return this->insert(__pos, __s, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->insert(__pos, __s, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Insert multiple characters.
@@ -962,10 +986,8 @@ namespace std
       */
       basic_string&
       insert(size_type __pos, size_type __n, _CharT __c)
-      {
-       this->insert(_M_check(__pos), __n, __c);
-       return *this;
-      }
+      { return _M_replace_aux(_M_check(__pos, "basic_string::insert"),
+                             size_type(0), __n, __c); }
 
       /**
        *  @brief  Insert one character.
@@ -973,7 +995,6 @@ namespace std
        *  @param c  The character to insert.
        *  @return  Iterator referencing newly inserted char.
        *  @throw  std::length_error  If new length exceeds @c max_size().
-       *  @throw  std::out_of_range  If @a p is beyond the end of this string.
        *
        *  Inserts character @a c at position referenced by @a p.  If adding
        *  character causes the length to exceed max_size(), length_error is
@@ -981,12 +1002,13 @@ namespace std
        *  The value of the string doesn't change if an error is thrown.
       */
       iterator
-      insert(iterator __p, _CharT __c = _CharT())
+      insert(iterator __p, _CharT __c)
       {
+       _GLIBCXX_DEBUG_PEDASSERT(__p >= _M_ibegin() && __p <= _M_iend());
        const size_type __pos = __p - _M_ibegin();
-       this->insert(_M_check(__pos), size_type(1), __c);
+       _M_replace_aux(__pos, size_type(0), size_type(1), __c);
        _M_rep()->_M_set_leaked();
-       return this->_M_ibegin() + __pos;
+       return this->_M_ibegin() + __pos;
       }
 
       /**
@@ -1005,29 +1027,26 @@ namespace std
       */
       basic_string&
       erase(size_type __pos = 0, size_type __n = npos)
-      {
-       return this->replace(_M_check(__pos), _M_fold(__pos, __n),
-                            _M_data(), _M_data());
-      }
+      { return _M_replace_safe(_M_check(__pos, "basic_string::erase"),
+                              _M_limit(__pos, __n), NULL, size_type(0)); }
 
       /**
        *  @brief  Remove one character.
        *  @param position  Iterator referencing the character to remove.
        *  @return  iterator referencing same location after removal.
-       *  @throw  std::out_of_range  If @a position is beyond the end of this
-       *  string. 
        *
-       *  Removes the character at @a position from this string.  If @a
-       *  position is beyond end of string, out_of_range is thrown.  The value
+       *  Removes the character at @a position from this string. The value
        *  of the string doesn't change if an error is thrown.
       */
       iterator
       erase(iterator __position)
       {
-       const size_type __i = __position - _M_ibegin();
-        this->replace(__position, __position + 1, _M_data(), _M_data());
+       _GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
+                                && __position < _M_iend());
+       const size_type __pos = __position - _M_ibegin();
+       _M_replace_safe(__pos, size_type(1), NULL, size_type(0));
        _M_rep()->_M_set_leaked();
-       return _M_ibegin() + __i;
+       return _M_ibegin() + __pos;
       }
 
       /**
@@ -1035,20 +1054,19 @@ namespace std
        *  @param first  Iterator referencing the first character to remove.
        *  @param last  Iterator referencing the end of the range.
        *  @return  Iterator referencing location of first after removal.
-       *  @throw  std::out_of_range  If @a first is beyond the end of this
-       *  string. 
        *
        *  Removes the characters in the range [first,last) from this string.
-       *  If @a first is beyond end of string, out_of_range is thrown.  The
-       *  value of the string doesn't change if an error is thrown.
+       *  The value of the string doesn't change if an error is thrown.
       */
       iterator
       erase(iterator __first, iterator __last)
       {
-        const size_type __i = __first - _M_ibegin();
-       this->replace(__first, __last, _M_data(), _M_data());
+       _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
+                                && __last <= _M_iend());
+        const size_type __pos = __first - _M_ibegin();
+       _M_replace_safe(__pos, __last - __first, NULL, size_type(0));
        _M_rep()->_M_set_leaked();
-       return _M_ibegin() + __i;
+       return _M_ibegin() + __pos;
       }
 
       /**
@@ -1058,7 +1076,7 @@ namespace std
        *  @param str  String to insert.
        *  @return  Reference to this string.
        *  @throw  std::out_of_range  If @a pos is beyond the end of this
-       *  string. 
+       *  string.
        *  @throw  std::length_error  If new length exceeds @c max_size().
        *
        *  Removes the characters in the range [pos,pos+n) from this string.
@@ -1080,7 +1098,7 @@ namespace std
        *  @param n2  Number of characters from str to use.
        *  @return  Reference to this string.
        *  @throw  std::out_of_range  If @a pos1 > size() or @a pos2 >
-       *  str.size(). 
+       *  str.size().
        *  @throw  std::length_error  If new length exceeds @c max_size().
        *
        *  Removes the characters in the range [pos1,pos1 + n) from this
@@ -1091,7 +1109,10 @@ namespace std
       */
       basic_string&
       replace(size_type __pos1, size_type __n1, const basic_string& __str,
-             size_type __pos2, size_type __n2);
+             size_type __pos2, size_type __n2)
+      { return this->replace(__pos1, __n1, __str._M_data()
+                            + __str._M_check(__pos2, "basic_string::replace"),
+                            __str._M_limit(__pos2, __n2)); }
 
       /**
        *  @brief  Replace characters with value of a C substring.
@@ -1131,7 +1152,10 @@ namespace std
       */
       basic_string&
       replace(size_type __pos, size_type __n1, const _CharT* __s)
-      { return this->replace(__pos, __n1, __s, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->replace(__pos, __n1, __s, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Replace characters with multiple characters.
@@ -1151,7 +1175,8 @@ namespace std
       */
       basic_string&
       replace(size_type __pos, size_type __n1, size_type __n2, _CharT __c)
-      { return this->replace(_M_check(__pos), _M_fold(__pos, __n1), __n2, __c); }
+      { return _M_replace_aux(_M_check(__pos, "basic_string::replace"),
+                             _M_limit(__pos, __n1), __n2, __c); }
 
       /**
        *  @brief  Replace range of characters with string.
@@ -1185,9 +1210,12 @@ namespace std
        *  change if an error is thrown.
       */
       basic_string&
-      replace(iterator __i1, iterator __i2,
-                           const _CharT* __s, size_type __n)
-      { return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n); }
+      replace(iterator __i1, iterator __i2, const _CharT* __s, size_type __n)
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       return this->replace(__i1 - _M_ibegin(), __i2 - __i1, __s, __n);
+      }
 
       /**
        *  @brief  Replace range of characters with C string.
@@ -1204,7 +1232,10 @@ namespace std
       */
       basic_string&
       replace(iterator __i1, iterator __i2, const _CharT* __s)
-      { return this->replace(__i1, __i2, __s, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->replace(__i1, __i2, __s, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Replace range of characters with multiple characters
@@ -1222,7 +1253,11 @@ namespace std
       */
       basic_string&
       replace(iterator __i1, iterator __i2, size_type __n, _CharT __c)
-      { return _M_replace_aux(__i1, __i2, __n, __c); }
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __c);
+      }
 
       /**
        *  @brief  Replace range of characters with range.
@@ -1242,69 +1277,102 @@ namespace std
         basic_string&
         replace(iterator __i1, iterator __i2,
                _InputIterator __k1, _InputIterator __k2)
-        { typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
-         return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral()); }
+        {
+         _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                  && __i2 <= _M_iend());
+         __glibcxx_requires_valid_range(__k1, __k2);
+         typedef typename _Is_integer<_InputIterator>::_Integral _Integral;
+         return _M_replace_dispatch(__i1, __i2, __k1, __k2, _Integral());
+       }
 
       // Specializations for the common case of pointer and iterator:
       // useful to avoid the overhead of temporary buffering in _M_replace.
       basic_string&
       replace(iterator __i1, iterator __i2, _CharT* __k1, _CharT* __k2)
-        { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
-                              __k1, __k2 - __k1); }
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       __glibcxx_requires_valid_range(__k1, __k2);
+       return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
+                            __k1, __k2 - __k1);
+      }
 
       basic_string&
-      replace(iterator __i1, iterator __i2, const _CharT* __k1, const _CharT* __k2)
-        { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
-                              __k1, __k2 - __k1); }
+      replace(iterator __i1, iterator __i2,
+             const _CharT* __k1, const _CharT* __k2)
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       __glibcxx_requires_valid_range(__k1, __k2);
+       return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
+                            __k1, __k2 - __k1);
+      }
 
       basic_string&
       replace(iterator __i1, iterator __i2, iterator __k1, iterator __k2)
-        { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
-                              __k1.base(), __k2 - __k1);
-       }
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       __glibcxx_requires_valid_range(__k1, __k2);
+       return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
+                            __k1.base(), __k2 - __k1);
+      }
 
       basic_string&
-      replace(iterator __i1, iterator __i2, const_iterator __k1, const_iterator __k2)
-        { return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
-                              __k1.base(), __k2 - __k1);
-       }
-
+      replace(iterator __i1, iterator __i2,
+             const_iterator __k1, const_iterator __k2)
+      {
+       _GLIBCXX_DEBUG_PEDASSERT(_M_ibegin() <= __i1 && __i1 <= __i2
+                                && __i2 <= _M_iend());
+       __glibcxx_requires_valid_range(__k1, __k2);
+       return this->replace(__i1 - _M_ibegin(), __i2 - __i1,
+                            __k1.base(), __k2 - __k1);
+      }
+      
     private:
       template<class _Integer>
        basic_string&
-       _M_replace_dispatch(iterator __i1, iterator __i2, _Integer __n, 
+       _M_replace_dispatch(iterator __i1, iterator __i2, _Integer __n,
                            _Integer __val, __true_type)
-        { return _M_replace_aux(__i1, __i2, __n, __val); }
+        { return _M_replace_aux(__i1 - _M_ibegin(), __i2 - __i1, __n, __val); }
 
       template<class _InputIterator>
        basic_string&
        _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
-                           _InputIterator __k2, __false_type)
-        { 
-         typedef typename iterator_traits<_InputIterator>::iterator_category
-           _Category;
-         return _M_replace(__i1, __i2, __k1, __k2, _Category());
-       }
+                           _InputIterator __k2, __false_type);
 
       basic_string&
-      _M_replace_aux(iterator __i1, iterator __i2, size_type __n2, _CharT __c);
-
-      template<class _InputIterator>
-        basic_string&
-        _M_replace(iterator __i1, iterator __i2, _InputIterator __k1,
-                  _InputIterator __k2, input_iterator_tag);
+      _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
+                    _CharT __c)
+      {
+       if (this->max_size() - (this->size() - __n1) < __n2)
+         __throw_length_error(__N("basic_string::_M_replace_aux"));
+       _M_mutate(__pos1, __n1, __n2);
+       if (__n2 == 1)
+         _M_data()[__pos1] = __c;
+       else if (__n2)
+         traits_type::assign(_M_data() + __pos1, __n2, __c);
+       return *this;
+      }
 
-      template<class _ForwardIterator>
-        basic_string&
-        _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1,
-                  _ForwardIterator __k2);
+      basic_string&
+      _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
+                     size_type __n2)
+      {
+       _M_mutate(__pos1, __n1, __n2);
+       if (__n2 == 1)
+         _M_data()[__pos1] = *__s;
+       else if (__n2)
+         traits_type::copy(_M_data() + __pos1, __s, __n2);
+       return *this;
+      }
 
       // _S_construct_aux is used to implement the 21.3.1 para 15 which
       // requires special behaviour if _InIter is an integral type
       template<class _InIterator>
         static _CharT*
-        _S_construct_aux(_InIterator __beg, _InIterator __end, const _Alloc& __a,
-                        __false_type)
+        _S_construct_aux(_InIterator __beg, _InIterator __end,
+                        const _Alloc& __a, __false_type)
        {
           typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
           return _S_construct(__beg, __end, __a, _Tag());
@@ -1312,12 +1380,10 @@ namespace std
 
       template<class _InIterator>
         static _CharT*
-        _S_construct_aux(_InIterator __beg, _InIterator __end, const _Alloc& __a,
-                        __true_type)
-       {
-         return _S_construct(static_cast<size_type>(__beg),
-                             static_cast<value_type>(__end), __a);
-       }
+        _S_construct_aux(_InIterator __beg, _InIterator __end,
+                        const _Alloc& __a, __true_type)
+       { return _S_construct(static_cast<size_type>(__beg),
+                             static_cast<value_type>(__end), __a); }
 
       template<class _InIterator>
         static _CharT*
@@ -1377,19 +1443,13 @@ namespace std
        *  happen.
       */
       const _CharT*
-      c_str() const
-      {
-       // MT: This assumes concurrent writes are OK.
-       const size_type __n = this->size();
-       traits_type::assign(_M_data()[__n], _Rep::_S_terminal);
-        return _M_data();
-      }
+      c_str() const { return _M_data(); }
 
       /**
        *  @brief  Return const pointer to contents.
        *
-       *  This is a handle to internal data.  It may not be null-terminated.
-       *  Do not modify or dire things may happen.
+       *  This is a handle to internal data.  Do not modify or dire things may
+       *  happen.
       */
       const _CharT*
       data() const { return _M_data(); }
@@ -1440,7 +1500,10 @@ namespace std
       */
       size_type
       find(const _CharT* __s, size_type __pos = 0) const
-      { return this->find(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->find(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find position of a character.
@@ -1495,7 +1558,10 @@ namespace std
       */
       size_type
       rfind(const _CharT* __s, size_type __pos = npos) const
-      { return this->rfind(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->rfind(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find last position of a character.
@@ -1550,7 +1616,10 @@ namespace std
       */
       size_type
       find_first_of(const _CharT* __s, size_type __pos = 0) const
-      { return this->find_first_of(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->find_first_of(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find position of a character.
@@ -1608,7 +1677,10 @@ namespace std
       */
       size_type
       find_last_of(const _CharT* __s, size_type __pos = npos) const
-      { return this->find_last_of(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->find_last_of(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find last position of a character.
@@ -1667,7 +1739,10 @@ namespace std
       */
       size_type
       find_first_not_of(const _CharT* __s, size_type __pos = 0) const
-      { return this->find_first_not_of(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->find_first_not_of(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find position of a different character.
@@ -1723,7 +1798,10 @@ namespace std
       */
       size_type
       find_last_not_of(const _CharT* __s, size_type __pos = npos) const
-      { return this->find_last_not_of(__s, __pos, traits_type::length(__s)); }
+      {
+       __glibcxx_requires_string(__s);
+       return this->find_last_not_of(__s, __pos, traits_type::length(__s));
+      }
 
       /**
        *  @brief  Find last position of a different character.
@@ -1752,11 +1830,8 @@ namespace std
       */
       basic_string
       substr(size_type __pos = 0, size_type __n = npos) const
-      {
-       if (__pos > this->size())
-         __throw_out_of_range(__N("basic_string::substr"));
-       return basic_string(*this, __pos, __n);
-      }
+      { return basic_string(*this,
+                           _M_check(__pos, "basic_string::substr"), __n); }
 
       /**
        *  @brief  Compare to a string.
@@ -1858,21 +1933,24 @@ namespace std
       compare(size_type __pos, size_type __n1, const _CharT* __s) const;
 
       /**
-       *  @brief  Compare substring against a C substring.
+       *  @brief  Compare substring against a character array.
        *  @param pos1  Index of first character of substring.
        *  @param n1  Number of characters in substring.
-       *  @param s  C string to compare against.
-       *  @param n2  Number of characters in substring of s.
+       *  @param s  character array to compare against.
+       *  @param n2  Number of characters of s.
        *  @return  Integer < 0, 0, or > 0.
        *
        *  Form the substring of this string from the @a n1 characters starting
-       *  at @a pos1.  Form the substring of @a s from the first @a n
-       *  characters of @a s.  Returns an integer < 0 if this substring is
-       *  ordered before the substring of @a s, 0 if their values are
-       *  equivalent, or > 0 if this substring is ordered after the substring
-       *  of @a s.  If the lengths of this substring and @a n are different,
-       *  the shorter one is ordered first.  If they are the same, returns the
-       *  result of traits::compare(substring.data(),s,size());
+       *  at @a pos1.  Form a string from the first @a n2 characters of @a s.
+       *  Returns an integer < 0 if this substring is ordered before the string
+       *  from @a s, 0 if their values are equivalent, or > 0 if this substring
+       *  is ordered after the string from @a s. If the lengths of this
+       *  substring and @a n2 are different, the shorter one is ordered first.
+       *  If they are the same, returns the result of
+       *  traits::compare(substring.data(),s,size());
+       *
+       *  NB: s must have at least n2 characters, '\0' has no special
+       *  meaning.
       */
       int
       compare(size_type __pos, size_type __n1, const _CharT* __s,
@@ -1891,8 +1969,8 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Last string.
    *  @return  New string with value of @a lhs followed by @a rhs.
-   */ 
- template<typename _CharT, typename _Traits, typename _Alloc>
+   */
 template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>
     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
              const basic_string<_CharT, _Traits, _Alloc>& __rhs)
@@ -1907,7 +1985,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Last string.
    *  @return  New string with value of @a lhs followed by @a rhs.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT,_Traits,_Alloc>
     operator+(const _CharT* __lhs,
@@ -1918,7 +1996,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Last string.
    *  @return  New string with @a lhs followed by @a rhs.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT,_Traits,_Alloc>
     operator+(_CharT __lhs, const basic_string<_CharT,_Traits,_Alloc>& __rhs);
@@ -1928,7 +2006,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Last string.
    *  @return  New string with @a lhs followed by @a rhs.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline basic_string<_CharT, _Traits, _Alloc>
     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -1944,12 +2022,12 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Last string.
    *  @return  New string with @a lhs followed by @a rhs.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline basic_string<_CharT, _Traits, _Alloc>
     operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs, _CharT __rhs)
     {
-      typedef basic_string<_CharT, _Traits, _Alloc>    __string_type;
+      typedef basic_string<_CharT, _Traits, _Alloc>    __string_type;
       typedef typename __string_type::size_type                __size_type;
       __string_type __str(__lhs);
       __str.append(__size_type(1), __rhs);
@@ -1962,7 +2040,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs.compare(@a rhs) == 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -1974,7 +2052,7 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a rhs.compare(@a lhs) == 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator==(const _CharT* __lhs,
@@ -1986,7 +2064,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs.compare(@a rhs) == 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator==(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -1999,7 +2077,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs.compare(@a rhs) != 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2011,7 +2089,7 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a rhs.compare(@a lhs) != 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator!=(const _CharT* __lhs,
@@ -2023,7 +2101,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs.compare(@a rhs) != 0.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator!=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2036,7 +2114,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs precedes @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2048,7 +2126,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs precedes @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2060,7 +2138,7 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a lhs precedes @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<(const _CharT* __lhs,
@@ -2073,7 +2151,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs follows @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2085,7 +2163,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs follows @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2097,7 +2175,7 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a lhs follows @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>(const _CharT* __lhs,
@@ -2110,7 +2188,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs doesn't follow @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2122,7 +2200,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs doesn't follow @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2134,7 +2212,7 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a lhs doesn't follow @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator<=(const _CharT* __lhs,
@@ -2147,7 +2225,7 @@ namespace std
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *  @return  True if @a lhs doesn't precede @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2159,7 +2237,7 @@ namespace std
    *  @param lhs  String.
    *  @param rhs  C string.
    *  @return  True if @a lhs doesn't precede @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>=(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
@@ -2171,20 +2249,19 @@ namespace std
    *  @param lhs  C string.
    *  @param rhs  String.
    *  @return  True if @a lhs doesn't precede @a rhs.  False otherwise.
-   */ 
+   */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline bool
     operator>=(const _CharT* __lhs,
             const basic_string<_CharT, _Traits, _Alloc>& __rhs)
     { return __rhs.compare(__lhs) <= 0; }
 
-
   /**
    *  @brief  Swap contents of two strings.
    *  @param lhs  First string.
    *  @param rhs  Second string.
    *
-   *  Exchanges the contents of @a lhs and @a rhs in constant time. 
+   *  Exchanges the contents of @a lhs and @a rhs in constant time.
    */
   template<typename _CharT, typename _Traits, typename _Alloc>
     inline void