sso_string_base.h 16 KB

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