]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/include/bits/basic_string.tcc
Daily bump.
[thirdparty/gcc.git] / libstdc++-v3 / include / bits / basic_string.tcc
CommitLineData
725dc051
BK
1// Components for manipulating sequences of characters -*- C++ -*-
2
e61c3e8c 3// Copyright (C) 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
725dc051
BK
4//
5// This file is part of the GNU ISO C++ Library. This library is free
6// software; you can redistribute it and/or modify it under the
7// terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2, or (at your option)
9// any later version.
10
11// This library is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License along
17// with this library; see the file COPYING. If not, write to the Free
18// Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19// USA.
20
21// As a special exception, you may use this file as part of a free software
22// library without restriction. Specifically, if other files instantiate
23// templates or use macros or inline functions from this file, or you compile
24// this file and link it with other files to produce an executable, this
25// file does not by itself cause the resulting executable to be covered by
26// the GNU General Public License. This exception does not however
27// invalidate any other reasons why the executable file might be covered by
28// the GNU General Public License.
29
30//
31// ISO C++ 14882: 21 Strings library
32//
33
34// This file is included by <string>. It is not meant to be included
35// separately.
36
37// Written by Jason Merrill based upon the specification by Takanori Adachi
38// in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882.
39
40#ifndef _CPP_BITS_STRING_TCC
41#define _CPP_BITS_STRING_TCC 1
42
43namespace std
44{
725dc051 45 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 46 const _CharT
725dc051
BK
47 basic_string<_CharT, _Traits, _Alloc>::
48 _Rep::_S_terminal = _CharT();
49
50 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 51 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
52 basic_string<_CharT, _Traits, _Alloc>::
53 _Rep::_S_max_size = (((npos - sizeof(_Rep))/sizeof(_CharT)) - 1) / 4;
54
55 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 56 const typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
57 basic_string<_CharT, _Traits, _Alloc>::npos;
58
59 // Linker sets _S_empty_rep_storage to all 0s (one reference, empty string)
60 // at static init time (before static ctors are run).
61 template<typename _CharT, typename _Traits, typename _Alloc>
4f12dd3c 62 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
63 basic_string<_CharT, _Traits, _Alloc>::_S_empty_rep_storage[
64 (sizeof(_Rep) + sizeof(_CharT) + sizeof(size_type) - 1)/sizeof(size_type)];
65
66 // NB: This is the special case for Input Iterators, used in
67 // istreambuf_iterators, etc.
68 // Input Iterators have a cost structure very different from
69 // pointers, calling for a different coding style.
70 template<typename _CharT, typename _Traits, typename _Alloc>
71 template<typename _InIter>
72 _CharT*
73 basic_string<_CharT, _Traits, _Alloc>::
74 _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
75 input_iterator_tag)
76 {
77 if (__beg == __end && __a == _Alloc())
78 return _S_empty_rep()._M_refcopy();
79 // Avoid reallocation for common case.
80 _CharT __buf[100];
81 size_type __i = 0;
82 while (__beg != __end && __i < sizeof(__buf) / sizeof(_CharT))
83 {
84 __buf[__i++] = *__beg;
85 ++__beg;
86 }
87 _Rep* __r = _Rep::_S_create(__i, __a);
88 traits_type::copy(__r->_M_refdata(), __buf, __i);
89 __r->_M_length = __i;
e2c09482
BK
90 try
91 {
92 // NB: this loop looks precisely this way because
93 // it avoids comparing __beg != __end any more
94 // than strictly necessary; != might be expensive!
95 for (;;)
96 {
97 _CharT* __p = __r->_M_refdata() + __r->_M_length;
98 _CharT* __last = __r->_M_refdata() + __r->_M_capacity;
99 for (;;)
100 {
101 if (__beg == __end)
102 {
103 __r->_M_length = __p - __r->_M_refdata();
104 *__p = _Rep::_S_terminal; // grrr.
105 return __r->_M_refdata();
106 }
107 if (__p == __last)
108 break;
109 *__p++ = *__beg;
110 ++__beg;
111 }
112 // Allocate more space.
113 size_type __len = __p - __r->_M_refdata();
114 _Rep* __another = _Rep::_S_create(__len + 1, __a);
115 traits_type::copy(__another->_M_refdata(),
116 __r->_M_refdata(), __len);
117 __r->_M_destroy(__a);
118 __r = __another;
119 __r->_M_length = __len;
120 }
121 }
122 catch(...)
123 {
725dc051 124 __r->_M_destroy(__a);
e2c09482
BK
125 __throw_exception_again;
126 }
725dc051
BK
127 return 0;
128 }
e2c09482 129
725dc051
BK
130 template<typename _CharT, typename _Traits, typename _Alloc>
131 template <class _InIter>
132 _CharT*
9a304d17 133 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
134 _S_construct(_InIter __beg, _InIter __end, const _Alloc& __a,
135 forward_iterator_tag)
136 {
137 size_type __dnew = static_cast<size_type>(distance(__beg, __end));
138
139 if (__beg == __end && __a == _Alloc())
140 return _S_empty_rep()._M_refcopy();
141
142 // Check for out_of_range and length_error exceptions.
143 _Rep* __r = _Rep::_S_create(__dnew, __a);
e2c09482
BK
144 try
145 { _S_copy_chars(__r->_M_refdata(), __beg, __end); }
146 catch(...)
147 {
148 __r->_M_destroy(__a);
149 __throw_exception_again;
150 }
725dc051
BK
151 __r->_M_length = __dnew;
152
153 __r->_M_refdata()[__dnew] = _Rep::_S_terminal; // grrr.
154 return __r->_M_refdata();
155 }
156
157 template<typename _CharT, typename _Traits, typename _Alloc>
158 _CharT*
9a304d17 159 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
160 _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
161 {
162 if (__n == 0 && __a == _Alloc())
163 return _S_empty_rep()._M_refcopy();
164
165 // Check for out_of_range and length_error exceptions.
166 _Rep* __r = _Rep::_S_create(__n, __a);
e2c09482
BK
167 try
168 {
169 if (__n)
170 traits_type::assign(__r->_M_refdata(), __n, __c);
171 }
172 catch(...)
173 {
174 __r->_M_destroy(__a);
175 __throw_exception_again;
176 }
725dc051
BK
177 __r->_M_length = __n;
178 __r->_M_refdata()[__n] = _Rep::_S_terminal; // grrr
179 return __r->_M_refdata();
180 }
181
182 template<typename _CharT, typename _Traits, typename _Alloc>
183 basic_string<_CharT, _Traits, _Alloc>::
184 basic_string(const basic_string& __str)
185 : _M_dataplus(__str._M_rep()->_M_grab(_Alloc(), __str.get_allocator()),
186 __str.get_allocator())
187 { }
188
189 template<typename _CharT, typename _Traits, typename _Alloc>
190 basic_string<_CharT, _Traits, _Alloc>::
191 basic_string(const _Alloc& __a)
192 : _M_dataplus(_S_construct(size_type(), _CharT(), __a), __a)
193 { }
194
195 template<typename _CharT, typename _Traits, typename _Alloc>
196 basic_string<_CharT, _Traits, _Alloc>::
197 basic_string(const basic_string& __str, size_type __pos, size_type __n)
198 : _M_dataplus(_S_construct(__str._M_check(__pos),
199 __str._M_fold(__pos, __n), _Alloc()), _Alloc())
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)
206 : _M_dataplus(_S_construct(__str._M_check(__pos),
207 __str._M_fold(__pos, __n), __a), __a)
208 { }
209
210 template<typename _CharT, typename _Traits, typename _Alloc>
211 basic_string<_CharT, _Traits, _Alloc>::
212 basic_string(const _CharT* __s, size_type __n, const _Alloc& __a)
213 : _M_dataplus(_S_construct(__s, __s + __n, __a), __a)
214 { }
215
216 template<typename _CharT, typename _Traits, typename _Alloc>
217 basic_string<_CharT, _Traits, _Alloc>::
218 basic_string(const _CharT* __s, const _Alloc& __a)
219 : _M_dataplus(_S_construct(__s, __s + traits_type::length(__s), __a), __a)
220 { }
221
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)
226 { }
227
228 template<typename _CharT, typename _Traits, typename _Alloc>
229 template<typename _InputIter>
230 basic_string<_CharT, _Traits, _Alloc>::
231 basic_string(_InputIter __beg, _InputIter __end, const _Alloc& __a)
232 : _M_dataplus(_S_construct(__beg, __end, __a), __a)
233 { }
234
235 template<typename _CharT, typename _Traits, typename _Alloc>
236 basic_string<_CharT, _Traits, _Alloc>&
237 basic_string<_CharT, _Traits, _Alloc>::assign(const basic_string& __str)
238 {
239 if (_M_rep() != __str._M_rep())
240 {
241 // XXX MT
242 allocator_type __a = this->get_allocator();
243 _CharT* __tmp = __str._M_rep()->_M_grab(__a, __str.get_allocator());
244 _M_rep()->_M_dispose(__a);
245 _M_data(__tmp);
246 }
247 return *this;
248 }
249
250 template<typename _CharT, typename _Traits, typename _Alloc>
251 void
252 basic_string<_CharT, _Traits, _Alloc>::_Rep::
253 _M_destroy(const _Alloc& __a) throw ()
254 {
255 size_type __size = sizeof(_Rep) + (_M_capacity + 1) * sizeof(_CharT);
256 _Raw_bytes_alloc(__a).deallocate(reinterpret_cast<char*>(this), __size);
257 }
258
259 template<typename _CharT, typename _Traits, typename _Alloc>
260 void
261 basic_string<_CharT, _Traits, _Alloc>::_M_leak_hard()
262 {
263 if (_M_rep()->_M_is_shared())
264 _M_mutate(0, 0, 0);
265 _M_rep()->_M_set_leaked();
266 }
267
268 template<typename _CharT, typename _Traits, typename _Alloc>
269 void
270 basic_string<_CharT, _Traits, _Alloc>::
271 _M_mutate(size_type __pos, size_type __len1, size_type __len2)
272 {
273 size_type __old_size = this->size();
274 const size_type __new_size = __old_size + __len2 - __len1;
275 const _CharT* __src = _M_data() + __pos + __len1;
276 const size_type __how_much = __old_size - __pos - __len1;
277
278 if (_M_rep()->_M_is_shared() || __new_size > capacity())
279 {
280 // Must reallocate.
281 allocator_type __a = get_allocator();
282 _Rep* __r = _Rep::_S_create(__new_size, __a);
e2c09482
BK
283 try
284 {
285 if (__pos)
286 traits_type::copy(__r->_M_refdata(), _M_data(), __pos);
287 if (__how_much)
288 traits_type::copy(__r->_M_refdata() + __pos + __len2,
289 __src, __how_much);
290 }
291 catch(...)
292 {
293 __r->_M_dispose(get_allocator());
294 __throw_exception_again;
295 }
725dc051
BK
296 _M_rep()->_M_dispose(__a);
297 _M_data(__r->_M_refdata());
298 }
299 else if (__how_much && __len1 != __len2)
300 {
301 // Work in-place
302 traits_type::move(_M_data() + __pos + __len2, __src, __how_much);
303 }
304 _M_rep()->_M_set_sharable();
305 _M_rep()->_M_length = __new_size;
306 _M_data()[__new_size] = _Rep::_S_terminal; // grrr. (per 21.3.4)
307 // You cannot leave those LWG people alone for a second.
308 }
309
310 template<typename _CharT, typename _Traits, typename _Alloc>
311 void
312 basic_string<_CharT, _Traits, _Alloc>::reserve(size_type __res)
313 {
314 if (__res > this->capacity() || _M_rep()->_M_is_shared())
315 {
e2c09482
BK
316 if (__res > this->max_size())
317 __throw_length_error("basic_string::reserve");
dcc61724
PC
318 // Make sure we don't shrink below the current size
319 if (__res < this->size())
320 __res = this->size();
725dc051
BK
321 allocator_type __a = get_allocator();
322 _CharT* __tmp = _M_rep()->_M_clone(__a, __res - this->size());
323 _M_rep()->_M_dispose(__a);
324 _M_data(__tmp);
325 }
326 }
327
328 template<typename _CharT, typename _Traits, typename _Alloc>
329 void basic_string<_CharT, _Traits, _Alloc>::swap(basic_string& __s)
330 {
331 if (_M_rep()->_M_is_leaked())
332 _M_rep()->_M_set_sharable();
333 if (__s._M_rep()->_M_is_leaked())
334 __s._M_rep()->_M_set_sharable();
335 if (this->get_allocator() == __s.get_allocator())
336 {
337 _CharT* __tmp = _M_data();
338 _M_data(__s._M_data());
339 __s._M_data(__tmp);
340 }
341 // The code below can usually be optimized away.
342 else
343 {
344 basic_string __tmp1(_M_ibegin(), _M_iend(), __s.get_allocator());
345 basic_string __tmp2(__s._M_ibegin(), __s._M_iend(),
346 this->get_allocator());
347 *this = __tmp2;
348 __s = __tmp1;
349 }
350 }
351
725dc051 352 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 353 typename basic_string<_CharT, _Traits, _Alloc>::_Rep*
725dc051
BK
354 basic_string<_CharT, _Traits, _Alloc>::_Rep::
355 _S_create(size_t __capacity, const _Alloc& __alloc)
356 {
e2c09482 357 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051
BK
358#ifdef _GLIBCPP_RESOLVE_LIB_DEFECTS
359 // 83. String::npos vs. string::max_size()
e2c09482 360 if (__capacity > _S_max_size)
725dc051 361#else
e2c09482 362 if (__capacity == npos)
725dc051 363#endif
e2c09482 364 __throw_length_error("basic_string::_S_create");
725dc051
BK
365
366 // NB: Need an array of char_type[__capacity], plus a
367 // terminating null char_type() element, plus enough for the
368 // _Rep data structure. Whew. Seemingly so needy, yet so elemental.
369 size_t __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
2883d58b
LR
370
371 // The standard places no restriction on allocating more memory
372 // than is strictly needed within this layer at the moment or as
373 // requested by an explicit application call to reserve(). Many
374 // malloc implementations perform quite poorly when an
375 // application attempts to allocate memory in a stepwise fashion
376 // growing each allocation size by only 1 char. Additionally,
377 // it makes little sense to allocate less linear memory than the
378 // natural blocking size of the malloc implementation.
379 // Unfortunately, we would need a somewhat low-level calculation
380 // with tuned parameters to get this perfect for any particular
381 // malloc implementation. Fortunately, generalizations about
382 // common features seen among implementations seems to suffice.
383 // This algorithm does not replace the need for an exponential
384 // growth shaper to meet library specification. Note: THIS IS
385 // NOT THE CORRECT LOCATION FOR AN EXPONENTIAL GROWTH SHAPER
386 // (since this code affect initial allocation as well as
387 // reallocation).
388
389 // __pagesize need not match the actual VM page size for good
390 // results in practice, thus we pick a common value on the low
391 // side. __malloc_header_size is an estimate of the amount of
392 // overhead per memory allocation (in practice seen N * sizeof
393 // (void*) where N is 0, 2 or 4). According to folklore,
394 // picking this value on the high side is better than
395 // low-balling it (especially when this algorithm is used with
396 // malloc implementations that allocate memory blocks rounded up
397 // to a size which is a power of 2).
398 const size_t __pagesize = 4096; // must be 2^i * __subpagesize
399 const size_t __subpagesize = 128; // should be >> __malloc_header_size
400 const size_t __malloc_header_size = 4 * sizeof (void*);
401 if ((__size + __malloc_header_size) > __pagesize)
402 {
403 size_t __extra =
404 (__pagesize - ((__size + __malloc_header_size) % __pagesize))
405 % __pagesize;
406 __capacity += __extra / sizeof(_CharT);
407 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
408 }
409 else if (__size > __subpagesize)
410 {
411 size_t __extra =
412 (__subpagesize - ((__size + __malloc_header_size) % __subpagesize))
413 % __subpagesize;
414 __capacity += __extra / sizeof(_CharT);
415 __size = (__capacity + 1) * sizeof(_CharT) + sizeof(_Rep);
416 }
417
725dc051
BK
418 // NB: Might throw, but no worries about a leak, mate: _Rep()
419 // does not throw.
420 void* __place = _Raw_bytes_alloc(__alloc).allocate(__size);
421 _Rep *__p = new (__place) _Rep;
422 __p->_M_capacity = __capacity;
423 __p->_M_set_sharable(); // one reference
424 __p->_M_length = 0;
425 return __p;
426 }
427
428 template<typename _CharT, typename _Traits, typename _Alloc>
429 _CharT*
430 basic_string<_CharT, _Traits, _Alloc>::_Rep::
431 _M_clone(const _Alloc& __alloc, size_type __res)
432 {
433 _Rep* __r = _Rep::_S_create(_M_length + __res, __alloc);
434 if (_M_length)
435 {
e2c09482
BK
436 try
437 { traits_type::copy(__r->_M_refdata(), _M_refdata(), _M_length); }
438 catch(...)
439 {
440 __r->_M_destroy(__alloc);
441 __throw_exception_again;
442 }
725dc051
BK
443 }
444 __r->_M_length = _M_length;
445 return __r->_M_refdata();
446 }
447
725dc051
BK
448 template<typename _CharT, typename _Traits, typename _Alloc>
449 void
450 basic_string<_CharT, _Traits, _Alloc>::resize(size_type __n, _CharT __c)
451 {
e2c09482
BK
452 if (__n > max_size())
453 __throw_length_error("basic_string::resize");
725dc051
BK
454 size_type __size = this->size();
455 if (__size < __n)
456 this->append(__n - __size, __c);
457 else if (__n < __size)
458 this->erase(__n);
459 // else nothing (in particular, avoid calling _M_mutate() unnecessarily.)
460 }
461
462 template<typename _CharT, typename _Traits, typename _Alloc>
463 template<typename _InputIter>
464 basic_string<_CharT, _Traits, _Alloc>&
465 basic_string<_CharT, _Traits, _Alloc>::
466 _M_replace(iterator __i1, iterator __i2, _InputIter __k1,
467 _InputIter __k2, input_iterator_tag)
468 {
469 basic_string __s(__k1, __k2);
470 return this->replace(__i1, __i2, __s._M_ibegin(), __s._M_iend());
471 }
472
473 template<typename _CharT, typename _Traits, typename _Alloc>
474 template<typename _ForwardIter>
475 basic_string<_CharT, _Traits, _Alloc>&
476 basic_string<_CharT, _Traits, _Alloc>::
477 _M_replace(iterator __i1, iterator __i2, _ForwardIter __k1,
478 _ForwardIter __k2, forward_iterator_tag)
479 {
9a304d17 480 size_type __dnew = static_cast<size_type>(distance(__k1, __k2));
725dc051
BK
481 size_type __dold = __i2 - __i1;
482 size_type __dmax = this->max_size();
725dc051 483
e2c09482
BK
484 if (__dmax <= __dnew)
485 __throw_length_error("basic_string::_M_replace");
725dc051 486 size_type __off = __i1 - _M_ibegin();
9a304d17
PC
487
488 // Save concerned source string data in a temporary.
489 basic_string __temp(__k1, __k2);
725dc051 490 _M_mutate(__off, __dold, __dnew);
725dc051 491
9a304d17
PC
492 // Invalidated __i1, __i2 (and clobbered original source string
493 // data when destination string == source string and the string
494 // is unshared).
495 if (__dnew)
496 _S_copy_chars(_M_data() + __off, __temp.begin(), __temp.end());
497
725dc051
BK
498 return *this;
499 }
500
501 template<typename _CharT, typename _Traits, typename _Alloc>
502 basic_string<_CharT, _Traits, _Alloc>&
503 basic_string<_CharT, _Traits, _Alloc>::
504 replace(size_type __pos1, size_type __n1, const basic_string& __str,
505 size_type __pos2, size_type __n2)
506 {
507 return this->replace(_M_check(__pos1), _M_fold(__pos1, __n1),
508 __str._M_check(__pos2),
509 __str._M_fold(__pos2, __n2));
510 }
511
512 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
513 basic_string<_CharT, _Traits, _Alloc>&
514 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
515 append(const basic_string& __str)
516 {
517 // Iff appending itself, string needs to pre-reserve the
518 // correct size so that _M_mutate does not clobber the
519 // iterators formed here.
520 size_type __size = __str.size();
521 size_type __len = __size + this->size();
522 if (__len > this->capacity())
523 this->reserve(__len);
524 return this->replace(_M_iend(), _M_iend(), __str._M_ibegin(),
525 __str._M_iend());
526 }
527
528 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
529 basic_string<_CharT, _Traits, _Alloc>&
530 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
531 append(const basic_string& __str, size_type __pos, size_type __n)
532 {
533 // Iff appending itself, string needs to pre-reserve the
534 // correct size so that _M_mutate does not clobber the
535 // iterators formed here.
536 size_type __len = min(__str.size() - __pos, __n) + this->size();
537 if (__len > this->capacity())
538 this->reserve(__len);
539 return this->replace(_M_iend(), _M_iend(), __str._M_check(__pos),
540 __str._M_fold(__pos, __n));
541 }
542
543 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
544 basic_string<_CharT, _Traits, _Alloc>&
545 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
546 append(const _CharT* __s, size_type __n)
547 {
548 size_type __len = __n + this->size();
549 if (__len > this->capacity())
550 this->reserve(__len);
551 return this->replace(_M_iend(), _M_iend(), __s, __s + __n);
552 }
553
554 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
555 basic_string<_CharT, _Traits, _Alloc>&
556 basic_string<_CharT, _Traits, _Alloc>::
725dc051
BK
557 append(size_type __n, _CharT __c)
558 {
559 size_type __len = __n + this->size();
560 if (__len > this->capacity())
561 this->reserve(__len);
562 return this->replace(_M_iend(), _M_iend(), __n, __c);
563 }
564
565 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17 566 basic_string<_CharT, _Traits, _Alloc>
725dc051 567 operator+(const _CharT* __lhs,
9a304d17 568 const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 569 {
9a304d17 570 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051
BK
571 typedef typename __string_type::size_type __size_type;
572 __size_type __len = _Traits::length(__lhs);
573 __string_type __str;
574 __str.reserve(__len + __rhs.size());
575 __str.append(__lhs, __lhs + __len);
576 __str.append(__rhs);
577 return __str;
578 }
579
580 template<typename _CharT, typename _Traits, typename _Alloc>
9a304d17
PC
581 basic_string<_CharT, _Traits, _Alloc>
582 operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs)
725dc051 583 {
9a304d17 584 typedef basic_string<_CharT, _Traits, _Alloc> __string_type;
725dc051
BK
585 typedef typename __string_type::size_type __size_type;
586 __string_type __str;
587 __size_type __len = __rhs.size();
588 __str.reserve(__len + 1);
15f13f01 589 __str.append(__size_type(1), __lhs);
725dc051
BK
590 __str.append(__rhs);
591 return __str;
592 }
593
594 template<typename _CharT, typename _Traits, typename _Alloc>
595 basic_string<_CharT, _Traits, _Alloc>&
596 basic_string<_CharT, _Traits, _Alloc>::
597 replace(iterator __i1, iterator __i2, size_type __n2, _CharT __c)
598 {
599 size_type __n1 = __i2 - __i1;
600 size_type __off1 = __i1 - _M_ibegin();
e2c09482
BK
601 if (max_size() - (this->size() - __n1) <= __n2)
602 __throw_length_error("basic_string::replace");
725dc051
BK
603 _M_mutate (__off1, __n1, __n2);
604 // Invalidated __i1, __i2
605 if (__n2)
606 traits_type::assign(_M_data() + __off1, __n2, __c);
607 return *this;
608 }
609
610 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 611 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
612 basic_string<_CharT, _Traits, _Alloc>::
613 copy(_CharT* __s, size_type __n, size_type __pos) const
614 {
e2c09482
BK
615 if (__pos > this->size())
616 __throw_out_of_range("basic_string::copy");
725dc051
BK
617
618 if (__n > this->size() - __pos)
619 __n = this->size() - __pos;
620
621 traits_type::copy(__s, _M_data() + __pos, __n);
622 // 21.3.5.7 par 3: do not append null. (good.)
623 return __n;
624 }
625
725dc051 626 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 627 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
628 basic_string<_CharT, _Traits, _Alloc>::
629 find(const _CharT* __s, size_type __pos, size_type __n) const
630 {
97644827 631 size_type __size = this->size();
725dc051
BK
632 size_t __xpos = __pos;
633 const _CharT* __data = _M_data();
97644827 634 for (; __xpos + __n <= __size; ++__xpos)
725dc051
BK
635 if (traits_type::compare(__data + __xpos, __s, __n) == 0)
636 return __xpos;
637 return npos;
638 }
639
640 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 641 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
642 basic_string<_CharT, _Traits, _Alloc>::
643 find(_CharT __c, size_type __pos) const
644 {
645 size_type __size = this->size();
646 size_type __ret = npos;
647 if (__pos < __size)
648 {
649 const _CharT* __data = _M_data();
97644827
BK
650 size_type __n = __size - __pos;
651 const _CharT* __p = traits_type::find(__data + __pos, __n, __c);
652 if (__p)
725dc051
BK
653 __ret = __p - __data;
654 }
655 return __ret;
656 }
657
658
659 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 660 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
661 basic_string<_CharT, _Traits, _Alloc>::
662 rfind(const _CharT* __s, size_type __pos, size_type __n) const
663 {
664 size_type __size = this->size();
665 if (__n <= __size)
666 {
9a304d17 667 __pos = std::min(__size - __n, __pos);
725dc051
BK
668 const _CharT* __data = _M_data();
669 do
670 {
671 if (traits_type::compare(__data + __pos, __s, __n) == 0)
672 return __pos;
673 }
674 while (__pos-- > 0);
675 }
676 return npos;
677 }
678
679 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 680 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
681 basic_string<_CharT, _Traits, _Alloc>::
682 rfind(_CharT __c, size_type __pos) const
683 {
684 size_type __size = this->size();
685 if (__size)
686 {
687 size_t __xpos = __size - 1;
688 if (__xpos > __pos)
689 __xpos = __pos;
690
691 for (++__xpos; __xpos-- > 0; )
692 if (traits_type::eq(_M_data()[__xpos], __c))
693 return __xpos;
694 }
695 return npos;
696 }
697
698 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 699 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
700 basic_string<_CharT, _Traits, _Alloc>::
701 find_first_of(const _CharT* __s, size_type __pos, size_type __n) const
702 {
725dc051
BK
703 for (; __n && __pos < this->size(); ++__pos)
704 {
97644827
BK
705 const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]);
706 if (__p)
725dc051
BK
707 return __pos;
708 }
709 return npos;
710 }
711
712 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 713 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
714 basic_string<_CharT, _Traits, _Alloc>::
715 find_last_of(const _CharT* __s, size_type __pos, size_type __n) const
716 {
717 size_type __size = this->size();
718 if (__size && __n)
719 {
720 if (--__size > __pos)
721 __size = __pos;
722 do
723 {
97644827 724 if (traits_type::find(__s, __n, _M_data()[__size]))
725dc051
BK
725 return __size;
726 }
727 while (__size-- != 0);
728 }
729 return npos;
730 }
731
732 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 733 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
734 basic_string<_CharT, _Traits, _Alloc>::
735 find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const
736 {
737 size_t __xpos = __pos;
ba317c52 738 for (; __xpos < this->size(); ++__xpos)
97644827 739 if (!traits_type::find(__s, __n, _M_data()[__xpos]))
725dc051
BK
740 return __xpos;
741 return npos;
742 }
743
744 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 745 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
746 basic_string<_CharT, _Traits, _Alloc>::
747 find_first_not_of(_CharT __c, size_type __pos) const
748 {
749 size_t __xpos = __pos;
97644827 750 for (; __xpos < this->size(); ++__xpos)
725dc051
BK
751 if (!traits_type::eq(_M_data()[__xpos], __c))
752 return __xpos;
753 return npos;
754 }
755
756 template<typename _CharT, typename _Traits, typename _Alloc>
31bfa177 757 typename basic_string<_CharT, _Traits, _Alloc>::size_type
725dc051
BK
758 basic_string<_CharT, _Traits, _Alloc>::
759 find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const
760 {
761 size_type __size = this->size();
ba317c52 762 if (__size)
725dc051
BK
763 {
764 if (--__size > __pos)
765 __size = __pos;
766 do
767 {
97644827 768 if (!traits_type::find(__s, __n, _M_data()[__size]))
725dc051
BK
769 return __size;
770 }
771 while (__size--);
772 }
773 return npos;
774 }
775
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 find_last_not_of(_CharT __c, size_type __pos) const
780 {
781 size_type __size = this->size();
782 if (__size)
783 {
784 if (--__size > __pos)
785 __size = __pos;
786 do
787 {
788 if (!traits_type::eq(_M_data()[__size], __c))
789 return __size;
790 }
791 while (__size--);
792 }
793 return npos;
794 }
795
796 template<typename _CharT, typename _Traits, typename _Alloc>
797 int
798 basic_string<_CharT, _Traits, _Alloc>::
799 compare(size_type __pos, size_type __n, const basic_string& __str) const
800 {
801 size_type __size = this->size();
802 size_type __osize = __str.size();
e2c09482
BK
803 if (__pos > __size)
804 __throw_out_of_range("basic_string::compare");
725dc051
BK
805
806 size_type __rsize= min(__size - __pos, __n);
807 size_type __len = min(__rsize, __osize);
808 int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len);
809 if (!__r)
810 __r = __rsize - __osize;
811 return __r;
812 }
813
814 template<typename _CharT, typename _Traits, typename _Alloc>
815 int
816 basic_string<_CharT, _Traits, _Alloc>::
817 compare(size_type __pos1, size_type __n1, const basic_string& __str,
818 size_type __pos2, size_type __n2) const
819 {
820 size_type __size = this->size();
821 size_type __osize = __str.size();
e2c09482
BK
822 if (__pos1 > __size || __pos2 > __osize)
823 __throw_out_of_range("basic_string::compare");
725dc051
BK
824
825 size_type __rsize = min(__size - __pos1, __n1);
826 size_type __rosize = min(__osize - __pos2, __n2);
827 size_type __len = min(__rsize, __rosize);
828 int __r = traits_type::compare(_M_data() + __pos1,
829 __str.data() + __pos2, __len);
830 if (!__r)
831 __r = __rsize - __rosize;
832 return __r;
833 }
834
835
836 template<typename _CharT, typename _Traits, typename _Alloc>
837 int
838 basic_string<_CharT, _Traits, _Alloc>::
839 compare(const _CharT* __s) const
840 {
841 size_type __size = this->size();
842 int __r = traits_type::compare(_M_data(), __s, __size);
843 if (!__r)
844 __r = __size - traits_type::length(__s);
845 return __r;
846 }
847
848
3b0fd4bc
BK
849 template<typename _CharT, typename _Traits, typename _Alloc>
850 int
9a304d17 851 basic_string <_CharT, _Traits, _Alloc>::
3b0fd4bc
BK
852 compare(size_type __pos, size_type __n1, const _CharT* __s) const
853 {
854 size_type __size = this->size();
855 if (__pos > __size)
856 __throw_out_of_range("basic_string::compare");
857
858 size_type __osize = traits_type::length(__s);
859 size_type __rsize = min(__size - __pos, __n1);
860 size_type __len = min(__rsize, __osize);
861 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
862 if (!__r)
863 __r = __rsize - __osize;
864 return __r;
865 }
866
725dc051
BK
867 template<typename _CharT, typename _Traits, typename _Alloc>
868 int
9a304d17 869 basic_string <_CharT, _Traits, _Alloc>::
725dc051
BK
870 compare(size_type __pos, size_type __n1, const _CharT* __s,
871 size_type __n2) const
872 {
873 size_type __size = this->size();
e2c09482
BK
874 if (__pos > __size)
875 __throw_out_of_range("basic_string::compare");
725dc051
BK
876
877 size_type __osize = min(traits_type::length(__s), __n2);
878 size_type __rsize = min(__size - __pos, __n1);
879 size_type __len = min(__rsize, __osize);
880 int __r = traits_type::compare(_M_data() + __pos, __s, __len);
881 if (!__r)
882 __r = __rsize - __osize;
883 return __r;
884 }
885
886 template <class _CharT, class _Traits, class _Alloc>
887 void
888 _S_string_copy(const basic_string<_CharT, _Traits, _Alloc>& __str,
889 _CharT* __buf, typename _Alloc::size_type __bufsiz)
890 {
891 typedef typename _Alloc::size_type size_type;
892 size_type __strsize = __str.size();
893 size_type __bytes = min(__strsize, __bufsiz - 1);
894 _Traits::copy(__buf, __str.data(), __bytes);
895 __buf[__bytes] = _CharT();
896 }
3b0fd4bc 897} // namespace std
725dc051 898
3b0fd4bc 899#endif