197403Sobrien// Components for manipulating sequences of characters -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4169691Skan// 2006, 2007
597403Sobrien// Free Software Foundation, Inc.
697403Sobrien//
797403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
897403Sobrien// software; you can redistribute it and/or modify it under the
997403Sobrien// terms of the GNU General Public License as published by the
1097403Sobrien// Free Software Foundation; either version 2, or (at your option)
1197403Sobrien// any later version.
1297403Sobrien
1397403Sobrien// This library is distributed in the hope that it will be useful,
1497403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1597403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1697403Sobrien// GNU General Public License for more details.
1797403Sobrien
1897403Sobrien// You should have received a copy of the GNU General Public License along
1997403Sobrien// with this library; see the file COPYING.  If not, write to the Free
20169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2197403Sobrien// USA.
2297403Sobrien
2397403Sobrien// As a special exception, you may use this file as part of a free software
2497403Sobrien// library without restriction.  Specifically, if other files instantiate
2597403Sobrien// templates or use macros or inline functions from this file, or you compile
2697403Sobrien// this file and link it with other files to produce an executable, this
2797403Sobrien// file does not by itself cause the resulting executable to be covered by
2897403Sobrien// the GNU General Public License.  This exception does not however
2997403Sobrien// invalidate any other reasons why the executable file might be covered by
3097403Sobrien// the GNU General Public License.
3197403Sobrien
32169691Skan/** @file basic_string.tcc
33169691Skan *  This is an internal header file, included by other library headers.
34169691Skan *  You should not attempt to use it directly.
35169691Skan */
36169691Skan
3797403Sobrien//
3897403Sobrien// ISO C++ 14882: 21  Strings library
3997403Sobrien//
4097403Sobrien
4197403Sobrien// Written by Jason Merrill based upon the specification by Takanori Adachi
4297403Sobrien// in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
4397403Sobrien
44132720Skan#ifndef _BASIC_STRING_TCC
45132720Skan#define _BASIC_STRING_TCC 1
4697403Sobrien
4797403Sobrien#pragma GCC system_header
4897403Sobrien
49169691Skan_GLIBCXX_BEGIN_NAMESPACE(std)
50169691Skan
51132720Skan  template<typename _Type>
52132720Skan    inline bool
53132720Skan    __is_null_pointer(_Type* __ptr)
54132720Skan    { return __ptr == 0; }
55132720Skan
56132720Skan  template<typename _Type>
57132720Skan    inline bool
58132720Skan    __is_null_pointer(_Type)
59132720Skan    { return false; }
60132720Skan
6197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
62132720Skan    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
6397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
64132720Skan    _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
6597403Sobrien
6697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
67132720Skan    const _CharT
6897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
6997403Sobrien    _Rep::_S_terminal = _CharT();
7097403Sobrien
7197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
7297403Sobrien    const typename basic_string<_CharT, _Traits, _Alloc>::size_type
7397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::npos;
7497403Sobrien
7597403Sobrien  // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
7697403Sobrien  // at static init time (before static ctors are run).
7797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
7897403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
79132720Skan    basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
80132720Skan    (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
81132720Skan      sizeof(size_type)];
8297403Sobrien
8397403Sobrien  // NB: This is the special case for Input Iterators, used in
8497403Sobrien  // istreambuf_iterators, etc.
8597403Sobrien  // Input Iterators have a cost structure very different from
8697403Sobrien  // pointers, calling for a different coding style.
8797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
88132720Skan    template<typename _InIterator>
8997403Sobrien      _CharT*
9097403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
91132720Skan      _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
9297403Sobrien		   input_iterator_tag)
9397403Sobrien      {
94146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
9597403Sobrien	if (__beg == __end && __a == _Alloc())
96132720Skan	  return _S_empty_rep()._M_refdata();
97146897Skan#endif
9897403Sobrien	// Avoid reallocation for common case.
99132720Skan	_CharT __buf[128];
100132720Skan	size_type __len = 0;
101132720Skan	while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
102132720Skan	  {
103132720Skan	    __buf[__len++] = *__beg;
104132720Skan	    ++__beg;
10597403Sobrien	  }
106132720Skan	_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
107169691Skan	_M_copy(__r->_M_refdata(), __buf, __len);
108132720Skan	try
10997403Sobrien	  {
110132720Skan	    while (__beg != __end)
11197403Sobrien	      {
112132720Skan		if (__len == __r->_M_capacity)
11397403Sobrien		  {
114132720Skan		    // Allocate more space.
115132720Skan		    _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
116169691Skan		    _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
117132720Skan		    __r->_M_destroy(__a);
118132720Skan		    __r = __another;
11997403Sobrien		  }
120132720Skan		__r->_M_refdata()[__len++] = *__beg;
121132720Skan		++__beg;
12297403Sobrien	      }
12397403Sobrien	  }
124132720Skan	catch(...)
12597403Sobrien	  {
126132720Skan	    __r->_M_destroy(__a);
12797403Sobrien	    __throw_exception_again;
12897403Sobrien	  }
129169691Skan	__r->_M_set_length_and_sharable(__len);
130132720Skan	return __r->_M_refdata();
13197403Sobrien      }
132132720Skan
13397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
134132720Skan    template <typename _InIterator>
13597403Sobrien      _CharT*
13697403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
137132720Skan      _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
13897403Sobrien		   forward_iterator_tag)
13997403Sobrien      {
140146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
141107606Sobrien	if (__beg == __end && __a == _Alloc())
142132720Skan	  return _S_empty_rep()._M_refdata();
143146897Skan#endif
14497403Sobrien	// NB: Not required, but considered best practice.
145146897Skan	if (__builtin_expect(__is_null_pointer(__beg) && __beg != __end, 0))
146132720Skan	  __throw_logic_error(__N("basic_string::_S_construct NULL not valid"));
147117397Skan
148132720Skan	const size_type __dnew = static_cast<size_type>(std::distance(__beg,
149132720Skan								      __end));
15097403Sobrien	// Check for out_of_range and length_error exceptions.
151132720Skan	_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
152132720Skan	try
15397403Sobrien	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
154132720Skan	catch(...)
155132720Skan	  {
156132720Skan	    __r->_M_destroy(__a);
15797403Sobrien	    __throw_exception_again;
15897403Sobrien	  }
159169691Skan	__r->_M_set_length_and_sharable(__dnew);
16097403Sobrien	return __r->_M_refdata();
16197403Sobrien      }
16297403Sobrien
16397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
16497403Sobrien    _CharT*
16597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
16697403Sobrien    _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
16797403Sobrien    {
168146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
16997403Sobrien      if (__n == 0 && __a == _Alloc())
170132720Skan	return _S_empty_rep()._M_refdata();
171146897Skan#endif
17297403Sobrien      // Check for out_of_range and length_error exceptions.
173132720Skan      _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
174132720Skan      if (__n)
175169691Skan	_M_assign(__r->_M_refdata(), __n, __c);
176132720Skan
177169691Skan      __r->_M_set_length_and_sharable(__n);
17897403Sobrien      return __r->_M_refdata();
17997403Sobrien    }
18097403Sobrien
18197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
18297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
18397403Sobrien    basic_string(const basic_string& __str)
184132720Skan    : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
185132720Skan					  __str.get_allocator()),
186132720Skan		  __str.get_allocator())
18797403Sobrien    { }
18897403Sobrien
18997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
19097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
19197403Sobrien    basic_string(const _Alloc& __a)
19297403Sobrien    : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
19397403Sobrien    { }
194132720Skan
19597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
19697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
19797403Sobrien    basic_string(const basic_string& __str, size_type __pos, size_type __n)
198132720Skan    : _M_dataplus(_S_construct(__str._M_data()
199132720Skan			       + __str._M_check(__pos,
200132720Skan						"basic_string::basic_string"),
201132720Skan			       __str._M_data() + __str._M_limit(__pos, __n)
202132720Skan			       + __pos, _Alloc()), _Alloc())
20397403Sobrien    { }
20497403Sobrien
20597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
20697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
20797403Sobrien    basic_string(const basic_string& __str, size_type __pos,
20897403Sobrien		 size_type __n, const _Alloc& __a)
209132720Skan    : _M_dataplus(_S_construct(__str._M_data()
210132720Skan			       + __str._M_check(__pos,
211132720Skan						"basic_string::basic_string"),
212132720Skan			       __str._M_data() + __str._M_limit(__pos, __n)
213132720Skan			       + __pos, __a), __a)
21497403Sobrien    { }
21597403Sobrien
216132720Skan  // TBD: DPG annotate
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
223132720Skan  // TBD: DPG annotate
22497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
22597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
22697403Sobrien    basic_string(const _CharT* __s, const _Alloc& __a)
227107606Sobrien    : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
228107606Sobrien			       __s + npos, __a), __a)
22997403Sobrien    { }
23097403Sobrien
23197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
23297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
23397403Sobrien    basic_string(size_type __n, _CharT __c, const _Alloc& __a)
23497403Sobrien    : _M_dataplus(_S_construct(__n, __c, __a), __a)
23597403Sobrien    { }
236132720Skan
237132720Skan  // TBD: DPG annotate
23897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
239132720Skan    template<typename _InputIterator>
24097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
241132720Skan    basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
24297403Sobrien    : _M_dataplus(_S_construct(__beg, __end, __a), __a)
24397403Sobrien    { }
24497403Sobrien
24597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
24697403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
247132720Skan    basic_string<_CharT, _Traits, _Alloc>::
248132720Skan    assign(const basic_string& __str)
24997403Sobrien    {
25097403Sobrien      if (_M_rep() != __str._M_rep())
25197403Sobrien	{
25297403Sobrien	  // XXX MT
253132720Skan	  const allocator_type __a = this->get_allocator();
25497403Sobrien	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
25597403Sobrien	  _M_rep()->_M_dispose(__a);
25697403Sobrien	  _M_data(__tmp);
25797403Sobrien	}
25897403Sobrien      return *this;
25997403Sobrien    }
260117397Skan
261169691Skan  template<typename _CharT, typename _Traits, typename _Alloc>
262169691Skan    basic_string<_CharT, _Traits, _Alloc>&
263169691Skan    basic_string<_CharT, _Traits, _Alloc>::
264169691Skan    assign(const _CharT* __s, size_type __n)
265169691Skan    {
266169691Skan      __glibcxx_requires_string_len(__s, __n);
267169691Skan      _M_check_length(this->size(), __n, "basic_string::assign");
268169691Skan      if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
269169691Skan	return _M_replace_safe(size_type(0), this->size(), __s, __n);
270169691Skan      else
271169691Skan	{
272169691Skan	  // Work in-place.
273169691Skan	  const size_type __pos = __s - _M_data();
274169691Skan	  if (__pos >= __n)
275169691Skan	    _M_copy(_M_data(), __s, __n);
276169691Skan	  else if (__pos)
277169691Skan	    _M_move(_M_data(), __s, __n);
278169691Skan	  _M_rep()->_M_set_length_and_sharable(__n);
279169691Skan	  return *this;
280169691Skan	}
281117397Skan     }
282117397Skan
283169691Skan  template<typename _CharT, typename _Traits, typename _Alloc>
284169691Skan    basic_string<_CharT, _Traits, _Alloc>&
285169691Skan    basic_string<_CharT, _Traits, _Alloc>::
286169691Skan    append(size_type __n, _CharT __c)
287169691Skan    {
288169691Skan      if (__n)
289169691Skan	{
290169691Skan	  _M_check_length(size_type(0), __n, "basic_string::append");	  
291169691Skan	  const size_type __len = __n + this->size();
292169691Skan	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
293169691Skan	    this->reserve(__len);
294169691Skan	  _M_assign(_M_data() + this->size(), __n, __c);
295169691Skan	  _M_rep()->_M_set_length_and_sharable(__len);
296169691Skan	}
297169691Skan      return *this;
298169691Skan    }
299169691Skan
300169691Skan  template<typename _CharT, typename _Traits, typename _Alloc>
301169691Skan    basic_string<_CharT, _Traits, _Alloc>&
302169691Skan    basic_string<_CharT, _Traits, _Alloc>::
303169691Skan    append(const _CharT* __s, size_type __n)
304169691Skan    {
305169691Skan      __glibcxx_requires_string_len(__s, __n);
306169691Skan      if (__n)
307169691Skan	{
308169691Skan	  _M_check_length(size_type(0), __n, "basic_string::append");
309169691Skan	  const size_type __len = __n + this->size();
310169691Skan	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
311169691Skan	    {
312169691Skan	      if (_M_disjunct(__s))
313169691Skan		this->reserve(__len);
314169691Skan	      else
315169691Skan		{
316169691Skan		  const size_type __off = __s - _M_data();
317169691Skan		  this->reserve(__len);
318169691Skan		  __s = _M_data() + __off;
319169691Skan		}
320169691Skan	    }
321169691Skan	  _M_copy(_M_data() + this->size(), __s, __n);
322169691Skan	  _M_rep()->_M_set_length_and_sharable(__len);
323169691Skan	}
324169691Skan      return *this;
325169691Skan    }
326169691Skan
327169691Skan  template<typename _CharT, typename _Traits, typename _Alloc>
328169691Skan    basic_string<_CharT, _Traits, _Alloc>&
329169691Skan    basic_string<_CharT, _Traits, _Alloc>::
330169691Skan    append(const basic_string& __str)
331169691Skan    {
332169691Skan      const size_type __size = __str.size();
333169691Skan      if (__size)
334169691Skan	{
335169691Skan	  const size_type __len = __size + this->size();
336169691Skan	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
337169691Skan	    this->reserve(__len);
338169691Skan	  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
339169691Skan	  _M_rep()->_M_set_length_and_sharable(__len);
340169691Skan	}
341169691Skan      return *this;
342169691Skan    }    
343169691Skan
344169691Skan  template<typename _CharT, typename _Traits, typename _Alloc>
345169691Skan    basic_string<_CharT, _Traits, _Alloc>&
346169691Skan    basic_string<_CharT, _Traits, _Alloc>::
347169691Skan    append(const basic_string& __str, size_type __pos, size_type __n)
348169691Skan    {
349169691Skan      __str._M_check(__pos, "basic_string::append");
350169691Skan      __n = __str._M_limit(__pos, __n);
351169691Skan      if (__n)
352169691Skan	{
353169691Skan	  const size_type __len = __n + this->size();
354169691Skan	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
355169691Skan	    this->reserve(__len);
356169691Skan	  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
357169691Skan	  _M_rep()->_M_set_length_and_sharable(__len);	  
358169691Skan	}
359169691Skan      return *this;
360169691Skan    }
361169691Skan
362117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
363117397Skan     basic_string<_CharT, _Traits, _Alloc>&
364117397Skan     basic_string<_CharT, _Traits, _Alloc>::
365117397Skan     insert(size_type __pos, const _CharT* __s, size_type __n)
366117397Skan     {
367132720Skan       __glibcxx_requires_string_len(__s, __n);
368132720Skan       _M_check(__pos, "basic_string::insert");
369169691Skan       _M_check_length(size_type(0), __n, "basic_string::insert");
370169691Skan       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
371132720Skan         return _M_replace_safe(__pos, size_type(0), __s, __n);
372117397Skan       else
373117397Skan         {
374169691Skan           // Work in-place.
375117397Skan           const size_type __off = __s - _M_data();
376117397Skan           _M_mutate(__pos, 0, __n);
377117397Skan           __s = _M_data() + __off;
378117397Skan           _CharT* __p = _M_data() + __pos;
379117397Skan           if (__s  + __n <= __p)
380169691Skan             _M_copy(__p, __s, __n);
381117397Skan           else if (__s >= __p)
382169691Skan             _M_copy(__p, __s + __n, __n);
383117397Skan           else
384117397Skan             {
385132720Skan	       const size_type __nleft = __p - __s;
386169691Skan               _M_copy(__p, __s, __nleft);
387169691Skan               _M_copy(__p + __nleft, __p + __n, __n - __nleft);
388117397Skan             }
389117397Skan           return *this;
390117397Skan         }
391117397Skan     }
392132720Skan
393117397Skan   template<typename _CharT, typename _Traits, typename _Alloc>
394117397Skan     basic_string<_CharT, _Traits, _Alloc>&
395117397Skan     basic_string<_CharT, _Traits, _Alloc>::
396117397Skan     replace(size_type __pos, size_type __n1, const _CharT* __s,
397117397Skan	     size_type __n2)
398117397Skan     {
399132720Skan       __glibcxx_requires_string_len(__s, __n2);
400132720Skan       _M_check(__pos, "basic_string::replace");
401132720Skan       __n1 = _M_limit(__pos, __n1);
402169691Skan       _M_check_length(__n1, __n2, "basic_string::replace");
403132720Skan       bool __left;
404169691Skan       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
405132720Skan         return _M_replace_safe(__pos, __n1, __s, __n2);
406132720Skan       else if ((__left = __s + __n2 <= _M_data() + __pos)
407132720Skan		|| _M_data() + __pos + __n1 <= __s)
408132720Skan	 {
409132720Skan	   // Work in-place: non-overlapping case.
410169691Skan	   size_type __off = __s - _M_data();
411169691Skan	   __left ? __off : (__off += __n2 - __n1);
412132720Skan	   _M_mutate(__pos, __n1, __n2);
413169691Skan	   _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
414132720Skan	   return *this;
415132720Skan	 }
416117397Skan       else
417132720Skan	 {
418132720Skan	   // Todo: overlapping case.
419132720Skan	   const basic_string __tmp(__s, __n2);
420132720Skan	   return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
421132720Skan	 }
422117397Skan     }
423132720Skan
42497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
42597403Sobrien    void
42697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
42797403Sobrien    _M_destroy(const _Alloc& __a) throw ()
42897403Sobrien    {
429132720Skan      const size_type __size = sizeof(_Rep_base) +
430132720Skan	                       (this->_M_capacity + 1) * sizeof(_CharT);
43197403Sobrien      _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
43297403Sobrien    }
43397403Sobrien
43497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
43597403Sobrien    void
436169691Skan    basic_string<_CharT, _Traits, _Alloc>::
437169691Skan    _M_leak_hard()
43897403Sobrien    {
439146897Skan#ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
440132720Skan      if (_M_rep() == &_S_empty_rep())
441146897Skan	return;
442146897Skan#endif
443132720Skan      if (_M_rep()->_M_is_shared())
44497403Sobrien	_M_mutate(0, 0, 0);
44597403Sobrien      _M_rep()->_M_set_leaked();
44697403Sobrien    }
44797403Sobrien
44897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
44997403Sobrien    void
45097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
45197403Sobrien    _M_mutate(size_type __pos, size_type __len1, size_type __len2)
45297403Sobrien    {
453132720Skan      const size_type __old_size = this->size();
45497403Sobrien      const size_type __new_size = __old_size + __len2 - __len1;
45597403Sobrien      const size_type __how_much = __old_size - __pos - __len1;
456132720Skan
457169691Skan      if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
45897403Sobrien	{
45997403Sobrien	  // Must reallocate.
460132720Skan	  const allocator_type __a = get_allocator();
461169691Skan	  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
462132720Skan
463132720Skan	  if (__pos)
464169691Skan	    _M_copy(__r->_M_refdata(), _M_data(), __pos);
465132720Skan	  if (__how_much)
466169691Skan	    _M_copy(__r->_M_refdata() + __pos + __len2,
467169691Skan		    _M_data() + __pos + __len1, __how_much);
468132720Skan
46997403Sobrien	  _M_rep()->_M_dispose(__a);
47097403Sobrien	  _M_data(__r->_M_refdata());
471132720Skan	}
47297403Sobrien      else if (__how_much && __len1 != __len2)
47397403Sobrien	{
474169691Skan	  // Work in-place.
475169691Skan	  _M_move(_M_data() + __pos + __len2,
476169691Skan		  _M_data() + __pos + __len1, __how_much);
47797403Sobrien	}
478169691Skan      _M_rep()->_M_set_length_and_sharable(__new_size);
47997403Sobrien    }
480132720Skan
48197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
48297403Sobrien    void
483169691Skan    basic_string<_CharT, _Traits, _Alloc>::
484169691Skan    reserve(size_type __res)
48597403Sobrien    {
486132720Skan      if (__res != this->capacity() || _M_rep()->_M_is_shared())
48797403Sobrien        {
48897403Sobrien	  // Make sure we don't shrink below the current size
48997403Sobrien	  if (__res < this->size())
49097403Sobrien	    __res = this->size();
491132720Skan	  const allocator_type __a = get_allocator();
49297403Sobrien	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
49397403Sobrien	  _M_rep()->_M_dispose(__a);
49497403Sobrien	  _M_data(__tmp);
49597403Sobrien        }
49697403Sobrien    }
497132720Skan
49897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
499169691Skan    void
500169691Skan    basic_string<_CharT, _Traits, _Alloc>::
501169691Skan    swap(basic_string& __s)
50297403Sobrien    {
503132720Skan      if (_M_rep()->_M_is_leaked())
50497403Sobrien	_M_rep()->_M_set_sharable();
505132720Skan      if (__s._M_rep()->_M_is_leaked())
50697403Sobrien	__s._M_rep()->_M_set_sharable();
50797403Sobrien      if (this->get_allocator() == __s.get_allocator())
50897403Sobrien	{
50997403Sobrien	  _CharT* __tmp = _M_data();
51097403Sobrien	  _M_data(__s._M_data());
51197403Sobrien	  __s._M_data(__tmp);
51297403Sobrien	}
51397403Sobrien      // The code below can usually be optimized away.
514132720Skan      else
51597403Sobrien	{
516132720Skan	  const basic_string __tmp1(_M_ibegin(), _M_iend(),
517132720Skan				    __s.get_allocator());
518132720Skan	  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
519132720Skan				    this->get_allocator());
52097403Sobrien	  *this = __tmp2;
52197403Sobrien	  __s = __tmp1;
52297403Sobrien	}
52397403Sobrien    }
52497403Sobrien
52597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
52697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
52797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
528132720Skan    _S_create(size_type __capacity, size_type __old_capacity,
529132720Skan	      const _Alloc& __alloc)
53097403Sobrien    {
531132720Skan      // _GLIBCXX_RESOLVE_LIB_DEFECTS
53297403Sobrien      // 83.  String::npos vs. string::max_size()
53397403Sobrien      if (__capacity > _S_max_size)
534132720Skan	__throw_length_error(__N("basic_string::_S_create"));
53597403Sobrien
53697403Sobrien      // The standard places no restriction on allocating more memory
53797403Sobrien      // than is strictly needed within this layer at the moment or as
538132720Skan      // requested by an explicit application call to reserve().
539132720Skan
540132720Skan      // Many malloc implementations perform quite poorly when an
54197403Sobrien      // application attempts to allocate memory in a stepwise fashion
54297403Sobrien      // growing each allocation size by only 1 char.  Additionally,
54397403Sobrien      // it makes little sense to allocate less linear memory than the
54497403Sobrien      // natural blocking size of the malloc implementation.
54597403Sobrien      // Unfortunately, we would need a somewhat low-level calculation
54697403Sobrien      // with tuned parameters to get this perfect for any particular
54797403Sobrien      // malloc implementation.  Fortunately, generalizations about
54897403Sobrien      // common features seen among implementations seems to suffice.
54997403Sobrien
55097403Sobrien      // __pagesize need not match the actual VM page size for good
55197403Sobrien      // results in practice, thus we pick a common value on the low
55297403Sobrien      // side.  __malloc_header_size is an estimate of the amount of
55397403Sobrien      // overhead per memory allocation (in practice seen N * sizeof
55497403Sobrien      // (void*) where N is 0, 2 or 4).  According to folklore,
55597403Sobrien      // picking this value on the high side is better than
55697403Sobrien      // low-balling it (especially when this algorithm is used with
55797403Sobrien      // malloc implementations that allocate memory blocks rounded up
55897403Sobrien      // to a size which is a power of 2).
559169691Skan      const size_type __pagesize = 4096;
560169691Skan      const size_type __malloc_header_size = 4 * sizeof(void*);
561132720Skan
562132720Skan      // The below implements an exponential growth policy, necessary to
563132720Skan      // meet amortized linear time requirements of the library: see
564132720Skan      // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
565132720Skan      // It's active for allocations requiring an amount of memory above
566132720Skan      // system pagesize. This is consistent with the requirements of the
567132720Skan      // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
568169691Skan      if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
569132720Skan	__capacity = 2 * __old_capacity;
570132720Skan
571132720Skan      // NB: Need an array of char_type[__capacity], plus a terminating
572132720Skan      // null char_type() element, plus enough for the _Rep data structure.
573132720Skan      // Whew. Seemingly so needy, yet so elemental.
574132720Skan      size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
575132720Skan
576132720Skan      const size_type __adj_size = __size + __malloc_header_size;
577169691Skan      if (__adj_size > __pagesize && __capacity > __old_capacity)
57897403Sobrien	{
579132720Skan	  const size_type __extra = __pagesize - __adj_size % __pagesize;
58097403Sobrien	  __capacity += __extra / sizeof(_CharT);
581132720Skan	  // Never allocate a string bigger than _S_max_size.
582132720Skan	  if (__capacity > _S_max_size)
583132720Skan	    __capacity = _S_max_size;
58497403Sobrien	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
58597403Sobrien	}
58697403Sobrien
58797403Sobrien      // NB: Might throw, but no worries about a leak, mate: _Rep()
58897403Sobrien      // does not throw.
58997403Sobrien      void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
59097403Sobrien      _Rep *__p = new (__place) _Rep;
59197403Sobrien      __p->_M_capacity = __capacity;
592169691Skan      // ABI compatibility - 3.4.x set in _S_create both
593169691Skan      // _M_refcount and _M_length.  All callers of _S_create
594169691Skan      // in basic_string.tcc then set just _M_length.
595169691Skan      // In 4.0.x and later both _M_refcount and _M_length
596169691Skan      // are initialized in the callers, unfortunately we can
597169691Skan      // have 3.4.x compiled code with _S_create callers inlined
598169691Skan      // calling 4.0.x+ _S_create.
599169691Skan      __p->_M_set_sharable();
60097403Sobrien      return __p;
60197403Sobrien    }
60297403Sobrien
60397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
60497403Sobrien    _CharT*
60597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::_Rep::
60697403Sobrien    _M_clone(const _Alloc& __alloc, size_type __res)
60797403Sobrien    {
60897403Sobrien      // Requested capacity of the clone.
609132720Skan      const size_type __requested_cap = this->_M_length + __res;
610132720Skan      _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
611132720Skan				  __alloc);
612132720Skan      if (this->_M_length)
613169691Skan	_M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
614132720Skan
615169691Skan      __r->_M_set_length_and_sharable(this->_M_length);
61697403Sobrien      return __r->_M_refdata();
61797403Sobrien    }
618132720Skan
61997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
62097403Sobrien    void
621169691Skan    basic_string<_CharT, _Traits, _Alloc>::
622169691Skan    resize(size_type __n, _CharT __c)
62397403Sobrien    {
624132720Skan      const size_type __size = this->size();
625169691Skan      _M_check_length(__size, __n, "basic_string::resize");
62697403Sobrien      if (__size < __n)
62797403Sobrien	this->append(__n - __size, __c);
62897403Sobrien      else if (__n < __size)
62997403Sobrien	this->erase(__n);
63097403Sobrien      // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
63197403Sobrien    }
632102782Skan
63397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
634132720Skan    template<typename _InputIterator>
63597403Sobrien      basic_string<_CharT, _Traits, _Alloc>&
63697403Sobrien      basic_string<_CharT, _Traits, _Alloc>::
637132720Skan      _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
638132720Skan			  _InputIterator __k2, __false_type)
63997403Sobrien      {
640132720Skan	const basic_string __s(__k1, __k2);
641132720Skan	const size_type __n1 = __i2 - __i1;
642169691Skan	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
643132720Skan	return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
644132720Skan			       __s.size());
64597403Sobrien      }
64697403Sobrien
64797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
64897403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
64997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
650169691Skan    _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
651169691Skan		   _CharT __c)
65297403Sobrien    {
653169691Skan      _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
654169691Skan      _M_mutate(__pos1, __n1, __n2);
655169691Skan      if (__n2)
656169691Skan	_M_assign(_M_data() + __pos1, __n2, __c);
657169691Skan      return *this;
65897403Sobrien    }
65997403Sobrien
66097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
66197403Sobrien    basic_string<_CharT, _Traits, _Alloc>&
66297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
663169691Skan    _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
664169691Skan		    size_type __n2)
66597403Sobrien    {
666169691Skan      _M_mutate(__pos1, __n1, __n2);
667169691Skan      if (__n2)
668169691Skan	_M_copy(_M_data() + __pos1, __s, __n2);
669169691Skan      return *this;
67097403Sobrien    }
671169691Skan   
67297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
67397403Sobrien    basic_string<_CharT, _Traits, _Alloc>
67497403Sobrien    operator+(const _CharT* __lhs,
67597403Sobrien	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
67697403Sobrien    {
677132720Skan      __glibcxx_requires_string(__lhs);
67897403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
67997403Sobrien      typedef typename __string_type::size_type	  __size_type;
680132720Skan      const __size_type __len = _Traits::length(__lhs);
68197403Sobrien      __string_type __str;
68297403Sobrien      __str.reserve(__len + __rhs.size());
683132720Skan      __str.append(__lhs, __len);
68497403Sobrien      __str.append(__rhs);
68597403Sobrien      return __str;
68697403Sobrien    }
68797403Sobrien
68897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
68997403Sobrien    basic_string<_CharT, _Traits, _Alloc>
69097403Sobrien    operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
69197403Sobrien    {
69297403Sobrien      typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
69397403Sobrien      typedef typename __string_type::size_type	  __size_type;
69497403Sobrien      __string_type __str;
695132720Skan      const __size_type __len = __rhs.size();
69697403Sobrien      __str.reserve(__len + 1);
69797403Sobrien      __str.append(__size_type(1), __lhs);
69897403Sobrien      __str.append(__rhs);
69997403Sobrien      return __str;
70097403Sobrien    }
70197403Sobrien
70297403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
70397403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
70497403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
70597403Sobrien    copy(_CharT* __s, size_type __n, size_type __pos) const
70697403Sobrien    {
707132720Skan      _M_check(__pos, "basic_string::copy");
708132720Skan      __n = _M_limit(__pos, __n);
709132720Skan      __glibcxx_requires_string_len(__s, __n);
710132720Skan      if (__n)
711169691Skan	_M_copy(__s, _M_data() + __pos, __n);
71297403Sobrien      // 21.3.5.7 par 3: do not append null.  (good.)
71397403Sobrien      return __n;
71497403Sobrien    }
71597403Sobrien
71697403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
71797403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
71897403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
71997403Sobrien    find(const _CharT* __s, size_type __pos, size_type __n) const
72097403Sobrien    {
721132720Skan      __glibcxx_requires_string_len(__s, __n);
722132720Skan      const size_type __size = this->size();
72397403Sobrien      const _CharT* __data = _M_data();
724169691Skan
725169691Skan      if (__n == 0)
726169691Skan	return __pos <= __size ? __pos : npos;
727169691Skan
728169691Skan      if (__n <= __size)
729169691Skan	{
730169691Skan	  for (; __pos <= __size - __n; ++__pos)
731169691Skan	    if (traits_type::eq(__data[__pos], __s[0])
732169691Skan		&& traits_type::compare(__data + __pos + 1,
733169691Skan					__s + 1, __n - 1) == 0)
734169691Skan	      return __pos;
735169691Skan	}
73697403Sobrien      return npos;
73797403Sobrien    }
73897403Sobrien
73997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
74097403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
74197403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
74297403Sobrien    find(_CharT __c, size_type __pos) const
74397403Sobrien    {
744169691Skan      size_type __ret = npos;
745132720Skan      const size_type __size = this->size();
74697403Sobrien      if (__pos < __size)
74797403Sobrien	{
74897403Sobrien	  const _CharT* __data = _M_data();
749132720Skan	  const size_type __n = __size - __pos;
75097403Sobrien	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
75197403Sobrien	  if (__p)
75297403Sobrien	    __ret = __p - __data;
75397403Sobrien	}
75497403Sobrien      return __ret;
75597403Sobrien    }
75697403Sobrien
75797403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
75897403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
75997403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
76097403Sobrien    rfind(const _CharT* __s, size_type __pos, size_type __n) const
76197403Sobrien    {
762132720Skan      __glibcxx_requires_string_len(__s, __n);
763132720Skan      const size_type __size = this->size();
76497403Sobrien      if (__n <= __size)
76597403Sobrien	{
766117397Skan	  __pos = std::min(size_type(__size - __n), __pos);
76797403Sobrien	  const _CharT* __data = _M_data();
768132720Skan	  do
76997403Sobrien	    {
77097403Sobrien	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
77197403Sobrien		return __pos;
772132720Skan	    }
77397403Sobrien	  while (__pos-- > 0);
77497403Sobrien	}
77597403Sobrien      return npos;
77697403Sobrien    }
777132720Skan
77897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
77997403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
78097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
78197403Sobrien    rfind(_CharT __c, size_type __pos) const
78297403Sobrien    {
78397403Sobrien      size_type __size = this->size();
78497403Sobrien      if (__size)
78597403Sobrien	{
786132720Skan	  if (--__size > __pos)
787132720Skan	    __size = __pos;
788132720Skan	  for (++__size; __size-- > 0; )
789132720Skan	    if (traits_type::eq(_M_data()[__size], __c))
790132720Skan	      return __size;
79197403Sobrien	}
79297403Sobrien      return npos;
79397403Sobrien    }
794132720Skan
79597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
79697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
79797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
79897403Sobrien    find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
79997403Sobrien    {
800132720Skan      __glibcxx_requires_string_len(__s, __n);
80197403Sobrien      for (; __n && __pos < this->size(); ++__pos)
80297403Sobrien	{
80397403Sobrien	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
80497403Sobrien	  if (__p)
80597403Sobrien	    return __pos;
80697403Sobrien	}
80797403Sobrien      return npos;
80897403Sobrien    }
809132720Skan
81097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
81197403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
81297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
81397403Sobrien    find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
81497403Sobrien    {
815132720Skan      __glibcxx_requires_string_len(__s, __n);
81697403Sobrien      size_type __size = this->size();
81797403Sobrien      if (__size && __n)
818132720Skan	{
819132720Skan	  if (--__size > __pos)
82097403Sobrien	    __size = __pos;
82197403Sobrien	  do
82297403Sobrien	    {
82397403Sobrien	      if (traits_type::find(__s, __n, _M_data()[__size]))
82497403Sobrien		return __size;
825132720Skan	    }
82697403Sobrien	  while (__size-- != 0);
82797403Sobrien	}
82897403Sobrien      return npos;
82997403Sobrien    }
830132720Skan
83197403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
83297403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
83397403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
83497403Sobrien    find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
83597403Sobrien    {
836132720Skan      __glibcxx_requires_string_len(__s, __n);
837132720Skan      for (; __pos < this->size(); ++__pos)
838132720Skan	if (!traits_type::find(__s, __n, _M_data()[__pos]))
839132720Skan	  return __pos;
84097403Sobrien      return npos;
84197403Sobrien    }
84297403Sobrien
84397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
84497403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
84597403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
84697403Sobrien    find_first_not_of(_CharT __c, size_type __pos) const
84797403Sobrien    {
848132720Skan      for (; __pos < this->size(); ++__pos)
849132720Skan	if (!traits_type::eq(_M_data()[__pos], __c))
850132720Skan	  return __pos;
85197403Sobrien      return npos;
85297403Sobrien    }
85397403Sobrien
85497403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
85597403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
85697403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
85797403Sobrien    find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
85897403Sobrien    {
859132720Skan      __glibcxx_requires_string_len(__s, __n);
86097403Sobrien      size_type __size = this->size();
86197403Sobrien      if (__size)
862132720Skan	{
863132720Skan	  if (--__size > __pos)
86497403Sobrien	    __size = __pos;
86597403Sobrien	  do
86697403Sobrien	    {
86797403Sobrien	      if (!traits_type::find(__s, __n, _M_data()[__size]))
86897403Sobrien		return __size;
869132720Skan	    }
87097403Sobrien	  while (__size--);
87197403Sobrien	}
87297403Sobrien      return npos;
87397403Sobrien    }
87497403Sobrien
87597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
87697403Sobrien    typename basic_string<_CharT, _Traits, _Alloc>::size_type
87797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
87897403Sobrien    find_last_not_of(_CharT __c, size_type __pos) const
87997403Sobrien    {
88097403Sobrien      size_type __size = this->size();
88197403Sobrien      if (__size)
882132720Skan	{
883132720Skan	  if (--__size > __pos)
88497403Sobrien	    __size = __pos;
88597403Sobrien	  do
88697403Sobrien	    {
88797403Sobrien	      if (!traits_type::eq(_M_data()[__size], __c))
88897403Sobrien		return __size;
889132720Skan	    }
89097403Sobrien	  while (__size--);
89197403Sobrien	}
89297403Sobrien      return npos;
89397403Sobrien    }
894132720Skan
89597403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
89697403Sobrien    int
89797403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
89897403Sobrien    compare(size_type __pos, size_type __n, const basic_string& __str) const
89997403Sobrien    {
900132720Skan      _M_check(__pos, "basic_string::compare");
901132720Skan      __n = _M_limit(__pos, __n);
902132720Skan      const size_type __osize = __str.size();
903132720Skan      const size_type __len = std::min(__n, __osize);
90497403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
90597403Sobrien      if (!__r)
906259694Spfg	__r = _S_compare(__n, __osize);
90797403Sobrien      return __r;
90897403Sobrien    }
90997403Sobrien
91097403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
91197403Sobrien    int
91297403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
91397403Sobrien    compare(size_type __pos1, size_type __n1, const basic_string& __str,
91497403Sobrien	    size_type __pos2, size_type __n2) const
91597403Sobrien    {
916132720Skan      _M_check(__pos1, "basic_string::compare");
917132720Skan      __str._M_check(__pos2, "basic_string::compare");
918132720Skan      __n1 = _M_limit(__pos1, __n1);
919132720Skan      __n2 = __str._M_limit(__pos2, __n2);
920132720Skan      const size_type __len = std::min(__n1, __n2);
921132720Skan      int __r = traits_type::compare(_M_data() + __pos1,
92297403Sobrien				     __str.data() + __pos2, __len);
92397403Sobrien      if (!__r)
924259694Spfg	__r = _S_compare(__n1, __n2);
92597403Sobrien      return __r;
92697403Sobrien    }
92797403Sobrien
92897403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
92997403Sobrien    int
93097403Sobrien    basic_string<_CharT, _Traits, _Alloc>::
93197403Sobrien    compare(const _CharT* __s) const
93297403Sobrien    {
933132720Skan      __glibcxx_requires_string(__s);
934132720Skan      const size_type __size = this->size();
935132720Skan      const size_type __osize = traits_type::length(__s);
936132720Skan      const size_type __len = std::min(__size, __osize);
937107606Sobrien      int __r = traits_type::compare(_M_data(), __s, __len);
93897403Sobrien      if (!__r)
939259694Spfg	__r = _S_compare(__size, __osize);
94097403Sobrien      return __r;
94197403Sobrien    }
94297403Sobrien
94397403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
94497403Sobrien    int
94597403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
94697403Sobrien    compare(size_type __pos, size_type __n1, const _CharT* __s) const
94797403Sobrien    {
948132720Skan      __glibcxx_requires_string(__s);
949132720Skan      _M_check(__pos, "basic_string::compare");
950132720Skan      __n1 = _M_limit(__pos, __n1);
951132720Skan      const size_type __osize = traits_type::length(__s);
952132720Skan      const size_type __len = std::min(__n1, __osize);
95397403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
95497403Sobrien      if (!__r)
955259694Spfg	__r = _S_compare(__n1, __osize);
95697403Sobrien      return __r;
95797403Sobrien    }
95897403Sobrien
95997403Sobrien  template<typename _CharT, typename _Traits, typename _Alloc>
96097403Sobrien    int
96197403Sobrien    basic_string <_CharT, _Traits, _Alloc>::
962132720Skan    compare(size_type __pos, size_type __n1, const _CharT* __s,
96397403Sobrien	    size_type __n2) const
96497403Sobrien    {
965132720Skan      __glibcxx_requires_string_len(__s, __n2);
966132720Skan      _M_check(__pos, "basic_string::compare");
967132720Skan      __n1 = _M_limit(__pos, __n1);
968132720Skan      const size_type __len = std::min(__n1, __n2);
96997403Sobrien      int __r = traits_type::compare(_M_data() + __pos, __s, __len);
97097403Sobrien      if (!__r)
971259694Spfg	__r = _S_compare(__n1, __n2);
97297403Sobrien      return __r;
97397403Sobrien    }
97497403Sobrien
97597403Sobrien  // Inhibit implicit instantiations for required instantiations,
976132720Skan  // which are defined via explicit instantiations elsewhere.
97797403Sobrien  // NB: This syntax is a GNU extension.
978132720Skan#if _GLIBCXX_EXTERN_TEMPLATE
97997403Sobrien  extern template class basic_string<char>;
980132720Skan  extern template
981132720Skan    basic_istream<char>&
98297403Sobrien    operator>>(basic_istream<char>&, string&);
983132720Skan  extern template
984132720Skan    basic_ostream<char>&
98597403Sobrien    operator<<(basic_ostream<char>&, const string&);
986132720Skan  extern template
987132720Skan    basic_istream<char>&
98897403Sobrien    getline(basic_istream<char>&, string&, char);
989132720Skan  extern template
990132720Skan    basic_istream<char>&
99197403Sobrien    getline(basic_istream<char>&, string&);
99297403Sobrien
993132720Skan#ifdef _GLIBCXX_USE_WCHAR_T
99497403Sobrien  extern template class basic_string<wchar_t>;
995132720Skan  extern template
996132720Skan    basic_istream<wchar_t>&
99797403Sobrien    operator>>(basic_istream<wchar_t>&, wstring&);
998132720Skan  extern template
999132720Skan    basic_ostream<wchar_t>&
100097403Sobrien    operator<<(basic_ostream<wchar_t>&, const wstring&);
1001132720Skan  extern template
1002132720Skan    basic_istream<wchar_t>&
100397403Sobrien    getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1004132720Skan  extern template
1005132720Skan    basic_istream<wchar_t>&
100697403Sobrien    getline(basic_istream<wchar_t>&, wstring&);
1007107606Sobrien#endif
1008117397Skan#endif
100997403Sobrien
1010169691Skan_GLIBCXX_END_NAMESPACE
1011169691Skan
101297403Sobrien#endif
1013