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