sso_string_base.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580
  1. // Short-string-optimized versatile string base -*- C++ -*-
  2. // Copyright (C) 2005-2020 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 ext/sso_string_base.h
  21. * This is an internal header file, included by other library headers.
  22. * Do not attempt to use it directly. @headername{ext/vstring.h}
  23. */
  24. #ifndef _SSO_STRING_BASE_H
  25. #define _SSO_STRING_BASE_H 1
  26. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  27. {
  28. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  29. template<typename _CharT, typename _Traits, typename _Alloc>
  30. class __sso_string_base
  31. : protected __vstring_utility<_CharT, _Traits, _Alloc>
  32. {
  33. public:
  34. typedef _Traits traits_type;
  35. typedef typename _Traits::char_type value_type;
  36. typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
  37. typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
  38. typedef typename _CharT_alloc_type::size_type size_type;
  39. private:
  40. // Data Members:
  41. typename _Util_Base::template _Alloc_hider<_CharT_alloc_type>
  42. _M_dataplus;
  43. size_type _M_string_length;
  44. enum { _S_local_capacity = 15 };
  45. union
  46. {
  47. _CharT _M_local_data[_S_local_capacity + 1];
  48. size_type _M_allocated_capacity;
  49. };
  50. void
  51. _M_data(_CharT* __p)
  52. { _M_dataplus._M_p = __p; }
  53. void
  54. _M_length(size_type __length)
  55. { _M_string_length = __length; }
  56. void
  57. _M_capacity(size_type __capacity)
  58. { _M_allocated_capacity = __capacity; }
  59. bool
  60. _M_is_local() const
  61. { return _M_data() == _M_local_data; }
  62. // Create & Destroy
  63. _CharT*
  64. _M_create(size_type&, size_type);
  65. void
  66. _M_dispose()
  67. {
  68. if (!_M_is_local())
  69. _M_destroy(_M_allocated_capacity);
  70. }
  71. void
  72. _M_destroy(size_type __size) throw()
  73. { _M_get_allocator().deallocate(_M_data(), __size + 1); }
  74. // _M_construct_aux is used to implement the 21.3.1 para 15 which
  75. // requires special behaviour if _InIterator is an integral type
  76. template<typename _InIterator>
  77. void
  78. _M_construct_aux(_InIterator __beg, _InIterator __end,
  79. std::__false_type)
  80. {
  81. typedef typename std::iterator_traits<_InIterator>::iterator_category
  82. _Tag;
  83. _M_construct(__beg, __end, _Tag());
  84. }
  85. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  86. // 438. Ambiguity in the "do the right thing" clause
  87. template<typename _Integer>
  88. void
  89. _M_construct_aux(_Integer __beg, _Integer __end, std::__true_type)
  90. { _M_construct_aux_2(static_cast<size_type>(__beg), __end); }
  91. void
  92. _M_construct_aux_2(size_type __req, _CharT __c)
  93. { _M_construct(__req, __c); }
  94. template<typename _InIterator>
  95. void
  96. _M_construct(_InIterator __beg, _InIterator __end)
  97. {
  98. typedef typename std::__is_integer<_InIterator>::__type _Integral;
  99. _M_construct_aux(__beg, __end, _Integral());
  100. }
  101. // For Input Iterators, used in istreambuf_iterators, etc.
  102. template<typename _InIterator>
  103. void
  104. _M_construct(_InIterator __beg, _InIterator __end,
  105. std::input_iterator_tag);
  106. // For forward_iterators up to random_access_iterators, used for
  107. // string::iterator, _CharT*, etc.
  108. template<typename _FwdIterator>
  109. void
  110. _M_construct(_FwdIterator __beg, _FwdIterator __end,
  111. std::forward_iterator_tag);
  112. void
  113. _M_construct(size_type __req, _CharT __c);
  114. public:
  115. size_type
  116. _M_max_size() const
  117. {
  118. typedef __alloc_traits<_CharT_alloc_type> _ATraits;
  119. return (_ATraits::max_size(_M_get_allocator()) - 1) / 2;
  120. }
  121. _CharT*
  122. _M_data() const
  123. { return _M_dataplus._M_p; }
  124. size_type
  125. _M_length() const
  126. { return _M_string_length; }
  127. size_type
  128. _M_capacity() const
  129. {
  130. return _M_is_local() ? size_type(_S_local_capacity)
  131. : _M_allocated_capacity;
  132. }
  133. bool
  134. _M_is_shared() const
  135. { return false; }
  136. void
  137. _M_set_leaked() { }
  138. void
  139. _M_leak() { }
  140. void
  141. _M_set_length(size_type __n)
  142. {
  143. _M_length(__n);
  144. traits_type::assign(_M_data()[__n], _CharT());
  145. }
  146. __sso_string_base()
  147. : _M_dataplus(_M_local_data)
  148. { _M_set_length(0); }
  149. __sso_string_base(const _Alloc& __a);
  150. __sso_string_base(const __sso_string_base& __rcs);
  151. #if __cplusplus >= 201103L
  152. __sso_string_base(__sso_string_base&& __rcs);
  153. #endif
  154. __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a);
  155. template<typename _InputIterator>
  156. __sso_string_base(_InputIterator __beg, _InputIterator __end,
  157. const _Alloc& __a);
  158. ~__sso_string_base()
  159. { _M_dispose(); }
  160. _CharT_alloc_type&
  161. _M_get_allocator()
  162. { return _M_dataplus; }
  163. const _CharT_alloc_type&
  164. _M_get_allocator() const
  165. { return _M_dataplus; }
  166. void
  167. _M_swap(__sso_string_base& __rcs);
  168. void
  169. _M_assign(const __sso_string_base& __rcs);
  170. void
  171. _M_reserve(size_type __res);
  172. void
  173. _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  174. size_type __len2);
  175. void
  176. _M_erase(size_type __pos, size_type __n);
  177. void
  178. _M_clear()
  179. { _M_set_length(0); }
  180. bool
  181. _M_compare(const __sso_string_base&) const
  182. { return false; }
  183. };
  184. template<typename _CharT, typename _Traits, typename _Alloc>
  185. void
  186. __sso_string_base<_CharT, _Traits, _Alloc>::
  187. _M_swap(__sso_string_base& __rcs)
  188. {
  189. if (this == &__rcs)
  190. return;
  191. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  192. // 431. Swapping containers with unequal allocators.
  193. std::__alloc_swap<_CharT_alloc_type>::_S_do_it(_M_get_allocator(),
  194. __rcs._M_get_allocator());
  195. if (_M_is_local())
  196. if (__rcs._M_is_local())
  197. {
  198. if (_M_length() && __rcs._M_length())
  199. {
  200. _CharT __tmp_data[_S_local_capacity + 1];
  201. traits_type::copy(__tmp_data, __rcs._M_local_data,
  202. _S_local_capacity + 1);
  203. traits_type::copy(__rcs._M_local_data, _M_local_data,
  204. _S_local_capacity + 1);
  205. traits_type::copy(_M_local_data, __tmp_data,
  206. _S_local_capacity + 1);
  207. }
  208. else if (__rcs._M_length())
  209. {
  210. traits_type::copy(_M_local_data, __rcs._M_local_data,
  211. _S_local_capacity + 1);
  212. _M_length(__rcs._M_length());
  213. __rcs._M_set_length(0);
  214. return;
  215. }
  216. else if (_M_length())
  217. {
  218. traits_type::copy(__rcs._M_local_data, _M_local_data,
  219. _S_local_capacity + 1);
  220. __rcs._M_length(_M_length());
  221. _M_set_length(0);
  222. return;
  223. }
  224. }
  225. else
  226. {
  227. const size_type __tmp_capacity = __rcs._M_allocated_capacity;
  228. traits_type::copy(__rcs._M_local_data, _M_local_data,
  229. _S_local_capacity + 1);
  230. _M_data(__rcs._M_data());
  231. __rcs._M_data(__rcs._M_local_data);
  232. _M_capacity(__tmp_capacity);
  233. }
  234. else
  235. {
  236. const size_type __tmp_capacity = _M_allocated_capacity;
  237. if (__rcs._M_is_local())
  238. {
  239. traits_type::copy(_M_local_data, __rcs._M_local_data,
  240. _S_local_capacity + 1);
  241. __rcs._M_data(_M_data());
  242. _M_data(_M_local_data);
  243. }
  244. else
  245. {
  246. _CharT* __tmp_ptr = _M_data();
  247. _M_data(__rcs._M_data());
  248. __rcs._M_data(__tmp_ptr);
  249. _M_capacity(__rcs._M_allocated_capacity);
  250. }
  251. __rcs._M_capacity(__tmp_capacity);
  252. }
  253. const size_type __tmp_length = _M_length();
  254. _M_length(__rcs._M_length());
  255. __rcs._M_length(__tmp_length);
  256. }
  257. template<typename _CharT, typename _Traits, typename _Alloc>
  258. _CharT*
  259. __sso_string_base<_CharT, _Traits, _Alloc>::
  260. _M_create(size_type& __capacity, size_type __old_capacity)
  261. {
  262. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  263. // 83. String::npos vs. string::max_size()
  264. if (__capacity > _M_max_size())
  265. std::__throw_length_error(__N("__sso_string_base::_M_create"));
  266. // The below implements an exponential growth policy, necessary to
  267. // meet amortized linear time requirements of the library: see
  268. // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
  269. if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
  270. {
  271. __capacity = 2 * __old_capacity;
  272. // Never allocate a string bigger than max_size.
  273. if (__capacity > _M_max_size())
  274. __capacity = _M_max_size();
  275. }
  276. // NB: Need an array of char_type[__capacity], plus a terminating
  277. // null char_type() element.
  278. return _M_get_allocator().allocate(__capacity + 1);
  279. }
  280. template<typename _CharT, typename _Traits, typename _Alloc>
  281. __sso_string_base<_CharT, _Traits, _Alloc>::
  282. __sso_string_base(const _Alloc& __a)
  283. : _M_dataplus(__a, _M_local_data)
  284. { _M_set_length(0); }
  285. template<typename _CharT, typename _Traits, typename _Alloc>
  286. __sso_string_base<_CharT, _Traits, _Alloc>::
  287. __sso_string_base(const __sso_string_base& __rcs)
  288. : _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
  289. { _M_construct(__rcs._M_data(), __rcs._M_data() + __rcs._M_length()); }
  290. #if __cplusplus >= 201103L
  291. template<typename _CharT, typename _Traits, typename _Alloc>
  292. __sso_string_base<_CharT, _Traits, _Alloc>::
  293. __sso_string_base(__sso_string_base&& __rcs)
  294. : _M_dataplus(__rcs._M_get_allocator(), _M_local_data)
  295. {
  296. if (__rcs._M_is_local())
  297. {
  298. if (__rcs._M_length())
  299. traits_type::copy(_M_local_data, __rcs._M_local_data,
  300. _S_local_capacity + 1);
  301. }
  302. else
  303. {
  304. _M_data(__rcs._M_data());
  305. _M_capacity(__rcs._M_allocated_capacity);
  306. }
  307. _M_set_length(__rcs._M_length());
  308. __rcs._M_data(__rcs._M_local_data);
  309. __rcs._M_set_length(0);
  310. }
  311. #endif
  312. template<typename _CharT, typename _Traits, typename _Alloc>
  313. __sso_string_base<_CharT, _Traits, _Alloc>::
  314. __sso_string_base(size_type __n, _CharT __c, const _Alloc& __a)
  315. : _M_dataplus(__a, _M_local_data)
  316. { _M_construct(__n, __c); }
  317. template<typename _CharT, typename _Traits, typename _Alloc>
  318. template<typename _InputIterator>
  319. __sso_string_base<_CharT, _Traits, _Alloc>::
  320. __sso_string_base(_InputIterator __beg, _InputIterator __end,
  321. const _Alloc& __a)
  322. : _M_dataplus(__a, _M_local_data)
  323. { _M_construct(__beg, __end); }
  324. // NB: This is the special case for Input Iterators, used in
  325. // istreambuf_iterators, etc.
  326. // Input Iterators have a cost structure very different from
  327. // pointers, calling for a different coding style.
  328. template<typename _CharT, typename _Traits, typename _Alloc>
  329. template<typename _InIterator>
  330. void
  331. __sso_string_base<_CharT, _Traits, _Alloc>::
  332. _M_construct(_InIterator __beg, _InIterator __end,
  333. std::input_iterator_tag)
  334. {
  335. size_type __len = 0;
  336. size_type __capacity = size_type(_S_local_capacity);
  337. while (__beg != __end && __len < __capacity)
  338. {
  339. _M_data()[__len++] = *__beg;
  340. ++__beg;
  341. }
  342. __try
  343. {
  344. while (__beg != __end)
  345. {
  346. if (__len == __capacity)
  347. {
  348. // Allocate more space.
  349. __capacity = __len + 1;
  350. _CharT* __another = _M_create(__capacity, __len);
  351. this->_S_copy(__another, _M_data(), __len);
  352. _M_dispose();
  353. _M_data(__another);
  354. _M_capacity(__capacity);
  355. }
  356. _M_data()[__len++] = *__beg;
  357. ++__beg;
  358. }
  359. }
  360. __catch(...)
  361. {
  362. _M_dispose();
  363. __throw_exception_again;
  364. }
  365. _M_set_length(__len);
  366. }
  367. template<typename _CharT, typename _Traits, typename _Alloc>
  368. template<typename _InIterator>
  369. void
  370. __sso_string_base<_CharT, _Traits, _Alloc>::
  371. _M_construct(_InIterator __beg, _InIterator __end,
  372. std::forward_iterator_tag)
  373. {
  374. // NB: Not required, but considered best practice.
  375. if (__is_null_pointer(__beg) && __beg != __end)
  376. std::__throw_logic_error(__N("__sso_string_base::"
  377. "_M_construct null not valid"));
  378. size_type __dnew = static_cast<size_type>(std::distance(__beg, __end));
  379. if (__dnew > size_type(_S_local_capacity))
  380. {
  381. _M_data(_M_create(__dnew, size_type(0)));
  382. _M_capacity(__dnew);
  383. }
  384. // Check for out_of_range and length_error exceptions.
  385. __try
  386. { this->_S_copy_chars(_M_data(), __beg, __end); }
  387. __catch(...)
  388. {
  389. _M_dispose();
  390. __throw_exception_again;
  391. }
  392. _M_set_length(__dnew);
  393. }
  394. template<typename _CharT, typename _Traits, typename _Alloc>
  395. void
  396. __sso_string_base<_CharT, _Traits, _Alloc>::
  397. _M_construct(size_type __n, _CharT __c)
  398. {
  399. if (__n > size_type(_S_local_capacity))
  400. {
  401. _M_data(_M_create(__n, size_type(0)));
  402. _M_capacity(__n);
  403. }
  404. if (__n)
  405. this->_S_assign(_M_data(), __n, __c);
  406. _M_set_length(__n);
  407. }
  408. template<typename _CharT, typename _Traits, typename _Alloc>
  409. void
  410. __sso_string_base<_CharT, _Traits, _Alloc>::
  411. _M_assign(const __sso_string_base& __rcs)
  412. {
  413. if (this != &__rcs)
  414. {
  415. const size_type __rsize = __rcs._M_length();
  416. const size_type __capacity = _M_capacity();
  417. if (__rsize > __capacity)
  418. {
  419. size_type __new_capacity = __rsize;
  420. _CharT* __tmp = _M_create(__new_capacity, __capacity);
  421. _M_dispose();
  422. _M_data(__tmp);
  423. _M_capacity(__new_capacity);
  424. }
  425. if (__rsize)
  426. this->_S_copy(_M_data(), __rcs._M_data(), __rsize);
  427. _M_set_length(__rsize);
  428. }
  429. }
  430. template<typename _CharT, typename _Traits, typename _Alloc>
  431. void
  432. __sso_string_base<_CharT, _Traits, _Alloc>::
  433. _M_reserve(size_type __res)
  434. {
  435. // Make sure we don't shrink below the current size.
  436. if (__res < _M_length())
  437. __res = _M_length();
  438. const size_type __capacity = _M_capacity();
  439. if (__res != __capacity)
  440. {
  441. if (__res > __capacity
  442. || __res > size_type(_S_local_capacity))
  443. {
  444. _CharT* __tmp = _M_create(__res, __capacity);
  445. this->_S_copy(__tmp, _M_data(), _M_length() + 1);
  446. _M_dispose();
  447. _M_data(__tmp);
  448. _M_capacity(__res);
  449. }
  450. else if (!_M_is_local())
  451. {
  452. this->_S_copy(_M_local_data, _M_data(), _M_length() + 1);
  453. _M_destroy(__capacity);
  454. _M_data(_M_local_data);
  455. }
  456. }
  457. }
  458. template<typename _CharT, typename _Traits, typename _Alloc>
  459. void
  460. __sso_string_base<_CharT, _Traits, _Alloc>::
  461. _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  462. size_type __len2)
  463. {
  464. const size_type __how_much = _M_length() - __pos - __len1;
  465. size_type __new_capacity = _M_length() + __len2 - __len1;
  466. _CharT* __r = _M_create(__new_capacity, _M_capacity());
  467. if (__pos)
  468. this->_S_copy(__r, _M_data(), __pos);
  469. if (__s && __len2)
  470. this->_S_copy(__r + __pos, __s, __len2);
  471. if (__how_much)
  472. this->_S_copy(__r + __pos + __len2,
  473. _M_data() + __pos + __len1, __how_much);
  474. _M_dispose();
  475. _M_data(__r);
  476. _M_capacity(__new_capacity);
  477. }
  478. template<typename _CharT, typename _Traits, typename _Alloc>
  479. void
  480. __sso_string_base<_CharT, _Traits, _Alloc>::
  481. _M_erase(size_type __pos, size_type __n)
  482. {
  483. const size_type __how_much = _M_length() - __pos - __n;
  484. if (__how_much && __n)
  485. this->_S_move(_M_data() + __pos, _M_data() + __pos + __n, __how_much);
  486. _M_set_length(_M_length() - __n);
  487. }
  488. _GLIBCXX_END_NAMESPACE_VERSION
  489. } // namespace
  490. #endif /* _SSO_STRING_BASE_H */