basic_string.tcc 30 KB

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