ropeimpl.h 48 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710
  1. // SGI's rope class implementation -*- C++ -*-
  2. // Copyright (C) 2001-2022 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. /*
  21. * Copyright (c) 1997
  22. * Silicon Graphics Computer Systems, Inc.
  23. *
  24. * Permission to use, copy, modify, distribute and sell this software
  25. * and its documentation for any purpose is hereby granted without fee,
  26. * provided that the above copyright notice appear in all copies and
  27. * that both that copyright notice and this permission notice appear
  28. * in supporting documentation. Silicon Graphics makes no
  29. * representations about the suitability of this software for any
  30. * purpose. It is provided "as is" without express or implied warranty.
  31. */
  32. /** @file ropeimpl.h
  33. * This is an internal header file, included by other library headers.
  34. * Do not attempt to use it directly. @headername{ext/rope}
  35. */
  36. #include <cstdio>
  37. #include <ostream>
  38. #include <bits/functexcept.h>
  39. #include <ext/algorithm> // For copy_n and lexicographical_compare_3way
  40. #include <ext/memory> // For uninitialized_copy_n
  41. #include <ext/numeric> // For power
  42. namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
  43. {
  44. _GLIBCXX_BEGIN_NAMESPACE_VERSION
  45. // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
  46. // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct.
  47. // Results in a valid buf_ptr if the iterator can be legitimately
  48. // dereferenced.
  49. template <class _CharT, class _Alloc>
  50. void
  51. _Rope_iterator_base<_CharT, _Alloc>::
  52. _S_setbuf(_Rope_iterator_base<_CharT, _Alloc>& __x)
  53. {
  54. using std::size_t;
  55. const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index];
  56. size_t __leaf_pos = __x._M_leaf_pos;
  57. size_t __pos = __x._M_current_pos;
  58. switch(__leaf->_M_tag)
  59. {
  60. case __detail::_S_leaf:
  61. __x._M_buf_start = ((_Rope_RopeLeaf<_CharT, _Alloc>*)__leaf)->_M_data;
  62. __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos);
  63. __x._M_buf_end = __x._M_buf_start + __leaf->_M_size;
  64. break;
  65. case __detail::_S_function:
  66. case __detail::_S_substringfn:
  67. {
  68. size_t __len = _S_iterator_buf_len;
  69. size_t __buf_start_pos = __leaf_pos;
  70. size_t __leaf_end = __leaf_pos + __leaf->_M_size;
  71. char_producer<_CharT>* __fn = ((_Rope_RopeFunction<_CharT,
  72. _Alloc>*)__leaf)->_M_fn;
  73. if (__buf_start_pos + __len <= __pos)
  74. {
  75. __buf_start_pos = __pos - __len / 4;
  76. if (__buf_start_pos + __len > __leaf_end)
  77. __buf_start_pos = __leaf_end - __len;
  78. }
  79. if (__buf_start_pos + __len > __leaf_end)
  80. __len = __leaf_end - __buf_start_pos;
  81. (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf);
  82. __x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos);
  83. __x._M_buf_start = __x._M_tmp_buf;
  84. __x._M_buf_end = __x._M_tmp_buf + __len;
  85. }
  86. break;
  87. default:
  88. break;
  89. }
  90. }
  91. // Set path and buffer inside a rope iterator. We assume that
  92. // pos and root are already set.
  93. template <class _CharT, class _Alloc>
  94. void
  95. _Rope_iterator_base<_CharT, _Alloc>::
  96. _S_setcache(_Rope_iterator_base<_CharT, _Alloc>& __x)
  97. {
  98. using std::size_t;
  99. const _RopeRep* __path[int(__detail::_S_max_rope_depth) + 1];
  100. const _RopeRep* __curr_rope;
  101. int __curr_depth = -1; /* index into path */
  102. size_t __curr_start_pos = 0;
  103. size_t __pos = __x._M_current_pos;
  104. unsigned char __dirns = 0; // Bit vector marking right turns in the path
  105. if (__pos >= __x._M_root->_M_size)
  106. {
  107. __x._M_buf_ptr = 0;
  108. return;
  109. }
  110. __curr_rope = __x._M_root;
  111. if (0 != __curr_rope->_M_c_string)
  112. {
  113. /* Treat the root as a leaf. */
  114. __x._M_buf_start = __curr_rope->_M_c_string;
  115. __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size;
  116. __x._M_buf_ptr = __curr_rope->_M_c_string + __pos;
  117. __x._M_path_end[0] = __curr_rope;
  118. __x._M_leaf_index = 0;
  119. __x._M_leaf_pos = 0;
  120. return;
  121. }
  122. for(;;)
  123. {
  124. ++__curr_depth;
  125. __path[__curr_depth] = __curr_rope;
  126. switch(__curr_rope->_M_tag)
  127. {
  128. case __detail::_S_leaf:
  129. case __detail::_S_function:
  130. case __detail::_S_substringfn:
  131. __x._M_leaf_pos = __curr_start_pos;
  132. goto done;
  133. case __detail::_S_concat:
  134. {
  135. _Rope_RopeConcatenation<_CharT, _Alloc>* __c =
  136. (_Rope_RopeConcatenation<_CharT, _Alloc>*)__curr_rope;
  137. _RopeRep* __left = __c->_M_left;
  138. size_t __left_len = __left->_M_size;
  139. __dirns <<= 1;
  140. if (__pos >= __curr_start_pos + __left_len)
  141. {
  142. __dirns |= 1;
  143. __curr_rope = __c->_M_right;
  144. __curr_start_pos += __left_len;
  145. }
  146. else
  147. __curr_rope = __left;
  148. }
  149. break;
  150. }
  151. }
  152. done:
  153. // Copy last section of path into _M_path_end.
  154. {
  155. int __i = -1;
  156. int __j = __curr_depth + 1 - int(_S_path_cache_len);
  157. if (__j < 0) __j = 0;
  158. while (__j <= __curr_depth)
  159. __x._M_path_end[++__i] = __path[__j++];
  160. __x._M_leaf_index = __i;
  161. }
  162. __x._M_path_directions = __dirns;
  163. _S_setbuf(__x);
  164. }
  165. // Specialized version of the above. Assumes that
  166. // the path cache is valid for the previous position.
  167. template <class _CharT, class _Alloc>
  168. void
  169. _Rope_iterator_base<_CharT, _Alloc>::
  170. _S_setcache_for_incr(_Rope_iterator_base<_CharT, _Alloc>& __x)
  171. {
  172. using std::size_t;
  173. int __current_index = __x._M_leaf_index;
  174. const _RopeRep* __current_node = __x._M_path_end[__current_index];
  175. size_t __len = __current_node->_M_size;
  176. size_t __node_start_pos = __x._M_leaf_pos;
  177. unsigned char __dirns = __x._M_path_directions;
  178. _Rope_RopeConcatenation<_CharT, _Alloc>* __c;
  179. if (__x._M_current_pos - __node_start_pos < __len)
  180. {
  181. /* More stuff in this leaf, we just didn't cache it. */
  182. _S_setbuf(__x);
  183. return;
  184. }
  185. // node_start_pos is starting position of last_node.
  186. while (--__current_index >= 0)
  187. {
  188. if (!(__dirns & 1) /* Path turned left */)
  189. break;
  190. __current_node = __x._M_path_end[__current_index];
  191. __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node;
  192. // Otherwise we were in the right child. Thus we should pop
  193. // the concatenation node.
  194. __node_start_pos -= __c->_M_left->_M_size;
  195. __dirns >>= 1;
  196. }
  197. if (__current_index < 0)
  198. {
  199. // We underflowed the cache. Punt.
  200. _S_setcache(__x);
  201. return;
  202. }
  203. __current_node = __x._M_path_end[__current_index];
  204. __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node;
  205. // current_node is a concatenation node. We are positioned on the first
  206. // character in its right child.
  207. // node_start_pos is starting position of current_node.
  208. __node_start_pos += __c->_M_left->_M_size;
  209. __current_node = __c->_M_right;
  210. __x._M_path_end[++__current_index] = __current_node;
  211. __dirns |= 1;
  212. while (__detail::_S_concat == __current_node->_M_tag)
  213. {
  214. ++__current_index;
  215. if (int(_S_path_cache_len) == __current_index)
  216. {
  217. int __i;
  218. for (__i = 0; __i < int(_S_path_cache_len) - 1; __i++)
  219. __x._M_path_end[__i] = __x._M_path_end[__i+1];
  220. --__current_index;
  221. }
  222. __current_node =
  223. ((_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node)->_M_left;
  224. __x._M_path_end[__current_index] = __current_node;
  225. __dirns <<= 1;
  226. // node_start_pos is unchanged.
  227. }
  228. __x._M_leaf_index = __current_index;
  229. __x._M_leaf_pos = __node_start_pos;
  230. __x._M_path_directions = __dirns;
  231. _S_setbuf(__x);
  232. }
  233. template <class _CharT, class _Alloc>
  234. void
  235. _Rope_iterator_base<_CharT, _Alloc>::
  236. _M_incr(std::size_t __n)
  237. {
  238. _M_current_pos += __n;
  239. if (0 != _M_buf_ptr)
  240. {
  241. std::size_t __chars_left = _M_buf_end - _M_buf_ptr;
  242. if (__chars_left > __n)
  243. _M_buf_ptr += __n;
  244. else if (__chars_left == __n)
  245. {
  246. _M_buf_ptr += __n;
  247. _S_setcache_for_incr(*this);
  248. }
  249. else
  250. _M_buf_ptr = 0;
  251. }
  252. }
  253. template <class _CharT, class _Alloc>
  254. void
  255. _Rope_iterator_base<_CharT, _Alloc>::
  256. _M_decr(std::size_t __n)
  257. {
  258. if (0 != _M_buf_ptr)
  259. {
  260. std::size_t __chars_left = _M_buf_ptr - _M_buf_start;
  261. if (__chars_left >= __n)
  262. _M_buf_ptr -= __n;
  263. else
  264. _M_buf_ptr = 0;
  265. }
  266. _M_current_pos -= __n;
  267. }
  268. template <class _CharT, class _Alloc>
  269. void
  270. _Rope_iterator<_CharT, _Alloc>::
  271. _M_check()
  272. {
  273. if (_M_root_rope->_M_tree_ptr != this->_M_root)
  274. {
  275. // _Rope was modified. Get things fixed up.
  276. _RopeRep::_S_unref(this->_M_root);
  277. this->_M_root = _M_root_rope->_M_tree_ptr;
  278. _RopeRep::_S_ref(this->_M_root);
  279. this->_M_buf_ptr = 0;
  280. }
  281. }
  282. template <class _CharT, class _Alloc>
  283. inline
  284. _Rope_const_iterator<_CharT, _Alloc>::
  285. _Rope_const_iterator(const _Rope_iterator<_CharT, _Alloc>& __x)
  286. : _Rope_iterator_base<_CharT, _Alloc>(__x)
  287. { }
  288. template <class _CharT, class _Alloc>
  289. inline
  290. _Rope_iterator<_CharT, _Alloc>::
  291. _Rope_iterator(rope<_CharT, _Alloc>& __r, std::size_t __pos)
  292. : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos),
  293. _M_root_rope(&__r)
  294. { _RopeRep::_S_ref(this->_M_root); }
  295. template <class _CharT, class _Alloc>
  296. inline std::size_t
  297. rope<_CharT, _Alloc>::
  298. _S_char_ptr_len(const _CharT* __s)
  299. {
  300. const _CharT* __p = __s;
  301. while (!_S_is0(*__p))
  302. ++__p;
  303. return (__p - __s);
  304. }
  305. #ifndef __GC
  306. template <class _CharT, class _Alloc>
  307. inline void
  308. _Rope_RopeRep<_CharT, _Alloc>::
  309. _M_free_c_string()
  310. {
  311. _CharT* __cstr = _M_c_string;
  312. if (0 != __cstr)
  313. {
  314. std::size_t __size = this->_M_size + 1;
  315. std::_Destroy(__cstr, __cstr + __size, _M_get_allocator());
  316. this->_Data_deallocate(__cstr, __size);
  317. }
  318. }
  319. template <class _CharT, class _Alloc>
  320. inline void
  321. _Rope_RopeRep<_CharT, _Alloc>::
  322. _S_free_string(_CharT* __s, std::size_t __n, allocator_type& __a)
  323. {
  324. if (!_S_is_basic_char_type((_CharT*)0))
  325. std::_Destroy(__s, __s + __n, __a);
  326. // This has to be a static member, so this gets a bit messy
  327. __a.deallocate(__s,
  328. _Rope_RopeLeaf<_CharT, _Alloc>::_S_rounded_up_size(__n));
  329. }
  330. // There are several reasons for not doing this with virtual destructors
  331. // and a class specific delete operator:
  332. // - A class specific delete operator can't easily get access to
  333. // allocator instances if we need them.
  334. // - Any virtual function would need a 4 or byte vtable pointer;
  335. // this only requires a one byte tag per object.
  336. template <class _CharT, class _Alloc>
  337. void
  338. _Rope_RopeRep<_CharT, _Alloc>::
  339. _M_free_tree()
  340. {
  341. switch(_M_tag)
  342. {
  343. case __detail::_S_leaf:
  344. {
  345. _Rope_RopeLeaf<_CharT, _Alloc>* __l
  346. = (_Rope_RopeLeaf<_CharT, _Alloc>*)this;
  347. __l->_Rope_RopeLeaf<_CharT, _Alloc>::~_Rope_RopeLeaf();
  348. this->_L_deallocate(__l, 1);
  349. break;
  350. }
  351. case __detail::_S_concat:
  352. {
  353. _Rope_RopeConcatenation<_CharT,_Alloc>* __c
  354. = (_Rope_RopeConcatenation<_CharT, _Alloc>*)this;
  355. __c->_Rope_RopeConcatenation<_CharT, _Alloc>::
  356. ~_Rope_RopeConcatenation();
  357. this->_C_deallocate(__c, 1);
  358. break;
  359. }
  360. case __detail::_S_function:
  361. {
  362. _Rope_RopeFunction<_CharT, _Alloc>* __f
  363. = (_Rope_RopeFunction<_CharT, _Alloc>*)this;
  364. __f->_Rope_RopeFunction<_CharT, _Alloc>::~_Rope_RopeFunction();
  365. this->_F_deallocate(__f, 1);
  366. break;
  367. }
  368. case __detail::_S_substringfn:
  369. {
  370. _Rope_RopeSubstring<_CharT, _Alloc>* __ss =
  371. (_Rope_RopeSubstring<_CharT, _Alloc>*)this;
  372. __ss->_Rope_RopeSubstring<_CharT, _Alloc>::
  373. ~_Rope_RopeSubstring();
  374. this->_S_deallocate(__ss, 1);
  375. break;
  376. }
  377. }
  378. }
  379. #else
  380. template <class _CharT, class _Alloc>
  381. inline void
  382. _Rope_RopeRep<_CharT, _Alloc>::
  383. _S_free_string(const _CharT*, std::size_t, allocator_type)
  384. { }
  385. #endif
  386. // Concatenate a C string onto a leaf rope by copying the rope data.
  387. // Used for short ropes.
  388. template <class _CharT, class _Alloc>
  389. typename rope<_CharT, _Alloc>::_RopeLeaf*
  390. rope<_CharT, _Alloc>::
  391. _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter,
  392. std::size_t __len)
  393. {
  394. std::size_t __old_len = __r->_M_size;
  395. _CharT* __new_data = (_CharT*)
  396. rope::_Data_allocate(_S_rounded_up_size(__old_len + __len));
  397. _RopeLeaf* __result;
  398. uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
  399. uninitialized_copy_n(__iter, __len, __new_data + __old_len);
  400. _S_cond_store_eos(__new_data[__old_len + __len]);
  401. __try
  402. {
  403. __result = _S_new_RopeLeaf(__new_data, __old_len + __len,
  404. __r->_M_get_allocator());
  405. }
  406. __catch(...)
  407. {
  408. _RopeRep::__STL_FREE_STRING(__new_data, __old_len + __len,
  409. __r->_M_get_allocator());
  410. __throw_exception_again;
  411. }
  412. return __result;
  413. }
  414. #ifndef __GC
  415. // As above, but it's OK to clobber original if refcount is 1
  416. template <class _CharT, class _Alloc>
  417. typename rope<_CharT,_Alloc>::_RopeLeaf*
  418. rope<_CharT, _Alloc>::
  419. _S_destr_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter,
  420. std::size_t __len)
  421. {
  422. if (__r->_M_ref_count > 1)
  423. return _S_leaf_concat_char_iter(__r, __iter, __len);
  424. std::size_t __old_len = __r->_M_size;
  425. if (_S_allocated_capacity(__old_len) >= __old_len + __len)
  426. {
  427. // The space has been partially initialized for the standard
  428. // character types. But that doesn't matter for those types.
  429. uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len);
  430. if (_S_is_basic_char_type((_CharT*)0))
  431. _S_cond_store_eos(__r->_M_data[__old_len + __len]);
  432. else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string)
  433. {
  434. __r->_M_free_c_string();
  435. __r->_M_c_string = 0;
  436. }
  437. __r->_M_size = __old_len + __len;
  438. __r->_M_ref_count = 2;
  439. return __r;
  440. }
  441. else
  442. {
  443. _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len);
  444. return __result;
  445. }
  446. }
  447. #endif
  448. // Assumes left and right are not 0.
  449. // Does not increment (nor decrement on exception) child reference counts.
  450. // Result has ref count 1.
  451. template <class _CharT, class _Alloc>
  452. typename rope<_CharT, _Alloc>::_RopeRep*
  453. rope<_CharT, _Alloc>::
  454. _S_tree_concat(_RopeRep* __left, _RopeRep* __right)
  455. {
  456. using std::size_t;
  457. _RopeConcatenation* __result = _S_new_RopeConcatenation(__left, __right,
  458. __left->
  459. _M_get_allocator());
  460. size_t __depth = __result->_M_depth;
  461. if (__depth > 20
  462. && (__result->_M_size < 1000
  463. || __depth > size_t(__detail::_S_max_rope_depth)))
  464. {
  465. _RopeRep* __balanced;
  466. __try
  467. {
  468. __balanced = _S_balance(__result);
  469. __result->_M_unref_nonnil();
  470. }
  471. __catch(...)
  472. {
  473. rope::_C_deallocate(__result,1);
  474. __throw_exception_again;
  475. }
  476. // In case of exception, we need to deallocate
  477. // otherwise dangling result node. But caller
  478. // still owns its children. Thus unref is
  479. // inappropriate.
  480. return __balanced;
  481. }
  482. else
  483. return __result;
  484. }
  485. template <class _CharT, class _Alloc>
  486. typename rope<_CharT, _Alloc>::_RopeRep*
  487. rope<_CharT, _Alloc>::
  488. _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, std::size_t __slen,
  489. allocator_type& __a)
  490. {
  491. using std::size_t;
  492. _RopeRep* __result;
  493. if (0 == __slen)
  494. {
  495. _S_ref(__r);
  496. return __r;
  497. }
  498. if (0 == __r)
  499. return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
  500. if (__r->_M_tag == __detail::_S_leaf
  501. && __r->_M_size + __slen <= size_t(_S_copy_max))
  502. {
  503. __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
  504. return __result;
  505. }
  506. if (__detail::_S_concat == __r->_M_tag
  507. && __detail::_S_leaf == ((_RopeConcatenation*) __r)->_M_right->_M_tag)
  508. {
  509. _RopeLeaf* __right =
  510. (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right);
  511. if (__right->_M_size + __slen <= size_t(_S_copy_max))
  512. {
  513. _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left;
  514. _RopeRep* __nright =
  515. _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen);
  516. __left->_M_ref_nonnil();
  517. __try
  518. { __result = _S_tree_concat(__left, __nright); }
  519. __catch(...)
  520. {
  521. _S_unref(__left);
  522. _S_unref(__nright);
  523. __throw_exception_again;
  524. }
  525. return __result;
  526. }
  527. }
  528. _RopeRep* __nright = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
  529. __try
  530. {
  531. __r->_M_ref_nonnil();
  532. __result = _S_tree_concat(__r, __nright);
  533. }
  534. __catch(...)
  535. {
  536. _S_unref(__r);
  537. _S_unref(__nright);
  538. __throw_exception_again;
  539. }
  540. return __result;
  541. }
  542. #ifndef __GC
  543. template <class _CharT, class _Alloc>
  544. typename rope<_CharT,_Alloc>::_RopeRep*
  545. rope<_CharT,_Alloc>::
  546. _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s,
  547. std::size_t __slen, allocator_type& __a)
  548. {
  549. using std::size_t;
  550. _RopeRep* __result;
  551. if (0 == __r)
  552. return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
  553. size_t __count = __r->_M_ref_count;
  554. size_t __orig_size = __r->_M_size;
  555. if (__count > 1)
  556. return _S_concat_char_iter(__r, __s, __slen, __a);
  557. if (0 == __slen)
  558. {
  559. __r->_M_ref_count = 2; // One more than before
  560. return __r;
  561. }
  562. if (__orig_size + __slen <= size_t(_S_copy_max)
  563. && __detail::_S_leaf == __r->_M_tag)
  564. {
  565. __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s,
  566. __slen);
  567. return __result;
  568. }
  569. if (__detail::_S_concat == __r->_M_tag)
  570. {
  571. _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*)
  572. __r)->_M_right);
  573. if (__detail::_S_leaf == __right->_M_tag
  574. && __right->_M_size + __slen <= size_t(_S_copy_max))
  575. {
  576. _RopeRep* __new_right =
  577. _S_destr_leaf_concat_char_iter(__right, __s, __slen);
  578. if (__right == __new_right)
  579. __new_right->_M_ref_count = 1;
  580. else
  581. __right->_M_unref_nonnil();
  582. __r->_M_ref_count = 2; // One more than before.
  583. ((_RopeConcatenation*)__r)->_M_right = __new_right;
  584. __r->_M_size = __orig_size + __slen;
  585. if (0 != __r->_M_c_string)
  586. {
  587. __r->_M_free_c_string();
  588. __r->_M_c_string = 0;
  589. }
  590. return __r;
  591. }
  592. }
  593. _RopeRep* __right = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __a);
  594. __r->_M_ref_nonnil();
  595. __try
  596. { __result = _S_tree_concat(__r, __right); }
  597. __catch(...)
  598. {
  599. _S_unref(__r);
  600. _S_unref(__right);
  601. __throw_exception_again;
  602. }
  603. return __result;
  604. }
  605. #endif /* !__GC */
  606. template <class _CharT, class _Alloc>
  607. typename rope<_CharT, _Alloc>::_RopeRep*
  608. rope<_CharT, _Alloc>::
  609. _S_concat(_RopeRep* __left, _RopeRep* __right)
  610. {
  611. using std::size_t;
  612. if (0 == __left)
  613. {
  614. _S_ref(__right);
  615. return __right;
  616. }
  617. if (0 == __right)
  618. {
  619. __left->_M_ref_nonnil();
  620. return __left;
  621. }
  622. if (__detail::_S_leaf == __right->_M_tag)
  623. {
  624. if (__detail::_S_leaf == __left->_M_tag)
  625. {
  626. if (__right->_M_size + __left->_M_size <= size_t(_S_copy_max))
  627. return _S_leaf_concat_char_iter((_RopeLeaf*)__left,
  628. ((_RopeLeaf*)__right)->_M_data,
  629. __right->_M_size);
  630. }
  631. else if (__detail::_S_concat == __left->_M_tag
  632. && __detail::_S_leaf == ((_RopeConcatenation*)
  633. __left)->_M_right->_M_tag)
  634. {
  635. _RopeLeaf* __leftright =
  636. (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right);
  637. if (__leftright->_M_size
  638. + __right->_M_size <= size_t(_S_copy_max))
  639. {
  640. _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left;
  641. _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright,
  642. ((_RopeLeaf*)
  643. __right)->
  644. _M_data,
  645. __right->_M_size);
  646. __leftleft->_M_ref_nonnil();
  647. __try
  648. { return(_S_tree_concat(__leftleft, __rest)); }
  649. __catch(...)
  650. {
  651. _S_unref(__leftleft);
  652. _S_unref(__rest);
  653. __throw_exception_again;
  654. }
  655. }
  656. }
  657. }
  658. __left->_M_ref_nonnil();
  659. __right->_M_ref_nonnil();
  660. __try
  661. { return(_S_tree_concat(__left, __right)); }
  662. __catch(...)
  663. {
  664. _S_unref(__left);
  665. _S_unref(__right);
  666. __throw_exception_again;
  667. }
  668. }
  669. template <class _CharT, class _Alloc>
  670. typename rope<_CharT, _Alloc>::_RopeRep*
  671. rope<_CharT, _Alloc>::
  672. _S_substring(_RopeRep* __base, std::size_t __start, std::size_t __endp1)
  673. {
  674. using std::size_t;
  675. if (0 == __base)
  676. return 0;
  677. size_t __len = __base->_M_size;
  678. size_t __adj_endp1;
  679. const size_t __lazy_threshold = 128;
  680. if (__endp1 >= __len)
  681. {
  682. if (0 == __start)
  683. {
  684. __base->_M_ref_nonnil();
  685. return __base;
  686. }
  687. else
  688. __adj_endp1 = __len;
  689. }
  690. else
  691. __adj_endp1 = __endp1;
  692. switch(__base->_M_tag)
  693. {
  694. case __detail::_S_concat:
  695. {
  696. _RopeConcatenation* __c = (_RopeConcatenation*)__base;
  697. _RopeRep* __left = __c->_M_left;
  698. _RopeRep* __right = __c->_M_right;
  699. size_t __left_len = __left->_M_size;
  700. _RopeRep* __result;
  701. if (__adj_endp1 <= __left_len)
  702. return _S_substring(__left, __start, __endp1);
  703. else if (__start >= __left_len)
  704. return _S_substring(__right, __start - __left_len,
  705. __adj_endp1 - __left_len);
  706. _Self_destruct_ptr __left_result(_S_substring(__left,
  707. __start,
  708. __left_len));
  709. _Self_destruct_ptr __right_result(_S_substring(__right, 0,
  710. __endp1
  711. - __left_len));
  712. __result = _S_concat(__left_result, __right_result);
  713. return __result;
  714. }
  715. case __detail::_S_leaf:
  716. {
  717. _RopeLeaf* __l = (_RopeLeaf*)__base;
  718. _RopeLeaf* __result;
  719. size_t __result_len;
  720. if (__start >= __adj_endp1)
  721. return 0;
  722. __result_len = __adj_endp1 - __start;
  723. if (__result_len > __lazy_threshold)
  724. goto lazy;
  725. #ifdef __GC
  726. const _CharT* __section = __l->_M_data + __start;
  727. __result = _S_new_RopeLeaf(__section, __result_len,
  728. __base->_M_get_allocator());
  729. __result->_M_c_string = 0; // Not eos terminated.
  730. #else
  731. // We should sometimes create substring node instead.
  732. __result = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__l->_M_data + __start,
  733. __result_len,
  734. __base->
  735. _M_get_allocator());
  736. #endif
  737. return __result;
  738. }
  739. case __detail::_S_substringfn:
  740. // Avoid introducing multiple layers of substring nodes.
  741. {
  742. _RopeSubstring* __old = (_RopeSubstring*)__base;
  743. size_t __result_len;
  744. if (__start >= __adj_endp1)
  745. return 0;
  746. __result_len = __adj_endp1 - __start;
  747. if (__result_len > __lazy_threshold)
  748. {
  749. _RopeSubstring* __result =
  750. _S_new_RopeSubstring(__old->_M_base,
  751. __start + __old->_M_start,
  752. __adj_endp1 - __start,
  753. __base->_M_get_allocator());
  754. return __result;
  755. } // *** else fall through: ***
  756. }
  757. case __detail::_S_function:
  758. {
  759. _RopeFunction* __f = (_RopeFunction*)__base;
  760. _CharT* __section;
  761. size_t __result_len;
  762. if (__start >= __adj_endp1)
  763. return 0;
  764. __result_len = __adj_endp1 - __start;
  765. if (__result_len > __lazy_threshold)
  766. goto lazy;
  767. __section = (_CharT*)
  768. rope::_Data_allocate(_S_rounded_up_size(__result_len));
  769. __try
  770. { (*(__f->_M_fn))(__start, __result_len, __section); }
  771. __catch(...)
  772. {
  773. _RopeRep::__STL_FREE_STRING(__section, __result_len,
  774. __base->_M_get_allocator());
  775. __throw_exception_again;
  776. }
  777. _S_cond_store_eos(__section[__result_len]);
  778. return _S_new_RopeLeaf(__section, __result_len,
  779. __base->_M_get_allocator());
  780. }
  781. }
  782. lazy:
  783. {
  784. // Create substring node.
  785. return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start,
  786. __base->_M_get_allocator());
  787. }
  788. }
  789. template<class _CharT>
  790. class _Rope_flatten_char_consumer
  791. : public _Rope_char_consumer<_CharT>
  792. {
  793. private:
  794. _CharT* _M_buf_ptr;
  795. public:
  796. _Rope_flatten_char_consumer(_CharT* __buffer)
  797. { _M_buf_ptr = __buffer; }
  798. ~_Rope_flatten_char_consumer() {}
  799. bool
  800. operator()(const _CharT* __leaf, std::size_t __n)
  801. {
  802. uninitialized_copy_n(__leaf, __n, _M_buf_ptr);
  803. _M_buf_ptr += __n;
  804. return true;
  805. }
  806. };
  807. template<class _CharT>
  808. class _Rope_find_char_char_consumer
  809. : public _Rope_char_consumer<_CharT>
  810. {
  811. private:
  812. _CharT _M_pattern;
  813. public:
  814. std::size_t _M_count; // Number of nonmatching characters
  815. _Rope_find_char_char_consumer(_CharT __p)
  816. : _M_pattern(__p), _M_count(0) {}
  817. ~_Rope_find_char_char_consumer() {}
  818. bool
  819. operator()(const _CharT* __leaf, std::size_t __n)
  820. {
  821. std::size_t __i;
  822. for (__i = 0; __i < __n; __i++)
  823. {
  824. if (__leaf[__i] == _M_pattern)
  825. {
  826. _M_count += __i;
  827. return false;
  828. }
  829. }
  830. _M_count += __n; return true;
  831. }
  832. };
  833. template<class _CharT, class _Traits>
  834. // Here _CharT is both the stream and rope character type.
  835. class _Rope_insert_char_consumer
  836. : public _Rope_char_consumer<_CharT>
  837. {
  838. private:
  839. typedef std::basic_ostream<_CharT,_Traits> _Insert_ostream;
  840. _Insert_ostream& _M_o;
  841. public:
  842. _Rope_insert_char_consumer(_Insert_ostream& __writer)
  843. : _M_o(__writer) {}
  844. ~_Rope_insert_char_consumer() { }
  845. // Caller is presumed to own the ostream
  846. bool operator() (const _CharT* __leaf, std::size_t __n);
  847. // Returns true to continue traversal.
  848. };
  849. template<class _CharT, class _Traits>
  850. bool
  851. _Rope_insert_char_consumer<_CharT, _Traits>::
  852. operator()(const _CharT* __leaf, std::size_t __n)
  853. {
  854. std::size_t __i;
  855. // We assume that formatting is set up correctly for each element.
  856. for (__i = 0; __i < __n; __i++)
  857. _M_o.put(__leaf[__i]);
  858. return true;
  859. }
  860. template <class _CharT, class _Alloc>
  861. bool
  862. rope<_CharT, _Alloc>::
  863. _S_apply_to_pieces(_Rope_char_consumer<_CharT>& __c, const _RopeRep* __r,
  864. std::size_t __begin, std::size_t __end)
  865. {
  866. using std::size_t;
  867. if (0 == __r)
  868. return true;
  869. switch(__r->_M_tag)
  870. {
  871. case __detail::_S_concat:
  872. {
  873. _RopeConcatenation* __conc = (_RopeConcatenation*)__r;
  874. _RopeRep* __left = __conc->_M_left;
  875. size_t __left_len = __left->_M_size;
  876. if (__begin < __left_len)
  877. {
  878. size_t __left_end = std::min(__left_len, __end);
  879. if (!_S_apply_to_pieces(__c, __left, __begin, __left_end))
  880. return false;
  881. }
  882. if (__end > __left_len)
  883. {
  884. _RopeRep* __right = __conc->_M_right;
  885. size_t __right_start = std::max(__left_len, __begin);
  886. if (!_S_apply_to_pieces(__c, __right,
  887. __right_start - __left_len,
  888. __end - __left_len))
  889. return false;
  890. }
  891. }
  892. return true;
  893. case __detail::_S_leaf:
  894. {
  895. _RopeLeaf* __l = (_RopeLeaf*)__r;
  896. return __c(__l->_M_data + __begin, __end - __begin);
  897. }
  898. case __detail::_S_function:
  899. case __detail::_S_substringfn:
  900. {
  901. _RopeFunction* __f = (_RopeFunction*)__r;
  902. size_t __len = __end - __begin;
  903. bool __result;
  904. _CharT* __buffer =
  905. (_CharT*)_Alloc().allocate(__len * sizeof(_CharT));
  906. __try
  907. {
  908. (*(__f->_M_fn))(__begin, __len, __buffer);
  909. __result = __c(__buffer, __len);
  910. _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
  911. }
  912. __catch(...)
  913. {
  914. _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
  915. __throw_exception_again;
  916. }
  917. return __result;
  918. }
  919. default:
  920. return false;
  921. }
  922. }
  923. template<class _CharT, class _Traits>
  924. inline void
  925. _Rope_fill(std::basic_ostream<_CharT, _Traits>& __o, std::size_t __n)
  926. {
  927. char __f = __o.fill();
  928. std::size_t __i;
  929. for (__i = 0; __i < __n; __i++)
  930. __o.put(__f);
  931. }
  932. template <class _CharT>
  933. inline bool
  934. _Rope_is_simple(_CharT*)
  935. { return false; }
  936. inline bool
  937. _Rope_is_simple(char*)
  938. { return true; }
  939. inline bool
  940. _Rope_is_simple(wchar_t*)
  941. { return true; }
  942. template<class _CharT, class _Traits, class _Alloc>
  943. std::basic_ostream<_CharT, _Traits>&
  944. operator<<(std::basic_ostream<_CharT, _Traits>& __o,
  945. const rope<_CharT, _Alloc>& __r)
  946. {
  947. using std::size_t;
  948. size_t __w = __o.width();
  949. bool __left = bool(__o.flags() & std::ios::left);
  950. size_t __pad_len;
  951. size_t __rope_len = __r.size();
  952. _Rope_insert_char_consumer<_CharT, _Traits> __c(__o);
  953. bool __is_simple = _Rope_is_simple((_CharT*)0);
  954. if (__rope_len < __w)
  955. __pad_len = __w - __rope_len;
  956. else
  957. __pad_len = 0;
  958. if (!__is_simple)
  959. __o.width(__w / __rope_len);
  960. __try
  961. {
  962. if (__is_simple && !__left && __pad_len > 0)
  963. _Rope_fill(__o, __pad_len);
  964. __r.apply_to_pieces(0, __r.size(), __c);
  965. if (__is_simple && __left && __pad_len > 0)
  966. _Rope_fill(__o, __pad_len);
  967. if (!__is_simple)
  968. __o.width(__w);
  969. }
  970. __catch(...)
  971. {
  972. if (!__is_simple)
  973. __o.width(__w);
  974. __throw_exception_again;
  975. }
  976. return __o;
  977. }
  978. template <class _CharT, class _Alloc>
  979. _CharT*
  980. rope<_CharT, _Alloc>::
  981. _S_flatten(_RopeRep* __r, std::size_t __start, std::size_t __len,
  982. _CharT* __buffer)
  983. {
  984. _Rope_flatten_char_consumer<_CharT> __c(__buffer);
  985. _S_apply_to_pieces(__c, __r, __start, __start + __len);
  986. return(__buffer + __len);
  987. }
  988. template <class _CharT, class _Alloc>
  989. std::size_t
  990. rope<_CharT, _Alloc>::
  991. find(_CharT __pattern, std::size_t __start) const
  992. {
  993. _Rope_find_char_char_consumer<_CharT> __c(__pattern);
  994. _S_apply_to_pieces(__c, this->_M_tree_ptr, __start, size());
  995. size_type __result_pos = __start + __c._M_count;
  996. #ifndef __STL_OLD_ROPE_SEMANTICS
  997. if (__result_pos == size())
  998. __result_pos = npos;
  999. #endif
  1000. return __result_pos;
  1001. }
  1002. template <class _CharT, class _Alloc>
  1003. _CharT*
  1004. rope<_CharT, _Alloc>::
  1005. _S_flatten(_RopeRep* __r, _CharT* __buffer)
  1006. {
  1007. if (0 == __r)
  1008. return __buffer;
  1009. switch(__r->_M_tag)
  1010. {
  1011. case __detail::_S_concat:
  1012. {
  1013. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1014. _RopeRep* __left = __c->_M_left;
  1015. _RopeRep* __right = __c->_M_right;
  1016. _CharT* __rest = _S_flatten(__left, __buffer);
  1017. return _S_flatten(__right, __rest);
  1018. }
  1019. case __detail::_S_leaf:
  1020. {
  1021. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1022. return copy_n(__l->_M_data, __l->_M_size, __buffer).second;
  1023. }
  1024. case __detail::_S_function:
  1025. case __detail::_S_substringfn:
  1026. // We don't yet do anything with substring nodes.
  1027. // This needs to be fixed before ropefiles will work well.
  1028. {
  1029. _RopeFunction* __f = (_RopeFunction*)__r;
  1030. (*(__f->_M_fn))(0, __f->_M_size, __buffer);
  1031. return __buffer + __f->_M_size;
  1032. }
  1033. default:
  1034. return 0;
  1035. }
  1036. }
  1037. // This needs work for _CharT != char
  1038. template <class _CharT, class _Alloc>
  1039. void
  1040. rope<_CharT, _Alloc>::
  1041. _S_dump(_RopeRep* __r, int __indent)
  1042. {
  1043. using std::printf;
  1044. for (int __i = 0; __i < __indent; __i++)
  1045. putchar(' ');
  1046. if (0 == __r)
  1047. {
  1048. printf("NULL\n");
  1049. return;
  1050. }
  1051. if (__detail::_S_concat == __r->_M_tag)
  1052. {
  1053. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1054. _RopeRep* __left = __c->_M_left;
  1055. _RopeRep* __right = __c->_M_right;
  1056. #ifdef __GC
  1057. printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
  1058. __r, __r->_M_depth, __r->_M_size,
  1059. __r->_M_is_balanced? "" : "not");
  1060. #else
  1061. printf("Concatenation %p (rc = %ld, depth = %d, "
  1062. "len = %ld, %s balanced)\n",
  1063. __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size,
  1064. __r->_M_is_balanced? "" : "not");
  1065. #endif
  1066. _S_dump(__left, __indent + 2);
  1067. _S_dump(__right, __indent + 2);
  1068. return;
  1069. }
  1070. else
  1071. {
  1072. const char* __kind;
  1073. switch (__r->_M_tag)
  1074. {
  1075. case __detail::_S_leaf:
  1076. __kind = "Leaf";
  1077. break;
  1078. case __detail::_S_function:
  1079. __kind = "Function";
  1080. break;
  1081. case __detail::_S_substringfn:
  1082. __kind = "Function representing substring";
  1083. break;
  1084. default:
  1085. __kind = "(corrupted kind field!)";
  1086. }
  1087. #ifdef __GC
  1088. printf("%s %p (depth = %d, len = %ld) ",
  1089. __kind, __r, __r->_M_depth, __r->_M_size);
  1090. #else
  1091. printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
  1092. __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size);
  1093. #endif
  1094. if (_S_is_one_byte_char_type((_CharT*)0))
  1095. {
  1096. const int __max_len = 40;
  1097. _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len));
  1098. _CharT __buffer[__max_len + 1];
  1099. bool __too_big = __r->_M_size > __prefix->_M_size;
  1100. _S_flatten(__prefix, __buffer);
  1101. __buffer[__prefix->_M_size] = _S_eos((_CharT*)0);
  1102. printf("%s%s\n", (char*)__buffer,
  1103. __too_big? "...\n" : "\n");
  1104. }
  1105. else
  1106. printf("\n");
  1107. }
  1108. }
  1109. template <class _CharT, class _Alloc>
  1110. const unsigned long
  1111. rope<_CharT, _Alloc>::
  1112. _S_min_len[int(__detail::_S_max_rope_depth) + 1] = {
  1113. /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21,
  1114. /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377,
  1115. /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181,
  1116. /* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368,
  1117. /* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811,
  1118. /* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309,
  1119. /* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352,
  1120. /* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155,
  1121. /* 39 */165580141, /* 40 */267914296, /* 41 */433494437,
  1122. /* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903,
  1123. /* 45 */2971215073u };
  1124. // These are Fibonacci numbers < 2**32.
  1125. template <class _CharT, class _Alloc>
  1126. typename rope<_CharT, _Alloc>::_RopeRep*
  1127. rope<_CharT, _Alloc>::
  1128. _S_balance(_RopeRep* __r)
  1129. {
  1130. _RopeRep* __forest[int(__detail::_S_max_rope_depth) + 1];
  1131. _RopeRep* __result = 0;
  1132. int __i;
  1133. // Invariant:
  1134. // The concatenation of forest in descending order is equal to __r.
  1135. // __forest[__i]._M_size >= _S_min_len[__i]
  1136. // __forest[__i]._M_depth = __i
  1137. // References from forest are included in refcount.
  1138. for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
  1139. __forest[__i] = 0;
  1140. __try
  1141. {
  1142. _S_add_to_forest(__r, __forest);
  1143. for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
  1144. if (0 != __forest[__i])
  1145. {
  1146. #ifndef __GC
  1147. _Self_destruct_ptr __old(__result);
  1148. #endif
  1149. __result = _S_concat(__forest[__i], __result);
  1150. __forest[__i]->_M_unref_nonnil();
  1151. #if !defined(__GC) && __cpp_exceptions
  1152. __forest[__i] = 0;
  1153. #endif
  1154. }
  1155. }
  1156. __catch(...)
  1157. {
  1158. for(__i = 0; __i <= int(__detail::_S_max_rope_depth); __i++)
  1159. _S_unref(__forest[__i]);
  1160. __throw_exception_again;
  1161. }
  1162. if (__result->_M_depth > int(__detail::_S_max_rope_depth))
  1163. std::__throw_length_error(__N("rope::_S_balance"));
  1164. return(__result);
  1165. }
  1166. template <class _CharT, class _Alloc>
  1167. void
  1168. rope<_CharT, _Alloc>::
  1169. _S_add_to_forest(_RopeRep* __r, _RopeRep** __forest)
  1170. {
  1171. if (__r->_M_is_balanced)
  1172. {
  1173. _S_add_leaf_to_forest(__r, __forest);
  1174. return;
  1175. }
  1176. {
  1177. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1178. _S_add_to_forest(__c->_M_left, __forest);
  1179. _S_add_to_forest(__c->_M_right, __forest);
  1180. }
  1181. }
  1182. template <class _CharT, class _Alloc>
  1183. void
  1184. rope<_CharT, _Alloc>::
  1185. _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest)
  1186. {
  1187. _RopeRep* __insertee; // included in refcount
  1188. _RopeRep* __too_tiny = 0; // included in refcount
  1189. int __i; // forest[0..__i-1] is empty
  1190. std::size_t __s = __r->_M_size;
  1191. for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i)
  1192. {
  1193. if (0 != __forest[__i])
  1194. {
  1195. #ifndef __GC
  1196. _Self_destruct_ptr __old(__too_tiny);
  1197. #endif
  1198. __too_tiny = _S_concat_and_set_balanced(__forest[__i],
  1199. __too_tiny);
  1200. __forest[__i]->_M_unref_nonnil();
  1201. __forest[__i] = 0;
  1202. }
  1203. }
  1204. {
  1205. #ifndef __GC
  1206. _Self_destruct_ptr __old(__too_tiny);
  1207. #endif
  1208. __insertee = _S_concat_and_set_balanced(__too_tiny, __r);
  1209. }
  1210. // Too_tiny dead, and no longer included in refcount.
  1211. // Insertee is live and included.
  1212. for (;; ++__i)
  1213. {
  1214. if (0 != __forest[__i])
  1215. {
  1216. #ifndef __GC
  1217. _Self_destruct_ptr __old(__insertee);
  1218. #endif
  1219. __insertee = _S_concat_and_set_balanced(__forest[__i],
  1220. __insertee);
  1221. __forest[__i]->_M_unref_nonnil();
  1222. __forest[__i] = 0;
  1223. }
  1224. if (__i == int(__detail::_S_max_rope_depth)
  1225. || __insertee->_M_size < _S_min_len[__i+1])
  1226. {
  1227. __forest[__i] = __insertee;
  1228. // refcount is OK since __insertee is now dead.
  1229. return;
  1230. }
  1231. }
  1232. }
  1233. template <class _CharT, class _Alloc>
  1234. _CharT
  1235. rope<_CharT, _Alloc>::
  1236. _S_fetch(_RopeRep* __r, size_type __i)
  1237. {
  1238. __GC_CONST _CharT* __cstr = __r->_M_c_string;
  1239. if (0 != __cstr)
  1240. return __cstr[__i];
  1241. for(;;)
  1242. {
  1243. switch(__r->_M_tag)
  1244. {
  1245. case __detail::_S_concat:
  1246. {
  1247. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1248. _RopeRep* __left = __c->_M_left;
  1249. std::size_t __left_len = __left->_M_size;
  1250. if (__i >= __left_len)
  1251. {
  1252. __i -= __left_len;
  1253. __r = __c->_M_right;
  1254. }
  1255. else
  1256. __r = __left;
  1257. }
  1258. break;
  1259. case __detail::_S_leaf:
  1260. {
  1261. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1262. return __l->_M_data[__i];
  1263. }
  1264. case __detail::_S_function:
  1265. case __detail::_S_substringfn:
  1266. {
  1267. _RopeFunction* __f = (_RopeFunction*)__r;
  1268. _CharT __result;
  1269. (*(__f->_M_fn))(__i, 1, &__result);
  1270. return __result;
  1271. }
  1272. }
  1273. }
  1274. }
  1275. #ifndef __GC
  1276. // Return a uniquely referenced character slot for the given
  1277. // position, or 0 if that's not possible.
  1278. template <class _CharT, class _Alloc>
  1279. _CharT*
  1280. rope<_CharT, _Alloc>::
  1281. _S_fetch_ptr(_RopeRep* __r, size_type __i)
  1282. {
  1283. _RopeRep* __clrstack[__detail::_S_max_rope_depth];
  1284. std::size_t __csptr = 0;
  1285. for(;;)
  1286. {
  1287. if (__r->_M_ref_count > 1)
  1288. return 0;
  1289. switch(__r->_M_tag)
  1290. {
  1291. case __detail::_S_concat:
  1292. {
  1293. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1294. _RopeRep* __left = __c->_M_left;
  1295. std::size_t __left_len = __left->_M_size;
  1296. if (__c->_M_c_string != 0)
  1297. __clrstack[__csptr++] = __c;
  1298. if (__i >= __left_len)
  1299. {
  1300. __i -= __left_len;
  1301. __r = __c->_M_right;
  1302. }
  1303. else
  1304. __r = __left;
  1305. }
  1306. break;
  1307. case __detail::_S_leaf:
  1308. {
  1309. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1310. if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0)
  1311. __clrstack[__csptr++] = __l;
  1312. while (__csptr > 0)
  1313. {
  1314. -- __csptr;
  1315. _RopeRep* __d = __clrstack[__csptr];
  1316. __d->_M_free_c_string();
  1317. __d->_M_c_string = 0;
  1318. }
  1319. return __l->_M_data + __i;
  1320. }
  1321. case __detail::_S_function:
  1322. case __detail::_S_substringfn:
  1323. return 0;
  1324. }
  1325. }
  1326. }
  1327. #endif /* __GC */
  1328. // The following could be implemented trivially using
  1329. // lexicographical_compare_3way.
  1330. // We do a little more work to avoid dealing with rope iterators for
  1331. // flat strings.
  1332. template <class _CharT, class _Alloc>
  1333. int
  1334. rope<_CharT, _Alloc>::
  1335. _S_compare (const _RopeRep* __left, const _RopeRep* __right)
  1336. {
  1337. std::size_t __left_len;
  1338. std::size_t __right_len;
  1339. if (0 == __right)
  1340. return 0 != __left;
  1341. if (0 == __left)
  1342. return -1;
  1343. __left_len = __left->_M_size;
  1344. __right_len = __right->_M_size;
  1345. if (__detail::_S_leaf == __left->_M_tag)
  1346. {
  1347. _RopeLeaf* __l = (_RopeLeaf*) __left;
  1348. if (__detail::_S_leaf == __right->_M_tag)
  1349. {
  1350. _RopeLeaf* __r = (_RopeLeaf*) __right;
  1351. return lexicographical_compare_3way(__l->_M_data,
  1352. __l->_M_data + __left_len,
  1353. __r->_M_data, __r->_M_data
  1354. + __right_len);
  1355. }
  1356. else
  1357. {
  1358. const_iterator __rstart(__right, 0);
  1359. const_iterator __rend(__right, __right_len);
  1360. return lexicographical_compare_3way(__l->_M_data, __l->_M_data
  1361. + __left_len,
  1362. __rstart, __rend);
  1363. }
  1364. }
  1365. else
  1366. {
  1367. const_iterator __lstart(__left, 0);
  1368. const_iterator __lend(__left, __left_len);
  1369. if (__detail::_S_leaf == __right->_M_tag)
  1370. {
  1371. _RopeLeaf* __r = (_RopeLeaf*) __right;
  1372. return lexicographical_compare_3way(__lstart, __lend,
  1373. __r->_M_data, __r->_M_data
  1374. + __right_len);
  1375. }
  1376. else
  1377. {
  1378. const_iterator __rstart(__right, 0);
  1379. const_iterator __rend(__right, __right_len);
  1380. return lexicographical_compare_3way(__lstart, __lend,
  1381. __rstart, __rend);
  1382. }
  1383. }
  1384. }
  1385. // Assignment to reference proxies.
  1386. template <class _CharT, class _Alloc>
  1387. _Rope_char_ref_proxy<_CharT, _Alloc>&
  1388. _Rope_char_ref_proxy<_CharT, _Alloc>::
  1389. operator=(_CharT __c)
  1390. {
  1391. _RopeRep* __old = _M_root->_M_tree_ptr;
  1392. #ifndef __GC
  1393. // First check for the case in which everything is uniquely
  1394. // referenced. In that case we can do this destructively.
  1395. _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos);
  1396. if (0 != __ptr)
  1397. {
  1398. *__ptr = __c;
  1399. return *this;
  1400. }
  1401. #endif
  1402. _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos));
  1403. _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1,
  1404. __old->_M_size));
  1405. typename _RopeRep::allocator_type __a = _M_root->_M_get_allocator();
  1406. _Self_destruct_ptr __result_left(_My_rope::
  1407. _S_destr_concat_char_iter(__left,
  1408. &__c, 1,
  1409. __a));
  1410. _RopeRep* __result = _My_rope::_S_concat(__result_left, __right);
  1411. #ifndef __GC
  1412. _RopeRep::_S_unref(__old);
  1413. #endif
  1414. _M_root->_M_tree_ptr = __result;
  1415. return *this;
  1416. }
  1417. template <class _CharT, class _Alloc>
  1418. inline _Rope_char_ref_proxy<_CharT, _Alloc>::
  1419. operator _CharT() const
  1420. {
  1421. if (_M_current_valid)
  1422. return _M_current;
  1423. else
  1424. return _My_rope::_S_fetch(_M_root->_M_tree_ptr, _M_pos);
  1425. }
  1426. template <class _CharT, class _Alloc>
  1427. _Rope_char_ptr_proxy<_CharT, _Alloc>
  1428. _Rope_char_ref_proxy<_CharT, _Alloc>::
  1429. operator&() const
  1430. { return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); }
  1431. template <class _CharT, class _Alloc>
  1432. rope<_CharT, _Alloc>::
  1433. rope(std::size_t __n, _CharT __c, const allocator_type& __a)
  1434. : _Base(__a)
  1435. {
  1436. using std::__uninitialized_fill_n_a;
  1437. rope<_CharT,_Alloc> __result;
  1438. const std::size_t __exponentiate_threshold = 32;
  1439. std::size_t __exponent;
  1440. std::size_t __rest;
  1441. _CharT* __rest_buffer;
  1442. _RopeRep* __remainder;
  1443. rope<_CharT, _Alloc> __remainder_rope;
  1444. if (0 == __n)
  1445. return;
  1446. __exponent = __n / __exponentiate_threshold;
  1447. __rest = __n % __exponentiate_threshold;
  1448. if (0 == __rest)
  1449. __remainder = 0;
  1450. else
  1451. {
  1452. __rest_buffer = this->_Data_allocate(_S_rounded_up_size(__rest));
  1453. __uninitialized_fill_n_a(__rest_buffer, __rest, __c,
  1454. _M_get_allocator());
  1455. _S_cond_store_eos(__rest_buffer[__rest]);
  1456. __try
  1457. { __remainder = _S_new_RopeLeaf(__rest_buffer, __rest,
  1458. _M_get_allocator()); }
  1459. __catch(...)
  1460. {
  1461. _RopeRep::__STL_FREE_STRING(__rest_buffer, __rest,
  1462. _M_get_allocator());
  1463. __throw_exception_again;
  1464. }
  1465. }
  1466. __remainder_rope._M_tree_ptr = __remainder;
  1467. if (__exponent != 0)
  1468. {
  1469. _CharT* __base_buffer =
  1470. this->_Data_allocate(_S_rounded_up_size(__exponentiate_threshold));
  1471. _RopeLeaf* __base_leaf;
  1472. rope __base_rope;
  1473. __uninitialized_fill_n_a(__base_buffer, __exponentiate_threshold, __c,
  1474. _M_get_allocator());
  1475. _S_cond_store_eos(__base_buffer[__exponentiate_threshold]);
  1476. __try
  1477. {
  1478. __base_leaf = _S_new_RopeLeaf(__base_buffer,
  1479. __exponentiate_threshold,
  1480. _M_get_allocator());
  1481. }
  1482. __catch(...)
  1483. {
  1484. _RopeRep::__STL_FREE_STRING(__base_buffer,
  1485. __exponentiate_threshold,
  1486. _M_get_allocator());
  1487. __throw_exception_again;
  1488. }
  1489. __base_rope._M_tree_ptr = __base_leaf;
  1490. if (1 == __exponent)
  1491. __result = __base_rope;
  1492. else
  1493. __result = power(__base_rope, __exponent,
  1494. _Rope_Concat_fn<_CharT, _Alloc>());
  1495. if (0 != __remainder)
  1496. __result += __remainder_rope;
  1497. }
  1498. else
  1499. __result = __remainder_rope;
  1500. this->_M_tree_ptr = __result._M_tree_ptr;
  1501. this->_M_tree_ptr->_M_ref_nonnil();
  1502. }
  1503. template<class _CharT, class _Alloc>
  1504. _CharT
  1505. rope<_CharT, _Alloc>::_S_empty_c_str[1];
  1506. template<class _CharT, class _Alloc>
  1507. const _CharT*
  1508. rope<_CharT, _Alloc>::
  1509. c_str() const
  1510. {
  1511. if (0 == this->_M_tree_ptr)
  1512. {
  1513. _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant,
  1514. // but probably fast.
  1515. return _S_empty_c_str;
  1516. }
  1517. __gthread_mutex_lock (&this->_M_tree_ptr->_M_c_string_lock);
  1518. __GC_CONST _CharT* __result = this->_M_tree_ptr->_M_c_string;
  1519. if (0 == __result)
  1520. {
  1521. std::size_t __s = size();
  1522. __result = this->_Data_allocate(__s + 1);
  1523. _S_flatten(this->_M_tree_ptr, __result);
  1524. __result[__s] = _S_eos((_CharT*)0);
  1525. this->_M_tree_ptr->_M_c_string = __result;
  1526. }
  1527. __gthread_mutex_unlock (&this->_M_tree_ptr->_M_c_string_lock);
  1528. return(__result);
  1529. }
  1530. template<class _CharT, class _Alloc>
  1531. const _CharT* rope<_CharT, _Alloc>::
  1532. replace_with_c_str()
  1533. {
  1534. if (0 == this->_M_tree_ptr)
  1535. {
  1536. _S_empty_c_str[0] = _S_eos((_CharT*)0);
  1537. return _S_empty_c_str;
  1538. }
  1539. __GC_CONST _CharT* __old_c_string = this->_M_tree_ptr->_M_c_string;
  1540. if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag
  1541. && 0 != __old_c_string)
  1542. return(__old_c_string);
  1543. std::size_t __s = size();
  1544. _CharT* __result = this->_Data_allocate(_S_rounded_up_size(__s));
  1545. _S_flatten(this->_M_tree_ptr, __result);
  1546. __result[__s] = _S_eos((_CharT*)0);
  1547. this->_M_tree_ptr->_M_unref_nonnil();
  1548. this->_M_tree_ptr = _S_new_RopeLeaf(__result, __s,
  1549. this->_M_get_allocator());
  1550. return(__result);
  1551. }
  1552. // Algorithm specializations. More should be added.
  1553. template<class _Rope_iterator> // was templated on CharT and Alloc
  1554. void // VC++ workaround
  1555. _Rope_rotate(_Rope_iterator __first,
  1556. _Rope_iterator __middle,
  1557. _Rope_iterator __last)
  1558. {
  1559. typedef typename _Rope_iterator::value_type _CharT;
  1560. typedef typename _Rope_iterator::_allocator_type _Alloc;
  1561. rope<_CharT, _Alloc>& __r(__first.container());
  1562. rope<_CharT, _Alloc> __prefix = __r.substr(0, __first.index());
  1563. rope<_CharT, _Alloc> __suffix =
  1564. __r.substr(__last.index(), __r.size() - __last.index());
  1565. rope<_CharT, _Alloc> __part1 =
  1566. __r.substr(__middle.index(), __last.index() - __middle.index());
  1567. rope<_CharT, _Alloc> __part2 =
  1568. __r.substr(__first.index(), __middle.index() - __first.index());
  1569. __r = __prefix;
  1570. __r += __part1;
  1571. __r += __part2;
  1572. __r += __suffix;
  1573. }
  1574. #if !defined(__GNUC__)
  1575. // Appears to confuse g++
  1576. inline void
  1577. rotate(_Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __first,
  1578. _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __middle,
  1579. _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __last)
  1580. { _Rope_rotate(__first, __middle, __last); }
  1581. #endif
  1582. # if 0
  1583. // Probably not useful for several reasons:
  1584. // - for SGIs 7.1 compiler and probably some others,
  1585. // this forces lots of rope<wchar_t, ...> instantiations, creating a
  1586. // code bloat and compile time problem. (Fixed in 7.2.)
  1587. // - wchar_t is 4 bytes wide on most UNIX platforms, making it
  1588. // unattractive for unicode strings. Unsigned short may be a better
  1589. // character type.
  1590. inline void
  1591. rotate(_Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __first,
  1592. _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __middle,
  1593. _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __last)
  1594. { _Rope_rotate(__first, __middle, __last); }
  1595. # endif
  1596. _GLIBCXX_END_NAMESPACE_VERSION
  1597. } // namespace