rc_string_base.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. // Reference-counted 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/rc_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 _RC_STRING_BASE_H
  25. #define _RC_STRING_BASE_H 1
  26. #include <ext/atomicity.h>
  27. #include <bits/stl_iterator_base_funcs.h>
  28. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  29. {
  30. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  31. /**
  32. * Documentation? What's that?
  33. * Nathan Myers <ncm@cantrip.org>.
  34. *
  35. * A string looks like this:
  36. *
  37. * @code
  38. * [_Rep]
  39. * _M_length
  40. * [__rc_string_base<char_type>] _M_capacity
  41. * _M_dataplus _M_refcount
  42. * _M_p ----------------> unnamed array of char_type
  43. * @endcode
  44. *
  45. * Where the _M_p points to the first character in the string, and
  46. * you cast it to a pointer-to-_Rep and subtract 1 to get a
  47. * pointer to the header.
  48. *
  49. * This approach has the enormous advantage that a string object
  50. * requires only one allocation. All the ugliness is confined
  51. * within a single pair of inline functions, which each compile to
  52. * a single @a add instruction: _Rep::_M_refdata(), and
  53. * __rc_string_base::_M_rep(); and the allocation function which gets a
  54. * block of raw bytes and with room enough and constructs a _Rep
  55. * object at the front.
  56. *
  57. * The reason you want _M_data pointing to the character array and
  58. * not the _Rep is so that the debugger can see the string
  59. * contents. (Probably we should add a non-inline member to get
  60. * the _Rep for the debugger to use, so users can check the actual
  61. * string length.)
  62. *
  63. * Note that the _Rep object is a POD so that you can have a
  64. * static <em>empty string</em> _Rep object already @a constructed before
  65. * static constructors have run. The reference-count encoding is
  66. * chosen so that a 0 indicates one reference, so you never try to
  67. * destroy the empty-string _Rep object.
  68. *
  69. * All but the last paragraph is considered pretty conventional
  70. * for a C++ string implementation.
  71. */
  72. template<typename _CharT, typename _Traits, typename _Alloc>
  73. class __rc_string_base
  74. : protected __vstring_utility<_CharT, _Traits, _Alloc>
  75. {
  76. public:
  77. typedef _Traits traits_type;
  78. typedef typename _Traits::char_type value_type;
  79. typedef _Alloc allocator_type;
  80. typedef __vstring_utility<_CharT, _Traits, _Alloc> _Util_Base;
  81. typedef typename _Util_Base::_CharT_alloc_type _CharT_alloc_type;
  82. typedef typename _CharT_alloc_type::size_type size_type;
  83. private:
  84. // _Rep: string representation
  85. // Invariants:
  86. // 1. String really contains _M_length + 1 characters: due to 21.3.4
  87. // must be kept null-terminated.
  88. // 2. _M_capacity >= _M_length
  89. // Allocated memory is always (_M_capacity + 1) * sizeof(_CharT).
  90. // 3. _M_refcount has three states:
  91. // -1: leaked, one reference, no ref-copies allowed, non-const.
  92. // 0: one reference, non-const.
  93. // n>0: n + 1 references, operations require a lock, const.
  94. // 4. All fields == 0 is an empty string, given the extra storage
  95. // beyond-the-end for a null terminator; thus, the shared
  96. // empty string representation needs no constructor.
  97. struct _Rep
  98. {
  99. union
  100. {
  101. struct
  102. {
  103. size_type _M_length;
  104. size_type _M_capacity;
  105. _Atomic_word _M_refcount;
  106. } _M_info;
  107. // Only for alignment purposes.
  108. _CharT _M_align;
  109. };
  110. typedef typename _Alloc::template rebind<_Rep>::other _Rep_alloc_type;
  111. _CharT*
  112. _M_refdata() throw()
  113. { return reinterpret_cast<_CharT*>(this + 1); }
  114. _CharT*
  115. _M_refcopy() throw()
  116. {
  117. __atomic_add_dispatch(&_M_info._M_refcount, 1);
  118. return _M_refdata();
  119. } // XXX MT
  120. void
  121. _M_set_length(size_type __n)
  122. {
  123. _M_info._M_refcount = 0; // One reference.
  124. _M_info._M_length = __n;
  125. // grrr. (per 21.3.4)
  126. // You cannot leave those LWG people alone for a second.
  127. traits_type::assign(_M_refdata()[__n], _CharT());
  128. }
  129. // Create & Destroy
  130. static _Rep*
  131. _S_create(size_type, size_type, const _Alloc&);
  132. void
  133. _M_destroy(const _Alloc&) throw();
  134. _CharT*
  135. _M_clone(const _Alloc&, size_type __res = 0);
  136. };
  137. struct _Rep_empty
  138. : public _Rep
  139. {
  140. _CharT _M_terminal;
  141. };
  142. static _Rep_empty _S_empty_rep;
  143. // The maximum number of individual char_type elements of an
  144. // individual string is determined by _S_max_size. This is the
  145. // value that will be returned by max_size(). (Whereas npos
  146. // is the maximum number of bytes the allocator can allocate.)
  147. // If one was to divvy up the theoretical largest size string,
  148. // with a terminating character and m _CharT elements, it'd
  149. // look like this:
  150. // npos = sizeof(_Rep) + (m * sizeof(_CharT)) + sizeof(_CharT)
  151. // + sizeof(_Rep) - 1
  152. // (NB: last two terms for rounding reasons, see _M_create below)
  153. // Solving for m:
  154. // m = ((npos - 2 * sizeof(_Rep) + 1) / sizeof(_CharT)) - 1
  155. // In addition, this implementation halves this amount.
  156. enum { _S_max_size = (((static_cast<size_type>(-1) - 2 * sizeof(_Rep)
  157. + 1) / sizeof(_CharT)) - 1) / 2 };
  158. // Data Member (private):
  159. mutable typename _Util_Base::template _Alloc_hider<_Alloc> _M_dataplus;
  160. void
  161. _M_data(_CharT* __p)
  162. { _M_dataplus._M_p = __p; }
  163. _Rep*
  164. _M_rep() const
  165. { return &((reinterpret_cast<_Rep*>(_M_data()))[-1]); }
  166. _CharT*
  167. _M_grab(const _Alloc& __alloc) const
  168. {
  169. return (!_M_is_leaked() && _M_get_allocator() == __alloc)
  170. ? _M_rep()->_M_refcopy() : _M_rep()->_M_clone(__alloc);
  171. }
  172. void
  173. _M_dispose()
  174. {
  175. // Be race-detector-friendly. For more info see bits/c++config.
  176. _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&_M_rep()->_M_info.
  177. _M_refcount);
  178. if (__exchange_and_add_dispatch(&_M_rep()->_M_info._M_refcount,
  179. -1) <= 0)
  180. {
  181. _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&_M_rep()->_M_info.
  182. _M_refcount);
  183. _M_rep()->_M_destroy(_M_get_allocator());
  184. }
  185. } // XXX MT
  186. bool
  187. _M_is_leaked() const
  188. { return _M_rep()->_M_info._M_refcount < 0; }
  189. void
  190. _M_set_sharable()
  191. { _M_rep()->_M_info._M_refcount = 0; }
  192. void
  193. _M_leak_hard();
  194. // _S_construct_aux is used to implement the 21.3.1 para 15 which
  195. // requires special behaviour if _InIterator is an integral type
  196. template<typename _InIterator>
  197. static _CharT*
  198. _S_construct_aux(_InIterator __beg, _InIterator __end,
  199. const _Alloc& __a, std::__false_type)
  200. {
  201. typedef typename iterator_traits<_InIterator>::iterator_category _Tag;
  202. return _S_construct(__beg, __end, __a, _Tag());
  203. }
  204. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  205. // 438. Ambiguity in the "do the right thing" clause
  206. template<typename _Integer>
  207. static _CharT*
  208. _S_construct_aux(_Integer __beg, _Integer __end,
  209. const _Alloc& __a, std::__true_type)
  210. { return _S_construct_aux_2(static_cast<size_type>(__beg),
  211. __end, __a); }
  212. static _CharT*
  213. _S_construct_aux_2(size_type __req, _CharT __c, const _Alloc& __a)
  214. { return _S_construct(__req, __c, __a); }
  215. template<typename _InIterator>
  216. static _CharT*
  217. _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a)
  218. {
  219. typedef typename std::__is_integer<_InIterator>::__type _Integral;
  220. return _S_construct_aux(__beg, __end, __a, _Integral());
  221. }
  222. // For Input Iterators, used in istreambuf_iterators, etc.
  223. template<typename _InIterator>
  224. static _CharT*
  225. _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  226. std::input_iterator_tag);
  227. // For forward_iterators up to random_access_iterators, used for
  228. // string::iterator, _CharT*, etc.
  229. template<typename _FwdIterator>
  230. static _CharT*
  231. _S_construct(_FwdIterator __beg, _FwdIterator __end, const _Alloc& __a,
  232. std::forward_iterator_tag);
  233. static _CharT*
  234. _S_construct(size_type __req, _CharT __c, const _Alloc& __a);
  235. public:
  236. size_type
  237. _M_max_size() const
  238. { return size_type(_S_max_size); }
  239. _CharT*
  240. _M_data() const
  241. { return _M_dataplus._M_p; }
  242. size_type
  243. _M_length() const
  244. { return _M_rep()->_M_info._M_length; }
  245. size_type
  246. _M_capacity() const
  247. { return _M_rep()->_M_info._M_capacity; }
  248. bool
  249. _M_is_shared() const
  250. { return _M_rep()->_M_info._M_refcount > 0; }
  251. void
  252. _M_set_leaked()
  253. { _M_rep()->_M_info._M_refcount = -1; }
  254. void
  255. _M_leak() // for use in begin() & non-const op[]
  256. {
  257. if (!_M_is_leaked())
  258. _M_leak_hard();
  259. }
  260. void
  261. _M_set_length(size_type __n)
  262. { _M_rep()->_M_set_length(__n); }
  263. __rc_string_base()
  264. : _M_dataplus(_S_empty_rep._M_refcopy()) { }
  265. __rc_string_base(const _Alloc& __a);
  266. __rc_string_base(const __rc_string_base& __rcs);
  267. #if __cplusplus >= 201103L
  268. __rc_string_base(__rc_string_base&& __rcs)
  269. : _M_dataplus(__rcs._M_dataplus)
  270. { __rcs._M_data(_S_empty_rep._M_refcopy()); }
  271. #endif
  272. __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a);
  273. template<typename _InputIterator>
  274. __rc_string_base(_InputIterator __beg, _InputIterator __end,
  275. const _Alloc& __a);
  276. ~__rc_string_base()
  277. { _M_dispose(); }
  278. allocator_type&
  279. _M_get_allocator()
  280. { return _M_dataplus; }
  281. const allocator_type&
  282. _M_get_allocator() const
  283. { return _M_dataplus; }
  284. void
  285. _M_swap(__rc_string_base& __rcs);
  286. void
  287. _M_assign(const __rc_string_base& __rcs);
  288. void
  289. _M_reserve(size_type __res);
  290. void
  291. _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  292. size_type __len2);
  293. void
  294. _M_erase(size_type __pos, size_type __n);
  295. void
  296. _M_clear()
  297. {
  298. _M_dispose();
  299. _M_data(_S_empty_rep._M_refcopy());
  300. }
  301. bool
  302. _M_compare(const __rc_string_base&) const
  303. { return false; }
  304. };
  305. template<typename _CharT, typename _Traits, typename _Alloc>
  306. typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep_empty
  307. __rc_string_base<_CharT, _Traits, _Alloc>::_S_empty_rep;
  308. template<typename _CharT, typename _Traits, typename _Alloc>
  309. typename __rc_string_base<_CharT, _Traits, _Alloc>::_Rep*
  310. __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  311. _S_create(size_type __capacity, size_type __old_capacity,
  312. const _Alloc& __alloc)
  313. {
  314. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  315. // 83. String::npos vs. string::max_size()
  316. if (__capacity > size_type(_S_max_size))
  317. std::__throw_length_error(__N("__rc_string_base::_Rep::_S_create"));
  318. // The standard places no restriction on allocating more memory
  319. // than is strictly needed within this layer at the moment or as
  320. // requested by an explicit application call to reserve().
  321. // Many malloc implementations perform quite poorly when an
  322. // application attempts to allocate memory in a stepwise fashion
  323. // growing each allocation size by only 1 char. Additionally,
  324. // it makes little sense to allocate less linear memory than the
  325. // natural blocking size of the malloc implementation.
  326. // Unfortunately, we would need a somewhat low-level calculation
  327. // with tuned parameters to get this perfect for any particular
  328. // malloc implementation. Fortunately, generalizations about
  329. // common features seen among implementations seems to suffice.
  330. // __pagesize need not match the actual VM page size for good
  331. // results in practice, thus we pick a common value on the low
  332. // side. __malloc_header_size is an estimate of the amount of
  333. // overhead per memory allocation (in practice seen N * sizeof
  334. // (void*) where N is 0, 2 or 4). According to folklore,
  335. // picking this value on the high side is better than
  336. // low-balling it (especially when this algorithm is used with
  337. // malloc implementations that allocate memory blocks rounded up
  338. // to a size which is a power of 2).
  339. const size_type __pagesize = 4096;
  340. const size_type __malloc_header_size = 4 * sizeof(void*);
  341. // The below implements an exponential growth policy, necessary to
  342. // meet amortized linear time requirements of the library: see
  343. // http://gcc.gnu.org/ml/libstdc++/2001-07/msg00085.html.
  344. if (__capacity > __old_capacity && __capacity < 2 * __old_capacity)
  345. {
  346. __capacity = 2 * __old_capacity;
  347. // Never allocate a string bigger than _S_max_size.
  348. if (__capacity > size_type(_S_max_size))
  349. __capacity = size_type(_S_max_size);
  350. }
  351. // NB: Need an array of char_type[__capacity], plus a terminating
  352. // null char_type() element, plus enough for the _Rep data structure,
  353. // plus sizeof(_Rep) - 1 to upper round to a size multiple of
  354. // sizeof(_Rep).
  355. // Whew. Seemingly so needy, yet so elemental.
  356. size_type __size = ((__capacity + 1) * sizeof(_CharT)
  357. + 2 * sizeof(_Rep) - 1);
  358. const size_type __adj_size = __size + __malloc_header_size;
  359. if (__adj_size > __pagesize && __capacity > __old_capacity)
  360. {
  361. const size_type __extra = __pagesize - __adj_size % __pagesize;
  362. __capacity += __extra / sizeof(_CharT);
  363. if (__capacity > size_type(_S_max_size))
  364. __capacity = size_type(_S_max_size);
  365. __size = (__capacity + 1) * sizeof(_CharT) + 2 * sizeof(_Rep) - 1;
  366. }
  367. // NB: Might throw, but no worries about a leak, mate: _Rep()
  368. // does not throw.
  369. _Rep* __place = _Rep_alloc_type(__alloc).allocate(__size / sizeof(_Rep));
  370. _Rep* __p = new (__place) _Rep;
  371. __p->_M_info._M_capacity = __capacity;
  372. return __p;
  373. }
  374. template<typename _CharT, typename _Traits, typename _Alloc>
  375. void
  376. __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  377. _M_destroy(const _Alloc& __a) throw ()
  378. {
  379. const size_type __size = ((_M_info._M_capacity + 1) * sizeof(_CharT)
  380. + 2 * sizeof(_Rep) - 1);
  381. _Rep_alloc_type(__a).deallocate(this, __size / sizeof(_Rep));
  382. }
  383. template<typename _CharT, typename _Traits, typename _Alloc>
  384. _CharT*
  385. __rc_string_base<_CharT, _Traits, _Alloc>::_Rep::
  386. _M_clone(const _Alloc& __alloc, size_type __res)
  387. {
  388. // Requested capacity of the clone.
  389. const size_type __requested_cap = _M_info._M_length + __res;
  390. _Rep* __r = _Rep::_S_create(__requested_cap, _M_info._M_capacity,
  391. __alloc);
  392. if (_M_info._M_length)
  393. __rc_string_base::_S_copy(__r->_M_refdata(), _M_refdata(), _M_info._M_length);
  394. __r->_M_set_length(_M_info._M_length);
  395. return __r->_M_refdata();
  396. }
  397. template<typename _CharT, typename _Traits, typename _Alloc>
  398. __rc_string_base<_CharT, _Traits, _Alloc>::
  399. __rc_string_base(const _Alloc& __a)
  400. : _M_dataplus(__a, _S_construct(size_type(), _CharT(), __a)) { }
  401. template<typename _CharT, typename _Traits, typename _Alloc>
  402. __rc_string_base<_CharT, _Traits, _Alloc>::
  403. __rc_string_base(const __rc_string_base& __rcs)
  404. : _M_dataplus(__rcs._M_get_allocator(),
  405. __rcs._M_grab(__rcs._M_get_allocator())) { }
  406. template<typename _CharT, typename _Traits, typename _Alloc>
  407. __rc_string_base<_CharT, _Traits, _Alloc>::
  408. __rc_string_base(size_type __n, _CharT __c, const _Alloc& __a)
  409. : _M_dataplus(__a, _S_construct(__n, __c, __a)) { }
  410. template<typename _CharT, typename _Traits, typename _Alloc>
  411. template<typename _InputIterator>
  412. __rc_string_base<_CharT, _Traits, _Alloc>::
  413. __rc_string_base(_InputIterator __beg, _InputIterator __end,
  414. const _Alloc& __a)
  415. : _M_dataplus(__a, _S_construct(__beg, __end, __a)) { }
  416. template<typename _CharT, typename _Traits, typename _Alloc>
  417. void
  418. __rc_string_base<_CharT, _Traits, _Alloc>::
  419. _M_leak_hard()
  420. {
  421. if (_M_is_shared())
  422. _M_erase(0, 0);
  423. _M_set_leaked();
  424. }
  425. // NB: This is the special case for Input Iterators, used in
  426. // istreambuf_iterators, etc.
  427. // Input Iterators have a cost structure very different from
  428. // pointers, calling for a different coding style.
  429. template<typename _CharT, typename _Traits, typename _Alloc>
  430. template<typename _InIterator>
  431. _CharT*
  432. __rc_string_base<_CharT, _Traits, _Alloc>::
  433. _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  434. std::input_iterator_tag)
  435. {
  436. if (__beg == __end && __a == _Alloc())
  437. return _S_empty_rep._M_refcopy();
  438. // Avoid reallocation for common case.
  439. _CharT __buf[128];
  440. size_type __len = 0;
  441. while (__beg != __end && __len < sizeof(__buf) / sizeof(_CharT))
  442. {
  443. __buf[__len++] = *__beg;
  444. ++__beg;
  445. }
  446. _Rep* __r = _Rep::_S_create(__len, size_type(0), __a);
  447. _S_copy(__r->_M_refdata(), __buf, __len);
  448. __try
  449. {
  450. while (__beg != __end)
  451. {
  452. if (__len == __r->_M_info._M_capacity)
  453. {
  454. // Allocate more space.
  455. _Rep* __another = _Rep::_S_create(__len + 1, __len, __a);
  456. _S_copy(__another->_M_refdata(), __r->_M_refdata(), __len);
  457. __r->_M_destroy(__a);
  458. __r = __another;
  459. }
  460. __r->_M_refdata()[__len++] = *__beg;
  461. ++__beg;
  462. }
  463. }
  464. __catch(...)
  465. {
  466. __r->_M_destroy(__a);
  467. __throw_exception_again;
  468. }
  469. __r->_M_set_length(__len);
  470. return __r->_M_refdata();
  471. }
  472. template<typename _CharT, typename _Traits, typename _Alloc>
  473. template<typename _InIterator>
  474. _CharT*
  475. __rc_string_base<_CharT, _Traits, _Alloc>::
  476. _S_construct(_InIterator __beg, _InIterator __end, const _Alloc& __a,
  477. std::forward_iterator_tag)
  478. {
  479. if (__beg == __end && __a == _Alloc())
  480. return _S_empty_rep._M_refcopy();
  481. // NB: Not required, but considered best practice.
  482. if (__is_null_pointer(__beg) && __beg != __end)
  483. std::__throw_logic_error(__N("__rc_string_base::"
  484. "_S_construct null not valid"));
  485. const size_type __dnew = static_cast<size_type>(std::distance(__beg,
  486. __end));
  487. // Check for out_of_range and length_error exceptions.
  488. _Rep* __r = _Rep::_S_create(__dnew, size_type(0), __a);
  489. __try
  490. { __rc_string_base::_S_copy_chars(__r->_M_refdata(), __beg, __end); }
  491. __catch(...)
  492. {
  493. __r->_M_destroy(__a);
  494. __throw_exception_again;
  495. }
  496. __r->_M_set_length(__dnew);
  497. return __r->_M_refdata();
  498. }
  499. template<typename _CharT, typename _Traits, typename _Alloc>
  500. _CharT*
  501. __rc_string_base<_CharT, _Traits, _Alloc>::
  502. _S_construct(size_type __n, _CharT __c, const _Alloc& __a)
  503. {
  504. if (__n == 0 && __a == _Alloc())
  505. return _S_empty_rep._M_refcopy();
  506. // Check for out_of_range and length_error exceptions.
  507. _Rep* __r = _Rep::_S_create(__n, size_type(0), __a);
  508. if (__n)
  509. __rc_string_base::_S_assign(__r->_M_refdata(), __n, __c);
  510. __r->_M_set_length(__n);
  511. return __r->_M_refdata();
  512. }
  513. template<typename _CharT, typename _Traits, typename _Alloc>
  514. void
  515. __rc_string_base<_CharT, _Traits, _Alloc>::
  516. _M_swap(__rc_string_base& __rcs)
  517. {
  518. if (_M_is_leaked())
  519. _M_set_sharable();
  520. if (__rcs._M_is_leaked())
  521. __rcs._M_set_sharable();
  522. _CharT* __tmp = _M_data();
  523. _M_data(__rcs._M_data());
  524. __rcs._M_data(__tmp);
  525. // _GLIBCXX_RESOLVE_LIB_DEFECTS
  526. // 431. Swapping containers with unequal allocators.
  527. std::__alloc_swap<allocator_type>::_S_do_it(_M_get_allocator(),
  528. __rcs._M_get_allocator());
  529. }
  530. template<typename _CharT, typename _Traits, typename _Alloc>
  531. void
  532. __rc_string_base<_CharT, _Traits, _Alloc>::
  533. _M_assign(const __rc_string_base& __rcs)
  534. {
  535. if (_M_rep() != __rcs._M_rep())
  536. {
  537. _CharT* __tmp = __rcs._M_grab(_M_get_allocator());
  538. _M_dispose();
  539. _M_data(__tmp);
  540. }
  541. }
  542. template<typename _CharT, typename _Traits, typename _Alloc>
  543. void
  544. __rc_string_base<_CharT, _Traits, _Alloc>::
  545. _M_reserve(size_type __res)
  546. {
  547. // Make sure we don't shrink below the current size.
  548. if (__res < _M_length())
  549. __res = _M_length();
  550. if (__res != _M_capacity() || _M_is_shared())
  551. {
  552. _CharT* __tmp = _M_rep()->_M_clone(_M_get_allocator(),
  553. __res - _M_length());
  554. _M_dispose();
  555. _M_data(__tmp);
  556. }
  557. }
  558. template<typename _CharT, typename _Traits, typename _Alloc>
  559. void
  560. __rc_string_base<_CharT, _Traits, _Alloc>::
  561. _M_mutate(size_type __pos, size_type __len1, const _CharT* __s,
  562. size_type __len2)
  563. {
  564. const size_type __how_much = _M_length() - __pos - __len1;
  565. _Rep* __r = _Rep::_S_create(_M_length() + __len2 - __len1,
  566. _M_capacity(), _M_get_allocator());
  567. if (__pos)
  568. this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
  569. if (__s && __len2)
  570. this->_S_copy(__r->_M_refdata() + __pos, __s, __len2);
  571. if (__how_much)
  572. this->_S_copy(__r->_M_refdata() + __pos + __len2,
  573. _M_data() + __pos + __len1, __how_much);
  574. _M_dispose();
  575. _M_data(__r->_M_refdata());
  576. }
  577. template<typename _CharT, typename _Traits, typename _Alloc>
  578. void
  579. __rc_string_base<_CharT, _Traits, _Alloc>::
  580. _M_erase(size_type __pos, size_type __n)
  581. {
  582. const size_type __new_size = _M_length() - __n;
  583. const size_type __how_much = _M_length() - __pos - __n;
  584. if (_M_is_shared())
  585. {
  586. // Must reallocate.
  587. _Rep* __r = _Rep::_S_create(__new_size, _M_capacity(),
  588. _M_get_allocator());
  589. if (__pos)
  590. this->_S_copy(__r->_M_refdata(), _M_data(), __pos);
  591. if (__how_much)
  592. this->_S_copy(__r->_M_refdata() + __pos,
  593. _M_data() + __pos + __n, __how_much);
  594. _M_dispose();
  595. _M_data(__r->_M_refdata());
  596. }
  597. else if (__how_much && __n)
  598. {
  599. // Work in-place.
  600. this->_S_move(_M_data() + __pos,
  601. _M_data() + __pos + __n, __how_much);
  602. }
  603. _M_rep()->_M_set_length(__new_size);
  604. }
  605. template<>
  606. inline bool
  607. __rc_string_base<char, std::char_traits<char>,
  608. std::allocator<char> >::
  609. _M_compare(const __rc_string_base& __rcs) const
  610. {
  611. if (_M_rep() == __rcs._M_rep())
  612. return true;
  613. return false;
  614. }
  615. #ifdef _GLIBCXX_USE_WCHAR_T
  616. template<>
  617. inline bool
  618. __rc_string_base<wchar_t, std::char_traits<wchar_t>,
  619. std::allocator<wchar_t> >::
  620. _M_compare(const __rc_string_base& __rcs) const
  621. {
  622. if (_M_rep() == __rcs._M_rep())
  623. return true;
  624. return false;
  625. }
  626. #endif
  627. _GLIBCXX_END_NAMESPACE_VERSION
  628. } // namespace
  629. #endif /* _RC_STRING_BASE_H */