197403Sobrien// SGI's rope class -*- C++ -*-
297403Sobrien
3169691Skan// Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006
4169691Skan// Free Software Foundation, Inc.
597403Sobrien//
697403Sobrien// This file is part of the GNU ISO C++ Library.  This library is free
797403Sobrien// software; you can redistribute it and/or modify it under the
897403Sobrien// terms of the GNU General Public License as published by the
997403Sobrien// Free Software Foundation; either version 2, or (at your option)
1097403Sobrien// any later version.
1197403Sobrien
1297403Sobrien// This library is distributed in the hope that it will be useful,
1397403Sobrien// but WITHOUT ANY WARRANTY; without even the implied warranty of
1497403Sobrien// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1597403Sobrien// GNU General Public License for more details.
1697403Sobrien
1797403Sobrien// You should have received a copy of the GNU General Public License along
1897403Sobrien// with this library; see the file COPYING.  If not, write to the Free
19169691Skan// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
2097403Sobrien// USA.
2197403Sobrien
2297403Sobrien// As a special exception, you may use this file as part of a free software
2397403Sobrien// library without restriction.  Specifically, if other files instantiate
2497403Sobrien// templates or use macros or inline functions from this file, or you compile
2597403Sobrien// this file and link it with other files to produce an executable, this
2697403Sobrien// file does not by itself cause the resulting executable to be covered by
2797403Sobrien// the GNU General Public License.  This exception does not however
2897403Sobrien// invalidate any other reasons why the executable file might be covered by
2997403Sobrien// the GNU General Public License.
3097403Sobrien
3197403Sobrien/*
3297403Sobrien * Copyright (c) 1997
3397403Sobrien * Silicon Graphics Computer Systems, Inc.
3497403Sobrien *
3597403Sobrien * Permission to use, copy, modify, distribute and sell this software
3697403Sobrien * and its documentation for any purpose is hereby granted without fee,
3797403Sobrien * provided that the above copyright notice appear in all copies and
3897403Sobrien * that both that copyright notice and this permission notice appear
3997403Sobrien * in supporting documentation.  Silicon Graphics makes no
4097403Sobrien * representations about the suitability of this software for any
4197403Sobrien * purpose.  It is provided "as is" without express or implied warranty.
4297403Sobrien */
4397403Sobrien
4497403Sobrien/** @file ext/rope
4597403Sobrien *  This file is a GNU extension to the Standard C++ Library (possibly
46169691Skan *  containing extensions from the HP/SGI STL subset). 
4797403Sobrien */
4897403Sobrien
49132720Skan#ifndef _ROPE
50132720Skan#define _ROPE 1
5197403Sobrien
5297403Sobrien#include <bits/stl_algobase.h>
53132720Skan#include <bits/stl_construct.h>
54132720Skan#include <bits/stl_uninitialized.h>
5597403Sobrien#include <bits/stl_algo.h>
5697403Sobrien#include <bits/stl_function.h>
5797403Sobrien#include <bits/stl_numeric.h>
58132720Skan#include <bits/allocator.h>
59132720Skan#include <ext/hash_fun.h>
6097403Sobrien
61132720Skan# ifdef __GC
62132720Skan#   define __GC_CONST const
63132720Skan# else
64132720Skan#   include <bits/gthr.h>
65132720Skan#   define __GC_CONST   // constant except for deallocation
66132720Skan# endif
6797403Sobrien
68132720Skan#include <ext/memory> // For uninitialized_copy_n
69132720Skan
70169691Skan_GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
71132720Skan
72169691Skan  namespace __detail
73169691Skan  {
74169691Skan    enum { _S_max_rope_depth = 45 };
75169691Skan    enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
76169691Skan  } // namespace __detail
77132720Skan
78169691Skan  using std::size_t;
79169691Skan  using std::ptrdiff_t;
80169691Skan  using std::allocator;
81169691Skan  using std::iterator;
82169691Skan  using std::reverse_iterator;
83169691Skan  using std::_Destroy;
84132720Skan
85169691Skan  // The _S_eos function is used for those functions that
86169691Skan  // convert to/from C-like strings to detect the end of the string.
87169691Skan  
88169691Skan  // The end-of-C-string character.
89169691Skan  // This is what the draft standard says it should be.
90169691Skan  template <class _CharT>
91169691Skan    inline _CharT
92169691Skan    _S_eos(_CharT*)
93169691Skan    { return _CharT(); }
94132720Skan
95169691Skan  // Test for basic character types.
96169691Skan  // For basic character types leaves having a trailing eos.
97169691Skan  template <class _CharT>
98169691Skan    inline bool
99169691Skan    _S_is_basic_char_type(_CharT*)
100169691Skan    { return false; }
101169691Skan  
102169691Skan  template <class _CharT>
103169691Skan    inline bool
104169691Skan    _S_is_one_byte_char_type(_CharT*)
105169691Skan    { return false; }
106132720Skan
107169691Skan  inline bool
108169691Skan  _S_is_basic_char_type(char*)
109169691Skan  { return true; }
110169691Skan  
111169691Skan  inline bool
112169691Skan  _S_is_one_byte_char_type(char*)
113169691Skan  { return true; }
114169691Skan  
115169691Skan  inline bool
116169691Skan  _S_is_basic_char_type(wchar_t*)
117169691Skan  { return true; }
118132720Skan
119169691Skan  // Store an eos iff _CharT is a basic character type.
120169691Skan  // Do not reference _S_eos if it isn't.
121169691Skan  template <class _CharT>
122169691Skan    inline void
123169691Skan    _S_cond_store_eos(_CharT&) { }
124132720Skan
125169691Skan  inline void
126169691Skan  _S_cond_store_eos(char& __c)
127169691Skan  { __c = 0; }
128169691Skan
129169691Skan  inline void
130169691Skan  _S_cond_store_eos(wchar_t& __c)
131169691Skan  { __c = 0; }
132169691Skan
133169691Skan  // char_producers are logically functions that generate a section of
134169691Skan  // a string.  These can be convereted to ropes.  The resulting rope
135169691Skan  // invokes the char_producer on demand.  This allows, for example,
136169691Skan  // files to be viewed as ropes without reading the entire file.
137169691Skan  template <class _CharT>
138169691Skan    class char_producer
139169691Skan    {
140132720Skan    public:
141169691Skan      virtual ~char_producer() { };
142132720Skan
143169691Skan      virtual void
144169691Skan      operator()(size_t __start_pos, size_t __len,
145169691Skan		 _CharT* __buffer) = 0;
146169691Skan      // Buffer should really be an arbitrary output iterator.
147169691Skan      // That way we could flatten directly into an ostream, etc.
148169691Skan      // This is thoroughly impossible, since iterator types don't
149169691Skan      // have runtime descriptions.
150169691Skan    };
151132720Skan
152169691Skan  // Sequence buffers:
153169691Skan  //
154169691Skan  // Sequence must provide an append operation that appends an
155169691Skan  // array to the sequence.  Sequence buffers are useful only if
156169691Skan  // appending an entire array is cheaper than appending element by element.
157169691Skan  // This is true for many string representations.
158169691Skan  // This should  perhaps inherit from ostream<sequence::value_type>
159169691Skan  // and be implemented correspondingly, so that they can be used
160169691Skan  // for formatted.  For the sake of portability, we don't do this yet.
161169691Skan  //
162169691Skan  // For now, sequence buffers behave as output iterators.  But they also
163169691Skan  // behave a little like basic_ostringstream<sequence::value_type> and a
164169691Skan  // little like containers.
165169691Skan
166169691Skan  template<class _Sequence, size_t _Buf_sz = 100>
167169691Skan    class sequence_buffer
168169691Skan    : public iterator<std::output_iterator_tag, void, void, void, void>
169169691Skan    {
170132720Skan    public:
171169691Skan      typedef typename _Sequence::value_type value_type;
172132720Skan    protected:
173169691Skan      _Sequence* _M_prefix;
174169691Skan      value_type _M_buffer[_Buf_sz];
175169691Skan      size_t     _M_buf_count;
176132720Skan    public:
177132720Skan
178169691Skan      void
179169691Skan      flush()
180169691Skan      {
181169691Skan	_M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);
182169691Skan	_M_buf_count = 0;
183169691Skan      }
184169691Skan      
185169691Skan      ~sequence_buffer()
186169691Skan      { flush(); }
187169691Skan      
188169691Skan      sequence_buffer()
189169691Skan      : _M_prefix(0), _M_buf_count(0) { }
190132720Skan
191169691Skan      sequence_buffer(const sequence_buffer& __x)
192169691Skan      {
193169691Skan	_M_prefix = __x._M_prefix;
194169691Skan	_M_buf_count = __x._M_buf_count;
195169691Skan	std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
196169691Skan      }
197169691Skan      
198169691Skan      sequence_buffer(sequence_buffer& __x)
199169691Skan      {
200169691Skan	__x.flush();
201169691Skan	_M_prefix = __x._M_prefix;
202169691Skan	_M_buf_count = 0;
203169691Skan      }
204169691Skan      
205169691Skan      sequence_buffer(_Sequence& __s)
206169691Skan      : _M_prefix(&__s), _M_buf_count(0) { }
207169691Skan      
208169691Skan      sequence_buffer&
209169691Skan      operator=(sequence_buffer& __x)
210169691Skan      {
211169691Skan	__x.flush();
212169691Skan	_M_prefix = __x._M_prefix;
213169691Skan	_M_buf_count = 0;
214169691Skan	return *this;
215169691Skan      }
216132720Skan
217169691Skan      sequence_buffer&
218169691Skan      operator=(const sequence_buffer& __x)
219169691Skan      {
220169691Skan	_M_prefix = __x._M_prefix;
221169691Skan	_M_buf_count = __x._M_buf_count;
222169691Skan	std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
223169691Skan	return *this;
224169691Skan      }
225169691Skan      
226169691Skan      void
227169691Skan      push_back(value_type __x)
228169691Skan      {
229169691Skan	if (_M_buf_count < _Buf_sz)
230169691Skan	  {
231169691Skan	    _M_buffer[_M_buf_count] = __x;
232169691Skan	    ++_M_buf_count;
233169691Skan	  }
234169691Skan	else
235169691Skan	  {
236169691Skan	    flush();
237169691Skan	    _M_buffer[0] = __x;
238169691Skan	    _M_buf_count = 1;
239169691Skan	  }
240169691Skan      }
241169691Skan      
242169691Skan      void
243169691Skan      append(value_type* __s, size_t __len)
244169691Skan      {
245169691Skan	if (__len + _M_buf_count <= _Buf_sz)
246169691Skan	  {
247169691Skan	    size_t __i = _M_buf_count;
248169691Skan	    for (size_t __j = 0; __j < __len; __i++, __j++)
249169691Skan	      _M_buffer[__i] = __s[__j];
250169691Skan	    _M_buf_count += __len;
251169691Skan	  }
252169691Skan	else if (0 == _M_buf_count)
253169691Skan	  _M_prefix->append(__s, __s + __len);
254169691Skan	else
255169691Skan	  {
256169691Skan	    flush();
257169691Skan	    append(__s, __len);
258169691Skan	  }
259169691Skan      }
260132720Skan
261169691Skan      sequence_buffer&
262169691Skan      write(value_type* __s, size_t __len)
263169691Skan      {
264169691Skan	append(__s, __len);
265169691Skan	return *this;
266169691Skan      }
267169691Skan      
268169691Skan      sequence_buffer&
269169691Skan      put(value_type __x)
270169691Skan      {
271169691Skan	push_back(__x);
272169691Skan	return *this;
273169691Skan      }
274169691Skan      
275169691Skan      sequence_buffer&
276169691Skan      operator=(const value_type& __rhs)
277169691Skan      {
278169691Skan	push_back(__rhs);
279169691Skan	return *this;
280169691Skan      }
281169691Skan      
282169691Skan      sequence_buffer&
283169691Skan      operator*()
284169691Skan      { return *this; }
285169691Skan      
286169691Skan      sequence_buffer&
287169691Skan      operator++()
288169691Skan      { return *this; }
289169691Skan      
290169691Skan      sequence_buffer
291169691Skan      operator++(int)
292169691Skan      { return *this; }
293169691Skan    };
294169691Skan  
295169691Skan  // The following should be treated as private, at least for now.
296169691Skan  template<class _CharT>
297169691Skan    class _Rope_char_consumer
298169691Skan    {
299169691Skan    public:
300169691Skan      // If we had member templates, these should not be virtual.
301169691Skan      // For now we need to use run-time parametrization where
302169691Skan      // compile-time would do.  Hence this should all be private
303169691Skan      // for now.
304169691Skan      // The symmetry with char_producer is accidental and temporary.
305169691Skan      virtual ~_Rope_char_consumer() { };
306169691Skan  
307169691Skan      virtual bool
308169691Skan      operator()(const _CharT* __buffer, size_t __len) = 0;
309169691Skan    };
310169691Skan  
311169691Skan  // First a lot of forward declarations.  The standard seems to require
312169691Skan  // much stricter "declaration before use" than many of the implementations
313169691Skan  // that preceded it.
314169691Skan  template<class _CharT, class _Alloc = allocator<_CharT> >
315169691Skan    class rope;
316169691Skan  
317169691Skan  template<class _CharT, class _Alloc>
318169691Skan    struct _Rope_RopeConcatenation;
319132720Skan
320169691Skan  template<class _CharT, class _Alloc>
321169691Skan    struct _Rope_RopeLeaf;
322169691Skan  
323169691Skan  template<class _CharT, class _Alloc>
324169691Skan    struct _Rope_RopeFunction;
325169691Skan  
326169691Skan  template<class _CharT, class _Alloc>
327169691Skan    struct _Rope_RopeSubstring;
328169691Skan  
329169691Skan  template<class _CharT, class _Alloc>
330169691Skan    class _Rope_iterator;
331169691Skan  
332169691Skan  template<class _CharT, class _Alloc>
333169691Skan    class _Rope_const_iterator;
334169691Skan  
335169691Skan  template<class _CharT, class _Alloc>
336169691Skan    class _Rope_char_ref_proxy;
337169691Skan  
338169691Skan  template<class _CharT, class _Alloc>
339169691Skan    class _Rope_char_ptr_proxy;
340132720Skan
341169691Skan  template<class _CharT, class _Alloc>
342169691Skan    bool
343169691Skan    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
344169691Skan	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);
345132720Skan
346169691Skan  template<class _CharT, class _Alloc>
347169691Skan    _Rope_const_iterator<_CharT, _Alloc>
348169691Skan    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
349169691Skan	      ptrdiff_t __n);
350132720Skan
351169691Skan  template<class _CharT, class _Alloc>
352169691Skan    _Rope_const_iterator<_CharT, _Alloc>
353169691Skan    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
354169691Skan	      ptrdiff_t __n);
355132720Skan
356169691Skan  template<class _CharT, class _Alloc>
357169691Skan    _Rope_const_iterator<_CharT, _Alloc>
358169691Skan    operator+(ptrdiff_t __n,
359169691Skan	      const _Rope_const_iterator<_CharT, _Alloc>& __x);
360132720Skan
361169691Skan  template<class _CharT, class _Alloc>
362169691Skan    bool
363169691Skan    operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
364169691Skan	       const _Rope_const_iterator<_CharT, _Alloc>& __y);
365132720Skan
366169691Skan  template<class _CharT, class _Alloc>
367169691Skan    bool
368169691Skan    operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
369169691Skan	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
370169691Skan  
371169691Skan  template<class _CharT, class _Alloc>
372169691Skan    ptrdiff_t
373169691Skan    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
374169691Skan	      const _Rope_const_iterator<_CharT, _Alloc>& __y);
375132720Skan
376169691Skan  template<class _CharT, class _Alloc>
377169691Skan    _Rope_iterator<_CharT, _Alloc>
378169691Skan    operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
379132720Skan
380169691Skan  template<class _CharT, class _Alloc>
381169691Skan    _Rope_iterator<_CharT, _Alloc>
382169691Skan    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);
383132720Skan
384169691Skan  template<class _CharT, class _Alloc>
385169691Skan    _Rope_iterator<_CharT, _Alloc>
386169691Skan    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);
387132720Skan
388169691Skan  template<class _CharT, class _Alloc>
389169691Skan    bool
390169691Skan    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
391169691Skan	       const _Rope_iterator<_CharT, _Alloc>& __y);
392132720Skan
393169691Skan  template<class _CharT, class _Alloc>
394169691Skan    bool
395169691Skan    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
396169691Skan	      const _Rope_iterator<_CharT, _Alloc>& __y);
397132720Skan
398169691Skan  template<class _CharT, class _Alloc>
399169691Skan    ptrdiff_t
400169691Skan    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
401169691Skan	      const _Rope_iterator<_CharT, _Alloc>& __y);
402132720Skan
403169691Skan  template<class _CharT, class _Alloc>
404169691Skan    rope<_CharT, _Alloc>
405169691Skan    operator+(const rope<_CharT, _Alloc>& __left,
406169691Skan	      const rope<_CharT, _Alloc>& __right);
407132720Skan
408169691Skan  template<class _CharT, class _Alloc>
409169691Skan    rope<_CharT, _Alloc>
410169691Skan    operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);
411132720Skan
412169691Skan  template<class _CharT, class _Alloc>
413169691Skan    rope<_CharT, _Alloc>
414169691Skan    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);
415132720Skan
416169691Skan  // Some helpers, so we can use power on ropes.
417169691Skan  // See below for why this isn't local to the implementation.
418169691Skan  
419169691Skan  // This uses a nonstandard refcount convention.
420169691Skan  // The result has refcount 0.
421169691Skan  template<class _CharT, class _Alloc>
422169691Skan    struct _Rope_Concat_fn
423169691Skan    : public std::binary_function<rope<_CharT, _Alloc>, rope<_CharT, _Alloc>,
424169691Skan				  rope<_CharT, _Alloc> >
425169691Skan    {
426169691Skan      rope<_CharT, _Alloc>
427169691Skan      operator()(const rope<_CharT, _Alloc>& __x,
428169691Skan		 const rope<_CharT, _Alloc>& __y)
429169691Skan      { return __x + __y; }
430169691Skan    };
431132720Skan
432169691Skan  template <class _CharT, class _Alloc>
433169691Skan    inline rope<_CharT, _Alloc>
434169691Skan    identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
435169691Skan    { return rope<_CharT, _Alloc>(); }
436132720Skan
437132720Skan  // Class _Refcount_Base provides a type, _RC_t, a data member,
438132720Skan  // _M_ref_count, and member functions _M_incr and _M_decr, which perform
439132720Skan  // atomic preincrement/predecrement.  The constructor initializes
440132720Skan  // _M_ref_count.
441132720Skan  struct _Refcount_Base
442132720Skan  {
443132720Skan    // The type _RC_t
444132720Skan    typedef size_t _RC_t;
445169691Skan    
446132720Skan    // The data member _M_ref_count
447132720Skan    volatile _RC_t _M_ref_count;
448132720Skan
449132720Skan    // Constructor
450132720Skan    __gthread_mutex_t _M_ref_count_lock;
451132720Skan
452132720Skan    _Refcount_Base(_RC_t __n) : _M_ref_count(__n), _M_ref_count_lock()
453132720Skan    {
454132720Skan#ifdef __GTHREAD_MUTEX_INIT
455132720Skan      __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
456132720Skan      _M_ref_count_lock = __tmp;
457132720Skan#elif defined(__GTHREAD_MUTEX_INIT_FUNCTION)
458132720Skan      __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
459132720Skan#else
460132720Skan#error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
461132720Skan#endif
462132720Skan    }
463132720Skan
464132720Skan    void
465132720Skan    _M_incr()
466132720Skan    {
467132720Skan      __gthread_mutex_lock(&_M_ref_count_lock);
468132720Skan      ++_M_ref_count;
469132720Skan      __gthread_mutex_unlock(&_M_ref_count_lock);
470132720Skan    }
471132720Skan
472132720Skan    _RC_t
473132720Skan    _M_decr()
474132720Skan    {
475132720Skan      __gthread_mutex_lock(&_M_ref_count_lock);
476132720Skan      volatile _RC_t __tmp = --_M_ref_count;
477132720Skan      __gthread_mutex_unlock(&_M_ref_count_lock);
478132720Skan      return __tmp;
479132720Skan    }
480132720Skan  };
481132720Skan
482169691Skan  //
483169691Skan  // What follows should really be local to rope.  Unfortunately,
484169691Skan  // that doesn't work, since it makes it impossible to define generic
485169691Skan  // equality on rope iterators.  According to the draft standard, the
486169691Skan  // template parameters for such an equality operator cannot be inferred
487169691Skan  // from the occurrence of a member class as a parameter.
488169691Skan  // (SGI compilers in fact allow this, but the __result wouldn't be
489169691Skan  // portable.)
490169691Skan  // Similarly, some of the static member functions are member functions
491169691Skan  // only to avoid polluting the global namespace, and to circumvent
492169691Skan  // restrictions on type inference for template functions.
493169691Skan  //
494132720Skan
495169691Skan  //
496169691Skan  // The internal data structure for representing a rope.  This is
497169691Skan  // private to the implementation.  A rope is really just a pointer
498169691Skan  // to one of these.
499169691Skan  //
500169691Skan  // A few basic functions for manipulating this data structure
501169691Skan  // are members of _RopeRep.  Most of the more complex algorithms
502169691Skan  // are implemented as rope members.
503169691Skan  //
504169691Skan  // Some of the static member functions of _RopeRep have identically
505169691Skan  // named functions in rope that simply invoke the _RopeRep versions.
506132720Skan
507132720Skan#define __ROPE_DEFINE_ALLOCS(__a) \
508132720Skan        __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \
509132720Skan        typedef _Rope_RopeConcatenation<_CharT,__a> __C; \
510132720Skan        __ROPE_DEFINE_ALLOC(__C,_C) \
511132720Skan        typedef _Rope_RopeLeaf<_CharT,__a> __L; \
512132720Skan        __ROPE_DEFINE_ALLOC(__L,_L) \
513132720Skan        typedef _Rope_RopeFunction<_CharT,__a> __F; \
514132720Skan        __ROPE_DEFINE_ALLOC(__F,_F) \
515132720Skan        typedef _Rope_RopeSubstring<_CharT,__a> __S; \
516132720Skan        __ROPE_DEFINE_ALLOC(__S,_S)
517132720Skan
518169691Skan  //  Internal rope nodes potentially store a copy of the allocator
519169691Skan  //  instance used to allocate them.  This is mostly redundant.
520169691Skan  //  But the alternative would be to pass allocator instances around
521169691Skan  //  in some form to nearly all internal functions, since any pointer
522169691Skan  //  assignment may result in a zero reference count and thus require
523169691Skan  //  deallocation.
524132720Skan
525132720Skan#define __STATIC_IF_SGI_ALLOC  /* not static */
526132720Skan
527169691Skan  template <class _CharT, class _Alloc>
528169691Skan    struct _Rope_rep_base
529169691Skan    : public _Alloc
530169691Skan    {
531169691Skan      typedef _Alloc allocator_type;
532132720Skan
533169691Skan      allocator_type
534169691Skan      get_allocator() const
535169691Skan      { return *static_cast<const _Alloc*>(this); }
536132720Skan
537169691Skan      _Rope_rep_base(size_t __size, const allocator_type&)
538169691Skan      : _M_size(__size) { }
539132720Skan
540169691Skan      size_t _M_size;
541132720Skan
542132720Skan# define __ROPE_DEFINE_ALLOC(_Tp, __name) \
543132720Skan        typedef typename \
544132720Skan          _Alloc::template rebind<_Tp>::other __name##Alloc; \
545132720Skan        static _Tp* __name##_allocate(size_t __n) \
546132720Skan          { return __name##Alloc().allocate(__n); } \
547132720Skan        static void __name##_deallocate(_Tp *__p, size_t __n) \
548132720Skan          { __name##Alloc().deallocate(__p, __n); }
549169691Skan      __ROPE_DEFINE_ALLOCS(_Alloc)
550132720Skan# undef __ROPE_DEFINE_ALLOC
551169691Skan    };
552132720Skan
553169691Skan  template<class _CharT, class _Alloc>
554169691Skan    struct _Rope_RopeRep
555169691Skan    : public _Rope_rep_base<_CharT, _Alloc>
556132720Skan# ifndef __GC
557169691Skan	     , _Refcount_Base
558132720Skan# endif
559169691Skan    {
560132720Skan    public:
561169691Skan      __detail::_Tag _M_tag:8;
562169691Skan      bool _M_is_balanced:8;
563169691Skan      unsigned char _M_depth;
564169691Skan      __GC_CONST _CharT* _M_c_string;
565169691Skan      __gthread_mutex_t _M_c_string_lock;
566132720Skan                        /* Flattened version of string, if needed.  */
567132720Skan                        /* typically 0.                             */
568132720Skan                        /* If it's not 0, then the memory is owned  */
569132720Skan                        /* by this node.                            */
570132720Skan                        /* In the case of a leaf, this may point to */
571132720Skan                        /* the same memory as the data field.       */
572169691Skan      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
573169691Skan        allocator_type;
574169691Skan
575169691Skan      using _Rope_rep_base<_CharT, _Alloc>::get_allocator;
576169691Skan
577169691Skan      _Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_t __size,
578169691Skan		    allocator_type __a)
579169691Skan      : _Rope_rep_base<_CharT, _Alloc>(__size, __a),
580169691Skan#ifndef __GC
581169691Skan	_Refcount_Base(1),
582169691Skan#endif
583169691Skan	_M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
584132720Skan#ifdef __GTHREAD_MUTEX_INIT
585132720Skan    {
586169691Skan      // Do not copy a POSIX/gthr mutex once in use.  However, bits are bits.
587169691Skan      __gthread_mutex_t __tmp = __GTHREAD_MUTEX_INIT;
588169691Skan      _M_c_string_lock = __tmp;
589132720Skan    }
590132720Skan#else
591132720Skan    { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }
592132720Skan#endif
593169691Skan#ifdef __GC
594169691Skan      void
595169691Skan      _M_incr () { }
596169691Skan#endif
597169691Skan      static void
598169691Skan      _S_free_string(__GC_CONST _CharT*, size_t __len,
599169691Skan		     allocator_type __a);
600169691Skan#define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);
601132720Skan                        // Deallocate data section of a leaf.
602132720Skan                        // This shouldn't be a member function.
603132720Skan                        // But its hard to do anything else at the
604132720Skan                        // moment, because it's templatized w.r.t.
605132720Skan                        // an allocator.
606132720Skan                        // Does nothing if __GC is defined.
607169691Skan#ifndef __GC
608169691Skan      void _M_free_c_string();
609169691Skan      void _M_free_tree();
610169691Skan      // Deallocate t. Assumes t is not 0.
611169691Skan      void
612169691Skan      _M_unref_nonnil()
613169691Skan      {
614169691Skan	if (0 == _M_decr())
615169691Skan	  _M_free_tree();
616169691Skan      }
617169691Skan
618169691Skan      void
619169691Skan      _M_ref_nonnil()
620169691Skan      { _M_incr(); }
621169691Skan
622169691Skan      static void
623169691Skan      _S_unref(_Rope_RopeRep* __t)
624169691Skan      {
625169691Skan	if (0 != __t)
626169691Skan	  __t->_M_unref_nonnil();
627169691Skan      }
628169691Skan
629169691Skan      static void
630169691Skan      _S_ref(_Rope_RopeRep* __t)
631169691Skan      {
632169691Skan	if (0 != __t)
633169691Skan	  __t->_M_incr();
634169691Skan      }
635169691Skan      
636169691Skan      static void
637169691Skan      _S_free_if_unref(_Rope_RopeRep* __t)
638169691Skan      {
639169691Skan	if (0 != __t && 0 == __t->_M_ref_count)
640169691Skan	  __t->_M_free_tree();
641169691Skan      }
642132720Skan#   else /* __GC */
643169691Skan      void _M_unref_nonnil() { }
644169691Skan      void _M_ref_nonnil() { }
645169691Skan      static void _S_unref(_Rope_RopeRep*) { }
646169691Skan      static void _S_ref(_Rope_RopeRep*) { }
647169691Skan      static void _S_free_if_unref(_Rope_RopeRep*) { }
648132720Skan#   endif
649132720Skanprotected:
650169691Skan      _Rope_RopeRep&
651169691Skan      operator=(const _Rope_RopeRep&);
652132720Skan
653169691Skan      _Rope_RopeRep(const _Rope_RopeRep&);
654169691Skan    };
655132720Skan
656169691Skan  template<class _CharT, class _Alloc>
657169691Skan    struct _Rope_RopeLeaf
658169691Skan    : public _Rope_RopeRep<_CharT, _Alloc>
659169691Skan    {
660169691Skan    public:
661169691Skan      // Apparently needed by VC++
662169691Skan      // The data fields of leaves are allocated with some
663169691Skan      // extra space, to accommodate future growth and for basic
664169691Skan      // character types, to hold a trailing eos character.
665169691Skan      enum { _S_alloc_granularity = 8 };
666169691Skan      
667169691Skan      static size_t
668169691Skan      _S_rounded_up_size(size_t __n)
669169691Skan      {
670132720Skan        size_t __size_with_eos;
671169691Skan	
672169691Skan        if (_S_is_basic_char_type((_CharT*)0))
673169691Skan	  __size_with_eos = __n + 1;
674169691Skan	else
675169691Skan	  __size_with_eos = __n;
676169691Skan#ifdef __GC
677169691Skan	return __size_with_eos;
678169691Skan#else
679169691Skan	// Allow slop for in-place expansion.
680169691Skan	return ((__size_with_eos + size_t(_S_alloc_granularity) - 1)
681169691Skan		&~ (size_t(_S_alloc_granularity) - 1));
682169691Skan#endif
683169691Skan      }
684169691Skan      __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */
685169691Skan                                  /* The allocated size is         */
686169691Skan                                  /* _S_rounded_up_size(size), except */
687169691Skan                                  /* in the GC case, in which it   */
688169691Skan                                  /* doesn't matter.               */
689169691Skan      typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
690169691Skan        allocator_type;
691132720Skan
692169691Skan      _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size,
693169691Skan		     allocator_type __a)
694169691Skan      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true,
695169691Skan				      __size, __a), _M_data(__d)
696169691Skan      {
697169691Skan        if (_S_is_basic_char_type((_CharT *)0))
698169691Skan	  {
699132720Skan            // already eos terminated.
700132720Skan            this->_M_c_string = __d;
701169691Skan	  }
702169691Skan      }
703169691Skan      // The constructor assumes that d has been allocated with
704169691Skan      // the proper allocator and the properly padded size.
705169691Skan      // In contrast, the destructor deallocates the data:
706169691Skan#ifndef __GC
707169691Skan      ~_Rope_RopeLeaf() throw()
708169691Skan      {
709169691Skan        if (_M_data != this->_M_c_string)
710132720Skan	  this->_M_free_c_string();
711169691Skan	
712132720Skan        __STL_FREE_STRING(_M_data, this->_M_size, this->get_allocator());
713169691Skan      }
714169691Skan#endif
715132720Skanprotected:
716169691Skan      _Rope_RopeLeaf&
717169691Skan      operator=(const _Rope_RopeLeaf&);
718132720Skan
719169691Skan      _Rope_RopeLeaf(const _Rope_RopeLeaf&);
720169691Skan    };
721132720Skan
722169691Skan  template<class _CharT, class _Alloc>
723169691Skan    struct _Rope_RopeConcatenation
724169691Skan    : public _Rope_RopeRep<_CharT, _Alloc>
725169691Skan    {
726169691Skan    public:
727169691Skan      _Rope_RopeRep<_CharT, _Alloc>* _M_left;
728169691Skan      _Rope_RopeRep<_CharT, _Alloc>* _M_right;
729132720Skan
730169691Skan      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
731169691Skan        allocator_type;
732169691Skan
733169691Skan      _Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l,
734169691Skan			      _Rope_RopeRep<_CharT, _Alloc>* __r,
735169691Skan			      allocator_type __a)
736169691Skan	: _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat,
737169691Skan				      std::max(__l->_M_depth,
738169691Skan					       __r->_M_depth) + 1,
739169691Skan				      false,
740169691Skan				      __l->_M_size + __r->_M_size, __a),
741132720Skan        _M_left(__l), _M_right(__r)
742169691Skan      { }
743169691Skan#ifndef __GC
744169691Skan      ~_Rope_RopeConcatenation() throw()
745169691Skan      {
746169691Skan	this->_M_free_c_string();
747169691Skan	_M_left->_M_unref_nonnil();
748169691Skan	_M_right->_M_unref_nonnil();
749169691Skan      }
750169691Skan#endif
751132720Skanprotected:
752169691Skan      _Rope_RopeConcatenation&
753169691Skan      operator=(const _Rope_RopeConcatenation&);
754169691Skan      
755169691Skan      _Rope_RopeConcatenation(const _Rope_RopeConcatenation&);
756169691Skan    };
757132720Skan
758169691Skan  template<class _CharT, class _Alloc>
759169691Skan    struct _Rope_RopeFunction
760169691Skan    : public _Rope_RopeRep<_CharT, _Alloc>
761169691Skan    {
762169691Skan    public:
763169691Skan      char_producer<_CharT>* _M_fn;
764169691Skan#ifndef __GC
765132720Skan      bool _M_delete_when_done; // Char_producer is owned by the
766132720Skan                                // rope and should be explicitly
767132720Skan                                // deleted when the rope becomes
768132720Skan                                // inaccessible.
769169691Skan#else
770132720Skan      // In the GC case, we either register the rope for
771132720Skan      // finalization, or not.  Thus the field is unnecessary;
772132720Skan      // the information is stored in the collector data structures.
773132720Skan      // We do need a finalization procedure to be invoked by the
774132720Skan      // collector.
775169691Skan      static void
776169691Skan      _S_fn_finalization_proc(void * __tree, void *)
777169691Skan      { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
778169691Skan#endif
779169691Skan    typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
780169691Skan      allocator_type;
781169691Skan
782169691Skan      _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size,
783169691Skan                        bool __d, allocator_type __a)
784169691Skan      : _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a)
785169691Skan	, _M_fn(__f)
786169691Skan#ifndef __GC
787169691Skan	, _M_delete_when_done(__d)
788169691Skan#endif
789169691Skan      {
790169691Skan#ifdef __GC
791169691Skan	if (__d)
792169691Skan	  {
793169691Skan	    GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::
794169691Skan				  _S_fn_finalization_proc, 0, 0, 0);
795169691Skan	  }
796169691Skan#endif
797132720Skan      }
798169691Skan#ifndef __GC
799169691Skan      ~_Rope_RopeFunction() throw()
800169691Skan      {
801169691Skan	this->_M_free_c_string();
802169691Skan	if (_M_delete_when_done)
803169691Skan	  delete _M_fn;
804169691Skan      }
805132720Skan# endif
806169691Skan    protected:
807169691Skan      _Rope_RopeFunction&
808169691Skan      operator=(const _Rope_RopeFunction&);
809132720Skan
810169691Skan      _Rope_RopeFunction(const _Rope_RopeFunction&);
811169691Skan    };
812169691Skan  // Substring results are usually represented using just
813169691Skan  // concatenation nodes.  But in the case of very long flat ropes
814169691Skan  // or ropes with a functional representation that isn't practical.
815169691Skan  // In that case, we represent the __result as a special case of
816169691Skan  // RopeFunction, whose char_producer points back to the rope itself.
817169691Skan  // In all cases except repeated substring operations and
818169691Skan  // deallocation, we treat the __result as a RopeFunction.
819169691Skan  template<class _CharT, class _Alloc>
820169691Skan    struct _Rope_RopeSubstring
821169691Skan    : public _Rope_RopeFunction<_CharT, _Alloc>,
822169691Skan      public char_producer<_CharT>
823169691Skan    {
824169691Skan    public:
825169691Skan      // XXX this whole class should be rewritten.
826169691Skan      _Rope_RopeRep<_CharT,_Alloc>* _M_base;      // not 0
827169691Skan      size_t _M_start;
828169691Skan
829169691Skan      virtual void
830169691Skan      operator()(size_t __start_pos, size_t __req_len,
831169691Skan		 _CharT* __buffer)
832169691Skan      {
833169691Skan        switch(_M_base->_M_tag)
834169691Skan	  {
835169691Skan	  case __detail::_S_function:
836169691Skan	  case __detail::_S_substringfn:
837169691Skan	    {
838169691Skan	      char_producer<_CharT>* __fn =
839169691Skan		((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;
840169691Skan	      (*__fn)(__start_pos + _M_start, __req_len, __buffer);
841169691Skan	    }
842169691Skan	    break;
843169691Skan	  case __detail::_S_leaf:
844169691Skan	    {
845169691Skan	      __GC_CONST _CharT* __s =
846169691Skan		((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data;
847169691Skan	      uninitialized_copy_n(__s + __start_pos + _M_start, __req_len,
848169691Skan				   __buffer);
849169691Skan	    }
850169691Skan	    break;
851169691Skan	  default:
852169691Skan	    break;
853169691Skan	  }
854169691Skan      }
855169691Skan      
856169691Skan      typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
857132720Skan        allocator_type;
858169691Skan
859169691Skan      _Rope_RopeSubstring(_Rope_RopeRep<_CharT, _Alloc>* __b, size_t __s,
860132720Skan                          size_t __l, allocator_type __a)
861169691Skan      : _Rope_RopeFunction<_CharT, _Alloc>(this, __l, false, __a),
862169691Skan        char_producer<_CharT>(), _M_base(__b), _M_start(__s)
863169691Skan      {
864169691Skan#ifndef __GC
865169691Skan	_M_base->_M_ref_nonnil();
866169691Skan#endif
867169691Skan        this->_M_tag = __detail::_S_substringfn;
868169691Skan      }
869132720Skan    virtual ~_Rope_RopeSubstring() throw()
870132720Skan      {
871169691Skan#ifndef __GC
872169691Skan	_M_base->_M_unref_nonnil();
873169691Skan	// _M_free_c_string();  -- done by parent class
874169691Skan#endif
875132720Skan      }
876169691Skan    };
877132720Skan
878169691Skan  // Self-destructing pointers to Rope_rep.
879169691Skan  // These are not conventional smart pointers.  Their
880169691Skan  // only purpose in life is to ensure that unref is called
881169691Skan  // on the pointer either at normal exit or if an exception
882169691Skan  // is raised.  It is the caller's responsibility to
883169691Skan  // adjust reference counts when these pointers are initialized
884169691Skan  // or assigned to.  (This convention significantly reduces
885169691Skan  // the number of potentially expensive reference count
886169691Skan  // updates.)
887132720Skan#ifndef __GC
888132720Skan  template<class _CharT, class _Alloc>
889169691Skan    struct _Rope_self_destruct_ptr
890169691Skan    {
891169691Skan      _Rope_RopeRep<_CharT, _Alloc>* _M_ptr;
892169691Skan
893169691Skan      ~_Rope_self_destruct_ptr()
894169691Skan      { _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
895132720Skan#ifdef __EXCEPTIONS
896169691Skan      _Rope_self_destruct_ptr() : _M_ptr(0) { };
897132720Skan#else
898169691Skan      _Rope_self_destruct_ptr() { };
899132720Skan#endif
900169691Skan      _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p)
901169691Skan      : _M_ptr(__p) { }
902169691Skan    
903169691Skan      _Rope_RopeRep<_CharT, _Alloc>&
904169691Skan      operator*()
905169691Skan      { return *_M_ptr; }
906169691Skan    
907169691Skan      _Rope_RopeRep<_CharT, _Alloc>*
908169691Skan      operator->()
909169691Skan      { return _M_ptr; }
910169691Skan    
911169691Skan      operator _Rope_RopeRep<_CharT, _Alloc>*()
912169691Skan      { return _M_ptr; }
913169691Skan    
914169691Skan      _Rope_self_destruct_ptr&
915169691Skan      operator=(_Rope_RopeRep<_CharT, _Alloc>* __x)
916169691Skan      { _M_ptr = __x; return *this; }
917169691Skan    };
918132720Skan#endif
919132720Skan
920169691Skan  // Dereferencing a nonconst iterator has to return something
921169691Skan  // that behaves almost like a reference.  It's not possible to
922169691Skan  // return an actual reference since assignment requires extra
923169691Skan  // work.  And we would get into the same problems as with the
924169691Skan  // CD2 version of basic_string.
925169691Skan  template<class _CharT, class _Alloc>
926169691Skan    class _Rope_char_ref_proxy
927169691Skan    {
928169691Skan      friend class rope<_CharT, _Alloc>;
929169691Skan      friend class _Rope_iterator<_CharT, _Alloc>;
930169691Skan      friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
931169691Skan#ifdef __GC
932169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
933169691Skan#else
934169691Skan      typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
935169691Skan#endif
936169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
937169691Skan      typedef rope<_CharT, _Alloc> _My_rope;
938169691Skan      size_t _M_pos;
939169691Skan      _CharT _M_current;
940169691Skan      bool _M_current_valid;
941169691Skan      _My_rope* _M_root;     // The whole rope.
942169691Skan    public:
943169691Skan      _Rope_char_ref_proxy(_My_rope* __r, size_t __p)
944169691Skan      :  _M_pos(__p), _M_current(), _M_current_valid(false), _M_root(__r) { }
945132720Skan
946169691Skan      _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x)
947169691Skan      : _M_pos(__x._M_pos), _M_current(__x._M_current), 
948169691Skan	_M_current_valid(false), _M_root(__x._M_root) { }
949132720Skan
950169691Skan      // Don't preserve cache if the reference can outlive the
951169691Skan      // expression.  We claim that's not possible without calling
952169691Skan      // a copy constructor or generating reference to a proxy
953169691Skan      // reference.  We declare the latter to have undefined semantics.
954169691Skan      _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c)
955169691Skan      : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) { }
956169691Skan
957169691Skan      inline operator _CharT () const;
958169691Skan
959169691Skan      _Rope_char_ref_proxy&
960169691Skan      operator=(_CharT __c);
961169691Skan    
962169691Skan      _Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const;
963169691Skan      
964169691Skan      _Rope_char_ref_proxy&
965169691Skan      operator=(const _Rope_char_ref_proxy& __c)
966169691Skan      { return operator=((_CharT)__c); }
967169691Skan    };
968169691Skan
969169691Skan  template<class _CharT, class __Alloc>
970169691Skan    inline void
971169691Skan    swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,
972169691Skan	 _Rope_char_ref_proxy <_CharT, __Alloc > __b)
973169691Skan    {
974169691Skan      _CharT __tmp = __a;
975169691Skan      __a = __b;
976169691Skan      __b = __tmp;
977132720Skan    }
978132720Skan
979169691Skan  template<class _CharT, class _Alloc>
980169691Skan    class _Rope_char_ptr_proxy
981169691Skan    {
982169691Skan      // XXX this class should be rewritten.
983169691Skan      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
984169691Skan      size_t _M_pos;
985169691Skan      rope<_CharT,_Alloc>* _M_root;     // The whole rope.
986169691Skan    public:
987169691Skan      _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x)
988169691Skan      : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
989132720Skan
990169691Skan      _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x)
991169691Skan      : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
992169691Skan
993169691Skan      _Rope_char_ptr_proxy() { }
994169691Skan      
995169691Skan      _Rope_char_ptr_proxy(_CharT* __x)
996169691Skan      : _M_root(0), _M_pos(0) { }
997169691Skan
998169691Skan      _Rope_char_ptr_proxy&
999169691Skan      operator=(const _Rope_char_ptr_proxy& __x)
1000169691Skan      {
1001132720Skan        _M_pos = __x._M_pos;
1002132720Skan        _M_root = __x._M_root;
1003132720Skan        return *this;
1004169691Skan      }
1005132720Skan
1006169691Skan      template<class _CharT2, class _Alloc2>
1007169691Skan        friend bool
1008169691Skan        operator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x,
1009169691Skan		   const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y);
1010132720Skan
1011169691Skan      _Rope_char_ref_proxy<_CharT, _Alloc> operator*() const
1012169691Skan      { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); }
1013169691Skan    };
1014132720Skan
1015169691Skan  // Rope iterators:
1016169691Skan  // Unlike in the C version, we cache only part of the stack
1017169691Skan  // for rope iterators, since they must be efficiently copyable.
1018169691Skan  // When we run out of cache, we have to reconstruct the iterator
1019169691Skan  // value.
1020169691Skan  // Pointers from iterators are not included in reference counts.
1021169691Skan  // Iterators are assumed to be thread private.  Ropes can
1022169691Skan  // be shared.
1023169691Skan  
1024169691Skan  template<class _CharT, class _Alloc>
1025169691Skan    class _Rope_iterator_base
1026169691Skan    : public iterator<std::random_access_iterator_tag, _CharT>
1027169691Skan    {
1028169691Skan      friend class rope<_CharT, _Alloc>;
1029169691Skan    public:
1030169691Skan      typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaround
1031169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1032169691Skan      // Borland doesn't want this to be protected.
1033169691Skan    protected:
1034169691Skan      enum { _S_path_cache_len = 4 }; // Must be <= 9.
1035169691Skan      enum { _S_iterator_buf_len = 15 };
1036169691Skan      size_t _M_current_pos;
1037169691Skan      _RopeRep* _M_root;     // The whole rope.
1038169691Skan      size_t _M_leaf_pos;    // Starting position for current leaf
1039169691Skan      __GC_CONST _CharT* _M_buf_start;
1040169691Skan                             // Buffer possibly
1041169691Skan                             // containing current char.
1042169691Skan      __GC_CONST _CharT* _M_buf_ptr;
1043169691Skan                             // Pointer to current char in buffer.
1044169691Skan                             // != 0 ==> buffer valid.
1045169691Skan      __GC_CONST _CharT* _M_buf_end;
1046169691Skan                             // One past __last valid char in buffer.
1047169691Skan      // What follows is the path cache.  We go out of our
1048169691Skan      // way to make this compact.
1049169691Skan      // Path_end contains the bottom section of the path from
1050169691Skan      // the root to the current leaf.
1051169691Skan      const _RopeRep* _M_path_end[_S_path_cache_len];
1052169691Skan      int _M_leaf_index;     // Last valid __pos in path_end;
1053169691Skan                             // _M_path_end[0] ... _M_path_end[leaf_index-1]
1054169691Skan                             // point to concatenation nodes.
1055169691Skan      unsigned char _M_path_directions;
1056132720Skan                          // (path_directions >> __i) & 1 is 1
1057132720Skan                          // iff we got from _M_path_end[leaf_index - __i - 1]
1058132720Skan                          // to _M_path_end[leaf_index - __i] by going to the
1059132720Skan                          // __right. Assumes path_cache_len <= 9.
1060169691Skan      _CharT _M_tmp_buf[_S_iterator_buf_len];
1061132720Skan                        // Short buffer for surrounding chars.
1062132720Skan                        // This is useful primarily for
1063132720Skan                        // RopeFunctions.  We put the buffer
1064132720Skan                        // here to avoid locking in the
1065132720Skan                        // multithreaded case.
1066169691Skan      // The cached path is generally assumed to be valid
1067169691Skan      // only if the buffer is valid.
1068169691Skan      static void _S_setbuf(_Rope_iterator_base& __x);
1069132720Skan                                        // Set buffer contents given
1070132720Skan                                        // path cache.
1071169691Skan      static void _S_setcache(_Rope_iterator_base& __x);
1072132720Skan                                        // Set buffer contents and
1073132720Skan                                        // path cache.
1074169691Skan      static void _S_setcache_for_incr(_Rope_iterator_base& __x);
1075132720Skan                                        // As above, but assumes path
1076132720Skan                                        // cache is valid for previous posn.
1077169691Skan      _Rope_iterator_base() { }
1078169691Skan
1079169691Skan      _Rope_iterator_base(_RopeRep* __root, size_t __pos)
1080169691Skan      : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }
1081169691Skan
1082169691Skan      void _M_incr(size_t __n);
1083169691Skan      void _M_decr(size_t __n);
1084169691Skan    public:
1085169691Skan      size_t
1086169691Skan      index() const
1087169691Skan      { return _M_current_pos; }
1088169691Skan    
1089169691Skan      _Rope_iterator_base(const _Rope_iterator_base& __x)
1090169691Skan      {
1091169691Skan        if (0 != __x._M_buf_ptr)
1092169691Skan	  *this = __x;
1093169691Skan	else
1094169691Skan	  {
1095132720Skan            _M_current_pos = __x._M_current_pos;
1096132720Skan            _M_root = __x._M_root;
1097132720Skan            _M_buf_ptr = 0;
1098169691Skan	  }
1099169691Skan      }
1100169691Skan    };
1101132720Skan
1102169691Skan  template<class _CharT, class _Alloc>
1103169691Skan    class _Rope_iterator;
1104132720Skan
1105169691Skan  template<class _CharT, class _Alloc>
1106169691Skan    class _Rope_const_iterator
1107169691Skan    : public _Rope_iterator_base<_CharT, _Alloc>
1108169691Skan    {
1109169691Skan      friend class rope<_CharT, _Alloc>;
1110169691Skan    protected:
1111169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1112132720Skan      // The one from the base class may not be directly visible.
1113169691Skan      _Rope_const_iterator(const _RopeRep* __root, size_t __pos)
1114169691Skan      : _Rope_iterator_base<_CharT, _Alloc>(const_cast<_RopeRep*>(__root),
1115169691Skan					    __pos)
1116132720Skan                   // Only nonconst iterators modify root ref count
1117169691Skan      { }
1118132720Skan  public:
1119169691Skan      typedef _CharT reference;   // Really a value.  Returning a reference
1120169691Skan                                  // Would be a mess, since it would have
1121169691Skan                                  // to be included in refcount.
1122169691Skan      typedef const _CharT* pointer;
1123132720Skan
1124169691Skan    public:
1125169691Skan      _Rope_const_iterator() { };
1126169691Skan
1127169691Skan      _Rope_const_iterator(const _Rope_const_iterator& __x)
1128169691Skan      : _Rope_iterator_base<_CharT,_Alloc>(__x) { }
1129169691Skan
1130169691Skan      _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);
1131169691Skan    
1132169691Skan      _Rope_const_iterator(const rope<_CharT, _Alloc>& __r, size_t __pos)
1133169691Skan      : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { }
1134169691Skan
1135169691Skan      _Rope_const_iterator&
1136169691Skan      operator=(const _Rope_const_iterator& __x)
1137169691Skan      {
1138169691Skan        if (0 != __x._M_buf_ptr)
1139169691Skan	  *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1140169691Skan	else
1141169691Skan	  {
1142132720Skan            this->_M_current_pos = __x._M_current_pos;
1143132720Skan            this->_M_root = __x._M_root;
1144132720Skan            this->_M_buf_ptr = 0;
1145169691Skan	  }
1146132720Skan        return(*this);
1147169691Skan      }
1148169691Skan
1149169691Skan      reference
1150169691Skan      operator*()
1151169691Skan      {
1152169691Skan        if (0 == this->_M_buf_ptr)
1153169691Skan	  _S_setcache(*this);
1154132720Skan        return *this->_M_buf_ptr;
1155169691Skan      }
1156169691Skan
1157169691Skan      // Without this const version, Rope iterators do not meet the
1158169691Skan      // requirements of an Input Iterator.
1159169691Skan      reference
1160169691Skan      operator*() const
1161169691Skan      {
1162169691Skan	return *const_cast<_Rope_const_iterator&>(*this);
1163169691Skan      }
1164169691Skan
1165169691Skan      _Rope_const_iterator&
1166169691Skan      operator++()
1167169691Skan      {
1168132720Skan        __GC_CONST _CharT* __next;
1169132720Skan        if (0 != this->_M_buf_ptr
1170169691Skan	    && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end)
1171169691Skan	  {
1172132720Skan            this->_M_buf_ptr = __next;
1173132720Skan            ++this->_M_current_pos;
1174169691Skan	  }
1175169691Skan	else
1176169691Skan	  this->_M_incr(1);
1177169691Skan	return *this;
1178169691Skan      }
1179169691Skan
1180169691Skan      _Rope_const_iterator&
1181169691Skan      operator+=(ptrdiff_t __n)
1182169691Skan      {
1183169691Skan        if (__n >= 0)
1184169691Skan	  this->_M_incr(__n);
1185169691Skan	else
1186169691Skan	  this->_M_decr(-__n);
1187169691Skan	return *this;
1188169691Skan      }
1189169691Skan
1190169691Skan      _Rope_const_iterator&
1191169691Skan      operator--()
1192169691Skan      {
1193132720Skan        this->_M_decr(1);
1194132720Skan        return *this;
1195169691Skan      }
1196169691Skan
1197169691Skan      _Rope_const_iterator&
1198169691Skan      operator-=(ptrdiff_t __n)
1199169691Skan      {
1200169691Skan        if (__n >= 0)
1201169691Skan	  this->_M_decr(__n);
1202169691Skan	else
1203169691Skan	  this->_M_incr(-__n);
1204169691Skan	return *this;
1205169691Skan      }
1206169691Skan
1207169691Skan      _Rope_const_iterator
1208169691Skan      operator++(int)
1209169691Skan      {
1210132720Skan        size_t __old_pos = this->_M_current_pos;
1211132720Skan        this->_M_incr(1);
1212132720Skan        return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1213132720Skan        // This makes a subsequent dereference expensive.
1214132720Skan        // Perhaps we should instead copy the iterator
1215132720Skan        // if it has a valid cache?
1216169691Skan      }
1217169691Skan
1218169691Skan      _Rope_const_iterator
1219169691Skan      operator--(int)
1220169691Skan      {
1221132720Skan        size_t __old_pos = this->_M_current_pos;
1222132720Skan        this->_M_decr(1);
1223132720Skan        return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
1224169691Skan      }
1225132720Skan
1226169691Skan      template<class _CharT2, class _Alloc2>
1227169691Skan        friend _Rope_const_iterator<_CharT2, _Alloc2>
1228169691Skan        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1229169691Skan		  ptrdiff_t __n);
1230132720Skan
1231169691Skan      template<class _CharT2, class _Alloc2>
1232169691Skan        friend _Rope_const_iterator<_CharT2, _Alloc2>
1233169691Skan        operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1234169691Skan		  ptrdiff_t __n);
1235169691Skan
1236169691Skan      template<class _CharT2, class _Alloc2>
1237169691Skan        friend _Rope_const_iterator<_CharT2, _Alloc2>
1238169691Skan        operator+(ptrdiff_t __n,
1239169691Skan		  const _Rope_const_iterator<_CharT2, _Alloc2>& __x);
1240169691Skan
1241169691Skan      reference
1242169691Skan      operator[](size_t __n)
1243169691Skan      { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,
1244169691Skan					      this->_M_current_pos + __n); }
1245169691Skan
1246169691Skan      template<class _CharT2, class _Alloc2>
1247169691Skan        friend bool
1248169691Skan        operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1249169691Skan		   const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1250169691Skan
1251169691Skan      template<class _CharT2, class _Alloc2>
1252169691Skan        friend bool
1253169691Skan        operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1254169691Skan		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1255169691Skan
1256169691Skan      template<class _CharT2, class _Alloc2>
1257169691Skan        friend ptrdiff_t
1258169691Skan        operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1259169691Skan		  const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1260169691Skan    };
1261169691Skan
1262169691Skan  template<class _CharT, class _Alloc>
1263169691Skan    class _Rope_iterator
1264169691Skan    : public _Rope_iterator_base<_CharT, _Alloc>
1265169691Skan    {
1266169691Skan      friend class rope<_CharT, _Alloc>;
1267169691Skan    protected:
1268169691Skan      typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep;
1269169691Skan      rope<_CharT, _Alloc>* _M_root_rope;
1270169691Skan
1271169691Skan      // root is treated as a cached version of this, and is used to
1272169691Skan      // detect changes to the underlying rope.
1273169691Skan
1274169691Skan      // Root is included in the reference count.  This is necessary
1275169691Skan      // so that we can detect changes reliably.  Unfortunately, it
1276169691Skan      // requires careful bookkeeping for the nonGC case.
1277169691Skan      _Rope_iterator(rope<_CharT, _Alloc>* __r, size_t __pos)
1278169691Skan      : _Rope_iterator_base<_CharT, _Alloc>(__r->_M_tree_ptr, __pos),
1279132720Skan        _M_root_rope(__r)
1280132720Skan      { _RopeRep::_S_ref(this->_M_root);
1281169691Skan        if (!(__r -> empty()))
1282169691Skan	  _S_setcache(*this);
1283169691Skan      }
1284132720Skan
1285169691Skan      void _M_check();
1286169691Skan    public:
1287169691Skan      typedef _Rope_char_ref_proxy<_CharT, _Alloc>  reference;
1288169691Skan      typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer;
1289132720Skan
1290169691Skan      rope<_CharT, _Alloc>&
1291169691Skan      container()
1292169691Skan      { return *_M_root_rope; }
1293169691Skan
1294169691Skan      _Rope_iterator()
1295169691Skan      {
1296132720Skan        this->_M_root = 0;  // Needed for reference counting.
1297169691Skan      };
1298169691Skan
1299169691Skan      _Rope_iterator(const _Rope_iterator& __x)
1300169691Skan      : _Rope_iterator_base<_CharT, _Alloc>(__x)
1301169691Skan      {
1302132720Skan        _M_root_rope = __x._M_root_rope;
1303132720Skan        _RopeRep::_S_ref(this->_M_root);
1304169691Skan      }
1305169691Skan
1306169691Skan      _Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos);
1307169691Skan
1308169691Skan      ~_Rope_iterator()
1309169691Skan      { _RopeRep::_S_unref(this->_M_root); }
1310169691Skan
1311169691Skan      _Rope_iterator&
1312169691Skan      operator=(const _Rope_iterator& __x)
1313169691Skan      {
1314132720Skan        _RopeRep* __old = this->_M_root;
1315169691Skan	
1316132720Skan        _RopeRep::_S_ref(__x._M_root);
1317169691Skan        if (0 != __x._M_buf_ptr)
1318169691Skan	  {
1319132720Skan            _M_root_rope = __x._M_root_rope;
1320169691Skan            *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
1321169691Skan	  }
1322169691Skan	else
1323169691Skan	  {
1324132720Skan	    this->_M_current_pos = __x._M_current_pos;
1325132720Skan            this->_M_root = __x._M_root;
1326132720Skan            _M_root_rope = __x._M_root_rope;
1327132720Skan            this->_M_buf_ptr = 0;
1328169691Skan	  }
1329132720Skan        _RopeRep::_S_unref(__old);
1330132720Skan        return(*this);
1331169691Skan      }
1332169691Skan
1333169691Skan      reference
1334169691Skan      operator*()
1335169691Skan      {
1336132720Skan        _M_check();
1337169691Skan        if (0 == this->_M_buf_ptr)
1338169691Skan	  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1339169691Skan						      this->_M_current_pos);
1340169691Skan	else
1341169691Skan	  return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1342169691Skan						      this->_M_current_pos,
1343169691Skan						      *this->_M_buf_ptr);
1344169691Skan      }
1345169691Skan
1346169691Skan      // See above comment.
1347169691Skan      reference
1348169691Skan      operator*() const
1349169691Skan      {
1350169691Skan	return *const_cast<_Rope_iterator&>(*this);
1351169691Skan      }
1352169691Skan
1353169691Skan      _Rope_iterator&
1354169691Skan      operator++()
1355169691Skan      {
1356132720Skan        this->_M_incr(1);
1357132720Skan        return *this;
1358169691Skan      }
1359169691Skan
1360169691Skan      _Rope_iterator&
1361169691Skan      operator+=(ptrdiff_t __n)
1362169691Skan      {
1363169691Skan        if (__n >= 0)
1364169691Skan	  this->_M_incr(__n);
1365169691Skan	else
1366169691Skan	  this->_M_decr(-__n);
1367169691Skan	return *this;
1368169691Skan      }
1369169691Skan
1370169691Skan      _Rope_iterator&
1371169691Skan      operator--()
1372169691Skan      {
1373132720Skan        this->_M_decr(1);
1374132720Skan        return *this;
1375169691Skan      }
1376169691Skan
1377169691Skan      _Rope_iterator&
1378169691Skan      operator-=(ptrdiff_t __n)
1379169691Skan      {
1380169691Skan        if (__n >= 0)
1381169691Skan	  this->_M_decr(__n);
1382169691Skan	else
1383169691Skan	  this->_M_incr(-__n);
1384169691Skan	return *this;
1385169691Skan      }
1386169691Skan
1387169691Skan      _Rope_iterator
1388169691Skan      operator++(int)
1389169691Skan      {
1390132720Skan        size_t __old_pos = this->_M_current_pos;
1391132720Skan        this->_M_incr(1);
1392132720Skan        return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1393169691Skan      }
1394169691Skan
1395169691Skan      _Rope_iterator
1396169691Skan      operator--(int)
1397169691Skan      {
1398132720Skan        size_t __old_pos = this->_M_current_pos;
1399132720Skan        this->_M_decr(1);
1400132720Skan        return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1401169691Skan      }
1402132720Skan
1403169691Skan      reference
1404169691Skan      operator[](ptrdiff_t __n)
1405169691Skan      { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1406169691Skan						    this->_M_current_pos
1407169691Skan						    + __n); }
1408132720Skan
1409169691Skan      template<class _CharT2, class _Alloc2>
1410169691Skan        friend bool
1411169691Skan        operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1412169691Skan		   const _Rope_iterator<_CharT2, _Alloc2>& __y);
1413132720Skan
1414169691Skan      template<class _CharT2, class _Alloc2>
1415169691Skan        friend bool
1416169691Skan        operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1417169691Skan		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1418132720Skan
1419169691Skan      template<class _CharT2, class _Alloc2>
1420169691Skan        friend ptrdiff_t
1421169691Skan        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1422169691Skan		  const _Rope_iterator<_CharT2, _Alloc2>& __y);
1423132720Skan
1424169691Skan      template<class _CharT2, class _Alloc2>
1425169691Skan        friend _Rope_iterator<_CharT2, _Alloc2>
1426169691Skan        operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1427132720Skan
1428169691Skan      template<class _CharT2, class _Alloc2>
1429169691Skan        friend _Rope_iterator<_CharT2, _Alloc2>
1430169691Skan        operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);
1431132720Skan
1432169691Skan      template<class _CharT2, class _Alloc2>
1433169691Skan        friend _Rope_iterator<_CharT2, _Alloc2>
1434169691Skan        operator+(ptrdiff_t __n, const _Rope_iterator<_CharT2, _Alloc2>& __x);
1435169691Skan    };
1436132720Skan
1437169691Skan
1438169691Skan  template <class _CharT, class _Alloc>
1439169691Skan    struct _Rope_base
1440169691Skan    : public _Alloc
1441169691Skan    {
1442169691Skan      typedef _Alloc allocator_type;
1443169691Skan
1444169691Skan      allocator_type
1445169691Skan      get_allocator() const
1446169691Skan      { return *static_cast<const _Alloc*>(this); }
1447169691Skan
1448169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1449169691Skan      // The one in _Base may not be visible due to template rules.
1450169691Skan
1451169691Skan      _Rope_base(_RopeRep* __t, const allocator_type&)
1452169691Skan      : _M_tree_ptr(__t) { }
1453169691Skan
1454169691Skan      _Rope_base(const allocator_type&) { }
1455169691Skan
1456169691Skan      // The only data member of a rope:
1457169691Skan      _RopeRep *_M_tree_ptr;
1458169691Skan
1459169691Skan#define __ROPE_DEFINE_ALLOC(_Tp, __name) \
1460132720Skan        typedef typename \
1461132720Skan          _Alloc::template rebind<_Tp>::other __name##Alloc; \
1462132720Skan        static _Tp* __name##_allocate(size_t __n) \
1463132720Skan          { return __name##Alloc().allocate(__n); } \
1464132720Skan        static void __name##_deallocate(_Tp *__p, size_t __n) \
1465132720Skan          { __name##Alloc().deallocate(__p, __n); }
1466169691Skan      __ROPE_DEFINE_ALLOCS(_Alloc)
1467169691Skan#undef __ROPE_DEFINE_ALLOC
1468132720Skan
1469169691Skan	protected:
1470169691Skan      _Rope_base&
1471169691Skan      operator=(const _Rope_base&);
1472169691Skan      
1473169691Skan      _Rope_base(const _Rope_base&);
1474169691Skan    };
1475132720Skan
1476169691Skan  /**
1477169691Skan   *  This is an SGI extension.
1478169691Skan   *  @ingroup SGIextensions
1479169691Skan   *  @doctodo
1480169691Skan   */
1481169691Skan  template <class _CharT, class _Alloc>
1482169691Skan    class rope : public _Rope_base<_CharT, _Alloc>
1483169691Skan    {
1484132720Skan    public:
1485169691Skan      typedef _CharT value_type;
1486169691Skan      typedef ptrdiff_t difference_type;
1487169691Skan      typedef size_t size_type;
1488169691Skan      typedef _CharT const_reference;
1489169691Skan      typedef const _CharT* const_pointer;
1490169691Skan      typedef _Rope_iterator<_CharT, _Alloc> iterator;
1491169691Skan      typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator;
1492169691Skan      typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1493169691Skan      typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer;
1494132720Skan
1495169691Skan      friend class _Rope_iterator<_CharT, _Alloc>;
1496169691Skan      friend class _Rope_const_iterator<_CharT, _Alloc>;
1497169691Skan      friend struct _Rope_RopeRep<_CharT, _Alloc>;
1498169691Skan      friend class _Rope_iterator_base<_CharT, _Alloc>;
1499169691Skan      friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
1500169691Skan      friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1501169691Skan      friend struct _Rope_RopeSubstring<_CharT, _Alloc>;
1502132720Skan
1503132720Skan    protected:
1504169691Skan      typedef _Rope_base<_CharT, _Alloc> _Base;
1505169691Skan      typedef typename _Base::allocator_type allocator_type;
1506169691Skan      using _Base::_M_tree_ptr;
1507169691Skan      using _Base::get_allocator;
1508169691Skan      typedef __GC_CONST _CharT* _Cstrptr;
1509169691Skan      
1510169691Skan      static _CharT _S_empty_c_str[1];
1511169691Skan      
1512169691Skan      static bool
1513169691Skan      _S_is0(_CharT __c)
1514169691Skan      { return __c == _S_eos((_CharT*)0); }
1515169691Skan      
1516169691Skan      enum { _S_copy_max = 23 };
1517132720Skan                // For strings shorter than _S_copy_max, we copy to
1518132720Skan                // concatenate.
1519132720Skan
1520169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1521169691Skan      typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;
1522169691Skan      typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;
1523169691Skan      typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;
1524169691Skan      typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;
1525132720Skan
1526169691Skan      // Retrieve a character at the indicated position.
1527169691Skan      static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
1528132720Skan
1529169691Skan#ifndef __GC
1530169691Skan      // Obtain a pointer to the character at the indicated position.
1531169691Skan      // The pointer can be used to change the character.
1532169691Skan      // If such a pointer cannot be produced, as is frequently the
1533169691Skan      // case, 0 is returned instead.
1534169691Skan      // (Returns nonzero only if all nodes in the path have a refcount
1535169691Skan      // of 1.)
1536169691Skan      static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
1537169691Skan#endif
1538132720Skan
1539169691Skan      static bool
1540169691Skan      _S_apply_to_pieces(// should be template parameter
1541169691Skan			 _Rope_char_consumer<_CharT>& __c,
1542169691Skan			 const _RopeRep* __r,
1543169691Skan			 size_t __begin, size_t __end);
1544169691Skan                         // begin and end are assumed to be in range.
1545132720Skan
1546169691Skan#ifndef __GC
1547169691Skan      static void
1548169691Skan      _S_unref(_RopeRep* __t)
1549169691Skan      { _RopeRep::_S_unref(__t); }
1550132720Skan
1551169691Skan      static void
1552169691Skan      _S_ref(_RopeRep* __t)
1553169691Skan      { _RopeRep::_S_ref(__t); }
1554132720Skan
1555169691Skan#else /* __GC */
1556169691Skan      static void _S_unref(_RopeRep*) { }
1557169691Skan      static void _S_ref(_RopeRep*) { }
1558169691Skan#endif
1559132720Skan
1560169691Skan#ifdef __GC
1561169691Skan      typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
1562169691Skan#else
1563169691Skan      typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
1564169691Skan#endif
1565169691Skan
1566169691Skan      // _Result is counted in refcount.
1567169691Skan      static _RopeRep* _S_substring(_RopeRep* __base,
1568132720Skan                                    size_t __start, size_t __endp1);
1569132720Skan
1570169691Skan      static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
1571169691Skan					   const _CharT* __iter, size_t __slen);
1572169691Skan      // Concatenate rope and char ptr, copying __s.
1573169691Skan      // Should really take an arbitrary iterator.
1574169691Skan      // Result is counted in refcount.
1575169691Skan      static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
1576169691Skan						 const _CharT* __iter,
1577169691Skan						 size_t __slen)
1578169691Skan	// As above, but one reference to __r is about to be
1579169691Skan	// destroyed.  Thus the pieces may be recycled if all
1580169691Skan	// relevant reference counts are 1.
1581169691Skan#ifdef __GC
1582169691Skan	// We can't really do anything since refcounts are unavailable.
1583169691Skan      { return _S_concat_char_iter(__r, __iter, __slen); }
1584169691Skan#else
1585169691Skan      ;
1586169691Skan#endif
1587132720Skan
1588169691Skan      static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
1589169691Skan      // General concatenation on _RopeRep.  _Result
1590169691Skan      // has refcount of 1.  Adjusts argument refcounts.
1591132720Skan
1592132720Skan   public:
1593169691Skan      void
1594169691Skan      apply_to_pieces(size_t __begin, size_t __end,
1595169691Skan		      _Rope_char_consumer<_CharT>& __c) const
1596169691Skan      { _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); }
1597132720Skan
1598132720Skan   protected:
1599132720Skan
1600169691Skan      static size_t
1601169691Skan      _S_rounded_up_size(size_t __n)
1602169691Skan      { return _RopeLeaf::_S_rounded_up_size(__n); }
1603132720Skan
1604169691Skan      static size_t
1605169691Skan      _S_allocated_capacity(size_t __n)
1606169691Skan      {
1607169691Skan	if (_S_is_basic_char_type((_CharT*)0))
1608169691Skan	  return _S_rounded_up_size(__n) - 1;
1609169691Skan	else
1610169691Skan	  return _S_rounded_up_size(__n);
1611169691Skan	
1612169691Skan      }
1613132720Skan
1614169691Skan      // Allocate and construct a RopeLeaf using the supplied allocator
1615169691Skan      // Takes ownership of s instead of copying.
1616169691Skan      static _RopeLeaf*
1617169691Skan      _S_new_RopeLeaf(__GC_CONST _CharT *__s,
1618169691Skan		      size_t __size, allocator_type __a)
1619169691Skan      {
1620169691Skan	_RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);
1621169691Skan	return new(__space) _RopeLeaf(__s, __size, __a);
1622169691Skan      }
1623132720Skan
1624169691Skan      static _RopeConcatenation*
1625169691Skan      _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,
1626169691Skan			       allocator_type __a)
1627169691Skan      {
1628169691Skan	_RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);
1629169691Skan	return new(__space) _RopeConcatenation(__left, __right, __a);
1630169691Skan      }
1631132720Skan
1632169691Skan      static _RopeFunction*
1633169691Skan      _S_new_RopeFunction(char_producer<_CharT>* __f,
1634169691Skan			  size_t __size, bool __d, allocator_type __a)
1635169691Skan      {
1636169691Skan	_RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);
1637169691Skan	return new(__space) _RopeFunction(__f, __size, __d, __a);
1638169691Skan      }
1639132720Skan
1640169691Skan      static _RopeSubstring*
1641169691Skan      _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,
1642169691Skan			   size_t __l, allocator_type __a)
1643169691Skan      {
1644169691Skan	_RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);
1645169691Skan	return new(__space) _RopeSubstring(__b, __s, __l, __a);
1646169691Skan      }
1647169691Skan      
1648169691Skan      static _RopeLeaf*
1649169691Skan      _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,
1650169691Skan					size_t __size, allocator_type __a)
1651169691Skan#define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \
1652132720Skan                _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a)
1653169691Skan      {
1654169691Skan	if (0 == __size)
1655169691Skan	  return 0;
1656169691Skan	_CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
1657169691Skan	
1658169691Skan	__uninitialized_copy_n_a(__s, __size, __buf, __a);
1659169691Skan	_S_cond_store_eos(__buf[__size]);
1660169691Skan	try
1661169691Skan	  { return _S_new_RopeLeaf(__buf, __size, __a); }
1662169691Skan	catch(...)
1663169691Skan	  {
1664169691Skan	    _RopeRep::__STL_FREE_STRING(__buf, __size, __a);
1665169691Skan	    __throw_exception_again;
1666169691Skan	  }
1667169691Skan      }
1668132720Skan
1669169691Skan      // Concatenation of nonempty strings.
1670169691Skan      // Always builds a concatenation node.
1671169691Skan      // Rebalances if the result is too deep.
1672169691Skan      // Result has refcount 1.
1673169691Skan      // Does not increment left and right ref counts even though
1674169691Skan      // they are referenced.
1675169691Skan      static _RopeRep*
1676169691Skan      _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
1677132720Skan
1678169691Skan      // Concatenation helper functions
1679169691Skan      static _RopeLeaf*
1680169691Skan      _S_leaf_concat_char_iter(_RopeLeaf* __r,
1681169691Skan			       const _CharT* __iter, size_t __slen);
1682169691Skan      // Concatenate by copying leaf.
1683169691Skan      // should take an arbitrary iterator
1684169691Skan      // result has refcount 1.
1685169691Skan#ifndef __GC
1686169691Skan      static _RopeLeaf*
1687169691Skan      _S_destr_leaf_concat_char_iter(_RopeLeaf* __r,
1688169691Skan				     const _CharT* __iter, size_t __slen);
1689169691Skan      // A version that potentially clobbers __r if __r->_M_ref_count == 1.
1690169691Skan#endif
1691132720Skan
1692169691Skan    private:
1693169691Skan      
1694169691Skan      static size_t _S_char_ptr_len(const _CharT* __s);
1695169691Skan      // slightly generalized strlen
1696132720Skan
1697169691Skan      rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
1698169691Skan      : _Base(__t, __a) { }
1699132720Skan
1700132720Skan
1701169691Skan      // Copy __r to the _CharT buffer.
1702169691Skan      // Returns __buffer + __r->_M_size.
1703169691Skan      // Assumes that buffer is uninitialized.
1704169691Skan      static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);
1705132720Skan
1706169691Skan      // Again, with explicit starting position and length.
1707169691Skan      // Assumes that buffer is uninitialized.
1708169691Skan      static _CharT* _S_flatten(_RopeRep* __r,
1709169691Skan				size_t __start, size_t __len,
1710169691Skan				_CharT* __buffer);
1711132720Skan
1712169691Skan      static const unsigned long
1713169691Skan      _S_min_len[__detail::_S_max_rope_depth + 1];
1714169691Skan      
1715169691Skan      static bool
1716169691Skan      _S_is_balanced(_RopeRep* __r)
1717169691Skan      { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
1718132720Skan
1719169691Skan      static bool
1720169691Skan      _S_is_almost_balanced(_RopeRep* __r)
1721169691Skan      { return (__r->_M_depth == 0
1722169691Skan		|| __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
1723132720Skan
1724169691Skan      static bool
1725169691Skan      _S_is_roughly_balanced(_RopeRep* __r)
1726169691Skan      { return (__r->_M_depth <= 1
1727169691Skan		|| __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
1728132720Skan
1729169691Skan      // Assumes the result is not empty.
1730169691Skan      static _RopeRep*
1731169691Skan      _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right)
1732169691Skan      {
1733169691Skan	_RopeRep* __result = _S_concat(__left, __right);
1734169691Skan	if (_S_is_balanced(__result))
1735169691Skan	  __result->_M_is_balanced = true;
1736169691Skan	return __result;
1737169691Skan      }
1738132720Skan
1739169691Skan      // The basic rebalancing operation.  Logically copies the
1740169691Skan      // rope.  The result has refcount of 1.  The client will
1741169691Skan      // usually decrement the reference count of __r.
1742169691Skan      // The result is within height 2 of balanced by the above
1743169691Skan      // definition.
1744169691Skan      static _RopeRep* _S_balance(_RopeRep* __r);
1745132720Skan
1746169691Skan      // Add all unbalanced subtrees to the forest of balanceed trees.
1747169691Skan      // Used only by balance.
1748169691Skan      static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);
1749132720Skan
1750169691Skan      // Add __r to forest, assuming __r is already balanced.
1751169691Skan      static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
1752169691Skan      
1753169691Skan      // Print to stdout, exposing structure
1754169691Skan      static void _S_dump(_RopeRep* __r, int __indent = 0);
1755169691Skan      
1756169691Skan      // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.
1757169691Skan      static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);
1758169691Skan      
1759169691Skan    public:
1760169691Skan      bool
1761169691Skan      empty() const
1762169691Skan      { return 0 == this->_M_tree_ptr; }
1763169691Skan      
1764169691Skan      // Comparison member function.  This is public only for those
1765169691Skan      // clients that need a ternary comparison.  Others
1766169691Skan      // should use the comparison operators below.
1767169691Skan      int
1768169691Skan      compare(const rope& __y) const
1769169691Skan      { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }
1770132720Skan
1771169691Skan      rope(const _CharT* __s, const allocator_type& __a = allocator_type())
1772169691Skan      : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
1773169691Skan					       __a), __a)
1774169691Skan      { }
1775132720Skan
1776169691Skan      rope(const _CharT* __s, size_t __len,
1777169691Skan	   const allocator_type& __a = allocator_type())
1778169691Skan      : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, __a), __a)
1779169691Skan      { }
1780132720Skan
1781169691Skan      // Should perhaps be templatized with respect to the iterator type
1782169691Skan      // and use Sequence_buffer.  (It should perhaps use sequence_buffer
1783169691Skan      // even now.)
1784169691Skan      rope(const _CharT *__s, const _CharT *__e,
1785169691Skan	   const allocator_type& __a = allocator_type())
1786169691Skan      : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, __a), __a)
1787169691Skan      { }
1788132720Skan
1789169691Skan      rope(const const_iterator& __s, const const_iterator& __e,
1790169691Skan	   const allocator_type& __a = allocator_type())
1791169691Skan      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1792169691Skan			   __e._M_current_pos), __a)
1793169691Skan      { }
1794132720Skan
1795169691Skan      rope(const iterator& __s, const iterator& __e,
1796169691Skan	   const allocator_type& __a = allocator_type())
1797169691Skan      : _Base(_S_substring(__s._M_root, __s._M_current_pos,
1798169691Skan			   __e._M_current_pos), __a)
1799169691Skan      { }
1800132720Skan
1801169691Skan      rope(_CharT __c, const allocator_type& __a = allocator_type())
1802169691Skan      : _Base(__a)
1803169691Skan      {
1804169691Skan	_CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));
1805169691Skan	
1806169691Skan	get_allocator().construct(__buf, __c);
1807169691Skan	try
1808169691Skan	  { this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1, __a); }
1809169691Skan	catch(...)
1810169691Skan	  {
1811169691Skan	    _RopeRep::__STL_FREE_STRING(__buf, 1, __a);
1812169691Skan	    __throw_exception_again;
1813169691Skan	  }
1814169691Skan      }
1815132720Skan
1816169691Skan      rope(size_t __n, _CharT __c,
1817169691Skan	   const allocator_type& __a = allocator_type());
1818132720Skan
1819169691Skan      rope(const allocator_type& __a = allocator_type())
1820169691Skan      : _Base(0, __a) { }
1821132720Skan
1822169691Skan      // Construct a rope from a function that can compute its members
1823169691Skan      rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn,
1824169691Skan	   const allocator_type& __a = allocator_type())
1825169691Skan      : _Base(__a)
1826169691Skan      {
1827169691Skan	this->_M_tree_ptr = (0 == __len) ?
1828169691Skan	  0 : _S_new_RopeFunction(__fn, __len, __delete_fn, __a);
1829169691Skan      }
1830132720Skan
1831169691Skan      rope(const rope& __x, const allocator_type& __a = allocator_type())
1832169691Skan      : _Base(__x._M_tree_ptr, __a)
1833169691Skan      { _S_ref(this->_M_tree_ptr); }
1834132720Skan
1835132720Skan      ~rope() throw()
1836169691Skan      { _S_unref(this->_M_tree_ptr); }
1837132720Skan
1838169691Skan      rope&
1839169691Skan      operator=(const rope& __x)
1840169691Skan      {
1841169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1842169691Skan	this->_M_tree_ptr = __x._M_tree_ptr;
1843169691Skan	_S_ref(this->_M_tree_ptr);
1844169691Skan	_S_unref(__old);
1845169691Skan	return *this;
1846169691Skan      }
1847132720Skan
1848169691Skan      void
1849169691Skan      clear()
1850169691Skan      {
1851169691Skan	_S_unref(this->_M_tree_ptr);
1852169691Skan	this->_M_tree_ptr = 0;
1853169691Skan      }
1854169691Skan      
1855169691Skan      void
1856169691Skan      push_back(_CharT __x)
1857169691Skan      {
1858169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1859169691Skan	this->_M_tree_ptr
1860169691Skan	  = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);
1861169691Skan	_S_unref(__old);
1862169691Skan      }
1863132720Skan
1864169691Skan      void
1865169691Skan      pop_back()
1866169691Skan      {
1867169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1868169691Skan	this->_M_tree_ptr = _S_substring(this->_M_tree_ptr,
1869169691Skan					 0, this->_M_tree_ptr->_M_size - 1);
1870169691Skan	_S_unref(__old);
1871169691Skan      }
1872132720Skan
1873169691Skan      _CharT
1874169691Skan      back() const
1875169691Skan      { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }
1876132720Skan
1877169691Skan      void
1878169691Skan      push_front(_CharT __x)
1879169691Skan      {
1880169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1881169691Skan	_RopeRep* __left =
1882169691Skan	  __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, this->get_allocator());
1883169691Skan	try
1884169691Skan	  {
1885169691Skan	    this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
1886169691Skan	    _S_unref(__old);
1887169691Skan	    _S_unref(__left);
1888169691Skan	  }
1889169691Skan	catch(...)
1890169691Skan	  {
1891169691Skan	    _S_unref(__left);
1892169691Skan	    __throw_exception_again;
1893169691Skan	  }
1894169691Skan      }
1895132720Skan
1896169691Skan      void
1897169691Skan      pop_front()
1898169691Skan      {
1899169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1900169691Skan	this->_M_tree_ptr
1901169691Skan	  = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
1902169691Skan	_S_unref(__old);
1903169691Skan      }
1904132720Skan
1905169691Skan      _CharT
1906169691Skan      front() const
1907169691Skan      { return _S_fetch(this->_M_tree_ptr, 0); }
1908132720Skan
1909169691Skan      void
1910169691Skan      balance()
1911169691Skan      {
1912169691Skan	_RopeRep* __old = this->_M_tree_ptr;
1913169691Skan	this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
1914169691Skan	_S_unref(__old);
1915169691Skan      }
1916169691Skan      
1917169691Skan      void
1918169691Skan      copy(_CharT* __buffer) const
1919169691Skan      {
1920169691Skan	_Destroy(__buffer, __buffer + size(), get_allocator());
1921169691Skan	_S_flatten(this->_M_tree_ptr, __buffer);
1922169691Skan      }
1923132720Skan
1924169691Skan      // This is the copy function from the standard, but
1925169691Skan      // with the arguments reordered to make it consistent with the
1926169691Skan      // rest of the interface.
1927169691Skan      // Note that this guaranteed not to compile if the draft standard
1928169691Skan      // order is assumed.
1929169691Skan      size_type
1930169691Skan      copy(size_type __pos, size_type __n, _CharT* __buffer) const
1931169691Skan      {
1932169691Skan	size_t __size = size();
1933169691Skan	size_t __len = (__pos + __n > __size? __size - __pos : __n);
1934169691Skan	
1935169691Skan	_Destroy(__buffer, __buffer + __len, get_allocator());
1936169691Skan	_S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);
1937169691Skan	return __len;
1938169691Skan      }
1939132720Skan
1940169691Skan      // Print to stdout, exposing structure.  May be useful for
1941169691Skan      // performance debugging.
1942169691Skan      void
1943169691Skan      dump()
1944169691Skan      { _S_dump(this->_M_tree_ptr); }
1945169691Skan      
1946169691Skan      // Convert to 0 terminated string in new allocated memory.
1947169691Skan      // Embedded 0s in the input do not terminate the copy.
1948169691Skan      const _CharT* c_str() const;
1949132720Skan
1950169691Skan      // As above, but lso use the flattened representation as the
1951169691Skan      // the new rope representation.
1952169691Skan      const _CharT* replace_with_c_str();
1953169691Skan      
1954169691Skan      // Reclaim memory for the c_str generated flattened string.
1955169691Skan      // Intentionally undocumented, since it's hard to say when this
1956169691Skan      // is safe for multiple threads.
1957169691Skan      void
1958169691Skan      delete_c_str ()
1959169691Skan      {
1960169691Skan	if (0 == this->_M_tree_ptr)
1961169691Skan	  return;
1962169691Skan	if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag &&
1963169691Skan	    ((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==
1964169691Skan	    this->_M_tree_ptr->_M_c_string)
1965169691Skan	  {
1966169691Skan	    // Representation shared
1967169691Skan	    return;
1968169691Skan	  }
1969169691Skan#ifndef __GC
1970169691Skan	this->_M_tree_ptr->_M_free_c_string();
1971169691Skan#endif
1972169691Skan	this->_M_tree_ptr->_M_c_string = 0;
1973169691Skan      }
1974132720Skan
1975169691Skan      _CharT
1976169691Skan      operator[] (size_type __pos) const
1977169691Skan      { return _S_fetch(this->_M_tree_ptr, __pos); }
1978132720Skan
1979169691Skan      _CharT
1980169691Skan      at(size_type __pos) const
1981169691Skan      {
1982169691Skan	// if (__pos >= size()) throw out_of_range;  // XXX
1983169691Skan	return (*this)[__pos];
1984169691Skan      }
1985132720Skan
1986169691Skan      const_iterator
1987169691Skan      begin() const
1988169691Skan      { return(const_iterator(this->_M_tree_ptr, 0)); }
1989132720Skan
1990169691Skan      // An easy way to get a const iterator from a non-const container.
1991169691Skan      const_iterator
1992169691Skan      const_begin() const
1993169691Skan      { return(const_iterator(this->_M_tree_ptr, 0)); }
1994132720Skan
1995169691Skan      const_iterator
1996169691Skan      end() const
1997169691Skan      { return(const_iterator(this->_M_tree_ptr, size())); }
1998132720Skan
1999169691Skan      const_iterator
2000169691Skan      const_end() const
2001169691Skan      { return(const_iterator(this->_M_tree_ptr, size())); }
2002132720Skan
2003169691Skan      size_type
2004169691Skan      size() const
2005169691Skan      {	return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }
2006169691Skan      
2007169691Skan      size_type
2008169691Skan      length() const
2009169691Skan      {	return size(); }
2010132720Skan
2011169691Skan      size_type
2012169691Skan      max_size() const
2013169691Skan      {
2014169691Skan	return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1;
2015169691Skan	//  Guarantees that the result can be sufficirntly
2016169691Skan	//  balanced.  Longer ropes will probably still work,
2017169691Skan	//  but it's harder to make guarantees.
2018169691Skan      }
2019132720Skan
2020169691Skan      typedef reverse_iterator<const_iterator> const_reverse_iterator;
2021132720Skan
2022169691Skan      const_reverse_iterator
2023169691Skan      rbegin() const
2024169691Skan      { return const_reverse_iterator(end()); }
2025132720Skan
2026169691Skan      const_reverse_iterator
2027169691Skan      const_rbegin() const
2028169691Skan      {	return const_reverse_iterator(end()); }
2029132720Skan
2030169691Skan      const_reverse_iterator
2031169691Skan      rend() const
2032169691Skan      { return const_reverse_iterator(begin()); }
2033169691Skan      
2034169691Skan      const_reverse_iterator
2035169691Skan      const_rend() const
2036169691Skan      {	return const_reverse_iterator(begin()); }
2037132720Skan
2038169691Skan      template<class _CharT2, class _Alloc2>
2039169691Skan        friend rope<_CharT2, _Alloc2>
2040169691Skan        operator+(const rope<_CharT2, _Alloc2>& __left,
2041169691Skan		  const rope<_CharT2, _Alloc2>& __right);
2042132720Skan
2043169691Skan      template<class _CharT2, class _Alloc2>
2044169691Skan        friend rope<_CharT2, _Alloc2>
2045169691Skan        operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);
2046132720Skan
2047169691Skan      template<class _CharT2, class _Alloc2>
2048169691Skan        friend rope<_CharT2, _Alloc2>
2049169691Skan        operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);
2050132720Skan
2051169691Skan      // The symmetric cases are intentionally omitted, since they're
2052169691Skan      // presumed to be less common, and we don't handle them as well.
2053132720Skan
2054169691Skan      // The following should really be templatized.  The first
2055169691Skan      // argument should be an input iterator or forward iterator with
2056169691Skan      // value_type _CharT.
2057169691Skan      rope&
2058169691Skan      append(const _CharT* __iter, size_t __n)
2059169691Skan      {
2060169691Skan	_RopeRep* __result =
2061169691Skan	  _S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n);
2062169691Skan	_S_unref(this->_M_tree_ptr);
2063169691Skan	this->_M_tree_ptr = __result;
2064169691Skan	return *this;
2065169691Skan      }
2066132720Skan
2067169691Skan      rope&
2068169691Skan      append(const _CharT* __c_string)
2069169691Skan      {
2070169691Skan	size_t __len = _S_char_ptr_len(__c_string);
2071169691Skan	append(__c_string, __len);
2072169691Skan	return(*this);
2073169691Skan      }
2074132720Skan
2075169691Skan      rope&
2076169691Skan      append(const _CharT* __s, const _CharT* __e)
2077169691Skan      {
2078169691Skan	_RopeRep* __result =
2079169691Skan	  _S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s);
2080169691Skan	_S_unref(this->_M_tree_ptr);
2081169691Skan	this->_M_tree_ptr = __result;
2082169691Skan	return *this;
2083169691Skan      }
2084132720Skan
2085169691Skan      rope&
2086169691Skan      append(const_iterator __s, const_iterator __e)
2087169691Skan      {
2088169691Skan	_Self_destruct_ptr __appendee(_S_substring(__s._M_root,
2089169691Skan						   __s._M_current_pos,
2090169691Skan						   __e._M_current_pos));
2091169691Skan	_RopeRep* __result = _S_concat(this->_M_tree_ptr, 
2092169691Skan				       (_RopeRep*)__appendee);
2093169691Skan	_S_unref(this->_M_tree_ptr);
2094169691Skan	this->_M_tree_ptr = __result;
2095169691Skan	return *this;
2096169691Skan      }
2097132720Skan
2098169691Skan      rope&
2099169691Skan      append(_CharT __c)
2100169691Skan      {
2101169691Skan	_RopeRep* __result =
2102169691Skan	  _S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1);
2103169691Skan	_S_unref(this->_M_tree_ptr);
2104169691Skan	this->_M_tree_ptr = __result;
2105169691Skan	return *this;
2106169691Skan      }
2107132720Skan
2108169691Skan      rope&
2109169691Skan      append()
2110169691Skan      { return append(_CharT()); }  // XXX why?
2111132720Skan
2112169691Skan      rope&
2113169691Skan      append(const rope& __y)
2114169691Skan      {
2115169691Skan	_RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr);
2116169691Skan	_S_unref(this->_M_tree_ptr);
2117169691Skan	this->_M_tree_ptr = __result;
2118169691Skan	return *this;
2119169691Skan      }
2120132720Skan
2121169691Skan      rope&
2122169691Skan      append(size_t __n, _CharT __c)
2123169691Skan      {
2124169691Skan	rope<_CharT,_Alloc> __last(__n, __c);
2125169691Skan	return append(__last);
2126169691Skan      }
2127132720Skan
2128169691Skan      void
2129169691Skan      swap(rope& __b)
2130169691Skan      {
2131169691Skan	_RopeRep* __tmp = this->_M_tree_ptr;
2132169691Skan	this->_M_tree_ptr = __b._M_tree_ptr;
2133169691Skan	__b._M_tree_ptr = __tmp;
2134169691Skan      }
2135132720Skan
2136132720Skan    protected:
2137169691Skan      // Result is included in refcount.
2138169691Skan      static _RopeRep*
2139169691Skan      replace(_RopeRep* __old, size_t __pos1,
2140169691Skan	      size_t __pos2, _RopeRep* __r)
2141169691Skan      {
2142169691Skan	if (0 == __old)
2143169691Skan	  {
2144169691Skan	    _S_ref(__r);
2145169691Skan	    return __r;
2146169691Skan	  }
2147169691Skan	_Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));
2148169691Skan	_Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));
2149169691Skan	_RopeRep* __result;
2150132720Skan
2151169691Skan	if (0 == __r)
2152169691Skan	  __result = _S_concat(__left, __right);
2153169691Skan	else
2154169691Skan	  {
2155169691Skan	    _Self_destruct_ptr __left_result(_S_concat(__left, __r));
2156169691Skan	    __result = _S_concat(__left_result, __right);
2157169691Skan	  }
2158169691Skan	return __result;
2159169691Skan      }
2160132720Skan
2161132720Skan    public:
2162169691Skan      void
2163169691Skan      insert(size_t __p, const rope& __r)
2164169691Skan      {
2165169691Skan	_RopeRep* __result =
2166169691Skan	  replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr);
2167169691Skan	_S_unref(this->_M_tree_ptr);
2168169691Skan	this->_M_tree_ptr = __result;
2169169691Skan      }
2170132720Skan
2171169691Skan      void
2172169691Skan      insert(size_t __p, size_t __n, _CharT __c)
2173169691Skan      {
2174169691Skan	rope<_CharT,_Alloc> __r(__n,__c);
2175169691Skan	insert(__p, __r);
2176169691Skan      }
2177169691Skan      
2178169691Skan      void
2179169691Skan      insert(size_t __p, const _CharT* __i, size_t __n)
2180169691Skan      {
2181169691Skan	_Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
2182169691Skan	_Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
2183169691Skan						__p, size()));
2184169691Skan	_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n));
2185169691Skan	// _S_ destr_concat_char_iter should be safe here.
2186169691Skan	// But as it stands it's probably not a win, since __left
2187169691Skan	// is likely to have additional references.
2188169691Skan	_RopeRep* __result = _S_concat(__left_result, __right);
2189169691Skan	_S_unref(this->_M_tree_ptr);
2190169691Skan	this->_M_tree_ptr = __result;
2191169691Skan      }
2192132720Skan
2193169691Skan      void
2194169691Skan      insert(size_t __p, const _CharT* __c_string)
2195169691Skan      {	insert(__p, __c_string, _S_char_ptr_len(__c_string)); }
2196132720Skan
2197169691Skan      void
2198169691Skan      insert(size_t __p, _CharT __c)
2199169691Skan      { insert(__p, &__c, 1); }
2200132720Skan
2201169691Skan      void
2202169691Skan      insert(size_t __p)
2203169691Skan      {
2204169691Skan	_CharT __c = _CharT();
2205169691Skan	insert(__p, &__c, 1);
2206169691Skan      }
2207132720Skan
2208169691Skan      void
2209169691Skan      insert(size_t __p, const _CharT* __i, const _CharT* __j)
2210169691Skan      {
2211169691Skan	rope __r(__i, __j);
2212169691Skan	insert(__p, __r);
2213169691Skan      }
2214132720Skan
2215169691Skan      void
2216169691Skan      insert(size_t __p, const const_iterator& __i,
2217169691Skan	     const const_iterator& __j)
2218169691Skan      {
2219169691Skan	rope __r(__i, __j);
2220169691Skan	insert(__p, __r);
2221169691Skan      }
2222132720Skan
2223169691Skan      void
2224169691Skan      insert(size_t __p, const iterator& __i,
2225169691Skan	     const iterator& __j)
2226169691Skan      {
2227169691Skan	rope __r(__i, __j);
2228169691Skan	insert(__p, __r);
2229169691Skan      }
2230132720Skan
2231169691Skan      // (position, length) versions of replace operations:
2232169691Skan      
2233169691Skan      void
2234169691Skan      replace(size_t __p, size_t __n, const rope& __r)
2235169691Skan      {
2236169691Skan	_RopeRep* __result =
2237169691Skan	  replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);
2238169691Skan	_S_unref(this->_M_tree_ptr);
2239169691Skan	this->_M_tree_ptr = __result;
2240169691Skan      }
2241132720Skan
2242169691Skan      void
2243169691Skan      replace(size_t __p, size_t __n,
2244169691Skan	      const _CharT* __i, size_t __i_len)
2245169691Skan      {
2246169691Skan	rope __r(__i, __i_len);
2247169691Skan	replace(__p, __n, __r);
2248169691Skan      }
2249132720Skan
2250169691Skan      void
2251169691Skan      replace(size_t __p, size_t __n, _CharT __c)
2252169691Skan      {
2253169691Skan	rope __r(__c);
2254169691Skan	replace(__p, __n, __r);
2255169691Skan      }
2256132720Skan
2257169691Skan      void
2258169691Skan      replace(size_t __p, size_t __n, const _CharT* __c_string)
2259169691Skan      {
2260169691Skan	rope __r(__c_string);
2261169691Skan	replace(__p, __n, __r);
2262169691Skan      }
2263169691Skan      
2264169691Skan      void
2265169691Skan      replace(size_t __p, size_t __n,
2266169691Skan	      const _CharT* __i, const _CharT* __j)
2267169691Skan      {
2268169691Skan	rope __r(__i, __j);
2269169691Skan	replace(__p, __n, __r);
2270169691Skan      }
2271169691Skan      
2272169691Skan      void
2273169691Skan      replace(size_t __p, size_t __n,
2274169691Skan	      const const_iterator& __i, const const_iterator& __j)
2275169691Skan      {
2276169691Skan	rope __r(__i, __j);
2277169691Skan	replace(__p, __n, __r);
2278169691Skan      }
2279132720Skan
2280169691Skan      void
2281169691Skan      replace(size_t __p, size_t __n,
2282169691Skan	      const iterator& __i, const iterator& __j)
2283169691Skan      {
2284169691Skan	rope __r(__i, __j);
2285169691Skan	replace(__p, __n, __r);
2286169691Skan      }
2287132720Skan
2288169691Skan      // Single character variants:
2289169691Skan      void
2290169691Skan      replace(size_t __p, _CharT __c)
2291169691Skan      {
2292169691Skan	iterator __i(this, __p);
2293169691Skan	*__i = __c;
2294169691Skan      }
2295132720Skan
2296169691Skan      void
2297169691Skan      replace(size_t __p, const rope& __r)
2298169691Skan      { replace(__p, 1, __r); }
2299132720Skan
2300169691Skan      void
2301169691Skan      replace(size_t __p, const _CharT* __i, size_t __i_len)
2302169691Skan      { replace(__p, 1, __i, __i_len); }
2303132720Skan
2304169691Skan      void
2305169691Skan      replace(size_t __p, const _CharT* __c_string)
2306169691Skan      {	replace(__p, 1, __c_string); }
2307132720Skan
2308169691Skan      void
2309169691Skan      replace(size_t __p, const _CharT* __i, const _CharT* __j)
2310169691Skan      {	replace(__p, 1, __i, __j); }
2311132720Skan
2312169691Skan      void
2313169691Skan      replace(size_t __p, const const_iterator& __i,
2314169691Skan	      const const_iterator& __j)
2315169691Skan      { replace(__p, 1, __i, __j); }
2316132720Skan
2317169691Skan      void
2318169691Skan      replace(size_t __p, const iterator& __i,
2319169691Skan	      const iterator& __j)
2320169691Skan      { replace(__p, 1, __i, __j); }
2321132720Skan
2322169691Skan      // Erase, (position, size) variant.
2323169691Skan      void
2324169691Skan      erase(size_t __p, size_t __n)
2325169691Skan      {
2326169691Skan	_RopeRep* __result = replace(this->_M_tree_ptr, __p,
2327169691Skan				     __p + __n, 0);
2328169691Skan	_S_unref(this->_M_tree_ptr);
2329169691Skan	this->_M_tree_ptr = __result;
2330169691Skan      }
2331132720Skan
2332169691Skan      // Erase, single character
2333169691Skan      void
2334169691Skan      erase(size_t __p)
2335169691Skan      { erase(__p, __p + 1); }
2336132720Skan
2337169691Skan      // Insert, iterator variants.
2338169691Skan      iterator
2339169691Skan      insert(const iterator& __p, const rope& __r)
2340169691Skan      {
2341169691Skan	insert(__p.index(), __r);
2342169691Skan	return __p;
2343169691Skan      }
2344132720Skan
2345169691Skan      iterator
2346169691Skan      insert(const iterator& __p, size_t __n, _CharT __c)
2347169691Skan      {
2348169691Skan	insert(__p.index(), __n, __c);
2349169691Skan	return __p;
2350169691Skan      }
2351132720Skan
2352169691Skan      iterator insert(const iterator& __p, _CharT __c)
2353169691Skan      {
2354169691Skan	insert(__p.index(), __c);
2355169691Skan	return __p;
2356169691Skan      }
2357169691Skan      
2358169691Skan      iterator
2359169691Skan      insert(const iterator& __p )
2360169691Skan      {
2361169691Skan	insert(__p.index());
2362169691Skan	return __p;
2363169691Skan      }
2364169691Skan      
2365169691Skan      iterator
2366169691Skan      insert(const iterator& __p, const _CharT* c_string)
2367169691Skan      {
2368169691Skan	insert(__p.index(), c_string);
2369169691Skan	return __p;
2370169691Skan      }
2371169691Skan      
2372169691Skan      iterator
2373169691Skan      insert(const iterator& __p, const _CharT* __i, size_t __n)
2374169691Skan      {
2375169691Skan	insert(__p.index(), __i, __n);
2376169691Skan	return __p;
2377169691Skan      }
2378169691Skan      
2379169691Skan      iterator
2380169691Skan      insert(const iterator& __p, const _CharT* __i,
2381169691Skan	     const _CharT* __j)
2382169691Skan      {
2383169691Skan	insert(__p.index(), __i, __j); 
2384169691Skan	return __p;
2385169691Skan      }
2386169691Skan      
2387169691Skan      iterator
2388169691Skan      insert(const iterator& __p,
2389169691Skan	     const const_iterator& __i, const const_iterator& __j)
2390169691Skan      {
2391169691Skan	insert(__p.index(), __i, __j);
2392169691Skan	return __p;
2393169691Skan      }
2394169691Skan      
2395169691Skan      iterator
2396169691Skan      insert(const iterator& __p,
2397169691Skan	     const iterator& __i, const iterator& __j)
2398169691Skan      {
2399169691Skan	insert(__p.index(), __i, __j);
2400169691Skan	return __p;
2401169691Skan      }
2402132720Skan
2403169691Skan      // Replace, range variants.
2404169691Skan      void
2405169691Skan      replace(const iterator& __p, const iterator& __q, const rope& __r)
2406169691Skan      {	replace(__p.index(), __q.index() - __p.index(), __r); }
2407132720Skan
2408169691Skan      void
2409169691Skan      replace(const iterator& __p, const iterator& __q, _CharT __c)
2410169691Skan      { replace(__p.index(), __q.index() - __p.index(), __c); }
2411169691Skan      
2412169691Skan      void
2413169691Skan      replace(const iterator& __p, const iterator& __q,
2414169691Skan	      const _CharT* __c_string)
2415169691Skan      { replace(__p.index(), __q.index() - __p.index(), __c_string); }
2416169691Skan      
2417169691Skan      void
2418169691Skan      replace(const iterator& __p, const iterator& __q,
2419169691Skan	      const _CharT* __i, size_t __n)
2420169691Skan      { replace(__p.index(), __q.index() - __p.index(), __i, __n); }
2421169691Skan      
2422169691Skan      void
2423169691Skan      replace(const iterator& __p, const iterator& __q,
2424169691Skan	      const _CharT* __i, const _CharT* __j)
2425169691Skan      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2426169691Skan      
2427169691Skan      void
2428169691Skan      replace(const iterator& __p, const iterator& __q,
2429169691Skan	      const const_iterator& __i, const const_iterator& __j)
2430169691Skan      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2431169691Skan      
2432169691Skan      void
2433169691Skan      replace(const iterator& __p, const iterator& __q,
2434169691Skan	      const iterator& __i, const iterator& __j)
2435169691Skan      { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
2436132720Skan
2437169691Skan      // Replace, iterator variants.
2438169691Skan      void
2439169691Skan      replace(const iterator& __p, const rope& __r)
2440169691Skan      { replace(__p.index(), __r); }
2441169691Skan      
2442169691Skan      void
2443169691Skan      replace(const iterator& __p, _CharT __c)
2444169691Skan      { replace(__p.index(), __c); }
2445169691Skan      
2446169691Skan      void
2447169691Skan      replace(const iterator& __p, const _CharT* __c_string)
2448169691Skan      { replace(__p.index(), __c_string); }
2449169691Skan      
2450169691Skan      void
2451169691Skan      replace(const iterator& __p, const _CharT* __i, size_t __n)
2452169691Skan      { replace(__p.index(), __i, __n); }
2453169691Skan      
2454169691Skan      void
2455169691Skan      replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
2456169691Skan      { replace(__p.index(), __i, __j); }
2457169691Skan      
2458169691Skan      void
2459169691Skan      replace(const iterator& __p, const_iterator __i, const_iterator __j)
2460169691Skan      { replace(__p.index(), __i, __j); }
2461169691Skan      
2462169691Skan      void
2463169691Skan      replace(const iterator& __p, iterator __i, iterator __j)
2464169691Skan      { replace(__p.index(), __i, __j); }
2465132720Skan
2466169691Skan      // Iterator and range variants of erase
2467169691Skan      iterator
2468169691Skan      erase(const iterator& __p, const iterator& __q)
2469169691Skan      {
2470169691Skan	size_t __p_index = __p.index();
2471169691Skan	erase(__p_index, __q.index() - __p_index);
2472169691Skan	return iterator(this, __p_index);
2473169691Skan      }
2474132720Skan
2475169691Skan      iterator
2476169691Skan      erase(const iterator& __p)
2477169691Skan      {
2478169691Skan	size_t __p_index = __p.index();
2479169691Skan	erase(__p_index, 1);
2480169691Skan	return iterator(this, __p_index);
2481169691Skan      }
2482132720Skan
2483169691Skan      rope
2484169691Skan      substr(size_t __start, size_t __len = 1) const
2485169691Skan      {
2486169691Skan	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2487169691Skan						 __start,
2488169691Skan						 __start + __len));
2489169691Skan      }
2490132720Skan
2491169691Skan      rope
2492169691Skan      substr(iterator __start, iterator __end) const
2493169691Skan      {
2494169691Skan	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2495169691Skan						 __start.index(),
2496169691Skan						 __end.index()));
2497169691Skan      }
2498132720Skan
2499169691Skan      rope
2500169691Skan      substr(iterator __start) const
2501169691Skan      {
2502169691Skan	size_t __pos = __start.index();
2503169691Skan	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2504169691Skan						 __pos, __pos + 1));
2505169691Skan      }
2506132720Skan
2507169691Skan      rope
2508169691Skan      substr(const_iterator __start, const_iterator __end) const
2509169691Skan      {
2510169691Skan	// This might eventually take advantage of the cache in the
2511169691Skan	// iterator.
2512169691Skan	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2513169691Skan						 __start.index(),
2514169691Skan						 __end.index()));
2515169691Skan      }
2516132720Skan
2517169691Skan      rope<_CharT, _Alloc>
2518169691Skan      substr(const_iterator __start)
2519169691Skan      {
2520169691Skan	size_t __pos = __start.index();
2521169691Skan	return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2522169691Skan						 __pos, __pos + 1));
2523169691Skan      }
2524132720Skan
2525169691Skan      static const size_type npos;
2526132720Skan
2527169691Skan      size_type find(_CharT __c, size_type __pos = 0) const;
2528132720Skan
2529169691Skan      size_type
2530169691Skan      find(const _CharT* __s, size_type __pos = 0) const
2531169691Skan      {
2532169691Skan	size_type __result_pos;
2533169691Skan	const_iterator __result =
2534169691Skan	  std::search(const_begin() + __pos, const_end(),
2535169691Skan		      __s, __s + _S_char_ptr_len(__s));
2536169691Skan	__result_pos = __result.index();
2537169691Skan#ifndef __STL_OLD_ROPE_SEMANTICS
2538169691Skan	if (__result_pos == size())
2539169691Skan	  __result_pos = npos;
2540169691Skan#endif
2541169691Skan	return __result_pos;
2542169691Skan      }
2543132720Skan
2544169691Skan      iterator
2545169691Skan      mutable_begin()
2546169691Skan      { return(iterator(this, 0)); }
2547169691Skan      
2548169691Skan      iterator
2549169691Skan      mutable_end()
2550169691Skan      { return(iterator(this, size())); }
2551132720Skan
2552169691Skan      typedef reverse_iterator<iterator> reverse_iterator;
2553169691Skan      
2554169691Skan      reverse_iterator
2555169691Skan      mutable_rbegin()
2556169691Skan      { return reverse_iterator(mutable_end()); }
2557132720Skan
2558169691Skan      reverse_iterator
2559169691Skan      mutable_rend()
2560169691Skan      { return reverse_iterator(mutable_begin()); }
2561132720Skan
2562169691Skan      reference
2563169691Skan      mutable_reference_at(size_type __pos)
2564169691Skan      { return reference(this, __pos); }
2565132720Skan
2566169691Skan#ifdef __STD_STUFF
2567169691Skan      reference
2568169691Skan      operator[] (size_type __pos)
2569169691Skan      { return _char_ref_proxy(this, __pos); }
2570132720Skan
2571169691Skan      reference
2572169691Skan      at(size_type __pos)
2573169691Skan      {
2574169691Skan	// if (__pos >= size()) throw out_of_range;  // XXX
2575169691Skan	return (*this)[__pos];
2576169691Skan      }
2577169691Skan      
2578169691Skan      void resize(size_type __n, _CharT __c) { }
2579169691Skan      void resize(size_type __n) { }
2580169691Skan      void reserve(size_type __res_arg = 0) { }
2581169691Skan      
2582169691Skan      size_type
2583169691Skan      capacity() const
2584169691Skan      { return max_size(); }
2585132720Skan
2586169691Skan      // Stuff below this line is dangerous because it's error prone.
2587169691Skan      // I would really like to get rid of it.
2588169691Skan      // copy function with funny arg ordering.
2589169691Skan      size_type
2590169691Skan      copy(_CharT* __buffer, size_type __n,
2591169691Skan	   size_type __pos = 0) const
2592169691Skan      { return copy(__pos, __n, __buffer); }
2593132720Skan
2594169691Skan      iterator
2595169691Skan      end()
2596169691Skan      { return mutable_end(); }
2597132720Skan
2598169691Skan      iterator
2599169691Skan      begin()
2600169691Skan      { return mutable_begin(); }
2601132720Skan
2602169691Skan      reverse_iterator
2603169691Skan      rend()
2604169691Skan      { return mutable_rend(); }
2605169691Skan      
2606169691Skan      reverse_iterator
2607169691Skan      rbegin()
2608169691Skan      { return mutable_rbegin(); }
2609132720Skan
2610169691Skan#else
2611169691Skan      const_iterator
2612169691Skan      end()
2613169691Skan      { return const_end(); }
2614132720Skan
2615169691Skan      const_iterator
2616169691Skan      begin()
2617169691Skan      { return const_begin(); }
2618132720Skan
2619169691Skan      const_reverse_iterator
2620169691Skan      rend()
2621169691Skan      { return const_rend(); }
2622132720Skan
2623169691Skan      const_reverse_iterator
2624169691Skan      rbegin()
2625169691Skan      { return const_rbegin(); }
2626132720Skan
2627169691Skan#endif
2628169691Skan    };
2629132720Skan
2630169691Skan  template <class _CharT, class _Alloc>
2631169691Skan    const typename rope<_CharT, _Alloc>::size_type
2632169691Skan    rope<_CharT, _Alloc>::npos = (size_type)(-1);
2633169691Skan  
2634169691Skan  template <class _CharT, class _Alloc>
2635169691Skan    inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2636169691Skan			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2637169691Skan    { return (__x._M_current_pos == __y._M_current_pos
2638169691Skan	      && __x._M_root == __y._M_root); }
2639132720Skan
2640169691Skan  template <class _CharT, class _Alloc>
2641169691Skan    inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2642169691Skan			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2643169691Skan    { return (__x._M_current_pos < __y._M_current_pos); }
2644132720Skan
2645169691Skan  template <class _CharT, class _Alloc>
2646169691Skan    inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2647169691Skan			   const _Rope_const_iterator<_CharT, _Alloc>& __y)
2648169691Skan    { return !(__x == __y); }
2649132720Skan
2650169691Skan  template <class _CharT, class _Alloc>
2651169691Skan    inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2652169691Skan			  const _Rope_const_iterator<_CharT, _Alloc>& __y)
2653169691Skan    { return __y < __x; }
2654132720Skan
2655169691Skan  template <class _CharT, class _Alloc>
2656169691Skan    inline bool
2657169691Skan    operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2658169691Skan	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2659169691Skan    { return !(__y < __x); }
2660132720Skan
2661169691Skan  template <class _CharT, class _Alloc>
2662169691Skan    inline bool
2663169691Skan    operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2664169691Skan	       const _Rope_const_iterator<_CharT, _Alloc>& __y)
2665169691Skan    { return !(__x < __y); }
2666132720Skan
2667169691Skan  template <class _CharT, class _Alloc>
2668169691Skan    inline ptrdiff_t
2669169691Skan    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2670169691Skan	      const _Rope_const_iterator<_CharT, _Alloc>& __y)
2671169691Skan    { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; }
2672132720Skan
2673169691Skan  template <class _CharT, class _Alloc>
2674169691Skan    inline _Rope_const_iterator<_CharT, _Alloc>
2675169691Skan    operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2676169691Skan    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2677169691Skan						  __x._M_current_pos - __n); }
2678132720Skan
2679169691Skan  template <class _CharT, class _Alloc>
2680169691Skan    inline _Rope_const_iterator<_CharT, _Alloc>
2681169691Skan    operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2682169691Skan    { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2683169691Skan						  __x._M_current_pos + __n); }
2684132720Skan
2685169691Skan  template <class _CharT, class _Alloc>
2686169691Skan    inline _Rope_const_iterator<_CharT, _Alloc>
2687169691Skan    operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x)
2688169691Skan  { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2689169691Skan						__x._M_current_pos + __n); }
2690132720Skan
2691169691Skan  template <class _CharT, class _Alloc>
2692169691Skan    inline bool
2693169691Skan    operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
2694169691Skan	       const _Rope_iterator<_CharT, _Alloc>& __y)
2695169691Skan    {return (__x._M_current_pos == __y._M_current_pos
2696169691Skan	     && __x._M_root_rope == __y._M_root_rope); }
2697169691Skan  
2698169691Skan  template <class _CharT, class _Alloc>
2699169691Skan    inline bool
2700169691Skan    operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
2701169691Skan	      const _Rope_iterator<_CharT, _Alloc>& __y)
2702169691Skan    { return (__x._M_current_pos < __y._M_current_pos); }
2703132720Skan
2704169691Skan  template <class _CharT, class _Alloc>
2705169691Skan    inline bool
2706169691Skan    operator!=(const _Rope_iterator<_CharT, _Alloc>& __x,
2707169691Skan	       const _Rope_iterator<_CharT, _Alloc>& __y)
2708169691Skan    { return !(__x == __y); }
2709132720Skan
2710169691Skan  template <class _CharT, class _Alloc>
2711169691Skan    inline bool
2712169691Skan    operator>(const _Rope_iterator<_CharT, _Alloc>& __x,
2713169691Skan	      const _Rope_iterator<_CharT, _Alloc>& __y)
2714169691Skan    { return __y < __x; }
2715132720Skan
2716169691Skan  template <class _CharT, class _Alloc>
2717169691Skan    inline bool
2718169691Skan    operator<=(const _Rope_iterator<_CharT, _Alloc>& __x,
2719169691Skan	       const _Rope_iterator<_CharT, _Alloc>& __y)
2720169691Skan    { return !(__y < __x); }
2721132720Skan
2722169691Skan  template <class _CharT, class _Alloc>
2723169691Skan    inline bool
2724169691Skan    operator>=(const _Rope_iterator<_CharT, _Alloc>& __x,
2725169691Skan	       const _Rope_iterator<_CharT, _Alloc>& __y)
2726169691Skan    { return !(__x < __y); }
2727132720Skan
2728169691Skan  template <class _CharT, class _Alloc>
2729169691Skan    inline ptrdiff_t
2730169691Skan    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2731169691Skan	      const _Rope_iterator<_CharT, _Alloc>& __y)
2732169691Skan    { return ((ptrdiff_t)__x._M_current_pos
2733169691Skan	      - (ptrdiff_t)__y._M_current_pos); }
2734132720Skan
2735169691Skan  template <class _CharT, class _Alloc>
2736169691Skan    inline _Rope_iterator<_CharT, _Alloc>
2737169691Skan    operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2738169691Skan	      ptrdiff_t __n)
2739169691Skan    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2740169691Skan					    __x._M_current_pos - __n); }
2741132720Skan
2742169691Skan  template <class _CharT, class _Alloc>
2743169691Skan    inline _Rope_iterator<_CharT, _Alloc>
2744169691Skan    operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n)
2745169691Skan    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2746169691Skan					    __x._M_current_pos + __n); }
2747132720Skan
2748169691Skan  template <class _CharT, class _Alloc>
2749169691Skan    inline _Rope_iterator<_CharT, _Alloc>
2750169691Skan    operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x)
2751169691Skan    { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2752169691Skan					    __x._M_current_pos + __n); }
2753132720Skan
2754169691Skan  template <class _CharT, class _Alloc>
2755169691Skan    inline rope<_CharT, _Alloc>
2756169691Skan    operator+(const rope<_CharT, _Alloc>& __left,
2757169691Skan	      const rope<_CharT, _Alloc>& __right)
2758169691Skan    {
2759169691Skan      // Inlining this should make it possible to keep __left and
2760169691Skan      // __right in registers.
2761169691Skan      typedef rope<_CharT, _Alloc> rope_type;
2762169691Skan      return rope_type(rope_type::_S_concat(__left._M_tree_ptr, 
2763169691Skan					    __right._M_tree_ptr));
2764169691Skan    }
2765132720Skan
2766169691Skan  template <class _CharT, class _Alloc>
2767169691Skan    inline rope<_CharT, _Alloc>&
2768169691Skan    operator+=(rope<_CharT, _Alloc>& __left,
2769169691Skan	       const rope<_CharT, _Alloc>& __right)
2770169691Skan    {
2771169691Skan      __left.append(__right);
2772169691Skan      return __left;
2773169691Skan    }
2774132720Skan
2775169691Skan  template <class _CharT, class _Alloc>
2776169691Skan    inline rope<_CharT, _Alloc>
2777169691Skan    operator+(const rope<_CharT, _Alloc>& __left,
2778169691Skan	      const _CharT* __right)
2779169691Skan    {
2780169691Skan      typedef rope<_CharT, _Alloc> rope_type;
2781169691Skan      size_t __rlen = rope_type::_S_char_ptr_len(__right);
2782169691Skan      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2783169691Skan						      __right, __rlen));
2784169691Skan    }
2785132720Skan
2786169691Skan  template <class _CharT, class _Alloc>
2787169691Skan    inline rope<_CharT, _Alloc>&
2788169691Skan    operator+=(rope<_CharT, _Alloc>& __left,
2789169691Skan	       const _CharT* __right)
2790169691Skan    {
2791169691Skan      __left.append(__right);
2792169691Skan      return __left;
2793169691Skan    }
2794132720Skan
2795169691Skan  template <class _CharT, class _Alloc>
2796169691Skan    inline rope<_CharT, _Alloc>
2797169691Skan    operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
2798169691Skan    {
2799169691Skan      typedef rope<_CharT, _Alloc> rope_type;
2800169691Skan      return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,
2801169691Skan						      &__right, 1));
2802169691Skan    }
2803132720Skan
2804169691Skan  template <class _CharT, class _Alloc>
2805169691Skan    inline rope<_CharT, _Alloc>&
2806169691Skan    operator+=(rope<_CharT, _Alloc>& __left, _CharT __right)
2807169691Skan    {
2808169691Skan      __left.append(__right);
2809169691Skan      return __left;
2810169691Skan    }
2811169691Skan  
2812169691Skan  template <class _CharT, class _Alloc>
2813169691Skan    bool
2814169691Skan    operator<(const rope<_CharT, _Alloc>& __left,
2815169691Skan	      const rope<_CharT, _Alloc>& __right)
2816169691Skan    { return __left.compare(__right) < 0; }
2817132720Skan
2818169691Skan  template <class _CharT, class _Alloc>
2819169691Skan    bool
2820169691Skan    operator==(const rope<_CharT, _Alloc>& __left,
2821169691Skan	       const rope<_CharT, _Alloc>& __right)
2822169691Skan    { return __left.compare(__right) == 0; }
2823132720Skan
2824169691Skan  template <class _CharT, class _Alloc>
2825169691Skan    inline bool
2826169691Skan    operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2827169691Skan	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2828169691Skan    { return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); }
2829132720Skan
2830169691Skan  template <class _CharT, class _Alloc>
2831169691Skan    inline bool
2832169691Skan    operator!=(const rope<_CharT, _Alloc>& __x,
2833169691Skan	       const rope<_CharT, _Alloc>& __y)
2834169691Skan    { return !(__x == __y); }
2835132720Skan
2836169691Skan  template <class _CharT, class _Alloc>
2837169691Skan    inline bool
2838169691Skan    operator>(const rope<_CharT, _Alloc>& __x,
2839169691Skan	      const rope<_CharT, _Alloc>& __y)
2840169691Skan    { return __y < __x; }
2841132720Skan
2842169691Skan  template <class _CharT, class _Alloc>
2843169691Skan    inline bool
2844169691Skan    operator<=(const rope<_CharT, _Alloc>& __x,
2845169691Skan	       const rope<_CharT, _Alloc>& __y)
2846169691Skan    { return !(__y < __x); }
2847132720Skan
2848169691Skan  template <class _CharT, class _Alloc>
2849169691Skan    inline bool
2850169691Skan    operator>=(const rope<_CharT, _Alloc>& __x,
2851169691Skan	       const rope<_CharT, _Alloc>& __y)
2852169691Skan    { return !(__x < __y); }
2853132720Skan
2854169691Skan  template <class _CharT, class _Alloc>
2855169691Skan    inline bool
2856169691Skan    operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2857169691Skan	       const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2858169691Skan    { return !(__x == __y); }
2859132720Skan
2860169691Skan  template<class _CharT, class _Traits, class _Alloc>
2861169691Skan    std::basic_ostream<_CharT, _Traits>&
2862169691Skan    operator<<(std::basic_ostream<_CharT, _Traits>& __o,
2863169691Skan	       const rope<_CharT, _Alloc>& __r);
2864132720Skan
2865169691Skan  typedef rope<char> crope;
2866169691Skan  typedef rope<wchar_t> wrope;
2867132720Skan
2868169691Skan  inline crope::reference
2869169691Skan  __mutable_reference_at(crope& __c, size_t __i)
2870169691Skan  { return __c.mutable_reference_at(__i); }
2871132720Skan
2872169691Skan  inline wrope::reference
2873169691Skan  __mutable_reference_at(wrope& __c, size_t __i)
2874169691Skan  { return __c.mutable_reference_at(__i); }
2875132720Skan
2876169691Skan  template <class _CharT, class _Alloc>
2877169691Skan    inline void
2878169691Skan    swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y)
2879169691Skan    { __x.swap(__y); }
2880132720Skan
2881169691Skan  // Hash functions should probably be revisited later:
2882169691Skan  template<>
2883169691Skan    struct hash<crope>
2884169691Skan    {
2885169691Skan      size_t
2886169691Skan      operator()(const crope& __str) const
2887169691Skan      {
2888169691Skan	size_t __size = __str.size();
2889169691Skan	if (0 == __size)
2890169691Skan	  return 0;
2891169691Skan	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2892169691Skan      }
2893169691Skan    };
2894132720Skan
2895132720Skan
2896169691Skan  template<>
2897169691Skan    struct hash<wrope>
2898169691Skan    {
2899169691Skan      size_t
2900169691Skan      operator()(const wrope& __str) const
2901169691Skan      {
2902169691Skan	size_t __size = __str.size();
2903169691Skan	if (0 == __size)
2904169691Skan	  return 0;
2905169691Skan	return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2906169691Skan      }
2907169691Skan    };
2908132720Skan
2909169691Skan_GLIBCXX_END_NAMESPACE
2910132720Skan
2911132720Skan# include <ext/ropeimpl.h>
2912132720Skan
2913132720Skan#endif
2914