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