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