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