xref: /dflybsd-src/contrib/gcc-4.7/libstdc++-v3/include/ext/rope (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino// SGI's rope class -*- C++ -*-
2*e4b17023SJohn Marino
3*e4b17023SJohn Marino// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
4*e4b17023SJohn Marino// 2012 Free Software Foundation, Inc.
5*e4b17023SJohn Marino//
6*e4b17023SJohn Marino// This file is part of the GNU ISO C++ Library.  This library is free
7*e4b17023SJohn Marino// software; you can redistribute it and/or modify it under the
8*e4b17023SJohn Marino// terms of the GNU General Public License as published by the
9*e4b17023SJohn Marino// Free Software Foundation; either version 3, or (at your option)
10*e4b17023SJohn Marino// any later version.
11*e4b17023SJohn Marino
12*e4b17023SJohn Marino// This library is distributed in the hope that it will be useful,
13*e4b17023SJohn Marino// but WITHOUT ANY WARRANTY; without even the implied warranty of
14*e4b17023SJohn Marino// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*e4b17023SJohn Marino// GNU General Public License for more details.
16*e4b17023SJohn Marino
17*e4b17023SJohn Marino// Under Section 7 of GPL version 3, you are granted additional
18*e4b17023SJohn Marino// permissions described in the GCC Runtime Library Exception, version
19*e4b17023SJohn Marino// 3.1, as published by the Free Software Foundation.
20*e4b17023SJohn Marino
21*e4b17023SJohn Marino// You should have received a copy of the GNU General Public License and
22*e4b17023SJohn Marino// a copy of the GCC Runtime Library Exception along with this program;
23*e4b17023SJohn Marino// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*e4b17023SJohn Marino// <http://www.gnu.org/licenses/>.
25*e4b17023SJohn Marino
26*e4b17023SJohn Marino/*
27*e4b17023SJohn Marino * Copyright (c) 1997
28*e4b17023SJohn Marino * Silicon Graphics Computer Systems, Inc.
29*e4b17023SJohn Marino *
30*e4b17023SJohn Marino * Permission to use, copy, modify, distribute and sell this software
31*e4b17023SJohn Marino * and its documentation for any purpose is hereby granted without fee,
32*e4b17023SJohn Marino * provided that the above copyright notice appear in all copies and
33*e4b17023SJohn Marino * that both that copyright notice and this permission notice appear
34*e4b17023SJohn Marino * in supporting documentation.  Silicon Graphics makes no
35*e4b17023SJohn Marino * representations about the suitability of this software for any
36*e4b17023SJohn Marino * purpose.  It is provided "as is" without express or implied warranty.
37*e4b17023SJohn Marino */
38*e4b17023SJohn Marino
39*e4b17023SJohn Marino/** @file ext/rope
40*e4b17023SJohn Marino *  This file is a GNU extension to the Standard C++ Library (possibly
41*e4b17023SJohn Marino *  containing extensions from the HP/SGI STL subset).
42*e4b17023SJohn Marino */
43*e4b17023SJohn Marino
44*e4b17023SJohn Marino#ifndef _ROPE
45*e4b17023SJohn Marino#define _ROPE 1
46*e4b17023SJohn Marino
47*e4b17023SJohn Marino#pragma GCC system_header
48*e4b17023SJohn Marino
49*e4b17023SJohn Marino#include <algorithm>
50*e4b17023SJohn Marino#include <iosfwd>
51*e4b17023SJohn Marino#include <bits/stl_construct.h>
52*e4b17023SJohn Marino#include <bits/stl_uninitialized.h>
53*e4b17023SJohn Marino#include <bits/stl_function.h>
54*e4b17023SJohn Marino#include <bits/stl_numeric.h>
55*e4b17023SJohn Marino#include <bits/allocator.h>
56*e4b17023SJohn Marino#include <bits/gthr.h>
57*e4b17023SJohn Marino#include <tr1/functional>
58*e4b17023SJohn Marino
59*e4b17023SJohn Marino# ifdef __GC
60*e4b17023SJohn Marino#   define __GC_CONST const
61*e4b17023SJohn Marino# else
62*e4b17023SJohn Marino#   define __GC_CONST   // constant except for deallocation
63*e4b17023SJohn Marino# endif
64*e4b17023SJohn Marino
65*e4b17023SJohn Marino#include <ext/memory> // For uninitialized_copy_n
66*e4b17023SJohn Marino
67*e4b17023SJohn Marinonamespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
68*e4b17023SJohn Marino{
69*e4b17023SJohn Marino  namespace __detail
70*e4b17023SJohn Marino  {
71*e4b17023SJohn Marino    enum { _S_max_rope_depth = 45 };
72*e4b17023SJohn Marino    enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
73*e4b17023SJohn Marino  } // namespace __detail
74*e4b17023SJohn Marino
75*e4b17023SJohn Marino  using std::size_t;
76*e4b17023SJohn Marino  using std::ptrdiff_t;
77*e4b17023SJohn Marino  using std::allocator;
78*e4b17023SJohn Marino  using std::_Destroy;
79*e4b17023SJohn Marino
80*e4b17023SJohn Marino_GLIBCXX_BEGIN_NAMESPACE_VERSION
81*e4b17023SJohn Marino
82*e4b17023SJohn Marino  // See libstdc++/36832.
83*e4b17023SJohn Marino  template<typename _ForwardIterator, typename _Allocator>
84*e4b17023SJohn Marino    void
85*e4b17023SJohn Marino    _Destroy_const(_ForwardIterator __first,
86*e4b17023SJohn Marino		   _ForwardIterator __last, _Allocator __alloc)
87*e4b17023SJohn Marino    {
88*e4b17023SJohn Marino      for (; __first != __last; ++__first)
89*e4b17023SJohn Marino	__alloc.destroy(&*__first);
90*e4b17023SJohn Marino    }
91*e4b17023SJohn Marino
92*e4b17023SJohn Marino  template<typename _ForwardIterator, typename _Tp>
93*e4b17023SJohn Marino    inline void
94*e4b17023SJohn Marino    _Destroy_const(_ForwardIterator __first,
95*e4b17023SJohn Marino		   _ForwardIterator __last, allocator<_Tp>)
96*e4b17023SJohn Marino    { _Destroy(__first, __last); }
97*e4b17023SJohn Marino
98*e4b17023SJohn Marino  // The _S_eos function is used for those functions that
99*e4b17023SJohn Marino  // convert to/from C-like strings to detect the end of the string.
100*e4b17023SJohn Marino
101*e4b17023SJohn Marino  // The end-of-C-string character.
102*e4b17023SJohn Marino  // This is what the draft standard says it should be.
103*e4b17023SJohn Marino  template <class _CharT>
104*e4b17023SJohn Marino    inline _CharT
105*e4b17023SJohn Marino    _S_eos(_CharT*)
106*e4b17023SJohn Marino    { return _CharT(); }
107*e4b17023SJohn Marino
108*e4b17023SJohn Marino  // Test for basic character types.
109*e4b17023SJohn Marino  // For basic character types leaves having a trailing eos.
110*e4b17023SJohn Marino  template <class _CharT>
111*e4b17023SJohn Marino    inline bool
112*e4b17023SJohn Marino    _S_is_basic_char_type(_CharT*)
113*e4b17023SJohn Marino    { return false; }
114*e4b17023SJohn Marino
115*e4b17023SJohn Marino  template <class _CharT>
116*e4b17023SJohn Marino    inline bool
117*e4b17023SJohn Marino    _S_is_one_byte_char_type(_CharT*)
118*e4b17023SJohn Marino    { return false; }
119*e4b17023SJohn Marino
120*e4b17023SJohn Marino  inline bool
121*e4b17023SJohn Marino  _S_is_basic_char_type(char*)
122*e4b17023SJohn Marino  { return true; }
123*e4b17023SJohn Marino
124*e4b17023SJohn Marino  inline bool
125*e4b17023SJohn Marino  _S_is_one_byte_char_type(char*)
126*e4b17023SJohn Marino  { return true; }
127*e4b17023SJohn Marino
128*e4b17023SJohn Marino  inline bool
129*e4b17023SJohn Marino  _S_is_basic_char_type(wchar_t*)
130*e4b17023SJohn Marino  { return true; }
131*e4b17023SJohn Marino
132*e4b17023SJohn Marino  // Store an eos iff _CharT is a basic character type.
133*e4b17023SJohn Marino  // Do not reference _S_eos if it isn't.
134*e4b17023SJohn Marino  template <class _CharT>
135*e4b17023SJohn Marino    inline void
136*e4b17023SJohn Marino    _S_cond_store_eos(_CharT&) { }
137*e4b17023SJohn Marino
138*e4b17023SJohn Marino  inline void
139*e4b17023SJohn Marino  _S_cond_store_eos(char& __c)
140*e4b17023SJohn Marino  { __c = 0; }
141*e4b17023SJohn Marino
142*e4b17023SJohn Marino  inline void
143*e4b17023SJohn Marino  _S_cond_store_eos(wchar_t& __c)
144*e4b17023SJohn Marino  { __c = 0; }
145*e4b17023SJohn Marino
146*e4b17023SJohn Marino  // char_producers are logically functions that generate a section of
147*e4b17023SJohn Marino  // a string.  These can be converted to ropes.  The resulting rope
148*e4b17023SJohn Marino  // invokes the char_producer on demand.  This allows, for example,
149*e4b17023SJohn Marino  // files to be viewed as ropes without reading the entire file.
150*e4b17023SJohn Marino  template <class _CharT>
151*e4b17023SJohn Marino    class char_producer
152*e4b17023SJohn Marino    {
153*e4b17023SJohn Marino    public:
154*e4b17023SJohn Marino      virtual ~char_producer() { };
155*e4b17023SJohn Marino
156*e4b17023SJohn Marino      virtual void
157*e4b17023SJohn Marino      operator()(size_t __start_pos, size_t __len,
158*e4b17023SJohn Marino		 _CharT* __buffer) = 0;
159*e4b17023SJohn Marino      // Buffer should really be an arbitrary output iterator.
160*e4b17023SJohn Marino      // That way we could flatten directly into an ostream, etc.
161*e4b17023SJohn Marino      // This is thoroughly impossible, since iterator types don't
162*e4b17023SJohn Marino      // have runtime descriptions.
163*e4b17023SJohn Marino    };
164*e4b17023SJohn Marino
165*e4b17023SJohn Marino  // Sequence buffers:
166*e4b17023SJohn Marino  //
167*e4b17023SJohn Marino  // Sequence must provide an append operation that appends an
168*e4b17023SJohn Marino  // array to the sequence.  Sequence buffers are useful only if
169*e4b17023SJohn Marino  // appending an entire array is cheaper than appending element by element.
170*e4b17023SJohn Marino  // This is true for many string representations.
171*e4b17023SJohn Marino  // This should  perhaps inherit from ostream<sequence::value_type>
172*e4b17023SJohn Marino  // and be implemented correspondingly, so that they can be used
173*e4b17023SJohn Marino  // for formatted.  For the sake of portability, we don't do this yet.
174*e4b17023SJohn Marino  //
175*e4b17023SJohn Marino  // For now, sequence buffers behave as output iterators.  But they also
176*e4b17023SJohn Marino  // behave a little like basic_ostringstream<sequence::value_type> and a
177*e4b17023SJohn Marino  // little like containers.
178*e4b17023SJohn Marino
179*e4b17023SJohn Marino  template<class _Sequence, size_t _Buf_sz = 100>
180*e4b17023SJohn Marino    class sequence_buffer
181*e4b17023SJohn Marino    : public std::iterator<std::output_iterator_tag, void, void, void, void>
182*e4b17023SJohn Marino    {
183*e4b17023SJohn Marino    public:
184*e4b17023SJohn Marino      typedef typename _Sequence::value_type value_type;
185*e4b17023SJohn Marino    protected:
186*e4b17023SJohn Marino      _Sequence* _M_prefix;
187*e4b17023SJohn Marino      value_type _M_buffer[_Buf_sz];
188*e4b17023SJohn Marino      size_t     _M_buf_count;
189*e4b17023SJohn Marino    public:
190*e4b17023SJohn Marino
191*e4b17023SJohn Marino      void
192*e4b17023SJohn Marino      flush()
193*e4b17023SJohn Marino      {
194*e4b17023SJohn Marino	_M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);
195*e4b17023SJohn Marino	_M_buf_count = 0;
196*e4b17023SJohn Marino      }
197*e4b17023SJohn Marino
198*e4b17023SJohn Marino      ~sequence_buffer()
199*e4b17023SJohn Marino      { flush(); }
200*e4b17023SJohn Marino
201*e4b17023SJohn Marino      sequence_buffer()
202*e4b17023SJohn Marino      : _M_prefix(0), _M_buf_count(0) { }
203*e4b17023SJohn Marino
204*e4b17023SJohn Marino      sequence_buffer(const sequence_buffer& __x)
205*e4b17023SJohn Marino      {
206*e4b17023SJohn Marino	_M_prefix = __x._M_prefix;
207*e4b17023SJohn Marino	_M_buf_count = __x._M_buf_count;
208*e4b17023SJohn Marino	std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
209*e4b17023SJohn Marino      }
210*e4b17023SJohn Marino
211*e4b17023SJohn Marino      sequence_buffer(sequence_buffer& __x)
212*e4b17023SJohn Marino      {
213*e4b17023SJohn Marino	__x.flush();
214*e4b17023SJohn Marino	_M_prefix = __x._M_prefix;
215*e4b17023SJohn Marino	_M_buf_count = 0;
216*e4b17023SJohn Marino      }
217*e4b17023SJohn Marino
218*e4b17023SJohn Marino      sequence_buffer(_Sequence& __s)
219*e4b17023SJohn Marino      : _M_prefix(&__s), _M_buf_count(0) { }
220*e4b17023SJohn Marino
221*e4b17023SJohn Marino      sequence_buffer&
222*e4b17023SJohn Marino      operator=(sequence_buffer& __x)
223*e4b17023SJohn Marino      {
224*e4b17023SJohn Marino	__x.flush();
225*e4b17023SJohn Marino	_M_prefix = __x._M_prefix;
226*e4b17023SJohn Marino	_M_buf_count = 0;
227*e4b17023SJohn Marino	return *this;
228*e4b17023SJohn Marino      }
229*e4b17023SJohn Marino
230*e4b17023SJohn Marino      sequence_buffer&
231*e4b17023SJohn Marino      operator=(const sequence_buffer& __x)
232*e4b17023SJohn Marino      {
233*e4b17023SJohn Marino	_M_prefix = __x._M_prefix;
234*e4b17023SJohn Marino	_M_buf_count = __x._M_buf_count;
235*e4b17023SJohn Marino	std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
236*e4b17023SJohn Marino	return *this;
237*e4b17023SJohn Marino      }
238*e4b17023SJohn Marino
239*e4b17023SJohn Marino      void
240*e4b17023SJohn Marino      push_back(value_type __x)
241*e4b17023SJohn Marino      {
242*e4b17023SJohn Marino	if (_M_buf_count < _Buf_sz)
243*e4b17023SJohn Marino	  {
244*e4b17023SJohn Marino	    _M_buffer[_M_buf_count] = __x;
245*e4b17023SJohn Marino	    ++_M_buf_count;
246*e4b17023SJohn Marino	  }
247*e4b17023SJohn Marino	else
248*e4b17023SJohn Marino	  {
249*e4b17023SJohn Marino	    flush();
250*e4b17023SJohn Marino	    _M_buffer[0] = __x;
251*e4b17023SJohn Marino	    _M_buf_count = 1;
252*e4b17023SJohn Marino	  }
253*e4b17023SJohn Marino      }
254*e4b17023SJohn Marino
255*e4b17023SJohn Marino      void
256*e4b17023SJohn Marino      append(value_type* __s, size_t __len)
257*e4b17023SJohn Marino      {
258*e4b17023SJohn Marino	if (__len + _M_buf_count <= _Buf_sz)
259*e4b17023SJohn Marino	  {
260*e4b17023SJohn Marino	    size_t __i = _M_buf_count;
261*e4b17023SJohn Marino	    for (size_t __j = 0; __j < __len; __i++, __j++)
262*e4b17023SJohn Marino	      _M_buffer[__i] = __s[__j];
263*e4b17023SJohn Marino	    _M_buf_count += __len;
264*e4b17023SJohn Marino	  }
265*e4b17023SJohn Marino	else if (0 == _M_buf_count)
266*e4b17023SJohn Marino	  _M_prefix->append(__s, __s + __len);
267*e4b17023SJohn Marino	else
268*e4b17023SJohn Marino	  {
269*e4b17023SJohn Marino	    flush();
270*e4b17023SJohn Marino	    append(__s, __len);
271*e4b17023SJohn Marino	  }
272*e4b17023SJohn Marino      }
273*e4b17023SJohn Marino
274*e4b17023SJohn Marino      sequence_buffer&
275*e4b17023SJohn Marino      write(value_type* __s, size_t __len)
276*e4b17023SJohn Marino      {
277*e4b17023SJohn Marino	append(__s, __len);
278*e4b17023SJohn Marino	return *this;
279*e4b17023SJohn Marino      }
280*e4b17023SJohn Marino
281*e4b17023SJohn Marino      sequence_buffer&
282*e4b17023SJohn Marino      put(value_type __x)
283*e4b17023SJohn Marino      {
284*e4b17023SJohn Marino	push_back(__x);
285*e4b17023SJohn Marino	return *this;
286*e4b17023SJohn Marino      }
287*e4b17023SJohn Marino
288*e4b17023SJohn Marino      sequence_buffer&
289*e4b17023SJohn Marino      operator=(const value_type& __rhs)
290*e4b17023SJohn Marino      {
291*e4b17023SJohn Marino	push_back(__rhs);
292*e4b17023SJohn Marino	return *this;
293*e4b17023SJohn Marino      }
294*e4b17023SJohn Marino
295*e4b17023SJohn Marino      sequence_buffer&
296*e4b17023SJohn Marino      operator*()
297*e4b17023SJohn Marino      { return *this; }
298*e4b17023SJohn Marino
299*e4b17023SJohn Marino      sequence_buffer&
300*e4b17023SJohn Marino      operator++()
301*e4b17023SJohn Marino      { return *this; }
302*e4b17023SJohn Marino
303*e4b17023SJohn Marino      sequence_buffer
304*e4b17023SJohn Marino      operator++(int)
305*e4b17023SJohn Marino      { return *this; }
306*e4b17023SJohn Marino    };
307*e4b17023SJohn Marino
308*e4b17023SJohn Marino  // The following should be treated as private, at least for now.
309*e4b17023SJohn Marino  template<class _CharT>
310*e4b17023SJohn Marino    class _Rope_char_consumer
311*e4b17023SJohn Marino    {
312*e4b17023SJohn Marino    public:
313*e4b17023SJohn Marino      // If we had member templates, these should not be virtual.
314*e4b17023SJohn Marino      // For now we need to use run-time parametrization where
315*e4b17023SJohn Marino      // compile-time would do.  Hence this should all be private
316*e4b17023SJohn Marino      // for now.
317*e4b17023SJohn Marino      // The symmetry with char_producer is accidental and temporary.
318*e4b17023SJohn Marino      virtual ~_Rope_char_consumer() { };
319*e4b17023SJohn Marino
320*e4b17023SJohn Marino      virtual bool
321*e4b17023SJohn Marino      operator()(const _CharT* __buffer, size_t __len) = 0;
322*e4b17023SJohn Marino    };
323*e4b17023SJohn Marino
324*e4b17023SJohn Marino  // First a lot of forward declarations.  The standard seems to require
325*e4b17023SJohn Marino  // much stricter "declaration before use" than many of the implementations
326*e4b17023SJohn Marino  // that preceded it.
327*e4b17023SJohn Marino  template<class _CharT, class _Alloc = allocator<_CharT> >
328*e4b17023SJohn Marino    class rope;
329*e4b17023SJohn Marino
330*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
331*e4b17023SJohn Marino    struct _Rope_RopeConcatenation;
332*e4b17023SJohn Marino
333*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
334*e4b17023SJohn Marino    struct _Rope_RopeLeaf;
335*e4b17023SJohn Marino
336*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
337*e4b17023SJohn Marino    struct _Rope_RopeFunction;
338*e4b17023SJohn Marino
339*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
340*e4b17023SJohn Marino    struct _Rope_RopeSubstring;
341*e4b17023SJohn Marino
342*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
343*e4b17023SJohn Marino    class _Rope_iterator;
344*e4b17023SJohn Marino
345*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
346*e4b17023SJohn Marino    class _Rope_const_iterator;
347*e4b17023SJohn Marino
348*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
349*e4b17023SJohn Marino    class _Rope_char_ref_proxy;
350*e4b17023SJohn Marino
351*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
352*e4b17023SJohn Marino    class _Rope_char_ptr_proxy;
353*e4b17023SJohn Marino
354*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
355*e4b17023SJohn Marino    bool
356*e4b17023SJohn Marino    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
357*e4b17023SJohn Marino	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);
358*e4b17023SJohn Marino
359*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
360*e4b17023SJohn Marino    _Rope_const_iterator<_CharT, _Alloc>
361*e4b17023SJohn Marino    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
362*e4b17023SJohn Marino	      ptrdiff_t __n);
363*e4b17023SJohn Marino
364*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
365*e4b17023SJohn Marino    _Rope_const_iterator<_CharT, _Alloc>
366*e4b17023SJohn Marino    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
367*e4b17023SJohn Marino	      ptrdiff_t __n);
368*e4b17023SJohn Marino
369*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
370*e4b17023SJohn Marino    _Rope_const_iterator<_CharT, _Alloc>
371*e4b17023SJohn Marino    operator+(ptrdiff_t __n,
372*e4b17023SJohn Marino	      const _Rope_const_iterator<_CharT, _Alloc>& __x);
373*e4b17023SJohn Marino
374*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
375*e4b17023SJohn Marino    bool
376*e4b17023SJohn Marino    operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
377*e4b17023SJohn Marino	       const _Rope_const_iterator<_CharT, _Alloc>& __y);
378*e4b17023SJohn Marino
379*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
380*e4b17023SJohn Marino    bool
381*e4b17023SJohn Marino    operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
382*e4b17023SJohn Marino	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
383*e4b17023SJohn Marino
384*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
385*e4b17023SJohn Marino    ptrdiff_t
386*e4b17023SJohn Marino    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
387*e4b17023SJohn Marino	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
388*e4b17023SJohn Marino
389*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
390*e4b17023SJohn Marino    _Rope_iterator<_CharT, _Alloc>
391*e4b17023SJohn Marino    operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
392*e4b17023SJohn Marino
393*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
394*e4b17023SJohn Marino    _Rope_iterator<_CharT, _Alloc>
395*e4b17023SJohn Marino    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
396*e4b17023SJohn Marino
397*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
398*e4b17023SJohn Marino    _Rope_iterator<_CharT, _Alloc>
399*e4b17023SJohn Marino    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);
400*e4b17023SJohn Marino
401*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
402*e4b17023SJohn Marino    bool
403*e4b17023SJohn Marino    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
404*e4b17023SJohn Marino	       const _Rope_iterator<_CharT, _Alloc>& __y);
405*e4b17023SJohn Marino
406*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
407*e4b17023SJohn Marino    bool
408*e4b17023SJohn Marino    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
409*e4b17023SJohn Marino	      const _Rope_iterator<_CharT, _Alloc>& __y);
410*e4b17023SJohn Marino
411*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
412*e4b17023SJohn Marino    ptrdiff_t
413*e4b17023SJohn Marino    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
414*e4b17023SJohn Marino	      const _Rope_iterator<_CharT, _Alloc>& __y);
415*e4b17023SJohn Marino
416*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
417*e4b17023SJohn Marino    rope<_CharT, _Alloc>
418*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left,
419*e4b17023SJohn Marino	      const rope<_CharT, _Alloc>& __right);
420*e4b17023SJohn Marino
421*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
422*e4b17023SJohn Marino    rope<_CharT, _Alloc>
423*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);
424*e4b17023SJohn Marino
425*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
426*e4b17023SJohn Marino    rope<_CharT, _Alloc>
427*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);
428*e4b17023SJohn Marino
429*e4b17023SJohn Marino  // Some helpers, so we can use power on ropes.
430*e4b17023SJohn Marino  // See below for why this isn't local to the implementation.
431*e4b17023SJohn Marino
432*e4b17023SJohn Marino  // This uses a nonstandard refcount convention.
433*e4b17023SJohn Marino  // The result has refcount 0.
434*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
435*e4b17023SJohn Marino    struct _Rope_Concat_fn
436*e4b17023SJohn Marino    : public std::binary_function<rope<_CharT, _Alloc>, rope<_CharT, _Alloc>,
437*e4b17023SJohn Marino				  rope<_CharT, _Alloc> >
438*e4b17023SJohn Marino    {
439*e4b17023SJohn Marino      rope<_CharT, _Alloc>
440*e4b17023SJohn Marino      operator()(const rope<_CharT, _Alloc>& __x,
441*e4b17023SJohn Marino		 const rope<_CharT, _Alloc>& __y)
442*e4b17023SJohn Marino      { return __x + __y; }
443*e4b17023SJohn Marino    };
444*e4b17023SJohn Marino
445*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
446*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>
447*e4b17023SJohn Marino    identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
448*e4b17023SJohn Marino    { return rope<_CharT, _Alloc>(); }
449*e4b17023SJohn Marino
450*e4b17023SJohn Marino  // Class _Refcount_Base provides a type, _RC_t, a data member,
451*e4b17023SJohn Marino  // _M_ref_count, and member functions _M_incr and _M_decr, which perform
452*e4b17023SJohn Marino  // atomic preincrement/predecrement.  The constructor initializes
453*e4b17023SJohn Marino  // _M_ref_count.
454*e4b17023SJohn Marino  struct _Refcount_Base
455*e4b17023SJohn Marino  {
456*e4b17023SJohn Marino    // The type _RC_t
457*e4b17023SJohn Marino    typedef size_t _RC_t;
458*e4b17023SJohn Marino
459*e4b17023SJohn Marino    // The data member _M_ref_count
460*e4b17023SJohn Marino    volatile _RC_t _M_ref_count;
461*e4b17023SJohn Marino
462*e4b17023SJohn Marino    // Constructor
463*e4b17023SJohn Marino#ifdef __GTHREAD_MUTEX_INIT
464*e4b17023SJohn Marino    __gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT;
465*e4b17023SJohn Marino#else
466*e4b17023SJohn Marino    __gthread_mutex_t _M_ref_count_lock;
467*e4b17023SJohn Marino#endif
468*e4b17023SJohn Marino
469*e4b17023SJohn Marino    _Refcount_Base(_RC_t __n) : _M_ref_count(__n)
470*e4b17023SJohn Marino    {
471*e4b17023SJohn Marino#ifndef __GTHREAD_MUTEX_INIT
472*e4b17023SJohn Marino#ifdef __GTHREAD_MUTEX_INIT_FUNCTION
473*e4b17023SJohn Marino      __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
474*e4b17023SJohn Marino#else
475*e4b17023SJohn Marino#error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
476*e4b17023SJohn Marino#endif
477*e4b17023SJohn Marino#endif
478*e4b17023SJohn Marino    }
479*e4b17023SJohn Marino
480*e4b17023SJohn Marino#ifndef __GTHREAD_MUTEX_INIT
481*e4b17023SJohn Marino    ~_Refcount_Base()
482*e4b17023SJohn Marino    { __gthread_mutex_destroy(&_M_ref_count_lock); }
483*e4b17023SJohn Marino#endif
484*e4b17023SJohn Marino
485*e4b17023SJohn Marino    void
486*e4b17023SJohn Marino    _M_incr()
487*e4b17023SJohn Marino    {
488*e4b17023SJohn Marino      __gthread_mutex_lock(&_M_ref_count_lock);
489*e4b17023SJohn Marino      ++_M_ref_count;
490*e4b17023SJohn Marino      __gthread_mutex_unlock(&_M_ref_count_lock);
491*e4b17023SJohn Marino    }
492*e4b17023SJohn Marino
493*e4b17023SJohn Marino    _RC_t
494*e4b17023SJohn Marino    _M_decr()
495*e4b17023SJohn Marino    {
496*e4b17023SJohn Marino      __gthread_mutex_lock(&_M_ref_count_lock);
497*e4b17023SJohn Marino      volatile _RC_t __tmp = --_M_ref_count;
498*e4b17023SJohn Marino      __gthread_mutex_unlock(&_M_ref_count_lock);
499*e4b17023SJohn Marino      return __tmp;
500*e4b17023SJohn Marino    }
501*e4b17023SJohn Marino  };
502*e4b17023SJohn Marino
503*e4b17023SJohn Marino  //
504*e4b17023SJohn Marino  // What follows should really be local to rope.  Unfortunately,
505*e4b17023SJohn Marino  // that doesn't work, since it makes it impossible to define generic
506*e4b17023SJohn Marino  // equality on rope iterators.  According to the draft standard, the
507*e4b17023SJohn Marino  // template parameters for such an equality operator cannot be inferred
508*e4b17023SJohn Marino  // from the occurrence of a member class as a parameter.
509*e4b17023SJohn Marino  // (SGI compilers in fact allow this, but the __result wouldn't be
510*e4b17023SJohn Marino  // portable.)
511*e4b17023SJohn Marino  // Similarly, some of the static member functions are member functions
512*e4b17023SJohn Marino  // only to avoid polluting the global namespace, and to circumvent
513*e4b17023SJohn Marino  // restrictions on type inference for template functions.
514*e4b17023SJohn Marino  //
515*e4b17023SJohn Marino
516*e4b17023SJohn Marino  //
517*e4b17023SJohn Marino  // The internal data structure for representing a rope.  This is
518*e4b17023SJohn Marino  // private to the implementation.  A rope is really just a pointer
519*e4b17023SJohn Marino  // to one of these.
520*e4b17023SJohn Marino  //
521*e4b17023SJohn Marino  // A few basic functions for manipulating this data structure
522*e4b17023SJohn Marino  // are members of _RopeRep.  Most of the more complex algorithms
523*e4b17023SJohn Marino  // are implemented as rope members.
524*e4b17023SJohn Marino  //
525*e4b17023SJohn Marino  // Some of the static member functions of _RopeRep have identically
526*e4b17023SJohn Marino  // named functions in rope that simply invoke the _RopeRep versions.
527*e4b17023SJohn Marino
528*e4b17023SJohn Marino#define __ROPE_DEFINE_ALLOCS(__a) \
529*e4b17023SJohn Marino        __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \
530*e4b17023SJohn Marino        typedef _Rope_RopeConcatenation<_CharT,__a> __C; \
531*e4b17023SJohn Marino        __ROPE_DEFINE_ALLOC(__C,_C) \
532*e4b17023SJohn Marino        typedef _Rope_RopeLeaf<_CharT,__a> __L; \
533*e4b17023SJohn Marino        __ROPE_DEFINE_ALLOC(__L,_L) \
534*e4b17023SJohn Marino        typedef _Rope_RopeFunction<_CharT,__a> __F; \
535*e4b17023SJohn Marino        __ROPE_DEFINE_ALLOC(__F,_F) \
536*e4b17023SJohn Marino        typedef _Rope_RopeSubstring<_CharT,__a> __S; \
537*e4b17023SJohn Marino        __ROPE_DEFINE_ALLOC(__S,_S)
538*e4b17023SJohn Marino
539*e4b17023SJohn Marino  //  Internal rope nodes potentially store a copy of the allocator
540*e4b17023SJohn Marino  //  instance used to allocate them.  This is mostly redundant.
541*e4b17023SJohn Marino  //  But the alternative would be to pass allocator instances around
542*e4b17023SJohn Marino  //  in some form to nearly all internal functions, since any pointer
543*e4b17023SJohn Marino  //  assignment may result in a zero reference count and thus require
544*e4b17023SJohn Marino  //  deallocation.
545*e4b17023SJohn Marino
546*e4b17023SJohn Marino#define __STATIC_IF_SGI_ALLOC  /* not static */
547*e4b17023SJohn Marino
548*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
549*e4b17023SJohn Marino    struct _Rope_rep_base
550*e4b17023SJohn Marino    : public _Alloc
551*e4b17023SJohn Marino    {
552*e4b17023SJohn Marino      typedef _Alloc allocator_type;
553*e4b17023SJohn Marino
554*e4b17023SJohn Marino      allocator_type
555*e4b17023SJohn Marino      get_allocator() const
556*e4b17023SJohn Marino      { return *static_cast<const _Alloc*>(this); }
557*e4b17023SJohn Marino
558*e4b17023SJohn Marino      allocator_type&
559*e4b17023SJohn Marino      _M_get_allocator()
560*e4b17023SJohn Marino      { return *static_cast<_Alloc*>(this); }
561*e4b17023SJohn Marino
562*e4b17023SJohn Marino      const allocator_type&
563*e4b17023SJohn Marino      _M_get_allocator() const
564*e4b17023SJohn Marino      { return *static_cast<const _Alloc*>(this); }
565*e4b17023SJohn Marino
566*e4b17023SJohn Marino      _Rope_rep_base(size_t __size, const allocator_type&)
567*e4b17023SJohn Marino      : _M_size(__size) { }
568*e4b17023SJohn Marino
569*e4b17023SJohn Marino      size_t _M_size;
570*e4b17023SJohn Marino
571*e4b17023SJohn Marino# define __ROPE_DEFINE_ALLOC(_Tp, __name) \
572*e4b17023SJohn Marino        typedef typename \
573*e4b17023SJohn Marino          _Alloc::template rebind<_Tp>::other __name##Alloc; \
574*e4b17023SJohn Marino        static _Tp* __name##_allocate(size_t __n) \
575*e4b17023SJohn Marino          { return __name##Alloc().allocate(__n); } \
576*e4b17023SJohn Marino        static void __name##_deallocate(_Tp *__p, size_t __n) \
577*e4b17023SJohn Marino          { __name##Alloc().deallocate(__p, __n); }
578*e4b17023SJohn Marino      __ROPE_DEFINE_ALLOCS(_Alloc)
579*e4b17023SJohn Marino# undef __ROPE_DEFINE_ALLOC
580*e4b17023SJohn Marino    };
581*e4b17023SJohn Marino
582*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
583*e4b17023SJohn Marino    struct _Rope_RopeRep
584*e4b17023SJohn Marino    : public _Rope_rep_base<_CharT, _Alloc>
585*e4b17023SJohn Marino# ifndef __GC
586*e4b17023SJohn Marino	     , _Refcount_Base
587*e4b17023SJohn Marino# endif
588*e4b17023SJohn Marino    {
589*e4b17023SJohn Marino    public:
590*e4b17023SJohn Marino      __detail::_Tag _M_tag:8;
591*e4b17023SJohn Marino      bool _M_is_balanced:8;
592*e4b17023SJohn Marino      unsigned char _M_depth;
593*e4b17023SJohn Marino      __GC_CONST _CharT* _M_c_string;
594*e4b17023SJohn Marino#ifdef __GTHREAD_MUTEX_INIT
595*e4b17023SJohn Marino      __gthread_mutex_t _M_c_string_lock = __GTHREAD_MUTEX_INIT;
596*e4b17023SJohn Marino#else
597*e4b17023SJohn Marino      __gthread_mutex_t _M_c_string_lock;
598*e4b17023SJohn Marino#endif
599*e4b17023SJohn Marino                        /* Flattened version of string, if needed.  */
600*e4b17023SJohn Marino                        /* typically 0.                             */
601*e4b17023SJohn Marino                        /* If it's not 0, then the memory is owned  */
602*e4b17023SJohn Marino                        /* by this node.                            */
603*e4b17023SJohn Marino                        /* In the case of a leaf, this may point to */
604*e4b17023SJohn Marino                        /* the same memory as the data field.       */
605*e4b17023SJohn Marino      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
606*e4b17023SJohn Marino        allocator_type;
607*e4b17023SJohn Marino
608*e4b17023SJohn Marino      using _Rope_rep_base<_CharT, _Alloc>::get_allocator;
609*e4b17023SJohn Marino      using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator;
610*e4b17023SJohn Marino
611*e4b17023SJohn Marino      _Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_t __size,
612*e4b17023SJohn Marino		    const allocator_type& __a)
613*e4b17023SJohn Marino      : _Rope_rep_base<_CharT, _Alloc>(__size, __a),
614*e4b17023SJohn Marino#ifndef __GC
615*e4b17023SJohn Marino	_Refcount_Base(1),
616*e4b17023SJohn Marino#endif
617*e4b17023SJohn Marino	_M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
618*e4b17023SJohn Marino#ifdef __GTHREAD_MUTEX_INIT
619*e4b17023SJohn Marino      { }
620*e4b17023SJohn Marino#else
621*e4b17023SJohn Marino      { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }
622*e4b17023SJohn Marino      ~_Rope_RopeRep()
623*e4b17023SJohn Marino      { __gthread_mutex_destroy (&_M_c_string_lock); }
624*e4b17023SJohn Marino#endif
625*e4b17023SJohn Marino#ifdef __GC
626*e4b17023SJohn Marino      void
627*e4b17023SJohn Marino      _M_incr () { }
628*e4b17023SJohn Marino#endif
629*e4b17023SJohn Marino      static void
630*e4b17023SJohn Marino      _S_free_string(__GC_CONST _CharT*, size_t __len,
631*e4b17023SJohn Marino		     allocator_type& __a);
632*e4b17023SJohn Marino#define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);
633*e4b17023SJohn Marino                        // Deallocate data section of a leaf.
634*e4b17023SJohn Marino                        // This shouldn't be a member function.
635*e4b17023SJohn Marino                        // But its hard to do anything else at the
636*e4b17023SJohn Marino                        // moment, because it's templatized w.r.t.
637*e4b17023SJohn Marino                        // an allocator.
638*e4b17023SJohn Marino                        // Does nothing if __GC is defined.
639*e4b17023SJohn Marino#ifndef __GC
640*e4b17023SJohn Marino      void _M_free_c_string();
641*e4b17023SJohn Marino      void _M_free_tree();
642*e4b17023SJohn Marino      // Deallocate t. Assumes t is not 0.
643*e4b17023SJohn Marino      void
644*e4b17023SJohn Marino      _M_unref_nonnil()
645*e4b17023SJohn Marino      {
646*e4b17023SJohn Marino	if (0 == _M_decr())
647*e4b17023SJohn Marino	  _M_free_tree();
648*e4b17023SJohn Marino      }
649*e4b17023SJohn Marino
650*e4b17023SJohn Marino      void
651*e4b17023SJohn Marino      _M_ref_nonnil()
652*e4b17023SJohn Marino      { _M_incr(); }
653*e4b17023SJohn Marino
654*e4b17023SJohn Marino      static void
655*e4b17023SJohn Marino      _S_unref(_Rope_RopeRep* __t)
656*e4b17023SJohn Marino      {
657*e4b17023SJohn Marino	if (0 != __t)
658*e4b17023SJohn Marino	  __t->_M_unref_nonnil();
659*e4b17023SJohn Marino      }
660*e4b17023SJohn Marino
661*e4b17023SJohn Marino      static void
662*e4b17023SJohn Marino      _S_ref(_Rope_RopeRep* __t)
663*e4b17023SJohn Marino      {
664*e4b17023SJohn Marino	if (0 != __t)
665*e4b17023SJohn Marino	  __t->_M_incr();
666*e4b17023SJohn Marino      }
667*e4b17023SJohn Marino
668*e4b17023SJohn Marino      static void
669*e4b17023SJohn Marino      _S_free_if_unref(_Rope_RopeRep* __t)
670*e4b17023SJohn Marino      {
671*e4b17023SJohn Marino	if (0 != __t && 0 == __t->_M_ref_count)
672*e4b17023SJohn Marino	  __t->_M_free_tree();
673*e4b17023SJohn Marino      }
674*e4b17023SJohn Marino#   else /* __GC */
675*e4b17023SJohn Marino      void _M_unref_nonnil() { }
676*e4b17023SJohn Marino      void _M_ref_nonnil() { }
677*e4b17023SJohn Marino      static void _S_unref(_Rope_RopeRep*) { }
678*e4b17023SJohn Marino      static void _S_ref(_Rope_RopeRep*) { }
679*e4b17023SJohn Marino      static void _S_free_if_unref(_Rope_RopeRep*) { }
680*e4b17023SJohn Marino#   endif
681*e4b17023SJohn Marinoprotected:
682*e4b17023SJohn Marino      _Rope_RopeRep&
683*e4b17023SJohn Marino      operator=(const _Rope_RopeRep&);
684*e4b17023SJohn Marino
685*e4b17023SJohn Marino      _Rope_RopeRep(const _Rope_RopeRep&);
686*e4b17023SJohn Marino    };
687*e4b17023SJohn Marino
688*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
689*e4b17023SJohn Marino    struct _Rope_RopeLeaf
690*e4b17023SJohn Marino    : public _Rope_RopeRep<_CharT, _Alloc>
691*e4b17023SJohn Marino    {
692*e4b17023SJohn Marino    public:
693*e4b17023SJohn Marino      // Apparently needed by VC++
694*e4b17023SJohn Marino      // The data fields of leaves are allocated with some
695*e4b17023SJohn Marino      // extra space, to accommodate future growth and for basic
696*e4b17023SJohn Marino      // character types, to hold a trailing eos character.
697*e4b17023SJohn Marino      enum { _S_alloc_granularity = 8 };
698*e4b17023SJohn Marino
699*e4b17023SJohn Marino      static size_t
700*e4b17023SJohn Marino      _S_rounded_up_size(size_t __n)
701*e4b17023SJohn Marino      {
702*e4b17023SJohn Marino        size_t __size_with_eos;
703*e4b17023SJohn Marino
704*e4b17023SJohn Marino        if (_S_is_basic_char_type((_CharT*)0))
705*e4b17023SJohn Marino	  __size_with_eos = __n + 1;
706*e4b17023SJohn Marino	else
707*e4b17023SJohn Marino	  __size_with_eos = __n;
708*e4b17023SJohn Marino#ifdef __GC
709*e4b17023SJohn Marino	return __size_with_eos;
710*e4b17023SJohn Marino#else
711*e4b17023SJohn Marino	// Allow slop for in-place expansion.
712*e4b17023SJohn Marino	return ((__size_with_eos + size_t(_S_alloc_granularity) - 1)
713*e4b17023SJohn Marino		&~ (size_t(_S_alloc_granularity) - 1));
714*e4b17023SJohn Marino#endif
715*e4b17023SJohn Marino      }
716*e4b17023SJohn Marino      __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */
717*e4b17023SJohn Marino                                  /* The allocated size is         */
718*e4b17023SJohn Marino                                  /* _S_rounded_up_size(size), except */
719*e4b17023SJohn Marino                                  /* in the GC case, in which it   */
720*e4b17023SJohn Marino                                  /* doesn't matter.               */
721*e4b17023SJohn Marino      typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
722*e4b17023SJohn Marino        allocator_type;
723*e4b17023SJohn Marino
724*e4b17023SJohn Marino      _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size,
725*e4b17023SJohn Marino		     const allocator_type& __a)
726*e4b17023SJohn Marino      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true,
727*e4b17023SJohn Marino				      __size, __a), _M_data(__d)
728*e4b17023SJohn Marino      {
729*e4b17023SJohn Marino        if (_S_is_basic_char_type((_CharT *)0))
730*e4b17023SJohn Marino	  {
731*e4b17023SJohn Marino            // already eos terminated.
732*e4b17023SJohn Marino            this->_M_c_string = __d;
733*e4b17023SJohn Marino	  }
734*e4b17023SJohn Marino      }
735*e4b17023SJohn Marino      // The constructor assumes that d has been allocated with
736*e4b17023SJohn Marino      // the proper allocator and the properly padded size.
737*e4b17023SJohn Marino      // In contrast, the destructor deallocates the data:
738*e4b17023SJohn Marino#ifndef __GC
739*e4b17023SJohn Marino      ~_Rope_RopeLeaf() throw()
740*e4b17023SJohn Marino      {
741*e4b17023SJohn Marino        if (_M_data != this->_M_c_string)
742*e4b17023SJohn Marino	  this->_M_free_c_string();
743*e4b17023SJohn Marino
744*e4b17023SJohn Marino	this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
745*e4b17023SJohn Marino      }
746*e4b17023SJohn Marino#endif
747*e4b17023SJohn Marinoprotected:
748*e4b17023SJohn Marino      _Rope_RopeLeaf&
749*e4b17023SJohn Marino      operator=(const _Rope_RopeLeaf&);
750*e4b17023SJohn Marino
751*e4b17023SJohn Marino      _Rope_RopeLeaf(const _Rope_RopeLeaf&);
752*e4b17023SJohn Marino    };
753*e4b17023SJohn Marino
754*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
755*e4b17023SJohn Marino    struct _Rope_RopeConcatenation
756*e4b17023SJohn Marino    : public _Rope_RopeRep<_CharT, _Alloc>
757*e4b17023SJohn Marino    {
758*e4b17023SJohn Marino    public:
759*e4b17023SJohn Marino      _Rope_RopeRep<_CharT, _Alloc>* _M_left;
760*e4b17023SJohn Marino      _Rope_RopeRep<_CharT, _Alloc>* _M_right;
761*e4b17023SJohn Marino
762*e4b17023SJohn Marino      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
763*e4b17023SJohn Marino        allocator_type;
764*e4b17023SJohn Marino
765*e4b17023SJohn Marino      _Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l,
766*e4b17023SJohn Marino			      _Rope_RopeRep<_CharT, _Alloc>* __r,
767*e4b17023SJohn Marino			      const allocator_type& __a)
768*e4b17023SJohn Marino	: _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat,
769*e4b17023SJohn Marino				      std::max(__l->_M_depth,
770*e4b17023SJohn Marino					       __r->_M_depth) + 1,
771*e4b17023SJohn Marino				      false,
772*e4b17023SJohn Marino				      __l->_M_size + __r->_M_size, __a),
773*e4b17023SJohn Marino        _M_left(__l), _M_right(__r)
774*e4b17023SJohn Marino      { }
775*e4b17023SJohn Marino#ifndef __GC
776*e4b17023SJohn Marino      ~_Rope_RopeConcatenation() throw()
777*e4b17023SJohn Marino      {
778*e4b17023SJohn Marino	this->_M_free_c_string();
779*e4b17023SJohn Marino	_M_left->_M_unref_nonnil();
780*e4b17023SJohn Marino	_M_right->_M_unref_nonnil();
781*e4b17023SJohn Marino      }
782*e4b17023SJohn Marino#endif
783*e4b17023SJohn Marinoprotected:
784*e4b17023SJohn Marino      _Rope_RopeConcatenation&
785*e4b17023SJohn Marino      operator=(const _Rope_RopeConcatenation&);
786*e4b17023SJohn Marino
787*e4b17023SJohn Marino      _Rope_RopeConcatenation(const _Rope_RopeConcatenation&);
788*e4b17023SJohn Marino    };
789*e4b17023SJohn Marino
790*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
791*e4b17023SJohn Marino    struct _Rope_RopeFunction
792*e4b17023SJohn Marino    : public _Rope_RopeRep<_CharT, _Alloc>
793*e4b17023SJohn Marino    {
794*e4b17023SJohn Marino    public:
795*e4b17023SJohn Marino      char_producer<_CharT>* _M_fn;
796*e4b17023SJohn Marino#ifndef __GC
797*e4b17023SJohn Marino      bool _M_delete_when_done; // Char_producer is owned by the
798*e4b17023SJohn Marino                                // rope and should be explicitly
799*e4b17023SJohn Marino                                // deleted when the rope becomes
800*e4b17023SJohn Marino                                // inaccessible.
801*e4b17023SJohn Marino#else
802*e4b17023SJohn Marino      // In the GC case, we either register the rope for
803*e4b17023SJohn Marino      // finalization, or not.  Thus the field is unnecessary;
804*e4b17023SJohn Marino      // the information is stored in the collector data structures.
805*e4b17023SJohn Marino      // We do need a finalization procedure to be invoked by the
806*e4b17023SJohn Marino      // collector.
807*e4b17023SJohn Marino      static void
808*e4b17023SJohn Marino      _S_fn_finalization_proc(void * __tree, void *)
809*e4b17023SJohn Marino      { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
810*e4b17023SJohn Marino#endif
811*e4b17023SJohn Marino    typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
812*e4b17023SJohn Marino      allocator_type;
813*e4b17023SJohn Marino
814*e4b17023SJohn Marino      _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size,
815*e4b17023SJohn Marino                        bool __d, const allocator_type& __a)
816*e4b17023SJohn Marino      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a)
817*e4b17023SJohn Marino	, _M_fn(__f)
818*e4b17023SJohn Marino#ifndef __GC
819*e4b17023SJohn Marino	, _M_delete_when_done(__d)
820*e4b17023SJohn Marino#endif
821*e4b17023SJohn Marino      {
822*e4b17023SJohn Marino#ifdef __GC
823*e4b17023SJohn Marino	if (__d)
824*e4b17023SJohn Marino	  {
825*e4b17023SJohn Marino	    GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::
826*e4b17023SJohn Marino				  _S_fn_finalization_proc, 0, 0, 0);
827*e4b17023SJohn Marino	  }
828*e4b17023SJohn Marino#endif
829*e4b17023SJohn Marino      }
830*e4b17023SJohn Marino#ifndef __GC
831*e4b17023SJohn Marino      ~_Rope_RopeFunction() throw()
832*e4b17023SJohn Marino      {
833*e4b17023SJohn Marino	this->_M_free_c_string();
834*e4b17023SJohn Marino	if (_M_delete_when_done)
835*e4b17023SJohn Marino	  delete _M_fn;
836*e4b17023SJohn Marino      }
837*e4b17023SJohn Marino# endif
838*e4b17023SJohn Marino    protected:
839*e4b17023SJohn Marino      _Rope_RopeFunction&
840*e4b17023SJohn Marino      operator=(const _Rope_RopeFunction&);
841*e4b17023SJohn Marino
842*e4b17023SJohn Marino      _Rope_RopeFunction(const _Rope_RopeFunction&);
843*e4b17023SJohn Marino    };
844*e4b17023SJohn Marino  // Substring results are usually represented using just
845*e4b17023SJohn Marino  // concatenation nodes.  But in the case of very long flat ropes
846*e4b17023SJohn Marino  // or ropes with a functional representation that isn't practical.
847*e4b17023SJohn Marino  // In that case, we represent the __result as a special case of
848*e4b17023SJohn Marino  // RopeFunction, whose char_producer points back to the rope itself.
849*e4b17023SJohn Marino  // In all cases except repeated substring operations and
850*e4b17023SJohn Marino  // deallocation, we treat the __result as a RopeFunction.
851*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
852*e4b17023SJohn Marino    struct _Rope_RopeSubstring
853*e4b17023SJohn Marino    : public _Rope_RopeFunction<_CharT, _Alloc>,
854*e4b17023SJohn Marino      public char_producer<_CharT>
855*e4b17023SJohn Marino    {
856*e4b17023SJohn Marino    public:
857*e4b17023SJohn Marino      // XXX this whole class should be rewritten.
858*e4b17023SJohn Marino      _Rope_RopeRep<_CharT,_Alloc>* _M_base;      // not 0
859*e4b17023SJohn Marino      size_t _M_start;
860*e4b17023SJohn Marino
861*e4b17023SJohn Marino      virtual void
862*e4b17023SJohn Marino      operator()(size_t __start_pos, size_t __req_len,
863*e4b17023SJohn Marino		 _CharT* __buffer)
864*e4b17023SJohn Marino      {
865*e4b17023SJohn Marino        switch(_M_base->_M_tag)
866*e4b17023SJohn Marino	  {
867*e4b17023SJohn Marino	  case __detail::_S_function:
868*e4b17023SJohn Marino	  case __detail::_S_substringfn:
869*e4b17023SJohn Marino	    {
870*e4b17023SJohn Marino	      char_producer<_CharT>* __fn =
871*e4b17023SJohn Marino		((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;
872*e4b17023SJohn Marino	      (*__fn)(__start_pos + _M_start, __req_len, __buffer);
873*e4b17023SJohn Marino	    }
874*e4b17023SJohn Marino	    break;
875*e4b17023SJohn Marino	  case __detail::_S_leaf:
876*e4b17023SJohn Marino	    {
877*e4b17023SJohn Marino	      __GC_CONST _CharT* __s =
878*e4b17023SJohn Marino		((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data;
879*e4b17023SJohn Marino	      uninitialized_copy_n(__s + __start_pos + _M_start, __req_len,
880*e4b17023SJohn Marino				   __buffer);
881*e4b17023SJohn Marino	    }
882*e4b17023SJohn Marino	    break;
883*e4b17023SJohn Marino	  default:
884*e4b17023SJohn Marino	    break;
885*e4b17023SJohn Marino	  }
886*e4b17023SJohn Marino      }
887*e4b17023SJohn Marino
888*e4b17023SJohn Marino      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
889*e4b17023SJohn Marino        allocator_type;
890*e4b17023SJohn Marino
891*e4b17023SJohn Marino      _Rope_RopeSubstring(_Rope_RopeRep<_CharT, _Alloc>* __b, size_t __s,
892*e4b17023SJohn Marino                          size_t __l, const allocator_type& __a)
893*e4b17023SJohn Marino      : _Rope_RopeFunction<_CharT, _Alloc>(this, __l, false, __a),
894*e4b17023SJohn Marino        char_producer<_CharT>(), _M_base(__b), _M_start(__s)
895*e4b17023SJohn Marino      {
896*e4b17023SJohn Marino#ifndef __GC
897*e4b17023SJohn Marino	_M_base->_M_ref_nonnil();
898*e4b17023SJohn Marino#endif
899*e4b17023SJohn Marino        this->_M_tag = __detail::_S_substringfn;
900*e4b17023SJohn Marino      }
901*e4b17023SJohn Marino    virtual ~_Rope_RopeSubstring() throw()
902*e4b17023SJohn Marino      {
903*e4b17023SJohn Marino#ifndef __GC
904*e4b17023SJohn Marino	_M_base->_M_unref_nonnil();
905*e4b17023SJohn Marino	// _M_free_c_string();  -- done by parent class
906*e4b17023SJohn Marino#endif
907*e4b17023SJohn Marino      }
908*e4b17023SJohn Marino    };
909*e4b17023SJohn Marino
910*e4b17023SJohn Marino  // Self-destructing pointers to Rope_rep.
911*e4b17023SJohn Marino  // These are not conventional smart pointers.  Their
912*e4b17023SJohn Marino  // only purpose in life is to ensure that unref is called
913*e4b17023SJohn Marino  // on the pointer either at normal exit or if an exception
914*e4b17023SJohn Marino  // is raised.  It is the caller's responsibility to
915*e4b17023SJohn Marino  // adjust reference counts when these pointers are initialized
916*e4b17023SJohn Marino  // or assigned to.  (This convention significantly reduces
917*e4b17023SJohn Marino  // the number of potentially expensive reference count
918*e4b17023SJohn Marino  // updates.)
919*e4b17023SJohn Marino#ifndef __GC
920*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
921*e4b17023SJohn Marino    struct _Rope_self_destruct_ptr
922*e4b17023SJohn Marino    {
923*e4b17023SJohn Marino      _Rope_RopeRep<_CharT, _Alloc>* _M_ptr;
924*e4b17023SJohn Marino
925*e4b17023SJohn Marino      ~_Rope_self_destruct_ptr()
926*e4b17023SJohn Marino      { _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
927*e4b17023SJohn Marino#ifdef __EXCEPTIONS
928*e4b17023SJohn Marino      _Rope_self_destruct_ptr() : _M_ptr(0) { };
929*e4b17023SJohn Marino#else
930*e4b17023SJohn Marino      _Rope_self_destruct_ptr() { };
931*e4b17023SJohn Marino#endif
932*e4b17023SJohn Marino      _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p)
933*e4b17023SJohn Marino      : _M_ptr(__p) { }
934*e4b17023SJohn Marino
935*e4b17023SJohn Marino      _Rope_RopeRep<_CharT, _Alloc>&
936*e4b17023SJohn Marino      operator*()
937*e4b17023SJohn Marino      { return *_M_ptr; }
938*e4b17023SJohn Marino
939*e4b17023SJohn Marino      _Rope_RopeRep<_CharT, _Alloc>*
940*e4b17023SJohn Marino      operator->()
941*e4b17023SJohn Marino      { return _M_ptr; }
942*e4b17023SJohn Marino
943*e4b17023SJohn Marino      operator _Rope_RopeRep<_CharT, _Alloc>*()
944*e4b17023SJohn Marino      { return _M_ptr; }
945*e4b17023SJohn Marino
946*e4b17023SJohn Marino      _Rope_self_destruct_ptr&
947*e4b17023SJohn Marino      operator=(_Rope_RopeRep<_CharT, _Alloc>* __x)
948*e4b17023SJohn Marino      { _M_ptr = __x; return *this; }
949*e4b17023SJohn Marino    };
950*e4b17023SJohn Marino#endif
951*e4b17023SJohn Marino
952*e4b17023SJohn Marino  // Dereferencing a nonconst iterator has to return something
953*e4b17023SJohn Marino  // that behaves almost like a reference.  It's not possible to
954*e4b17023SJohn Marino  // return an actual reference since assignment requires extra
955*e4b17023SJohn Marino  // work.  And we would get into the same problems as with the
956*e4b17023SJohn Marino  // CD2 version of basic_string.
957*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
958*e4b17023SJohn Marino    class _Rope_char_ref_proxy
959*e4b17023SJohn Marino    {
960*e4b17023SJohn Marino      friend class rope<_CharT, _Alloc>;
961*e4b17023SJohn Marino      friend class _Rope_iterator<_CharT, _Alloc>;
962*e4b17023SJohn Marino      friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
963*e4b17023SJohn Marino#ifdef __GC
964*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
965*e4b17023SJohn Marino#else
966*e4b17023SJohn Marino      typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
967*e4b17023SJohn Marino#endif
968*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
969*e4b17023SJohn Marino      typedef rope<_CharT, _Alloc> _My_rope;
970*e4b17023SJohn Marino      size_t _M_pos;
971*e4b17023SJohn Marino      _CharT _M_current;
972*e4b17023SJohn Marino      bool _M_current_valid;
973*e4b17023SJohn Marino      _My_rope* _M_root;     // The whole rope.
974*e4b17023SJohn Marino    public:
975*e4b17023SJohn Marino      _Rope_char_ref_proxy(_My_rope* __r, size_t __p)
976*e4b17023SJohn Marino      :  _M_pos(__p), _M_current(), _M_current_valid(false), _M_root(__r) { }
977*e4b17023SJohn Marino
978*e4b17023SJohn Marino      _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x)
979*e4b17023SJohn Marino      : _M_pos(__x._M_pos), _M_current(__x._M_current),
980*e4b17023SJohn Marino	_M_current_valid(false), _M_root(__x._M_root) { }
981*e4b17023SJohn Marino
982*e4b17023SJohn Marino      // Don't preserve cache if the reference can outlive the
983*e4b17023SJohn Marino      // expression.  We claim that's not possible without calling
984*e4b17023SJohn Marino      // a copy constructor or generating reference to a proxy
985*e4b17023SJohn Marino      // reference.  We declare the latter to have undefined semantics.
986*e4b17023SJohn Marino      _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c)
987*e4b17023SJohn Marino      : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) { }
988*e4b17023SJohn Marino
989*e4b17023SJohn Marino      inline operator _CharT () const;
990*e4b17023SJohn Marino
991*e4b17023SJohn Marino      _Rope_char_ref_proxy&
992*e4b17023SJohn Marino      operator=(_CharT __c);
993*e4b17023SJohn Marino
994*e4b17023SJohn Marino      _Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const;
995*e4b17023SJohn Marino
996*e4b17023SJohn Marino      _Rope_char_ref_proxy&
997*e4b17023SJohn Marino      operator=(const _Rope_char_ref_proxy& __c)
998*e4b17023SJohn Marino      { return operator=((_CharT)__c); }
999*e4b17023SJohn Marino    };
1000*e4b17023SJohn Marino
1001*e4b17023SJohn Marino  template<class _CharT, class __Alloc>
1002*e4b17023SJohn Marino    inline void
1003*e4b17023SJohn Marino    swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,
1004*e4b17023SJohn Marino	 _Rope_char_ref_proxy <_CharT, __Alloc > __b)
1005*e4b17023SJohn Marino    {
1006*e4b17023SJohn Marino      _CharT __tmp = __a;
1007*e4b17023SJohn Marino      __a = __b;
1008*e4b17023SJohn Marino      __b = __tmp;
1009*e4b17023SJohn Marino    }
1010*e4b17023SJohn Marino
1011*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
1012*e4b17023SJohn Marino    class _Rope_char_ptr_proxy
1013*e4b17023SJohn Marino    {
1014*e4b17023SJohn Marino      // XXX this class should be rewritten.
1015*e4b17023SJohn Marino      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1016*e4b17023SJohn Marino      size_t _M_pos;
1017*e4b17023SJohn Marino      rope<_CharT,_Alloc>* _M_root;     // The whole rope.
1018*e4b17023SJohn Marino    public:
1019*e4b17023SJohn Marino      _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x)
1020*e4b17023SJohn Marino      : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1021*e4b17023SJohn Marino
1022*e4b17023SJohn Marino      _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x)
1023*e4b17023SJohn Marino      : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1024*e4b17023SJohn Marino
1025*e4b17023SJohn Marino      _Rope_char_ptr_proxy() { }
1026*e4b17023SJohn Marino
1027*e4b17023SJohn Marino      _Rope_char_ptr_proxy(_CharT* __x)
1028*e4b17023SJohn Marino      : _M_root(0), _M_pos(0) { }
1029*e4b17023SJohn Marino
1030*e4b17023SJohn Marino      _Rope_char_ptr_proxy&
1031*e4b17023SJohn Marino      operator=(const _Rope_char_ptr_proxy& __x)
1032*e4b17023SJohn Marino      {
1033*e4b17023SJohn Marino        _M_pos = __x._M_pos;
1034*e4b17023SJohn Marino        _M_root = __x._M_root;
1035*e4b17023SJohn Marino        return *this;
1036*e4b17023SJohn Marino      }
1037*e4b17023SJohn Marino
1038*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1039*e4b17023SJohn Marino        friend bool
1040*e4b17023SJohn Marino        operator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x,
1041*e4b17023SJohn Marino		   const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y);
1042*e4b17023SJohn Marino
1043*e4b17023SJohn Marino      _Rope_char_ref_proxy<_CharT, _Alloc> operator*() const
1044*e4b17023SJohn Marino      { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); }
1045*e4b17023SJohn Marino    };
1046*e4b17023SJohn Marino
1047*e4b17023SJohn Marino  // Rope iterators:
1048*e4b17023SJohn Marino  // Unlike in the C version, we cache only part of the stack
1049*e4b17023SJohn Marino  // for rope iterators, since they must be efficiently copyable.
1050*e4b17023SJohn Marino  // When we run out of cache, we have to reconstruct the iterator
1051*e4b17023SJohn Marino  // value.
1052*e4b17023SJohn Marino  // Pointers from iterators are not included in reference counts.
1053*e4b17023SJohn Marino  // Iterators are assumed to be thread private.  Ropes can
1054*e4b17023SJohn Marino  // be shared.
1055*e4b17023SJohn Marino
1056*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
1057*e4b17023SJohn Marino    class _Rope_iterator_base
1058*e4b17023SJohn Marino    : public std::iterator<std::random_access_iterator_tag, _CharT>
1059*e4b17023SJohn Marino    {
1060*e4b17023SJohn Marino      friend class rope<_CharT, _Alloc>;
1061*e4b17023SJohn Marino    public:
1062*e4b17023SJohn Marino      typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaround
1063*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1064*e4b17023SJohn Marino      // Borland doesn't want this to be protected.
1065*e4b17023SJohn Marino    protected:
1066*e4b17023SJohn Marino      enum { _S_path_cache_len = 4 }; // Must be <= 9.
1067*e4b17023SJohn Marino      enum { _S_iterator_buf_len = 15 };
1068*e4b17023SJohn Marino      size_t _M_current_pos;
1069*e4b17023SJohn Marino      _RopeRep* _M_root;     // The whole rope.
1070*e4b17023SJohn Marino      size_t _M_leaf_pos;    // Starting position for current leaf
1071*e4b17023SJohn Marino      __GC_CONST _CharT* _M_buf_start;
1072*e4b17023SJohn Marino                             // Buffer possibly
1073*e4b17023SJohn Marino                             // containing current char.
1074*e4b17023SJohn Marino      __GC_CONST _CharT* _M_buf_ptr;
1075*e4b17023SJohn Marino                             // Pointer to current char in buffer.
1076*e4b17023SJohn Marino                             // != 0 ==> buffer valid.
1077*e4b17023SJohn Marino      __GC_CONST _CharT* _M_buf_end;
1078*e4b17023SJohn Marino                             // One past __last valid char in buffer.
1079*e4b17023SJohn Marino      // What follows is the path cache.  We go out of our
1080*e4b17023SJohn Marino      // way to make this compact.
1081*e4b17023SJohn Marino      // Path_end contains the bottom section of the path from
1082*e4b17023SJohn Marino      // the root to the current leaf.
1083*e4b17023SJohn Marino      const _RopeRep* _M_path_end[_S_path_cache_len];
1084*e4b17023SJohn Marino      int _M_leaf_index;     // Last valid __pos in path_end;
1085*e4b17023SJohn Marino                             // _M_path_end[0] ... _M_path_end[leaf_index-1]
1086*e4b17023SJohn Marino                             // point to concatenation nodes.
1087*e4b17023SJohn Marino      unsigned char _M_path_directions;
1088*e4b17023SJohn Marino                          // (path_directions >> __i) & 1 is 1
1089*e4b17023SJohn Marino                          // iff we got from _M_path_end[leaf_index - __i - 1]
1090*e4b17023SJohn Marino                          // to _M_path_end[leaf_index - __i] by going to the
1091*e4b17023SJohn Marino                          // __right. Assumes path_cache_len <= 9.
1092*e4b17023SJohn Marino      _CharT _M_tmp_buf[_S_iterator_buf_len];
1093*e4b17023SJohn Marino                        // Short buffer for surrounding chars.
1094*e4b17023SJohn Marino                        // This is useful primarily for
1095*e4b17023SJohn Marino                        // RopeFunctions.  We put the buffer
1096*e4b17023SJohn Marino                        // here to avoid locking in the
1097*e4b17023SJohn Marino                        // multithreaded case.
1098*e4b17023SJohn Marino      // The cached path is generally assumed to be valid
1099*e4b17023SJohn Marino      // only if the buffer is valid.
1100*e4b17023SJohn Marino      static void _S_setbuf(_Rope_iterator_base& __x);
1101*e4b17023SJohn Marino                                        // Set buffer contents given
1102*e4b17023SJohn Marino                                        // path cache.
1103*e4b17023SJohn Marino      static void _S_setcache(_Rope_iterator_base& __x);
1104*e4b17023SJohn Marino                                        // Set buffer contents and
1105*e4b17023SJohn Marino                                        // path cache.
1106*e4b17023SJohn Marino      static void _S_setcache_for_incr(_Rope_iterator_base& __x);
1107*e4b17023SJohn Marino                                        // As above, but assumes path
1108*e4b17023SJohn Marino                                        // cache is valid for previous posn.
1109*e4b17023SJohn Marino      _Rope_iterator_base() { }
1110*e4b17023SJohn Marino
1111*e4b17023SJohn Marino      _Rope_iterator_base(_RopeRep* __root, size_t __pos)
1112*e4b17023SJohn Marino      : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }
1113*e4b17023SJohn Marino
1114*e4b17023SJohn Marino      void _M_incr(size_t __n);
1115*e4b17023SJohn Marino      void _M_decr(size_t __n);
1116*e4b17023SJohn Marino    public:
1117*e4b17023SJohn Marino      size_t
1118*e4b17023SJohn Marino      index() const
1119*e4b17023SJohn Marino      { return _M_current_pos; }
1120*e4b17023SJohn Marino
1121*e4b17023SJohn Marino      _Rope_iterator_base(const _Rope_iterator_base& __x)
1122*e4b17023SJohn Marino      {
1123*e4b17023SJohn Marino        if (0 != __x._M_buf_ptr)
1124*e4b17023SJohn Marino	  *this = __x;
1125*e4b17023SJohn Marino	else
1126*e4b17023SJohn Marino	  {
1127*e4b17023SJohn Marino            _M_current_pos = __x._M_current_pos;
1128*e4b17023SJohn Marino            _M_root = __x._M_root;
1129*e4b17023SJohn Marino            _M_buf_ptr = 0;
1130*e4b17023SJohn Marino	  }
1131*e4b17023SJohn Marino      }
1132*e4b17023SJohn Marino    };
1133*e4b17023SJohn Marino
1134*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
1135*e4b17023SJohn Marino    class _Rope_iterator;
1136*e4b17023SJohn Marino
1137*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
1138*e4b17023SJohn Marino    class _Rope_const_iterator
1139*e4b17023SJohn Marino    : public _Rope_iterator_base<_CharT, _Alloc>
1140*e4b17023SJohn Marino    {
1141*e4b17023SJohn Marino      friend class rope<_CharT, _Alloc>;
1142*e4b17023SJohn Marino    protected:
1143*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1144*e4b17023SJohn Marino      // The one from the base class may not be directly visible.
1145*e4b17023SJohn Marino      _Rope_const_iterator(const _RopeRep* __root, size_t __pos)
1146*e4b17023SJohn Marino      : _Rope_iterator_base<_CharT, _Alloc>(const_cast<_RopeRep*>(__root),
1147*e4b17023SJohn Marino					    __pos)
1148*e4b17023SJohn Marino                   // Only nonconst iterators modify root ref count
1149*e4b17023SJohn Marino      { }
1150*e4b17023SJohn Marino  public:
1151*e4b17023SJohn Marino      typedef _CharT reference;   // Really a value.  Returning a reference
1152*e4b17023SJohn Marino                                  // Would be a mess, since it would have
1153*e4b17023SJohn Marino                                  // to be included in refcount.
1154*e4b17023SJohn Marino      typedef const _CharT* pointer;
1155*e4b17023SJohn Marino
1156*e4b17023SJohn Marino    public:
1157*e4b17023SJohn Marino      _Rope_const_iterator() { };
1158*e4b17023SJohn Marino
1159*e4b17023SJohn Marino      _Rope_const_iterator(const _Rope_const_iterator& __x)
1160*e4b17023SJohn Marino      : _Rope_iterator_base<_CharT,_Alloc>(__x) { }
1161*e4b17023SJohn Marino
1162*e4b17023SJohn Marino      _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);
1163*e4b17023SJohn Marino
1164*e4b17023SJohn Marino      _Rope_const_iterator(const rope<_CharT, _Alloc>& __r, size_t __pos)
1165*e4b17023SJohn Marino      : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { }
1166*e4b17023SJohn Marino
1167*e4b17023SJohn Marino      _Rope_const_iterator&
1168*e4b17023SJohn Marino      operator=(const _Rope_const_iterator& __x)
1169*e4b17023SJohn Marino      {
1170*e4b17023SJohn Marino        if (0 != __x._M_buf_ptr)
1171*e4b17023SJohn Marino	  *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1172*e4b17023SJohn Marino	else
1173*e4b17023SJohn Marino	  {
1174*e4b17023SJohn Marino            this->_M_current_pos = __x._M_current_pos;
1175*e4b17023SJohn Marino            this->_M_root = __x._M_root;
1176*e4b17023SJohn Marino            this->_M_buf_ptr = 0;
1177*e4b17023SJohn Marino	  }
1178*e4b17023SJohn Marino        return(*this);
1179*e4b17023SJohn Marino      }
1180*e4b17023SJohn Marino
1181*e4b17023SJohn Marino      reference
1182*e4b17023SJohn Marino      operator*()
1183*e4b17023SJohn Marino      {
1184*e4b17023SJohn Marino        if (0 == this->_M_buf_ptr)
1185*e4b17023SJohn Marino	  this->_S_setcache(*this);
1186*e4b17023SJohn Marino        return *this->_M_buf_ptr;
1187*e4b17023SJohn Marino      }
1188*e4b17023SJohn Marino
1189*e4b17023SJohn Marino      // Without this const version, Rope iterators do not meet the
1190*e4b17023SJohn Marino      // requirements of an Input Iterator.
1191*e4b17023SJohn Marino      reference
1192*e4b17023SJohn Marino      operator*() const
1193*e4b17023SJohn Marino      {
1194*e4b17023SJohn Marino	return *const_cast<_Rope_const_iterator&>(*this);
1195*e4b17023SJohn Marino      }
1196*e4b17023SJohn Marino
1197*e4b17023SJohn Marino      _Rope_const_iterator&
1198*e4b17023SJohn Marino      operator++()
1199*e4b17023SJohn Marino      {
1200*e4b17023SJohn Marino        __GC_CONST _CharT* __next;
1201*e4b17023SJohn Marino        if (0 != this->_M_buf_ptr
1202*e4b17023SJohn Marino	    && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end)
1203*e4b17023SJohn Marino	  {
1204*e4b17023SJohn Marino            this->_M_buf_ptr = __next;
1205*e4b17023SJohn Marino            ++this->_M_current_pos;
1206*e4b17023SJohn Marino	  }
1207*e4b17023SJohn Marino	else
1208*e4b17023SJohn Marino	  this->_M_incr(1);
1209*e4b17023SJohn Marino	return *this;
1210*e4b17023SJohn Marino      }
1211*e4b17023SJohn Marino
1212*e4b17023SJohn Marino      _Rope_const_iterator&
1213*e4b17023SJohn Marino      operator+=(ptrdiff_t __n)
1214*e4b17023SJohn Marino      {
1215*e4b17023SJohn Marino        if (__n >= 0)
1216*e4b17023SJohn Marino	  this->_M_incr(__n);
1217*e4b17023SJohn Marino	else
1218*e4b17023SJohn Marino	  this->_M_decr(-__n);
1219*e4b17023SJohn Marino	return *this;
1220*e4b17023SJohn Marino      }
1221*e4b17023SJohn Marino
1222*e4b17023SJohn Marino      _Rope_const_iterator&
1223*e4b17023SJohn Marino      operator--()
1224*e4b17023SJohn Marino      {
1225*e4b17023SJohn Marino        this->_M_decr(1);
1226*e4b17023SJohn Marino        return *this;
1227*e4b17023SJohn Marino      }
1228*e4b17023SJohn Marino
1229*e4b17023SJohn Marino      _Rope_const_iterator&
1230*e4b17023SJohn Marino      operator-=(ptrdiff_t __n)
1231*e4b17023SJohn Marino      {
1232*e4b17023SJohn Marino        if (__n >= 0)
1233*e4b17023SJohn Marino	  this->_M_decr(__n);
1234*e4b17023SJohn Marino	else
1235*e4b17023SJohn Marino	  this->_M_incr(-__n);
1236*e4b17023SJohn Marino	return *this;
1237*e4b17023SJohn Marino      }
1238*e4b17023SJohn Marino
1239*e4b17023SJohn Marino      _Rope_const_iterator
1240*e4b17023SJohn Marino      operator++(int)
1241*e4b17023SJohn Marino      {
1242*e4b17023SJohn Marino        size_t __old_pos = this->_M_current_pos;
1243*e4b17023SJohn Marino        this->_M_incr(1);
1244*e4b17023SJohn Marino        return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1245*e4b17023SJohn Marino        // This makes a subsequent dereference expensive.
1246*e4b17023SJohn Marino        // Perhaps we should instead copy the iterator
1247*e4b17023SJohn Marino        // if it has a valid cache?
1248*e4b17023SJohn Marino      }
1249*e4b17023SJohn Marino
1250*e4b17023SJohn Marino      _Rope_const_iterator
1251*e4b17023SJohn Marino      operator--(int)
1252*e4b17023SJohn Marino      {
1253*e4b17023SJohn Marino        size_t __old_pos = this->_M_current_pos;
1254*e4b17023SJohn Marino        this->_M_decr(1);
1255*e4b17023SJohn Marino        return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1256*e4b17023SJohn Marino      }
1257*e4b17023SJohn Marino
1258*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1259*e4b17023SJohn Marino        friend _Rope_const_iterator<_CharT2, _Alloc2>
1260*e4b17023SJohn Marino        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1261*e4b17023SJohn Marino		  ptrdiff_t __n);
1262*e4b17023SJohn Marino
1263*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1264*e4b17023SJohn Marino        friend _Rope_const_iterator<_CharT2, _Alloc2>
1265*e4b17023SJohn Marino        operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1266*e4b17023SJohn Marino		  ptrdiff_t __n);
1267*e4b17023SJohn Marino
1268*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1269*e4b17023SJohn Marino        friend _Rope_const_iterator<_CharT2, _Alloc2>
1270*e4b17023SJohn Marino        operator+(ptrdiff_t __n,
1271*e4b17023SJohn Marino		  const _Rope_const_iterator<_CharT2, _Alloc2>& __x);
1272*e4b17023SJohn Marino
1273*e4b17023SJohn Marino      reference
1274*e4b17023SJohn Marino      operator[](size_t __n)
1275*e4b17023SJohn Marino      { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,
1276*e4b17023SJohn Marino					      this->_M_current_pos + __n); }
1277*e4b17023SJohn Marino
1278*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1279*e4b17023SJohn Marino        friend bool
1280*e4b17023SJohn Marino        operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1281*e4b17023SJohn Marino		   const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1282*e4b17023SJohn Marino
1283*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1284*e4b17023SJohn Marino        friend bool
1285*e4b17023SJohn Marino        operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1286*e4b17023SJohn Marino		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1287*e4b17023SJohn Marino
1288*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1289*e4b17023SJohn Marino        friend ptrdiff_t
1290*e4b17023SJohn Marino        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1291*e4b17023SJohn Marino		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1292*e4b17023SJohn Marino    };
1293*e4b17023SJohn Marino
1294*e4b17023SJohn Marino  template<class _CharT, class _Alloc>
1295*e4b17023SJohn Marino    class _Rope_iterator
1296*e4b17023SJohn Marino    : public _Rope_iterator_base<_CharT, _Alloc>
1297*e4b17023SJohn Marino    {
1298*e4b17023SJohn Marino      friend class rope<_CharT, _Alloc>;
1299*e4b17023SJohn Marino    protected:
1300*e4b17023SJohn Marino      typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep;
1301*e4b17023SJohn Marino      rope<_CharT, _Alloc>* _M_root_rope;
1302*e4b17023SJohn Marino
1303*e4b17023SJohn Marino      // root is treated as a cached version of this, and is used to
1304*e4b17023SJohn Marino      // detect changes to the underlying rope.
1305*e4b17023SJohn Marino
1306*e4b17023SJohn Marino      // Root is included in the reference count.  This is necessary
1307*e4b17023SJohn Marino      // so that we can detect changes reliably.  Unfortunately, it
1308*e4b17023SJohn Marino      // requires careful bookkeeping for the nonGC case.
1309*e4b17023SJohn Marino      _Rope_iterator(rope<_CharT, _Alloc>* __r, size_t __pos)
1310*e4b17023SJohn Marino      : _Rope_iterator_base<_CharT, _Alloc>(__r->_M_tree_ptr, __pos),
1311*e4b17023SJohn Marino        _M_root_rope(__r)
1312*e4b17023SJohn Marino      { _RopeRep::_S_ref(this->_M_root);
1313*e4b17023SJohn Marino        if (!(__r -> empty()))
1314*e4b17023SJohn Marino	  this->_S_setcache(*this);
1315*e4b17023SJohn Marino      }
1316*e4b17023SJohn Marino
1317*e4b17023SJohn Marino      void _M_check();
1318*e4b17023SJohn Marino    public:
1319*e4b17023SJohn Marino      typedef _Rope_char_ref_proxy<_CharT, _Alloc>  reference;
1320*e4b17023SJohn Marino      typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer;
1321*e4b17023SJohn Marino
1322*e4b17023SJohn Marino      rope<_CharT, _Alloc>&
1323*e4b17023SJohn Marino      container()
1324*e4b17023SJohn Marino      { return *_M_root_rope; }
1325*e4b17023SJohn Marino
1326*e4b17023SJohn Marino      _Rope_iterator()
1327*e4b17023SJohn Marino      {
1328*e4b17023SJohn Marino        this->_M_root = 0;  // Needed for reference counting.
1329*e4b17023SJohn Marino      };
1330*e4b17023SJohn Marino
1331*e4b17023SJohn Marino      _Rope_iterator(const _Rope_iterator& __x)
1332*e4b17023SJohn Marino      : _Rope_iterator_base<_CharT, _Alloc>(__x)
1333*e4b17023SJohn Marino      {
1334*e4b17023SJohn Marino        _M_root_rope = __x._M_root_rope;
1335*e4b17023SJohn Marino        _RopeRep::_S_ref(this->_M_root);
1336*e4b17023SJohn Marino      }
1337*e4b17023SJohn Marino
1338*e4b17023SJohn Marino      _Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos);
1339*e4b17023SJohn Marino
1340*e4b17023SJohn Marino      ~_Rope_iterator()
1341*e4b17023SJohn Marino      { _RopeRep::_S_unref(this->_M_root); }
1342*e4b17023SJohn Marino
1343*e4b17023SJohn Marino      _Rope_iterator&
1344*e4b17023SJohn Marino      operator=(const _Rope_iterator& __x)
1345*e4b17023SJohn Marino      {
1346*e4b17023SJohn Marino        _RopeRep* __old = this->_M_root;
1347*e4b17023SJohn Marino
1348*e4b17023SJohn Marino        _RopeRep::_S_ref(__x._M_root);
1349*e4b17023SJohn Marino        if (0 != __x._M_buf_ptr)
1350*e4b17023SJohn Marino	  {
1351*e4b17023SJohn Marino            _M_root_rope = __x._M_root_rope;
1352*e4b17023SJohn Marino            *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1353*e4b17023SJohn Marino	  }
1354*e4b17023SJohn Marino	else
1355*e4b17023SJohn Marino	  {
1356*e4b17023SJohn Marino	    this->_M_current_pos = __x._M_current_pos;
1357*e4b17023SJohn Marino            this->_M_root = __x._M_root;
1358*e4b17023SJohn Marino            _M_root_rope = __x._M_root_rope;
1359*e4b17023SJohn Marino            this->_M_buf_ptr = 0;
1360*e4b17023SJohn Marino	  }
1361*e4b17023SJohn Marino        _RopeRep::_S_unref(__old);
1362*e4b17023SJohn Marino        return(*this);
1363*e4b17023SJohn Marino      }
1364*e4b17023SJohn Marino
1365*e4b17023SJohn Marino      reference
1366*e4b17023SJohn Marino      operator*()
1367*e4b17023SJohn Marino      {
1368*e4b17023SJohn Marino        _M_check();
1369*e4b17023SJohn Marino        if (0 == this->_M_buf_ptr)
1370*e4b17023SJohn Marino	  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1371*e4b17023SJohn Marino						      this->_M_current_pos);
1372*e4b17023SJohn Marino	else
1373*e4b17023SJohn Marino	  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1374*e4b17023SJohn Marino						      this->_M_current_pos,
1375*e4b17023SJohn Marino						      *this->_M_buf_ptr);
1376*e4b17023SJohn Marino      }
1377*e4b17023SJohn Marino
1378*e4b17023SJohn Marino      // See above comment.
1379*e4b17023SJohn Marino      reference
1380*e4b17023SJohn Marino      operator*() const
1381*e4b17023SJohn Marino      {
1382*e4b17023SJohn Marino	return *const_cast<_Rope_iterator&>(*this);
1383*e4b17023SJohn Marino      }
1384*e4b17023SJohn Marino
1385*e4b17023SJohn Marino      _Rope_iterator&
1386*e4b17023SJohn Marino      operator++()
1387*e4b17023SJohn Marino      {
1388*e4b17023SJohn Marino        this->_M_incr(1);
1389*e4b17023SJohn Marino        return *this;
1390*e4b17023SJohn Marino      }
1391*e4b17023SJohn Marino
1392*e4b17023SJohn Marino      _Rope_iterator&
1393*e4b17023SJohn Marino      operator+=(ptrdiff_t __n)
1394*e4b17023SJohn Marino      {
1395*e4b17023SJohn Marino        if (__n >= 0)
1396*e4b17023SJohn Marino	  this->_M_incr(__n);
1397*e4b17023SJohn Marino	else
1398*e4b17023SJohn Marino	  this->_M_decr(-__n);
1399*e4b17023SJohn Marino	return *this;
1400*e4b17023SJohn Marino      }
1401*e4b17023SJohn Marino
1402*e4b17023SJohn Marino      _Rope_iterator&
1403*e4b17023SJohn Marino      operator--()
1404*e4b17023SJohn Marino      {
1405*e4b17023SJohn Marino        this->_M_decr(1);
1406*e4b17023SJohn Marino        return *this;
1407*e4b17023SJohn Marino      }
1408*e4b17023SJohn Marino
1409*e4b17023SJohn Marino      _Rope_iterator&
1410*e4b17023SJohn Marino      operator-=(ptrdiff_t __n)
1411*e4b17023SJohn Marino      {
1412*e4b17023SJohn Marino        if (__n >= 0)
1413*e4b17023SJohn Marino	  this->_M_decr(__n);
1414*e4b17023SJohn Marino	else
1415*e4b17023SJohn Marino	  this->_M_incr(-__n);
1416*e4b17023SJohn Marino	return *this;
1417*e4b17023SJohn Marino      }
1418*e4b17023SJohn Marino
1419*e4b17023SJohn Marino      _Rope_iterator
1420*e4b17023SJohn Marino      operator++(int)
1421*e4b17023SJohn Marino      {
1422*e4b17023SJohn Marino        size_t __old_pos = this->_M_current_pos;
1423*e4b17023SJohn Marino        this->_M_incr(1);
1424*e4b17023SJohn Marino        return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1425*e4b17023SJohn Marino      }
1426*e4b17023SJohn Marino
1427*e4b17023SJohn Marino      _Rope_iterator
1428*e4b17023SJohn Marino      operator--(int)
1429*e4b17023SJohn Marino      {
1430*e4b17023SJohn Marino        size_t __old_pos = this->_M_current_pos;
1431*e4b17023SJohn Marino        this->_M_decr(1);
1432*e4b17023SJohn Marino        return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1433*e4b17023SJohn Marino      }
1434*e4b17023SJohn Marino
1435*e4b17023SJohn Marino      reference
1436*e4b17023SJohn Marino      operator[](ptrdiff_t __n)
1437*e4b17023SJohn Marino      { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1438*e4b17023SJohn Marino						    this->_M_current_pos
1439*e4b17023SJohn Marino						    + __n); }
1440*e4b17023SJohn Marino
1441*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1442*e4b17023SJohn Marino        friend bool
1443*e4b17023SJohn Marino        operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1444*e4b17023SJohn Marino		   const _Rope_iterator<_CharT2, _Alloc2>& __y);
1445*e4b17023SJohn Marino
1446*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1447*e4b17023SJohn Marino        friend bool
1448*e4b17023SJohn Marino        operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1449*e4b17023SJohn Marino		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1450*e4b17023SJohn Marino
1451*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1452*e4b17023SJohn Marino        friend ptrdiff_t
1453*e4b17023SJohn Marino        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1454*e4b17023SJohn Marino		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1455*e4b17023SJohn Marino
1456*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1457*e4b17023SJohn Marino        friend _Rope_iterator<_CharT2, _Alloc2>
1458*e4b17023SJohn Marino        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1459*e4b17023SJohn Marino
1460*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1461*e4b17023SJohn Marino        friend _Rope_iterator<_CharT2, _Alloc2>
1462*e4b17023SJohn Marino        operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1463*e4b17023SJohn Marino
1464*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
1465*e4b17023SJohn Marino        friend _Rope_iterator<_CharT2, _Alloc2>
1466*e4b17023SJohn Marino        operator+(ptrdiff_t __n, const _Rope_iterator<_CharT2, _Alloc2>& __x);
1467*e4b17023SJohn Marino    };
1468*e4b17023SJohn Marino
1469*e4b17023SJohn Marino
1470*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
1471*e4b17023SJohn Marino    struct _Rope_base
1472*e4b17023SJohn Marino    : public _Alloc
1473*e4b17023SJohn Marino    {
1474*e4b17023SJohn Marino      typedef _Alloc allocator_type;
1475*e4b17023SJohn Marino
1476*e4b17023SJohn Marino      allocator_type
1477*e4b17023SJohn Marino      get_allocator() const
1478*e4b17023SJohn Marino      { return *static_cast<const _Alloc*>(this); }
1479*e4b17023SJohn Marino
1480*e4b17023SJohn Marino      allocator_type&
1481*e4b17023SJohn Marino      _M_get_allocator()
1482*e4b17023SJohn Marino      { return *static_cast<_Alloc*>(this); }
1483*e4b17023SJohn Marino
1484*e4b17023SJohn Marino      const allocator_type&
1485*e4b17023SJohn Marino      _M_get_allocator() const
1486*e4b17023SJohn Marino      { return *static_cast<const _Alloc*>(this); }
1487*e4b17023SJohn Marino
1488*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1489*e4b17023SJohn Marino      // The one in _Base may not be visible due to template rules.
1490*e4b17023SJohn Marino
1491*e4b17023SJohn Marino      _Rope_base(_RopeRep* __t, const allocator_type&)
1492*e4b17023SJohn Marino      : _M_tree_ptr(__t) { }
1493*e4b17023SJohn Marino
1494*e4b17023SJohn Marino      _Rope_base(const allocator_type&) { }
1495*e4b17023SJohn Marino
1496*e4b17023SJohn Marino      // The only data member of a rope:
1497*e4b17023SJohn Marino      _RopeRep *_M_tree_ptr;
1498*e4b17023SJohn Marino
1499*e4b17023SJohn Marino#define __ROPE_DEFINE_ALLOC(_Tp, __name) \
1500*e4b17023SJohn Marino        typedef typename \
1501*e4b17023SJohn Marino          _Alloc::template rebind<_Tp>::other __name##Alloc; \
1502*e4b17023SJohn Marino        static _Tp* __name##_allocate(size_t __n) \
1503*e4b17023SJohn Marino          { return __name##Alloc().allocate(__n); } \
1504*e4b17023SJohn Marino        static void __name##_deallocate(_Tp *__p, size_t __n) \
1505*e4b17023SJohn Marino          { __name##Alloc().deallocate(__p, __n); }
1506*e4b17023SJohn Marino      __ROPE_DEFINE_ALLOCS(_Alloc)
1507*e4b17023SJohn Marino#undef __ROPE_DEFINE_ALLOC
1508*e4b17023SJohn Marino
1509*e4b17023SJohn Marino	protected:
1510*e4b17023SJohn Marino      _Rope_base&
1511*e4b17023SJohn Marino      operator=(const _Rope_base&);
1512*e4b17023SJohn Marino
1513*e4b17023SJohn Marino      _Rope_base(const _Rope_base&);
1514*e4b17023SJohn Marino    };
1515*e4b17023SJohn Marino
1516*e4b17023SJohn Marino  /**
1517*e4b17023SJohn Marino   *  This is an SGI extension.
1518*e4b17023SJohn Marino   *  @ingroup SGIextensions
1519*e4b17023SJohn Marino   *  @doctodo
1520*e4b17023SJohn Marino   */
1521*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
1522*e4b17023SJohn Marino    class rope : public _Rope_base<_CharT, _Alloc>
1523*e4b17023SJohn Marino    {
1524*e4b17023SJohn Marino    public:
1525*e4b17023SJohn Marino      typedef _CharT value_type;
1526*e4b17023SJohn Marino      typedef ptrdiff_t difference_type;
1527*e4b17023SJohn Marino      typedef size_t size_type;
1528*e4b17023SJohn Marino      typedef _CharT const_reference;
1529*e4b17023SJohn Marino      typedef const _CharT* const_pointer;
1530*e4b17023SJohn Marino      typedef _Rope_iterator<_CharT, _Alloc> iterator;
1531*e4b17023SJohn Marino      typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator;
1532*e4b17023SJohn Marino      typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1533*e4b17023SJohn Marino      typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer;
1534*e4b17023SJohn Marino
1535*e4b17023SJohn Marino      friend class _Rope_iterator<_CharT, _Alloc>;
1536*e4b17023SJohn Marino      friend class _Rope_const_iterator<_CharT, _Alloc>;
1537*e4b17023SJohn Marino      friend struct _Rope_RopeRep<_CharT, _Alloc>;
1538*e4b17023SJohn Marino      friend class _Rope_iterator_base<_CharT, _Alloc>;
1539*e4b17023SJohn Marino      friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
1540*e4b17023SJohn Marino      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1541*e4b17023SJohn Marino      friend struct _Rope_RopeSubstring<_CharT, _Alloc>;
1542*e4b17023SJohn Marino
1543*e4b17023SJohn Marino    protected:
1544*e4b17023SJohn Marino      typedef _Rope_base<_CharT, _Alloc> _Base;
1545*e4b17023SJohn Marino      typedef typename _Base::allocator_type allocator_type;
1546*e4b17023SJohn Marino      using _Base::_M_tree_ptr;
1547*e4b17023SJohn Marino      using _Base::get_allocator;
1548*e4b17023SJohn Marino      using _Base::_M_get_allocator;
1549*e4b17023SJohn Marino      typedef __GC_CONST _CharT* _Cstrptr;
1550*e4b17023SJohn Marino
1551*e4b17023SJohn Marino      static _CharT _S_empty_c_str[1];
1552*e4b17023SJohn Marino
1553*e4b17023SJohn Marino      static bool
1554*e4b17023SJohn Marino      _S_is0(_CharT __c)
1555*e4b17023SJohn Marino      { return __c == _S_eos((_CharT*)0); }
1556*e4b17023SJohn Marino
1557*e4b17023SJohn Marino      enum { _S_copy_max = 23 };
1558*e4b17023SJohn Marino                // For strings shorter than _S_copy_max, we copy to
1559*e4b17023SJohn Marino                // concatenate.
1560*e4b17023SJohn Marino
1561*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1562*e4b17023SJohn Marino      typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;
1563*e4b17023SJohn Marino      typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;
1564*e4b17023SJohn Marino      typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;
1565*e4b17023SJohn Marino      typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;
1566*e4b17023SJohn Marino
1567*e4b17023SJohn Marino      // Retrieve a character at the indicated position.
1568*e4b17023SJohn Marino      static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
1569*e4b17023SJohn Marino
1570*e4b17023SJohn Marino#ifndef __GC
1571*e4b17023SJohn Marino      // Obtain a pointer to the character at the indicated position.
1572*e4b17023SJohn Marino      // The pointer can be used to change the character.
1573*e4b17023SJohn Marino      // If such a pointer cannot be produced, as is frequently the
1574*e4b17023SJohn Marino      // case, 0 is returned instead.
1575*e4b17023SJohn Marino      // (Returns nonzero only if all nodes in the path have a refcount
1576*e4b17023SJohn Marino      // of 1.)
1577*e4b17023SJohn Marino      static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
1578*e4b17023SJohn Marino#endif
1579*e4b17023SJohn Marino
1580*e4b17023SJohn Marino      static bool
1581*e4b17023SJohn Marino      _S_apply_to_pieces(// should be template parameter
1582*e4b17023SJohn Marino			 _Rope_char_consumer<_CharT>& __c,
1583*e4b17023SJohn Marino			 const _RopeRep* __r,
1584*e4b17023SJohn Marino			 size_t __begin, size_t __end);
1585*e4b17023SJohn Marino                         // begin and end are assumed to be in range.
1586*e4b17023SJohn Marino
1587*e4b17023SJohn Marino#ifndef __GC
1588*e4b17023SJohn Marino      static void
1589*e4b17023SJohn Marino      _S_unref(_RopeRep* __t)
1590*e4b17023SJohn Marino      { _RopeRep::_S_unref(__t); }
1591*e4b17023SJohn Marino
1592*e4b17023SJohn Marino      static void
1593*e4b17023SJohn Marino      _S_ref(_RopeRep* __t)
1594*e4b17023SJohn Marino      { _RopeRep::_S_ref(__t); }
1595*e4b17023SJohn Marino
1596*e4b17023SJohn Marino#else /* __GC */
1597*e4b17023SJohn Marino      static void _S_unref(_RopeRep*) { }
1598*e4b17023SJohn Marino      static void _S_ref(_RopeRep*) { }
1599*e4b17023SJohn Marino#endif
1600*e4b17023SJohn Marino
1601*e4b17023SJohn Marino#ifdef __GC
1602*e4b17023SJohn Marino      typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
1603*e4b17023SJohn Marino#else
1604*e4b17023SJohn Marino      typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
1605*e4b17023SJohn Marino#endif
1606*e4b17023SJohn Marino
1607*e4b17023SJohn Marino      // _Result is counted in refcount.
1608*e4b17023SJohn Marino      static _RopeRep* _S_substring(_RopeRep* __base,
1609*e4b17023SJohn Marino                                    size_t __start, size_t __endp1);
1610*e4b17023SJohn Marino
1611*e4b17023SJohn Marino      static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
1612*e4b17023SJohn Marino					   const _CharT* __iter, size_t __slen);
1613*e4b17023SJohn Marino      // Concatenate rope and char ptr, copying __s.
1614*e4b17023SJohn Marino      // Should really take an arbitrary iterator.
1615*e4b17023SJohn Marino      // Result is counted in refcount.
1616*e4b17023SJohn Marino      static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
1617*e4b17023SJohn Marino						 const _CharT* __iter,
1618*e4b17023SJohn Marino						 size_t __slen)
1619*e4b17023SJohn Marino	// As above, but one reference to __r is about to be
1620*e4b17023SJohn Marino	// destroyed.  Thus the pieces may be recycled if all
1621*e4b17023SJohn Marino	// relevant reference counts are 1.
1622*e4b17023SJohn Marino#ifdef __GC
1623*e4b17023SJohn Marino	// We can't really do anything since refcounts are unavailable.
1624*e4b17023SJohn Marino      { return _S_concat_char_iter(__r, __iter, __slen); }
1625*e4b17023SJohn Marino#else
1626*e4b17023SJohn Marino      ;
1627*e4b17023SJohn Marino#endif
1628*e4b17023SJohn Marino
1629*e4b17023SJohn Marino      static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
1630*e4b17023SJohn Marino      // General concatenation on _RopeRep.  _Result
1631*e4b17023SJohn Marino      // has refcount of 1.  Adjusts argument refcounts.
1632*e4b17023SJohn Marino
1633*e4b17023SJohn Marino   public:
1634*e4b17023SJohn Marino      void
1635*e4b17023SJohn Marino      apply_to_pieces(size_t __begin, size_t __end,
1636*e4b17023SJohn Marino		      _Rope_char_consumer<_CharT>& __c) const
1637*e4b17023SJohn Marino      { _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); }
1638*e4b17023SJohn Marino
1639*e4b17023SJohn Marino   protected:
1640*e4b17023SJohn Marino
1641*e4b17023SJohn Marino      static size_t
1642*e4b17023SJohn Marino      _S_rounded_up_size(size_t __n)
1643*e4b17023SJohn Marino      { return _RopeLeaf::_S_rounded_up_size(__n); }
1644*e4b17023SJohn Marino
1645*e4b17023SJohn Marino      static size_t
1646*e4b17023SJohn Marino      _S_allocated_capacity(size_t __n)
1647*e4b17023SJohn Marino      {
1648*e4b17023SJohn Marino	if (_S_is_basic_char_type((_CharT*)0))
1649*e4b17023SJohn Marino	  return _S_rounded_up_size(__n) - 1;
1650*e4b17023SJohn Marino	else
1651*e4b17023SJohn Marino	  return _S_rounded_up_size(__n);
1652*e4b17023SJohn Marino
1653*e4b17023SJohn Marino      }
1654*e4b17023SJohn Marino
1655*e4b17023SJohn Marino      // Allocate and construct a RopeLeaf using the supplied allocator
1656*e4b17023SJohn Marino      // Takes ownership of s instead of copying.
1657*e4b17023SJohn Marino      static _RopeLeaf*
1658*e4b17023SJohn Marino      _S_new_RopeLeaf(__GC_CONST _CharT *__s,
1659*e4b17023SJohn Marino		      size_t __size, allocator_type& __a)
1660*e4b17023SJohn Marino      {
1661*e4b17023SJohn Marino	_RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);
1662*e4b17023SJohn Marino	return new(__space) _RopeLeaf(__s, __size, __a);
1663*e4b17023SJohn Marino      }
1664*e4b17023SJohn Marino
1665*e4b17023SJohn Marino      static _RopeConcatenation*
1666*e4b17023SJohn Marino      _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,
1667*e4b17023SJohn Marino			       allocator_type& __a)
1668*e4b17023SJohn Marino      {
1669*e4b17023SJohn Marino	_RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);
1670*e4b17023SJohn Marino	return new(__space) _RopeConcatenation(__left, __right, __a);
1671*e4b17023SJohn Marino      }
1672*e4b17023SJohn Marino
1673*e4b17023SJohn Marino      static _RopeFunction*
1674*e4b17023SJohn Marino      _S_new_RopeFunction(char_producer<_CharT>* __f,
1675*e4b17023SJohn Marino			  size_t __size, bool __d, allocator_type& __a)
1676*e4b17023SJohn Marino      {
1677*e4b17023SJohn Marino	_RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);
1678*e4b17023SJohn Marino	return new(__space) _RopeFunction(__f, __size, __d, __a);
1679*e4b17023SJohn Marino      }
1680*e4b17023SJohn Marino
1681*e4b17023SJohn Marino      static _RopeSubstring*
1682*e4b17023SJohn Marino      _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,
1683*e4b17023SJohn Marino			   size_t __l, allocator_type& __a)
1684*e4b17023SJohn Marino      {
1685*e4b17023SJohn Marino	_RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);
1686*e4b17023SJohn Marino	return new(__space) _RopeSubstring(__b, __s, __l, __a);
1687*e4b17023SJohn Marino      }
1688*e4b17023SJohn Marino
1689*e4b17023SJohn Marino      static _RopeLeaf*
1690*e4b17023SJohn Marino      _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,
1691*e4b17023SJohn Marino					size_t __size, allocator_type& __a)
1692*e4b17023SJohn Marino#define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \
1693*e4b17023SJohn Marino                _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a)
1694*e4b17023SJohn Marino      {
1695*e4b17023SJohn Marino	if (0 == __size)
1696*e4b17023SJohn Marino	  return 0;
1697*e4b17023SJohn Marino	_CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
1698*e4b17023SJohn Marino
1699*e4b17023SJohn Marino	__uninitialized_copy_n_a(__s, __size, __buf, __a);
1700*e4b17023SJohn Marino	_S_cond_store_eos(__buf[__size]);
1701*e4b17023SJohn Marino	__try
1702*e4b17023SJohn Marino	  { return _S_new_RopeLeaf(__buf, __size, __a); }
1703*e4b17023SJohn Marino	__catch(...)
1704*e4b17023SJohn Marino	  {
1705*e4b17023SJohn Marino	    _RopeRep::__STL_FREE_STRING(__buf, __size, __a);
1706*e4b17023SJohn Marino	    __throw_exception_again;
1707*e4b17023SJohn Marino	  }
1708*e4b17023SJohn Marino      }
1709*e4b17023SJohn Marino
1710*e4b17023SJohn Marino      // Concatenation of nonempty strings.
1711*e4b17023SJohn Marino      // Always builds a concatenation node.
1712*e4b17023SJohn Marino      // Rebalances if the result is too deep.
1713*e4b17023SJohn Marino      // Result has refcount 1.
1714*e4b17023SJohn Marino      // Does not increment left and right ref counts even though
1715*e4b17023SJohn Marino      // they are referenced.
1716*e4b17023SJohn Marino      static _RopeRep*
1717*e4b17023SJohn Marino      _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
1718*e4b17023SJohn Marino
1719*e4b17023SJohn Marino      // Concatenation helper functions
1720*e4b17023SJohn Marino      static _RopeLeaf*
1721*e4b17023SJohn Marino      _S_leaf_concat_char_iter(_RopeLeaf* __r,
1722*e4b17023SJohn Marino			       const _CharT* __iter, size_t __slen);
1723*e4b17023SJohn Marino      // Concatenate by copying leaf.
1724*e4b17023SJohn Marino      // should take an arbitrary iterator
1725*e4b17023SJohn Marino      // result has refcount 1.
1726*e4b17023SJohn Marino#ifndef __GC
1727*e4b17023SJohn Marino      static _RopeLeaf*
1728*e4b17023SJohn Marino      _S_destr_leaf_concat_char_iter(_RopeLeaf* __r,
1729*e4b17023SJohn Marino				     const _CharT* __iter, size_t __slen);
1730*e4b17023SJohn Marino      // A version that potentially clobbers __r if __r->_M_ref_count == 1.
1731*e4b17023SJohn Marino#endif
1732*e4b17023SJohn Marino
1733*e4b17023SJohn Marino    private:
1734*e4b17023SJohn Marino
1735*e4b17023SJohn Marino      static size_t _S_char_ptr_len(const _CharT* __s);
1736*e4b17023SJohn Marino      // slightly generalized strlen
1737*e4b17023SJohn Marino
1738*e4b17023SJohn Marino      rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
1739*e4b17023SJohn Marino      : _Base(__t, __a) { }
1740*e4b17023SJohn Marino
1741*e4b17023SJohn Marino
1742*e4b17023SJohn Marino      // Copy __r to the _CharT buffer.
1743*e4b17023SJohn Marino      // Returns __buffer + __r->_M_size.
1744*e4b17023SJohn Marino      // Assumes that buffer is uninitialized.
1745*e4b17023SJohn Marino      static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);
1746*e4b17023SJohn Marino
1747*e4b17023SJohn Marino      // Again, with explicit starting position and length.
1748*e4b17023SJohn Marino      // Assumes that buffer is uninitialized.
1749*e4b17023SJohn Marino      static _CharT* _S_flatten(_RopeRep* __r,
1750*e4b17023SJohn Marino				size_t __start, size_t __len,
1751*e4b17023SJohn Marino				_CharT* __buffer);
1752*e4b17023SJohn Marino
1753*e4b17023SJohn Marino      static const unsigned long
1754*e4b17023SJohn Marino      _S_min_len[__detail::_S_max_rope_depth + 1];
1755*e4b17023SJohn Marino
1756*e4b17023SJohn Marino      static bool
1757*e4b17023SJohn Marino      _S_is_balanced(_RopeRep* __r)
1758*e4b17023SJohn Marino      { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
1759*e4b17023SJohn Marino
1760*e4b17023SJohn Marino      static bool
1761*e4b17023SJohn Marino      _S_is_almost_balanced(_RopeRep* __r)
1762*e4b17023SJohn Marino      { return (__r->_M_depth == 0
1763*e4b17023SJohn Marino		|| __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
1764*e4b17023SJohn Marino
1765*e4b17023SJohn Marino      static bool
1766*e4b17023SJohn Marino      _S_is_roughly_balanced(_RopeRep* __r)
1767*e4b17023SJohn Marino      { return (__r->_M_depth <= 1
1768*e4b17023SJohn Marino		|| __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
1769*e4b17023SJohn Marino
1770*e4b17023SJohn Marino      // Assumes the result is not empty.
1771*e4b17023SJohn Marino      static _RopeRep*
1772*e4b17023SJohn Marino      _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right)
1773*e4b17023SJohn Marino      {
1774*e4b17023SJohn Marino	_RopeRep* __result = _S_concat(__left, __right);
1775*e4b17023SJohn Marino	if (_S_is_balanced(__result))
1776*e4b17023SJohn Marino	  __result->_M_is_balanced = true;
1777*e4b17023SJohn Marino	return __result;
1778*e4b17023SJohn Marino      }
1779*e4b17023SJohn Marino
1780*e4b17023SJohn Marino      // The basic rebalancing operation.  Logically copies the
1781*e4b17023SJohn Marino      // rope.  The result has refcount of 1.  The client will
1782*e4b17023SJohn Marino      // usually decrement the reference count of __r.
1783*e4b17023SJohn Marino      // The result is within height 2 of balanced by the above
1784*e4b17023SJohn Marino      // definition.
1785*e4b17023SJohn Marino      static _RopeRep* _S_balance(_RopeRep* __r);
1786*e4b17023SJohn Marino
1787*e4b17023SJohn Marino      // Add all unbalanced subtrees to the forest of balanced trees.
1788*e4b17023SJohn Marino      // Used only by balance.
1789*e4b17023SJohn Marino      static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);
1790*e4b17023SJohn Marino
1791*e4b17023SJohn Marino      // Add __r to forest, assuming __r is already balanced.
1792*e4b17023SJohn Marino      static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
1793*e4b17023SJohn Marino
1794*e4b17023SJohn Marino      // Print to stdout, exposing structure
1795*e4b17023SJohn Marino      static void _S_dump(_RopeRep* __r, int __indent = 0);
1796*e4b17023SJohn Marino
1797*e4b17023SJohn Marino      // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.
1798*e4b17023SJohn Marino      static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);
1799*e4b17023SJohn Marino
1800*e4b17023SJohn Marino    public:
1801*e4b17023SJohn Marino      bool
1802*e4b17023SJohn Marino      empty() const
1803*e4b17023SJohn Marino      { return 0 == this->_M_tree_ptr; }
1804*e4b17023SJohn Marino
1805*e4b17023SJohn Marino      // Comparison member function.  This is public only for those
1806*e4b17023SJohn Marino      // clients that need a ternary comparison.  Others
1807*e4b17023SJohn Marino      // should use the comparison operators below.
1808*e4b17023SJohn Marino      int
1809*e4b17023SJohn Marino      compare(const rope& __y) const
1810*e4b17023SJohn Marino      { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }
1811*e4b17023SJohn Marino
1812*e4b17023SJohn Marino      rope(const _CharT* __s, const allocator_type& __a = allocator_type())
1813*e4b17023SJohn Marino      : _Base(__a)
1814*e4b17023SJohn Marino      {
1815*e4b17023SJohn Marino	this->_M_tree_ptr =
1816*e4b17023SJohn Marino	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
1817*e4b17023SJohn Marino					   _M_get_allocator());
1818*e4b17023SJohn Marino      }
1819*e4b17023SJohn Marino
1820*e4b17023SJohn Marino      rope(const _CharT* __s, size_t __len,
1821*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type())
1822*e4b17023SJohn Marino      : _Base(__a)
1823*e4b17023SJohn Marino      {
1824*e4b17023SJohn Marino	this->_M_tree_ptr =
1825*e4b17023SJohn Marino	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator());
1826*e4b17023SJohn Marino      }
1827*e4b17023SJohn Marino
1828*e4b17023SJohn Marino      // Should perhaps be templatized with respect to the iterator type
1829*e4b17023SJohn Marino      // and use Sequence_buffer.  (It should perhaps use sequence_buffer
1830*e4b17023SJohn Marino      // even now.)
1831*e4b17023SJohn Marino      rope(const _CharT* __s, const _CharT* __e,
1832*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type())
1833*e4b17023SJohn Marino      : _Base(__a)
1834*e4b17023SJohn Marino      {
1835*e4b17023SJohn Marino	this->_M_tree_ptr =
1836*e4b17023SJohn Marino	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator());
1837*e4b17023SJohn Marino      }
1838*e4b17023SJohn Marino
1839*e4b17023SJohn Marino      rope(const const_iterator& __s, const const_iterator& __e,
1840*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type())
1841*e4b17023SJohn Marino      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1842*e4b17023SJohn Marino			   __e._M_current_pos), __a)
1843*e4b17023SJohn Marino      { }
1844*e4b17023SJohn Marino
1845*e4b17023SJohn Marino      rope(const iterator& __s, const iterator& __e,
1846*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type())
1847*e4b17023SJohn Marino      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1848*e4b17023SJohn Marino			   __e._M_current_pos), __a)
1849*e4b17023SJohn Marino      { }
1850*e4b17023SJohn Marino
1851*e4b17023SJohn Marino      rope(_CharT __c, const allocator_type& __a = allocator_type())
1852*e4b17023SJohn Marino      : _Base(__a)
1853*e4b17023SJohn Marino      {
1854*e4b17023SJohn Marino	_CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));
1855*e4b17023SJohn Marino
1856*e4b17023SJohn Marino	_M_get_allocator().construct(__buf, __c);
1857*e4b17023SJohn Marino	__try
1858*e4b17023SJohn Marino	  {
1859*e4b17023SJohn Marino	    this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1,
1860*e4b17023SJohn Marino						_M_get_allocator());
1861*e4b17023SJohn Marino	  }
1862*e4b17023SJohn Marino	__catch(...)
1863*e4b17023SJohn Marino	  {
1864*e4b17023SJohn Marino	    _RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator());
1865*e4b17023SJohn Marino	    __throw_exception_again;
1866*e4b17023SJohn Marino	  }
1867*e4b17023SJohn Marino      }
1868*e4b17023SJohn Marino
1869*e4b17023SJohn Marino      rope(size_t __n, _CharT __c,
1870*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type());
1871*e4b17023SJohn Marino
1872*e4b17023SJohn Marino      rope(const allocator_type& __a = allocator_type())
1873*e4b17023SJohn Marino      : _Base(0, __a) { }
1874*e4b17023SJohn Marino
1875*e4b17023SJohn Marino      // Construct a rope from a function that can compute its members
1876*e4b17023SJohn Marino      rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn,
1877*e4b17023SJohn Marino	   const allocator_type& __a = allocator_type())
1878*e4b17023SJohn Marino      : _Base(__a)
1879*e4b17023SJohn Marino      {
1880*e4b17023SJohn Marino	this->_M_tree_ptr = (0 == __len) ?
1881*e4b17023SJohn Marino	  0 : _S_new_RopeFunction(__fn, __len, __delete_fn, __a);
1882*e4b17023SJohn Marino      }
1883*e4b17023SJohn Marino
1884*e4b17023SJohn Marino      rope(const rope& __x, const allocator_type& __a = allocator_type())
1885*e4b17023SJohn Marino      : _Base(__x._M_tree_ptr, __a)
1886*e4b17023SJohn Marino      { _S_ref(this->_M_tree_ptr); }
1887*e4b17023SJohn Marino
1888*e4b17023SJohn Marino      ~rope() throw()
1889*e4b17023SJohn Marino      { _S_unref(this->_M_tree_ptr); }
1890*e4b17023SJohn Marino
1891*e4b17023SJohn Marino      rope&
1892*e4b17023SJohn Marino      operator=(const rope& __x)
1893*e4b17023SJohn Marino      {
1894*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1895*e4b17023SJohn Marino	this->_M_tree_ptr = __x._M_tree_ptr;
1896*e4b17023SJohn Marino	_S_ref(this->_M_tree_ptr);
1897*e4b17023SJohn Marino	_S_unref(__old);
1898*e4b17023SJohn Marino	return *this;
1899*e4b17023SJohn Marino      }
1900*e4b17023SJohn Marino
1901*e4b17023SJohn Marino      void
1902*e4b17023SJohn Marino      clear()
1903*e4b17023SJohn Marino      {
1904*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
1905*e4b17023SJohn Marino	this->_M_tree_ptr = 0;
1906*e4b17023SJohn Marino      }
1907*e4b17023SJohn Marino
1908*e4b17023SJohn Marino      void
1909*e4b17023SJohn Marino      push_back(_CharT __x)
1910*e4b17023SJohn Marino      {
1911*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1912*e4b17023SJohn Marino	this->_M_tree_ptr
1913*e4b17023SJohn Marino	  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);
1914*e4b17023SJohn Marino	_S_unref(__old);
1915*e4b17023SJohn Marino      }
1916*e4b17023SJohn Marino
1917*e4b17023SJohn Marino      void
1918*e4b17023SJohn Marino      pop_back()
1919*e4b17023SJohn Marino      {
1920*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1921*e4b17023SJohn Marino	this->_M_tree_ptr = _S_substring(this->_M_tree_ptr,
1922*e4b17023SJohn Marino					 0, this->_M_tree_ptr->_M_size - 1);
1923*e4b17023SJohn Marino	_S_unref(__old);
1924*e4b17023SJohn Marino      }
1925*e4b17023SJohn Marino
1926*e4b17023SJohn Marino      _CharT
1927*e4b17023SJohn Marino      back() const
1928*e4b17023SJohn Marino      { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }
1929*e4b17023SJohn Marino
1930*e4b17023SJohn Marino      void
1931*e4b17023SJohn Marino      push_front(_CharT __x)
1932*e4b17023SJohn Marino      {
1933*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1934*e4b17023SJohn Marino	_RopeRep* __left =
1935*e4b17023SJohn Marino	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator());
1936*e4b17023SJohn Marino	__try
1937*e4b17023SJohn Marino	  {
1938*e4b17023SJohn Marino	    this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
1939*e4b17023SJohn Marino	    _S_unref(__old);
1940*e4b17023SJohn Marino	    _S_unref(__left);
1941*e4b17023SJohn Marino	  }
1942*e4b17023SJohn Marino	__catch(...)
1943*e4b17023SJohn Marino	  {
1944*e4b17023SJohn Marino	    _S_unref(__left);
1945*e4b17023SJohn Marino	    __throw_exception_again;
1946*e4b17023SJohn Marino	  }
1947*e4b17023SJohn Marino      }
1948*e4b17023SJohn Marino
1949*e4b17023SJohn Marino      void
1950*e4b17023SJohn Marino      pop_front()
1951*e4b17023SJohn Marino      {
1952*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1953*e4b17023SJohn Marino	this->_M_tree_ptr
1954*e4b17023SJohn Marino	  = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
1955*e4b17023SJohn Marino	_S_unref(__old);
1956*e4b17023SJohn Marino      }
1957*e4b17023SJohn Marino
1958*e4b17023SJohn Marino      _CharT
1959*e4b17023SJohn Marino      front() const
1960*e4b17023SJohn Marino      { return _S_fetch(this->_M_tree_ptr, 0); }
1961*e4b17023SJohn Marino
1962*e4b17023SJohn Marino      void
1963*e4b17023SJohn Marino      balance()
1964*e4b17023SJohn Marino      {
1965*e4b17023SJohn Marino	_RopeRep* __old = this->_M_tree_ptr;
1966*e4b17023SJohn Marino	this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
1967*e4b17023SJohn Marino	_S_unref(__old);
1968*e4b17023SJohn Marino      }
1969*e4b17023SJohn Marino
1970*e4b17023SJohn Marino      void
1971*e4b17023SJohn Marino      copy(_CharT* __buffer) const
1972*e4b17023SJohn Marino      {
1973*e4b17023SJohn Marino	_Destroy_const(__buffer, __buffer + size(), _M_get_allocator());
1974*e4b17023SJohn Marino	_S_flatten(this->_M_tree_ptr, __buffer);
1975*e4b17023SJohn Marino      }
1976*e4b17023SJohn Marino
1977*e4b17023SJohn Marino      // This is the copy function from the standard, but
1978*e4b17023SJohn Marino      // with the arguments reordered to make it consistent with the
1979*e4b17023SJohn Marino      // rest of the interface.
1980*e4b17023SJohn Marino      // Note that this guaranteed not to compile if the draft standard
1981*e4b17023SJohn Marino      // order is assumed.
1982*e4b17023SJohn Marino      size_type
1983*e4b17023SJohn Marino      copy(size_type __pos, size_type __n, _CharT* __buffer) const
1984*e4b17023SJohn Marino      {
1985*e4b17023SJohn Marino	size_t __size = size();
1986*e4b17023SJohn Marino	size_t __len = (__pos + __n > __size? __size - __pos : __n);
1987*e4b17023SJohn Marino
1988*e4b17023SJohn Marino	_Destroy_const(__buffer, __buffer + __len, _M_get_allocator());
1989*e4b17023SJohn Marino	_S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);
1990*e4b17023SJohn Marino	return __len;
1991*e4b17023SJohn Marino      }
1992*e4b17023SJohn Marino
1993*e4b17023SJohn Marino      // Print to stdout, exposing structure.  May be useful for
1994*e4b17023SJohn Marino      // performance debugging.
1995*e4b17023SJohn Marino      void
1996*e4b17023SJohn Marino      dump()
1997*e4b17023SJohn Marino      { _S_dump(this->_M_tree_ptr); }
1998*e4b17023SJohn Marino
1999*e4b17023SJohn Marino      // Convert to 0 terminated string in new allocated memory.
2000*e4b17023SJohn Marino      // Embedded 0s in the input do not terminate the copy.
2001*e4b17023SJohn Marino      const _CharT* c_str() const;
2002*e4b17023SJohn Marino
2003*e4b17023SJohn Marino      // As above, but also use the flattened representation as
2004*e4b17023SJohn Marino      // the new rope representation.
2005*e4b17023SJohn Marino      const _CharT* replace_with_c_str();
2006*e4b17023SJohn Marino
2007*e4b17023SJohn Marino      // Reclaim memory for the c_str generated flattened string.
2008*e4b17023SJohn Marino      // Intentionally undocumented, since it's hard to say when this
2009*e4b17023SJohn Marino      // is safe for multiple threads.
2010*e4b17023SJohn Marino      void
2011*e4b17023SJohn Marino      delete_c_str ()
2012*e4b17023SJohn Marino      {
2013*e4b17023SJohn Marino	if (0 == this->_M_tree_ptr)
2014*e4b17023SJohn Marino	  return;
2015*e4b17023SJohn Marino	if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag &&
2016*e4b17023SJohn Marino	    ((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==
2017*e4b17023SJohn Marino	    this->_M_tree_ptr->_M_c_string)
2018*e4b17023SJohn Marino	  {
2019*e4b17023SJohn Marino	    // Representation shared
2020*e4b17023SJohn Marino	    return;
2021*e4b17023SJohn Marino	  }
2022*e4b17023SJohn Marino#ifndef __GC
2023*e4b17023SJohn Marino	this->_M_tree_ptr->_M_free_c_string();
2024*e4b17023SJohn Marino#endif
2025*e4b17023SJohn Marino	this->_M_tree_ptr->_M_c_string = 0;
2026*e4b17023SJohn Marino      }
2027*e4b17023SJohn Marino
2028*e4b17023SJohn Marino      _CharT
2029*e4b17023SJohn Marino      operator[] (size_type __pos) const
2030*e4b17023SJohn Marino      { return _S_fetch(this->_M_tree_ptr, __pos); }
2031*e4b17023SJohn Marino
2032*e4b17023SJohn Marino      _CharT
2033*e4b17023SJohn Marino      at(size_type __pos) const
2034*e4b17023SJohn Marino      {
2035*e4b17023SJohn Marino	// if (__pos >= size()) throw out_of_range;  // XXX
2036*e4b17023SJohn Marino	return (*this)[__pos];
2037*e4b17023SJohn Marino      }
2038*e4b17023SJohn Marino
2039*e4b17023SJohn Marino      const_iterator
2040*e4b17023SJohn Marino      begin() const
2041*e4b17023SJohn Marino      { return(const_iterator(this->_M_tree_ptr, 0)); }
2042*e4b17023SJohn Marino
2043*e4b17023SJohn Marino      // An easy way to get a const iterator from a non-const container.
2044*e4b17023SJohn Marino      const_iterator
2045*e4b17023SJohn Marino      const_begin() const
2046*e4b17023SJohn Marino      { return(const_iterator(this->_M_tree_ptr, 0)); }
2047*e4b17023SJohn Marino
2048*e4b17023SJohn Marino      const_iterator
2049*e4b17023SJohn Marino      end() const
2050*e4b17023SJohn Marino      { return(const_iterator(this->_M_tree_ptr, size())); }
2051*e4b17023SJohn Marino
2052*e4b17023SJohn Marino      const_iterator
2053*e4b17023SJohn Marino      const_end() const
2054*e4b17023SJohn Marino      { return(const_iterator(this->_M_tree_ptr, size())); }
2055*e4b17023SJohn Marino
2056*e4b17023SJohn Marino      size_type
2057*e4b17023SJohn Marino      size() const
2058*e4b17023SJohn Marino      {	return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }
2059*e4b17023SJohn Marino
2060*e4b17023SJohn Marino      size_type
2061*e4b17023SJohn Marino      length() const
2062*e4b17023SJohn Marino      {	return size(); }
2063*e4b17023SJohn Marino
2064*e4b17023SJohn Marino      size_type
2065*e4b17023SJohn Marino      max_size() const
2066*e4b17023SJohn Marino      {
2067*e4b17023SJohn Marino	return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1;
2068*e4b17023SJohn Marino	//  Guarantees that the result can be sufficiently
2069*e4b17023SJohn Marino	//  balanced.  Longer ropes will probably still work,
2070*e4b17023SJohn Marino	//  but it's harder to make guarantees.
2071*e4b17023SJohn Marino      }
2072*e4b17023SJohn Marino
2073*e4b17023SJohn Marino      typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
2074*e4b17023SJohn Marino
2075*e4b17023SJohn Marino      const_reverse_iterator
2076*e4b17023SJohn Marino      rbegin() const
2077*e4b17023SJohn Marino      { return const_reverse_iterator(end()); }
2078*e4b17023SJohn Marino
2079*e4b17023SJohn Marino      const_reverse_iterator
2080*e4b17023SJohn Marino      const_rbegin() const
2081*e4b17023SJohn Marino      {	return const_reverse_iterator(end()); }
2082*e4b17023SJohn Marino
2083*e4b17023SJohn Marino      const_reverse_iterator
2084*e4b17023SJohn Marino      rend() const
2085*e4b17023SJohn Marino      { return const_reverse_iterator(begin()); }
2086*e4b17023SJohn Marino
2087*e4b17023SJohn Marino      const_reverse_iterator
2088*e4b17023SJohn Marino      const_rend() const
2089*e4b17023SJohn Marino      {	return const_reverse_iterator(begin()); }
2090*e4b17023SJohn Marino
2091*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
2092*e4b17023SJohn Marino        friend rope<_CharT2, _Alloc2>
2093*e4b17023SJohn Marino        operator+(const rope<_CharT2, _Alloc2>& __left,
2094*e4b17023SJohn Marino		  const rope<_CharT2, _Alloc2>& __right);
2095*e4b17023SJohn Marino
2096*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
2097*e4b17023SJohn Marino        friend rope<_CharT2, _Alloc2>
2098*e4b17023SJohn Marino        operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);
2099*e4b17023SJohn Marino
2100*e4b17023SJohn Marino      template<class _CharT2, class _Alloc2>
2101*e4b17023SJohn Marino        friend rope<_CharT2, _Alloc2>
2102*e4b17023SJohn Marino        operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);
2103*e4b17023SJohn Marino
2104*e4b17023SJohn Marino      // The symmetric cases are intentionally omitted, since they're
2105*e4b17023SJohn Marino      // presumed to be less common, and we don't handle them as well.
2106*e4b17023SJohn Marino
2107*e4b17023SJohn Marino      // The following should really be templatized.  The first
2108*e4b17023SJohn Marino      // argument should be an input iterator or forward iterator with
2109*e4b17023SJohn Marino      // value_type _CharT.
2110*e4b17023SJohn Marino      rope&
2111*e4b17023SJohn Marino      append(const _CharT* __iter, size_t __n)
2112*e4b17023SJohn Marino      {
2113*e4b17023SJohn Marino	_RopeRep* __result =
2114*e4b17023SJohn Marino	  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n);
2115*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2116*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2117*e4b17023SJohn Marino	return *this;
2118*e4b17023SJohn Marino      }
2119*e4b17023SJohn Marino
2120*e4b17023SJohn Marino      rope&
2121*e4b17023SJohn Marino      append(const _CharT* __c_string)
2122*e4b17023SJohn Marino      {
2123*e4b17023SJohn Marino	size_t __len = _S_char_ptr_len(__c_string);
2124*e4b17023SJohn Marino	append(__c_string, __len);
2125*e4b17023SJohn Marino	return(*this);
2126*e4b17023SJohn Marino      }
2127*e4b17023SJohn Marino
2128*e4b17023SJohn Marino      rope&
2129*e4b17023SJohn Marino      append(const _CharT* __s, const _CharT* __e)
2130*e4b17023SJohn Marino      {
2131*e4b17023SJohn Marino	_RopeRep* __result =
2132*e4b17023SJohn Marino	  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s);
2133*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2134*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2135*e4b17023SJohn Marino	return *this;
2136*e4b17023SJohn Marino      }
2137*e4b17023SJohn Marino
2138*e4b17023SJohn Marino      rope&
2139*e4b17023SJohn Marino      append(const_iterator __s, const_iterator __e)
2140*e4b17023SJohn Marino      {
2141*e4b17023SJohn Marino	_Self_destruct_ptr __appendee(_S_substring(__s._M_root,
2142*e4b17023SJohn Marino						   __s._M_current_pos,
2143*e4b17023SJohn Marino						   __e._M_current_pos));
2144*e4b17023SJohn Marino	_RopeRep* __result = _S_concat(this->_M_tree_ptr,
2145*e4b17023SJohn Marino				       (_RopeRep*)__appendee);
2146*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2147*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2148*e4b17023SJohn Marino	return *this;
2149*e4b17023SJohn Marino      }
2150*e4b17023SJohn Marino
2151*e4b17023SJohn Marino      rope&
2152*e4b17023SJohn Marino      append(_CharT __c)
2153*e4b17023SJohn Marino      {
2154*e4b17023SJohn Marino	_RopeRep* __result =
2155*e4b17023SJohn Marino	  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1);
2156*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2157*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2158*e4b17023SJohn Marino	return *this;
2159*e4b17023SJohn Marino      }
2160*e4b17023SJohn Marino
2161*e4b17023SJohn Marino      rope&
2162*e4b17023SJohn Marino      append()
2163*e4b17023SJohn Marino      { return append(_CharT()); }  // XXX why?
2164*e4b17023SJohn Marino
2165*e4b17023SJohn Marino      rope&
2166*e4b17023SJohn Marino      append(const rope& __y)
2167*e4b17023SJohn Marino      {
2168*e4b17023SJohn Marino	_RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr);
2169*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2170*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2171*e4b17023SJohn Marino	return *this;
2172*e4b17023SJohn Marino      }
2173*e4b17023SJohn Marino
2174*e4b17023SJohn Marino      rope&
2175*e4b17023SJohn Marino      append(size_t __n, _CharT __c)
2176*e4b17023SJohn Marino      {
2177*e4b17023SJohn Marino	rope<_CharT,_Alloc> __last(__n, __c);
2178*e4b17023SJohn Marino	return append(__last);
2179*e4b17023SJohn Marino      }
2180*e4b17023SJohn Marino
2181*e4b17023SJohn Marino      void
2182*e4b17023SJohn Marino      swap(rope& __b)
2183*e4b17023SJohn Marino      {
2184*e4b17023SJohn Marino	_RopeRep* __tmp = this->_M_tree_ptr;
2185*e4b17023SJohn Marino	this->_M_tree_ptr = __b._M_tree_ptr;
2186*e4b17023SJohn Marino	__b._M_tree_ptr = __tmp;
2187*e4b17023SJohn Marino      }
2188*e4b17023SJohn Marino
2189*e4b17023SJohn Marino    protected:
2190*e4b17023SJohn Marino      // Result is included in refcount.
2191*e4b17023SJohn Marino      static _RopeRep*
2192*e4b17023SJohn Marino      replace(_RopeRep* __old, size_t __pos1,
2193*e4b17023SJohn Marino	      size_t __pos2, _RopeRep* __r)
2194*e4b17023SJohn Marino      {
2195*e4b17023SJohn Marino	if (0 == __old)
2196*e4b17023SJohn Marino	  {
2197*e4b17023SJohn Marino	    _S_ref(__r);
2198*e4b17023SJohn Marino	    return __r;
2199*e4b17023SJohn Marino	  }
2200*e4b17023SJohn Marino	_Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));
2201*e4b17023SJohn Marino	_Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));
2202*e4b17023SJohn Marino	_RopeRep* __result;
2203*e4b17023SJohn Marino
2204*e4b17023SJohn Marino	if (0 == __r)
2205*e4b17023SJohn Marino	  __result = _S_concat(__left, __right);
2206*e4b17023SJohn Marino	else
2207*e4b17023SJohn Marino	  {
2208*e4b17023SJohn Marino	    _Self_destruct_ptr __left_result(_S_concat(__left, __r));
2209*e4b17023SJohn Marino	    __result = _S_concat(__left_result, __right);
2210*e4b17023SJohn Marino	  }
2211*e4b17023SJohn Marino	return __result;
2212*e4b17023SJohn Marino      }
2213*e4b17023SJohn Marino
2214*e4b17023SJohn Marino    public:
2215*e4b17023SJohn Marino      void
2216*e4b17023SJohn Marino      insert(size_t __p, const rope& __r)
2217*e4b17023SJohn Marino      {
2218*e4b17023SJohn Marino	_RopeRep* __result =
2219*e4b17023SJohn Marino	  replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr);
2220*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2221*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2222*e4b17023SJohn Marino      }
2223*e4b17023SJohn Marino
2224*e4b17023SJohn Marino      void
2225*e4b17023SJohn Marino      insert(size_t __p, size_t __n, _CharT __c)
2226*e4b17023SJohn Marino      {
2227*e4b17023SJohn Marino	rope<_CharT,_Alloc> __r(__n,__c);
2228*e4b17023SJohn Marino	insert(__p, __r);
2229*e4b17023SJohn Marino      }
2230*e4b17023SJohn Marino
2231*e4b17023SJohn Marino      void
2232*e4b17023SJohn Marino      insert(size_t __p, const _CharT* __i, size_t __n)
2233*e4b17023SJohn Marino      {
2234*e4b17023SJohn Marino	_Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
2235*e4b17023SJohn Marino	_Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
2236*e4b17023SJohn Marino						__p, size()));
2237*e4b17023SJohn Marino	_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n));
2238*e4b17023SJohn Marino	// _S_ destr_concat_char_iter should be safe here.
2239*e4b17023SJohn Marino	// But as it stands it's probably not a win, since __left
2240*e4b17023SJohn Marino	// is likely to have additional references.
2241*e4b17023SJohn Marino	_RopeRep* __result = _S_concat(__left_result, __right);
2242*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2243*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2244*e4b17023SJohn Marino      }
2245*e4b17023SJohn Marino
2246*e4b17023SJohn Marino      void
2247*e4b17023SJohn Marino      insert(size_t __p, const _CharT* __c_string)
2248*e4b17023SJohn Marino      {	insert(__p, __c_string, _S_char_ptr_len(__c_string)); }
2249*e4b17023SJohn Marino
2250*e4b17023SJohn Marino      void
2251*e4b17023SJohn Marino      insert(size_t __p, _CharT __c)
2252*e4b17023SJohn Marino      { insert(__p, &__c, 1); }
2253*e4b17023SJohn Marino
2254*e4b17023SJohn Marino      void
2255*e4b17023SJohn Marino      insert(size_t __p)
2256*e4b17023SJohn Marino      {
2257*e4b17023SJohn Marino	_CharT __c = _CharT();
2258*e4b17023SJohn Marino	insert(__p, &__c, 1);
2259*e4b17023SJohn Marino      }
2260*e4b17023SJohn Marino
2261*e4b17023SJohn Marino      void
2262*e4b17023SJohn Marino      insert(size_t __p, const _CharT* __i, const _CharT* __j)
2263*e4b17023SJohn Marino      {
2264*e4b17023SJohn Marino	rope __r(__i, __j);
2265*e4b17023SJohn Marino	insert(__p, __r);
2266*e4b17023SJohn Marino      }
2267*e4b17023SJohn Marino
2268*e4b17023SJohn Marino      void
2269*e4b17023SJohn Marino      insert(size_t __p, const const_iterator& __i,
2270*e4b17023SJohn Marino	     const const_iterator& __j)
2271*e4b17023SJohn Marino      {
2272*e4b17023SJohn Marino	rope __r(__i, __j);
2273*e4b17023SJohn Marino	insert(__p, __r);
2274*e4b17023SJohn Marino      }
2275*e4b17023SJohn Marino
2276*e4b17023SJohn Marino      void
2277*e4b17023SJohn Marino      insert(size_t __p, const iterator& __i,
2278*e4b17023SJohn Marino	     const iterator& __j)
2279*e4b17023SJohn Marino      {
2280*e4b17023SJohn Marino	rope __r(__i, __j);
2281*e4b17023SJohn Marino	insert(__p, __r);
2282*e4b17023SJohn Marino      }
2283*e4b17023SJohn Marino
2284*e4b17023SJohn Marino      // (position, length) versions of replace operations:
2285*e4b17023SJohn Marino
2286*e4b17023SJohn Marino      void
2287*e4b17023SJohn Marino      replace(size_t __p, size_t __n, const rope& __r)
2288*e4b17023SJohn Marino      {
2289*e4b17023SJohn Marino	_RopeRep* __result =
2290*e4b17023SJohn Marino	  replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);
2291*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2292*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2293*e4b17023SJohn Marino      }
2294*e4b17023SJohn Marino
2295*e4b17023SJohn Marino      void
2296*e4b17023SJohn Marino      replace(size_t __p, size_t __n,
2297*e4b17023SJohn Marino	      const _CharT* __i, size_t __i_len)
2298*e4b17023SJohn Marino      {
2299*e4b17023SJohn Marino	rope __r(__i, __i_len);
2300*e4b17023SJohn Marino	replace(__p, __n, __r);
2301*e4b17023SJohn Marino      }
2302*e4b17023SJohn Marino
2303*e4b17023SJohn Marino      void
2304*e4b17023SJohn Marino      replace(size_t __p, size_t __n, _CharT __c)
2305*e4b17023SJohn Marino      {
2306*e4b17023SJohn Marino	rope __r(__c);
2307*e4b17023SJohn Marino	replace(__p, __n, __r);
2308*e4b17023SJohn Marino      }
2309*e4b17023SJohn Marino
2310*e4b17023SJohn Marino      void
2311*e4b17023SJohn Marino      replace(size_t __p, size_t __n, const _CharT* __c_string)
2312*e4b17023SJohn Marino      {
2313*e4b17023SJohn Marino	rope __r(__c_string);
2314*e4b17023SJohn Marino	replace(__p, __n, __r);
2315*e4b17023SJohn Marino      }
2316*e4b17023SJohn Marino
2317*e4b17023SJohn Marino      void
2318*e4b17023SJohn Marino      replace(size_t __p, size_t __n,
2319*e4b17023SJohn Marino	      const _CharT* __i, const _CharT* __j)
2320*e4b17023SJohn Marino      {
2321*e4b17023SJohn Marino	rope __r(__i, __j);
2322*e4b17023SJohn Marino	replace(__p, __n, __r);
2323*e4b17023SJohn Marino      }
2324*e4b17023SJohn Marino
2325*e4b17023SJohn Marino      void
2326*e4b17023SJohn Marino      replace(size_t __p, size_t __n,
2327*e4b17023SJohn Marino	      const const_iterator& __i, const const_iterator& __j)
2328*e4b17023SJohn Marino      {
2329*e4b17023SJohn Marino	rope __r(__i, __j);
2330*e4b17023SJohn Marino	replace(__p, __n, __r);
2331*e4b17023SJohn Marino      }
2332*e4b17023SJohn Marino
2333*e4b17023SJohn Marino      void
2334*e4b17023SJohn Marino      replace(size_t __p, size_t __n,
2335*e4b17023SJohn Marino	      const iterator& __i, const iterator& __j)
2336*e4b17023SJohn Marino      {
2337*e4b17023SJohn Marino	rope __r(__i, __j);
2338*e4b17023SJohn Marino	replace(__p, __n, __r);
2339*e4b17023SJohn Marino      }
2340*e4b17023SJohn Marino
2341*e4b17023SJohn Marino      // Single character variants:
2342*e4b17023SJohn Marino      void
2343*e4b17023SJohn Marino      replace(size_t __p, _CharT __c)
2344*e4b17023SJohn Marino      {
2345*e4b17023SJohn Marino	iterator __i(this, __p);
2346*e4b17023SJohn Marino	*__i = __c;
2347*e4b17023SJohn Marino      }
2348*e4b17023SJohn Marino
2349*e4b17023SJohn Marino      void
2350*e4b17023SJohn Marino      replace(size_t __p, const rope& __r)
2351*e4b17023SJohn Marino      { replace(__p, 1, __r); }
2352*e4b17023SJohn Marino
2353*e4b17023SJohn Marino      void
2354*e4b17023SJohn Marino      replace(size_t __p, const _CharT* __i, size_t __i_len)
2355*e4b17023SJohn Marino      { replace(__p, 1, __i, __i_len); }
2356*e4b17023SJohn Marino
2357*e4b17023SJohn Marino      void
2358*e4b17023SJohn Marino      replace(size_t __p, const _CharT* __c_string)
2359*e4b17023SJohn Marino      {	replace(__p, 1, __c_string); }
2360*e4b17023SJohn Marino
2361*e4b17023SJohn Marino      void
2362*e4b17023SJohn Marino      replace(size_t __p, const _CharT* __i, const _CharT* __j)
2363*e4b17023SJohn Marino      {	replace(__p, 1, __i, __j); }
2364*e4b17023SJohn Marino
2365*e4b17023SJohn Marino      void
2366*e4b17023SJohn Marino      replace(size_t __p, const const_iterator& __i,
2367*e4b17023SJohn Marino	      const const_iterator& __j)
2368*e4b17023SJohn Marino      { replace(__p, 1, __i, __j); }
2369*e4b17023SJohn Marino
2370*e4b17023SJohn Marino      void
2371*e4b17023SJohn Marino      replace(size_t __p, const iterator& __i,
2372*e4b17023SJohn Marino	      const iterator& __j)
2373*e4b17023SJohn Marino      { replace(__p, 1, __i, __j); }
2374*e4b17023SJohn Marino
2375*e4b17023SJohn Marino      // Erase, (position, size) variant.
2376*e4b17023SJohn Marino      void
2377*e4b17023SJohn Marino      erase(size_t __p, size_t __n)
2378*e4b17023SJohn Marino      {
2379*e4b17023SJohn Marino	_RopeRep* __result = replace(this->_M_tree_ptr, __p,
2380*e4b17023SJohn Marino				     __p + __n, 0);
2381*e4b17023SJohn Marino	_S_unref(this->_M_tree_ptr);
2382*e4b17023SJohn Marino	this->_M_tree_ptr = __result;
2383*e4b17023SJohn Marino      }
2384*e4b17023SJohn Marino
2385*e4b17023SJohn Marino      // Erase, single character
2386*e4b17023SJohn Marino      void
2387*e4b17023SJohn Marino      erase(size_t __p)
2388*e4b17023SJohn Marino      { erase(__p, __p + 1); }
2389*e4b17023SJohn Marino
2390*e4b17023SJohn Marino      // Insert, iterator variants.
2391*e4b17023SJohn Marino      iterator
2392*e4b17023SJohn Marino      insert(const iterator& __p, const rope& __r)
2393*e4b17023SJohn Marino      {
2394*e4b17023SJohn Marino	insert(__p.index(), __r);
2395*e4b17023SJohn Marino	return __p;
2396*e4b17023SJohn Marino      }
2397*e4b17023SJohn Marino
2398*e4b17023SJohn Marino      iterator
2399*e4b17023SJohn Marino      insert(const iterator& __p, size_t __n, _CharT __c)
2400*e4b17023SJohn Marino      {
2401*e4b17023SJohn Marino	insert(__p.index(), __n, __c);
2402*e4b17023SJohn Marino	return __p;
2403*e4b17023SJohn Marino      }
2404*e4b17023SJohn Marino
2405*e4b17023SJohn Marino      iterator insert(const iterator& __p, _CharT __c)
2406*e4b17023SJohn Marino      {
2407*e4b17023SJohn Marino	insert(__p.index(), __c);
2408*e4b17023SJohn Marino	return __p;
2409*e4b17023SJohn Marino      }
2410*e4b17023SJohn Marino
2411*e4b17023SJohn Marino      iterator
2412*e4b17023SJohn Marino      insert(const iterator& __p )
2413*e4b17023SJohn Marino      {
2414*e4b17023SJohn Marino	insert(__p.index());
2415*e4b17023SJohn Marino	return __p;
2416*e4b17023SJohn Marino      }
2417*e4b17023SJohn Marino
2418*e4b17023SJohn Marino      iterator
2419*e4b17023SJohn Marino      insert(const iterator& __p, const _CharT* c_string)
2420*e4b17023SJohn Marino      {
2421*e4b17023SJohn Marino	insert(__p.index(), c_string);
2422*e4b17023SJohn Marino	return __p;
2423*e4b17023SJohn Marino      }
2424*e4b17023SJohn Marino
2425*e4b17023SJohn Marino      iterator
2426*e4b17023SJohn Marino      insert(const iterator& __p, const _CharT* __i, size_t __n)
2427*e4b17023SJohn Marino      {
2428*e4b17023SJohn Marino	insert(__p.index(), __i, __n);
2429*e4b17023SJohn Marino	return __p;
2430*e4b17023SJohn Marino      }
2431*e4b17023SJohn Marino
2432*e4b17023SJohn Marino      iterator
2433*e4b17023SJohn Marino      insert(const iterator& __p, const _CharT* __i,
2434*e4b17023SJohn Marino	     const _CharT* __j)
2435*e4b17023SJohn Marino      {
2436*e4b17023SJohn Marino	insert(__p.index(), __i, __j);
2437*e4b17023SJohn Marino	return __p;
2438*e4b17023SJohn Marino      }
2439*e4b17023SJohn Marino
2440*e4b17023SJohn Marino      iterator
2441*e4b17023SJohn Marino      insert(const iterator& __p,
2442*e4b17023SJohn Marino	     const const_iterator& __i, const const_iterator& __j)
2443*e4b17023SJohn Marino      {
2444*e4b17023SJohn Marino	insert(__p.index(), __i, __j);
2445*e4b17023SJohn Marino	return __p;
2446*e4b17023SJohn Marino      }
2447*e4b17023SJohn Marino
2448*e4b17023SJohn Marino      iterator
2449*e4b17023SJohn Marino      insert(const iterator& __p,
2450*e4b17023SJohn Marino	     const iterator& __i, const iterator& __j)
2451*e4b17023SJohn Marino      {
2452*e4b17023SJohn Marino	insert(__p.index(), __i, __j);
2453*e4b17023SJohn Marino	return __p;
2454*e4b17023SJohn Marino      }
2455*e4b17023SJohn Marino
2456*e4b17023SJohn Marino      // Replace, range variants.
2457*e4b17023SJohn Marino      void
2458*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q, const rope& __r)
2459*e4b17023SJohn Marino      {	replace(__p.index(), __q.index() - __p.index(), __r); }
2460*e4b17023SJohn Marino
2461*e4b17023SJohn Marino      void
2462*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q, _CharT __c)
2463*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __c); }
2464*e4b17023SJohn Marino
2465*e4b17023SJohn Marino      void
2466*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q,
2467*e4b17023SJohn Marino	      const _CharT* __c_string)
2468*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __c_string); }
2469*e4b17023SJohn Marino
2470*e4b17023SJohn Marino      void
2471*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q,
2472*e4b17023SJohn Marino	      const _CharT* __i, size_t __n)
2473*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __i, __n); }
2474*e4b17023SJohn Marino
2475*e4b17023SJohn Marino      void
2476*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q,
2477*e4b17023SJohn Marino	      const _CharT* __i, const _CharT* __j)
2478*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2479*e4b17023SJohn Marino
2480*e4b17023SJohn Marino      void
2481*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q,
2482*e4b17023SJohn Marino	      const const_iterator& __i, const const_iterator& __j)
2483*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2484*e4b17023SJohn Marino
2485*e4b17023SJohn Marino      void
2486*e4b17023SJohn Marino      replace(const iterator& __p, const iterator& __q,
2487*e4b17023SJohn Marino	      const iterator& __i, const iterator& __j)
2488*e4b17023SJohn Marino      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2489*e4b17023SJohn Marino
2490*e4b17023SJohn Marino      // Replace, iterator variants.
2491*e4b17023SJohn Marino      void
2492*e4b17023SJohn Marino      replace(const iterator& __p, const rope& __r)
2493*e4b17023SJohn Marino      { replace(__p.index(), __r); }
2494*e4b17023SJohn Marino
2495*e4b17023SJohn Marino      void
2496*e4b17023SJohn Marino      replace(const iterator& __p, _CharT __c)
2497*e4b17023SJohn Marino      { replace(__p.index(), __c); }
2498*e4b17023SJohn Marino
2499*e4b17023SJohn Marino      void
2500*e4b17023SJohn Marino      replace(const iterator& __p, const _CharT* __c_string)
2501*e4b17023SJohn Marino      { replace(__p.index(), __c_string); }
2502*e4b17023SJohn Marino
2503*e4b17023SJohn Marino      void
2504*e4b17023SJohn Marino      replace(const iterator& __p, const _CharT* __i, size_t __n)
2505*e4b17023SJohn Marino      { replace(__p.index(), __i, __n); }
2506*e4b17023SJohn Marino
2507*e4b17023SJohn Marino      void
2508*e4b17023SJohn Marino      replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
2509*e4b17023SJohn Marino      { replace(__p.index(), __i, __j); }
2510*e4b17023SJohn Marino
2511*e4b17023SJohn Marino      void
2512*e4b17023SJohn Marino      replace(const iterator& __p, const_iterator __i, const_iterator __j)
2513*e4b17023SJohn Marino      { replace(__p.index(), __i, __j); }
2514*e4b17023SJohn Marino
2515*e4b17023SJohn Marino      void
2516*e4b17023SJohn Marino      replace(const iterator& __p, iterator __i, iterator __j)
2517*e4b17023SJohn Marino      { replace(__p.index(), __i, __j); }
2518*e4b17023SJohn Marino
2519*e4b17023SJohn Marino      // Iterator and range variants of erase
2520*e4b17023SJohn Marino      iterator
2521*e4b17023SJohn Marino      erase(const iterator& __p, const iterator& __q)
2522*e4b17023SJohn Marino      {
2523*e4b17023SJohn Marino	size_t __p_index = __p.index();
2524*e4b17023SJohn Marino	erase(__p_index, __q.index() - __p_index);
2525*e4b17023SJohn Marino	return iterator(this, __p_index);
2526*e4b17023SJohn Marino      }
2527*e4b17023SJohn Marino
2528*e4b17023SJohn Marino      iterator
2529*e4b17023SJohn Marino      erase(const iterator& __p)
2530*e4b17023SJohn Marino      {
2531*e4b17023SJohn Marino	size_t __p_index = __p.index();
2532*e4b17023SJohn Marino	erase(__p_index, 1);
2533*e4b17023SJohn Marino	return iterator(this, __p_index);
2534*e4b17023SJohn Marino      }
2535*e4b17023SJohn Marino
2536*e4b17023SJohn Marino      rope
2537*e4b17023SJohn Marino      substr(size_t __start, size_t __len = 1) const
2538*e4b17023SJohn Marino      {
2539*e4b17023SJohn Marino	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2540*e4b17023SJohn Marino						 __start,
2541*e4b17023SJohn Marino						 __start + __len));
2542*e4b17023SJohn Marino      }
2543*e4b17023SJohn Marino
2544*e4b17023SJohn Marino      rope
2545*e4b17023SJohn Marino      substr(iterator __start, iterator __end) const
2546*e4b17023SJohn Marino      {
2547*e4b17023SJohn Marino	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2548*e4b17023SJohn Marino						 __start.index(),
2549*e4b17023SJohn Marino						 __end.index()));
2550*e4b17023SJohn Marino      }
2551*e4b17023SJohn Marino
2552*e4b17023SJohn Marino      rope
2553*e4b17023SJohn Marino      substr(iterator __start) const
2554*e4b17023SJohn Marino      {
2555*e4b17023SJohn Marino	size_t __pos = __start.index();
2556*e4b17023SJohn Marino	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2557*e4b17023SJohn Marino						 __pos, __pos + 1));
2558*e4b17023SJohn Marino      }
2559*e4b17023SJohn Marino
2560*e4b17023SJohn Marino      rope
2561*e4b17023SJohn Marino      substr(const_iterator __start, const_iterator __end) const
2562*e4b17023SJohn Marino      {
2563*e4b17023SJohn Marino	// This might eventually take advantage of the cache in the
2564*e4b17023SJohn Marino	// iterator.
2565*e4b17023SJohn Marino	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2566*e4b17023SJohn Marino						 __start.index(),
2567*e4b17023SJohn Marino						 __end.index()));
2568*e4b17023SJohn Marino      }
2569*e4b17023SJohn Marino
2570*e4b17023SJohn Marino      rope<_CharT, _Alloc>
2571*e4b17023SJohn Marino      substr(const_iterator __start)
2572*e4b17023SJohn Marino      {
2573*e4b17023SJohn Marino	size_t __pos = __start.index();
2574*e4b17023SJohn Marino	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2575*e4b17023SJohn Marino						 __pos, __pos + 1));
2576*e4b17023SJohn Marino      }
2577*e4b17023SJohn Marino
2578*e4b17023SJohn Marino      static const size_type npos;
2579*e4b17023SJohn Marino
2580*e4b17023SJohn Marino      size_type find(_CharT __c, size_type __pos = 0) const;
2581*e4b17023SJohn Marino
2582*e4b17023SJohn Marino      size_type
2583*e4b17023SJohn Marino      find(const _CharT* __s, size_type __pos = 0) const
2584*e4b17023SJohn Marino      {
2585*e4b17023SJohn Marino	size_type __result_pos;
2586*e4b17023SJohn Marino	const_iterator __result =
2587*e4b17023SJohn Marino	  std::search(const_begin() + __pos, const_end(),
2588*e4b17023SJohn Marino		      __s, __s + _S_char_ptr_len(__s));
2589*e4b17023SJohn Marino	__result_pos = __result.index();
2590*e4b17023SJohn Marino#ifndef __STL_OLD_ROPE_SEMANTICS
2591*e4b17023SJohn Marino	if (__result_pos == size())
2592*e4b17023SJohn Marino	  __result_pos = npos;
2593*e4b17023SJohn Marino#endif
2594*e4b17023SJohn Marino	return __result_pos;
2595*e4b17023SJohn Marino      }
2596*e4b17023SJohn Marino
2597*e4b17023SJohn Marino      iterator
2598*e4b17023SJohn Marino      mutable_begin()
2599*e4b17023SJohn Marino      { return(iterator(this, 0)); }
2600*e4b17023SJohn Marino
2601*e4b17023SJohn Marino      iterator
2602*e4b17023SJohn Marino      mutable_end()
2603*e4b17023SJohn Marino      { return(iterator(this, size())); }
2604*e4b17023SJohn Marino
2605*e4b17023SJohn Marino      typedef std::reverse_iterator<iterator> reverse_iterator;
2606*e4b17023SJohn Marino
2607*e4b17023SJohn Marino      reverse_iterator
2608*e4b17023SJohn Marino      mutable_rbegin()
2609*e4b17023SJohn Marino      { return reverse_iterator(mutable_end()); }
2610*e4b17023SJohn Marino
2611*e4b17023SJohn Marino      reverse_iterator
2612*e4b17023SJohn Marino      mutable_rend()
2613*e4b17023SJohn Marino      { return reverse_iterator(mutable_begin()); }
2614*e4b17023SJohn Marino
2615*e4b17023SJohn Marino      reference
2616*e4b17023SJohn Marino      mutable_reference_at(size_type __pos)
2617*e4b17023SJohn Marino      { return reference(this, __pos); }
2618*e4b17023SJohn Marino
2619*e4b17023SJohn Marino#ifdef __STD_STUFF
2620*e4b17023SJohn Marino      reference
2621*e4b17023SJohn Marino      operator[] (size_type __pos)
2622*e4b17023SJohn Marino      { return _char_ref_proxy(this, __pos); }
2623*e4b17023SJohn Marino
2624*e4b17023SJohn Marino      reference
2625*e4b17023SJohn Marino      at(size_type __pos)
2626*e4b17023SJohn Marino      {
2627*e4b17023SJohn Marino	// if (__pos >= size()) throw out_of_range;  // XXX
2628*e4b17023SJohn Marino	return (*this)[__pos];
2629*e4b17023SJohn Marino      }
2630*e4b17023SJohn Marino
2631*e4b17023SJohn Marino      void resize(size_type __n, _CharT __c) { }
2632*e4b17023SJohn Marino      void resize(size_type __n) { }
2633*e4b17023SJohn Marino      void reserve(size_type __res_arg = 0) { }
2634*e4b17023SJohn Marino
2635*e4b17023SJohn Marino      size_type
2636*e4b17023SJohn Marino      capacity() const
2637*e4b17023SJohn Marino      { return max_size(); }
2638*e4b17023SJohn Marino
2639*e4b17023SJohn Marino      // Stuff below this line is dangerous because it's error prone.
2640*e4b17023SJohn Marino      // I would really like to get rid of it.
2641*e4b17023SJohn Marino      // copy function with funny arg ordering.
2642*e4b17023SJohn Marino      size_type
2643*e4b17023SJohn Marino      copy(_CharT* __buffer, size_type __n,
2644*e4b17023SJohn Marino	   size_type __pos = 0) const
2645*e4b17023SJohn Marino      { return copy(__pos, __n, __buffer); }
2646*e4b17023SJohn Marino
2647*e4b17023SJohn Marino      iterator
2648*e4b17023SJohn Marino      end()
2649*e4b17023SJohn Marino      { return mutable_end(); }
2650*e4b17023SJohn Marino
2651*e4b17023SJohn Marino      iterator
2652*e4b17023SJohn Marino      begin()
2653*e4b17023SJohn Marino      { return mutable_begin(); }
2654*e4b17023SJohn Marino
2655*e4b17023SJohn Marino      reverse_iterator
2656*e4b17023SJohn Marino      rend()
2657*e4b17023SJohn Marino      { return mutable_rend(); }
2658*e4b17023SJohn Marino
2659*e4b17023SJohn Marino      reverse_iterator
2660*e4b17023SJohn Marino      rbegin()
2661*e4b17023SJohn Marino      { return mutable_rbegin(); }
2662*e4b17023SJohn Marino
2663*e4b17023SJohn Marino#else
2664*e4b17023SJohn Marino      const_iterator
2665*e4b17023SJohn Marino      end()
2666*e4b17023SJohn Marino      { return const_end(); }
2667*e4b17023SJohn Marino
2668*e4b17023SJohn Marino      const_iterator
2669*e4b17023SJohn Marino      begin()
2670*e4b17023SJohn Marino      { return const_begin(); }
2671*e4b17023SJohn Marino
2672*e4b17023SJohn Marino      const_reverse_iterator
2673*e4b17023SJohn Marino      rend()
2674*e4b17023SJohn Marino      { return const_rend(); }
2675*e4b17023SJohn Marino
2676*e4b17023SJohn Marino      const_reverse_iterator
2677*e4b17023SJohn Marino      rbegin()
2678*e4b17023SJohn Marino      { return const_rbegin(); }
2679*e4b17023SJohn Marino
2680*e4b17023SJohn Marino#endif
2681*e4b17023SJohn Marino    };
2682*e4b17023SJohn Marino
2683*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2684*e4b17023SJohn Marino    const typename rope<_CharT, _Alloc>::size_type
2685*e4b17023SJohn Marino    rope<_CharT, _Alloc>::npos = (size_type)(-1);
2686*e4b17023SJohn Marino
2687*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2688*e4b17023SJohn Marino    inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2689*e4b17023SJohn Marino			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2690*e4b17023SJohn Marino    { return (__x._M_current_pos == __y._M_current_pos
2691*e4b17023SJohn Marino	      && __x._M_root == __y._M_root); }
2692*e4b17023SJohn Marino
2693*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2694*e4b17023SJohn Marino    inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2695*e4b17023SJohn Marino			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2696*e4b17023SJohn Marino    { return (__x._M_current_pos < __y._M_current_pos); }
2697*e4b17023SJohn Marino
2698*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2699*e4b17023SJohn Marino    inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2700*e4b17023SJohn Marino			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2701*e4b17023SJohn Marino    { return !(__x == __y); }
2702*e4b17023SJohn Marino
2703*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2704*e4b17023SJohn Marino    inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2705*e4b17023SJohn Marino			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2706*e4b17023SJohn Marino    { return __y < __x; }
2707*e4b17023SJohn Marino
2708*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2709*e4b17023SJohn Marino    inline bool
2710*e4b17023SJohn Marino    operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2711*e4b17023SJohn Marino	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2712*e4b17023SJohn Marino    { return !(__y < __x); }
2713*e4b17023SJohn Marino
2714*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2715*e4b17023SJohn Marino    inline bool
2716*e4b17023SJohn Marino    operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2717*e4b17023SJohn Marino	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2718*e4b17023SJohn Marino    { return !(__x < __y); }
2719*e4b17023SJohn Marino
2720*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2721*e4b17023SJohn Marino    inline ptrdiff_t
2722*e4b17023SJohn Marino    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2723*e4b17023SJohn Marino	      const _Rope_const_iterator<_CharT, _Alloc>& __y)
2724*e4b17023SJohn Marino    { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; }
2725*e4b17023SJohn Marino
2726*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2727*e4b17023SJohn Marino    inline _Rope_const_iterator<_CharT, _Alloc>
2728*e4b17023SJohn Marino    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2729*e4b17023SJohn Marino    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2730*e4b17023SJohn Marino						  __x._M_current_pos - __n); }
2731*e4b17023SJohn Marino
2732*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2733*e4b17023SJohn Marino    inline _Rope_const_iterator<_CharT, _Alloc>
2734*e4b17023SJohn Marino    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2735*e4b17023SJohn Marino    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2736*e4b17023SJohn Marino						  __x._M_current_pos + __n); }
2737*e4b17023SJohn Marino
2738*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2739*e4b17023SJohn Marino    inline _Rope_const_iterator<_CharT, _Alloc>
2740*e4b17023SJohn Marino    operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x)
2741*e4b17023SJohn Marino  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2742*e4b17023SJohn Marino						__x._M_current_pos + __n); }
2743*e4b17023SJohn Marino
2744*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2745*e4b17023SJohn Marino    inline bool
2746*e4b17023SJohn Marino    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
2747*e4b17023SJohn Marino	       const _Rope_iterator<_CharT, _Alloc>& __y)
2748*e4b17023SJohn Marino    {return (__x._M_current_pos == __y._M_current_pos
2749*e4b17023SJohn Marino	     && __x._M_root_rope == __y._M_root_rope); }
2750*e4b17023SJohn Marino
2751*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2752*e4b17023SJohn Marino    inline bool
2753*e4b17023SJohn Marino    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
2754*e4b17023SJohn Marino	      const _Rope_iterator<_CharT, _Alloc>& __y)
2755*e4b17023SJohn Marino    { return (__x._M_current_pos < __y._M_current_pos); }
2756*e4b17023SJohn Marino
2757*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2758*e4b17023SJohn Marino    inline bool
2759*e4b17023SJohn Marino    operator!=(const _Rope_iterator<_CharT, _Alloc>& __x,
2760*e4b17023SJohn Marino	       const _Rope_iterator<_CharT, _Alloc>& __y)
2761*e4b17023SJohn Marino    { return !(__x == __y); }
2762*e4b17023SJohn Marino
2763*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2764*e4b17023SJohn Marino    inline bool
2765*e4b17023SJohn Marino    operator>(const _Rope_iterator<_CharT, _Alloc>& __x,
2766*e4b17023SJohn Marino	      const _Rope_iterator<_CharT, _Alloc>& __y)
2767*e4b17023SJohn Marino    { return __y < __x; }
2768*e4b17023SJohn Marino
2769*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2770*e4b17023SJohn Marino    inline bool
2771*e4b17023SJohn Marino    operator<=(const _Rope_iterator<_CharT, _Alloc>& __x,
2772*e4b17023SJohn Marino	       const _Rope_iterator<_CharT, _Alloc>& __y)
2773*e4b17023SJohn Marino    { return !(__y < __x); }
2774*e4b17023SJohn Marino
2775*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2776*e4b17023SJohn Marino    inline bool
2777*e4b17023SJohn Marino    operator>=(const _Rope_iterator<_CharT, _Alloc>& __x,
2778*e4b17023SJohn Marino	       const _Rope_iterator<_CharT, _Alloc>& __y)
2779*e4b17023SJohn Marino    { return !(__x < __y); }
2780*e4b17023SJohn Marino
2781*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2782*e4b17023SJohn Marino    inline ptrdiff_t
2783*e4b17023SJohn Marino    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2784*e4b17023SJohn Marino	      const _Rope_iterator<_CharT, _Alloc>& __y)
2785*e4b17023SJohn Marino    { return ((ptrdiff_t)__x._M_current_pos
2786*e4b17023SJohn Marino	      - (ptrdiff_t)__y._M_current_pos); }
2787*e4b17023SJohn Marino
2788*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2789*e4b17023SJohn Marino    inline _Rope_iterator<_CharT, _Alloc>
2790*e4b17023SJohn Marino    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2791*e4b17023SJohn Marino	      ptrdiff_t __n)
2792*e4b17023SJohn Marino    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2793*e4b17023SJohn Marino					    __x._M_current_pos - __n); }
2794*e4b17023SJohn Marino
2795*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2796*e4b17023SJohn Marino    inline _Rope_iterator<_CharT, _Alloc>
2797*e4b17023SJohn Marino    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2798*e4b17023SJohn Marino    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2799*e4b17023SJohn Marino					    __x._M_current_pos + __n); }
2800*e4b17023SJohn Marino
2801*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2802*e4b17023SJohn Marino    inline _Rope_iterator<_CharT, _Alloc>
2803*e4b17023SJohn Marino    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x)
2804*e4b17023SJohn Marino    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2805*e4b17023SJohn Marino					    __x._M_current_pos + __n); }
2806*e4b17023SJohn Marino
2807*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2808*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>
2809*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left,
2810*e4b17023SJohn Marino	      const rope<_CharT, _Alloc>& __right)
2811*e4b17023SJohn Marino    {
2812*e4b17023SJohn Marino      // Inlining this should make it possible to keep __left and
2813*e4b17023SJohn Marino      // __right in registers.
2814*e4b17023SJohn Marino      typedef rope<_CharT, _Alloc> rope_type;
2815*e4b17023SJohn Marino      return rope_type(rope_type::_S_concat(__left._M_tree_ptr,
2816*e4b17023SJohn Marino					    __right._M_tree_ptr));
2817*e4b17023SJohn Marino    }
2818*e4b17023SJohn Marino
2819*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2820*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>&
2821*e4b17023SJohn Marino    operator+=(rope<_CharT, _Alloc>& __left,
2822*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __right)
2823*e4b17023SJohn Marino    {
2824*e4b17023SJohn Marino      __left.append(__right);
2825*e4b17023SJohn Marino      return __left;
2826*e4b17023SJohn Marino    }
2827*e4b17023SJohn Marino
2828*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2829*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>
2830*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left,
2831*e4b17023SJohn Marino	      const _CharT* __right)
2832*e4b17023SJohn Marino    {
2833*e4b17023SJohn Marino      typedef rope<_CharT, _Alloc> rope_type;
2834*e4b17023SJohn Marino      size_t __rlen = rope_type::_S_char_ptr_len(__right);
2835*e4b17023SJohn Marino      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2836*e4b17023SJohn Marino						      __right, __rlen));
2837*e4b17023SJohn Marino    }
2838*e4b17023SJohn Marino
2839*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2840*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>&
2841*e4b17023SJohn Marino    operator+=(rope<_CharT, _Alloc>& __left,
2842*e4b17023SJohn Marino	       const _CharT* __right)
2843*e4b17023SJohn Marino    {
2844*e4b17023SJohn Marino      __left.append(__right);
2845*e4b17023SJohn Marino      return __left;
2846*e4b17023SJohn Marino    }
2847*e4b17023SJohn Marino
2848*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2849*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>
2850*e4b17023SJohn Marino    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
2851*e4b17023SJohn Marino    {
2852*e4b17023SJohn Marino      typedef rope<_CharT, _Alloc> rope_type;
2853*e4b17023SJohn Marino      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2854*e4b17023SJohn Marino						      &__right, 1));
2855*e4b17023SJohn Marino    }
2856*e4b17023SJohn Marino
2857*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2858*e4b17023SJohn Marino    inline rope<_CharT, _Alloc>&
2859*e4b17023SJohn Marino    operator+=(rope<_CharT, _Alloc>& __left, _CharT __right)
2860*e4b17023SJohn Marino    {
2861*e4b17023SJohn Marino      __left.append(__right);
2862*e4b17023SJohn Marino      return __left;
2863*e4b17023SJohn Marino    }
2864*e4b17023SJohn Marino
2865*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2866*e4b17023SJohn Marino    bool
2867*e4b17023SJohn Marino    operator<(const rope<_CharT, _Alloc>& __left,
2868*e4b17023SJohn Marino	      const rope<_CharT, _Alloc>& __right)
2869*e4b17023SJohn Marino    { return __left.compare(__right) < 0; }
2870*e4b17023SJohn Marino
2871*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2872*e4b17023SJohn Marino    bool
2873*e4b17023SJohn Marino    operator==(const rope<_CharT, _Alloc>& __left,
2874*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __right)
2875*e4b17023SJohn Marino    { return __left.compare(__right) == 0; }
2876*e4b17023SJohn Marino
2877*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2878*e4b17023SJohn Marino    inline bool
2879*e4b17023SJohn Marino    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2880*e4b17023SJohn Marino	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2881*e4b17023SJohn Marino    { return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); }
2882*e4b17023SJohn Marino
2883*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2884*e4b17023SJohn Marino    inline bool
2885*e4b17023SJohn Marino    operator!=(const rope<_CharT, _Alloc>& __x,
2886*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __y)
2887*e4b17023SJohn Marino    { return !(__x == __y); }
2888*e4b17023SJohn Marino
2889*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2890*e4b17023SJohn Marino    inline bool
2891*e4b17023SJohn Marino    operator>(const rope<_CharT, _Alloc>& __x,
2892*e4b17023SJohn Marino	      const rope<_CharT, _Alloc>& __y)
2893*e4b17023SJohn Marino    { return __y < __x; }
2894*e4b17023SJohn Marino
2895*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2896*e4b17023SJohn Marino    inline bool
2897*e4b17023SJohn Marino    operator<=(const rope<_CharT, _Alloc>& __x,
2898*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __y)
2899*e4b17023SJohn Marino    { return !(__y < __x); }
2900*e4b17023SJohn Marino
2901*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2902*e4b17023SJohn Marino    inline bool
2903*e4b17023SJohn Marino    operator>=(const rope<_CharT, _Alloc>& __x,
2904*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __y)
2905*e4b17023SJohn Marino    { return !(__x < __y); }
2906*e4b17023SJohn Marino
2907*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2908*e4b17023SJohn Marino    inline bool
2909*e4b17023SJohn Marino    operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2910*e4b17023SJohn Marino	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2911*e4b17023SJohn Marino    { return !(__x == __y); }
2912*e4b17023SJohn Marino
2913*e4b17023SJohn Marino  template<class _CharT, class _Traits, class _Alloc>
2914*e4b17023SJohn Marino    std::basic_ostream<_CharT, _Traits>&
2915*e4b17023SJohn Marino    operator<<(std::basic_ostream<_CharT, _Traits>& __o,
2916*e4b17023SJohn Marino	       const rope<_CharT, _Alloc>& __r);
2917*e4b17023SJohn Marino
2918*e4b17023SJohn Marino  typedef rope<char> crope;
2919*e4b17023SJohn Marino  typedef rope<wchar_t> wrope;
2920*e4b17023SJohn Marino
2921*e4b17023SJohn Marino  inline crope::reference
2922*e4b17023SJohn Marino  __mutable_reference_at(crope& __c, size_t __i)
2923*e4b17023SJohn Marino  { return __c.mutable_reference_at(__i); }
2924*e4b17023SJohn Marino
2925*e4b17023SJohn Marino  inline wrope::reference
2926*e4b17023SJohn Marino  __mutable_reference_at(wrope& __c, size_t __i)
2927*e4b17023SJohn Marino  { return __c.mutable_reference_at(__i); }
2928*e4b17023SJohn Marino
2929*e4b17023SJohn Marino  template <class _CharT, class _Alloc>
2930*e4b17023SJohn Marino    inline void
2931*e4b17023SJohn Marino    swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y)
2932*e4b17023SJohn Marino    { __x.swap(__y); }
2933*e4b17023SJohn Marino
2934*e4b17023SJohn Marino_GLIBCXX_END_NAMESPACE_VERSION
2935*e4b17023SJohn Marino} // namespace
2936*e4b17023SJohn Marino
2937*e4b17023SJohn Marino
2938*e4b17023SJohn Marinonamespace std _GLIBCXX_VISIBILITY(default)
2939*e4b17023SJohn Marino{
2940*e4b17023SJohn Marinonamespace tr1
2941*e4b17023SJohn Marino{
2942*e4b17023SJohn Marino_GLIBCXX_BEGIN_NAMESPACE_VERSION
2943*e4b17023SJohn Marino
2944*e4b17023SJohn Marino  template<>
2945*e4b17023SJohn Marino    struct hash<__gnu_cxx::crope>
2946*e4b17023SJohn Marino    {
2947*e4b17023SJohn Marino      size_t
2948*e4b17023SJohn Marino      operator()(const __gnu_cxx::crope& __str) const
2949*e4b17023SJohn Marino      {
2950*e4b17023SJohn Marino	size_t __size = __str.size();
2951*e4b17023SJohn Marino	if (0 == __size)
2952*e4b17023SJohn Marino	  return 0;
2953*e4b17023SJohn Marino	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2954*e4b17023SJohn Marino      }
2955*e4b17023SJohn Marino    };
2956*e4b17023SJohn Marino
2957*e4b17023SJohn Marino
2958*e4b17023SJohn Marino  template<>
2959*e4b17023SJohn Marino    struct hash<__gnu_cxx::wrope>
2960*e4b17023SJohn Marino    {
2961*e4b17023SJohn Marino      size_t
2962*e4b17023SJohn Marino      operator()(const __gnu_cxx::wrope& __str) const
2963*e4b17023SJohn Marino      {
2964*e4b17023SJohn Marino	size_t __size = __str.size();
2965*e4b17023SJohn Marino	if (0 == __size)
2966*e4b17023SJohn Marino	  return 0;
2967*e4b17023SJohn Marino	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2968*e4b17023SJohn Marino      }
2969*e4b17023SJohn Marino    };
2970*e4b17023SJohn Marino
2971*e4b17023SJohn Marino_GLIBCXX_END_NAMESPACE_VERSION
2972*e4b17023SJohn Marino} // namespace tr1
2973*e4b17023SJohn Marino} // namespace std
2974*e4b17023SJohn Marino
2975*e4b17023SJohn Marino# include <ext/ropeimpl.h>
2976*e4b17023SJohn Marino
2977*e4b17023SJohn Marino#endif
2978