]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/basic_string.tcc
c-typeck.c (default_function_array_conversion): Use build_pointer_type not TYPE_POINT...
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / basic_string.tcc
CommitLineData
725dc051
BK
1// Components for manipulating sequences of characters -*- C++ -*-
2
9c96a689 3// Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
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{
285b36d6
BK
48 template<typename _Type>
49 inline bool
50 __is_null_pointer(_Type* __ptr)
51 { return __ptr == 0; }
52
53 template<typename _Type>
54 inline bool
1b80d64a 55 __is_null_pointer(_Type)
285b36d6
BK
56 { return false; }
57
725dc051 58 template<typename _CharT, typename _Traits, typename _Alloc>
ed6814f7 59 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051 60 basic_string<_CharT, _Traits, _Alloc>::
ca566e4c 61 _Rep::_S_max_size = (((npos - sizeof(_Rep_base))/sizeof(_CharT)) - 1) / 4;
725dc051
BK
62
63 template<typename _CharT, typename _Traits, typename _Alloc>
ed6814f7 64 const _CharT
725dc051 65 basic_string<_CharT, _Traits, _Alloc>::
00532602 66 _Rep::_S_terminal = _CharT();
725dc051
BK
67
68 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 69 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
70 basic_string<_CharT, _Traits, _Alloc>::npos;
71
72 // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
73 // at static init time (before static ctors are run).
74 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 75 typename basic_string<_CharT, _Traits, _Alloc>::size_type
ca566e4c
NM
76 basic_string<_CharT, _Traits, _Alloc>::_Rep::_S_empty_rep_storage[
77 (sizeof(_Rep_base) + sizeof(_CharT) + sizeof(size_type) - 1) /
78 sizeof(size_type)];
725dc051
BK
79
80 // NB: This is the special case for Input Iterators, used in
81 // istreambuf_iterators, etc.
82 // Input Iterators have a cost structure very different from
83 // pointers, calling for a different coding style.
84 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 85 template<typename _InIterator>
725dc051
BK
86 _CharT*
87 basic_string<_CharT, _Traits, _Alloc>::
08addde6 88 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
725dc051
BK
89 input_iterator_tag)
90 {
91 if (__beg == __end && __a == _Alloc())
ca566e4c 92 return _S_empty_rep()._M_refdata();
725dc051 93 // Avoid reallocation for common case.
247791f5 94 _CharT __buf[128];
690495b0
PC
95 size_type __len = 0;
96 while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
ed6814f7
BI
97 {
98 __buf[__len++] = *__beg;
690495b0 99 ++__beg;
725dc051 100 }
690495b0
PC
101 _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
102 traits_type::copy(__r->_M_refdata(), __buf, __len);
ed6814f7 103 try
e2c09482 104 {
690495b0 105 while (__beg != __end)
e2c09482 106 {
690495b0 107 if (__len == __r->_M_capacity)
e2c09482 108 {
690495b0
PC
109 // Allocate more space.
110 _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
ed6814f7 111 traits_type::copy(__another->_M_refdata(),
690495b0
PC
112 __r->_M_refdata(), __len);
113 __r->_M_destroy(__a);
114 __r = __another;
e2c09482 115 }
ed6814f7 116 __r->_M_refdata()[__len++] = *__beg;
690495b0 117 ++__beg;
e2c09482
BK
118 }
119 }
ed6814f7 120 catch(...)
e2c09482 121 {
ed6814f7 122 __r->_M_destroy(__a);
e2c09482
BK
123 __throw_exception_again;
124 }
690495b0
PC
125 __r->_M_length = __len;
126 __r->_M_refdata()[__len] = _Rep::_S_terminal; // grrr.
127 return __r->_M_refdata();
725dc051 128 }
ed6814f7 129
725dc051 130 template<typename _CharT, typename _Traits, typename _Alloc>
91eab378 131 template <typename _InIterator>
725dc051 132 _CharT*
9a304d17 133 basic_string<_CharT, _Traits, _Alloc>::
ed6814f7 134 _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
725dc051
BK
135 forward_iterator_tag)
136 {
085825b8 137 if (__beg == __end && __a == _Alloc())
ca566e4c 138 return _S_empty_rep()._M_refdata();
085825b8 139
ed6814f7 140 // NB: Not required, but considered best practice.
285b36d6 141 if (__builtin_expect(__is_null_pointer(__beg), 0))
0e50667c 142 __throw_logic_error(__N("basic_string::_S_construct NULL not valid"));
aa863dca 143
0e50667c
PC
144 const size_type __dnew = static_cast<size_type>(std::distance(__beg,
145 __end));
725dc051 146 // Check for out_of_range and length_error exceptions.
234e0d31 147 _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
ed6814f7 148 try
e2c09482 149 { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
ed6814f7
BI
150 catch(...)
151 {
152 __r->_M_destroy(__a);
e2c09482
BK
153 __throw_exception_again;
154 }
725dc051 155 __r->_M_length = __dnew;
725dc051
BK
156 __r->_M_refdata()[__dnew] = _Rep::_S_terminal; // grrr.
157 return __r->_M_refdata();
158 }
159
160 template<typename _CharT, typename _Traits, typename _Alloc>
161 _CharT*
9a304d17 162 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
163 _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
164 {
165 if (__n == 0 && __a == _Alloc())
ca566e4c 166 return _S_empty_rep()._M_refdata();
725dc051
BK
167
168 // Check for out_of_range and length_error exceptions.
234e0d31 169 _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
ed6814f7
BI
170 if (__n)
171 traits_type::assign(__r->_M_refdata(), __n, __c);
954b12d2 172
725dc051
BK
173 __r->_M_length = __n;
174 __r->_M_refdata()[__n] = _Rep::_S_terminal; // grrr
175 return __r->_M_refdata();
176 }
177
178 template<typename _CharT, typename _Traits, typename _Alloc>
179 basic_string<_CharT, _Traits, _Alloc>::
180 basic_string(const basic_string& __str)
f26e5597
CB
181 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(__str.get_allocator()),
182 __str.get_allocator()),
183 __str.get_allocator())
725dc051
BK
184 { }
185
186 template<typename _CharT, typename _Traits, typename _Alloc>
187 basic_string<_CharT, _Traits, _Alloc>::
188 basic_string(const _Alloc& __a)
189 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
190 { }
ed6814f7 191
725dc051
BK
192 template<typename _CharT, typename _Traits, typename _Alloc>
193 basic_string<_CharT, _Traits, _Alloc>::
194 basic_string(const basic_string& __str, size_type __pos, size_type __n)
a3af79ea 195 : _M_dataplus(_S_construct(__str._M_data()
0e50667c
PC
196 + __str._M_check(__pos,
197 "basic_string::basic_string"),
690495b0
PC
198 __str._M_data() + __str._M_limit(__pos, __n)
199 + __pos, _Alloc()), _Alloc())
725dc051
BK
200 { }
201
202 template<typename _CharT, typename _Traits, typename _Alloc>
203 basic_string<_CharT, _Traits, _Alloc>::
204 basic_string(const basic_string& __str, size_type __pos,
205 size_type __n, const _Alloc& __a)
a3af79ea 206 : _M_dataplus(_S_construct(__str._M_data()
0e50667c
PC
207 + __str._M_check(__pos,
208 "basic_string::basic_string"),
690495b0
PC
209 __str._M_data() + __str._M_limit(__pos, __n)
210 + __pos, __a), __a)
725dc051
BK
211 { }
212
285b36d6 213 // TBD: DPG annotate
725dc051
BK
214 template<typename _CharT, typename _Traits, typename _Alloc>
215 basic_string<_CharT, _Traits, _Alloc>::
216 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
217 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
218 { }
219
285b36d6 220 // TBD: DPG annotate
725dc051
BK
221 template<typename _CharT, typename _Traits, typename _Alloc>
222 basic_string<_CharT, _Traits, _Alloc>::
223 basic_string(const _CharT* __s, const _Alloc& __a)
085825b8
PC
224 : _M_dataplus(_S_construct(__s, __s ? __s + traits_type::length(__s) :
225 __s + npos, __a), __a)
725dc051
BK
226 { }
227
228 template<typename _CharT, typename _Traits, typename _Alloc>
229 basic_string<_CharT, _Traits, _Alloc>::
230 basic_string(size_type __n, _CharT __c, const _Alloc& __a)
231 : _M_dataplus(_S_construct(__n, __c, __a), __a)
232 { }
285b36d6 233
ed6814f7 234 // TBD: DPG annotate
725dc051 235 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 236 template<typename _InputIterator>
725dc051 237 basic_string<_CharT, _Traits, _Alloc>::
08addde6 238 basic_string(_InputIterator __beg, _InputIterator __end, const _Alloc& __a)
725dc051
BK
239 : _M_dataplus(_S_construct(__beg, __end, __a), __a)
240 { }
241
242 template<typename _CharT, typename _Traits, typename _Alloc>
243 basic_string<_CharT, _Traits, _Alloc>&
ca566e4c
NM
244 basic_string<_CharT, _Traits, _Alloc>::
245 assign(const basic_string& __str)
725dc051
BK
246 {
247 if (_M_rep() != __str._M_rep())
248 {
249 // XXX MT
690495b0 250 const allocator_type __a = this->get_allocator();
725dc051
BK
251 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
252 _M_rep()->_M_dispose(__a);
253 _M_data(__tmp);
254 }
255 return *this;
256 }
2d9d5235 257
2d9d5235
NM
258 template<typename _CharT, typename _Traits, typename _Alloc>
259 basic_string<_CharT, _Traits, _Alloc>&
260 basic_string<_CharT, _Traits, _Alloc>::
261 assign(const _CharT* __s, size_type __n)
262 {
285b36d6 263 __glibcxx_requires_string_len(__s, __n);
2d9d5235 264 if (__n > this->max_size())
0e50667c 265 __throw_length_error(__N("basic_string::assign"));
2d9d5235
NM
266 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
267 || less<const _CharT*>()(_M_data() + this->size(), __s))
7bb9b33b 268 return _M_replace_safe(size_type(0), this->size(), __s, __n);
2d9d5235
NM
269 else
270 {
271 // Work in-place
272 const size_type __pos = __s - _M_data();
273 if (__pos >= __n)
274 traits_type::copy(_M_data(), __s, __n);
275 else if (__pos)
276 traits_type::move(_M_data(), __s, __n);
fd95f498 277 _M_rep()->_M_set_sharable();
2d9d5235
NM
278 _M_rep()->_M_length = __n;
279 _M_data()[__n] = _Rep::_S_terminal; // grr.
280 return *this;
281 }
282 }
283
2d9d5235
NM
284 template<typename _CharT, typename _Traits, typename _Alloc>
285 basic_string<_CharT, _Traits, _Alloc>&
286 basic_string<_CharT, _Traits, _Alloc>::
287 insert(size_type __pos, const _CharT* __s, size_type __n)
288 {
285b36d6 289 __glibcxx_requires_string_len(__s, __n);
04cc8aef 290 _M_check(__pos, "basic_string::insert");
251804e6 291 if (this->max_size() - this->size() < __n)
0e50667c 292 __throw_length_error(__N("basic_string::insert"));
2d9d5235 293 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
e03a6fb7 294 || less<const _CharT*>()(_M_data() + this->size(), __s))
7bb9b33b 295 return _M_replace_safe(__pos, size_type(0), __s, __n);
2d9d5235
NM
296 else
297 {
298 // Work in-place. If _M_mutate reallocates the string, __s
299 // does not point anymore to valid data, therefore we save its
300 // offset, then we restore it.
301 const size_type __off = __s - _M_data();
302 _M_mutate(__pos, 0, __n);
303 __s = _M_data() + __off;
304 _CharT* __p = _M_data() + __pos;
305 if (__s + __n <= __p)
306 traits_type::copy(__p, __s, __n);
307 else if (__s >= __p)
308 traits_type::copy(__p, __s + __n, __n);
309 else
310 {
2cb612d1
PC
311 const size_type __nleft = __p - __s;
312 traits_type::copy(__p, __s, __nleft);
313 traits_type::copy(__p + __nleft, __p + __n, __n - __nleft);
2d9d5235
NM
314 }
315 return *this;
316 }
317 }
ed6814f7 318
2d9d5235
NM
319 template<typename _CharT, typename _Traits, typename _Alloc>
320 basic_string<_CharT, _Traits, _Alloc>&
321 basic_string<_CharT, _Traits, _Alloc>::
322 replace(size_type __pos, size_type __n1, const _CharT* __s,
323 size_type __n2)
324 {
285b36d6 325 __glibcxx_requires_string_len(__s, __n2);
04cc8aef 326 _M_check(__pos, "basic_string::replace");
e03a6fb7 327 __n1 = _M_limit(__pos, __n1);
251804e6 328 if (this->max_size() - (this->size() - __n1) < __n2)
0e50667c 329 __throw_length_error(__N("basic_string::replace"));
2cb612d1 330 bool __left;
2d9d5235 331 if (_M_rep()->_M_is_shared() || less<const _CharT*>()(__s, _M_data())
251804e6 332 || less<const _CharT*>()(_M_data() + this->size(), __s))
7bb9b33b 333 return _M_replace_safe(__pos, __n1, __s, __n2);
2cb612d1
PC
334 else if ((__left = __s + __n2 <= _M_data() + __pos)
335 || _M_data() + __pos + __n1 <= __s)
336 {
337 // Work in-place: non-overlapping case.
338 const size_type __off = __s - _M_data();
339 _M_mutate(__pos, __n1, __n2);
340 if (__left)
341 traits_type::copy(_M_data() + __pos,
342 _M_data() + __off, __n2);
343 else
344 traits_type::copy(_M_data() + __pos,
345 _M_data() + __off + __n2 - __n1, __n2);
346 return *this;
347 }
2d9d5235 348 else
251804e6 349 {
2cb612d1 350 // Todo: overlapping case.
251804e6
PC
351 const basic_string __tmp(__s, __n2);
352 return _M_replace_safe(__pos, __n1, __tmp._M_data(), __n2);
353 }
2d9d5235 354 }
ed6814f7 355
725dc051
BK
356 template<typename _CharT, typename _Traits, typename _Alloc>
357 void
358 basic_string<_CharT, _Traits, _Alloc>::_Rep::
359 _M_destroy(const _Alloc& __a) throw ()
360 {
ca566e4c
NM
361 if (this == &_S_empty_rep())
362 return;
363 const size_type __size = sizeof(_Rep_base) +
364 (this->_M_capacity + 1) * sizeof(_CharT);
725dc051
BK
365 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
366 }
367
368 template<typename _CharT, typename _Traits, typename _Alloc>
369 void
370 basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
371 {
ca566e4c
NM
372 if (_M_rep() == &_S_empty_rep())
373 return;
ed6814f7 374 if (_M_rep()->_M_is_shared())
725dc051
BK
375 _M_mutate(0, 0, 0);
376 _M_rep()->_M_set_leaked();
377 }
378
379 template<typename _CharT, typename _Traits, typename _Alloc>
380 void
381 basic_string<_CharT, _Traits, _Alloc>::
382 _M_mutate(size_type __pos, size_type __len1, size_type __len2)
383 {
7778fa6e 384 const size_type __old_size = this->size();
725dc051 385 const size_type __new_size = __old_size + __len2 - __len1;
725dc051 386 const size_type __how_much = __old_size - __pos - __len1;
ed6814f7 387
ca566e4c
NM
388 if (_M_rep() == &_S_empty_rep()
389 || _M_rep()->_M_is_shared() || __new_size > capacity())
725dc051
BK
390 {
391 // Must reallocate.
91eab378 392 const allocator_type __a = get_allocator();
234e0d31 393 _Rep* __r = _Rep::_S_create(__new_size, capacity(), __a);
954b12d2
PC
394
395 if (__pos)
396 traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
397 if (__how_much)
234e0d31 398 traits_type::copy(__r->_M_refdata() + __pos + __len2,
0a746019 399 _M_data() + __pos + __len1, __how_much);
954b12d2 400
725dc051
BK
401 _M_rep()->_M_dispose(__a);
402 _M_data(__r->_M_refdata());
ca566e4c 403 }
725dc051
BK
404 else if (__how_much && __len1 != __len2)
405 {
406 // Work in-place
0a746019
PC
407 traits_type::move(_M_data() + __pos + __len2,
408 _M_data() + __pos + __len1, __how_much);
725dc051
BK
409 }
410 _M_rep()->_M_set_sharable();
411 _M_rep()->_M_length = __new_size;
412 _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
ca566e4c 413 // You cannot leave those LWG people alone for a second.
725dc051 414 }
ed6814f7 415
725dc051
BK
416 template<typename _CharT, typename _Traits, typename _Alloc>
417 void
418 basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
419 {
cbc67955 420 if (__res != this->capacity() || _M_rep()->_M_is_shared())
725dc051 421 {
e2c09482 422 if (__res > this->max_size())
0e50667c 423 __throw_length_error(__N("basic_string::reserve"));
dcc61724
PC
424 // Make sure we don't shrink below the current size
425 if (__res < this->size())
426 __res = this->size();
91eab378 427 const allocator_type __a = get_allocator();
725dc051
BK
428 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
429 _M_rep()->_M_dispose(__a);
430 _M_data(__tmp);
431 }
432 }
ed6814f7 433
725dc051
BK
434 template<typename _CharT, typename _Traits, typename _Alloc>
435 void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
436 {
ed6814f7 437 if (_M_rep()->_M_is_leaked())
725dc051 438 _M_rep()->_M_set_sharable();
ed6814f7 439 if (__s._M_rep()->_M_is_leaked())
725dc051
BK
440 __s._M_rep()->_M_set_sharable();
441 if (this->get_allocator() == __s.get_allocator())
442 {
443 _CharT* __tmp = _M_data();
444 _M_data(__s._M_data());
445 __s._M_data(__tmp);
446 }
447 // The code below can usually be optimized away.
ed6814f7 448 else
725dc051 449 {
0e50667c
PC
450 const basic_string __tmp1(_M_ibegin(), _M_iend(),
451 __s.get_allocator());
ed6814f7 452 const basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
0e50667c 453 this->get_allocator());
725dc051
BK
454 *this = __tmp2;
455 __s = __tmp1;
456 }
457 }
458
725dc051 459 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 460 typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
725dc051 461 basic_string<_CharT, _Traits, _Alloc>::_Rep::
234e0d31
PC
462 _S_create(size_type __capacity, size_type __old_capacity,
463 const _Alloc& __alloc)
725dc051 464 {
e2c09482 465 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
f5677b15 466 // _GLIBCXX_RESOLVE_LIB_DEFECTS
725dc051 467 // 83. String::npos vs. string::max_size()
e2c09482 468 if (__capacity > _S_max_size)
0e50667c 469 __throw_length_error(__N("basic_string::_S_create"));
725dc051 470
2883d58b
LR
471 // The standard places no restriction on allocating more memory
472 // than is strictly needed within this layer at the moment or as
234e0d31
PC
473 // requested by an explicit application call to reserve().
474
475 // Many malloc implementations perform quite poorly when an
2883d58b
LR
476 // application attempts to allocate memory in a stepwise fashion
477 // growing each allocation size by only 1 char. Additionally,
478 // it makes little sense to allocate less linear memory than the
479 // natural blocking size of the malloc implementation.
480 // Unfortunately, we would need a somewhat low-level calculation
481 // with tuned parameters to get this perfect for any particular
482 // malloc implementation. Fortunately, generalizations about
483 // common features seen among implementations seems to suffice.
2883d58b
LR
484
485 // __pagesize need not match the actual VM page size for good
486 // results in practice, thus we pick a common value on the low
487 // side. __malloc_header_size is an estimate of the amount of
488 // overhead per memory allocation (in practice seen N * sizeof
489 // (void*) where N is 0, 2 or 4). According to folklore,
490 // picking this value on the high side is better than
491 // low-balling it (especially when this algorithm is used with
492 // malloc implementations that allocate memory blocks rounded up
493 // to a size which is a power of 2).
234e0d31
PC
494 const size_type __pagesize = 4096; // must be 2^i * __subpagesize
495 const size_type __subpagesize = 128; // should be >> __malloc_header_size
496 const size_type __malloc_header_size = 4 * sizeof (void*);
497
498 // The below implements an exponential growth policy, necessary to
499 // meet amortized linear time requirements of the library: see
500 // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
501 // It's active for allocations requiring an amount of memory above
502 // system pagesize. This is consistent with the requirements of the
503 // standard: http://gcc.gnu.org/ml/libstdc++/2001-07/msg00130.html
504
505 // The biggest string which fits in a memory page
506 const size_type __page_capacity = ((__pagesize - __malloc_header_size
507 - sizeof(_Rep) - sizeof(_CharT))
508 / sizeof(_CharT));
ed6814f7 509
234e0d31
PC
510 if (__capacity > __old_capacity && __capacity < 2 * __old_capacity
511 && __capacity > __page_capacity)
512 __capacity = 2 * __old_capacity;
513
514 // NB: Need an array of char_type[__capacity], plus a terminating
515 // null char_type() element, plus enough for the _Rep data structure.
516 // Whew. Seemingly so needy, yet so elemental.
517 size_type __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
518
24f33069
PC
519 const size_type __adj_size = __size + __malloc_header_size;
520 if (__adj_size > __pagesize)
2883d58b 521 {
24f33069 522 const size_type __extra = __pagesize - __adj_size % __pagesize;
2883d58b 523 __capacity += __extra / sizeof(_CharT);
d1615643
PC
524 // Never allocate a string bigger than _S_max_size.
525 if (__capacity > _S_max_size)
526 __capacity = _S_max_size;
527 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
2883d58b
LR
528 }
529 else if (__size > __subpagesize)
530 {
24f33069 531 const size_type __extra = __subpagesize - __adj_size % __subpagesize;
2883d58b 532 __capacity += __extra / sizeof(_CharT);
d1615643 533 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
2883d58b
LR
534 }
535
725dc051
BK
536 // NB: Might throw, but no worries about a leak, mate: _Rep()
537 // does not throw.
538 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
539 _Rep *__p = new (__place) _Rep;
540 __p->_M_capacity = __capacity;
d3a193e3 541 __p->_M_set_sharable(); // One reference.
725dc051
BK
542 __p->_M_length = 0;
543 return __p;
544 }
545
546 template<typename _CharT, typename _Traits, typename _Alloc>
547 _CharT*
548 basic_string<_CharT, _Traits, _Alloc>::_Rep::
549 _M_clone(const _Alloc& __alloc, size_type __res)
550 {
79f57f23 551 // Requested capacity of the clone.
ca566e4c 552 const size_type __requested_cap = this->_M_length + __res;
234e0d31
PC
553 _Rep* __r = _Rep::_S_create(__requested_cap, this->_M_capacity,
554 __alloc);
ca566e4c 555 if (this->_M_length)
954b12d2
PC
556 traits_type::copy(__r->_M_refdata(), _M_refdata(),
557 this->_M_length);
558
ca566e4c 559 __r->_M_length = this->_M_length;
acbab5bf 560 __r->_M_refdata()[this->_M_length] = _Rep::_S_terminal;
725dc051
BK
561 return __r->_M_refdata();
562 }
ed6814f7 563
725dc051
BK
564 template<typename _CharT, typename _Traits, typename _Alloc>
565 void
566 basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
567 {
e2c09482 568 if (__n > max_size())
0e50667c 569 __throw_length_error(__N("basic_string::resize"));
7778fa6e 570 const size_type __size = this->size();
725dc051
BK
571 if (__size < __n)
572 this->append(__n - __size, __c);
573 else if (__n < __size)
574 this->erase(__n);
575 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
576 }
418bb880 577
725dc051 578 template<typename _CharT, typename _Traits, typename _Alloc>
08addde6 579 template<typename _InputIterator>
725dc051
BK
580 basic_string<_CharT, _Traits, _Alloc>&
581 basic_string<_CharT, _Traits, _Alloc>::
ed6814f7 582 _M_replace_dispatch(iterator __i1, iterator __i2, _InputIterator __k1,
fefe561e 583 _InputIterator __k2, __false_type)
725dc051 584 {
7778fa6e 585 const basic_string __s(__k1, __k2);
251804e6
PC
586 const size_type __n1 = __i2 - __i1;
587 if (this->max_size() - (this->size() - __n1) < __s.size())
0e50667c 588 __throw_length_error(__N("basic_string::_M_replace_dispatch"));
251804e6 589 return _M_replace_safe(__i1 - _M_ibegin(), __n1, __s._M_data(),
7bb9b33b 590 __s.size());
725dc051
BK
591 }
592
725dc051 593 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
594 basic_string<_CharT, _Traits, _Alloc>&
595 basic_string<_CharT, _Traits, _Alloc>::
725dc051 596 append(const basic_string& __str)
3e7782b2
PC
597 {
598 // Iff appending itself, string needs to pre-reserve the
599 // correct size so that _M_mutate does not clobber the
251804e6 600 // pointer __str._M_data() formed here.
3e7782b2
PC
601 const size_type __size = __str.size();
602 const size_type __len = __size + this->size();
603 if (__len > this->capacity())
604 this->reserve(__len);
7bb9b33b
PC
605 return _M_replace_safe(this->size(), size_type(0), __str._M_data(),
606 __str.size());
3e7782b2 607 }
725dc051
BK
608
609 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
610 basic_string<_CharT, _Traits, _Alloc>&
611 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
612 append(const basic_string& __str, size_type __pos, size_type __n)
613 {
3e7782b2
PC
614 // Iff appending itself, string needs to pre-reserve the
615 // correct size so that _M_mutate does not clobber the
251804e6 616 // pointer __str._M_data() formed here.
04cc8aef 617 __str._M_check(__pos, "basic_string::append");
3e7782b2
PC
618 __n = __str._M_limit(__pos, __n);
619 const size_type __len = __n + this->size();
620 if (__len > this->capacity())
621 this->reserve(__len);
7bb9b33b
PC
622 return _M_replace_safe(this->size(), size_type(0), __str._M_data()
623 + __pos, __n);
725dc051
BK
624 }
625
626 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
627 basic_string<_CharT, _Traits, _Alloc>&
628 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
629 append(const _CharT* __s, size_type __n)
630 {
285b36d6 631 __glibcxx_requires_string_len(__s, __n);
7778fa6e 632 const size_type __len = __n + this->size();
725dc051
BK
633 if (__len > this->capacity())
634 this->reserve(__len);
7bb9b33b 635 return _M_replace_safe(this->size(), size_type(0), __s, __n);
725dc051
BK
636 }
637
638 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17 639 basic_string<_CharT, _Traits, _Alloc>
725dc051 640 operator+(const _CharT* __lhs,
9a304d17 641 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 642 {
285b36d6 643 __glibcxx_requires_string(__lhs);
9a304d17 644 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051 645 typedef typename __string_type::size_type __size_type;
7778fa6e 646 const __size_type __len = _Traits::length(__lhs);
725dc051
BK
647 __string_type __str;
648 __str.reserve(__len + __rhs.size());
bb9909b0 649 __str.append(__lhs, __len);
725dc051
BK
650 __str.append(__rhs);
651 return __str;
652 }
653
654 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
655 basic_string<_CharT, _Traits, _Alloc>
656 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 657 {
9a304d17 658 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051
BK
659 typedef typename __string_type::size_type __size_type;
660 __string_type __str;
7778fa6e 661 const __size_type __len = __rhs.size();
725dc051 662 __str.reserve(__len + 1);
15f13f01 663 __str.append(__size_type(1), __lhs);
725dc051
BK
664 __str.append(__rhs);
665 return __str;
666 }
667
725dc051 668 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 669 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
670 basic_string<_CharT, _Traits, _Alloc>::
671 copy(_CharT* __s, size_type __n, size_type __pos) const
672 {
04cc8aef 673 _M_check(__pos, "basic_string::copy");
e03a6fb7 674 __n = _M_limit(__pos, __n);
285b36d6 675 __glibcxx_requires_string_len(__s, __n);
251804e6
PC
676 if (__n)
677 traits_type::copy(__s, _M_data() + __pos, __n);
725dc051
BK
678 // 21.3.5.7 par 3: do not append null. (good.)
679 return __n;
680 }
681
725dc051 682 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 683 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
684 basic_string<_CharT, _Traits, _Alloc>::
685 find(const _CharT* __s, size_type __pos, size_type __n) const
686 {
285b36d6 687 __glibcxx_requires_string_len(__s, __n);
7778fa6e 688 const size_type __size = this->size();
725dc051 689 const _CharT* __data = _M_data();
fefe561e
PC
690 for (; __pos + __n <= __size; ++__pos)
691 if (traits_type::compare(__data + __pos, __s, __n) == 0)
692 return __pos;
725dc051
BK
693 return npos;
694 }
695
696 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 697 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
698 basic_string<_CharT, _Traits, _Alloc>::
699 find(_CharT __c, size_type __pos) const
700 {
7778fa6e 701 const size_type __size = this->size();
725dc051
BK
702 size_type __ret = npos;
703 if (__pos < __size)
704 {
705 const _CharT* __data = _M_data();
7778fa6e 706 const size_type __n = __size - __pos;
97644827
BK
707 const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
708 if (__p)
725dc051
BK
709 __ret = __p - __data;
710 }
711 return __ret;
712 }
713
725dc051 714 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 715 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
716 basic_string<_CharT, _Traits, _Alloc>::
717 rfind(const _CharT* __s, size_type __pos, size_type __n) const
718 {
285b36d6 719 __glibcxx_requires_string_len(__s, __n);
7778fa6e 720 const size_type __size = this->size();
725dc051
BK
721 if (__n <= __size)
722 {
dd6eaaed 723 __pos = std::min(size_type(__size - __n), __pos);
725dc051 724 const _CharT* __data = _M_data();
ed6814f7 725 do
725dc051
BK
726 {
727 if (traits_type::compare(__data + __pos, __s, __n) == 0)
728 return __pos;
ed6814f7 729 }
725dc051
BK
730 while (__pos-- > 0);
731 }
732 return npos;
733 }
ed6814f7 734
725dc051 735 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 736 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
737 basic_string<_CharT, _Traits, _Alloc>::
738 rfind(_CharT __c, size_type __pos) const
739 {
04cc8aef 740 size_type __size = this->size();
725dc051
BK
741 if (__size)
742 {
04cc8aef
PC
743 if (--__size > __pos)
744 __size = __pos;
745 for (++__size; __size-- > 0; )
746 if (traits_type::eq(_M_data()[__size], __c))
747 return __size;
725dc051
BK
748 }
749 return npos;
750 }
ed6814f7 751
725dc051 752 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 753 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
754 basic_string<_CharT, _Traits, _Alloc>::
755 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
756 {
285b36d6 757 __glibcxx_requires_string_len(__s, __n);
725dc051
BK
758 for (; __n && __pos < this->size(); ++__pos)
759 {
97644827
BK
760 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
761 if (__p)
725dc051
BK
762 return __pos;
763 }
764 return npos;
765 }
ed6814f7 766
725dc051 767 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 768 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
769 basic_string<_CharT, _Traits, _Alloc>::
770 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
771 {
285b36d6 772 __glibcxx_requires_string_len(__s, __n);
725dc051
BK
773 size_type __size = this->size();
774 if (__size && __n)
ed6814f7
BI
775 {
776 if (--__size > __pos)
725dc051
BK
777 __size = __pos;
778 do
779 {
97644827 780 if (traits_type::find(__s, __n, _M_data()[__size]))
725dc051 781 return __size;
ed6814f7 782 }
725dc051
BK
783 while (__size-- != 0);
784 }
785 return npos;
786 }
ed6814f7 787
725dc051 788 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 789 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
790 basic_string<_CharT, _Traits, _Alloc>::
791 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
792 {
285b36d6 793 __glibcxx_requires_string_len(__s, __n);
fefe561e
PC
794 for (; __pos < this->size(); ++__pos)
795 if (!traits_type::find(__s, __n, _M_data()[__pos]))
796 return __pos;
725dc051
BK
797 return npos;
798 }
799
800 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 801 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
802 basic_string<_CharT, _Traits, _Alloc>::
803 find_first_not_of(_CharT __c, size_type __pos) const
804 {
fefe561e
PC
805 for (; __pos < this->size(); ++__pos)
806 if (!traits_type::eq(_M_data()[__pos], __c))
807 return __pos;
725dc051
BK
808 return npos;
809 }
810
811 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 812 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
813 basic_string<_CharT, _Traits, _Alloc>::
814 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
815 {
285b36d6 816 __glibcxx_requires_string_len(__s, __n);
04cc8aef 817 size_type __size = this->size();
ba317c52 818 if (__size)
04cc8aef
PC
819 {
820 if (--__size > __pos)
821 __size = __pos;
ed6814f7 822 do
725dc051 823 {
04cc8aef
PC
824 if (!traits_type::find(__s, __n, _M_data()[__size]))
825 return __size;
ed6814f7 826 }
04cc8aef 827 while (__size--);
725dc051
BK
828 }
829 return npos;
830 }
831
832 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 833 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
834 basic_string<_CharT, _Traits, _Alloc>::
835 find_last_not_of(_CharT __c, size_type __pos) const
836 {
04cc8aef 837 size_type __size = this->size();
725dc051 838 if (__size)
fefe561e 839 {
04cc8aef 840 if (--__size > __pos)
ed6814f7 841 __size = __pos;
725dc051
BK
842 do
843 {
04cc8aef
PC
844 if (!traits_type::eq(_M_data()[__size], __c))
845 return __size;
ed6814f7 846 }
04cc8aef 847 while (__size--);
725dc051
BK
848 }
849 return npos;
850 }
ed6814f7 851
725dc051
BK
852 template<typename _CharT, typename _Traits, typename _Alloc>
853 int
854 basic_string<_CharT, _Traits, _Alloc>::
855 compare(size_type __pos, size_type __n, const basic_string& __str) const
856 {
04cc8aef 857 _M_check(__pos, "basic_string::compare");
e03a6fb7 858 __n = _M_limit(__pos, __n);
7778fa6e 859 const size_type __osize = __str.size();
e03a6fb7 860 const size_type __len = std::min(__n, __osize);
725dc051
BK
861 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
862 if (!__r)
e03a6fb7 863 __r = __n - __osize;
725dc051
BK
864 return __r;
865 }
866
867 template<typename _CharT, typename _Traits, typename _Alloc>
868 int
869 basic_string<_CharT, _Traits, _Alloc>::
870 compare(size_type __pos1, size_type __n1, const basic_string& __str,
871 size_type __pos2, size_type __n2) const
872 {
04cc8aef
PC
873 _M_check(__pos1, "basic_string::compare");
874 __str._M_check(__pos2, "basic_string::compare");
e03a6fb7
PC
875 __n1 = _M_limit(__pos1, __n1);
876 __n2 = __str._M_limit(__pos2, __n2);
877 const size_type __len = std::min(__n1, __n2);
ed6814f7 878 int __r = traits_type::compare(_M_data() + __pos1,
725dc051
BK
879 __str.data() + __pos2, __len);
880 if (!__r)
e03a6fb7 881 __r = __n1 - __n2;
725dc051
BK
882 return __r;
883 }
884
725dc051
BK
885 template<typename _CharT, typename _Traits, typename _Alloc>
886 int
887 basic_string<_CharT, _Traits, _Alloc>::
888 compare(const _CharT* __s) const
889 {
285b36d6 890 __glibcxx_requires_string(__s);
7778fa6e
PC
891 const size_type __size = this->size();
892 const size_type __osize = traits_type::length(__s);
893 const size_type __len = std::min(__size, __osize);
c86c54e6 894 int __r = traits_type::compare(_M_data(), __s, __len);
725dc051 895 if (!__r)
c86c54e6 896 __r = __size - __osize;
725dc051
BK
897 return __r;
898 }
899
3b0fd4bc
BK
900 template<typename _CharT, typename _Traits, typename _Alloc>
901 int
9a304d17 902 basic_string <_CharT, _Traits, _Alloc>::
3b0fd4bc
BK
903 compare(size_type __pos, size_type __n1, const _CharT* __s) const
904 {
285b36d6 905 __glibcxx_requires_string(__s);
04cc8aef 906 _M_check(__pos, "basic_string::compare");
e03a6fb7 907 __n1 = _M_limit(__pos, __n1);
7778fa6e 908 const size_type __osize = traits_type::length(__s);
e03a6fb7 909 const size_type __len = std::min(__n1, __osize);
3b0fd4bc
BK
910 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
911 if (!__r)
e03a6fb7 912 __r = __n1 - __osize;
3b0fd4bc
BK
913 return __r;
914 }
915
725dc051
BK
916 template<typename _CharT, typename _Traits, typename _Alloc>
917 int
9a304d17 918 basic_string <_CharT, _Traits, _Alloc>::
ed6814f7 919 compare(size_type __pos, size_type __n1, const _CharT* __s,
725dc051
BK
920 size_type __n2) const
921 {
285b36d6 922 __glibcxx_requires_string_len(__s, __n2);
04cc8aef 923 _M_check(__pos, "basic_string::compare");
e03a6fb7
PC
924 __n1 = _M_limit(__pos, __n1);
925 const size_type __len = std::min(__n1, __n2);
725dc051
BK
926 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
927 if (!__r)
e03a6fb7 928 __r = __n1 - __n2;
725dc051
BK
929 return __r;
930 }
931
a32e3c09 932 // Inhibit implicit instantiations for required instantiations,
ed6814f7 933 // which are defined via explicit instantiations elsewhere.
a32e3c09 934 // NB: This syntax is a GNU extension.
3d7c150e 935#if _GLIBCXX_EXTERN_TEMPLATE
a32e3c09 936 extern template class basic_string<char>;
ed6814f7
BI
937 extern template
938 basic_istream<char>&
a32e3c09 939 operator>>(basic_istream<char>&, string&);
ed6814f7
BI
940 extern template
941 basic_ostream<char>&
a32e3c09 942 operator<<(basic_ostream<char>&, const string&);
ed6814f7
BI
943 extern template
944 basic_istream<char>&
a32e3c09 945 getline(basic_istream<char>&, string&, char);
ed6814f7
BI
946 extern template
947 basic_istream<char>&
a32e3c09
BK
948 getline(basic_istream<char>&, string&);
949
3d7c150e 950#ifdef _GLIBCXX_USE_WCHAR_T
a32e3c09 951 extern template class basic_string<wchar_t>;
ed6814f7
BI
952 extern template
953 basic_istream<wchar_t>&
a32e3c09 954 operator>>(basic_istream<wchar_t>&, wstring&);
ed6814f7
BI
955 extern template
956 basic_ostream<wchar_t>&
a32e3c09 957 operator<<(basic_ostream<wchar_t>&, const wstring&);
ed6814f7
BI
958 extern template
959 basic_istream<wchar_t>&
a32e3c09 960 getline(basic_istream<wchar_t>&, wstring&, wchar_t);
ed6814f7
BI
961 extern template
962 basic_istream<wchar_t>&
a32e3c09 963 getline(basic_istream<wchar_t>&, wstring&);
5112ae3a 964#endif
1bc8b0ad 965#endif
3b0fd4bc 966} // namespace std
725dc051 967
3b0fd4bc 968#endif