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