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