basic_string.tcc revision 102782
1250323Sdteske// Components for manipulating sequences of characters -*- C++ -*-
2250323Sdteske
3250323Sdteske// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002
4250323Sdteske// Free Software Foundation, Inc.
5250323Sdteske//
6250323Sdteske// This file is part of the GNU ISO C++ Library.  This library is free
7250323Sdteske// software; you can redistribute it and/or modify it under the
8250323Sdteske// terms of the GNU General Public License as published by the
9250323Sdteske// Free Software Foundation; either version 2, or (at your option)
10250323Sdteske// any later version.
11250323Sdteske
12250323Sdteske// This library is distributed in the hope that it will be useful,
13250323Sdteske// but WITHOUT ANY WARRANTY; without even the implied warranty of
14250323Sdteske// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15250323Sdteske// GNU General Public License for more details.
16250323Sdteske
17250323Sdteske// You should have received a copy of the GNU General Public License along
18250323Sdteske// with this library; see the file COPYING.  If not, write to the Free
19250323Sdteske// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20250323Sdteske// USA.
21250323Sdteske
22250323Sdteske// As a special exception, you may use this file as part of a free software
23250323Sdteske// library without restriction.  Specifically, if other files instantiate
24250323Sdteske// templates or use macros or inline functions from this file, or you compile
25250323Sdteske// this file and link it with other files to produce an executable, this
26250323Sdteske// file does not by itself cause the resulting executable to be covered by
27250323Sdteske// the GNU General Public License.  This exception does not however
28250323Sdteske// invalidate any other reasons why the executable file might be covered by
29250323Sdteske// the GNU General Public License.
30250323Sdteske
31250323Sdteske//
32250323Sdteske// ISO C++ 14882: 21  Strings library
33250323Sdteske//
34250323Sdteske
35250323Sdteske// This file is included by <string>.  It is not meant to be included
36250323Sdteske// separately.
37250323Sdteske
38250323Sdteske// Written by Jason Merrill based upon the specification by Takanori Adachi
39250323Sdteske// in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
40250323Sdteske
41250323Sdteske#ifndef _CPP_BITS_STRING_TCC
42250323Sdteske#define _CPP_BITS_STRING_TCC 1
43250323Sdteske
44250323Sdteske#pragma GCC system_header
45250323Sdteske
46250323Sdteskenamespace std
47250323Sdteske{
48250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
49250323Sdteske    const typename basic_string<_CharT, _Traits, _Alloc>::size_type 
50250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
51250323Sdteske    _Rep::_S_max_size = (((npos - sizeof(_Rep))/sizeof(_CharT)) - 1) / 4;
52250323Sdteske
53250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
54250323Sdteske    const _CharT 
55250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
56250323Sdteske    _Rep::_S_terminal = _CharT();
57250323Sdteske
58250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
59250323Sdteske    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
60250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::npos;
61250323Sdteske
62250323Sdteske  // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
63250323Sdteske  // at static init time (before static ctors are run).
64250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
65250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
66250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::_S_empty_rep_storage[
67250323Sdteske    (sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
68250323Sdteske
69250323Sdteske  // NB: This is the special case for Input Iterators, used in
70250323Sdteske  // istreambuf_iterators, etc.
71250323Sdteske  // Input Iterators have a cost structure very different from
72250323Sdteske  // pointers, calling for a different coding style.
73250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
74250323Sdteske    template<typename _InIter>
75250323Sdteske      _CharT*
76250323Sdteske      basic_string<_CharT, _Traits, _Alloc>::
77250323Sdteske      _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
78250323Sdteske		   input_iterator_tag)
79250323Sdteske      {
80250323Sdteske	if (__beg == __end && __a == _Alloc())
81250323Sdteske	  return _S_empty_rep()._M_refcopy();
82250538Sdteske	// Avoid reallocation for common case.
83250538Sdteske	_CharT __buf[100];
84250323Sdteske	size_type __i = 0;
85250323Sdteske	while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT))
86250323Sdteske	  { 
87250538Sdteske	    __buf[__i++] = *__beg; 
88250538Sdteske	    ++__beg; 
89250538Sdteske	  }
90250538Sdteske	_Rep* __r = _Rep::_S_create(__i, __a);
91250538Sdteske	traits_type::copy(__r->_M_refdata(), __buf, __i);
92250323Sdteske	__r->_M_length = __i;
93250323Sdteske	try 
94250323Sdteske	  {
95250538Sdteske	    // NB: this loop looks precisely this way because
96250538Sdteske	    // it avoids comparing __beg != __end any more
97250538Sdteske	    // than strictly necessary; != might be expensive!
98250538Sdteske	    for (;;)
99250538Sdteske	      {
100250323Sdteske		_CharT* __p = __r->_M_refdata() + __r->_M_length;
101250538Sdteske		_CharT* __last = __r->_M_refdata() + __r->_M_capacity;
102250538Sdteske		for (;;)
103250538Sdteske		  {
104250323Sdteske		    if (__beg == __end)
105250323Sdteske		      {
106250323Sdteske			__r->_M_length = __p - __r->_M_refdata();
107250323Sdteske			*__p = _Rep::_S_terminal;       // grrr.
108250323Sdteske			return __r->_M_refdata();
109250323Sdteske		      }
110250323Sdteske		    if (__p == __last)
111250323Sdteske		      break;
112250323Sdteske		    *__p++ = *__beg; 
113250323Sdteske		    ++__beg;
114250323Sdteske		  }
115250323Sdteske		// Allocate more space.
116250323Sdteske		size_type __len = __p - __r->_M_refdata();
117250323Sdteske		_Rep* __another = _Rep::_S_create(__len + 1, __a);
118250323Sdteske		traits_type::copy(__another->_M_refdata(), 
119250323Sdteske				  __r->_M_refdata(), __len);
120250323Sdteske		__r->_M_destroy(__a);
121250323Sdteske		__r = __another;
122250323Sdteske		__r->_M_length = __len;
123250323Sdteske	      }
124250323Sdteske	  }
125250323Sdteske	catch(...) 
126250323Sdteske	  {
127250323Sdteske	    __r->_M_destroy(__a); 
128250323Sdteske	    __throw_exception_again;
129250323Sdteske	  }
130250323Sdteske	return 0;
131250323Sdteske      }
132250323Sdteske  
133250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
134250323Sdteske    template <class _InIter>
135250323Sdteske      _CharT*
136250323Sdteske      basic_string<_CharT, _Traits, _Alloc>::
137250323Sdteske      _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a, 
138250323Sdteske		   forward_iterator_tag)
139250323Sdteske      {
140250323Sdteske	size_type __dnew = static_cast<size_type>(distance(__beg, __end));
141250323Sdteske
142250323Sdteske	// NB: Not required, but considered best practice.
143250323Sdteske	if (__builtin_expect(__beg == _InIter(), 0))
144250323Sdteske	  __throw_logic_error("attempt to create string with null pointer");
145250323Sdteske	
146250323Sdteske	if (__beg == __end && __a == _Alloc())
147250323Sdteske	  return _S_empty_rep()._M_refcopy();
148250323Sdteske
149250323Sdteske	// Check for out_of_range and length_error exceptions.
150250323Sdteske	_Rep* __r = _Rep::_S_create(__dnew, __a);
151250323Sdteske	try 
152250323Sdteske	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
153250323Sdteske	catch(...) 
154250323Sdteske	  { 
155250323Sdteske	    __r->_M_destroy(__a); 
156250323Sdteske	    __throw_exception_again;
157250323Sdteske	  }
158250323Sdteske	__r->_M_length = __dnew;
159250323Sdteske
160250323Sdteske	__r->_M_refdata()[__dnew] = _Rep::_S_terminal;  // grrr.
161250323Sdteske	return __r->_M_refdata();
162250323Sdteske      }
163250323Sdteske
164250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
165250323Sdteske    _CharT*
166250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
167250323Sdteske    _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
168250323Sdteske    {
169250323Sdteske      if (__n == 0 && __a == _Alloc())
170250323Sdteske	return _S_empty_rep()._M_refcopy();
171250323Sdteske
172250323Sdteske      // Check for out_of_range and length_error exceptions.
173250323Sdteske      _Rep* __r = _Rep::_S_create(__n, __a);
174250323Sdteske      try 
175250323Sdteske	{ 
176250323Sdteske	  if (__n) 
177250323Sdteske	    traits_type::assign(__r->_M_refdata(), __n, __c); 
178250323Sdteske	}
179250323Sdteske      catch(...) 
180250323Sdteske	{ 
181250323Sdteske	  __r->_M_destroy(__a); 
182250323Sdteske	  __throw_exception_again;
183250323Sdteske	}
184250323Sdteske      __r->_M_length = __n;
185250323Sdteske      __r->_M_refdata()[__n] = _Rep::_S_terminal;  // grrr
186250323Sdteske      return __r->_M_refdata();
187250323Sdteske    }
188250323Sdteske
189250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
190250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
191250323Sdteske    basic_string(const basic_string& __str)
192250323Sdteske    : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()),
193250323Sdteske		 __str.get_allocator())
194250323Sdteske    { }
195250323Sdteske
196250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
197250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
198250323Sdteske    basic_string(const _Alloc& __a)
199250323Sdteske    : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
200250323Sdteske    { }
201250323Sdteske 
202250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
203250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
204250323Sdteske    basic_string(const basic_string& __str, size_type __pos, size_type __n)
205250323Sdteske    : _M_dataplus(_S_construct(__str._M_check(__pos), 
206250323Sdteske			       __str._M_fold(__pos, __n), _Alloc()), _Alloc())
207250323Sdteske    { }
208250323Sdteske
209250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
210250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
211250323Sdteske    basic_string(const basic_string& __str, size_type __pos,
212250323Sdteske		 size_type __n, const _Alloc& __a)
213250323Sdteske    : _M_dataplus(_S_construct(__str._M_check(__pos), 
214250323Sdteske			       __str._M_fold(__pos, __n), __a), __a)
215250323Sdteske    { }
216250323Sdteske
217250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
218250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
219250323Sdteske    basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
220250323Sdteske    : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
221250323Sdteske    { }
222250323Sdteske
223250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
224250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
225250323Sdteske    basic_string(const _CharT* __s, const _Alloc& __a)
226250323Sdteske    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) : 0, 
227250323Sdteske			       __a), __a)
228250323Sdteske    { }
229250323Sdteske
230250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
231250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
232250323Sdteske    basic_string(size_type __n, _CharT __c, const _Alloc& __a)
233250323Sdteske    : _M_dataplus(_S_construct(__n, __c, __a), __a)
234250323Sdteske    { }
235250323Sdteske 
236250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
237250323Sdteske    template<typename _InputIter>
238250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
239250323Sdteske    basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a)
240250323Sdteske    : _M_dataplus(_S_construct(__beg, __end, __a), __a)
241250323Sdteske    { }
242250323Sdteske
243250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
244250323Sdteske    basic_string<_CharT, _Traits, _Alloc>&
245250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str)
246250323Sdteske    {
247250323Sdteske      if (_M_rep() != __str._M_rep())
248250323Sdteske	{
249250323Sdteske	  // XXX MT
250250323Sdteske	  allocator_type __a = this->get_allocator();
251250323Sdteske	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
252250323Sdteske	  _M_rep()->_M_dispose(__a);
253250323Sdteske	  _M_data(__tmp);
254250323Sdteske	}
255250323Sdteske      return *this;
256250323Sdteske    }
257250323Sdteske  
258250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
259250323Sdteske    void
260250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::_Rep::
261250323Sdteske    _M_destroy(const _Alloc& __a) throw ()
262250323Sdteske    {
263250323Sdteske      size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT);
264250323Sdteske      _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
265250323Sdteske    }
266250323Sdteske
267250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
268250323Sdteske    void
269250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
270250323Sdteske    {
271250323Sdteske      if (_M_rep()->_M_is_shared()) 
272250323Sdteske	_M_mutate(0, 0, 0);
273250323Sdteske      _M_rep()->_M_set_leaked();
274250323Sdteske    }
275251236Sdteske
276251236Sdteske  // _M_mutate and, below, _M_clone, include, in the same form, an exponential
277250323Sdteske  // growth policy, necessary to meet amortized linear time requirements of
278250323Sdteske  // the library: see http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
279250323Sdteske  // The policy is active for allocations requiring an amount of memory above
280251264Sdteske  // system pagesize. This is consistent with the requirements of the standard:
281251264Sdteske  // see, f.i., http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
282251264Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
283251264Sdteske    void
284251264Sdteske    basic_string<_CharT, _Traits, _Alloc>::
285251264Sdteske    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
286250323Sdteske    {
287250323Sdteske      size_type       __old_size = this->size();
288250323Sdteske      const size_type __new_size = __old_size + __len2 - __len1;
289250323Sdteske      const _CharT*        __src = _M_data()  + __pos + __len1;
290250323Sdteske      const size_type __how_much = __old_size - __pos - __len1;
291250323Sdteske      
292251264Sdteske      if (_M_rep()->_M_is_shared() || __new_size > capacity())
293250323Sdteske	{
294250323Sdteske	  // Must reallocate.
295250323Sdteske	  allocator_type __a = get_allocator();
296250323Sdteske	  // See below (_S_create) for the meaning and value of these
297250323Sdteske	  // constants.
298251264Sdteske	  const size_type __pagesize = 4096;
299251264Sdteske	  const size_type __malloc_header_size = 4 * sizeof (void*);
300250323Sdteske	  // The biggest string which fits in a memory page
301251236Sdteske	  const size_type __page_capacity = (__pagesize - __malloc_header_size
302251232Sdteske					     - sizeof(_Rep) - sizeof(_CharT)) 
303251232Sdteske	    				     / sizeof(_CharT);
304251232Sdteske	  _Rep* __r;
305251232Sdteske	  if (__new_size > capacity() && __new_size > __page_capacity)
306251232Sdteske	    // Growing exponentially.
307251232Sdteske	    __r = _Rep::_S_create(__new_size > 2*capacity() ?
308251236Sdteske				  __new_size : 2*capacity(), __a);
309251236Sdteske	  else
310251266Sdteske	    __r = _Rep::_S_create(__new_size, __a);
311251266Sdteske	  try 
312251266Sdteske	    {
313251266Sdteske	      if (__pos)
314251266Sdteske		traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
315251266Sdteske	      if (__how_much)
316251266Sdteske		traits_type::copy(__r->_M_refdata() + __pos + __len2, 
317251266Sdteske				  __src, __how_much);
318251266Sdteske	    }
319251266Sdteske	  catch(...) 
320251266Sdteske	    { 
321251266Sdteske	      __r->_M_dispose(get_allocator()); 
322250323Sdteske	      __throw_exception_again;
323251236Sdteske	    }
324250323Sdteske	  _M_rep()->_M_dispose(__a);
325250323Sdteske	  _M_data(__r->_M_refdata());
326250323Sdteske      }
327250323Sdteske      else if (__how_much && __len1 != __len2)
328250323Sdteske	{
329250323Sdteske	  // Work in-place
330250323Sdteske	  traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
331250323Sdteske	}
332250323Sdteske      _M_rep()->_M_set_sharable();
333250323Sdteske      _M_rep()->_M_length = __new_size;
334250323Sdteske      _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
335250323Sdteske    // You cannot leave those LWG people alone for a second.
336250323Sdteske    }
337250323Sdteske  
338250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
339250323Sdteske    void
340250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
341250323Sdteske    {
342250323Sdteske      if (__res > this->capacity() || _M_rep()->_M_is_shared())
343250323Sdteske        {
344250323Sdteske	  if (__res > this->max_size())
345250323Sdteske	    __throw_length_error("basic_string::reserve");
346250323Sdteske	  // Make sure we don't shrink below the current size
347250323Sdteske	  if (__res < this->size())
348250323Sdteske	    __res = this->size();
349250323Sdteske	  allocator_type __a = get_allocator();
350250323Sdteske	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
351250323Sdteske	  _M_rep()->_M_dispose(__a);
352250323Sdteske	  _M_data(__tmp);
353250323Sdteske        }
354250323Sdteske    }
355250323Sdteske  
356251266Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
357250323Sdteske    void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
358250323Sdteske    {
359250323Sdteske      if (_M_rep()->_M_is_leaked()) 
360250323Sdteske	_M_rep()->_M_set_sharable();
361250323Sdteske      if (__s._M_rep()->_M_is_leaked()) 
362250323Sdteske	__s._M_rep()->_M_set_sharable();
363250323Sdteske      if (this->get_allocator() == __s.get_allocator())
364250323Sdteske	{
365251236Sdteske	  _CharT* __tmp = _M_data();
366250323Sdteske	  _M_data(__s._M_data());
367250323Sdteske	  __s._M_data(__tmp);
368250323Sdteske	}
369251264Sdteske      // The code below can usually be optimized away.
370251264Sdteske      else 
371251264Sdteske	{
372251264Sdteske	  basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
373251264Sdteske	  basic_string __tmp2(__s._M_ibegin(), __s._M_iend(), 
374250323Sdteske			      this->get_allocator());
375250323Sdteske	  *this = __tmp2;
376250323Sdteske	  __s = __tmp1;
377251264Sdteske	}
378250323Sdteske    }
379250323Sdteske
380250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
381251264Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
382250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::_Rep::
383250538Sdteske    _S_create(size_t __capacity, const _Alloc& __alloc)
384250323Sdteske    {
385250323Sdteske      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
386250323Sdteske#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
387250323Sdteske      // 83.  String::npos vs. string::max_size()
388251264Sdteske      if (__capacity > _S_max_size)
389250323Sdteske#else
390250323Sdteske      if (__capacity == npos)
391250323Sdteske#endif
392250323Sdteske	__throw_length_error("basic_string::_S_create");
393250323Sdteske
394250323Sdteske      // NB: Need an array of char_type[__capacity], plus a
395250323Sdteske      // terminating null char_type() element, plus enough for the
396250323Sdteske      // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
397250323Sdteske      size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
398250323Sdteske
399250323Sdteske      // The standard places no restriction on allocating more memory
400250323Sdteske      // than is strictly needed within this layer at the moment or as
401250323Sdteske      // requested by an explicit application call to reserve().  Many
402250323Sdteske      // malloc implementations perform quite poorly when an
403250323Sdteske      // application attempts to allocate memory in a stepwise fashion
404250323Sdteske      // growing each allocation size by only 1 char.  Additionally,
405250323Sdteske      // it makes little sense to allocate less linear memory than the
406250323Sdteske      // natural blocking size of the malloc implementation.
407250323Sdteske      // Unfortunately, we would need a somewhat low-level calculation
408250323Sdteske      // with tuned parameters to get this perfect for any particular
409250323Sdteske      // malloc implementation.  Fortunately, generalizations about
410250323Sdteske      // common features seen among implementations seems to suffice.
411250323Sdteske
412250323Sdteske      // __pagesize need not match the actual VM page size for good
413250323Sdteske      // results in practice, thus we pick a common value on the low
414250323Sdteske      // side.  __malloc_header_size is an estimate of the amount of
415251264Sdteske      // overhead per memory allocation (in practice seen N * sizeof
416251264Sdteske      // (void*) where N is 0, 2 or 4).  According to folklore,
417251264Sdteske      // picking this value on the high side is better than
418250323Sdteske      // low-balling it (especially when this algorithm is used with
419250323Sdteske      // malloc implementations that allocate memory blocks rounded up
420250323Sdteske      // to a size which is a power of 2).
421250323Sdteske      const size_t __pagesize = 4096; // must be 2^i * __subpagesize
422250323Sdteske      const size_t __subpagesize = 128; // should be >> __malloc_header_size
423250323Sdteske      const size_t __malloc_header_size = 4 * sizeof (void*);
424250323Sdteske      if ((__size + __malloc_header_size) > __pagesize)
425250323Sdteske	{
426250323Sdteske	  size_t __extra =
427250323Sdteske	    (__pagesize - ((__size + __malloc_header_size) % __pagesize))
428250323Sdteske	    % __pagesize;
429250323Sdteske	  __capacity += __extra / sizeof(_CharT);
430250323Sdteske	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
431250323Sdteske	}
432250323Sdteske      else if (__size > __subpagesize)
433250323Sdteske	{
434250323Sdteske	  size_t __extra =
435250323Sdteske	    (__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
436250323Sdteske	    % __subpagesize;
437250323Sdteske	  __capacity += __extra / sizeof(_CharT);
438250323Sdteske	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
439250323Sdteske	}
440250323Sdteske
441250323Sdteske      // NB: Might throw, but no worries about a leak, mate: _Rep()
442250323Sdteske      // does not throw.
443250323Sdteske      void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
444250323Sdteske      _Rep *__p = new (__place) _Rep;
445250323Sdteske      __p->_M_capacity = __capacity;
446250323Sdteske      __p->_M_set_sharable();  // One reference.
447250323Sdteske      __p->_M_length = 0;
448250323Sdteske      return __p;
449250323Sdteske    }
450250323Sdteske
451250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
452250323Sdteske    _CharT*
453250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::_Rep::
454250323Sdteske    _M_clone(const _Alloc& __alloc, size_type __res)
455250323Sdteske    {
456250323Sdteske      // Requested capacity of the clone.
457250538Sdteske      const size_type __requested_cap = _M_length + __res;
458250538Sdteske      // See above (_S_create) for the meaning and value of these constants.
459250538Sdteske      const size_type __pagesize = 4096;
460250538Sdteske      const size_type __malloc_header_size = 4 * sizeof (void*);
461250538Sdteske      // The biggest string which fits in a memory page.
462250538Sdteske      const size_type __page_capacity =
463250323Sdteske        (__pagesize - __malloc_header_size - sizeof(_Rep) - sizeof(_CharT))
464250323Sdteske        / sizeof(_CharT);
465250323Sdteske      _Rep* __r;
466251232Sdteske      if (__requested_cap > _M_capacity && __requested_cap > __page_capacity)
467251232Sdteske        // Growing exponentially.
468251232Sdteske        __r = _Rep::_S_create(__requested_cap > 2*_M_capacity ?
469251232Sdteske                              __requested_cap : 2*_M_capacity, __alloc);
470251232Sdteske      else
471251232Sdteske        __r = _Rep::_S_create(__requested_cap, __alloc);
472251232Sdteske      
473251232Sdteske      if (_M_length)
474251236Sdteske	{
475251236Sdteske	  try 
476251236Sdteske	    { traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); }
477250323Sdteske	  catch(...)  
478250323Sdteske	    { 
479250323Sdteske	      __r->_M_destroy(__alloc); 
480250323Sdteske	      __throw_exception_again;
481250323Sdteske	    }
482250323Sdteske	}
483250323Sdteske      __r->_M_length = _M_length;
484250323Sdteske      return __r->_M_refdata();
485251232Sdteske    }
486251232Sdteske  
487250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
488250323Sdteske    void
489250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
490251232Sdteske    {
491251232Sdteske      if (__n > max_size())
492250323Sdteske	__throw_length_error("basic_string::resize");
493250323Sdteske      size_type __size = this->size();
494250323Sdteske      if (__size < __n)
495251236Sdteske	this->append(__n - __size, __c);
496251236Sdteske      else if (__n < __size)
497250323Sdteske	this->erase(__n);
498250323Sdteske      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
499251236Sdteske    }
500250323Sdteske  
501251236Sdteske
502250323Sdteske  // This is the general replace helper, which currently gets instantiated both
503250323Sdteske  // for input iterators and reverse iterators. It buffers internally and then
504250323Sdteske  // calls _M_replace_safe.
505250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
506250323Sdteske    template<typename _InputIter>
507250323Sdteske      basic_string<_CharT, _Traits, _Alloc>&
508250323Sdteske      basic_string<_CharT, _Traits, _Alloc>::
509250323Sdteske      _M_replace(iterator __i1, iterator __i2, _InputIter __k1, 
510250323Sdteske		 _InputIter __k2, input_iterator_tag)
511250323Sdteske      {
512250323Sdteske	// Save concerned source string data in a temporary.
513250323Sdteske	basic_string __s(__k1, __k2);
514251236Sdteske	return _M_replace_safe(__i1, __i2, __s._M_ibegin(), __s._M_iend());
515250323Sdteske      }
516250323Sdteske
517250323Sdteske  // This is a special replace helper, which does not buffer internally
518251264Sdteske  // and can be used in "safe" situations involving forward iterators,
519251264Sdteske  // i.e., when source and destination ranges are known to not overlap.
520251264Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
521250323Sdteske    template<typename _ForwardIter>
522250323Sdteske      basic_string<_CharT, _Traits, _Alloc>&
523250323Sdteske      basic_string<_CharT, _Traits, _Alloc>::
524250323Sdteske      _M_replace_safe(iterator __i1, iterator __i2, _ForwardIter __k1, 
525251264Sdteske		      _ForwardIter __k2)
526251232Sdteske      {
527251264Sdteske	size_type __dnew = static_cast<size_type>(distance(__k1, __k2));
528251264Sdteske	size_type __dold = __i2 - __i1;
529251232Sdteske	size_type __dmax = this->max_size();
530251232Sdteske
531251232Sdteske	if (__dmax <= __dnew)
532251232Sdteske	  __throw_length_error("basic_string::_M_replace");
533251232Sdteske	size_type __off = __i1 - _M_ibegin();
534251232Sdteske	_M_mutate(__off, __dold, __dnew);
535251232Sdteske
536251236Sdteske	// Invalidated __i1, __i2
537251236Sdteske        if (__dnew)
538250323Sdteske	  _S_copy_chars(_M_data() + __off, __k1, __k2);
539250323Sdteske
540250323Sdteske	return *this;
541250323Sdteske      }
542250323Sdteske
543251232Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
544251232Sdteske    basic_string<_CharT, _Traits, _Alloc>&
545250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
546250323Sdteske    replace(size_type __pos1, size_type __n1, const basic_string& __str,
547250323Sdteske	    size_type __pos2, size_type __n2)
548250323Sdteske    {
549251236Sdteske      const size_type __strsize = __str.size();
550250323Sdteske      if (__pos2 > __strsize)
551250323Sdteske	__throw_out_of_range("basic_string::replace");
552250323Sdteske      const bool __testn2 = __n2 < __strsize - __pos2;
553250323Sdteske      const size_type __foldn2 = __testn2 ? __n2 : __strsize - __pos2;
554250323Sdteske      return this->replace(__pos1, __n1,
555250323Sdteske			   __str._M_data() + __pos2, __foldn2);      
556250323Sdteske    }
557250323Sdteske
558250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
559250323Sdteske    basic_string<_CharT, _Traits, _Alloc>&
560250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
561250323Sdteske    append(const basic_string& __str)
562251264Sdteske    {
563251264Sdteske      // Iff appending itself, string needs to pre-reserve the
564250323Sdteske      // correct size so that _M_mutate does not clobber the
565251264Sdteske      // iterators formed here.
566250323Sdteske      size_type __size = __str.size();
567250323Sdteske      size_type __len = __size + this->size();
568251264Sdteske      if (__len > this->capacity())
569251264Sdteske	this->reserve(__len);
570251264Sdteske      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_ibegin(),
571251264Sdteske			     __str._M_iend());
572250323Sdteske    }
573250323Sdteske
574250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
575250323Sdteske    basic_string<_CharT, _Traits, _Alloc>&
576250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
577250323Sdteske    append(const basic_string& __str, size_type __pos, size_type __n)
578250323Sdteske    {
579250323Sdteske      // Iff appending itself, string needs to pre-reserve the
580250323Sdteske      // correct size so that _M_mutate does not clobber the
581250323Sdteske      // iterators formed here.
582250323Sdteske      size_type __len = min(__str.size() - __pos, __n) + this->size();
583250323Sdteske      if (__len > this->capacity())
584250323Sdteske	this->reserve(__len);
585250323Sdteske      return _M_replace_safe(_M_iend(), _M_iend(), __str._M_check(__pos),
586251232Sdteske			     __str._M_fold(__pos, __n));
587251232Sdteske    }
588251232Sdteske
589251232Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
590251232Sdteske    basic_string<_CharT, _Traits, _Alloc>&
591251232Sdteske    basic_string<_CharT, _Traits, _Alloc>::
592251232Sdteske    append(const _CharT* __s, size_type __n)
593251232Sdteske    {
594251232Sdteske      size_type __len = __n + this->size();
595251236Sdteske      if (__len > this->capacity())
596251236Sdteske	this->reserve(__len);
597250323Sdteske      return _M_replace_safe(_M_iend(), _M_iend(), __s, __s + __n);
598250323Sdteske    }
599250323Sdteske
600250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
601250323Sdteske    basic_string<_CharT, _Traits, _Alloc>&
602251232Sdteske    basic_string<_CharT, _Traits, _Alloc>::
603251232Sdteske    append(size_type __n, _CharT __c)
604250323Sdteske    {
605251236Sdteske      size_type __len = __n + this->size();
606250323Sdteske      if (__len > this->capacity())
607250323Sdteske	this->reserve(__len);
608250323Sdteske       return this->replace(_M_iend(), _M_iend(), __n, __c);
609250323Sdteske    }
610250323Sdteske
611250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
612250323Sdteske    basic_string<_CharT, _Traits, _Alloc>
613250323Sdteske    operator+(const _CharT* __lhs,
614250323Sdteske	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
615250323Sdteske    {
616250323Sdteske      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
617250323Sdteske      typedef typename __string_type::size_type	  __size_type;
618250323Sdteske      __size_type __len = _Traits::length(__lhs);
619250323Sdteske      __string_type __str;
620250323Sdteske      __str.reserve(__len + __rhs.size());
621250323Sdteske      __str.append(__lhs, __lhs + __len);
622250323Sdteske      __str.append(__rhs);
623250323Sdteske      return __str;
624250323Sdteske    }
625250323Sdteske
626250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
627250323Sdteske    basic_string<_CharT, _Traits, _Alloc>
628250323Sdteske    operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
629250323Sdteske    {
630250323Sdteske      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
631250323Sdteske      typedef typename __string_type::size_type	  __size_type;
632250323Sdteske      __string_type __str;
633250323Sdteske      __size_type __len = __rhs.size();
634250323Sdteske      __str.reserve(__len + 1);
635250323Sdteske      __str.append(__size_type(1), __lhs);
636250323Sdteske      __str.append(__rhs);
637250323Sdteske      return __str;
638250323Sdteske    }
639250323Sdteske
640250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
641250323Sdteske    basic_string<_CharT, _Traits, _Alloc>&
642250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
643250323Sdteske    replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
644251236Sdteske    {
645250323Sdteske      size_type __n1 = __i2 - __i1;
646250323Sdteske      size_type __off1 = __i1 - _M_ibegin();
647250323Sdteske      if (max_size() - (this->size() - __n1) <= __n2)
648250323Sdteske	__throw_length_error("basic_string::replace");
649250323Sdteske      _M_mutate (__off1, __n1, __n2);
650250323Sdteske      // Invalidated __i1, __i2
651250323Sdteske      if (__n2)
652250323Sdteske	traits_type::assign(_M_data() + __off1, __n2, __c);
653250323Sdteske      return *this;
654250323Sdteske    }
655250323Sdteske  
656250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
657250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
658250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
659250323Sdteske    copy(_CharT* __s, size_type __n, size_type __pos) const
660250323Sdteske    {
661250323Sdteske      if (__pos > this->size())
662250323Sdteske	__throw_out_of_range("basic_string::copy");
663250323Sdteske      
664250323Sdteske      if (__n > this->size() - __pos)
665250323Sdteske	__n = this->size() - __pos;
666251236Sdteske      
667250323Sdteske      traits_type::copy(__s, _M_data() + __pos, __n);
668250323Sdteske      // 21.3.5.7 par 3: do not append null.  (good.)
669250323Sdteske      return __n;
670250323Sdteske    }
671250323Sdteske
672250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
673250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
674250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
675251236Sdteske    find(const _CharT* __s, size_type __pos, size_type __n) const
676251236Sdteske    {
677250323Sdteske      size_type __size = this->size();
678250323Sdteske      size_t __xpos = __pos;
679250323Sdteske      const _CharT* __data = _M_data();
680250323Sdteske      for (; __xpos + __n <= __size; ++__xpos)
681250323Sdteske	if (traits_type::compare(__data + __xpos, __s, __n) == 0)
682250323Sdteske	  return __xpos;
683250323Sdteske      return npos;
684251236Sdteske    }
685250323Sdteske
686250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
687250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
688250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
689251236Sdteske    find(_CharT __c, size_type __pos) const
690250323Sdteske    {
691250323Sdteske      size_type __size = this->size();
692250323Sdteske      size_type __ret = npos;
693251236Sdteske      if (__pos < __size)
694250323Sdteske	{
695250323Sdteske	  const _CharT* __data = _M_data();
696250323Sdteske	  size_type __n = __size - __pos;
697251236Sdteske	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
698250323Sdteske	  if (__p)
699250323Sdteske	    __ret = __p - __data;
700250323Sdteske	}
701251236Sdteske      return __ret;
702250323Sdteske    }
703250323Sdteske
704250323Sdteske
705250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
706250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
707250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
708250323Sdteske    rfind(const _CharT* __s, size_type __pos, size_type __n) const
709250323Sdteske    {
710250323Sdteske      size_type __size = this->size();
711250323Sdteske      if (__n <= __size)
712250323Sdteske	{
713250323Sdteske	  __pos = std::min(__size - __n, __pos);
714250323Sdteske	  const _CharT* __data = _M_data();
715250323Sdteske	  do 
716250323Sdteske	    {
717250323Sdteske	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
718250323Sdteske		return __pos;
719250323Sdteske	    } 
720250323Sdteske	  while (__pos-- > 0);
721250323Sdteske	}
722250323Sdteske      return npos;
723250323Sdteske    }
724250323Sdteske  
725250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
726250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
727250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
728250323Sdteske    rfind(_CharT __c, size_type __pos) const
729250323Sdteske    {
730250323Sdteske      size_type __size = this->size();
731250323Sdteske      if (__size)
732250323Sdteske	{
733250323Sdteske	  size_t __xpos = __size - 1;
734250323Sdteske	  if (__xpos > __pos)
735250323Sdteske	    __xpos = __pos;
736250323Sdteske      
737250323Sdteske	  for (++__xpos; __xpos-- > 0; )
738250323Sdteske	    if (traits_type::eq(_M_data()[__xpos], __c))
739250323Sdteske	      return __xpos;
740251236Sdteske	}
741250323Sdteske      return npos;
742250323Sdteske    }
743250323Sdteske  
744250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
745250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
746250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
747250323Sdteske    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
748250323Sdteske    {
749250323Sdteske      for (; __n && __pos < this->size(); ++__pos)
750250323Sdteske	{
751250323Sdteske	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
752250323Sdteske	  if (__p)
753250323Sdteske	    return __pos;
754250323Sdteske	}
755250323Sdteske      return npos;
756251236Sdteske    }
757251236Sdteske 
758250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
759250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
760250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
761250323Sdteske    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
762250323Sdteske    {
763250323Sdteske      size_type __size = this->size();
764250323Sdteske      if (__size && __n)
765250323Sdteske	{ 
766250323Sdteske	  if (--__size > __pos) 
767250323Sdteske	    __size = __pos;
768250323Sdteske	  do
769250323Sdteske	    {
770250323Sdteske	      if (traits_type::find(__s, __n, _M_data()[__size]))
771250323Sdteske		return __size;
772250323Sdteske	    } 
773250323Sdteske	  while (__size-- != 0);
774250323Sdteske	}
775250323Sdteske      return npos;
776250323Sdteske    }
777250323Sdteske  
778250323Sdteske  template<typename _CharT, typename _Traits, typename _Alloc>
779250323Sdteske    typename basic_string<_CharT, _Traits, _Alloc>::size_type
780250323Sdteske    basic_string<_CharT, _Traits, _Alloc>::
781250323Sdteske    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
782250323Sdteske    {
783250323Sdteske      size_t __xpos = __pos;
784      for (; __xpos < this->size(); ++__xpos)
785	if (!traits_type::find(__s, __n, _M_data()[__xpos]))
786	  return __xpos;
787      return npos;
788    }
789
790  template<typename _CharT, typename _Traits, typename _Alloc>
791    typename basic_string<_CharT, _Traits, _Alloc>::size_type
792    basic_string<_CharT, _Traits, _Alloc>::
793    find_first_not_of(_CharT __c, size_type __pos) const
794    {
795      size_t __xpos = __pos;
796      for (; __xpos < this->size(); ++__xpos)
797	if (!traits_type::eq(_M_data()[__xpos], __c))
798	  return __xpos;
799      return npos;
800    }
801
802  template<typename _CharT, typename _Traits, typename _Alloc>
803    typename basic_string<_CharT, _Traits, _Alloc>::size_type
804    basic_string<_CharT, _Traits, _Alloc>::
805    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
806    {
807      size_type __size = this->size();
808      if (__size)
809	{ 
810	  if (--__size > __pos) 
811	    __size = __pos;
812	  do
813	    {
814	      if (!traits_type::find(__s, __n, _M_data()[__size]))
815		return __size;
816	    } 
817	  while (__size--);
818	}
819      return npos;
820    }
821
822  template<typename _CharT, typename _Traits, typename _Alloc>
823    typename basic_string<_CharT, _Traits, _Alloc>::size_type
824    basic_string<_CharT, _Traits, _Alloc>::
825    find_last_not_of(_CharT __c, size_type __pos) const
826    {
827      size_type __size = this->size();
828      if (__size)
829	{ 
830	  if (--__size > __pos) 
831	    __size = __pos;
832	  do
833	    {
834	      if (!traits_type::eq(_M_data()[__size], __c))
835		return __size;
836	    } 
837	  while (__size--);
838	}
839      return npos;
840    }
841  
842  template<typename _CharT, typename _Traits, typename _Alloc>
843    int
844    basic_string<_CharT, _Traits, _Alloc>::
845    compare(size_type __pos, size_type __n, const basic_string& __str) const
846    {
847      size_type __size = this->size();
848      size_type __osize = __str.size();
849      if (__pos > __size)
850	__throw_out_of_range("basic_string::compare");
851      
852      size_type __rsize= min(__size - __pos, __n);
853      size_type __len = min(__rsize, __osize);
854      int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
855      if (!__r)
856	__r = __rsize - __osize;
857      return __r;
858    }
859
860  template<typename _CharT, typename _Traits, typename _Alloc>
861    int
862    basic_string<_CharT, _Traits, _Alloc>::
863    compare(size_type __pos1, size_type __n1, const basic_string& __str,
864	    size_type __pos2, size_type __n2) const
865    {
866      size_type __size = this->size();
867      size_type __osize = __str.size();
868      if (__pos1 > __size || __pos2 > __osize)
869	__throw_out_of_range("basic_string::compare");
870      
871      size_type __rsize = min(__size - __pos1, __n1);
872      size_type __rosize = min(__osize - __pos2, __n2);
873      size_type __len = min(__rsize, __rosize);
874      int __r = traits_type::compare(_M_data() + __pos1, 
875				     __str.data() + __pos2, __len);
876      if (!__r)
877	__r = __rsize - __rosize;
878      return __r;
879    }
880
881
882  template<typename _CharT, typename _Traits, typename _Alloc>
883    int
884    basic_string<_CharT, _Traits, _Alloc>::
885    compare(const _CharT* __s) const
886    {
887      size_type __size = this->size();
888      int __r = traits_type::compare(_M_data(), __s, __size);
889      if (!__r)
890	__r = __size - traits_type::length(__s);
891      return __r;
892    }
893
894
895  template<typename _CharT, typename _Traits, typename _Alloc>
896    int
897    basic_string <_CharT, _Traits, _Alloc>::
898    compare(size_type __pos, size_type __n1, const _CharT* __s) const
899    {
900      size_type __size = this->size();
901      if (__pos > __size)
902	__throw_out_of_range("basic_string::compare");
903      
904      size_type __osize = traits_type::length(__s);
905      size_type __rsize = min(__size - __pos, __n1);
906      size_type __len = min(__rsize, __osize);
907      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
908      if (!__r)
909	__r = __rsize - __osize;
910      return __r;
911    }
912
913  template<typename _CharT, typename _Traits, typename _Alloc>
914    int
915    basic_string <_CharT, _Traits, _Alloc>::
916    compare(size_type __pos, size_type __n1, const _CharT* __s, 
917	    size_type __n2) const
918    {
919      size_type __size = this->size();
920      if (__pos > __size)
921	__throw_out_of_range("basic_string::compare");
922      
923      size_type __osize = min(traits_type::length(__s), __n2);
924      size_type __rsize = min(__size - __pos, __n1);
925      size_type __len = min(__rsize, __osize);
926      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
927      if (!__r)
928	__r = __rsize - __osize;
929      return __r;
930    }
931
932  template <class _CharT, class _Traits, class _Alloc>
933    void
934    _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str,
935		   _CharT* __buf, typename _Alloc::size_type __bufsiz)
936    {
937      typedef typename _Alloc::size_type size_type;
938      size_type __strsize = __str.size();
939      size_type __bytes = min(__strsize, __bufsiz - 1);
940      _Traits::copy(__buf, __str.data(), __bytes);
941      __buf[__bytes] = _CharT();
942    }
943
944  // Inhibit implicit instantiations for required instantiations,
945  // which are defined via explicit instantiations elsewhere.  
946  // NB: This syntax is a GNU extension.
947  extern template class basic_string<char>;
948  extern template 
949    basic_istream<char>& 
950    operator>>(basic_istream<char>&, string&);
951  extern template 
952    basic_ostream<char>& 
953    operator<<(basic_ostream<char>&, const string&);
954  extern template 
955    basic_istream<char>& 
956    getline(basic_istream<char>&, string&, char);
957  extern template 
958    basic_istream<char>& 
959    getline(basic_istream<char>&, string&);
960
961  extern template class basic_string<wchar_t>;
962  extern template 
963    basic_istream<wchar_t>& 
964    operator>>(basic_istream<wchar_t>&, wstring&);
965  extern template 
966    basic_ostream<wchar_t>& 
967    operator<<(basic_ostream<wchar_t>&, const wstring&);
968  extern template 
969    basic_istream<wchar_t>& 
970    getline(basic_istream<wchar_t>&, wstring&, wchar_t);
971  extern template 
972    basic_istream<wchar_t>& 
973    getline(basic_istream<wchar_t>&, wstring&);
974} // namespace std
975
976#endif
977