basic_string.tcc revision 102782
197403Sobrien// Components for manipulating sequences of characters -*- C++ -*-
297403Sobrien
397403Sobrien// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
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      {
14097403Sobrien	size_type __dnew = static_cast<size_type>(distance(__beg, __end));
14197403Sobrien
14297403Sobrien	// NB: Not required, but considered best practice.
143102782Skan	if (__builtin_expect(__beg == _InIter(), 0))
14497403Sobrien	  __throw_logic_error("attempt to create string with null pointer");
14597403Sobrien	
14697403Sobrien	if (__beg == __end && __a == _Alloc())
14797403Sobrien	  return _S_empty_rep()._M_refcopy();
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)
22697403Sobrien    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : 0, 
22797403Sobrien			       __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    }
25797403Sobrien  
25897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
25997403Sobrien    void
26097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
26197403Sobrien    _M_destroy(const _Alloc& __a) throw ()
26297403Sobrien    {
26397403Sobrien      size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT);
26497403Sobrien      _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
26597403Sobrien    }
26697403Sobrien
26797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
26897403Sobrien    void
26997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
27097403Sobrien    {
27197403Sobrien      if (_M_rep()->_M_is_shared()) 
27297403Sobrien	_M_mutate(0, 0, 0);
27397403Sobrien      _M_rep()->_M_set_leaked();
27497403Sobrien    }
27597403Sobrien
27697403Sobrien  // _M_mutate and, below, _M_clone, include, in the same form, an exponential
27797403Sobrien  // growth policy, necessary to meet amortized linear time requirements of
27897403Sobrien  // the library: see http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
27997403Sobrien  // The policy is active for allocations requiring an amount of memory above
28097403Sobrien  // system pagesize. This is consistent with the requirements of the standard:
28197403Sobrien  // see, f.i., http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
28297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
28397403Sobrien    void
28497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
28597403Sobrien    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
28697403Sobrien    {
28797403Sobrien      size_type       __old_size = this->size();
28897403Sobrien      const size_type __new_size = __old_size + __len2 - __len1;
28997403Sobrien      const _CharT*        __src = _M_data()  + __pos + __len1;
29097403Sobrien      const size_type __how_much = __old_size - __pos - __len1;
29197403Sobrien      
29297403Sobrien      if (_M_rep()->_M_is_shared() || __new_size > capacity())
29397403Sobrien	{
29497403Sobrien	  // Must reallocate.
29597403Sobrien	  allocator_type __a = get_allocator();
29697403Sobrien	  // See below (_S_create) for the meaning and value of these
29797403Sobrien	  // constants.
29897403Sobrien	  const size_type __pagesize = 4096;
29997403Sobrien	  const size_type __malloc_header_size = 4 * sizeof (void*);
30097403Sobrien	  // The biggest string which fits in a memory page
30197403Sobrien	  const size_type __page_capacity = (__pagesize - __malloc_header_size
30297403Sobrien					     - sizeof(_Rep) - sizeof(_CharT)) 
30397403Sobrien	    				     / sizeof(_CharT);
30497403Sobrien	  _Rep* __r;
30597403Sobrien	  if (__new_size > capacity() && __new_size > __page_capacity)
30697403Sobrien	    // Growing exponentially.
30797403Sobrien	    __r = _Rep::_S_create(__new_size > 2*capacity() ?
30897403Sobrien				  __new_size : 2*capacity(), __a);
30997403Sobrien	  else
31097403Sobrien	    __r = _Rep::_S_create(__new_size, __a);
31197403Sobrien	  try 
31297403Sobrien	    {
31397403Sobrien	      if (__pos)
31497403Sobrien		traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
31597403Sobrien	      if (__how_much)
31697403Sobrien		traits_type::copy(__r->_M_refdata() + __pos + __len2, 
31797403Sobrien				  __src, __how_much);
31897403Sobrien	    }
31997403Sobrien	  catch(...) 
32097403Sobrien	    { 
32197403Sobrien	      __r->_M_dispose(get_allocator()); 
32297403Sobrien	      __throw_exception_again;
32397403Sobrien	    }
32497403Sobrien	  _M_rep()->_M_dispose(__a);
32597403Sobrien	  _M_data(__r->_M_refdata());
32697403Sobrien      }
32797403Sobrien      else if (__how_much && __len1 != __len2)
32897403Sobrien	{
32997403Sobrien	  // Work in-place
33097403Sobrien	  traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
33197403Sobrien	}
33297403Sobrien      _M_rep()->_M_set_sharable();
33397403Sobrien      _M_rep()->_M_length = __new_size;
33497403Sobrien      _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
33597403Sobrien    // You cannot leave those LWG people alone for a second.
33697403Sobrien    }
33797403Sobrien  
33897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
33997403Sobrien    void
34097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
34197403Sobrien    {
34297403Sobrien      if (__res > this->capacity() || _M_rep()->_M_is_shared())
34397403Sobrien        {
34497403Sobrien	  if (__res > this->max_size())
34597403Sobrien	    __throw_length_error("basic_string::reserve");
34697403Sobrien	  // Make sure we don't shrink below the current size
34797403Sobrien	  if (__res < this->size())
34897403Sobrien	    __res = this->size();
34997403Sobrien	  allocator_type __a = get_allocator();
35097403Sobrien	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
35197403Sobrien	  _M_rep()->_M_dispose(__a);
35297403Sobrien	  _M_data(__tmp);
35397403Sobrien        }
35497403Sobrien    }
35597403Sobrien  
35697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
35797403Sobrien    void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
35897403Sobrien    {
35997403Sobrien      if (_M_rep()->_M_is_leaked()) 
36097403Sobrien	_M_rep()->_M_set_sharable();
36197403Sobrien      if (__s._M_rep()->_M_is_leaked()) 
36297403Sobrien	__s._M_rep()->_M_set_sharable();
36397403Sobrien      if (this->get_allocator() == __s.get_allocator())
36497403Sobrien	{
36597403Sobrien	  _CharT* __tmp = _M_data();
36697403Sobrien	  _M_data(__s._M_data());
36797403Sobrien	  __s._M_data(__tmp);
36897403Sobrien	}
36997403Sobrien      // The code below can usually be optimized away.
37097403Sobrien      else 
37197403Sobrien	{
37297403Sobrien	  basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
37397403Sobrien	  basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 
37497403Sobrien			      this->get_allocator());
37597403Sobrien	  *this = __tmp2;
37697403Sobrien	  __s = __tmp1;
37797403Sobrien	}
37897403Sobrien    }
37997403Sobrien
38097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
38197403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
38297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
38397403Sobrien    _S_create(size_t __capacity, const _Alloc& __alloc)
38497403Sobrien    {
38597403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
38697403Sobrien#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
38797403Sobrien      // 83.  String::npos vs. string::max_size()
38897403Sobrien      if (__capacity > _S_max_size)
38997403Sobrien#else
39097403Sobrien      if (__capacity == npos)
39197403Sobrien#endif
39297403Sobrien	__throw_length_error("basic_string::_S_create");
39397403Sobrien
39497403Sobrien      // NB: Need an array of char_type[__capacity], plus a
39597403Sobrien      // terminating null char_type() element, plus enough for the
39697403Sobrien      // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
39797403Sobrien      size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
39897403Sobrien
39997403Sobrien      // The standard places no restriction on allocating more memory
40097403Sobrien      // than is strictly needed within this layer at the moment or as
40197403Sobrien      // requested by an explicit application call to reserve().  Many
40297403Sobrien      // malloc implementations perform quite poorly when an
40397403Sobrien      // application attempts to allocate memory in a stepwise fashion
40497403Sobrien      // growing each allocation size by only 1 char.  Additionally,
40597403Sobrien      // it makes little sense to allocate less linear memory than the
40697403Sobrien      // natural blocking size of the malloc implementation.
40797403Sobrien      // Unfortunately, we would need a somewhat low-level calculation
40897403Sobrien      // with tuned parameters to get this perfect for any particular
40997403Sobrien      // malloc implementation.  Fortunately, generalizations about
41097403Sobrien      // common features seen among implementations seems to suffice.
41197403Sobrien
41297403Sobrien      // __pagesize need not match the actual VM page size for good
41397403Sobrien      // results in practice, thus we pick a common value on the low
41497403Sobrien      // side.  __malloc_header_size is an estimate of the amount of
41597403Sobrien      // overhead per memory allocation (in practice seen N * sizeof
41697403Sobrien      // (void*) where N is 0, 2 or 4).  According to folklore,
41797403Sobrien      // picking this value on the high side is better than
41897403Sobrien      // low-balling it (especially when this algorithm is used with
41997403Sobrien      // malloc implementations that allocate memory blocks rounded up
42097403Sobrien      // to a size which is a power of 2).
42197403Sobrien      const size_t __pagesize = 4096; // must be 2^i * __subpagesize
42297403Sobrien      const size_t __subpagesize = 128; // should be >> __malloc_header_size
42397403Sobrien      const size_t __malloc_header_size = 4 * sizeof (void*);
42497403Sobrien      if ((__size + __malloc_header_size) > __pagesize)
42597403Sobrien	{
42697403Sobrien	  size_t __extra =
42797403Sobrien	    (__pagesize - ((__size + __malloc_header_size) % __pagesize))
42897403Sobrien	    % __pagesize;
42997403Sobrien	  __capacity += __extra / sizeof(_CharT);
43097403Sobrien	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
43197403Sobrien	}
43297403Sobrien      else if (__size > __subpagesize)
43397403Sobrien	{
43497403Sobrien	  size_t __extra =
43597403Sobrien	    (__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
43697403Sobrien	    % __subpagesize;
43797403Sobrien	  __capacity += __extra / sizeof(_CharT);
43897403Sobrien	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
43997403Sobrien	}
44097403Sobrien
44197403Sobrien      // NB: Might throw, but no worries about a leak, mate: _Rep()
44297403Sobrien      // does not throw.
44397403Sobrien      void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
44497403Sobrien      _Rep *__p = new (__place) _Rep;
44597403Sobrien      __p->_M_capacity = __capacity;
44697403Sobrien      __p->_M_set_sharable();  // One reference.
44797403Sobrien      __p->_M_length = 0;
44897403Sobrien      return __p;
44997403Sobrien    }
45097403Sobrien
45197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
45297403Sobrien    _CharT*
45397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
45497403Sobrien    _M_clone(const _Alloc& __alloc, size_type __res)
45597403Sobrien    {
45697403Sobrien      // Requested capacity of the clone.
45797403Sobrien      const size_type __requested_cap = _M_length + __res;
45897403Sobrien      // See above (_S_create) for the meaning and value of these constants.
45997403Sobrien      const size_type __pagesize = 4096;
46097403Sobrien      const size_type __malloc_header_size = 4 * sizeof (void*);
46197403Sobrien      // The biggest string which fits in a memory page.
46297403Sobrien      const size_type __page_capacity =
46397403Sobrien        (__pagesize - __malloc_header_size - sizeof(_Rep) - sizeof(_CharT))
46497403Sobrien        / sizeof(_CharT);
46597403Sobrien      _Rep* __r;
46697403Sobrien      if (__requested_cap > _M_capacity && __requested_cap > __page_capacity)
46797403Sobrien        // Growing exponentially.
46897403Sobrien        __r = _Rep::_S_create(__requested_cap > 2*_M_capacity ?
46997403Sobrien                              __requested_cap : 2*_M_capacity, __alloc);
47097403Sobrien      else
47197403Sobrien        __r = _Rep::_S_create(__requested_cap, __alloc);
47297403Sobrien      
47397403Sobrien      if (_M_length)
47497403Sobrien	{
47597403Sobrien	  try 
47697403Sobrien	    { traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); }
47797403Sobrien	  catch(...)  
47897403Sobrien	    { 
47997403Sobrien	      __r->_M_destroy(__alloc); 
48097403Sobrien	      __throw_exception_again;
48197403Sobrien	    }
48297403Sobrien	}
48397403Sobrien      __r->_M_length = _M_length;
48497403Sobrien      return __r->_M_refdata();
48597403Sobrien    }
48697403Sobrien  
48797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
48897403Sobrien    void
48997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
49097403Sobrien    {
49197403Sobrien      if (__n > max_size())
49297403Sobrien	__throw_length_error("basic_string::resize");
49397403Sobrien      size_type __size = this->size();
49497403Sobrien      if (__size < __n)
49597403Sobrien	this->append(__n - __size, __c);
49697403Sobrien      else if (__n < __size)
49797403Sobrien	this->erase(__n);
49897403Sobrien      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
49997403Sobrien    }
50097403Sobrien  
501102782Skan
502102782Skan  // This is the general replace helper, which currently gets instantiated both
503102782Skan  // for input iterators and reverse iterators. It buffers internally and then
504102782Skan  // calls _M_replace_safe.
50597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
50697403Sobrien    template<typename _InputIter>
50797403Sobrien      basic_string<_CharT, _Traits, _Alloc>&
50897403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
50997403Sobrien      _M_replace(iterator __i1, iterator __i2, _InputIter __k1, 
51097403Sobrien		 _InputIter __k2, input_iterator_tag)
51197403Sobrien      {
51297403Sobrien	// Save concerned source string data in a temporary.
51397403Sobrien	basic_string __s(__k1, __k2);
51497403Sobrien	return _M_replace_safe(__i1, __i2, __s._M_ibegin(), __s._M_iend());
51597403Sobrien      }
51697403Sobrien
51797403Sobrien  // This is a special replace helper, which does not buffer internally
518102782Skan  // and can be used in "safe" situations involving forward iterators,
51997403Sobrien  // i.e., when source and destination ranges are known to not overlap.
52097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
52197403Sobrien    template<typename _ForwardIter>
52297403Sobrien      basic_string<_CharT, _Traits, _Alloc>&
52397403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
52497403Sobrien      _M_replace_safe(iterator __i1, iterator __i2, _ForwardIter __k1, 
52597403Sobrien		      _ForwardIter __k2)
52697403Sobrien      {
52797403Sobrien	size_type __dnew = static_cast<size_type>(distance(__k1, __k2));
52897403Sobrien	size_type __dold = __i2 - __i1;
52997403Sobrien	size_type __dmax = this->max_size();
53097403Sobrien
53197403Sobrien	if (__dmax <= __dnew)
53297403Sobrien	  __throw_length_error("basic_string::_M_replace");
53397403Sobrien	size_type __off = __i1 - _M_ibegin();
53497403Sobrien	_M_mutate(__off, __dold, __dnew);
53597403Sobrien
53697403Sobrien	// Invalidated __i1, __i2
53797403Sobrien        if (__dnew)
53897403Sobrien	  _S_copy_chars(_M_data() + __off, __k1, __k2);
53997403Sobrien
54097403Sobrien	return *this;
54197403Sobrien      }
54297403Sobrien
54397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
54497403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
54597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
54697403Sobrien    replace(size_type __pos1, size_type __n1, const basic_string& __str,
54797403Sobrien	    size_type __pos2, size_type __n2)
54897403Sobrien    {
54997403Sobrien      const size_type __strsize = __str.size();
55097403Sobrien      if (__pos2 > __strsize)
55197403Sobrien	__throw_out_of_range("basic_string::replace");
55297403Sobrien      const bool __testn2 = __n2 < __strsize - __pos2;
55397403Sobrien      const size_type __foldn2 = __testn2 ? __n2 : __strsize - __pos2;
55497403Sobrien      return this->replace(__pos1, __n1,
55597403Sobrien			   __str._M_data() + __pos2, __foldn2);      
55697403Sobrien    }
55797403Sobrien
55897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
55997403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
56097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
56197403Sobrien    append(const basic_string& __str)
56297403Sobrien    {
56397403Sobrien      // Iff appending itself, string needs to pre-reserve the
56497403Sobrien      // correct size so that _M_mutate does not clobber the
56597403Sobrien      // iterators formed here.
56697403Sobrien      size_type __size = __str.size();
56797403Sobrien      size_type __len = __size + this->size();
56897403Sobrien      if (__len > this->capacity())
56997403Sobrien	this->reserve(__len);
57097403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_ibegin(),
57197403Sobrien			     __str._M_iend());
57297403Sobrien    }
57397403Sobrien
57497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
57597403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
57697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
57797403Sobrien    append(const basic_string& __str, size_type __pos, size_type __n)
57897403Sobrien    {
57997403Sobrien      // Iff appending itself, string needs to pre-reserve the
58097403Sobrien      // correct size so that _M_mutate does not clobber the
58197403Sobrien      // iterators formed here.
58297403Sobrien      size_type __len = min(__str.size() - __pos, __n) + this->size();
58397403Sobrien      if (__len > this->capacity())
58497403Sobrien	this->reserve(__len);
58597403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_check(__pos),
58697403Sobrien			     __str._M_fold(__pos, __n));
58797403Sobrien    }
58897403Sobrien
58997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
59097403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
59197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
59297403Sobrien    append(const _CharT* __s, size_type __n)
59397403Sobrien    {
59497403Sobrien      size_type __len = __n + this->size();
59597403Sobrien      if (__len > this->capacity())
59697403Sobrien	this->reserve(__len);
59797403Sobrien      return _M_replace_safe(_M_iend(), _M_iend(), __s, __s + __n);
59897403Sobrien    }
59997403Sobrien
60097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
60197403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
60297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
60397403Sobrien    append(size_type __n, _CharT __c)
60497403Sobrien    {
60597403Sobrien      size_type __len = __n + this->size();
60697403Sobrien      if (__len > this->capacity())
60797403Sobrien	this->reserve(__len);
60897403Sobrien       return this->replace(_M_iend(), _M_iend(), __n, __c);
60997403Sobrien    }
61097403Sobrien
61197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
61297403Sobrien    basic_string<_CharT, _Traits, _Alloc>
61397403Sobrien    operator+(const _CharT* __lhs,
61497403Sobrien	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
61597403Sobrien    {
61697403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
61797403Sobrien      typedef typename __string_type::size_type	  __size_type;
61897403Sobrien      __size_type __len = _Traits::length(__lhs);
61997403Sobrien      __string_type __str;
62097403Sobrien      __str.reserve(__len + __rhs.size());
62197403Sobrien      __str.append(__lhs, __lhs + __len);
62297403Sobrien      __str.append(__rhs);
62397403Sobrien      return __str;
62497403Sobrien    }
62597403Sobrien
62697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
62797403Sobrien    basic_string<_CharT, _Traits, _Alloc>
62897403Sobrien    operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
62997403Sobrien    {
63097403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
63197403Sobrien      typedef typename __string_type::size_type	  __size_type;
63297403Sobrien      __string_type __str;
63397403Sobrien      __size_type __len = __rhs.size();
63497403Sobrien      __str.reserve(__len + 1);
63597403Sobrien      __str.append(__size_type(1), __lhs);
63697403Sobrien      __str.append(__rhs);
63797403Sobrien      return __str;
63897403Sobrien    }
63997403Sobrien
64097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
64197403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
64297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
64397403Sobrien    replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
64497403Sobrien    {
64597403Sobrien      size_type __n1 = __i2 - __i1;
64697403Sobrien      size_type __off1 = __i1 - _M_ibegin();
64797403Sobrien      if (max_size() - (this->size() - __n1) <= __n2)
64897403Sobrien	__throw_length_error("basic_string::replace");
64997403Sobrien      _M_mutate (__off1, __n1, __n2);
65097403Sobrien      // Invalidated __i1, __i2
65197403Sobrien      if (__n2)
65297403Sobrien	traits_type::assign(_M_data() + __off1, __n2, __c);
65397403Sobrien      return *this;
65497403Sobrien    }
65597403Sobrien  
65697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
65797403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
65897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
65997403Sobrien    copy(_CharT* __s, size_type __n, size_type __pos) const
66097403Sobrien    {
66197403Sobrien      if (__pos > this->size())
66297403Sobrien	__throw_out_of_range("basic_string::copy");
66397403Sobrien      
66497403Sobrien      if (__n > this->size() - __pos)
66597403Sobrien	__n = this->size() - __pos;
66697403Sobrien      
66797403Sobrien      traits_type::copy(__s, _M_data() + __pos, __n);
66897403Sobrien      // 21.3.5.7 par 3: do not append null.  (good.)
66997403Sobrien      return __n;
67097403Sobrien    }
67197403Sobrien
67297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
67397403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
67497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
67597403Sobrien    find(const _CharT* __s, size_type __pos, size_type __n) const
67697403Sobrien    {
67797403Sobrien      size_type __size = this->size();
67897403Sobrien      size_t __xpos = __pos;
67997403Sobrien      const _CharT* __data = _M_data();
68097403Sobrien      for (; __xpos + __n <= __size; ++__xpos)
68197403Sobrien	if (traits_type::compare(__data + __xpos, __s, __n) == 0)
68297403Sobrien	  return __xpos;
68397403Sobrien      return npos;
68497403Sobrien    }
68597403Sobrien
68697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
68797403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
68897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
68997403Sobrien    find(_CharT __c, size_type __pos) const
69097403Sobrien    {
69197403Sobrien      size_type __size = this->size();
69297403Sobrien      size_type __ret = npos;
69397403Sobrien      if (__pos < __size)
69497403Sobrien	{
69597403Sobrien	  const _CharT* __data = _M_data();
69697403Sobrien	  size_type __n = __size - __pos;
69797403Sobrien	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
69897403Sobrien	  if (__p)
69997403Sobrien	    __ret = __p - __data;
70097403Sobrien	}
70197403Sobrien      return __ret;
70297403Sobrien    }
70397403Sobrien
70497403Sobrien
70597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
70697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
70797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
70897403Sobrien    rfind(const _CharT* __s, size_type __pos, size_type __n) const
70997403Sobrien    {
71097403Sobrien      size_type __size = this->size();
71197403Sobrien      if (__n <= __size)
71297403Sobrien	{
71397403Sobrien	  __pos = std::min(__size - __n, __pos);
71497403Sobrien	  const _CharT* __data = _M_data();
71597403Sobrien	  do 
71697403Sobrien	    {
71797403Sobrien	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
71897403Sobrien		return __pos;
71997403Sobrien	    } 
72097403Sobrien	  while (__pos-- > 0);
72197403Sobrien	}
72297403Sobrien      return npos;
72397403Sobrien    }
72497403Sobrien  
72597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
72697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
72797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
72897403Sobrien    rfind(_CharT __c, size_type __pos) const
72997403Sobrien    {
73097403Sobrien      size_type __size = this->size();
73197403Sobrien      if (__size)
73297403Sobrien	{
73397403Sobrien	  size_t __xpos = __size - 1;
73497403Sobrien	  if (__xpos > __pos)
73597403Sobrien	    __xpos = __pos;
73697403Sobrien      
73797403Sobrien	  for (++__xpos; __xpos-- > 0; )
73897403Sobrien	    if (traits_type::eq(_M_data()[__xpos], __c))
73997403Sobrien	      return __xpos;
74097403Sobrien	}
74197403Sobrien      return npos;
74297403Sobrien    }
74397403Sobrien  
74497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
74597403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
74697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
74797403Sobrien    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
74897403Sobrien    {
74997403Sobrien      for (; __n && __pos < this->size(); ++__pos)
75097403Sobrien	{
75197403Sobrien	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
75297403Sobrien	  if (__p)
75397403Sobrien	    return __pos;
75497403Sobrien	}
75597403Sobrien      return npos;
75697403Sobrien    }
75797403Sobrien 
75897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
75997403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
76097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
76197403Sobrien    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
76297403Sobrien    {
76397403Sobrien      size_type __size = this->size();
76497403Sobrien      if (__size && __n)
76597403Sobrien	{ 
76697403Sobrien	  if (--__size > __pos) 
76797403Sobrien	    __size = __pos;
76897403Sobrien	  do
76997403Sobrien	    {
77097403Sobrien	      if (traits_type::find(__s, __n, _M_data()[__size]))
77197403Sobrien		return __size;
77297403Sobrien	    } 
77397403Sobrien	  while (__size-- != 0);
77497403Sobrien	}
77597403Sobrien      return npos;
77697403Sobrien    }
77797403Sobrien  
77897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
77997403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
78097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
78197403Sobrien    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
78297403Sobrien    {
78397403Sobrien      size_t __xpos = __pos;
78497403Sobrien      for (; __xpos < this->size(); ++__xpos)
78597403Sobrien	if (!traits_type::find(__s, __n, _M_data()[__xpos]))
78697403Sobrien	  return __xpos;
78797403Sobrien      return npos;
78897403Sobrien    }
78997403Sobrien
79097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
79197403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
79297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
79397403Sobrien    find_first_not_of(_CharT __c, size_type __pos) const
79497403Sobrien    {
79597403Sobrien      size_t __xpos = __pos;
79697403Sobrien      for (; __xpos < this->size(); ++__xpos)
79797403Sobrien	if (!traits_type::eq(_M_data()[__xpos], __c))
79897403Sobrien	  return __xpos;
79997403Sobrien      return npos;
80097403Sobrien    }
80197403Sobrien
80297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
80397403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
80497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
80597403Sobrien    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
80697403Sobrien    {
80797403Sobrien      size_type __size = this->size();
80897403Sobrien      if (__size)
80997403Sobrien	{ 
81097403Sobrien	  if (--__size > __pos) 
81197403Sobrien	    __size = __pos;
81297403Sobrien	  do
81397403Sobrien	    {
81497403Sobrien	      if (!traits_type::find(__s, __n, _M_data()[__size]))
81597403Sobrien		return __size;
81697403Sobrien	    } 
81797403Sobrien	  while (__size--);
81897403Sobrien	}
81997403Sobrien      return npos;
82097403Sobrien    }
82197403Sobrien
82297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
82397403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
82497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
82597403Sobrien    find_last_not_of(_CharT __c, size_type __pos) const
82697403Sobrien    {
82797403Sobrien      size_type __size = this->size();
82897403Sobrien      if (__size)
82997403Sobrien	{ 
83097403Sobrien	  if (--__size > __pos) 
83197403Sobrien	    __size = __pos;
83297403Sobrien	  do
83397403Sobrien	    {
83497403Sobrien	      if (!traits_type::eq(_M_data()[__size], __c))
83597403Sobrien		return __size;
83697403Sobrien	    } 
83797403Sobrien	  while (__size--);
83897403Sobrien	}
83997403Sobrien      return npos;
84097403Sobrien    }
84197403Sobrien  
84297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
84397403Sobrien    int
84497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
84597403Sobrien    compare(size_type __pos, size_type __n, const basic_string& __str) const
84697403Sobrien    {
84797403Sobrien      size_type __size = this->size();
84897403Sobrien      size_type __osize = __str.size();
84997403Sobrien      if (__pos > __size)
85097403Sobrien	__throw_out_of_range("basic_string::compare");
85197403Sobrien      
85297403Sobrien      size_type __rsize= min(__size - __pos, __n);
85397403Sobrien      size_type __len = min(__rsize, __osize);
85497403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
85597403Sobrien      if (!__r)
85697403Sobrien	__r = __rsize - __osize;
85797403Sobrien      return __r;
85897403Sobrien    }
85997403Sobrien
86097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
86197403Sobrien    int
86297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
86397403Sobrien    compare(size_type __pos1, size_type __n1, const basic_string& __str,
86497403Sobrien	    size_type __pos2, size_type __n2) const
86597403Sobrien    {
86697403Sobrien      size_type __size = this->size();
86797403Sobrien      size_type __osize = __str.size();
86897403Sobrien      if (__pos1 > __size || __pos2 > __osize)
86997403Sobrien	__throw_out_of_range("basic_string::compare");
87097403Sobrien      
87197403Sobrien      size_type __rsize = min(__size - __pos1, __n1);
87297403Sobrien      size_type __rosize = min(__osize - __pos2, __n2);
87397403Sobrien      size_type __len = min(__rsize, __rosize);
87497403Sobrien      int __r = traits_type::compare(_M_data() + __pos1, 
87597403Sobrien				     __str.data() + __pos2, __len);
87697403Sobrien      if (!__r)
87797403Sobrien	__r = __rsize - __rosize;
87897403Sobrien      return __r;
87997403Sobrien    }
88097403Sobrien
88197403Sobrien
88297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
88397403Sobrien    int
88497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
88597403Sobrien    compare(const _CharT* __s) const
88697403Sobrien    {
88797403Sobrien      size_type __size = this->size();
88897403Sobrien      int __r = traits_type::compare(_M_data(), __s, __size);
88997403Sobrien      if (!__r)
89097403Sobrien	__r = __size - traits_type::length(__s);
89197403Sobrien      return __r;
89297403Sobrien    }
89397403Sobrien
89497403Sobrien
89597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
89697403Sobrien    int
89797403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
89897403Sobrien    compare(size_type __pos, size_type __n1, const _CharT* __s) const
89997403Sobrien    {
90097403Sobrien      size_type __size = this->size();
90197403Sobrien      if (__pos > __size)
90297403Sobrien	__throw_out_of_range("basic_string::compare");
90397403Sobrien      
90497403Sobrien      size_type __osize = traits_type::length(__s);
90597403Sobrien      size_type __rsize = min(__size - __pos, __n1);
90697403Sobrien      size_type __len = min(__rsize, __osize);
90797403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
90897403Sobrien      if (!__r)
90997403Sobrien	__r = __rsize - __osize;
91097403Sobrien      return __r;
91197403Sobrien    }
91297403Sobrien
91397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
91497403Sobrien    int
91597403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
91697403Sobrien    compare(size_type __pos, size_type __n1, const _CharT* __s, 
91797403Sobrien	    size_type __n2) const
91897403Sobrien    {
91997403Sobrien      size_type __size = this->size();
92097403Sobrien      if (__pos > __size)
92197403Sobrien	__throw_out_of_range("basic_string::compare");
92297403Sobrien      
92397403Sobrien      size_type __osize = min(traits_type::length(__s), __n2);
92497403Sobrien      size_type __rsize = min(__size - __pos, __n1);
92597403Sobrien      size_type __len = min(__rsize, __osize);
92697403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
92797403Sobrien      if (!__r)
92897403Sobrien	__r = __rsize - __osize;
92997403Sobrien      return __r;
93097403Sobrien    }
93197403Sobrien
93297403Sobrien  template <class _CharT, class _Traits, class _Alloc>
93397403Sobrien    void
93497403Sobrien    _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str,
93597403Sobrien		   _CharT* __buf, typename _Alloc::size_type __bufsiz)
93697403Sobrien    {
93797403Sobrien      typedef typename _Alloc::size_type size_type;
93897403Sobrien      size_type __strsize = __str.size();
93997403Sobrien      size_type __bytes = min(__strsize, __bufsiz - 1);
94097403Sobrien      _Traits::copy(__buf, __str.data(), __bytes);
94197403Sobrien      __buf[__bytes] = _CharT();
94297403Sobrien    }
94397403Sobrien
94497403Sobrien  // Inhibit implicit instantiations for required instantiations,
94597403Sobrien  // which are defined via explicit instantiations elsewhere.  
94697403Sobrien  // NB: This syntax is a GNU extension.
94797403Sobrien  extern template class basic_string<char>;
94897403Sobrien  extern template 
94997403Sobrien    basic_istream<char>& 
95097403Sobrien    operator>>(basic_istream<char>&, string&);
95197403Sobrien  extern template 
95297403Sobrien    basic_ostream<char>& 
95397403Sobrien    operator<<(basic_ostream<char>&, const string&);
95497403Sobrien  extern template 
95597403Sobrien    basic_istream<char>& 
95697403Sobrien    getline(basic_istream<char>&, string&, char);
95797403Sobrien  extern template 
95897403Sobrien    basic_istream<char>& 
95997403Sobrien    getline(basic_istream<char>&, string&);
96097403Sobrien
96197403Sobrien  extern template class basic_string<wchar_t>;
96297403Sobrien  extern template 
96397403Sobrien    basic_istream<wchar_t>& 
96497403Sobrien    operator>>(basic_istream<wchar_t>&, wstring&);
96597403Sobrien  extern template 
96697403Sobrien    basic_ostream<wchar_t>& 
96797403Sobrien    operator<<(basic_ostream<wchar_t>&, const wstring&);
96897403Sobrien  extern template 
96997403Sobrien    basic_istream<wchar_t>& 
97097403Sobrien    getline(basic_istream<wchar_t>&, wstring&, wchar_t);
97197403Sobrien  extern template 
97297403Sobrien    basic_istream<wchar_t>& 
97397403Sobrien    getline(basic_istream<wchar_t>&, wstring&);
97497403Sobrien} // namespace std
97597403Sobrien
97697403Sobrien#endif
977