libstdc++
basic_string.tcc
Go to the documentation of this file.
1 // Components for manipulating sequences of characters -*- C++ -*-
2 
3 // Copyright (C) 1997-2024 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  _GLIBCXX20_CONSTEXPR
58  void
60  swap(basic_string& __s) _GLIBCXX_NOEXCEPT
61  {
62  if (this == std::__addressof(__s))
63  return;
64 
65  _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
66 
67  if (_M_is_local())
68  if (__s._M_is_local())
69  {
70  if (length() && __s.length())
71  {
72  _CharT __tmp_data[_S_local_capacity + 1];
73  traits_type::copy(__tmp_data, __s._M_local_buf,
74  __s.length() + 1);
75  traits_type::copy(__s._M_local_buf, _M_local_buf,
76  length() + 1);
77  traits_type::copy(_M_local_buf, __tmp_data,
78  __s.length() + 1);
79  }
80  else if (__s.length())
81  {
82  _M_init_local_buf();
83  traits_type::copy(_M_local_buf, __s._M_local_buf,
84  __s.length() + 1);
85  _M_length(__s.length());
86  __s._M_set_length(0);
87  return;
88  }
89  else if (length())
90  {
91  __s._M_init_local_buf();
92  traits_type::copy(__s._M_local_buf, _M_local_buf,
93  length() + 1);
94  __s._M_length(length());
95  _M_set_length(0);
96  return;
97  }
98  }
99  else
100  {
101  const size_type __tmp_capacity = __s._M_allocated_capacity;
102  __s._M_init_local_buf();
103  traits_type::copy(__s._M_local_buf, _M_local_buf,
104  length() + 1);
105  _M_data(__s._M_data());
106  __s._M_data(__s._M_local_buf);
107  _M_capacity(__tmp_capacity);
108  }
109  else
110  {
111  const size_type __tmp_capacity = _M_allocated_capacity;
112  if (__s._M_is_local())
113  {
114  _M_init_local_buf();
115  traits_type::copy(_M_local_buf, __s._M_local_buf,
116  __s.length() + 1);
117  __s._M_data(_M_data());
118  _M_data(_M_local_buf);
119  }
120  else
121  {
122  pointer __tmp_ptr = _M_data();
123  _M_data(__s._M_data());
124  __s._M_data(__tmp_ptr);
125  _M_capacity(__s._M_allocated_capacity);
126  }
127  __s._M_capacity(__tmp_capacity);
128  }
129 
130  const size_type __tmp_length = length();
131  _M_length(__s.length());
132  __s._M_length(__tmp_length);
133  }
134 
135  template<typename _CharT, typename _Traits, typename _Alloc>
136  _GLIBCXX20_CONSTEXPR
137  typename basic_string<_CharT, _Traits, _Alloc>::pointer
138  basic_string<_CharT, _Traits, _Alloc>::
139  _M_create(size_type& __capacity, size_type __old_capacity)
140  {
141  // _GLIBCXX_RESOLVE_LIB_DEFECTS
142  // 83. String::npos vs. string::max_size()
143  if (__capacity > max_size())
144  std::__throw_length_error(__N("basic_string::_M_create"));
145 
146  // The below implements an exponential growth policy, necessary to
147  // meet amortized linear time requirements of the library: see
148  // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
149  if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
150  {
151  __capacity = 2 * __old_capacity;
152  // Never allocate a string bigger than max_size.
153  if (__capacity > max_size())
154  __capacity = max_size();
155  }
156 
157  // NB: Need an array of char_type[__capacity], plus a terminating
158  // null char_type() element.
159  return _S_allocate(_M_get_allocator(), __capacity + 1);
160  }
161 
162  // NB: This is the special case for Input Iterators, used in
163  // istreambuf_iterators, etc.
164  // Input Iterators have a cost structure very different from
165  // pointers, calling for a different coding style.
166  template<typename _CharT, typename _Traits, typename _Alloc>
167  template<typename _InIterator>
168  _GLIBCXX20_CONSTEXPR
169  void
170  basic_string<_CharT, _Traits, _Alloc>::
171  _M_construct(_InIterator __beg, _InIterator __end,
173  {
174  size_type __len = 0;
175  size_type __capacity = size_type(_S_local_capacity);
176 
177  _M_init_local_buf();
178 
179  while (__beg != __end && __len < __capacity)
180  {
181  _M_local_buf[__len++] = *__beg;
182  ++__beg;
183  }
184 
185  struct _Guard
186  {
187  _GLIBCXX20_CONSTEXPR
188  explicit _Guard(basic_string* __s) : _M_guarded(__s) { }
189 
190  _GLIBCXX20_CONSTEXPR
191  ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
192 
193  basic_string* _M_guarded;
194  } __guard(this);
195 
196  while (__beg != __end)
197  {
198  if (__len == __capacity)
199  {
200  // Allocate more space.
201  __capacity = __len + 1;
202  pointer __another = _M_create(__capacity, __len);
203  this->_S_copy(__another, _M_data(), __len);
204  _M_dispose();
205  _M_data(__another);
206  _M_capacity(__capacity);
207  }
208  traits_type::assign(_M_data()[__len++], *__beg);
209  ++__beg;
210  }
211 
212  __guard._M_guarded = 0;
213 
214  _M_set_length(__len);
215  }
216 
217  template<typename _CharT, typename _Traits, typename _Alloc>
218  template<typename _InIterator>
219  _GLIBCXX20_CONSTEXPR
220  void
221  basic_string<_CharT, _Traits, _Alloc>::
222  _M_construct(_InIterator __beg, _InIterator __end,
224  {
225  size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
226 
227  if (__dnew > size_type(_S_local_capacity))
228  {
229  _M_data(_M_create(__dnew, size_type(0)));
230  _M_capacity(__dnew);
231  }
232  else
233  _M_init_local_buf();
234 
235  // Check for out_of_range and length_error exceptions.
236  struct _Guard
237  {
238  _GLIBCXX20_CONSTEXPR
239  explicit _Guard(basic_string* __s) : _M_guarded(__s) { }
240 
241  _GLIBCXX20_CONSTEXPR
242  ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
243 
244  basic_string* _M_guarded;
245  } __guard(this);
246 
247  this->_S_copy_chars(_M_data(), __beg, __end);
248 
249  __guard._M_guarded = 0;
250 
251  _M_set_length(__dnew);
252  }
253 
254  template<typename _CharT, typename _Traits, typename _Alloc>
255  _GLIBCXX20_CONSTEXPR
256  void
257  basic_string<_CharT, _Traits, _Alloc>::
258  _M_construct(size_type __n, _CharT __c)
259  {
260  if (__n > size_type(_S_local_capacity))
261  {
262  _M_data(_M_create(__n, size_type(0)));
263  _M_capacity(__n);
264  }
265  else
266  _M_init_local_buf();
267 
268  if (__n)
269  this->_S_assign(_M_data(), __n, __c);
270 
271  _M_set_length(__n);
272  }
273 
274  template<typename _CharT, typename _Traits, typename _Alloc>
275  _GLIBCXX20_CONSTEXPR
276  void
277  basic_string<_CharT, _Traits, _Alloc>::
278  _M_assign(const basic_string& __str)
279  {
280  if (this != std::__addressof(__str))
281  {
282  const size_type __rsize = __str.length();
283  const size_type __capacity = capacity();
284 
285  if (__rsize > __capacity)
286  {
287  size_type __new_capacity = __rsize;
288  pointer __tmp = _M_create(__new_capacity, __capacity);
289  _M_dispose();
290  _M_data(__tmp);
291  _M_capacity(__new_capacity);
292  }
293 
294  if (__rsize)
295  this->_S_copy(_M_data(), __str._M_data(), __rsize);
296 
297  _M_set_length(__rsize);
298  }
299  }
300 
301  template<typename _CharT, typename _Traits, typename _Alloc>
302  _GLIBCXX20_CONSTEXPR
303  void
305  reserve(size_type __res)
306  {
307  const size_type __capacity = capacity();
308  // _GLIBCXX_RESOLVE_LIB_DEFECTS
309  // 2968. Inconsistencies between basic_string reserve and
310  // vector/unordered_map/unordered_set reserve functions
311  // P0966 reserve should not shrink
312  if (__res <= __capacity)
313  return;
314 
315  pointer __tmp = _M_create(__res, __capacity);
316  this->_S_copy(__tmp, _M_data(), length() + 1);
317  _M_dispose();
318  _M_data(__tmp);
319  _M_capacity(__res);
320  }
321 
322  template<typename _CharT, typename _Traits, typename _Alloc>
323  _GLIBCXX20_CONSTEXPR
324  void
325  basic_string<_CharT, _Traits, _Alloc>::
326  _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
327  size_type __len2)
328  {
329  const size_type __how_much = length() - __pos - __len1;
330 
331  size_type __new_capacity = length() + __len2 - __len1;
332  pointer __r = _M_create(__new_capacity, capacity());
333 
334  if (__pos)
335  this->_S_copy(__r, _M_data(), __pos);
336  if (__s && __len2)
337  this->_S_copy(__r + __pos, __s, __len2);
338  if (__how_much)
339  this->_S_copy(__r + __pos + __len2,
340  _M_data() + __pos + __len1, __how_much);
341 
342  _M_dispose();
343  _M_data(__r);
344  _M_capacity(__new_capacity);
345  }
346 
347  template<typename _CharT, typename _Traits, typename _Alloc>
348  _GLIBCXX20_CONSTEXPR
349  void
350  basic_string<_CharT, _Traits, _Alloc>::
351  _M_erase(size_type __pos, size_type __n)
352  {
353  const size_type __how_much = length() - __pos - __n;
354 
355  if (__how_much && __n)
356  this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
357 
358  _M_set_length(length() - __n);
359  }
360 
361  template<typename _CharT, typename _Traits, typename _Alloc>
362  _GLIBCXX20_CONSTEXPR
363  void
365  reserve()
366  {
367  if (_M_is_local())
368  return;
369 
370  const size_type __length = length();
371  const size_type __capacity = _M_allocated_capacity;
372 
373  if (__length <= size_type(_S_local_capacity))
374  {
375  _M_init_local_buf();
376  this->_S_copy(_M_local_buf, _M_data(), __length + 1);
377  _M_destroy(__capacity);
378  _M_data(_M_local_data());
379  }
380 #if __cpp_exceptions
381  else if (__length < __capacity)
382  try
383  {
384  pointer __tmp = _S_allocate(_M_get_allocator(), __length + 1);
385  this->_S_copy(__tmp, _M_data(), __length + 1);
386  _M_dispose();
387  _M_data(__tmp);
388  _M_capacity(__length);
389  }
390  catch (const __cxxabiv1::__forced_unwind&)
391  { throw; }
392  catch (...)
393  { /* swallow the exception */ }
394 #endif
395  }
396 
397  template<typename _CharT, typename _Traits, typename _Alloc>
398  _GLIBCXX20_CONSTEXPR
399  void
401  resize(size_type __n, _CharT __c)
402  {
403  const size_type __size = this->size();
404  if (__size < __n)
405  this->append(__n - __size, __c);
406  else if (__n < __size)
407  this->_M_set_length(__n);
408  }
409 
410  template<typename _CharT, typename _Traits, typename _Alloc>
411  _GLIBCXX20_CONSTEXPR
412  basic_string<_CharT, _Traits, _Alloc>&
413  basic_string<_CharT, _Traits, _Alloc>::
414  _M_append(const _CharT* __s, size_type __n)
415  {
416  const size_type __len = __n + this->size();
417 
418  if (__len <= this->capacity())
419  {
420  if (__n)
421  this->_S_copy(this->_M_data() + this->size(), __s, __n);
422  }
423  else
424  this->_M_mutate(this->size(), size_type(0), __s, __n);
425 
426  this->_M_set_length(__len);
427  return *this;
428  }
429 
430  template<typename _CharT, typename _Traits, typename _Alloc>
431  template<typename _InputIterator>
432  _GLIBCXX20_CONSTEXPR
433  basic_string<_CharT, _Traits, _Alloc>&
434  basic_string<_CharT, _Traits, _Alloc>::
435  _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
436  _InputIterator __k1, _InputIterator __k2,
437  std::__false_type)
438  {
439  // _GLIBCXX_RESOLVE_LIB_DEFECTS
440  // 2788. unintentionally require a default constructible allocator
441  const basic_string __s(__k1, __k2, this->get_allocator());
442  const size_type __n1 = __i2 - __i1;
443  return _M_replace(__i1 - begin(), __n1, __s._M_data(),
444  __s.size());
445  }
446 
447  template<typename _CharT, typename _Traits, typename _Alloc>
448  _GLIBCXX20_CONSTEXPR
449  basic_string<_CharT, _Traits, _Alloc>&
450  basic_string<_CharT, _Traits, _Alloc>::
451  _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
452  _CharT __c)
453  {
454  _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
455 
456  const size_type __old_size = this->size();
457  const size_type __new_size = __old_size + __n2 - __n1;
458 
459  if (__new_size <= this->capacity())
460  {
461  pointer __p = this->_M_data() + __pos1;
462 
463  const size_type __how_much = __old_size - __pos1 - __n1;
464  if (__how_much && __n1 != __n2)
465  this->_S_move(__p + __n2, __p + __n1, __how_much);
466  }
467  else
468  this->_M_mutate(__pos1, __n1, 0, __n2);
469 
470  if (__n2)
471  this->_S_assign(this->_M_data() + __pos1, __n2, __c);
472 
473  this->_M_set_length(__new_size);
474  return *this;
475  }
476 
477  template<typename _CharT, typename _Traits, typename _Alloc>
478  __attribute__((__noinline__, __noclone__, __cold__)) void
479  basic_string<_CharT, _Traits, _Alloc>::
480  _M_replace_cold(pointer __p, size_type __len1, const _CharT* __s,
481  const size_type __len2, const size_type __how_much)
482  {
483  // Work in-place.
484  if (__len2 && __len2 <= __len1)
485  this->_S_move(__p, __s, __len2);
486  if (__how_much && __len1 != __len2)
487  this->_S_move(__p + __len2, __p + __len1, __how_much);
488  if (__len2 > __len1)
489  {
490  if (__s + __len2 <= __p + __len1)
491  this->_S_move(__p, __s, __len2);
492  else if (__s >= __p + __len1)
493  {
494  // Hint to middle end that __p and __s overlap
495  // (PR 98465).
496  const size_type __poff = (__s - __p) + (__len2 - __len1);
497  this->_S_copy(__p, __p + __poff, __len2);
498  }
499  else
500  {
501  const size_type __nleft = (__p + __len1) - __s;
502  this->_S_move(__p, __s, __nleft);
503  this->_S_copy(__p + __nleft, __p + __len2, __len2 - __nleft);
504  }
505  }
506  }
507 
508  template<typename _CharT, typename _Traits, typename _Alloc>
509  _GLIBCXX20_CONSTEXPR
510  basic_string<_CharT, _Traits, _Alloc>&
511  basic_string<_CharT, _Traits, _Alloc>::
512  _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
513  const size_type __len2)
514  {
515  _M_check_length(__len1, __len2, "basic_string::_M_replace");
516 
517  const size_type __old_size = this->size();
518  const size_type __new_size = __old_size + __len2 - __len1;
519 
520  if (__new_size <= this->capacity())
521  {
522  pointer __p = this->_M_data() + __pos;
523 
524  const size_type __how_much = __old_size - __pos - __len1;
525 #if __cpp_lib_is_constant_evaluated
526  if (std::is_constant_evaluated())
527  {
528  auto __newp = _S_allocate(_M_get_allocator(), __new_size);
529  _S_copy(__newp, this->_M_data(), __pos);
530  _S_copy(__newp + __pos, __s, __len2);
531  _S_copy(__newp + __pos + __len2, __p + __len1, __how_much);
532  _S_copy(this->_M_data(), __newp, __new_size);
533  this->_M_get_allocator().deallocate(__newp, __new_size);
534  }
535  else
536 #endif
537  if (__builtin_expect(_M_disjunct(__s), true))
538  {
539  if (__how_much && __len1 != __len2)
540  this->_S_move(__p + __len2, __p + __len1, __how_much);
541  if (__len2)
542  this->_S_copy(__p, __s, __len2);
543  }
544  else
545  _M_replace_cold(__p, __len1, __s, __len2, __how_much);
546  }
547  else
548  this->_M_mutate(__pos, __len1, __s, __len2);
549 
550  this->_M_set_length(__new_size);
551  return *this;
552  }
553 
554  template<typename _CharT, typename _Traits, typename _Alloc>
555  _GLIBCXX20_CONSTEXPR
556  typename basic_string<_CharT, _Traits, _Alloc>::size_type
558  copy(_CharT* __s, size_type __n, size_type __pos) const
559  {
560  _M_check(__pos, "basic_string::copy");
561  __n = _M_limit(__pos, __n);
562  __glibcxx_requires_string_len(__s, __n);
563  if (__n)
564  _S_copy(__s, _M_data() + __pos, __n);
565  // 21.3.5.7 par 3: do not append null. (good.)
566  return __n;
567  }
568 
569 #ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
570  template<typename _CharT, typename _Traits, typename _Alloc>
571  template<typename _Operation>
572  [[__gnu__::__always_inline__]]
573  constexpr void
575  __resize_and_overwrite(const size_type __n, _Operation __op)
576  { resize_and_overwrite<_Operation&>(__n, __op); }
577 #endif
578 
579 #if __cplusplus >= 201103L
580  template<typename _CharT, typename _Traits, typename _Alloc>
581  template<typename _Operation>
582  _GLIBCXX20_CONSTEXPR void
583  basic_string<_CharT, _Traits, _Alloc>::
584 #ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
585  resize_and_overwrite(const size_type __n, _Operation __op)
586 #else
587  __resize_and_overwrite(const size_type __n, _Operation __op)
588 #endif
589  {
590  reserve(__n);
591  _CharT* const __p = _M_data();
592 #if __cpp_lib_is_constant_evaluated
593  if (std::__is_constant_evaluated() && __n > size())
594  traits_type::assign(__p + size(), __n - size(), _CharT());
595 #endif
596  struct _Terminator {
597  _GLIBCXX20_CONSTEXPR ~_Terminator() { _M_this->_M_set_length(_M_r); }
598  basic_string* _M_this;
599  size_type _M_r;
600  };
601  _Terminator __term{this, 0};
602  auto __r = std::move(__op)(__p + 0, __n + 0);
603 #ifdef __cpp_lib_concepts
604  static_assert(ranges::__detail::__is_integer_like<decltype(__r)>);
605 #else
606  static_assert(__gnu_cxx::__is_integer_nonstrict<decltype(__r)>::__value,
607  "resize_and_overwrite operation must return an integer");
608 #endif
609  _GLIBCXX_DEBUG_ASSERT(__r >= 0 && __r <= __n);
610  __term._M_r = size_type(__r);
611  if (__term._M_r > __n)
612  __builtin_unreachable();
613  }
614 #endif // C++11
615 
616 #endif // _GLIBCXX_USE_CXX11_ABI
617 
618 #if __glibcxx_constexpr_string >= 201907L
619 # define _GLIBCXX_STRING_CONSTEXPR constexpr
620 #else
621 # define _GLIBCXX_STRING_CONSTEXPR
622 #endif
623  template<typename _CharT, typename _Traits, typename _Alloc>
624  _GLIBCXX_STRING_CONSTEXPR
625  typename basic_string<_CharT, _Traits, _Alloc>::size_type
627  find(const _CharT* __s, size_type __pos, size_type __n) const
628  _GLIBCXX_NOEXCEPT
629  {
630  __glibcxx_requires_string_len(__s, __n);
631  const size_type __size = this->size();
632 
633  if (__n == 0)
634  return __pos <= __size ? __pos : npos;
635  if (__pos >= __size)
636  return npos;
637 
638  const _CharT __elem0 = __s[0];
639  const _CharT* const __data = data();
640  const _CharT* __first = __data + __pos;
641  const _CharT* const __last = __data + __size;
642  size_type __len = __size - __pos;
643 
644  while (__len >= __n)
645  {
646  // Find the first occurrence of __elem0:
647  __first = traits_type::find(__first, __len - __n + 1, __elem0);
648  if (!__first)
649  return npos;
650  // Compare the full strings from the first occurrence of __elem0.
651  // We already know that __first[0] == __s[0] but compare them again
652  // anyway because __s is probably aligned, which helps memcmp.
653  if (traits_type::compare(__first, __s, __n) == 0)
654  return __first - __data;
655  __len = __last - ++__first;
656  }
657  return npos;
658  }
659 
660  template<typename _CharT, typename _Traits, typename _Alloc>
661  _GLIBCXX_STRING_CONSTEXPR
662  typename basic_string<_CharT, _Traits, _Alloc>::size_type
664  find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
665  {
666  size_type __ret = npos;
667  const size_type __size = this->size();
668  if (__pos < __size)
669  {
670  const _CharT* __data = _M_data();
671  const size_type __n = __size - __pos;
672  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
673  if (__p)
674  __ret = __p - __data;
675  }
676  return __ret;
677  }
678 
679  template<typename _CharT, typename _Traits, typename _Alloc>
680  _GLIBCXX_STRING_CONSTEXPR
681  typename basic_string<_CharT, _Traits, _Alloc>::size_type
683  rfind(const _CharT* __s, size_type __pos, size_type __n) const
684  _GLIBCXX_NOEXCEPT
685  {
686  __glibcxx_requires_string_len(__s, __n);
687  const size_type __size = this->size();
688  if (__n <= __size)
689  {
690  __pos = std::min(size_type(__size - __n), __pos);
691  const _CharT* __data = _M_data();
692  do
693  {
694  if (traits_type::compare(__data + __pos, __s, __n) == 0)
695  return __pos;
696  }
697  while (__pos-- > 0);
698  }
699  return npos;
700  }
701 
702  template<typename _CharT, typename _Traits, typename _Alloc>
703  _GLIBCXX_STRING_CONSTEXPR
704  typename basic_string<_CharT, _Traits, _Alloc>::size_type
706  rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
707  {
708  size_type __size = this->size();
709  if (__size)
710  {
711  if (--__size > __pos)
712  __size = __pos;
713  for (++__size; __size-- > 0; )
714  if (traits_type::eq(_M_data()[__size], __c))
715  return __size;
716  }
717  return npos;
718  }
719 
720  template<typename _CharT, typename _Traits, typename _Alloc>
721  _GLIBCXX_STRING_CONSTEXPR
722  typename basic_string<_CharT, _Traits, _Alloc>::size_type
724  find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
725  _GLIBCXX_NOEXCEPT
726  {
727  __glibcxx_requires_string_len(__s, __n);
728  for (; __n && __pos < this->size(); ++__pos)
729  {
730  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
731  if (__p)
732  return __pos;
733  }
734  return npos;
735  }
736 
737  template<typename _CharT, typename _Traits, typename _Alloc>
738  _GLIBCXX_STRING_CONSTEXPR
739  typename basic_string<_CharT, _Traits, _Alloc>::size_type
741  find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
742  _GLIBCXX_NOEXCEPT
743  {
744  __glibcxx_requires_string_len(__s, __n);
745  size_type __size = this->size();
746  if (__size && __n)
747  {
748  if (--__size > __pos)
749  __size = __pos;
750  do
751  {
752  if (traits_type::find(__s, __n, _M_data()[__size]))
753  return __size;
754  }
755  while (__size-- != 0);
756  }
757  return npos;
758  }
759 
760  template<typename _CharT, typename _Traits, typename _Alloc>
761  _GLIBCXX_STRING_CONSTEXPR
762  typename basic_string<_CharT, _Traits, _Alloc>::size_type
764  find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
765  _GLIBCXX_NOEXCEPT
766  {
767  __glibcxx_requires_string_len(__s, __n);
768  for (; __pos < this->size(); ++__pos)
769  if (!traits_type::find(__s, __n, _M_data()[__pos]))
770  return __pos;
771  return npos;
772  }
773 
774  template<typename _CharT, typename _Traits, typename _Alloc>
775  _GLIBCXX_STRING_CONSTEXPR
776  typename basic_string<_CharT, _Traits, _Alloc>::size_type
778  find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
779  {
780  for (; __pos < this->size(); ++__pos)
781  if (!traits_type::eq(_M_data()[__pos], __c))
782  return __pos;
783  return npos;
784  }
785 
786  template<typename _CharT, typename _Traits, typename _Alloc>
787  _GLIBCXX_STRING_CONSTEXPR
788  typename basic_string<_CharT, _Traits, _Alloc>::size_type
790  find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
791  _GLIBCXX_NOEXCEPT
792  {
793  __glibcxx_requires_string_len(__s, __n);
794  size_type __size = this->size();
795  if (__size)
796  {
797  if (--__size > __pos)
798  __size = __pos;
799  do
800  {
801  if (!traits_type::find(__s, __n, _M_data()[__size]))
802  return __size;
803  }
804  while (__size--);
805  }
806  return npos;
807  }
808 
809  template<typename _CharT, typename _Traits, typename _Alloc>
810  _GLIBCXX_STRING_CONSTEXPR
811  typename basic_string<_CharT, _Traits, _Alloc>::size_type
813  find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
814  {
815  size_type __size = this->size();
816  if (__size)
817  {
818  if (--__size > __pos)
819  __size = __pos;
820  do
821  {
822  if (!traits_type::eq(_M_data()[__size], __c))
823  return __size;
824  }
825  while (__size--);
826  }
827  return npos;
828  }
829 
830 #undef _GLIBCXX_STRING_CONSTEXPR
831 
832  // 21.3.7.9 basic_string::getline and operators
833  template<typename _CharT, typename _Traits, typename _Alloc>
837  {
838  typedef basic_istream<_CharT, _Traits> __istream_type;
839  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
840  typedef typename __istream_type::ios_base __ios_base;
841  typedef typename __istream_type::int_type __int_type;
842  typedef typename __string_type::size_type __size_type;
843  typedef ctype<_CharT> __ctype_type;
844  typedef typename __ctype_type::ctype_base __ctype_base;
845 
846  __size_type __extracted = 0;
847  typename __ios_base::iostate __err = __ios_base::goodbit;
848  typename __istream_type::sentry __cerb(__in, false);
849  if (__cerb)
850  {
851  __try
852  {
853  // Avoid reallocation for common case.
854  __str.erase();
855  _CharT __buf[128];
856  __size_type __len = 0;
857  const streamsize __w = __in.width();
858  const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
859  : __str.max_size();
860  const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
861  const __int_type __eof = _Traits::eof();
862  __int_type __c = __in.rdbuf()->sgetc();
863 
864  while (__extracted < __n
865  && !_Traits::eq_int_type(__c, __eof)
866  && !__ct.is(__ctype_base::space,
867  _Traits::to_char_type(__c)))
868  {
869  if (__len == sizeof(__buf) / sizeof(_CharT))
870  {
871  __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
872  __len = 0;
873  }
874  __buf[__len++] = _Traits::to_char_type(__c);
875  ++__extracted;
876  __c = __in.rdbuf()->snextc();
877  }
878  __str.append(__buf, __len);
879 
880  if (__extracted < __n && _Traits::eq_int_type(__c, __eof))
881  __err |= __ios_base::eofbit;
882  __in.width(0);
883  }
885  {
886  __in._M_setstate(__ios_base::badbit);
887  __throw_exception_again;
888  }
889  __catch(...)
890  {
891  // _GLIBCXX_RESOLVE_LIB_DEFECTS
892  // 91. Description of operator>> and getline() for string<>
893  // might cause endless loop
894  __in._M_setstate(__ios_base::badbit);
895  }
896  }
897  // 211. operator>>(istream&, string&) doesn't set failbit
898  if (!__extracted)
899  __err |= __ios_base::failbit;
900  if (__err)
901  __in.setstate(__err);
902  return __in;
903  }
904 
905  template<typename _CharT, typename _Traits, typename _Alloc>
906  basic_istream<_CharT, _Traits>&
908  basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
909  {
910  typedef basic_istream<_CharT, _Traits> __istream_type;
911  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
912  typedef typename __istream_type::ios_base __ios_base;
913  typedef typename __istream_type::int_type __int_type;
914  typedef typename __string_type::size_type __size_type;
915 
916  __size_type __extracted = 0;
917  const __size_type __n = __str.max_size();
918  typename __ios_base::iostate __err = __ios_base::goodbit;
919  typename __istream_type::sentry __cerb(__in, true);
920  if (__cerb)
921  {
922  __try
923  {
924  __str.erase();
925  const __int_type __idelim = _Traits::to_int_type(__delim);
926  const __int_type __eof = _Traits::eof();
927  __int_type __c = __in.rdbuf()->sgetc();
928 
929  while (__extracted < __n
930  && !_Traits::eq_int_type(__c, __eof)
931  && !_Traits::eq_int_type(__c, __idelim))
932  {
933  __str += _Traits::to_char_type(__c);
934  ++__extracted;
935  __c = __in.rdbuf()->snextc();
936  }
937 
938  if (_Traits::eq_int_type(__c, __eof))
939  __err |= __ios_base::eofbit;
940  else if (_Traits::eq_int_type(__c, __idelim))
941  {
942  ++__extracted;
943  __in.rdbuf()->sbumpc();
944  }
945  else
946  __err |= __ios_base::failbit;
947  }
949  {
950  __in._M_setstate(__ios_base::badbit);
951  __throw_exception_again;
952  }
953  __catch(...)
954  {
955  // _GLIBCXX_RESOLVE_LIB_DEFECTS
956  // 91. Description of operator>> and getline() for string<>
957  // might cause endless loop
958  __in._M_setstate(__ios_base::badbit);
959  }
960  }
961  if (!__extracted)
962  __err |= __ios_base::failbit;
963  if (__err)
964  __in.setstate(__err);
965  return __in;
966  }
967 
968  // Inhibit implicit instantiations for required instantiations,
969  // which are defined via explicit instantiations elsewhere.
970 #if _GLIBCXX_EXTERN_TEMPLATE
971  // The explicit instantiation definitions in src/c++11/string-inst.cc and
972  // src/c++17/string-inst.cc only instantiate the members required for C++17
973  // and earlier standards (so not C++20's starts_with and ends_with).
974  // Suppress the explicit instantiation declarations for C++20, so C++20
975  // code will implicitly instantiate std::string and std::wstring as needed.
976 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
977  extern template class basic_string<char>;
978 # elif ! _GLIBCXX_USE_CXX11_ABI
979  // Still need to prevent implicit instantiation of the COW empty rep,
980  // to ensure the definition in libstdc++.so is unique (PR 86138).
981  extern template basic_string<char>::size_type
982  basic_string<char>::_Rep::_S_empty_rep_storage[];
983 # elif _GLIBCXX_EXTERN_TEMPLATE > 0
984  // Export _M_replace_cold even for C++20.
985  extern template void
986  basic_string<char>::_M_replace_cold(char *, size_type, const char*,
987  const size_type, const size_type);
988 # endif
989 
990  extern template
991  basic_istream<char>&
992  operator>>(basic_istream<char>&, string&);
993  extern template
994  basic_ostream<char>&
995  operator<<(basic_ostream<char>&, const string&);
996  extern template
997  basic_istream<char>&
998  getline(basic_istream<char>&, string&, char);
999  extern template
1000  basic_istream<char>&
1001  getline(basic_istream<char>&, string&);
1002 
1003 #ifdef _GLIBCXX_USE_WCHAR_T
1004 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
1005  extern template class basic_string<wchar_t>;
1006 # elif ! _GLIBCXX_USE_CXX11_ABI
1007  extern template basic_string<wchar_t>::size_type
1008  basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
1009 # elif _GLIBCXX_EXTERN_TEMPLATE > 0
1010  // Export _M_replace_cold even for C++20.
1011  extern template void
1012  basic_string<wchar_t>::_M_replace_cold(wchar_t*, size_type, const wchar_t*,
1013  const size_type, const size_type);
1014 # endif
1015 
1016  extern template
1017  basic_istream<wchar_t>&
1018  operator>>(basic_istream<wchar_t>&, wstring&);
1019  extern template
1020  basic_ostream<wchar_t>&
1021  operator<<(basic_ostream<wchar_t>&, const wstring&);
1022  extern template
1023  basic_istream<wchar_t>&
1024  getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1025  extern template
1026  basic_istream<wchar_t>&
1027  getline(basic_istream<wchar_t>&, wstring&);
1028 #endif // _GLIBCXX_USE_WCHAR_T
1029 #endif // _GLIBCXX_EXTERN_TEMPLATE
1030 
1031 _GLIBCXX_END_NAMESPACE_VERSION
1032 } // namespace std
1033 
1034 #endif
constexpr _Tp * __addressof(_Tp &__r) noexcept
Same as C++11 std::addressof.
Definition: move.h:51
constexpr std::remove_reference< _Tp >::type && move(_Tp &&__t) noexcept
Convert a value to an rvalue.
Definition: move.h:126
_Tp * begin(valarray< _Tp > &__va) noexcept
Return an iterator pointing to the first element of the valarray.
Definition: valarray:1227
constexpr const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:233
basic_string< wchar_t > wstring
A string of wchar_t.
Definition: stringfwd.h:80
ISO C++ entities toplevel namespace is std.
std::basic_istream< _CharT, _Traits > & operator>>(std::basic_istream< _CharT, _Traits > &__is, bitset< _Nb > &__x)
Global I/O operators for bitsets.
Definition: bitset:1597
ptrdiff_t streamsize
Integral type for I/O operation counts and buffer sizes.
Definition: postypes.h:68
constexpr iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
std::basic_ostream< _CharT, _Traits > & operator<<(std::basic_ostream< _CharT, _Traits > &__os, const bitset< _Nb > &__x)
Global I/O operators for bitsets.
Definition: bitset:1687
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.
constexpr auto size(const _Container &__cont) noexcept(noexcept(__cont.size())) -> decltype(__cont.size())
Return the size of a container.
Definition: range_access.h:262
constexpr auto data(_Container &__cont) noexcept(noexcept(__cont.data())) -> decltype(__cont.data())
Return the data pointer of a container.
Definition: range_access.h:312
basic_streambuf< _CharT, _Traits > * rdbuf() const
Accessing the underlying buffer.
Definition: basic_ios.h:325
void setstate(iostate __state)
Sets additional flags in the error state.
Definition: basic_ios.h:161
Template class basic_istream.
Definition: istream:61
Managing sequences of characters and character-like objects.
Definition: cow_string.h:109
void swap(basic_string &__s) noexcept(/*conditional */)
Swap contents with another string.
Definition: cow_string.h:3547
size_type find_first_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character of string.
Definition: cow_string.h:2454
void __resize_and_overwrite(size_type __n, _Operation __op)
Non-standard version of resize_and_overwrite for C++11 and above.
size_type find(const _CharT *__s, size_type __pos, size_type __n) const noexcept
Find position of a C substring.
size_type find_last_not_of(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a character not in string.
Definition: cow_string.h:2703
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.
Definition: cow_string.h:2621
size_type copy(_CharT *__s, size_type __n, size_type __pos=0) const
Copy substring into C string.
Definition: cow_string.h:3743
size_type find_last_of(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a character of string.
Definition: cow_string.h:2538
size_type rfind(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a string.
Definition: cow_string.h:2375
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
Definition: cow_string.h:3669
void reserve()
Equivalent to shrink_to_fit().
Definition: cow_string.h:3722
basic_string & append(const basic_string &__str)
Append a string to this string.
Definition: cow_string.h:3341
static const size_type npos
Value returned by various member functions when they fail.
Definition: cow_string.h:322
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
Definition: cow_string.h:1752
size_type max_size() const noexcept
Returns the size() of the largest possible string.
Definition: cow_string.h:925
Thrown as part of forced unwinding.
Definition: cxxabi_forced.h:49
streamsize width() const
Flags access.
Definition: ios_base.h:775
locale getloc() const
Locale access.
Definition: ios_base.h:826
Primary class template ctype facet.
Marking input iterators.
Forward iterators support a superset of input iterator operations.