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