ropeimpl.h 48 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711
  1. // SGI's rope class implementation -*- C++ -*-
  2. // Copyright (C) 2001-2020 Free Software Foundation, Inc.
  3. //
  4. // This file is part of the GNU ISO C++ Library. This library is free
  5. // software; you can redistribute it and/or modify it under the
  6. // terms of the GNU General Public License as published by the
  7. // Free Software Foundation; either version 3, or (at your option)
  8. // any later version.
  9. // This library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // Under Section 7 of GPL version 3, you are granted additional
  14. // permissions described in the GCC Runtime Library Exception, version
  15. // 3.1, as published by the Free Software Foundation.
  16. // You should have received a copy of the GNU General Public License and
  17. // a copy of the GCC Runtime Library Exception along with this program;
  18. // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  19. // <http://www.gnu.org/licenses/>.
  20. /*
  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. {
  490. using std::size_t;
  491. _RopeRep* __result;
  492. if (0 == __slen)
  493. {
  494. _S_ref(__r);
  495. return __r;
  496. }
  497. if (0 == __r)
  498. return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
  499. __r->_M_get_allocator());
  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 =
  529. __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
  530. __try
  531. {
  532. __r->_M_ref_nonnil();
  533. __result = _S_tree_concat(__r, __nright);
  534. }
  535. __catch(...)
  536. {
  537. _S_unref(__r);
  538. _S_unref(__nright);
  539. __throw_exception_again;
  540. }
  541. return __result;
  542. }
  543. #ifndef __GC
  544. template <class _CharT, class _Alloc>
  545. typename rope<_CharT,_Alloc>::_RopeRep*
  546. rope<_CharT,_Alloc>::
  547. _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s,
  548. std::size_t __slen)
  549. {
  550. using std::size_t;
  551. _RopeRep* __result;
  552. if (0 == __r)
  553. return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
  554. __r->_M_get_allocator());
  555. size_t __count = __r->_M_ref_count;
  556. size_t __orig_size = __r->_M_size;
  557. if (__count > 1)
  558. return _S_concat_char_iter(__r, __s, __slen);
  559. if (0 == __slen)
  560. {
  561. __r->_M_ref_count = 2; // One more than before
  562. return __r;
  563. }
  564. if (__orig_size + __slen <= size_t(_S_copy_max)
  565. && __detail::_S_leaf == __r->_M_tag)
  566. {
  567. __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s,
  568. __slen);
  569. return __result;
  570. }
  571. if (__detail::_S_concat == __r->_M_tag)
  572. {
  573. _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*)
  574. __r)->_M_right);
  575. if (__detail::_S_leaf == __right->_M_tag
  576. && __right->_M_size + __slen <= size_t(_S_copy_max))
  577. {
  578. _RopeRep* __new_right =
  579. _S_destr_leaf_concat_char_iter(__right, __s, __slen);
  580. if (__right == __new_right)
  581. __new_right->_M_ref_count = 1;
  582. else
  583. __right->_M_unref_nonnil();
  584. __r->_M_ref_count = 2; // One more than before.
  585. ((_RopeConcatenation*)__r)->_M_right = __new_right;
  586. __r->_M_size = __orig_size + __slen;
  587. if (0 != __r->_M_c_string)
  588. {
  589. __r->_M_free_c_string();
  590. __r->_M_c_string = 0;
  591. }
  592. return __r;
  593. }
  594. }
  595. _RopeRep* __right =
  596. __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
  597. __r->_M_ref_nonnil();
  598. __try
  599. { __result = _S_tree_concat(__r, __right); }
  600. __catch(...)
  601. {
  602. _S_unref(__r);
  603. _S_unref(__right);
  604. __throw_exception_again;
  605. }
  606. return __result;
  607. }
  608. #endif /* !__GC */
  609. template <class _CharT, class _Alloc>
  610. typename rope<_CharT, _Alloc>::_RopeRep*
  611. rope<_CharT, _Alloc>::
  612. _S_concat(_RopeRep* __left, _RopeRep* __right)
  613. {
  614. using std::size_t;
  615. if (0 == __left)
  616. {
  617. _S_ref(__right);
  618. return __right;
  619. }
  620. if (0 == __right)
  621. {
  622. __left->_M_ref_nonnil();
  623. return __left;
  624. }
  625. if (__detail::_S_leaf == __right->_M_tag)
  626. {
  627. if (__detail::_S_leaf == __left->_M_tag)
  628. {
  629. if (__right->_M_size + __left->_M_size <= size_t(_S_copy_max))
  630. return _S_leaf_concat_char_iter((_RopeLeaf*)__left,
  631. ((_RopeLeaf*)__right)->_M_data,
  632. __right->_M_size);
  633. }
  634. else if (__detail::_S_concat == __left->_M_tag
  635. && __detail::_S_leaf == ((_RopeConcatenation*)
  636. __left)->_M_right->_M_tag)
  637. {
  638. _RopeLeaf* __leftright =
  639. (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right);
  640. if (__leftright->_M_size
  641. + __right->_M_size <= size_t(_S_copy_max))
  642. {
  643. _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left;
  644. _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright,
  645. ((_RopeLeaf*)
  646. __right)->
  647. _M_data,
  648. __right->_M_size);
  649. __leftleft->_M_ref_nonnil();
  650. __try
  651. { return(_S_tree_concat(__leftleft, __rest)); }
  652. __catch(...)
  653. {
  654. _S_unref(__leftleft);
  655. _S_unref(__rest);
  656. __throw_exception_again;
  657. }
  658. }
  659. }
  660. }
  661. __left->_M_ref_nonnil();
  662. __right->_M_ref_nonnil();
  663. __try
  664. { return(_S_tree_concat(__left, __right)); }
  665. __catch(...)
  666. {
  667. _S_unref(__left);
  668. _S_unref(__right);
  669. __throw_exception_again;
  670. }
  671. }
  672. template <class _CharT, class _Alloc>
  673. typename rope<_CharT, _Alloc>::_RopeRep*
  674. rope<_CharT, _Alloc>::
  675. _S_substring(_RopeRep* __base, std::size_t __start, std::size_t __endp1)
  676. {
  677. using std::size_t;
  678. if (0 == __base)
  679. return 0;
  680. size_t __len = __base->_M_size;
  681. size_t __adj_endp1;
  682. const size_t __lazy_threshold = 128;
  683. if (__endp1 >= __len)
  684. {
  685. if (0 == __start)
  686. {
  687. __base->_M_ref_nonnil();
  688. return __base;
  689. }
  690. else
  691. __adj_endp1 = __len;
  692. }
  693. else
  694. __adj_endp1 = __endp1;
  695. switch(__base->_M_tag)
  696. {
  697. case __detail::_S_concat:
  698. {
  699. _RopeConcatenation* __c = (_RopeConcatenation*)__base;
  700. _RopeRep* __left = __c->_M_left;
  701. _RopeRep* __right = __c->_M_right;
  702. size_t __left_len = __left->_M_size;
  703. _RopeRep* __result;
  704. if (__adj_endp1 <= __left_len)
  705. return _S_substring(__left, __start, __endp1);
  706. else if (__start >= __left_len)
  707. return _S_substring(__right, __start - __left_len,
  708. __adj_endp1 - __left_len);
  709. _Self_destruct_ptr __left_result(_S_substring(__left,
  710. __start,
  711. __left_len));
  712. _Self_destruct_ptr __right_result(_S_substring(__right, 0,
  713. __endp1
  714. - __left_len));
  715. __result = _S_concat(__left_result, __right_result);
  716. return __result;
  717. }
  718. case __detail::_S_leaf:
  719. {
  720. _RopeLeaf* __l = (_RopeLeaf*)__base;
  721. _RopeLeaf* __result;
  722. size_t __result_len;
  723. if (__start >= __adj_endp1)
  724. return 0;
  725. __result_len = __adj_endp1 - __start;
  726. if (__result_len > __lazy_threshold)
  727. goto lazy;
  728. #ifdef __GC
  729. const _CharT* __section = __l->_M_data + __start;
  730. __result = _S_new_RopeLeaf(__section, __result_len,
  731. __base->_M_get_allocator());
  732. __result->_M_c_string = 0; // Not eos terminated.
  733. #else
  734. // We should sometimes create substring node instead.
  735. __result = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__l->_M_data + __start,
  736. __result_len,
  737. __base->
  738. _M_get_allocator());
  739. #endif
  740. return __result;
  741. }
  742. case __detail::_S_substringfn:
  743. // Avoid introducing multiple layers of substring nodes.
  744. {
  745. _RopeSubstring* __old = (_RopeSubstring*)__base;
  746. size_t __result_len;
  747. if (__start >= __adj_endp1)
  748. return 0;
  749. __result_len = __adj_endp1 - __start;
  750. if (__result_len > __lazy_threshold)
  751. {
  752. _RopeSubstring* __result =
  753. _S_new_RopeSubstring(__old->_M_base,
  754. __start + __old->_M_start,
  755. __adj_endp1 - __start,
  756. __base->_M_get_allocator());
  757. return __result;
  758. } // *** else fall through: ***
  759. }
  760. case __detail::_S_function:
  761. {
  762. _RopeFunction* __f = (_RopeFunction*)__base;
  763. _CharT* __section;
  764. size_t __result_len;
  765. if (__start >= __adj_endp1)
  766. return 0;
  767. __result_len = __adj_endp1 - __start;
  768. if (__result_len > __lazy_threshold)
  769. goto lazy;
  770. __section = (_CharT*)
  771. rope::_Data_allocate(_S_rounded_up_size(__result_len));
  772. __try
  773. { (*(__f->_M_fn))(__start, __result_len, __section); }
  774. __catch(...)
  775. {
  776. _RopeRep::__STL_FREE_STRING(__section, __result_len,
  777. __base->_M_get_allocator());
  778. __throw_exception_again;
  779. }
  780. _S_cond_store_eos(__section[__result_len]);
  781. return _S_new_RopeLeaf(__section, __result_len,
  782. __base->_M_get_allocator());
  783. }
  784. }
  785. lazy:
  786. {
  787. // Create substring node.
  788. return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start,
  789. __base->_M_get_allocator());
  790. }
  791. }
  792. template<class _CharT>
  793. class _Rope_flatten_char_consumer
  794. : public _Rope_char_consumer<_CharT>
  795. {
  796. private:
  797. _CharT* _M_buf_ptr;
  798. public:
  799. _Rope_flatten_char_consumer(_CharT* __buffer)
  800. { _M_buf_ptr = __buffer; }
  801. ~_Rope_flatten_char_consumer() {}
  802. bool
  803. operator()(const _CharT* __leaf, std::size_t __n)
  804. {
  805. uninitialized_copy_n(__leaf, __n, _M_buf_ptr);
  806. _M_buf_ptr += __n;
  807. return true;
  808. }
  809. };
  810. template<class _CharT>
  811. class _Rope_find_char_char_consumer
  812. : public _Rope_char_consumer<_CharT>
  813. {
  814. private:
  815. _CharT _M_pattern;
  816. public:
  817. std::size_t _M_count; // Number of nonmatching characters
  818. _Rope_find_char_char_consumer(_CharT __p)
  819. : _M_pattern(__p), _M_count(0) {}
  820. ~_Rope_find_char_char_consumer() {}
  821. bool
  822. operator()(const _CharT* __leaf, std::size_t __n)
  823. {
  824. std::size_t __i;
  825. for (__i = 0; __i < __n; __i++)
  826. {
  827. if (__leaf[__i] == _M_pattern)
  828. {
  829. _M_count += __i;
  830. return false;
  831. }
  832. }
  833. _M_count += __n; return true;
  834. }
  835. };
  836. template<class _CharT, class _Traits>
  837. // Here _CharT is both the stream and rope character type.
  838. class _Rope_insert_char_consumer
  839. : public _Rope_char_consumer<_CharT>
  840. {
  841. private:
  842. typedef std::basic_ostream<_CharT,_Traits> _Insert_ostream;
  843. _Insert_ostream& _M_o;
  844. public:
  845. _Rope_insert_char_consumer(_Insert_ostream& __writer)
  846. : _M_o(__writer) {}
  847. ~_Rope_insert_char_consumer() { }
  848. // Caller is presumed to own the ostream
  849. bool operator() (const _CharT* __leaf, std::size_t __n);
  850. // Returns true to continue traversal.
  851. };
  852. template<class _CharT, class _Traits>
  853. bool
  854. _Rope_insert_char_consumer<_CharT, _Traits>::
  855. operator()(const _CharT* __leaf, std::size_t __n)
  856. {
  857. std::size_t __i;
  858. // We assume that formatting is set up correctly for each element.
  859. for (__i = 0; __i < __n; __i++)
  860. _M_o.put(__leaf[__i]);
  861. return true;
  862. }
  863. template <class _CharT, class _Alloc>
  864. bool
  865. rope<_CharT, _Alloc>::
  866. _S_apply_to_pieces(_Rope_char_consumer<_CharT>& __c, const _RopeRep* __r,
  867. std::size_t __begin, std::size_t __end)
  868. {
  869. using std::size_t;
  870. if (0 == __r)
  871. return true;
  872. switch(__r->_M_tag)
  873. {
  874. case __detail::_S_concat:
  875. {
  876. _RopeConcatenation* __conc = (_RopeConcatenation*)__r;
  877. _RopeRep* __left = __conc->_M_left;
  878. size_t __left_len = __left->_M_size;
  879. if (__begin < __left_len)
  880. {
  881. size_t __left_end = std::min(__left_len, __end);
  882. if (!_S_apply_to_pieces(__c, __left, __begin, __left_end))
  883. return false;
  884. }
  885. if (__end > __left_len)
  886. {
  887. _RopeRep* __right = __conc->_M_right;
  888. size_t __right_start = std::max(__left_len, __begin);
  889. if (!_S_apply_to_pieces(__c, __right,
  890. __right_start - __left_len,
  891. __end - __left_len))
  892. return false;
  893. }
  894. }
  895. return true;
  896. case __detail::_S_leaf:
  897. {
  898. _RopeLeaf* __l = (_RopeLeaf*)__r;
  899. return __c(__l->_M_data + __begin, __end - __begin);
  900. }
  901. case __detail::_S_function:
  902. case __detail::_S_substringfn:
  903. {
  904. _RopeFunction* __f = (_RopeFunction*)__r;
  905. size_t __len = __end - __begin;
  906. bool __result;
  907. _CharT* __buffer =
  908. (_CharT*)_Alloc().allocate(__len * sizeof(_CharT));
  909. __try
  910. {
  911. (*(__f->_M_fn))(__begin, __len, __buffer);
  912. __result = __c(__buffer, __len);
  913. _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
  914. }
  915. __catch(...)
  916. {
  917. _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
  918. __throw_exception_again;
  919. }
  920. return __result;
  921. }
  922. default:
  923. return false;
  924. }
  925. }
  926. template<class _CharT, class _Traits>
  927. inline void
  928. _Rope_fill(std::basic_ostream<_CharT, _Traits>& __o, std::size_t __n)
  929. {
  930. char __f = __o.fill();
  931. std::size_t __i;
  932. for (__i = 0; __i < __n; __i++)
  933. __o.put(__f);
  934. }
  935. template <class _CharT>
  936. inline bool
  937. _Rope_is_simple(_CharT*)
  938. { return false; }
  939. inline bool
  940. _Rope_is_simple(char*)
  941. { return true; }
  942. inline bool
  943. _Rope_is_simple(wchar_t*)
  944. { return true; }
  945. template<class _CharT, class _Traits, class _Alloc>
  946. std::basic_ostream<_CharT, _Traits>&
  947. operator<<(std::basic_ostream<_CharT, _Traits>& __o,
  948. const rope<_CharT, _Alloc>& __r)
  949. {
  950. using std::size_t;
  951. size_t __w = __o.width();
  952. bool __left = bool(__o.flags() & std::ios::left);
  953. size_t __pad_len;
  954. size_t __rope_len = __r.size();
  955. _Rope_insert_char_consumer<_CharT, _Traits> __c(__o);
  956. bool __is_simple = _Rope_is_simple((_CharT*)0);
  957. if (__rope_len < __w)
  958. __pad_len = __w - __rope_len;
  959. else
  960. __pad_len = 0;
  961. if (!__is_simple)
  962. __o.width(__w / __rope_len);
  963. __try
  964. {
  965. if (__is_simple && !__left && __pad_len > 0)
  966. _Rope_fill(__o, __pad_len);
  967. __r.apply_to_pieces(0, __r.size(), __c);
  968. if (__is_simple && __left && __pad_len > 0)
  969. _Rope_fill(__o, __pad_len);
  970. if (!__is_simple)
  971. __o.width(__w);
  972. }
  973. __catch(...)
  974. {
  975. if (!__is_simple)
  976. __o.width(__w);
  977. __throw_exception_again;
  978. }
  979. return __o;
  980. }
  981. template <class _CharT, class _Alloc>
  982. _CharT*
  983. rope<_CharT, _Alloc>::
  984. _S_flatten(_RopeRep* __r, std::size_t __start, std::size_t __len,
  985. _CharT* __buffer)
  986. {
  987. _Rope_flatten_char_consumer<_CharT> __c(__buffer);
  988. _S_apply_to_pieces(__c, __r, __start, __start + __len);
  989. return(__buffer + __len);
  990. }
  991. template <class _CharT, class _Alloc>
  992. std::size_t
  993. rope<_CharT, _Alloc>::
  994. find(_CharT __pattern, std::size_t __start) const
  995. {
  996. _Rope_find_char_char_consumer<_CharT> __c(__pattern);
  997. _S_apply_to_pieces(__c, this->_M_tree_ptr, __start, size());
  998. size_type __result_pos = __start + __c._M_count;
  999. #ifndef __STL_OLD_ROPE_SEMANTICS
  1000. if (__result_pos == size())
  1001. __result_pos = npos;
  1002. #endif
  1003. return __result_pos;
  1004. }
  1005. template <class _CharT, class _Alloc>
  1006. _CharT*
  1007. rope<_CharT, _Alloc>::
  1008. _S_flatten(_RopeRep* __r, _CharT* __buffer)
  1009. {
  1010. if (0 == __r)
  1011. return __buffer;
  1012. switch(__r->_M_tag)
  1013. {
  1014. case __detail::_S_concat:
  1015. {
  1016. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1017. _RopeRep* __left = __c->_M_left;
  1018. _RopeRep* __right = __c->_M_right;
  1019. _CharT* __rest = _S_flatten(__left, __buffer);
  1020. return _S_flatten(__right, __rest);
  1021. }
  1022. case __detail::_S_leaf:
  1023. {
  1024. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1025. return copy_n(__l->_M_data, __l->_M_size, __buffer).second;
  1026. }
  1027. case __detail::_S_function:
  1028. case __detail::_S_substringfn:
  1029. // We don't yet do anything with substring nodes.
  1030. // This needs to be fixed before ropefiles will work well.
  1031. {
  1032. _RopeFunction* __f = (_RopeFunction*)__r;
  1033. (*(__f->_M_fn))(0, __f->_M_size, __buffer);
  1034. return __buffer + __f->_M_size;
  1035. }
  1036. default:
  1037. return 0;
  1038. }
  1039. }
  1040. // This needs work for _CharT != char
  1041. template <class _CharT, class _Alloc>
  1042. void
  1043. rope<_CharT, _Alloc>::
  1044. _S_dump(_RopeRep* __r, int __indent)
  1045. {
  1046. using std::printf;
  1047. for (int __i = 0; __i < __indent; __i++)
  1048. putchar(' ');
  1049. if (0 == __r)
  1050. {
  1051. printf("NULL\n");
  1052. return;
  1053. }
  1054. if (__detail::_S_concat == __r->_M_tag)
  1055. {
  1056. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1057. _RopeRep* __left = __c->_M_left;
  1058. _RopeRep* __right = __c->_M_right;
  1059. #ifdef __GC
  1060. printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
  1061. __r, __r->_M_depth, __r->_M_size,
  1062. __r->_M_is_balanced? "" : "not");
  1063. #else
  1064. printf("Concatenation %p (rc = %ld, depth = %d, "
  1065. "len = %ld, %s balanced)\n",
  1066. __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size,
  1067. __r->_M_is_balanced? "" : "not");
  1068. #endif
  1069. _S_dump(__left, __indent + 2);
  1070. _S_dump(__right, __indent + 2);
  1071. return;
  1072. }
  1073. else
  1074. {
  1075. const char* __kind;
  1076. switch (__r->_M_tag)
  1077. {
  1078. case __detail::_S_leaf:
  1079. __kind = "Leaf";
  1080. break;
  1081. case __detail::_S_function:
  1082. __kind = "Function";
  1083. break;
  1084. case __detail::_S_substringfn:
  1085. __kind = "Function representing substring";
  1086. break;
  1087. default:
  1088. __kind = "(corrupted kind field!)";
  1089. }
  1090. #ifdef __GC
  1091. printf("%s %p (depth = %d, len = %ld) ",
  1092. __kind, __r, __r->_M_depth, __r->_M_size);
  1093. #else
  1094. printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
  1095. __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size);
  1096. #endif
  1097. if (_S_is_one_byte_char_type((_CharT*)0))
  1098. {
  1099. const int __max_len = 40;
  1100. _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len));
  1101. _CharT __buffer[__max_len + 1];
  1102. bool __too_big = __r->_M_size > __prefix->_M_size;
  1103. _S_flatten(__prefix, __buffer);
  1104. __buffer[__prefix->_M_size] = _S_eos((_CharT*)0);
  1105. printf("%s%s\n", (char*)__buffer,
  1106. __too_big? "...\n" : "\n");
  1107. }
  1108. else
  1109. printf("\n");
  1110. }
  1111. }
  1112. template <class _CharT, class _Alloc>
  1113. const unsigned long
  1114. rope<_CharT, _Alloc>::
  1115. _S_min_len[int(__detail::_S_max_rope_depth) + 1] = {
  1116. /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21,
  1117. /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377,
  1118. /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181,
  1119. /* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368,
  1120. /* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811,
  1121. /* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309,
  1122. /* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352,
  1123. /* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155,
  1124. /* 39 */165580141, /* 40 */267914296, /* 41 */433494437,
  1125. /* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903,
  1126. /* 45 */2971215073u };
  1127. // These are Fibonacci numbers < 2**32.
  1128. template <class _CharT, class _Alloc>
  1129. typename rope<_CharT, _Alloc>::_RopeRep*
  1130. rope<_CharT, _Alloc>::
  1131. _S_balance(_RopeRep* __r)
  1132. {
  1133. _RopeRep* __forest[int(__detail::_S_max_rope_depth) + 1];
  1134. _RopeRep* __result = 0;
  1135. int __i;
  1136. // Invariant:
  1137. // The concatenation of forest in descending order is equal to __r.
  1138. // __forest[__i]._M_size >= _S_min_len[__i]
  1139. // __forest[__i]._M_depth = __i
  1140. // References from forest are included in refcount.
  1141. for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
  1142. __forest[__i] = 0;
  1143. __try
  1144. {
  1145. _S_add_to_forest(__r, __forest);
  1146. for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
  1147. if (0 != __forest[__i])
  1148. {
  1149. #ifndef __GC
  1150. _Self_destruct_ptr __old(__result);
  1151. #endif
  1152. __result = _S_concat(__forest[__i], __result);
  1153. __forest[__i]->_M_unref_nonnil();
  1154. #if !defined(__GC) && __cpp_exceptions
  1155. __forest[__i] = 0;
  1156. #endif
  1157. }
  1158. }
  1159. __catch(...)
  1160. {
  1161. for(__i = 0; __i <= int(__detail::_S_max_rope_depth); __i++)
  1162. _S_unref(__forest[__i]);
  1163. __throw_exception_again;
  1164. }
  1165. if (__result->_M_depth > int(__detail::_S_max_rope_depth))
  1166. std::__throw_length_error(__N("rope::_S_balance"));
  1167. return(__result);
  1168. }
  1169. template <class _CharT, class _Alloc>
  1170. void
  1171. rope<_CharT, _Alloc>::
  1172. _S_add_to_forest(_RopeRep* __r, _RopeRep** __forest)
  1173. {
  1174. if (__r->_M_is_balanced)
  1175. {
  1176. _S_add_leaf_to_forest(__r, __forest);
  1177. return;
  1178. }
  1179. {
  1180. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1181. _S_add_to_forest(__c->_M_left, __forest);
  1182. _S_add_to_forest(__c->_M_right, __forest);
  1183. }
  1184. }
  1185. template <class _CharT, class _Alloc>
  1186. void
  1187. rope<_CharT, _Alloc>::
  1188. _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest)
  1189. {
  1190. _RopeRep* __insertee; // included in refcount
  1191. _RopeRep* __too_tiny = 0; // included in refcount
  1192. int __i; // forest[0..__i-1] is empty
  1193. std::size_t __s = __r->_M_size;
  1194. for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i)
  1195. {
  1196. if (0 != __forest[__i])
  1197. {
  1198. #ifndef __GC
  1199. _Self_destruct_ptr __old(__too_tiny);
  1200. #endif
  1201. __too_tiny = _S_concat_and_set_balanced(__forest[__i],
  1202. __too_tiny);
  1203. __forest[__i]->_M_unref_nonnil();
  1204. __forest[__i] = 0;
  1205. }
  1206. }
  1207. {
  1208. #ifndef __GC
  1209. _Self_destruct_ptr __old(__too_tiny);
  1210. #endif
  1211. __insertee = _S_concat_and_set_balanced(__too_tiny, __r);
  1212. }
  1213. // Too_tiny dead, and no longer included in refcount.
  1214. // Insertee is live and included.
  1215. for (;; ++__i)
  1216. {
  1217. if (0 != __forest[__i])
  1218. {
  1219. #ifndef __GC
  1220. _Self_destruct_ptr __old(__insertee);
  1221. #endif
  1222. __insertee = _S_concat_and_set_balanced(__forest[__i],
  1223. __insertee);
  1224. __forest[__i]->_M_unref_nonnil();
  1225. __forest[__i] = 0;
  1226. }
  1227. if (__i == int(__detail::_S_max_rope_depth)
  1228. || __insertee->_M_size < _S_min_len[__i+1])
  1229. {
  1230. __forest[__i] = __insertee;
  1231. // refcount is OK since __insertee is now dead.
  1232. return;
  1233. }
  1234. }
  1235. }
  1236. template <class _CharT, class _Alloc>
  1237. _CharT
  1238. rope<_CharT, _Alloc>::
  1239. _S_fetch(_RopeRep* __r, size_type __i)
  1240. {
  1241. __GC_CONST _CharT* __cstr = __r->_M_c_string;
  1242. if (0 != __cstr)
  1243. return __cstr[__i];
  1244. for(;;)
  1245. {
  1246. switch(__r->_M_tag)
  1247. {
  1248. case __detail::_S_concat:
  1249. {
  1250. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1251. _RopeRep* __left = __c->_M_left;
  1252. std::size_t __left_len = __left->_M_size;
  1253. if (__i >= __left_len)
  1254. {
  1255. __i -= __left_len;
  1256. __r = __c->_M_right;
  1257. }
  1258. else
  1259. __r = __left;
  1260. }
  1261. break;
  1262. case __detail::_S_leaf:
  1263. {
  1264. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1265. return __l->_M_data[__i];
  1266. }
  1267. case __detail::_S_function:
  1268. case __detail::_S_substringfn:
  1269. {
  1270. _RopeFunction* __f = (_RopeFunction*)__r;
  1271. _CharT __result;
  1272. (*(__f->_M_fn))(__i, 1, &__result);
  1273. return __result;
  1274. }
  1275. }
  1276. }
  1277. }
  1278. #ifndef __GC
  1279. // Return a uniquely referenced character slot for the given
  1280. // position, or 0 if that's not possible.
  1281. template <class _CharT, class _Alloc>
  1282. _CharT*
  1283. rope<_CharT, _Alloc>::
  1284. _S_fetch_ptr(_RopeRep* __r, size_type __i)
  1285. {
  1286. _RopeRep* __clrstack[__detail::_S_max_rope_depth];
  1287. std::size_t __csptr = 0;
  1288. for(;;)
  1289. {
  1290. if (__r->_M_ref_count > 1)
  1291. return 0;
  1292. switch(__r->_M_tag)
  1293. {
  1294. case __detail::_S_concat:
  1295. {
  1296. _RopeConcatenation* __c = (_RopeConcatenation*)__r;
  1297. _RopeRep* __left = __c->_M_left;
  1298. std::size_t __left_len = __left->_M_size;
  1299. if (__c->_M_c_string != 0)
  1300. __clrstack[__csptr++] = __c;
  1301. if (__i >= __left_len)
  1302. {
  1303. __i -= __left_len;
  1304. __r = __c->_M_right;
  1305. }
  1306. else
  1307. __r = __left;
  1308. }
  1309. break;
  1310. case __detail::_S_leaf:
  1311. {
  1312. _RopeLeaf* __l = (_RopeLeaf*)__r;
  1313. if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0)
  1314. __clrstack[__csptr++] = __l;
  1315. while (__csptr > 0)
  1316. {
  1317. -- __csptr;
  1318. _RopeRep* __d = __clrstack[__csptr];
  1319. __d->_M_free_c_string();
  1320. __d->_M_c_string = 0;
  1321. }
  1322. return __l->_M_data + __i;
  1323. }
  1324. case __detail::_S_function:
  1325. case __detail::_S_substringfn:
  1326. return 0;
  1327. }
  1328. }
  1329. }
  1330. #endif /* __GC */
  1331. // The following could be implemented trivially using
  1332. // lexicographical_compare_3way.
  1333. // We do a little more work to avoid dealing with rope iterators for
  1334. // flat strings.
  1335. template <class _CharT, class _Alloc>
  1336. int
  1337. rope<_CharT, _Alloc>::
  1338. _S_compare (const _RopeRep* __left, const _RopeRep* __right)
  1339. {
  1340. std::size_t __left_len;
  1341. std::size_t __right_len;
  1342. if (0 == __right)
  1343. return 0 != __left;
  1344. if (0 == __left)
  1345. return -1;
  1346. __left_len = __left->_M_size;
  1347. __right_len = __right->_M_size;
  1348. if (__detail::_S_leaf == __left->_M_tag)
  1349. {
  1350. _RopeLeaf* __l = (_RopeLeaf*) __left;
  1351. if (__detail::_S_leaf == __right->_M_tag)
  1352. {
  1353. _RopeLeaf* __r = (_RopeLeaf*) __right;
  1354. return lexicographical_compare_3way(__l->_M_data,
  1355. __l->_M_data + __left_len,
  1356. __r->_M_data, __r->_M_data
  1357. + __right_len);
  1358. }
  1359. else
  1360. {
  1361. const_iterator __rstart(__right, 0);
  1362. const_iterator __rend(__right, __right_len);
  1363. return lexicographical_compare_3way(__l->_M_data, __l->_M_data
  1364. + __left_len,
  1365. __rstart, __rend);
  1366. }
  1367. }
  1368. else
  1369. {
  1370. const_iterator __lstart(__left, 0);
  1371. const_iterator __lend(__left, __left_len);
  1372. if (__detail::_S_leaf == __right->_M_tag)
  1373. {
  1374. _RopeLeaf* __r = (_RopeLeaf*) __right;
  1375. return lexicographical_compare_3way(__lstart, __lend,
  1376. __r->_M_data, __r->_M_data
  1377. + __right_len);
  1378. }
  1379. else
  1380. {
  1381. const_iterator __rstart(__right, 0);
  1382. const_iterator __rend(__right, __right_len);
  1383. return lexicographical_compare_3way(__lstart, __lend,
  1384. __rstart, __rend);
  1385. }
  1386. }
  1387. }
  1388. // Assignment to reference proxies.
  1389. template <class _CharT, class _Alloc>
  1390. _Rope_char_ref_proxy<_CharT, _Alloc>&
  1391. _Rope_char_ref_proxy<_CharT, _Alloc>::
  1392. operator=(_CharT __c)
  1393. {
  1394. _RopeRep* __old = _M_root->_M_tree_ptr;
  1395. #ifndef __GC
  1396. // First check for the case in which everything is uniquely
  1397. // referenced. In that case we can do this destructively.
  1398. _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos);
  1399. if (0 != __ptr)
  1400. {
  1401. *__ptr = __c;
  1402. return *this;
  1403. }
  1404. #endif
  1405. _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos));
  1406. _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1,
  1407. __old->_M_size));
  1408. _Self_destruct_ptr __result_left(_My_rope::
  1409. _S_destr_concat_char_iter(__left,
  1410. &__c, 1));
  1411. _RopeRep* __result = _My_rope::_S_concat(__result_left, __right);
  1412. #ifndef __GC
  1413. _RopeRep::_S_unref(__old);
  1414. #endif
  1415. _M_root->_M_tree_ptr = __result;
  1416. return *this;
  1417. }
  1418. template <class _CharT, class _Alloc>
  1419. inline _Rope_char_ref_proxy<_CharT, _Alloc>::
  1420. operator _CharT() const
  1421. {
  1422. if (_M_current_valid)
  1423. return _M_current;
  1424. else
  1425. return _My_rope::_S_fetch(_M_root->_M_tree_ptr, _M_pos);
  1426. }
  1427. template <class _CharT, class _Alloc>
  1428. _Rope_char_ptr_proxy<_CharT, _Alloc>
  1429. _Rope_char_ref_proxy<_CharT, _Alloc>::
  1430. operator&() const
  1431. { return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); }
  1432. template <class _CharT, class _Alloc>
  1433. rope<_CharT, _Alloc>::
  1434. rope(std::size_t __n, _CharT __c, const allocator_type& __a)
  1435. : _Base(__a)
  1436. {
  1437. using std::__uninitialized_fill_n_a;
  1438. rope<_CharT,_Alloc> __result;
  1439. const std::size_t __exponentiate_threshold = 32;
  1440. std::size_t __exponent;
  1441. std::size_t __rest;
  1442. _CharT* __rest_buffer;
  1443. _RopeRep* __remainder;
  1444. rope<_CharT, _Alloc> __remainder_rope;
  1445. if (0 == __n)
  1446. return;
  1447. __exponent = __n / __exponentiate_threshold;
  1448. __rest = __n % __exponentiate_threshold;
  1449. if (0 == __rest)
  1450. __remainder = 0;
  1451. else
  1452. {
  1453. __rest_buffer = this->_Data_allocate(_S_rounded_up_size(__rest));
  1454. __uninitialized_fill_n_a(__rest_buffer, __rest, __c,
  1455. _M_get_allocator());
  1456. _S_cond_store_eos(__rest_buffer[__rest]);
  1457. __try
  1458. { __remainder = _S_new_RopeLeaf(__rest_buffer, __rest,
  1459. _M_get_allocator()); }
  1460. __catch(...)
  1461. {
  1462. _RopeRep::__STL_FREE_STRING(__rest_buffer, __rest,
  1463. _M_get_allocator());
  1464. __throw_exception_again;
  1465. }
  1466. }
  1467. __remainder_rope._M_tree_ptr = __remainder;
  1468. if (__exponent != 0)
  1469. {
  1470. _CharT* __base_buffer =
  1471. this->_Data_allocate(_S_rounded_up_size(__exponentiate_threshold));
  1472. _RopeLeaf* __base_leaf;
  1473. rope __base_rope;
  1474. __uninitialized_fill_n_a(__base_buffer, __exponentiate_threshold, __c,
  1475. _M_get_allocator());
  1476. _S_cond_store_eos(__base_buffer[__exponentiate_threshold]);
  1477. __try
  1478. {
  1479. __base_leaf = _S_new_RopeLeaf(__base_buffer,
  1480. __exponentiate_threshold,
  1481. _M_get_allocator());
  1482. }
  1483. __catch(...)
  1484. {
  1485. _RopeRep::__STL_FREE_STRING(__base_buffer,
  1486. __exponentiate_threshold,
  1487. _M_get_allocator());
  1488. __throw_exception_again;
  1489. }
  1490. __base_rope._M_tree_ptr = __base_leaf;
  1491. if (1 == __exponent)
  1492. __result = __base_rope;
  1493. else
  1494. __result = power(__base_rope, __exponent,
  1495. _Rope_Concat_fn<_CharT, _Alloc>());
  1496. if (0 != __remainder)
  1497. __result += __remainder_rope;
  1498. }
  1499. else
  1500. __result = __remainder_rope;
  1501. this->_M_tree_ptr = __result._M_tree_ptr;
  1502. this->_M_tree_ptr->_M_ref_nonnil();
  1503. }
  1504. template<class _CharT, class _Alloc>
  1505. _CharT
  1506. rope<_CharT, _Alloc>::_S_empty_c_str[1];
  1507. template<class _CharT, class _Alloc>
  1508. const _CharT*
  1509. rope<_CharT, _Alloc>::
  1510. c_str() const
  1511. {
  1512. if (0 == this->_M_tree_ptr)
  1513. {
  1514. _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant,
  1515. // but probably fast.
  1516. return _S_empty_c_str;
  1517. }
  1518. __gthread_mutex_lock (&this->_M_tree_ptr->_M_c_string_lock);
  1519. __GC_CONST _CharT* __result = this->_M_tree_ptr->_M_c_string;
  1520. if (0 == __result)
  1521. {
  1522. std::size_t __s = size();
  1523. __result = this->_Data_allocate(__s + 1);
  1524. _S_flatten(this->_M_tree_ptr, __result);
  1525. __result[__s] = _S_eos((_CharT*)0);
  1526. this->_M_tree_ptr->_M_c_string = __result;
  1527. }
  1528. __gthread_mutex_unlock (&this->_M_tree_ptr->_M_c_string_lock);
  1529. return(__result);
  1530. }
  1531. template<class _CharT, class _Alloc>
  1532. const _CharT* rope<_CharT, _Alloc>::
  1533. replace_with_c_str()
  1534. {
  1535. if (0 == this->_M_tree_ptr)
  1536. {
  1537. _S_empty_c_str[0] = _S_eos((_CharT*)0);
  1538. return _S_empty_c_str;
  1539. }
  1540. __GC_CONST _CharT* __old_c_string = this->_M_tree_ptr->_M_c_string;
  1541. if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag
  1542. && 0 != __old_c_string)
  1543. return(__old_c_string);
  1544. std::size_t __s = size();
  1545. _CharT* __result = this->_Data_allocate(_S_rounded_up_size(__s));
  1546. _S_flatten(this->_M_tree_ptr, __result);
  1547. __result[__s] = _S_eos((_CharT*)0);
  1548. this->_M_tree_ptr->_M_unref_nonnil();
  1549. this->_M_tree_ptr = _S_new_RopeLeaf(__result, __s,
  1550. this->_M_get_allocator());
  1551. return(__result);
  1552. }
  1553. // Algorithm specializations. More should be added.
  1554. template<class _Rope_iterator> // was templated on CharT and Alloc
  1555. void // VC++ workaround
  1556. _Rope_rotate(_Rope_iterator __first,
  1557. _Rope_iterator __middle,
  1558. _Rope_iterator __last)
  1559. {
  1560. typedef typename _Rope_iterator::value_type _CharT;
  1561. typedef typename _Rope_iterator::_allocator_type _Alloc;
  1562. rope<_CharT, _Alloc>& __r(__first.container());
  1563. rope<_CharT, _Alloc> __prefix = __r.substr(0, __first.index());
  1564. rope<_CharT, _Alloc> __suffix =
  1565. __r.substr(__last.index(), __r.size() - __last.index());
  1566. rope<_CharT, _Alloc> __part1 =
  1567. __r.substr(__middle.index(), __last.index() - __middle.index());
  1568. rope<_CharT, _Alloc> __part2 =
  1569. __r.substr(__first.index(), __middle.index() - __first.index());
  1570. __r = __prefix;
  1571. __r += __part1;
  1572. __r += __part2;
  1573. __r += __suffix;
  1574. }
  1575. #if !defined(__GNUC__)
  1576. // Appears to confuse g++
  1577. inline void
  1578. rotate(_Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __first,
  1579. _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __middle,
  1580. _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __last)
  1581. { _Rope_rotate(__first, __middle, __last); }
  1582. #endif
  1583. # if 0
  1584. // Probably not useful for several reasons:
  1585. // - for SGIs 7.1 compiler and probably some others,
  1586. // this forces lots of rope<wchar_t, ...> instantiations, creating a
  1587. // code bloat and compile time problem. (Fixed in 7.2.)
  1588. // - wchar_t is 4 bytes wide on most UNIX platforms, making it
  1589. // unattractive for unicode strings. Unsigned short may be a better
  1590. // character type.
  1591. inline void
  1592. rotate(_Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __first,
  1593. _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __middle,
  1594. _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __last)
  1595. { _Rope_rotate(__first, __middle, __last); }
  1596. # endif
  1597. _GLIBCXX_END_NAMESPACE_VERSION
  1598. } // namespace