Return-Path: Delivered-To: apmail-stdcxx-commits-archive@www.apache.org Received: (qmail 95422 invoked from network); 22 Feb 2008 17:38:24 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 22 Feb 2008 17:38:24 -0000 Received: (qmail 84503 invoked by uid 500); 22 Feb 2008 17:38:19 -0000 Delivered-To: apmail-stdcxx-commits-archive@stdcxx.apache.org Received: (qmail 84477 invoked by uid 500); 22 Feb 2008 17:38:19 -0000 Mailing-List: contact commits-help@stdcxx.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@stdcxx.apache.org Delivered-To: mailing list commits@stdcxx.apache.org Received: (qmail 84468 invoked by uid 99); 22 Feb 2008 17:38:19 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 22 Feb 2008 09:38:19 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 22 Feb 2008 17:37:32 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 112991A9832; Fri, 22 Feb 2008 09:37:52 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r630259 - /stdcxx/branches/4.2.x/include/string.cc Date: Fri, 22 Feb 2008 17:37:51 -0000 To: commits@stdcxx.apache.org From: faridz@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080222173752.112991A9832@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: faridz Date: Fri Feb 22 09:37:43 2008 New Revision: 630259 URL: http://svn.apache.org/viewvc?rev=630259&view=rev Log: 2008-02-22 Farid Zaripov Merged r629550 from trunk with a fix for 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/branches/4.2.x/include/string.cc Modified: stdcxx/branches/4.2.x/include/string.cc URL: http://svn.apache.org/viewvc/stdcxx/branches/4.2.x/include/string.cc?rev=630259&r1=630258&r2=630259&view=diff ============================================================================== --- stdcxx/branches/4.2.x/include/string.cc (original) +++ stdcxx/branches/4.2.x/include/string.cc Fri Feb 22 09:37:43 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 _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,57 @@ _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 __delta = __cap - __s.size (); + const size_type __cap = __s3._C_grow (__s3.size (), size_type ()); // 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,6 +573,9 @@ 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 _C_string_ref_type; @@ -592,23 +601,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 +627,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 +648,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) { + const _RWSTD_SIZE_T __tmp_size = __n2 * sizeof (value_type); + __tmp = _RWSTD_STATIC_CAST (pointer, + ::operator new (__tmp_size)); + 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); + ::operator delete (__tmp); + } + 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;