xref: /dflybsd-src/contrib/gcc-8.0/libstdc++-v3/include/bits/basic_string.tcc (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj // Components for manipulating sequences of characters -*- C++ -*-
2*38fd1498Szrj 
3*38fd1498Szrj // Copyright (C) 1997-2018 Free Software Foundation, Inc.
4*38fd1498Szrj //
5*38fd1498Szrj // This file is part of the GNU ISO C++ Library.  This library is free
6*38fd1498Szrj // software; you can redistribute it and/or modify it under the
7*38fd1498Szrj // terms of the GNU General Public License as published by the
8*38fd1498Szrj // Free Software Foundation; either version 3, or (at your option)
9*38fd1498Szrj // any later version.
10*38fd1498Szrj 
11*38fd1498Szrj // This library is distributed in the hope that it will be useful,
12*38fd1498Szrj // but WITHOUT ANY WARRANTY; without even the implied warranty of
13*38fd1498Szrj // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14*38fd1498Szrj // GNU General Public License for more details.
15*38fd1498Szrj 
16*38fd1498Szrj // Under Section 7 of GPL version 3, you are granted additional
17*38fd1498Szrj // permissions described in the GCC Runtime Library Exception, version
18*38fd1498Szrj // 3.1, as published by the Free Software Foundation.
19*38fd1498Szrj 
20*38fd1498Szrj // You should have received a copy of the GNU General Public License and
21*38fd1498Szrj // a copy of the GCC Runtime Library Exception along with this program;
22*38fd1498Szrj // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
23*38fd1498Szrj // <http://www.gnu.org/licenses/>.
24*38fd1498Szrj 
25*38fd1498Szrj /** @file bits/basic_string.tcc
26*38fd1498Szrj  *  This is an internal header file, included by other library headers.
27*38fd1498Szrj  *  Do not attempt to use it directly. @headername{string}
28*38fd1498Szrj  */
29*38fd1498Szrj 
30*38fd1498Szrj //
31*38fd1498Szrj // ISO C++ 14882: 21  Strings library
32*38fd1498Szrj //
33*38fd1498Szrj 
34*38fd1498Szrj // Written by Jason Merrill based upon the specification by Takanori Adachi
35*38fd1498Szrj // in ANSI X3J16/94-0013R2.  Rewritten by Nathan Myers to ISO-14882.
36*38fd1498Szrj // Non-reference-counted implementation written by Paolo Carlini and
37*38fd1498Szrj // updated by Jonathan Wakely for ISO-14882-2011.
38*38fd1498Szrj 
39*38fd1498Szrj #ifndef _BASIC_STRING_TCC
40*38fd1498Szrj #define _BASIC_STRING_TCC 1
41*38fd1498Szrj 
42*38fd1498Szrj #pragma GCC system_header
43*38fd1498Szrj 
44*38fd1498Szrj #include <bits/cxxabi_forced.h>
45*38fd1498Szrj 
46*38fd1498Szrj namespace std _GLIBCXX_VISIBILITY(default)
47*38fd1498Szrj {
48*38fd1498Szrj _GLIBCXX_BEGIN_NAMESPACE_VERSION
49*38fd1498Szrj 
50*38fd1498Szrj #if _GLIBCXX_USE_CXX11_ABI
51*38fd1498Szrj 
52*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
53*38fd1498Szrj     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
54*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::npos;
55*38fd1498Szrj 
56*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
57*38fd1498Szrj     void
58*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
59*38fd1498Szrj     swap(basic_string& __s) _GLIBCXX_NOEXCEPT
60*38fd1498Szrj     {
61*38fd1498Szrj       if (this == &__s)
62*38fd1498Szrj 	return;
63*38fd1498Szrj 
64*38fd1498Szrj       _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
65*38fd1498Szrj 
66*38fd1498Szrj       if (_M_is_local())
67*38fd1498Szrj 	if (__s._M_is_local())
68*38fd1498Szrj 	  {
69*38fd1498Szrj 	    if (length() && __s.length())
70*38fd1498Szrj 	      {
71*38fd1498Szrj 		_CharT __tmp_data[_S_local_capacity + 1];
72*38fd1498Szrj 		traits_type::copy(__tmp_data, __s._M_local_buf,
73*38fd1498Szrj 				  _S_local_capacity + 1);
74*38fd1498Szrj 		traits_type::copy(__s._M_local_buf, _M_local_buf,
75*38fd1498Szrj 				  _S_local_capacity + 1);
76*38fd1498Szrj 		traits_type::copy(_M_local_buf, __tmp_data,
77*38fd1498Szrj 				  _S_local_capacity + 1);
78*38fd1498Szrj 	      }
79*38fd1498Szrj 	    else if (__s.length())
80*38fd1498Szrj 	      {
81*38fd1498Szrj 		traits_type::copy(_M_local_buf, __s._M_local_buf,
82*38fd1498Szrj 				  _S_local_capacity + 1);
83*38fd1498Szrj 		_M_length(__s.length());
84*38fd1498Szrj 		__s._M_set_length(0);
85*38fd1498Szrj 		return;
86*38fd1498Szrj 	      }
87*38fd1498Szrj 	    else if (length())
88*38fd1498Szrj 	      {
89*38fd1498Szrj 		traits_type::copy(__s._M_local_buf, _M_local_buf,
90*38fd1498Szrj 				  _S_local_capacity + 1);
91*38fd1498Szrj 		__s._M_length(length());
92*38fd1498Szrj 		_M_set_length(0);
93*38fd1498Szrj 		return;
94*38fd1498Szrj 	      }
95*38fd1498Szrj 	  }
96*38fd1498Szrj 	else
97*38fd1498Szrj 	  {
98*38fd1498Szrj 	    const size_type __tmp_capacity = __s._M_allocated_capacity;
99*38fd1498Szrj 	    traits_type::copy(__s._M_local_buf, _M_local_buf,
100*38fd1498Szrj 			      _S_local_capacity + 1);
101*38fd1498Szrj 	    _M_data(__s._M_data());
102*38fd1498Szrj 	    __s._M_data(__s._M_local_buf);
103*38fd1498Szrj 	    _M_capacity(__tmp_capacity);
104*38fd1498Szrj 	  }
105*38fd1498Szrj       else
106*38fd1498Szrj 	{
107*38fd1498Szrj 	  const size_type __tmp_capacity = _M_allocated_capacity;
108*38fd1498Szrj 	  if (__s._M_is_local())
109*38fd1498Szrj 	    {
110*38fd1498Szrj 	      traits_type::copy(_M_local_buf, __s._M_local_buf,
111*38fd1498Szrj 				_S_local_capacity + 1);
112*38fd1498Szrj 	      __s._M_data(_M_data());
113*38fd1498Szrj 	      _M_data(_M_local_buf);
114*38fd1498Szrj 	    }
115*38fd1498Szrj 	  else
116*38fd1498Szrj 	    {
117*38fd1498Szrj 	      pointer __tmp_ptr = _M_data();
118*38fd1498Szrj 	      _M_data(__s._M_data());
119*38fd1498Szrj 	      __s._M_data(__tmp_ptr);
120*38fd1498Szrj 	      _M_capacity(__s._M_allocated_capacity);
121*38fd1498Szrj 	    }
122*38fd1498Szrj 	  __s._M_capacity(__tmp_capacity);
123*38fd1498Szrj 	}
124*38fd1498Szrj 
125*38fd1498Szrj       const size_type __tmp_length = length();
126*38fd1498Szrj       _M_length(__s.length());
127*38fd1498Szrj       __s._M_length(__tmp_length);
128*38fd1498Szrj     }
129*38fd1498Szrj 
130*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
131*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::pointer
132*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
133*38fd1498Szrj     _M_create(size_type& __capacity, size_type __old_capacity)
134*38fd1498Szrj     {
135*38fd1498Szrj       // _GLIBCXX_RESOLVE_LIB_DEFECTS
136*38fd1498Szrj       // 83.  String::npos vs. string::max_size()
137*38fd1498Szrj       if (__capacity > max_size())
138*38fd1498Szrj 	std::__throw_length_error(__N("basic_string::_M_create"));
139*38fd1498Szrj 
140*38fd1498Szrj       // The below implements an exponential growth policy, necessary to
141*38fd1498Szrj       // meet amortized linear time requirements of the library: see
142*38fd1498Szrj       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
143*38fd1498Szrj       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
144*38fd1498Szrj 	{
145*38fd1498Szrj 	  __capacity = 2 * __old_capacity;
146*38fd1498Szrj 	  // Never allocate a string bigger than max_size.
147*38fd1498Szrj 	  if (__capacity > max_size())
148*38fd1498Szrj 	    __capacity = max_size();
149*38fd1498Szrj 	}
150*38fd1498Szrj 
151*38fd1498Szrj       // NB: Need an array of char_type[__capacity], plus a terminating
152*38fd1498Szrj       // null char_type() element.
153*38fd1498Szrj       return _Alloc_traits::allocate(_M_get_allocator(), __capacity + 1);
154*38fd1498Szrj     }
155*38fd1498Szrj 
156*38fd1498Szrj   // NB: This is the special case for Input Iterators, used in
157*38fd1498Szrj   // istreambuf_iterators, etc.
158*38fd1498Szrj   // Input Iterators have a cost structure very different from
159*38fd1498Szrj   // pointers, calling for a different coding style.
160*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
161*38fd1498Szrj     template<typename _InIterator>
162*38fd1498Szrj       void
163*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
164*38fd1498Szrj       _M_construct(_InIterator __beg, _InIterator __end,
165*38fd1498Szrj 		   std::input_iterator_tag)
166*38fd1498Szrj       {
167*38fd1498Szrj 	size_type __len = 0;
168*38fd1498Szrj 	size_type __capacity = size_type(_S_local_capacity);
169*38fd1498Szrj 
170*38fd1498Szrj 	while (__beg != __end && __len < __capacity)
171*38fd1498Szrj 	  {
172*38fd1498Szrj 	    _M_data()[__len++] = *__beg;
173*38fd1498Szrj 	    ++__beg;
174*38fd1498Szrj 	  }
175*38fd1498Szrj 
176*38fd1498Szrj 	__try
177*38fd1498Szrj 	  {
178*38fd1498Szrj 	    while (__beg != __end)
179*38fd1498Szrj 	      {
180*38fd1498Szrj 		if (__len == __capacity)
181*38fd1498Szrj 		  {
182*38fd1498Szrj 		    // Allocate more space.
183*38fd1498Szrj 		    __capacity = __len + 1;
184*38fd1498Szrj 		    pointer __another = _M_create(__capacity, __len);
185*38fd1498Szrj 		    this->_S_copy(__another, _M_data(), __len);
186*38fd1498Szrj 		    _M_dispose();
187*38fd1498Szrj 		    _M_data(__another);
188*38fd1498Szrj 		    _M_capacity(__capacity);
189*38fd1498Szrj 		  }
190*38fd1498Szrj 		_M_data()[__len++] = *__beg;
191*38fd1498Szrj 		++__beg;
192*38fd1498Szrj 	      }
193*38fd1498Szrj 	  }
194*38fd1498Szrj 	__catch(...)
195*38fd1498Szrj 	  {
196*38fd1498Szrj 	    _M_dispose();
197*38fd1498Szrj 	    __throw_exception_again;
198*38fd1498Szrj 	  }
199*38fd1498Szrj 
200*38fd1498Szrj 	_M_set_length(__len);
201*38fd1498Szrj       }
202*38fd1498Szrj 
203*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
204*38fd1498Szrj     template<typename _InIterator>
205*38fd1498Szrj       void
206*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
207*38fd1498Szrj       _M_construct(_InIterator __beg, _InIterator __end,
208*38fd1498Szrj 		   std::forward_iterator_tag)
209*38fd1498Szrj       {
210*38fd1498Szrj 	// NB: Not required, but considered best practice.
211*38fd1498Szrj 	if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
212*38fd1498Szrj 	  std::__throw_logic_error(__N("basic_string::"
213*38fd1498Szrj 				       "_M_construct null not valid"));
214*38fd1498Szrj 
215*38fd1498Szrj 	size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
216*38fd1498Szrj 
217*38fd1498Szrj 	if (__dnew > size_type(_S_local_capacity))
218*38fd1498Szrj 	  {
219*38fd1498Szrj 	    _M_data(_M_create(__dnew, size_type(0)));
220*38fd1498Szrj 	    _M_capacity(__dnew);
221*38fd1498Szrj 	  }
222*38fd1498Szrj 
223*38fd1498Szrj 	// Check for out_of_range and length_error exceptions.
224*38fd1498Szrj 	__try
225*38fd1498Szrj 	  { this->_S_copy_chars(_M_data(), __beg, __end); }
226*38fd1498Szrj 	__catch(...)
227*38fd1498Szrj 	  {
228*38fd1498Szrj 	    _M_dispose();
229*38fd1498Szrj 	    __throw_exception_again;
230*38fd1498Szrj 	  }
231*38fd1498Szrj 
232*38fd1498Szrj 	_M_set_length(__dnew);
233*38fd1498Szrj       }
234*38fd1498Szrj 
235*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
236*38fd1498Szrj     void
237*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
238*38fd1498Szrj     _M_construct(size_type __n, _CharT __c)
239*38fd1498Szrj     {
240*38fd1498Szrj       if (__n > size_type(_S_local_capacity))
241*38fd1498Szrj 	{
242*38fd1498Szrj 	  _M_data(_M_create(__n, size_type(0)));
243*38fd1498Szrj 	  _M_capacity(__n);
244*38fd1498Szrj 	}
245*38fd1498Szrj 
246*38fd1498Szrj       if (__n)
247*38fd1498Szrj 	this->_S_assign(_M_data(), __n, __c);
248*38fd1498Szrj 
249*38fd1498Szrj       _M_set_length(__n);
250*38fd1498Szrj     }
251*38fd1498Szrj 
252*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
253*38fd1498Szrj     void
254*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
255*38fd1498Szrj     _M_assign(const basic_string& __str)
256*38fd1498Szrj     {
257*38fd1498Szrj       if (this != &__str)
258*38fd1498Szrj 	{
259*38fd1498Szrj 	  const size_type __rsize = __str.length();
260*38fd1498Szrj 	  const size_type __capacity = capacity();
261*38fd1498Szrj 
262*38fd1498Szrj 	  if (__rsize > __capacity)
263*38fd1498Szrj 	    {
264*38fd1498Szrj 	      size_type __new_capacity = __rsize;
265*38fd1498Szrj 	      pointer __tmp = _M_create(__new_capacity, __capacity);
266*38fd1498Szrj 	      _M_dispose();
267*38fd1498Szrj 	      _M_data(__tmp);
268*38fd1498Szrj 	      _M_capacity(__new_capacity);
269*38fd1498Szrj 	    }
270*38fd1498Szrj 
271*38fd1498Szrj 	  if (__rsize)
272*38fd1498Szrj 	    this->_S_copy(_M_data(), __str._M_data(), __rsize);
273*38fd1498Szrj 
274*38fd1498Szrj 	  _M_set_length(__rsize);
275*38fd1498Szrj 	}
276*38fd1498Szrj     }
277*38fd1498Szrj 
278*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
279*38fd1498Szrj     void
280*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
281*38fd1498Szrj     reserve(size_type __res)
282*38fd1498Szrj     {
283*38fd1498Szrj       // Make sure we don't shrink below the current size.
284*38fd1498Szrj       if (__res < length())
285*38fd1498Szrj 	__res = length();
286*38fd1498Szrj 
287*38fd1498Szrj       const size_type __capacity = capacity();
288*38fd1498Szrj       if (__res != __capacity)
289*38fd1498Szrj 	{
290*38fd1498Szrj 	  if (__res > __capacity
291*38fd1498Szrj 	      || __res > size_type(_S_local_capacity))
292*38fd1498Szrj 	    {
293*38fd1498Szrj 	      pointer __tmp = _M_create(__res, __capacity);
294*38fd1498Szrj 	      this->_S_copy(__tmp, _M_data(), length() + 1);
295*38fd1498Szrj 	      _M_dispose();
296*38fd1498Szrj 	      _M_data(__tmp);
297*38fd1498Szrj 	      _M_capacity(__res);
298*38fd1498Szrj 	    }
299*38fd1498Szrj 	  else if (!_M_is_local())
300*38fd1498Szrj 	    {
301*38fd1498Szrj 	      this->_S_copy(_M_local_data(), _M_data(), length() + 1);
302*38fd1498Szrj 	      _M_destroy(__capacity);
303*38fd1498Szrj 	      _M_data(_M_local_data());
304*38fd1498Szrj 	    }
305*38fd1498Szrj 	}
306*38fd1498Szrj     }
307*38fd1498Szrj 
308*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
309*38fd1498Szrj     void
310*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
311*38fd1498Szrj     _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
312*38fd1498Szrj 	      size_type __len2)
313*38fd1498Szrj     {
314*38fd1498Szrj       const size_type __how_much = length() - __pos - __len1;
315*38fd1498Szrj 
316*38fd1498Szrj       size_type __new_capacity = length() + __len2 - __len1;
317*38fd1498Szrj       pointer __r = _M_create(__new_capacity, capacity());
318*38fd1498Szrj 
319*38fd1498Szrj       if (__pos)
320*38fd1498Szrj 	this->_S_copy(__r, _M_data(), __pos);
321*38fd1498Szrj       if (__s && __len2)
322*38fd1498Szrj 	this->_S_copy(__r + __pos, __s, __len2);
323*38fd1498Szrj       if (__how_much)
324*38fd1498Szrj 	this->_S_copy(__r + __pos + __len2,
325*38fd1498Szrj 		      _M_data() + __pos + __len1, __how_much);
326*38fd1498Szrj 
327*38fd1498Szrj       _M_dispose();
328*38fd1498Szrj       _M_data(__r);
329*38fd1498Szrj       _M_capacity(__new_capacity);
330*38fd1498Szrj     }
331*38fd1498Szrj 
332*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
333*38fd1498Szrj     void
334*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
335*38fd1498Szrj     _M_erase(size_type __pos, size_type __n)
336*38fd1498Szrj     {
337*38fd1498Szrj       const size_type __how_much = length() - __pos - __n;
338*38fd1498Szrj 
339*38fd1498Szrj       if (__how_much && __n)
340*38fd1498Szrj 	this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
341*38fd1498Szrj 
342*38fd1498Szrj       _M_set_length(length() - __n);
343*38fd1498Szrj     }
344*38fd1498Szrj 
345*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
346*38fd1498Szrj     void
347*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
348*38fd1498Szrj     resize(size_type __n, _CharT __c)
349*38fd1498Szrj     {
350*38fd1498Szrj       const size_type __size = this->size();
351*38fd1498Szrj       if (__size < __n)
352*38fd1498Szrj 	this->append(__n - __size, __c);
353*38fd1498Szrj       else if (__n < __size)
354*38fd1498Szrj 	this->_M_set_length(__n);
355*38fd1498Szrj     }
356*38fd1498Szrj 
357*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
358*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
359*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
360*38fd1498Szrj     _M_append(const _CharT* __s, size_type __n)
361*38fd1498Szrj     {
362*38fd1498Szrj       const size_type __len = __n + this->size();
363*38fd1498Szrj 
364*38fd1498Szrj       if (__len <= this->capacity())
365*38fd1498Szrj 	{
366*38fd1498Szrj 	  if (__n)
367*38fd1498Szrj 	    this->_S_copy(this->_M_data() + this->size(), __s, __n);
368*38fd1498Szrj 	}
369*38fd1498Szrj       else
370*38fd1498Szrj 	this->_M_mutate(this->size(), size_type(0), __s, __n);
371*38fd1498Szrj 
372*38fd1498Szrj       this->_M_set_length(__len);
373*38fd1498Szrj       return *this;
374*38fd1498Szrj     }
375*38fd1498Szrj 
376*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
377*38fd1498Szrj     template<typename _InputIterator>
378*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>&
379*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
380*38fd1498Szrj       _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
381*38fd1498Szrj 			  _InputIterator __k1, _InputIterator __k2,
382*38fd1498Szrj 			  std::__false_type)
383*38fd1498Szrj       {
384*38fd1498Szrj 	const basic_string __s(__k1, __k2);
385*38fd1498Szrj 	const size_type __n1 = __i2 - __i1;
386*38fd1498Szrj 	return _M_replace(__i1 - begin(), __n1, __s._M_data(),
387*38fd1498Szrj 			  __s.size());
388*38fd1498Szrj       }
389*38fd1498Szrj 
390*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
391*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
392*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
393*38fd1498Szrj     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
394*38fd1498Szrj 		   _CharT __c)
395*38fd1498Szrj     {
396*38fd1498Szrj       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
397*38fd1498Szrj 
398*38fd1498Szrj       const size_type __old_size = this->size();
399*38fd1498Szrj       const size_type __new_size = __old_size + __n2 - __n1;
400*38fd1498Szrj 
401*38fd1498Szrj       if (__new_size <= this->capacity())
402*38fd1498Szrj 	{
403*38fd1498Szrj 	  pointer __p = this->_M_data() + __pos1;
404*38fd1498Szrj 
405*38fd1498Szrj 	  const size_type __how_much = __old_size - __pos1 - __n1;
406*38fd1498Szrj 	  if (__how_much && __n1 != __n2)
407*38fd1498Szrj 	    this->_S_move(__p + __n2, __p + __n1, __how_much);
408*38fd1498Szrj 	}
409*38fd1498Szrj       else
410*38fd1498Szrj 	this->_M_mutate(__pos1, __n1, 0, __n2);
411*38fd1498Szrj 
412*38fd1498Szrj       if (__n2)
413*38fd1498Szrj 	this->_S_assign(this->_M_data() + __pos1, __n2, __c);
414*38fd1498Szrj 
415*38fd1498Szrj       this->_M_set_length(__new_size);
416*38fd1498Szrj       return *this;
417*38fd1498Szrj     }
418*38fd1498Szrj 
419*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
420*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
421*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
422*38fd1498Szrj     _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
423*38fd1498Szrj 	       const size_type __len2)
424*38fd1498Szrj     {
425*38fd1498Szrj       _M_check_length(__len1, __len2, "basic_string::_M_replace");
426*38fd1498Szrj 
427*38fd1498Szrj       const size_type __old_size = this->size();
428*38fd1498Szrj       const size_type __new_size = __old_size + __len2 - __len1;
429*38fd1498Szrj 
430*38fd1498Szrj       if (__new_size <= this->capacity())
431*38fd1498Szrj 	{
432*38fd1498Szrj 	  pointer __p = this->_M_data() + __pos;
433*38fd1498Szrj 
434*38fd1498Szrj 	  const size_type __how_much = __old_size - __pos - __len1;
435*38fd1498Szrj 	  if (_M_disjunct(__s))
436*38fd1498Szrj 	    {
437*38fd1498Szrj 	      if (__how_much && __len1 != __len2)
438*38fd1498Szrj 		this->_S_move(__p + __len2, __p + __len1, __how_much);
439*38fd1498Szrj 	      if (__len2)
440*38fd1498Szrj 		this->_S_copy(__p, __s, __len2);
441*38fd1498Szrj 	    }
442*38fd1498Szrj 	  else
443*38fd1498Szrj 	    {
444*38fd1498Szrj 	      // Work in-place.
445*38fd1498Szrj 	      if (__len2 && __len2 <= __len1)
446*38fd1498Szrj 		this->_S_move(__p, __s, __len2);
447*38fd1498Szrj 	      if (__how_much && __len1 != __len2)
448*38fd1498Szrj 		this->_S_move(__p + __len2, __p + __len1, __how_much);
449*38fd1498Szrj 	      if (__len2 > __len1)
450*38fd1498Szrj 		{
451*38fd1498Szrj 		  if (__s + __len2 <= __p + __len1)
452*38fd1498Szrj 		    this->_S_move(__p, __s, __len2);
453*38fd1498Szrj 		  else if (__s >= __p + __len1)
454*38fd1498Szrj 		    this->_S_copy(__p, __s + __len2 - __len1, __len2);
455*38fd1498Szrj 		  else
456*38fd1498Szrj 		    {
457*38fd1498Szrj 		      const size_type __nleft = (__p + __len1) - __s;
458*38fd1498Szrj 		      this->_S_move(__p, __s, __nleft);
459*38fd1498Szrj 		      this->_S_copy(__p + __nleft, __p + __len2,
460*38fd1498Szrj 				    __len2 - __nleft);
461*38fd1498Szrj 		    }
462*38fd1498Szrj 		}
463*38fd1498Szrj 	    }
464*38fd1498Szrj 	}
465*38fd1498Szrj       else
466*38fd1498Szrj 	this->_M_mutate(__pos, __len1, __s, __len2);
467*38fd1498Szrj 
468*38fd1498Szrj       this->_M_set_length(__new_size);
469*38fd1498Szrj       return *this;
470*38fd1498Szrj     }
471*38fd1498Szrj 
472*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
473*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
474*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
475*38fd1498Szrj     copy(_CharT* __s, size_type __n, size_type __pos) const
476*38fd1498Szrj     {
477*38fd1498Szrj       _M_check(__pos, "basic_string::copy");
478*38fd1498Szrj       __n = _M_limit(__pos, __n);
479*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
480*38fd1498Szrj       if (__n)
481*38fd1498Szrj 	_S_copy(__s, _M_data() + __pos, __n);
482*38fd1498Szrj       // 21.3.5.7 par 3: do not append null.  (good.)
483*38fd1498Szrj       return __n;
484*38fd1498Szrj     }
485*38fd1498Szrj 
486*38fd1498Szrj #else  // !_GLIBCXX_USE_CXX11_ABI
487*38fd1498Szrj 
488*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
489*38fd1498Szrj     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
490*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
491*38fd1498Szrj     _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
492*38fd1498Szrj 
493*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
494*38fd1498Szrj     const _CharT
495*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
496*38fd1498Szrj     _Rep::_S_terminal = _CharT();
497*38fd1498Szrj 
498*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
499*38fd1498Szrj     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
500*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::npos;
501*38fd1498Szrj 
502*38fd1498Szrj   // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
503*38fd1498Szrj   // at static init time (before static ctors are run).
504*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
505*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
506*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
507*38fd1498Szrj     (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
508*38fd1498Szrj       sizeof(size_type)];
509*38fd1498Szrj 
510*38fd1498Szrj   // NB: This is the special case for Input Iterators, used in
511*38fd1498Szrj   // istreambuf_iterators, etc.
512*38fd1498Szrj   // Input Iterators have a cost structure very different from
513*38fd1498Szrj   // pointers, calling for a different coding style.
514*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
515*38fd1498Szrj     template<typename _InIterator>
516*38fd1498Szrj       _CharT*
517*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
518*38fd1498Szrj       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
519*38fd1498Szrj 		   input_iterator_tag)
520*38fd1498Szrj       {
521*38fd1498Szrj #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
522*38fd1498Szrj 	if (__beg == __end && __a == _Alloc())
523*38fd1498Szrj 	  return _S_empty_rep()._M_refdata();
524*38fd1498Szrj #endif
525*38fd1498Szrj 	// Avoid reallocation for common case.
526*38fd1498Szrj 	_CharT __buf[128];
527*38fd1498Szrj 	size_type __len = 0;
528*38fd1498Szrj 	while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
529*38fd1498Szrj 	  {
530*38fd1498Szrj 	    __buf[__len++] = *__beg;
531*38fd1498Szrj 	    ++__beg;
532*38fd1498Szrj 	  }
533*38fd1498Szrj 	_Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
534*38fd1498Szrj 	_M_copy(__r->_M_refdata(), __buf, __len);
535*38fd1498Szrj 	__try
536*38fd1498Szrj 	  {
537*38fd1498Szrj 	    while (__beg != __end)
538*38fd1498Szrj 	      {
539*38fd1498Szrj 		if (__len == __r->_M_capacity)
540*38fd1498Szrj 		  {
541*38fd1498Szrj 		    // Allocate more space.
542*38fd1498Szrj 		    _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
543*38fd1498Szrj 		    _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
544*38fd1498Szrj 		    __r->_M_destroy(__a);
545*38fd1498Szrj 		    __r = __another;
546*38fd1498Szrj 		  }
547*38fd1498Szrj 		__r->_M_refdata()[__len++] = *__beg;
548*38fd1498Szrj 		++__beg;
549*38fd1498Szrj 	      }
550*38fd1498Szrj 	  }
551*38fd1498Szrj 	__catch(...)
552*38fd1498Szrj 	  {
553*38fd1498Szrj 	    __r->_M_destroy(__a);
554*38fd1498Szrj 	    __throw_exception_again;
555*38fd1498Szrj 	  }
556*38fd1498Szrj 	__r->_M_set_length_and_sharable(__len);
557*38fd1498Szrj 	return __r->_M_refdata();
558*38fd1498Szrj       }
559*38fd1498Szrj 
560*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
561*38fd1498Szrj     template <typename _InIterator>
562*38fd1498Szrj       _CharT*
563*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
564*38fd1498Szrj       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
565*38fd1498Szrj 		   forward_iterator_tag)
566*38fd1498Szrj       {
567*38fd1498Szrj #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
568*38fd1498Szrj 	if (__beg == __end && __a == _Alloc())
569*38fd1498Szrj 	  return _S_empty_rep()._M_refdata();
570*38fd1498Szrj #endif
571*38fd1498Szrj 	// NB: Not required, but considered best practice.
572*38fd1498Szrj 	if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
573*38fd1498Szrj 	  __throw_logic_error(__N("basic_string::_S_construct null not valid"));
574*38fd1498Szrj 
575*38fd1498Szrj 	const size_type __dnew = static_cast<size_type>(std::distance(__beg,
576*38fd1498Szrj 								      __end));
577*38fd1498Szrj 	// Check for out_of_range and length_error exceptions.
578*38fd1498Szrj 	_Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
579*38fd1498Szrj 	__try
580*38fd1498Szrj 	  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
581*38fd1498Szrj 	__catch(...)
582*38fd1498Szrj 	  {
583*38fd1498Szrj 	    __r->_M_destroy(__a);
584*38fd1498Szrj 	    __throw_exception_again;
585*38fd1498Szrj 	  }
586*38fd1498Szrj 	__r->_M_set_length_and_sharable(__dnew);
587*38fd1498Szrj 	return __r->_M_refdata();
588*38fd1498Szrj       }
589*38fd1498Szrj 
590*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
591*38fd1498Szrj     _CharT*
592*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
593*38fd1498Szrj     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
594*38fd1498Szrj     {
595*38fd1498Szrj #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
596*38fd1498Szrj       if (__n == 0 && __a == _Alloc())
597*38fd1498Szrj 	return _S_empty_rep()._M_refdata();
598*38fd1498Szrj #endif
599*38fd1498Szrj       // Check for out_of_range and length_error exceptions.
600*38fd1498Szrj       _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
601*38fd1498Szrj       if (__n)
602*38fd1498Szrj 	_M_assign(__r->_M_refdata(), __n, __c);
603*38fd1498Szrj 
604*38fd1498Szrj       __r->_M_set_length_and_sharable(__n);
605*38fd1498Szrj       return __r->_M_refdata();
606*38fd1498Szrj     }
607*38fd1498Szrj 
608*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
609*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
610*38fd1498Szrj     basic_string(const basic_string& __str)
611*38fd1498Szrj     : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
612*38fd1498Szrj 					  __str.get_allocator()),
613*38fd1498Szrj 		  __str.get_allocator())
614*38fd1498Szrj     { }
615*38fd1498Szrj 
616*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
617*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
618*38fd1498Szrj     basic_string(const _Alloc& __a)
619*38fd1498Szrj     : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
620*38fd1498Szrj     { }
621*38fd1498Szrj 
622*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
623*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
624*38fd1498Szrj     basic_string(const basic_string& __str, size_type __pos, const _Alloc& __a)
625*38fd1498Szrj     : _M_dataplus(_S_construct(__str._M_data()
626*38fd1498Szrj 			       + __str._M_check(__pos,
627*38fd1498Szrj 						"basic_string::basic_string"),
628*38fd1498Szrj 			       __str._M_data() + __str._M_limit(__pos, npos)
629*38fd1498Szrj 			       + __pos, __a), __a)
630*38fd1498Szrj     { }
631*38fd1498Szrj 
632*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
633*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
634*38fd1498Szrj     basic_string(const basic_string& __str, size_type __pos, size_type __n)
635*38fd1498Szrj     : _M_dataplus(_S_construct(__str._M_data()
636*38fd1498Szrj 			       + __str._M_check(__pos,
637*38fd1498Szrj 						"basic_string::basic_string"),
638*38fd1498Szrj 			       __str._M_data() + __str._M_limit(__pos, __n)
639*38fd1498Szrj 			       + __pos, _Alloc()), _Alloc())
640*38fd1498Szrj     { }
641*38fd1498Szrj 
642*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
643*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
644*38fd1498Szrj     basic_string(const basic_string& __str, size_type __pos,
645*38fd1498Szrj 		 size_type __n, const _Alloc& __a)
646*38fd1498Szrj     : _M_dataplus(_S_construct(__str._M_data()
647*38fd1498Szrj 			       + __str._M_check(__pos,
648*38fd1498Szrj 						"basic_string::basic_string"),
649*38fd1498Szrj 			       __str._M_data() + __str._M_limit(__pos, __n)
650*38fd1498Szrj 			       + __pos, __a), __a)
651*38fd1498Szrj     { }
652*38fd1498Szrj 
653*38fd1498Szrj   // TBD: DPG annotate
654*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
655*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
656*38fd1498Szrj     basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
657*38fd1498Szrj     : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
658*38fd1498Szrj     { }
659*38fd1498Szrj 
660*38fd1498Szrj   // TBD: DPG annotate
661*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
662*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
663*38fd1498Szrj     basic_string(const _CharT* __s, const _Alloc& __a)
664*38fd1498Szrj     : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
665*38fd1498Szrj 			       __s + npos, __a), __a)
666*38fd1498Szrj     { }
667*38fd1498Szrj 
668*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
669*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
670*38fd1498Szrj     basic_string(size_type __n, _CharT __c, const _Alloc& __a)
671*38fd1498Szrj     : _M_dataplus(_S_construct(__n, __c, __a), __a)
672*38fd1498Szrj     { }
673*38fd1498Szrj 
674*38fd1498Szrj   // TBD: DPG annotate
675*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
676*38fd1498Szrj     template<typename _InputIterator>
677*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
678*38fd1498Szrj     basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
679*38fd1498Szrj     : _M_dataplus(_S_construct(__beg, __end, __a), __a)
680*38fd1498Szrj     { }
681*38fd1498Szrj 
682*38fd1498Szrj #if __cplusplus >= 201103L
683*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
684*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
685*38fd1498Szrj     basic_string(initializer_list<_CharT> __l, const _Alloc& __a)
686*38fd1498Szrj     : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a)
687*38fd1498Szrj     { }
688*38fd1498Szrj #endif
689*38fd1498Szrj 
690*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
691*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
692*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
693*38fd1498Szrj     assign(const basic_string& __str)
694*38fd1498Szrj     {
695*38fd1498Szrj       if (_M_rep() != __str._M_rep())
696*38fd1498Szrj 	{
697*38fd1498Szrj 	  // XXX MT
698*38fd1498Szrj 	  const allocator_type __a = this->get_allocator();
699*38fd1498Szrj 	  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
700*38fd1498Szrj 	  _M_rep()->_M_dispose(__a);
701*38fd1498Szrj 	  _M_data(__tmp);
702*38fd1498Szrj 	}
703*38fd1498Szrj       return *this;
704*38fd1498Szrj     }
705*38fd1498Szrj 
706*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
707*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
708*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
709*38fd1498Szrj     assign(const _CharT* __s, size_type __n)
710*38fd1498Szrj     {
711*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
712*38fd1498Szrj       _M_check_length(this->size(), __n, "basic_string::assign");
713*38fd1498Szrj       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
714*38fd1498Szrj 	return _M_replace_safe(size_type(0), this->size(), __s, __n);
715*38fd1498Szrj       else
716*38fd1498Szrj 	{
717*38fd1498Szrj 	  // Work in-place.
718*38fd1498Szrj 	  const size_type __pos = __s - _M_data();
719*38fd1498Szrj 	  if (__pos >= __n)
720*38fd1498Szrj 	    _M_copy(_M_data(), __s, __n);
721*38fd1498Szrj 	  else if (__pos)
722*38fd1498Szrj 	    _M_move(_M_data(), __s, __n);
723*38fd1498Szrj 	  _M_rep()->_M_set_length_and_sharable(__n);
724*38fd1498Szrj 	  return *this;
725*38fd1498Szrj 	}
726*38fd1498Szrj      }
727*38fd1498Szrj 
728*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
729*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
730*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
731*38fd1498Szrj     append(size_type __n, _CharT __c)
732*38fd1498Szrj     {
733*38fd1498Szrj       if (__n)
734*38fd1498Szrj 	{
735*38fd1498Szrj 	  _M_check_length(size_type(0), __n, "basic_string::append");
736*38fd1498Szrj 	  const size_type __len = __n + this->size();
737*38fd1498Szrj 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
738*38fd1498Szrj 	    this->reserve(__len);
739*38fd1498Szrj 	  _M_assign(_M_data() + this->size(), __n, __c);
740*38fd1498Szrj 	  _M_rep()->_M_set_length_and_sharable(__len);
741*38fd1498Szrj 	}
742*38fd1498Szrj       return *this;
743*38fd1498Szrj     }
744*38fd1498Szrj 
745*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
746*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
747*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
748*38fd1498Szrj     append(const _CharT* __s, size_type __n)
749*38fd1498Szrj     {
750*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
751*38fd1498Szrj       if (__n)
752*38fd1498Szrj 	{
753*38fd1498Szrj 	  _M_check_length(size_type(0), __n, "basic_string::append");
754*38fd1498Szrj 	  const size_type __len = __n + this->size();
755*38fd1498Szrj 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
756*38fd1498Szrj 	    {
757*38fd1498Szrj 	      if (_M_disjunct(__s))
758*38fd1498Szrj 		this->reserve(__len);
759*38fd1498Szrj 	      else
760*38fd1498Szrj 		{
761*38fd1498Szrj 		  const size_type __off = __s - _M_data();
762*38fd1498Szrj 		  this->reserve(__len);
763*38fd1498Szrj 		  __s = _M_data() + __off;
764*38fd1498Szrj 		}
765*38fd1498Szrj 	    }
766*38fd1498Szrj 	  _M_copy(_M_data() + this->size(), __s, __n);
767*38fd1498Szrj 	  _M_rep()->_M_set_length_and_sharable(__len);
768*38fd1498Szrj 	}
769*38fd1498Szrj       return *this;
770*38fd1498Szrj     }
771*38fd1498Szrj 
772*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
773*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
774*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
775*38fd1498Szrj     append(const basic_string& __str)
776*38fd1498Szrj     {
777*38fd1498Szrj       const size_type __size = __str.size();
778*38fd1498Szrj       if (__size)
779*38fd1498Szrj 	{
780*38fd1498Szrj 	  const size_type __len = __size + this->size();
781*38fd1498Szrj 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
782*38fd1498Szrj 	    this->reserve(__len);
783*38fd1498Szrj 	  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
784*38fd1498Szrj 	  _M_rep()->_M_set_length_and_sharable(__len);
785*38fd1498Szrj 	}
786*38fd1498Szrj       return *this;
787*38fd1498Szrj     }
788*38fd1498Szrj 
789*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
790*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
791*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
792*38fd1498Szrj     append(const basic_string& __str, size_type __pos, size_type __n)
793*38fd1498Szrj     {
794*38fd1498Szrj       __str._M_check(__pos, "basic_string::append");
795*38fd1498Szrj       __n = __str._M_limit(__pos, __n);
796*38fd1498Szrj       if (__n)
797*38fd1498Szrj 	{
798*38fd1498Szrj 	  const size_type __len = __n + this->size();
799*38fd1498Szrj 	  if (__len > this->capacity() || _M_rep()->_M_is_shared())
800*38fd1498Szrj 	    this->reserve(__len);
801*38fd1498Szrj 	  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
802*38fd1498Szrj 	  _M_rep()->_M_set_length_and_sharable(__len);
803*38fd1498Szrj 	}
804*38fd1498Szrj       return *this;
805*38fd1498Szrj     }
806*38fd1498Szrj 
807*38fd1498Szrj    template<typename _CharT, typename _Traits, typename _Alloc>
808*38fd1498Szrj      basic_string<_CharT, _Traits, _Alloc>&
809*38fd1498Szrj      basic_string<_CharT, _Traits, _Alloc>::
810*38fd1498Szrj      insert(size_type __pos, const _CharT* __s, size_type __n)
811*38fd1498Szrj      {
812*38fd1498Szrj        __glibcxx_requires_string_len(__s, __n);
813*38fd1498Szrj        _M_check(__pos, "basic_string::insert");
814*38fd1498Szrj        _M_check_length(size_type(0), __n, "basic_string::insert");
815*38fd1498Szrj        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
816*38fd1498Szrj          return _M_replace_safe(__pos, size_type(0), __s, __n);
817*38fd1498Szrj        else
818*38fd1498Szrj          {
819*38fd1498Szrj            // Work in-place.
820*38fd1498Szrj            const size_type __off = __s - _M_data();
821*38fd1498Szrj            _M_mutate(__pos, 0, __n);
822*38fd1498Szrj            __s = _M_data() + __off;
823*38fd1498Szrj            _CharT* __p = _M_data() + __pos;
824*38fd1498Szrj            if (__s  + __n <= __p)
825*38fd1498Szrj              _M_copy(__p, __s, __n);
826*38fd1498Szrj            else if (__s >= __p)
827*38fd1498Szrj              _M_copy(__p, __s + __n, __n);
828*38fd1498Szrj            else
829*38fd1498Szrj              {
830*38fd1498Szrj 	       const size_type __nleft = __p - __s;
831*38fd1498Szrj                _M_copy(__p, __s, __nleft);
832*38fd1498Szrj                _M_copy(__p + __nleft, __p + __n, __n - __nleft);
833*38fd1498Szrj              }
834*38fd1498Szrj            return *this;
835*38fd1498Szrj          }
836*38fd1498Szrj      }
837*38fd1498Szrj 
838*38fd1498Szrj    template<typename _CharT, typename _Traits, typename _Alloc>
839*38fd1498Szrj      typename basic_string<_CharT, _Traits, _Alloc>::iterator
840*38fd1498Szrj      basic_string<_CharT, _Traits, _Alloc>::
841*38fd1498Szrj      erase(iterator __first, iterator __last)
842*38fd1498Szrj      {
843*38fd1498Szrj        _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
844*38fd1498Szrj 				&& __last <= _M_iend());
845*38fd1498Szrj 
846*38fd1498Szrj        // NB: This isn't just an optimization (bail out early when
847*38fd1498Szrj        // there is nothing to do, really), it's also a correctness
848*38fd1498Szrj        // issue vs MT, see libstdc++/40518.
849*38fd1498Szrj        const size_type __size = __last - __first;
850*38fd1498Szrj        if (__size)
851*38fd1498Szrj 	 {
852*38fd1498Szrj 	   const size_type __pos = __first - _M_ibegin();
853*38fd1498Szrj 	   _M_mutate(__pos, __size, size_type(0));
854*38fd1498Szrj 	   _M_rep()->_M_set_leaked();
855*38fd1498Szrj 	   return iterator(_M_data() + __pos);
856*38fd1498Szrj 	 }
857*38fd1498Szrj        else
858*38fd1498Szrj 	 return __first;
859*38fd1498Szrj      }
860*38fd1498Szrj 
861*38fd1498Szrj    template<typename _CharT, typename _Traits, typename _Alloc>
862*38fd1498Szrj      basic_string<_CharT, _Traits, _Alloc>&
863*38fd1498Szrj      basic_string<_CharT, _Traits, _Alloc>::
864*38fd1498Szrj      replace(size_type __pos, size_type __n1, const _CharT* __s,
865*38fd1498Szrj 	     size_type __n2)
866*38fd1498Szrj      {
867*38fd1498Szrj        __glibcxx_requires_string_len(__s, __n2);
868*38fd1498Szrj        _M_check(__pos, "basic_string::replace");
869*38fd1498Szrj        __n1 = _M_limit(__pos, __n1);
870*38fd1498Szrj        _M_check_length(__n1, __n2, "basic_string::replace");
871*38fd1498Szrj        bool __left;
872*38fd1498Szrj        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
873*38fd1498Szrj          return _M_replace_safe(__pos, __n1, __s, __n2);
874*38fd1498Szrj        else if ((__left = __s + __n2 <= _M_data() + __pos)
875*38fd1498Szrj 		|| _M_data() + __pos + __n1 <= __s)
876*38fd1498Szrj 	 {
877*38fd1498Szrj 	   // Work in-place: non-overlapping case.
878*38fd1498Szrj 	   size_type __off = __s - _M_data();
879*38fd1498Szrj 	   __left ? __off : (__off += __n2 - __n1);
880*38fd1498Szrj 	   _M_mutate(__pos, __n1, __n2);
881*38fd1498Szrj 	   _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
882*38fd1498Szrj 	   return *this;
883*38fd1498Szrj 	 }
884*38fd1498Szrj        else
885*38fd1498Szrj 	 {
886*38fd1498Szrj 	   // Todo: overlapping case.
887*38fd1498Szrj 	   const basic_string __tmp(__s, __n2);
888*38fd1498Szrj 	   return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
889*38fd1498Szrj 	 }
890*38fd1498Szrj      }
891*38fd1498Szrj 
892*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
893*38fd1498Szrj     void
894*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::_Rep::
895*38fd1498Szrj     _M_destroy(const _Alloc& __a) throw ()
896*38fd1498Szrj     {
897*38fd1498Szrj       const size_type __size = sizeof(_Rep_base) +
898*38fd1498Szrj 	                       (this->_M_capacity + 1) * sizeof(_CharT);
899*38fd1498Szrj       _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
900*38fd1498Szrj     }
901*38fd1498Szrj 
902*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
903*38fd1498Szrj     void
904*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
905*38fd1498Szrj     _M_leak_hard()
906*38fd1498Szrj     {
907*38fd1498Szrj #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
908*38fd1498Szrj       if (_M_rep() == &_S_empty_rep())
909*38fd1498Szrj 	return;
910*38fd1498Szrj #endif
911*38fd1498Szrj       if (_M_rep()->_M_is_shared())
912*38fd1498Szrj 	_M_mutate(0, 0, 0);
913*38fd1498Szrj       _M_rep()->_M_set_leaked();
914*38fd1498Szrj     }
915*38fd1498Szrj 
916*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
917*38fd1498Szrj     void
918*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
919*38fd1498Szrj     _M_mutate(size_type __pos, size_type __len1, size_type __len2)
920*38fd1498Szrj     {
921*38fd1498Szrj       const size_type __old_size = this->size();
922*38fd1498Szrj       const size_type __new_size = __old_size + __len2 - __len1;
923*38fd1498Szrj       const size_type __how_much = __old_size - __pos - __len1;
924*38fd1498Szrj 
925*38fd1498Szrj       if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
926*38fd1498Szrj 	{
927*38fd1498Szrj 	  // Must reallocate.
928*38fd1498Szrj 	  const allocator_type __a = get_allocator();
929*38fd1498Szrj 	  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
930*38fd1498Szrj 
931*38fd1498Szrj 	  if (__pos)
932*38fd1498Szrj 	    _M_copy(__r->_M_refdata(), _M_data(), __pos);
933*38fd1498Szrj 	  if (__how_much)
934*38fd1498Szrj 	    _M_copy(__r->_M_refdata() + __pos + __len2,
935*38fd1498Szrj 		    _M_data() + __pos + __len1, __how_much);
936*38fd1498Szrj 
937*38fd1498Szrj 	  _M_rep()->_M_dispose(__a);
938*38fd1498Szrj 	  _M_data(__r->_M_refdata());
939*38fd1498Szrj 	}
940*38fd1498Szrj       else if (__how_much && __len1 != __len2)
941*38fd1498Szrj 	{
942*38fd1498Szrj 	  // Work in-place.
943*38fd1498Szrj 	  _M_move(_M_data() + __pos + __len2,
944*38fd1498Szrj 		  _M_data() + __pos + __len1, __how_much);
945*38fd1498Szrj 	}
946*38fd1498Szrj       _M_rep()->_M_set_length_and_sharable(__new_size);
947*38fd1498Szrj     }
948*38fd1498Szrj 
949*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
950*38fd1498Szrj     void
951*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
952*38fd1498Szrj     reserve(size_type __res)
953*38fd1498Szrj     {
954*38fd1498Szrj       if (__res != this->capacity() || _M_rep()->_M_is_shared())
955*38fd1498Szrj         {
956*38fd1498Szrj 	  // Make sure we don't shrink below the current size
957*38fd1498Szrj 	  if (__res < this->size())
958*38fd1498Szrj 	    __res = this->size();
959*38fd1498Szrj 	  const allocator_type __a = get_allocator();
960*38fd1498Szrj 	  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
961*38fd1498Szrj 	  _M_rep()->_M_dispose(__a);
962*38fd1498Szrj 	  _M_data(__tmp);
963*38fd1498Szrj         }
964*38fd1498Szrj     }
965*38fd1498Szrj 
966*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
967*38fd1498Szrj     void
968*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
969*38fd1498Szrj     swap(basic_string& __s)
970*38fd1498Szrj     {
971*38fd1498Szrj       if (_M_rep()->_M_is_leaked())
972*38fd1498Szrj 	_M_rep()->_M_set_sharable();
973*38fd1498Szrj       if (__s._M_rep()->_M_is_leaked())
974*38fd1498Szrj 	__s._M_rep()->_M_set_sharable();
975*38fd1498Szrj       if (this->get_allocator() == __s.get_allocator())
976*38fd1498Szrj 	{
977*38fd1498Szrj 	  _CharT* __tmp = _M_data();
978*38fd1498Szrj 	  _M_data(__s._M_data());
979*38fd1498Szrj 	  __s._M_data(__tmp);
980*38fd1498Szrj 	}
981*38fd1498Szrj       // The code below can usually be optimized away.
982*38fd1498Szrj       else
983*38fd1498Szrj 	{
984*38fd1498Szrj 	  const basic_string __tmp1(_M_ibegin(), _M_iend(),
985*38fd1498Szrj 				    __s.get_allocator());
986*38fd1498Szrj 	  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
987*38fd1498Szrj 				    this->get_allocator());
988*38fd1498Szrj 	  *this = __tmp2;
989*38fd1498Szrj 	  __s = __tmp1;
990*38fd1498Szrj 	}
991*38fd1498Szrj     }
992*38fd1498Szrj 
993*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
994*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
995*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::_Rep::
996*38fd1498Szrj     _S_create(size_type __capacity, size_type __old_capacity,
997*38fd1498Szrj 	      const _Alloc& __alloc)
998*38fd1498Szrj     {
999*38fd1498Szrj       // _GLIBCXX_RESOLVE_LIB_DEFECTS
1000*38fd1498Szrj       // 83.  String::npos vs. string::max_size()
1001*38fd1498Szrj       if (__capacity > _S_max_size)
1002*38fd1498Szrj 	__throw_length_error(__N("basic_string::_S_create"));
1003*38fd1498Szrj 
1004*38fd1498Szrj       // The standard places no restriction on allocating more memory
1005*38fd1498Szrj       // than is strictly needed within this layer at the moment or as
1006*38fd1498Szrj       // requested by an explicit application call to reserve().
1007*38fd1498Szrj 
1008*38fd1498Szrj       // Many malloc implementations perform quite poorly when an
1009*38fd1498Szrj       // application attempts to allocate memory in a stepwise fashion
1010*38fd1498Szrj       // growing each allocation size by only 1 char.  Additionally,
1011*38fd1498Szrj       // it makes little sense to allocate less linear memory than the
1012*38fd1498Szrj       // natural blocking size of the malloc implementation.
1013*38fd1498Szrj       // Unfortunately, we would need a somewhat low-level calculation
1014*38fd1498Szrj       // with tuned parameters to get this perfect for any particular
1015*38fd1498Szrj       // malloc implementation.  Fortunately, generalizations about
1016*38fd1498Szrj       // common features seen among implementations seems to suffice.
1017*38fd1498Szrj 
1018*38fd1498Szrj       // __pagesize need not match the actual VM page size for good
1019*38fd1498Szrj       // results in practice, thus we pick a common value on the low
1020*38fd1498Szrj       // side.  __malloc_header_size is an estimate of the amount of
1021*38fd1498Szrj       // overhead per memory allocation (in practice seen N * sizeof
1022*38fd1498Szrj       // (void*) where N is 0, 2 or 4).  According to folklore,
1023*38fd1498Szrj       // picking this value on the high side is better than
1024*38fd1498Szrj       // low-balling it (especially when this algorithm is used with
1025*38fd1498Szrj       // malloc implementations that allocate memory blocks rounded up
1026*38fd1498Szrj       // to a size which is a power of 2).
1027*38fd1498Szrj       const size_type __pagesize = 4096;
1028*38fd1498Szrj       const size_type __malloc_header_size = 4 * sizeof(void*);
1029*38fd1498Szrj 
1030*38fd1498Szrj       // The below implements an exponential growth policy, necessary to
1031*38fd1498Szrj       // meet amortized linear time requirements of the library: see
1032*38fd1498Szrj       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
1033*38fd1498Szrj       // It's active for allocations requiring an amount of memory above
1034*38fd1498Szrj       // system pagesize. This is consistent with the requirements of the
1035*38fd1498Szrj       // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
1036*38fd1498Szrj       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
1037*38fd1498Szrj 	__capacity = 2 * __old_capacity;
1038*38fd1498Szrj 
1039*38fd1498Szrj       // NB: Need an array of char_type[__capacity], plus a terminating
1040*38fd1498Szrj       // null char_type() element, plus enough for the _Rep data structure.
1041*38fd1498Szrj       // Whew. Seemingly so needy, yet so elemental.
1042*38fd1498Szrj       size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1043*38fd1498Szrj 
1044*38fd1498Szrj       const size_type __adj_size = __size + __malloc_header_size;
1045*38fd1498Szrj       if (__adj_size > __pagesize && __capacity > __old_capacity)
1046*38fd1498Szrj 	{
1047*38fd1498Szrj 	  const size_type __extra = __pagesize - __adj_size % __pagesize;
1048*38fd1498Szrj 	  __capacity += __extra / sizeof(_CharT);
1049*38fd1498Szrj 	  // Never allocate a string bigger than _S_max_size.
1050*38fd1498Szrj 	  if (__capacity > _S_max_size)
1051*38fd1498Szrj 	    __capacity = _S_max_size;
1052*38fd1498Szrj 	  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1053*38fd1498Szrj 	}
1054*38fd1498Szrj 
1055*38fd1498Szrj       // NB: Might throw, but no worries about a leak, mate: _Rep()
1056*38fd1498Szrj       // does not throw.
1057*38fd1498Szrj       void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
1058*38fd1498Szrj       _Rep *__p = new (__place) _Rep;
1059*38fd1498Szrj       __p->_M_capacity = __capacity;
1060*38fd1498Szrj       // ABI compatibility - 3.4.x set in _S_create both
1061*38fd1498Szrj       // _M_refcount and _M_length.  All callers of _S_create
1062*38fd1498Szrj       // in basic_string.tcc then set just _M_length.
1063*38fd1498Szrj       // In 4.0.x and later both _M_refcount and _M_length
1064*38fd1498Szrj       // are initialized in the callers, unfortunately we can
1065*38fd1498Szrj       // have 3.4.x compiled code with _S_create callers inlined
1066*38fd1498Szrj       // calling 4.0.x+ _S_create.
1067*38fd1498Szrj       __p->_M_set_sharable();
1068*38fd1498Szrj       return __p;
1069*38fd1498Szrj     }
1070*38fd1498Szrj 
1071*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1072*38fd1498Szrj     _CharT*
1073*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::_Rep::
1074*38fd1498Szrj     _M_clone(const _Alloc& __alloc, size_type __res)
1075*38fd1498Szrj     {
1076*38fd1498Szrj       // Requested capacity of the clone.
1077*38fd1498Szrj       const size_type __requested_cap = this->_M_length + __res;
1078*38fd1498Szrj       _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
1079*38fd1498Szrj 				  __alloc);
1080*38fd1498Szrj       if (this->_M_length)
1081*38fd1498Szrj 	_M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
1082*38fd1498Szrj 
1083*38fd1498Szrj       __r->_M_set_length_and_sharable(this->_M_length);
1084*38fd1498Szrj       return __r->_M_refdata();
1085*38fd1498Szrj     }
1086*38fd1498Szrj 
1087*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1088*38fd1498Szrj     void
1089*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1090*38fd1498Szrj     resize(size_type __n, _CharT __c)
1091*38fd1498Szrj     {
1092*38fd1498Szrj       const size_type __size = this->size();
1093*38fd1498Szrj       _M_check_length(__size, __n, "basic_string::resize");
1094*38fd1498Szrj       if (__size < __n)
1095*38fd1498Szrj 	this->append(__n - __size, __c);
1096*38fd1498Szrj       else if (__n < __size)
1097*38fd1498Szrj 	this->erase(__n);
1098*38fd1498Szrj       // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
1099*38fd1498Szrj     }
1100*38fd1498Szrj 
1101*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1102*38fd1498Szrj     template<typename _InputIterator>
1103*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>&
1104*38fd1498Szrj       basic_string<_CharT, _Traits, _Alloc>::
1105*38fd1498Szrj       _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
1106*38fd1498Szrj 			  _InputIterator __k2, __false_type)
1107*38fd1498Szrj       {
1108*38fd1498Szrj 	const basic_string __s(__k1, __k2);
1109*38fd1498Szrj 	const size_type __n1 = __i2 - __i1;
1110*38fd1498Szrj 	_M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
1111*38fd1498Szrj 	return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
1112*38fd1498Szrj 			       __s.size());
1113*38fd1498Szrj       }
1114*38fd1498Szrj 
1115*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1116*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
1117*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1118*38fd1498Szrj     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
1119*38fd1498Szrj 		   _CharT __c)
1120*38fd1498Szrj     {
1121*38fd1498Szrj       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
1122*38fd1498Szrj       _M_mutate(__pos1, __n1, __n2);
1123*38fd1498Szrj       if (__n2)
1124*38fd1498Szrj 	_M_assign(_M_data() + __pos1, __n2, __c);
1125*38fd1498Szrj       return *this;
1126*38fd1498Szrj     }
1127*38fd1498Szrj 
1128*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1129*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>&
1130*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1131*38fd1498Szrj     _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
1132*38fd1498Szrj 		    size_type __n2)
1133*38fd1498Szrj     {
1134*38fd1498Szrj       _M_mutate(__pos1, __n1, __n2);
1135*38fd1498Szrj       if (__n2)
1136*38fd1498Szrj 	_M_copy(_M_data() + __pos1, __s, __n2);
1137*38fd1498Szrj       return *this;
1138*38fd1498Szrj     }
1139*38fd1498Szrj 
1140*38fd1498Szrj     template<typename _CharT, typename _Traits, typename _Alloc>
1141*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1142*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1143*38fd1498Szrj     copy(_CharT* __s, size_type __n, size_type __pos) const
1144*38fd1498Szrj     {
1145*38fd1498Szrj       _M_check(__pos, "basic_string::copy");
1146*38fd1498Szrj       __n = _M_limit(__pos, __n);
1147*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1148*38fd1498Szrj       if (__n)
1149*38fd1498Szrj 	_M_copy(__s, _M_data() + __pos, __n);
1150*38fd1498Szrj       // 21.3.5.7 par 3: do not append null.  (good.)
1151*38fd1498Szrj       return __n;
1152*38fd1498Szrj     }
1153*38fd1498Szrj #endif  // !_GLIBCXX_USE_CXX11_ABI
1154*38fd1498Szrj 
1155*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1156*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>
1157*38fd1498Szrj     operator+(const _CharT* __lhs,
1158*38fd1498Szrj 	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1159*38fd1498Szrj     {
1160*38fd1498Szrj       __glibcxx_requires_string(__lhs);
1161*38fd1498Szrj       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1162*38fd1498Szrj       typedef typename __string_type::size_type	  __size_type;
1163*38fd1498Szrj       const __size_type __len = _Traits::length(__lhs);
1164*38fd1498Szrj       __string_type __str;
1165*38fd1498Szrj       __str.reserve(__len + __rhs.size());
1166*38fd1498Szrj       __str.append(__lhs, __len);
1167*38fd1498Szrj       __str.append(__rhs);
1168*38fd1498Szrj       return __str;
1169*38fd1498Szrj     }
1170*38fd1498Szrj 
1171*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1172*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>
1173*38fd1498Szrj     operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1174*38fd1498Szrj     {
1175*38fd1498Szrj       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1176*38fd1498Szrj       typedef typename __string_type::size_type	  __size_type;
1177*38fd1498Szrj       __string_type __str;
1178*38fd1498Szrj       const __size_type __len = __rhs.size();
1179*38fd1498Szrj       __str.reserve(__len + 1);
1180*38fd1498Szrj       __str.append(__size_type(1), __lhs);
1181*38fd1498Szrj       __str.append(__rhs);
1182*38fd1498Szrj       return __str;
1183*38fd1498Szrj     }
1184*38fd1498Szrj 
1185*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1186*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1187*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1188*38fd1498Szrj     find(const _CharT* __s, size_type __pos, size_type __n) const
1189*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1190*38fd1498Szrj     {
1191*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1192*38fd1498Szrj       const size_type __size = this->size();
1193*38fd1498Szrj 
1194*38fd1498Szrj       if (__n == 0)
1195*38fd1498Szrj 	return __pos <= __size ? __pos : npos;
1196*38fd1498Szrj       if (__pos >= __size)
1197*38fd1498Szrj 	return npos;
1198*38fd1498Szrj 
1199*38fd1498Szrj       const _CharT __elem0 = __s[0];
1200*38fd1498Szrj       const _CharT* const __data = data();
1201*38fd1498Szrj       const _CharT* __first = __data + __pos;
1202*38fd1498Szrj       const _CharT* const __last = __data + __size;
1203*38fd1498Szrj       size_type __len = __size - __pos;
1204*38fd1498Szrj 
1205*38fd1498Szrj       while (__len >= __n)
1206*38fd1498Szrj 	{
1207*38fd1498Szrj 	  // Find the first occurrence of __elem0:
1208*38fd1498Szrj 	  __first = traits_type::find(__first, __len - __n + 1, __elem0);
1209*38fd1498Szrj 	  if (!__first)
1210*38fd1498Szrj 	    return npos;
1211*38fd1498Szrj 	  // Compare the full strings from the first occurrence of __elem0.
1212*38fd1498Szrj 	  // We already know that __first[0] == __s[0] but compare them again
1213*38fd1498Szrj 	  // anyway because __s is probably aligned, which helps memcmp.
1214*38fd1498Szrj 	  if (traits_type::compare(__first, __s, __n) == 0)
1215*38fd1498Szrj 	    return __first - __data;
1216*38fd1498Szrj 	  __len = __last - ++__first;
1217*38fd1498Szrj 	}
1218*38fd1498Szrj       return npos;
1219*38fd1498Szrj     }
1220*38fd1498Szrj 
1221*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1222*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1223*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1224*38fd1498Szrj     find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1225*38fd1498Szrj     {
1226*38fd1498Szrj       size_type __ret = npos;
1227*38fd1498Szrj       const size_type __size = this->size();
1228*38fd1498Szrj       if (__pos < __size)
1229*38fd1498Szrj 	{
1230*38fd1498Szrj 	  const _CharT* __data = _M_data();
1231*38fd1498Szrj 	  const size_type __n = __size - __pos;
1232*38fd1498Szrj 	  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
1233*38fd1498Szrj 	  if (__p)
1234*38fd1498Szrj 	    __ret = __p - __data;
1235*38fd1498Szrj 	}
1236*38fd1498Szrj       return __ret;
1237*38fd1498Szrj     }
1238*38fd1498Szrj 
1239*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1240*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1241*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1242*38fd1498Szrj     rfind(const _CharT* __s, size_type __pos, size_type __n) const
1243*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1244*38fd1498Szrj     {
1245*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1246*38fd1498Szrj       const size_type __size = this->size();
1247*38fd1498Szrj       if (__n <= __size)
1248*38fd1498Szrj 	{
1249*38fd1498Szrj 	  __pos = std::min(size_type(__size - __n), __pos);
1250*38fd1498Szrj 	  const _CharT* __data = _M_data();
1251*38fd1498Szrj 	  do
1252*38fd1498Szrj 	    {
1253*38fd1498Szrj 	      if (traits_type::compare(__data + __pos, __s, __n) == 0)
1254*38fd1498Szrj 		return __pos;
1255*38fd1498Szrj 	    }
1256*38fd1498Szrj 	  while (__pos-- > 0);
1257*38fd1498Szrj 	}
1258*38fd1498Szrj       return npos;
1259*38fd1498Szrj     }
1260*38fd1498Szrj 
1261*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1262*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1263*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1264*38fd1498Szrj     rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1265*38fd1498Szrj     {
1266*38fd1498Szrj       size_type __size = this->size();
1267*38fd1498Szrj       if (__size)
1268*38fd1498Szrj 	{
1269*38fd1498Szrj 	  if (--__size > __pos)
1270*38fd1498Szrj 	    __size = __pos;
1271*38fd1498Szrj 	  for (++__size; __size-- > 0; )
1272*38fd1498Szrj 	    if (traits_type::eq(_M_data()[__size], __c))
1273*38fd1498Szrj 	      return __size;
1274*38fd1498Szrj 	}
1275*38fd1498Szrj       return npos;
1276*38fd1498Szrj     }
1277*38fd1498Szrj 
1278*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1279*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1280*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1281*38fd1498Szrj     find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
1282*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1283*38fd1498Szrj     {
1284*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1285*38fd1498Szrj       for (; __n && __pos < this->size(); ++__pos)
1286*38fd1498Szrj 	{
1287*38fd1498Szrj 	  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
1288*38fd1498Szrj 	  if (__p)
1289*38fd1498Szrj 	    return __pos;
1290*38fd1498Szrj 	}
1291*38fd1498Szrj       return npos;
1292*38fd1498Szrj     }
1293*38fd1498Szrj 
1294*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1295*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1296*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1297*38fd1498Szrj     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
1298*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1299*38fd1498Szrj     {
1300*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1301*38fd1498Szrj       size_type __size = this->size();
1302*38fd1498Szrj       if (__size && __n)
1303*38fd1498Szrj 	{
1304*38fd1498Szrj 	  if (--__size > __pos)
1305*38fd1498Szrj 	    __size = __pos;
1306*38fd1498Szrj 	  do
1307*38fd1498Szrj 	    {
1308*38fd1498Szrj 	      if (traits_type::find(__s, __n, _M_data()[__size]))
1309*38fd1498Szrj 		return __size;
1310*38fd1498Szrj 	    }
1311*38fd1498Szrj 	  while (__size-- != 0);
1312*38fd1498Szrj 	}
1313*38fd1498Szrj       return npos;
1314*38fd1498Szrj     }
1315*38fd1498Szrj 
1316*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1317*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1318*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1319*38fd1498Szrj     find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1320*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1321*38fd1498Szrj     {
1322*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1323*38fd1498Szrj       for (; __pos < this->size(); ++__pos)
1324*38fd1498Szrj 	if (!traits_type::find(__s, __n, _M_data()[__pos]))
1325*38fd1498Szrj 	  return __pos;
1326*38fd1498Szrj       return npos;
1327*38fd1498Szrj     }
1328*38fd1498Szrj 
1329*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1330*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1331*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1332*38fd1498Szrj     find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1333*38fd1498Szrj     {
1334*38fd1498Szrj       for (; __pos < this->size(); ++__pos)
1335*38fd1498Szrj 	if (!traits_type::eq(_M_data()[__pos], __c))
1336*38fd1498Szrj 	  return __pos;
1337*38fd1498Szrj       return npos;
1338*38fd1498Szrj     }
1339*38fd1498Szrj 
1340*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1341*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1342*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1343*38fd1498Szrj     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1344*38fd1498Szrj     _GLIBCXX_NOEXCEPT
1345*38fd1498Szrj     {
1346*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n);
1347*38fd1498Szrj       size_type __size = this->size();
1348*38fd1498Szrj       if (__size)
1349*38fd1498Szrj 	{
1350*38fd1498Szrj 	  if (--__size > __pos)
1351*38fd1498Szrj 	    __size = __pos;
1352*38fd1498Szrj 	  do
1353*38fd1498Szrj 	    {
1354*38fd1498Szrj 	      if (!traits_type::find(__s, __n, _M_data()[__size]))
1355*38fd1498Szrj 		return __size;
1356*38fd1498Szrj 	    }
1357*38fd1498Szrj 	  while (__size--);
1358*38fd1498Szrj 	}
1359*38fd1498Szrj       return npos;
1360*38fd1498Szrj     }
1361*38fd1498Szrj 
1362*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1363*38fd1498Szrj     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1364*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1365*38fd1498Szrj     find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1366*38fd1498Szrj     {
1367*38fd1498Szrj       size_type __size = this->size();
1368*38fd1498Szrj       if (__size)
1369*38fd1498Szrj 	{
1370*38fd1498Szrj 	  if (--__size > __pos)
1371*38fd1498Szrj 	    __size = __pos;
1372*38fd1498Szrj 	  do
1373*38fd1498Szrj 	    {
1374*38fd1498Szrj 	      if (!traits_type::eq(_M_data()[__size], __c))
1375*38fd1498Szrj 		return __size;
1376*38fd1498Szrj 	    }
1377*38fd1498Szrj 	  while (__size--);
1378*38fd1498Szrj 	}
1379*38fd1498Szrj       return npos;
1380*38fd1498Szrj     }
1381*38fd1498Szrj 
1382*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1383*38fd1498Szrj     int
1384*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1385*38fd1498Szrj     compare(size_type __pos, size_type __n, const basic_string& __str) const
1386*38fd1498Szrj     {
1387*38fd1498Szrj       _M_check(__pos, "basic_string::compare");
1388*38fd1498Szrj       __n = _M_limit(__pos, __n);
1389*38fd1498Szrj       const size_type __osize = __str.size();
1390*38fd1498Szrj       const size_type __len = std::min(__n, __osize);
1391*38fd1498Szrj       int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
1392*38fd1498Szrj       if (!__r)
1393*38fd1498Szrj 	__r = _S_compare(__n, __osize);
1394*38fd1498Szrj       return __r;
1395*38fd1498Szrj     }
1396*38fd1498Szrj 
1397*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1398*38fd1498Szrj     int
1399*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1400*38fd1498Szrj     compare(size_type __pos1, size_type __n1, const basic_string& __str,
1401*38fd1498Szrj 	    size_type __pos2, size_type __n2) const
1402*38fd1498Szrj     {
1403*38fd1498Szrj       _M_check(__pos1, "basic_string::compare");
1404*38fd1498Szrj       __str._M_check(__pos2, "basic_string::compare");
1405*38fd1498Szrj       __n1 = _M_limit(__pos1, __n1);
1406*38fd1498Szrj       __n2 = __str._M_limit(__pos2, __n2);
1407*38fd1498Szrj       const size_type __len = std::min(__n1, __n2);
1408*38fd1498Szrj       int __r = traits_type::compare(_M_data() + __pos1,
1409*38fd1498Szrj 				     __str.data() + __pos2, __len);
1410*38fd1498Szrj       if (!__r)
1411*38fd1498Szrj 	__r = _S_compare(__n1, __n2);
1412*38fd1498Szrj       return __r;
1413*38fd1498Szrj     }
1414*38fd1498Szrj 
1415*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1416*38fd1498Szrj     int
1417*38fd1498Szrj     basic_string<_CharT, _Traits, _Alloc>::
1418*38fd1498Szrj     compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT
1419*38fd1498Szrj     {
1420*38fd1498Szrj       __glibcxx_requires_string(__s);
1421*38fd1498Szrj       const size_type __size = this->size();
1422*38fd1498Szrj       const size_type __osize = traits_type::length(__s);
1423*38fd1498Szrj       const size_type __len = std::min(__size, __osize);
1424*38fd1498Szrj       int __r = traits_type::compare(_M_data(), __s, __len);
1425*38fd1498Szrj       if (!__r)
1426*38fd1498Szrj 	__r = _S_compare(__size, __osize);
1427*38fd1498Szrj       return __r;
1428*38fd1498Szrj     }
1429*38fd1498Szrj 
1430*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1431*38fd1498Szrj     int
1432*38fd1498Szrj     basic_string <_CharT, _Traits, _Alloc>::
1433*38fd1498Szrj     compare(size_type __pos, size_type __n1, const _CharT* __s) const
1434*38fd1498Szrj     {
1435*38fd1498Szrj       __glibcxx_requires_string(__s);
1436*38fd1498Szrj       _M_check(__pos, "basic_string::compare");
1437*38fd1498Szrj       __n1 = _M_limit(__pos, __n1);
1438*38fd1498Szrj       const size_type __osize = traits_type::length(__s);
1439*38fd1498Szrj       const size_type __len = std::min(__n1, __osize);
1440*38fd1498Szrj       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1441*38fd1498Szrj       if (!__r)
1442*38fd1498Szrj 	__r = _S_compare(__n1, __osize);
1443*38fd1498Szrj       return __r;
1444*38fd1498Szrj     }
1445*38fd1498Szrj 
1446*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1447*38fd1498Szrj     int
1448*38fd1498Szrj     basic_string <_CharT, _Traits, _Alloc>::
1449*38fd1498Szrj     compare(size_type __pos, size_type __n1, const _CharT* __s,
1450*38fd1498Szrj 	    size_type __n2) const
1451*38fd1498Szrj     {
1452*38fd1498Szrj       __glibcxx_requires_string_len(__s, __n2);
1453*38fd1498Szrj       _M_check(__pos, "basic_string::compare");
1454*38fd1498Szrj       __n1 = _M_limit(__pos, __n1);
1455*38fd1498Szrj       const size_type __len = std::min(__n1, __n2);
1456*38fd1498Szrj       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1457*38fd1498Szrj       if (!__r)
1458*38fd1498Szrj 	__r = _S_compare(__n1, __n2);
1459*38fd1498Szrj       return __r;
1460*38fd1498Szrj     }
1461*38fd1498Szrj 
1462*38fd1498Szrj   // 21.3.7.9 basic_string::getline and operators
1463*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1464*38fd1498Szrj     basic_istream<_CharT, _Traits>&
1465*38fd1498Szrj     operator>>(basic_istream<_CharT, _Traits>& __in,
1466*38fd1498Szrj 	       basic_string<_CharT, _Traits, _Alloc>& __str)
1467*38fd1498Szrj     {
1468*38fd1498Szrj       typedef basic_istream<_CharT, _Traits>		__istream_type;
1469*38fd1498Szrj       typedef basic_string<_CharT, _Traits, _Alloc>	__string_type;
1470*38fd1498Szrj       typedef typename __istream_type::ios_base         __ios_base;
1471*38fd1498Szrj       typedef typename __istream_type::int_type		__int_type;
1472*38fd1498Szrj       typedef typename __string_type::size_type		__size_type;
1473*38fd1498Szrj       typedef ctype<_CharT>				__ctype_type;
1474*38fd1498Szrj       typedef typename __ctype_type::ctype_base         __ctype_base;
1475*38fd1498Szrj 
1476*38fd1498Szrj       __size_type __extracted = 0;
1477*38fd1498Szrj       typename __ios_base::iostate __err = __ios_base::goodbit;
1478*38fd1498Szrj       typename __istream_type::sentry __cerb(__in, false);
1479*38fd1498Szrj       if (__cerb)
1480*38fd1498Szrj 	{
1481*38fd1498Szrj 	  __try
1482*38fd1498Szrj 	    {
1483*38fd1498Szrj 	      // Avoid reallocation for common case.
1484*38fd1498Szrj 	      __str.erase();
1485*38fd1498Szrj 	      _CharT __buf[128];
1486*38fd1498Szrj 	      __size_type __len = 0;
1487*38fd1498Szrj 	      const streamsize __w = __in.width();
1488*38fd1498Szrj 	      const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
1489*38fd1498Szrj 		                              : __str.max_size();
1490*38fd1498Szrj 	      const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
1491*38fd1498Szrj 	      const __int_type __eof = _Traits::eof();
1492*38fd1498Szrj 	      __int_type __c = __in.rdbuf()->sgetc();
1493*38fd1498Szrj 
1494*38fd1498Szrj 	      while (__extracted < __n
1495*38fd1498Szrj 		     && !_Traits::eq_int_type(__c, __eof)
1496*38fd1498Szrj 		     && !__ct.is(__ctype_base::space,
1497*38fd1498Szrj 				 _Traits::to_char_type(__c)))
1498*38fd1498Szrj 		{
1499*38fd1498Szrj 		  if (__len == sizeof(__buf) / sizeof(_CharT))
1500*38fd1498Szrj 		    {
1501*38fd1498Szrj 		      __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
1502*38fd1498Szrj 		      __len = 0;
1503*38fd1498Szrj 		    }
1504*38fd1498Szrj 		  __buf[__len++] = _Traits::to_char_type(__c);
1505*38fd1498Szrj 		  ++__extracted;
1506*38fd1498Szrj 		  __c = __in.rdbuf()->snextc();
1507*38fd1498Szrj 		}
1508*38fd1498Szrj 	      __str.append(__buf, __len);
1509*38fd1498Szrj 
1510*38fd1498Szrj 	      if (_Traits::eq_int_type(__c, __eof))
1511*38fd1498Szrj 		__err |= __ios_base::eofbit;
1512*38fd1498Szrj 	      __in.width(0);
1513*38fd1498Szrj 	    }
1514*38fd1498Szrj 	  __catch(__cxxabiv1::__forced_unwind&)
1515*38fd1498Szrj 	    {
1516*38fd1498Szrj 	      __in._M_setstate(__ios_base::badbit);
1517*38fd1498Szrj 	      __throw_exception_again;
1518*38fd1498Szrj 	    }
1519*38fd1498Szrj 	  __catch(...)
1520*38fd1498Szrj 	    {
1521*38fd1498Szrj 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1522*38fd1498Szrj 	      // 91. Description of operator>> and getline() for string<>
1523*38fd1498Szrj 	      // might cause endless loop
1524*38fd1498Szrj 	      __in._M_setstate(__ios_base::badbit);
1525*38fd1498Szrj 	    }
1526*38fd1498Szrj 	}
1527*38fd1498Szrj       // 211.  operator>>(istream&, string&) doesn't set failbit
1528*38fd1498Szrj       if (!__extracted)
1529*38fd1498Szrj 	__err |= __ios_base::failbit;
1530*38fd1498Szrj       if (__err)
1531*38fd1498Szrj 	__in.setstate(__err);
1532*38fd1498Szrj       return __in;
1533*38fd1498Szrj     }
1534*38fd1498Szrj 
1535*38fd1498Szrj   template<typename _CharT, typename _Traits, typename _Alloc>
1536*38fd1498Szrj     basic_istream<_CharT, _Traits>&
1537*38fd1498Szrj     getline(basic_istream<_CharT, _Traits>& __in,
1538*38fd1498Szrj 	    basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
1539*38fd1498Szrj     {
1540*38fd1498Szrj       typedef basic_istream<_CharT, _Traits>		__istream_type;
1541*38fd1498Szrj       typedef basic_string<_CharT, _Traits, _Alloc>	__string_type;
1542*38fd1498Szrj       typedef typename __istream_type::ios_base         __ios_base;
1543*38fd1498Szrj       typedef typename __istream_type::int_type		__int_type;
1544*38fd1498Szrj       typedef typename __string_type::size_type		__size_type;
1545*38fd1498Szrj 
1546*38fd1498Szrj       __size_type __extracted = 0;
1547*38fd1498Szrj       const __size_type __n = __str.max_size();
1548*38fd1498Szrj       typename __ios_base::iostate __err = __ios_base::goodbit;
1549*38fd1498Szrj       typename __istream_type::sentry __cerb(__in, true);
1550*38fd1498Szrj       if (__cerb)
1551*38fd1498Szrj 	{
1552*38fd1498Szrj 	  __try
1553*38fd1498Szrj 	    {
1554*38fd1498Szrj 	      __str.erase();
1555*38fd1498Szrj 	      const __int_type __idelim = _Traits::to_int_type(__delim);
1556*38fd1498Szrj 	      const __int_type __eof = _Traits::eof();
1557*38fd1498Szrj 	      __int_type __c = __in.rdbuf()->sgetc();
1558*38fd1498Szrj 
1559*38fd1498Szrj 	      while (__extracted < __n
1560*38fd1498Szrj 		     && !_Traits::eq_int_type(__c, __eof)
1561*38fd1498Szrj 		     && !_Traits::eq_int_type(__c, __idelim))
1562*38fd1498Szrj 		{
1563*38fd1498Szrj 		  __str += _Traits::to_char_type(__c);
1564*38fd1498Szrj 		  ++__extracted;
1565*38fd1498Szrj 		  __c = __in.rdbuf()->snextc();
1566*38fd1498Szrj 		}
1567*38fd1498Szrj 
1568*38fd1498Szrj 	      if (_Traits::eq_int_type(__c, __eof))
1569*38fd1498Szrj 		__err |= __ios_base::eofbit;
1570*38fd1498Szrj 	      else if (_Traits::eq_int_type(__c, __idelim))
1571*38fd1498Szrj 		{
1572*38fd1498Szrj 		  ++__extracted;
1573*38fd1498Szrj 		  __in.rdbuf()->sbumpc();
1574*38fd1498Szrj 		}
1575*38fd1498Szrj 	      else
1576*38fd1498Szrj 		__err |= __ios_base::failbit;
1577*38fd1498Szrj 	    }
1578*38fd1498Szrj 	  __catch(__cxxabiv1::__forced_unwind&)
1579*38fd1498Szrj 	    {
1580*38fd1498Szrj 	      __in._M_setstate(__ios_base::badbit);
1581*38fd1498Szrj 	      __throw_exception_again;
1582*38fd1498Szrj 	    }
1583*38fd1498Szrj 	  __catch(...)
1584*38fd1498Szrj 	    {
1585*38fd1498Szrj 	      // _GLIBCXX_RESOLVE_LIB_DEFECTS
1586*38fd1498Szrj 	      // 91. Description of operator>> and getline() for string<>
1587*38fd1498Szrj 	      // might cause endless loop
1588*38fd1498Szrj 	      __in._M_setstate(__ios_base::badbit);
1589*38fd1498Szrj 	    }
1590*38fd1498Szrj 	}
1591*38fd1498Szrj       if (!__extracted)
1592*38fd1498Szrj 	__err |= __ios_base::failbit;
1593*38fd1498Szrj       if (__err)
1594*38fd1498Szrj 	__in.setstate(__err);
1595*38fd1498Szrj       return __in;
1596*38fd1498Szrj     }
1597*38fd1498Szrj 
1598*38fd1498Szrj   // Inhibit implicit instantiations for required instantiations,
1599*38fd1498Szrj   // which are defined via explicit instantiations elsewhere.
1600*38fd1498Szrj #if _GLIBCXX_EXTERN_TEMPLATE > 0 && __cplusplus <= 201402L
1601*38fd1498Szrj   extern template class basic_string<char>;
1602*38fd1498Szrj   extern template
1603*38fd1498Szrj     basic_istream<char>&
1604*38fd1498Szrj     operator>>(basic_istream<char>&, string&);
1605*38fd1498Szrj   extern template
1606*38fd1498Szrj     basic_ostream<char>&
1607*38fd1498Szrj     operator<<(basic_ostream<char>&, const string&);
1608*38fd1498Szrj   extern template
1609*38fd1498Szrj     basic_istream<char>&
1610*38fd1498Szrj     getline(basic_istream<char>&, string&, char);
1611*38fd1498Szrj   extern template
1612*38fd1498Szrj     basic_istream<char>&
1613*38fd1498Szrj     getline(basic_istream<char>&, string&);
1614*38fd1498Szrj 
1615*38fd1498Szrj #ifdef _GLIBCXX_USE_WCHAR_T
1616*38fd1498Szrj   extern template class basic_string<wchar_t>;
1617*38fd1498Szrj   extern template
1618*38fd1498Szrj     basic_istream<wchar_t>&
1619*38fd1498Szrj     operator>>(basic_istream<wchar_t>&, wstring&);
1620*38fd1498Szrj   extern template
1621*38fd1498Szrj     basic_ostream<wchar_t>&
1622*38fd1498Szrj     operator<<(basic_ostream<wchar_t>&, const wstring&);
1623*38fd1498Szrj   extern template
1624*38fd1498Szrj     basic_istream<wchar_t>&
1625*38fd1498Szrj     getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1626*38fd1498Szrj   extern template
1627*38fd1498Szrj     basic_istream<wchar_t>&
1628*38fd1498Szrj     getline(basic_istream<wchar_t>&, wstring&);
1629*38fd1498Szrj #endif
1630*38fd1498Szrj #endif
1631*38fd1498Szrj 
1632*38fd1498Szrj _GLIBCXX_END_NAMESPACE_VERSION
1633*38fd1498Szrj } // namespace std
1634*38fd1498Szrj 
1635*38fd1498Szrj #endif
1636