]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/basic_string.tcc
jacks.exp (gcj_jacks_write): Enable "assert" constraint.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / basic_string.tcc
CommitLineData
725dc051
BK
1// Components for manipulating sequences of characters -*- C++ -*-
2
1bc8b0ad 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003
c68cd521 4// Free Software Foundation, Inc.
725dc051
BK
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 2, 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// You should have received a copy of the GNU General Public License along
18// with this library; see the file COPYING. If not, write to the Free
19// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
20// USA.
21
22// As a special exception, you may use this file as part of a free software
23// library without restriction. Specifically, if other files instantiate
24// templates or use macros or inline functions from this file, or you compile
25// this file and link it with other files to produce an executable, this
26// file does not by itself cause the resulting executable to be covered by
27// the GNU General Public License. This exception does not however
28// invalidate any other reasons why the executable file might be covered by
29// the GNU General Public License.
30
31//
32// ISO C++ 14882: 21 Strings library
33//
34
35// This file is included by <string>. It is not meant to be included
36// separately.
37
38// Written by Jason Merrill based upon the specification by Takanori Adachi
39// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882.
40
3d7c150e
BK
41#ifndef _BASIC_STRING_TCC
42#define _BASIC_STRING_TCC 1
725dc051 43
3b794528
BK
44#pragma GCC system_header
45
725dc051
BK
46namespace std
47{
725dc051 48 template<typename _CharT, typename _Traits, typename _Alloc>
00532602 49 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051 50 basic_string<_CharT, _Traits, _Alloc>::
ca566e4c 51 _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
725dc051
BK
52
53 template<typename _CharT, typename _Traits, typename _Alloc>
00532602 54 const _CharT
725dc051 55 basic_string<_CharT, _Traits, _Alloc>::
00532602 56 _Rep::_S_terminal = _CharT();
725dc051
BK
57
58 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 59 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
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>
4f12dd3c 65 typename basic_string<_CharT, _Traits, _Alloc>::size_type
ca566e4c
NM
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)];
725dc051
BK
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>
08addde6 75 template<typename _InIterator>
725dc051
BK
76 _CharT*
77 basic_string<_CharT, _Traits, _Alloc>::
08addde6 78 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
725dc051
BK
79 input_iterator_tag)
80 {
81 if (__beg == __end && __a == _Alloc())
ca566e4c 82 return _S_empty_rep()._M_refdata();
725dc051
BK
83 // Avoid reallocation for common case.
84 _CharT __buf[100];
85 size_type __i = 0;
86 while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT))
87 {
88 __buf[__i++] = *__beg;
89 ++__beg;
90 }
91 _Rep* __r = _Rep::_S_create(__i, __a);
92 traits_type::copy(__r->_M_refdata(), __buf, __i);
93 __r->_M_length = __i;
e2c09482
BK
94 try
95 {
96 // NB: this loop looks precisely this way because
97 // it avoids comparing __beg != __end any more
98 // than strictly necessary; != might be expensive!
99 for (;;)
100 {
101 _CharT* __p = __r->_M_refdata() + __r->_M_length;
102 _CharT* __last = __r->_M_refdata() + __r->_M_capacity;
103 for (;;)
104 {
105 if (__beg == __end)
106 {
107 __r->_M_length = __p - __r->_M_refdata();
108 *__p = _Rep::_S_terminal; // grrr.
109 return __r->_M_refdata();
110 }
111 if (__p == __last)
112 break;
113 *__p++ = *__beg;
114 ++__beg;
115 }
116 // Allocate more space.
7778fa6e 117 const size_type __len = __p - __r->_M_refdata();
e2c09482
BK
118 _Rep* __another = _Rep::_S_create(__len + 1, __a);
119 traits_type::copy(__another->_M_refdata(),
120 __r->_M_refdata(), __len);
121 __r->_M_destroy(__a);
122 __r = __another;
123 __r->_M_length = __len;
124 }
125 }
126 catch(...)
127 {
725dc051 128 __r->_M_destroy(__a);
e2c09482
BK
129 __throw_exception_again;
130 }
725dc051
BK
131 return 0;
132 }
e2c09482 133
725dc051 134 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 135 template <class _InIterator>
725dc051 136 _CharT*
9a304d17 137 basic_string<_CharT, _Traits, _Alloc>::
08addde6 138 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
725dc051
BK
139 forward_iterator_tag)
140 {
085825b8 141 if (__beg == __end && __a == _Alloc())
ca566e4c 142 return _S_empty_rep()._M_refdata();
085825b8 143
fcaa8101 144 // NB: Not required, but considered best practice.
08addde6 145 if (__builtin_expect(__beg == _InIterator(), 0))
988ad90d 146 __throw_logic_error("basic_string::_S_construct NULL not valid");
aa863dca 147
7778fa6e 148 const size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
fcaa8101 149
725dc051
BK
150 // Check for out_of_range and length_error exceptions.
151 _Rep* __r = _Rep::_S_create(__dnew, __a);
e2c09482
BK
152 try
153 { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
154 catch(...)
155 {
156 __r->_M_destroy(__a);
157 __throw_exception_again;
158 }
725dc051
BK
159 __r->_M_length = __dnew;
160
161 __r->_M_refdata()[__dnew] = _Rep::_S_terminal; // grrr.
162 return __r->_M_refdata();
163 }
164
165 template<typename _CharT, typename _Traits, typename _Alloc>
166 _CharT*
9a304d17 167 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
168 _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
169 {
170 if (__n == 0 && __a == _Alloc())
ca566e4c 171 return _S_empty_rep()._M_refdata();
725dc051
BK
172
173 // Check for out_of_range and length_error exceptions.
174 _Rep* __r = _Rep::_S_create(__n, __a);
e2c09482
BK
175 try
176 {
177 if (__n)
178 traits_type::assign(__r->_M_refdata(), __n, __c);
179 }
180 catch(...)
181 {
182 __r->_M_destroy(__a);
183 __throw_exception_again;
184 }
725dc051
BK
185 __r->_M_length = __n;
186 __r->_M_refdata()[__n] = _Rep::_S_terminal; // grrr
187 return __r->_M_refdata();
188 }
189
190 template<typename _CharT, typename _Traits, typename _Alloc>
191 basic_string<_CharT, _Traits, _Alloc>::
192 basic_string(const basic_string& __str)
193 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()),
194 __str.get_allocator())
195 { }
196
197 template<typename _CharT, typename _Traits, typename _Alloc>
198 basic_string<_CharT, _Traits, _Alloc>::
199 basic_string(const _Alloc& __a)
200 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
201 { }
202
203 template<typename _CharT, typename _Traits, typename _Alloc>
204 basic_string<_CharT, _Traits, _Alloc>::
205 basic_string(const basic_string& __str, size_type __pos, size_type __n)
206 : _M_dataplus(_S_construct(__str._M_check(__pos),
207 __str._M_fold(__pos, __n), _Alloc()), _Alloc())
208 { }
209
210 template<typename _CharT, typename _Traits, typename _Alloc>
211 basic_string<_CharT, _Traits, _Alloc>::
212 basic_string(const basic_string& __str, size_type __pos,
213 size_type __n, const _Alloc& __a)
214 : _M_dataplus(_S_construct(__str._M_check(__pos),
215 __str._M_fold(__pos, __n), __a), __a)
216 { }
217
218 template<typename _CharT, typename _Traits, typename _Alloc>
219 basic_string<_CharT, _Traits, _Alloc>::
220 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
221 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
222 { }
223
224 template<typename _CharT, typename _Traits, typename _Alloc>
225 basic_string<_CharT, _Traits, _Alloc>::
226 basic_string(const _CharT* __s, const _Alloc& __a)
085825b8
PC
227 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
228 __s + npos, __a), __a)
725dc051
BK
229 { }
230
231 template<typename _CharT, typename _Traits, typename _Alloc>
232 basic_string<_CharT, _Traits, _Alloc>::
233 basic_string(size_type __n, _CharT __c, const _Alloc& __a)
234 : _M_dataplus(_S_construct(__n, __c, __a), __a)
235 { }
236
237 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 238 template<typename _InputIterator>
725dc051 239 basic_string<_CharT, _Traits, _Alloc>::
08addde6 240 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
725dc051
BK
241 : _M_dataplus(_S_construct(__beg, __end, __a), __a)
242 { }
243
244 template<typename _CharT, typename _Traits, typename _Alloc>
245 basic_string<_CharT, _Traits, _Alloc>&
ca566e4c
NM
246 basic_string<_CharT, _Traits, _Alloc>::
247 assign(const basic_string& __str)
725dc051
BK
248 {
249 if (_M_rep() != __str._M_rep())
250 {
251 // XXX MT
252 allocator_type __a = this->get_allocator();
253 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
254 _M_rep()->_M_dispose(__a);
255 _M_data(__tmp);
256 }
257 return *this;
258 }
2d9d5235
NM
259
260 template<typename _CharT, typename _Traits, typename _Alloc>
261 basic_string<_CharT, _Traits, _Alloc>&
262 basic_string<_CharT, _Traits, _Alloc>::
263 assign(const basic_string& __str, size_type __pos, size_type __n)
264 {
265 const size_type __strsize = __str.size();
266 if (__pos > __strsize)
267 __throw_out_of_range("basic_string::assign");
268 const bool __testn = __n < __strsize - __pos;
269 const size_type __newsize = __testn ? __n : __strsize - __pos;
270 return this->assign(__str._M_data() + __pos, __newsize);
271 }
272
273 template<typename _CharT, typename _Traits, typename _Alloc>
274 basic_string<_CharT, _Traits, _Alloc>&
275 basic_string<_CharT, _Traits, _Alloc>::
276 assign(const _CharT* __s, size_type __n)
277 {
278 if (__n > this->max_size())
279 __throw_length_error("basic_string::assign");
280 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
281 || less<const _CharT*>()(_M_data() + this->size(), __s))
282 return _M_replace_safe(_M_ibegin(), _M_iend(), __s, __s + __n);
283 else
284 {
285 // Work in-place
286 const size_type __pos = __s - _M_data();
287 if (__pos >= __n)
288 traits_type::copy(_M_data(), __s, __n);
289 else if (__pos)
290 traits_type::move(_M_data(), __s, __n);
291 _M_rep()->_M_length = __n;
292 _M_data()[__n] = _Rep::_S_terminal; // grr.
293 return *this;
294 }
295 }
296
297 template<typename _CharT, typename _Traits, typename _Alloc>
298 basic_string<_CharT, _Traits, _Alloc>&
299 basic_string<_CharT, _Traits, _Alloc>::
300 insert(size_type __pos1, const basic_string& __str,
301 size_type __pos2, size_type __n)
302 {
303 const size_type __strsize = __str.size();
304 if (__pos2 > __strsize)
305 __throw_out_of_range("basic_string::insert");
306 const bool __testn = __n < __strsize - __pos2;
307 const size_type __newsize = __testn ? __n : __strsize - __pos2;
308 return this->insert(__pos1, __str._M_data() + __pos2, __newsize);
309 }
310
311 template<typename _CharT, typename _Traits, typename _Alloc>
312 basic_string<_CharT, _Traits, _Alloc>&
313 basic_string<_CharT, _Traits, _Alloc>::
314 insert(size_type __pos, const _CharT* __s, size_type __n)
315 {
316 const size_type __size = this->size();
317 if (__pos > __size)
318 __throw_out_of_range("basic_string::insert");
319 if (__size > this->max_size() - __n)
320 __throw_length_error("basic_string::insert");
321 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
322 || less<const _CharT*>()(_M_data() + __size, __s))
323 return _M_replace_safe(_M_ibegin() + __pos, _M_ibegin() + __pos,
324 __s, __s + __n);
325 else
326 {
327 // Work in-place. If _M_mutate reallocates the string, __s
328 // does not point anymore to valid data, therefore we save its
329 // offset, then we restore it.
330 const size_type __off = __s - _M_data();
331 _M_mutate(__pos, 0, __n);
332 __s = _M_data() + __off;
333 _CharT* __p = _M_data() + __pos;
334 if (__s + __n <= __p)
335 traits_type::copy(__p, __s, __n);
336 else if (__s >= __p)
337 traits_type::copy(__p, __s + __n, __n);
338 else
339 {
340 traits_type::copy(__p, __s, __p - __s);
341 traits_type::copy(__p + (__p-__s), __p + __n, __n - (__p-__s));
342 }
343 return *this;
344 }
345 }
346
347 template<typename _CharT, typename _Traits, typename _Alloc>
348 basic_string<_CharT, _Traits, _Alloc>&
349 basic_string<_CharT, _Traits, _Alloc>::
350 replace(size_type __pos, size_type __n1, const _CharT* __s,
351 size_type __n2)
352 {
353 const size_type __size = this->size();
354 if (__pos > __size)
355 __throw_out_of_range("basic_string::replace");
356 const bool __testn1 = __n1 < __size - __pos;
357 const size_type __foldn1 = __testn1 ? __n1 : __size - __pos;
358 if (__size - __foldn1 > this->max_size() - __n2)
359 __throw_length_error("basic_string::replace");
360 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
361 || less<const _CharT*>()(_M_data() + __size, __s))
362 return _M_replace_safe(_M_ibegin() + __pos,
363 _M_ibegin() + __pos + __foldn1, __s, __s + __n2);
364 // Todo: optimized in-place replace.
365 else
366 return _M_replace(_M_ibegin() + __pos, _M_ibegin() + __pos + __foldn1,
367 __s, __s + __n2,
368 typename iterator_traits<const _CharT*>::iterator_category());
369 }
725dc051
BK
370
371 template<typename _CharT, typename _Traits, typename _Alloc>
372 void
373 basic_string<_CharT, _Traits, _Alloc>::_Rep::
374 _M_destroy(const _Alloc& __a) throw ()
375 {
ca566e4c
NM
376 if (this == &_S_empty_rep())
377 return;
378 const size_type __size = sizeof(_Rep_base) +
379 (this->_M_capacity + 1) * sizeof(_CharT);
725dc051
BK
380 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
381 }
382
383 template<typename _CharT, typename _Traits, typename _Alloc>
384 void
385 basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
386 {
ca566e4c
NM
387 if (_M_rep() == &_S_empty_rep())
388 return;
725dc051
BK
389 if (_M_rep()->_M_is_shared())
390 _M_mutate(0, 0, 0);
391 _M_rep()->_M_set_leaked();
392 }
393
79f57f23
PC
394 // _M_mutate and, below, _M_clone, include, in the same form, an exponential
395 // growth policy, necessary to meet amortized linear time requirements of
396 // the library: see http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
397 // The policy is active for allocations requiring an amount of memory above
398 // system pagesize. This is consistent with the requirements of the standard:
399 // see, f.i., http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
725dc051
BK
400 template<typename _CharT, typename _Traits, typename _Alloc>
401 void
402 basic_string<_CharT, _Traits, _Alloc>::
403 _M_mutate(size_type __pos, size_type __len1, size_type __len2)
404 {
7778fa6e 405 const size_type __old_size = this->size();
725dc051
BK
406 const size_type __new_size = __old_size + __len2 - __len1;
407 const _CharT* __src = _M_data() + __pos + __len1;
408 const size_type __how_much = __old_size - __pos - __len1;
409
ca566e4c
NM
410 if (_M_rep() == &_S_empty_rep()
411 || _M_rep()->_M_is_shared() || __new_size > capacity())
725dc051
BK
412 {
413 // Must reallocate.
414 allocator_type __a = get_allocator();
79f57f23
PC
415 // See below (_S_create) for the meaning and value of these
416 // constants.
417 const size_type __pagesize = 4096;
418 const size_type __malloc_header_size = 4 * sizeof (void*);
419 // The biggest string which fits in a memory page
cc894391
PC
420 const size_type __page_capacity = (__pagesize - __malloc_header_size
421 - sizeof(_Rep) - sizeof(_CharT))
422 / sizeof(_CharT);
79f57f23
PC
423 _Rep* __r;
424 if (__new_size > capacity() && __new_size > __page_capacity)
425 // Growing exponentially.
426 __r = _Rep::_S_create(__new_size > 2*capacity() ?
427 __new_size : 2*capacity(), __a);
428 else
429 __r = _Rep::_S_create(__new_size, __a);
e2c09482
BK
430 try
431 {
432 if (__pos)
433 traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
434 if (__how_much)
435 traits_type::copy(__r->_M_refdata() + __pos + __len2,
436 __src, __how_much);
437 }
438 catch(...)
439 {
440 __r->_M_dispose(get_allocator());
441 __throw_exception_again;
442 }
725dc051
BK
443 _M_rep()->_M_dispose(__a);
444 _M_data(__r->_M_refdata());
ca566e4c 445 }
725dc051
BK
446 else if (__how_much && __len1 != __len2)
447 {
448 // Work in-place
449 traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
450 }
451 _M_rep()->_M_set_sharable();
452 _M_rep()->_M_length = __new_size;
453 _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
ca566e4c 454 // You cannot leave those LWG people alone for a second.
725dc051
BK
455 }
456
457 template<typename _CharT, typename _Traits, typename _Alloc>
458 void
459 basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
460 {
461 if (__res > this->capacity() || _M_rep()->_M_is_shared())
462 {
e2c09482
BK
463 if (__res > this->max_size())
464 __throw_length_error("basic_string::reserve");
dcc61724
PC
465 // Make sure we don't shrink below the current size
466 if (__res < this->size())
467 __res = this->size();
725dc051
BK
468 allocator_type __a = get_allocator();
469 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
470 _M_rep()->_M_dispose(__a);
471 _M_data(__tmp);
472 }
473 }
474
475 template<typename _CharT, typename _Traits, typename _Alloc>
476 void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
477 {
478 if (_M_rep()->_M_is_leaked())
479 _M_rep()->_M_set_sharable();
480 if (__s._M_rep()->_M_is_leaked())
481 __s._M_rep()->_M_set_sharable();
482 if (this->get_allocator() == __s.get_allocator())
483 {
484 _CharT* __tmp = _M_data();
485 _M_data(__s._M_data());
486 __s._M_data(__tmp);
487 }
488 // The code below can usually be optimized away.
489 else
490 {
491 basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
492 basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
493 this->get_allocator());
494 *this = __tmp2;
495 __s = __tmp1;
496 }
497 }
498
725dc051 499 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 500 typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
725dc051
BK
501 basic_string<_CharT, _Traits, _Alloc>::_Rep::
502 _S_create(size_t __capacity, const _Alloc& __alloc)
503 {
e2c09482 504 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
f5677b15 505 // _GLIBCXX_RESOLVE_LIB_DEFECTS
725dc051 506 // 83. String::npos vs. string::max_size()
e2c09482 507 if (__capacity > _S_max_size)
e2c09482 508 __throw_length_error("basic_string::_S_create");
725dc051
BK
509
510 // NB: Need an array of char_type[__capacity], plus a
511 // terminating null char_type() element, plus enough for the
512 // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
ca566e4c 513 size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep_base);
2883d58b
LR
514
515 // The standard places no restriction on allocating more memory
516 // than is strictly needed within this layer at the moment or as
517 // requested by an explicit application call to reserve(). Many
518 // malloc implementations perform quite poorly when an
519 // application attempts to allocate memory in a stepwise fashion
520 // growing each allocation size by only 1 char. Additionally,
521 // it makes little sense to allocate less linear memory than the
522 // natural blocking size of the malloc implementation.
523 // Unfortunately, we would need a somewhat low-level calculation
524 // with tuned parameters to get this perfect for any particular
525 // malloc implementation. Fortunately, generalizations about
526 // common features seen among implementations seems to suffice.
2883d58b
LR
527
528 // __pagesize need not match the actual VM page size for good
529 // results in practice, thus we pick a common value on the low
530 // side. __malloc_header_size is an estimate of the amount of
531 // overhead per memory allocation (in practice seen N * sizeof
532 // (void*) where N is 0, 2 or 4). According to folklore,
533 // picking this value on the high side is better than
534 // low-balling it (especially when this algorithm is used with
535 // malloc implementations that allocate memory blocks rounded up
536 // to a size which is a power of 2).
537 const size_t __pagesize = 4096; // must be 2^i * __subpagesize
538 const size_t __subpagesize = 128; // should be >> __malloc_header_size
539 const size_t __malloc_header_size = 4 * sizeof (void*);
540 if ((__size + __malloc_header_size) > __pagesize)
541 {
7778fa6e 542 const size_t __extra =
2883d58b
LR
543 (__pagesize - ((__size + __malloc_header_size) % __pagesize))
544 % __pagesize;
545 __capacity += __extra / sizeof(_CharT);
ca566e4c 546 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep_base);
2883d58b
LR
547 }
548 else if (__size > __subpagesize)
549 {
7778fa6e 550 const size_t __extra =
2883d58b
LR
551 (__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
552 % __subpagesize;
553 __capacity += __extra / sizeof(_CharT);
ca566e4c 554 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep_base);
2883d58b
LR
555 }
556
725dc051
BK
557 // NB: Might throw, but no worries about a leak, mate: _Rep()
558 // does not throw.
559 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
560 _Rep *__p = new (__place) _Rep;
561 __p->_M_capacity = __capacity;
d3a193e3 562 __p->_M_set_sharable(); // One reference.
725dc051
BK
563 __p->_M_length = 0;
564 return __p;
565 }
566
567 template<typename _CharT, typename _Traits, typename _Alloc>
568 _CharT*
569 basic_string<_CharT, _Traits, _Alloc>::_Rep::
570 _M_clone(const _Alloc& __alloc, size_type __res)
571 {
79f57f23 572 // Requested capacity of the clone.
ca566e4c 573 const size_type __requested_cap = this->_M_length + __res;
79f57f23
PC
574 // See above (_S_create) for the meaning and value of these constants.
575 const size_type __pagesize = 4096;
576 const size_type __malloc_header_size = 4 * sizeof (void*);
577 // The biggest string which fits in a memory page.
578 const size_type __page_capacity =
ca566e4c 579 (__pagesize - __malloc_header_size - sizeof(_Rep_base) - sizeof(_CharT))
79f57f23
PC
580 / sizeof(_CharT);
581 _Rep* __r;
ca566e4c
NM
582 if (__requested_cap > this->_M_capacity
583 && __requested_cap > __page_capacity)
79f57f23 584 // Growing exponentially.
ca566e4c
NM
585 __r = _Rep::_S_create(__requested_cap > 2*this->_M_capacity ?
586 __requested_cap : 2*this->_M_capacity, __alloc);
79f57f23
PC
587 else
588 __r = _Rep::_S_create(__requested_cap, __alloc);
589
ca566e4c 590 if (this->_M_length)
725dc051 591 {
e2c09482 592 try
ca566e4c
NM
593 {
594 traits_type::copy(__r->_M_refdata(), _M_refdata(),
595 this->_M_length);
596 }
e2c09482
BK
597 catch(...)
598 {
599 __r->_M_destroy(__alloc);
600 __throw_exception_again;
601 }
725dc051 602 }
ca566e4c 603 __r->_M_length = this->_M_length;
725dc051
BK
604 return __r->_M_refdata();
605 }
606
725dc051
BK
607 template<typename _CharT, typename _Traits, typename _Alloc>
608 void
609 basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
610 {
e2c09482
BK
611 if (__n > max_size())
612 __throw_length_error("basic_string::resize");
7778fa6e 613 const size_type __size = this->size();
725dc051
BK
614 if (__size < __n)
615 this->append(__n - __size, __c);
616 else if (__n < __size)
617 this->erase(__n);
618 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
619 }
418bb880 620
bdb0f0f5
DG
621 template<typename _CharT, typename _Traits, typename _Alloc>
622 basic_string<_CharT, _Traits, _Alloc>&
623 basic_string<_CharT, _Traits, _Alloc>::
624 _M_replace_aux(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
625 {
41ba4c46
PC
626 const size_type __n1 = __i2 - __i1;
627 const size_type __off1 = __i1 - _M_ibegin();
bdb0f0f5
DG
628 if (max_size() - (this->size() - __n1) <= __n2)
629 __throw_length_error("basic_string::replace");
630 _M_mutate (__off1, __n1, __n2);
631 // Invalidated __i1, __i2
632 if (__n2)
633 traits_type::assign(_M_data() + __off1, __n2, __c);
634 return *this;
635 }
636
418bb880
PC
637 // This is the general replace helper, which currently gets instantiated both
638 // for input iterators and reverse iterators. It buffers internally and then
639 // calls _M_replace_safe.
725dc051 640 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 641 template<typename _InputIterator>
725dc051
BK
642 basic_string<_CharT, _Traits, _Alloc>&
643 basic_string<_CharT, _Traits, _Alloc>::
08addde6
PE
644 _M_replace(iterator __i1, iterator __i2, _InputIterator __k1,
645 _InputIterator __k2, input_iterator_tag)
725dc051 646 {
78bd5031 647 // Save concerned source string data in a temporary.
7778fa6e 648 const basic_string __s(__k1, __k2);
78bd5031 649 return _M_replace_safe(__i1, __i2, __s._M_ibegin(), __s._M_iend());
725dc051
BK
650 }
651
78bd5031 652 // This is a special replace helper, which does not buffer internally
418bb880 653 // and can be used in "safe" situations involving forward iterators,
78bd5031 654 // i.e., when source and destination ranges are known to not overlap.
725dc051 655 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 656 template<typename _ForwardIterator>
725dc051
BK
657 basic_string<_CharT, _Traits, _Alloc>&
658 basic_string<_CharT, _Traits, _Alloc>::
08addde6
PE
659 _M_replace_safe(iterator __i1, iterator __i2, _ForwardIterator __k1,
660 _ForwardIterator __k2)
725dc051 661 {
7778fa6e
PC
662 const size_type __dnew = static_cast<size_type>(std::distance(__k1, __k2));
663 const size_type __dold = __i2 - __i1;
664 const size_type __dmax = this->max_size();
725dc051 665
e2c09482
BK
666 if (__dmax <= __dnew)
667 __throw_length_error("basic_string::_M_replace");
7778fa6e 668 const size_type __off = __i1 - _M_ibegin();
725dc051 669 _M_mutate(__off, __dold, __dnew);
78bd5031
PC
670
671 // Invalidated __i1, __i2
9a304d17 672 if (__dnew)
78bd5031 673 _S_copy_chars(_M_data() + __off, __k1, __k2);
9a304d17 674
725dc051
BK
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 replace(size_type __pos1, size_type __n1, const basic_string& __str,
682 size_type __pos2, size_type __n2)
683 {
c68cd521
PC
684 const size_type __strsize = __str.size();
685 if (__pos2 > __strsize)
686 __throw_out_of_range("basic_string::replace");
687 const bool __testn2 = __n2 < __strsize - __pos2;
688 const size_type __foldn2 = __testn2 ? __n2 : __strsize - __pos2;
689 return this->replace(__pos1, __n1,
690 __str._M_data() + __pos2, __foldn2);
725dc051
BK
691 }
692
693 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
694 basic_string<_CharT, _Traits, _Alloc>&
695 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
696 append(const basic_string& __str)
697 {
698 // Iff appending itself, string needs to pre-reserve the
699 // correct size so that _M_mutate does not clobber the
700 // iterators formed here.
7778fa6e
PC
701 const size_type __size = __str.size();
702 const size_type __len = __size + this->size();
725dc051
BK
703 if (__len > this->capacity())
704 this->reserve(__len);
78bd5031
PC
705 return _M_replace_safe(_M_iend(), _M_iend(), __str._M_ibegin(),
706 __str._M_iend());
725dc051
BK
707 }
708
709 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
710 basic_string<_CharT, _Traits, _Alloc>&
711 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
712 append(const basic_string& __str, size_type __pos, size_type __n)
713 {
714 // Iff appending itself, string needs to pre-reserve the
715 // correct size so that _M_mutate does not clobber the
716 // iterators formed here.
7778fa6e
PC
717 const size_type __len = std::min(size_type(__str.size() - __pos),
718 __n) + this->size();
725dc051
BK
719 if (__len > this->capacity())
720 this->reserve(__len);
78bd5031
PC
721 return _M_replace_safe(_M_iend(), _M_iend(), __str._M_check(__pos),
722 __str._M_fold(__pos, __n));
725dc051
BK
723 }
724
725 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
726 basic_string<_CharT, _Traits, _Alloc>&
727 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
728 append(const _CharT* __s, size_type __n)
729 {
7778fa6e 730 const size_type __len = __n + this->size();
725dc051
BK
731 if (__len > this->capacity())
732 this->reserve(__len);
78bd5031 733 return _M_replace_safe(_M_iend(), _M_iend(), __s, __s + __n);
725dc051
BK
734 }
735
736 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
737 basic_string<_CharT, _Traits, _Alloc>&
738 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
739 append(size_type __n, _CharT __c)
740 {
7778fa6e 741 const size_type __len = __n + this->size();
725dc051
BK
742 if (__len > this->capacity())
743 this->reserve(__len);
744 return this->replace(_M_iend(), _M_iend(), __n, __c);
745 }
746
747 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17 748 basic_string<_CharT, _Traits, _Alloc>
725dc051 749 operator+(const _CharT* __lhs,
9a304d17 750 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 751 {
9a304d17 752 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051 753 typedef typename __string_type::size_type __size_type;
7778fa6e 754 const __size_type __len = _Traits::length(__lhs);
725dc051
BK
755 __string_type __str;
756 __str.reserve(__len + __rhs.size());
757 __str.append(__lhs, __lhs + __len);
758 __str.append(__rhs);
759 return __str;
760 }
761
762 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
763 basic_string<_CharT, _Traits, _Alloc>
764 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 765 {
9a304d17 766 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051
BK
767 typedef typename __string_type::size_type __size_type;
768 __string_type __str;
7778fa6e 769 const __size_type __len = __rhs.size();
725dc051 770 __str.reserve(__len + 1);
15f13f01 771 __str.append(__size_type(1), __lhs);
725dc051
BK
772 __str.append(__rhs);
773 return __str;
774 }
775
725dc051 776 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 777 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
778 basic_string<_CharT, _Traits, _Alloc>::
779 copy(_CharT* __s, size_type __n, size_type __pos) const
780 {
e2c09482
BK
781 if (__pos > this->size())
782 __throw_out_of_range("basic_string::copy");
725dc051
BK
783
784 if (__n > this->size() - __pos)
785 __n = this->size() - __pos;
786
787 traits_type::copy(__s, _M_data() + __pos, __n);
788 // 21.3.5.7 par 3: do not append null. (good.)
789 return __n;
790 }
791
725dc051 792 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 793 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
794 basic_string<_CharT, _Traits, _Alloc>::
795 find(const _CharT* __s, size_type __pos, size_type __n) const
796 {
7778fa6e 797 const size_type __size = this->size();
725dc051
BK
798 size_t __xpos = __pos;
799 const _CharT* __data = _M_data();
97644827 800 for (; __xpos + __n <= __size; ++__xpos)
725dc051
BK
801 if (traits_type::compare(__data + __xpos, __s, __n) == 0)
802 return __xpos;
803 return npos;
804 }
805
806 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 807 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
808 basic_string<_CharT, _Traits, _Alloc>::
809 find(_CharT __c, size_type __pos) const
810 {
7778fa6e 811 const size_type __size = this->size();
725dc051
BK
812 size_type __ret = npos;
813 if (__pos < __size)
814 {
815 const _CharT* __data = _M_data();
7778fa6e 816 const size_type __n = __size - __pos;
97644827
BK
817 const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
818 if (__p)
725dc051
BK
819 __ret = __p - __data;
820 }
821 return __ret;
822 }
823
824
825 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 826 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
827 basic_string<_CharT, _Traits, _Alloc>::
828 rfind(const _CharT* __s, size_type __pos, size_type __n) const
829 {
7778fa6e 830 const size_type __size = this->size();
725dc051
BK
831 if (__n <= __size)
832 {
dd6eaaed 833 __pos = std::min(size_type(__size - __n), __pos);
725dc051
BK
834 const _CharT* __data = _M_data();
835 do
836 {
837 if (traits_type::compare(__data + __pos, __s, __n) == 0)
838 return __pos;
839 }
840 while (__pos-- > 0);
841 }
842 return npos;
843 }
844
845 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 846 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
847 basic_string<_CharT, _Traits, _Alloc>::
848 rfind(_CharT __c, size_type __pos) const
849 {
7778fa6e 850 const size_type __size = this->size();
725dc051
BK
851 if (__size)
852 {
853 size_t __xpos = __size - 1;
854 if (__xpos > __pos)
855 __xpos = __pos;
856
857 for (++__xpos; __xpos-- > 0; )
858 if (traits_type::eq(_M_data()[__xpos], __c))
859 return __xpos;
860 }
861 return npos;
862 }
863
864 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 865 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
866 basic_string<_CharT, _Traits, _Alloc>::
867 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
868 {
725dc051
BK
869 for (; __n && __pos < this->size(); ++__pos)
870 {
97644827
BK
871 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
872 if (__p)
725dc051
BK
873 return __pos;
874 }
875 return npos;
876 }
877
878 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 879 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
880 basic_string<_CharT, _Traits, _Alloc>::
881 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
882 {
883 size_type __size = this->size();
884 if (__size && __n)
885 {
886 if (--__size > __pos)
887 __size = __pos;
888 do
889 {
97644827 890 if (traits_type::find(__s, __n, _M_data()[__size]))
725dc051
BK
891 return __size;
892 }
893 while (__size-- != 0);
894 }
895 return npos;
896 }
897
898 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 899 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
900 basic_string<_CharT, _Traits, _Alloc>::
901 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
902 {
903 size_t __xpos = __pos;
ba317c52 904 for (; __xpos < this->size(); ++__xpos)
97644827 905 if (!traits_type::find(__s, __n, _M_data()[__xpos]))
725dc051
BK
906 return __xpos;
907 return npos;
908 }
909
910 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 911 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
912 basic_string<_CharT, _Traits, _Alloc>::
913 find_first_not_of(_CharT __c, size_type __pos) const
914 {
915 size_t __xpos = __pos;
97644827 916 for (; __xpos < this->size(); ++__xpos)
725dc051
BK
917 if (!traits_type::eq(_M_data()[__xpos], __c))
918 return __xpos;
919 return npos;
920 }
921
922 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 923 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
924 basic_string<_CharT, _Traits, _Alloc>::
925 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
926 {
927 size_type __size = this->size();
ba317c52 928 if (__size)
725dc051
BK
929 {
930 if (--__size > __pos)
931 __size = __pos;
932 do
933 {
97644827 934 if (!traits_type::find(__s, __n, _M_data()[__size]))
725dc051
BK
935 return __size;
936 }
937 while (__size--);
938 }
939 return npos;
940 }
941
942 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 943 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
944 basic_string<_CharT, _Traits, _Alloc>::
945 find_last_not_of(_CharT __c, size_type __pos) const
946 {
947 size_type __size = this->size();
948 if (__size)
949 {
950 if (--__size > __pos)
951 __size = __pos;
952 do
953 {
954 if (!traits_type::eq(_M_data()[__size], __c))
955 return __size;
956 }
957 while (__size--);
958 }
959 return npos;
960 }
961
962 template<typename _CharT, typename _Traits, typename _Alloc>
963 int
964 basic_string<_CharT, _Traits, _Alloc>::
965 compare(size_type __pos, size_type __n, const basic_string& __str) const
966 {
7778fa6e
PC
967 const size_type __size = this->size();
968 const size_type __osize = __str.size();
e2c09482
BK
969 if (__pos > __size)
970 __throw_out_of_range("basic_string::compare");
725dc051 971
7778fa6e
PC
972 const size_type __rsize= std::min(size_type(__size - __pos), __n);
973 const size_type __len = std::min(__rsize, __osize);
725dc051
BK
974 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
975 if (!__r)
976 __r = __rsize - __osize;
977 return __r;
978 }
979
980 template<typename _CharT, typename _Traits, typename _Alloc>
981 int
982 basic_string<_CharT, _Traits, _Alloc>::
983 compare(size_type __pos1, size_type __n1, const basic_string& __str,
984 size_type __pos2, size_type __n2) const
985 {
7778fa6e
PC
986 const size_type __size = this->size();
987 const size_type __osize = __str.size();
e2c09482
BK
988 if (__pos1 > __size || __pos2 > __osize)
989 __throw_out_of_range("basic_string::compare");
725dc051 990
7778fa6e
PC
991 const size_type __rsize = std::min(size_type(__size - __pos1), __n1);
992 const size_type __rosize = std::min(size_type(__osize - __pos2), __n2);
993 const size_type __len = std::min(__rsize, __rosize);
725dc051
BK
994 int __r = traits_type::compare(_M_data() + __pos1,
995 __str.data() + __pos2, __len);
996 if (!__r)
997 __r = __rsize - __rosize;
998 return __r;
999 }
1000
1001
1002 template<typename _CharT, typename _Traits, typename _Alloc>
1003 int
1004 basic_string<_CharT, _Traits, _Alloc>::
1005 compare(const _CharT* __s) const
1006 {
7778fa6e
PC
1007 const size_type __size = this->size();
1008 const size_type __osize = traits_type::length(__s);
1009 const size_type __len = std::min(__size, __osize);
c86c54e6 1010 int __r = traits_type::compare(_M_data(), __s, __len);
725dc051 1011 if (!__r)
c86c54e6 1012 __r = __size - __osize;
725dc051
BK
1013 return __r;
1014 }
1015
1016
3b0fd4bc
BK
1017 template<typename _CharT, typename _Traits, typename _Alloc>
1018 int
9a304d17 1019 basic_string <_CharT, _Traits, _Alloc>::
3b0fd4bc
BK
1020 compare(size_type __pos, size_type __n1, const _CharT* __s) const
1021 {
7778fa6e 1022 const size_type __size = this->size();
3b0fd4bc
BK
1023 if (__pos > __size)
1024 __throw_out_of_range("basic_string::compare");
1025
7778fa6e
PC
1026 const size_type __osize = traits_type::length(__s);
1027 const size_type __rsize = std::min(size_type(__size - __pos), __n1);
1028 const size_type __len = std::min(__rsize, __osize);
3b0fd4bc
BK
1029 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1030 if (!__r)
1031 __r = __rsize - __osize;
1032 return __r;
1033 }
1034
725dc051
BK
1035 template<typename _CharT, typename _Traits, typename _Alloc>
1036 int
9a304d17 1037 basic_string <_CharT, _Traits, _Alloc>::
725dc051
BK
1038 compare(size_type __pos, size_type __n1, const _CharT* __s,
1039 size_type __n2) const
1040 {
7778fa6e 1041 const size_type __size = this->size();
e2c09482
BK
1042 if (__pos > __size)
1043 __throw_out_of_range("basic_string::compare");
725dc051 1044
7778fa6e
PC
1045 const size_type __osize = std::min(traits_type::length(__s), __n2);
1046 const size_type __rsize = std::min(size_type(__size - __pos), __n1);
1047 const size_type __len = std::min(__rsize, __osize);
725dc051
BK
1048 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
1049 if (!__r)
1050 __r = __rsize - __osize;
1051 return __r;
1052 }
1053
a32e3c09
BK
1054 // Inhibit implicit instantiations for required instantiations,
1055 // which are defined via explicit instantiations elsewhere.
1056 // NB: This syntax is a GNU extension.
3d7c150e 1057#if _GLIBCXX_EXTERN_TEMPLATE
a32e3c09 1058 extern template class basic_string<char>;
41b4d44b 1059 extern template
a32e3c09
BK
1060 basic_istream<char>&
1061 operator>>(basic_istream<char>&, string&);
1062 extern template
1063 basic_ostream<char>&
1064 operator<<(basic_ostream<char>&, const string&);
1065 extern template
1066 basic_istream<char>&
1067 getline(basic_istream<char>&, string&, char);
1068 extern template
1069 basic_istream<char>&
1070 getline(basic_istream<char>&, string&);
1071
3d7c150e 1072#ifdef _GLIBCXX_USE_WCHAR_T
a32e3c09
BK
1073 extern template class basic_string<wchar_t>;
1074 extern template
1075 basic_istream<wchar_t>&
1076 operator>>(basic_istream<wchar_t>&, wstring&);
1077 extern template
1078 basic_ostream<wchar_t>&
1079 operator<<(basic_ostream<wchar_t>&, const wstring&);
1080 extern template
1081 basic_istream<wchar_t>&
1082 getline(basic_istream<wchar_t>&, wstring&, wchar_t);
1083 extern template
1084 basic_istream<wchar_t>&
1085 getline(basic_istream<wchar_t>&, wstring&);
5112ae3a 1086#endif
1bc8b0ad 1087#endif
3b0fd4bc 1088} // namespace std
725dc051 1089
3b0fd4bc 1090#endif