Daily bump.
[official-gcc.git] / libstdc++-v3 / include / bits / basic_string.tcc
blobcaeddaf2f5be35caa131298e8c00a345fe5de850
1 // Components for manipulating sequences of characters -*- C++ -*-
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.
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.
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.
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/>.
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  */
31 // ISO C++ 14882: 21  Strings library
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.
39 #ifndef _BASIC_STRING_TCC
40 #define _BASIC_STRING_TCC 1
42 #ifdef _GLIBCXX_SYSHDR
43 #pragma GCC system_header
44 #endif
46 #pragma GCC diagnostic push
47 #pragma GCC diagnostic ignored "-Wc++11-extensions"
49 #include <bits/cxxabi_forced.h>
51 namespace std _GLIBCXX_VISIBILITY(default)
53 _GLIBCXX_BEGIN_NAMESPACE_VERSION
55 #if _GLIBCXX_USE_CXX11_ABI
57   template<typename _CharT, typename _Traits, typename _Alloc>
58     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
59     basic_string<_CharT, _Traits, _Alloc>::npos;
61   template<typename _CharT, typename _Traits, typename _Alloc>
62     _GLIBCXX20_CONSTEXPR
63     void
64     basic_string<_CharT, _Traits, _Alloc>::
65     swap(basic_string& __s) _GLIBCXX_NOEXCEPT
66     {
67       if (this == std::__addressof(__s))
68         return;
70       _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
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         }
135       const size_type __tmp_length = length();
136       _M_length(__s.length());
137       __s._M_length(__tmp_length);
138     }
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"));
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         }
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     }
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,
177                    std::input_iterator_tag)
178       {
179         size_type __len = 0;
180         size_type __capacity = size_type(_S_local_capacity);
182         _M_init_local_buf();
184         while (__beg != __end && __len < __capacity)
185           {
186             _M_local_buf[__len++] = *__beg;
187             ++__beg;
188           }
190         struct _Guard
191         {
192           _GLIBCXX20_CONSTEXPR
193           explicit _Guard(basic_string* __s) : _M_guarded(__s) { }
195           _GLIBCXX20_CONSTEXPR
196           ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
198           basic_string* _M_guarded;
199         } __guard(this);
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           }
217         __guard._M_guarded = 0;
219         _M_set_length(__len);
220       }
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,
228                    std::forward_iterator_tag)
229       {
230         size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
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();
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) { }
246           _GLIBCXX20_CONSTEXPR
247           ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); }
249           basic_string* _M_guarded;
250         } __guard(this);
252         this->_S_copy_chars(_M_data(), __beg, __end);
254         __guard._M_guarded = 0;
256         _M_set_length(__dnew);
257       }
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();
273       if (__n)
274         this->_S_assign(_M_data(), __n, __c);
276       _M_set_length(__n);
277     }
279   template<typename _CharT, typename _Traits, typename _Alloc>
280     _GLIBCXX20_CONSTEXPR
281     void
282     basic_string<_CharT, _Traits, _Alloc>::
283     _M_assign(const basic_string& __str)
284     {
285       if (this != std::__addressof(__str))
286         {
287           const size_type __rsize = __str.length();
288           const size_type __capacity = capacity();
290           if (__rsize > __capacity)
291             {
292               size_type __new_capacity = __rsize;
293               pointer __tmp = _M_create(__new_capacity, __capacity);
294               _M_dispose();
295               _M_data(__tmp);
296               _M_capacity(__new_capacity);
297             }
299           if (__rsize)
300             this->_S_copy(_M_data(), __str._M_data(), __rsize);
302           _M_set_length(__rsize);
303         }
304     }
306   template<typename _CharT, typename _Traits, typename _Alloc>
307     _GLIBCXX20_CONSTEXPR
308     void
309     basic_string<_CharT, _Traits, _Alloc>::
310     reserve(size_type __res)
311     {
312       const size_type __capacity = capacity();
313       // _GLIBCXX_RESOLVE_LIB_DEFECTS
314       // 2968. Inconsistencies between basic_string reserve and
315       // vector/unordered_map/unordered_set reserve functions
316       // P0966 reserve should not shrink
317       if (__res <= __capacity)
318         return;
320       pointer __tmp = _M_create(__res, __capacity);
321       this->_S_copy(__tmp, _M_data(), length() + 1);
322       _M_dispose();
323       _M_data(__tmp);
324       _M_capacity(__res);
325     }
327   template<typename _CharT, typename _Traits, typename _Alloc>
328     _GLIBCXX20_CONSTEXPR
329     void
330     basic_string<_CharT, _Traits, _Alloc>::
331     _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
332               size_type __len2)
333     {
334       const size_type __how_much = length() - __pos - __len1;
336       size_type __new_capacity = length() + __len2 - __len1;
337       pointer __r = _M_create(__new_capacity, capacity());
339       if (__pos)
340         this->_S_copy(__r, _M_data(), __pos);
341       if (__s && __len2)
342         this->_S_copy(__r + __pos, __s, __len2);
343       if (__how_much)
344         this->_S_copy(__r + __pos + __len2,
345                       _M_data() + __pos + __len1, __how_much);
347       _M_dispose();
348       _M_data(__r);
349       _M_capacity(__new_capacity);
350     }
352   template<typename _CharT, typename _Traits, typename _Alloc>
353     _GLIBCXX20_CONSTEXPR
354     void
355     basic_string<_CharT, _Traits, _Alloc>::
356     _M_erase(size_type __pos, size_type __n)
357     {
358       const size_type __how_much = length() - __pos - __n;
360       if (__how_much && __n)
361         this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
363       _M_set_length(length() - __n);
364     }
366   template<typename _CharT, typename _Traits, typename _Alloc>
367     _GLIBCXX20_CONSTEXPR
368     void
369     basic_string<_CharT, _Traits, _Alloc>::
370     reserve()
371     {
372       if (_M_is_local())
373         return;
375       const size_type __length = length();
376       const size_type __capacity = _M_allocated_capacity;
378       if (__length <= size_type(_S_local_capacity))
379         {
380           _M_init_local_buf();
381           this->_S_copy(_M_local_buf, _M_data(), __length + 1);
382           _M_destroy(__capacity);
383           _M_data(_M_local_data());
384         }
385 #if __cpp_exceptions
386       else if (__length < __capacity)
387         try
388           {
389             pointer __tmp = _S_allocate(_M_get_allocator(), __length + 1);
390             this->_S_copy(__tmp, _M_data(), __length + 1);
391             _M_dispose();
392             _M_data(__tmp);
393             _M_capacity(__length);
394           }
395         catch (const __cxxabiv1::__forced_unwind&)
396           { throw; }
397         catch (...)
398           { /* swallow the exception */ }
399 #endif
400     }
402   template<typename _CharT, typename _Traits, typename _Alloc>
403     _GLIBCXX20_CONSTEXPR
404     void
405     basic_string<_CharT, _Traits, _Alloc>::
406     resize(size_type __n, _CharT __c)
407     {
408       const size_type __size = this->size();
409       if (__size < __n)
410         this->append(__n - __size, __c);
411       else if (__n < __size)
412         this->_M_set_length(__n);
413     }
415   template<typename _CharT, typename _Traits, typename _Alloc>
416     _GLIBCXX20_CONSTEXPR
417     basic_string<_CharT, _Traits, _Alloc>&
418     basic_string<_CharT, _Traits, _Alloc>::
419     _M_append(const _CharT* __s, size_type __n)
420     {
421       const size_type __len = __n + this->size();
423       if (__len <= this->capacity())
424         {
425           if (__n)
426             this->_S_copy(this->_M_data() + this->size(), __s, __n);
427         }
428       else
429         this->_M_mutate(this->size(), size_type(0), __s, __n);
431       this->_M_set_length(__len);
432       return *this;
433     }
435   template<typename _CharT, typename _Traits, typename _Alloc>
436     template<typename _InputIterator>
437       _GLIBCXX20_CONSTEXPR
438       basic_string<_CharT, _Traits, _Alloc>&
439       basic_string<_CharT, _Traits, _Alloc>::
440       _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
441                           _InputIterator __k1, _InputIterator __k2,
442                           std::__false_type)
443       {
444         // _GLIBCXX_RESOLVE_LIB_DEFECTS
445         // 2788. unintentionally require a default constructible allocator
446         const basic_string __s(__k1, __k2, this->get_allocator());
447         const size_type __n1 = __i2 - __i1;
448         return _M_replace(__i1 - begin(), __n1, __s._M_data(),
449                           __s.size());
450       }
452   template<typename _CharT, typename _Traits, typename _Alloc>
453     _GLIBCXX20_CONSTEXPR
454     basic_string<_CharT, _Traits, _Alloc>&
455     basic_string<_CharT, _Traits, _Alloc>::
456     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
457                    _CharT __c)
458     {
459       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
461       const size_type __old_size = this->size();
462       const size_type __new_size = __old_size + __n2 - __n1;
464       if (__new_size <= this->capacity())
465         {
466           pointer __p = this->_M_data() + __pos1;
468           const size_type __how_much = __old_size - __pos1 - __n1;
469           if (__how_much && __n1 != __n2)
470             this->_S_move(__p + __n2, __p + __n1, __how_much);
471         }
472       else
473         this->_M_mutate(__pos1, __n1, 0, __n2);
475       if (__n2)
476         this->_S_assign(this->_M_data() + __pos1, __n2, __c);
478       this->_M_set_length(__new_size);
479       return *this;
480     }
482   template<typename _CharT, typename _Traits, typename _Alloc>
483     __attribute__((__noinline__, __noclone__, __cold__)) void
484     basic_string<_CharT, _Traits, _Alloc>::
485     _M_replace_cold(pointer __p, size_type __len1, const _CharT* __s,
486                     const size_type __len2, const size_type __how_much)
487     {
488       // Work in-place.
489       if (__len2 && __len2 <= __len1)
490         this->_S_move(__p, __s, __len2);
491       if (__how_much && __len1 != __len2)
492         this->_S_move(__p + __len2, __p + __len1, __how_much);
493       if (__len2 > __len1)
494         {
495           if (__s + __len2 <= __p + __len1)
496             this->_S_move(__p, __s, __len2);
497           else if (__s >= __p + __len1)
498             {
499               // Hint to middle end that __p and __s overlap
500               // (PR 98465).
501               const size_type __poff = (__s - __p) + (__len2 - __len1);
502               this->_S_copy(__p, __p + __poff, __len2);
503             }
504           else
505             {
506               const size_type __nleft = (__p + __len1) - __s;
507               this->_S_move(__p, __s, __nleft);
508               this->_S_copy(__p + __nleft, __p + __len2, __len2 - __nleft);
509             }
510         }
511     }
513   template<typename _CharT, typename _Traits, typename _Alloc>
514     _GLIBCXX20_CONSTEXPR
515     basic_string<_CharT, _Traits, _Alloc>&
516     basic_string<_CharT, _Traits, _Alloc>::
517     _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
518                const size_type __len2)
519     {
520       _M_check_length(__len1, __len2, "basic_string::_M_replace");
522       const size_type __old_size = this->size();
523       const size_type __new_size = __old_size + __len2 - __len1;
525       if (__new_size <= this->capacity())
526         {
527           pointer __p = this->_M_data() + __pos;
529           const size_type __how_much = __old_size - __pos - __len1;
530 #if __cpp_lib_is_constant_evaluated
531           if (std::is_constant_evaluated())
532             {
533               auto __newp = _S_allocate(_M_get_allocator(), __new_size);
534               _S_copy(__newp, this->_M_data(), __pos);
535               _S_copy(__newp + __pos, __s, __len2);
536               _S_copy(__newp + __pos + __len2, __p + __len1, __how_much);
537               _S_copy(this->_M_data(), __newp, __new_size);
538               this->_M_get_allocator().deallocate(__newp, __new_size);
539             }
540           else
541 #endif
542           if (__builtin_expect(_M_disjunct(__s), true))
543             {
544               if (__how_much && __len1 != __len2)
545                 this->_S_move(__p + __len2, __p + __len1, __how_much);
546               if (__len2)
547                 this->_S_copy(__p, __s, __len2);
548             }
549           else
550             _M_replace_cold(__p, __len1, __s, __len2, __how_much);
551         }
552       else
553         this->_M_mutate(__pos, __len1, __s, __len2);
555       this->_M_set_length(__new_size);
556       return *this;
557     }
559   template<typename _CharT, typename _Traits, typename _Alloc>
560     _GLIBCXX20_CONSTEXPR
561     typename basic_string<_CharT, _Traits, _Alloc>::size_type
562     basic_string<_CharT, _Traits, _Alloc>::
563     copy(_CharT* __s, size_type __n, size_type __pos) const
564     {
565       _M_check(__pos, "basic_string::copy");
566       __n = _M_limit(__pos, __n);
567       __glibcxx_requires_string_len(__s, __n);
568       if (__n)
569         _S_copy(__s, _M_data() + __pos, __n);
570       // 21.3.5.7 par 3: do not append null.  (good.)
571       return __n;
572     }
574 #ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
575   template<typename _CharT, typename _Traits, typename _Alloc>
576   template<typename _Operation>
577     [[__gnu__::__always_inline__]]
578     constexpr void
579     basic_string<_CharT, _Traits, _Alloc>::
580     __resize_and_overwrite(const size_type __n, _Operation __op)
581     { resize_and_overwrite<_Operation&>(__n, __op); }
582 #endif
584 #if __cplusplus >= 201103L
585   template<typename _CharT, typename _Traits, typename _Alloc>
586   template<typename _Operation>
587     _GLIBCXX20_CONSTEXPR void
588     basic_string<_CharT, _Traits, _Alloc>::
589 #ifdef __glibcxx_string_resize_and_overwrite // C++ >= 23
590     resize_and_overwrite(const size_type __n, _Operation __op)
591 #else
592     __resize_and_overwrite(const size_type __n, _Operation __op)
593 #endif
594     {
595       reserve(__n);
596       _CharT* const __p = _M_data();
597 #if __cpp_lib_is_constant_evaluated
598       if (std::__is_constant_evaluated() && __n > size())
599         traits_type::assign(__p + size(), __n - size(), _CharT());
600 #endif
601       struct _Terminator {
602         _GLIBCXX20_CONSTEXPR ~_Terminator() { _M_this->_M_set_length(_M_r); }
603         basic_string* _M_this;
604         size_type _M_r;
605       };
606       _Terminator __term{this, 0};
607       auto __r = std::move(__op)(__p + 0, __n + 0);
608 #ifdef __cpp_lib_concepts
609       static_assert(ranges::__detail::__is_integer_like<decltype(__r)>);
610 #else
611       static_assert(__gnu_cxx::__is_integer_nonstrict<decltype(__r)>::__value,
612                     "resize_and_overwrite operation must return an integer");
613 #endif
614       _GLIBCXX_DEBUG_ASSERT(__r >= 0 && size_type(__r) <= __n);
615       __term._M_r = size_type(__r);
616       if (__term._M_r > __n)
617         __builtin_unreachable();
618     }
619 #endif // C++11
621 #endif  // _GLIBCXX_USE_CXX11_ABI
622    
623 #if __glibcxx_constexpr_string >= 201907L
624 # define _GLIBCXX_STRING_CONSTEXPR constexpr
625 #else
626 # define _GLIBCXX_STRING_CONSTEXPR
627 #endif
628   template<typename _CharT, typename _Traits, typename _Alloc>
629     _GLIBCXX_STRING_CONSTEXPR
630     typename basic_string<_CharT, _Traits, _Alloc>::size_type
631     basic_string<_CharT, _Traits, _Alloc>::
632     find(const _CharT* __s, size_type __pos, size_type __n) const
633     _GLIBCXX_NOEXCEPT
634     {
635       __glibcxx_requires_string_len(__s, __n);
636       const size_type __size = this->size();
638       if (__n == 0)
639         return __pos <= __size ? __pos : npos;
640       if (__pos >= __size)
641         return npos;
643       const _CharT __elem0 = __s[0];
644       const _CharT* const __data = data();
645       const _CharT* __first = __data + __pos;
646       const _CharT* const __last = __data + __size;
647       size_type __len = __size - __pos;
649       while (__len >= __n)
650         {
651           // Find the first occurrence of __elem0:
652           __first = traits_type::find(__first, __len - __n + 1, __elem0);
653           if (!__first)
654             return npos;
655           // Compare the full strings from the first occurrence of __elem0.
656           // We already know that __first[0] == __s[0] but compare them again
657           // anyway because __s is probably aligned, which helps memcmp.
658           if (traits_type::compare(__first, __s, __n) == 0)
659             return __first - __data;
660           __len = __last - ++__first;
661         }
662       return npos;
663     }
665   template<typename _CharT, typename _Traits, typename _Alloc>
666     _GLIBCXX_STRING_CONSTEXPR
667     typename basic_string<_CharT, _Traits, _Alloc>::size_type
668     basic_string<_CharT, _Traits, _Alloc>::
669     find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
670     {
671       size_type __ret = npos;
672       const size_type __size = this->size();
673       if (__pos < __size)
674         {
675           const _CharT* __data = _M_data();
676           const size_type __n = __size - __pos;
677           const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
678           if (__p)
679             __ret = __p - __data;
680         }
681       return __ret;
682     }
684   template<typename _CharT, typename _Traits, typename _Alloc>
685     _GLIBCXX_STRING_CONSTEXPR
686     typename basic_string<_CharT, _Traits, _Alloc>::size_type
687     basic_string<_CharT, _Traits, _Alloc>::
688     rfind(const _CharT* __s, size_type __pos, size_type __n) const
689     _GLIBCXX_NOEXCEPT
690     {
691       __glibcxx_requires_string_len(__s, __n);
692       const size_type __size = this->size();
693       if (__n <= __size)
694         {
695           __pos = std::min(size_type(__size - __n), __pos);
696           const _CharT* __data = _M_data();
697           do
698             {
699               if (traits_type::compare(__data + __pos, __s, __n) == 0)
700                 return __pos;
701             }
702           while (__pos-- > 0);
703         }
704       return npos;
705     }
707   template<typename _CharT, typename _Traits, typename _Alloc>
708     _GLIBCXX_STRING_CONSTEXPR
709     typename basic_string<_CharT, _Traits, _Alloc>::size_type
710     basic_string<_CharT, _Traits, _Alloc>::
711     rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
712     {
713       size_type __size = this->size();
714       if (__size)
715         {
716           if (--__size > __pos)
717             __size = __pos;
718           for (++__size; __size-- > 0; )
719             if (traits_type::eq(_M_data()[__size], __c))
720               return __size;
721         }
722       return npos;
723     }
725   template<typename _CharT, typename _Traits, typename _Alloc>
726     _GLIBCXX_STRING_CONSTEXPR
727     typename basic_string<_CharT, _Traits, _Alloc>::size_type
728     basic_string<_CharT, _Traits, _Alloc>::
729     find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
730     _GLIBCXX_NOEXCEPT
731     {
732       __glibcxx_requires_string_len(__s, __n);
733       for (; __n && __pos < this->size(); ++__pos)
734         {
735           const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
736           if (__p)
737             return __pos;
738         }
739       return npos;
740     }
742   template<typename _CharT, typename _Traits, typename _Alloc>
743     _GLIBCXX_STRING_CONSTEXPR
744     typename basic_string<_CharT, _Traits, _Alloc>::size_type
745     basic_string<_CharT, _Traits, _Alloc>::
746     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
747     _GLIBCXX_NOEXCEPT
748     {
749       __glibcxx_requires_string_len(__s, __n);
750       size_type __size = this->size();
751       if (__size && __n)
752         {
753           if (--__size > __pos)
754             __size = __pos;
755           do
756             {
757               if (traits_type::find(__s, __n, _M_data()[__size]))
758                 return __size;
759             }
760           while (__size-- != 0);
761         }
762       return npos;
763     }
765   template<typename _CharT, typename _Traits, typename _Alloc>
766     _GLIBCXX_STRING_CONSTEXPR
767     typename basic_string<_CharT, _Traits, _Alloc>::size_type
768     basic_string<_CharT, _Traits, _Alloc>::
769     find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
770     _GLIBCXX_NOEXCEPT
771     {
772       __glibcxx_requires_string_len(__s, __n);
773       for (; __pos < this->size(); ++__pos)
774         if (!traits_type::find(__s, __n, _M_data()[__pos]))
775           return __pos;
776       return npos;
777     }
779   template<typename _CharT, typename _Traits, typename _Alloc>
780     _GLIBCXX_STRING_CONSTEXPR
781     typename basic_string<_CharT, _Traits, _Alloc>::size_type
782     basic_string<_CharT, _Traits, _Alloc>::
783     find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
784     {
785       for (; __pos < this->size(); ++__pos)
786         if (!traits_type::eq(_M_data()[__pos], __c))
787           return __pos;
788       return npos;
789     }
791   template<typename _CharT, typename _Traits, typename _Alloc>
792     _GLIBCXX_STRING_CONSTEXPR
793     typename basic_string<_CharT, _Traits, _Alloc>::size_type
794     basic_string<_CharT, _Traits, _Alloc>::
795     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
796     _GLIBCXX_NOEXCEPT
797     {
798       __glibcxx_requires_string_len(__s, __n);
799       size_type __size = this->size();
800       if (__size)
801         {
802           if (--__size > __pos)
803             __size = __pos;
804           do
805             {
806               if (!traits_type::find(__s, __n, _M_data()[__size]))
807                 return __size;
808             }
809           while (__size--);
810         }
811       return npos;
812     }
814   template<typename _CharT, typename _Traits, typename _Alloc>
815     _GLIBCXX_STRING_CONSTEXPR
816     typename basic_string<_CharT, _Traits, _Alloc>::size_type
817     basic_string<_CharT, _Traits, _Alloc>::
818     find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
819     {
820       size_type __size = this->size();
821       if (__size)
822         {
823           if (--__size > __pos)
824             __size = __pos;
825           do
826             {
827               if (!traits_type::eq(_M_data()[__size], __c))
828                 return __size;
829             }
830           while (__size--);
831         }
832       return npos;
833     }
835 #undef _GLIBCXX_STRING_CONSTEXPR
837   // 21.3.7.9 basic_string::getline and operators
838   template<typename _CharT, typename _Traits, typename _Alloc>
839     basic_istream<_CharT, _Traits>&
840     operator>>(basic_istream<_CharT, _Traits>& __in,
841                basic_string<_CharT, _Traits, _Alloc>& __str)
842     {
843       typedef basic_istream<_CharT, _Traits>            __istream_type;
844       typedef basic_string<_CharT, _Traits, _Alloc>     __string_type;
845       typedef typename __istream_type::ios_base         __ios_base;
846       typedef typename __istream_type::int_type         __int_type;
847       typedef typename __string_type::size_type         __size_type;
848       typedef ctype<_CharT>                             __ctype_type;
849       typedef typename __ctype_type::ctype_base         __ctype_base;
851       __size_type __extracted = 0;
852       typename __ios_base::iostate __err = __ios_base::goodbit;
853       typename __istream_type::sentry __cerb(__in, false);
854       if (__cerb)
855         {
856           __try
857             {
858               // Avoid reallocation for common case.
859               __str.erase();
860               _CharT __buf[128];
861               __size_type __len = 0;          
862               const streamsize __w = __in.width();
863               const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
864                                               : __str.max_size();
865               const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
866               const __int_type __eof = _Traits::eof();
867               __int_type __c = __in.rdbuf()->sgetc();
869               while (__extracted < __n
870                      && !_Traits::eq_int_type(__c, __eof)
871                      && !__ct.is(__ctype_base::space,
872                                  _Traits::to_char_type(__c)))
873                 {
874                   if (__len == sizeof(__buf) / sizeof(_CharT))
875                     {
876                       __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
877                       __len = 0;
878                     }
879                   __buf[__len++] = _Traits::to_char_type(__c);
880                   ++__extracted;
881                   __c = __in.rdbuf()->snextc();
882                 }
883               __str.append(__buf, __len);
885               if (__extracted < __n && _Traits::eq_int_type(__c, __eof))
886                 __err |= __ios_base::eofbit;
887               __in.width(0);
888             }
889           __catch(__cxxabiv1::__forced_unwind&)
890             {
891               __in._M_setstate(__ios_base::badbit);
892               __throw_exception_again;
893             }
894           __catch(...)
895             {
896               // _GLIBCXX_RESOLVE_LIB_DEFECTS
897               // 91. Description of operator>> and getline() for string<>
898               // might cause endless loop
899               __in._M_setstate(__ios_base::badbit);
900             }
901         }
902       // 211.  operator>>(istream&, string&) doesn't set failbit
903       if (!__extracted)
904         __err |= __ios_base::failbit;
905       if (__err)
906         __in.setstate(__err);
907       return __in;
908     }
910   template<typename _CharT, typename _Traits, typename _Alloc>
911     basic_istream<_CharT, _Traits>&
912     getline(basic_istream<_CharT, _Traits>& __in,
913             basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
914     {
915       typedef basic_istream<_CharT, _Traits>            __istream_type;
916       typedef basic_string<_CharT, _Traits, _Alloc>     __string_type;
917       typedef typename __istream_type::ios_base         __ios_base;
918       typedef typename __istream_type::int_type         __int_type;
919       typedef typename __string_type::size_type         __size_type;
921       __size_type __extracted = 0;
922       const __size_type __n = __str.max_size();
923       typename __ios_base::iostate __err = __ios_base::goodbit;
924       typename __istream_type::sentry __cerb(__in, true);
925       if (__cerb)
926         {
927           __try
928             {
929               __str.erase();
930               const __int_type __idelim = _Traits::to_int_type(__delim);
931               const __int_type __eof = _Traits::eof();
932               __int_type __c = __in.rdbuf()->sgetc();
934               while (__extracted < __n
935                      && !_Traits::eq_int_type(__c, __eof)
936                      && !_Traits::eq_int_type(__c, __idelim))
937                 {
938                   __str += _Traits::to_char_type(__c);
939                   ++__extracted;
940                   __c = __in.rdbuf()->snextc();
941                 }
943               if (_Traits::eq_int_type(__c, __eof))
944                 __err |= __ios_base::eofbit;
945               else if (_Traits::eq_int_type(__c, __idelim))
946                 {
947                   ++__extracted;                  
948                   __in.rdbuf()->sbumpc();
949                 }
950               else
951                 __err |= __ios_base::failbit;
952             }
953           __catch(__cxxabiv1::__forced_unwind&)
954             {
955               __in._M_setstate(__ios_base::badbit);
956               __throw_exception_again;
957             }
958           __catch(...)
959             {
960               // _GLIBCXX_RESOLVE_LIB_DEFECTS
961               // 91. Description of operator>> and getline() for string<>
962               // might cause endless loop
963               __in._M_setstate(__ios_base::badbit);
964             }
965         }
966       if (!__extracted)
967         __err |= __ios_base::failbit;
968       if (__err)
969         __in.setstate(__err);
970       return __in;
971     }
973   // Inhibit implicit instantiations for required instantiations,
974   // which are defined via explicit instantiations elsewhere.
975 #if _GLIBCXX_EXTERN_TEMPLATE
976   // The explicit instantiation definitions in src/c++11/string-inst.cc and
977   // src/c++17/string-inst.cc only instantiate the members required for C++17
978   // and earlier standards (so not C++20's starts_with and ends_with).
979   // Suppress the explicit instantiation declarations for C++20, so C++20
980   // code will implicitly instantiate std::string and std::wstring as needed.
981 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
982   extern template class basic_string<char>;
983 # elif ! _GLIBCXX_USE_CXX11_ABI
984   // Still need to prevent implicit instantiation of the COW empty rep,
985   // to ensure the definition in libstdc++.so is unique (PR 86138).
986   extern template basic_string<char>::size_type
987     basic_string<char>::_Rep::_S_empty_rep_storage[];
988 # elif _GLIBCXX_EXTERN_TEMPLATE > 0
989   // Export _M_replace_cold even for C++20.
990   extern template void
991     basic_string<char>::_M_replace_cold(char *, size_type, const char*,
992                                         const size_type, const size_type);
993 # endif
995   extern template
996     basic_istream<char>&
997     operator>>(basic_istream<char>&, string&);
998   extern template
999     basic_ostream<char>&
1000     operator<<(basic_ostream<char>&, const string&);
1001   extern template
1002     basic_istream<char>&
1003     getline(basic_istream<char>&, string&, char);
1004   extern template
1005     basic_istream<char>&
1006     getline(basic_istream<char>&, string&);
1008 #ifdef _GLIBCXX_USE_WCHAR_T
1009 # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0
1010   extern template class basic_string<wchar_t>;
1011 # elif ! _GLIBCXX_USE_CXX11_ABI
1012   extern template basic_string<wchar_t>::size_type
1013     basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
1014 # elif _GLIBCXX_EXTERN_TEMPLATE > 0
1015   // Export _M_replace_cold even for C++20.
1016   extern template void
1017     basic_string<wchar_t>::_M_replace_cold(wchar_t*, size_type, const wchar_t*,
1018                                            const size_type, const size_type);
1019 # endif
1021   extern template
1022     basic_istream<wchar_t>&
1023     operator>>(basic_istream<wchar_t>&, wstring&);
1024   extern template
1025     basic_ostream<wchar_t>&
1026     operator<<(basic_ostream<wchar_t>&, const wstring&);
1027   extern template
1028     basic_istream<wchar_t>&
1029     getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1030   extern template
1031     basic_istream<wchar_t>&
1032     getline(basic_istream<wchar_t>&, wstring&);
1033 #endif // _GLIBCXX_USE_WCHAR_T
1034 #endif // _GLIBCXX_EXTERN_TEMPLATE
1036 _GLIBCXX_END_NAMESPACE_VERSION
1037 } // namespace std
1039 #pragma GCC diagnostic pop
1040 #endif