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