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