]>
Commit | Line | Data |
---|---|---|
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 | ||
43 | namespace 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 |