gcc:
[official-gcc.git] / libstdc++-v3 / include / bits / basic_string.tcc
blob51bbb7bd6a0603d6ce529960674282648e0772d2
1 // Components for manipulating sequences of characters -*- C++ -*-
3 // Copyright (C) 1997-2018 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 #pragma GCC system_header
44 #include <bits/cxxabi_forced.h>
46 namespace std _GLIBCXX_VISIBILITY(default)
48 _GLIBCXX_BEGIN_NAMESPACE_VERSION
50 #if _GLIBCXX_USE_CXX11_ABI
52   template<typename _CharT, typename _Traits, typename _Alloc>
53     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
54     basic_string<_CharT, _Traits, _Alloc>::npos;
56   template<typename _CharT, typename _Traits, typename _Alloc>
57     void
58     basic_string<_CharT, _Traits, _Alloc>::
59     swap(basic_string& __s) _GLIBCXX_NOEXCEPT
60     {
61       if (this == &__s)
62         return;
64       _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator());
66       if (_M_is_local())
67         if (__s._M_is_local())
68           {
69             if (length() && __s.length())
70               {
71                 _CharT __tmp_data[_S_local_capacity + 1];
72                 traits_type::copy(__tmp_data, __s._M_local_buf,
73                                   _S_local_capacity + 1);
74                 traits_type::copy(__s._M_local_buf, _M_local_buf,
75                                   _S_local_capacity + 1);
76                 traits_type::copy(_M_local_buf, __tmp_data,
77                                   _S_local_capacity + 1);
78               }
79             else if (__s.length())
80               {
81                 traits_type::copy(_M_local_buf, __s._M_local_buf,
82                                   _S_local_capacity + 1);
83                 _M_length(__s.length());
84                 __s._M_set_length(0);
85                 return;
86               }
87             else if (length())
88               {
89                 traits_type::copy(__s._M_local_buf, _M_local_buf,
90                                   _S_local_capacity + 1);
91                 __s._M_length(length());
92                 _M_set_length(0);
93                 return;
94               }
95           }
96         else
97           {
98             const size_type __tmp_capacity = __s._M_allocated_capacity;
99             traits_type::copy(__s._M_local_buf, _M_local_buf,
100                               _S_local_capacity + 1);
101             _M_data(__s._M_data());
102             __s._M_data(__s._M_local_buf);
103             _M_capacity(__tmp_capacity);
104           }
105       else
106         {
107           const size_type __tmp_capacity = _M_allocated_capacity;
108           if (__s._M_is_local())
109             {
110               traits_type::copy(_M_local_buf, __s._M_local_buf,
111                                 _S_local_capacity + 1);
112               __s._M_data(_M_data());
113               _M_data(_M_local_buf);
114             }
115           else
116             {
117               pointer __tmp_ptr = _M_data();
118               _M_data(__s._M_data());
119               __s._M_data(__tmp_ptr);
120               _M_capacity(__s._M_allocated_capacity);
121             }
122           __s._M_capacity(__tmp_capacity);
123         }
125       const size_type __tmp_length = length();
126       _M_length(__s.length());
127       __s._M_length(__tmp_length);
128     }
130   template<typename _CharT, typename _Traits, typename _Alloc>
131     typename basic_string<_CharT, _Traits, _Alloc>::pointer
132     basic_string<_CharT, _Traits, _Alloc>::
133     _M_create(size_type& __capacity, size_type __old_capacity)
134     {
135       // _GLIBCXX_RESOLVE_LIB_DEFECTS
136       // 83.  String::npos vs. string::max_size()
137       if (__capacity > max_size())
138         std::__throw_length_error(__N("basic_string::_M_create"));
140       // The below implements an exponential growth policy, necessary to
141       // meet amortized linear time requirements of the library: see
142       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
143       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
144         {
145           __capacity = 2 * __old_capacity;
146           // Never allocate a string bigger than max_size.
147           if (__capacity > max_size())
148             __capacity = max_size();
149         }
151       // NB: Need an array of char_type[__capacity], plus a terminating
152       // null char_type() element.
153       return _Alloc_traits::allocate(_M_get_allocator(), __capacity + 1);
154     }
156   // NB: This is the special case for Input Iterators, used in
157   // istreambuf_iterators, etc.
158   // Input Iterators have a cost structure very different from
159   // pointers, calling for a different coding style.
160   template<typename _CharT, typename _Traits, typename _Alloc>
161     template<typename _InIterator>
162       void
163       basic_string<_CharT, _Traits, _Alloc>::
164       _M_construct(_InIterator __beg, _InIterator __end,
165                    std::input_iterator_tag)
166       {
167         size_type __len = 0;
168         size_type __capacity = size_type(_S_local_capacity);
170         while (__beg != __end && __len < __capacity)
171           {
172             _M_data()[__len++] = *__beg;
173             ++__beg;
174           }
176         __try
177           {
178             while (__beg != __end)
179               {
180                 if (__len == __capacity)
181                   {
182                     // Allocate more space.
183                     __capacity = __len + 1;
184                     pointer __another = _M_create(__capacity, __len);
185                     this->_S_copy(__another, _M_data(), __len);
186                     _M_dispose();
187                     _M_data(__another);
188                     _M_capacity(__capacity);
189                   }
190                 _M_data()[__len++] = *__beg;
191                 ++__beg;
192               }
193           }
194         __catch(...)
195           {
196             _M_dispose();
197             __throw_exception_again;
198           }
200         _M_set_length(__len);
201       }
203   template<typename _CharT, typename _Traits, typename _Alloc>
204     template<typename _InIterator>
205       void
206       basic_string<_CharT, _Traits, _Alloc>::
207       _M_construct(_InIterator __beg, _InIterator __end,
208                    std::forward_iterator_tag)
209       {
210         // NB: Not required, but considered best practice.
211         if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
212           std::__throw_logic_error(__N("basic_string::"
213                                        "_M_construct null not valid"));
215         size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
217         if (__dnew > size_type(_S_local_capacity))
218           {
219             _M_data(_M_create(__dnew, size_type(0)));
220             _M_capacity(__dnew);
221           }
223         // Check for out_of_range and length_error exceptions.
224         __try
225           { this->_S_copy_chars(_M_data(), __beg, __end); }
226         __catch(...)
227           {
228             _M_dispose();
229             __throw_exception_again;
230           }
232         _M_set_length(__dnew);
233       }
235   template<typename _CharT, typename _Traits, typename _Alloc>
236     void
237     basic_string<_CharT, _Traits, _Alloc>::
238     _M_construct(size_type __n, _CharT __c)
239     {
240       if (__n > size_type(_S_local_capacity))
241         {
242           _M_data(_M_create(__n, size_type(0)));
243           _M_capacity(__n);
244         }
246       if (__n)
247         this->_S_assign(_M_data(), __n, __c);
249       _M_set_length(__n);
250     }
252   template<typename _CharT, typename _Traits, typename _Alloc>
253     void
254     basic_string<_CharT, _Traits, _Alloc>::
255     _M_assign(const basic_string& __str)
256     {
257       if (this != &__str)
258         {
259           const size_type __rsize = __str.length();
260           const size_type __capacity = capacity();
262           if (__rsize > __capacity)
263             {
264               size_type __new_capacity = __rsize;
265               pointer __tmp = _M_create(__new_capacity, __capacity);
266               _M_dispose();
267               _M_data(__tmp);
268               _M_capacity(__new_capacity);
269             }
271           if (__rsize)
272             this->_S_copy(_M_data(), __str._M_data(), __rsize);
274           _M_set_length(__rsize);
275         }
276     }
278   template<typename _CharT, typename _Traits, typename _Alloc>
279     void
280     basic_string<_CharT, _Traits, _Alloc>::
281     reserve(size_type __res)
282     {
283       // Make sure we don't shrink below the current size.
284       if (__res < length())
285         __res = length();
287       const size_type __capacity = capacity();
288       if (__res != __capacity)
289         {
290           if (__res > __capacity
291               || __res > size_type(_S_local_capacity))
292             {
293               pointer __tmp = _M_create(__res, __capacity);
294               this->_S_copy(__tmp, _M_data(), length() + 1);
295               _M_dispose();
296               _M_data(__tmp);
297               _M_capacity(__res);
298             }
299           else if (!_M_is_local())
300             {
301               this->_S_copy(_M_local_data(), _M_data(), length() + 1);
302               _M_destroy(__capacity);
303               _M_data(_M_local_data());
304             }
305         }
306     }
308   template<typename _CharT, typename _Traits, typename _Alloc>
309     void
310     basic_string<_CharT, _Traits, _Alloc>::
311     _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
312               size_type __len2)
313     {
314       const size_type __how_much = length() - __pos - __len1;
316       size_type __new_capacity = length() + __len2 - __len1;
317       pointer __r = _M_create(__new_capacity, capacity());
319       if (__pos)
320         this->_S_copy(__r, _M_data(), __pos);
321       if (__s && __len2)
322         this->_S_copy(__r + __pos, __s, __len2);
323       if (__how_much)
324         this->_S_copy(__r + __pos + __len2,
325                       _M_data() + __pos + __len1, __how_much);
327       _M_dispose();
328       _M_data(__r);
329       _M_capacity(__new_capacity);
330     }
332   template<typename _CharT, typename _Traits, typename _Alloc>
333     void
334     basic_string<_CharT, _Traits, _Alloc>::
335     _M_erase(size_type __pos, size_type __n)
336     {
337       const size_type __how_much = length() - __pos - __n;
339       if (__how_much && __n)
340         this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
342       _M_set_length(length() - __n);
343     }
345   template<typename _CharT, typename _Traits, typename _Alloc>
346     void
347     basic_string<_CharT, _Traits, _Alloc>::
348     resize(size_type __n, _CharT __c)
349     {
350       const size_type __size = this->size();
351       if (__size < __n)
352         this->append(__n - __size, __c);
353       else if (__n < __size)
354         this->_M_set_length(__n);
355     }
357   template<typename _CharT, typename _Traits, typename _Alloc>
358     basic_string<_CharT, _Traits, _Alloc>&
359     basic_string<_CharT, _Traits, _Alloc>::
360     _M_append(const _CharT* __s, size_type __n)
361     {
362       const size_type __len = __n + this->size();
364       if (__len <= this->capacity())
365         {
366           if (__n)
367             this->_S_copy(this->_M_data() + this->size(), __s, __n);
368         }
369       else
370         this->_M_mutate(this->size(), size_type(0), __s, __n);
372       this->_M_set_length(__len);
373       return *this;
374     }
376   template<typename _CharT, typename _Traits, typename _Alloc>
377     template<typename _InputIterator>
378       basic_string<_CharT, _Traits, _Alloc>&
379       basic_string<_CharT, _Traits, _Alloc>::
380       _M_replace_dispatch(const_iterator __i1, const_iterator __i2,
381                           _InputIterator __k1, _InputIterator __k2,
382                           std::__false_type)
383       {
384         const basic_string __s(__k1, __k2);
385         const size_type __n1 = __i2 - __i1;
386         return _M_replace(__i1 - begin(), __n1, __s._M_data(),
387                           __s.size());
388       }
390   template<typename _CharT, typename _Traits, typename _Alloc>
391     basic_string<_CharT, _Traits, _Alloc>&
392     basic_string<_CharT, _Traits, _Alloc>::
393     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
394                    _CharT __c)
395     {
396       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
398       const size_type __old_size = this->size();
399       const size_type __new_size = __old_size + __n2 - __n1;
401       if (__new_size <= this->capacity())
402         {
403           pointer __p = this->_M_data() + __pos1;
405           const size_type __how_much = __old_size - __pos1 - __n1;
406           if (__how_much && __n1 != __n2)
407             this->_S_move(__p + __n2, __p + __n1, __how_much);
408         }
409       else
410         this->_M_mutate(__pos1, __n1, 0, __n2);
412       if (__n2)
413         this->_S_assign(this->_M_data() + __pos1, __n2, __c);
415       this->_M_set_length(__new_size);
416       return *this;
417     }
419   template<typename _CharT, typename _Traits, typename _Alloc>
420     basic_string<_CharT, _Traits, _Alloc>&
421     basic_string<_CharT, _Traits, _Alloc>::
422     _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
423                const size_type __len2)
424     {
425       _M_check_length(__len1, __len2, "basic_string::_M_replace");
427       const size_type __old_size = this->size();
428       const size_type __new_size = __old_size + __len2 - __len1;
430       if (__new_size <= this->capacity())
431         {
432           pointer __p = this->_M_data() + __pos;
434           const size_type __how_much = __old_size - __pos - __len1;
435           if (_M_disjunct(__s))
436             {
437               if (__how_much && __len1 != __len2)
438                 this->_S_move(__p + __len2, __p + __len1, __how_much);
439               if (__len2)
440                 this->_S_copy(__p, __s, __len2);
441             }
442           else
443             {
444               // Work in-place.
445               if (__len2 && __len2 <= __len1)
446                 this->_S_move(__p, __s, __len2);
447               if (__how_much && __len1 != __len2)
448                 this->_S_move(__p + __len2, __p + __len1, __how_much);
449               if (__len2 > __len1)
450                 {
451                   if (__s + __len2 <= __p + __len1)
452                     this->_S_move(__p, __s, __len2);
453                   else if (__s >= __p + __len1)
454                     this->_S_copy(__p, __s + __len2 - __len1, __len2);
455                   else
456                     {
457                       const size_type __nleft = (__p + __len1) - __s;
458                       this->_S_move(__p, __s, __nleft);
459                       this->_S_copy(__p + __nleft, __p + __len2,
460                                     __len2 - __nleft);
461                     }
462                 }
463             }
464         }
465       else
466         this->_M_mutate(__pos, __len1, __s, __len2);
468       this->_M_set_length(__new_size);
469       return *this;
470     }
472   template<typename _CharT, typename _Traits, typename _Alloc>
473     typename basic_string<_CharT, _Traits, _Alloc>::size_type
474     basic_string<_CharT, _Traits, _Alloc>::
475     copy(_CharT* __s, size_type __n, size_type __pos) const
476     {
477       _M_check(__pos, "basic_string::copy");
478       __n = _M_limit(__pos, __n);
479       __glibcxx_requires_string_len(__s, __n);
480       if (__n)
481         _S_copy(__s, _M_data() + __pos, __n);
482       // 21.3.5.7 par 3: do not append null.  (good.)
483       return __n;
484     }
486 #else  // !_GLIBCXX_USE_CXX11_ABI
488   template<typename _CharT, typename _Traits, typename _Alloc>
489     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
490     basic_string<_CharT, _Traits, _Alloc>::
491     _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
493   template<typename _CharT, typename _Traits, typename _Alloc>
494     const _CharT
495     basic_string<_CharT, _Traits, _Alloc>::
496     _Rep::_S_terminal = _CharT();
498   template<typename _CharT, typename _Traits, typename _Alloc>
499     const typename basic_string<_CharT, _Traits, _Alloc>::size_type
500     basic_string<_CharT, _Traits, _Alloc>::npos;
502   // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
503   // at static init time (before static ctors are run).
504   template<typename _CharT, typename _Traits, typename _Alloc>
505     typename basic_string<_CharT, _Traits, _Alloc>::size_type
506     basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
507     (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
508       sizeof(size_type)];
510   // NB: This is the special case for Input Iterators, used in
511   // istreambuf_iterators, etc.
512   // Input Iterators have a cost structure very different from
513   // pointers, calling for a different coding style.
514   template<typename _CharT, typename _Traits, typename _Alloc>
515     template<typename _InIterator>
516       _CharT*
517       basic_string<_CharT, _Traits, _Alloc>::
518       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
519                    input_iterator_tag)
520       {
521 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
522         if (__beg == __end && __a == _Alloc())
523           return _S_empty_rep()._M_refdata();
524 #endif
525         // Avoid reallocation for common case.
526         _CharT __buf[128];
527         size_type __len = 0;
528         while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
529           {
530             __buf[__len++] = *__beg;
531             ++__beg;
532           }
533         _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
534         _M_copy(__r->_M_refdata(), __buf, __len);
535         __try
536           {
537             while (__beg != __end)
538               {
539                 if (__len == __r->_M_capacity)
540                   {
541                     // Allocate more space.
542                     _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
543                     _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
544                     __r->_M_destroy(__a);
545                     __r = __another;
546                   }
547                 __r->_M_refdata()[__len++] = *__beg;
548                 ++__beg;
549               }
550           }
551         __catch(...)
552           {
553             __r->_M_destroy(__a);
554             __throw_exception_again;
555           }
556         __r->_M_set_length_and_sharable(__len);
557         return __r->_M_refdata();
558       }
560   template<typename _CharT, typename _Traits, typename _Alloc>
561     template <typename _InIterator>
562       _CharT*
563       basic_string<_CharT, _Traits, _Alloc>::
564       _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
565                    forward_iterator_tag)
566       {
567 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
568         if (__beg == __end && __a == _Alloc())
569           return _S_empty_rep()._M_refdata();
570 #endif
571         // NB: Not required, but considered best practice.
572         if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
573           __throw_logic_error(__N("basic_string::_S_construct null not valid"));
575         const size_type __dnew = static_cast<size_type>(std::distance(__beg,
576                                                                       __end));
577         // Check for out_of_range and length_error exceptions.
578         _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
579         __try
580           { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
581         __catch(...)
582           {
583             __r->_M_destroy(__a);
584             __throw_exception_again;
585           }
586         __r->_M_set_length_and_sharable(__dnew);
587         return __r->_M_refdata();
588       }
590   template<typename _CharT, typename _Traits, typename _Alloc>
591     _CharT*
592     basic_string<_CharT, _Traits, _Alloc>::
593     _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
594     {
595 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
596       if (__n == 0 && __a == _Alloc())
597         return _S_empty_rep()._M_refdata();
598 #endif
599       // Check for out_of_range and length_error exceptions.
600       _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
601       if (__n)
602         _M_assign(__r->_M_refdata(), __n, __c);
604       __r->_M_set_length_and_sharable(__n);
605       return __r->_M_refdata();
606     }
608   template<typename _CharT, typename _Traits, typename _Alloc>
609     basic_string<_CharT, _Traits, _Alloc>::
610     basic_string(const basic_string& __str)
611     : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
612                                           __str.get_allocator()),
613                   __str.get_allocator())
614     { }
616   template<typename _CharT, typename _Traits, typename _Alloc>
617     basic_string<_CharT, _Traits, _Alloc>::
618     basic_string(const _Alloc& __a)
619     : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
620     { }
622   template<typename _CharT, typename _Traits, typename _Alloc>
623     basic_string<_CharT, _Traits, _Alloc>::
624     basic_string(const basic_string& __str, size_type __pos, const _Alloc& __a)
625     : _M_dataplus(_S_construct(__str._M_data()
626                                + __str._M_check(__pos,
627                                                 "basic_string::basic_string"),
628                                __str._M_data() + __str._M_limit(__pos, npos)
629                                + __pos, __a), __a)
630     { }
632   template<typename _CharT, typename _Traits, typename _Alloc>
633     basic_string<_CharT, _Traits, _Alloc>::
634     basic_string(const basic_string& __str, size_type __pos, size_type __n)
635     : _M_dataplus(_S_construct(__str._M_data()
636                                + __str._M_check(__pos,
637                                                 "basic_string::basic_string"),
638                                __str._M_data() + __str._M_limit(__pos, __n)
639                                + __pos, _Alloc()), _Alloc())
640     { }
642   template<typename _CharT, typename _Traits, typename _Alloc>
643     basic_string<_CharT, _Traits, _Alloc>::
644     basic_string(const basic_string& __str, size_type __pos,
645                  size_type __n, const _Alloc& __a)
646     : _M_dataplus(_S_construct(__str._M_data()
647                                + __str._M_check(__pos,
648                                                 "basic_string::basic_string"),
649                                __str._M_data() + __str._M_limit(__pos, __n)
650                                + __pos, __a), __a)
651     { }
653   // TBD: DPG annotate
654   template<typename _CharT, typename _Traits, typename _Alloc>
655     basic_string<_CharT, _Traits, _Alloc>::
656     basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
657     : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
658     { }
660   // TBD: DPG annotate
661   template<typename _CharT, typename _Traits, typename _Alloc>
662     basic_string<_CharT, _Traits, _Alloc>::
663     basic_string(const _CharT* __s, const _Alloc& __a)
664     : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
665                                __s + npos, __a), __a)
666     { }
668   template<typename _CharT, typename _Traits, typename _Alloc>
669     basic_string<_CharT, _Traits, _Alloc>::
670     basic_string(size_type __n, _CharT __c, const _Alloc& __a)
671     : _M_dataplus(_S_construct(__n, __c, __a), __a)
672     { }
674   // TBD: DPG annotate
675   template<typename _CharT, typename _Traits, typename _Alloc>
676     template<typename _InputIterator>
677     basic_string<_CharT, _Traits, _Alloc>::
678     basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
679     : _M_dataplus(_S_construct(__beg, __end, __a), __a)
680     { }
682 #if __cplusplus >= 201103L
683   template<typename _CharT, typename _Traits, typename _Alloc>
684     basic_string<_CharT, _Traits, _Alloc>::
685     basic_string(initializer_list<_CharT> __l, const _Alloc& __a)
686     : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a)
687     { }
688 #endif
690   template<typename _CharT, typename _Traits, typename _Alloc>
691     basic_string<_CharT, _Traits, _Alloc>&
692     basic_string<_CharT, _Traits, _Alloc>::
693     assign(const basic_string& __str)
694     {
695       if (_M_rep() != __str._M_rep())
696         {
697           // XXX MT
698           const allocator_type __a = this->get_allocator();
699           _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
700           _M_rep()->_M_dispose(__a);
701           _M_data(__tmp);
702         }
703       return *this;
704     }
706   template<typename _CharT, typename _Traits, typename _Alloc>
707     basic_string<_CharT, _Traits, _Alloc>&
708     basic_string<_CharT, _Traits, _Alloc>::
709     assign(const _CharT* __s, size_type __n)
710     {
711       __glibcxx_requires_string_len(__s, __n);
712       _M_check_length(this->size(), __n, "basic_string::assign");
713       if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
714         return _M_replace_safe(size_type(0), this->size(), __s, __n);
715       else
716         {
717           // Work in-place.
718           const size_type __pos = __s - _M_data();
719           if (__pos >= __n)
720             _M_copy(_M_data(), __s, __n);
721           else if (__pos)
722             _M_move(_M_data(), __s, __n);
723           _M_rep()->_M_set_length_and_sharable(__n);
724           return *this;
725         }
726      }
728   template<typename _CharT, typename _Traits, typename _Alloc>
729     basic_string<_CharT, _Traits, _Alloc>&
730     basic_string<_CharT, _Traits, _Alloc>::
731     append(size_type __n, _CharT __c)
732     {
733       if (__n)
734         {
735           _M_check_length(size_type(0), __n, "basic_string::append");     
736           const size_type __len = __n + this->size();
737           if (__len > this->capacity() || _M_rep()->_M_is_shared())
738             this->reserve(__len);
739           _M_assign(_M_data() + this->size(), __n, __c);
740           _M_rep()->_M_set_length_and_sharable(__len);
741         }
742       return *this;
743     }
745   template<typename _CharT, typename _Traits, typename _Alloc>
746     basic_string<_CharT, _Traits, _Alloc>&
747     basic_string<_CharT, _Traits, _Alloc>::
748     append(const _CharT* __s, size_type __n)
749     {
750       __glibcxx_requires_string_len(__s, __n);
751       if (__n)
752         {
753           _M_check_length(size_type(0), __n, "basic_string::append");
754           const size_type __len = __n + this->size();
755           if (__len > this->capacity() || _M_rep()->_M_is_shared())
756             {
757               if (_M_disjunct(__s))
758                 this->reserve(__len);
759               else
760                 {
761                   const size_type __off = __s - _M_data();
762                   this->reserve(__len);
763                   __s = _M_data() + __off;
764                 }
765             }
766           _M_copy(_M_data() + this->size(), __s, __n);
767           _M_rep()->_M_set_length_and_sharable(__len);
768         }
769       return *this;
770     }
772   template<typename _CharT, typename _Traits, typename _Alloc>
773     basic_string<_CharT, _Traits, _Alloc>&
774     basic_string<_CharT, _Traits, _Alloc>::
775     append(const basic_string& __str)
776     {
777       const size_type __size = __str.size();
778       if (__size)
779         {
780           const size_type __len = __size + this->size();
781           if (__len > this->capacity() || _M_rep()->_M_is_shared())
782             this->reserve(__len);
783           _M_copy(_M_data() + this->size(), __str._M_data(), __size);
784           _M_rep()->_M_set_length_and_sharable(__len);
785         }
786       return *this;
787     }    
789   template<typename _CharT, typename _Traits, typename _Alloc>
790     basic_string<_CharT, _Traits, _Alloc>&
791     basic_string<_CharT, _Traits, _Alloc>::
792     append(const basic_string& __str, size_type __pos, size_type __n)
793     {
794       __str._M_check(__pos, "basic_string::append");
795       __n = __str._M_limit(__pos, __n);
796       if (__n)
797         {
798           const size_type __len = __n + this->size();
799           if (__len > this->capacity() || _M_rep()->_M_is_shared())
800             this->reserve(__len);
801           _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
802           _M_rep()->_M_set_length_and_sharable(__len);    
803         }
804       return *this;
805     }
807    template<typename _CharT, typename _Traits, typename _Alloc>
808      basic_string<_CharT, _Traits, _Alloc>&
809      basic_string<_CharT, _Traits, _Alloc>::
810      insert(size_type __pos, const _CharT* __s, size_type __n)
811      {
812        __glibcxx_requires_string_len(__s, __n);
813        _M_check(__pos, "basic_string::insert");
814        _M_check_length(size_type(0), __n, "basic_string::insert");
815        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
816          return _M_replace_safe(__pos, size_type(0), __s, __n);
817        else
818          {
819            // Work in-place.
820            const size_type __off = __s - _M_data();
821            _M_mutate(__pos, 0, __n);
822            __s = _M_data() + __off;
823            _CharT* __p = _M_data() + __pos;
824            if (__s  + __n <= __p)
825              _M_copy(__p, __s, __n);
826            else if (__s >= __p)
827              _M_copy(__p, __s + __n, __n);
828            else
829              {
830                const size_type __nleft = __p - __s;
831                _M_copy(__p, __s, __nleft);
832                _M_copy(__p + __nleft, __p + __n, __n - __nleft);
833              }
834            return *this;
835          }
836      }
838    template<typename _CharT, typename _Traits, typename _Alloc>
839      typename basic_string<_CharT, _Traits, _Alloc>::iterator
840      basic_string<_CharT, _Traits, _Alloc>::
841      erase(iterator __first, iterator __last)
842      {
843        _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
844                                 && __last <= _M_iend());
846        // NB: This isn't just an optimization (bail out early when
847        // there is nothing to do, really), it's also a correctness
848        // issue vs MT, see libstdc++/40518.
849        const size_type __size = __last - __first;
850        if (__size)
851          {
852            const size_type __pos = __first - _M_ibegin();
853            _M_mutate(__pos, __size, size_type(0));
854            _M_rep()->_M_set_leaked();
855            return iterator(_M_data() + __pos);
856          }
857        else
858          return __first;
859      }
861    template<typename _CharT, typename _Traits, typename _Alloc>
862      basic_string<_CharT, _Traits, _Alloc>&
863      basic_string<_CharT, _Traits, _Alloc>::
864      replace(size_type __pos, size_type __n1, const _CharT* __s,
865              size_type __n2)
866      {
867        __glibcxx_requires_string_len(__s, __n2);
868        _M_check(__pos, "basic_string::replace");
869        __n1 = _M_limit(__pos, __n1);
870        _M_check_length(__n1, __n2, "basic_string::replace");
871        bool __left;
872        if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
873          return _M_replace_safe(__pos, __n1, __s, __n2);
874        else if ((__left = __s + __n2 <= _M_data() + __pos)
875                 || _M_data() + __pos + __n1 <= __s)
876          {
877            // Work in-place: non-overlapping case.
878            size_type __off = __s - _M_data();
879            __left ? __off : (__off += __n2 - __n1);
880            _M_mutate(__pos, __n1, __n2);
881            _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
882            return *this;
883          }
884        else
885          {
886            // Todo: overlapping case.
887            const basic_string __tmp(__s, __n2);
888            return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
889          }
890      }
892   template<typename _CharT, typename _Traits, typename _Alloc>
893     void
894     basic_string<_CharT, _Traits, _Alloc>::_Rep::
895     _M_destroy(const _Alloc& __a) throw ()
896     {
897       const size_type __size = sizeof(_Rep_base) +
898                                (this->_M_capacity + 1) * sizeof(_CharT);
899       _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
900     }
902   template<typename _CharT, typename _Traits, typename _Alloc>
903     void
904     basic_string<_CharT, _Traits, _Alloc>::
905     _M_leak_hard()
906     {
907 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
908       if (_M_rep() == &_S_empty_rep())
909         return;
910 #endif
911       if (_M_rep()->_M_is_shared())
912         _M_mutate(0, 0, 0);
913       _M_rep()->_M_set_leaked();
914     }
916   template<typename _CharT, typename _Traits, typename _Alloc>
917     void
918     basic_string<_CharT, _Traits, _Alloc>::
919     _M_mutate(size_type __pos, size_type __len1, size_type __len2)
920     {
921       const size_type __old_size = this->size();
922       const size_type __new_size = __old_size + __len2 - __len1;
923       const size_type __how_much = __old_size - __pos - __len1;
925       if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
926         {
927           // Must reallocate.
928           const allocator_type __a = get_allocator();
929           _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
931           if (__pos)
932             _M_copy(__r->_M_refdata(), _M_data(), __pos);
933           if (__how_much)
934             _M_copy(__r->_M_refdata() + __pos + __len2,
935                     _M_data() + __pos + __len1, __how_much);
937           _M_rep()->_M_dispose(__a);
938           _M_data(__r->_M_refdata());
939         }
940       else if (__how_much && __len1 != __len2)
941         {
942           // Work in-place.
943           _M_move(_M_data() + __pos + __len2,
944                   _M_data() + __pos + __len1, __how_much);
945         }
946       _M_rep()->_M_set_length_and_sharable(__new_size);
947     }
949   template<typename _CharT, typename _Traits, typename _Alloc>
950     void
951     basic_string<_CharT, _Traits, _Alloc>::
952     reserve(size_type __res)
953     {
954       if (__res != this->capacity() || _M_rep()->_M_is_shared())
955         {
956           // Make sure we don't shrink below the current size
957           if (__res < this->size())
958             __res = this->size();
959           const allocator_type __a = get_allocator();
960           _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
961           _M_rep()->_M_dispose(__a);
962           _M_data(__tmp);
963         }
964     }
966   template<typename _CharT, typename _Traits, typename _Alloc>
967     void
968     basic_string<_CharT, _Traits, _Alloc>::
969     swap(basic_string& __s)
970     _GLIBCXX_NOEXCEPT_IF(allocator_traits<_Alloc>::is_always_equal::value)
971     {
972       if (_M_rep()->_M_is_leaked())
973         _M_rep()->_M_set_sharable();
974       if (__s._M_rep()->_M_is_leaked())
975         __s._M_rep()->_M_set_sharable();
976       if (this->get_allocator() == __s.get_allocator())
977         {
978           _CharT* __tmp = _M_data();
979           _M_data(__s._M_data());
980           __s._M_data(__tmp);
981         }
982       // The code below can usually be optimized away.
983       else
984         {
985           const basic_string __tmp1(_M_ibegin(), _M_iend(),
986                                     __s.get_allocator());
987           const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
988                                     this->get_allocator());
989           *this = __tmp2;
990           __s = __tmp1;
991         }
992     }
994   template<typename _CharT, typename _Traits, typename _Alloc>
995     typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
996     basic_string<_CharT, _Traits, _Alloc>::_Rep::
997     _S_create(size_type __capacity, size_type __old_capacity,
998               const _Alloc& __alloc)
999     {
1000       // _GLIBCXX_RESOLVE_LIB_DEFECTS
1001       // 83.  String::npos vs. string::max_size()
1002       if (__capacity > _S_max_size)
1003         __throw_length_error(__N("basic_string::_S_create"));
1005       // The standard places no restriction on allocating more memory
1006       // than is strictly needed within this layer at the moment or as
1007       // requested by an explicit application call to reserve().
1009       // Many malloc implementations perform quite poorly when an
1010       // application attempts to allocate memory in a stepwise fashion
1011       // growing each allocation size by only 1 char.  Additionally,
1012       // it makes little sense to allocate less linear memory than the
1013       // natural blocking size of the malloc implementation.
1014       // Unfortunately, we would need a somewhat low-level calculation
1015       // with tuned parameters to get this perfect for any particular
1016       // malloc implementation.  Fortunately, generalizations about
1017       // common features seen among implementations seems to suffice.
1019       // __pagesize need not match the actual VM page size for good
1020       // results in practice, thus we pick a common value on the low
1021       // side.  __malloc_header_size is an estimate of the amount of
1022       // overhead per memory allocation (in practice seen N * sizeof
1023       // (void*) where N is 0, 2 or 4).  According to folklore,
1024       // picking this value on the high side is better than
1025       // low-balling it (especially when this algorithm is used with
1026       // malloc implementations that allocate memory blocks rounded up
1027       // to a size which is a power of 2).
1028       const size_type __pagesize = 4096;
1029       const size_type __malloc_header_size = 4 * sizeof(void*);
1031       // The below implements an exponential growth policy, necessary to
1032       // meet amortized linear time requirements of the library: see
1033       // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
1034       // It's active for allocations requiring an amount of memory above
1035       // system pagesize. This is consistent with the requirements of the
1036       // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
1037       if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
1038         __capacity = 2 * __old_capacity;
1040       // NB: Need an array of char_type[__capacity], plus a terminating
1041       // null char_type() element, plus enough for the _Rep data structure.
1042       // Whew. Seemingly so needy, yet so elemental.
1043       size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1045       const size_type __adj_size = __size + __malloc_header_size;
1046       if (__adj_size > __pagesize && __capacity > __old_capacity)
1047         {
1048           const size_type __extra = __pagesize - __adj_size % __pagesize;
1049           __capacity += __extra / sizeof(_CharT);
1050           // Never allocate a string bigger than _S_max_size.
1051           if (__capacity > _S_max_size)
1052             __capacity = _S_max_size;
1053           __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
1054         }
1056       // NB: Might throw, but no worries about a leak, mate: _Rep()
1057       // does not throw.
1058       void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
1059       _Rep *__p = new (__place) _Rep;
1060       __p->_M_capacity = __capacity;
1061       // ABI compatibility - 3.4.x set in _S_create both
1062       // _M_refcount and _M_length.  All callers of _S_create
1063       // in basic_string.tcc then set just _M_length.
1064       // In 4.0.x and later both _M_refcount and _M_length
1065       // are initialized in the callers, unfortunately we can
1066       // have 3.4.x compiled code with _S_create callers inlined
1067       // calling 4.0.x+ _S_create.
1068       __p->_M_set_sharable();
1069       return __p;
1070     }
1072   template<typename _CharT, typename _Traits, typename _Alloc>
1073     _CharT*
1074     basic_string<_CharT, _Traits, _Alloc>::_Rep::
1075     _M_clone(const _Alloc& __alloc, size_type __res)
1076     {
1077       // Requested capacity of the clone.
1078       const size_type __requested_cap = this->_M_length + __res;
1079       _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
1080                                   __alloc);
1081       if (this->_M_length)
1082         _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
1084       __r->_M_set_length_and_sharable(this->_M_length);
1085       return __r->_M_refdata();
1086     }
1088   template<typename _CharT, typename _Traits, typename _Alloc>
1089     void
1090     basic_string<_CharT, _Traits, _Alloc>::
1091     resize(size_type __n, _CharT __c)
1092     {
1093       const size_type __size = this->size();
1094       _M_check_length(__size, __n, "basic_string::resize");
1095       if (__size < __n)
1096         this->append(__n - __size, __c);
1097       else if (__n < __size)
1098         this->erase(__n);
1099       // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
1100     }
1102   template<typename _CharT, typename _Traits, typename _Alloc>
1103     template<typename _InputIterator>
1104       basic_string<_CharT, _Traits, _Alloc>&
1105       basic_string<_CharT, _Traits, _Alloc>::
1106       _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
1107                           _InputIterator __k2, __false_type)
1108       {
1109         const basic_string __s(__k1, __k2);
1110         const size_type __n1 = __i2 - __i1;
1111         _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
1112         return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
1113                                __s.size());
1114       }
1116   template<typename _CharT, typename _Traits, typename _Alloc>
1117     basic_string<_CharT, _Traits, _Alloc>&
1118     basic_string<_CharT, _Traits, _Alloc>::
1119     _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
1120                    _CharT __c)
1121     {
1122       _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
1123       _M_mutate(__pos1, __n1, __n2);
1124       if (__n2)
1125         _M_assign(_M_data() + __pos1, __n2, __c);
1126       return *this;
1127     }
1129   template<typename _CharT, typename _Traits, typename _Alloc>
1130     basic_string<_CharT, _Traits, _Alloc>&
1131     basic_string<_CharT, _Traits, _Alloc>::
1132     _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
1133                     size_type __n2)
1134     {
1135       _M_mutate(__pos1, __n1, __n2);
1136       if (__n2)
1137         _M_copy(_M_data() + __pos1, __s, __n2);
1138       return *this;
1139     }
1141     template<typename _CharT, typename _Traits, typename _Alloc>
1142     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1143     basic_string<_CharT, _Traits, _Alloc>::
1144     copy(_CharT* __s, size_type __n, size_type __pos) const
1145     {
1146       _M_check(__pos, "basic_string::copy");
1147       __n = _M_limit(__pos, __n);
1148       __glibcxx_requires_string_len(__s, __n);
1149       if (__n)
1150         _M_copy(__s, _M_data() + __pos, __n);
1151       // 21.3.5.7 par 3: do not append null.  (good.)
1152       return __n;
1153     }
1154 #endif  // !_GLIBCXX_USE_CXX11_ABI
1155    
1156   template<typename _CharT, typename _Traits, typename _Alloc>
1157     basic_string<_CharT, _Traits, _Alloc>
1158     operator+(const _CharT* __lhs,
1159               const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1160     {
1161       __glibcxx_requires_string(__lhs);
1162       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1163       typedef typename __string_type::size_type   __size_type;
1164       const __size_type __len = _Traits::length(__lhs);
1165       __string_type __str;
1166       __str.reserve(__len + __rhs.size());
1167       __str.append(__lhs, __len);
1168       __str.append(__rhs);
1169       return __str;
1170     }
1172   template<typename _CharT, typename _Traits, typename _Alloc>
1173     basic_string<_CharT, _Traits, _Alloc>
1174     operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
1175     {
1176       typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1177       typedef typename __string_type::size_type   __size_type;
1178       __string_type __str;
1179       const __size_type __len = __rhs.size();
1180       __str.reserve(__len + 1);
1181       __str.append(__size_type(1), __lhs);
1182       __str.append(__rhs);
1183       return __str;
1184     }
1186   template<typename _CharT, typename _Traits, typename _Alloc>
1187     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1188     basic_string<_CharT, _Traits, _Alloc>::
1189     find(const _CharT* __s, size_type __pos, size_type __n) const
1190     _GLIBCXX_NOEXCEPT
1191     {
1192       __glibcxx_requires_string_len(__s, __n);
1193       const size_type __size = this->size();
1195       if (__n == 0)
1196         return __pos <= __size ? __pos : npos;
1197       if (__pos >= __size)
1198         return npos;
1200       const _CharT __elem0 = __s[0];
1201       const _CharT* const __data = data();
1202       const _CharT* __first = __data + __pos;
1203       const _CharT* const __last = __data + __size;
1204       size_type __len = __size - __pos;
1206       while (__len >= __n)
1207         {
1208           // Find the first occurrence of __elem0:
1209           __first = traits_type::find(__first, __len - __n + 1, __elem0);
1210           if (!__first)
1211             return npos;
1212           // Compare the full strings from the first occurrence of __elem0.
1213           // We already know that __first[0] == __s[0] but compare them again
1214           // anyway because __s is probably aligned, which helps memcmp.
1215           if (traits_type::compare(__first, __s, __n) == 0)
1216             return __first - __data;
1217           __len = __last - ++__first;
1218         }
1219       return npos;
1220     }
1222   template<typename _CharT, typename _Traits, typename _Alloc>
1223     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1224     basic_string<_CharT, _Traits, _Alloc>::
1225     find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1226     {
1227       size_type __ret = npos;
1228       const size_type __size = this->size();
1229       if (__pos < __size)
1230         {
1231           const _CharT* __data = _M_data();
1232           const size_type __n = __size - __pos;
1233           const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
1234           if (__p)
1235             __ret = __p - __data;
1236         }
1237       return __ret;
1238     }
1240   template<typename _CharT, typename _Traits, typename _Alloc>
1241     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1242     basic_string<_CharT, _Traits, _Alloc>::
1243     rfind(const _CharT* __s, size_type __pos, size_type __n) const
1244     _GLIBCXX_NOEXCEPT
1245     {
1246       __glibcxx_requires_string_len(__s, __n);
1247       const size_type __size = this->size();
1248       if (__n <= __size)
1249         {
1250           __pos = std::min(size_type(__size - __n), __pos);
1251           const _CharT* __data = _M_data();
1252           do
1253             {
1254               if (traits_type::compare(__data + __pos, __s, __n) == 0)
1255                 return __pos;
1256             }
1257           while (__pos-- > 0);
1258         }
1259       return npos;
1260     }
1262   template<typename _CharT, typename _Traits, typename _Alloc>
1263     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1264     basic_string<_CharT, _Traits, _Alloc>::
1265     rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1266     {
1267       size_type __size = this->size();
1268       if (__size)
1269         {
1270           if (--__size > __pos)
1271             __size = __pos;
1272           for (++__size; __size-- > 0; )
1273             if (traits_type::eq(_M_data()[__size], __c))
1274               return __size;
1275         }
1276       return npos;
1277     }
1279   template<typename _CharT, typename _Traits, typename _Alloc>
1280     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1281     basic_string<_CharT, _Traits, _Alloc>::
1282     find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
1283     _GLIBCXX_NOEXCEPT
1284     {
1285       __glibcxx_requires_string_len(__s, __n);
1286       for (; __n && __pos < this->size(); ++__pos)
1287         {
1288           const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
1289           if (__p)
1290             return __pos;
1291         }
1292       return npos;
1293     }
1295   template<typename _CharT, typename _Traits, typename _Alloc>
1296     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1297     basic_string<_CharT, _Traits, _Alloc>::
1298     find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
1299     _GLIBCXX_NOEXCEPT
1300     {
1301       __glibcxx_requires_string_len(__s, __n);
1302       size_type __size = this->size();
1303       if (__size && __n)
1304         {
1305           if (--__size > __pos)
1306             __size = __pos;
1307           do
1308             {
1309               if (traits_type::find(__s, __n, _M_data()[__size]))
1310                 return __size;
1311             }
1312           while (__size-- != 0);
1313         }
1314       return npos;
1315     }
1317   template<typename _CharT, typename _Traits, typename _Alloc>
1318     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1319     basic_string<_CharT, _Traits, _Alloc>::
1320     find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1321     _GLIBCXX_NOEXCEPT
1322     {
1323       __glibcxx_requires_string_len(__s, __n);
1324       for (; __pos < this->size(); ++__pos)
1325         if (!traits_type::find(__s, __n, _M_data()[__pos]))
1326           return __pos;
1327       return npos;
1328     }
1330   template<typename _CharT, typename _Traits, typename _Alloc>
1331     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1332     basic_string<_CharT, _Traits, _Alloc>::
1333     find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1334     {
1335       for (; __pos < this->size(); ++__pos)
1336         if (!traits_type::eq(_M_data()[__pos], __c))
1337           return __pos;
1338       return npos;
1339     }
1341   template<typename _CharT, typename _Traits, typename _Alloc>
1342     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1343     basic_string<_CharT, _Traits, _Alloc>::
1344     find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
1345     _GLIBCXX_NOEXCEPT
1346     {
1347       __glibcxx_requires_string_len(__s, __n);
1348       size_type __size = this->size();
1349       if (__size)
1350         {
1351           if (--__size > __pos)
1352             __size = __pos;
1353           do
1354             {
1355               if (!traits_type::find(__s, __n, _M_data()[__size]))
1356                 return __size;
1357             }
1358           while (__size--);
1359         }
1360       return npos;
1361     }
1363   template<typename _CharT, typename _Traits, typename _Alloc>
1364     typename basic_string<_CharT, _Traits, _Alloc>::size_type
1365     basic_string<_CharT, _Traits, _Alloc>::
1366     find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
1367     {
1368       size_type __size = this->size();
1369       if (__size)
1370         {
1371           if (--__size > __pos)
1372             __size = __pos;
1373           do
1374             {
1375               if (!traits_type::eq(_M_data()[__size], __c))
1376                 return __size;
1377             }
1378           while (__size--);
1379         }
1380       return npos;
1381     }
1383   template<typename _CharT, typename _Traits, typename _Alloc>
1384     int
1385     basic_string<_CharT, _Traits, _Alloc>::
1386     compare(size_type __pos, size_type __n, const basic_string& __str) const
1387     {
1388       _M_check(__pos, "basic_string::compare");
1389       __n = _M_limit(__pos, __n);
1390       const size_type __osize = __str.size();
1391       const size_type __len = std::min(__n, __osize);
1392       int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
1393       if (!__r)
1394         __r = _S_compare(__n, __osize);
1395       return __r;
1396     }
1398   template<typename _CharT, typename _Traits, typename _Alloc>
1399     int
1400     basic_string<_CharT, _Traits, _Alloc>::
1401     compare(size_type __pos1, size_type __n1, const basic_string& __str,
1402             size_type __pos2, size_type __n2) const
1403     {
1404       _M_check(__pos1, "basic_string::compare");
1405       __str._M_check(__pos2, "basic_string::compare");
1406       __n1 = _M_limit(__pos1, __n1);
1407       __n2 = __str._M_limit(__pos2, __n2);
1408       const size_type __len = std::min(__n1, __n2);
1409       int __r = traits_type::compare(_M_data() + __pos1,
1410                                      __str.data() + __pos2, __len);
1411       if (!__r)
1412         __r = _S_compare(__n1, __n2);
1413       return __r;
1414     }
1416   template<typename _CharT, typename _Traits, typename _Alloc>
1417     int
1418     basic_string<_CharT, _Traits, _Alloc>::
1419     compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT
1420     {
1421       __glibcxx_requires_string(__s);
1422       const size_type __size = this->size();
1423       const size_type __osize = traits_type::length(__s);
1424       const size_type __len = std::min(__size, __osize);
1425       int __r = traits_type::compare(_M_data(), __s, __len);
1426       if (!__r)
1427         __r = _S_compare(__size, __osize);
1428       return __r;
1429     }
1431   template<typename _CharT, typename _Traits, typename _Alloc>
1432     int
1433     basic_string <_CharT, _Traits, _Alloc>::
1434     compare(size_type __pos, size_type __n1, const _CharT* __s) const
1435     {
1436       __glibcxx_requires_string(__s);
1437       _M_check(__pos, "basic_string::compare");
1438       __n1 = _M_limit(__pos, __n1);
1439       const size_type __osize = traits_type::length(__s);
1440       const size_type __len = std::min(__n1, __osize);
1441       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1442       if (!__r)
1443         __r = _S_compare(__n1, __osize);
1444       return __r;
1445     }
1447   template<typename _CharT, typename _Traits, typename _Alloc>
1448     int
1449     basic_string <_CharT, _Traits, _Alloc>::
1450     compare(size_type __pos, size_type __n1, const _CharT* __s,
1451             size_type __n2) const
1452     {
1453       __glibcxx_requires_string_len(__s, __n2);
1454       _M_check(__pos, "basic_string::compare");
1455       __n1 = _M_limit(__pos, __n1);
1456       const size_type __len = std::min(__n1, __n2);
1457       int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1458       if (!__r)
1459         __r = _S_compare(__n1, __n2);
1460       return __r;
1461     }
1463   // 21.3.7.9 basic_string::getline and operators
1464   template<typename _CharT, typename _Traits, typename _Alloc>
1465     basic_istream<_CharT, _Traits>&
1466     operator>>(basic_istream<_CharT, _Traits>& __in,
1467                basic_string<_CharT, _Traits, _Alloc>& __str)
1468     {
1469       typedef basic_istream<_CharT, _Traits>            __istream_type;
1470       typedef basic_string<_CharT, _Traits, _Alloc>     __string_type;
1471       typedef typename __istream_type::ios_base         __ios_base;
1472       typedef typename __istream_type::int_type         __int_type;
1473       typedef typename __string_type::size_type         __size_type;
1474       typedef ctype<_CharT>                             __ctype_type;
1475       typedef typename __ctype_type::ctype_base         __ctype_base;
1477       __size_type __extracted = 0;
1478       typename __ios_base::iostate __err = __ios_base::goodbit;
1479       typename __istream_type::sentry __cerb(__in, false);
1480       if (__cerb)
1481         {
1482           __try
1483             {
1484               // Avoid reallocation for common case.
1485               __str.erase();
1486               _CharT __buf[128];
1487               __size_type __len = 0;          
1488               const streamsize __w = __in.width();
1489               const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
1490                                               : __str.max_size();
1491               const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
1492               const __int_type __eof = _Traits::eof();
1493               __int_type __c = __in.rdbuf()->sgetc();
1495               while (__extracted < __n
1496                      && !_Traits::eq_int_type(__c, __eof)
1497                      && !__ct.is(__ctype_base::space,
1498                                  _Traits::to_char_type(__c)))
1499                 {
1500                   if (__len == sizeof(__buf) / sizeof(_CharT))
1501                     {
1502                       __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
1503                       __len = 0;
1504                     }
1505                   __buf[__len++] = _Traits::to_char_type(__c);
1506                   ++__extracted;
1507                   __c = __in.rdbuf()->snextc();
1508                 }
1509               __str.append(__buf, __len);
1511               if (_Traits::eq_int_type(__c, __eof))
1512                 __err |= __ios_base::eofbit;
1513               __in.width(0);
1514             }
1515           __catch(__cxxabiv1::__forced_unwind&)
1516             {
1517               __in._M_setstate(__ios_base::badbit);
1518               __throw_exception_again;
1519             }
1520           __catch(...)
1521             {
1522               // _GLIBCXX_RESOLVE_LIB_DEFECTS
1523               // 91. Description of operator>> and getline() for string<>
1524               // might cause endless loop
1525               __in._M_setstate(__ios_base::badbit);
1526             }
1527         }
1528       // 211.  operator>>(istream&, string&) doesn't set failbit
1529       if (!__extracted)
1530         __err |= __ios_base::failbit;
1531       if (__err)
1532         __in.setstate(__err);
1533       return __in;
1534     }
1536   template<typename _CharT, typename _Traits, typename _Alloc>
1537     basic_istream<_CharT, _Traits>&
1538     getline(basic_istream<_CharT, _Traits>& __in,
1539             basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
1540     {
1541       typedef basic_istream<_CharT, _Traits>            __istream_type;
1542       typedef basic_string<_CharT, _Traits, _Alloc>     __string_type;
1543       typedef typename __istream_type::ios_base         __ios_base;
1544       typedef typename __istream_type::int_type         __int_type;
1545       typedef typename __string_type::size_type         __size_type;
1547       __size_type __extracted = 0;
1548       const __size_type __n = __str.max_size();
1549       typename __ios_base::iostate __err = __ios_base::goodbit;
1550       typename __istream_type::sentry __cerb(__in, true);
1551       if (__cerb)
1552         {
1553           __try
1554             {
1555               __str.erase();
1556               const __int_type __idelim = _Traits::to_int_type(__delim);
1557               const __int_type __eof = _Traits::eof();
1558               __int_type __c = __in.rdbuf()->sgetc();
1560               while (__extracted < __n
1561                      && !_Traits::eq_int_type(__c, __eof)
1562                      && !_Traits::eq_int_type(__c, __idelim))
1563                 {
1564                   __str += _Traits::to_char_type(__c);
1565                   ++__extracted;
1566                   __c = __in.rdbuf()->snextc();
1567                 }
1569               if (_Traits::eq_int_type(__c, __eof))
1570                 __err |= __ios_base::eofbit;
1571               else if (_Traits::eq_int_type(__c, __idelim))
1572                 {
1573                   ++__extracted;                  
1574                   __in.rdbuf()->sbumpc();
1575                 }
1576               else
1577                 __err |= __ios_base::failbit;
1578             }
1579           __catch(__cxxabiv1::__forced_unwind&)
1580             {
1581               __in._M_setstate(__ios_base::badbit);
1582               __throw_exception_again;
1583             }
1584           __catch(...)
1585             {
1586               // _GLIBCXX_RESOLVE_LIB_DEFECTS
1587               // 91. Description of operator>> and getline() for string<>
1588               // might cause endless loop
1589               __in._M_setstate(__ios_base::badbit);
1590             }
1591         }
1592       if (!__extracted)
1593         __err |= __ios_base::failbit;
1594       if (__err)
1595         __in.setstate(__err);
1596       return __in;
1597     }
1599   // Inhibit implicit instantiations for required instantiations,
1600   // which are defined via explicit instantiations elsewhere.
1601 #if _GLIBCXX_EXTERN_TEMPLATE
1602   // The explicit instantiations definitions in src/c++11/string-inst.cc
1603   // are compiled as C++14, so the new C++17 members aren't instantiated.
1604   // Until those definitions are compiled as C++17 suppress the declaration,
1605   // so C++17 code will implicitly instantiate std::string and std::wstring
1606   // as needed.
1607 # if __cplusplus <= 201402L && _GLIBCXX_EXTERN_TEMPLATE > 0
1608   extern template class basic_string<char>;
1609 # elif ! _GLIBCXX_USE_CXX11_ABI
1610   // Still need to prevent implicit instantiation of the COW empty rep,
1611   // to ensure the definition in libstdc++.so is unique (PR 86138).
1612   extern template basic_string<char>::size_type
1613     basic_string<char>::_Rep::_S_empty_rep_storage[];
1614 # endif
1616   extern template
1617     basic_istream<char>&
1618     operator>>(basic_istream<char>&, string&);
1619   extern template
1620     basic_ostream<char>&
1621     operator<<(basic_ostream<char>&, const string&);
1622   extern template
1623     basic_istream<char>&
1624     getline(basic_istream<char>&, string&, char);
1625   extern template
1626     basic_istream<char>&
1627     getline(basic_istream<char>&, string&);
1629 #ifdef _GLIBCXX_USE_WCHAR_T
1630 # if __cplusplus <= 201402L && _GLIBCXX_EXTERN_TEMPLATE > 0
1631   extern template class basic_string<wchar_t>;
1632 # elif ! _GLIBCXX_USE_CXX11_ABI
1633   extern template basic_string<wchar_t>::size_type
1634     basic_string<wchar_t>::_Rep::_S_empty_rep_storage[];
1635 # endif
1637   extern template
1638     basic_istream<wchar_t>&
1639     operator>>(basic_istream<wchar_t>&, wstring&);
1640   extern template
1641     basic_ostream<wchar_t>&
1642     operator<<(basic_ostream<wchar_t>&, const wstring&);
1643   extern template
1644     basic_istream<wchar_t>&
1645     getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1646   extern template
1647     basic_istream<wchar_t>&
1648     getline(basic_istream<wchar_t>&, wstring&);
1649 #endif // _GLIBCXX_USE_WCHAR_T
1650 #endif // _GLIBCXX_EXTERN_TEMPLATE
1652 _GLIBCXX_END_NAMESPACE_VERSION
1653 } // namespace std
1655 #endif