This is the mail archive of the libstdc++@gcc.gnu.org mailing list for the libstdc++ 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]

Re: [Patch] Batch of basic_string correctness and performance work


Hi Paolo,

I am seriously worried about performance improvements obtained by inlining functions. I'm not disputing the performance measurements you made below, but this type of test is very much contrived I'm sure you'll agree.

Modern microprocessor architecture is highly dependent on use of caching and branch prediction. Inlining causes the compiler to clone the code, which is detrimental to both of these:

   * increasing the amount of code means the amount of cache is
     effectively reduced
   * duplication of code means that branch prediction is no longer
     possible as branch prediction only improves beyond that of a
     random guess when the same code is evaluated

Furthermore, inlining such basic string functions could increase the amount of memory required for an application to run. Larger applications can then seriously impact system performance by increasing the amount of swapping on systems that have virtual memory. On embedded systems without virtual memory the increased code size can have a catastrophic effect if the application can no longer fit in memory.

As such I think it is very important to look at the difference in code size for optimizations as well. Could you perhaps use the "size" command to see what the difference in code size is.

Cheers,


Gawain


Paolo Carlini wrote:

Hi,

the below is the results of few days of coding and thinkering... The
inspiration, as often happens, is from Nathan: recenrly he hinted to
tweak inlining and avoid always using the heavy and non-inlinable
_M_mutate.

Then, I noticed that the existing append in basic_string.tcc were
already rather close to this objective if only I could avoid calling
_M_replace_safe and make the result sufficiently simple to be inlinable.
This I did (together with a correctness fix, noticed during the work,
and the addition of a few helpers, that clean-up remarkably the code).

To give you an idea:

21_strings/string_append.cc
===========================
current
-------
Execution time of 10000000 string::append(char) calls: 0.26 sec.
Execution time of 10000000 string::append(const string&) calls: 0.49 sec.

patched
-------
Execution time of 10000000 string::append(char) calls: 0.14 sec.
Execution time of 10000000 string::append(const string&) calls: 0.14 sec.

Also, I verified, that a typical use of +=(_CharT), in extract_float,
actually benefited from this kind of work:

27_io/ifstream_extract_float.cc (p = 12)
========================================
current
-------
14.130u 0.060s 0:14.25 99.5%    0+0k 0+0io 235pf+0w

patched
-------
13.570u 0.080s 0:13.70 99.6%    0+0k 0+0io 238pf+0w

indeed, besides the numbers, operations on strings almost disappeared from the
profile: unpatched mainline shows _M_mutate in the 4th position (after the
extract_float code itself, memchr and strtof), whereas now the first one is
_Alloc_hider::_Alloc_hider in the 9th position.


Various versions regtested x86/ia64-linux many times: I plan to n-th-check the
code again during the next few hours and commit tomorrow barring objections.


Paolo.

/////////////////

------------------------------------------------------------------------

2004-10-24 Paolo Carlini <pcarlini@suse.de>

	* include/bits/basic_string.h (_Rep::_M_is_safe, _M_check_length,
	_M_move, _M_copy, _M_assign): New, use througout.
	(operator+=(_CharT)): Define in terms of push_back.
	(append(const basic_string&)): Define here, inline, and simplify,
	don't use the full _M_replace_safe.
	(append(size_type, _CharT)): Likewise, don't use _M_replace_aux.
	(push_back): Likewise.
	(assign(const basic_string&)): Define here, inline.
	* include/bits/basic_string.tcc (append(const _CharT*, size_type):
	Fix: upon reallocation (reserve), we were copying from deallocated
	memory.
	(append(const basic_string&, size_type, size_type)): Simplify,
	don't use _M_replace_safe.
	(replace(size_type, size_type, const _CharT*, size_type)): Slightly
	tweak.
	(reserve): Likewise.
	* testsuite/21_strings/basic_string/append/char/2.cc: New.
	* testsuite/21_strings/basic_string/append/char/3.cc: Likewise.
	* testsuite/21_strings/basic_string/append/wchar_t/2.cc: Likewise.
	* testsuite/21_strings/basic_string/append/wchar_t/3.cc: Likewise.

* 21_strings/basic_string/assign/char/3.cc: Remove junk.
* 21_strings/basic_string/assign/wchar_t/3.cc: Likewise.


------------------------------------------------------------------------

diff -urN libstdc++-v3-orig/include/bits/basic_string.h libstdc++-v3/include/bits/basic_string.h
--- libstdc++-v3-orig/include/bits/basic_string.h	2004-10-21 20:17:00.000000000 +0200
+++ libstdc++-v3/include/bits/basic_string.h	2004-10-24 10:35:29.000000000 +0200
@@ -185,6 +185,14 @@
	_M_is_shared() const
        { return this->_M_refcount > 0; }

+	// True if source and destination do not overlap.
+	bool
+	_M_is_safe(const _CharT* __data, const _CharT* __s) const
+	{
+	  return (less<const _CharT*>()(__s, __data)
+		  || less<const _CharT*>()(__data + this->_M_length, __s));
+	}
+
        void
	_M_set_leaked()
        { this->_M_refcount = -1; }
@@ -302,6 +310,13 @@
	return __pos;
      }

+      void
+      _M_check_length(size_type __n1, size_type __n2, const char* __s) const
+      {
+	if (this->max_size() - (this->size() - __n1) < __n2)
+	  __throw_length_error(__N(__s));
+      }
+
      // NB: _M_limit doesn't check for a bad __pos value.
      size_type
      _M_limit(size_type __pos, size_type __off) const
@@ -310,6 +325,35 @@
	return __testoff ? __off : this->size() - __pos;
      }

+ // When __n = 1 way faster than the general multichar
+ // traits_type::copy/move/assign.
+ static void
+ _M_copy(_CharT* __d, const _CharT* __s, size_type __n)
+ {
+ if (__n == 1)
+ traits_type::assign(*__d, *__s);
+ else
+ traits_type::copy(__d, __s, __n);
+ }
+
+ static void
+ _M_move(_CharT* __d, const _CharT* __s, size_type __n)
+ {
+ if (__n == 1)
+ traits_type::assign(*__d, *__s);
+ else
+ traits_type::move(__d, __s, __n); + }
+
+ static void
+ _M_assign(_CharT* __d, size_type __n, _CharT __c)
+ {
+ if (__n == 1)
+ traits_type::assign(*__d, __c);
+ else
+ traits_type::assign(__d, __n, __c); + }
+
// _S_copy_chars is a separate template to permit specialization
// to optimize for the common case of pointers as iterators.
template<class _Iterator>
@@ -330,11 +374,11 @@


      static void
      _S_copy_chars(_CharT* __p, _CharT* __k1, _CharT* __k2)
-      { traits_type::copy(__p, __k1, __k2 - __k1); }
+      { _M_copy(__p, __k1, __k2 - __k1); }

      static void
      _S_copy_chars(_CharT* __p, const _CharT* __k1, const _CharT* __k2)
-      { traits_type::copy(__p, __k1, __k2 - __k1); }
+      { _M_copy(__p, __k1, __k2 - __k1); }

void
_M_mutate(size_type __pos, size_type __len1, size_type __len2);
@@ -721,7 +765,10 @@
*/
basic_string&
operator+=(_CharT __c)
- { return this->append(size_type(1), __c); }
+ { + this->push_back(__c);
+ return *this;
+ }


      /**
       *  @brief  Append a string to this string.
@@ -729,7 +776,19 @@
       *  @return  Reference to this string.
       */
      basic_string&
-      append(const basic_string& __str);
+      append(const basic_string& __str)
+      {
+	const size_type __size = __str.size();
+	if (__size)
+	  {
+	    const size_type __len = __size + this->size();
+	    if (__len > this->capacity() || _M_rep()->_M_is_shared())
+	      this->reserve(__len);
+	    _M_copy(_M_data() + this->size(), __str._M_data(), __size);
+	    _M_rep()->_M_set_length_and_sharable(__len);
+	  }
+	return *this;
+      }

/**
* @brief Append a substring.
@@ -777,7 +836,18 @@
*/
basic_string&
append(size_type __n, _CharT __c)
- { return _M_replace_aux(this->size(), size_type(0), __n, __c); }
+ {
+ if (__n)
+ {
+ _M_check_length(size_type(0), __n, "basic_string::append"); + const size_type __len = __n + this->size();
+ if (__len > this->capacity() || _M_rep()->_M_is_shared())
+ this->reserve(__len);
+ _M_assign(_M_data() + this->size(), __n, __c);
+ _M_rep()->_M_set_length_and_sharable(__len);
+ }
+ return *this;
+ }


/**
* @brief Append a range of characters.
@@ -798,7 +868,13 @@
*/
void
push_back(_CharT __c)
- { _M_replace_aux(this->size(), size_type(0), size_type(1), __c); }
+ { + const size_type __len = 1 + this->size();
+ if (__len > this->capacity() || _M_rep()->_M_is_shared())
+ this->reserve(__len);
+ traits_type::assign(_M_data()[this->size()], __c);
+ _M_rep()->_M_set_length_and_sharable(__len);
+ }


      /**
       *  @brief  Set value to contents of another string.
@@ -806,7 +882,18 @@
       *  @return  Reference to this string.
       */
      basic_string&
-      assign(const basic_string& __str);
+      assign(const basic_string& __str)
+      {
+	if (_M_rep() != __str._M_rep())
+	  {
+	    // XXX MT
+	    const allocator_type __a = this->get_allocator();
+	    _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
+	    _M_rep()->_M_dispose(__a);
+	    _M_data(__tmp);
+	  }
+	return *this;
+      }

      /**
       *  @brief  Set value to a substring of a string.
@@ -909,7 +996,8 @@
       *  of the string doesn't change if an error is thrown.
      */
      template<class _InputIterator>
-        void insert(iterator __p, _InputIterator __beg, _InputIterator __end)
+        void
+        insert(iterator __p, _InputIterator __beg, _InputIterator __end)
        { this->replace(__p, __p, __beg, __end); }

      /**
@@ -1370,13 +1458,10 @@
      _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_check_length(__n1, __n2, "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);
+	if (__n2)
+	  _M_assign(_M_data() + __pos1, __n2, __c);
	return *this;
      }

@@ -1385,10 +1470,8 @@
		      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);
+	if (__n2)
+	  _M_copy(_M_data() + __pos1, __s, __n2);
	return *this;
      }

diff -urN libstdc++-v3-orig/include/bits/basic_string.tcc libstdc++-v3/include/bits/basic_string.tcc
--- libstdc++-v3-orig/include/bits/basic_string.tcc	2004-10-21 23:36:37.000000000 +0200
+++ libstdc++-v3/include/bits/basic_string.tcc	2004-10-24 17:34:06.000000000 +0200
@@ -101,7 +101,7 @@
	    ++__beg;
	  }
	_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
-	traits_type::copy(__r->_M_refdata(), __buf, __len);
+	_M_copy(__r->_M_refdata(), __buf, __len);
	try
	  {
	    while (__beg != __end)
@@ -110,8 +110,7 @@
		  {
		    // Allocate more space.
		    _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
-		    traits_type::copy(__another->_M_refdata(),
-				      __r->_M_refdata(), __len);
+		    _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
		    __r->_M_destroy(__a);
		    __r = __another;
		  }
@@ -170,7 +169,7 @@
      // Check for out_of_range and length_error exceptions.
      _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
      if (__n)
-	traits_type::assign(__r->_M_refdata(), __n, __c);
+	_M_assign(__r->_M_refdata(), __n, __c);

      __r->_M_set_length_and_sharable(__n);
      return __r->_M_refdata();
@@ -243,42 +242,69 @@
  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_string<_CharT, _Traits, _Alloc>&
    basic_string<_CharT, _Traits, _Alloc>::
-    assign(const basic_string& __str)
+    assign(const _CharT* __s, size_type __n)
    {
-      if (_M_rep() != __str._M_rep())
+      __glibcxx_requires_string_len(__s, __n);
+      _M_check_length(this->size(), __n, "basic_string::assign");
+      if (_M_rep()->_M_is_safe(_M_data(), __s) || _M_rep()->_M_is_shared())
+	return _M_replace_safe(size_type(0), this->size(), __s, __n);
+      else
	{
-	  // XXX MT
-	  const allocator_type __a = this->get_allocator();
-	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
-	  _M_rep()->_M_dispose(__a);
-	  _M_data(__tmp);
+	  // Work in-place.
+	  const size_type __pos = __s - _M_data();
+	  if (__pos >= __n)
+	    traits_type::copy(_M_data(), __s, __n);
+	  else if (__pos)
+	    traits_type::move(_M_data(), __s, __n);
+	  _M_rep()->_M_set_length_and_sharable(__n);
+	  return *this;
+	}
+     }
+
+  template<typename _CharT, typename _Traits, typename _Alloc>
+    basic_string<_CharT, _Traits, _Alloc>&
+    basic_string<_CharT, _Traits, _Alloc>::
+    append(const _CharT* __s, size_type __n)
+    {
+      __glibcxx_requires_string_len(__s, __n);
+      if (__n)
+	{
+	  _M_check_length(size_type(0), __n, "basic_string::append");
+	  const size_type __len = __n + this->size();
+	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
+	    {
+	      if (_M_rep()->_M_is_safe(_M_data(), __s))
+		this->reserve(__len);
+	      else
+		{
+		  const size_type __off = __s - _M_data();
+		  this->reserve(__len);
+		  __s = _M_data() + __off;
+		}
+	    }
+	  _M_copy(_M_data() + this->size(), __s, __n);
+	  _M_rep()->_M_set_length_and_sharable(__len);
	}
      return *this;
    }

- 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);
- if (__n > this->max_size())
- __throw_length_error(__N("basic_string::assign"));
- if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
- || less<const _CharT*>()(_M_data() + this->size(), __s))
- return _M_replace_safe(size_type(0), this->size(), __s, __n);
- else
- {
- // Work in-place
- const size_type __pos = __s - _M_data();
- if (__pos >= __n)
- traits_type::copy(_M_data(), __s, __n);
- else if (__pos)
- traits_type::move(_M_data(), __s, __n);
- _M_rep()->_M_set_length_and_sharable(__n);
- return *this;
- }
- }
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ basic_string<_CharT, _Traits, _Alloc>&
+ basic_string<_CharT, _Traits, _Alloc>::
+ append(const basic_string& __str, size_type __pos, size_type __n)
+ {
+ __str._M_check(__pos, "basic_string::append");
+ __n = __str._M_limit(__pos, __n);
+ if (__n)
+ {
+ const size_type __len = __n + this->size();
+ if (__len > this->capacity() || _M_rep()->_M_is_shared())
+ this->reserve(__len);
+ _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
+ _M_rep()->_M_set_length_and_sharable(__len); + }
+ return *this;
+ }


   template<typename _CharT, typename _Traits, typename _Alloc>
     basic_string<_CharT, _Traits, _Alloc>&
@@ -287,29 +313,25 @@
     {
       __glibcxx_requires_string_len(__s, __n);
       _M_check(__pos, "basic_string::insert");
-       if (this->max_size() - this->size() < __n)
-	 __throw_length_error(__N("basic_string::insert"));
-       if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
-           || less<const _CharT*>()(_M_data() + this->size(), __s))
+       _M_check_length(size_type(0), __n, "basic_string::insert");
+       if (_M_rep()->_M_is_safe(_M_data(), __s) || _M_rep()->_M_is_shared())
         return _M_replace_safe(__pos, size_type(0), __s, __n);
       else
         {
-           // Work in-place. If _M_mutate reallocates the string, __s
-           // does not point anymore to valid data, therefore we save its
-           // offset, then we restore it.
+           // Work in-place.
           const size_type __off = __s - _M_data();
           _M_mutate(__pos, 0, __n);
           __s = _M_data() + __off;
           _CharT* __p = _M_data() + __pos;
           if (__s  + __n <= __p)
-             traits_type::copy(__p, __s, __n);
+             _M_copy(__p, __s, __n);
           else if (__s >= __p)
-             traits_type::copy(__p, __s + __n, __n);
+             _M_copy(__p, __s + __n, __n);
           else
             {
	       const size_type __nleft = __p - __s;
-               traits_type::copy(__p, __s, __nleft);
-               traits_type::copy(__p + __nleft, __p + __n, __n - __nleft);
+               _M_copy(__p, __s, __nleft);
+               _M_copy(__p + __nleft, __p + __n, __n - __nleft);
             }
           return *this;
         }
@@ -324,24 +346,18 @@
       __glibcxx_requires_string_len(__s, __n2);
       _M_check(__pos, "basic_string::replace");
       __n1 = _M_limit(__pos, __n1);
-       if (this->max_size() - (this->size() - __n1) < __n2)
-         __throw_length_error(__N("basic_string::replace"));
+       _M_check_length(__n1, __n2, "basic_string::replace");
       bool __left;
-       if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
-	   || less<const _CharT*>()(_M_data() + this->size(), __s))
+       if (_M_rep()->_M_is_safe(_M_data(), __s) || _M_rep()->_M_is_shared())
         return _M_replace_safe(__pos, __n1, __s, __n2);
       else if ((__left = __s + __n2 <= _M_data() + __pos)
		|| _M_data() + __pos + __n1 <= __s)
	 {
	   // Work in-place: non-overlapping case.
-	   const size_type __off = __s - _M_data();
+	   size_type __off = __s - _M_data();
+	   __left ? __off : (__off += __n2 - __n1);
	   _M_mutate(__pos, __n1, __n2);
-	   if (__left)
-	     traits_type::copy(_M_data() + __pos,
-			       _M_data() + __off, __n2);
-	   else
-	     traits_type::copy(_M_data() + __pos,
-			       _M_data() + __off + __n2 - __n1, __n2);
+	   _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
	   return *this;
	 }
       else
@@ -396,19 +412,19 @@
	  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);

	  if (__pos)
-	    traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
+	    _M_copy(__r->_M_refdata(), _M_data(), __pos);
	  if (__how_much)
-	    traits_type::copy(__r->_M_refdata() + __pos + __len2,
-			      _M_data() + __pos + __len1, __how_much);
+	    _M_copy(__r->_M_refdata() + __pos + __len2,
+		    _M_data() + __pos + __len1, __how_much);

	  _M_rep()->_M_dispose(__a);
	  _M_data(__r->_M_refdata());
	}
      else if (__how_much && __len1 != __len2)
	{
-	  // Work in-place
-	  traits_type::move(_M_data() + __pos + __len2,
-			    _M_data() + __pos + __len1, __how_much);
+	  // Work in-place.
+	  _M_move(_M_data() + __pos + __len2,
+		  _M_data() + __pos + __len1, __how_much);
	}
      _M_rep()->_M_set_length_and_sharable(__new_size);
    }
@@ -420,8 +436,6 @@
    {
      if (__res != this->capacity() || _M_rep()->_M_is_shared())
        {
-	  if (__res > this->max_size())
-	    __throw_length_error(__N("basic_string::reserve"));
	  // Make sure we don't shrink below the current size
	  if (__res < this->size())
	    __res = this->size();
@@ -539,7 +553,7 @@
      _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
				  __alloc);
      if (this->_M_length)
-	traits_type::copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
+	_M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);

__r->_M_set_length_and_sharable(this->_M_length);
return __r->_M_refdata();
@@ -550,9 +564,8 @@
basic_string<_CharT, _Traits, _Alloc>::
resize(size_type __n, _CharT __c)
{
- if (__n > max_size())
- __throw_length_error(__N("basic_string::resize"));
const size_type __size = this->size();
+ _M_check_length(__size, __n, "basic_string::resize");
if (__size < __n)
this->append(__n - __size, __c);
else if (__n < __size)
@@ -569,57 +582,11 @@
{
const basic_string __s(__k1, __k2);
const size_type __n1 = __i2 - __i1;
- if (this->max_size() - (this->size() - __n1) < __s.size())
- __throw_length_error(__N("basic_string::_M_replace_dispatch"));
+ _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
__s.size());
}
-
- template<typename _CharT, typename _Traits, typename _Alloc>
- basic_string<_CharT, _Traits, _Alloc>&
- basic_string<_CharT, _Traits, _Alloc>::
- append(const basic_string& __str)
- {
- // Iff appending itself, string needs to pre-reserve the
- // correct size so that _M_mutate does not clobber the
- // pointer __str._M_data() formed here.
- const size_type __size = __str.size();
- const size_type __len = __size + this->size();
- if (__len > this->capacity())
- this->reserve(__len);
- return _M_replace_safe(this->size(), size_type(0), __str._M_data(),
- __str.size());
- }
-
- template<typename _CharT, typename _Traits, typename _Alloc>
- basic_string<_CharT, _Traits, _Alloc>&
- basic_string<_CharT, _Traits, _Alloc>::
- append(const basic_string& __str, size_type __pos, size_type __n)
- {
- // Iff appending itself, string needs to pre-reserve the
- // correct size so that _M_mutate does not clobber the
- // pointer __str._M_data() formed here.
- __str._M_check(__pos, "basic_string::append");
- __n = __str._M_limit(__pos, __n);
- const size_type __len = __n + this->size();
- if (__len > this->capacity())
- this->reserve(__len);
- return _M_replace_safe(this->size(), size_type(0), __str._M_data()
- + __pos, __n);
- }
-
- template<typename _CharT, typename _Traits, typename _Alloc>
- basic_string<_CharT, _Traits, _Alloc>&
- basic_string<_CharT, _Traits, _Alloc>::
- append(const _CharT* __s, size_type __n)
- {
- __glibcxx_requires_string_len(__s, __n);
- const size_type __len = __n + this->size();
- if (__len > this->capacity())
- this->reserve(__len);
- return _M_replace_safe(this->size(), size_type(0), __s, __n);
- }
-
+ template<typename _CharT, typename _Traits, typename _Alloc>
basic_string<_CharT, _Traits, _Alloc>
operator+(const _CharT* __lhs,
@@ -659,7 +626,7 @@
__n = _M_limit(__pos, __n);
__glibcxx_requires_string_len(__s, __n);
if (__n)
- traits_type::copy(__s, _M_data() + __pos, __n);
+ _M_copy(__s, _M_data() + __pos, __n);
// 21.3.5.7 par 3: do not append null. (good.)
return __n;
}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/1.cc libstdc++-v3/testsuite/21_strings/basic_string/append/char/1.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/1.cc 2003-09-23 22:02:04.000000000 +0200
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/char/1.cc 2004-10-23 02:19:29.000000000 +0200
@@ -18,7 +18,7 @@
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.


-// 21.3.5.3 basic_string::assign
+// 21.3.5.2 basic_string::append

#include <string>
#include <stdexcept>
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/2.cc libstdc++-v3/testsuite/21_strings/basic_string/append/char/2.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/2.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/char/2.cc 2004-10-24 17:31:35.000000000 +0200
@@ -0,0 +1,67 @@
+// 2004-25-10 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.5 string modifiers
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// append(const _CharT* __s, size_type __n)
+// append(const _CharT* __s)
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ using namespace std;
+ + string one; + string two;
+ string three;
+ const char * source = "Written in your eyes";
+
+ one.append(source);
+ VERIFY( one == "Written in your eyes" );
+
+ two.append(source, 20);
+ VERIFY( two == "Written in your eyes" );
+
+ three.append(source, 7);
+ VERIFY( three == "Written" );
+ + three.clear();
+ three.append(source + 8, 2);
+ VERIFY( three == "in" );
+
+ one.append(one.c_str(), 20);
+ VERIFY( one == "Written in your eyesWritten in your eyes" );
+
+ two.append(two.c_str() + 16, 4);
+ VERIFY( two == "Written in your eyeseyes" );
+
+ two.append(two.c_str(), 3);
+ VERIFY( two == "Written in your eyeseyesWri" );
+}
+
+int main()
+{ + test02();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/3.cc libstdc++-v3/testsuite/21_strings/basic_string/append/char/3.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/char/3.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/char/3.cc 2004-10-24 17:31:40.000000000 +0200
@@ -0,0 +1,56 @@
+// 2004-25-10 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.5 string modifiers
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// Upon reallocation (basic_string::reserve) we were copying from
+// deallocated memory.
+void
+test03()
+{
+ bool test __attribute__((unused)) = true;
+
+ using namespace std;
+ + const char * source = "Kesto";
+
+ for (unsigned i = 0; i < 10; ++i)
+ {
+ string one(source);
+ string two(source);
+ for (string::size_type j = 0; j < 18; ++j)
+ {
+ VERIFY( one == two );
+ one.append(one);
+ one += 'x';
+ two.append(two.c_str(), two.size());
+ two += 'x';
+ }
+ }
+}
+
+int main()
+{ + test03();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/1.cc libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/1.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/1.cc 2003-09-23 22:02:05.000000000 +0200
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/1.cc 2004-10-23 02:19:29.000000000 +0200
@@ -18,7 +18,7 @@
// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
// USA.


-// 21.3.5.3 basic_string::assign
+// 21.3.5.2 basic_string::append

#include <string>
#include <stdexcept>
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/2.cc libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/2.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/2.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/2.cc 2004-10-24 17:31:51.000000000 +0200
@@ -0,0 +1,67 @@
+// 2004-25-10 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.5 string modifiers
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// append(const _CharT* __s, size_type __n)
+// append(const _CharT* __s)
+void
+test02()
+{
+ bool test __attribute__((unused)) = true;
+
+ using namespace std;
+ + wstring one; + wstring two;
+ wstring three;
+ const wchar_t * source = L"Written in your eyes";
+
+ one.append(source);
+ VERIFY( one == L"Written in your eyes" );
+
+ two.append(source, 20);
+ VERIFY( two == L"Written in your eyes" );
+
+ three.append(source, 7);
+ VERIFY( three == L"Written" );
+ + three.clear();
+ three.append(source + 8, 2);
+ VERIFY( three == L"in" );
+
+ one.append(one.c_str(), 20);
+ VERIFY( one == L"Written in your eyesWritten in your eyes" );
+
+ two.append(two.c_str() + 16, 4);
+ VERIFY( two == L"Written in your eyeseyes" );
+
+ two.append(two.c_str(), 3);
+ VERIFY( two == L"Written in your eyeseyesWri" );
+}
+
+int main()
+{ + test02();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/3.cc libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/3.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/append/wchar_t/3.cc 1970-01-01 01:00:00.000000000 +0100
+++ libstdc++-v3/testsuite/21_strings/basic_string/append/wchar_t/3.cc 2004-10-24 17:31:59.000000000 +0200
@@ -0,0 +1,56 @@
+// 2004-25-10 Paolo Carlini <pcarlini@suse.de>
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 2, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING. If not, write to the Free
+// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+// USA.
+
+// 21.3.5 string modifiers
+
+#include <string>
+#include <testsuite_hooks.h>
+
+// Upon reallocation (basic_string::reserve) we were copying from
+// deallocated memory.
+void
+test03()
+{
+ bool test __attribute__((unused)) = true;
+
+ using namespace std;
+ + const wchar_t * source = L"Kesto";
+
+ for (unsigned i = 0; i < 10; ++i)
+ {
+ wstring one(source);
+ wstring two(source);
+ for (wstring::size_type j = 0; j < 18; ++j)
+ {
+ VERIFY( one == two );
+ one.append(one);
+ one += L'x';
+ two.append(two.c_str(), two.size());
+ two += L'x';
+ }
+ }
+}
+
+int main()
+{ + test03();
+ return 0;
+}
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/assign/char/3.cc libstdc++-v3/testsuite/21_strings/basic_string/assign/char/3.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/assign/char/3.cc 2003-09-23 22:02:05.000000000 +0200
+++ libstdc++-v3/testsuite/21_strings/basic_string/assign/char/3.cc 2004-10-24 16:55:29.000000000 +0200
@@ -1,6 +1,6 @@
// 2001-10-30 Benjamin Kosnik <bkoz@redhat.com>


-// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
@@ -21,7 +21,6 @@
// 21.3.5 string modifiers

#include <string>
-#include <cstdio>
#include <testsuite_hooks.h>

// assign(const _CharT* __s, size_type __n)
@@ -35,7 +34,6 @@
string one; string two;
- string three = two;
const char * source = "Selling England by the pound";


  one.assign(source);
diff -urN libstdc++-v3-orig/testsuite/21_strings/basic_string/assign/wchar_t/3.cc libstdc++-v3/testsuite/21_strings/basic_string/assign/wchar_t/3.cc
--- libstdc++-v3-orig/testsuite/21_strings/basic_string/assign/wchar_t/3.cc	2003-09-23 22:02:05.000000000 +0200
+++ libstdc++-v3/testsuite/21_strings/basic_string/assign/wchar_t/3.cc	2004-10-24 16:55:19.000000000 +0200
@@ -1,6 +1,6 @@
// 2001-10-30 Benjamin Kosnik  <bkoz@redhat.com>

-// Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+// Copyright (C) 2001, 2003, 2004 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
@@ -21,7 +21,6 @@
// 21.3.5 string modifiers

#include <string>
-#include <cstdio>
#include <testsuite_hooks.h>

// assign(const _CharT* __s, size_type __n)
@@ -35,7 +34,6 @@
wstring one; wstring two;
- wstring three = two;
const wchar_t* source = L"Selling England by the pound";


one.assign(source);





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