]>
Commit | Line | Data |
---|---|---|
725dc051 BK |
1 | // Components for manipulating sequences of characters -*- C++ -*- |
2 | ||
7adcbafe | 3 | // Copyright (C) 1997-2022 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 | |
748086b7 | 8 | // Free Software Foundation; either version 3, or (at your option) |
725dc051 BK |
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 | ||
748086b7 JJ |
16 | // Under Section 7 of GPL version 3, you are granted additional |
17 | // permissions described in the GCC Runtime Library Exception, version | |
18 | // 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | // You should have received a copy of the GNU General Public License and | |
21 | // a copy of the GCC Runtime Library Exception along with this program; | |
22 | // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | // <http://www.gnu.org/licenses/>. | |
725dc051 | 24 | |
f910786b | 25 | /** @file bits/basic_string.tcc |
0aa06b18 | 26 | * This is an internal header file, included by other library headers. |
f910786b | 27 | * Do not attempt to use it directly. @headername{string} |
0aa06b18 BK |
28 | */ |
29 | ||
725dc051 BK |
30 | // |
31 | // ISO C++ 14882: 21 Strings library | |
32 | // | |
33 | ||
725dc051 BK |
34 | // Written by Jason Merrill based upon the specification by Takanori Adachi |
35 | // in ANSI X3J16/94-0013R2. Rewritten by Nathan Myers to ISO-14882. | |
34a2b755 JW |
36 | // Non-reference-counted implementation written by Paolo Carlini and |
37 | // updated by Jonathan Wakely for ISO-14882-2011. | |
725dc051 | 38 | |
3d7c150e BK |
39 | #ifndef _BASIC_STRING_TCC |
40 | #define _BASIC_STRING_TCC 1 | |
725dc051 | 41 | |
3b794528 BK |
42 | #pragma GCC system_header |
43 | ||
7c3e9502 | 44 | #include <bits/cxxabi_forced.h> |
d05f74f1 | 45 | |
12ffa228 BK |
46 | namespace std _GLIBCXX_VISIBILITY(default) |
47 | { | |
48 | _GLIBCXX_BEGIN_NAMESPACE_VERSION | |
3cbc7af0 | 49 | |
34a2b755 JW |
50 | #if _GLIBCXX_USE_CXX11_ABI |
51 | ||
52 | template<typename _CharT, typename _Traits, typename _Alloc> | |
53 | const typename basic_string<_CharT, _Traits, _Alloc>::size_type | |
54 | basic_string<_CharT, _Traits, _Alloc>::npos; | |
55 | ||
56 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 57 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
58 | void |
59 | basic_string<_CharT, _Traits, _Alloc>:: | |
60 | swap(basic_string& __s) _GLIBCXX_NOEXCEPT | |
61 | { | |
47915ef8 | 62 | if (this == std::__addressof(__s)) |
34a2b755 JW |
63 | return; |
64 | ||
5caff414 | 65 | _Alloc_traits::_S_on_swap(_M_get_allocator(), __s._M_get_allocator()); |
34a2b755 JW |
66 | |
67 | if (_M_is_local()) | |
68 | if (__s._M_is_local()) | |
69 | { | |
70 | if (length() && __s.length()) | |
71 | { | |
72 | _CharT __tmp_data[_S_local_capacity + 1]; | |
73 | traits_type::copy(__tmp_data, __s._M_local_buf, | |
b96e2ff9 | 74 | __s.length() + 1); |
34a2b755 | 75 | traits_type::copy(__s._M_local_buf, _M_local_buf, |
b96e2ff9 | 76 | length() + 1); |
34a2b755 | 77 | traits_type::copy(_M_local_buf, __tmp_data, |
b96e2ff9 | 78 | __s.length() + 1); |
34a2b755 JW |
79 | } |
80 | else if (__s.length()) | |
81 | { | |
82 | traits_type::copy(_M_local_buf, __s._M_local_buf, | |
b96e2ff9 | 83 | __s.length() + 1); |
34a2b755 JW |
84 | _M_length(__s.length()); |
85 | __s._M_set_length(0); | |
86 | return; | |
87 | } | |
88 | else if (length()) | |
89 | { | |
90 | traits_type::copy(__s._M_local_buf, _M_local_buf, | |
b96e2ff9 | 91 | length() + 1); |
34a2b755 JW |
92 | __s._M_length(length()); |
93 | _M_set_length(0); | |
94 | return; | |
95 | } | |
96 | } | |
97 | else | |
98 | { | |
99 | const size_type __tmp_capacity = __s._M_allocated_capacity; | |
100 | traits_type::copy(__s._M_local_buf, _M_local_buf, | |
b96e2ff9 | 101 | length() + 1); |
34a2b755 JW |
102 | _M_data(__s._M_data()); |
103 | __s._M_data(__s._M_local_buf); | |
104 | _M_capacity(__tmp_capacity); | |
105 | } | |
106 | else | |
107 | { | |
108 | const size_type __tmp_capacity = _M_allocated_capacity; | |
109 | if (__s._M_is_local()) | |
110 | { | |
111 | traits_type::copy(_M_local_buf, __s._M_local_buf, | |
b96e2ff9 | 112 | __s.length() + 1); |
34a2b755 JW |
113 | __s._M_data(_M_data()); |
114 | _M_data(_M_local_buf); | |
115 | } | |
116 | else | |
117 | { | |
118 | pointer __tmp_ptr = _M_data(); | |
119 | _M_data(__s._M_data()); | |
120 | __s._M_data(__tmp_ptr); | |
121 | _M_capacity(__s._M_allocated_capacity); | |
122 | } | |
123 | __s._M_capacity(__tmp_capacity); | |
124 | } | |
125 | ||
126 | const size_type __tmp_length = length(); | |
127 | _M_length(__s.length()); | |
128 | __s._M_length(__tmp_length); | |
129 | } | |
130 | ||
131 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 132 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
133 | typename basic_string<_CharT, _Traits, _Alloc>::pointer |
134 | basic_string<_CharT, _Traits, _Alloc>:: | |
135 | _M_create(size_type& __capacity, size_type __old_capacity) | |
136 | { | |
137 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
138 | // 83. String::npos vs. string::max_size() | |
139 | if (__capacity > max_size()) | |
140 | std::__throw_length_error(__N("basic_string::_M_create")); | |
141 | ||
142 | // The below implements an exponential growth policy, necessary to | |
143 | // meet amortized linear time requirements of the library: see | |
144 | // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html. | |
145 | if (__capacity > __old_capacity && __capacity < 2 * __old_capacity) | |
146 | { | |
147 | __capacity = 2 * __old_capacity; | |
148 | // Never allocate a string bigger than max_size. | |
149 | if (__capacity > max_size()) | |
150 | __capacity = max_size(); | |
151 | } | |
152 | ||
153 | // NB: Need an array of char_type[__capacity], plus a terminating | |
154 | // null char_type() element. | |
155 | return _Alloc_traits::allocate(_M_get_allocator(), __capacity + 1); | |
156 | } | |
157 | ||
158 | // NB: This is the special case for Input Iterators, used in | |
159 | // istreambuf_iterators, etc. | |
160 | // Input Iterators have a cost structure very different from | |
161 | // pointers, calling for a different coding style. | |
162 | template<typename _CharT, typename _Traits, typename _Alloc> | |
163 | template<typename _InIterator> | |
b96e2ff9 | 164 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
165 | void |
166 | basic_string<_CharT, _Traits, _Alloc>:: | |
167 | _M_construct(_InIterator __beg, _InIterator __end, | |
168 | std::input_iterator_tag) | |
169 | { | |
170 | size_type __len = 0; | |
171 | size_type __capacity = size_type(_S_local_capacity); | |
172 | ||
6afa1083 JW |
173 | pointer __p = _M_use_local_data(); |
174 | ||
34a2b755 JW |
175 | while (__beg != __end && __len < __capacity) |
176 | { | |
6afa1083 | 177 | __p[__len++] = *__beg; |
34a2b755 JW |
178 | ++__beg; |
179 | } | |
180 | ||
5a9572e4 JW |
181 | struct _Guard |
182 | { | |
183 | _GLIBCXX20_CONSTEXPR | |
184 | explicit _Guard(basic_string* __s) : _M_guarded(__s) { } | |
185 | ||
186 | _GLIBCXX20_CONSTEXPR | |
187 | ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); } | |
188 | ||
189 | basic_string* _M_guarded; | |
190 | } __guard(this); | |
191 | ||
192 | while (__beg != __end) | |
34a2b755 | 193 | { |
5a9572e4 | 194 | if (__len == __capacity) |
34a2b755 | 195 | { |
5a9572e4 JW |
196 | // Allocate more space. |
197 | __capacity = __len + 1; | |
198 | pointer __another = _M_create(__capacity, __len); | |
199 | this->_S_copy(__another, _M_data(), __len); | |
200 | _M_dispose(); | |
201 | _M_data(__another); | |
202 | _M_capacity(__capacity); | |
34a2b755 | 203 | } |
1f8d01eb | 204 | traits_type::assign(_M_data()[__len++], *__beg); |
5a9572e4 | 205 | ++__beg; |
34a2b755 | 206 | } |
5a9572e4 JW |
207 | |
208 | __guard._M_guarded = 0; | |
34a2b755 JW |
209 | |
210 | _M_set_length(__len); | |
211 | } | |
212 | ||
213 | template<typename _CharT, typename _Traits, typename _Alloc> | |
214 | template<typename _InIterator> | |
b96e2ff9 | 215 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
216 | void |
217 | basic_string<_CharT, _Traits, _Alloc>:: | |
218 | _M_construct(_InIterator __beg, _InIterator __end, | |
219 | std::forward_iterator_tag) | |
220 | { | |
34a2b755 JW |
221 | size_type __dnew = static_cast<size_type>(std::distance(__beg, __end)); |
222 | ||
223 | if (__dnew > size_type(_S_local_capacity)) | |
224 | { | |
225 | _M_data(_M_create(__dnew, size_type(0))); | |
226 | _M_capacity(__dnew); | |
227 | } | |
6afa1083 JW |
228 | else |
229 | _M_use_local_data(); | |
34a2b755 JW |
230 | |
231 | // Check for out_of_range and length_error exceptions. | |
5a9572e4 JW |
232 | struct _Guard |
233 | { | |
234 | _GLIBCXX20_CONSTEXPR | |
235 | explicit _Guard(basic_string* __s) : _M_guarded(__s) { } | |
236 | ||
237 | _GLIBCXX20_CONSTEXPR | |
238 | ~_Guard() { if (_M_guarded) _M_guarded->_M_dispose(); } | |
239 | ||
240 | basic_string* _M_guarded; | |
241 | } __guard(this); | |
242 | ||
243 | this->_S_copy_chars(_M_data(), __beg, __end); | |
244 | ||
245 | __guard._M_guarded = 0; | |
34a2b755 JW |
246 | |
247 | _M_set_length(__dnew); | |
248 | } | |
249 | ||
250 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 251 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
252 | void |
253 | basic_string<_CharT, _Traits, _Alloc>:: | |
254 | _M_construct(size_type __n, _CharT __c) | |
255 | { | |
256 | if (__n > size_type(_S_local_capacity)) | |
257 | { | |
258 | _M_data(_M_create(__n, size_type(0))); | |
259 | _M_capacity(__n); | |
260 | } | |
6afa1083 JW |
261 | else |
262 | _M_use_local_data(); | |
34a2b755 JW |
263 | |
264 | if (__n) | |
265 | this->_S_assign(_M_data(), __n, __c); | |
266 | ||
267 | _M_set_length(__n); | |
268 | } | |
269 | ||
270 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 271 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
272 | void |
273 | basic_string<_CharT, _Traits, _Alloc>:: | |
274 | _M_assign(const basic_string& __str) | |
275 | { | |
47915ef8 | 276 | if (this != std::__addressof(__str)) |
34a2b755 JW |
277 | { |
278 | const size_type __rsize = __str.length(); | |
279 | const size_type __capacity = capacity(); | |
280 | ||
281 | if (__rsize > __capacity) | |
282 | { | |
283 | size_type __new_capacity = __rsize; | |
284 | pointer __tmp = _M_create(__new_capacity, __capacity); | |
285 | _M_dispose(); | |
286 | _M_data(__tmp); | |
287 | _M_capacity(__new_capacity); | |
288 | } | |
289 | ||
290 | if (__rsize) | |
291 | this->_S_copy(_M_data(), __str._M_data(), __rsize); | |
292 | ||
293 | _M_set_length(__rsize); | |
294 | } | |
295 | } | |
296 | ||
297 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 298 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
299 | void |
300 | basic_string<_CharT, _Traits, _Alloc>:: | |
301 | reserve(size_type __res) | |
302 | { | |
34a2b755 | 303 | const size_type __capacity = capacity(); |
140cf935 AL |
304 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
305 | // 2968. Inconsistencies between basic_string reserve and | |
306 | // vector/unordered_map/unordered_set reserve functions | |
307 | // P0966 reserve should not shrink | |
308 | if (__res <= __capacity) | |
309 | return; | |
310 | ||
311 | pointer __tmp = _M_create(__res, __capacity); | |
312 | this->_S_copy(__tmp, _M_data(), length() + 1); | |
313 | _M_dispose(); | |
314 | _M_data(__tmp); | |
315 | _M_capacity(__res); | |
34a2b755 JW |
316 | } |
317 | ||
318 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 319 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
320 | void |
321 | basic_string<_CharT, _Traits, _Alloc>:: | |
322 | _M_mutate(size_type __pos, size_type __len1, const _CharT* __s, | |
323 | size_type __len2) | |
324 | { | |
325 | const size_type __how_much = length() - __pos - __len1; | |
326 | ||
327 | size_type __new_capacity = length() + __len2 - __len1; | |
328 | pointer __r = _M_create(__new_capacity, capacity()); | |
329 | ||
330 | if (__pos) | |
2d60da10 | 331 | this->_S_copy(__r, _M_data(), __pos); |
34a2b755 | 332 | if (__s && __len2) |
2d60da10 | 333 | this->_S_copy(__r + __pos, __s, __len2); |
34a2b755 | 334 | if (__how_much) |
2d60da10 JW |
335 | this->_S_copy(__r + __pos + __len2, |
336 | _M_data() + __pos + __len1, __how_much); | |
34a2b755 JW |
337 | |
338 | _M_dispose(); | |
339 | _M_data(__r); | |
340 | _M_capacity(__new_capacity); | |
341 | } | |
342 | ||
343 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 344 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
345 | void |
346 | basic_string<_CharT, _Traits, _Alloc>:: | |
347 | _M_erase(size_type __pos, size_type __n) | |
348 | { | |
349 | const size_type __how_much = length() - __pos - __n; | |
350 | ||
351 | if (__how_much && __n) | |
2d60da10 | 352 | this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much); |
34a2b755 JW |
353 | |
354 | _M_set_length(length() - __n); | |
355 | } | |
356 | ||
140cf935 | 357 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 358 | _GLIBCXX20_CONSTEXPR |
140cf935 AL |
359 | void |
360 | basic_string<_CharT, _Traits, _Alloc>:: | |
361 | reserve() | |
362 | { | |
363 | if (_M_is_local()) | |
364 | return; | |
365 | ||
366 | const size_type __length = length(); | |
367 | const size_type __capacity = _M_allocated_capacity; | |
368 | ||
369 | if (__length <= size_type(_S_local_capacity)) | |
370 | { | |
6afa1083 | 371 | this->_S_copy(_M_use_local_data(), _M_data(), __length + 1); |
140cf935 AL |
372 | _M_destroy(__capacity); |
373 | _M_data(_M_local_data()); | |
374 | } | |
375 | #if __cpp_exceptions | |
376 | else if (__length < __capacity) | |
377 | try | |
378 | { | |
379 | pointer __tmp | |
380 | = _Alloc_traits::allocate(_M_get_allocator(), __length + 1); | |
381 | this->_S_copy(__tmp, _M_data(), __length + 1); | |
382 | _M_dispose(); | |
383 | _M_data(__tmp); | |
384 | _M_capacity(__length); | |
385 | } | |
386 | catch (const __cxxabiv1::__forced_unwind&) | |
387 | { throw; } | |
388 | catch (...) | |
389 | { /* swallow the exception */ } | |
390 | #endif | |
391 | } | |
392 | ||
34a2b755 | 393 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 394 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
395 | void |
396 | basic_string<_CharT, _Traits, _Alloc>:: | |
397 | resize(size_type __n, _CharT __c) | |
398 | { | |
399 | const size_type __size = this->size(); | |
400 | if (__size < __n) | |
401 | this->append(__n - __size, __c); | |
402 | else if (__n < __size) | |
a922c5ff | 403 | this->_M_set_length(__n); |
34a2b755 JW |
404 | } |
405 | ||
406 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 407 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
408 | basic_string<_CharT, _Traits, _Alloc>& |
409 | basic_string<_CharT, _Traits, _Alloc>:: | |
410 | _M_append(const _CharT* __s, size_type __n) | |
411 | { | |
412 | const size_type __len = __n + this->size(); | |
413 | ||
414 | if (__len <= this->capacity()) | |
415 | { | |
416 | if (__n) | |
417 | this->_S_copy(this->_M_data() + this->size(), __s, __n); | |
418 | } | |
419 | else | |
420 | this->_M_mutate(this->size(), size_type(0), __s, __n); | |
421 | ||
422 | this->_M_set_length(__len); | |
423 | return *this; | |
424 | } | |
425 | ||
426 | template<typename _CharT, typename _Traits, typename _Alloc> | |
427 | template<typename _InputIterator> | |
b96e2ff9 | 428 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
429 | basic_string<_CharT, _Traits, _Alloc>& |
430 | basic_string<_CharT, _Traits, _Alloc>:: | |
431 | _M_replace_dispatch(const_iterator __i1, const_iterator __i2, | |
432 | _InputIterator __k1, _InputIterator __k2, | |
433 | std::__false_type) | |
434 | { | |
046af809 NDR |
435 | // _GLIBCXX_RESOLVE_LIB_DEFECTS |
436 | // 2788. unintentionally require a default constructible allocator | |
437 | const basic_string __s(__k1, __k2, this->get_allocator()); | |
34a2b755 JW |
438 | const size_type __n1 = __i2 - __i1; |
439 | return _M_replace(__i1 - begin(), __n1, __s._M_data(), | |
440 | __s.size()); | |
441 | } | |
442 | ||
443 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 444 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
445 | basic_string<_CharT, _Traits, _Alloc>& |
446 | basic_string<_CharT, _Traits, _Alloc>:: | |
447 | _M_replace_aux(size_type __pos1, size_type __n1, size_type __n2, | |
448 | _CharT __c) | |
449 | { | |
450 | _M_check_length(__n1, __n2, "basic_string::_M_replace_aux"); | |
451 | ||
452 | const size_type __old_size = this->size(); | |
453 | const size_type __new_size = __old_size + __n2 - __n1; | |
454 | ||
455 | if (__new_size <= this->capacity()) | |
456 | { | |
2d60da10 | 457 | pointer __p = this->_M_data() + __pos1; |
34a2b755 JW |
458 | |
459 | const size_type __how_much = __old_size - __pos1 - __n1; | |
460 | if (__how_much && __n1 != __n2) | |
461 | this->_S_move(__p + __n2, __p + __n1, __how_much); | |
462 | } | |
463 | else | |
464 | this->_M_mutate(__pos1, __n1, 0, __n2); | |
465 | ||
466 | if (__n2) | |
2d60da10 | 467 | this->_S_assign(this->_M_data() + __pos1, __n2, __c); |
34a2b755 JW |
468 | |
469 | this->_M_set_length(__new_size); | |
470 | return *this; | |
471 | } | |
472 | ||
473 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 474 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
475 | basic_string<_CharT, _Traits, _Alloc>& |
476 | basic_string<_CharT, _Traits, _Alloc>:: | |
477 | _M_replace(size_type __pos, size_type __len1, const _CharT* __s, | |
478 | const size_type __len2) | |
479 | { | |
480 | _M_check_length(__len1, __len2, "basic_string::_M_replace"); | |
481 | ||
482 | const size_type __old_size = this->size(); | |
483 | const size_type __new_size = __old_size + __len2 - __len1; | |
484 | ||
485 | if (__new_size <= this->capacity()) | |
486 | { | |
5caff414 | 487 | pointer __p = this->_M_data() + __pos; |
34a2b755 JW |
488 | |
489 | const size_type __how_much = __old_size - __pos - __len1; | |
b96e2ff9 | 490 | #if __cpp_lib_is_constant_evaluated |
74d14778 | 491 | if (std::is_constant_evaluated()) |
b96e2ff9 | 492 | { |
2d76292b JW |
493 | auto __newp = _Alloc_traits::allocate(_M_get_allocator(), |
494 | __new_size); | |
b96e2ff9 ML |
495 | _S_copy(__newp, this->_M_data(), __pos); |
496 | _S_copy(__newp + __pos, __s, __len2); | |
497 | _S_copy(__newp + __pos + __len2, __p + __len1, __how_much); | |
498 | _S_copy(this->_M_data(), __newp, __new_size); | |
499 | this->_M_get_allocator().deallocate(__newp, __new_size); | |
500 | } | |
501 | else | |
502 | #endif | |
34a2b755 JW |
503 | if (_M_disjunct(__s)) |
504 | { | |
505 | if (__how_much && __len1 != __len2) | |
506 | this->_S_move(__p + __len2, __p + __len1, __how_much); | |
507 | if (__len2) | |
508 | this->_S_copy(__p, __s, __len2); | |
509 | } | |
510 | else | |
511 | { | |
512 | // Work in-place. | |
513 | if (__len2 && __len2 <= __len1) | |
514 | this->_S_move(__p, __s, __len2); | |
515 | if (__how_much && __len1 != __len2) | |
516 | this->_S_move(__p + __len2, __p + __len1, __how_much); | |
517 | if (__len2 > __len1) | |
518 | { | |
519 | if (__s + __len2 <= __p + __len1) | |
520 | this->_S_move(__p, __s, __len2); | |
521 | else if (__s >= __p + __len1) | |
e14ea108 JJ |
522 | { |
523 | // Hint to middle end that __p and __s overlap | |
524 | // (PR 98465). | |
525 | const size_type __poff = (__s - __p) + (__len2 - __len1); | |
526 | this->_S_copy(__p, __p + __poff, __len2); | |
527 | } | |
34a2b755 JW |
528 | else |
529 | { | |
530 | const size_type __nleft = (__p + __len1) - __s; | |
531 | this->_S_move(__p, __s, __nleft); | |
532 | this->_S_copy(__p + __nleft, __p + __len2, | |
533 | __len2 - __nleft); | |
534 | } | |
535 | } | |
536 | } | |
537 | } | |
538 | else | |
539 | this->_M_mutate(__pos, __len1, __s, __len2); | |
540 | ||
541 | this->_M_set_length(__new_size); | |
542 | return *this; | |
543 | } | |
544 | ||
545 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 546 | _GLIBCXX20_CONSTEXPR |
34a2b755 JW |
547 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
548 | basic_string<_CharT, _Traits, _Alloc>:: | |
549 | copy(_CharT* __s, size_type __n, size_type __pos) const | |
550 | { | |
551 | _M_check(__pos, "basic_string::copy"); | |
552 | __n = _M_limit(__pos, __n); | |
553 | __glibcxx_requires_string_len(__s, __n); | |
554 | if (__n) | |
555 | _S_copy(__s, _M_data() + __pos, __n); | |
556 | // 21.3.5.7 par 3: do not append null. (good.) | |
557 | return __n; | |
558 | } | |
559 | ||
929abc7f JW |
560 | #if __cplusplus > 202002L |
561 | template<typename _CharT, typename _Traits, typename _Alloc> | |
562 | template<typename _Operation> | |
563 | constexpr void | |
564 | basic_string<_CharT, _Traits, _Alloc>:: | |
565 | resize_and_overwrite(size_type __n, _Operation __op) | |
566 | { | |
567 | const size_type __capacity = capacity(); | |
568 | _CharT* __p; | |
569 | if (__n > __capacity) | |
570 | { | |
571 | __p = _M_create(__n, __capacity); | |
572 | this->_S_copy(__p, _M_data(), length()); // exclude trailing null | |
2d76292b | 573 | #if __cpp_lib_is_constant_evaluated |
74d14778 | 574 | if (std::is_constant_evaluated()) |
2d76292b JW |
575 | traits_type::assign(__p + length(), __n - length(), _CharT()); |
576 | #endif | |
929abc7f JW |
577 | _M_dispose(); |
578 | _M_data(__p); | |
579 | _M_capacity(__n); | |
580 | } | |
581 | else | |
582 | __p = _M_data(); | |
583 | struct _Terminator { | |
b96e2ff9 | 584 | constexpr ~_Terminator() { _M_this->_M_set_length(_M_r); } |
929abc7f JW |
585 | basic_string* _M_this; |
586 | size_type _M_r; | |
587 | }; | |
588 | _Terminator __term{this}; | |
589 | const size_type __n2 [[maybe_unused]] = __n; | |
590 | __term._M_r = std::move(__op)(__p, __n); | |
591 | _GLIBCXX_DEBUG_ASSERT(__term._M_r >= 0 && __term._M_r <= __n2); | |
592 | } | |
593 | #endif // C++23 | |
594 | ||
7b527614 | 595 | #endif // _GLIBCXX_USE_CXX11_ABI |
6bfad5e1 | 596 | |
b96e2ff9 ML |
597 | #if __cpp_lib_constexpr_string >= 201907L |
598 | # define _GLIBCXX_STRING_CONSTEXPR constexpr | |
599 | #else | |
600 | # define _GLIBCXX_STRING_CONSTEXPR | |
601 | #endif | |
602 | ||
725dc051 | 603 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 604 | _GLIBCXX20_CONSTEXPR |
9a304d17 | 605 | basic_string<_CharT, _Traits, _Alloc> |
725dc051 | 606 | operator+(const _CharT* __lhs, |
9a304d17 | 607 | const basic_string<_CharT, _Traits, _Alloc>& __rhs) |
725dc051 | 608 | { |
285b36d6 | 609 | __glibcxx_requires_string(__lhs); |
9a304d17 | 610 | typedef basic_string<_CharT, _Traits, _Alloc> __string_type; |
725dc051 | 611 | typedef typename __string_type::size_type __size_type; |
f4e678ef NDR |
612 | typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template |
613 | rebind<_CharT>::other _Char_alloc_type; | |
614 | typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; | |
7778fa6e | 615 | const __size_type __len = _Traits::length(__lhs); |
f4e678ef NDR |
616 | __string_type __str(_Alloc_traits::_S_select_on_copy( |
617 | __rhs.get_allocator())); | |
725dc051 | 618 | __str.reserve(__len + __rhs.size()); |
bb9909b0 | 619 | __str.append(__lhs, __len); |
725dc051 BK |
620 | __str.append(__rhs); |
621 | return __str; | |
622 | } | |
623 | ||
624 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 625 | _GLIBCXX20_CONSTEXPR |
9a304d17 PC |
626 | basic_string<_CharT, _Traits, _Alloc> |
627 | operator+(_CharT __lhs, const basic_string<_CharT, _Traits, _Alloc>& __rhs) | |
725dc051 | 628 | { |
9a304d17 | 629 | typedef basic_string<_CharT, _Traits, _Alloc> __string_type; |
725dc051 | 630 | typedef typename __string_type::size_type __size_type; |
f4e678ef NDR |
631 | typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template |
632 | rebind<_CharT>::other _Char_alloc_type; | |
633 | typedef __gnu_cxx::__alloc_traits<_Char_alloc_type> _Alloc_traits; | |
634 | __string_type __str(_Alloc_traits::_S_select_on_copy( | |
635 | __rhs.get_allocator())); | |
7778fa6e | 636 | const __size_type __len = __rhs.size(); |
725dc051 | 637 | __str.reserve(__len + 1); |
15f13f01 | 638 | __str.append(__size_type(1), __lhs); |
725dc051 BK |
639 | __str.append(__rhs); |
640 | return __str; | |
641 | } | |
642 | ||
725dc051 | 643 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 644 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 645 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 | 646 | basic_string<_CharT, _Traits, _Alloc>:: |
725dc051 | 647 | find(const _CharT* __s, size_type __pos, size_type __n) const |
39a03251 | 648 | _GLIBCXX_NOEXCEPT |
725dc051 | 649 | { |
285b36d6 | 650 | __glibcxx_requires_string_len(__s, __n); |
7778fa6e | 651 | const size_type __size = this->size(); |
1a4ba99f PC |
652 | |
653 | if (__n == 0) | |
654 | return __pos <= __size ? __pos : npos; | |
cb627cdf JW |
655 | if (__pos >= __size) |
656 | return npos; | |
1a4ba99f | 657 | |
cb627cdf JW |
658 | const _CharT __elem0 = __s[0]; |
659 | const _CharT* const __data = data(); | |
660 | const _CharT* __first = __data + __pos; | |
661 | const _CharT* const __last = __data + __size; | |
662 | size_type __len = __size - __pos; | |
663 | ||
664 | while (__len >= __n) | |
5527be59 | 665 | { |
cb627cdf JW |
666 | // Find the first occurrence of __elem0: |
667 | __first = traits_type::find(__first, __len - __n + 1, __elem0); | |
668 | if (!__first) | |
669 | return npos; | |
670 | // Compare the full strings from the first occurrence of __elem0. | |
671 | // We already know that __first[0] == __s[0] but compare them again | |
672 | // anyway because __s is probably aligned, which helps memcmp. | |
673 | if (traits_type::compare(__first, __s, __n) == 0) | |
674 | return __first - __data; | |
675 | __len = __last - ++__first; | |
5527be59 | 676 | } |
1a4ba99f | 677 | return npos; |
725dc051 BK |
678 | } |
679 | ||
680 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 681 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 682 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 | 683 | basic_string<_CharT, _Traits, _Alloc>:: |
cea8c6de | 684 | find(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT |
725dc051 | 685 | { |
725dc051 | 686 | size_type __ret = npos; |
4a787fa8 | 687 | const size_type __size = this->size(); |
725dc051 BK |
688 | if (__pos < __size) |
689 | { | |
690 | const _CharT* __data = _M_data(); | |
7778fa6e | 691 | const size_type __n = __size - __pos; |
97644827 BK |
692 | const _CharT* __p = traits_type::find(__data + __pos, __n, __c); |
693 | if (__p) | |
725dc051 BK |
694 | __ret = __p - __data; |
695 | } | |
696 | return __ret; | |
697 | } | |
698 | ||
725dc051 | 699 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 700 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 701 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 BK |
702 | basic_string<_CharT, _Traits, _Alloc>:: |
703 | rfind(const _CharT* __s, size_type __pos, size_type __n) const | |
39a03251 | 704 | _GLIBCXX_NOEXCEPT |
725dc051 | 705 | { |
285b36d6 | 706 | __glibcxx_requires_string_len(__s, __n); |
7778fa6e | 707 | const size_type __size = this->size(); |
725dc051 BK |
708 | if (__n <= __size) |
709 | { | |
dd6eaaed | 710 | __pos = std::min(size_type(__size - __n), __pos); |
725dc051 | 711 | const _CharT* __data = _M_data(); |
ed6814f7 | 712 | do |
725dc051 BK |
713 | { |
714 | if (traits_type::compare(__data + __pos, __s, __n) == 0) | |
715 | return __pos; | |
ed6814f7 | 716 | } |
725dc051 BK |
717 | while (__pos-- > 0); |
718 | } | |
719 | return npos; | |
720 | } | |
ed6814f7 | 721 | |
725dc051 | 722 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 723 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 724 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 | 725 | basic_string<_CharT, _Traits, _Alloc>:: |
cea8c6de | 726 | rfind(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT |
725dc051 | 727 | { |
04cc8aef | 728 | size_type __size = this->size(); |
725dc051 BK |
729 | if (__size) |
730 | { | |
04cc8aef PC |
731 | if (--__size > __pos) |
732 | __size = __pos; | |
733 | for (++__size; __size-- > 0; ) | |
734 | if (traits_type::eq(_M_data()[__size], __c)) | |
735 | return __size; | |
725dc051 BK |
736 | } |
737 | return npos; | |
738 | } | |
ed6814f7 | 739 | |
725dc051 | 740 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 741 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 742 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 BK |
743 | basic_string<_CharT, _Traits, _Alloc>:: |
744 | find_first_of(const _CharT* __s, size_type __pos, size_type __n) const | |
39a03251 | 745 | _GLIBCXX_NOEXCEPT |
725dc051 | 746 | { |
285b36d6 | 747 | __glibcxx_requires_string_len(__s, __n); |
725dc051 BK |
748 | for (; __n && __pos < this->size(); ++__pos) |
749 | { | |
97644827 BK |
750 | const _CharT* __p = traits_type::find(__s, __n, _M_data()[__pos]); |
751 | if (__p) | |
725dc051 BK |
752 | return __pos; |
753 | } | |
754 | return npos; | |
755 | } | |
ed6814f7 | 756 | |
725dc051 | 757 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 758 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 759 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 BK |
760 | basic_string<_CharT, _Traits, _Alloc>:: |
761 | find_last_of(const _CharT* __s, size_type __pos, size_type __n) const | |
39a03251 | 762 | _GLIBCXX_NOEXCEPT |
725dc051 | 763 | { |
285b36d6 | 764 | __glibcxx_requires_string_len(__s, __n); |
725dc051 BK |
765 | size_type __size = this->size(); |
766 | if (__size && __n) | |
ed6814f7 BI |
767 | { |
768 | if (--__size > __pos) | |
725dc051 BK |
769 | __size = __pos; |
770 | do | |
771 | { | |
97644827 | 772 | if (traits_type::find(__s, __n, _M_data()[__size])) |
725dc051 | 773 | return __size; |
ed6814f7 | 774 | } |
725dc051 BK |
775 | while (__size-- != 0); |
776 | } | |
777 | return npos; | |
778 | } | |
ed6814f7 | 779 | |
725dc051 | 780 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 781 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 782 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 BK |
783 | basic_string<_CharT, _Traits, _Alloc>:: |
784 | find_first_not_of(const _CharT* __s, size_type __pos, size_type __n) const | |
39a03251 | 785 | _GLIBCXX_NOEXCEPT |
725dc051 | 786 | { |
285b36d6 | 787 | __glibcxx_requires_string_len(__s, __n); |
fefe561e PC |
788 | for (; __pos < this->size(); ++__pos) |
789 | if (!traits_type::find(__s, __n, _M_data()[__pos])) | |
790 | return __pos; | |
725dc051 BK |
791 | return npos; |
792 | } | |
793 | ||
794 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 795 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 796 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 | 797 | basic_string<_CharT, _Traits, _Alloc>:: |
cea8c6de | 798 | find_first_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT |
725dc051 | 799 | { |
fefe561e PC |
800 | for (; __pos < this->size(); ++__pos) |
801 | if (!traits_type::eq(_M_data()[__pos], __c)) | |
802 | return __pos; | |
725dc051 BK |
803 | return npos; |
804 | } | |
805 | ||
806 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 807 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 808 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 BK |
809 | basic_string<_CharT, _Traits, _Alloc>:: |
810 | find_last_not_of(const _CharT* __s, size_type __pos, size_type __n) const | |
39a03251 | 811 | _GLIBCXX_NOEXCEPT |
725dc051 | 812 | { |
285b36d6 | 813 | __glibcxx_requires_string_len(__s, __n); |
04cc8aef | 814 | size_type __size = this->size(); |
ba317c52 | 815 | if (__size) |
04cc8aef PC |
816 | { |
817 | if (--__size > __pos) | |
818 | __size = __pos; | |
ed6814f7 | 819 | do |
725dc051 | 820 | { |
04cc8aef PC |
821 | if (!traits_type::find(__s, __n, _M_data()[__size])) |
822 | return __size; | |
ed6814f7 | 823 | } |
04cc8aef | 824 | while (__size--); |
725dc051 BK |
825 | } |
826 | return npos; | |
827 | } | |
828 | ||
829 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 830 | _GLIBCXX_STRING_CONSTEXPR |
31bfa177 | 831 | typename basic_string<_CharT, _Traits, _Alloc>::size_type |
725dc051 | 832 | basic_string<_CharT, _Traits, _Alloc>:: |
cea8c6de | 833 | find_last_not_of(_CharT __c, size_type __pos) const _GLIBCXX_NOEXCEPT |
725dc051 | 834 | { |
04cc8aef | 835 | size_type __size = this->size(); |
725dc051 | 836 | if (__size) |
fefe561e | 837 | { |
04cc8aef | 838 | if (--__size > __pos) |
ed6814f7 | 839 | __size = __pos; |
725dc051 BK |
840 | do |
841 | { | |
04cc8aef PC |
842 | if (!traits_type::eq(_M_data()[__size], __c)) |
843 | return __size; | |
ed6814f7 | 844 | } |
04cc8aef | 845 | while (__size--); |
725dc051 BK |
846 | } |
847 | return npos; | |
848 | } | |
ed6814f7 | 849 | |
725dc051 | 850 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 851 | _GLIBCXX_STRING_CONSTEXPR |
725dc051 BK |
852 | int |
853 | basic_string<_CharT, _Traits, _Alloc>:: | |
854 | compare(size_type __pos, size_type __n, const basic_string& __str) const | |
855 | { | |
04cc8aef | 856 | _M_check(__pos, "basic_string::compare"); |
e03a6fb7 | 857 | __n = _M_limit(__pos, __n); |
7778fa6e | 858 | const size_type __osize = __str.size(); |
e03a6fb7 | 859 | const size_type __len = std::min(__n, __osize); |
725dc051 BK |
860 | int __r = traits_type::compare(_M_data() + __pos, __str.data(), __len); |
861 | if (!__r) | |
9521dd6b | 862 | __r = _S_compare(__n, __osize); |
725dc051 BK |
863 | return __r; |
864 | } | |
865 | ||
866 | template<typename _CharT, typename _Traits, typename _Alloc> | |
b96e2ff9 | 867 | _GLIBCXX_STRING_CONSTEXPR |
725dc051 BK |
868 | int |
869 | basic_string<_CharT, _Traits, _Alloc>:: | |
870 | compare(size_type __pos1, size_type __n1, const basic_string& __str, | |
871 | size_type __pos2, size_type __n2) const | |
872 | { | |
04cc8aef PC |
873 | _M_check(__pos1, "basic_string::compare"); |
874 | __str._M_check(__pos2, "basic_string::compare"); | |
e03a6fb7 PC |
875 | __n1 = _M_limit(__pos1, __n1); |
876 | __n2 = __str._M_limit(__pos2, __n2); | |
877 | const size_type __len = std::min(__n1, __n2); | |
ed6814f7 | 878 | int __r = traits_type::compare(_M_data() + __pos1, |
725dc051 BK |
879 | __str.data() + __pos2, __len); |
880 | if (!__r) | |
9521dd6b | 881 | __r = _S_compare(__n1, __n2); |
725dc051 BK |
882 | return __r; |
883 | } | |
884 | ||
725dc051 | 885 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 886 | _GLIBCXX_STRING_CONSTEXPR |
725dc051 BK |
887 | int |
888 | basic_string<_CharT, _Traits, _Alloc>:: | |
39a03251 | 889 | compare(const _CharT* __s) const _GLIBCXX_NOEXCEPT |
725dc051 | 890 | { |
285b36d6 | 891 | __glibcxx_requires_string(__s); |
7778fa6e PC |
892 | const size_type __size = this->size(); |
893 | const size_type __osize = traits_type::length(__s); | |
894 | const size_type __len = std::min(__size, __osize); | |
c86c54e6 | 895 | int __r = traits_type::compare(_M_data(), __s, __len); |
725dc051 | 896 | if (!__r) |
9521dd6b | 897 | __r = _S_compare(__size, __osize); |
725dc051 BK |
898 | return __r; |
899 | } | |
900 | ||
3b0fd4bc | 901 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 902 | _GLIBCXX_STRING_CONSTEXPR |
3b0fd4bc | 903 | int |
9a304d17 | 904 | basic_string <_CharT, _Traits, _Alloc>:: |
3b0fd4bc BK |
905 | compare(size_type __pos, size_type __n1, const _CharT* __s) const |
906 | { | |
285b36d6 | 907 | __glibcxx_requires_string(__s); |
04cc8aef | 908 | _M_check(__pos, "basic_string::compare"); |
e03a6fb7 | 909 | __n1 = _M_limit(__pos, __n1); |
7778fa6e | 910 | const size_type __osize = traits_type::length(__s); |
e03a6fb7 | 911 | const size_type __len = std::min(__n1, __osize); |
3b0fd4bc BK |
912 | int __r = traits_type::compare(_M_data() + __pos, __s, __len); |
913 | if (!__r) | |
9521dd6b | 914 | __r = _S_compare(__n1, __osize); |
3b0fd4bc BK |
915 | return __r; |
916 | } | |
917 | ||
725dc051 | 918 | template<typename _CharT, typename _Traits, typename _Alloc> |
b96e2ff9 | 919 | _GLIBCXX_STRING_CONSTEXPR |
725dc051 | 920 | int |
9a304d17 | 921 | basic_string <_CharT, _Traits, _Alloc>:: |
ed6814f7 | 922 | compare(size_type __pos, size_type __n1, const _CharT* __s, |
725dc051 BK |
923 | size_type __n2) const |
924 | { | |
285b36d6 | 925 | __glibcxx_requires_string_len(__s, __n2); |
04cc8aef | 926 | _M_check(__pos, "basic_string::compare"); |
e03a6fb7 PC |
927 | __n1 = _M_limit(__pos, __n1); |
928 | const size_type __len = std::min(__n1, __n2); | |
725dc051 BK |
929 | int __r = traits_type::compare(_M_data() + __pos, __s, __len); |
930 | if (!__r) | |
9521dd6b | 931 | __r = _S_compare(__n1, __n2); |
725dc051 BK |
932 | return __r; |
933 | } | |
934 | ||
b96e2ff9 ML |
935 | #undef _GLIBCXX_STRING_CONSTEXPR |
936 | ||
11202768 PC |
937 | // 21.3.7.9 basic_string::getline and operators |
938 | template<typename _CharT, typename _Traits, typename _Alloc> | |
939 | basic_istream<_CharT, _Traits>& | |
940 | operator>>(basic_istream<_CharT, _Traits>& __in, | |
941 | basic_string<_CharT, _Traits, _Alloc>& __str) | |
942 | { | |
943 | typedef basic_istream<_CharT, _Traits> __istream_type; | |
944 | typedef basic_string<_CharT, _Traits, _Alloc> __string_type; | |
945 | typedef typename __istream_type::ios_base __ios_base; | |
946 | typedef typename __istream_type::int_type __int_type; | |
947 | typedef typename __string_type::size_type __size_type; | |
948 | typedef ctype<_CharT> __ctype_type; | |
949 | typedef typename __ctype_type::ctype_base __ctype_base; | |
950 | ||
951 | __size_type __extracted = 0; | |
952 | typename __ios_base::iostate __err = __ios_base::goodbit; | |
953 | typename __istream_type::sentry __cerb(__in, false); | |
880b527f | 954 | if (__cerb) |
11202768 | 955 | { |
bc2631e0 | 956 | __try |
11202768 PC |
957 | { |
958 | // Avoid reallocation for common case. | |
959 | __str.erase(); | |
960 | _CharT __buf[128]; | |
961 | __size_type __len = 0; | |
962 | const streamsize __w = __in.width(); | |
963 | const __size_type __n = __w > 0 ? static_cast<__size_type>(__w) | |
964 | : __str.max_size(); | |
965 | const __ctype_type& __ct = use_facet<__ctype_type>(__in.getloc()); | |
966 | const __int_type __eof = _Traits::eof(); | |
967 | __int_type __c = __in.rdbuf()->sgetc(); | |
968 | ||
969 | while (__extracted < __n | |
970 | && !_Traits::eq_int_type(__c, __eof) | |
971 | && !__ct.is(__ctype_base::space, | |
972 | _Traits::to_char_type(__c))) | |
973 | { | |
974 | if (__len == sizeof(__buf) / sizeof(_CharT)) | |
975 | { | |
976 | __str.append(__buf, sizeof(__buf) / sizeof(_CharT)); | |
977 | __len = 0; | |
978 | } | |
979 | __buf[__len++] = _Traits::to_char_type(__c); | |
980 | ++__extracted; | |
981 | __c = __in.rdbuf()->snextc(); | |
982 | } | |
983 | __str.append(__buf, __len); | |
984 | ||
4e39f563 | 985 | if (__extracted < __n && _Traits::eq_int_type(__c, __eof)) |
11202768 PC |
986 | __err |= __ios_base::eofbit; |
987 | __in.width(0); | |
988 | } | |
bc2631e0 | 989 | __catch(__cxxabiv1::__forced_unwind&) |
d05f74f1 JM |
990 | { |
991 | __in._M_setstate(__ios_base::badbit); | |
992 | __throw_exception_again; | |
993 | } | |
bc2631e0 | 994 | __catch(...) |
11202768 PC |
995 | { |
996 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
997 | // 91. Description of operator>> and getline() for string<> | |
998 | // might cause endless loop | |
999 | __in._M_setstate(__ios_base::badbit); | |
1000 | } | |
1001 | } | |
1002 | // 211. operator>>(istream&, string&) doesn't set failbit | |
1003 | if (!__extracted) | |
1004 | __err |= __ios_base::failbit; | |
1005 | if (__err) | |
1006 | __in.setstate(__err); | |
1007 | return __in; | |
1008 | } | |
1009 | ||
1010 | template<typename _CharT, typename _Traits, typename _Alloc> | |
1011 | basic_istream<_CharT, _Traits>& | |
1012 | getline(basic_istream<_CharT, _Traits>& __in, | |
1013 | basic_string<_CharT, _Traits, _Alloc>& __str, _CharT __delim) | |
1014 | { | |
1015 | typedef basic_istream<_CharT, _Traits> __istream_type; | |
1016 | typedef basic_string<_CharT, _Traits, _Alloc> __string_type; | |
1017 | typedef typename __istream_type::ios_base __ios_base; | |
1018 | typedef typename __istream_type::int_type __int_type; | |
1019 | typedef typename __string_type::size_type __size_type; | |
1020 | ||
1021 | __size_type __extracted = 0; | |
1022 | const __size_type __n = __str.max_size(); | |
1023 | typename __ios_base::iostate __err = __ios_base::goodbit; | |
1024 | typename __istream_type::sentry __cerb(__in, true); | |
880b527f | 1025 | if (__cerb) |
11202768 | 1026 | { |
bc2631e0 | 1027 | __try |
11202768 PC |
1028 | { |
1029 | __str.erase(); | |
1030 | const __int_type __idelim = _Traits::to_int_type(__delim); | |
1031 | const __int_type __eof = _Traits::eof(); | |
1032 | __int_type __c = __in.rdbuf()->sgetc(); | |
1033 | ||
1034 | while (__extracted < __n | |
1035 | && !_Traits::eq_int_type(__c, __eof) | |
1036 | && !_Traits::eq_int_type(__c, __idelim)) | |
1037 | { | |
1038 | __str += _Traits::to_char_type(__c); | |
1039 | ++__extracted; | |
1040 | __c = __in.rdbuf()->snextc(); | |
1041 | } | |
1042 | ||
1043 | if (_Traits::eq_int_type(__c, __eof)) | |
1044 | __err |= __ios_base::eofbit; | |
1045 | else if (_Traits::eq_int_type(__c, __idelim)) | |
1046 | { | |
1047 | ++__extracted; | |
1048 | __in.rdbuf()->sbumpc(); | |
1049 | } | |
1050 | else | |
1051 | __err |= __ios_base::failbit; | |
1052 | } | |
bc2631e0 | 1053 | __catch(__cxxabiv1::__forced_unwind&) |
d05f74f1 JM |
1054 | { |
1055 | __in._M_setstate(__ios_base::badbit); | |
1056 | __throw_exception_again; | |
1057 | } | |
bc2631e0 | 1058 | __catch(...) |
11202768 PC |
1059 | { |
1060 | // _GLIBCXX_RESOLVE_LIB_DEFECTS | |
1061 | // 91. Description of operator>> and getline() for string<> | |
1062 | // might cause endless loop | |
1063 | __in._M_setstate(__ios_base::badbit); | |
1064 | } | |
1065 | } | |
1066 | if (!__extracted) | |
1067 | __err |= __ios_base::failbit; | |
1068 | if (__err) | |
1069 | __in.setstate(__err); | |
1070 | return __in; | |
1071 | } | |
1072 | ||
a32e3c09 | 1073 | // Inhibit implicit instantiations for required instantiations, |
ed6814f7 | 1074 | // which are defined via explicit instantiations elsewhere. |
db9e7b2a | 1075 | #if _GLIBCXX_EXTERN_TEMPLATE |
8f159176 JW |
1076 | // The explicit instantiation definitions in src/c++11/string-inst.cc and |
1077 | // src/c++17/string-inst.cc only instantiate the members required for C++17 | |
1078 | // and earlier standards (so not C++20's starts_with and ends_with). | |
1079 | // Suppress the explicit instantiation declarations for C++20, so C++20 | |
1080 | // code will implicitly instantiate std::string and std::wstring as needed. | |
1a289fa3 | 1081 | # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0 |
a32e3c09 | 1082 | extern template class basic_string<char>; |
d72888d3 JW |
1083 | # elif ! _GLIBCXX_USE_CXX11_ABI |
1084 | // Still need to prevent implicit instantiation of the COW empty rep, | |
1085 | // to ensure the definition in libstdc++.so is unique (PR 86138). | |
1086 | extern template basic_string<char>::size_type | |
1087 | basic_string<char>::_Rep::_S_empty_rep_storage[]; | |
1088 | # endif | |
1089 | ||
ed6814f7 BI |
1090 | extern template |
1091 | basic_istream<char>& | |
a32e3c09 | 1092 | operator>>(basic_istream<char>&, string&); |
ed6814f7 BI |
1093 | extern template |
1094 | basic_ostream<char>& | |
a32e3c09 | 1095 | operator<<(basic_ostream<char>&, const string&); |
ed6814f7 BI |
1096 | extern template |
1097 | basic_istream<char>& | |
a32e3c09 | 1098 | getline(basic_istream<char>&, string&, char); |
ed6814f7 BI |
1099 | extern template |
1100 | basic_istream<char>& | |
a32e3c09 BK |
1101 | getline(basic_istream<char>&, string&); |
1102 | ||
3d7c150e | 1103 | #ifdef _GLIBCXX_USE_WCHAR_T |
1a289fa3 | 1104 | # if __cplusplus <= 201703L && _GLIBCXX_EXTERN_TEMPLATE > 0 |
a32e3c09 | 1105 | extern template class basic_string<wchar_t>; |
d72888d3 JW |
1106 | # elif ! _GLIBCXX_USE_CXX11_ABI |
1107 | extern template basic_string<wchar_t>::size_type | |
1108 | basic_string<wchar_t>::_Rep::_S_empty_rep_storage[]; | |
1109 | # endif | |
1110 | ||
ed6814f7 BI |
1111 | extern template |
1112 | basic_istream<wchar_t>& | |
a32e3c09 | 1113 | operator>>(basic_istream<wchar_t>&, wstring&); |
ed6814f7 BI |
1114 | extern template |
1115 | basic_ostream<wchar_t>& | |
a32e3c09 | 1116 | operator<<(basic_ostream<wchar_t>&, const wstring&); |
ed6814f7 BI |
1117 | extern template |
1118 | basic_istream<wchar_t>& | |
a32e3c09 | 1119 | getline(basic_istream<wchar_t>&, wstring&, wchar_t); |
ed6814f7 BI |
1120 | extern template |
1121 | basic_istream<wchar_t>& | |
a32e3c09 | 1122 | getline(basic_istream<wchar_t>&, wstring&); |
d72888d3 | 1123 | #endif // _GLIBCXX_USE_WCHAR_T |
db9e7b2a | 1124 | #endif // _GLIBCXX_EXTERN_TEMPLATE |
3cbc7af0 | 1125 | |
12ffa228 | 1126 | _GLIBCXX_END_NAMESPACE_VERSION |
ed4f96af | 1127 | } // namespace std |
725dc051 | 1128 | |
3b0fd4bc | 1129 | #endif |