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