This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[v3, v7-branch] Various changes


Hi,

the below changes _M_get_Tp_allocator to return by ref, implements a
long standing TODO in string::replace and reorganizes rather heavily the
code surrounding the latter. Plus other smaller tweaks. Tested both
string bases on x86-linux (as usual, the string changes will go also in
mainline/4_1 for ext/vstring.h)

Paolo.

////////////////////
2005-11-30  Paolo Carlini  <pcarlini@suse.de>

	* include/ext/sso_string.h (__sso_string<>::_M_get_allocator): Add
	non const version.
	* include/ext/rc_string.h (__rc_string<>::_M_get_allocator): Likewise.
	* include/bits/basic_string.h (basic_string(__gnu_cxx::__rvalref<>):
	Use it.
	* include/bits/stl_vector.h (vector<>::_M_get_Tp_allocator): Change
	to return by ref and add non const version.
	(vector(const vector&), vector(__gnu_cxx::__rvalref<>)): Use it.
	* include/bits/stl_deque.h (deque<>::_M_get_Tp_allocator): Likewise.
	(deque(const deque&), deque(__gnu_cxx::__rvalref<>)): Likewise.
	(_M_destroy_data): Adjust.
	
	* include/ext/sso_string.h (__sso_string<>::_M_erase): Add.
	* include/ext/rc_string.h (__rc_string<>::_M_erase): Likewise.
	(_M_leak_hard): Use it.
	* include/bits/basic_string.h (basic_string<>::clear, erase, all
	versions): Use it.
	* include/bits/basic_string.tcc (basic_string<>::resize): Likewise.

	* include/bits/basic_string.h (basic_string<>::_M_replace_safe):
	Remove.
	* include/bits/basic_string.h (basic_string<>::_M_replace): New, does
	the in-place work or delegates to _M_mutate in case of reallocation.
	* include/bits/basic_string.tcc (basic_string<>::_M_replace_safe):
	Remove.
	* include/bits/basic_string.tcc (basic_string<>::_M_replace): Define.
	(assign, replace, _M_replace_dispatch, _M_replace_aux): Use it.
	* include/ext/sso_string.h (__sso_string<>::_M_mutate): Change to
	manage only reallocations.
	* include/ext/rc_string.h (__rc_string<>::_M_mutate): Likewise.

	* include/bits/basic_string.h (basic_string<>::insert(size_type,
	const basic_string&), insert(size_type, const basic_string&, size_type,
	size_type), insert(size_type, const _CharT*, size_type),
	insert(size_type, const _CharT*)): Delegate to replace.

	* include/bits/basic_string.h (basic_string<>::reserve): Move out of
	line.
	* include/bits/basic_string.tcc (basic_string<>::reserve): Do the
	checks and call _M_reserve.
	* include/bits/basic_string.h (basic_string<>::append): Call _M_reserve
	instead of reserve.
	* include/bits/basic_string.tcc (basic_string<>::append, all versions):
	Likewise.
	* include/ext/sso_string.h (__sso_string<>::_M_reserve): Adjust.
	* include/ext/rc_string.h (__rc_string<>::_M_reserve): Likewise.
Index: include/ext/sso_string.h
===================================================================
--- include/ext/sso_string.h	(revision 107309)
+++ include/ext/sso_string.h	(working copy)
@@ -202,6 +202,10 @@
       ~__sso_string()
       { _M_dispose(); }
 
+      allocator_type&
+      _M_get_allocator()
+      { return _M_dataplus; }
+
       const allocator_type&
       _M_get_allocator() const
       { return _M_dataplus; }
@@ -216,7 +220,11 @@
       _M_reserve(size_type __res);
 
       void
-      _M_mutate(size_type __pos, size_type __len1, size_type __len2);
+      _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+		size_type __len2);
+
+      void
+      _M_erase(size_type __pos, size_type __n);
     };
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -471,69 +479,66 @@
     _M_reserve(size_type __res)
     {
       const size_type __capacity = _M_capacity();
-      if (__res != __capacity)
+
+      if (__res > __capacity
+	  || __res > size_type(_S_local_capacity))
 	{
-	  // Make sure we don't shrink below the current size.
-	  if (__res < _M_length())
-	    __res = _M_length();
-
-	  if (__res > __capacity
-	      || __res > size_type(_S_local_capacity))
-	    {
-	      _CharT* __tmp = _M_create(__res, __capacity);
-	      if (_M_length())
-		_S_copy(__tmp, _M_data(), _M_length());
-	      _M_dispose();
-	      _M_data(__tmp);
-	      _M_capacity(__res);
-	    }
-	  else if (!_M_is_local())
-	    {
-	      const size_type __tmp_capacity = _M_allocated_capacity;
-	      if (_M_length())
-		_S_copy(_M_local_data, _M_data(), _M_length());
-	      _M_destroy(__tmp_capacity + 1);
-	      _M_data(_M_local_data);
-	    }	  
-	  
-	  _M_set_length(_M_length());
+	  _CharT* __tmp = _M_create(__res, __capacity);
+	  if (_M_length())
+	    _S_copy(__tmp, _M_data(), _M_length());
+	  _M_dispose();
+	  _M_data(__tmp);
+	  _M_capacity(__res);
 	}
+      else if (!_M_is_local())
+	{
+	  const size_type __tmp_capacity = _M_allocated_capacity;
+	  if (_M_length())
+	    _S_copy(_M_local_data, _M_data(), _M_length());
+	  _M_destroy(__tmp_capacity + 1);
+	  _M_data(_M_local_data);
+	}	  
+      
+      _M_set_length(_M_length());
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     __sso_string<_CharT, _Traits, _Alloc>::
-    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
+    _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+	      const size_type __len2)
     {
-      const size_type __old_size = _M_length();
-      const size_type __new_size = __old_size + __len2 - __len1;
-      const size_type __how_much = __old_size - __pos - __len1;
+      const size_type __how_much = _M_length() - __pos - __len1;
       
-      if (__new_size > _M_capacity())
-	{
-	  // Must reallocate.
-	  size_type __new_capacity = __new_size;
-	  _CharT* __r = _M_create(__new_capacity, _M_capacity());
+      size_type __new_capacity = _M_length() + __len2 - __len1;
+      _CharT* __r = _M_create(__new_capacity, _M_capacity());
 
-	  if (__pos)
-	    _S_copy(__r, _M_data(), __pos);
-	  if (__how_much)
-	    _S_copy(__r + __pos + __len2,
-		    _M_data() + __pos + __len1, __how_much);
+      if (__pos)
+	_S_copy(__r, _M_data(), __pos);
+      if (__s && __len2)
+	_S_copy(__r + __pos, __s, __len2);
+      if (__how_much)
+	_S_copy(__r + __pos + __len2,
+		_M_data() + __pos + __len1, __how_much);
+      
+      _M_dispose();
+      _M_data(__r);
+      _M_capacity(__new_capacity);
+    }
 
-	  _M_dispose();
-	  _M_data(__r);
-	  _M_capacity(__new_capacity);
-	}
-      else if (__how_much && __len1 != __len2)
-	{
-	  // Work in-place.
-	  _S_move(_M_data() + __pos + __len2,
-		  _M_data() + __pos + __len1, __how_much);
-	}
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    void
+    __sso_string<_CharT, _Traits, _Alloc>::
+    _M_erase(size_type __pos, size_type __n)
+    {
+      const size_type __how_much = _M_length() - __pos - __n;
 
-      _M_set_length(__new_size);
-    }
+      if (__how_much && __n)
+	_S_move(_M_data() + __pos, _M_data() + __pos + __n,
+		__how_much);
+
+      _M_set_length(_M_length() - __n);
+    } 
 } // namespace __gnu_cxx
 
 #endif /* _SSO_STRING_H */
Index: include/ext/rc_string.h
===================================================================
--- include/ext/rc_string.h	(revision 107309)
+++ include/ext/rc_string.h	(working copy)
@@ -310,6 +310,10 @@
       ~__rc_string()
       { _M_dispose(); }      
 
+      allocator_type&
+      _M_get_allocator()
+      { return _M_dataplus; }
+
       const allocator_type&
       _M_get_allocator() const
       { return _M_dataplus; }
@@ -324,7 +328,11 @@
       _M_reserve(size_type __res);
 
       void
-      _M_mutate(size_type __pos, size_type __len1, size_type __len2);
+      _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+		size_type __len2);
+      
+      void
+      _M_erase(size_type __pos, size_type __n);
     };
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -456,7 +464,7 @@
     _M_leak_hard()
     {
       if (_M_is_shared())
-	_M_mutate(0, 0, 0);
+	_M_erase(0, 0);
       _M_set_leaked();
     }
 
@@ -592,29 +600,44 @@
     __rc_string<_CharT, _Traits, _Alloc>::
     _M_reserve(size_type __res)
     {
-      if (__res != _M_capacity() || _M_is_shared())
-	{
-	  // Make sure we don't shrink below the current size.
-	  if (__res < _M_length())
-	    __res = _M_length();
-	  
-	  _CharT* __tmp = _M_rep()->_M_clone(_M_get_allocator(),
-					     __res - _M_length());
-	  _M_dispose();
-	  _M_data(__tmp);
-	}
+      _CharT* __tmp = _M_rep()->_M_clone(_M_get_allocator(),
+					 __res - _M_length());
+      _M_dispose();
+      _M_data(__tmp);
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     __rc_string<_CharT, _Traits, _Alloc>::
-    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
+    _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
+	      size_type __len2)
     {
-      const size_type __old_size = _M_length();
-      const size_type __new_size = __old_size + __len2 - __len1;
-      const size_type __how_much = __old_size - __pos - __len1;
+      const size_type __how_much = _M_length() - __pos - __len1;
       
-      if (__new_size > _M_capacity() || _M_is_shared())
+      _Rep* __r = _Rep::_S_create(_M_length() + __len2 - __len1,
+				  _M_capacity(), _M_get_allocator());
+      
+      if (__pos)
+	_S_copy(__r->_M_refdata(), _M_data(), __pos);
+      if (__s && __len2)
+	_S_copy(__r->_M_refdata() + __pos, __s, __len2);
+      if (__how_much)
+	_S_copy(__r->_M_refdata() + __pos + __len2,
+		_M_data() + __pos + __len1, __how_much);
+      
+      _M_dispose();
+      _M_data(__r->_M_refdata());
+    }
+
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    void
+    __rc_string<_CharT, _Traits, _Alloc>::
+    _M_erase(size_type __pos, size_type __n)
+    {
+      const size_type __new_size = _M_length() - __n;
+      const size_type __how_much = _M_length() - __pos - __n;
+      
+      if (_M_is_shared())
 	{
 	  // Must reallocate.
 	  _Rep* __r = _Rep::_S_create(__new_size, _M_capacity(),
@@ -623,20 +646,21 @@
 	  if (__pos)
 	    _S_copy(__r->_M_refdata(), _M_data(), __pos);
 	  if (__how_much)
-	    _S_copy(__r->_M_refdata() + __pos + __len2,
-		    _M_data() + __pos + __len1, __how_much);
+	    _S_copy(__r->_M_refdata() + __pos,
+		    _M_data() + __pos + __n, __how_much);
 
 	  _M_dispose();
 	  _M_data(__r->_M_refdata());
 	}
-      else if (__how_much && __len1 != __len2)
+      else if (__how_much && __n)
 	{
 	  // Work in-place.
-	  _S_move(_M_data() + __pos + __len2,
-		  _M_data() + __pos + __len1, __how_much);
+	  _S_move(_M_data() + __pos,
+		  _M_data() + __pos + __n, __how_much);
 	}
-      _M_rep()->_M_set_length(__new_size);
-    }
+
+      _M_rep()->_M_set_length(__new_size);      
+    } 
 } // namespace __gnu_cxx
 
 #endif /* _RC_STRING_H */
Index: include/bits/basic_string.h
===================================================================
--- include/bits/basic_string.h	(revision 106945)
+++ include/bits/basic_string.h	(working copy)
@@ -118,8 +118,7 @@
 	const bool __testoff =  __off < this->size() - __pos;
 	return __testoff ? __off : this->size() - __pos;
       }
-
-      // True if _Rep and source do not overlap.
+      
       bool
       _M_disjunct(const _CharT* __s) const
       {
@@ -175,7 +174,7 @@
        */
       template<typename _String>
         basic_string(__gnu_cxx::__rvalref<_String> __str)
-	: __string_base(__str.__ref.get_allocator())
+	: __string_base(__str.__ref._M_get_allocator())
 	{ this->swap(__str.__ref); }
 
       /**
@@ -447,15 +446,14 @@
        *  data.
        */
       void
-      reserve(size_type __res_arg = 0)
-      {	this->_M_reserve(__res_arg); }
-
+      reserve(size_type __res_arg = 0);
+ 
       /**
        *  Erases the string, making it empty.
        */
       void
       clear()
-      { this->_M_mutate(0, this->size(), 0); }
+      { this->_M_erase(size_type(0), this->size()); }
 
       /**
        *  Returns true if the %string is empty.  Equivalent to *this == "".
@@ -646,7 +644,7 @@
       { 
 	const size_type __len = 1 + this->size();
 	if (__len > this->capacity() || this->_M_is_shared())
-	  this->reserve(__len);
+	  this->_M_reserve(__len);
 	traits_type::assign(this->_M_data()[this->size()], __c);
 	this->_M_set_length(__len);
       }
@@ -781,7 +779,8 @@
       */
       basic_string&
       insert(size_type __pos1, const basic_string& __str)
-      { return this->insert(__pos1, __str, size_type(0), __str.size()); }
+      { return this->replace(__pos1, size_type(0),
+			     __str._M_data(), __str.size()); }
 
       /**
        *  @brief  Insert a substring.
@@ -804,9 +803,9 @@
       basic_string&
       insert(size_type __pos1, const basic_string& __str,
 	     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)); }
+      { return this->replace(__pos1, size_type(0), __str._M_data()
+			     + __str._M_check(__pos2, "basic_string::insert"),
+			     __str._M_limit(__pos2, __n)); }
 
       /**
        *  @brief  Insert a C substring.
@@ -825,7 +824,8 @@
        *  thrown.
       */
       basic_string&
-      insert(size_type __pos, const _CharT* __s, size_type __n);
+      insert(size_type __pos, const _CharT* __s, size_type __n)
+      { return this->replace(__pos, size_type(0), __s, __n); }
 
       /**
        *  @brief  Insert a C string.
@@ -846,7 +846,8 @@
       insert(size_type __pos, const _CharT* __s)
       {
 	__glibcxx_requires_string(__s);
-	return this->insert(__pos, __s, traits_type::length(__s));
+	return this->replace(__pos, size_type(0), __s,
+			     traits_type::length(__s));
       }
 
       /**
@@ -909,8 +910,8 @@
       basic_string&
       erase(size_type __pos = 0, size_type __n = npos)
       { 
-	this->_M_mutate(_M_check(__pos, "basic_string::erase"),
-			_M_limit(__pos, __n), size_type(0));
+	this->_M_erase(_M_check(__pos, "basic_string::erase"),
+		       _M_limit(__pos, __n));
 	return *this;
       }
 
@@ -928,7 +929,7 @@
 	_GLIBCXX_DEBUG_PEDASSERT(__position >= _M_ibegin()
 				 && __position < _M_iend());
 	const size_type __pos = __position - _M_ibegin();
-	this->_M_mutate(__pos, size_type(1), size_type(0));
+	this->_M_erase(__pos, size_type(1));
 	this->_M_set_leaked();
 	return _M_ibegin() + __pos;
       }
@@ -948,7 +949,7 @@
 	_GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
 				 && __last <= _M_iend());
         const size_type __pos = __first - _M_ibegin();
-	this->_M_mutate(__pos, __last - __first, size_type(0));
+	this->_M_erase(__pos, __last - __first);
 	this->_M_set_leaked();
 	return _M_ibegin() + __pos;
       }
@@ -1230,8 +1231,8 @@
 		     _CharT __c);
 
       basic_string&
-      _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
-		      size_type __n2);
+      _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
+		 const size_type __len2);
 
     public:
 
Index: include/bits/stl_vector.h
===================================================================
--- include/bits/stl_vector.h	(revision 106945)
+++ include/bits/stl_vector.h	(working copy)
@@ -92,7 +92,11 @@
     public:
       typedef _Alloc allocator_type;
 
-      _Tp_alloc_type
+      _Tp_alloc_type&
+      _M_get_Tp_allocator()
+      { return *static_cast<_Tp_alloc_type*>(&this->_M_impl); }
+
+      const _Tp_alloc_type&
       _M_get_Tp_allocator() const
       { return *static_cast<const _Tp_alloc_type*>(&this->_M_impl); }
 
@@ -227,7 +231,7 @@
        *  @a x (for fast expansion) will not be copied.
        */
       vector(const vector& __x)
-      : _Base(__x.size(), __x.get_allocator())
+      : _Base(__x.size(), __x._M_get_Tp_allocator())
       { this->_M_impl._M_finish =
 	  std::__uninitialized_copy_a(__x.begin(), __x.end(),
 				      this->_M_impl._M_start,
@@ -246,7 +250,7 @@
        */
       template<typename _Vector>
 	vector(__gnu_cxx::__rvalref<_Vector> __x)
-	: _Base(__x.__ref.get_allocator())
+	: _Base(__x.__ref._M_get_Tp_allocator())
 	{ this->swap(__x.__ref); }
 
       /**
@@ -282,8 +286,7 @@
        */
       ~vector()
       { std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish,
-		      _M_get_Tp_allocator());
-      }
+		      _M_get_Tp_allocator()); }
 
       /**
        *  @brief  %Vector assignment operator.
Index: include/bits/stl_deque.h
===================================================================
--- include/bits/stl_deque.h	(revision 107547)
+++ include/bits/stl_deque.h	(working copy)
@@ -339,6 +339,7 @@
     operator+(ptrdiff_t __n, const _Deque_iterator<_Tp, _Ref, _Ptr>& __x)
     { return __x + __n; }
 
+
   /**
    *  @if maint
    *  Deque base class.  This class provides the unified face for %deque's
@@ -396,7 +397,11 @@
 	{ }
       };
 
-      _Tp_alloc_type
+      _Tp_alloc_type&
+      _M_get_Tp_allocator()
+      { return *static_cast<_Tp_alloc_type*>(&this->_M_impl); }
+
+      const _Tp_alloc_type&
       _M_get_Tp_allocator() const
       { return *static_cast<const _Tp_alloc_type*>(&this->_M_impl); }
 
@@ -684,7 +689,7 @@
        *  by @a x.
        */
       deque(const deque& __x)
-      : _Base(__x.get_allocator(), __x.size())
+      : _Base(__x._M_get_Tp_allocator(), __x.size())
       { std::__uninitialized_copy_a(__x.begin(), __x.end(), 
 				    this->_M_impl._M_start,
 				    _M_get_Tp_allocator()); }
@@ -701,10 +706,9 @@
        */
       template<typename _Deque>
 	deque(__gnu_cxx::__rvalref<_Deque> __x)
-	: _Base(__x.__ref.get_allocator(), 0)
-	{	this->swap(__x.__ref); }
+	: _Base(__x.__ref._M_get_Tp_allocator(), 0)
+	{ this->swap(__x.__ref); }
 
-
       /**
        *  @brief  Builds a %deque from a range.
        *  @param  first  An input iterator.
@@ -862,7 +866,8 @@
        *  in reverse element order.
        */
       reverse_iterator
-      rend() { return reverse_iterator(this->_M_impl._M_start); }
+      rend()
+      { return reverse_iterator(this->_M_impl._M_start); }
 
       /**
        *  Returns a read-only (constant) reverse iterator that points
@@ -1491,11 +1496,12 @@
       // NB: Doesn't deallocate the nodes.
       template<typename _Alloc1>
         void
-        _M_destroy_data(iterator __first, iterator __last, _Alloc1)
+        _M_destroy_data(iterator __first, iterator __last, const _Alloc1&)
         { _M_destroy_data_aux(__first, __last); }
 
       void
-      _M_destroy_data(iterator __first, iterator __last, std::allocator<_Tp>)
+      _M_destroy_data(iterator __first, iterator __last,
+		      const std::allocator<_Tp>&)
       {
 	typedef typename std::__is_scalar<value_type>::__type
 	  _Has_trivial_destructor;
Index: include/bits/basic_string.tcc
===================================================================
--- include/bits/basic_string.tcc	(revision 106945)
+++ include/bits/basic_string.tcc	(working copy)
@@ -52,26 +52,29 @@
     basic_string<_CharT, _Traits, _Alloc>::npos;
 
   template<typename _CharT, typename _Traits, typename _Alloc>
+    void
+    basic_string<_CharT, _Traits, _Alloc>::
+    reserve(size_type __res_arg)
+    {
+      if (__res_arg != this->capacity() || this->_M_is_shared())
+	{
+	  // Make sure we don't shrink below the current size.
+	  if (__res_arg < this->size())
+	    __res_arg = this->size();
+	  
+	  this->_M_reserve(__res_arg);
+	}
+    }
+
+  template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>&
     basic_string<_CharT, _Traits, _Alloc>::
     assign(const _CharT* __s, size_type __n)
     {
       __glibcxx_requires_string_len(__s, __n);
       _M_check_length(this->size(), __n, "basic_string::assign");
-      if (_M_disjunct(__s) || this->_M_is_shared())
-	return _M_replace_safe(size_type(0), this->size(), __s, __n);
-      else
-	{
-	  // Work in-place.
-	  const size_type __pos = __s - this->_M_data();
-	  if (__pos >= __n)
-	    this->_S_copy(this->_M_data(), __s, __n);
-	  else if (__pos)
-	    this->_S_move(this->_M_data(), __s, __n);
-	  this->_M_set_length(__n);
-	  return *this;
-	}
-     }
+      return _M_replace(size_type(0), this->size(), __s, __n);
+    }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>&
@@ -83,7 +86,7 @@
 	  _M_check_length(size_type(0), __n, "basic_string::append");	  
 	  const size_type __len = __n + this->size();
 	  if (__len > this->capacity() || this->_M_is_shared())
-	    this->reserve(__len);
+	    this->_M_reserve(__len);
 	  this->_S_assign(this->_M_data() + this->size(), __n, __c);
 	  this->_M_set_length(__len);
 	}
@@ -102,12 +105,12 @@
 	  const size_type __len = __n + this->size();
 	  if (__len > this->capacity() || this->_M_is_shared())
 	    {
-	      if (_M_disjunct(__s))
-		this->reserve(__len);
+	      if (this->_M_disjunct(__s))
+		this->_M_reserve(__len);
 	      else
 		{
 		  const size_type __off = __s - this->_M_data();
-		  this->reserve(__len);
+		  this->_M_reserve(__len);
 		  __s = this->_M_data() + __off;
 		}
 	    }
@@ -127,7 +130,7 @@
 	{
 	  const size_type __len = __size + this->size();
 	  if (__len > this->capacity() || this->_M_is_shared())
-	    this->reserve(__len);
+	    this->_M_reserve(__len);
 	  this->_S_copy(this->_M_data() + this->size(), __str._M_data(),
 			__size);
 	  this->_M_set_length(__len);
@@ -146,77 +149,27 @@
 	{
 	  const size_type __len = __n + this->size();
 	  if (__len > this->capacity() || this->_M_is_shared())
-	    this->reserve(__len);
+	    this->_M_reserve(__len);
 	  this->_S_copy(this->_M_data() + this->size(),
 			__str._M_data() + __pos, __n);
-	  this->_M_set_length(__len);	  
+	  this->_M_set_length(__len);
 	}
       return *this;
     }
 
-   template<typename _CharT, typename _Traits, typename _Alloc>
-     basic_string<_CharT, _Traits, _Alloc>&
-     basic_string<_CharT, _Traits, _Alloc>::
-     insert(size_type __pos, const _CharT* __s, size_type __n)
-     {
-       __glibcxx_requires_string_len(__s, __n);
-       _M_check(__pos, "basic_string::insert");
-       _M_check_length(size_type(0), __n, "basic_string::insert");
-       if (_M_disjunct(__s) || this->_M_is_shared())
-         return _M_replace_safe(__pos, size_type(0), __s, __n);
-       else
-         {
-           // Work in-place.
-           const size_type __off = __s - this->_M_data();
-           this->_M_mutate(__pos, 0, __n);
-           __s = this->_M_data() + __off;
-           _CharT* __p = this->_M_data() + __pos;
-           if (__s  + __n <= __p)
-             this->_S_copy(__p, __s, __n);
-           else if (__s >= __p)
-             this->_S_copy(__p, __s + __n, __n);
-           else
-             {
-	       const size_type __nleft = __p - __s;
-               this->_S_copy(__p, __s, __nleft);
-               this->_S_copy(__p + __nleft, __p + __n, __n - __nleft);
-             }
-           return *this;
-         }
-     }
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    basic_string<_CharT, _Traits, _Alloc>&
+    basic_string<_CharT, _Traits, _Alloc>::
+    replace(size_type __pos, size_type __n1, const _CharT* __s,
+	    size_type __n2)
+    {
+      __glibcxx_requires_string_len(__s, __n2);
+      _M_check(__pos, "basic_string::replace");
+      __n1 = _M_limit(__pos, __n1);
+      _M_check_length(__n1, __n2, "basic_string::replace");
+      return _M_replace(__pos, __n1, __s, __n2);
+    }
 
-   template<typename _CharT, typename _Traits, typename _Alloc>
-     basic_string<_CharT, _Traits, _Alloc>&
-     basic_string<_CharT, _Traits, _Alloc>::
-     replace(size_type __pos, size_type __n1, const _CharT* __s,
-	     size_type __n2)
-     {
-       __glibcxx_requires_string_len(__s, __n2);
-       _M_check(__pos, "basic_string::replace");
-       __n1 = _M_limit(__pos, __n1);
-       _M_check_length(__n1, __n2, "basic_string::replace");
-       bool __left;
-       if (_M_disjunct(__s) || this->_M_is_shared())
-         return _M_replace_safe(__pos, __n1, __s, __n2);
-       else if ((__left = __s + __n2 <= this->_M_data() + __pos)
-		|| this->_M_data() + __pos + __n1 <= __s)
-	 {
-	   // Work in-place: non-overlapping case.
-	   size_type __off = __s - this->_M_data();
-	   __left ? __off : (__off += __n2 - __n1);
-	   this->_M_mutate(__pos, __n1, __n2);
-	   this->_S_copy(this->_M_data() + __pos,
-			 this->_M_data() + __off, __n2);
-	   return *this;
-	 }
-       else
-	 {
-	   // Todo: overlapping case.
-	   const basic_string __tmp(__s, __n2);
-	   return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
-	 }
-     }
-
   template<typename _CharT, typename _Traits, typename _Alloc>
     void
     basic_string<_CharT, _Traits, _Alloc>::
@@ -227,8 +180,7 @@
       if (__size < __n)
 	this->append(__n - __size, __c);
       else if (__n < __size)
-	this->erase(__n);
-      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
+	this->_M_erase(__n, __size - __n);
     }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -241,8 +193,8 @@
 	const basic_string __s(__k1, __k2);
 	const size_type __n1 = __i2 - __i1;
 	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
-	return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
-			       __s.size());
+	return _M_replace(__i1 - _M_ibegin(), __n1, __s._M_data(),
+			  __s.size());
       }
 
   template<typename _CharT, typename _Traits, typename _Alloc>
@@ -252,7 +204,7 @@
 		   _CharT __c)
     {
       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
-      this->_M_mutate(__pos1, __n1, __n2);
+      _M_replace(__pos1, __n1, 0, __n2);
       if (__n2)
 	this->_S_assign(this->_M_data() + __pos1, __n2, __c);
       return *this;
@@ -261,15 +213,58 @@
   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>&
     basic_string<_CharT, _Traits, _Alloc>::
-    _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
-		    size_type __n2)
+    _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
+	       const size_type __len2)
     {
-      this->_M_mutate(__pos1, __n1, __n2);
-      if (__n2)
-	this->_S_copy(this->_M_data() + __pos1, __s, __n2);
+      const size_type __old_size = this->size();
+      const size_type __new_size = __old_size + __len2 - __len1;
+      const size_type __how_much = __old_size - __pos - __len1;
+      
+      if (__new_size <= this->capacity() && !this->_M_is_shared())
+	{
+	  _CharT* __p = this->_M_data() + __pos;
+	  if (__s)
+	    {
+	      if (_M_disjunct(__s))
+		{
+		  if (__how_much && __len1 != __len2)
+		    this->_S_move(__p + __len2, __p + __len1, __how_much);
+		  if (__len2)
+		    this->_S_copy(__p, __s, __len2);
+		}
+	      else
+		{
+		  // Work in-place.
+		  if (__len2 && __len2 <= __len1)
+		    this->_S_move(__p, __s, __len2);
+		  if (__how_much && __len1 != __len2)
+		    this->_S_move(__p + __len2, __p + __len1, __how_much);
+		  if (__len2 > __len1)
+		    {
+		      if (__s + __len2 <= __p + __len1)
+			this->_S_move(__p, __s, __len2);
+		      else if (__s >= __p + __len1)
+			this->_S_copy(__p, __s + __len2 - __len1, __len2);
+		      else
+			{
+			  const size_type __nleft = (__p + __len1) - __s;
+			  this->_S_move(__p, __s, __nleft);
+			  this->_S_copy(__p + __nleft, __p + __len2,
+					__len2 - __nleft);
+			}
+		    }
+		}
+	    }
+	  else if (__how_much && __len1 != __len2)
+	    this->_S_move(__p + __len2, __p + __len1, __how_much);
+	}
+      else
+	this->_M_mutate(__pos, __len1, __s, __len2);
+
+      this->_M_set_length(__new_size);
       return *this;
     }
-   
+
   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>
     operator+(const _CharT* __lhs,

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]