xref: /netbsd-src/external/gpl3/gcc.old/dist/libstdc++-v3/include/ext/ropeimpl.h (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
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