100db7afdSDavid E. O'Brien // SGI's rope class implementation -*- C++ -*- 200db7afdSDavid E. O'Brien 3f8a1b7d9SAlexander Kabaev // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 4f8a1b7d9SAlexander Kabaev // Free Software Foundation, Inc. 500db7afdSDavid E. O'Brien // 600db7afdSDavid E. O'Brien // This file is part of the GNU ISO C++ Library. This library is free 700db7afdSDavid E. O'Brien // software; you can redistribute it and/or modify it under the 800db7afdSDavid E. O'Brien // terms of the GNU General Public License as published by the 900db7afdSDavid E. O'Brien // Free Software Foundation; either version 2, or (at your option) 1000db7afdSDavid E. O'Brien // any later version. 1100db7afdSDavid E. O'Brien 1200db7afdSDavid E. O'Brien // This library is distributed in the hope that it will be useful, 1300db7afdSDavid E. O'Brien // but WITHOUT ANY WARRANTY; without even the implied warranty of 1400db7afdSDavid E. O'Brien // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1500db7afdSDavid E. O'Brien // GNU General Public License for more details. 1600db7afdSDavid E. O'Brien 1700db7afdSDavid E. O'Brien // You should have received a copy of the GNU General Public License along 1800db7afdSDavid E. O'Brien // with this library; see the file COPYING. If not, write to the Free 19f8a1b7d9SAlexander Kabaev // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 2000db7afdSDavid E. O'Brien // USA. 2100db7afdSDavid E. O'Brien 2200db7afdSDavid E. O'Brien // As a special exception, you may use this file as part of a free software 2300db7afdSDavid E. O'Brien // library without restriction. Specifically, if other files instantiate 2400db7afdSDavid E. O'Brien // templates or use macros or inline functions from this file, or you compile 2500db7afdSDavid E. O'Brien // this file and link it with other files to produce an executable, this 2600db7afdSDavid E. O'Brien // file does not by itself cause the resulting executable to be covered by 2700db7afdSDavid E. O'Brien // the GNU General Public License. This exception does not however 2800db7afdSDavid E. O'Brien // invalidate any other reasons why the executable file might be covered by 2900db7afdSDavid E. O'Brien // the GNU General Public License. 3000db7afdSDavid E. O'Brien 3100db7afdSDavid E. O'Brien /* 3200db7afdSDavid E. O'Brien * Copyright (c) 1997 3300db7afdSDavid E. O'Brien * Silicon Graphics Computer Systems, Inc. 3400db7afdSDavid E. O'Brien * 3500db7afdSDavid E. O'Brien * Permission to use, copy, modify, distribute and sell this software 3600db7afdSDavid E. O'Brien * and its documentation for any purpose is hereby granted without fee, 3700db7afdSDavid E. O'Brien * provided that the above copyright notice appear in all copies and 3800db7afdSDavid E. O'Brien * that both that copyright notice and this permission notice appear 3900db7afdSDavid E. O'Brien * in supporting documentation. Silicon Graphics makes no 4000db7afdSDavid E. O'Brien * representations about the suitability of this software for any 4100db7afdSDavid E. O'Brien * purpose. It is provided "as is" without express or implied warranty. 4200db7afdSDavid E. O'Brien */ 4300db7afdSDavid E. O'Brien 4400db7afdSDavid E. O'Brien /** @file ropeimpl.h 4500db7afdSDavid E. O'Brien * This is an internal header file, included by other library headers. 4600db7afdSDavid E. O'Brien * You should not attempt to use it directly. 4700db7afdSDavid E. O'Brien */ 4800db7afdSDavid E. O'Brien 4900db7afdSDavid E. O'Brien #include <cstdio> 50ffeaf689SAlexander Kabaev #include <ostream> 5100db7afdSDavid E. O'Brien #include <bits/functexcept.h> 5200db7afdSDavid E. O'Brien 5300db7afdSDavid E. O'Brien #include <ext/algorithm> // For copy_n and lexicographical_compare_3way 5400db7afdSDavid E. O'Brien #include <ext/memory> // For uninitialized_copy_n 5500db7afdSDavid E. O'Brien #include <ext/numeric> // For power 5600db7afdSDavid E. O'Brien 57f8a1b7d9SAlexander Kabaev _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 58f8a1b7d9SAlexander Kabaev 5900db7afdSDavid E. O'Brien using std::size_t; 6000db7afdSDavid E. O'Brien using std::printf; 6100db7afdSDavid E. O'Brien using std::basic_ostream; 6200db7afdSDavid E. O'Brien using std::__throw_length_error; 6300db7afdSDavid E. O'Brien using std::_Destroy; 6400db7afdSDavid E. O'Brien using std::uninitialized_fill_n; 6500db7afdSDavid E. O'Brien 6600db7afdSDavid E. O'Brien // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf 6700db7afdSDavid E. O'Brien // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct. 6800db7afdSDavid E. O'Brien // Results in a valid buf_ptr if the iterator can be legitimately 6900db7afdSDavid E. O'Brien // dereferenced. 7000db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 71f8a1b7d9SAlexander Kabaev void 72f8a1b7d9SAlexander Kabaev _Rope_iterator_base<_CharT, _Alloc>:: _S_setbuf(_Rope_iterator_base<_CharT,_Alloc> & __x)73f8a1b7d9SAlexander Kabaev _S_setbuf(_Rope_iterator_base<_CharT, _Alloc>& __x) 7400db7afdSDavid E. O'Brien { 7500db7afdSDavid E. O'Brien const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index]; 7600db7afdSDavid E. O'Brien size_t __leaf_pos = __x._M_leaf_pos; 7700db7afdSDavid E. O'Brien size_t __pos = __x._M_current_pos; 7800db7afdSDavid E. O'Brien 79f8a1b7d9SAlexander Kabaev switch(__leaf->_M_tag) 80f8a1b7d9SAlexander Kabaev { 81f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 82f8a1b7d9SAlexander Kabaev __x._M_buf_start = ((_Rope_RopeLeaf<_CharT, _Alloc>*)__leaf)->_M_data; 8300db7afdSDavid E. O'Brien __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos); 8400db7afdSDavid E. O'Brien __x._M_buf_end = __x._M_buf_start + __leaf->_M_size; 8500db7afdSDavid E. O'Brien break; 86f8a1b7d9SAlexander Kabaev case __detail::_S_function: 87f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 8800db7afdSDavid E. O'Brien { 8900db7afdSDavid E. O'Brien size_t __len = _S_iterator_buf_len; 9000db7afdSDavid E. O'Brien size_t __buf_start_pos = __leaf_pos; 9100db7afdSDavid E. O'Brien size_t __leaf_end = __leaf_pos + __leaf->_M_size; 92f8a1b7d9SAlexander Kabaev char_producer<_CharT>* __fn = ((_Rope_RopeFunction<_CharT, 93f8a1b7d9SAlexander Kabaev _Alloc>*)__leaf)->_M_fn; 94f8a1b7d9SAlexander Kabaev if (__buf_start_pos + __len <= __pos) 95f8a1b7d9SAlexander Kabaev { 9600db7afdSDavid E. O'Brien __buf_start_pos = __pos - __len / 4; 97f8a1b7d9SAlexander Kabaev if (__buf_start_pos + __len > __leaf_end) 9800db7afdSDavid E. O'Brien __buf_start_pos = __leaf_end - __len; 9900db7afdSDavid E. O'Brien } 100f8a1b7d9SAlexander Kabaev if (__buf_start_pos + __len > __leaf_end) 10100db7afdSDavid E. O'Brien __len = __leaf_end - __buf_start_pos; 10200db7afdSDavid E. O'Brien (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf); 10300db7afdSDavid E. O'Brien __x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos); 10400db7afdSDavid E. O'Brien __x._M_buf_start = __x._M_tmp_buf; 10500db7afdSDavid E. O'Brien __x._M_buf_end = __x._M_tmp_buf + __len; 10600db7afdSDavid E. O'Brien } 10700db7afdSDavid E. O'Brien break; 10800db7afdSDavid E. O'Brien default: 10900db7afdSDavid E. O'Brien break; 11000db7afdSDavid E. O'Brien } 11100db7afdSDavid E. O'Brien } 11200db7afdSDavid E. O'Brien 11300db7afdSDavid E. O'Brien // Set path and buffer inside a rope iterator. We assume that 11400db7afdSDavid E. O'Brien // pos and root are already set. 11500db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 116f8a1b7d9SAlexander Kabaev void 117f8a1b7d9SAlexander Kabaev _Rope_iterator_base<_CharT, _Alloc>:: _S_setcache(_Rope_iterator_base<_CharT,_Alloc> & __x)118f8a1b7d9SAlexander Kabaev _S_setcache(_Rope_iterator_base<_CharT, _Alloc>& __x) 11900db7afdSDavid E. O'Brien { 120f8a1b7d9SAlexander Kabaev const _RopeRep* __path[int(__detail::_S_max_rope_depth) + 1]; 12100db7afdSDavid E. O'Brien const _RopeRep* __curr_rope; 12200db7afdSDavid E. O'Brien int __curr_depth = -1; /* index into path */ 12300db7afdSDavid E. O'Brien size_t __curr_start_pos = 0; 12400db7afdSDavid E. O'Brien size_t __pos = __x._M_current_pos; 12500db7afdSDavid E. O'Brien unsigned char __dirns = 0; // Bit vector marking right turns in the path 12600db7afdSDavid E. O'Brien 127f8a1b7d9SAlexander Kabaev if (__pos >= __x._M_root->_M_size) 128f8a1b7d9SAlexander Kabaev { 12900db7afdSDavid E. O'Brien __x._M_buf_ptr = 0; 13000db7afdSDavid E. O'Brien return; 13100db7afdSDavid E. O'Brien } 13200db7afdSDavid E. O'Brien __curr_rope = __x._M_root; 133f8a1b7d9SAlexander Kabaev if (0 != __curr_rope->_M_c_string) 134f8a1b7d9SAlexander Kabaev { 13500db7afdSDavid E. O'Brien /* Treat the root as a leaf. */ 13600db7afdSDavid E. O'Brien __x._M_buf_start = __curr_rope->_M_c_string; 13700db7afdSDavid E. O'Brien __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size; 13800db7afdSDavid E. O'Brien __x._M_buf_ptr = __curr_rope->_M_c_string + __pos; 13900db7afdSDavid E. O'Brien __x._M_path_end[0] = __curr_rope; 14000db7afdSDavid E. O'Brien __x._M_leaf_index = 0; 14100db7afdSDavid E. O'Brien __x._M_leaf_pos = 0; 14200db7afdSDavid E. O'Brien return; 14300db7afdSDavid E. O'Brien } 144f8a1b7d9SAlexander Kabaev for(;;) 145f8a1b7d9SAlexander Kabaev { 14600db7afdSDavid E. O'Brien ++__curr_depth; 14700db7afdSDavid E. O'Brien __path[__curr_depth] = __curr_rope; 148f8a1b7d9SAlexander Kabaev switch(__curr_rope->_M_tag) 149f8a1b7d9SAlexander Kabaev { 150f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 151f8a1b7d9SAlexander Kabaev case __detail::_S_function: 152f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 15300db7afdSDavid E. O'Brien __x._M_leaf_pos = __curr_start_pos; 15400db7afdSDavid E. O'Brien goto done; 155f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 15600db7afdSDavid E. O'Brien { 15700db7afdSDavid E. O'Brien _Rope_RopeConcatenation<_CharT, _Alloc>* __c = 15800db7afdSDavid E. O'Brien (_Rope_RopeConcatenation<_CharT, _Alloc>*)__curr_rope; 15900db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 16000db7afdSDavid E. O'Brien size_t __left_len = __left->_M_size; 16100db7afdSDavid E. O'Brien 16200db7afdSDavid E. O'Brien __dirns <<= 1; 163f8a1b7d9SAlexander Kabaev if (__pos >= __curr_start_pos + __left_len) 164f8a1b7d9SAlexander Kabaev { 16500db7afdSDavid E. O'Brien __dirns |= 1; 16600db7afdSDavid E. O'Brien __curr_rope = __c->_M_right; 16700db7afdSDavid E. O'Brien __curr_start_pos += __left_len; 16800db7afdSDavid E. O'Brien } 169f8a1b7d9SAlexander Kabaev else 170f8a1b7d9SAlexander Kabaev __curr_rope = __left; 17100db7afdSDavid E. O'Brien } 17200db7afdSDavid E. O'Brien break; 17300db7afdSDavid E. O'Brien } 17400db7afdSDavid E. O'Brien } 17500db7afdSDavid E. O'Brien done: 17600db7afdSDavid E. O'Brien // Copy last section of path into _M_path_end. 17700db7afdSDavid E. O'Brien { 17800db7afdSDavid E. O'Brien int __i = -1; 179f8a1b7d9SAlexander Kabaev int __j = __curr_depth + 1 - int(_S_path_cache_len); 18000db7afdSDavid E. O'Brien 18100db7afdSDavid E. O'Brien if (__j < 0) __j = 0; 182f8a1b7d9SAlexander Kabaev while (__j <= __curr_depth) 18300db7afdSDavid E. O'Brien __x._M_path_end[++__i] = __path[__j++]; 18400db7afdSDavid E. O'Brien __x._M_leaf_index = __i; 18500db7afdSDavid E. O'Brien } 18600db7afdSDavid E. O'Brien __x._M_path_directions = __dirns; 18700db7afdSDavid E. O'Brien _S_setbuf(__x); 18800db7afdSDavid E. O'Brien } 18900db7afdSDavid E. O'Brien 19000db7afdSDavid E. O'Brien // Specialized version of the above. Assumes that 19100db7afdSDavid E. O'Brien // the path cache is valid for the previous position. 19200db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 193f8a1b7d9SAlexander Kabaev void 194f8a1b7d9SAlexander Kabaev _Rope_iterator_base<_CharT, _Alloc>:: _S_setcache_for_incr(_Rope_iterator_base<_CharT,_Alloc> & __x)195f8a1b7d9SAlexander Kabaev _S_setcache_for_incr(_Rope_iterator_base<_CharT, _Alloc>& __x) 19600db7afdSDavid E. O'Brien { 19700db7afdSDavid E. O'Brien int __current_index = __x._M_leaf_index; 19800db7afdSDavid E. O'Brien const _RopeRep* __current_node = __x._M_path_end[__current_index]; 19900db7afdSDavid E. O'Brien size_t __len = __current_node->_M_size; 20000db7afdSDavid E. O'Brien size_t __node_start_pos = __x._M_leaf_pos; 20100db7afdSDavid E. O'Brien unsigned char __dirns = __x._M_path_directions; 20200db7afdSDavid E. O'Brien _Rope_RopeConcatenation<_CharT, _Alloc>* __c; 20300db7afdSDavid E. O'Brien 204f8a1b7d9SAlexander Kabaev if (__x._M_current_pos - __node_start_pos < __len) 205f8a1b7d9SAlexander Kabaev { 20600db7afdSDavid E. O'Brien /* More stuff in this leaf, we just didn't cache it. */ 20700db7afdSDavid E. O'Brien _S_setbuf(__x); 20800db7afdSDavid E. O'Brien return; 20900db7afdSDavid E. O'Brien } 21000db7afdSDavid E. O'Brien // node_start_pos is starting position of last_node. 211f8a1b7d9SAlexander Kabaev while (--__current_index >= 0) 212f8a1b7d9SAlexander Kabaev { 21300db7afdSDavid E. O'Brien if (!(__dirns & 1) /* Path turned left */) 21400db7afdSDavid E. O'Brien break; 21500db7afdSDavid E. O'Brien __current_node = __x._M_path_end[__current_index]; 21600db7afdSDavid E. O'Brien __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node; 21700db7afdSDavid E. O'Brien // Otherwise we were in the right child. Thus we should pop 21800db7afdSDavid E. O'Brien // the concatenation node. 21900db7afdSDavid E. O'Brien __node_start_pos -= __c->_M_left->_M_size; 22000db7afdSDavid E. O'Brien __dirns >>= 1; 22100db7afdSDavid E. O'Brien } 222f8a1b7d9SAlexander Kabaev if (__current_index < 0) 223f8a1b7d9SAlexander Kabaev { 22400db7afdSDavid E. O'Brien // We underflowed the cache. Punt. 22500db7afdSDavid E. O'Brien _S_setcache(__x); 22600db7afdSDavid E. O'Brien return; 22700db7afdSDavid E. O'Brien } 22800db7afdSDavid E. O'Brien __current_node = __x._M_path_end[__current_index]; 22900db7afdSDavid E. O'Brien __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node; 23000db7afdSDavid E. O'Brien // current_node is a concatenation node. We are positioned on the first 23100db7afdSDavid E. O'Brien // character in its right child. 23200db7afdSDavid E. O'Brien // node_start_pos is starting position of current_node. 23300db7afdSDavid E. O'Brien __node_start_pos += __c->_M_left->_M_size; 23400db7afdSDavid E. O'Brien __current_node = __c->_M_right; 23500db7afdSDavid E. O'Brien __x._M_path_end[++__current_index] = __current_node; 23600db7afdSDavid E. O'Brien __dirns |= 1; 237f8a1b7d9SAlexander Kabaev while (__detail::_S_concat == __current_node->_M_tag) 238f8a1b7d9SAlexander Kabaev { 23900db7afdSDavid E. O'Brien ++__current_index; 240f8a1b7d9SAlexander Kabaev if (int(_S_path_cache_len) == __current_index) 241f8a1b7d9SAlexander Kabaev { 24200db7afdSDavid E. O'Brien int __i; 243f8a1b7d9SAlexander Kabaev for (__i = 0; __i < int(_S_path_cache_len) - 1; __i++) 24400db7afdSDavid E. O'Brien __x._M_path_end[__i] = __x._M_path_end[__i+1]; 24500db7afdSDavid E. O'Brien --__current_index; 24600db7afdSDavid E. O'Brien } 24700db7afdSDavid E. O'Brien __current_node = 24800db7afdSDavid E. O'Brien ((_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node)->_M_left; 24900db7afdSDavid E. O'Brien __x._M_path_end[__current_index] = __current_node; 25000db7afdSDavid E. O'Brien __dirns <<= 1; 25100db7afdSDavid E. O'Brien // node_start_pos is unchanged. 25200db7afdSDavid E. O'Brien } 25300db7afdSDavid E. O'Brien __x._M_leaf_index = __current_index; 25400db7afdSDavid E. O'Brien __x._M_leaf_pos = __node_start_pos; 25500db7afdSDavid E. O'Brien __x._M_path_directions = __dirns; 25600db7afdSDavid E. O'Brien _S_setbuf(__x); 25700db7afdSDavid E. O'Brien } 25800db7afdSDavid E. O'Brien 25900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 260f8a1b7d9SAlexander Kabaev void 261f8a1b7d9SAlexander Kabaev _Rope_iterator_base<_CharT, _Alloc>:: _M_incr(size_t __n)262f8a1b7d9SAlexander Kabaev _M_incr(size_t __n) 263f8a1b7d9SAlexander Kabaev { 26400db7afdSDavid E. O'Brien _M_current_pos += __n; 265f8a1b7d9SAlexander Kabaev if (0 != _M_buf_ptr) 266f8a1b7d9SAlexander Kabaev { 26700db7afdSDavid E. O'Brien size_t __chars_left = _M_buf_end - _M_buf_ptr; 268f8a1b7d9SAlexander Kabaev if (__chars_left > __n) 26900db7afdSDavid E. O'Brien _M_buf_ptr += __n; 270f8a1b7d9SAlexander Kabaev else if (__chars_left == __n) 271f8a1b7d9SAlexander Kabaev { 27200db7afdSDavid E. O'Brien _M_buf_ptr += __n; 27300db7afdSDavid E. O'Brien _S_setcache_for_incr(*this); 27400db7afdSDavid E. O'Brien } 275f8a1b7d9SAlexander Kabaev else 276f8a1b7d9SAlexander Kabaev _M_buf_ptr = 0; 27700db7afdSDavid E. O'Brien } 27800db7afdSDavid E. O'Brien } 27900db7afdSDavid E. O'Brien 28000db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 281f8a1b7d9SAlexander Kabaev void 282f8a1b7d9SAlexander Kabaev _Rope_iterator_base<_CharT, _Alloc>:: _M_decr(size_t __n)283f8a1b7d9SAlexander Kabaev _M_decr(size_t __n) 284f8a1b7d9SAlexander Kabaev { 285f8a1b7d9SAlexander Kabaev if (0 != _M_buf_ptr) 286f8a1b7d9SAlexander Kabaev { 28700db7afdSDavid E. O'Brien size_t __chars_left = _M_buf_ptr - _M_buf_start; 288f8a1b7d9SAlexander Kabaev if (__chars_left >= __n) 28900db7afdSDavid E. O'Brien _M_buf_ptr -= __n; 290f8a1b7d9SAlexander Kabaev else 29100db7afdSDavid E. O'Brien _M_buf_ptr = 0; 29200db7afdSDavid E. O'Brien } 29300db7afdSDavid E. O'Brien _M_current_pos -= __n; 29400db7afdSDavid E. O'Brien } 29500db7afdSDavid E. O'Brien 29600db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 297f8a1b7d9SAlexander Kabaev void 298f8a1b7d9SAlexander Kabaev _Rope_iterator<_CharT, _Alloc>:: _M_check()299f8a1b7d9SAlexander Kabaev _M_check() 300f8a1b7d9SAlexander Kabaev { 301f8a1b7d9SAlexander Kabaev if (_M_root_rope->_M_tree_ptr != this->_M_root) 302f8a1b7d9SAlexander Kabaev { 30300db7afdSDavid E. O'Brien // _Rope was modified. Get things fixed up. 304ffeaf689SAlexander Kabaev _RopeRep::_S_unref(this->_M_root); 305ffeaf689SAlexander Kabaev this->_M_root = _M_root_rope->_M_tree_ptr; 306ffeaf689SAlexander Kabaev _RopeRep::_S_ref(this->_M_root); 307ffeaf689SAlexander Kabaev this->_M_buf_ptr = 0; 30800db7afdSDavid E. O'Brien } 30900db7afdSDavid E. O'Brien } 31000db7afdSDavid E. O'Brien 31100db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 31200db7afdSDavid E. O'Brien inline 313f8a1b7d9SAlexander Kabaev _Rope_const_iterator<_CharT, _Alloc>:: _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc> & __x)314f8a1b7d9SAlexander Kabaev _Rope_const_iterator(const _Rope_iterator<_CharT, _Alloc>& __x) 31500db7afdSDavid E. O'Brien : _Rope_iterator_base<_CharT, _Alloc>(__x) 31600db7afdSDavid E. O'Brien { } 31700db7afdSDavid E. O'Brien 31800db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 319f8a1b7d9SAlexander Kabaev inline 320f8a1b7d9SAlexander Kabaev _Rope_iterator<_CharT, _Alloc>:: _Rope_iterator(rope<_CharT,_Alloc> & __r,size_t __pos)321f8a1b7d9SAlexander Kabaev _Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos) 32200db7afdSDavid E. O'Brien : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos), 32300db7afdSDavid E. O'Brien _M_root_rope(&__r) 324f8a1b7d9SAlexander Kabaev { _RopeRep::_S_ref(this->_M_root); } 32500db7afdSDavid E. O'Brien 32600db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 32700db7afdSDavid E. O'Brien inline size_t 328f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_char_ptr_len(const _CharT * __s)329f8a1b7d9SAlexander Kabaev _S_char_ptr_len(const _CharT* __s) 33000db7afdSDavid E. O'Brien { 33100db7afdSDavid E. O'Brien const _CharT* __p = __s; 33200db7afdSDavid E. O'Brien 333f8a1b7d9SAlexander Kabaev while (!_S_is0(*__p)) 334f8a1b7d9SAlexander Kabaev ++__p; 33500db7afdSDavid E. O'Brien return (__p - __s); 33600db7afdSDavid E. O'Brien } 33700db7afdSDavid E. O'Brien 33800db7afdSDavid E. O'Brien 33900db7afdSDavid E. O'Brien #ifndef __GC 34000db7afdSDavid E. O'Brien 34100db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 342f8a1b7d9SAlexander Kabaev inline void 343f8a1b7d9SAlexander Kabaev _Rope_RopeRep<_CharT, _Alloc>:: _M_free_c_string()344f8a1b7d9SAlexander Kabaev _M_free_c_string() 34500db7afdSDavid E. O'Brien { 34600db7afdSDavid E. O'Brien _CharT* __cstr = _M_c_string; 347f8a1b7d9SAlexander Kabaev if (0 != __cstr) 348f8a1b7d9SAlexander Kabaev { 349ffeaf689SAlexander Kabaev size_t __size = this->_M_size + 1; 350f8a1b7d9SAlexander Kabaev _Destroy(__cstr, __cstr + __size, get_allocator()); 351ffeaf689SAlexander Kabaev this->_Data_deallocate(__cstr, __size); 35200db7afdSDavid E. O'Brien } 35300db7afdSDavid E. O'Brien } 35400db7afdSDavid E. O'Brien 35500db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 356f8a1b7d9SAlexander Kabaev inline void 357f8a1b7d9SAlexander Kabaev _Rope_RopeRep<_CharT, _Alloc>:: _S_free_string(_CharT * __s,size_t __n,allocator_type __a)358f8a1b7d9SAlexander Kabaev _S_free_string(_CharT* __s, size_t __n, allocator_type __a) 35900db7afdSDavid E. O'Brien { 360f8a1b7d9SAlexander Kabaev if (!_S_is_basic_char_type((_CharT*)0)) 361f8a1b7d9SAlexander Kabaev _Destroy(__s, __s + __n, __a); 36200db7afdSDavid E. O'Brien 363f8a1b7d9SAlexander Kabaev // This has to be a static member, so this gets a bit messy 364f8a1b7d9SAlexander Kabaev __a.deallocate(__s, 365f8a1b7d9SAlexander Kabaev _Rope_RopeLeaf<_CharT, _Alloc>::_S_rounded_up_size(__n)); 366f8a1b7d9SAlexander Kabaev } 36700db7afdSDavid E. O'Brien 36800db7afdSDavid E. O'Brien // There are several reasons for not doing this with virtual destructors 36900db7afdSDavid E. O'Brien // and a class specific delete operator: 37000db7afdSDavid E. O'Brien // - A class specific delete operator can't easily get access to 37100db7afdSDavid E. O'Brien // allocator instances if we need them. 37200db7afdSDavid E. O'Brien // - Any virtual function would need a 4 or byte vtable pointer; 37300db7afdSDavid E. O'Brien // this only requires a one byte tag per object. 37400db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 375f8a1b7d9SAlexander Kabaev void 376f8a1b7d9SAlexander Kabaev _Rope_RopeRep<_CharT, _Alloc>:: _M_free_tree()377f8a1b7d9SAlexander Kabaev _M_free_tree() 37800db7afdSDavid E. O'Brien { 379f8a1b7d9SAlexander Kabaev switch(_M_tag) 380f8a1b7d9SAlexander Kabaev { 381f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 38200db7afdSDavid E. O'Brien { 38300db7afdSDavid E. O'Brien _Rope_RopeLeaf<_CharT, _Alloc>* __l 38400db7afdSDavid E. O'Brien = (_Rope_RopeLeaf<_CharT, _Alloc>*)this; 3851fdc87e7SRui Paulo __l->template _Rope_RopeLeaf<_CharT, _Alloc>::~_Rope_RopeLeaf(); 38600db7afdSDavid E. O'Brien _L_deallocate(__l, 1); 38700db7afdSDavid E. O'Brien break; 38800db7afdSDavid E. O'Brien } 389f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 39000db7afdSDavid E. O'Brien { 39100db7afdSDavid E. O'Brien _Rope_RopeConcatenation<_CharT,_Alloc>* __c 39200db7afdSDavid E. O'Brien = (_Rope_RopeConcatenation<_CharT, _Alloc>*)this; 3931fdc87e7SRui Paulo __c->template _Rope_RopeConcatenation<_CharT, _Alloc>:: 39400db7afdSDavid E. O'Brien ~_Rope_RopeConcatenation(); 39500db7afdSDavid E. O'Brien _C_deallocate(__c, 1); 39600db7afdSDavid E. O'Brien break; 39700db7afdSDavid E. O'Brien } 398f8a1b7d9SAlexander Kabaev case __detail::_S_function: 39900db7afdSDavid E. O'Brien { 40000db7afdSDavid E. O'Brien _Rope_RopeFunction<_CharT, _Alloc>* __f 40100db7afdSDavid E. O'Brien = (_Rope_RopeFunction<_CharT, _Alloc>*)this; 4021fdc87e7SRui Paulo __f->template _Rope_RopeFunction<_CharT, _Alloc>::~_Rope_RopeFunction(); 40300db7afdSDavid E. O'Brien _F_deallocate(__f, 1); 40400db7afdSDavid E. O'Brien break; 40500db7afdSDavid E. O'Brien } 406f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 40700db7afdSDavid E. O'Brien { 40800db7afdSDavid E. O'Brien _Rope_RopeSubstring<_CharT, _Alloc>* __ss = 40900db7afdSDavid E. O'Brien (_Rope_RopeSubstring<_CharT, _Alloc>*)this; 4101fdc87e7SRui Paulo __ss->template _Rope_RopeSubstring<_CharT, _Alloc>:: 41100db7afdSDavid E. O'Brien ~_Rope_RopeSubstring(); 41200db7afdSDavid E. O'Brien _S_deallocate(__ss, 1); 41300db7afdSDavid E. O'Brien break; 41400db7afdSDavid E. O'Brien } 41500db7afdSDavid E. O'Brien } 41600db7afdSDavid E. O'Brien } 41700db7afdSDavid E. O'Brien #else 41800db7afdSDavid E. O'Brien 41900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 420f8a1b7d9SAlexander Kabaev inline void 421f8a1b7d9SAlexander Kabaev _Rope_RopeRep<_CharT, _Alloc>:: _S_free_string(const _CharT *,size_t,allocator_type)422f8a1b7d9SAlexander Kabaev _S_free_string(const _CharT*, size_t, allocator_type) 42300db7afdSDavid E. O'Brien { } 42400db7afdSDavid E. O'Brien 42500db7afdSDavid E. O'Brien #endif 42600db7afdSDavid E. O'Brien 42700db7afdSDavid E. O'Brien // Concatenate a C string onto a leaf rope by copying the rope data. 42800db7afdSDavid E. O'Brien // Used for short ropes. 42900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 43000db7afdSDavid E. O'Brien typename rope<_CharT, _Alloc>::_RopeLeaf* 431f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_leaf_concat_char_iter(_RopeLeaf * __r,const _CharT * __iter,size_t __len)432f8a1b7d9SAlexander Kabaev _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, size_t __len) 43300db7afdSDavid E. O'Brien { 43400db7afdSDavid E. O'Brien size_t __old_len = __r->_M_size; 43500db7afdSDavid E. O'Brien _CharT* __new_data = (_CharT*) 4361fdc87e7SRui Paulo _Rope_rep_base<_CharT, _Alloc>::_Data_allocate(_S_rounded_up_size(__old_len + __len)); 43700db7afdSDavid E. O'Brien _RopeLeaf* __result; 43800db7afdSDavid E. O'Brien 43900db7afdSDavid E. O'Brien uninitialized_copy_n(__r->_M_data, __old_len, __new_data); 44000db7afdSDavid E. O'Brien uninitialized_copy_n(__iter, __len, __new_data + __old_len); 44100db7afdSDavid E. O'Brien _S_cond_store_eos(__new_data[__old_len + __len]); 442f8a1b7d9SAlexander Kabaev try 443f8a1b7d9SAlexander Kabaev { 44400db7afdSDavid E. O'Brien __result = _S_new_RopeLeaf(__new_data, __old_len + __len, 44500db7afdSDavid E. O'Brien __r->get_allocator()); 44600db7afdSDavid E. O'Brien } 44700db7afdSDavid E. O'Brien catch(...) 44800db7afdSDavid E. O'Brien { 44900db7afdSDavid E. O'Brien _RopeRep::__STL_FREE_STRING(__new_data, __old_len + __len, 45000db7afdSDavid E. O'Brien __r->get_allocator()); 45100db7afdSDavid E. O'Brien __throw_exception_again; 45200db7afdSDavid E. O'Brien } 45300db7afdSDavid E. O'Brien return __result; 45400db7afdSDavid E. O'Brien } 45500db7afdSDavid E. O'Brien 45600db7afdSDavid E. O'Brien #ifndef __GC 45700db7afdSDavid E. O'Brien // As above, but it's OK to clobber original if refcount is 1 45800db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 45900db7afdSDavid E. O'Brien typename rope<_CharT,_Alloc>::_RopeLeaf* 460f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_destr_leaf_concat_char_iter(_RopeLeaf * __r,const _CharT * __iter,size_t __len)461f8a1b7d9SAlexander Kabaev _S_destr_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter, 462f8a1b7d9SAlexander Kabaev size_t __len) 46300db7afdSDavid E. O'Brien { 46400db7afdSDavid E. O'Brien if (__r->_M_ref_count > 1) 46500db7afdSDavid E. O'Brien return _S_leaf_concat_char_iter(__r, __iter, __len); 46600db7afdSDavid E. O'Brien size_t __old_len = __r->_M_size; 467f8a1b7d9SAlexander Kabaev if (_S_allocated_capacity(__old_len) >= __old_len + __len) 468f8a1b7d9SAlexander Kabaev { 46900db7afdSDavid E. O'Brien // The space has been partially initialized for the standard 47000db7afdSDavid E. O'Brien // character types. But that doesn't matter for those types. 47100db7afdSDavid E. O'Brien uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len); 472f8a1b7d9SAlexander Kabaev if (_S_is_basic_char_type((_CharT*)0)) 47300db7afdSDavid E. O'Brien _S_cond_store_eos(__r->_M_data[__old_len + __len]); 474f8a1b7d9SAlexander Kabaev else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string) 475f8a1b7d9SAlexander Kabaev { 47600db7afdSDavid E. O'Brien __r->_M_free_c_string(); 47700db7afdSDavid E. O'Brien __r->_M_c_string = 0; 47800db7afdSDavid E. O'Brien } 47900db7afdSDavid E. O'Brien __r->_M_size = __old_len + __len; 48000db7afdSDavid E. O'Brien __r->_M_ref_count = 2; 48100db7afdSDavid E. O'Brien return __r; 482f8a1b7d9SAlexander Kabaev } 483f8a1b7d9SAlexander Kabaev else 484f8a1b7d9SAlexander Kabaev { 48500db7afdSDavid E. O'Brien _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len); 48600db7afdSDavid E. O'Brien return __result; 48700db7afdSDavid E. O'Brien } 48800db7afdSDavid E. O'Brien } 48900db7afdSDavid E. O'Brien #endif 49000db7afdSDavid E. O'Brien 49100db7afdSDavid E. O'Brien // Assumes left and right are not 0. 49200db7afdSDavid E. O'Brien // Does not increment (nor decrement on exception) child reference counts. 49300db7afdSDavid E. O'Brien // Result has ref count 1. 49400db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 49500db7afdSDavid E. O'Brien typename rope<_CharT, _Alloc>::_RopeRep* 496f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_tree_concat(_RopeRep * __left,_RopeRep * __right)497f8a1b7d9SAlexander Kabaev _S_tree_concat(_RopeRep* __left, _RopeRep* __right) 49800db7afdSDavid E. O'Brien { 49900db7afdSDavid E. O'Brien _RopeConcatenation* __result = _S_new_RopeConcatenation(__left, __right, 500f8a1b7d9SAlexander Kabaev __left-> 501f8a1b7d9SAlexander Kabaev get_allocator()); 50200db7afdSDavid E. O'Brien size_t __depth = __result->_M_depth; 50300db7afdSDavid E. O'Brien 504f8a1b7d9SAlexander Kabaev if (__depth > 20 505f8a1b7d9SAlexander Kabaev && (__result->_M_size < 1000 506f8a1b7d9SAlexander Kabaev || __depth > size_t(__detail::_S_max_rope_depth))) 50700db7afdSDavid E. O'Brien { 50800db7afdSDavid E. O'Brien _RopeRep* __balanced; 50900db7afdSDavid E. O'Brien 51000db7afdSDavid E. O'Brien try 51100db7afdSDavid E. O'Brien { 51200db7afdSDavid E. O'Brien __balanced = _S_balance(__result); 51300db7afdSDavid E. O'Brien __result->_M_unref_nonnil(); 51400db7afdSDavid E. O'Brien } 51500db7afdSDavid E. O'Brien catch(...) 51600db7afdSDavid E. O'Brien { 51700db7afdSDavid E. O'Brien _C_deallocate(__result,1); 51800db7afdSDavid E. O'Brien __throw_exception_again; 51900db7afdSDavid E. O'Brien } 52000db7afdSDavid E. O'Brien // In case of exception, we need to deallocate 52100db7afdSDavid E. O'Brien // otherwise dangling result node. But caller 52200db7afdSDavid E. O'Brien // still owns its children. Thus unref is 52300db7afdSDavid E. O'Brien // inappropriate. 52400db7afdSDavid E. O'Brien return __balanced; 52500db7afdSDavid E. O'Brien } 52600db7afdSDavid E. O'Brien else 52700db7afdSDavid E. O'Brien return __result; 52800db7afdSDavid E. O'Brien } 52900db7afdSDavid E. O'Brien 53000db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 531f8a1b7d9SAlexander Kabaev typename rope<_CharT, _Alloc>::_RopeRep* 532f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_concat_char_iter(_RopeRep * __r,const _CharT * __s,size_t __slen)533f8a1b7d9SAlexander Kabaev _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, size_t __slen) 53400db7afdSDavid E. O'Brien { 53500db7afdSDavid E. O'Brien _RopeRep* __result; 536f8a1b7d9SAlexander Kabaev if (0 == __slen) 537f8a1b7d9SAlexander Kabaev { 53800db7afdSDavid E. O'Brien _S_ref(__r); 53900db7afdSDavid E. O'Brien return __r; 54000db7afdSDavid E. O'Brien } 54100db7afdSDavid E. O'Brien if (0 == __r) 54200db7afdSDavid E. O'Brien return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, 54300db7afdSDavid E. O'Brien __r->get_allocator()); 544f8a1b7d9SAlexander Kabaev if (__r->_M_tag == __detail::_S_leaf 545f8a1b7d9SAlexander Kabaev && __r->_M_size + __slen <= size_t(_S_copy_max)) 546f8a1b7d9SAlexander Kabaev { 54700db7afdSDavid E. O'Brien __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen); 54800db7afdSDavid E. O'Brien return __result; 54900db7afdSDavid E. O'Brien } 550f8a1b7d9SAlexander Kabaev if (__detail::_S_concat == __r->_M_tag 551f8a1b7d9SAlexander Kabaev && __detail::_S_leaf == ((_RopeConcatenation*) __r)->_M_right->_M_tag) 552f8a1b7d9SAlexander Kabaev { 55300db7afdSDavid E. O'Brien _RopeLeaf* __right = 55400db7afdSDavid E. O'Brien (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right); 555f8a1b7d9SAlexander Kabaev if (__right->_M_size + __slen <= size_t(_S_copy_max)) 556f8a1b7d9SAlexander Kabaev { 55700db7afdSDavid E. O'Brien _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left; 55800db7afdSDavid E. O'Brien _RopeRep* __nright = 55900db7afdSDavid E. O'Brien _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen); 56000db7afdSDavid E. O'Brien __left->_M_ref_nonnil(); 561f8a1b7d9SAlexander Kabaev try 562f8a1b7d9SAlexander Kabaev { __result = _S_tree_concat(__left, __nright); } 56300db7afdSDavid E. O'Brien catch(...) 56400db7afdSDavid E. O'Brien { 56500db7afdSDavid E. O'Brien _S_unref(__left); 56600db7afdSDavid E. O'Brien _S_unref(__nright); 56700db7afdSDavid E. O'Brien __throw_exception_again; 56800db7afdSDavid E. O'Brien } 56900db7afdSDavid E. O'Brien return __result; 57000db7afdSDavid E. O'Brien } 57100db7afdSDavid E. O'Brien } 57200db7afdSDavid E. O'Brien _RopeRep* __nright = 57300db7afdSDavid E. O'Brien __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator()); 574f8a1b7d9SAlexander Kabaev try 575f8a1b7d9SAlexander Kabaev { 57600db7afdSDavid E. O'Brien __r->_M_ref_nonnil(); 57700db7afdSDavid E. O'Brien __result = _S_tree_concat(__r, __nright); 57800db7afdSDavid E. O'Brien } 57900db7afdSDavid E. O'Brien catch(...) 58000db7afdSDavid E. O'Brien { 58100db7afdSDavid E. O'Brien _S_unref(__r); 58200db7afdSDavid E. O'Brien _S_unref(__nright); 58300db7afdSDavid E. O'Brien __throw_exception_again; 58400db7afdSDavid E. O'Brien } 58500db7afdSDavid E. O'Brien return __result; 58600db7afdSDavid E. O'Brien } 58700db7afdSDavid E. O'Brien 58800db7afdSDavid E. O'Brien #ifndef __GC 58900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 59000db7afdSDavid E. O'Brien typename rope<_CharT,_Alloc>::_RopeRep* 591f8a1b7d9SAlexander Kabaev rope<_CharT,_Alloc>:: _S_destr_concat_char_iter(_RopeRep * __r,const _CharT * __s,size_t __slen)592f8a1b7d9SAlexander Kabaev _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s, size_t __slen) 59300db7afdSDavid E. O'Brien { 59400db7afdSDavid E. O'Brien _RopeRep* __result; 59500db7afdSDavid E. O'Brien if (0 == __r) 59600db7afdSDavid E. O'Brien return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, 59700db7afdSDavid E. O'Brien __r->get_allocator()); 59800db7afdSDavid E. O'Brien size_t __count = __r->_M_ref_count; 59900db7afdSDavid E. O'Brien size_t __orig_size = __r->_M_size; 600f8a1b7d9SAlexander Kabaev if (__count > 1) 601f8a1b7d9SAlexander Kabaev return _S_concat_char_iter(__r, __s, __slen); 602f8a1b7d9SAlexander Kabaev if (0 == __slen) 603f8a1b7d9SAlexander Kabaev { 60400db7afdSDavid E. O'Brien __r->_M_ref_count = 2; // One more than before 60500db7afdSDavid E. O'Brien return __r; 60600db7afdSDavid E. O'Brien } 607f8a1b7d9SAlexander Kabaev if (__orig_size + __slen <= size_t(_S_copy_max) 608f8a1b7d9SAlexander Kabaev && __detail::_S_leaf == __r->_M_tag) 609f8a1b7d9SAlexander Kabaev { 610f8a1b7d9SAlexander Kabaev __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s, 611f8a1b7d9SAlexander Kabaev __slen); 61200db7afdSDavid E. O'Brien return __result; 61300db7afdSDavid E. O'Brien } 614f8a1b7d9SAlexander Kabaev if (__detail::_S_concat == __r->_M_tag) 615f8a1b7d9SAlexander Kabaev { 616f8a1b7d9SAlexander Kabaev _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*) 617f8a1b7d9SAlexander Kabaev __r)->_M_right); 618f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __right->_M_tag 619f8a1b7d9SAlexander Kabaev && __right->_M_size + __slen <= size_t(_S_copy_max)) 620f8a1b7d9SAlexander Kabaev { 62100db7afdSDavid E. O'Brien _RopeRep* __new_right = 62200db7afdSDavid E. O'Brien _S_destr_leaf_concat_char_iter(__right, __s, __slen); 62300db7afdSDavid E. O'Brien if (__right == __new_right) 62400db7afdSDavid E. O'Brien __new_right->_M_ref_count = 1; 62500db7afdSDavid E. O'Brien else 62600db7afdSDavid E. O'Brien __right->_M_unref_nonnil(); 62700db7afdSDavid E. O'Brien __r->_M_ref_count = 2; // One more than before. 62800db7afdSDavid E. O'Brien ((_RopeConcatenation*)__r)->_M_right = __new_right; 62900db7afdSDavid E. O'Brien __r->_M_size = __orig_size + __slen; 630f8a1b7d9SAlexander Kabaev if (0 != __r->_M_c_string) 631f8a1b7d9SAlexander Kabaev { 63200db7afdSDavid E. O'Brien __r->_M_free_c_string(); 63300db7afdSDavid E. O'Brien __r->_M_c_string = 0; 63400db7afdSDavid E. O'Brien } 63500db7afdSDavid E. O'Brien return __r; 63600db7afdSDavid E. O'Brien } 63700db7afdSDavid E. O'Brien } 63800db7afdSDavid E. O'Brien _RopeRep* __right = 63900db7afdSDavid E. O'Brien __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator()); 64000db7afdSDavid E. O'Brien __r->_M_ref_nonnil(); 641f8a1b7d9SAlexander Kabaev try 642f8a1b7d9SAlexander Kabaev { __result = _S_tree_concat(__r, __right); } 64300db7afdSDavid E. O'Brien catch(...) 64400db7afdSDavid E. O'Brien { 64500db7afdSDavid E. O'Brien _S_unref(__r); 64600db7afdSDavid E. O'Brien _S_unref(__right); 64700db7afdSDavid E. O'Brien __throw_exception_again; 64800db7afdSDavid E. O'Brien } 64900db7afdSDavid E. O'Brien return __result; 65000db7afdSDavid E. O'Brien } 65100db7afdSDavid E. O'Brien #endif /* !__GC */ 65200db7afdSDavid E. O'Brien 65300db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 65400db7afdSDavid E. O'Brien typename rope<_CharT, _Alloc>::_RopeRep* 655f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_concat(_RopeRep * __left,_RopeRep * __right)656f8a1b7d9SAlexander Kabaev _S_concat(_RopeRep* __left, _RopeRep* __right) 65700db7afdSDavid E. O'Brien { 658f8a1b7d9SAlexander Kabaev if (0 == __left) 659f8a1b7d9SAlexander Kabaev { 66000db7afdSDavid E. O'Brien _S_ref(__right); 66100db7afdSDavid E. O'Brien return __right; 66200db7afdSDavid E. O'Brien } 663f8a1b7d9SAlexander Kabaev if (0 == __right) 664f8a1b7d9SAlexander Kabaev { 66500db7afdSDavid E. O'Brien __left->_M_ref_nonnil(); 66600db7afdSDavid E. O'Brien return __left; 66700db7afdSDavid E. O'Brien } 668f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __right->_M_tag) 669f8a1b7d9SAlexander Kabaev { 670f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __left->_M_tag) 671f8a1b7d9SAlexander Kabaev { 672f8a1b7d9SAlexander Kabaev if (__right->_M_size + __left->_M_size <= size_t(_S_copy_max)) 67300db7afdSDavid E. O'Brien return _S_leaf_concat_char_iter((_RopeLeaf*)__left, 67400db7afdSDavid E. O'Brien ((_RopeLeaf*)__right)->_M_data, 67500db7afdSDavid E. O'Brien __right->_M_size); 67600db7afdSDavid E. O'Brien } 677f8a1b7d9SAlexander Kabaev else if (__detail::_S_concat == __left->_M_tag 678f8a1b7d9SAlexander Kabaev && __detail::_S_leaf == ((_RopeConcatenation*) 679f8a1b7d9SAlexander Kabaev __left)->_M_right->_M_tag) 680f8a1b7d9SAlexander Kabaev { 68100db7afdSDavid E. O'Brien _RopeLeaf* __leftright = 68200db7afdSDavid E. O'Brien (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right); 683f8a1b7d9SAlexander Kabaev if (__leftright->_M_size 684f8a1b7d9SAlexander Kabaev + __right->_M_size <= size_t(_S_copy_max)) 685f8a1b7d9SAlexander Kabaev { 68600db7afdSDavid E. O'Brien _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left; 68700db7afdSDavid E. O'Brien _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright, 688f8a1b7d9SAlexander Kabaev ((_RopeLeaf*) 689f8a1b7d9SAlexander Kabaev __right)-> 690f8a1b7d9SAlexander Kabaev _M_data, 69100db7afdSDavid E. O'Brien __right->_M_size); 69200db7afdSDavid E. O'Brien __leftleft->_M_ref_nonnil(); 693f8a1b7d9SAlexander Kabaev try 694f8a1b7d9SAlexander Kabaev { return(_S_tree_concat(__leftleft, __rest)); } 69500db7afdSDavid E. O'Brien catch(...) 69600db7afdSDavid E. O'Brien { 69700db7afdSDavid E. O'Brien _S_unref(__leftleft); 69800db7afdSDavid E. O'Brien _S_unref(__rest); 69900db7afdSDavid E. O'Brien __throw_exception_again; 70000db7afdSDavid E. O'Brien } 70100db7afdSDavid E. O'Brien } 70200db7afdSDavid E. O'Brien } 70300db7afdSDavid E. O'Brien } 70400db7afdSDavid E. O'Brien __left->_M_ref_nonnil(); 70500db7afdSDavid E. O'Brien __right->_M_ref_nonnil(); 706f8a1b7d9SAlexander Kabaev try 707f8a1b7d9SAlexander Kabaev { return(_S_tree_concat(__left, __right)); } 70800db7afdSDavid E. O'Brien catch(...) 70900db7afdSDavid E. O'Brien { 71000db7afdSDavid E. O'Brien _S_unref(__left); 71100db7afdSDavid E. O'Brien _S_unref(__right); 71200db7afdSDavid E. O'Brien __throw_exception_again; 71300db7afdSDavid E. O'Brien } 71400db7afdSDavid E. O'Brien } 71500db7afdSDavid E. O'Brien 71600db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 71700db7afdSDavid E. O'Brien typename rope<_CharT, _Alloc>::_RopeRep* 718f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_substring(_RopeRep * __base,size_t __start,size_t __endp1)719f8a1b7d9SAlexander Kabaev _S_substring(_RopeRep* __base, size_t __start, size_t __endp1) 72000db7afdSDavid E. O'Brien { 721f8a1b7d9SAlexander Kabaev if (0 == __base) 722f8a1b7d9SAlexander Kabaev return 0; 72300db7afdSDavid E. O'Brien size_t __len = __base->_M_size; 72400db7afdSDavid E. O'Brien size_t __adj_endp1; 72500db7afdSDavid E. O'Brien const size_t __lazy_threshold = 128; 72600db7afdSDavid E. O'Brien 727f8a1b7d9SAlexander Kabaev if (__endp1 >= __len) 728f8a1b7d9SAlexander Kabaev { 729f8a1b7d9SAlexander Kabaev if (0 == __start) 730f8a1b7d9SAlexander Kabaev { 73100db7afdSDavid E. O'Brien __base->_M_ref_nonnil(); 73200db7afdSDavid E. O'Brien return __base; 733f8a1b7d9SAlexander Kabaev } 734f8a1b7d9SAlexander Kabaev else 73500db7afdSDavid E. O'Brien __adj_endp1 = __len; 736f8a1b7d9SAlexander Kabaev 73700db7afdSDavid E. O'Brien } 738f8a1b7d9SAlexander Kabaev else 73900db7afdSDavid E. O'Brien __adj_endp1 = __endp1; 740f8a1b7d9SAlexander Kabaev 741f8a1b7d9SAlexander Kabaev switch(__base->_M_tag) 742f8a1b7d9SAlexander Kabaev { 743f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 74400db7afdSDavid E. O'Brien { 74500db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__base; 74600db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 74700db7afdSDavid E. O'Brien _RopeRep* __right = __c->_M_right; 74800db7afdSDavid E. O'Brien size_t __left_len = __left->_M_size; 74900db7afdSDavid E. O'Brien _RopeRep* __result; 75000db7afdSDavid E. O'Brien 751f8a1b7d9SAlexander Kabaev if (__adj_endp1 <= __left_len) 75200db7afdSDavid E. O'Brien return _S_substring(__left, __start, __endp1); 753f8a1b7d9SAlexander Kabaev else if (__start >= __left_len) 75400db7afdSDavid E. O'Brien return _S_substring(__right, __start - __left_len, 75500db7afdSDavid E. O'Brien __adj_endp1 - __left_len); 756f8a1b7d9SAlexander Kabaev _Self_destruct_ptr __left_result(_S_substring(__left, 757f8a1b7d9SAlexander Kabaev __start, 758f8a1b7d9SAlexander Kabaev __left_len)); 759f8a1b7d9SAlexander Kabaev _Self_destruct_ptr __right_result(_S_substring(__right, 0, 760f8a1b7d9SAlexander Kabaev __endp1 761f8a1b7d9SAlexander Kabaev - __left_len)); 76200db7afdSDavid E. O'Brien __result = _S_concat(__left_result, __right_result); 76300db7afdSDavid E. O'Brien return __result; 76400db7afdSDavid E. O'Brien } 765f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 76600db7afdSDavid E. O'Brien { 76700db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*)__base; 76800db7afdSDavid E. O'Brien _RopeLeaf* __result; 76900db7afdSDavid E. O'Brien size_t __result_len; 770f8a1b7d9SAlexander Kabaev if (__start >= __adj_endp1) 771f8a1b7d9SAlexander Kabaev return 0; 77200db7afdSDavid E. O'Brien __result_len = __adj_endp1 - __start; 773f8a1b7d9SAlexander Kabaev if (__result_len > __lazy_threshold) 774f8a1b7d9SAlexander Kabaev goto lazy; 77500db7afdSDavid E. O'Brien #ifdef __GC 77600db7afdSDavid E. O'Brien const _CharT* __section = __l->_M_data + __start; 77700db7afdSDavid E. O'Brien __result = _S_new_RopeLeaf(__section, __result_len, 77800db7afdSDavid E. O'Brien __base->get_allocator()); 77900db7afdSDavid E. O'Brien __result->_M_c_string = 0; // Not eos terminated. 78000db7afdSDavid E. O'Brien #else 78100db7afdSDavid E. O'Brien // We should sometimes create substring node instead. 782f8a1b7d9SAlexander Kabaev __result = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__l->_M_data + __start, 783f8a1b7d9SAlexander Kabaev __result_len, 784f8a1b7d9SAlexander Kabaev __base-> 785f8a1b7d9SAlexander Kabaev get_allocator()); 78600db7afdSDavid E. O'Brien #endif 78700db7afdSDavid E. O'Brien return __result; 78800db7afdSDavid E. O'Brien } 789f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 79000db7afdSDavid E. O'Brien // Avoid introducing multiple layers of substring nodes. 79100db7afdSDavid E. O'Brien { 79200db7afdSDavid E. O'Brien _RopeSubstring* __old = (_RopeSubstring*)__base; 79300db7afdSDavid E. O'Brien size_t __result_len; 794f8a1b7d9SAlexander Kabaev if (__start >= __adj_endp1) 795f8a1b7d9SAlexander Kabaev return 0; 79600db7afdSDavid E. O'Brien __result_len = __adj_endp1 - __start; 797f8a1b7d9SAlexander Kabaev if (__result_len > __lazy_threshold) 798f8a1b7d9SAlexander Kabaev { 79900db7afdSDavid E. O'Brien _RopeSubstring* __result = 80000db7afdSDavid E. O'Brien _S_new_RopeSubstring(__old->_M_base, 80100db7afdSDavid E. O'Brien __start + __old->_M_start, 80200db7afdSDavid E. O'Brien __adj_endp1 - __start, 80300db7afdSDavid E. O'Brien __base->get_allocator()); 80400db7afdSDavid E. O'Brien return __result; 80500db7afdSDavid E. O'Brien 80600db7afdSDavid E. O'Brien } // *** else fall through: *** 80700db7afdSDavid E. O'Brien } 808f8a1b7d9SAlexander Kabaev case __detail::_S_function: 80900db7afdSDavid E. O'Brien { 81000db7afdSDavid E. O'Brien _RopeFunction* __f = (_RopeFunction*)__base; 81100db7afdSDavid E. O'Brien _CharT* __section; 81200db7afdSDavid E. O'Brien size_t __result_len; 813f8a1b7d9SAlexander Kabaev if (__start >= __adj_endp1) 814f8a1b7d9SAlexander Kabaev return 0; 81500db7afdSDavid E. O'Brien __result_len = __adj_endp1 - __start; 81600db7afdSDavid E. O'Brien 817f8a1b7d9SAlexander Kabaev if (__result_len > __lazy_threshold) 818f8a1b7d9SAlexander Kabaev goto lazy; 81900db7afdSDavid E. O'Brien __section = (_CharT*) 8201fdc87e7SRui Paulo _Rope_rep_base<_CharT, _Alloc>::_Data_allocate(_S_rounded_up_size(__result_len)); 821f8a1b7d9SAlexander Kabaev try 822f8a1b7d9SAlexander Kabaev { (*(__f->_M_fn))(__start, __result_len, __section); } 82300db7afdSDavid E. O'Brien catch(...) 82400db7afdSDavid E. O'Brien { 825f8a1b7d9SAlexander Kabaev _RopeRep::__STL_FREE_STRING(__section, __result_len, 826f8a1b7d9SAlexander Kabaev __base->get_allocator()); 82700db7afdSDavid E. O'Brien __throw_exception_again; 82800db7afdSDavid E. O'Brien } 82900db7afdSDavid E. O'Brien _S_cond_store_eos(__section[__result_len]); 83000db7afdSDavid E. O'Brien return _S_new_RopeLeaf(__section, __result_len, 83100db7afdSDavid E. O'Brien __base->get_allocator()); 83200db7afdSDavid E. O'Brien } 83300db7afdSDavid E. O'Brien } 83400db7afdSDavid E. O'Brien lazy: 83500db7afdSDavid E. O'Brien { 83600db7afdSDavid E. O'Brien // Create substring node. 83700db7afdSDavid E. O'Brien return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start, 83800db7afdSDavid E. O'Brien __base->get_allocator()); 83900db7afdSDavid E. O'Brien } 84000db7afdSDavid E. O'Brien } 84100db7afdSDavid E. O'Brien 84200db7afdSDavid E. O'Brien template<class _CharT> 843f8a1b7d9SAlexander Kabaev class _Rope_flatten_char_consumer 844f8a1b7d9SAlexander Kabaev : public _Rope_char_consumer<_CharT> 845f8a1b7d9SAlexander Kabaev { 84600db7afdSDavid E. O'Brien private: 84700db7afdSDavid E. O'Brien _CharT* _M_buf_ptr; 84800db7afdSDavid E. O'Brien public: 84900db7afdSDavid E. O'Brien _Rope_flatten_char_consumer(_CharT * __buffer)850f8a1b7d9SAlexander Kabaev _Rope_flatten_char_consumer(_CharT* __buffer) 851f8a1b7d9SAlexander Kabaev { _M_buf_ptr = __buffer; }; 852f8a1b7d9SAlexander Kabaev ~_Rope_flatten_char_consumer()85300db7afdSDavid E. O'Brien ~_Rope_flatten_char_consumer() {} 854f8a1b7d9SAlexander Kabaev 855f8a1b7d9SAlexander Kabaev bool operator()856f8a1b7d9SAlexander Kabaev operator()(const _CharT* __leaf, size_t __n) 857f8a1b7d9SAlexander Kabaev { 85800db7afdSDavid E. O'Brien uninitialized_copy_n(__leaf, __n, _M_buf_ptr); 85900db7afdSDavid E. O'Brien _M_buf_ptr += __n; 86000db7afdSDavid E. O'Brien return true; 86100db7afdSDavid E. O'Brien } 86200db7afdSDavid E. O'Brien }; 86300db7afdSDavid E. O'Brien 86400db7afdSDavid E. O'Brien template<class _CharT> 865f8a1b7d9SAlexander Kabaev class _Rope_find_char_char_consumer 866f8a1b7d9SAlexander Kabaev : public _Rope_char_consumer<_CharT> 867f8a1b7d9SAlexander Kabaev { 86800db7afdSDavid E. O'Brien private: 86900db7afdSDavid E. O'Brien _CharT _M_pattern; 87000db7afdSDavid E. O'Brien public: 87100db7afdSDavid E. O'Brien size_t _M_count; // Number of nonmatching characters 872f8a1b7d9SAlexander Kabaev _Rope_find_char_char_consumer(_CharT __p)87300db7afdSDavid E. O'Brien _Rope_find_char_char_consumer(_CharT __p) 87400db7afdSDavid E. O'Brien : _M_pattern(__p), _M_count(0) {} 875f8a1b7d9SAlexander Kabaev ~_Rope_find_char_char_consumer()87600db7afdSDavid E. O'Brien ~_Rope_find_char_char_consumer() {} 877f8a1b7d9SAlexander Kabaev 878f8a1b7d9SAlexander Kabaev bool operator()879f8a1b7d9SAlexander Kabaev operator()(const _CharT* __leaf, size_t __n) 880f8a1b7d9SAlexander Kabaev { 88100db7afdSDavid E. O'Brien size_t __i; 882f8a1b7d9SAlexander Kabaev for (__i = 0; __i < __n; __i++) 883f8a1b7d9SAlexander Kabaev { 884f8a1b7d9SAlexander Kabaev if (__leaf[__i] == _M_pattern) 885f8a1b7d9SAlexander Kabaev { 886f8a1b7d9SAlexander Kabaev _M_count += __i; 887f8a1b7d9SAlexander Kabaev return false; 88800db7afdSDavid E. O'Brien } 88900db7afdSDavid E. O'Brien } 89000db7afdSDavid E. O'Brien _M_count += __n; return true; 89100db7afdSDavid E. O'Brien } 89200db7afdSDavid E. O'Brien }; 89300db7afdSDavid E. O'Brien 89400db7afdSDavid E. O'Brien template<class _CharT, class _Traits> 89500db7afdSDavid E. O'Brien // Here _CharT is both the stream and rope character type. 896f8a1b7d9SAlexander Kabaev class _Rope_insert_char_consumer 897f8a1b7d9SAlexander Kabaev : public _Rope_char_consumer<_CharT> 898f8a1b7d9SAlexander Kabaev { 89900db7afdSDavid E. O'Brien private: 90000db7afdSDavid E. O'Brien typedef basic_ostream<_CharT,_Traits> _Insert_ostream; 90100db7afdSDavid E. O'Brien _Insert_ostream& _M_o; 90200db7afdSDavid E. O'Brien public: _Rope_insert_char_consumer(_Insert_ostream & __writer)90300db7afdSDavid E. O'Brien _Rope_insert_char_consumer(_Insert_ostream& __writer) 90400db7afdSDavid E. O'Brien : _M_o(__writer) {}; ~_Rope_insert_char_consumer()90500db7afdSDavid E. O'Brien ~_Rope_insert_char_consumer() { }; 90600db7afdSDavid E. O'Brien // Caller is presumed to own the ostream 90700db7afdSDavid E. O'Brien bool operator() (const _CharT* __leaf, size_t __n); 90800db7afdSDavid E. O'Brien // Returns true to continue traversal. 90900db7afdSDavid E. O'Brien }; 91000db7afdSDavid E. O'Brien 91100db7afdSDavid E. O'Brien template<class _CharT, class _Traits> 912f8a1b7d9SAlexander Kabaev bool 913f8a1b7d9SAlexander Kabaev _Rope_insert_char_consumer<_CharT, _Traits>:: operator()914f8a1b7d9SAlexander Kabaev operator()(const _CharT* __leaf, size_t __n) 91500db7afdSDavid E. O'Brien { 91600db7afdSDavid E. O'Brien size_t __i; 91700db7afdSDavid E. O'Brien // We assume that formatting is set up correctly for each element. 918f8a1b7d9SAlexander Kabaev for (__i = 0; __i < __n; __i++) 919f8a1b7d9SAlexander Kabaev _M_o.put(__leaf[__i]); 92000db7afdSDavid E. O'Brien return true; 92100db7afdSDavid E. O'Brien } 92200db7afdSDavid E. O'Brien 92300db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 924f8a1b7d9SAlexander Kabaev bool 925f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_apply_to_pieces(_Rope_char_consumer<_CharT> & __c,const _RopeRep * __r,size_t __begin,size_t __end)926f8a1b7d9SAlexander Kabaev _S_apply_to_pieces(_Rope_char_consumer<_CharT>& __c, 927f8a1b7d9SAlexander Kabaev const _RopeRep* __r, size_t __begin, size_t __end) 92800db7afdSDavid E. O'Brien { 929f8a1b7d9SAlexander Kabaev if (0 == __r) 930f8a1b7d9SAlexander Kabaev return true; 931f8a1b7d9SAlexander Kabaev switch(__r->_M_tag) 932f8a1b7d9SAlexander Kabaev { 933f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 93400db7afdSDavid E. O'Brien { 93500db7afdSDavid E. O'Brien _RopeConcatenation* __conc = (_RopeConcatenation*)__r; 93600db7afdSDavid E. O'Brien _RopeRep* __left = __conc->_M_left; 93700db7afdSDavid E. O'Brien size_t __left_len = __left->_M_size; 938f8a1b7d9SAlexander Kabaev if (__begin < __left_len) 939f8a1b7d9SAlexander Kabaev { 94000db7afdSDavid E. O'Brien size_t __left_end = std::min(__left_len, __end); 94100db7afdSDavid E. O'Brien if (!_S_apply_to_pieces(__c, __left, __begin, __left_end)) 94200db7afdSDavid E. O'Brien return false; 94300db7afdSDavid E. O'Brien } 944f8a1b7d9SAlexander Kabaev if (__end > __left_len) 945f8a1b7d9SAlexander Kabaev { 94600db7afdSDavid E. O'Brien _RopeRep* __right = __conc->_M_right; 94700db7afdSDavid E. O'Brien size_t __right_start = std::max(__left_len, __begin); 94800db7afdSDavid E. O'Brien if (!_S_apply_to_pieces(__c, __right, 94900db7afdSDavid E. O'Brien __right_start - __left_len, 950f8a1b7d9SAlexander Kabaev __end - __left_len)) 95100db7afdSDavid E. O'Brien return false; 95200db7afdSDavid E. O'Brien } 95300db7afdSDavid E. O'Brien } 95400db7afdSDavid E. O'Brien return true; 955f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 95600db7afdSDavid E. O'Brien { 95700db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*)__r; 95800db7afdSDavid E. O'Brien return __c(__l->_M_data + __begin, __end - __begin); 95900db7afdSDavid E. O'Brien } 960f8a1b7d9SAlexander Kabaev case __detail::_S_function: 961f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 96200db7afdSDavid E. O'Brien { 96300db7afdSDavid E. O'Brien _RopeFunction* __f = (_RopeFunction*)__r; 96400db7afdSDavid E. O'Brien size_t __len = __end - __begin; 96500db7afdSDavid E. O'Brien bool __result; 96600db7afdSDavid E. O'Brien _CharT* __buffer = 967ffeaf689SAlexander Kabaev (_CharT*)_Alloc().allocate(__len * sizeof(_CharT)); 968f8a1b7d9SAlexander Kabaev try 969f8a1b7d9SAlexander Kabaev { 97000db7afdSDavid E. O'Brien (*(__f->_M_fn))(__begin, __len, __buffer); 97100db7afdSDavid E. O'Brien __result = __c(__buffer, __len); 972ffeaf689SAlexander Kabaev _Alloc().deallocate(__buffer, __len * sizeof(_CharT)); 97300db7afdSDavid E. O'Brien } 97400db7afdSDavid E. O'Brien catch(...) 97500db7afdSDavid E. O'Brien { 976ffeaf689SAlexander Kabaev _Alloc().deallocate(__buffer, __len * sizeof(_CharT)); 97700db7afdSDavid E. O'Brien __throw_exception_again; 97800db7afdSDavid E. O'Brien } 97900db7afdSDavid E. O'Brien return __result; 98000db7afdSDavid E. O'Brien } 98100db7afdSDavid E. O'Brien default: 98200db7afdSDavid E. O'Brien return false; 98300db7afdSDavid E. O'Brien } 98400db7afdSDavid E. O'Brien } 98500db7afdSDavid E. O'Brien 98600db7afdSDavid E. O'Brien template<class _CharT, class _Traits> 987f8a1b7d9SAlexander Kabaev inline void _Rope_fill(basic_ostream<_CharT,_Traits> & __o,size_t __n)988f8a1b7d9SAlexander Kabaev _Rope_fill(basic_ostream<_CharT, _Traits>& __o, size_t __n) 98900db7afdSDavid E. O'Brien { 99000db7afdSDavid E. O'Brien char __f = __o.fill(); 99100db7afdSDavid E. O'Brien size_t __i; 99200db7afdSDavid E. O'Brien 993f8a1b7d9SAlexander Kabaev for (__i = 0; __i < __n; __i++) 994f8a1b7d9SAlexander Kabaev __o.put(__f); 99500db7afdSDavid E. O'Brien } 99600db7afdSDavid E. O'Brien 99700db7afdSDavid E. O'Brien 998f8a1b7d9SAlexander Kabaev template <class _CharT> 999f8a1b7d9SAlexander Kabaev inline bool _Rope_is_simple(_CharT *)1000f8a1b7d9SAlexander Kabaev _Rope_is_simple(_CharT*) 1001f8a1b7d9SAlexander Kabaev { return false; } 1002f8a1b7d9SAlexander Kabaev 1003f8a1b7d9SAlexander Kabaev inline bool _Rope_is_simple(char *)1004f8a1b7d9SAlexander Kabaev _Rope_is_simple(char*) 1005f8a1b7d9SAlexander Kabaev { return true; } 1006f8a1b7d9SAlexander Kabaev 1007f8a1b7d9SAlexander Kabaev inline bool _Rope_is_simple(wchar_t *)1008f8a1b7d9SAlexander Kabaev _Rope_is_simple(wchar_t*) 1009f8a1b7d9SAlexander Kabaev { return true; } 101000db7afdSDavid E. O'Brien 101100db7afdSDavid E. O'Brien template<class _CharT, class _Traits, class _Alloc> 1012f8a1b7d9SAlexander Kabaev basic_ostream<_CharT, _Traits>& 1013f8a1b7d9SAlexander Kabaev operator<<(basic_ostream<_CharT, _Traits>& __o, 101400db7afdSDavid E. O'Brien const rope<_CharT, _Alloc>& __r) 101500db7afdSDavid E. O'Brien { 101600db7afdSDavid E. O'Brien size_t __w = __o.width(); 101700db7afdSDavid E. O'Brien bool __left = bool(__o.flags() & std::ios::left); 101800db7afdSDavid E. O'Brien size_t __pad_len; 101900db7afdSDavid E. O'Brien size_t __rope_len = __r.size(); 102000db7afdSDavid E. O'Brien _Rope_insert_char_consumer<_CharT, _Traits> __c(__o); 102100db7afdSDavid E. O'Brien bool __is_simple = _Rope_is_simple((_CharT*)0); 102200db7afdSDavid E. O'Brien 1023f8a1b7d9SAlexander Kabaev if (__rope_len < __w) 102400db7afdSDavid E. O'Brien __pad_len = __w - __rope_len; 1025f8a1b7d9SAlexander Kabaev else 102600db7afdSDavid E. O'Brien __pad_len = 0; 1027f8a1b7d9SAlexander Kabaev 1028f8a1b7d9SAlexander Kabaev if (!__is_simple) 1029f8a1b7d9SAlexander Kabaev __o.width(__w / __rope_len); 1030f8a1b7d9SAlexander Kabaev try 1031f8a1b7d9SAlexander Kabaev { 1032f8a1b7d9SAlexander Kabaev if (__is_simple && !__left && __pad_len > 0) 103300db7afdSDavid E. O'Brien _Rope_fill(__o, __pad_len); 103400db7afdSDavid E. O'Brien __r.apply_to_pieces(0, __r.size(), __c); 1035f8a1b7d9SAlexander Kabaev if (__is_simple && __left && __pad_len > 0) 103600db7afdSDavid E. O'Brien _Rope_fill(__o, __pad_len); 103700db7afdSDavid E. O'Brien if (!__is_simple) 103800db7afdSDavid E. O'Brien __o.width(__w); 103900db7afdSDavid E. O'Brien } catch(...)104000db7afdSDavid E. O'Brien catch(...) 104100db7afdSDavid E. O'Brien { 104200db7afdSDavid E. O'Brien if (!__is_simple) 104300db7afdSDavid E. O'Brien __o.width(__w); 104400db7afdSDavid E. O'Brien __throw_exception_again; 104500db7afdSDavid E. O'Brien } 104600db7afdSDavid E. O'Brien return __o; 104700db7afdSDavid E. O'Brien } 104800db7afdSDavid E. O'Brien 104900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 105000db7afdSDavid E. O'Brien _CharT* 1051f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_flatten(_RopeRep * __r,size_t __start,size_t __len,_CharT * __buffer)1052f8a1b7d9SAlexander Kabaev _S_flatten(_RopeRep* __r, size_t __start, size_t __len, 105300db7afdSDavid E. O'Brien _CharT* __buffer) 105400db7afdSDavid E. O'Brien { 105500db7afdSDavid E. O'Brien _Rope_flatten_char_consumer<_CharT> __c(__buffer); 105600db7afdSDavid E. O'Brien _S_apply_to_pieces(__c, __r, __start, __start + __len); 105700db7afdSDavid E. O'Brien return(__buffer + __len); 105800db7afdSDavid E. O'Brien } 105900db7afdSDavid E. O'Brien 106000db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 106100db7afdSDavid E. O'Brien size_t 1062f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: find(_CharT __pattern,size_t __start)1063f8a1b7d9SAlexander Kabaev find(_CharT __pattern, size_t __start) const 106400db7afdSDavid E. O'Brien { 106500db7afdSDavid E. O'Brien _Rope_find_char_char_consumer<_CharT> __c(__pattern); 1066ffeaf689SAlexander Kabaev _S_apply_to_pieces(__c, this->_M_tree_ptr, __start, size()); 106700db7afdSDavid E. O'Brien size_type __result_pos = __start + __c._M_count; 106800db7afdSDavid E. O'Brien #ifndef __STL_OLD_ROPE_SEMANTICS 1069f8a1b7d9SAlexander Kabaev if (__result_pos == size()) 1070f8a1b7d9SAlexander Kabaev __result_pos = npos; 107100db7afdSDavid E. O'Brien #endif 107200db7afdSDavid E. O'Brien return __result_pos; 107300db7afdSDavid E. O'Brien } 107400db7afdSDavid E. O'Brien 107500db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 107600db7afdSDavid E. O'Brien _CharT* 1077f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_flatten(_RopeRep * __r,_CharT * __buffer)1078f8a1b7d9SAlexander Kabaev _S_flatten(_RopeRep* __r, _CharT* __buffer) 107900db7afdSDavid E. O'Brien { 1080f8a1b7d9SAlexander Kabaev if (0 == __r) 1081f8a1b7d9SAlexander Kabaev return __buffer; 1082f8a1b7d9SAlexander Kabaev switch(__r->_M_tag) 1083f8a1b7d9SAlexander Kabaev { 1084f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 108500db7afdSDavid E. O'Brien { 108600db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__r; 108700db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 108800db7afdSDavid E. O'Brien _RopeRep* __right = __c->_M_right; 108900db7afdSDavid E. O'Brien _CharT* __rest = _S_flatten(__left, __buffer); 109000db7afdSDavid E. O'Brien return _S_flatten(__right, __rest); 109100db7afdSDavid E. O'Brien } 1092f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 109300db7afdSDavid E. O'Brien { 109400db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*)__r; 109500db7afdSDavid E. O'Brien return copy_n(__l->_M_data, __l->_M_size, __buffer).second; 109600db7afdSDavid E. O'Brien } 1097f8a1b7d9SAlexander Kabaev case __detail::_S_function: 1098f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 109900db7afdSDavid E. O'Brien // We don't yet do anything with substring nodes. 110000db7afdSDavid E. O'Brien // This needs to be fixed before ropefiles will work well. 110100db7afdSDavid E. O'Brien { 110200db7afdSDavid E. O'Brien _RopeFunction* __f = (_RopeFunction*)__r; 110300db7afdSDavid E. O'Brien (*(__f->_M_fn))(0, __f->_M_size, __buffer); 110400db7afdSDavid E. O'Brien return __buffer + __f->_M_size; 110500db7afdSDavid E. O'Brien } 110600db7afdSDavid E. O'Brien default: 110700db7afdSDavid E. O'Brien return 0; 110800db7afdSDavid E. O'Brien } 110900db7afdSDavid E. O'Brien } 111000db7afdSDavid E. O'Brien 111100db7afdSDavid E. O'Brien // This needs work for _CharT != char 111200db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 111300db7afdSDavid E. O'Brien void 1114f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_dump(_RopeRep * __r,int __indent)1115f8a1b7d9SAlexander Kabaev _S_dump(_RopeRep* __r, int __indent) 111600db7afdSDavid E. O'Brien { 1117f8a1b7d9SAlexander Kabaev for (int __i = 0; __i < __indent; __i++) 1118f8a1b7d9SAlexander Kabaev putchar(' '); 1119f8a1b7d9SAlexander Kabaev if (0 == __r) 1120f8a1b7d9SAlexander Kabaev { 1121f8a1b7d9SAlexander Kabaev printf("NULL\n"); 1122f8a1b7d9SAlexander Kabaev return; 112300db7afdSDavid E. O'Brien } 1124f8a1b7d9SAlexander Kabaev if (_S_concat == __r->_M_tag) 1125f8a1b7d9SAlexander Kabaev { 112600db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__r; 112700db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 112800db7afdSDavid E. O'Brien _RopeRep* __right = __c->_M_right; 112900db7afdSDavid E. O'Brien 113000db7afdSDavid E. O'Brien #ifdef __GC 113100db7afdSDavid E. O'Brien printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n", 1132f8a1b7d9SAlexander Kabaev __r, __r->_M_depth, __r->_M_size, 1133f8a1b7d9SAlexander Kabaev __r->_M_is_balanced? "" : "not"); 113400db7afdSDavid E. O'Brien #else 113500db7afdSDavid E. O'Brien printf("Concatenation %p (rc = %ld, depth = %d, " 113600db7afdSDavid E. O'Brien "len = %ld, %s balanced)\n", 113700db7afdSDavid E. O'Brien __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size, 113800db7afdSDavid E. O'Brien __r->_M_is_balanced? "" : "not"); 113900db7afdSDavid E. O'Brien #endif 114000db7afdSDavid E. O'Brien _S_dump(__left, __indent + 2); 114100db7afdSDavid E. O'Brien _S_dump(__right, __indent + 2); 114200db7afdSDavid E. O'Brien return; 1143f8a1b7d9SAlexander Kabaev } 1144f8a1b7d9SAlexander Kabaev else 1145f8a1b7d9SAlexander Kabaev { 1146*387c85f1SDimitry Andric const char* __kind; 114700db7afdSDavid E. O'Brien 1148f8a1b7d9SAlexander Kabaev switch (__r->_M_tag) 1149f8a1b7d9SAlexander Kabaev { 1150f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 115100db7afdSDavid E. O'Brien __kind = "Leaf"; 115200db7afdSDavid E. O'Brien break; 1153f8a1b7d9SAlexander Kabaev case __detail::_S_function: 115400db7afdSDavid E. O'Brien __kind = "Function"; 115500db7afdSDavid E. O'Brien break; 1156f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 115700db7afdSDavid E. O'Brien __kind = "Function representing substring"; 115800db7afdSDavid E. O'Brien break; 115900db7afdSDavid E. O'Brien default: 116000db7afdSDavid E. O'Brien __kind = "(corrupted kind field!)"; 116100db7afdSDavid E. O'Brien } 116200db7afdSDavid E. O'Brien #ifdef __GC 116300db7afdSDavid E. O'Brien printf("%s %p (depth = %d, len = %ld) ", 116400db7afdSDavid E. O'Brien __kind, __r, __r->_M_depth, __r->_M_size); 116500db7afdSDavid E. O'Brien #else 116600db7afdSDavid E. O'Brien printf("%s %p (rc = %ld, depth = %d, len = %ld) ", 116700db7afdSDavid E. O'Brien __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size); 116800db7afdSDavid E. O'Brien #endif 1169f8a1b7d9SAlexander Kabaev if (_S_is_one_byte_char_type((_CharT*)0)) 1170f8a1b7d9SAlexander Kabaev { 117100db7afdSDavid E. O'Brien const int __max_len = 40; 117200db7afdSDavid E. O'Brien _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len)); 117300db7afdSDavid E. O'Brien _CharT __buffer[__max_len + 1]; 117400db7afdSDavid E. O'Brien bool __too_big = __r->_M_size > __prefix->_M_size; 117500db7afdSDavid E. O'Brien 117600db7afdSDavid E. O'Brien _S_flatten(__prefix, __buffer); 117700db7afdSDavid E. O'Brien __buffer[__prefix->_M_size] = _S_eos((_CharT*)0); 1178f8a1b7d9SAlexander Kabaev printf("%s%s\n", (char*)__buffer, 1179f8a1b7d9SAlexander Kabaev __too_big? "...\n" : "\n"); 118000db7afdSDavid E. O'Brien } 1181f8a1b7d9SAlexander Kabaev else 1182f8a1b7d9SAlexander Kabaev printf("\n"); 118300db7afdSDavid E. O'Brien } 118400db7afdSDavid E. O'Brien } 118500db7afdSDavid E. O'Brien 118600db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 118700db7afdSDavid E. O'Brien const unsigned long 1188f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: 1189f8a1b7d9SAlexander Kabaev _S_min_len[int(__detail::_S_max_rope_depth) + 1] = { 119000db7afdSDavid E. O'Brien /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21, 119100db7afdSDavid E. O'Brien /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377, 119200db7afdSDavid E. O'Brien /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181, 119300db7afdSDavid E. O'Brien /* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368, 119400db7afdSDavid E. O'Brien /* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811, 119500db7afdSDavid E. O'Brien /* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309, 119600db7afdSDavid E. O'Brien /* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352, 119700db7afdSDavid E. O'Brien /* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155, 119800db7afdSDavid E. O'Brien /* 39 */165580141, /* 40 */267914296, /* 41 */433494437, 119900db7afdSDavid E. O'Brien /* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903, 120000db7afdSDavid E. O'Brien /* 45 */2971215073u }; 120100db7afdSDavid E. O'Brien // These are Fibonacci numbers < 2**32. 120200db7afdSDavid E. O'Brien 120300db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 120400db7afdSDavid E. O'Brien typename rope<_CharT, _Alloc>::_RopeRep* 1205f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_balance(_RopeRep * __r)1206f8a1b7d9SAlexander Kabaev _S_balance(_RopeRep* __r) 120700db7afdSDavid E. O'Brien { 1208f8a1b7d9SAlexander Kabaev _RopeRep* __forest[int(__detail::_S_max_rope_depth) + 1]; 120900db7afdSDavid E. O'Brien _RopeRep* __result = 0; 121000db7afdSDavid E. O'Brien int __i; 121100db7afdSDavid E. O'Brien // Invariant: 121200db7afdSDavid E. O'Brien // The concatenation of forest in descending order is equal to __r. 121300db7afdSDavid E. O'Brien // __forest[__i]._M_size >= _S_min_len[__i] 121400db7afdSDavid E. O'Brien // __forest[__i]._M_depth = __i 121500db7afdSDavid E. O'Brien // References from forest are included in refcount. 121600db7afdSDavid E. O'Brien 1217f8a1b7d9SAlexander Kabaev for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i) 121800db7afdSDavid E. O'Brien __forest[__i] = 0; 1219f8a1b7d9SAlexander Kabaev try 1220f8a1b7d9SAlexander Kabaev { 122100db7afdSDavid E. O'Brien _S_add_to_forest(__r, __forest); 1222f8a1b7d9SAlexander Kabaev for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i) 1223f8a1b7d9SAlexander Kabaev if (0 != __forest[__i]) 1224f8a1b7d9SAlexander Kabaev { 122500db7afdSDavid E. O'Brien #ifndef __GC 122600db7afdSDavid E. O'Brien _Self_destruct_ptr __old(__result); 122700db7afdSDavid E. O'Brien #endif 122800db7afdSDavid E. O'Brien __result = _S_concat(__forest[__i], __result); 122900db7afdSDavid E. O'Brien __forest[__i]->_M_unref_nonnil(); 123000db7afdSDavid E. O'Brien #if !defined(__GC) && defined(__EXCEPTIONS) 123100db7afdSDavid E. O'Brien __forest[__i] = 0; 123200db7afdSDavid E. O'Brien #endif 123300db7afdSDavid E. O'Brien } 123400db7afdSDavid E. O'Brien } 123500db7afdSDavid E. O'Brien catch(...) 123600db7afdSDavid E. O'Brien { 1237f8a1b7d9SAlexander Kabaev for(__i = 0; __i <= int(__detail::_S_max_rope_depth); __i++) 123800db7afdSDavid E. O'Brien _S_unref(__forest[__i]); 123900db7afdSDavid E. O'Brien __throw_exception_again; 124000db7afdSDavid E. O'Brien } 124100db7afdSDavid E. O'Brien 1242f8a1b7d9SAlexander Kabaev if (__result->_M_depth > int(__detail::_S_max_rope_depth)) 1243ffeaf689SAlexander Kabaev __throw_length_error(__N("rope::_S_balance")); 124400db7afdSDavid E. O'Brien return(__result); 124500db7afdSDavid E. O'Brien } 124600db7afdSDavid E. O'Brien 124700db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 124800db7afdSDavid E. O'Brien void 1249f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_add_to_forest(_RopeRep * __r,_RopeRep ** __forest)1250f8a1b7d9SAlexander Kabaev _S_add_to_forest(_RopeRep* __r, _RopeRep** __forest) 125100db7afdSDavid E. O'Brien { 1252f8a1b7d9SAlexander Kabaev if (__r->_M_is_balanced) 1253f8a1b7d9SAlexander Kabaev { 125400db7afdSDavid E. O'Brien _S_add_leaf_to_forest(__r, __forest); 125500db7afdSDavid E. O'Brien return; 125600db7afdSDavid E. O'Brien } 125700db7afdSDavid E. O'Brien 125800db7afdSDavid E. O'Brien { 125900db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__r; 126000db7afdSDavid E. O'Brien 126100db7afdSDavid E. O'Brien _S_add_to_forest(__c->_M_left, __forest); 126200db7afdSDavid E. O'Brien _S_add_to_forest(__c->_M_right, __forest); 126300db7afdSDavid E. O'Brien } 126400db7afdSDavid E. O'Brien } 126500db7afdSDavid E. O'Brien 126600db7afdSDavid E. O'Brien 126700db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 126800db7afdSDavid E. O'Brien void 1269f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_add_leaf_to_forest(_RopeRep * __r,_RopeRep ** __forest)1270f8a1b7d9SAlexander Kabaev _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest) 127100db7afdSDavid E. O'Brien { 127200db7afdSDavid E. O'Brien _RopeRep* __insertee; // included in refcount 127300db7afdSDavid E. O'Brien _RopeRep* __too_tiny = 0; // included in refcount 127400db7afdSDavid E. O'Brien int __i; // forest[0..__i-1] is empty 127500db7afdSDavid E. O'Brien size_t __s = __r->_M_size; 127600db7afdSDavid E. O'Brien 1277f8a1b7d9SAlexander Kabaev for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i) 1278f8a1b7d9SAlexander Kabaev { 1279f8a1b7d9SAlexander Kabaev if (0 != __forest[__i]) 1280f8a1b7d9SAlexander Kabaev { 128100db7afdSDavid E. O'Brien #ifndef __GC 128200db7afdSDavid E. O'Brien _Self_destruct_ptr __old(__too_tiny); 128300db7afdSDavid E. O'Brien #endif 1284f8a1b7d9SAlexander Kabaev __too_tiny = _S_concat_and_set_balanced(__forest[__i], 1285f8a1b7d9SAlexander Kabaev __too_tiny); 128600db7afdSDavid E. O'Brien __forest[__i]->_M_unref_nonnil(); 128700db7afdSDavid E. O'Brien __forest[__i] = 0; 128800db7afdSDavid E. O'Brien } 128900db7afdSDavid E. O'Brien } 129000db7afdSDavid E. O'Brien { 129100db7afdSDavid E. O'Brien #ifndef __GC 129200db7afdSDavid E. O'Brien _Self_destruct_ptr __old(__too_tiny); 129300db7afdSDavid E. O'Brien #endif 129400db7afdSDavid E. O'Brien __insertee = _S_concat_and_set_balanced(__too_tiny, __r); 129500db7afdSDavid E. O'Brien } 129600db7afdSDavid E. O'Brien // Too_tiny dead, and no longer included in refcount. 129700db7afdSDavid E. O'Brien // Insertee is live and included. 1298f8a1b7d9SAlexander Kabaev for (;; ++__i) 1299f8a1b7d9SAlexander Kabaev { 1300f8a1b7d9SAlexander Kabaev if (0 != __forest[__i]) 1301f8a1b7d9SAlexander Kabaev { 130200db7afdSDavid E. O'Brien #ifndef __GC 130300db7afdSDavid E. O'Brien _Self_destruct_ptr __old(__insertee); 130400db7afdSDavid E. O'Brien #endif 1305f8a1b7d9SAlexander Kabaev __insertee = _S_concat_and_set_balanced(__forest[__i], 1306f8a1b7d9SAlexander Kabaev __insertee); 130700db7afdSDavid E. O'Brien __forest[__i]->_M_unref_nonnil(); 130800db7afdSDavid E. O'Brien __forest[__i] = 0; 130900db7afdSDavid E. O'Brien } 1310f8a1b7d9SAlexander Kabaev if (__i == int(__detail::_S_max_rope_depth) 1311f8a1b7d9SAlexander Kabaev || __insertee->_M_size < _S_min_len[__i+1]) 1312f8a1b7d9SAlexander Kabaev { 131300db7afdSDavid E. O'Brien __forest[__i] = __insertee; 131400db7afdSDavid E. O'Brien // refcount is OK since __insertee is now dead. 131500db7afdSDavid E. O'Brien return; 131600db7afdSDavid E. O'Brien } 131700db7afdSDavid E. O'Brien } 131800db7afdSDavid E. O'Brien } 131900db7afdSDavid E. O'Brien 132000db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 132100db7afdSDavid E. O'Brien _CharT 1322f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_fetch(_RopeRep * __r,size_type __i)1323f8a1b7d9SAlexander Kabaev _S_fetch(_RopeRep* __r, size_type __i) 132400db7afdSDavid E. O'Brien { 132500db7afdSDavid E. O'Brien __GC_CONST _CharT* __cstr = __r->_M_c_string; 132600db7afdSDavid E. O'Brien 1327f8a1b7d9SAlexander Kabaev if (0 != __cstr) 1328f8a1b7d9SAlexander Kabaev return __cstr[__i]; 1329f8a1b7d9SAlexander Kabaev for(;;) 1330f8a1b7d9SAlexander Kabaev { 1331f8a1b7d9SAlexander Kabaev switch(__r->_M_tag) 1332f8a1b7d9SAlexander Kabaev { 1333f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 133400db7afdSDavid E. O'Brien { 133500db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__r; 133600db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 133700db7afdSDavid E. O'Brien size_t __left_len = __left->_M_size; 133800db7afdSDavid E. O'Brien 1339f8a1b7d9SAlexander Kabaev if (__i >= __left_len) 1340f8a1b7d9SAlexander Kabaev { 134100db7afdSDavid E. O'Brien __i -= __left_len; 134200db7afdSDavid E. O'Brien __r = __c->_M_right; 1343f8a1b7d9SAlexander Kabaev } 1344f8a1b7d9SAlexander Kabaev else 134500db7afdSDavid E. O'Brien __r = __left; 134600db7afdSDavid E. O'Brien } 134700db7afdSDavid E. O'Brien break; 1348f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 134900db7afdSDavid E. O'Brien { 135000db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*)__r; 135100db7afdSDavid E. O'Brien return __l->_M_data[__i]; 135200db7afdSDavid E. O'Brien } 1353f8a1b7d9SAlexander Kabaev case __detail::_S_function: 1354f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 135500db7afdSDavid E. O'Brien { 135600db7afdSDavid E. O'Brien _RopeFunction* __f = (_RopeFunction*)__r; 135700db7afdSDavid E. O'Brien _CharT __result; 135800db7afdSDavid E. O'Brien 135900db7afdSDavid E. O'Brien (*(__f->_M_fn))(__i, 1, &__result); 136000db7afdSDavid E. O'Brien return __result; 136100db7afdSDavid E. O'Brien } 136200db7afdSDavid E. O'Brien } 136300db7afdSDavid E. O'Brien } 136400db7afdSDavid E. O'Brien } 136500db7afdSDavid E. O'Brien 136600db7afdSDavid E. O'Brien #ifndef __GC 136700db7afdSDavid E. O'Brien // Return a uniquely referenced character slot for the given 136800db7afdSDavid E. O'Brien // position, or 0 if that's not possible. 136900db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 137000db7afdSDavid E. O'Brien _CharT* 1371f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_fetch_ptr(_RopeRep * __r,size_type __i)1372f8a1b7d9SAlexander Kabaev _S_fetch_ptr(_RopeRep* __r, size_type __i) 137300db7afdSDavid E. O'Brien { 1374f8a1b7d9SAlexander Kabaev _RopeRep* __clrstack[__detail::_S_max_rope_depth]; 137500db7afdSDavid E. O'Brien size_t __csptr = 0; 137600db7afdSDavid E. O'Brien 1377f8a1b7d9SAlexander Kabaev for(;;) 1378f8a1b7d9SAlexander Kabaev { 1379f8a1b7d9SAlexander Kabaev if (__r->_M_ref_count > 1) 1380f8a1b7d9SAlexander Kabaev return 0; 1381f8a1b7d9SAlexander Kabaev switch(__r->_M_tag) 1382f8a1b7d9SAlexander Kabaev { 1383f8a1b7d9SAlexander Kabaev case __detail::_S_concat: 138400db7afdSDavid E. O'Brien { 138500db7afdSDavid E. O'Brien _RopeConcatenation* __c = (_RopeConcatenation*)__r; 138600db7afdSDavid E. O'Brien _RopeRep* __left = __c->_M_left; 138700db7afdSDavid E. O'Brien size_t __left_len = __left->_M_size; 138800db7afdSDavid E. O'Brien 1389f8a1b7d9SAlexander Kabaev if (__c->_M_c_string != 0) 1390f8a1b7d9SAlexander Kabaev __clrstack[__csptr++] = __c; 1391f8a1b7d9SAlexander Kabaev if (__i >= __left_len) 1392f8a1b7d9SAlexander Kabaev { 139300db7afdSDavid E. O'Brien __i -= __left_len; 139400db7afdSDavid E. O'Brien __r = __c->_M_right; 1395f8a1b7d9SAlexander Kabaev } 1396f8a1b7d9SAlexander Kabaev else 139700db7afdSDavid E. O'Brien __r = __left; 139800db7afdSDavid E. O'Brien } 139900db7afdSDavid E. O'Brien break; 1400f8a1b7d9SAlexander Kabaev case __detail::_S_leaf: 140100db7afdSDavid E. O'Brien { 140200db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*)__r; 140300db7afdSDavid E. O'Brien if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0) 140400db7afdSDavid E. O'Brien __clrstack[__csptr++] = __l; 1405f8a1b7d9SAlexander Kabaev while (__csptr > 0) 1406f8a1b7d9SAlexander Kabaev { 140700db7afdSDavid E. O'Brien -- __csptr; 140800db7afdSDavid E. O'Brien _RopeRep* __d = __clrstack[__csptr]; 140900db7afdSDavid E. O'Brien __d->_M_free_c_string(); 141000db7afdSDavid E. O'Brien __d->_M_c_string = 0; 141100db7afdSDavid E. O'Brien } 141200db7afdSDavid E. O'Brien return __l->_M_data + __i; 141300db7afdSDavid E. O'Brien } 1414f8a1b7d9SAlexander Kabaev case __detail::_S_function: 1415f8a1b7d9SAlexander Kabaev case __detail::_S_substringfn: 141600db7afdSDavid E. O'Brien return 0; 141700db7afdSDavid E. O'Brien } 141800db7afdSDavid E. O'Brien } 141900db7afdSDavid E. O'Brien } 142000db7afdSDavid E. O'Brien #endif /* __GC */ 142100db7afdSDavid E. O'Brien 142200db7afdSDavid E. O'Brien // The following could be implemented trivially using 142300db7afdSDavid E. O'Brien // lexicographical_compare_3way. 142400db7afdSDavid E. O'Brien // We do a little more work to avoid dealing with rope iterators for 142500db7afdSDavid E. O'Brien // flat strings. 142600db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 142700db7afdSDavid E. O'Brien int 1428f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: _S_compare(const _RopeRep * __left,const _RopeRep * __right)1429f8a1b7d9SAlexander Kabaev _S_compare (const _RopeRep* __left, const _RopeRep* __right) 143000db7afdSDavid E. O'Brien { 143100db7afdSDavid E. O'Brien size_t __left_len; 143200db7afdSDavid E. O'Brien size_t __right_len; 143300db7afdSDavid E. O'Brien 1434f8a1b7d9SAlexander Kabaev if (0 == __right) 1435f8a1b7d9SAlexander Kabaev return 0 != __left; 1436f8a1b7d9SAlexander Kabaev if (0 == __left) 1437f8a1b7d9SAlexander Kabaev return -1; 143800db7afdSDavid E. O'Brien __left_len = __left->_M_size; 143900db7afdSDavid E. O'Brien __right_len = __right->_M_size; 1440f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __left->_M_tag) 1441f8a1b7d9SAlexander Kabaev { 144200db7afdSDavid E. O'Brien _RopeLeaf* __l = (_RopeLeaf*) __left; 1443f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __right->_M_tag) 1444f8a1b7d9SAlexander Kabaev { 144500db7afdSDavid E. O'Brien _RopeLeaf* __r = (_RopeLeaf*) __right; 1446f8a1b7d9SAlexander Kabaev return lexicographical_compare_3way(__l->_M_data, 1447f8a1b7d9SAlexander Kabaev __l->_M_data + __left_len, 1448f8a1b7d9SAlexander Kabaev __r->_M_data, __r->_M_data 1449f8a1b7d9SAlexander Kabaev + __right_len); 1450f8a1b7d9SAlexander Kabaev } 1451f8a1b7d9SAlexander Kabaev else 1452f8a1b7d9SAlexander Kabaev { 145300db7afdSDavid E. O'Brien const_iterator __rstart(__right, 0); 145400db7afdSDavid E. O'Brien const_iterator __rend(__right, __right_len); 1455f8a1b7d9SAlexander Kabaev return lexicographical_compare_3way(__l->_M_data, __l->_M_data 1456f8a1b7d9SAlexander Kabaev + __left_len, 145700db7afdSDavid E. O'Brien __rstart, __rend); 145800db7afdSDavid E. O'Brien } 1459f8a1b7d9SAlexander Kabaev } 1460f8a1b7d9SAlexander Kabaev else 1461f8a1b7d9SAlexander Kabaev { 146200db7afdSDavid E. O'Brien const_iterator __lstart(__left, 0); 146300db7afdSDavid E. O'Brien const_iterator __lend(__left, __left_len); 1464f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == __right->_M_tag) 1465f8a1b7d9SAlexander Kabaev { 146600db7afdSDavid E. O'Brien _RopeLeaf* __r = (_RopeLeaf*) __right; 1467f8a1b7d9SAlexander Kabaev return lexicographical_compare_3way(__lstart, __lend, 1468f8a1b7d9SAlexander Kabaev __r->_M_data, __r->_M_data 1469f8a1b7d9SAlexander Kabaev + __right_len); 1470f8a1b7d9SAlexander Kabaev } 1471f8a1b7d9SAlexander Kabaev else 1472f8a1b7d9SAlexander Kabaev { 147300db7afdSDavid E. O'Brien const_iterator __rstart(__right, 0); 147400db7afdSDavid E. O'Brien const_iterator __rend(__right, __right_len); 1475f8a1b7d9SAlexander Kabaev return lexicographical_compare_3way(__lstart, __lend, 147600db7afdSDavid E. O'Brien __rstart, __rend); 147700db7afdSDavid E. O'Brien } 147800db7afdSDavid E. O'Brien } 147900db7afdSDavid E. O'Brien } 148000db7afdSDavid E. O'Brien 148100db7afdSDavid E. O'Brien // Assignment to reference proxies. 148200db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 148300db7afdSDavid E. O'Brien _Rope_char_ref_proxy<_CharT, _Alloc>& 1484f8a1b7d9SAlexander Kabaev _Rope_char_ref_proxy<_CharT, _Alloc>:: 1485f8a1b7d9SAlexander Kabaev operator=(_CharT __c) 1486f8a1b7d9SAlexander Kabaev { 148700db7afdSDavid E. O'Brien _RopeRep* __old = _M_root->_M_tree_ptr; 148800db7afdSDavid E. O'Brien #ifndef __GC 148900db7afdSDavid E. O'Brien // First check for the case in which everything is uniquely 149000db7afdSDavid E. O'Brien // referenced. In that case we can do this destructively. 149100db7afdSDavid E. O'Brien _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos); 1492f8a1b7d9SAlexander Kabaev if (0 != __ptr) 1493f8a1b7d9SAlexander Kabaev { 149400db7afdSDavid E. O'Brien *__ptr = __c; 149500db7afdSDavid E. O'Brien return *this; 149600db7afdSDavid E. O'Brien } 149700db7afdSDavid E. O'Brien #endif 1498f8a1b7d9SAlexander Kabaev _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos)); 1499f8a1b7d9SAlexander Kabaev _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1, 1500f8a1b7d9SAlexander Kabaev __old->_M_size)); 1501f8a1b7d9SAlexander Kabaev _Self_destruct_ptr __result_left(_My_rope:: 1502f8a1b7d9SAlexander Kabaev _S_destr_concat_char_iter(__left, 1503f8a1b7d9SAlexander Kabaev &__c, 1)); 150400db7afdSDavid E. O'Brien 1505f8a1b7d9SAlexander Kabaev _RopeRep* __result = _My_rope::_S_concat(__result_left, __right); 150600db7afdSDavid E. O'Brien #ifndef __GC 150700db7afdSDavid E. O'Brien _RopeRep::_S_unref(__old); 150800db7afdSDavid E. O'Brien #endif 150900db7afdSDavid E. O'Brien _M_root->_M_tree_ptr = __result; 151000db7afdSDavid E. O'Brien return *this; 151100db7afdSDavid E. O'Brien } 151200db7afdSDavid E. O'Brien 151300db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 1514f8a1b7d9SAlexander Kabaev inline _Rope_char_ref_proxy<_CharT, _Alloc>:: _CharT()1515f8a1b7d9SAlexander Kabaev operator _CharT() const 151600db7afdSDavid E. O'Brien { 1517f8a1b7d9SAlexander Kabaev if (_M_current_valid) 151800db7afdSDavid E. O'Brien return _M_current; 1519f8a1b7d9SAlexander Kabaev else 152000db7afdSDavid E. O'Brien return _My_rope::_S_fetch(_M_root->_M_tree_ptr, _M_pos); 152100db7afdSDavid E. O'Brien } 152200db7afdSDavid E. O'Brien 152300db7afdSDavid E. O'Brien template <class _CharT, class _Alloc> 1524f8a1b7d9SAlexander Kabaev _Rope_char_ptr_proxy<_CharT, _Alloc> 1525f8a1b7d9SAlexander Kabaev _Rope_char_ref_proxy<_CharT, _Alloc>:: 1526f8a1b7d9SAlexander Kabaev operator&() const 1527f8a1b7d9SAlexander Kabaev { return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); } 1528f8a1b7d9SAlexander Kabaev 1529f8a1b7d9SAlexander Kabaev template <class _CharT, class _Alloc> 1530f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: rope(size_t __n,_CharT __c,const allocator_type & __a)1531f8a1b7d9SAlexander Kabaev rope(size_t __n, _CharT __c, const allocator_type& __a) 153200db7afdSDavid E. O'Brien : _Base(__a) 153300db7afdSDavid E. O'Brien { 153400db7afdSDavid E. O'Brien rope<_CharT,_Alloc> __result; 153500db7afdSDavid E. O'Brien const size_t __exponentiate_threshold = 32; 153600db7afdSDavid E. O'Brien size_t __exponent; 153700db7afdSDavid E. O'Brien size_t __rest; 153800db7afdSDavid E. O'Brien _CharT* __rest_buffer; 153900db7afdSDavid E. O'Brien _RopeRep* __remainder; 154000db7afdSDavid E. O'Brien rope<_CharT, _Alloc> __remainder_rope; 154100db7afdSDavid E. O'Brien 154200db7afdSDavid E. O'Brien if (0 == __n) 154300db7afdSDavid E. O'Brien return; 154400db7afdSDavid E. O'Brien 154500db7afdSDavid E. O'Brien __exponent = __n / __exponentiate_threshold; 154600db7afdSDavid E. O'Brien __rest = __n % __exponentiate_threshold; 1547f8a1b7d9SAlexander Kabaev if (0 == __rest) 154800db7afdSDavid E. O'Brien __remainder = 0; 1549f8a1b7d9SAlexander Kabaev else 1550f8a1b7d9SAlexander Kabaev { 1551ffeaf689SAlexander Kabaev __rest_buffer = this->_Data_allocate(_S_rounded_up_size(__rest)); 1552f8a1b7d9SAlexander Kabaev __uninitialized_fill_n_a(__rest_buffer, __rest, __c, 1553f8a1b7d9SAlexander Kabaev get_allocator()); 155400db7afdSDavid E. O'Brien _S_cond_store_eos(__rest_buffer[__rest]); 1555f8a1b7d9SAlexander Kabaev try 1556f8a1b7d9SAlexander Kabaev { __remainder = _S_new_RopeLeaf(__rest_buffer, __rest, __a); } 155700db7afdSDavid E. O'Brien catch(...) 155800db7afdSDavid E. O'Brien { 155900db7afdSDavid E. O'Brien _RopeRep::__STL_FREE_STRING(__rest_buffer, __rest, __a); 156000db7afdSDavid E. O'Brien __throw_exception_again; 156100db7afdSDavid E. O'Brien } 156200db7afdSDavid E. O'Brien } 156300db7afdSDavid E. O'Brien __remainder_rope._M_tree_ptr = __remainder; 1564f8a1b7d9SAlexander Kabaev if (__exponent != 0) 1565f8a1b7d9SAlexander Kabaev { 156600db7afdSDavid E. O'Brien _CharT* __base_buffer = 1567ffeaf689SAlexander Kabaev this->_Data_allocate(_S_rounded_up_size(__exponentiate_threshold)); 156800db7afdSDavid E. O'Brien _RopeLeaf* __base_leaf; 156900db7afdSDavid E. O'Brien rope __base_rope; 1570f8a1b7d9SAlexander Kabaev __uninitialized_fill_n_a(__base_buffer, __exponentiate_threshold, __c, 1571f8a1b7d9SAlexander Kabaev get_allocator()); 157200db7afdSDavid E. O'Brien _S_cond_store_eos(__base_buffer[__exponentiate_threshold]); 1573f8a1b7d9SAlexander Kabaev try 1574f8a1b7d9SAlexander Kabaev { 157500db7afdSDavid E. O'Brien __base_leaf = _S_new_RopeLeaf(__base_buffer, 157600db7afdSDavid E. O'Brien __exponentiate_threshold, __a); 157700db7afdSDavid E. O'Brien } 157800db7afdSDavid E. O'Brien catch(...) 157900db7afdSDavid E. O'Brien { 158000db7afdSDavid E. O'Brien _RopeRep::__STL_FREE_STRING(__base_buffer, 158100db7afdSDavid E. O'Brien __exponentiate_threshold, __a); 158200db7afdSDavid E. O'Brien __throw_exception_again; 158300db7afdSDavid E. O'Brien } 158400db7afdSDavid E. O'Brien __base_rope._M_tree_ptr = __base_leaf; 1585f8a1b7d9SAlexander Kabaev if (1 == __exponent) 158600db7afdSDavid E. O'Brien __result = __base_rope; 1587f8a1b7d9SAlexander Kabaev else 158800db7afdSDavid E. O'Brien __result = power(__base_rope, __exponent, 158900db7afdSDavid E. O'Brien _Rope_Concat_fn<_CharT, _Alloc>()); 1590f8a1b7d9SAlexander Kabaev 1591f8a1b7d9SAlexander Kabaev if (0 != __remainder) 159200db7afdSDavid E. O'Brien __result += __remainder_rope; 159300db7afdSDavid E. O'Brien } 1594f8a1b7d9SAlexander Kabaev else 159500db7afdSDavid E. O'Brien __result = __remainder_rope; 1596f8a1b7d9SAlexander Kabaev 1597ffeaf689SAlexander Kabaev this->_M_tree_ptr = __result._M_tree_ptr; 1598ffeaf689SAlexander Kabaev this->_M_tree_ptr->_M_ref_nonnil(); 159900db7afdSDavid E. O'Brien } 160000db7afdSDavid E. O'Brien 160100db7afdSDavid E. O'Brien template<class _CharT, class _Alloc> 1602f8a1b7d9SAlexander Kabaev _CharT 1603f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>::_S_empty_c_str[1]; 160400db7afdSDavid E. O'Brien 160500db7afdSDavid E. O'Brien template<class _CharT, class _Alloc> 1606f8a1b7d9SAlexander Kabaev const _CharT* 1607f8a1b7d9SAlexander Kabaev rope<_CharT, _Alloc>:: c_str()1608f8a1b7d9SAlexander Kabaev c_str() const 1609f8a1b7d9SAlexander Kabaev { 1610f8a1b7d9SAlexander Kabaev if (0 == this->_M_tree_ptr) 1611f8a1b7d9SAlexander Kabaev { 161200db7afdSDavid E. O'Brien _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant, 161300db7afdSDavid E. O'Brien // but probably fast. 161400db7afdSDavid E. O'Brien return _S_empty_c_str; 161500db7afdSDavid E. O'Brien } 1616ffeaf689SAlexander Kabaev __gthread_mutex_lock (&this->_M_tree_ptr->_M_c_string_lock); 1617ffeaf689SAlexander Kabaev __GC_CONST _CharT* __result = this->_M_tree_ptr->_M_c_string; 1618ffeaf689SAlexander Kabaev if (0 == __result) 1619ffeaf689SAlexander Kabaev { 162000db7afdSDavid E. O'Brien size_t __s = size(); 1621ffeaf689SAlexander Kabaev __result = this->_Data_allocate(__s + 1); 1622ffeaf689SAlexander Kabaev _S_flatten(this->_M_tree_ptr, __result); 162300db7afdSDavid E. O'Brien __result[__s] = _S_eos((_CharT*)0); 1624ffeaf689SAlexander Kabaev this->_M_tree_ptr->_M_c_string = __result; 162500db7afdSDavid E. O'Brien } 1626ffeaf689SAlexander Kabaev __gthread_mutex_unlock (&this->_M_tree_ptr->_M_c_string_lock); 162700db7afdSDavid E. O'Brien return(__result); 162800db7afdSDavid E. O'Brien } 162900db7afdSDavid E. O'Brien 163000db7afdSDavid E. O'Brien template<class _CharT, class _Alloc> 1631f8a1b7d9SAlexander Kabaev const _CharT* rope<_CharT, _Alloc>:: replace_with_c_str()1632f8a1b7d9SAlexander Kabaev replace_with_c_str() 1633f8a1b7d9SAlexander Kabaev { 1634f8a1b7d9SAlexander Kabaev if (0 == this->_M_tree_ptr) 1635f8a1b7d9SAlexander Kabaev { 163600db7afdSDavid E. O'Brien _S_empty_c_str[0] = _S_eos((_CharT*)0); 163700db7afdSDavid E. O'Brien return _S_empty_c_str; 163800db7afdSDavid E. O'Brien } 1639ffeaf689SAlexander Kabaev __GC_CONST _CharT* __old_c_string = this->_M_tree_ptr->_M_c_string; 1640f8a1b7d9SAlexander Kabaev if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag 1641f8a1b7d9SAlexander Kabaev && 0 != __old_c_string) 164200db7afdSDavid E. O'Brien return(__old_c_string); 164300db7afdSDavid E. O'Brien size_t __s = size(); 1644ffeaf689SAlexander Kabaev _CharT* __result = this->_Data_allocate(_S_rounded_up_size(__s)); 1645ffeaf689SAlexander Kabaev _S_flatten(this->_M_tree_ptr, __result); 164600db7afdSDavid E. O'Brien __result[__s] = _S_eos((_CharT*)0); 1647ffeaf689SAlexander Kabaev this->_M_tree_ptr->_M_unref_nonnil(); 1648f8a1b7d9SAlexander Kabaev this->_M_tree_ptr = _S_new_RopeLeaf(__result, __s, 1649f8a1b7d9SAlexander Kabaev this->get_allocator()); 165000db7afdSDavid E. O'Brien return(__result); 165100db7afdSDavid E. O'Brien } 165200db7afdSDavid E. O'Brien 165300db7afdSDavid E. O'Brien // Algorithm specializations. More should be added. 165400db7afdSDavid E. O'Brien 165500db7afdSDavid E. O'Brien template<class _Rope_iterator> // was templated on CharT and Alloc 165600db7afdSDavid E. O'Brien void // VC++ workaround _Rope_rotate(_Rope_iterator __first,_Rope_iterator __middle,_Rope_iterator __last)165700db7afdSDavid E. O'Brien _Rope_rotate(_Rope_iterator __first, 165800db7afdSDavid E. O'Brien _Rope_iterator __middle, 165900db7afdSDavid E. O'Brien _Rope_iterator __last) 166000db7afdSDavid E. O'Brien { 166100db7afdSDavid E. O'Brien typedef typename _Rope_iterator::value_type _CharT; 166200db7afdSDavid E. O'Brien typedef typename _Rope_iterator::_allocator_type _Alloc; 166300db7afdSDavid E. O'Brien 166400db7afdSDavid E. O'Brien rope<_CharT, _Alloc>& __r(__first.container()); 166500db7afdSDavid E. O'Brien rope<_CharT, _Alloc> __prefix = __r.substr(0, __first.index()); 166600db7afdSDavid E. O'Brien rope<_CharT, _Alloc> __suffix = 166700db7afdSDavid E. O'Brien __r.substr(__last.index(), __r.size() - __last.index()); 166800db7afdSDavid E. O'Brien rope<_CharT, _Alloc> __part1 = 166900db7afdSDavid E. O'Brien __r.substr(__middle.index(), __last.index() - __middle.index()); 167000db7afdSDavid E. O'Brien rope<_CharT, _Alloc> __part2 = 167100db7afdSDavid E. O'Brien __r.substr(__first.index(), __middle.index() - __first.index()); 167200db7afdSDavid E. O'Brien __r = __prefix; 167300db7afdSDavid E. O'Brien __r += __part1; 167400db7afdSDavid E. O'Brien __r += __part2; 167500db7afdSDavid E. O'Brien __r += __suffix; 167600db7afdSDavid E. O'Brien } 167700db7afdSDavid E. O'Brien 167800db7afdSDavid E. O'Brien #if !defined(__GNUC__) 167900db7afdSDavid E. O'Brien // Appears to confuse g++ 1680f8a1b7d9SAlexander Kabaev 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)1681f8a1b7d9SAlexander Kabaev rotate(_Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __first, 168200db7afdSDavid E. O'Brien _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __middle, 1683f8a1b7d9SAlexander Kabaev _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __last) 1684f8a1b7d9SAlexander Kabaev { _Rope_rotate(__first, __middle, __last); } 168500db7afdSDavid E. O'Brien #endif 168600db7afdSDavid E. O'Brien 168700db7afdSDavid E. O'Brien # if 0 168800db7afdSDavid E. O'Brien // Probably not useful for several reasons: 168900db7afdSDavid E. O'Brien // - for SGIs 7.1 compiler and probably some others, 169000db7afdSDavid E. O'Brien // this forces lots of rope<wchar_t, ...> instantiations, creating a 169100db7afdSDavid E. O'Brien // code bloat and compile time problem. (Fixed in 7.2.) 1692f8a1b7d9SAlexander Kabaev // - wchar_t is 4 bytes wide on most UNIX platforms, making it 1693f8a1b7d9SAlexander Kabaev // unattractive for unicode strings. Unsigned short may be a better 1694f8a1b7d9SAlexander Kabaev // character type. 1695f8a1b7d9SAlexander Kabaev inline void 1696f8a1b7d9SAlexander Kabaev rotate(_Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __first, 169700db7afdSDavid E. O'Brien _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __middle, 1698f8a1b7d9SAlexander Kabaev _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __last) 1699f8a1b7d9SAlexander Kabaev { _Rope_rotate(__first, __middle, __last); } 170000db7afdSDavid E. O'Brien # endif 170100db7afdSDavid E. O'Brien 1702f8a1b7d9SAlexander Kabaev _GLIBCXX_END_NAMESPACE 1703