136ac495dSmrg // SGI's rope class implementation -*- C++ -*-
236ac495dSmrg
3*8feb0f0bSmrg // Copyright (C) 2001-2020 Free Software Foundation, Inc.
436ac495dSmrg //
536ac495dSmrg // This file is part of the GNU ISO C++ Library. This library is free
636ac495dSmrg // software; you can redistribute it and/or modify it under the
736ac495dSmrg // terms of the GNU General Public License as published by the
836ac495dSmrg // Free Software Foundation; either version 3, or (at your option)
936ac495dSmrg // any later version.
1036ac495dSmrg
1136ac495dSmrg // This library is distributed in the hope that it will be useful,
1236ac495dSmrg // but WITHOUT ANY WARRANTY; without even the implied warranty of
1336ac495dSmrg // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1436ac495dSmrg // GNU General Public License for more details.
1536ac495dSmrg
1636ac495dSmrg // Under Section 7 of GPL version 3, you are granted additional
1736ac495dSmrg // permissions described in the GCC Runtime Library Exception, version
1836ac495dSmrg // 3.1, as published by the Free Software Foundation.
1936ac495dSmrg
2036ac495dSmrg // You should have received a copy of the GNU General Public License and
2136ac495dSmrg // a copy of the GCC Runtime Library Exception along with this program;
2236ac495dSmrg // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
2336ac495dSmrg // <http://www.gnu.org/licenses/>.
2436ac495dSmrg
2536ac495dSmrg /*
2636ac495dSmrg * Copyright (c) 1997
2736ac495dSmrg * Silicon Graphics Computer Systems, Inc.
2836ac495dSmrg *
2936ac495dSmrg * Permission to use, copy, modify, distribute and sell this software
3036ac495dSmrg * and its documentation for any purpose is hereby granted without fee,
3136ac495dSmrg * provided that the above copyright notice appear in all copies and
3236ac495dSmrg * that both that copyright notice and this permission notice appear
3336ac495dSmrg * in supporting documentation. Silicon Graphics makes no
3436ac495dSmrg * representations about the suitability of this software for any
3536ac495dSmrg * purpose. It is provided "as is" without express or implied warranty.
3636ac495dSmrg */
3736ac495dSmrg
3836ac495dSmrg /** @file ropeimpl.h
3936ac495dSmrg * This is an internal header file, included by other library headers.
4036ac495dSmrg * Do not attempt to use it directly. @headername{ext/rope}
4136ac495dSmrg */
4236ac495dSmrg
4336ac495dSmrg #include <cstdio>
4436ac495dSmrg #include <ostream>
4536ac495dSmrg #include <bits/functexcept.h>
4636ac495dSmrg
4736ac495dSmrg #include <ext/algorithm> // For copy_n and lexicographical_compare_3way
4836ac495dSmrg #include <ext/memory> // For uninitialized_copy_n
4936ac495dSmrg #include <ext/numeric> // For power
5036ac495dSmrg
_GLIBCXX_VISIBILITY(default)5136ac495dSmrg namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
5236ac495dSmrg {
5336ac495dSmrg _GLIBCXX_BEGIN_NAMESPACE_VERSION
5436ac495dSmrg
5536ac495dSmrg // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
5636ac495dSmrg // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct.
5736ac495dSmrg // Results in a valid buf_ptr if the iterator can be legitimately
5836ac495dSmrg // dereferenced.
5936ac495dSmrg template <class _CharT, class _Alloc>
6036ac495dSmrg void
6136ac495dSmrg _Rope_iterator_base<_CharT, _Alloc>::
6236ac495dSmrg _S_setbuf(_Rope_iterator_base<_CharT, _Alloc>& __x)
6336ac495dSmrg {
64*8feb0f0bSmrg using std::size_t;
6536ac495dSmrg const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index];
6636ac495dSmrg size_t __leaf_pos = __x._M_leaf_pos;
6736ac495dSmrg size_t __pos = __x._M_current_pos;
6836ac495dSmrg
6936ac495dSmrg switch(__leaf->_M_tag)
7036ac495dSmrg {
7136ac495dSmrg case __detail::_S_leaf:
7236ac495dSmrg __x._M_buf_start = ((_Rope_RopeLeaf<_CharT, _Alloc>*)__leaf)->_M_data;
7336ac495dSmrg __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos);
7436ac495dSmrg __x._M_buf_end = __x._M_buf_start + __leaf->_M_size;
7536ac495dSmrg break;
7636ac495dSmrg case __detail::_S_function:
7736ac495dSmrg case __detail::_S_substringfn:
7836ac495dSmrg {
7936ac495dSmrg size_t __len = _S_iterator_buf_len;
8036ac495dSmrg size_t __buf_start_pos = __leaf_pos;
8136ac495dSmrg size_t __leaf_end = __leaf_pos + __leaf->_M_size;
8236ac495dSmrg char_producer<_CharT>* __fn = ((_Rope_RopeFunction<_CharT,
8336ac495dSmrg _Alloc>*)__leaf)->_M_fn;
8436ac495dSmrg if (__buf_start_pos + __len <= __pos)
8536ac495dSmrg {
8636ac495dSmrg __buf_start_pos = __pos - __len / 4;
8736ac495dSmrg if (__buf_start_pos + __len > __leaf_end)
8836ac495dSmrg __buf_start_pos = __leaf_end - __len;
8936ac495dSmrg }
9036ac495dSmrg if (__buf_start_pos + __len > __leaf_end)
9136ac495dSmrg __len = __leaf_end - __buf_start_pos;
9236ac495dSmrg (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf);
9336ac495dSmrg __x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos);
9436ac495dSmrg __x._M_buf_start = __x._M_tmp_buf;
9536ac495dSmrg __x._M_buf_end = __x._M_tmp_buf + __len;
9636ac495dSmrg }
9736ac495dSmrg break;
9836ac495dSmrg default:
9936ac495dSmrg break;
10036ac495dSmrg }
10136ac495dSmrg }
10236ac495dSmrg
10336ac495dSmrg // Set path and buffer inside a rope iterator. We assume that
10436ac495dSmrg // pos and root are already set.
10536ac495dSmrg template <class _CharT, class _Alloc>
10636ac495dSmrg void
10736ac495dSmrg _Rope_iterator_base<_CharT, _Alloc>::
10836ac495dSmrg _S_setcache(_Rope_iterator_base<_CharT, _Alloc>& __x)
10936ac495dSmrg {
110*8feb0f0bSmrg using std::size_t;
11136ac495dSmrg const _RopeRep* __path[int(__detail::_S_max_rope_depth) + 1];
11236ac495dSmrg const _RopeRep* __curr_rope;
11336ac495dSmrg int __curr_depth = -1; /* index into path */
11436ac495dSmrg size_t __curr_start_pos = 0;
11536ac495dSmrg size_t __pos = __x._M_current_pos;
11636ac495dSmrg unsigned char __dirns = 0; // Bit vector marking right turns in the path
11736ac495dSmrg
11836ac495dSmrg if (__pos >= __x._M_root->_M_size)
11936ac495dSmrg {
12036ac495dSmrg __x._M_buf_ptr = 0;
12136ac495dSmrg return;
12236ac495dSmrg }
12336ac495dSmrg __curr_rope = __x._M_root;
12436ac495dSmrg if (0 != __curr_rope->_M_c_string)
12536ac495dSmrg {
12636ac495dSmrg /* Treat the root as a leaf. */
12736ac495dSmrg __x._M_buf_start = __curr_rope->_M_c_string;
12836ac495dSmrg __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size;
12936ac495dSmrg __x._M_buf_ptr = __curr_rope->_M_c_string + __pos;
13036ac495dSmrg __x._M_path_end[0] = __curr_rope;
13136ac495dSmrg __x._M_leaf_index = 0;
13236ac495dSmrg __x._M_leaf_pos = 0;
13336ac495dSmrg return;
13436ac495dSmrg }
13536ac495dSmrg for(;;)
13636ac495dSmrg {
13736ac495dSmrg ++__curr_depth;
13836ac495dSmrg __path[__curr_depth] = __curr_rope;
13936ac495dSmrg switch(__curr_rope->_M_tag)
14036ac495dSmrg {
14136ac495dSmrg case __detail::_S_leaf:
14236ac495dSmrg case __detail::_S_function:
14336ac495dSmrg case __detail::_S_substringfn:
14436ac495dSmrg __x._M_leaf_pos = __curr_start_pos;
14536ac495dSmrg goto done;
14636ac495dSmrg case __detail::_S_concat:
14736ac495dSmrg {
14836ac495dSmrg _Rope_RopeConcatenation<_CharT, _Alloc>* __c =
14936ac495dSmrg (_Rope_RopeConcatenation<_CharT, _Alloc>*)__curr_rope;
15036ac495dSmrg _RopeRep* __left = __c->_M_left;
15136ac495dSmrg size_t __left_len = __left->_M_size;
15236ac495dSmrg
15336ac495dSmrg __dirns <<= 1;
15436ac495dSmrg if (__pos >= __curr_start_pos + __left_len)
15536ac495dSmrg {
15636ac495dSmrg __dirns |= 1;
15736ac495dSmrg __curr_rope = __c->_M_right;
15836ac495dSmrg __curr_start_pos += __left_len;
15936ac495dSmrg }
16036ac495dSmrg else
16136ac495dSmrg __curr_rope = __left;
16236ac495dSmrg }
16336ac495dSmrg break;
16436ac495dSmrg }
16536ac495dSmrg }
16636ac495dSmrg done:
16736ac495dSmrg // Copy last section of path into _M_path_end.
16836ac495dSmrg {
16936ac495dSmrg int __i = -1;
17036ac495dSmrg int __j = __curr_depth + 1 - int(_S_path_cache_len);
17136ac495dSmrg
17236ac495dSmrg if (__j < 0) __j = 0;
17336ac495dSmrg while (__j <= __curr_depth)
17436ac495dSmrg __x._M_path_end[++__i] = __path[__j++];
17536ac495dSmrg __x._M_leaf_index = __i;
17636ac495dSmrg }
17736ac495dSmrg __x._M_path_directions = __dirns;
17836ac495dSmrg _S_setbuf(__x);
17936ac495dSmrg }
18036ac495dSmrg
18136ac495dSmrg // Specialized version of the above. Assumes that
18236ac495dSmrg // the path cache is valid for the previous position.
18336ac495dSmrg template <class _CharT, class _Alloc>
18436ac495dSmrg void
18536ac495dSmrg _Rope_iterator_base<_CharT, _Alloc>::
18636ac495dSmrg _S_setcache_for_incr(_Rope_iterator_base<_CharT, _Alloc>& __x)
18736ac495dSmrg {
188*8feb0f0bSmrg using std::size_t;
18936ac495dSmrg int __current_index = __x._M_leaf_index;
19036ac495dSmrg const _RopeRep* __current_node = __x._M_path_end[__current_index];
19136ac495dSmrg size_t __len = __current_node->_M_size;
19236ac495dSmrg size_t __node_start_pos = __x._M_leaf_pos;
19336ac495dSmrg unsigned char __dirns = __x._M_path_directions;
19436ac495dSmrg _Rope_RopeConcatenation<_CharT, _Alloc>* __c;
19536ac495dSmrg
19636ac495dSmrg if (__x._M_current_pos - __node_start_pos < __len)
19736ac495dSmrg {
19836ac495dSmrg /* More stuff in this leaf, we just didn't cache it. */
19936ac495dSmrg _S_setbuf(__x);
20036ac495dSmrg return;
20136ac495dSmrg }
20236ac495dSmrg // node_start_pos is starting position of last_node.
20336ac495dSmrg while (--__current_index >= 0)
20436ac495dSmrg {
20536ac495dSmrg if (!(__dirns & 1) /* Path turned left */)
20636ac495dSmrg break;
20736ac495dSmrg __current_node = __x._M_path_end[__current_index];
20836ac495dSmrg __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node;
20936ac495dSmrg // Otherwise we were in the right child. Thus we should pop
21036ac495dSmrg // the concatenation node.
21136ac495dSmrg __node_start_pos -= __c->_M_left->_M_size;
21236ac495dSmrg __dirns >>= 1;
21336ac495dSmrg }
21436ac495dSmrg if (__current_index < 0)
21536ac495dSmrg {
21636ac495dSmrg // We underflowed the cache. Punt.
21736ac495dSmrg _S_setcache(__x);
21836ac495dSmrg return;
21936ac495dSmrg }
22036ac495dSmrg __current_node = __x._M_path_end[__current_index];
22136ac495dSmrg __c = (_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node;
22236ac495dSmrg // current_node is a concatenation node. We are positioned on the first
22336ac495dSmrg // character in its right child.
22436ac495dSmrg // node_start_pos is starting position of current_node.
22536ac495dSmrg __node_start_pos += __c->_M_left->_M_size;
22636ac495dSmrg __current_node = __c->_M_right;
22736ac495dSmrg __x._M_path_end[++__current_index] = __current_node;
22836ac495dSmrg __dirns |= 1;
22936ac495dSmrg while (__detail::_S_concat == __current_node->_M_tag)
23036ac495dSmrg {
23136ac495dSmrg ++__current_index;
23236ac495dSmrg if (int(_S_path_cache_len) == __current_index)
23336ac495dSmrg {
23436ac495dSmrg int __i;
23536ac495dSmrg for (__i = 0; __i < int(_S_path_cache_len) - 1; __i++)
23636ac495dSmrg __x._M_path_end[__i] = __x._M_path_end[__i+1];
23736ac495dSmrg --__current_index;
23836ac495dSmrg }
23936ac495dSmrg __current_node =
24036ac495dSmrg ((_Rope_RopeConcatenation<_CharT, _Alloc>*)__current_node)->_M_left;
24136ac495dSmrg __x._M_path_end[__current_index] = __current_node;
24236ac495dSmrg __dirns <<= 1;
24336ac495dSmrg // node_start_pos is unchanged.
24436ac495dSmrg }
24536ac495dSmrg __x._M_leaf_index = __current_index;
24636ac495dSmrg __x._M_leaf_pos = __node_start_pos;
24736ac495dSmrg __x._M_path_directions = __dirns;
24836ac495dSmrg _S_setbuf(__x);
24936ac495dSmrg }
25036ac495dSmrg
25136ac495dSmrg template <class _CharT, class _Alloc>
25236ac495dSmrg void
25336ac495dSmrg _Rope_iterator_base<_CharT, _Alloc>::
254*8feb0f0bSmrg _M_incr(std::size_t __n)
25536ac495dSmrg {
25636ac495dSmrg _M_current_pos += __n;
25736ac495dSmrg if (0 != _M_buf_ptr)
25836ac495dSmrg {
259*8feb0f0bSmrg std::size_t __chars_left = _M_buf_end - _M_buf_ptr;
26036ac495dSmrg if (__chars_left > __n)
26136ac495dSmrg _M_buf_ptr += __n;
26236ac495dSmrg else if (__chars_left == __n)
26336ac495dSmrg {
26436ac495dSmrg _M_buf_ptr += __n;
26536ac495dSmrg _S_setcache_for_incr(*this);
26636ac495dSmrg }
26736ac495dSmrg else
26836ac495dSmrg _M_buf_ptr = 0;
26936ac495dSmrg }
27036ac495dSmrg }
27136ac495dSmrg
27236ac495dSmrg template <class _CharT, class _Alloc>
27336ac495dSmrg void
27436ac495dSmrg _Rope_iterator_base<_CharT, _Alloc>::
275*8feb0f0bSmrg _M_decr(std::size_t __n)
27636ac495dSmrg {
27736ac495dSmrg if (0 != _M_buf_ptr)
27836ac495dSmrg {
279*8feb0f0bSmrg std::size_t __chars_left = _M_buf_ptr - _M_buf_start;
28036ac495dSmrg if (__chars_left >= __n)
28136ac495dSmrg _M_buf_ptr -= __n;
28236ac495dSmrg else
28336ac495dSmrg _M_buf_ptr = 0;
28436ac495dSmrg }
28536ac495dSmrg _M_current_pos -= __n;
28636ac495dSmrg }
28736ac495dSmrg
28836ac495dSmrg template <class _CharT, class _Alloc>
28936ac495dSmrg void
29036ac495dSmrg _Rope_iterator<_CharT, _Alloc>::
29136ac495dSmrg _M_check()
29236ac495dSmrg {
29336ac495dSmrg if (_M_root_rope->_M_tree_ptr != this->_M_root)
29436ac495dSmrg {
29536ac495dSmrg // _Rope was modified. Get things fixed up.
29636ac495dSmrg _RopeRep::_S_unref(this->_M_root);
29736ac495dSmrg this->_M_root = _M_root_rope->_M_tree_ptr;
29836ac495dSmrg _RopeRep::_S_ref(this->_M_root);
29936ac495dSmrg this->_M_buf_ptr = 0;
30036ac495dSmrg }
30136ac495dSmrg }
30236ac495dSmrg
30336ac495dSmrg template <class _CharT, class _Alloc>
30436ac495dSmrg inline
30536ac495dSmrg _Rope_const_iterator<_CharT, _Alloc>::
30636ac495dSmrg _Rope_const_iterator(const _Rope_iterator<_CharT, _Alloc>& __x)
30736ac495dSmrg : _Rope_iterator_base<_CharT, _Alloc>(__x)
30836ac495dSmrg { }
30936ac495dSmrg
31036ac495dSmrg template <class _CharT, class _Alloc>
31136ac495dSmrg inline
31236ac495dSmrg _Rope_iterator<_CharT, _Alloc>::
313*8feb0f0bSmrg _Rope_iterator(rope<_CharT, _Alloc>& __r, std::size_t __pos)
31436ac495dSmrg : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos),
31536ac495dSmrg _M_root_rope(&__r)
31636ac495dSmrg { _RopeRep::_S_ref(this->_M_root); }
31736ac495dSmrg
31836ac495dSmrg template <class _CharT, class _Alloc>
319*8feb0f0bSmrg inline std::size_t
32036ac495dSmrg rope<_CharT, _Alloc>::
32136ac495dSmrg _S_char_ptr_len(const _CharT* __s)
32236ac495dSmrg {
32336ac495dSmrg const _CharT* __p = __s;
32436ac495dSmrg
32536ac495dSmrg while (!_S_is0(*__p))
32636ac495dSmrg ++__p;
32736ac495dSmrg return (__p - __s);
32836ac495dSmrg }
32936ac495dSmrg
33036ac495dSmrg
33136ac495dSmrg #ifndef __GC
33236ac495dSmrg
33336ac495dSmrg template <class _CharT, class _Alloc>
33436ac495dSmrg inline void
33536ac495dSmrg _Rope_RopeRep<_CharT, _Alloc>::
33636ac495dSmrg _M_free_c_string()
33736ac495dSmrg {
33836ac495dSmrg _CharT* __cstr = _M_c_string;
33936ac495dSmrg if (0 != __cstr)
34036ac495dSmrg {
341*8feb0f0bSmrg std::size_t __size = this->_M_size + 1;
342*8feb0f0bSmrg std::_Destroy(__cstr, __cstr + __size, _M_get_allocator());
34336ac495dSmrg this->_Data_deallocate(__cstr, __size);
34436ac495dSmrg }
34536ac495dSmrg }
34636ac495dSmrg
34736ac495dSmrg template <class _CharT, class _Alloc>
34836ac495dSmrg inline void
34936ac495dSmrg _Rope_RopeRep<_CharT, _Alloc>::
350*8feb0f0bSmrg _S_free_string(_CharT* __s, std::size_t __n, allocator_type& __a)
35136ac495dSmrg {
35236ac495dSmrg if (!_S_is_basic_char_type((_CharT*)0))
353*8feb0f0bSmrg std::_Destroy(__s, __s + __n, __a);
35436ac495dSmrg
35536ac495dSmrg // This has to be a static member, so this gets a bit messy
35636ac495dSmrg __a.deallocate(__s,
35736ac495dSmrg _Rope_RopeLeaf<_CharT, _Alloc>::_S_rounded_up_size(__n));
35836ac495dSmrg }
35936ac495dSmrg
36036ac495dSmrg // There are several reasons for not doing this with virtual destructors
36136ac495dSmrg // and a class specific delete operator:
36236ac495dSmrg // - A class specific delete operator can't easily get access to
36336ac495dSmrg // allocator instances if we need them.
36436ac495dSmrg // - Any virtual function would need a 4 or byte vtable pointer;
36536ac495dSmrg // this only requires a one byte tag per object.
36636ac495dSmrg template <class _CharT, class _Alloc>
36736ac495dSmrg void
36836ac495dSmrg _Rope_RopeRep<_CharT, _Alloc>::
36936ac495dSmrg _M_free_tree()
37036ac495dSmrg {
37136ac495dSmrg switch(_M_tag)
37236ac495dSmrg {
37336ac495dSmrg case __detail::_S_leaf:
37436ac495dSmrg {
37536ac495dSmrg _Rope_RopeLeaf<_CharT, _Alloc>* __l
37636ac495dSmrg = (_Rope_RopeLeaf<_CharT, _Alloc>*)this;
37736ac495dSmrg __l->_Rope_RopeLeaf<_CharT, _Alloc>::~_Rope_RopeLeaf();
37836ac495dSmrg this->_L_deallocate(__l, 1);
37936ac495dSmrg break;
38036ac495dSmrg }
38136ac495dSmrg case __detail::_S_concat:
38236ac495dSmrg {
38336ac495dSmrg _Rope_RopeConcatenation<_CharT,_Alloc>* __c
38436ac495dSmrg = (_Rope_RopeConcatenation<_CharT, _Alloc>*)this;
38536ac495dSmrg __c->_Rope_RopeConcatenation<_CharT, _Alloc>::
38636ac495dSmrg ~_Rope_RopeConcatenation();
38736ac495dSmrg this->_C_deallocate(__c, 1);
38836ac495dSmrg break;
38936ac495dSmrg }
39036ac495dSmrg case __detail::_S_function:
39136ac495dSmrg {
39236ac495dSmrg _Rope_RopeFunction<_CharT, _Alloc>* __f
39336ac495dSmrg = (_Rope_RopeFunction<_CharT, _Alloc>*)this;
39436ac495dSmrg __f->_Rope_RopeFunction<_CharT, _Alloc>::~_Rope_RopeFunction();
39536ac495dSmrg this->_F_deallocate(__f, 1);
39636ac495dSmrg break;
39736ac495dSmrg }
39836ac495dSmrg case __detail::_S_substringfn:
39936ac495dSmrg {
40036ac495dSmrg _Rope_RopeSubstring<_CharT, _Alloc>* __ss =
40136ac495dSmrg (_Rope_RopeSubstring<_CharT, _Alloc>*)this;
40236ac495dSmrg __ss->_Rope_RopeSubstring<_CharT, _Alloc>::
40336ac495dSmrg ~_Rope_RopeSubstring();
40436ac495dSmrg this->_S_deallocate(__ss, 1);
40536ac495dSmrg break;
40636ac495dSmrg }
40736ac495dSmrg }
40836ac495dSmrg }
40936ac495dSmrg #else
41036ac495dSmrg
41136ac495dSmrg template <class _CharT, class _Alloc>
41236ac495dSmrg inline void
41336ac495dSmrg _Rope_RopeRep<_CharT, _Alloc>::
414*8feb0f0bSmrg _S_free_string(const _CharT*, std::size_t, allocator_type)
41536ac495dSmrg { }
41636ac495dSmrg
41736ac495dSmrg #endif
41836ac495dSmrg
41936ac495dSmrg // Concatenate a C string onto a leaf rope by copying the rope data.
42036ac495dSmrg // Used for short ropes.
42136ac495dSmrg template <class _CharT, class _Alloc>
42236ac495dSmrg typename rope<_CharT, _Alloc>::_RopeLeaf*
42336ac495dSmrg rope<_CharT, _Alloc>::
424*8feb0f0bSmrg _S_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter,
425*8feb0f0bSmrg std::size_t __len)
42636ac495dSmrg {
427*8feb0f0bSmrg std::size_t __old_len = __r->_M_size;
42836ac495dSmrg _CharT* __new_data = (_CharT*)
42936ac495dSmrg rope::_Data_allocate(_S_rounded_up_size(__old_len + __len));
43036ac495dSmrg _RopeLeaf* __result;
43136ac495dSmrg
43236ac495dSmrg uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
43336ac495dSmrg uninitialized_copy_n(__iter, __len, __new_data + __old_len);
43436ac495dSmrg _S_cond_store_eos(__new_data[__old_len + __len]);
43536ac495dSmrg __try
43636ac495dSmrg {
43736ac495dSmrg __result = _S_new_RopeLeaf(__new_data, __old_len + __len,
43836ac495dSmrg __r->_M_get_allocator());
43936ac495dSmrg }
44036ac495dSmrg __catch(...)
44136ac495dSmrg {
44236ac495dSmrg _RopeRep::__STL_FREE_STRING(__new_data, __old_len + __len,
44336ac495dSmrg __r->_M_get_allocator());
44436ac495dSmrg __throw_exception_again;
44536ac495dSmrg }
44636ac495dSmrg return __result;
44736ac495dSmrg }
44836ac495dSmrg
44936ac495dSmrg #ifndef __GC
45036ac495dSmrg // As above, but it's OK to clobber original if refcount is 1
45136ac495dSmrg template <class _CharT, class _Alloc>
45236ac495dSmrg typename rope<_CharT,_Alloc>::_RopeLeaf*
45336ac495dSmrg rope<_CharT, _Alloc>::
45436ac495dSmrg _S_destr_leaf_concat_char_iter(_RopeLeaf* __r, const _CharT* __iter,
455*8feb0f0bSmrg std::size_t __len)
45636ac495dSmrg {
45736ac495dSmrg if (__r->_M_ref_count > 1)
45836ac495dSmrg return _S_leaf_concat_char_iter(__r, __iter, __len);
459*8feb0f0bSmrg std::size_t __old_len = __r->_M_size;
46036ac495dSmrg if (_S_allocated_capacity(__old_len) >= __old_len + __len)
46136ac495dSmrg {
46236ac495dSmrg // The space has been partially initialized for the standard
46336ac495dSmrg // character types. But that doesn't matter for those types.
46436ac495dSmrg uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len);
46536ac495dSmrg if (_S_is_basic_char_type((_CharT*)0))
46636ac495dSmrg _S_cond_store_eos(__r->_M_data[__old_len + __len]);
46736ac495dSmrg else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string)
46836ac495dSmrg {
46936ac495dSmrg __r->_M_free_c_string();
47036ac495dSmrg __r->_M_c_string = 0;
47136ac495dSmrg }
47236ac495dSmrg __r->_M_size = __old_len + __len;
47336ac495dSmrg __r->_M_ref_count = 2;
47436ac495dSmrg return __r;
47536ac495dSmrg }
47636ac495dSmrg else
47736ac495dSmrg {
47836ac495dSmrg _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len);
47936ac495dSmrg return __result;
48036ac495dSmrg }
48136ac495dSmrg }
48236ac495dSmrg #endif
48336ac495dSmrg
48436ac495dSmrg // Assumes left and right are not 0.
48536ac495dSmrg // Does not increment (nor decrement on exception) child reference counts.
48636ac495dSmrg // Result has ref count 1.
48736ac495dSmrg template <class _CharT, class _Alloc>
48836ac495dSmrg typename rope<_CharT, _Alloc>::_RopeRep*
48936ac495dSmrg rope<_CharT, _Alloc>::
49036ac495dSmrg _S_tree_concat(_RopeRep* __left, _RopeRep* __right)
49136ac495dSmrg {
492*8feb0f0bSmrg using std::size_t;
49336ac495dSmrg _RopeConcatenation* __result = _S_new_RopeConcatenation(__left, __right,
49436ac495dSmrg __left->
49536ac495dSmrg _M_get_allocator());
49636ac495dSmrg size_t __depth = __result->_M_depth;
49736ac495dSmrg
49836ac495dSmrg if (__depth > 20
49936ac495dSmrg && (__result->_M_size < 1000
50036ac495dSmrg || __depth > size_t(__detail::_S_max_rope_depth)))
50136ac495dSmrg {
50236ac495dSmrg _RopeRep* __balanced;
50336ac495dSmrg
50436ac495dSmrg __try
50536ac495dSmrg {
50636ac495dSmrg __balanced = _S_balance(__result);
50736ac495dSmrg __result->_M_unref_nonnil();
50836ac495dSmrg }
50936ac495dSmrg __catch(...)
51036ac495dSmrg {
51136ac495dSmrg rope::_C_deallocate(__result,1);
51236ac495dSmrg __throw_exception_again;
51336ac495dSmrg }
51436ac495dSmrg // In case of exception, we need to deallocate
51536ac495dSmrg // otherwise dangling result node. But caller
51636ac495dSmrg // still owns its children. Thus unref is
51736ac495dSmrg // inappropriate.
51836ac495dSmrg return __balanced;
51936ac495dSmrg }
52036ac495dSmrg else
52136ac495dSmrg return __result;
52236ac495dSmrg }
52336ac495dSmrg
52436ac495dSmrg template <class _CharT, class _Alloc>
52536ac495dSmrg typename rope<_CharT, _Alloc>::_RopeRep*
52636ac495dSmrg rope<_CharT, _Alloc>::
527*8feb0f0bSmrg _S_concat_char_iter(_RopeRep* __r, const _CharT*__s, std::size_t __slen)
52836ac495dSmrg {
529*8feb0f0bSmrg using std::size_t;
53036ac495dSmrg _RopeRep* __result;
53136ac495dSmrg if (0 == __slen)
53236ac495dSmrg {
53336ac495dSmrg _S_ref(__r);
53436ac495dSmrg return __r;
53536ac495dSmrg }
53636ac495dSmrg if (0 == __r)
53736ac495dSmrg return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
53836ac495dSmrg __r->_M_get_allocator());
53936ac495dSmrg if (__r->_M_tag == __detail::_S_leaf
54036ac495dSmrg && __r->_M_size + __slen <= size_t(_S_copy_max))
54136ac495dSmrg {
54236ac495dSmrg __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
54336ac495dSmrg return __result;
54436ac495dSmrg }
54536ac495dSmrg if (__detail::_S_concat == __r->_M_tag
54636ac495dSmrg && __detail::_S_leaf == ((_RopeConcatenation*) __r)->_M_right->_M_tag)
54736ac495dSmrg {
54836ac495dSmrg _RopeLeaf* __right =
54936ac495dSmrg (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right);
55036ac495dSmrg if (__right->_M_size + __slen <= size_t(_S_copy_max))
55136ac495dSmrg {
55236ac495dSmrg _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left;
55336ac495dSmrg _RopeRep* __nright =
55436ac495dSmrg _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen);
55536ac495dSmrg __left->_M_ref_nonnil();
55636ac495dSmrg __try
55736ac495dSmrg { __result = _S_tree_concat(__left, __nright); }
55836ac495dSmrg __catch(...)
55936ac495dSmrg {
56036ac495dSmrg _S_unref(__left);
56136ac495dSmrg _S_unref(__nright);
56236ac495dSmrg __throw_exception_again;
56336ac495dSmrg }
56436ac495dSmrg return __result;
56536ac495dSmrg }
56636ac495dSmrg }
56736ac495dSmrg _RopeRep* __nright =
56836ac495dSmrg __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
56936ac495dSmrg __try
57036ac495dSmrg {
57136ac495dSmrg __r->_M_ref_nonnil();
57236ac495dSmrg __result = _S_tree_concat(__r, __nright);
57336ac495dSmrg }
57436ac495dSmrg __catch(...)
57536ac495dSmrg {
57636ac495dSmrg _S_unref(__r);
57736ac495dSmrg _S_unref(__nright);
57836ac495dSmrg __throw_exception_again;
57936ac495dSmrg }
58036ac495dSmrg return __result;
58136ac495dSmrg }
58236ac495dSmrg
58336ac495dSmrg #ifndef __GC
58436ac495dSmrg template <class _CharT, class _Alloc>
58536ac495dSmrg typename rope<_CharT,_Alloc>::_RopeRep*
58636ac495dSmrg rope<_CharT,_Alloc>::
587*8feb0f0bSmrg _S_destr_concat_char_iter(_RopeRep* __r, const _CharT* __s,
588*8feb0f0bSmrg std::size_t __slen)
58936ac495dSmrg {
590*8feb0f0bSmrg using std::size_t;
59136ac495dSmrg _RopeRep* __result;
59236ac495dSmrg if (0 == __r)
59336ac495dSmrg return __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
59436ac495dSmrg __r->_M_get_allocator());
59536ac495dSmrg size_t __count = __r->_M_ref_count;
59636ac495dSmrg size_t __orig_size = __r->_M_size;
59736ac495dSmrg if (__count > 1)
59836ac495dSmrg return _S_concat_char_iter(__r, __s, __slen);
59936ac495dSmrg if (0 == __slen)
60036ac495dSmrg {
60136ac495dSmrg __r->_M_ref_count = 2; // One more than before
60236ac495dSmrg return __r;
60336ac495dSmrg }
60436ac495dSmrg if (__orig_size + __slen <= size_t(_S_copy_max)
60536ac495dSmrg && __detail::_S_leaf == __r->_M_tag)
60636ac495dSmrg {
60736ac495dSmrg __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s,
60836ac495dSmrg __slen);
60936ac495dSmrg return __result;
61036ac495dSmrg }
61136ac495dSmrg if (__detail::_S_concat == __r->_M_tag)
61236ac495dSmrg {
61336ac495dSmrg _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*)
61436ac495dSmrg __r)->_M_right);
61536ac495dSmrg if (__detail::_S_leaf == __right->_M_tag
61636ac495dSmrg && __right->_M_size + __slen <= size_t(_S_copy_max))
61736ac495dSmrg {
61836ac495dSmrg _RopeRep* __new_right =
61936ac495dSmrg _S_destr_leaf_concat_char_iter(__right, __s, __slen);
62036ac495dSmrg if (__right == __new_right)
62136ac495dSmrg __new_right->_M_ref_count = 1;
62236ac495dSmrg else
62336ac495dSmrg __right->_M_unref_nonnil();
62436ac495dSmrg __r->_M_ref_count = 2; // One more than before.
62536ac495dSmrg ((_RopeConcatenation*)__r)->_M_right = __new_right;
62636ac495dSmrg __r->_M_size = __orig_size + __slen;
62736ac495dSmrg if (0 != __r->_M_c_string)
62836ac495dSmrg {
62936ac495dSmrg __r->_M_free_c_string();
63036ac495dSmrg __r->_M_c_string = 0;
63136ac495dSmrg }
63236ac495dSmrg return __r;
63336ac495dSmrg }
63436ac495dSmrg }
63536ac495dSmrg _RopeRep* __right =
63636ac495dSmrg __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->_M_get_allocator());
63736ac495dSmrg __r->_M_ref_nonnil();
63836ac495dSmrg __try
63936ac495dSmrg { __result = _S_tree_concat(__r, __right); }
64036ac495dSmrg __catch(...)
64136ac495dSmrg {
64236ac495dSmrg _S_unref(__r);
64336ac495dSmrg _S_unref(__right);
64436ac495dSmrg __throw_exception_again;
64536ac495dSmrg }
64636ac495dSmrg return __result;
64736ac495dSmrg }
64836ac495dSmrg #endif /* !__GC */
64936ac495dSmrg
65036ac495dSmrg template <class _CharT, class _Alloc>
65136ac495dSmrg typename rope<_CharT, _Alloc>::_RopeRep*
65236ac495dSmrg rope<_CharT, _Alloc>::
65336ac495dSmrg _S_concat(_RopeRep* __left, _RopeRep* __right)
65436ac495dSmrg {
655*8feb0f0bSmrg using std::size_t;
65636ac495dSmrg if (0 == __left)
65736ac495dSmrg {
65836ac495dSmrg _S_ref(__right);
65936ac495dSmrg return __right;
66036ac495dSmrg }
66136ac495dSmrg if (0 == __right)
66236ac495dSmrg {
66336ac495dSmrg __left->_M_ref_nonnil();
66436ac495dSmrg return __left;
66536ac495dSmrg }
66636ac495dSmrg if (__detail::_S_leaf == __right->_M_tag)
66736ac495dSmrg {
66836ac495dSmrg if (__detail::_S_leaf == __left->_M_tag)
66936ac495dSmrg {
67036ac495dSmrg if (__right->_M_size + __left->_M_size <= size_t(_S_copy_max))
67136ac495dSmrg return _S_leaf_concat_char_iter((_RopeLeaf*)__left,
67236ac495dSmrg ((_RopeLeaf*)__right)->_M_data,
67336ac495dSmrg __right->_M_size);
67436ac495dSmrg }
67536ac495dSmrg else if (__detail::_S_concat == __left->_M_tag
67636ac495dSmrg && __detail::_S_leaf == ((_RopeConcatenation*)
67736ac495dSmrg __left)->_M_right->_M_tag)
67836ac495dSmrg {
67936ac495dSmrg _RopeLeaf* __leftright =
68036ac495dSmrg (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right);
68136ac495dSmrg if (__leftright->_M_size
68236ac495dSmrg + __right->_M_size <= size_t(_S_copy_max))
68336ac495dSmrg {
68436ac495dSmrg _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left;
68536ac495dSmrg _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright,
68636ac495dSmrg ((_RopeLeaf*)
68736ac495dSmrg __right)->
68836ac495dSmrg _M_data,
68936ac495dSmrg __right->_M_size);
69036ac495dSmrg __leftleft->_M_ref_nonnil();
69136ac495dSmrg __try
69236ac495dSmrg { return(_S_tree_concat(__leftleft, __rest)); }
69336ac495dSmrg __catch(...)
69436ac495dSmrg {
69536ac495dSmrg _S_unref(__leftleft);
69636ac495dSmrg _S_unref(__rest);
69736ac495dSmrg __throw_exception_again;
69836ac495dSmrg }
69936ac495dSmrg }
70036ac495dSmrg }
70136ac495dSmrg }
70236ac495dSmrg __left->_M_ref_nonnil();
70336ac495dSmrg __right->_M_ref_nonnil();
70436ac495dSmrg __try
70536ac495dSmrg { return(_S_tree_concat(__left, __right)); }
70636ac495dSmrg __catch(...)
70736ac495dSmrg {
70836ac495dSmrg _S_unref(__left);
70936ac495dSmrg _S_unref(__right);
71036ac495dSmrg __throw_exception_again;
71136ac495dSmrg }
71236ac495dSmrg }
71336ac495dSmrg
71436ac495dSmrg template <class _CharT, class _Alloc>
71536ac495dSmrg typename rope<_CharT, _Alloc>::_RopeRep*
71636ac495dSmrg rope<_CharT, _Alloc>::
717*8feb0f0bSmrg _S_substring(_RopeRep* __base, std::size_t __start, std::size_t __endp1)
71836ac495dSmrg {
719*8feb0f0bSmrg using std::size_t;
72036ac495dSmrg if (0 == __base)
72136ac495dSmrg return 0;
72236ac495dSmrg size_t __len = __base->_M_size;
72336ac495dSmrg size_t __adj_endp1;
72436ac495dSmrg const size_t __lazy_threshold = 128;
72536ac495dSmrg
72636ac495dSmrg if (__endp1 >= __len)
72736ac495dSmrg {
72836ac495dSmrg if (0 == __start)
72936ac495dSmrg {
73036ac495dSmrg __base->_M_ref_nonnil();
73136ac495dSmrg return __base;
73236ac495dSmrg }
73336ac495dSmrg else
73436ac495dSmrg __adj_endp1 = __len;
73536ac495dSmrg
73636ac495dSmrg }
73736ac495dSmrg else
73836ac495dSmrg __adj_endp1 = __endp1;
73936ac495dSmrg
74036ac495dSmrg switch(__base->_M_tag)
74136ac495dSmrg {
74236ac495dSmrg case __detail::_S_concat:
74336ac495dSmrg {
74436ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__base;
74536ac495dSmrg _RopeRep* __left = __c->_M_left;
74636ac495dSmrg _RopeRep* __right = __c->_M_right;
74736ac495dSmrg size_t __left_len = __left->_M_size;
74836ac495dSmrg _RopeRep* __result;
74936ac495dSmrg
75036ac495dSmrg if (__adj_endp1 <= __left_len)
75136ac495dSmrg return _S_substring(__left, __start, __endp1);
75236ac495dSmrg else if (__start >= __left_len)
75336ac495dSmrg return _S_substring(__right, __start - __left_len,
75436ac495dSmrg __adj_endp1 - __left_len);
75536ac495dSmrg _Self_destruct_ptr __left_result(_S_substring(__left,
75636ac495dSmrg __start,
75736ac495dSmrg __left_len));
75836ac495dSmrg _Self_destruct_ptr __right_result(_S_substring(__right, 0,
75936ac495dSmrg __endp1
76036ac495dSmrg - __left_len));
76136ac495dSmrg __result = _S_concat(__left_result, __right_result);
76236ac495dSmrg return __result;
76336ac495dSmrg }
76436ac495dSmrg case __detail::_S_leaf:
76536ac495dSmrg {
76636ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*)__base;
76736ac495dSmrg _RopeLeaf* __result;
76836ac495dSmrg size_t __result_len;
76936ac495dSmrg if (__start >= __adj_endp1)
77036ac495dSmrg return 0;
77136ac495dSmrg __result_len = __adj_endp1 - __start;
77236ac495dSmrg if (__result_len > __lazy_threshold)
77336ac495dSmrg goto lazy;
77436ac495dSmrg #ifdef __GC
77536ac495dSmrg const _CharT* __section = __l->_M_data + __start;
77636ac495dSmrg __result = _S_new_RopeLeaf(__section, __result_len,
77736ac495dSmrg __base->_M_get_allocator());
77836ac495dSmrg __result->_M_c_string = 0; // Not eos terminated.
77936ac495dSmrg #else
78036ac495dSmrg // We should sometimes create substring node instead.
78136ac495dSmrg __result = __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__l->_M_data + __start,
78236ac495dSmrg __result_len,
78336ac495dSmrg __base->
78436ac495dSmrg _M_get_allocator());
78536ac495dSmrg #endif
78636ac495dSmrg return __result;
78736ac495dSmrg }
78836ac495dSmrg case __detail::_S_substringfn:
78936ac495dSmrg // Avoid introducing multiple layers of substring nodes.
79036ac495dSmrg {
79136ac495dSmrg _RopeSubstring* __old = (_RopeSubstring*)__base;
79236ac495dSmrg size_t __result_len;
79336ac495dSmrg if (__start >= __adj_endp1)
79436ac495dSmrg return 0;
79536ac495dSmrg __result_len = __adj_endp1 - __start;
79636ac495dSmrg if (__result_len > __lazy_threshold)
79736ac495dSmrg {
79836ac495dSmrg _RopeSubstring* __result =
79936ac495dSmrg _S_new_RopeSubstring(__old->_M_base,
80036ac495dSmrg __start + __old->_M_start,
80136ac495dSmrg __adj_endp1 - __start,
80236ac495dSmrg __base->_M_get_allocator());
80336ac495dSmrg return __result;
80436ac495dSmrg
80536ac495dSmrg } // *** else fall through: ***
80636ac495dSmrg }
80736ac495dSmrg case __detail::_S_function:
80836ac495dSmrg {
80936ac495dSmrg _RopeFunction* __f = (_RopeFunction*)__base;
81036ac495dSmrg _CharT* __section;
81136ac495dSmrg size_t __result_len;
81236ac495dSmrg if (__start >= __adj_endp1)
81336ac495dSmrg return 0;
81436ac495dSmrg __result_len = __adj_endp1 - __start;
81536ac495dSmrg
81636ac495dSmrg if (__result_len > __lazy_threshold)
81736ac495dSmrg goto lazy;
81836ac495dSmrg __section = (_CharT*)
81936ac495dSmrg rope::_Data_allocate(_S_rounded_up_size(__result_len));
82036ac495dSmrg __try
82136ac495dSmrg { (*(__f->_M_fn))(__start, __result_len, __section); }
82236ac495dSmrg __catch(...)
82336ac495dSmrg {
82436ac495dSmrg _RopeRep::__STL_FREE_STRING(__section, __result_len,
82536ac495dSmrg __base->_M_get_allocator());
82636ac495dSmrg __throw_exception_again;
82736ac495dSmrg }
82836ac495dSmrg _S_cond_store_eos(__section[__result_len]);
82936ac495dSmrg return _S_new_RopeLeaf(__section, __result_len,
83036ac495dSmrg __base->_M_get_allocator());
83136ac495dSmrg }
83236ac495dSmrg }
83336ac495dSmrg lazy:
83436ac495dSmrg {
83536ac495dSmrg // Create substring node.
83636ac495dSmrg return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start,
83736ac495dSmrg __base->_M_get_allocator());
83836ac495dSmrg }
83936ac495dSmrg }
84036ac495dSmrg
84136ac495dSmrg template<class _CharT>
84236ac495dSmrg class _Rope_flatten_char_consumer
84336ac495dSmrg : public _Rope_char_consumer<_CharT>
84436ac495dSmrg {
84536ac495dSmrg private:
84636ac495dSmrg _CharT* _M_buf_ptr;
84736ac495dSmrg public:
84836ac495dSmrg
84936ac495dSmrg _Rope_flatten_char_consumer(_CharT* __buffer)
850a2dc1f3fSmrg { _M_buf_ptr = __buffer; }
85136ac495dSmrg
85236ac495dSmrg ~_Rope_flatten_char_consumer() {}
85336ac495dSmrg
85436ac495dSmrg bool
855*8feb0f0bSmrg operator()(const _CharT* __leaf, std::size_t __n)
85636ac495dSmrg {
85736ac495dSmrg uninitialized_copy_n(__leaf, __n, _M_buf_ptr);
85836ac495dSmrg _M_buf_ptr += __n;
85936ac495dSmrg return true;
86036ac495dSmrg }
86136ac495dSmrg };
86236ac495dSmrg
86336ac495dSmrg template<class _CharT>
86436ac495dSmrg class _Rope_find_char_char_consumer
86536ac495dSmrg : public _Rope_char_consumer<_CharT>
86636ac495dSmrg {
86736ac495dSmrg private:
86836ac495dSmrg _CharT _M_pattern;
86936ac495dSmrg public:
870*8feb0f0bSmrg std::size_t _M_count; // Number of nonmatching characters
87136ac495dSmrg
87236ac495dSmrg _Rope_find_char_char_consumer(_CharT __p)
87336ac495dSmrg : _M_pattern(__p), _M_count(0) {}
87436ac495dSmrg
87536ac495dSmrg ~_Rope_find_char_char_consumer() {}
87636ac495dSmrg
87736ac495dSmrg bool
878*8feb0f0bSmrg operator()(const _CharT* __leaf, std::size_t __n)
87936ac495dSmrg {
880*8feb0f0bSmrg std::size_t __i;
88136ac495dSmrg for (__i = 0; __i < __n; __i++)
88236ac495dSmrg {
88336ac495dSmrg if (__leaf[__i] == _M_pattern)
88436ac495dSmrg {
88536ac495dSmrg _M_count += __i;
88636ac495dSmrg return false;
88736ac495dSmrg }
88836ac495dSmrg }
88936ac495dSmrg _M_count += __n; return true;
89036ac495dSmrg }
89136ac495dSmrg };
89236ac495dSmrg
89336ac495dSmrg template<class _CharT, class _Traits>
89436ac495dSmrg // Here _CharT is both the stream and rope character type.
89536ac495dSmrg class _Rope_insert_char_consumer
89636ac495dSmrg : public _Rope_char_consumer<_CharT>
89736ac495dSmrg {
89836ac495dSmrg private:
899*8feb0f0bSmrg typedef std::basic_ostream<_CharT,_Traits> _Insert_ostream;
90036ac495dSmrg _Insert_ostream& _M_o;
90136ac495dSmrg public:
90236ac495dSmrg _Rope_insert_char_consumer(_Insert_ostream& __writer)
903a2dc1f3fSmrg : _M_o(__writer) {}
904a2dc1f3fSmrg ~_Rope_insert_char_consumer() { }
90536ac495dSmrg // Caller is presumed to own the ostream
906*8feb0f0bSmrg bool operator() (const _CharT* __leaf, std::size_t __n);
90736ac495dSmrg // Returns true to continue traversal.
90836ac495dSmrg };
90936ac495dSmrg
91036ac495dSmrg template<class _CharT, class _Traits>
91136ac495dSmrg bool
91236ac495dSmrg _Rope_insert_char_consumer<_CharT, _Traits>::
913*8feb0f0bSmrg operator()(const _CharT* __leaf, std::size_t __n)
91436ac495dSmrg {
915*8feb0f0bSmrg std::size_t __i;
91636ac495dSmrg // We assume that formatting is set up correctly for each element.
91736ac495dSmrg for (__i = 0; __i < __n; __i++)
91836ac495dSmrg _M_o.put(__leaf[__i]);
91936ac495dSmrg return true;
92036ac495dSmrg }
92136ac495dSmrg
92236ac495dSmrg template <class _CharT, class _Alloc>
92336ac495dSmrg bool
92436ac495dSmrg rope<_CharT, _Alloc>::
925*8feb0f0bSmrg _S_apply_to_pieces(_Rope_char_consumer<_CharT>& __c, const _RopeRep* __r,
926*8feb0f0bSmrg std::size_t __begin, std::size_t __end)
92736ac495dSmrg {
928*8feb0f0bSmrg using std::size_t;
92936ac495dSmrg if (0 == __r)
93036ac495dSmrg return true;
93136ac495dSmrg switch(__r->_M_tag)
93236ac495dSmrg {
93336ac495dSmrg case __detail::_S_concat:
93436ac495dSmrg {
93536ac495dSmrg _RopeConcatenation* __conc = (_RopeConcatenation*)__r;
93636ac495dSmrg _RopeRep* __left = __conc->_M_left;
93736ac495dSmrg size_t __left_len = __left->_M_size;
93836ac495dSmrg if (__begin < __left_len)
93936ac495dSmrg {
94036ac495dSmrg size_t __left_end = std::min(__left_len, __end);
94136ac495dSmrg if (!_S_apply_to_pieces(__c, __left, __begin, __left_end))
94236ac495dSmrg return false;
94336ac495dSmrg }
94436ac495dSmrg if (__end > __left_len)
94536ac495dSmrg {
94636ac495dSmrg _RopeRep* __right = __conc->_M_right;
94736ac495dSmrg size_t __right_start = std::max(__left_len, __begin);
94836ac495dSmrg if (!_S_apply_to_pieces(__c, __right,
94936ac495dSmrg __right_start - __left_len,
95036ac495dSmrg __end - __left_len))
95136ac495dSmrg return false;
95236ac495dSmrg }
95336ac495dSmrg }
95436ac495dSmrg return true;
95536ac495dSmrg case __detail::_S_leaf:
95636ac495dSmrg {
95736ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*)__r;
95836ac495dSmrg return __c(__l->_M_data + __begin, __end - __begin);
95936ac495dSmrg }
96036ac495dSmrg case __detail::_S_function:
96136ac495dSmrg case __detail::_S_substringfn:
96236ac495dSmrg {
96336ac495dSmrg _RopeFunction* __f = (_RopeFunction*)__r;
96436ac495dSmrg size_t __len = __end - __begin;
96536ac495dSmrg bool __result;
96636ac495dSmrg _CharT* __buffer =
96736ac495dSmrg (_CharT*)_Alloc().allocate(__len * sizeof(_CharT));
96836ac495dSmrg __try
96936ac495dSmrg {
97036ac495dSmrg (*(__f->_M_fn))(__begin, __len, __buffer);
97136ac495dSmrg __result = __c(__buffer, __len);
97236ac495dSmrg _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
97336ac495dSmrg }
97436ac495dSmrg __catch(...)
97536ac495dSmrg {
97636ac495dSmrg _Alloc().deallocate(__buffer, __len * sizeof(_CharT));
97736ac495dSmrg __throw_exception_again;
97836ac495dSmrg }
97936ac495dSmrg return __result;
98036ac495dSmrg }
98136ac495dSmrg default:
98236ac495dSmrg return false;
98336ac495dSmrg }
98436ac495dSmrg }
98536ac495dSmrg
98636ac495dSmrg template<class _CharT, class _Traits>
98736ac495dSmrg inline void
988*8feb0f0bSmrg _Rope_fill(std::basic_ostream<_CharT, _Traits>& __o, std::size_t __n)
98936ac495dSmrg {
99036ac495dSmrg char __f = __o.fill();
991*8feb0f0bSmrg std::size_t __i;
99236ac495dSmrg
99336ac495dSmrg for (__i = 0; __i < __n; __i++)
99436ac495dSmrg __o.put(__f);
99536ac495dSmrg }
99636ac495dSmrg
99736ac495dSmrg
99836ac495dSmrg template <class _CharT>
99936ac495dSmrg inline bool
100036ac495dSmrg _Rope_is_simple(_CharT*)
100136ac495dSmrg { return false; }
100236ac495dSmrg
100336ac495dSmrg inline bool
100436ac495dSmrg _Rope_is_simple(char*)
100536ac495dSmrg { return true; }
100636ac495dSmrg
100736ac495dSmrg inline bool
100836ac495dSmrg _Rope_is_simple(wchar_t*)
100936ac495dSmrg { return true; }
101036ac495dSmrg
101136ac495dSmrg template<class _CharT, class _Traits, class _Alloc>
1012*8feb0f0bSmrg std::basic_ostream<_CharT, _Traits>&
1013*8feb0f0bSmrg operator<<(std::basic_ostream<_CharT, _Traits>& __o,
101436ac495dSmrg const rope<_CharT, _Alloc>& __r)
101536ac495dSmrg {
1016*8feb0f0bSmrg using std::size_t;
101736ac495dSmrg size_t __w = __o.width();
101836ac495dSmrg bool __left = bool(__o.flags() & std::ios::left);
101936ac495dSmrg size_t __pad_len;
102036ac495dSmrg size_t __rope_len = __r.size();
102136ac495dSmrg _Rope_insert_char_consumer<_CharT, _Traits> __c(__o);
102236ac495dSmrg bool __is_simple = _Rope_is_simple((_CharT*)0);
102336ac495dSmrg
102436ac495dSmrg if (__rope_len < __w)
102536ac495dSmrg __pad_len = __w - __rope_len;
102636ac495dSmrg else
102736ac495dSmrg __pad_len = 0;
102836ac495dSmrg
102936ac495dSmrg if (!__is_simple)
103036ac495dSmrg __o.width(__w / __rope_len);
103136ac495dSmrg __try
103236ac495dSmrg {
103336ac495dSmrg if (__is_simple && !__left && __pad_len > 0)
103436ac495dSmrg _Rope_fill(__o, __pad_len);
103536ac495dSmrg __r.apply_to_pieces(0, __r.size(), __c);
103636ac495dSmrg if (__is_simple && __left && __pad_len > 0)
103736ac495dSmrg _Rope_fill(__o, __pad_len);
103836ac495dSmrg if (!__is_simple)
103936ac495dSmrg __o.width(__w);
104036ac495dSmrg }
104136ac495dSmrg __catch(...)
104236ac495dSmrg {
104336ac495dSmrg if (!__is_simple)
104436ac495dSmrg __o.width(__w);
104536ac495dSmrg __throw_exception_again;
104636ac495dSmrg }
104736ac495dSmrg return __o;
104836ac495dSmrg }
104936ac495dSmrg
105036ac495dSmrg template <class _CharT, class _Alloc>
105136ac495dSmrg _CharT*
105236ac495dSmrg rope<_CharT, _Alloc>::
1053*8feb0f0bSmrg _S_flatten(_RopeRep* __r, std::size_t __start, std::size_t __len,
105436ac495dSmrg _CharT* __buffer)
105536ac495dSmrg {
105636ac495dSmrg _Rope_flatten_char_consumer<_CharT> __c(__buffer);
105736ac495dSmrg _S_apply_to_pieces(__c, __r, __start, __start + __len);
105836ac495dSmrg return(__buffer + __len);
105936ac495dSmrg }
106036ac495dSmrg
106136ac495dSmrg template <class _CharT, class _Alloc>
1062*8feb0f0bSmrg std::size_t
106336ac495dSmrg rope<_CharT, _Alloc>::
1064*8feb0f0bSmrg find(_CharT __pattern, std::size_t __start) const
106536ac495dSmrg {
106636ac495dSmrg _Rope_find_char_char_consumer<_CharT> __c(__pattern);
106736ac495dSmrg _S_apply_to_pieces(__c, this->_M_tree_ptr, __start, size());
106836ac495dSmrg size_type __result_pos = __start + __c._M_count;
106936ac495dSmrg #ifndef __STL_OLD_ROPE_SEMANTICS
107036ac495dSmrg if (__result_pos == size())
107136ac495dSmrg __result_pos = npos;
107236ac495dSmrg #endif
107336ac495dSmrg return __result_pos;
107436ac495dSmrg }
107536ac495dSmrg
107636ac495dSmrg template <class _CharT, class _Alloc>
107736ac495dSmrg _CharT*
107836ac495dSmrg rope<_CharT, _Alloc>::
107936ac495dSmrg _S_flatten(_RopeRep* __r, _CharT* __buffer)
108036ac495dSmrg {
108136ac495dSmrg if (0 == __r)
108236ac495dSmrg return __buffer;
108336ac495dSmrg switch(__r->_M_tag)
108436ac495dSmrg {
108536ac495dSmrg case __detail::_S_concat:
108636ac495dSmrg {
108736ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__r;
108836ac495dSmrg _RopeRep* __left = __c->_M_left;
108936ac495dSmrg _RopeRep* __right = __c->_M_right;
109036ac495dSmrg _CharT* __rest = _S_flatten(__left, __buffer);
109136ac495dSmrg return _S_flatten(__right, __rest);
109236ac495dSmrg }
109336ac495dSmrg case __detail::_S_leaf:
109436ac495dSmrg {
109536ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*)__r;
109636ac495dSmrg return copy_n(__l->_M_data, __l->_M_size, __buffer).second;
109736ac495dSmrg }
109836ac495dSmrg case __detail::_S_function:
109936ac495dSmrg case __detail::_S_substringfn:
110036ac495dSmrg // We don't yet do anything with substring nodes.
110136ac495dSmrg // This needs to be fixed before ropefiles will work well.
110236ac495dSmrg {
110336ac495dSmrg _RopeFunction* __f = (_RopeFunction*)__r;
110436ac495dSmrg (*(__f->_M_fn))(0, __f->_M_size, __buffer);
110536ac495dSmrg return __buffer + __f->_M_size;
110636ac495dSmrg }
110736ac495dSmrg default:
110836ac495dSmrg return 0;
110936ac495dSmrg }
111036ac495dSmrg }
111136ac495dSmrg
111236ac495dSmrg // This needs work for _CharT != char
111336ac495dSmrg template <class _CharT, class _Alloc>
111436ac495dSmrg void
111536ac495dSmrg rope<_CharT, _Alloc>::
111636ac495dSmrg _S_dump(_RopeRep* __r, int __indent)
111736ac495dSmrg {
1118*8feb0f0bSmrg using std::printf;
111936ac495dSmrg for (int __i = 0; __i < __indent; __i++)
112036ac495dSmrg putchar(' ');
112136ac495dSmrg if (0 == __r)
112236ac495dSmrg {
112336ac495dSmrg printf("NULL\n");
112436ac495dSmrg return;
112536ac495dSmrg }
112636ac495dSmrg if (__detail::_S_concat == __r->_M_tag)
112736ac495dSmrg {
112836ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__r;
112936ac495dSmrg _RopeRep* __left = __c->_M_left;
113036ac495dSmrg _RopeRep* __right = __c->_M_right;
113136ac495dSmrg
113236ac495dSmrg #ifdef __GC
113336ac495dSmrg printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
113436ac495dSmrg __r, __r->_M_depth, __r->_M_size,
113536ac495dSmrg __r->_M_is_balanced? "" : "not");
113636ac495dSmrg #else
113736ac495dSmrg printf("Concatenation %p (rc = %ld, depth = %d, "
113836ac495dSmrg "len = %ld, %s balanced)\n",
113936ac495dSmrg __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size,
114036ac495dSmrg __r->_M_is_balanced? "" : "not");
114136ac495dSmrg #endif
114236ac495dSmrg _S_dump(__left, __indent + 2);
114336ac495dSmrg _S_dump(__right, __indent + 2);
114436ac495dSmrg return;
114536ac495dSmrg }
114636ac495dSmrg else
114736ac495dSmrg {
1148a2dc1f3fSmrg const char* __kind;
114936ac495dSmrg
115036ac495dSmrg switch (__r->_M_tag)
115136ac495dSmrg {
115236ac495dSmrg case __detail::_S_leaf:
115336ac495dSmrg __kind = "Leaf";
115436ac495dSmrg break;
115536ac495dSmrg case __detail::_S_function:
115636ac495dSmrg __kind = "Function";
115736ac495dSmrg break;
115836ac495dSmrg case __detail::_S_substringfn:
115936ac495dSmrg __kind = "Function representing substring";
116036ac495dSmrg break;
116136ac495dSmrg default:
116236ac495dSmrg __kind = "(corrupted kind field!)";
116336ac495dSmrg }
116436ac495dSmrg #ifdef __GC
116536ac495dSmrg printf("%s %p (depth = %d, len = %ld) ",
116636ac495dSmrg __kind, __r, __r->_M_depth, __r->_M_size);
116736ac495dSmrg #else
116836ac495dSmrg printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
116936ac495dSmrg __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size);
117036ac495dSmrg #endif
117136ac495dSmrg if (_S_is_one_byte_char_type((_CharT*)0))
117236ac495dSmrg {
117336ac495dSmrg const int __max_len = 40;
117436ac495dSmrg _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len));
117536ac495dSmrg _CharT __buffer[__max_len + 1];
117636ac495dSmrg bool __too_big = __r->_M_size > __prefix->_M_size;
117736ac495dSmrg
117836ac495dSmrg _S_flatten(__prefix, __buffer);
117936ac495dSmrg __buffer[__prefix->_M_size] = _S_eos((_CharT*)0);
118036ac495dSmrg printf("%s%s\n", (char*)__buffer,
118136ac495dSmrg __too_big? "...\n" : "\n");
118236ac495dSmrg }
118336ac495dSmrg else
118436ac495dSmrg printf("\n");
118536ac495dSmrg }
118636ac495dSmrg }
118736ac495dSmrg
118836ac495dSmrg template <class _CharT, class _Alloc>
118936ac495dSmrg const unsigned long
119036ac495dSmrg rope<_CharT, _Alloc>::
119136ac495dSmrg _S_min_len[int(__detail::_S_max_rope_depth) + 1] = {
119236ac495dSmrg /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21,
119336ac495dSmrg /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377,
119436ac495dSmrg /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181,
119536ac495dSmrg /* 18 */6765, /* 19 */10946, /* 20 */17711, /* 21 */28657, /* 22 */46368,
119636ac495dSmrg /* 23 */75025, /* 24 */121393, /* 25 */196418, /* 26 */317811,
119736ac495dSmrg /* 27 */514229, /* 28 */832040, /* 29 */1346269, /* 30 */2178309,
119836ac495dSmrg /* 31 */3524578, /* 32 */5702887, /* 33 */9227465, /* 34 */14930352,
119936ac495dSmrg /* 35 */24157817, /* 36 */39088169, /* 37 */63245986, /* 38 */102334155,
120036ac495dSmrg /* 39 */165580141, /* 40 */267914296, /* 41 */433494437,
120136ac495dSmrg /* 42 */701408733, /* 43 */1134903170, /* 44 */1836311903,
120236ac495dSmrg /* 45 */2971215073u };
120336ac495dSmrg // These are Fibonacci numbers < 2**32.
120436ac495dSmrg
120536ac495dSmrg template <class _CharT, class _Alloc>
120636ac495dSmrg typename rope<_CharT, _Alloc>::_RopeRep*
120736ac495dSmrg rope<_CharT, _Alloc>::
120836ac495dSmrg _S_balance(_RopeRep* __r)
120936ac495dSmrg {
121036ac495dSmrg _RopeRep* __forest[int(__detail::_S_max_rope_depth) + 1];
121136ac495dSmrg _RopeRep* __result = 0;
121236ac495dSmrg int __i;
121336ac495dSmrg // Invariant:
121436ac495dSmrg // The concatenation of forest in descending order is equal to __r.
121536ac495dSmrg // __forest[__i]._M_size >= _S_min_len[__i]
121636ac495dSmrg // __forest[__i]._M_depth = __i
121736ac495dSmrg // References from forest are included in refcount.
121836ac495dSmrg
121936ac495dSmrg for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
122036ac495dSmrg __forest[__i] = 0;
122136ac495dSmrg __try
122236ac495dSmrg {
122336ac495dSmrg _S_add_to_forest(__r, __forest);
122436ac495dSmrg for (__i = 0; __i <= int(__detail::_S_max_rope_depth); ++__i)
122536ac495dSmrg if (0 != __forest[__i])
122636ac495dSmrg {
122736ac495dSmrg #ifndef __GC
122836ac495dSmrg _Self_destruct_ptr __old(__result);
122936ac495dSmrg #endif
123036ac495dSmrg __result = _S_concat(__forest[__i], __result);
123136ac495dSmrg __forest[__i]->_M_unref_nonnil();
123236ac495dSmrg #if !defined(__GC) && __cpp_exceptions
123336ac495dSmrg __forest[__i] = 0;
123436ac495dSmrg #endif
123536ac495dSmrg }
123636ac495dSmrg }
123736ac495dSmrg __catch(...)
123836ac495dSmrg {
123936ac495dSmrg for(__i = 0; __i <= int(__detail::_S_max_rope_depth); __i++)
124036ac495dSmrg _S_unref(__forest[__i]);
124136ac495dSmrg __throw_exception_again;
124236ac495dSmrg }
124336ac495dSmrg
124436ac495dSmrg if (__result->_M_depth > int(__detail::_S_max_rope_depth))
1245*8feb0f0bSmrg std::__throw_length_error(__N("rope::_S_balance"));
124636ac495dSmrg return(__result);
124736ac495dSmrg }
124836ac495dSmrg
124936ac495dSmrg template <class _CharT, class _Alloc>
125036ac495dSmrg void
125136ac495dSmrg rope<_CharT, _Alloc>::
125236ac495dSmrg _S_add_to_forest(_RopeRep* __r, _RopeRep** __forest)
125336ac495dSmrg {
125436ac495dSmrg if (__r->_M_is_balanced)
125536ac495dSmrg {
125636ac495dSmrg _S_add_leaf_to_forest(__r, __forest);
125736ac495dSmrg return;
125836ac495dSmrg }
125936ac495dSmrg
126036ac495dSmrg {
126136ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__r;
126236ac495dSmrg
126336ac495dSmrg _S_add_to_forest(__c->_M_left, __forest);
126436ac495dSmrg _S_add_to_forest(__c->_M_right, __forest);
126536ac495dSmrg }
126636ac495dSmrg }
126736ac495dSmrg
126836ac495dSmrg
126936ac495dSmrg template <class _CharT, class _Alloc>
127036ac495dSmrg void
127136ac495dSmrg rope<_CharT, _Alloc>::
127236ac495dSmrg _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest)
127336ac495dSmrg {
127436ac495dSmrg _RopeRep* __insertee; // included in refcount
127536ac495dSmrg _RopeRep* __too_tiny = 0; // included in refcount
127636ac495dSmrg int __i; // forest[0..__i-1] is empty
1277*8feb0f0bSmrg std::size_t __s = __r->_M_size;
127836ac495dSmrg
127936ac495dSmrg for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i)
128036ac495dSmrg {
128136ac495dSmrg if (0 != __forest[__i])
128236ac495dSmrg {
128336ac495dSmrg #ifndef __GC
128436ac495dSmrg _Self_destruct_ptr __old(__too_tiny);
128536ac495dSmrg #endif
128636ac495dSmrg __too_tiny = _S_concat_and_set_balanced(__forest[__i],
128736ac495dSmrg __too_tiny);
128836ac495dSmrg __forest[__i]->_M_unref_nonnil();
128936ac495dSmrg __forest[__i] = 0;
129036ac495dSmrg }
129136ac495dSmrg }
129236ac495dSmrg {
129336ac495dSmrg #ifndef __GC
129436ac495dSmrg _Self_destruct_ptr __old(__too_tiny);
129536ac495dSmrg #endif
129636ac495dSmrg __insertee = _S_concat_and_set_balanced(__too_tiny, __r);
129736ac495dSmrg }
129836ac495dSmrg // Too_tiny dead, and no longer included in refcount.
129936ac495dSmrg // Insertee is live and included.
130036ac495dSmrg for (;; ++__i)
130136ac495dSmrg {
130236ac495dSmrg if (0 != __forest[__i])
130336ac495dSmrg {
130436ac495dSmrg #ifndef __GC
130536ac495dSmrg _Self_destruct_ptr __old(__insertee);
130636ac495dSmrg #endif
130736ac495dSmrg __insertee = _S_concat_and_set_balanced(__forest[__i],
130836ac495dSmrg __insertee);
130936ac495dSmrg __forest[__i]->_M_unref_nonnil();
131036ac495dSmrg __forest[__i] = 0;
131136ac495dSmrg }
131236ac495dSmrg if (__i == int(__detail::_S_max_rope_depth)
131336ac495dSmrg || __insertee->_M_size < _S_min_len[__i+1])
131436ac495dSmrg {
131536ac495dSmrg __forest[__i] = __insertee;
131636ac495dSmrg // refcount is OK since __insertee is now dead.
131736ac495dSmrg return;
131836ac495dSmrg }
131936ac495dSmrg }
132036ac495dSmrg }
132136ac495dSmrg
132236ac495dSmrg template <class _CharT, class _Alloc>
132336ac495dSmrg _CharT
132436ac495dSmrg rope<_CharT, _Alloc>::
132536ac495dSmrg _S_fetch(_RopeRep* __r, size_type __i)
132636ac495dSmrg {
132736ac495dSmrg __GC_CONST _CharT* __cstr = __r->_M_c_string;
132836ac495dSmrg
132936ac495dSmrg if (0 != __cstr)
133036ac495dSmrg return __cstr[__i];
133136ac495dSmrg for(;;)
133236ac495dSmrg {
133336ac495dSmrg switch(__r->_M_tag)
133436ac495dSmrg {
133536ac495dSmrg case __detail::_S_concat:
133636ac495dSmrg {
133736ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__r;
133836ac495dSmrg _RopeRep* __left = __c->_M_left;
1339*8feb0f0bSmrg std::size_t __left_len = __left->_M_size;
134036ac495dSmrg
134136ac495dSmrg if (__i >= __left_len)
134236ac495dSmrg {
134336ac495dSmrg __i -= __left_len;
134436ac495dSmrg __r = __c->_M_right;
134536ac495dSmrg }
134636ac495dSmrg else
134736ac495dSmrg __r = __left;
134836ac495dSmrg }
134936ac495dSmrg break;
135036ac495dSmrg case __detail::_S_leaf:
135136ac495dSmrg {
135236ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*)__r;
135336ac495dSmrg return __l->_M_data[__i];
135436ac495dSmrg }
135536ac495dSmrg case __detail::_S_function:
135636ac495dSmrg case __detail::_S_substringfn:
135736ac495dSmrg {
135836ac495dSmrg _RopeFunction* __f = (_RopeFunction*)__r;
135936ac495dSmrg _CharT __result;
136036ac495dSmrg
136136ac495dSmrg (*(__f->_M_fn))(__i, 1, &__result);
136236ac495dSmrg return __result;
136336ac495dSmrg }
136436ac495dSmrg }
136536ac495dSmrg }
136636ac495dSmrg }
136736ac495dSmrg
136836ac495dSmrg #ifndef __GC
136936ac495dSmrg // Return a uniquely referenced character slot for the given
137036ac495dSmrg // position, or 0 if that's not possible.
137136ac495dSmrg template <class _CharT, class _Alloc>
137236ac495dSmrg _CharT*
137336ac495dSmrg rope<_CharT, _Alloc>::
137436ac495dSmrg _S_fetch_ptr(_RopeRep* __r, size_type __i)
137536ac495dSmrg {
137636ac495dSmrg _RopeRep* __clrstack[__detail::_S_max_rope_depth];
1377*8feb0f0bSmrg std::size_t __csptr = 0;
137836ac495dSmrg
137936ac495dSmrg for(;;)
138036ac495dSmrg {
138136ac495dSmrg if (__r->_M_ref_count > 1)
138236ac495dSmrg return 0;
138336ac495dSmrg switch(__r->_M_tag)
138436ac495dSmrg {
138536ac495dSmrg case __detail::_S_concat:
138636ac495dSmrg {
138736ac495dSmrg _RopeConcatenation* __c = (_RopeConcatenation*)__r;
138836ac495dSmrg _RopeRep* __left = __c->_M_left;
1389*8feb0f0bSmrg std::size_t __left_len = __left->_M_size;
139036ac495dSmrg
139136ac495dSmrg if (__c->_M_c_string != 0)
139236ac495dSmrg __clrstack[__csptr++] = __c;
139336ac495dSmrg if (__i >= __left_len)
139436ac495dSmrg {
139536ac495dSmrg __i -= __left_len;
139636ac495dSmrg __r = __c->_M_right;
139736ac495dSmrg }
139836ac495dSmrg else
139936ac495dSmrg __r = __left;
140036ac495dSmrg }
140136ac495dSmrg break;
140236ac495dSmrg case __detail::_S_leaf:
140336ac495dSmrg {
140436ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*)__r;
140536ac495dSmrg if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0)
140636ac495dSmrg __clrstack[__csptr++] = __l;
140736ac495dSmrg while (__csptr > 0)
140836ac495dSmrg {
140936ac495dSmrg -- __csptr;
141036ac495dSmrg _RopeRep* __d = __clrstack[__csptr];
141136ac495dSmrg __d->_M_free_c_string();
141236ac495dSmrg __d->_M_c_string = 0;
141336ac495dSmrg }
141436ac495dSmrg return __l->_M_data + __i;
141536ac495dSmrg }
141636ac495dSmrg case __detail::_S_function:
141736ac495dSmrg case __detail::_S_substringfn:
141836ac495dSmrg return 0;
141936ac495dSmrg }
142036ac495dSmrg }
142136ac495dSmrg }
142236ac495dSmrg #endif /* __GC */
142336ac495dSmrg
142436ac495dSmrg // The following could be implemented trivially using
142536ac495dSmrg // lexicographical_compare_3way.
142636ac495dSmrg // We do a little more work to avoid dealing with rope iterators for
142736ac495dSmrg // flat strings.
142836ac495dSmrg template <class _CharT, class _Alloc>
142936ac495dSmrg int
143036ac495dSmrg rope<_CharT, _Alloc>::
143136ac495dSmrg _S_compare (const _RopeRep* __left, const _RopeRep* __right)
143236ac495dSmrg {
1433*8feb0f0bSmrg std::size_t __left_len;
1434*8feb0f0bSmrg std::size_t __right_len;
143536ac495dSmrg
143636ac495dSmrg if (0 == __right)
143736ac495dSmrg return 0 != __left;
143836ac495dSmrg if (0 == __left)
143936ac495dSmrg return -1;
144036ac495dSmrg __left_len = __left->_M_size;
144136ac495dSmrg __right_len = __right->_M_size;
144236ac495dSmrg if (__detail::_S_leaf == __left->_M_tag)
144336ac495dSmrg {
144436ac495dSmrg _RopeLeaf* __l = (_RopeLeaf*) __left;
144536ac495dSmrg if (__detail::_S_leaf == __right->_M_tag)
144636ac495dSmrg {
144736ac495dSmrg _RopeLeaf* __r = (_RopeLeaf*) __right;
144836ac495dSmrg return lexicographical_compare_3way(__l->_M_data,
144936ac495dSmrg __l->_M_data + __left_len,
145036ac495dSmrg __r->_M_data, __r->_M_data
145136ac495dSmrg + __right_len);
145236ac495dSmrg }
145336ac495dSmrg else
145436ac495dSmrg {
145536ac495dSmrg const_iterator __rstart(__right, 0);
145636ac495dSmrg const_iterator __rend(__right, __right_len);
145736ac495dSmrg return lexicographical_compare_3way(__l->_M_data, __l->_M_data
145836ac495dSmrg + __left_len,
145936ac495dSmrg __rstart, __rend);
146036ac495dSmrg }
146136ac495dSmrg }
146236ac495dSmrg else
146336ac495dSmrg {
146436ac495dSmrg const_iterator __lstart(__left, 0);
146536ac495dSmrg const_iterator __lend(__left, __left_len);
146636ac495dSmrg if (__detail::_S_leaf == __right->_M_tag)
146736ac495dSmrg {
146836ac495dSmrg _RopeLeaf* __r = (_RopeLeaf*) __right;
146936ac495dSmrg return lexicographical_compare_3way(__lstart, __lend,
147036ac495dSmrg __r->_M_data, __r->_M_data
147136ac495dSmrg + __right_len);
147236ac495dSmrg }
147336ac495dSmrg else
147436ac495dSmrg {
147536ac495dSmrg const_iterator __rstart(__right, 0);
147636ac495dSmrg const_iterator __rend(__right, __right_len);
147736ac495dSmrg return lexicographical_compare_3way(__lstart, __lend,
147836ac495dSmrg __rstart, __rend);
147936ac495dSmrg }
148036ac495dSmrg }
148136ac495dSmrg }
148236ac495dSmrg
148336ac495dSmrg // Assignment to reference proxies.
148436ac495dSmrg template <class _CharT, class _Alloc>
148536ac495dSmrg _Rope_char_ref_proxy<_CharT, _Alloc>&
148636ac495dSmrg _Rope_char_ref_proxy<_CharT, _Alloc>::
148736ac495dSmrg operator=(_CharT __c)
148836ac495dSmrg {
148936ac495dSmrg _RopeRep* __old = _M_root->_M_tree_ptr;
149036ac495dSmrg #ifndef __GC
149136ac495dSmrg // First check for the case in which everything is uniquely
149236ac495dSmrg // referenced. In that case we can do this destructively.
149336ac495dSmrg _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos);
149436ac495dSmrg if (0 != __ptr)
149536ac495dSmrg {
149636ac495dSmrg *__ptr = __c;
149736ac495dSmrg return *this;
149836ac495dSmrg }
149936ac495dSmrg #endif
150036ac495dSmrg _Self_destruct_ptr __left(_My_rope::_S_substring(__old, 0, _M_pos));
150136ac495dSmrg _Self_destruct_ptr __right(_My_rope::_S_substring(__old, _M_pos + 1,
150236ac495dSmrg __old->_M_size));
150336ac495dSmrg _Self_destruct_ptr __result_left(_My_rope::
150436ac495dSmrg _S_destr_concat_char_iter(__left,
150536ac495dSmrg &__c, 1));
150636ac495dSmrg
150736ac495dSmrg _RopeRep* __result = _My_rope::_S_concat(__result_left, __right);
150836ac495dSmrg #ifndef __GC
150936ac495dSmrg _RopeRep::_S_unref(__old);
151036ac495dSmrg #endif
151136ac495dSmrg _M_root->_M_tree_ptr = __result;
151236ac495dSmrg return *this;
151336ac495dSmrg }
151436ac495dSmrg
151536ac495dSmrg template <class _CharT, class _Alloc>
151636ac495dSmrg inline _Rope_char_ref_proxy<_CharT, _Alloc>::
151736ac495dSmrg operator _CharT() const
151836ac495dSmrg {
151936ac495dSmrg if (_M_current_valid)
152036ac495dSmrg return _M_current;
152136ac495dSmrg else
152236ac495dSmrg return _My_rope::_S_fetch(_M_root->_M_tree_ptr, _M_pos);
152336ac495dSmrg }
152436ac495dSmrg
152536ac495dSmrg template <class _CharT, class _Alloc>
152636ac495dSmrg _Rope_char_ptr_proxy<_CharT, _Alloc>
152736ac495dSmrg _Rope_char_ref_proxy<_CharT, _Alloc>::
152836ac495dSmrg operator&() const
152936ac495dSmrg { return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); }
153036ac495dSmrg
153136ac495dSmrg template <class _CharT, class _Alloc>
153236ac495dSmrg rope<_CharT, _Alloc>::
1533*8feb0f0bSmrg rope(std::size_t __n, _CharT __c, const allocator_type& __a)
153436ac495dSmrg : _Base(__a)
153536ac495dSmrg {
1536*8feb0f0bSmrg using std::__uninitialized_fill_n_a;
1537*8feb0f0bSmrg
153836ac495dSmrg rope<_CharT,_Alloc> __result;
1539*8feb0f0bSmrg const std::size_t __exponentiate_threshold = 32;
1540*8feb0f0bSmrg std::size_t __exponent;
1541*8feb0f0bSmrg std::size_t __rest;
154236ac495dSmrg _CharT* __rest_buffer;
154336ac495dSmrg _RopeRep* __remainder;
154436ac495dSmrg rope<_CharT, _Alloc> __remainder_rope;
154536ac495dSmrg
154636ac495dSmrg if (0 == __n)
154736ac495dSmrg return;
154836ac495dSmrg
154936ac495dSmrg __exponent = __n / __exponentiate_threshold;
155036ac495dSmrg __rest = __n % __exponentiate_threshold;
155136ac495dSmrg if (0 == __rest)
155236ac495dSmrg __remainder = 0;
155336ac495dSmrg else
155436ac495dSmrg {
155536ac495dSmrg __rest_buffer = this->_Data_allocate(_S_rounded_up_size(__rest));
155636ac495dSmrg __uninitialized_fill_n_a(__rest_buffer, __rest, __c,
155736ac495dSmrg _M_get_allocator());
155836ac495dSmrg _S_cond_store_eos(__rest_buffer[__rest]);
155936ac495dSmrg __try
156036ac495dSmrg { __remainder = _S_new_RopeLeaf(__rest_buffer, __rest,
156136ac495dSmrg _M_get_allocator()); }
156236ac495dSmrg __catch(...)
156336ac495dSmrg {
156436ac495dSmrg _RopeRep::__STL_FREE_STRING(__rest_buffer, __rest,
156536ac495dSmrg _M_get_allocator());
156636ac495dSmrg __throw_exception_again;
156736ac495dSmrg }
156836ac495dSmrg }
156936ac495dSmrg __remainder_rope._M_tree_ptr = __remainder;
157036ac495dSmrg if (__exponent != 0)
157136ac495dSmrg {
157236ac495dSmrg _CharT* __base_buffer =
157336ac495dSmrg this->_Data_allocate(_S_rounded_up_size(__exponentiate_threshold));
157436ac495dSmrg _RopeLeaf* __base_leaf;
157536ac495dSmrg rope __base_rope;
157636ac495dSmrg __uninitialized_fill_n_a(__base_buffer, __exponentiate_threshold, __c,
157736ac495dSmrg _M_get_allocator());
157836ac495dSmrg _S_cond_store_eos(__base_buffer[__exponentiate_threshold]);
157936ac495dSmrg __try
158036ac495dSmrg {
158136ac495dSmrg __base_leaf = _S_new_RopeLeaf(__base_buffer,
158236ac495dSmrg __exponentiate_threshold,
158336ac495dSmrg _M_get_allocator());
158436ac495dSmrg }
158536ac495dSmrg __catch(...)
158636ac495dSmrg {
158736ac495dSmrg _RopeRep::__STL_FREE_STRING(__base_buffer,
158836ac495dSmrg __exponentiate_threshold,
158936ac495dSmrg _M_get_allocator());
159036ac495dSmrg __throw_exception_again;
159136ac495dSmrg }
159236ac495dSmrg __base_rope._M_tree_ptr = __base_leaf;
159336ac495dSmrg if (1 == __exponent)
159436ac495dSmrg __result = __base_rope;
159536ac495dSmrg else
159636ac495dSmrg __result = power(__base_rope, __exponent,
159736ac495dSmrg _Rope_Concat_fn<_CharT, _Alloc>());
159836ac495dSmrg
159936ac495dSmrg if (0 != __remainder)
160036ac495dSmrg __result += __remainder_rope;
160136ac495dSmrg }
160236ac495dSmrg else
160336ac495dSmrg __result = __remainder_rope;
160436ac495dSmrg
160536ac495dSmrg this->_M_tree_ptr = __result._M_tree_ptr;
160636ac495dSmrg this->_M_tree_ptr->_M_ref_nonnil();
160736ac495dSmrg }
160836ac495dSmrg
160936ac495dSmrg template<class _CharT, class _Alloc>
161036ac495dSmrg _CharT
161136ac495dSmrg rope<_CharT, _Alloc>::_S_empty_c_str[1];
161236ac495dSmrg
161336ac495dSmrg template<class _CharT, class _Alloc>
161436ac495dSmrg const _CharT*
161536ac495dSmrg rope<_CharT, _Alloc>::
161636ac495dSmrg c_str() const
161736ac495dSmrg {
161836ac495dSmrg if (0 == this->_M_tree_ptr)
161936ac495dSmrg {
162036ac495dSmrg _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant,
162136ac495dSmrg // but probably fast.
162236ac495dSmrg return _S_empty_c_str;
162336ac495dSmrg }
162436ac495dSmrg __gthread_mutex_lock (&this->_M_tree_ptr->_M_c_string_lock);
162536ac495dSmrg __GC_CONST _CharT* __result = this->_M_tree_ptr->_M_c_string;
162636ac495dSmrg if (0 == __result)
162736ac495dSmrg {
1628*8feb0f0bSmrg std::size_t __s = size();
162936ac495dSmrg __result = this->_Data_allocate(__s + 1);
163036ac495dSmrg _S_flatten(this->_M_tree_ptr, __result);
163136ac495dSmrg __result[__s] = _S_eos((_CharT*)0);
163236ac495dSmrg this->_M_tree_ptr->_M_c_string = __result;
163336ac495dSmrg }
163436ac495dSmrg __gthread_mutex_unlock (&this->_M_tree_ptr->_M_c_string_lock);
163536ac495dSmrg return(__result);
163636ac495dSmrg }
163736ac495dSmrg
163836ac495dSmrg template<class _CharT, class _Alloc>
163936ac495dSmrg const _CharT* rope<_CharT, _Alloc>::
164036ac495dSmrg replace_with_c_str()
164136ac495dSmrg {
164236ac495dSmrg if (0 == this->_M_tree_ptr)
164336ac495dSmrg {
164436ac495dSmrg _S_empty_c_str[0] = _S_eos((_CharT*)0);
164536ac495dSmrg return _S_empty_c_str;
164636ac495dSmrg }
164736ac495dSmrg __GC_CONST _CharT* __old_c_string = this->_M_tree_ptr->_M_c_string;
164836ac495dSmrg if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag
164936ac495dSmrg && 0 != __old_c_string)
165036ac495dSmrg return(__old_c_string);
1651*8feb0f0bSmrg std::size_t __s = size();
165236ac495dSmrg _CharT* __result = this->_Data_allocate(_S_rounded_up_size(__s));
165336ac495dSmrg _S_flatten(this->_M_tree_ptr, __result);
165436ac495dSmrg __result[__s] = _S_eos((_CharT*)0);
165536ac495dSmrg this->_M_tree_ptr->_M_unref_nonnil();
165636ac495dSmrg this->_M_tree_ptr = _S_new_RopeLeaf(__result, __s,
165736ac495dSmrg this->_M_get_allocator());
165836ac495dSmrg return(__result);
165936ac495dSmrg }
166036ac495dSmrg
166136ac495dSmrg // Algorithm specializations. More should be added.
166236ac495dSmrg
166336ac495dSmrg template<class _Rope_iterator> // was templated on CharT and Alloc
166436ac495dSmrg void // VC++ workaround
166536ac495dSmrg _Rope_rotate(_Rope_iterator __first,
166636ac495dSmrg _Rope_iterator __middle,
166736ac495dSmrg _Rope_iterator __last)
166836ac495dSmrg {
166936ac495dSmrg typedef typename _Rope_iterator::value_type _CharT;
167036ac495dSmrg typedef typename _Rope_iterator::_allocator_type _Alloc;
167136ac495dSmrg
167236ac495dSmrg rope<_CharT, _Alloc>& __r(__first.container());
167336ac495dSmrg rope<_CharT, _Alloc> __prefix = __r.substr(0, __first.index());
167436ac495dSmrg rope<_CharT, _Alloc> __suffix =
167536ac495dSmrg __r.substr(__last.index(), __r.size() - __last.index());
167636ac495dSmrg rope<_CharT, _Alloc> __part1 =
167736ac495dSmrg __r.substr(__middle.index(), __last.index() - __middle.index());
167836ac495dSmrg rope<_CharT, _Alloc> __part2 =
167936ac495dSmrg __r.substr(__first.index(), __middle.index() - __first.index());
168036ac495dSmrg __r = __prefix;
168136ac495dSmrg __r += __part1;
168236ac495dSmrg __r += __part2;
168336ac495dSmrg __r += __suffix;
168436ac495dSmrg }
168536ac495dSmrg
168636ac495dSmrg #if !defined(__GNUC__)
168736ac495dSmrg // Appears to confuse g++
168836ac495dSmrg inline void
168936ac495dSmrg rotate(_Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __first,
169036ac495dSmrg _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __middle,
169136ac495dSmrg _Rope_iterator<char, __STL_DEFAULT_ALLOCATOR(char)> __last)
169236ac495dSmrg { _Rope_rotate(__first, __middle, __last); }
169336ac495dSmrg #endif
169436ac495dSmrg
169536ac495dSmrg # if 0
169636ac495dSmrg // Probably not useful for several reasons:
169736ac495dSmrg // - for SGIs 7.1 compiler and probably some others,
169836ac495dSmrg // this forces lots of rope<wchar_t, ...> instantiations, creating a
169936ac495dSmrg // code bloat and compile time problem. (Fixed in 7.2.)
170036ac495dSmrg // - wchar_t is 4 bytes wide on most UNIX platforms, making it
170136ac495dSmrg // unattractive for unicode strings. Unsigned short may be a better
170236ac495dSmrg // character type.
170336ac495dSmrg inline void
170436ac495dSmrg rotate(_Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __first,
170536ac495dSmrg _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __middle,
170636ac495dSmrg _Rope_iterator<wchar_t, __STL_DEFAULT_ALLOCATOR(char)> __last)
170736ac495dSmrg { _Rope_rotate(__first, __middle, __last); }
170836ac495dSmrg # endif
170936ac495dSmrg
171036ac495dSmrg _GLIBCXX_END_NAMESPACE_VERSION
171136ac495dSmrg } // namespace
1712