You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stdcxx.apache.org by fa...@apache.org on 2008/02/20 19:11:46 UTC

svn commit: r629550 - /stdcxx/trunk/include/string.cc

Author: faridz
Date: Wed Feb 20 10:11:37 2008
New Revision: 629550

URL: http://svn.apache.org/viewvc?rev=629550&view=rev
Log:
2008-02-20 Farid Zaripov <fa...@epam.com>

	STDCXX-170
	* include/string.cc (__rw_replace): Use temporary string object
	when __first2 and __last2 are input iterators to satisfy string
	exception safety requirements (string should be unchanged if an
	exception occurs during replacing).
	(__rw_replace_aux): Correctly replacing characters in the case
	when [__first2, __last2) range belongs to the self string.

Modified:
    stdcxx/trunk/include/string.cc

Modified: stdcxx/trunk/include/string.cc
URL: http://svn.apache.org/viewvc/stdcxx/trunk/include/string.cc?rev=629550&r1=629549&r2=629550&view=diff
==============================================================================
--- stdcxx/trunk/include/string.cc (original)
+++ stdcxx/trunk/include/string.cc Wed Feb 20 10:11:37 2008
@@ -476,6 +476,8 @@
     typedef _Alloc                                allocator_type;
     typedef _TYPENAME allocator_type::size_type   size_type;
 
+    typedef _STD::basic_string<_CharT, _Traits, _Alloc> _C_string_type;
+
     typedef _RW::__string_ref<value_type, traits_type, allocator_type>
      _C_string_ref_type;
 
@@ -489,6 +491,8 @@
 replace (iterator __first1, iterator __last1,
          _InputIter __first2, _InputIter __last2, void*)
 {
+    typedef basic_string _C_string_type;
+
     basic_string &__s = *this;
 
 #  endif   // _RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES
@@ -498,55 +502,59 @@
     _RWSTD_ASSERT_RANGE (__first1, __last1);
     _RWSTD_ASSERT_RANGE (__first2, __last2);
 
+    if (__first2 == __last2) {
+        if (__first1 == __last1)
+            return __s;
+
+        const size_type __pos = __s._C_off (__first1);
+        const size_type __n = __s._C_off (__first1, __last1);
+        return __s.replace (__pos, __n, size_type (), value_type ());
+    }
+
      // use a (probably) faster algorithm if possible
     if (_STD::__is_bidirectional_iterator (_RWSTD_ITERATOR_CATEGORY(_InputIter,
                                                                     __last2)))
         return __s.__replace_aux (__first1, __last1, __first2, __last2);
 
-    for ( ; !(__first2 == __last2); ++__first1, ++__first2) {
+    _C_string_type __s3;
+    _TYPENAME _C_string_type::iterator __first3 = __s3.begin ();
+    
+    for ( ; !(__first2 == __last2); ++__first2, ++__first3) {
 
-        const size_type __off = __s._C_off (__first1);
+        const size_type __off = __s3._C_off (__first3);
 
-        _RWSTD_REQUIRES (__off <= __s.max_size (),
+        _RWSTD_REQUIRES (__off <= __s3.max_size (),
                          (_RWSTD_ERROR_LENGTH_ERROR,
                           _RWSTD_FUNC ("basic_string::replace (iterator, "
                                        "iterator, InputIterator, "
                                        "InputIterator)"),
-                          __s._C_off (__first1), __s.max_size ()));
+                          __s3._C_off (__first3), __s3.max_size ()));
          
         // extend the string if necessary
-        if (__first1 == __last1) {
+        if (__s3.end () == __first3) {
             // compute the size of new buffer
-            const size_type __cap = __s._C_grow (__s.size (), size_type ());
+            const size_type __cap = __s3._C_grow (__s3.size (), size_type ());
 
-            const size_type __delta = __cap - __s.size ();
+            const size_type __delta = __cap - __s3.size ();
 
             // allocate a new buffer
-            _C_string_ref_type *__tmp = __s._C_get_rep (__cap, __cap);
+            _C_string_ref_type *__tmp = __s3._C_get_rep (__cap, __cap);
 
             // copy data from old to new, leaving a hole for additions
-            traits_type::copy (__tmp->data (), __s._C_data, __off);
-            traits_type::copy (__tmp->data () + __off + __delta,
-                               __s._C_data + __off,
-                               __s._C_make_iter (__s._C_data + __s.size ()) 
-                               - __last1);
-            __s._C_unlink (__tmp->data ());
-            __first1 = __s._C_make_iter (__s._C_data + __off);
-            __last1  = __first1 + __delta;
+            traits_type::copy (__tmp->data (), __s3._C_data, __off);
+            __s3._C_unlink (__tmp->data ());
+            __first3 = __s3._C_make_iter (__s3._C_data + __off);
         }
 
         // copy data over
-        traits_type::assign (*__first1, *__first2);
+        traits_type::assign (*__first3, *__first2);
     }
 
-    if (!(__first1 == __last1)) {
-        const size_type __pos = __s._C_off (__first1);
-        const size_type __n   = __s._C_off (__first1, __last1);
-
-        __s.replace (__pos, __n, size_type (), value_type ());
-    }
+    const size_type __size = __s3._C_off (__first3);
+    traits_type::assign (__s3._C_data [__size], value_type ());
+    __s3._C_pref ()->_C_size._C_size = __size;
 
-    return __s;
+    return __s.__replace_aux (__first1, __last1, __s3.begin (), __s3.end ());
 }
 
 // Special function for random access and bi-directional iterators
@@ -567,10 +575,16 @@
     typedef _Alloc                                    allocator_type;
     typedef _TYPENAME allocator_type::size_type       size_type;
     typedef _TYPENAME allocator_type::difference_type difference_type;
+    typedef _TYPENAME allocator_type::pointer         pointer;
+    typedef _TYPENAME allocator_type::const_pointer   const_pointer;
+    typedef _TYPENAME allocator_type::const_reference const_reference;
 
     typedef _RW::__string_ref<value_type, traits_type, allocator_type>
     _C_string_ref_type;
 
+    typedef _RWSTD_ALLOC_TYPE (allocator_type, value_type)
+    _C_value_alloc_type;
+
 #  else   // if !defined (_RWSTD_NO_STRING_OUTLINED_MEMBER_TEMPLATES)
 
 template<class _CharT, class _Traits, class _Allocator>
@@ -592,23 +606,24 @@
     const size_type  __n2 = _DISTANCE (__first2, __last2, size_type);
     const size_type  __n  = __s._C_off (__first1, __last1);
     const size_type __pos = __s._C_off (__first1);
+    const size_type __ssize = __s.size ();
 
-    _RWSTD_REQUIRES (__pos <= __s.size (),
+    _RWSTD_REQUIRES (__pos <= __ssize,
                      (_RWSTD_ERROR_OUT_OF_RANGE,
                       _RWSTD_FUNC ("basic_string::__replace_aux (iterator, "
                                    "iterator, InputIterator, InputIterator)"),
-                      __pos, __s.size ()));
+                      __pos, __ssize));
 
-    size_type __slen = __s.size () - __pos;
+    size_type __slen = __ssize - __pos;
     size_type __xlen = __n < __slen ? __n : __slen; 
 
-    _RWSTD_REQUIRES (__s.size () - __xlen <= __s.max_size () - __n2,
+    _RWSTD_REQUIRES (__ssize - __xlen <= __s.max_size () - __n2,
                      (_RWSTD_ERROR_LENGTH_ERROR, 
                       _RWSTD_FUNC ("basic_string::__replace_aux (iterator, "
                                    "iterator, InputIterator, InputIterator)"),
-                      __s.size () - __xlen, __s.max_size () - __n2));
+                      __ssize - __xlen, __s.max_size () - __n2));
 
-    size_type __len = __s.size () - __xlen + __n2;  // Final string length.
+    size_type __len = __ssize - __xlen + __n2;  // Final string length.
 
     if (!__len) {
         // Special case a substitution that leaves the string empty.
@@ -617,13 +632,13 @@
     else {
         size_type __d = 0;
         // length of bit at the end
-        size_type __rem = __s.size () - __xlen - __pos;
-        // Check for shared representation, insufficient capacity, 
+        size_type __rem = __ssize - __xlen - __pos;
+        // Check for shared representation, insufficient capacity
         if (   __s.capacity () < __len
             || size_type (1) < size_type (__s._C_pref ()->_C_get_ref ()))
         {
             // Need to allocate a new reference.
-            const size_type __cap = __s._C_grow (__s.size (), __len);
+            const size_type __cap = __s._C_grow (__ssize, __len);
 
             _C_string_ref_type * __temp = __s._C_get_rep (__cap, __len);
             if (__pos)
@@ -638,14 +653,38 @@
         }
         else {
             // Current reference has enough room.
-            if (__rem)  
+            pointer __tmp = 0;
+
+            if (__n2) {
+                const const_pointer __ptr =
+                    &_RWSTD_REINTERPRET_CAST (const_reference, *__first2);
+
+                if (__s.data () <= __ptr && __s.data () + __ssize > __ptr) {
+                    __tmp = _RWSTD_VALUE_ALLOC (_C_value_alloc_type, __s,
+                                                allocate (__n2));
+                    for (__d = 0; __d < __n2; __d++)
+                        traits_type::assign (*(__tmp + __d), *__first2++);
+                }
+            }
+
+            if (__rem)
                 traits_type::move (__s._C_data + __pos + __n2,
                                    __s._C_data + __pos + __n, 
                                    __rem);
-            for (__d = 0; __d < __n2; __d++)
-                traits_type::assign (*(__s._C_data + __pos + __d), *__first2++);
-            traits_type::assign (__s._C_data [__s._C_pref ()->_C_size._C_size
-                                              = __len], value_type ());
+
+            if (__tmp) {
+                traits_type::copy (__s._C_data + __pos, __tmp, __n2);
+                _RWSTD_VALUE_ALLOC (_C_value_alloc_type, __s,
+                                    deallocate (__tmp, __n2));
+            }
+            else {
+                for (__d = 0; __d < __n2; __d++)
+                    traits_type::assign (*(__s._C_data + __pos + __d),
+                                         *__first2++);
+            }
+
+            __s._C_pref ()->_C_size._C_size = __len;
+            traits_type::assign (__s._C_data [__len], value_type ());
         }
     }
     return __s;