1 // Components for manipulating sequences of characters -*- C++ -*-
3 // Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
5 // Free Software Foundation, Inc.
7 // This file is part of the GNU ISO C++ Library. This library is free
8 // software; you can redistribute it and/or modify it under the
9 // terms of the GNU General Public License as published by the
10 // Free Software Foundation; either version 2, or (at your option)
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License along
19 // with this library; see the file COPYING. If not, write to the Free
20 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
23 // As a special exception, you may use this file as part of a free software
24 // library without restriction. Specifically, if other files instantiate
25 // templates or use macros or inline functions from this file, or you compile
26 // this file and link it with other files to produce an executable, this
27 // file does not by itself cause the resulting executable to be covered by
28 // the GNU General Public License. This exception does not however
29 // invalidate any other reasons why the executable file might be covered by
30 // the GNU General Public License.
32 /** @file basic_string.tcc
33 * This is an internal header file, included by other library headers.
34 * You should not attempt to use it directly.
38 // ISO C++ 14882: 21 Strings library
41 // Written by Jason Merrill based upon the specification by Takanori Adachi
42 // in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882.
44 #ifndef _BASIC_STRING_TCC
45 #define _BASIC_STRING_TCC 1
47 #pragma GCC system_header
49 _GLIBCXX_BEGIN_NAMESPACE(std)
51 template<typename _CharT, typename _Traits, typename _Alloc>
52 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
53 basic_string<_CharT, _Traits, _Alloc>::
54 _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
56 template<typename _CharT, typename _Traits, typename _Alloc>
58 basic_string<_CharT, _Traits, _Alloc>::
59 _Rep::_S_terminal = _CharT();
61 template<typename _CharT, typename _Traits, typename _Alloc>
62 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
63 basic_string<_CharT, _Traits, _Alloc>::npos;
65 // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
66 // at static init time (before static ctors are run).
67 template<typename _CharT, typename _Traits, typename _Alloc>
68 typename basic_string<_CharT, _Traits, _Alloc>::size_type
69 basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
70 (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
73 // NB: This is the special case for Input Iterators, used in
74 // istreambuf_iterators, etc.
75 // Input Iterators have a cost structure very different from
76 // pointers, calling for a different coding style.
77 template<typename _CharT, typename _Traits, typename _Alloc>
78 template<typename _InIterator>
80 basic_string<_CharT, _Traits, _Alloc>::
81 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
84 #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
85 if (__beg == __end && __a == _Alloc())
86 return _S_empty_rep()._M_refdata();
88 // Avoid reallocation for common case.
91 while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
93 __buf[__len++] = *__beg;
96 _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
97 _M_copy(__r->_M_refdata(), __buf, __len);
100 while (__beg != __end)
102 if (__len == __r->_M_capacity)
104 // Allocate more space.
105 _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
106 _M_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
107 __r->_M_destroy(__a);
110 __r->_M_refdata()[__len++] = *__beg;
116 __r->_M_destroy(__a);
117 __throw_exception_again;
119 __r->_M_set_length_and_sharable(__len);
120 return __r->_M_refdata();
123 template<typename _CharT, typename _Traits, typename _Alloc>
124 template <typename _InIterator>
126 basic_string<_CharT, _Traits, _Alloc>::
127 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
128 forward_iterator_tag)
130 #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
131 if (__beg == __end && __a == _Alloc())
132 return _S_empty_rep()._M_refdata();
134 // NB: Not required, but considered best practice.
135 if (__builtin_expect(__gnu_cxx::__is_null_pointer(__beg)
136 && __beg != __end, 0))
137 __throw_logic_error(__N("basic_string::_S_construct NULL not valid"));
139 const size_type __dnew = static_cast<size_type>(std::distance(__beg,
141 // Check for out_of_range and length_error exceptions.
142 _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
144 { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
147 __r->_M_destroy(__a);
148 __throw_exception_again;
150 __r->_M_set_length_and_sharable(__dnew);
151 return __r->_M_refdata();
154 template<typename _CharT, typename _Traits, typename _Alloc>
156 basic_string<_CharT, _Traits, _Alloc>::
157 _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
159 #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
160 if (__n == 0 && __a == _Alloc())
161 return _S_empty_rep()._M_refdata();
163 // Check for out_of_range and length_error exceptions.
164 _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
166 _M_assign(__r->_M_refdata(), __n, __c);
168 __r->_M_set_length_and_sharable(__n);
169 return __r->_M_refdata();
172 template<typename _CharT, typename _Traits, typename _Alloc>
173 basic_string<_CharT, _Traits, _Alloc>::
174 basic_string(const basic_string& __str)
175 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
176 __str.get_allocator()),
177 __str.get_allocator())
180 template<typename _CharT, typename _Traits, typename _Alloc>
181 basic_string<_CharT, _Traits, _Alloc>::
182 basic_string(const _Alloc& __a)
183 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
186 template<typename _CharT, typename _Traits, typename _Alloc>
187 basic_string<_CharT, _Traits, _Alloc>::
188 basic_string(const basic_string& __str, size_type __pos, size_type __n)
189 : _M_dataplus(_S_construct(__str._M_data()
190 + __str._M_check(__pos,
191 "basic_string::basic_string"),
192 __str._M_data() + __str._M_limit(__pos, __n)
193 + __pos, _Alloc()), _Alloc())
196 template<typename _CharT, typename _Traits, typename _Alloc>
197 basic_string<_CharT, _Traits, _Alloc>::
198 basic_string(const basic_string& __str, size_type __pos,
199 size_type __n, const _Alloc& __a)
200 : _M_dataplus(_S_construct(__str._M_data()
201 + __str._M_check(__pos,
202 "basic_string::basic_string"),
203 __str._M_data() + __str._M_limit(__pos, __n)
208 template<typename _CharT, typename _Traits, typename _Alloc>
209 basic_string<_CharT, _Traits, _Alloc>::
210 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
211 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
215 template<typename _CharT, typename _Traits, typename _Alloc>
216 basic_string<_CharT, _Traits, _Alloc>::
217 basic_string(const _CharT* __s, const _Alloc& __a)
218 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
219 __s + npos, __a), __a)
222 template<typename _CharT, typename _Traits, typename _Alloc>
223 basic_string<_CharT, _Traits, _Alloc>::
224 basic_string(size_type __n, _CharT __c, const _Alloc& __a)
225 : _M_dataplus(_S_construct(__n, __c, __a), __a)
229 template<typename _CharT, typename _Traits, typename _Alloc>
230 template<typename _InputIterator>
231 basic_string<_CharT, _Traits, _Alloc>::
232 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
233 : _M_dataplus(_S_construct(__beg, __end, __a), __a)
236 template<typename _CharT, typename _Traits, typename _Alloc>
237 basic_string<_CharT, _Traits, _Alloc>&
238 basic_string<_CharT, _Traits, _Alloc>::
239 assign(const basic_string& __str)
241 if (_M_rep() != __str._M_rep())
244 const allocator_type __a = this->get_allocator();
245 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
246 _M_rep()->_M_dispose(__a);
252 template<typename _CharT, typename _Traits, typename _Alloc>
253 basic_string<_CharT, _Traits, _Alloc>&
254 basic_string<_CharT, _Traits, _Alloc>::
255 assign(const _CharT* __s, size_type __n)
257 __glibcxx_requires_string_len(__s, __n);
258 _M_check_length(this->size(), __n, "basic_string::assign");
259 if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
260 return _M_replace_safe(size_type(0), this->size(), __s, __n);
264 const size_type __pos = __s - _M_data();
266 _M_copy(_M_data(), __s, __n);
268 _M_move(_M_data(), __s, __n);
269 _M_rep()->_M_set_length_and_sharable(__n);
274 template<typename _CharT, typename _Traits, typename _Alloc>
275 basic_string<_CharT, _Traits, _Alloc>&
276 basic_string<_CharT, _Traits, _Alloc>::
277 append(size_type __n, _CharT __c)
281 _M_check_length(size_type(0), __n, "basic_string::append");
282 const size_type __len = __n + this->size();
283 if (__len > this->capacity() || _M_rep()->_M_is_shared())
284 this->reserve(__len);
285 _M_assign(_M_data() + this->size(), __n, __c);
286 _M_rep()->_M_set_length_and_sharable(__len);
291 template<typename _CharT, typename _Traits, typename _Alloc>
292 basic_string<_CharT, _Traits, _Alloc>&
293 basic_string<_CharT, _Traits, _Alloc>::
294 append(const _CharT* __s, size_type __n)
296 __glibcxx_requires_string_len(__s, __n);
299 _M_check_length(size_type(0), __n, "basic_string::append");
300 const size_type __len = __n + this->size();
301 if (__len > this->capacity() || _M_rep()->_M_is_shared())
303 if (_M_disjunct(__s))
304 this->reserve(__len);
307 const size_type __off = __s - _M_data();
308 this->reserve(__len);
309 __s = _M_data() + __off;
312 _M_copy(_M_data() + this->size(), __s, __n);
313 _M_rep()->_M_set_length_and_sharable(__len);
318 template<typename _CharT, typename _Traits, typename _Alloc>
319 basic_string<_CharT, _Traits, _Alloc>&
320 basic_string<_CharT, _Traits, _Alloc>::
321 append(const basic_string& __str)
323 const size_type __size = __str.size();
326 const size_type __len = __size + this->size();
327 if (__len > this->capacity() || _M_rep()->_M_is_shared())
328 this->reserve(__len);
329 _M_copy(_M_data() + this->size(), __str._M_data(), __size);
330 _M_rep()->_M_set_length_and_sharable(__len);
335 template<typename _CharT, typename _Traits, typename _Alloc>
336 basic_string<_CharT, _Traits, _Alloc>&
337 basic_string<_CharT, _Traits, _Alloc>::
338 append(const basic_string& __str, size_type __pos, size_type __n)
340 __str._M_check(__pos, "basic_string::append");
341 __n = __str._M_limit(__pos, __n);
344 const size_type __len = __n + this->size();
345 if (__len > this->capacity() || _M_rep()->_M_is_shared())
346 this->reserve(__len);
347 _M_copy(_M_data() + this->size(), __str._M_data() + __pos, __n);
348 _M_rep()->_M_set_length_and_sharable(__len);
353 template<typename _CharT, typename _Traits, typename _Alloc>
354 basic_string<_CharT, _Traits, _Alloc>&
355 basic_string<_CharT, _Traits, _Alloc>::
356 insert(size_type __pos, const _CharT* __s, size_type __n)
358 __glibcxx_requires_string_len(__s, __n);
359 _M_check(__pos, "basic_string::insert");
360 _M_check_length(size_type(0), __n, "basic_string::insert");
361 if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
362 return _M_replace_safe(__pos, size_type(0), __s, __n);
366 const size_type __off = __s - _M_data();
367 _M_mutate(__pos, 0, __n);
368 __s = _M_data() + __off;
369 _CharT* __p = _M_data() + __pos;
370 if (__s + __n <= __p)
371 _M_copy(__p, __s, __n);
373 _M_copy(__p, __s + __n, __n);
376 const size_type __nleft = __p - __s;
377 _M_copy(__p, __s, __nleft);
378 _M_copy(__p + __nleft, __p + __n, __n - __nleft);
384 template<typename _CharT, typename _Traits, typename _Alloc>
385 basic_string<_CharT, _Traits, _Alloc>&
386 basic_string<_CharT, _Traits, _Alloc>::
387 replace(size_type __pos, size_type __n1, const _CharT* __s,
390 __glibcxx_requires_string_len(__s, __n2);
391 _M_check(__pos, "basic_string::replace");
392 __n1 = _M_limit(__pos, __n1);
393 _M_check_length(__n1, __n2, "basic_string::replace");
395 if (_M_disjunct(__s) || _M_rep()->_M_is_shared())
396 return _M_replace_safe(__pos, __n1, __s, __n2);
397 else if ((__left = __s + __n2 <= _M_data() + __pos)
398 || _M_data() + __pos + __n1 <= __s)
400 // Work in-place: non-overlapping case.
401 size_type __off = __s - _M_data();
402 __left ? __off : (__off += __n2 - __n1);
403 _M_mutate(__pos, __n1, __n2);
404 _M_copy(_M_data() + __pos, _M_data() + __off, __n2);
409 // Todo: overlapping case.
410 const basic_string __tmp(__s, __n2);
411 return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
415 template<typename _CharT, typename _Traits, typename _Alloc>
417 basic_string<_CharT, _Traits, _Alloc>::_Rep::
418 _M_destroy(const _Alloc& __a) throw ()
420 const size_type __size = sizeof(_Rep_base) +
421 (this->_M_capacity + 1) * sizeof(_CharT);
422 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
425 template<typename _CharT, typename _Traits, typename _Alloc>
427 basic_string<_CharT, _Traits, _Alloc>::
430 #ifndef _GLIBCXX_FULLY_DYNAMIC_STRING
431 if (_M_rep() == &_S_empty_rep())
434 if (_M_rep()->_M_is_shared())
436 _M_rep()->_M_set_leaked();
439 template<typename _CharT, typename _Traits, typename _Alloc>
441 basic_string<_CharT, _Traits, _Alloc>::
442 _M_mutate(size_type __pos, size_type __len1, size_type __len2)
444 const size_type __old_size = this->size();
445 const size_type __new_size = __old_size + __len2 - __len1;
446 const size_type __how_much = __old_size - __pos - __len1;
448 if (__new_size > this->capacity() || _M_rep()->_M_is_shared())
451 const allocator_type __a = get_allocator();
452 _Rep* __r = _Rep::_S_create(__new_size, this->capacity(), __a);
455 _M_copy(__r->_M_refdata(), _M_data(), __pos);
457 _M_copy(__r->_M_refdata() + __pos + __len2,
458 _M_data() + __pos + __len1, __how_much);
460 _M_rep()->_M_dispose(__a);
461 _M_data(__r->_M_refdata());
463 else if (__how_much && __len1 != __len2)
466 _M_move(_M_data() + __pos + __len2,
467 _M_data() + __pos + __len1, __how_much);
469 _M_rep()->_M_set_length_and_sharable(__new_size);
472 template<typename _CharT, typename _Traits, typename _Alloc>
474 basic_string<_CharT, _Traits, _Alloc>::
475 reserve(size_type __res)
477 if (__res != this->capacity() || _M_rep()->_M_is_shared())
479 // Make sure we don't shrink below the current size
480 if (__res < this->size())
481 __res = this->size();
482 const allocator_type __a = get_allocator();
483 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
484 _M_rep()->_M_dispose(__a);
489 template<typename _CharT, typename _Traits, typename _Alloc>
491 basic_string<_CharT, _Traits, _Alloc>::
492 swap(basic_string& __s)
494 if (_M_rep()->_M_is_leaked())
495 _M_rep()->_M_set_sharable();
496 if (__s._M_rep()->_M_is_leaked())
497 __s._M_rep()->_M_set_sharable();
498 if (this->get_allocator() == __s.get_allocator())
500 _CharT* __tmp = _M_data();
501 _M_data(__s._M_data());
504 // The code below can usually be optimized away.
507 const basic_string __tmp1(_M_ibegin(), _M_iend(),
508 __s.get_allocator());
509 const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
510 this->get_allocator());
516 template<typename _CharT, typename _Traits, typename _Alloc>
517 typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
518 basic_string<_CharT, _Traits, _Alloc>::_Rep::
519 _S_create(size_type __capacity, size_type __old_capacity,
520 const _Alloc& __alloc)
522 // _GLIBCXX_RESOLVE_LIB_DEFECTS
523 // 83. String::npos vs. string::max_size()
524 if (__capacity > _S_max_size)
525 __throw_length_error(__N("basic_string::_S_create"));
527 // The standard places no restriction on allocating more memory
528 // than is strictly needed within this layer at the moment or as
529 // requested by an explicit application call to reserve().
531 // Many malloc implementations perform quite poorly when an
532 // application attempts to allocate memory in a stepwise fashion
533 // growing each allocation size by only 1 char. Additionally,
534 // it makes little sense to allocate less linear memory than the
535 // natural blocking size of the malloc implementation.
536 // Unfortunately, we would need a somewhat low-level calculation
537 // with tuned parameters to get this perfect for any particular
538 // malloc implementation. Fortunately, generalizations about
539 // common features seen among implementations seems to suffice.
541 // __pagesize need not match the actual VM page size for good
542 // results in practice, thus we pick a common value on the low
543 // side. __malloc_header_size is an estimate of the amount of
544 // overhead per memory allocation (in practice seen N * sizeof
545 // (void*) where N is 0, 2 or 4). According to folklore,
546 // picking this value on the high side is better than
547 // low-balling it (especially when this algorithm is used with
548 // malloc implementations that allocate memory blocks rounded up
549 // to a size which is a power of 2).
550 const size_type __pagesize = 4096;
551 const size_type __malloc_header_size = 4 * sizeof(void*);
553 // The below implements an exponential growth policy, necessary to
554 // meet amortized linear time requirements of the library: see
555 // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
556 // It's active for allocations requiring an amount of memory above
557 // system pagesize. This is consistent with the requirements of the
558 // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
559 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
560 __capacity = 2 * __old_capacity;
562 // NB: Need an array of char_type[__capacity], plus a terminating
563 // null char_type() element, plus enough for the _Rep data structure.
564 // Whew. Seemingly so needy, yet so elemental.
565 size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
567 const size_type __adj_size = __size + __malloc_header_size;
568 if (__adj_size > __pagesize && __capacity > __old_capacity)
570 const size_type __extra = __pagesize - __adj_size % __pagesize;
571 __capacity += __extra / sizeof(_CharT);
572 // Never allocate a string bigger than _S_max_size.
573 if (__capacity > _S_max_size)
574 __capacity = _S_max_size;
575 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
578 // NB: Might throw, but no worries about a leak, mate: _Rep()
580 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
581 _Rep *__p = new (__place) _Rep;
582 __p->_M_capacity = __capacity;
583 // ABI compatibility - 3.4.x set in _S_create both
584 // _M_refcount and _M_length. All callers of _S_create
585 // in basic_string.tcc then set just _M_length.
586 // In 4.0.x and later both _M_refcount and _M_length
587 // are initialized in the callers, unfortunately we can
588 // have 3.4.x compiled code with _S_create callers inlined
589 // calling 4.0.x+ _S_create.
590 __p->_M_set_sharable();
594 template<typename _CharT, typename _Traits, typename _Alloc>
596 basic_string<_CharT, _Traits, _Alloc>::_Rep::
597 _M_clone(const _Alloc& __alloc, size_type __res)
599 // Requested capacity of the clone.
600 const size_type __requested_cap = this->_M_length + __res;
601 _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
604 _M_copy(__r->_M_refdata(), _M_refdata(), this->_M_length);
606 __r->_M_set_length_and_sharable(this->_M_length);
607 return __r->_M_refdata();
610 template<typename _CharT, typename _Traits, typename _Alloc>
612 basic_string<_CharT, _Traits, _Alloc>::
613 resize(size_type __n, _CharT __c)
615 const size_type __size = this->size();
616 _M_check_length(__size, __n, "basic_string::resize");
618 this->append(__n - __size, __c);
619 else if (__n < __size)
621 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
624 template<typename _CharT, typename _Traits, typename _Alloc>
625 template<typename _InputIterator>
626 basic_string<_CharT, _Traits, _Alloc>&
627 basic_string<_CharT, _Traits, _Alloc>::
628 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
629 _InputIterator __k2, __false_type)
631 const basic_string __s(__k1, __k2);
632 const size_type __n1 = __i2 - __i1;
633 _M_check_length(__n1, __s.size(), "basic_string::_M_replace_dispatch");
634 return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
638 template<typename _CharT, typename _Traits, typename _Alloc>
639 basic_string<_CharT, _Traits, _Alloc>&
640 basic_string<_CharT, _Traits, _Alloc>::
641 _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2,
644 _M_check_length(__n1, __n2, "basic_string::_M_replace_aux");
645 _M_mutate(__pos1, __n1, __n2);
647 _M_assign(_M_data() + __pos1, __n2, __c);
651 template<typename _CharT, typename _Traits, typename _Alloc>
652 basic_string<_CharT, _Traits, _Alloc>&
653 basic_string<_CharT, _Traits, _Alloc>::
654 _M_replace_safe(size_type __pos1, size_type __n1, const _CharT* __s,
657 _M_mutate(__pos1, __n1, __n2);
659 _M_copy(_M_data() + __pos1, __s, __n2);
663 template<typename _CharT, typename _Traits, typename _Alloc>
664 basic_string<_CharT, _Traits, _Alloc>
665 operator+(const _CharT* __lhs,
666 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
668 __glibcxx_requires_string(__lhs);
669 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
670 typedef typename __string_type::size_type __size_type;
671 const __size_type __len = _Traits::length(__lhs);
673 __str.reserve(__len + __rhs.size());
674 __str.append(__lhs, __len);
679 template<typename _CharT, typename _Traits, typename _Alloc>
680 basic_string<_CharT, _Traits, _Alloc>
681 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
683 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
684 typedef typename __string_type::size_type __size_type;
686 const __size_type __len = __rhs.size();
687 __str.reserve(__len + 1);
688 __str.append(__size_type(1), __lhs);
693 template<typename _CharT, typename _Traits, typename _Alloc>
694 typename basic_string<_CharT, _Traits, _Alloc>::size_type
695 basic_string<_CharT, _Traits, _Alloc>::
696 copy(_CharT* __s, size_type __n, size_type __pos) const
698 _M_check(__pos, "basic_string::copy");
699 __n = _M_limit(__pos, __n);
700 __glibcxx_requires_string_len(__s, __n);
702 _M_copy(__s, _M_data() + __pos, __n);
703 // 21.3.5.7 par 3: do not append null. (good.)
707 template<typename _CharT, typename _Traits, typename _Alloc>
708 typename basic_string<_CharT, _Traits, _Alloc>::size_type
709 basic_string<_CharT, _Traits, _Alloc>::
710 find(const _CharT* __s, size_type __pos, size_type __n) const
712 __glibcxx_requires_string_len(__s, __n);
713 const size_type __size = this->size();
714 const _CharT* __data = _M_data();
717 return __pos <= __size ? __pos : npos;
721 for (; __pos <= __size - __n; ++__pos)
722 if (traits_type::eq(__data[__pos], __s[0])
723 && traits_type::compare(__data + __pos + 1,
724 __s + 1, __n - 1) == 0)
730 template<typename _CharT, typename _Traits, typename _Alloc>
731 typename basic_string<_CharT, _Traits, _Alloc>::size_type
732 basic_string<_CharT, _Traits, _Alloc>::
733 find(_CharT __c, size_type __pos) const
735 size_type __ret = npos;
736 const size_type __size = this->size();
739 const _CharT* __data = _M_data();
740 const size_type __n = __size - __pos;
741 const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
743 __ret = __p - __data;
748 template<typename _CharT, typename _Traits, typename _Alloc>
749 typename basic_string<_CharT, _Traits, _Alloc>::size_type
750 basic_string<_CharT, _Traits, _Alloc>::
751 rfind(const _CharT* __s, size_type __pos, size_type __n) const
753 __glibcxx_requires_string_len(__s, __n);
754 const size_type __size = this->size();
757 __pos = std::min(size_type(__size - __n), __pos);
758 const _CharT* __data = _M_data();
761 if (traits_type::compare(__data + __pos, __s, __n) == 0)
769 template<typename _CharT, typename _Traits, typename _Alloc>
770 typename basic_string<_CharT, _Traits, _Alloc>::size_type
771 basic_string<_CharT, _Traits, _Alloc>::
772 rfind(_CharT __c, size_type __pos) const
774 size_type __size = this->size();
777 if (--__size > __pos)
779 for (++__size; __size-- > 0; )
780 if (traits_type::eq(_M_data()[__size], __c))
786 template<typename _CharT, typename _Traits, typename _Alloc>
787 typename basic_string<_CharT, _Traits, _Alloc>::size_type
788 basic_string<_CharT, _Traits, _Alloc>::
789 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
791 __glibcxx_requires_string_len(__s, __n);
792 for (; __n && __pos < this->size(); ++__pos)
794 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
801 template<typename _CharT, typename _Traits, typename _Alloc>
802 typename basic_string<_CharT, _Traits, _Alloc>::size_type
803 basic_string<_CharT, _Traits, _Alloc>::
804 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
806 __glibcxx_requires_string_len(__s, __n);
807 size_type __size = this->size();
810 if (--__size > __pos)
814 if (traits_type::find(__s, __n, _M_data()[__size]))
817 while (__size-- != 0);
822 template<typename _CharT, typename _Traits, typename _Alloc>
823 typename basic_string<_CharT, _Traits, _Alloc>::size_type
824 basic_string<_CharT, _Traits, _Alloc>::
825 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
827 __glibcxx_requires_string_len(__s, __n);
828 for (; __pos < this->size(); ++__pos)
829 if (!traits_type::find(__s, __n, _M_data()[__pos]))
834 template<typename _CharT, typename _Traits, typename _Alloc>
835 typename basic_string<_CharT, _Traits, _Alloc>::size_type
836 basic_string<_CharT, _Traits, _Alloc>::
837 find_first_not_of(_CharT __c, size_type __pos) const
839 for (; __pos < this->size(); ++__pos)
840 if (!traits_type::eq(_M_data()[__pos], __c))
845 template<typename _CharT, typename _Traits, typename _Alloc>
846 typename basic_string<_CharT, _Traits, _Alloc>::size_type
847 basic_string<_CharT, _Traits, _Alloc>::
848 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
850 __glibcxx_requires_string_len(__s, __n);
851 size_type __size = this->size();
854 if (--__size > __pos)
858 if (!traits_type::find(__s, __n, _M_data()[__size]))
866 template<typename _CharT, typename _Traits, typename _Alloc>
867 typename basic_string<_CharT, _Traits, _Alloc>::size_type
868 basic_string<_CharT, _Traits, _Alloc>::
869 find_last_not_of(_CharT __c, size_type __pos) const
871 size_type __size = this->size();
874 if (--__size > __pos)
878 if (!traits_type::eq(_M_data()[__size], __c))
886 template<typename _CharT, typename _Traits, typename _Alloc>
888 basic_string<_CharT, _Traits, _Alloc>::
889 compare(size_type __pos, size_type __n, const basic_string& __str) const
891 _M_check(__pos, "basic_string::compare");
892 __n = _M_limit(__pos, __n);
893 const size_type __osize = __str.size();
894 const size_type __len = std::min(__n, __osize);
895 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
897 __r = _S_compare(__n, __osize);
901 template<typename _CharT, typename _Traits, typename _Alloc>
903 basic_string<_CharT, _Traits, _Alloc>::
904 compare(size_type __pos1, size_type __n1, const basic_string& __str,
905 size_type __pos2, size_type __n2) const
907 _M_check(__pos1, "basic_string::compare");
908 __str._M_check(__pos2, "basic_string::compare");
909 __n1 = _M_limit(__pos1, __n1);
910 __n2 = __str._M_limit(__pos2, __n2);
911 const size_type __len = std::min(__n1, __n2);
912 int __r = traits_type::compare(_M_data() + __pos1,
913 __str.data() + __pos2, __len);
915 __r = _S_compare(__n1, __n2);
919 template<typename _CharT, typename _Traits, typename _Alloc>
921 basic_string<_CharT, _Traits, _Alloc>::
922 compare(const _CharT* __s) const
924 __glibcxx_requires_string(__s);
925 const size_type __size = this->size();
926 const size_type __osize = traits_type::length(__s);
927 const size_type __len = std::min(__size, __osize);
928 int __r = traits_type::compare(_M_data(), __s, __len);
930 __r = _S_compare(__size, __osize);
934 template<typename _CharT, typename _Traits, typename _Alloc>
936 basic_string <_CharT, _Traits, _Alloc>::
937 compare(size_type __pos, size_type __n1, const _CharT* __s) const
939 __glibcxx_requires_string(__s);
940 _M_check(__pos, "basic_string::compare");
941 __n1 = _M_limit(__pos, __n1);
942 const size_type __osize = traits_type::length(__s);
943 const size_type __len = std::min(__n1, __osize);
944 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
946 __r = _S_compare(__n1, __osize);
950 template<typename _CharT, typename _Traits, typename _Alloc>
952 basic_string <_CharT, _Traits, _Alloc>::
953 compare(size_type __pos, size_type __n1, const _CharT* __s,
954 size_type __n2) const
956 __glibcxx_requires_string_len(__s, __n2);
957 _M_check(__pos, "basic_string::compare");
958 __n1 = _M_limit(__pos, __n1);
959 const size_type __len = std::min(__n1, __n2);
960 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
962 __r = _S_compare(__n1, __n2);
966 // 21.3.7.9 basic_string::getline and operators
967 template<typename _CharT, typename _Traits, typename _Alloc>
968 basic_istream<_CharT, _Traits>&
969 operator>>(basic_istream<_CharT, _Traits>& __in,
970 basic_string<_CharT, _Traits, _Alloc>& __str)
972 typedef basic_istream<_CharT, _Traits> __istream_type;
973 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
974 typedef typename __istream_type::ios_base __ios_base;
975 typedef typename __istream_type::int_type __int_type;
976 typedef typename __string_type::size_type __size_type;
977 typedef ctype<_CharT> __ctype_type;
978 typedef typename __ctype_type::ctype_base __ctype_base;
980 __size_type __extracted = 0;
981 typename __ios_base::iostate __err = __ios_base::goodbit;
982 typename __istream_type::sentry __cerb(__in, false);
987 // Avoid reallocation for common case.
990 __size_type __len = 0;
991 const streamsize __w = __in.width();
992 const __size_type __n = __w > 0 ? static_cast<__size_type>(__w)
994 const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc());
995 const __int_type __eof = _Traits::eof();
996 __int_type __c = __in.rdbuf()->sgetc();
998 while (__extracted < __n
999 && !_Traits::eq_int_type(__c, __eof)
1000 && !__ct.is(__ctype_base::space,
1001 _Traits::to_char_type(__c)))
1003 if (__len == sizeof(__buf) / sizeof(_CharT))
1005 __str.append(__buf, sizeof(__buf) / sizeof(_CharT));
1008 __buf[__len++] = _Traits::to_char_type(__c);
1010 __c = __in.rdbuf()->snextc();
1012 __str.append(__buf, __len);
1014 if (_Traits::eq_int_type(__c, __eof))
1015 __err |= __ios_base::eofbit;
1020 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1021 // 91. Description of operator>> and getline() for string<>
1022 // might cause endless loop
1023 __in._M_setstate(__ios_base::badbit);
1026 // 211. operator>>(istream&, string&) doesn't set failbit
1028 __err |= __ios_base::failbit;
1030 __in.setstate(__err);
1034 template<typename _CharT, typename _Traits, typename _Alloc>
1035 basic_istream<_CharT, _Traits>&
1036 getline(basic_istream<_CharT, _Traits>& __in,
1037 basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim)
1039 typedef basic_istream<_CharT, _Traits> __istream_type;
1040 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
1041 typedef typename __istream_type::ios_base __ios_base;
1042 typedef typename __istream_type::int_type __int_type;
1043 typedef typename __string_type::size_type __size_type;
1045 __size_type __extracted = 0;
1046 const __size_type __n = __str.max_size();
1047 typename __ios_base::iostate __err = __ios_base::goodbit;
1048 typename __istream_type::sentry __cerb(__in, true);
1054 const __int_type __idelim = _Traits::to_int_type(__delim);
1055 const __int_type __eof = _Traits::eof();
1056 __int_type __c = __in.rdbuf()->sgetc();
1058 while (__extracted < __n
1059 && !_Traits::eq_int_type(__c, __eof)
1060 && !_Traits::eq_int_type(__c, __idelim))
1062 __str += _Traits::to_char_type(__c);
1064 __c = __in.rdbuf()->snextc();
1067 if (_Traits::eq_int_type(__c, __eof))
1068 __err |= __ios_base::eofbit;
1069 else if (_Traits::eq_int_type(__c, __idelim))
1072 __in.rdbuf()->sbumpc();
1075 __err |= __ios_base::failbit;
1079 // _GLIBCXX_RESOLVE_LIB_DEFECTS
1080 // 91. Description of operator>> and getline() for string<>
1081 // might cause endless loop
1082 __in._M_setstate(__ios_base::badbit);
1086 __err |= __ios_base::failbit;
1088 __in.setstate(__err);
1092 // Inhibit implicit instantiations for required instantiations,
1093 // which are defined via explicit instantiations elsewhere.
1094 // NB: This syntax is a GNU extension.
1095 #if _GLIBCXX_EXTERN_TEMPLATE
1096 extern template class basic_string<char>;
1098 basic_istream<char>&
1099 operator>>(basic_istream<char>&, string&);
1101 basic_ostream<char>&
1102 operator<<(basic_ostream<char>&, const string&);
1104 basic_istream<char>&
1105 getline(basic_istream<char>&, string&, char);
1107 basic_istream<char>&
1108 getline(basic_istream<char>&, string&);
1110 #ifdef _GLIBCXX_USE_WCHAR_T
1111 extern template class basic_string<wchar_t>;
1113 basic_istream<wchar_t>&
1114 operator>>(basic_istream<wchar_t>&, wstring&);
1116 basic_ostream<wchar_t>&
1117 operator<<(basic_ostream<wchar_t>&, const wstring&);
1119 basic_istream<wchar_t>&
1120 getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1122 basic_istream<wchar_t>&
1123 getline(basic_istream<wchar_t>&, wstring&);
1127 _GLIBCXX_END_NAMESPACE