libstdc++
basic_string.tcc
Go to the documentation of this file.
1 // Components for manipulating sequences of characters -*- C++ -*-
2 
3 // Copyright (C) 1997-2014 Free Software Foundation, Inc.
4 //
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 3, or (at your option)
9 // any later version.
10 
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 
16 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
19 
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
24 
25 /** @file bits/basic_string.tcc
26  * This is an internal header file, included by other library headers.
27  * Do not attempt to use it directly. @headername{string}
28  */
29 
30 //
31 // ISO C++ 14882: 21 Strings library
32 //
33 
34 // Written by Jason Merrill based upon the specification by Takanori Adachi
35 // in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882.
36 
37 #ifndef _BASIC_STRING_TCC
38 #define _BASIC_STRING_TCC 1
39 
40 #pragma GCC system_header
41 
42 #include <bits/cxxabi_forced.h>
43 
44 namespace std _GLIBCXX_VISIBILITY(default)
45 {
46 _GLIBCXX_BEGIN_NAMESPACE_VERSION
47 
48  template<typename _CharT, typename _Traits, typename _Alloc>
49  const typename basic_string<_CharT, _Traits, _Alloc>::size_type
50  basic_string<_CharT, _Traits, _Alloc>::
51  _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
52 
53  template<typename _CharT, typename _Traits, typename _Alloc>
54  const _CharT
55  basic_string<_CharT, _Traits, _Alloc>::
56  _Rep::_S_terminal = _CharT();
57 
58  template<typename _CharT, typename _Traits, typename _Alloc>
59  const typename basic_string<_CharT, _Traits, _Alloc>::size_type
60  basic_string<_CharT, _Traits, _Alloc>::npos;
61 
62  // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
63  // at static init time (before static ctors are run).
64  template<typename _CharT, typename _Traits, typename _Alloc>
65  typename basic_string<_CharT, _Traits, _Alloc>::size_type
66  basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
67  (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
68  sizeof(size_type)];
69 
70  // NB: This is the special case for Input Iterators, used in
71  // istreambuf_iterators, etc.
72  // Input Iterators have a cost structure very different from
73  // pointers, calling for a different coding style.
74  template<typename _CharT, typename _Traits, typename _Alloc>
75  template<typename _InIterator>
76  _CharT*
77  basic_string<_CharT, _Traits, _Alloc>::
78  _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
79  input_iterator_tag)
80  {
81 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
82  if (__beg == __end && __a == _Alloc())
83  return _S_empty_rep()._M_refdata();
84 #endif
85  // Avoid reallocation for common case.
86  _CharT __buf[128];
87  size_type __len = 0;
88  while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
89  {
90  __buf[__len++] = *__beg;
91  ++__beg;
92  }
93  _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
94  _M_copy(__r->_M_refdata(), __buf, __len);
95  __try
96  {
97  while (__beg != __end)
98  {
99  if (__len == __r->_M_capacity)
100  {
101  // Allocate more space.
102  _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
103  _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
104  __r->_M_destroy(__a);
105  __r = __another;
106  }
107  __r->_M_refdata()[__len++] = *__beg;
108  ++__beg;
109  }
110  }
111  __catch(...)
112  {
113  __r->_M_destroy(__a);
114  __throw_exception_again;
115  }
116  __r->_M_set_length_and_sharable(__len);
117  return __r->_M_refdata();
118  }
119 
120  template<typename _CharT, typename _Traits, typename _Alloc>
121  template <typename _InIterator>
122  _CharT*
123  basic_string<_CharT, _Traits, _Alloc>::
124  _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
125  forward_iterator_tag)
126  {
127 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
128  if (__beg == __end && __a == _Alloc())
129  return _S_empty_rep()._M_refdata();
130 #endif
131  // NB: Not required, but considered best practice.
132  if (__gnu_cxx::__is_null_pointer(__beg) && __beg != __end)
133  __throw_logic_error(__N("basic_string::_S_construct null not valid"));
134 
135  const size_type __dnew = static_cast<size_type>(std::distance(__beg,
136  __end));
137  // Check for out_of_range and length_error exceptions.
138  _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
139  __try
140  { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
141  __catch(...)
142  {
143  __r->_M_destroy(__a);
144  __throw_exception_again;
145  }
146  __r->_M_set_length_and_sharable(__dnew);
147  return __r->_M_refdata();
148  }
149 
150  template<typename _CharT, typename _Traits, typename _Alloc>
151  _CharT*
152  basic_string<_CharT, _Traits, _Alloc>::
153  _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
154  {
155 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
156  if (__n == 0 && __a == _Alloc())
157  return _S_empty_rep()._M_refdata();
158 #endif
159  // Check for out_of_range and length_error exceptions.
160  _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
161  if (__n)
162  _M_assign(__r->_M_refdata(), __n, __c);
163 
164  __r->_M_set_length_and_sharable(__n);
165  return __r->_M_refdata();
166  }
167 
168  template<typename _CharT, typename _Traits, typename _Alloc>
171  : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
172  __str.get_allocator()),
173  __str.get_allocator())
174  { }
175 
176  template<typename _CharT, typename _Traits, typename _Alloc>
178  basic_string(const _Alloc& __a)
179  : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
180  { }
181 
182  template<typename _CharT, typename _Traits, typename _Alloc>
184  basic_string(const basic_string& __str, size_type __pos, size_type __n)
185  : _M_dataplus(_S_construct(__str._M_data()
186  + __str._M_check(__pos,
187  "basic_string::basic_string"),
188  __str._M_data() + __str._M_limit(__pos, __n)
189  + __pos, _Alloc()), _Alloc())
190  { }
191 
192  template<typename _CharT, typename _Traits, typename _Alloc>
194  basic_string(const basic_string& __str, size_type __pos,
195  size_type __n, const _Alloc& __a)
196  : _M_dataplus(_S_construct(__str._M_data()
197  + __str._M_check(__pos,
198  "basic_string::basic_string"),
199  __str._M_data() + __str._M_limit(__pos, __n)
200  + __pos, __a), __a)
201  { }
202 
203  // TBD: DPG annotate
204  template<typename _CharT, typename _Traits, typename _Alloc>
206  basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
207  : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
208  { }
209 
210  // TBD: DPG annotate
211  template<typename _CharT, typename _Traits, typename _Alloc>
213  basic_string(const _CharT* __s, const _Alloc& __a)
214  : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
215  __s + npos, __a), __a)
216  { }
217 
218  template<typename _CharT, typename _Traits, typename _Alloc>
220  basic_string(size_type __n, _CharT __c, const _Alloc& __a)
221  : _M_dataplus(_S_construct(__n, __c, __a), __a)
222  { }
223 
224  // TBD: DPG annotate
225  template<typename _CharT, typename _Traits, typename _Alloc>
226  template<typename _InputIterator>
228  basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
229  : _M_dataplus(_S_construct(__beg, __end, __a), __a)
230  { }
231 
232 #if __cplusplus >= 201103L
233  template<typename _CharT, typename _Traits, typename _Alloc>
236  : _M_dataplus(_S_construct(__l.begin(), __l.end(), __a), __a)
237  { }
238 #endif
239 
240  template<typename _CharT, typename _Traits, typename _Alloc>
243  assign(const basic_string& __str)
244  {
245  if (_M_rep() != __str._M_rep())
246  {
247  // XXX MT
248  const allocator_type __a = this->get_allocator();
249  _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
250  _M_rep()->_M_dispose(__a);
251  _M_data(__tmp);
252  }
253  return *this;
254  }
255 
256  template<typename _CharT, typename _Traits, typename _Alloc>
259  assign(const _CharT* __s, size_type __n)
260  {
261  __glibcxx_requires_string_len(__s, __n);
262  _M_check_length(this->size(), __n, "basic_string::assign");
263  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
264  return _M_replace_safe(size_type(0), this->size(), __s, __n);
265  else
266  {
267  // Work in-place.
268  const size_type __pos = __s - _M_data();
269  if (__pos >= __n)
270  _M_copy(_M_data(), __s, __n);
271  else if (__pos)
272  _M_move(_M_data(), __s, __n);
273  _M_rep()->_M_set_length_and_sharable(__n);
274  return *this;
275  }
276  }
277 
278  template<typename _CharT, typename _Traits, typename _Alloc>
281  append(size_type __n, _CharT __c)
282  {
283  if (__n)
284  {
285  _M_check_length(size_type(0), __n, "basic_string::append");
286  const size_type __len = __n + this->size();
287  if (__len > this->capacity() || _M_rep()->_M_is_shared())
288  this->reserve(__len);
289  _M_assign(_M_data() + this->size(), __n, __c);
290  _M_rep()->_M_set_length_and_sharable(__len);
291  }
292  return *this;
293  }
294 
295  template<typename _CharT, typename _Traits, typename _Alloc>
298  append(const _CharT* __s, size_type __n)
299  {
300  __glibcxx_requires_string_len(__s, __n);
301  if (__n)
302  {
303  _M_check_length(size_type(0), __n, "basic_string::append");
304  const size_type __len = __n + this->size();
305  if (__len > this->capacity() || _M_rep()->_M_is_shared())
306  {
307  if (_M_disjunct(__s))
308  this->reserve(__len);
309  else
310  {
311  const size_type __off = __s - _M_data();
312  this->reserve(__len);
313  __s = _M_data() + __off;
314  }
315  }
316  _M_copy(_M_data() + this->size(), __s, __n);
317  _M_rep()->_M_set_length_and_sharable(__len);
318  }
319  return *this;
320  }
321 
322  template<typename _CharT, typename _Traits, typename _Alloc>
325  append(const basic_string& __str)
326  {
327  const size_type __size = __str.size();
328  if (__size)
329  {
330  const size_type __len = __size + this->size();
331  if (__len > this->capacity() || _M_rep()->_M_is_shared())
332  this->reserve(__len);
333  _M_copy(_M_data() + this->size(), __str._M_data(), __size);
334  _M_rep()->_M_set_length_and_sharable(__len);
335  }
336  return *this;
337  }
338 
339  template<typename _CharT, typename _Traits, typename _Alloc>
342  append(const basic_string& __str, size_type __pos, size_type __n)
343  {
344  __str._M_check(__pos, "basic_string::append");
345  __n = __str._M_limit(__pos, __n);
346  if (__n)
347  {
348  const size_type __len = __n + this->size();
349  if (__len > this->capacity() || _M_rep()->_M_is_shared())
350  this->reserve(__len);
351  _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
352  _M_rep()->_M_set_length_and_sharable(__len);
353  }
354  return *this;
355  }
356 
357  template<typename _CharT, typename _Traits, typename _Alloc>
360  insert(size_type __pos, const _CharT* __s, size_type __n)
361  {
362  __glibcxx_requires_string_len(__s, __n);
363  _M_check(__pos, "basic_string::insert");
364  _M_check_length(size_type(0), __n, "basic_string::insert");
365  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
366  return _M_replace_safe(__pos, size_type(0), __s, __n);
367  else
368  {
369  // Work in-place.
370  const size_type __off = __s - _M_data();
371  _M_mutate(__pos, 0, __n);
372  __s = _M_data() + __off;
373  _CharT* __p = _M_data() + __pos;
374  if (__s + __n <= __p)
375  _M_copy(__p, __s, __n);
376  else if (__s >= __p)
377  _M_copy(__p, __s + __n, __n);
378  else
379  {
380  const size_type __nleft = __p - __s;
381  _M_copy(__p, __s, __nleft);
382  _M_copy(__p + __nleft, __p + __n, __n - __nleft);
383  }
384  return *this;
385  }
386  }
387 
388  template<typename _CharT, typename _Traits, typename _Alloc>
389  typename basic_string<_CharT, _Traits, _Alloc>::iterator
391  erase(iterator __first, iterator __last)
392  {
393  _GLIBCXX_DEBUG_PEDASSERT(__first >= _M_ibegin() && __first <= __last
394  && __last <= _M_iend());
395 
396  // NB: This isn't just an optimization (bail out early when
397  // there is nothing to do, really), it's also a correctness
398  // issue vs MT, see libstdc++/40518.
399  const size_type __size = __last - __first;
400  if (__size)
401  {
402  const size_type __pos = __first - _M_ibegin();
403  _M_mutate(__pos, __size, size_type(0));
404  _M_rep()->_M_set_leaked();
405  return iterator(_M_data() + __pos);
406  }
407  else
408  return __first;
409  }
410 
411  template<typename _CharT, typename _Traits, typename _Alloc>
414  replace(size_type __pos, size_type __n1, const _CharT* __s,
415  size_type __n2)
416  {
417  __glibcxx_requires_string_len(__s, __n2);
418  _M_check(__pos, "basic_string::replace");
419  __n1 = _M_limit(__pos, __n1);
420  _M_check_length(__n1, __n2, "basic_string::replace");
421  bool __left;
422  if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
423  return _M_replace_safe(__pos, __n1, __s, __n2);
424  else if ((__left = __s + __n2 <= _M_data() + __pos)
425  || _M_data() + __pos + __n1 <= __s)
426  {
427  // Work in-place: non-overlapping case.
428  size_type __off = __s - _M_data();
429  __left ? __off : (__off += __n2 - __n1);
430  _M_mutate(__pos, __n1, __n2);
431  _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
432  return *this;
433  }
434  else
435  {
436  // Todo: overlapping case.
437  const basic_string __tmp(__s, __n2);
438  return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
439  }
440  }
441 
442  template<typename _CharT, typename _Traits, typename _Alloc>
443  void
445  _M_destroy(const _Alloc& __a) throw ()
446  {
447  const size_type __size = sizeof(_Rep_base) +
448  (this->_M_capacity + 1) * sizeof(_CharT);
449  _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
450  }
451 
452  template<typename _CharT, typename _Traits, typename _Alloc>
453  void
454  basic_string<_CharT, _Traits, _Alloc>::
455  _M_leak_hard()
456  {
457 #if _GLIBCXX_FULLY_DYNAMIC_STRING == 0
458  if (_M_rep() == &_S_empty_rep())
459  return;
460 #endif
461  if (_M_rep()->_M_is_shared())
462  _M_mutate(0, 0, 0);
463  _M_rep()->_M_set_leaked();
464  }
465 
466  template<typename _CharT, typename _Traits, typename _Alloc>
467  void
468  basic_string<_CharT, _Traits, _Alloc>::
469  _M_mutate(size_type __pos, size_type __len1, size_type __len2)
470  {
471  const size_type __old_size = this->size();
472  const size_type __new_size = __old_size + __len2 - __len1;
473  const size_type __how_much = __old_size - __pos - __len1;
474 
475  if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
476  {
477  // Must reallocate.
478  const allocator_type __a = get_allocator();
479  _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
480 
481  if (__pos)
482  _M_copy(__r->_M_refdata(), _M_data(), __pos);
483  if (__how_much)
484  _M_copy(__r->_M_refdata() + __pos + __len2,
485  _M_data() + __pos + __len1, __how_much);
486 
487  _M_rep()->_M_dispose(__a);
488  _M_data(__r->_M_refdata());
489  }
490  else if (__how_much && __len1 != __len2)
491  {
492  // Work in-place.
493  _M_move(_M_data() + __pos + __len2,
494  _M_data() + __pos + __len1, __how_much);
495  }
496  _M_rep()->_M_set_length_and_sharable(__new_size);
497  }
498 
499  template<typename _CharT, typename _Traits, typename _Alloc>
500  void
502  reserve(size_type __res)
503  {
504  if (__res != this->capacity() || _M_rep()->_M_is_shared())
505  {
506  // Make sure we don't shrink below the current size
507  if (__res < this->size())
508  __res = this->size();
509  const allocator_type __a = get_allocator();
510  _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
511  _M_rep()->_M_dispose(__a);
512  _M_data(__tmp);
513  }
514  }
515 
516  template<typename _CharT, typename _Traits, typename _Alloc>
517  void
520  {
521  if (_M_rep()->_M_is_leaked())
522  _M_rep()->_M_set_sharable();
523  if (__s._M_rep()->_M_is_leaked())
524  __s._M_rep()->_M_set_sharable();
525  if (this->get_allocator() == __s.get_allocator())
526  {
527  _CharT* __tmp = _M_data();
528  _M_data(__s._M_data());
529  __s._M_data(__tmp);
530  }
531  // The code below can usually be optimized away.
532  else
533  {
534  const basic_string __tmp1(_M_ibegin(), _M_iend(),
535  __s.get_allocator());
536  const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
537  this->get_allocator());
538  *this = __tmp2;
539  __s = __tmp1;
540  }
541  }
542 
543  template<typename _CharT, typename _Traits, typename _Alloc>
546  _S_create(size_type __capacity, size_type __old_capacity,
547  const _Alloc& __alloc)
548  {
549  // _GLIBCXX_RESOLVE_LIB_DEFECTS
550  // 83. String::npos vs. string::max_size()
551  if (__capacity > _S_max_size)
552  __throw_length_error(__N("basic_string::_S_create"));
553 
554  // The standard places no restriction on allocating more memory
555  // than is strictly needed within this layer at the moment or as
556  // requested by an explicit application call to reserve().
557 
558  // Many malloc implementations perform quite poorly when an
559  // application attempts to allocate memory in a stepwise fashion
560  // growing each allocation size by only 1 char. Additionally,
561  // it makes little sense to allocate less linear memory than the
562  // natural blocking size of the malloc implementation.
563  // Unfortunately, we would need a somewhat low-level calculation
564  // with tuned parameters to get this perfect for any particular
565  // malloc implementation. Fortunately, generalizations about
566  // common features seen among implementations seems to suffice.
567 
568  // __pagesize need not match the actual VM page size for good
569  // results in practice, thus we pick a common value on the low
570  // side. __malloc_header_size is an estimate of the amount of
571  // overhead per memory allocation (in practice seen N * sizeof
572  // (void*) where N is 0, 2 or 4). According to folklore,
573  // picking this value on the high side is better than
574  // low-balling it (especially when this algorithm is used with
575  // malloc implementations that allocate memory blocks rounded up
576  // to a size which is a power of 2).
577  const size_type __pagesize = 4096;
578  const size_type __malloc_header_size = 4 * sizeof(void*);
579 
580  // The below implements an exponential growth policy, necessary to
581  // meet amortized linear time requirements of the library: see
582  // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
583  // It's active for allocations requiring an amount of memory above
584  // system pagesize. This is consistent with the requirements of the
585  // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
586  if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
587  __capacity = 2 * __old_capacity;
588 
589  // NB: Need an array of char_type[__capacity], plus a terminating
590  // null char_type() element, plus enough for the _Rep data structure.
591  // Whew. Seemingly so needy, yet so elemental.
592  size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
593 
594  const size_type __adj_size = __size + __malloc_header_size;
595  if (__adj_size > __pagesize && __capacity > __old_capacity)
596  {
597  const size_type __extra = __pagesize - __adj_size % __pagesize;
598  __capacity += __extra / sizeof(_CharT);
599  // Never allocate a string bigger than _S_max_size.
600  if (__capacity > _S_max_size)
601  __capacity = _S_max_size;
602  __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
603  }
604 
605  // NB: Might throw, but no worries about a leak, mate: _Rep()
606  // does not throw.
607  void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
608  _Rep *__p = new (__place) _Rep;
609  __p->_M_capacity = __capacity;
610  // ABI compatibility - 3.4.x set in _S_create both
611  // _M_refcount and _M_length. All callers of _S_create
612  // in basic_string.tcc then set just _M_length.
613  // In 4.0.x and later both _M_refcount and _M_length
614  // are initialized in the callers, unfortunately we can
615  // have 3.4.x compiled code with _S_create callers inlined
616  // calling 4.0.x+ _S_create.
617  __p->_M_set_sharable();
618  return __p;
619  }
620 
621  template<typename _CharT, typename _Traits, typename _Alloc>
622  _CharT*
623  basic_string<_CharT, _Traits, _Alloc>::_Rep::
624  _M_clone(const _Alloc& __alloc, size_type __res)
625  {
626  // Requested capacity of the clone.
627  const size_type __requested_cap = this->_M_length + __res;
628  _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
629  __alloc);
630  if (this->_M_length)
631  _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
632 
633  __r->_M_set_length_and_sharable(this->_M_length);
634  return __r->_M_refdata();
635  }
636 
637  template<typename _CharT, typename _Traits, typename _Alloc>
638  void
640  resize(size_type __n, _CharT __c)
641  {
642  const size_type __size = this->size();
643  _M_check_length(__size, __n, "basic_string::resize");
644  if (__size < __n)
645  this->append(__n - __size, __c);
646  else if (__n < __size)
647  this->erase(__n);
648  // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
649  }
650 
651  template<typename _CharT, typename _Traits, typename _Alloc>
652  template<typename _InputIterator>
655  _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
656  _InputIterator __k2, __false_type)
657  {
658  const basic_string __s(__k1, __k2);
659  const size_type __n1 = __i2 - __i1;
660  _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
661  return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
662  __s.size());
663  }
664 
665  template<typename _CharT, typename _Traits, typename _Alloc>
666  basic_string<_CharT, _Traits, _Alloc>&
667  basic_string<_CharT, _Traits, _Alloc>::
668  _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
669  _CharT __c)
670  {
671  _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
672  _M_mutate(__pos1, __n1, __n2);
673  if (__n2)
674  _M_assign(_M_data() + __pos1, __n2, __c);
675  return *this;
676  }
677 
678  template<typename _CharT, typename _Traits, typename _Alloc>
679  basic_string<_CharT, _Traits, _Alloc>&
680  basic_string<_CharT, _Traits, _Alloc>::
681  _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
682  size_type __n2)
683  {
684  _M_mutate(__pos1, __n1, __n2);
685  if (__n2)
686  _M_copy(_M_data() + __pos1, __s, __n2);
687  return *this;
688  }
689 
690  template<typename _CharT, typename _Traits, typename _Alloc>
691  basic_string<_CharT, _Traits, _Alloc>
692  operator+(const _CharT* __lhs,
694  {
695  __glibcxx_requires_string(__lhs);
696  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
697  typedef typename __string_type::size_type __size_type;
698  const __size_type __len = _Traits::length(__lhs);
699  __string_type __str;
700  __str.reserve(__len + __rhs.size());
701  __str.append(__lhs, __len);
702  __str.append(__rhs);
703  return __str;
704  }
705 
706  template<typename _CharT, typename _Traits, typename _Alloc>
707  basic_string<_CharT, _Traits, _Alloc>
709  {
710  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
711  typedef typename __string_type::size_type __size_type;
712  __string_type __str;
713  const __size_type __len = __rhs.size();
714  __str.reserve(__len + 1);
715  __str.append(__size_type(1), __lhs);
716  __str.append(__rhs);
717  return __str;
718  }
719 
720  template<typename _CharT, typename _Traits, typename _Alloc>
721  typename basic_string<_CharT, _Traits, _Alloc>::size_type
723  copy(_CharT* __s, size_type __n, size_type __pos) const
724  {
725  _M_check(__pos, "basic_string::copy");
726  __n = _M_limit(__pos, __n);
727  __glibcxx_requires_string_len(__s, __n);
728  if (__n)
729  _M_copy(__s, _M_data() + __pos, __n);
730  // 21.3.5.7 par 3: do not append null. (good.)
731  return __n;
732  }
733 
734  template<typename _CharT, typename _Traits, typename _Alloc>
735  typename basic_string<_CharT, _Traits, _Alloc>::size_type
737  find(const _CharT* __s, size_type __pos, size_type __n) const
738  {
739  __glibcxx_requires_string_len(__s, __n);
740  const size_type __size = this->size();
741  const _CharT* __data = _M_data();
742 
743  if (__n == 0)
744  return __pos <= __size ? __pos : npos;
745 
746  if (__n <= __size)
747  {
748  for (; __pos <= __size - __n; ++__pos)
749  if (traits_type::eq(__data[__pos], __s[0])
750  && traits_type::compare(__data + __pos + 1,
751  __s + 1, __n - 1) == 0)
752  return __pos;
753  }
754  return npos;
755  }
756 
757  template<typename _CharT, typename _Traits, typename _Alloc>
758  typename basic_string<_CharT, _Traits, _Alloc>::size_type
760  find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
761  {
762  size_type __ret = npos;
763  const size_type __size = this->size();
764  if (__pos < __size)
765  {
766  const _CharT* __data = _M_data();
767  const size_type __n = __size - __pos;
768  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
769  if (__p)
770  __ret = __p - __data;
771  }
772  return __ret;
773  }
774 
775  template<typename _CharT, typename _Traits, typename _Alloc>
776  typename basic_string<_CharT, _Traits, _Alloc>::size_type
778  rfind(const _CharT* __s, size_type __pos, size_type __n) const
779  {
780  __glibcxx_requires_string_len(__s, __n);
781  const size_type __size = this->size();
782  if (__n <= __size)
783  {
784  __pos = std::min(size_type(__size - __n), __pos);
785  const _CharT* __data = _M_data();
786  do
787  {
788  if (traits_type::compare(__data + __pos, __s, __n) == 0)
789  return __pos;
790  }
791  while (__pos-- > 0);
792  }
793  return npos;
794  }
795 
796  template<typename _CharT, typename _Traits, typename _Alloc>
797  typename basic_string<_CharT, _Traits, _Alloc>::size_type
799  rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
800  {
801  size_type __size = this->size();
802  if (__size)
803  {
804  if (--__size > __pos)
805  __size = __pos;
806  for (++__size; __size-- > 0; )
807  if (traits_type::eq(_M_data()[__size], __c))
808  return __size;
809  }
810  return npos;
811  }
812 
813  template<typename _CharT, typename _Traits, typename _Alloc>
814  typename basic_string<_CharT, _Traits, _Alloc>::size_type
816  find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
817  {
818  __glibcxx_requires_string_len(__s, __n);
819  for (; __n && __pos < this->size(); ++__pos)
820  {
821  const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
822  if (__p)
823  return __pos;
824  }
825  return npos;
826  }
827 
828  template<typename _CharT, typename _Traits, typename _Alloc>
829  typename basic_string<_CharT, _Traits, _Alloc>::size_type
831  find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
832  {
833  __glibcxx_requires_string_len(__s, __n);
834  size_type __size = this->size();
835  if (__size && __n)
836  {
837  if (--__size > __pos)
838  __size = __pos;
839  do
840  {
841  if (traits_type::find(__s, __n, _M_data()[__size]))
842  return __size;
843  }
844  while (__size-- != 0);
845  }
846  return npos;
847  }
848 
849  template<typename _CharT, typename _Traits, typename _Alloc>
850  typename basic_string<_CharT, _Traits, _Alloc>::size_type
852  find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
853  {
854  __glibcxx_requires_string_len(__s, __n);
855  for (; __pos < this->size(); ++__pos)
856  if (!traits_type::find(__s, __n, _M_data()[__pos]))
857  return __pos;
858  return npos;
859  }
860 
861  template<typename _CharT, typename _Traits, typename _Alloc>
862  typename basic_string<_CharT, _Traits, _Alloc>::size_type
864  find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
865  {
866  for (; __pos < this->size(); ++__pos)
867  if (!traits_type::eq(_M_data()[__pos], __c))
868  return __pos;
869  return npos;
870  }
871 
872  template<typename _CharT, typename _Traits, typename _Alloc>
873  typename basic_string<_CharT, _Traits, _Alloc>::size_type
875  find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
876  {
877  __glibcxx_requires_string_len(__s, __n);
878  size_type __size = this->size();
879  if (__size)
880  {
881  if (--__size > __pos)
882  __size = __pos;
883  do
884  {
885  if (!traits_type::find(__s, __n, _M_data()[__size]))
886  return __size;
887  }
888  while (__size--);
889  }
890  return npos;
891  }
892 
893  template<typename _CharT, typename _Traits, typename _Alloc>
894  typename basic_string<_CharT, _Traits, _Alloc>::size_type
896  find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
897  {
898  size_type __size = this->size();
899  if (__size)
900  {
901  if (--__size > __pos)
902  __size = __pos;
903  do
904  {
905  if (!traits_type::eq(_M_data()[__size], __c))
906  return __size;
907  }
908  while (__size--);
909  }
910  return npos;
911  }
912 
913  template<typename _CharT, typename _Traits, typename _Alloc>
914  int
916  compare(size_type __pos, size_type __n, const basic_string& __str) const
917  {
918  _M_check(__pos, "basic_string::compare");
919  __n = _M_limit(__pos, __n);
920  const size_type __osize = __str.size();
921  const size_type __len = std::min(__n, __osize);
922  int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
923  if (!__r)
924  __r = _S_compare(__n, __osize);
925  return __r;
926  }
927 
928  template<typename _CharT, typename _Traits, typename _Alloc>
929  int
931  compare(size_type __pos1, size_type __n1, const basic_string& __str,
932  size_type __pos2, size_type __n2) const
933  {
934  _M_check(__pos1, "basic_string::compare");
935  __str._M_check(__pos2, "basic_string::compare");
936  __n1 = _M_limit(__pos1, __n1);
937  __n2 = __str._M_limit(__pos2, __n2);
938  const size_type __len = std::min(__n1, __n2);
939  int __r = traits_type::compare(_M_data() + __pos1,
940  __str.data() + __pos2, __len);
941  if (!__r)
942  __r = _S_compare(__n1, __n2);
943  return __r;
944  }
945 
946  template<typename _CharT, typename _Traits, typename _Alloc>
947  int
949  compare(const _CharT* __s) const
950  {
951  __glibcxx_requires_string(__s);
952  const size_type __size = this->size();
953  const size_type __osize = traits_type::length(__s);
954  const size_type __len = std::min(__size, __osize);
955  int __r = traits_type::compare(_M_data(), __s, __len);
956  if (!__r)
957  __r = _S_compare(__size, __osize);
958  return __r;
959  }
960 
961  template<typename _CharT, typename _Traits, typename _Alloc>
962  int
964  compare(size_type __pos, size_type __n1, const _CharT* __s) const
965  {
966  __glibcxx_requires_string(__s);
967  _M_check(__pos, "basic_string::compare");
968  __n1 = _M_limit(__pos, __n1);
969  const size_type __osize = traits_type::length(__s);
970  const size_type __len = std::min(__n1, __osize);
971  int __r = traits_type::compare(_M_data() + __pos, __s, __len);
972  if (!__r)
973  __r = _S_compare(__n1, __osize);
974  return __r;
975  }
976 
977  template<typename _CharT, typename _Traits, typename _Alloc>
978  int
980  compare(size_type __pos, size_type __n1, const _CharT* __s,
981  size_type __n2) const
982  {
983  __glibcxx_requires_string_len(__s, __n2);
984  _M_check(__pos, "basic_string::compare");
985  __n1 = _M_limit(__pos, __n1);
986  const size_type __len = std::min(__n1, __n2);
987  int __r = traits_type::compare(_M_data() + __pos, __s, __len);
988  if (!__r)
989  __r = _S_compare(__n1, __n2);
990  return __r;
991  }
992 
993  // 21.3.7.9 basic_string::getline and operators
994  template<typename _CharT, typename _Traits, typename _Alloc>
998  {
999  typedef basic_istream<_CharT, _Traits> __istream_type;
1000  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1001  typedef typename __istream_type::ios_base __ios_base;
1002  typedef typename __istream_type::int_type __int_type;
1003  typedef typename __string_type::size_type __size_type;
1004  typedef ctype<_CharT> __ctype_type;
1005  typedef typename __ctype_type::ctype_base __ctype_base;
1006 
1007  __size_type __extracted = 0;
1008  typename __ios_base::iostate __err = __ios_base::goodbit;
1009  typename __istream_type::sentry __cerb(__in, false);
1010  if (__cerb)
1011  {
1012  __try
1013  {
1014  // Avoid reallocation for common case.
1015  __str.erase();
1016  _CharT __buf[128];
1017  __size_type __len = 0;
1018  const streamsize __w = __in.width();
1019  const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
1020  : __str.max_size();
1021  const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
1022  const __int_type __eof = _Traits::eof();
1023  __int_type __c = __in.rdbuf()->sgetc();
1024 
1025  while (__extracted < __n
1026  && !_Traits::eq_int_type(__c, __eof)
1027  && !__ct.is(__ctype_base::space,
1028  _Traits::to_char_type(__c)))
1029  {
1030  if (__len == sizeof(__buf) / sizeof(_CharT))
1031  {
1032  __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
1033  __len = 0;
1034  }
1035  __buf[__len++] = _Traits::to_char_type(__c);
1036  ++__extracted;
1037  __c = __in.rdbuf()->snextc();
1038  }
1039  __str.append(__buf, __len);
1040 
1041  if (_Traits::eq_int_type(__c, __eof))
1042  __err |= __ios_base::eofbit;
1043  __in.width(0);
1044  }
1045  __catch(__cxxabiv1::__forced_unwind&)
1046  {
1047  __in._M_setstate(__ios_base::badbit);
1048  __throw_exception_again;
1049  }
1050  __catch(...)
1051  {
1052  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1053  // 91. Description of operator>> and getline() for string<>
1054  // might cause endless loop
1055  __in._M_setstate(__ios_base::badbit);
1056  }
1057  }
1058  // 211. operator>>(istream&, string&) doesn't set failbit
1059  if (!__extracted)
1060  __err |= __ios_base::failbit;
1061  if (__err)
1062  __in.setstate(__err);
1063  return __in;
1064  }
1065 
1066  template<typename _CharT, typename _Traits, typename _Alloc>
1067  basic_istream<_CharT, _Traits>&
1069  basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
1070  {
1071  typedef basic_istream<_CharT, _Traits> __istream_type;
1072  typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1073  typedef typename __istream_type::ios_base __ios_base;
1074  typedef typename __istream_type::int_type __int_type;
1075  typedef typename __string_type::size_type __size_type;
1076 
1077  __size_type __extracted = 0;
1078  const __size_type __n = __str.max_size();
1079  typename __ios_base::iostate __err = __ios_base::goodbit;
1080  typename __istream_type::sentry __cerb(__in, true);
1081  if (__cerb)
1082  {
1083  __try
1084  {
1085  __str.erase();
1086  const __int_type __idelim = _Traits::to_int_type(__delim);
1087  const __int_type __eof = _Traits::eof();
1088  __int_type __c = __in.rdbuf()->sgetc();
1089 
1090  while (__extracted < __n
1091  && !_Traits::eq_int_type(__c, __eof)
1092  && !_Traits::eq_int_type(__c, __idelim))
1093  {
1094  __str += _Traits::to_char_type(__c);
1095  ++__extracted;
1096  __c = __in.rdbuf()->snextc();
1097  }
1098 
1099  if (_Traits::eq_int_type(__c, __eof))
1100  __err |= __ios_base::eofbit;
1101  else if (_Traits::eq_int_type(__c, __idelim))
1102  {
1103  ++__extracted;
1104  __in.rdbuf()->sbumpc();
1105  }
1106  else
1107  __err |= __ios_base::failbit;
1108  }
1109  __catch(__cxxabiv1::__forced_unwind&)
1110  {
1111  __in._M_setstate(__ios_base::badbit);
1112  __throw_exception_again;
1113  }
1114  __catch(...)
1115  {
1116  // _GLIBCXX_RESOLVE_LIB_DEFECTS
1117  // 91. Description of operator>> and getline() for string<>
1118  // might cause endless loop
1119  __in._M_setstate(__ios_base::badbit);
1120  }
1121  }
1122  if (!__extracted)
1123  __err |= __ios_base::failbit;
1124  if (__err)
1125  __in.setstate(__err);
1126  return __in;
1127  }
1128 
1129  // Inhibit implicit instantiations for required instantiations,
1130  // which are defined via explicit instantiations elsewhere.
1131 #if _GLIBCXX_EXTERN_TEMPLATE > 0
1132  extern template class basic_string<char>;
1133  extern template
1134  basic_istream<char>&
1135  operator>>(basic_istream<char>&, string&);
1136  extern template
1137  basic_ostream<char>&
1138  operator<<(basic_ostream<char>&, const string&);
1139  extern template
1140  basic_istream<char>&
1141  getline(basic_istream<char>&, string&, char);
1142  extern template
1143  basic_istream<char>&
1144  getline(basic_istream<char>&, string&);
1145 
1146 #ifdef _GLIBCXX_USE_WCHAR_T
1147  extern template class basic_string<wchar_t>;
1148  extern template
1149  basic_istream<wchar_t>&
1150  operator>>(basic_istream<wchar_t>&, wstring&);
1151  extern template
1152  basic_ostream<wchar_t>&
1153  operator<<(basic_ostream<wchar_t>&, const wstring&);
1154  extern template
1155  basic_istream<wchar_t>&
1156  getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1157  extern template
1158  basic_istream<wchar_t>&
1159  getline(basic_istream<wchar_t>&, wstring&);
1160 #endif
1161 #endif
1162 
1163 _GLIBCXX_END_NAMESPACE_VERSION
1164 } // namespace std
1165 
1166 #endif
void resize(size_type __n, _CharT __c)
Resizes the string to the specified number of characters.
const _CharT * data() const noexcept
Return const pointer to contents.
complex< _Tp > operator+(const complex< _Tp > &__x, const complex< _Tp > &__y)
Return new complex value x plus y.
Definition: complex:321
size_type find(const _CharT *__s, size_type __pos, size_type __n) const
Find position of a C substring.
size_type find_last_not_of(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a character not in string.
Primary class template ctype facet.This template class defines classification and conversion function...
allocator_type get_allocator() const noexcept
Return copy of allocator used to construct this string.
constexpr const _Tp * begin(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to the first element of the initializer_list.
size_type max_size() const noexcept
Returns the size() of the largest possible string.
Definition: basic_string.h:735
basic_istream< _CharT, _Traits > & getline(basic_istream< _CharT, _Traits > &__is, basic_string< _CharT, _Traits, _Alloc > &__str, _CharT __delim)
Read a line from stream into a string.
Template class basic_istream.
Definition: iosfwd:83
basic_string & erase(size_type __pos=0, size_type __n=npos)
Remove characters.
constexpr size_t size() const noexcept
Returns the total number of bits.
Definition: bitset:1293
size_type size() const noexcept
Returns the number of characters in the string, not including any null-termination.
Definition: basic_string.h:724
size_type copy(_CharT *__s, size_type __n, size_type __pos=0) const
Copy substring into C string.
size_type find_first_not_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character not in string.
basic_string< wchar_t > wstring
A string of wchar_t.
Definition: stringfwd.h:68
locale getloc() const
Locale access.
Definition: ios_base.h:695
iterator_traits< _InputIterator >::difference_type distance(_InputIterator __first, _InputIterator __last)
A generalization of pointer arithmetic.
basic_streambuf< _CharT, _Traits > * rdbuf() const
Accessing the underlying buffer.
Definition: basic_ios.h:315
void swap(basic_string &__s)
Swap contents with another string.
Thrown as part of forced unwinding.A magic placeholder class that can be caught by reference to recog...
Definition: cxxabi_forced.h:48
const _Tp & min(const _Tp &, const _Tp &)
This does what you think it does.
Definition: stl_algobase.h:194
size_type find_first_of(const basic_string &__str, size_type __pos=0) const noexcept
Find position of a character of string.
basic_string(const _Alloc &__a)
Construct an empty string using allocator a.
void insert(iterator __p, size_type __n, _CharT __c)
Insert multiple characters.
void setstate(iostate __state)
Sets additional flags in the error state.
Definition: basic_ios.h:151
constexpr const _Tp * end(initializer_list< _Tp > __ils) noexcept
Return an iterator pointing to one past the last element of the initializer_list. ...
basic_string & append(const basic_string &__str)
Append a string to this string.
bitset< _Nb > operator>>(size_t __position) const noexcept
Self-explanatory.
Definition: bitset:1353
Common iterator class.
initializer_list
int compare(const basic_string &__str) const
Compare to a string.
basic_string & replace(size_type __pos, size_type __n, const basic_string &__str)
Replace characters with value from another string.
streamsize width() const
Flags access.
Definition: ios_base.h:644
Managing sequences of characters and character-like objects.
Definition: basic_string.h:112
size_type rfind(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a string.
ptrdiff_t streamsize
Integral type for I/O operation counts and buffer sizes.
Definition: postypes.h:98
void reserve(size_type __res_arg=0)
Attempt to preallocate enough memory for specified number of characters.
basic_string & assign(const basic_string &__str)
Set value to contents of another string.
size_type find_last_of(const basic_string &__str, size_type __pos=npos) const noexcept
Find last position of a character of string.