basic_string.tcc revision 117397
197403Sobrien// Components for manipulating sequences of characters -*- C++ -*-
297403Sobrien
3117397Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
497403Sobrien// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
1997403Sobrien// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien//
3297403Sobrien// ISO C++ 14882: 21  Strings library
3397403Sobrien//
3497403Sobrien
3597403Sobrien// This file is included by <string>.  It is not meant to be included
3697403Sobrien// separately.
3797403Sobrien
3897403Sobrien// Written by Jason Merrill based upon the specification by Takanori Adachi
3997403Sobrien// in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
4097403Sobrien
4197403Sobrien#ifndef _CPP_BITS_STRING_TCC
4297403Sobrien#define _CPP_BITS_STRING_TCC 1
4397403Sobrien
4497403Sobrien#pragma GCC system_header
4597403Sobrien
4697403Sobriennamespace std
4797403Sobrien{
4897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
4997403Sobrien    const typename basic_string<_CharT, _Traits, _Alloc>::size_type 
5097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
5197403Sobrien    _Rep::_S_max_size = (((npos - sizeof(_Rep))/sizeof(_CharT)) - 1) / 4;
5297403Sobrien
5397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
5497403Sobrien    const _CharT 
5597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
5697403Sobrien    _Rep::_S_terminal = _CharT();
5797403Sobrien
5897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
5997403Sobrien    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
6097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::npos;
6197403Sobrien
6297403Sobrien  // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
6397403Sobrien  // at static init time (before static ctors are run).
6497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
6597403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
6697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_S_empty_rep_storage[
6797403Sobrien    (sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
6897403Sobrien
6997403Sobrien  // NB: This is the special case for Input Iterators, used in
7097403Sobrien  // istreambuf_iterators, etc.
7197403Sobrien  // Input Iterators have a cost structure very different from
7297403Sobrien  // pointers, calling for a different coding style.
7397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
7497403Sobrien    template<typename _InIter>
7597403Sobrien      _CharT*
7697403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
7797403Sobrien      _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
7897403Sobrien		   input_iterator_tag)
7997403Sobrien      {
8097403Sobrien	if (__beg == __end && __a == _Alloc())
8197403Sobrien	  return _S_empty_rep()._M_refcopy();
8297403Sobrien	// Avoid reallocation for common case.
8397403Sobrien	_CharT __buf[100];
8497403Sobrien	size_type __i = 0;
8597403Sobrien	while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT))
8697403Sobrien	  { 
8797403Sobrien	    __buf[__i++] = *__beg; 
8897403Sobrien	    ++__beg; 
8997403Sobrien	  }
9097403Sobrien	_Rep* __r = _Rep::_S_create(__i, __a);
9197403Sobrien	traits_type::copy(__r->_M_refdata(), __buf, __i);
9297403Sobrien	__r->_M_length = __i;
9397403Sobrien	try 
9497403Sobrien	  {
9597403Sobrien	    // NB: this loop looks precisely this way because
9697403Sobrien	    // it avoids comparing __beg != __end any more
9797403Sobrien	    // than strictly necessary; != might be expensive!
9897403Sobrien	    for (;;)
9997403Sobrien	      {
10097403Sobrien		_CharT* __p = __r->_M_refdata() + __r->_M_length;
10197403Sobrien		_CharT* __last = __r->_M_refdata() + __r->_M_capacity;
10297403Sobrien		for (;;)
10397403Sobrien		  {
10497403Sobrien		    if (__beg == __end)
10597403Sobrien		      {
10697403Sobrien			__r->_M_length = __p - __r->_M_refdata();
10797403Sobrien			*__p = _Rep::_S_terminal;       // grrr.
10897403Sobrien			return __r->_M_refdata();
10997403Sobrien		      }
11097403Sobrien		    if (__p == __last)
11197403Sobrien		      break;
11297403Sobrien		    *__p++ = *__beg; 
11397403Sobrien		    ++__beg;
11497403Sobrien		  }
11597403Sobrien		// Allocate more space.
11697403Sobrien		size_type __len = __p - __r->_M_refdata();
11797403Sobrien		_Rep* __another = _Rep::_S_create(__len + 1, __a);
11897403Sobrien		traits_type::copy(__another->_M_refdata(), 
11997403Sobrien				  __r->_M_refdata(), __len);
12097403Sobrien		__r->_M_destroy(__a);
12197403Sobrien		__r = __another;
12297403Sobrien		__r->_M_length = __len;
12397403Sobrien	      }
12497403Sobrien	  }
12597403Sobrien	catch(...) 
12697403Sobrien	  {
12797403Sobrien	    __r->_M_destroy(__a); 
12897403Sobrien	    __throw_exception_again;
12997403Sobrien	  }
13097403Sobrien	return 0;
13197403Sobrien      }
13297403Sobrien  
13397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
13497403Sobrien    template <class _InIter>
13597403Sobrien      _CharT*
13697403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
13797403Sobrien      _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, 
13897403Sobrien		   forward_iterator_tag)
13997403Sobrien      {
140107606Sobrien	if (__beg == __end && __a == _Alloc())
141107606Sobrien	  return _S_empty_rep()._M_refcopy();
142107606Sobrien
14397403Sobrien	// NB: Not required, but considered best practice.
144102782Skan	if (__builtin_expect(__beg == _InIter(), 0))
14597403Sobrien	  __throw_logic_error("attempt to create string with null pointer");
146117397Skan
147117397Skan	size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
14897403Sobrien	
14997403Sobrien	// Check for out_of_range and length_error exceptions.
15097403Sobrien	_Rep* __r = _Rep::_S_create(__dnew, __a);
15197403Sobrien	try 
15297403Sobrien	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
15397403Sobrien	catch(...) 
15497403Sobrien	  { 
15597403Sobrien	    __r->_M_destroy(__a); 
15697403Sobrien	    __throw_exception_again;
15797403Sobrien	  }
15897403Sobrien	__r->_M_length = __dnew;
15997403Sobrien
16097403Sobrien	__r->_M_refdata()[__dnew] = _Rep::_S_terminal;  // grrr.
16197403Sobrien	return __r->_M_refdata();
16297403Sobrien      }
16397403Sobrien
16497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
16597403Sobrien    _CharT*
16697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
16797403Sobrien    _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
16897403Sobrien    {
16997403Sobrien      if (__n == 0 && __a == _Alloc())
17097403Sobrien	return _S_empty_rep()._M_refcopy();
17197403Sobrien
17297403Sobrien      // Check for out_of_range and length_error exceptions.
17397403Sobrien      _Rep* __r = _Rep::_S_create(__n, __a);
17497403Sobrien      try 
17597403Sobrien	{ 
17697403Sobrien	  if (__n) 
17797403Sobrien	    traits_type::assign(__r->_M_refdata(), __n, __c); 
17897403Sobrien	}
17997403Sobrien      catch(...) 
18097403Sobrien	{ 
18197403Sobrien	  __r->_M_destroy(__a); 
18297403Sobrien	  __throw_exception_again;
18397403Sobrien	}
18497403Sobrien      __r->_M_length = __n;
18597403Sobrien      __r->_M_refdata()[__n] = _Rep::_S_terminal;  // grrr
18697403Sobrien      return __r->_M_refdata();
18797403Sobrien    }
18897403Sobrien
18997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
19097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
19197403Sobrien    basic_string(const basic_string& __str)
19297403Sobrien    : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()),
19397403Sobrien		 __str.get_allocator())
19497403Sobrien    { }
19597403Sobrien
19697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
19797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
19897403Sobrien    basic_string(const _Alloc& __a)
19997403Sobrien    : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
20097403Sobrien    { }
20197403Sobrien 
20297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
20397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
20497403Sobrien    basic_string(const basic_string& __str, size_type __pos, size_type __n)
20597403Sobrien    : _M_dataplus(_S_construct(__str._M_check(__pos), 
20697403Sobrien			       __str._M_fold(__pos, __n), _Alloc()), _Alloc())
20797403Sobrien    { }
20897403Sobrien
20997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
21097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
21197403Sobrien    basic_string(const basic_string& __str, size_type __pos,
21297403Sobrien		 size_type __n, const _Alloc& __a)
21397403Sobrien    : _M_dataplus(_S_construct(__str._M_check(__pos), 
21497403Sobrien			       __str._M_fold(__pos, __n), __a), __a)
21597403Sobrien    { }
21697403Sobrien
21797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
21897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
21997403Sobrien    basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
22097403Sobrien    : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
22197403Sobrien    { }
22297403Sobrien
22397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
22497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
22597403Sobrien    basic_string(const _CharT* __s, const _Alloc& __a)
226107606Sobrien    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
227107606Sobrien			       __s + npos, __a), __a)
22897403Sobrien    { }
22997403Sobrien
23097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
23197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
23297403Sobrien    basic_string(size_type __n, _CharT __c, const _Alloc& __a)
23397403Sobrien    : _M_dataplus(_S_construct(__n, __c, __a), __a)
23497403Sobrien    { }
23597403Sobrien 
23697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
23797403Sobrien    template<typename _InputIter>
23897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
23997403Sobrien    basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a)
24097403Sobrien    : _M_dataplus(_S_construct(__beg, __end, __a), __a)
24197403Sobrien    { }
24297403Sobrien
24397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
24497403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
24597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str)
24697403Sobrien    {
24797403Sobrien      if (_M_rep() != __str._M_rep())
24897403Sobrien	{
24997403Sobrien	  // XXX MT
25097403Sobrien	  allocator_type __a = this->get_allocator();
25197403Sobrien	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
25297403Sobrien	  _M_rep()->_M_dispose(__a);
25397403Sobrien	  _M_data(__tmp);
25497403Sobrien	}
25597403Sobrien      return *this;
25697403Sobrien    }
257117397Skan
258117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
259117397Skan     basic_string<_CharT, _Traits, _Alloc>&
260117397Skan     basic_string<_CharT, _Traits, _Alloc>::
261117397Skan     assign(const basic_string& __str, size_type __pos, size_type __n)
262117397Skan     {
263117397Skan       const size_type __strsize = __str.size();
264117397Skan       if (__pos > __strsize)
265117397Skan	 __throw_out_of_range("basic_string::assign");
266117397Skan       const bool __testn = __n < __strsize - __pos;
267117397Skan       const size_type __newsize = __testn ? __n : __strsize - __pos;
268117397Skan       return this->assign(__str._M_data() + __pos, __newsize);
269117397Skan     }
270117397Skan
271117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
272117397Skan     basic_string<_CharT, _Traits, _Alloc>&
273117397Skan     basic_string<_CharT, _Traits, _Alloc>::
274117397Skan     assign(const _CharT* __s, size_type __n)
275117397Skan     {
276117397Skan       if (__n > this->max_size())
277117397Skan	 __throw_length_error("basic_string::assign");
278117397Skan       if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
279117397Skan	   || less<const _CharT*>()(_M_data() + this->size(), __s))
280117397Skan	 return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n);
281117397Skan       else
282117397Skan	 {
283117397Skan	   // Work in-place
284117397Skan	   const size_type __pos = __s - _M_data();
285117397Skan	   if (__pos >= __n)
286117397Skan	     traits_type::copy(_M_data(), __s, __n);
287117397Skan	   else if (__pos)
288117397Skan	     traits_type::move(_M_data(), __s, __n);
289117397Skan	   _M_rep()->_M_length = __n;
290117397Skan	   _M_data()[__n] = _Rep::_S_terminal;  // grr.
291117397Skan	   return *this;
292117397Skan	 }
293117397Skan     }
294117397Skan
295117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
296117397Skan     basic_string<_CharT, _Traits, _Alloc>&
297117397Skan     basic_string<_CharT, _Traits, _Alloc>::
298117397Skan     insert(size_type __pos1, const basic_string& __str,
299117397Skan            size_type __pos2, size_type __n)
300117397Skan     {
301117397Skan       const size_type __strsize = __str.size();
302117397Skan       if (__pos2 > __strsize)
303117397Skan	 __throw_out_of_range("basic_string::insert");
304117397Skan       const bool __testn = __n < __strsize - __pos2;
305117397Skan       const size_type __newsize = __testn ? __n : __strsize - __pos2;
306117397Skan       return this->insert(__pos1, __str._M_data() + __pos2, __newsize);
307117397Skan     }
308117397Skan
309117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
310117397Skan     basic_string<_CharT, _Traits, _Alloc>&
311117397Skan     basic_string<_CharT, _Traits, _Alloc>::
312117397Skan     insert(size_type __pos, const _CharT* __s, size_type __n)
313117397Skan     {
314117397Skan       const size_type __size = this->size();
315117397Skan       if (__pos > __size)
316117397Skan         __throw_out_of_range("basic_string::insert");
317117397Skan       if (__size > this->max_size() - __n)
318117397Skan         __throw_length_error("basic_string::insert");
319117397Skan       if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
320117397Skan           || less<const _CharT*>()(_M_data() + __size, __s))
321117397Skan         return _M_replace_safe(_M_ibegin() + __pos, _M_ibegin() + __pos,
322117397Skan                                __s, __s + __n);
323117397Skan       else
324117397Skan         {
325117397Skan           // Work in-place. If _M_mutate reallocates the string, __s
326117397Skan           // does not point anymore to valid data, therefore we save its
327117397Skan           // offset, then we restore it.
328117397Skan           const size_type __off = __s - _M_data();
329117397Skan           _M_mutate(__pos, 0, __n);
330117397Skan           __s = _M_data() + __off;
331117397Skan           _CharT* __p = _M_data() + __pos;
332117397Skan           if (__s  + __n <= __p)
333117397Skan             traits_type::copy(__p, __s, __n);
334117397Skan           else if (__s >= __p)
335117397Skan             traits_type::copy(__p, __s + __n, __n);
336117397Skan           else
337117397Skan             {
338117397Skan               traits_type::copy(__p, __s, __p - __s);
339117397Skan               traits_type::copy(__p + (__p-__s), __p + __n, __n - (__p-__s));
340117397Skan             }
341117397Skan           return *this;
342117397Skan         }
343117397Skan     }
344117397Skan 
345117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
346117397Skan     basic_string<_CharT, _Traits, _Alloc>&
347117397Skan     basic_string<_CharT, _Traits, _Alloc>::
348117397Skan     replace(size_type __pos, size_type __n1, const _CharT* __s,
349117397Skan	     size_type __n2)
350117397Skan     {
351117397Skan       const size_type __size = this->size();
352117397Skan       if (__pos > __size)
353117397Skan         __throw_out_of_range("basic_string::replace");
354117397Skan       const bool __testn1 = __n1 < __size - __pos;
355117397Skan       const size_type __foldn1 = __testn1 ? __n1 : __size - __pos;
356117397Skan       if (__size - __foldn1 > this->max_size() - __n2)
357117397Skan         __throw_length_error("basic_string::replace");
358117397Skan       if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
359117397Skan           || less<const _CharT*>()(_M_data() + __size, __s))
360117397Skan         return _M_replace_safe(_M_ibegin() + __pos,
361117397Skan				_M_ibegin() + __pos + __foldn1, __s, __s + __n2);
362117397Skan       // Todo: optimized in-place replace.
363117397Skan       else
364117397Skan	 return _M_replace(_M_ibegin() + __pos, _M_ibegin() + __pos + __foldn1,
365117397Skan			   __s, __s + __n2,
366117397Skan			   typename iterator_traits<const _CharT*>::iterator_category());
367117397Skan     }
36897403Sobrien  
36997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
37097403Sobrien    void
37197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
37297403Sobrien    _M_destroy(const _Alloc& __a) throw ()
37397403Sobrien    {
37497403Sobrien      size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT);
37597403Sobrien      _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
37697403Sobrien    }
37797403Sobrien
37897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
37997403Sobrien    void
38097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
38197403Sobrien    {
38297403Sobrien      if (_M_rep()->_M_is_shared()) 
38397403Sobrien	_M_mutate(0, 0, 0);
38497403Sobrien      _M_rep()->_M_set_leaked();
38597403Sobrien    }
38697403Sobrien
38797403Sobrien  // _M_mutate and, below, _M_clone, include, in the same form, an exponential
38897403Sobrien  // growth policy, necessary to meet amortized linear time requirements of
38997403Sobrien  // the library: see http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
39097403Sobrien  // The policy is active for allocations requiring an amount of memory above
39197403Sobrien  // system pagesize. This is consistent with the requirements of the standard:
39297403Sobrien  // see, f.i., http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
39397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
39497403Sobrien    void
39597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
39697403Sobrien    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
39797403Sobrien    {
39897403Sobrien      size_type       __old_size = this->size();
39997403Sobrien      const size_type __new_size = __old_size + __len2 - __len1;
40097403Sobrien      const _CharT*        __src = _M_data()  + __pos + __len1;
40197403Sobrien      const size_type __how_much = __old_size - __pos - __len1;
40297403Sobrien      
40397403Sobrien      if (_M_rep()->_M_is_shared() || __new_size > capacity())
40497403Sobrien	{
40597403Sobrien	  // Must reallocate.
40697403Sobrien	  allocator_type __a = get_allocator();
40797403Sobrien	  // See below (_S_create) for the meaning and value of these
40897403Sobrien	  // constants.
40997403Sobrien	  const size_type __pagesize = 4096;
41097403Sobrien	  const size_type __malloc_header_size = 4 * sizeof (void*);
41197403Sobrien	  // The biggest string which fits in a memory page
41297403Sobrien	  const size_type __page_capacity = (__pagesize - __malloc_header_size
41397403Sobrien					     - sizeof(_Rep) - sizeof(_CharT)) 
41497403Sobrien	    				     / sizeof(_CharT);
41597403Sobrien	  _Rep* __r;
41697403Sobrien	  if (__new_size > capacity() && __new_size > __page_capacity)
41797403Sobrien	    // Growing exponentially.
41897403Sobrien	    __r = _Rep::_S_create(__new_size > 2*capacity() ?
41997403Sobrien				  __new_size : 2*capacity(), __a);
42097403Sobrien	  else
42197403Sobrien	    __r = _Rep::_S_create(__new_size, __a);
42297403Sobrien	  try 
42397403Sobrien	    {
42497403Sobrien	      if (__pos)
42597403Sobrien		traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
42697403Sobrien	      if (__how_much)
42797403Sobrien		traits_type::copy(__r->_M_refdata() + __pos + __len2, 
42897403Sobrien				  __src, __how_much);
42997403Sobrien	    }
43097403Sobrien	  catch(...) 
43197403Sobrien	    { 
43297403Sobrien	      __r->_M_dispose(get_allocator()); 
43397403Sobrien	      __throw_exception_again;
43497403Sobrien	    }
43597403Sobrien	  _M_rep()->_M_dispose(__a);
43697403Sobrien	  _M_data(__r->_M_refdata());
43797403Sobrien      }
43897403Sobrien      else if (__how_much && __len1 != __len2)
43997403Sobrien	{
44097403Sobrien	  // Work in-place
44197403Sobrien	  traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
44297403Sobrien	}
44397403Sobrien      _M_rep()->_M_set_sharable();
44497403Sobrien      _M_rep()->_M_length = __new_size;
44597403Sobrien      _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
44697403Sobrien    // You cannot leave those LWG people alone for a second.
44797403Sobrien    }
44897403Sobrien  
44997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
45097403Sobrien    void
45197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
45297403Sobrien    {
45397403Sobrien      if (__res > this->capacity() || _M_rep()->_M_is_shared())
45497403Sobrien        {
45597403Sobrien	  if (__res > this->max_size())
45697403Sobrien	    __throw_length_error("basic_string::reserve");
45797403Sobrien	  // Make sure we don't shrink below the current size
45897403Sobrien	  if (__res < this->size())
45997403Sobrien	    __res = this->size();
46097403Sobrien	  allocator_type __a = get_allocator();
46197403Sobrien	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
46297403Sobrien	  _M_rep()->_M_dispose(__a);
46397403Sobrien	  _M_data(__tmp);
46497403Sobrien        }
46597403Sobrien    }
46697403Sobrien  
46797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
46897403Sobrien    void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
46997403Sobrien    {
47097403Sobrien      if (_M_rep()->_M_is_leaked()) 
47197403Sobrien	_M_rep()->_M_set_sharable();
47297403Sobrien      if (__s._M_rep()->_M_is_leaked()) 
47397403Sobrien	__s._M_rep()->_M_set_sharable();
47497403Sobrien      if (this->get_allocator() == __s.get_allocator())
47597403Sobrien	{
47697403Sobrien	  _CharT* __tmp = _M_data();
47797403Sobrien	  _M_data(__s._M_data());
47897403Sobrien	  __s._M_data(__tmp);
47997403Sobrien	}
48097403Sobrien      // The code below can usually be optimized away.
48197403Sobrien      else 
48297403Sobrien	{
48397403Sobrien	  basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
48497403Sobrien	  basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 
48597403Sobrien			      this->get_allocator());
48697403Sobrien	  *this = __tmp2;
48797403Sobrien	  __s = __tmp1;
48897403Sobrien	}
48997403Sobrien    }
49097403Sobrien
49197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
49297403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
49397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
49497403Sobrien    _S_create(size_t __capacity, const _Alloc& __alloc)
49597403Sobrien    {
49697403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
49797403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
49897403Sobrien      // 83.  String::npos vs. string::max_size()
49997403Sobrien      if (__capacity > _S_max_size)
50097403Sobrien#else
50197403Sobrien      if (__capacity == npos)
50297403Sobrien#endif
50397403Sobrien	__throw_length_error("basic_string::_S_create");
50497403Sobrien
50597403Sobrien      // NB: Need an array of char_type[__capacity], plus a
50697403Sobrien      // terminating null char_type() element, plus enough for the
50797403Sobrien      // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
50897403Sobrien      size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
50997403Sobrien
51097403Sobrien      // The standard places no restriction on allocating more memory
51197403Sobrien      // than is strictly needed within this layer at the moment or as
51297403Sobrien      // requested by an explicit application call to reserve().  Many
51397403Sobrien      // malloc implementations perform quite poorly when an
51497403Sobrien      // application attempts to allocate memory in a stepwise fashion
51597403Sobrien      // growing each allocation size by only 1 char.  Additionally,
51697403Sobrien      // it makes little sense to allocate less linear memory than the
51797403Sobrien      // natural blocking size of the malloc implementation.
51897403Sobrien      // Unfortunately, we would need a somewhat low-level calculation
51997403Sobrien      // with tuned parameters to get this perfect for any particular
52097403Sobrien      // malloc implementation.  Fortunately, generalizations about
52197403Sobrien      // common features seen among implementations seems to suffice.
52297403Sobrien
52397403Sobrien      // __pagesize need not match the actual VM page size for good
52497403Sobrien      // results in practice, thus we pick a common value on the low
52597403Sobrien      // side.  __malloc_header_size is an estimate of the amount of
52697403Sobrien      // overhead per memory allocation (in practice seen N * sizeof
52797403Sobrien      // (void*) where N is 0, 2 or 4).  According to folklore,
52897403Sobrien      // picking this value on the high side is better than
52997403Sobrien      // low-balling it (especially when this algorithm is used with
53097403Sobrien      // malloc implementations that allocate memory blocks rounded up
53197403Sobrien      // to a size which is a power of 2).
53297403Sobrien      const size_t __pagesize = 4096; // must be 2^i * __subpagesize
53397403Sobrien      const size_t __subpagesize = 128; // should be >> __malloc_header_size
53497403Sobrien      const size_t __malloc_header_size = 4 * sizeof (void*);
53597403Sobrien      if ((__size + __malloc_header_size) > __pagesize)
53697403Sobrien	{
53797403Sobrien	  size_t __extra =
53897403Sobrien	    (__pagesize - ((__size + __malloc_header_size) % __pagesize))
53997403Sobrien	    % __pagesize;
54097403Sobrien	  __capacity += __extra / sizeof(_CharT);
54197403Sobrien	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
54297403Sobrien	}
54397403Sobrien      else if (__size > __subpagesize)
54497403Sobrien	{
54597403Sobrien	  size_t __extra =
54697403Sobrien	    (__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
54797403Sobrien	    % __subpagesize;
54897403Sobrien	  __capacity += __extra / sizeof(_CharT);
54997403Sobrien	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
55097403Sobrien	}
55197403Sobrien
55297403Sobrien      // NB: Might throw, but no worries about a leak, mate: _Rep()
55397403Sobrien      // does not throw.
55497403Sobrien      void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
55597403Sobrien      _Rep *__p = new (__place) _Rep;
55697403Sobrien      __p->_M_capacity = __capacity;
55797403Sobrien      __p->_M_set_sharable();  // One reference.
55897403Sobrien      __p->_M_length = 0;
55997403Sobrien      return __p;
56097403Sobrien    }
56197403Sobrien
56297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
56397403Sobrien    _CharT*
56497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
56597403Sobrien    _M_clone(const _Alloc& __alloc, size_type __res)
56697403Sobrien    {
56797403Sobrien      // Requested capacity of the clone.
56897403Sobrien      const size_type __requested_cap = _M_length + __res;
56997403Sobrien      // See above (_S_create) for the meaning and value of these constants.
57097403Sobrien      const size_type __pagesize = 4096;
57197403Sobrien      const size_type __malloc_header_size = 4 * sizeof (void*);
57297403Sobrien      // The biggest string which fits in a memory page.
57397403Sobrien      const size_type __page_capacity =
57497403Sobrien        (__pagesize - __malloc_header_size - sizeof(_Rep) - sizeof(_CharT))
57597403Sobrien        / sizeof(_CharT);
57697403Sobrien      _Rep* __r;
57797403Sobrien      if (__requested_cap > _M_capacity && __requested_cap > __page_capacity)
57897403Sobrien        // Growing exponentially.
57997403Sobrien        __r = _Rep::_S_create(__requested_cap > 2*_M_capacity ?
58097403Sobrien                              __requested_cap : 2*_M_capacity, __alloc);
58197403Sobrien      else
58297403Sobrien        __r = _Rep::_S_create(__requested_cap, __alloc);
58397403Sobrien      
58497403Sobrien      if (_M_length)
58597403Sobrien	{
58697403Sobrien	  try 
58797403Sobrien	    { traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); }
58897403Sobrien	  catch(...)  
58997403Sobrien	    { 
59097403Sobrien	      __r->_M_destroy(__alloc); 
59197403Sobrien	      __throw_exception_again;
59297403Sobrien	    }
59397403Sobrien	}
59497403Sobrien      __r->_M_length = _M_length;
59597403Sobrien      return __r->_M_refdata();
59697403Sobrien    }
59797403Sobrien  
59897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
59997403Sobrien    void
60097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
60197403Sobrien    {
60297403Sobrien      if (__n > max_size())
60397403Sobrien	__throw_length_error("basic_string::resize");
60497403Sobrien      size_type __size = this->size();
60597403Sobrien      if (__size < __n)
60697403Sobrien	this->append(__n - __size, __c);
60797403Sobrien      else if (__n < __size)
60897403Sobrien	this->erase(__n);
60997403Sobrien      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
61097403Sobrien    }
611102782Skan
612102782Skan  // This is the general replace helper, which currently gets instantiated both
613102782Skan  // for input iterators and reverse iterators. It buffers internally and then
614102782Skan  // calls _M_replace_safe.
61597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
61697403Sobrien    template<typename _InputIter>
61797403Sobrien      basic_string<_CharT, _Traits, _Alloc>&
61897403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
61997403Sobrien      _M_replace(iterator __i1, iterator __i2, _InputIter __k1, 
62097403Sobrien		 _InputIter __k2, input_iterator_tag)
62197403Sobrien      {
62297403Sobrien	// Save concerned source string data in a temporary.
62397403Sobrien	basic_string __s(__k1, __k2);
62497403Sobrien	return _M_replace_safe(__i1, __i2, __s._M_ibegin(), __s._M_iend());
62597403Sobrien      }
62697403Sobrien
62797403Sobrien  // This is a special replace helper, which does not buffer internally
628102782Skan  // and can be used in "safe" situations involving forward iterators,
62997403Sobrien  // i.e., when source and destination ranges are known to not overlap.
63097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
63197403Sobrien    template<typename _ForwardIter>
63297403Sobrien      basic_string<_CharT, _Traits, _Alloc>&
63397403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
63497403Sobrien      _M_replace_safe(iterator __i1, iterator __i2, _ForwardIter __k1, 
63597403Sobrien		      _ForwardIter __k2)
63697403Sobrien      {
637117397Skan	size_type __dnew = static_cast<size_type>(std::distance(__k1, __k2));
63897403Sobrien	size_type __dold = __i2 - __i1;
63997403Sobrien	size_type __dmax = this->max_size();
64097403Sobrien
64197403Sobrien	if (__dmax <= __dnew)
64297403Sobrien	  __throw_length_error("basic_string::_M_replace");
64397403Sobrien	size_type __off = __i1 - _M_ibegin();
64497403Sobrien	_M_mutate(__off, __dold, __dnew);
64597403Sobrien
64697403Sobrien	// Invalidated __i1, __i2
64797403Sobrien        if (__dnew)
64897403Sobrien	  _S_copy_chars(_M_data() + __off, __k1, __k2);
64997403Sobrien
65097403Sobrien	return *this;
65197403Sobrien      }
65297403Sobrien
65397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
65497403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
65597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
65697403Sobrien    replace(size_type __pos1, size_type __n1, const basic_string& __str,
65797403Sobrien	    size_type __pos2, size_type __n2)
65897403Sobrien    {
65997403Sobrien      const size_type __strsize = __str.size();
66097403Sobrien      if (__pos2 > __strsize)
66197403Sobrien	__throw_out_of_range("basic_string::replace");
66297403Sobrien      const bool __testn2 = __n2 < __strsize - __pos2;
66397403Sobrien      const size_type __foldn2 = __testn2 ? __n2 : __strsize - __pos2;
66497403Sobrien      return this->replace(__pos1, __n1,
66597403Sobrien			   __str._M_data() + __pos2, __foldn2);      
66697403Sobrien    }
66797403Sobrien
66897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
66997403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
67097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
67197403Sobrien    append(const basic_string& __str)
67297403Sobrien    {
67397403Sobrien      // Iff appending itself, string needs to pre-reserve the
67497403Sobrien      // correct size so that _M_mutate does not clobber the
67597403Sobrien      // iterators formed here.
67697403Sobrien      size_type __size = __str.size();
67797403Sobrien      size_type __len = __size + this->size();
67897403Sobrien      if (__len > this->capacity())
67997403Sobrien	this->reserve(__len);
68097403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_ibegin(),
68197403Sobrien			     __str._M_iend());
68297403Sobrien    }
68397403Sobrien
68497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
68597403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
68697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
68797403Sobrien    append(const basic_string& __str, size_type __pos, size_type __n)
68897403Sobrien    {
68997403Sobrien      // Iff appending itself, string needs to pre-reserve the
69097403Sobrien      // correct size so that _M_mutate does not clobber the
69197403Sobrien      // iterators formed here.
692117397Skan      size_type __len = std::min(size_type(__str.size() - __pos),
693117397Skan				 __n) + this->size();
69497403Sobrien      if (__len > this->capacity())
69597403Sobrien	this->reserve(__len);
69697403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_check(__pos),
69797403Sobrien			     __str._M_fold(__pos, __n));
69897403Sobrien    }
69997403Sobrien
70097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
70197403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
70297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
70397403Sobrien    append(const _CharT* __s, size_type __n)
70497403Sobrien    {
70597403Sobrien      size_type __len = __n + this->size();
70697403Sobrien      if (__len > this->capacity())
70797403Sobrien	this->reserve(__len);
70897403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __s, __s + __n);
70997403Sobrien    }
71097403Sobrien
71197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
71297403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
71397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
71497403Sobrien    append(size_type __n, _CharT __c)
71597403Sobrien    {
71697403Sobrien      size_type __len = __n + this->size();
71797403Sobrien      if (__len > this->capacity())
71897403Sobrien	this->reserve(__len);
71997403Sobrien       return this->replace(_M_iend(), _M_iend(), __n, __c);
72097403Sobrien    }
72197403Sobrien
72297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
72397403Sobrien    basic_string<_CharT, _Traits, _Alloc>
72497403Sobrien    operator+(const _CharT* __lhs,
72597403Sobrien	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
72697403Sobrien    {
72797403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
72897403Sobrien      typedef typename __string_type::size_type	  __size_type;
72997403Sobrien      __size_type __len = _Traits::length(__lhs);
73097403Sobrien      __string_type __str;
73197403Sobrien      __str.reserve(__len + __rhs.size());
73297403Sobrien      __str.append(__lhs, __lhs + __len);
73397403Sobrien      __str.append(__rhs);
73497403Sobrien      return __str;
73597403Sobrien    }
73697403Sobrien
73797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
73897403Sobrien    basic_string<_CharT, _Traits, _Alloc>
73997403Sobrien    operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
74097403Sobrien    {
74197403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
74297403Sobrien      typedef typename __string_type::size_type	  __size_type;
74397403Sobrien      __string_type __str;
74497403Sobrien      __size_type __len = __rhs.size();
74597403Sobrien      __str.reserve(__len + 1);
74697403Sobrien      __str.append(__size_type(1), __lhs);
74797403Sobrien      __str.append(__rhs);
74897403Sobrien      return __str;
74997403Sobrien    }
75097403Sobrien
75197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
75297403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
75397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
75497403Sobrien    replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
75597403Sobrien    {
75697403Sobrien      size_type __n1 = __i2 - __i1;
75797403Sobrien      size_type __off1 = __i1 - _M_ibegin();
75897403Sobrien      if (max_size() - (this->size() - __n1) <= __n2)
75997403Sobrien	__throw_length_error("basic_string::replace");
76097403Sobrien      _M_mutate (__off1, __n1, __n2);
76197403Sobrien      // Invalidated __i1, __i2
76297403Sobrien      if (__n2)
76397403Sobrien	traits_type::assign(_M_data() + __off1, __n2, __c);
76497403Sobrien      return *this;
76597403Sobrien    }
76697403Sobrien  
76797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
76897403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
76997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
77097403Sobrien    copy(_CharT* __s, size_type __n, size_type __pos) const
77197403Sobrien    {
77297403Sobrien      if (__pos > this->size())
77397403Sobrien	__throw_out_of_range("basic_string::copy");
77497403Sobrien      
77597403Sobrien      if (__n > this->size() - __pos)
77697403Sobrien	__n = this->size() - __pos;
77797403Sobrien      
77897403Sobrien      traits_type::copy(__s, _M_data() + __pos, __n);
77997403Sobrien      // 21.3.5.7 par 3: do not append null.  (good.)
78097403Sobrien      return __n;
78197403Sobrien    }
78297403Sobrien
78397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
78497403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
78597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
78697403Sobrien    find(const _CharT* __s, size_type __pos, size_type __n) const
78797403Sobrien    {
78897403Sobrien      size_type __size = this->size();
78997403Sobrien      size_t __xpos = __pos;
79097403Sobrien      const _CharT* __data = _M_data();
79197403Sobrien      for (; __xpos + __n <= __size; ++__xpos)
79297403Sobrien	if (traits_type::compare(__data + __xpos, __s, __n) == 0)
79397403Sobrien	  return __xpos;
79497403Sobrien      return npos;
79597403Sobrien    }
79697403Sobrien
79797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
79897403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
79997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
80097403Sobrien    find(_CharT __c, size_type __pos) const
80197403Sobrien    {
80297403Sobrien      size_type __size = this->size();
80397403Sobrien      size_type __ret = npos;
80497403Sobrien      if (__pos < __size)
80597403Sobrien	{
80697403Sobrien	  const _CharT* __data = _M_data();
80797403Sobrien	  size_type __n = __size - __pos;
80897403Sobrien	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
80997403Sobrien	  if (__p)
81097403Sobrien	    __ret = __p - __data;
81197403Sobrien	}
81297403Sobrien      return __ret;
81397403Sobrien    }
81497403Sobrien
81597403Sobrien
81697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
81797403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
81897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
81997403Sobrien    rfind(const _CharT* __s, size_type __pos, size_type __n) const
82097403Sobrien    {
82197403Sobrien      size_type __size = this->size();
82297403Sobrien      if (__n <= __size)
82397403Sobrien	{
824117397Skan	  __pos = std::min(size_type(__size - __n), __pos);
82597403Sobrien	  const _CharT* __data = _M_data();
82697403Sobrien	  do 
82797403Sobrien	    {
82897403Sobrien	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
82997403Sobrien		return __pos;
83097403Sobrien	    } 
83197403Sobrien	  while (__pos-- > 0);
83297403Sobrien	}
83397403Sobrien      return npos;
83497403Sobrien    }
83597403Sobrien  
83697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
83797403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
83897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
83997403Sobrien    rfind(_CharT __c, size_type __pos) const
84097403Sobrien    {
84197403Sobrien      size_type __size = this->size();
84297403Sobrien      if (__size)
84397403Sobrien	{
84497403Sobrien	  size_t __xpos = __size - 1;
84597403Sobrien	  if (__xpos > __pos)
84697403Sobrien	    __xpos = __pos;
84797403Sobrien      
84897403Sobrien	  for (++__xpos; __xpos-- > 0; )
84997403Sobrien	    if (traits_type::eq(_M_data()[__xpos], __c))
85097403Sobrien	      return __xpos;
85197403Sobrien	}
85297403Sobrien      return npos;
85397403Sobrien    }
85497403Sobrien  
85597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
85697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
85797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
85897403Sobrien    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
85997403Sobrien    {
86097403Sobrien      for (; __n && __pos < this->size(); ++__pos)
86197403Sobrien	{
86297403Sobrien	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
86397403Sobrien	  if (__p)
86497403Sobrien	    return __pos;
86597403Sobrien	}
86697403Sobrien      return npos;
86797403Sobrien    }
86897403Sobrien 
86997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
87097403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
87197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
87297403Sobrien    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
87397403Sobrien    {
87497403Sobrien      size_type __size = this->size();
87597403Sobrien      if (__size && __n)
87697403Sobrien	{ 
87797403Sobrien	  if (--__size > __pos) 
87897403Sobrien	    __size = __pos;
87997403Sobrien	  do
88097403Sobrien	    {
88197403Sobrien	      if (traits_type::find(__s, __n, _M_data()[__size]))
88297403Sobrien		return __size;
88397403Sobrien	    } 
88497403Sobrien	  while (__size-- != 0);
88597403Sobrien	}
88697403Sobrien      return npos;
88797403Sobrien    }
88897403Sobrien  
88997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
89097403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
89197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
89297403Sobrien    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
89397403Sobrien    {
89497403Sobrien      size_t __xpos = __pos;
89597403Sobrien      for (; __xpos < this->size(); ++__xpos)
89697403Sobrien	if (!traits_type::find(__s, __n, _M_data()[__xpos]))
89797403Sobrien	  return __xpos;
89897403Sobrien      return npos;
89997403Sobrien    }
90097403Sobrien
90197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
90297403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
90397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
90497403Sobrien    find_first_not_of(_CharT __c, size_type __pos) const
90597403Sobrien    {
90697403Sobrien      size_t __xpos = __pos;
90797403Sobrien      for (; __xpos < this->size(); ++__xpos)
90897403Sobrien	if (!traits_type::eq(_M_data()[__xpos], __c))
90997403Sobrien	  return __xpos;
91097403Sobrien      return npos;
91197403Sobrien    }
91297403Sobrien
91397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
91497403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
91597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
91697403Sobrien    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
91797403Sobrien    {
91897403Sobrien      size_type __size = this->size();
91997403Sobrien      if (__size)
92097403Sobrien	{ 
92197403Sobrien	  if (--__size > __pos) 
92297403Sobrien	    __size = __pos;
92397403Sobrien	  do
92497403Sobrien	    {
92597403Sobrien	      if (!traits_type::find(__s, __n, _M_data()[__size]))
92697403Sobrien		return __size;
92797403Sobrien	    } 
92897403Sobrien	  while (__size--);
92997403Sobrien	}
93097403Sobrien      return npos;
93197403Sobrien    }
93297403Sobrien
93397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
93497403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
93597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
93697403Sobrien    find_last_not_of(_CharT __c, size_type __pos) const
93797403Sobrien    {
93897403Sobrien      size_type __size = this->size();
93997403Sobrien      if (__size)
94097403Sobrien	{ 
94197403Sobrien	  if (--__size > __pos) 
94297403Sobrien	    __size = __pos;
94397403Sobrien	  do
94497403Sobrien	    {
94597403Sobrien	      if (!traits_type::eq(_M_data()[__size], __c))
94697403Sobrien		return __size;
94797403Sobrien	    } 
94897403Sobrien	  while (__size--);
94997403Sobrien	}
95097403Sobrien      return npos;
95197403Sobrien    }
95297403Sobrien  
95397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
95497403Sobrien    int
95597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
95697403Sobrien    compare(size_type __pos, size_type __n, const basic_string& __str) const
95797403Sobrien    {
95897403Sobrien      size_type __size = this->size();
95997403Sobrien      size_type __osize = __str.size();
96097403Sobrien      if (__pos > __size)
96197403Sobrien	__throw_out_of_range("basic_string::compare");
96297403Sobrien      
963117397Skan      size_type __rsize= std::min(size_type(__size - __pos), __n);
964117397Skan      size_type __len = std::min(__rsize, __osize);
96597403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
96697403Sobrien      if (!__r)
96797403Sobrien	__r = __rsize - __osize;
96897403Sobrien      return __r;
96997403Sobrien    }
97097403Sobrien
97197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
97297403Sobrien    int
97397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
97497403Sobrien    compare(size_type __pos1, size_type __n1, const basic_string& __str,
97597403Sobrien	    size_type __pos2, size_type __n2) const
97697403Sobrien    {
97797403Sobrien      size_type __size = this->size();
97897403Sobrien      size_type __osize = __str.size();
97997403Sobrien      if (__pos1 > __size || __pos2 > __osize)
98097403Sobrien	__throw_out_of_range("basic_string::compare");
98197403Sobrien      
982117397Skan      size_type __rsize = std::min(size_type(__size - __pos1), __n1);
983117397Skan      size_type __rosize = std::min(size_type(__osize - __pos2), __n2);
984117397Skan      size_type __len = std::min(__rsize, __rosize);
98597403Sobrien      int __r = traits_type::compare(_M_data() + __pos1, 
98697403Sobrien				     __str.data() + __pos2, __len);
98797403Sobrien      if (!__r)
98897403Sobrien	__r = __rsize - __rosize;
98997403Sobrien      return __r;
99097403Sobrien    }
99197403Sobrien
99297403Sobrien
99397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
99497403Sobrien    int
99597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
99697403Sobrien    compare(const _CharT* __s) const
99797403Sobrien    {
99897403Sobrien      size_type __size = this->size();
999107606Sobrien      size_type __osize = traits_type::length(__s);
1000117397Skan      size_type __len = std::min(__size, __osize);
1001107606Sobrien      int __r = traits_type::compare(_M_data(), __s, __len);
100297403Sobrien      if (!__r)
1003107606Sobrien	__r = __size - __osize;
100497403Sobrien      return __r;
100597403Sobrien    }
100697403Sobrien
100797403Sobrien
100897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
100997403Sobrien    int
101097403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
101197403Sobrien    compare(size_type __pos, size_type __n1, const _CharT* __s) const
101297403Sobrien    {
101397403Sobrien      size_type __size = this->size();
101497403Sobrien      if (__pos > __size)
101597403Sobrien	__throw_out_of_range("basic_string::compare");
101697403Sobrien      
101797403Sobrien      size_type __osize = traits_type::length(__s);
1018117397Skan      size_type __rsize = std::min(size_type(__size - __pos), __n1);
1019117397Skan      size_type __len = std::min(__rsize, __osize);
102097403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
102197403Sobrien      if (!__r)
102297403Sobrien	__r = __rsize - __osize;
102397403Sobrien      return __r;
102497403Sobrien    }
102597403Sobrien
102697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
102797403Sobrien    int
102897403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
102997403Sobrien    compare(size_type __pos, size_type __n1, const _CharT* __s, 
103097403Sobrien	    size_type __n2) const
103197403Sobrien    {
103297403Sobrien      size_type __size = this->size();
103397403Sobrien      if (__pos > __size)
103497403Sobrien	__throw_out_of_range("basic_string::compare");
103597403Sobrien      
1036117397Skan      size_type __osize = std::min(traits_type::length(__s), __n2);
1037117397Skan      size_type __rsize = std::min(size_type(__size - __pos), __n1);
1038117397Skan      size_type __len = std::min(__rsize, __osize);
103997403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
104097403Sobrien      if (!__r)
104197403Sobrien	__r = __rsize - __osize;
104297403Sobrien      return __r;
104397403Sobrien    }
104497403Sobrien
104597403Sobrien  template <class _CharT, class _Traits, class _Alloc>
104697403Sobrien    void
104797403Sobrien    _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str,
104897403Sobrien		   _CharT* __buf, typename _Alloc::size_type __bufsiz)
104997403Sobrien    {
105097403Sobrien      typedef typename _Alloc::size_type size_type;
105197403Sobrien      size_type __strsize = __str.size();
1052117397Skan      size_type __bytes = std::min(__strsize, __bufsiz - 1);
105397403Sobrien      _Traits::copy(__buf, __str.data(), __bytes);
105497403Sobrien      __buf[__bytes] = _CharT();
105597403Sobrien    }
105697403Sobrien
105797403Sobrien  // Inhibit implicit instantiations for required instantiations,
105897403Sobrien  // which are defined via explicit instantiations elsewhere.  
105997403Sobrien  // NB: This syntax is a GNU extension.
1060117397Skan#if _GLIBCPP_EXTERN_TEMPLATE
106197403Sobrien  extern template class basic_string<char>;
106297403Sobrien  extern template 
106397403Sobrien    basic_istream<char>& 
106497403Sobrien    operator>>(basic_istream<char>&, string&);
106597403Sobrien  extern template 
106697403Sobrien    basic_ostream<char>& 
106797403Sobrien    operator<<(basic_ostream<char>&, const string&);
106897403Sobrien  extern template 
106997403Sobrien    basic_istream<char>& 
107097403Sobrien    getline(basic_istream<char>&, string&, char);
107197403Sobrien  extern template 
107297403Sobrien    basic_istream<char>& 
107397403Sobrien    getline(basic_istream<char>&, string&);
107497403Sobrien
1075107606Sobrien#ifdef _GLIBCPP_USE_WCHAR_T
107697403Sobrien  extern template class basic_string<wchar_t>;
107797403Sobrien  extern template 
107897403Sobrien    basic_istream<wchar_t>& 
107997403Sobrien    operator>>(basic_istream<wchar_t>&, wstring&);
108097403Sobrien  extern template 
108197403Sobrien    basic_ostream<wchar_t>& 
108297403Sobrien    operator<<(basic_ostream<wchar_t>&, const wstring&);
108397403Sobrien  extern template 
108497403Sobrien    basic_istream<wchar_t>& 
108597403Sobrien    getline(basic_istream<wchar_t>&, wstring&, wchar_t);
108697403Sobrien  extern template 
108797403Sobrien    basic_istream<wchar_t>& 
108897403Sobrien    getline(basic_istream<wchar_t>&, wstring&);
1089107606Sobrien#endif
1090117397Skan#endif
109197403Sobrien} // namespace std
109297403Sobrien
109397403Sobrien#endif
1094