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