ropeimpl.h 47 KB

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