libstdc++
basic_string.tcc
Go to the documentation of this file.
1 // Components for manipulating sequences of characters -*- C++ -*-
2 
3 // Copyright (C) 1997-2019 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
55 
56  template<typename _CharT, typename _Traits, typename _Alloc>
57  void
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>::
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>::
164  _M_construct(_InIterator __beg, _InIterator __end,
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>::
207  _M_construct(_InIterator __beg, _InIterator __end,
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>::
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>::
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
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>::
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>::
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
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_set_length(__n);
355  }
356 
357  template<typename _CharT, typename _Traits, typename _Alloc>
358  basic_string<_CharT, _Traits, _Alloc>&
359  basic_string<_CharT, _Traits, _Alloc>::
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>::
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>::
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>::
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
475  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
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>
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>
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>
624  basic_string(const basic_string& __str, size_type __pos, const _Alloc& __a)
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, npos)
629  + __pos, __a), __a)
630  { }
631 
632  template<typename _CharT, typename _Traits, typename _Alloc>
634  basic_string(const basic_string& __str, size_type __pos, size_type __n)
635  : _M_dataplus(_S_construct(__str._M_data()
636  + __str._M_check(__pos,
637  "basic_string::basic_string"),
638  __str._M_data() + __str._M_limit(__pos, __n)
639  + __pos, _Alloc()), _Alloc())
640  { }
641 
642  template<typename _CharT, typename _Traits, typename _Alloc>
644  basic_string(const basic_string& __str, size_type __pos,
645  size_type __n, const _Alloc& __a)
646  : _M_dataplus(_S_construct(__str._M_data()
647  + __str._M_check(__pos,
648  "basic_string::basic_string"),
649  __str._M_data() + __str._M_limit(__pos, __n)
650  + __pos, __a), __a)
651  { }
652 
653  // TBD: DPG annotate
654  template<typename _CharT, typename _Traits, typename _Alloc>
656  basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
657  : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
658  { }
659 
660  // TBD: DPG annotate
661  template<typename _CharT, typename _Traits, typename _Alloc>
663  basic_string(const _CharT* __s, const _Alloc& __a)
664  : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
665  __s + npos, __a), __a)
666  { }
667 
668  template<typename _CharT, typename _Traits, typename _Alloc>
670  basic_string(size_type __n, _CharT __c, const _Alloc& __a)
671  : _M_dataplus(_S_construct(__n, __c, __a), __a)
672  { }
673 
674  // TBD: DPG annotate
675  template<typename _CharT, typename _Traits, typename _Alloc>
676  template<typename _InputIterator>
678  basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
679  : _M_dataplus(_S_construct(__beg, __end, __a), __a)
680  { }
681 
682 #if __cplusplus >= 201103L
683  template<typename _CharT, typename _Traits, typename _Alloc>
686  : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a)
687  { }
688 #endif
689 
690  template<typename _CharT, typename _Traits, typename _Alloc>
693  assign(const basic_string& __str)
694  {
695  if (_M_rep() != __str._M_rep())
696  {
697  // XXX MT
698  const allocator_type __a = this->get_allocator();
699  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
700  _M_rep()->_M_dispose(__a);
701  _M_data(__tmp);
702  }
703  return *this;
704  }
705 
706  template<typename _CharT, typename _Traits, typename _Alloc>
709  assign(const _CharT* __s, size_type __n)
710  {
711  __glibcxx_requires_string_len(__s, __n);
712  _M_check_length(this->size(), __n, "basic_string::assign");
713  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
714  return _M_replace_safe(size_type(0), this->size(), __s, __n);
715  else
716  {
717  // Work in-place.
718  const size_type __pos = __s - _M_data();
719  if (__pos >= __n)
720  _M_copy(_M_data(), __s, __n);
721  else if (__pos)
722  _M_move(_M_data(), __s, __n);
723  _M_rep()->_M_set_length_and_sharable(__n);
724  return *this;
725  }
726  }
727 
728  template<typename _CharT, typename _Traits, typename _Alloc>
731  append(size_type __n, _CharT __c)
732  {
733  if (__n)
734  {
735  _M_check_length(size_type(0), __n, "basic_string::append");
736  const size_type __len = __n + this->size();
737  if (__len > this->capacity() || _M_rep()->_M_is_shared())
738  this->reserve(__len);
739  _M_assign(_M_data() + this->size(), __n, __c);
740  _M_rep()->_M_set_length_and_sharable(__len);
741  }
742  return *this;
743  }
744 
745  template<typename _CharT, typename _Traits, typename _Alloc>
748  append(const _CharT* __s, size_type __n)
749  {
750  __glibcxx_requires_string_len(__s, __n);
751  if (__n)
752  {
753  _M_check_length(size_type(0), __n, "basic_string::append");
754  const size_type __len = __n + this->size();
755  if (__len > this->capacity() || _M_rep()->_M_is_shared())
756  {
757  if (_M_disjunct(__s))
758  this->reserve(__len);
759  else
760  {
761  const size_type __off = __s - _M_data();
762  this->reserve(__len);
763  __s = _M_data() + __off;
764  }
765  }
766  _M_copy(_M_data() + this->size(), __s, __n);
767  _M_rep()->_M_set_length_and_sharable(__len);
768  }
769  return *this;
770  }
771 
772  template<typename _CharT, typename _Traits, typename _Alloc>
775  append(const basic_string& __str)
776  {
777  const size_type __size = __str.size();
778  if (__size)
779  {
780  const size_type __len = __size + this->size();
781  if (__len > this->capacity() || _M_rep()->_M_is_shared())
782  this->reserve(__len);
783  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
784  _M_rep()->_M_set_length_and_sharable(__len);
785  }
786  return *this;
787  }
788 
789  template<typename _CharT, typename _Traits, typename _Alloc>
792  append(const basic_string& __str, size_type __pos, size_type __n)
793  {
794  __str._M_check(__pos, "basic_string::append");
795  __n = __str._M_limit(__pos, __n);
796  if (__n)
797  {
798  const size_type __len = __n + this->size();
799  if (__len > this->capacity() || _M_rep()->_M_is_shared())
800  this->reserve(__len);
801  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
802  _M_rep()->_M_set_length_and_sharable(__len);
803  }
804  return *this;
805  }
806 
807  template<typename _CharT, typename _Traits, typename _Alloc>
810  insert(size_type __pos, const _CharT* __s, size_type __n)
811  {
812  __glibcxx_requires_string_len(__s, __n);
813  _M_check(__pos, "basic_string::insert");
814  _M_check_length(size_type(0), __n, "basic_string::insert");
815  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
816  return _M_replace_safe(__pos, size_type(0), __s, __n);
817  else
818  {
819  // Work in-place.
820  const size_type __off = __s - _M_data();
821  _M_mutate(__pos, 0, __n);
822  __s = _M_data() + __off;
823  _CharT* __p = _M_data() + __pos;
824  if (__s + __n <= __p)
825  _M_copy(__p, __s, __n);
826  else if (__s >= __p)
827  _M_copy(__p, __s + __n, __n);
828  else
829  {
830  const size_type __nleft = __p - __s;
831  _M_copy(__p, __s, __nleft);
832  _M_copy(__p + __nleft, __p + __n, __n - __nleft);
833  }
834  return *this;
835  }
836  }
837 
838  template<typename _CharT, typename _Traits, typename _Alloc>
839  typename basic_string<_CharT, _Traits, _Alloc>::iterator
841  erase(iterator __first, iterator __last)
842  {
843  _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
844  && __last <= _M_iend());
845 
846  // NB: This isn't just an optimization (bail out early when
847  // there is nothing to do, really), it's also a correctness
848  // issue vs MT, see libstdc++/40518.
849  const size_type __size = __last - __first;
850  if (__size)
851  {
852  const size_type __pos = __first - _M_ibegin();
853  _M_mutate(__pos, __size, size_type(0));
854  _M_rep()->_M_set_leaked();
855  return iterator(_M_data() + __pos);
856  }
857  else
858  return __first;
859  }
860 
861  template<typename _CharT, typename _Traits, typename _Alloc>
864  replace(size_type __pos, size_type __n1, const _CharT* __s,
865  size_type __n2)
866  {
867  __glibcxx_requires_string_len(__s, __n2);
868  _M_check(__pos, "basic_string::replace");
869  __n1 = _M_limit(__pos, __n1);
870  _M_check_length(__n1, __n2, "basic_string::replace");
871  bool __left;
872  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
873  return _M_replace_safe(__pos, __n1, __s, __n2);
874  else if ((__left = __s + __n2 <= _M_data() + __pos)
875  || _M_data() + __pos + __n1 <= __s)
876  {
877  // Work in-place: non-overlapping case.
878  size_type __off = __s - _M_data();
879  __left ? __off : (__off += __n2 - __n1);
880  _M_mutate(__pos, __n1, __n2);
881  _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
882  return *this;
883  }
884  else
885  {
886  // Todo: overlapping case.
887  const basic_string __tmp(__s, __n2);
888  return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
889  }
890  }
891 
892  template<typename _CharT, typename _Traits, typename _Alloc>
893  void
895  _M_destroy(const _Alloc& __a) throw ()
896  {
897  const size_type __size = sizeof(_Rep_base) +
898  (this->_M_capacity + 1) * sizeof(_CharT);
899  _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
900  }
901 
902  template<typename _CharT, typename _Traits, typename _Alloc>
903  void
904  basic_string<_CharT, _Traits, _Alloc>::
905  _M_leak_hard()
906  {
907 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
908  if (_M_rep() == &_S_empty_rep())
909  return;
910 #endif
911  if (_M_rep()->_M_is_shared())
912  _M_mutate(0, 0, 0);
913  _M_rep()->_M_set_leaked();
914  }
915 
916  template<typename _CharT, typename _Traits, typename _Alloc>
917  void
918  basic_string<_CharT, _Traits, _Alloc>::
919  _M_mutate(size_type __pos, size_type __len1, size_type __len2)
920  {
921  const size_type __old_size = this->size();
922  const size_type __new_size = __old_size + __len2 - __len1;
923  const size_type __how_much = __old_size - __pos - __len1;
924 
925  if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
926  {
927  // Must reallocate.
928  const allocator_type __a = get_allocator();
929  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
930 
931  if (__pos)
932  _M_copy(__r->_M_refdata(), _M_data(), __pos);
933  if (__how_much)
934  _M_copy(__r->_M_refdata() + __pos + __len2,
935  _M_data() + __pos + __len1, __how_much);
936 
937  _M_rep()->_M_dispose(__a);
938  _M_data(__r->_M_refdata());
939  }
940  else if (__how_much && __len1 != __len2)
941  {
942  // Work in-place.
943  _M_move(_M_data() + __pos + __len2,
944  _M_data() + __pos + __len1, __how_much);
945  }
946  _M_rep()->_M_set_length_and_sharable(__new_size);
947  }
948 
949  template<typename _CharT, typename _Traits, typename _Alloc>
950  void
951  basic_string<_CharT, _Traits, _Alloc>::
952  reserve(size_type __res)
953  {
954  if (__res != this->capacity() || _M_rep()->_M_is_shared())
955  {
956  // Make sure we don't shrink below the current size
957  if (__res < this->size())
958  __res = this->size();
959  const allocator_type __a = get_allocator();
960  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
961  _M_rep()->_M_dispose(__a);
962  _M_data(__tmp);
963  }
964  }
965 
966  template<typename _CharT, typename _Traits, typename _Alloc>
967  void
971  {
972  if (_M_rep()->_M_is_leaked())
973  _M_rep()->_M_set_sharable();
974  if (__s._M_rep()->_M_is_leaked())
975  __s._M_rep()->_M_set_sharable();
976  if (this->get_allocator() == __s.get_allocator())
977  {
978  _CharT* __tmp = _M_data();
979  _M_data(__s._M_data());
980  __s._M_data(__tmp);
981  }
982  // The code below can usually be optimized away.
983  else
984  {
985  const basic_string __tmp1(_M_ibegin(), _M_iend(),
986  __s.get_allocator());
987  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
988  this->get_allocator());
989  *this = __tmp2;
990  __s = __tmp1;
991  }
992  }
993 
994  template<typename _CharT, typename _Traits, typename _Alloc>
997  _S_create(size_type __capacity, size_type __old_capacity,
998  const _Alloc& __alloc)
999  {
1000  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1001  // 83. String::npos vs. string::max_size()
1002  if (__capacity > _S_max_size)
1003  __throw_length_error(__N("basic_string::_S_create"));
1004 
1005  // The standard places no restriction on allocating more memory
1006  // than is strictly needed within this layer at the moment or as
1007  // requested by an explicit application call to reserve().
1008 
1009  // Many malloc implementations perform quite poorly when an
1010  // application attempts to allocate memory in a stepwise fashion
1011  // growing each allocation size by only 1 char. Additionally,
1012  // it makes little sense to allocate less linear memory than the
1013  // natural blocking size of the malloc implementation.
1014  // Unfortunately, we would need a somewhat low-level calculation
1015  // with tuned parameters to get this perfect for any particular
1016  // malloc implementation. Fortunately, generalizations about
1017  // common features seen among implementations seems to suffice.
1018 
1019  // __pagesize need not match the actual VM page size for good
1020  // results in practice, thus we pick a common value on the low
1021  // side. __malloc_header_size is an estimate of the amount of
1022  // overhead per memory allocation (in practice seen N * sizeof
1023  // (void*) where N is 0, 2 or 4). According to folklore,
1024  // picking this value on the high side is better than
1025  // low-balling it (especially when this algorithm is used with
1026  // malloc implementations that allocate memory blocks rounded up
1027  // to a size which is a power of 2).
1028  const size_type __pagesize = 4096;
1029  const size_type __malloc_header_size = 4 * sizeof(void*);
1030 
1031  // The below implements an exponential growth policy, necessary to
1032  // meet amortized linear time requirements of the library: see
1033  // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
1034  // It's active for allocations requiring an amount of memory above
1035  // system pagesize. This is consistent with the requirements of the
1036  // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
1037  if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
1038  __capacity = 2 * __old_capacity;
1039 
1040  // NB: Need an array of char_type[__capacity], plus a terminating
1041  // null char_type() element, plus enough for the _Rep data structure.
1042  // Whew. Seemingly so needy, yet so elemental.
1043  size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1044 
1045  const size_type __adj_size = __size + __malloc_header_size;
1046  if (__adj_size > __pagesize && __capacity > __old_capacity)
1047  {
1048  const size_type __extra = __pagesize - __adj_size % __pagesize;
1049  __capacity += __extra / sizeof(_CharT);
1050  // Never allocate a string bigger than _S_max_size.
1051  if (__capacity > _S_max_size)
1052  __capacity = _S_max_size;
1053  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1054  }
1055 
1056  // NB: Might throw, but no worries about a leak, mate: _Rep()
1057  // does not throw.
1058  void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
1059  _Rep *__p = new (__place) _Rep;
1060  __p->_M_capacity = __capacity;
1061  // ABI compatibility - 3.4.x set in _S_create both
1062  // _M_refcount and _M_length. All callers of _S_create
1063  // in basic_string.tcc then set just _M_length.
1064  // In 4.0.x and later both _M_refcount and _M_length
1065  // are initialized in the callers, unfortunately we can
1066  // have 3.4.x compiled code with _S_create callers inlined
1067  // calling 4.0.x+ _S_create.
1068  __p->_M_set_sharable();
1069  return __p;
1070  }
1071 
1072  template<typename _CharT, typename _Traits, typename _Alloc>
1073  _CharT*
1074  basic_string<_CharT, _Traits, _Alloc>::_Rep::
1075  _M_clone(const _Alloc& __alloc, size_type __res)
1076  {
1077  // Requested capacity of the clone.
1078  const size_type __requested_cap = this->_M_length + __res;
1079  _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
1080  __alloc);
1081  if (this->_M_length)
1082  _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
1083 
1084  __r->_M_set_length_and_sharable(this->_M_length);
1085  return __r->_M_refdata();
1086  }
1087 
1088  template<typename _CharT, typename _Traits, typename _Alloc>
1089  void
1090  basic_string<_CharT, _Traits, _Alloc>::
1091  resize(size_type __n, _CharT __c)
1092  {
1093  const size_type __size = this->size();
1094  _M_check_length(__size, __n, "basic_string::resize");
1095  if (__size < __n)
1096  this->append(__n - __size, __c);
1097  else if (__n < __size)
1098  this->erase(__n);
1099  // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
1100  }
1101 
1102  template<typename _CharT, typename _Traits, typename _Alloc>
1103  template<typename _InputIterator>
1106  _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
1107  _InputIterator __k2, __false_type)
1108  {
1109  const basic_string __s(__k1, __k2);
1110  const size_type __n1 = __i2 - __i1;
1111  _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
1112  return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
1113  __s.size());
1114  }
1115 
1116  template<typename _CharT, typename _Traits, typename _Alloc>
1117  basic_string<_CharT, _Traits, _Alloc>&
1118  basic_string<_CharT, _Traits, _Alloc>::
1119  _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
1120  _CharT __c)
1121  {
1122  _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
1123  _M_mutate(__pos1, __n1, __n2);
1124  if (__n2)
1125  _M_assign(_M_data() + __pos1, __n2, __c);
1126  return *this;
1127  }
1128 
1129  template<typename _CharT, typename _Traits, typename _Alloc>
1130  basic_string<_CharT, _Traits, _Alloc>&
1131  basic_string<_CharT, _Traits, _Alloc>::
1132  _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
1133  size_type __n2)
1134  {
1135  _M_mutate(__pos1, __n1, __n2);
1136  if (__n2)
1137  _M_copy(_M_data() + __pos1, __s, __n2);
1138  return *this;
1139  }
1140 
1141  template<typename _CharT, typename _Traits, typename _Alloc>
1142  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1143  basic_string<_CharT, _Traits, _Alloc>::
1144  copy(_CharT* __s, size_type __n, size_type __pos) const
1145  {
1146  _M_check(__pos, "basic_string::copy");
1147  __n = _M_limit(__pos, __n);
1148  __glibcxx_requires_string_len(__s, __n);
1149  if (__n)
1150  _M_copy(__s, _M_data() + __pos, __n);
1151  // 21.3.5.7 par 3: do not append null. (good.)
1152  return __n;
1153  }
1154 #endif // !_GLIBCXX_USE_CXX11_ABI
1155 
1156  template<typename _CharT, typename _Traits, typename _Alloc>
1158  operator+(const _CharT* __lhs,
1160  {
1161  __glibcxx_requires_string(__lhs);
1162  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1163  typedef typename __string_type::size_type __size_type;
1164  const __size_type __len = _Traits::length(__lhs);
1165  __string_type __str;
1166  __str.reserve(__len + __rhs.size());
1167  __str.append(__lhs, __len);
1168  __str.append(__rhs);
1169  return __str;
1170  }
1171 
1172  template<typename _CharT, typename _Traits, typename _Alloc>
1173  basic_string<_CharT, _Traits, _Alloc>
1174  operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1175  {
1176  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1177  typedef typename __string_type::size_type __size_type;
1178  __string_type __str;
1179  const __size_type __len = __rhs.size();
1180  __str.reserve(__len + 1);
1181  __str.append(__size_type(1), __lhs);
1182  __str.append(__rhs);
1183  return __str;
1184  }
1185 
1186  template<typename _CharT, typename _Traits, typename _Alloc>
1187  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1188  basic_string<_CharT, _Traits, _Alloc>::
1189  find(const _CharT* __s, size_type __pos, size_type __n) const
1190  _GLIBCXX_NOEXCEPT
1191  {
1192  __glibcxx_requires_string_len(__s, __n);
1193  const size_type __size = this->size();
1194 
1195  if (__n == 0)
1196  return __pos <= __size ? __pos : npos;
1197  if (__pos >= __size)
1198  return npos;
1199 
1200  const _CharT __elem0 = __s[0];
1201  const _CharT* const __data = data();
1202  const _CharT* __first = __data + __pos;
1203  const _CharT* const __last = __data + __size;
1204  size_type __len = __size - __pos;
1205 
1206  while (__len >= __n)
1207  {
1208  // Find the first occurrence of __elem0:
1209  __first = traits_type::find(__first, __len - __n + 1, __elem0);
1210  if (!__first)
1211  return npos;
1212  // Compare the full strings from the first occurrence of __elem0.
1213  // We already know that __first[0] == __s[0] but compare them again
1214  // anyway because __s is probably aligned, which helps memcmp.
1215  if (traits_type::compare(__first, __s, __n) == 0)
1216  return __first - __data;
1217  __len = __last - ++__first;
1218  }
1219  return npos;
1220  }
1221 
1222  template<typename _CharT, typename _Traits, typename _Alloc>
1223  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1225  find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1226  {
1227  size_type __ret = npos;
1228  const size_type __size = this->size();
1229  if (__pos < __size)
1230  {
1231  const _CharT* __data = _M_data();
1232  const size_type __n = __size - __pos;
1233  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
1234  if (__p)
1235  __ret = __p - __data;
1236  }
1237  return __ret;
1238  }
1239 
1240  template<typename _CharT, typename _Traits, typename _Alloc>
1241  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1243  rfind(const _CharT* __s, size_type __pos, size_type __n) const
1244  _GLIBCXX_NOEXCEPT
1245  {
1246  __glibcxx_requires_string_len(__s, __n);
1247  const size_type __size = this->size();
1248  if (__n <= __size)
1249  {
1250  __pos = std::min(size_type(__size - __n), __pos);
1251  const _CharT* __data = _M_data();
1252  do
1253  {
1254  if (traits_type::compare(__data + __pos, __s, __n) == 0)
1255  return __pos;
1256  }
1257  while (__pos-- > 0);
1258  }
1259  return npos;
1260  }
1261 
1262  template<typename _CharT, typename _Traits, typename _Alloc>
1263  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1265  rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1266  {
1267  size_type __size = this->size();
1268  if (__size)
1269  {
1270  if (--__size > __pos)
1271  __size = __pos;
1272  for (++__size; __size-- > 0; )
1273  if (traits_type::eq(_M_data()[__size], __c))
1274  return __size;
1275  }
1276  return npos;
1277  }
1278 
1279  template<typename _CharT, typename _Traits, typename _Alloc>
1280  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1282  find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
1283  _GLIBCXX_NOEXCEPT
1284  {
1285  __glibcxx_requires_string_len(__s, __n);
1286  for (; __n && __pos < this->size(); ++__pos)
1287  {
1288  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
1289  if (__p)
1290  return __pos;
1291  }
1292  return npos;
1293  }
1294 
1295  template<typename _CharT, typename _Traits, typename _Alloc>
1296  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1298  find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
1299  _GLIBCXX_NOEXCEPT
1300  {
1301  __glibcxx_requires_string_len(__s, __n);
1302  size_type __size = this->size();
1303  if (__size && __n)
1304  {
1305  if (--__size > __pos)
1306  __size = __pos;
1307  do
1308  {
1309  if (traits_type::find(__s, __n, _M_data()[__size]))
1310  return __size;
1311  }
1312  while (__size-- != 0);
1313  }
1314  return npos;
1315  }
1316 
1317  template<typename _CharT, typename _Traits, typename _Alloc>
1318  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1320  find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1321  _GLIBCXX_NOEXCEPT
1322  {
1323  __glibcxx_requires_string_len(__s, __n);
1324  for (; __pos < this->size(); ++__pos)
1325  if (!traits_type::find(__s, __n, _M_data()[__pos]))
1326  return __pos;
1327  return npos;
1328  }
1329 
1330  template<typename _CharT, typename _Traits, typename _Alloc>
1331  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1333  find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1334  {
1335  for (; __pos < this->size(); ++__pos)
1336  if (!traits_type::eq(_M_data()[__pos], __c))
1337  return __pos;
1338  return npos;
1339  }
1340 
1341  template<typename _CharT, typename _Traits, typename _Alloc>
1342  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1344  find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1345  _GLIBCXX_NOEXCEPT
1346  {
1347  __glibcxx_requires_string_len(__s, __n);
1348  size_type __size = this->size();
1349  if (__size)
1350  {
1351  if (--__size > __pos)
1352  __size = __pos;
1353  do
1354  {
1355  if (!traits_type::find(__s, __n, _M_data()[__size]))
1356  return __size;
1357  }
1358  while (__size--);
1359  }
1360  return npos;
1361  }
1362 
1363  template<typename _CharT, typename _Traits, typename _Alloc>
1364  typename basic_string<_CharT, _Traits, _Alloc>::size_type
1366  find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1367  {
1368  size_type __size = this->size();
1369  if (__size)
1370  {
1371  if (--__size > __pos)
1372  __size = __pos;
1373  do
1374  {
1375  if (!traits_type::eq(_M_data()[__size], __c))
1376  return __size;
1377  }
1378  while (__size--);
1379  }
1380  return npos;
1381  }
1382 
1383  template<typename _CharT, typename _Traits, typename _Alloc>
1384  int
1386  compare(size_type __pos, size_type __n, const basic_string& __str) const
1387  {
1388  _M_check(__pos, "basic_string::compare");
1389  __n = _M_limit(__pos, __n);
1390  const size_type __osize = __str.size();
1391  const size_type __len = std::min(__n, __osize);
1392  int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
1393  if (!__r)
1394  __r = _S_compare(__n, __osize);
1395  return __r;
1396  }
1397 
1398  template<typename _CharT, typename _Traits, typename _Alloc>
1399  int
1401  compare(size_type __pos1, size_type __n1, const basic_string& __str,
1402  size_type __pos2, size_type __n2) const
1403  {
1404  _M_check(__pos1, "basic_string::compare");
1405  __str._M_check(__pos2, "basic_string::compare");
1406  __n1 = _M_limit(__pos1, __n1);
1407  __n2 = __str._M_limit(__pos2, __n2);
1408  const size_type __len = std::min(__n1, __n2);
1409  int __r = traits_type::compare(_M_data() + __pos1,
1410  __str.data() + __pos2, __len);
1411  if (!__r)
1412  __r = _S_compare(__n1, __n2);
1413  return __r;
1414  }
1415 
1416  template<typename _CharT, typename _Traits, typename _Alloc>
1417  int
1419  compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT
1420  {
1421  __glibcxx_requires_string(__s);
1422  const size_type __size = this->size();
1423  const size_type __osize = traits_type::length(__s);
1424  const size_type __len = std::min(__size, __osize);
1425  int __r = traits_type::compare(_M_data(), __s, __len);
1426  if (!__r)
1427  __r = _S_compare(__size, __osize);
1428  return __r;
1429  }
1430 
1431  template<typename _CharT, typename _Traits, typename _Alloc>
1432  int
1434  compare(size_type __pos, size_type __n1, const _CharT* __s) const
1435  {
1436  __glibcxx_requires_string(__s);
1437  _M_check(__pos, "basic_string::compare");
1438  __n1 = _M_limit(__pos, __n1);
1439  const size_type __osize = traits_type::length(__s);
1440  const size_type __len = std::min(__n1, __osize);
1441  int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1442  if (!__r)
1443  __r = _S_compare(__n1, __osize);
1444  return __r;
1445  }
1446 
1447  template<typename _CharT, typename _Traits, typename _Alloc>
1448  int
1450  compare(size_type __pos, size_type __n1, const _CharT* __s,
1451  size_type __n2) const
1452  {
1453  __glibcxx_requires_string_len(__s, __n2);
1454  _M_check(__pos, "basic_string::compare");
1455  __n1 = _M_limit(__pos, __n1);
1456  const size_type __len = std::min(__n1, __n2);
1457  int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1458  if (!__r)
1459  __r = _S_compare(__n1, __n2);
1460  return __r;
1461  }
1462 
1463  // 21.3.7.9 basic_string::getline and operators
1464  template<typename _CharT, typename _Traits, typename _Alloc>
1468  {
1469  typedef basic_istream<_CharT, _Traits> __istream_type;
1470  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1471  typedef typename __istream_type::ios_base __ios_base;
1472  typedef typename __istream_type::int_type __int_type;
1473  typedef typename __string_type::size_type __size_type;
1474  typedef ctype<_CharT> __ctype_type;
1475  typedef typename __ctype_type::ctype_base __ctype_base;
1476 
1477  __size_type __extracted = 0;
1478  typename __ios_base::iostate __err = __ios_base::goodbit;
1479  typename __istream_type::sentry __cerb(__in, false);
1480  if (__cerb)
1481  {
1482  __try
1483  {
1484  // Avoid reallocation for common case.
1485  __str.erase();
1486  _CharT __buf[128];
1487  __size_type __len = 0;
1488  const streamsize __w = __in.width();
1489  const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
1490  : __str.max_size();
1491  const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
1492  const __int_type __eof = _Traits::eof();
1493  __int_type __c = __in.rdbuf()->sgetc();
1494 
1495  while (__extracted < __n
1496  && !_Traits::eq_int_type(__c, __eof)
1497  && !__ct.is(__ctype_base::space,
1498  _Traits::to_char_type(__c)))
1499  {
1500  if (__len == sizeof(__buf) / sizeof(_CharT))
1501  {
1502  __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
1503  __len = 0;
1504  }
1505  __buf[__len++] = _Traits::to_char_type(__c);
1506  ++__extracted;
1507  __c = __in.rdbuf()->snextc();
1508  }
1509  __str.append(__buf, __len);
1510 
1511  if (_Traits::eq_int_type(__c, __eof))
1512  __err |= __ios_base::eofbit;
1513  __in.width(0);
1514  }
1515  __catch(__cxxabiv1::__forced_unwind&)
1516  {
1517  __in._M_setstate(__ios_base::badbit);
1518  __throw_exception_again;
1519  }
1520  __catch(...)
1521  {
1522  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1523  // 91. Description of operator>> and getline() for string<>
1524  // might cause endless loop
1525  __in._M_setstate(__ios_base::badbit);
1526  }
1527  }
1528  // 211. operator>>(istream&, string&) doesn't set failbit
1529  if (!__extracted)
1530  __err |= __ios_base::failbit;
1531  if (__err)
1532  __in.setstate(__err);
1533  return __in;
1534  }
1535 
1536  template<typename _CharT, typename _Traits, typename _Alloc>
1537  basic_istream<_CharT, _Traits>&
1539  basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
1540  {
1541  typedef basic_istream<_CharT, _Traits> __istream_type;
1542  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1543  typedef typename __istream_type::ios_base __ios_base;
1544  typedef typename __istream_type::int_type __int_type;
1545  typedef typename __string_type::size_type __size_type;
1546 
1547  __size_type __extracted = 0;
1548  const __size_type __n = __str.max_size();
1549  typename __ios_base::iostate __err = __ios_base::goodbit;
1550  typename __istream_type::sentry __cerb(__in, true);
1551  if (__cerb)
1552  {
1553  __try
1554  {
1555  __str.erase();
1556  const __int_type __idelim = _Traits::to_int_type(__delim);
1557  const __int_type __eof = _Traits::eof();
1558  __int_type __c = __in.rdbuf()->sgetc();
1559 
1560  while (__extracted < __n
1561  && !_Traits::eq_int_type(__c, __eof)
1562  && !_Traits::eq_int_type(__c, __idelim))
1563  {
1564  __str += _Traits::to_char_type(__c);
1565  ++__extracted;
1566  __c = __in.rdbuf()->snextc();
1567  }
1568 
1569  if (_Traits::eq_int_type(__c, __eof))
1570  __err |= __ios_base::eofbit;
1571  else if (_Traits::eq_int_type(__c, __idelim))
1572  {
1573  ++__extracted;
1574  __in.rdbuf()->sbumpc();
1575  }
1576  else
1577  __err |= __ios_base::failbit;
1578  }
1579  __catch(__cxxabiv1::__forced_unwind&)
1580  {
1581  __in._M_setstate(__ios_base::badbit);
1582  __throw_exception_again;
1583  }
1584  __catch(...)
1585  {
1586  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1587  // 91. Description of operator>> and getline() for string<>
1588  // might cause endless loop
1589  __in._M_setstate(__ios_base::badbit);
1590  }
1591  }
1592  if (!__extracted)
1593  __err |= __ios_base::failbit;
1594  if (__err)
1595  __in.setstate(__err);
1596  return __in;
1597  }
1598 
1599  // Inhibit implicit instantiations for required instantiations,
1600  // which are defined via explicit instantiations elsewhere.
1601 #if _GLIBCXX_EXTERN_TEMPLATE
1602  // The explicit instantiations definitions in src/c++11/string-inst.cc
1603  // are compiled as C++14, so the new C++17 members aren't instantiated.
1604  // Until those definitions are compiled as C++17 suppress the declaration,
1605  // so C++17 code will implicitly instantiate std::string and std::wstring
1606  // as needed.
1607 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
1608  extern template class basic_string<char>;
1609 # elif ! _GLIBCXX_USE_CXX11_ABI
1610  // Still need to prevent implicit instantiation of the COW empty rep,
1611  // to ensure the definition in libstdc++.so is unique (PR 86138).
1612  extern template basic_string<char>::size_type
1613  basic_string<char>::_Rep::_S_empty_rep_storage[];
1614 # endif
1615 
1616  extern template
1617  basic_istream<char>&
1618  operator>>(basic_istream<char>&, string&);
1619  extern template
1620  basic_ostream<char>&
1621  operator<<(basic_ostream<char>&, const string&);
1622  extern template
1623  basic_istream<char>&
1624  getline(basic_istream<char>&, string&, char);
1625  extern template
1626  basic_istream<char>&
1627  getline(basic_istream<char>&, string&);
1628 
1629 #ifdef _GLIBCXX_USE_WCHAR_T
1630 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
1631  extern template class basic_string<wchar_t>;
1632 # elif ! _GLIBCXX_USE_CXX11_ABI
1633  extern template basic_string<wchar_t>::size_type
1634  basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
1635 # endif
1636 
1637  extern template
1638  basic_istream<wchar_t>&
1639  operator>>(basic_istream<wchar_t>&, wstring&);
1640  extern template
1641  basic_ostream<wchar_t>&
1642  operator<<(basic_ostream<wchar_t>&, const wstring&);
1643  extern template
1644  basic_istream<wchar_t>&
1645  getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1646  extern template
1647  basic_istream<wchar_t>&
1648  getline(basic_istream<wchar_t>&, wstring&);
1649 #endif // _GLIBCXX_USE_WCHAR_T
1650 #endif // _GLIBCXX_EXTERN_TEMPLATE
1651 
1652 _GLIBCXX_END_NAMESPACE_VERSION
1653 } // namespace std
1654 
1655 #endif
locale getloc() const
Locale access.
Definition: ios_base.h:770
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
size_type copy(_CharT *__s, size_type __n, size_type __pos=0) const
Copy substring into C string.
static const size_type npos
Value returned by various member functions when they fail.
size_type max_size() const noexcept
Returns the size() of the largest possible string.
ISO C++ entities toplevel namespace is std.
Forward iterators support a superset of input iterator operations.
streamsize width() const
Flags access.
Definition: ios_base.h:719
ptrdiff_t streamsize
Integral type for I/O operation counts and buffer sizes.
Definition: postypes.h:98
const _CharT * data() const noexcept
Return const pointer to contents.
basic_string & append(const basic_string &__str)
Append a string to this string.
basic_string() noexcept
Default constructor creates an empty string.
Thrown as part of forced unwinding.A magic placeholder class that can be caught by reference to recog...
Definition: cxxabi_forced.h:48
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
basic_streambuf< _CharT, _Traits > * rdbuf() const
Accessing the underlying buffer.
Definition: basic_ios.h:321
Template class basic_istream.
Definition: iosfwd:83
Common iterator class.
void swap(basic_string &__s) noexcept(/*conditional */)
Swap contents with another string.
Uniform interface to all allocator types.
std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &__is, bitset< _Nb > &__x)
Global I/O operators for bitsets.
Definition: bitset:1470
initializer_list
basic_string< wchar_t > wstring
A string of wchar_t.
Definition: stringfwd.h:83
_GLIBCXX14_CONSTEXPR const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:198
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
void setstate(iostate __state)
Sets additional flags in the error state.
Definition: basic_ios.h:157
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Primary class template ctype facet.This template class defines classification and conversion function...
_GLIBCXX17_CONSTEXPR iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
Marking input iterators.
void reserve(size_type __res_arg=0)
Attempt to preallocate enough memory for specified number of characters.
basic_istream< _CharT, _Traits > & getline(basic_istream< _CharT, _Traits > &__is, basic_string< _CharT, _Traits, _Alloc > &__str, _CharT __delim)
Read a line from stream into a string.
Managing sequences of characters and character-like objects.
size_type size() const noexcept
Returns the number of characters in the string, not including any null-termination.
allocator_type get_allocator() const noexcept
Return copy of allocator used to construct this string.