libstdc++
vstring.tcc
Go to the documentation of this file.
1 // Versatile string -*- C++ -*-
2 
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011
4 // Free Software Foundation, Inc.
5 //
6 // This file is part of the GNU ISO C++ Library. This library is free
7 // software; you can redistribute it and/or modify it under the
8 // terms of the GNU General Public License as published by the
9 // Free Software Foundation; either version 3, or (at your option)
10 // any later version.
11 
12 // This library is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
16 
17 // Under Section 7 of GPL version 3, you are granted additional
18 // permissions described in the GCC Runtime Library Exception, version
19 // 3.1, as published by the Free Software Foundation.
20 
21 // You should have received a copy of the GNU General Public License and
22 // a copy of the GCC Runtime Library Exception along with this program;
23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 // <http://www.gnu.org/licenses/>.
25 
26 /** @file ext/vstring.tcc
27  * This is an internal header file, included by other library headers.
28  * Do not attempt to use it directly. @headername{ext/vstring.h}
29  */
30 
31 #ifndef _VSTRING_TCC
32 #define _VSTRING_TCC 1
33 
34 #pragma GCC system_header
35 
36 #include <bits/cxxabi_forced.h>
37 
38 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
39 {
40 _GLIBCXX_BEGIN_NAMESPACE_VERSION
41 
42  template<typename _CharT, typename _Traits, typename _Alloc,
43  template <typename, typename, typename> class _Base>
44  const typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
45  __versa_string<_CharT, _Traits, _Alloc, _Base>::npos;
46 
47  template<typename _CharT, typename _Traits, typename _Alloc,
48  template <typename, typename, typename> class _Base>
49  void
51  resize(size_type __n, _CharT __c)
52  {
53  const size_type __size = this->size();
54  if (__size < __n)
55  this->append(__n - __size, __c);
56  else if (__n < __size)
57  this->_M_erase(__n, __size - __n);
58  }
59 
60  template<typename _CharT, typename _Traits, typename _Alloc,
61  template <typename, typename, typename> class _Base>
64  _M_append(const _CharT* __s, size_type __n)
65  {
66  const size_type __len = __n + this->size();
67 
68  if (__len <= this->capacity() && !this->_M_is_shared())
69  {
70  if (__n)
71  this->_S_copy(this->_M_data() + this->size(), __s, __n);
72  }
73  else
74  this->_M_mutate(this->size(), size_type(0), __s, __n);
75 
76  this->_M_set_length(__len);
77  return *this;
78  }
79 
80  template<typename _CharT, typename _Traits, typename _Alloc,
81  template <typename, typename, typename> class _Base>
82  template<typename _InputIterator>
83  __versa_string<_CharT, _Traits, _Alloc, _Base>&
84  __versa_string<_CharT, _Traits, _Alloc, _Base>::
85  _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
86  _InputIterator __k2, std::__false_type)
87  {
88  const __versa_string __s(__k1, __k2);
89  const size_type __n1 = __i2 - __i1;
90  return _M_replace(__i1 - _M_ibegin(), __n1, __s._M_data(),
91  __s.size());
92  }
93 
94  template<typename _CharT, typename _Traits, typename _Alloc,
95  template <typename, typename, typename> class _Base>
96  __versa_string<_CharT, _Traits, _Alloc, _Base>&
97  __versa_string<_CharT, _Traits, _Alloc, _Base>::
98  _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
99  _CharT __c)
100  {
101  _M_check_length(__n1, __n2, "__versa_string::_M_replace_aux");
102 
103  const size_type __old_size = this->size();
104  const size_type __new_size = __old_size + __n2 - __n1;
105 
106  if (__new_size <= this->capacity() && !this->_M_is_shared())
107  {
108  _CharT* __p = this->_M_data() + __pos1;
109 
110  const size_type __how_much = __old_size - __pos1 - __n1;
111  if (__how_much && __n1 != __n2)
112  this->_S_move(__p + __n2, __p + __n1, __how_much);
113  }
114  else
115  this->_M_mutate(__pos1, __n1, 0, __n2);
116 
117  if (__n2)
118  this->_S_assign(this->_M_data() + __pos1, __n2, __c);
119 
120  this->_M_set_length(__new_size);
121  return *this;
122  }
123 
124  template<typename _CharT, typename _Traits, typename _Alloc,
125  template <typename, typename, typename> class _Base>
126  __versa_string<_CharT, _Traits, _Alloc, _Base>&
127  __versa_string<_CharT, _Traits, _Alloc, _Base>::
128  _M_replace(size_type __pos, size_type __len1, const _CharT* __s,
129  const size_type __len2)
130  {
131  _M_check_length(__len1, __len2, "__versa_string::_M_replace");
132 
133  const size_type __old_size = this->size();
134  const size_type __new_size = __old_size + __len2 - __len1;
135 
136  if (__new_size <= this->capacity() && !this->_M_is_shared())
137  {
138  _CharT* __p = this->_M_data() + __pos;
139 
140  const size_type __how_much = __old_size - __pos - __len1;
141  if (_M_disjunct(__s))
142  {
143  if (__how_much && __len1 != __len2)
144  this->_S_move(__p + __len2, __p + __len1, __how_much);
145  if (__len2)
146  this->_S_copy(__p, __s, __len2);
147  }
148  else
149  {
150  // Work in-place.
151  if (__len2 && __len2 <= __len1)
152  this->_S_move(__p, __s, __len2);
153  if (__how_much && __len1 != __len2)
154  this->_S_move(__p + __len2, __p + __len1, __how_much);
155  if (__len2 > __len1)
156  {
157  if (__s + __len2 <= __p + __len1)
158  this->_S_move(__p, __s, __len2);
159  else if (__s >= __p + __len1)
160  this->_S_copy(__p, __s + __len2 - __len1, __len2);
161  else
162  {
163  const size_type __nleft = (__p + __len1) - __s;
164  this->_S_move(__p, __s, __nleft);
165  this->_S_copy(__p + __nleft, __p + __len2,
166  __len2 - __nleft);
167  }
168  }
169  }
170  }
171  else
172  this->_M_mutate(__pos, __len1, __s, __len2);
173 
174  this->_M_set_length(__new_size);
175  return *this;
176  }
177 
178  template<typename _CharT, typename _Traits, typename _Alloc,
179  template <typename, typename, typename> class _Base>
180  __versa_string<_CharT, _Traits, _Alloc, _Base>
183  {
185  __str.reserve(__lhs.size() + __rhs.size());
186  __str.append(__lhs);
187  __str.append(__rhs);
188  return __str;
189  }
190 
191  template<typename _CharT, typename _Traits, typename _Alloc,
192  template <typename, typename, typename> class _Base>
193  __versa_string<_CharT, _Traits, _Alloc, _Base>
194  operator+(const _CharT* __lhs,
196  {
197  __glibcxx_requires_string(__lhs);
199  typedef typename __string_type::size_type __size_type;
200  const __size_type __len = _Traits::length(__lhs);
201  __string_type __str;
202  __str.reserve(__len + __rhs.size());
203  __str.append(__lhs, __len);
204  __str.append(__rhs);
205  return __str;
206  }
207 
208  template<typename _CharT, typename _Traits, typename _Alloc,
209  template <typename, typename, typename> class _Base>
210  __versa_string<_CharT, _Traits, _Alloc, _Base>
211  operator+(_CharT __lhs,
213  {
215  __str.reserve(__rhs.size() + 1);
216  __str.push_back(__lhs);
217  __str.append(__rhs);
218  return __str;
219  }
220 
221  template<typename _CharT, typename _Traits, typename _Alloc,
222  template <typename, typename, typename> class _Base>
223  __versa_string<_CharT, _Traits, _Alloc, _Base>
225  const _CharT* __rhs)
226  {
227  __glibcxx_requires_string(__rhs);
229  typedef typename __string_type::size_type __size_type;
230  const __size_type __len = _Traits::length(__rhs);
231  __string_type __str;
232  __str.reserve(__lhs.size() + __len);
233  __str.append(__lhs);
234  __str.append(__rhs, __len);
235  return __str;
236  }
237 
238  template<typename _CharT, typename _Traits, typename _Alloc,
239  template <typename, typename, typename> class _Base>
240  __versa_string<_CharT, _Traits, _Alloc, _Base>
242  _CharT __rhs)
243  {
245  __str.reserve(__lhs.size() + 1);
246  __str.append(__lhs);
247  __str.push_back(__rhs);
248  return __str;
249  }
250 
251  template<typename _CharT, typename _Traits, typename _Alloc,
252  template <typename, typename, typename> class _Base>
253  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
255  copy(_CharT* __s, size_type __n, size_type __pos) const
256  {
257  _M_check(__pos, "__versa_string::copy");
258  __n = _M_limit(__pos, __n);
259  __glibcxx_requires_string_len(__s, __n);
260  if (__n)
261  this->_S_copy(__s, this->_M_data() + __pos, __n);
262  // 21.3.5.7 par 3: do not append null. (good.)
263  return __n;
264  }
265 
266  template<typename _CharT, typename _Traits, typename _Alloc,
267  template <typename, typename, typename> class _Base>
268  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
270  find(const _CharT* __s, size_type __pos, size_type __n) const
271  {
272  __glibcxx_requires_string_len(__s, __n);
273  const size_type __size = this->size();
274  const _CharT* __data = this->_M_data();
275 
276  if (__n == 0)
277  return __pos <= __size ? __pos : npos;
278 
279  if (__n <= __size)
280  {
281  for (; __pos <= __size - __n; ++__pos)
282  if (traits_type::eq(__data[__pos], __s[0])
283  && traits_type::compare(__data + __pos + 1,
284  __s + 1, __n - 1) == 0)
285  return __pos;
286  }
287  return npos;
288  }
289 
290  template<typename _CharT, typename _Traits, typename _Alloc,
291  template <typename, typename, typename> class _Base>
292  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
294  find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
295  {
296  size_type __ret = npos;
297  const size_type __size = this->size();
298  if (__pos < __size)
299  {
300  const _CharT* __data = this->_M_data();
301  const size_type __n = __size - __pos;
302  const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
303  if (__p)
304  __ret = __p - __data;
305  }
306  return __ret;
307  }
308 
309  template<typename _CharT, typename _Traits, typename _Alloc,
310  template <typename, typename, typename> class _Base>
311  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
313  rfind(const _CharT* __s, size_type __pos, size_type __n) const
314  {
315  __glibcxx_requires_string_len(__s, __n);
316  const size_type __size = this->size();
317  if (__n <= __size)
318  {
319  __pos = std::min(size_type(__size - __n), __pos);
320  const _CharT* __data = this->_M_data();
321  do
322  {
323  if (traits_type::compare(__data + __pos, __s, __n) == 0)
324  return __pos;
325  }
326  while (__pos-- > 0);
327  }
328  return npos;
329  }
330 
331  template<typename _CharT, typename _Traits, typename _Alloc,
332  template <typename, typename, typename> class _Base>
333  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
335  rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
336  {
337  size_type __size = this->size();
338  if (__size)
339  {
340  if (--__size > __pos)
341  __size = __pos;
342  for (++__size; __size-- > 0; )
343  if (traits_type::eq(this->_M_data()[__size], __c))
344  return __size;
345  }
346  return npos;
347  }
348 
349  template<typename _CharT, typename _Traits, typename _Alloc,
350  template <typename, typename, typename> class _Base>
351  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
353  find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
354  {
355  __glibcxx_requires_string_len(__s, __n);
356  for (; __n && __pos < this->size(); ++__pos)
357  {
358  const _CharT* __p = traits_type::find(__s, __n,
359  this->_M_data()[__pos]);
360  if (__p)
361  return __pos;
362  }
363  return npos;
364  }
365 
366  template<typename _CharT, typename _Traits, typename _Alloc,
367  template <typename, typename, typename> class _Base>
368  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
370  find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
371  {
372  __glibcxx_requires_string_len(__s, __n);
373  size_type __size = this->size();
374  if (__size && __n)
375  {
376  if (--__size > __pos)
377  __size = __pos;
378  do
379  {
380  if (traits_type::find(__s, __n, this->_M_data()[__size]))
381  return __size;
382  }
383  while (__size-- != 0);
384  }
385  return npos;
386  }
387 
388  template<typename _CharT, typename _Traits, typename _Alloc,
389  template <typename, typename, typename> class _Base>
390  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
392  find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
393  {
394  __glibcxx_requires_string_len(__s, __n);
395  for (; __pos < this->size(); ++__pos)
396  if (!traits_type::find(__s, __n, this->_M_data()[__pos]))
397  return __pos;
398  return npos;
399  }
400 
401  template<typename _CharT, typename _Traits, typename _Alloc,
402  template <typename, typename, typename> class _Base>
403  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
405  find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
406  {
407  for (; __pos < this->size(); ++__pos)
408  if (!traits_type::eq(this->_M_data()[__pos], __c))
409  return __pos;
410  return npos;
411  }
412 
413  template<typename _CharT, typename _Traits, typename _Alloc,
414  template <typename, typename, typename> class _Base>
415  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
417  find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
418  {
419  __glibcxx_requires_string_len(__s, __n);
420  size_type __size = this->size();
421  if (__size)
422  {
423  if (--__size > __pos)
424  __size = __pos;
425  do
426  {
427  if (!traits_type::find(__s, __n, this->_M_data()[__size]))
428  return __size;
429  }
430  while (__size--);
431  }
432  return npos;
433  }
434 
435  template<typename _CharT, typename _Traits, typename _Alloc,
436  template <typename, typename, typename> class _Base>
437  typename __versa_string<_CharT, _Traits, _Alloc, _Base>::size_type
439  find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT
440  {
441  size_type __size = this->size();
442  if (__size)
443  {
444  if (--__size > __pos)
445  __size = __pos;
446  do
447  {
448  if (!traits_type::eq(this->_M_data()[__size], __c))
449  return __size;
450  }
451  while (__size--);
452  }
453  return npos;
454  }
455 
456  template<typename _CharT, typename _Traits, typename _Alloc,
457  template <typename, typename, typename> class _Base>
458  int
460  compare(size_type __pos, size_type __n, const __versa_string& __str) const
461  {
462  _M_check(__pos, "__versa_string::compare");
463  __n = _M_limit(__pos, __n);
464  const size_type __osize = __str.size();
465  const size_type __len = std::min(__n, __osize);
466  int __r = traits_type::compare(this->_M_data() + __pos,
467  __str.data(), __len);
468  if (!__r)
469  __r = this->_S_compare(__n, __osize);
470  return __r;
471  }
472 
473  template<typename _CharT, typename _Traits, typename _Alloc,
474  template <typename, typename, typename> class _Base>
475  int
477  compare(size_type __pos1, size_type __n1, const __versa_string& __str,
478  size_type __pos2, size_type __n2) const
479  {
480  _M_check(__pos1, "__versa_string::compare");
481  __str._M_check(__pos2, "__versa_string::compare");
482  __n1 = _M_limit(__pos1, __n1);
483  __n2 = __str._M_limit(__pos2, __n2);
484  const size_type __len = std::min(__n1, __n2);
485  int __r = traits_type::compare(this->_M_data() + __pos1,
486  __str.data() + __pos2, __len);
487  if (!__r)
488  __r = this->_S_compare(__n1, __n2);
489  return __r;
490  }
491 
492  template<typename _CharT, typename _Traits, typename _Alloc,
493  template <typename, typename, typename> class _Base>
494  int
496  compare(const _CharT* __s) const
497  {
498  __glibcxx_requires_string(__s);
499  const size_type __size = this->size();
500  const size_type __osize = traits_type::length(__s);
501  const size_type __len = std::min(__size, __osize);
502  int __r = traits_type::compare(this->_M_data(), __s, __len);
503  if (!__r)
504  __r = this->_S_compare(__size, __osize);
505  return __r;
506  }
507 
508  template<typename _CharT, typename _Traits, typename _Alloc,
509  template <typename, typename, typename> class _Base>
510  int
512  compare(size_type __pos, size_type __n1, const _CharT* __s) const
513  {
514  __glibcxx_requires_string(__s);
515  _M_check(__pos, "__versa_string::compare");
516  __n1 = _M_limit(__pos, __n1);
517  const size_type __osize = traits_type::length(__s);
518  const size_type __len = std::min(__n1, __osize);
519  int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
520  if (!__r)
521  __r = this->_S_compare(__n1, __osize);
522  return __r;
523  }
524 
525  template<typename _CharT, typename _Traits, typename _Alloc,
526  template <typename, typename, typename> class _Base>
527  int
529  compare(size_type __pos, size_type __n1, const _CharT* __s,
530  size_type __n2) const
531  {
532  __glibcxx_requires_string_len(__s, __n2);
533  _M_check(__pos, "__versa_string::compare");
534  __n1 = _M_limit(__pos, __n1);
535  const size_type __len = std::min(__n1, __n2);
536  int __r = traits_type::compare(this->_M_data() + __pos, __s, __len);
537  if (!__r)
538  __r = this->_S_compare(__n1, __n2);
539  return __r;
540  }
541 
542 _GLIBCXX_END_NAMESPACE_VERSION
543 } // namespace
544 
545 namespace std _GLIBCXX_VISIBILITY(default)
546 {
547 _GLIBCXX_BEGIN_NAMESPACE_VERSION
548 
549  template<typename _CharT, typename _Traits, typename _Alloc,
550  template <typename, typename, typename> class _Base>
551  basic_istream<_CharT, _Traits>&
553  __gnu_cxx::__versa_string<_CharT, _Traits,
554  _Alloc, _Base>& __str)
555  {
556  typedef basic_istream<_CharT, _Traits> __istream_type;
557  typedef typename __istream_type::ios_base __ios_base;
559  __string_type;
560  typedef typename __istream_type::int_type __int_type;
561  typedef typename __string_type::size_type __size_type;
562  typedef ctype<_CharT> __ctype_type;
563  typedef typename __ctype_type::ctype_base __ctype_base;
564 
565  __size_type __extracted = 0;
566  typename __ios_base::iostate __err = __ios_base::goodbit;
567  typename __istream_type::sentry __cerb(__in, false);
568  if (__cerb)
569  {
570  __try
571  {
572  // Avoid reallocation for common case.
573  __str.erase();
574  _CharT __buf[128];
575  __size_type __len = 0;
576  const streamsize __w = __in.width();
577  const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
578  : __str.max_size();
579  const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
580  const __int_type __eof = _Traits::eof();
581  __int_type __c = __in.rdbuf()->sgetc();
582 
583  while (__extracted < __n
584  && !_Traits::eq_int_type(__c, __eof)
585  && !__ct.is(__ctype_base::space,
586  _Traits::to_char_type(__c)))
587  {
588  if (__len == sizeof(__buf) / sizeof(_CharT))
589  {
590  __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
591  __len = 0;
592  }
593  __buf[__len++] = _Traits::to_char_type(__c);
594  ++__extracted;
595  __c = __in.rdbuf()->snextc();
596  }
597  __str.append(__buf, __len);
598 
599  if (_Traits::eq_int_type(__c, __eof))
600  __err |= __ios_base::eofbit;
601  __in.width(0);
602  }
604  {
605  __in._M_setstate(__ios_base::badbit);
606  __throw_exception_again;
607  }
608  __catch(...)
609  {
610  // _GLIBCXX_RESOLVE_LIB_DEFECTS
611  // 91. Description of operator>> and getline() for string<>
612  // might cause endless loop
613  __in._M_setstate(__ios_base::badbit);
614  }
615  }
616  // 211. operator>>(istream&, string&) doesn't set failbit
617  if (!__extracted)
618  __err |= __ios_base::failbit;
619  if (__err)
620  __in.setstate(__err);
621  return __in;
622  }
623 
624  template<typename _CharT, typename _Traits, typename _Alloc,
625  template <typename, typename, typename> class _Base>
626  basic_istream<_CharT, _Traits>&
629  _CharT __delim)
630  {
631  typedef basic_istream<_CharT, _Traits> __istream_type;
632  typedef typename __istream_type::ios_base __ios_base;
634  __string_type;
635  typedef typename __istream_type::int_type __int_type;
636  typedef typename __string_type::size_type __size_type;
637 
638  __size_type __extracted = 0;
639  const __size_type __n = __str.max_size();
640  typename __ios_base::iostate __err = __ios_base::goodbit;
641  typename __istream_type::sentry __cerb(__in, true);
642  if (__cerb)
643  {
644  __try
645  {
646  // Avoid reallocation for common case.
647  __str.erase();
648  _CharT __buf[128];
649  __size_type __len = 0;
650  const __int_type __idelim = _Traits::to_int_type(__delim);
651  const __int_type __eof = _Traits::eof();
652  __int_type __c = __in.rdbuf()->sgetc();
653 
654  while (__extracted < __n
655  && !_Traits::eq_int_type(__c, __eof)
656  && !_Traits::eq_int_type(__c, __idelim))
657  {
658  if (__len == sizeof(__buf) / sizeof(_CharT))
659  {
660  __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
661  __len = 0;
662  }
663  __buf[__len++] = _Traits::to_char_type(__c);
664  ++__extracted;
665  __c = __in.rdbuf()->snextc();
666  }
667  __str.append(__buf, __len);
668 
669  if (_Traits::eq_int_type(__c, __eof))
670  __err |= __ios_base::eofbit;
671  else if (_Traits::eq_int_type(__c, __idelim))
672  {
673  ++__extracted;
674  __in.rdbuf()->sbumpc();
675  }
676  else
677  __err |= __ios_base::failbit;
678  }
680  {
681  __in._M_setstate(__ios_base::badbit);
682  __throw_exception_again;
683  }
684  __catch(...)
685  {
686  // _GLIBCXX_RESOLVE_LIB_DEFECTS
687  // 91. Description of operator>> and getline() for string<>
688  // might cause endless loop
689  __in._M_setstate(__ios_base::badbit);
690  }
691  }
692  if (!__extracted)
693  __err |= __ios_base::failbit;
694  if (__err)
695  __in.setstate(__err);
696  return __in;
697  }
698 
699 _GLIBCXX_END_NAMESPACE_VERSION
700 } // namespace
701 
702 #endif // _VSTRING_TCC