Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

stl_rope.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1997-1998
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Permission to use, copy, modify, distribute and sell this software
00006  * and its documentation for any purpose is hereby granted without fee,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.  Silicon Graphics makes no
00010  * representations about the suitability of this software for any
00011  * purpose.  It is provided "as is" without express or implied warranty.
00012  */
00013 
00014 /* NOTE: This is an internal header file, included by other STL headers.
00015  *   You should not attempt to use it directly.
00016  */
00017 
00018 // rope<_CharT,_Alloc> is a sequence of _CharT.
00019 // Ropes appear to be mutable, but update operations
00020 // really copy enough of the data structure to leave the original
00021 // valid.  Thus ropes can be logically copied by just copying
00022 // a pointer value.
00023 
00024 #ifndef __SGI_STL_INTERNAL_ROPE_H
00025 # define __SGI_STL_INTERNAL_ROPE_H
00026 
00027 # ifdef __GC
00028 #   define __GC_CONST const
00029 # else
00030 #   include <bits/stl_threads.h>
00031 #   define __GC_CONST   // constant except for deallocation
00032 # endif
00033 # ifdef __STL_SGI_THREADS
00034 #    include <mutex.h>
00035 # endif
00036 
00037 namespace std
00038 {
00039 
00040 // The _S_eos function is used for those functions that
00041 // convert to/from C-like strings to detect the end of the string.
00042 
00043 // The end-of-C-string character.
00044 // This is what the draft standard says it should be.
00045 template <class _CharT>
00046 inline _CharT _S_eos(_CharT*) { return _CharT(); }
00047 
00048 // Test for basic character types.
00049 // For basic character types leaves having a trailing eos.
00050 template <class _CharT>
00051 inline bool _S_is_basic_char_type(_CharT*) { return false; }
00052 template <class _CharT>
00053 inline bool _S_is_one_byte_char_type(_CharT*) { return false; }
00054 
00055 inline bool _S_is_basic_char_type(char*) { return true; }
00056 inline bool _S_is_one_byte_char_type(char*) { return true; }
00057 inline bool _S_is_basic_char_type(wchar_t*) { return true; }
00058 
00059 // Store an eos iff _CharT is a basic character type.
00060 // Do not reference _S_eos if it isn't.
00061 template <class _CharT>
00062 inline void _S_cond_store_eos(_CharT&) {}
00063 
00064 inline void _S_cond_store_eos(char& __c) { __c = 0; }
00065 inline void _S_cond_store_eos(wchar_t& __c) { __c = 0; }
00066 
00067 // char_producers are logically functions that generate a section of
00068 // a string.  These can be convereted to ropes.  The resulting rope
00069 // invokes the char_producer on demand.  This allows, for example,
00070 // files to be viewed as ropes without reading the entire file.
00071 template <class _CharT>
00072 class char_producer {
00073     public:
00074         virtual ~char_producer() {};
00075         virtual void operator()(size_t __start_pos, size_t __len, 
00076                                 _CharT* __buffer) = 0;
00077         // Buffer should really be an arbitrary output iterator.
00078         // That way we could flatten directly into an ostream, etc.
00079         // This is thoroughly impossible, since iterator types don't
00080         // have runtime descriptions.
00081 };
00082 
00083 // Sequence buffers:
00084 //
00085 // Sequence must provide an append operation that appends an
00086 // array to the sequence.  Sequence buffers are useful only if
00087 // appending an entire array is cheaper than appending element by element.
00088 // This is true for many string representations.
00089 // This should  perhaps inherit from ostream<sequence::value_type>
00090 // and be implemented correspondingly, so that they can be used
00091 // for formatted.  For the sake of portability, we don't do this yet.
00092 //
00093 // For now, sequence buffers behave as output iterators.  But they also
00094 // behave a little like basic_ostringstream<sequence::value_type> and a
00095 // little like containers.
00096 
00097 template<class _Sequence, size_t _Buf_sz = 100>
00098 class sequence_buffer : public output_iterator {
00099     public:
00100         typedef typename _Sequence::value_type value_type;
00101     protected:
00102         _Sequence* _M_prefix;
00103         value_type _M_buffer[_Buf_sz];
00104         size_t     _M_buf_count;
00105     public:
00106         void flush() {
00107             _M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);
00108             _M_buf_count = 0;
00109         }
00110         ~sequence_buffer() { flush(); }
00111         sequence_buffer() : _M_prefix(0), _M_buf_count(0) {}
00112         sequence_buffer(const sequence_buffer& __x) {
00113             _M_prefix = __x._M_prefix;
00114             _M_buf_count = __x._M_buf_count;
00115             copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
00116         }
00117         sequence_buffer(sequence_buffer& __x) {
00118             __x.flush();
00119             _M_prefix = __x._M_prefix;
00120             _M_buf_count = 0;
00121         }
00122         sequence_buffer(_Sequence& __s) : _M_prefix(&__s), _M_buf_count(0) {}
00123         sequence_buffer& operator= (sequence_buffer& __x) {
00124             __x.flush();
00125             _M_prefix = __x._M_prefix;
00126             _M_buf_count = 0;
00127             return *this;
00128         }
00129         sequence_buffer& operator= (const sequence_buffer& __x) {
00130             _M_prefix = __x._M_prefix;
00131             _M_buf_count = __x._M_buf_count;
00132             copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);
00133             return *this;
00134         }
00135         void push_back(value_type __x)
00136         {
00137             if (_M_buf_count < _Buf_sz) {
00138                 _M_buffer[_M_buf_count] = __x;
00139                 ++_M_buf_count;
00140             } else {
00141                 flush();
00142                 _M_buffer[0] = __x;
00143                 _M_buf_count = 1;
00144             }
00145         }
00146         void append(value_type* __s, size_t __len)
00147         {
00148             if (__len + _M_buf_count <= _Buf_sz) {
00149                 size_t __i = _M_buf_count;
00150                 size_t __j = 0;
00151                 for (; __j < __len; __i++, __j++) {
00152                     _M_buffer[__i] = __s[__j];
00153                 }
00154                 _M_buf_count += __len;
00155             } else if (0 == _M_buf_count) {
00156                 _M_prefix->append(__s, __s + __len);
00157             } else {
00158                 flush();
00159                 append(__s, __len);
00160             }
00161         }
00162         sequence_buffer& write(value_type* __s, size_t __len)
00163         {
00164             append(__s, __len);
00165             return *this;
00166         }
00167         sequence_buffer& put(value_type __x)
00168         {
00169             push_back(__x);
00170             return *this;
00171         }
00172         sequence_buffer& operator=(const value_type& __rhs)
00173         {
00174             push_back(__rhs);
00175             return *this;
00176         }
00177         sequence_buffer& operator*() { return *this; }
00178         sequence_buffer& operator++() { return *this; }
00179         sequence_buffer& operator++(int) { return *this; }
00180 };
00181 
00182 // The following should be treated as private, at least for now.
00183 template<class _CharT>
00184 class _Rope_char_consumer {
00185     public:
00186         // If we had member templates, these should not be virtual.
00187         // For now we need to use run-time parametrization where
00188         // compile-time would do.  Hence this should all be private
00189         // for now.
00190         // The symmetry with char_producer is accidental and temporary.
00191         virtual ~_Rope_char_consumer() {};
00192         virtual bool operator()(const _CharT* __buffer, size_t __len) = 0;
00193 };
00194 
00195 // First a lot of forward declarations.  The standard seems to require
00196 // much stricter "declaration before use" than many of the implementations
00197 // that preceded it.
00198 template<class _CharT, class _Alloc=allocator<_CharT> > class rope;
00199 template<class _CharT, class _Alloc> struct _Rope_RopeConcatenation;
00200 template<class _CharT, class _Alloc> struct _Rope_RopeLeaf;
00201 template<class _CharT, class _Alloc> struct _Rope_RopeFunction;
00202 template<class _CharT, class _Alloc> struct _Rope_RopeSubstring;
00203 template<class _CharT, class _Alloc> class _Rope_iterator;
00204 template<class _CharT, class _Alloc> class _Rope_const_iterator;
00205 template<class _CharT, class _Alloc> class _Rope_char_ref_proxy;
00206 template<class _CharT, class _Alloc> class _Rope_char_ptr_proxy;
00207 
00208 template<class _CharT, class _Alloc>
00209 bool operator== (const _Rope_char_ptr_proxy<_CharT,_Alloc>& __x,
00210                  const _Rope_char_ptr_proxy<_CharT,_Alloc>& __y);
00211 
00212 template<class _CharT, class _Alloc>
00213 _Rope_const_iterator<_CharT,_Alloc> operator-
00214         (const _Rope_const_iterator<_CharT,_Alloc>& __x,
00215          ptrdiff_t __n);
00216 
00217 template<class _CharT, class _Alloc>
00218 _Rope_const_iterator<_CharT,_Alloc> operator+
00219         (const _Rope_const_iterator<_CharT,_Alloc>& __x,
00220          ptrdiff_t __n);
00221 
00222 template<class _CharT, class _Alloc>
00223 _Rope_const_iterator<_CharT,_Alloc> operator+
00224         (ptrdiff_t __n,
00225          const _Rope_const_iterator<_CharT,_Alloc>& __x);
00226 
00227 template<class _CharT, class _Alloc>
00228 bool operator== 
00229         (const _Rope_const_iterator<_CharT,_Alloc>& __x,
00230          const _Rope_const_iterator<_CharT,_Alloc>& __y);
00231 
00232 template<class _CharT, class _Alloc>
00233 bool operator< 
00234         (const _Rope_const_iterator<_CharT,_Alloc>& __x,
00235          const _Rope_const_iterator<_CharT,_Alloc>& __y);
00236 
00237 template<class _CharT, class _Alloc>
00238 ptrdiff_t operator- 
00239         (const _Rope_const_iterator<_CharT,_Alloc>& __x,
00240          const _Rope_const_iterator<_CharT,_Alloc>& __y);
00241 
00242 template<class _CharT, class _Alloc>
00243 _Rope_iterator<_CharT,_Alloc> operator-
00244         (const _Rope_iterator<_CharT,_Alloc>& __x,
00245          ptrdiff_t __n);
00246 
00247 template<class _CharT, class _Alloc>
00248 _Rope_iterator<_CharT,_Alloc> operator+
00249         (const _Rope_iterator<_CharT,_Alloc>& __x,
00250          ptrdiff_t __n);
00251 
00252 template<class _CharT, class _Alloc>
00253 _Rope_iterator<_CharT,_Alloc> operator+
00254         (ptrdiff_t __n,
00255          const _Rope_iterator<_CharT,_Alloc>& __x);
00256 
00257 template<class _CharT, class _Alloc>
00258 bool operator== 
00259         (const _Rope_iterator<_CharT,_Alloc>& __x,
00260          const _Rope_iterator<_CharT,_Alloc>& __y);
00261 
00262 template<class _CharT, class _Alloc>
00263 bool operator< 
00264         (const _Rope_iterator<_CharT,_Alloc>& __x,
00265          const _Rope_iterator<_CharT,_Alloc>& __y);
00266 
00267 template<class _CharT, class _Alloc>
00268 ptrdiff_t operator- 
00269         (const _Rope_iterator<_CharT,_Alloc>& __x,
00270          const _Rope_iterator<_CharT,_Alloc>& __y);
00271 
00272 template<class _CharT, class _Alloc>
00273 rope<_CharT,_Alloc> operator+ (const rope<_CharT,_Alloc>& __left,
00274                                const rope<_CharT,_Alloc>& __right);
00275         
00276 template<class _CharT, class _Alloc>
00277 rope<_CharT,_Alloc> operator+ (const rope<_CharT,_Alloc>& __left,
00278                                const _CharT* __right);
00279         
00280 template<class _CharT, class _Alloc>
00281 rope<_CharT,_Alloc> operator+ (const rope<_CharT,_Alloc>& __left,
00282                                _CharT __right);
00283         
00284 // Some helpers, so we can use power on ropes.
00285 // See below for why this isn't local to the implementation.
00286 
00287 // This uses a nonstandard refcount convention.
00288 // The result has refcount 0.
00289 template<class _CharT, class _Alloc>
00290 struct _Rope_Concat_fn
00291        : public binary_function<rope<_CharT,_Alloc>, rope<_CharT,_Alloc>,
00292                                      rope<_CharT,_Alloc> > {
00293         rope<_CharT,_Alloc> operator() (const rope<_CharT,_Alloc>& __x,
00294                                 const rope<_CharT,_Alloc>& __y) {
00295                     return __x + __y;
00296         }
00297 };
00298 
00299 template <class _CharT, class _Alloc>
00300 inline
00301 rope<_CharT,_Alloc>
00302 identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
00303 {
00304     return rope<_CharT,_Alloc>();
00305 }
00306 
00307 
00308 //
00309 // What follows should really be local to rope.  Unfortunately,
00310 // that doesn't work, since it makes it impossible to define generic
00311 // equality on rope iterators.  According to the draft standard, the
00312 // template parameters for such an equality operator cannot be inferred
00313 // from the occurence of a member class as a parameter.
00314 // (SGI compilers in fact allow this, but the __result wouldn't be
00315 // portable.)
00316 // Similarly, some of the static member functions are member functions
00317 // only to avoid polluting the global namespace, and to circumvent
00318 // restrictions on type inference for template functions.
00319 //
00320 
00321 //
00322 // The internal data structure for representing a rope.  This is
00323 // private to the implementation.  A rope is really just a pointer
00324 // to one of these.
00325 //
00326 // A few basic functions for manipulating this data structure
00327 // are members of _RopeRep.  Most of the more complex algorithms
00328 // are implemented as rope members.
00329 //
00330 // Some of the static member functions of _RopeRep have identically
00331 // named functions in rope that simply invoke the _RopeRep versions.
00332 //
00333 // A macro to introduce various allocation and deallocation functions
00334 // These need to be defined differently depending on whether or not
00335 // we are using standard conforming allocators, and whether the allocator
00336 // instances have real state.  Thus this macro is invoked repeatedly
00337 // with different definitions of __ROPE_DEFINE_ALLOC.
00338 // __ROPE_DEFINE_ALLOC(type,name) defines 
00339 //   type * name_allocate(size_t) and
00340 //   void name_deallocate(tipe *, size_t)
00341 // Both functions may or may not be static.
00342 
00343 #define __ROPE_DEFINE_ALLOCS(__a) \
00344         __ROPE_DEFINE_ALLOC(_CharT,_Data) /* character data */ \
00345         typedef _Rope_RopeConcatenation<_CharT,__a> __C; \
00346         __ROPE_DEFINE_ALLOC(__C,_C) \
00347         typedef _Rope_RopeLeaf<_CharT,__a> __L; \
00348         __ROPE_DEFINE_ALLOC(__L,_L) \
00349         typedef _Rope_RopeFunction<_CharT,__a> __F; \
00350         __ROPE_DEFINE_ALLOC(__F,_F) \
00351         typedef _Rope_RopeSubstring<_CharT,__a> __S; \
00352         __ROPE_DEFINE_ALLOC(__S,_S)
00353 
00354 //  Internal rope nodes potentially store a copy of the allocator
00355 //  instance used to allocate them.  This is mostly redundant.
00356 //  But the alternative would be to pass allocator instances around
00357 //  in some form to nearly all internal functions, since any pointer
00358 //  assignment may result in a zero reference count and thus require
00359 //  deallocation.
00360 //  The _Rope_rep_base class encapsulates
00361 //  the differences between SGI-style allocators and standard-conforming
00362 //  allocators.
00363 
00364 #define __STATIC_IF_SGI_ALLOC  /* not static */
00365 
00366 // Base class for ordinary allocators.
00367 template <class _CharT, class _Allocator, bool _IsStatic>
00368 class _Rope_rep_alloc_base {
00369 public:
00370   typedef typename _Alloc_traits<_CharT,_Allocator>::allocator_type
00371           allocator_type;
00372   allocator_type get_allocator() const { return _M_data_allocator; }
00373   _Rope_rep_alloc_base(size_t __size, const allocator_type& __a)
00374         : _M_size(__size), _M_data_allocator(__a) {}
00375   size_t _M_size;       // This is here only to avoid wasting space
00376                 // for an otherwise empty base class.
00377 
00378   
00379 protected:
00380     allocator_type _M_data_allocator;
00381 
00382 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
00383         typedef typename \
00384           _Alloc_traits<_Tp,_Allocator>::allocator_type __name##Allocator; \
00385         /*static*/ _Tp * __name##_allocate(size_t __n) \
00386           { return __name##Allocator(_M_data_allocator).allocate(__n); } \
00387         void __name##_deallocate(_Tp* __p, size_t __n) \
00388           { __name##Allocator(_M_data_allocator).deallocate(__p, __n); }
00389   __ROPE_DEFINE_ALLOCS(_Allocator);
00390 # undef __ROPE_DEFINE_ALLOC
00391 };
00392 
00393 // Specialization for allocators that have the property that we don't
00394 //  actually have to store an allocator object.  
00395 template <class _CharT, class _Allocator>
00396 class _Rope_rep_alloc_base<_CharT,_Allocator,true> {
00397 public:
00398   typedef typename _Alloc_traits<_CharT,_Allocator>::allocator_type
00399           allocator_type;
00400   allocator_type get_allocator() const { return allocator_type(); }
00401   _Rope_rep_alloc_base(size_t __size, const allocator_type&)
00402                 : _M_size(__size) {}
00403   size_t _M_size;
00404   
00405 protected:
00406 
00407 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
00408         typedef typename \
00409           _Alloc_traits<_Tp,_Allocator>::_Alloc_type __name##Alloc; \
00410         typedef typename \
00411           _Alloc_traits<_Tp,_Allocator>::allocator_type __name##Allocator; \
00412         static _Tp* __name##_allocate(size_t __n) \
00413                 { return __name##Alloc::allocate(__n); } \
00414         void __name##_deallocate(_Tp *__p, size_t __n) \
00415                 { __name##Alloc::deallocate(__p, __n); }
00416   __ROPE_DEFINE_ALLOCS(_Allocator);
00417 # undef __ROPE_DEFINE_ALLOC
00418 };
00419 
00420 template <class _CharT, class _Alloc>
00421 struct _Rope_rep_base
00422   : public _Rope_rep_alloc_base<_CharT,_Alloc,
00423                                 _Alloc_traits<_CharT,_Alloc>::_S_instanceless>
00424 {
00425   typedef _Rope_rep_alloc_base<_CharT,_Alloc,
00426                                _Alloc_traits<_CharT,_Alloc>::_S_instanceless>
00427           _Base;
00428   typedef typename _Base::allocator_type allocator_type;
00429   _Rope_rep_base(size_t __size, const allocator_type& __a)
00430     : _Base(__size, __a) {}
00431 };    
00432 
00433 
00434 template<class _CharT, class _Alloc>
00435 struct _Rope_RopeRep : public _Rope_rep_base<_CharT,_Alloc>
00436 # ifndef __GC
00437     , _Refcount_Base
00438 # endif
00439 {
00440     public:
00441     enum { _S_max_rope_depth = 45 };
00442     enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
00443     _Tag _M_tag:8;
00444     bool _M_is_balanced:8;
00445     unsigned char _M_depth;
00446     __GC_CONST _CharT* _M_c_string;
00447                         /* Flattened version of string, if needed.  */
00448                         /* typically 0.                             */
00449                         /* If it's not 0, then the memory is owned  */
00450                         /* by this node.                            */
00451                         /* In the case of a leaf, this may point to */
00452                         /* the same memory as the data field.       */
00453     typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
00454                         allocator_type;
00455     _Rope_RopeRep(_Tag __t, int __d, bool __b, size_t __size,
00456                   allocator_type __a)
00457         : _Rope_rep_base<_CharT,_Alloc>(__size, __a),
00458 #         ifndef __GC
00459           _Refcount_Base(1),
00460 #         endif
00461           _M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
00462     { }
00463 #   ifdef __GC
00464         void _M_incr () {}
00465 #   endif
00466         static void _S_free_string(__GC_CONST _CharT*, size_t __len,
00467                                    allocator_type __a);
00468 #       define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);
00469                         // Deallocate data section of a leaf.
00470                         // This shouldn't be a member function.
00471                         // But its hard to do anything else at the
00472                         // moment, because it's templatized w.r.t.
00473                         // an allocator.
00474                         // Does nothing if __GC is defined.
00475 #   ifndef __GC
00476           void _M_free_c_string();
00477           void _M_free_tree();
00478                         // Deallocate t. Assumes t is not 0.
00479           void _M_unref_nonnil()
00480           {
00481               if (0 == _M_decr()) _M_free_tree();
00482           }
00483           void _M_ref_nonnil()
00484           {
00485               _M_incr();
00486           }
00487           static void _S_unref(_Rope_RopeRep* __t)
00488           {
00489               if (0 != __t) {
00490                   __t->_M_unref_nonnil();
00491               }
00492           }
00493           static void _S_ref(_Rope_RopeRep* __t)
00494           {
00495               if (0 != __t) __t->_M_incr();
00496           }
00497           static void _S_free_if_unref(_Rope_RopeRep* __t)
00498           {
00499               if (0 != __t && 0 == __t->_M_ref_count) __t->_M_free_tree();
00500           }
00501 #   else /* __GC */
00502           void _M_unref_nonnil() {}
00503           void _M_ref_nonnil() {}
00504           static void _S_unref(_Rope_RopeRep*) {}
00505           static void _S_ref(_Rope_RopeRep*) {}
00506           static void _S_free_if_unref(_Rope_RopeRep*) {}
00507 #   endif
00508 
00509 };
00510 
00511 template<class _CharT, class _Alloc>
00512 struct _Rope_RopeLeaf : public _Rope_RopeRep<_CharT,_Alloc> {
00513   public:
00514     // Apparently needed by VC++
00515     // The data fields of leaves are allocated with some
00516     // extra space, to accomodate future growth and for basic
00517     // character types, to hold a trailing eos character.
00518     enum { _S_alloc_granularity = 8 };
00519     static size_t _S_rounded_up_size(size_t __n) {
00520         size_t __size_with_eos;
00521              
00522         if (_S_is_basic_char_type((_CharT*)0)) {
00523             __size_with_eos = __n + 1;
00524         } else {
00525             __size_with_eos = __n;
00526         }
00527 #       ifdef __GC
00528            return __size_with_eos;
00529 #       else
00530            // Allow slop for in-place expansion.
00531            return (__size_with_eos + _S_alloc_granularity-1)
00532                         &~ (_S_alloc_granularity-1);
00533 #       endif
00534     }
00535     __GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. */
00536                                 /* The allocated size is         */
00537                                 /* _S_rounded_up_size(size), except */
00538                                 /* in the GC case, in which it   */
00539                                 /* doesn't matter.               */
00540     typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
00541                         allocator_type;
00542     _Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size, allocator_type __a)
00543         : _Rope_RopeRep<_CharT,_Alloc>(_S_leaf, 0, true, __size, __a),
00544           _M_data(__d)
00545         {
00546         __stl_assert(__size > 0);
00547         if (_S_is_basic_char_type((_CharT *)0)) {
00548             // already eos terminated.
00549             _M_c_string = __d;
00550         }
00551     }
00552         // The constructor assumes that d has been allocated with
00553         // the proper allocator and the properly padded size.
00554         // In contrast, the destructor deallocates the data:
00555 # ifndef __GC
00556     ~_Rope_RopeLeaf() {
00557         if (_M_data != _M_c_string) {
00558             _M_free_c_string();
00559         }
00560         __STL_FREE_STRING(_M_data, _M_size, get_allocator());
00561     }
00562 # endif
00563 };
00564 
00565 template<class _CharT, class _Alloc>
00566 struct _Rope_RopeConcatenation : public _Rope_RopeRep<_CharT,_Alloc> {
00567   public:
00568     _Rope_RopeRep<_CharT,_Alloc>* _M_left;
00569     _Rope_RopeRep<_CharT,_Alloc>* _M_right;
00570     typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
00571                         allocator_type;
00572     _Rope_RopeConcatenation(_Rope_RopeRep<_CharT,_Alloc>* __l,
00573                              _Rope_RopeRep<_CharT,_Alloc>* __r,
00574                              allocator_type __a)
00575 
00576       : _Rope_RopeRep<_CharT,_Alloc>(_S_concat,
00577                                      max(__l->_M_depth, __r->_M_depth) + 1,
00578                                      false,
00579                                      __l->_M_size + __r->_M_size, __a),
00580         _M_left(__l), _M_right(__r)
00581       {}
00582 # ifndef __GC
00583     ~_Rope_RopeConcatenation() {
00584         _M_free_c_string();
00585         _M_left->_M_unref_nonnil();
00586         _M_right->_M_unref_nonnil();
00587     }
00588 # endif
00589 };
00590 
00591 template<class _CharT, class _Alloc>
00592 struct _Rope_RopeFunction : public _Rope_RopeRep<_CharT,_Alloc> {
00593   public:
00594     char_producer<_CharT>* _M_fn;
00595 #   ifndef __GC
00596       bool _M_delete_when_done; // Char_producer is owned by the
00597                                 // rope and should be explicitly
00598                                 // deleted when the rope becomes
00599                                 // inaccessible.
00600 #   else
00601       // In the GC case, we either register the rope for
00602       // finalization, or not.  Thus the field is unnecessary;
00603       // the information is stored in the collector data structures.
00604       // We do need a finalization procedure to be invoked by the
00605       // collector.
00606       static void _S_fn_finalization_proc(void * __tree, void *) {
00607         delete ((_Rope_RopeFunction *)__tree) -> _M_fn;
00608       }
00609 #   endif
00610     typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
00611                                         allocator_type;
00612     _Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size,
00613                         bool __d, allocator_type __a)
00614       : _Rope_RopeRep<_CharT,_Alloc>(_S_function, 0, true, __size, __a)
00615       , _M_fn(__f)
00616 #       ifndef __GC
00617       , _M_delete_when_done(__d)
00618 #       endif
00619     {
00620         __stl_assert(__size > 0);
00621 #       ifdef __GC
00622             if (__d) {
00623                 GC_REGISTER_FINALIZER(
00624                   this, _Rope_RopeFunction::_S_fn_finalization_proc, 0, 0, 0);
00625             }
00626 #       endif
00627     }
00628 # ifndef __GC
00629     ~_Rope_RopeFunction() {
00630           _M_free_c_string();
00631           if (_M_delete_when_done) {
00632               delete _M_fn;
00633           }
00634     }
00635 # endif
00636 };
00637 // Substring results are usually represented using just
00638 // concatenation nodes.  But in the case of very long flat ropes
00639 // or ropes with a functional representation that isn't practical.
00640 // In that case, we represent the __result as a special case of
00641 // RopeFunction, whose char_producer points back to the rope itself.
00642 // In all cases except repeated substring operations and
00643 // deallocation, we treat the __result as a RopeFunction.
00644 template<class _CharT, class _Alloc>
00645 struct _Rope_RopeSubstring : public _Rope_RopeFunction<_CharT,_Alloc>,
00646                              public char_producer<_CharT> {
00647   public:
00648     // XXX this whole class should be rewritten.
00649     _Rope_RopeRep<_CharT,_Alloc>* _M_base;      // not 0
00650     size_t _M_start;
00651     virtual void operator()(size_t __start_pos, size_t __req_len,
00652                             _CharT* __buffer) {
00653         switch(_M_base->_M_tag) {
00654             case _S_function:
00655             case _S_substringfn:
00656               {
00657                 char_producer<_CharT>* __fn =
00658                         ((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;
00659                 __stl_assert(__start_pos + __req_len <= _M_size);
00660                 __stl_assert(_M_start + _M_size <= _M_base->_M_size);
00661                 (*__fn)(__start_pos + _M_start, __req_len, __buffer);
00662               }
00663               break;
00664             case _S_leaf:
00665               {
00666                 __GC_CONST _CharT* __s =
00667                         ((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data;
00668                 uninitialized_copy_n(__s + __start_pos + _M_start, __req_len,
00669                                      __buffer);
00670               }
00671               break;
00672             default:
00673               __stl_assert(false);
00674         }
00675     }
00676     typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_type
00677         allocator_type;
00678     _Rope_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,
00679                           size_t __l, allocator_type __a)
00680       : _Rope_RopeFunction<_CharT,_Alloc>(this, __l, false, __a),
00681         char_producer<_CharT>(),
00682         _M_base(__b),
00683         _M_start(__s)
00684     {
00685         __stl_assert(__l > 0);
00686         __stl_assert(__s + __l <= __b->_M_size);
00687 #       ifndef __GC
00688             _M_base->_M_ref_nonnil();
00689 #       endif
00690         _M_tag = _S_substringfn;
00691     }
00692     virtual ~_Rope_RopeSubstring()
00693       { 
00694 #       ifndef __GC
00695           _M_base->_M_unref_nonnil();
00696           // _M_free_c_string();  -- done by parent class
00697 #       endif
00698       }
00699 };
00700 
00701 
00702 // Self-destructing pointers to Rope_rep.
00703 // These are not conventional smart pointers.  Their
00704 // only purpose in life is to ensure that unref is called
00705 // on the pointer either at normal exit or if an exception
00706 // is raised.  It is the caller's responsibility to
00707 // adjust reference counts when these pointers are initialized
00708 // or assigned to.  (This convention significantly reduces
00709 // the number of potentially expensive reference count
00710 // updates.)
00711 #ifndef __GC
00712   template<class _CharT, class _Alloc>
00713   struct _Rope_self_destruct_ptr {
00714     _Rope_RopeRep<_CharT,_Alloc>* _M_ptr;
00715     ~_Rope_self_destruct_ptr() 
00716       { _Rope_RopeRep<_CharT,_Alloc>::_S_unref(_M_ptr); }
00717 #   ifdef __STL_USE_EXCEPTIONS
00718         _Rope_self_destruct_ptr() : _M_ptr(0) {};
00719 #   else
00720         _Rope_self_destruct_ptr() {};
00721 #   endif
00722     _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT,_Alloc>* __p) : _M_ptr(__p) {}
00723     _Rope_RopeRep<_CharT,_Alloc>& operator*() { return *_M_ptr; }
00724     _Rope_RopeRep<_CharT,_Alloc>* operator->() { return _M_ptr; }
00725     operator _Rope_RopeRep<_CharT,_Alloc>*() { return _M_ptr; }
00726     _Rope_self_destruct_ptr& operator= (_Rope_RopeRep<_CharT,_Alloc>* __x)
00727         { _M_ptr = __x; return *this; }
00728   };
00729 #endif
00730 
00731 // Dereferencing a nonconst iterator has to return something
00732 // that behaves almost like a reference.  It's not possible to
00733 // return an actual reference since assignment requires extra
00734 // work.  And we would get into the same problems as with the
00735 // CD2 version of basic_string.
00736 template<class _CharT, class _Alloc>
00737 class _Rope_char_ref_proxy {
00738     friend class rope<_CharT,_Alloc>;
00739     friend class _Rope_iterator<_CharT,_Alloc>;
00740     friend class _Rope_char_ptr_proxy<_CharT,_Alloc>;
00741 #   ifdef __GC
00742         typedef _Rope_RopeRep<_CharT,_Alloc>* _Self_destruct_ptr;
00743 #   else
00744         typedef _Rope_self_destruct_ptr<_CharT,_Alloc> _Self_destruct_ptr;
00745 #   endif
00746     typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;
00747     typedef rope<_CharT,_Alloc> _My_rope;
00748     size_t _M_pos;
00749     _CharT _M_current;
00750     bool _M_current_valid;
00751     _My_rope* _M_root;     // The whole rope.
00752   public:
00753     _Rope_char_ref_proxy(_My_rope* __r, size_t __p)
00754       :  _M_pos(__p), _M_current_valid(false), _M_root(__r) {}
00755     _Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x)
00756       : _M_pos(__x._M_pos), _M_current_valid(false), _M_root(__x._M_root) {}
00757         // Don't preserve cache if the reference can outlive the
00758         // expression.  We claim that's not possible without calling
00759         // a copy constructor or generating reference to a proxy
00760         // reference.  We declare the latter to have undefined semantics.
00761     _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c)
00762       : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) {}
00763     inline operator _CharT () const;
00764     _Rope_char_ref_proxy& operator= (_CharT __c);
00765     _Rope_char_ptr_proxy<_CharT,_Alloc> operator& () const;
00766     _Rope_char_ref_proxy& operator= (const _Rope_char_ref_proxy& __c) {
00767         return operator=((_CharT)__c); 
00768     }
00769 };
00770 
00771 template<class _CharT, class __Alloc>
00772 inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,
00773                  _Rope_char_ref_proxy <_CharT, __Alloc > __b) {
00774     _CharT __tmp = __a;
00775     __a = __b;
00776     __b = __tmp;
00777 }
00778 
00779 template<class _CharT, class _Alloc>
00780 class _Rope_char_ptr_proxy {
00781     // XXX this class should be rewritten.
00782     friend class _Rope_char_ref_proxy<_CharT,_Alloc>;
00783     size_t _M_pos;
00784     rope<_CharT,_Alloc>* _M_root;     // The whole rope.
00785   public:
00786     _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x) 
00787       : _M_pos(__x._M_pos), _M_root(__x._M_root) {}
00788     _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x)
00789       : _M_pos(__x._M_pos), _M_root(__x._M_root) {}
00790     _Rope_char_ptr_proxy() {}
00791     _Rope_char_ptr_proxy(_CharT* __x) : _M_root(0), _M_pos(0) {
00792         __stl_assert(0 == __x);
00793     }
00794     _Rope_char_ptr_proxy& 
00795     operator= (const _Rope_char_ptr_proxy& __x) {
00796         _M_pos = __x._M_pos;
00797         _M_root = __x._M_root;
00798         return *this;
00799     }
00800     template<class _CharT2, class _Alloc2>
00801     friend bool operator== (const _Rope_char_ptr_proxy<_CharT2,_Alloc2>& __x,
00802                             const _Rope_char_ptr_proxy<_CharT2,_Alloc2>& __y);
00803     _Rope_char_ref_proxy<_CharT,_Alloc> operator*() const {
00804         return _Rope_char_ref_proxy<_CharT,_Alloc>(_M_root, _M_pos);
00805     }
00806 };
00807 
00808 
00809 // Rope iterators:
00810 // Unlike in the C version, we cache only part of the stack
00811 // for rope iterators, since they must be efficiently copyable.
00812 // When we run out of cache, we have to reconstruct the iterator
00813 // value.
00814 // Pointers from iterators are not included in reference counts.
00815 // Iterators are assumed to be thread private.  Ropes can
00816 // be shared.
00817 
00818 template<class _CharT, class _Alloc>
00819 class _Rope_iterator_base
00820   : public random_access_iterator<_CharT, ptrdiff_t> {
00821     friend class rope<_CharT,_Alloc>;
00822   public:
00823     typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaround
00824     typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;
00825         // Borland doesnt want this to be protected.
00826   protected:
00827     enum { _S_path_cache_len = 4 }; // Must be <= 9.
00828     enum { _S_iterator_buf_len = 15 };
00829     size_t _M_current_pos;
00830     _RopeRep* _M_root;     // The whole rope.
00831     size_t _M_leaf_pos;    // Starting position for current leaf
00832     __GC_CONST _CharT* _M_buf_start;
00833                         // Buffer possibly
00834                         // containing current char.
00835     __GC_CONST _CharT* _M_buf_ptr;
00836                         // Pointer to current char in buffer.
00837                         // != 0 ==> buffer valid.
00838     __GC_CONST _CharT* _M_buf_end;
00839                         // One past __last valid char in buffer.
00840     // What follows is the path cache.  We go out of our
00841     // way to make this compact.
00842     // Path_end contains the bottom section of the path from
00843     // the root to the current leaf.
00844     const _RopeRep* _M_path_end[_S_path_cache_len];
00845     int _M_leaf_index;     // Last valid __pos in path_end;
00846                         // _M_path_end[0] ... _M_path_end[leaf_index-1]
00847                         // point to concatenation nodes.
00848     unsigned char _M_path_directions;
00849                           // (path_directions >> __i) & 1 is 1
00850                           // iff we got from _M_path_end[leaf_index - __i - 1]
00851                           // to _M_path_end[leaf_index - __i] by going to the
00852                           // __right. Assumes path_cache_len <= 9.
00853     _CharT _M_tmp_buf[_S_iterator_buf_len];
00854                         // Short buffer for surrounding chars.
00855                         // This is useful primarily for 
00856                         // RopeFunctions.  We put the buffer
00857                         // here to avoid locking in the
00858                         // multithreaded case.
00859     // The cached path is generally assumed to be valid
00860     // only if the buffer is valid.
00861     static void _S_setbuf(_Rope_iterator_base& __x);
00862                                         // Set buffer contents given
00863                                         // path cache.
00864     static void _S_setcache(_Rope_iterator_base& __x);
00865                                         // Set buffer contents and
00866                                         // path cache.
00867     static void _S_setcache_for_incr(_Rope_iterator_base& __x);
00868                                         // As above, but assumes path
00869                                         // cache is valid for previous posn.
00870     _Rope_iterator_base() {}
00871     _Rope_iterator_base(_RopeRep* __root, size_t __pos)
00872       : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) {}
00873     void _M_incr(size_t __n);
00874     void _M_decr(size_t __n);
00875   public:
00876     size_t index() const { return _M_current_pos; }
00877     _Rope_iterator_base(const _Rope_iterator_base& __x) {
00878         if (0 != __x._M_buf_ptr) {
00879             *this = __x;
00880         } else {
00881             _M_current_pos = __x._M_current_pos;
00882             _M_root = __x._M_root;
00883             _M_buf_ptr = 0;
00884         }
00885     }
00886 };
00887 
00888 template<class _CharT, class _Alloc> class _Rope_iterator;
00889 
00890 template<class _CharT, class _Alloc>
00891 class _Rope_const_iterator : public _Rope_iterator_base<_CharT,_Alloc> {
00892     friend class rope<_CharT,_Alloc>;
00893   protected:
00894       typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;
00895       // The one from the base class may not be directly visible.
00896     _Rope_const_iterator(const _RopeRep* __root, size_t __pos):
00897                    _Rope_iterator_base<_CharT,_Alloc>(
00898                      const_cast<_RopeRep*>(__root), __pos)
00899                    // Only nonconst iterators modify root ref count
00900     {}
00901   public:
00902     typedef _CharT reference;   // Really a value.  Returning a reference
00903                                 // Would be a mess, since it would have
00904                                 // to be included in refcount.
00905     typedef const _CharT* pointer;
00906 
00907   public:
00908     _Rope_const_iterator() {};
00909     _Rope_const_iterator(const _Rope_const_iterator& __x) :
00910                                 _Rope_iterator_base<_CharT,_Alloc>(__x) { }
00911     _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);
00912     _Rope_const_iterator(const rope<_CharT,_Alloc>& __r, size_t __pos) :
00913         _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) {}
00914     _Rope_const_iterator& operator= (const _Rope_const_iterator& __x) {
00915         if (0 != __x._M_buf_ptr) {
00916             *(static_cast<_Rope_iterator_base<_CharT,_Alloc>*>(this)) = __x;
00917         } else {
00918             _M_current_pos = __x._M_current_pos;
00919             _M_root = __x._M_root;
00920             _M_buf_ptr = 0;
00921         }
00922         return(*this);
00923     }
00924     reference operator*() {
00925         if (0 == _M_buf_ptr) _S_setcache(*this);
00926         return *_M_buf_ptr;
00927     }
00928     _Rope_const_iterator& operator++() {
00929         __GC_CONST _CharT* __next;
00930         if (0 != _M_buf_ptr && (__next = _M_buf_ptr + 1) < _M_buf_end) {
00931             _M_buf_ptr = __next;
00932             ++_M_current_pos;
00933         } else {
00934             _M_incr(1);
00935         }
00936         return *this;
00937     }
00938     _Rope_const_iterator& operator+=(ptrdiff_t __n) {
00939         if (__n >= 0) {
00940             _M_incr(__n);
00941         } else {
00942             _M_decr(-__n);
00943         }
00944         return *this;
00945     }
00946     _Rope_const_iterator& operator--() {
00947         _M_decr(1);
00948         return *this;
00949     }
00950     _Rope_const_iterator& operator-=(ptrdiff_t __n) {
00951         if (__n >= 0) {
00952             _M_decr(__n);
00953         } else {
00954             _M_incr(-__n);
00955         }
00956         return *this;
00957     }
00958     _Rope_const_iterator operator++(int) {
00959         size_t __old_pos = _M_current_pos;
00960         _M_incr(1);
00961         return _Rope_const_iterator<_CharT,_Alloc>(_M_root, __old_pos);
00962         // This makes a subsequent dereference expensive.
00963         // Perhaps we should instead copy the iterator
00964         // if it has a valid cache?
00965     }
00966     _Rope_const_iterator operator--(int) {
00967         size_t __old_pos = _M_current_pos;
00968         _M_decr(1);
00969         return _Rope_const_iterator<_CharT,_Alloc>(_M_root, __old_pos);
00970     }
00971     template<class _CharT2, class _Alloc2>
00972     friend _Rope_const_iterator<_CharT2,_Alloc2> operator-
00973         (const _Rope_const_iterator<_CharT2,_Alloc2>& __x,
00974          ptrdiff_t __n);
00975     template<class _CharT2, class _Alloc2>
00976     friend _Rope_const_iterator<_CharT2,_Alloc2> operator+
00977         (const _Rope_const_iterator<_CharT2,_Alloc2>& __x,
00978          ptrdiff_t __n);
00979     template<class _CharT2, class _Alloc2>
00980     friend _Rope_const_iterator<_CharT2,_Alloc2> operator+
00981         (ptrdiff_t __n,
00982          const _Rope_const_iterator<_CharT2,_Alloc2>& __x);
00983     reference operator[](size_t __n) {
00984         return rope<_CharT,_Alloc>::_S_fetch(_M_root, _M_current_pos + __n);
00985     }
00986 
00987     template<class _CharT2, class _Alloc2>
00988     friend bool operator==
00989         (const _Rope_const_iterator<_CharT2,_Alloc2>& __x,
00990          const _Rope_const_iterator<_CharT2,_Alloc2>& __y);
00991     template<class _CharT2, class _Alloc2>
00992     friend bool operator< 
00993         (const _Rope_const_iterator<_CharT2,_Alloc2>& __x,
00994          const _Rope_const_iterator<_CharT2,_Alloc2>& __y);
00995     template<class _CharT2, class _Alloc2>
00996     friend ptrdiff_t operator-
00997         (const _Rope_const_iterator<_CharT2,_Alloc2>& __x,
00998          const _Rope_const_iterator<_CharT2,_Alloc2>& __y);
00999 };
01000 
01001 template<class _CharT, class _Alloc>
01002 class _Rope_iterator : public _Rope_iterator_base<_CharT,_Alloc> {
01003     friend class rope<_CharT,_Alloc>;
01004   protected:
01005     rope<_CharT,_Alloc>* _M_root_rope;
01006         // root is treated as a cached version of this,
01007         // and is used to detect changes to the underlying
01008         // rope.
01009         // Root is included in the reference count.
01010         // This is necessary so that we can detect changes reliably.
01011         // Unfortunately, it requires careful bookkeeping for the
01012         // nonGC case.
01013     _Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos)
01014       : _Rope_iterator_base<_CharT,_Alloc>(__r->_M_tree_ptr, __pos),
01015         _M_root_rope(__r) 
01016        { _RopeRep::_S_ref(_M_root); if (!(__r -> empty()))_S_setcache(*this); }
01017 
01018     void _M_check();
01019   public:
01020     typedef _Rope_char_ref_proxy<_CharT,_Alloc>  reference;
01021     typedef _Rope_char_ref_proxy<_CharT,_Alloc>* pointer;
01022 
01023   public:
01024     rope<_CharT,_Alloc>& container() { return *_M_root_rope; }
01025     _Rope_iterator() {
01026         _M_root = 0;  // Needed for reference counting.
01027     };
01028     _Rope_iterator(const _Rope_iterator& __x) :
01029         _Rope_iterator_base<_CharT,_Alloc>(__x) {
01030         _M_root_rope = __x._M_root_rope;
01031         _RopeRep::_S_ref(_M_root);
01032     }
01033     _Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos);
01034     ~_Rope_iterator() {
01035         _RopeRep::_S_unref(_M_root);
01036     }
01037     _Rope_iterator& operator= (const _Rope_iterator& __x) {
01038         _RopeRep* __old = _M_root;
01039 
01040         _RopeRep::_S_ref(__x._M_root);
01041         if (0 != __x._M_buf_ptr) {
01042             _M_root_rope = __x._M_root_rope;
01043             *(static_cast<_Rope_iterator_base<_CharT,_Alloc>*>(this)) = __x;
01044         } else {
01045             _M_current_pos = __x._M_current_pos;
01046             _M_root = __x._M_root;
01047             _M_root_rope = __x._M_root_rope;
01048             _M_buf_ptr = 0;
01049         }
01050         _RopeRep::_S_unref(__old);
01051         return(*this);
01052     }
01053     reference operator*() {
01054         _M_check();
01055         if (0 == _M_buf_ptr) {
01056             return _Rope_char_ref_proxy<_CharT,_Alloc>(
01057                _M_root_rope, _M_current_pos);
01058         } else {
01059             return _Rope_char_ref_proxy<_CharT,_Alloc>(
01060                _M_root_rope, _M_current_pos, *_M_buf_ptr);
01061         }
01062     }
01063     _Rope_iterator& operator++() {
01064         _M_incr(1);
01065         return *this;
01066     }
01067     _Rope_iterator& operator+=(ptrdiff_t __n) {
01068         if (__n >= 0) {
01069             _M_incr(__n);
01070         } else {
01071             _M_decr(-__n);
01072         }
01073         return *this;
01074     }
01075     _Rope_iterator& operator--() {
01076         _M_decr(1);
01077         return *this;
01078     }
01079     _Rope_iterator& operator-=(ptrdiff_t __n) {
01080         if (__n >= 0) {
01081             _M_decr(__n);
01082         } else {
01083             _M_incr(-__n);
01084         }
01085         return *this;
01086     }
01087     _Rope_iterator operator++(int) {
01088         size_t __old_pos = _M_current_pos;
01089         _M_incr(1);
01090         return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
01091     }
01092     _Rope_iterator operator--(int) {
01093         size_t __old_pos = _M_current_pos;
01094         _M_decr(1);
01095         return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
01096     }
01097     reference operator[](ptrdiff_t __n) {
01098         return _Rope_char_ref_proxy<_CharT,_Alloc>(
01099           _M_root_rope, _M_current_pos + __n);
01100     }
01101 
01102     template<class _CharT2, class _Alloc2>
01103     friend bool operator==
01104         (const _Rope_iterator<_CharT2,_Alloc2>& __x,
01105          const _Rope_iterator<_CharT2,_Alloc2>& __y);
01106     template<class _CharT2, class _Alloc2>
01107     friend bool operator<
01108         (const _Rope_iterator<_CharT2,_Alloc2>& __x,
01109          const _Rope_iterator<_CharT2,_Alloc2>& __y);
01110     template<class _CharT2, class _Alloc2>
01111     friend ptrdiff_t operator-
01112         (const _Rope_iterator<_CharT2,_Alloc2>& __x,
01113          const _Rope_iterator<_CharT2,_Alloc2>& __y);
01114     template<class _CharT2, class _Alloc2>
01115     friend _Rope_iterator<_CharT2,_Alloc2> operator-
01116         (const _Rope_iterator<_CharT2,_Alloc2>& __x,
01117          ptrdiff_t __n);
01118     template<class _CharT2, class _Alloc2>
01119     friend _Rope_iterator<_CharT2,_Alloc2> operator+
01120         (const _Rope_iterator<_CharT2,_Alloc2>& __x,
01121          ptrdiff_t __n);
01122     template<class _CharT2, class _Alloc2>
01123     friend _Rope_iterator<_CharT2,_Alloc2> operator+
01124         (ptrdiff_t __n,
01125          const _Rope_iterator<_CharT2,_Alloc2>& __x);
01126 };
01127 
01128 //  The rope base class encapsulates
01129 //  the differences between SGI-style allocators and standard-conforming
01130 //  allocators.
01131 
01132 // Base class for ordinary allocators.
01133 template <class _CharT, class _Allocator, bool _IsStatic>
01134 class _Rope_alloc_base {
01135 public:
01136   typedef _Rope_RopeRep<_CharT,_Allocator> _RopeRep;
01137   typedef typename _Alloc_traits<_CharT,_Allocator>::allocator_type
01138           allocator_type;
01139   allocator_type get_allocator() const { return _M_data_allocator; }
01140   _Rope_alloc_base(_RopeRep *__t, const allocator_type& __a)
01141         : _M_tree_ptr(__t), _M_data_allocator(__a) {}
01142   _Rope_alloc_base(const allocator_type& __a)
01143         : _M_data_allocator(__a) {}
01144   
01145 protected:
01146   // The only data members of a rope:
01147     allocator_type _M_data_allocator;
01148     _RopeRep* _M_tree_ptr;
01149 
01150 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
01151         typedef typename \
01152           _Alloc_traits<_Tp,_Allocator>::allocator_type __name##Allocator; \
01153         _Tp* __name##_allocate(size_t __n) const \
01154           { return __name##Allocator(_M_data_allocator).allocate(__n); } \
01155         void __name##_deallocate(_Tp *__p, size_t __n) const \
01156                 { __name##Allocator(_M_data_allocator).deallocate(__p, __n); }
01157   __ROPE_DEFINE_ALLOCS(_Allocator)
01158 # undef __ROPE_DEFINE_ALLOC
01159 };
01160 
01161 // Specialization for allocators that have the property that we don't
01162 //  actually have to store an allocator object.  
01163 template <class _CharT, class _Allocator>
01164 class _Rope_alloc_base<_CharT,_Allocator,true> {
01165 public:
01166   typedef _Rope_RopeRep<_CharT,_Allocator> _RopeRep;
01167   typedef typename _Alloc_traits<_CharT,_Allocator>::allocator_type
01168           allocator_type;
01169   allocator_type get_allocator() const { return allocator_type(); }
01170   _Rope_alloc_base(_RopeRep *__t, const allocator_type&)
01171                 : _M_tree_ptr(__t) {}
01172   _Rope_alloc_base(const allocator_type&) {}
01173   
01174 protected:
01175   // The only data member of a rope:
01176     _RopeRep *_M_tree_ptr;
01177 
01178 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
01179         typedef typename \
01180           _Alloc_traits<_Tp,_Allocator>::_Alloc_type __name##Alloc; \
01181         typedef typename \
01182           _Alloc_traits<_Tp,_Allocator>::allocator_type __name##Allocator; \
01183         static _Tp* __name##_allocate(size_t __n) \
01184           { return __name##Alloc::allocate(__n); } \
01185         static void __name##_deallocate(_Tp *__p, size_t __n) \
01186           { __name##Alloc::deallocate(__p, __n); }
01187   __ROPE_DEFINE_ALLOCS(_Allocator)
01188 # undef __ROPE_DEFINE_ALLOC
01189 };
01190 
01191 template <class _CharT, class _Alloc>
01192 struct _Rope_base 
01193   : public _Rope_alloc_base<_CharT,_Alloc,
01194                             _Alloc_traits<_CharT,_Alloc>::_S_instanceless>
01195 {
01196   typedef _Rope_alloc_base<_CharT,_Alloc,
01197                             _Alloc_traits<_CharT,_Alloc>::_S_instanceless>
01198           _Base;
01199   typedef typename _Base::allocator_type allocator_type;
01200   typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;
01201         // The one in _Base may not be visible due to template rules.
01202   _Rope_base(_RopeRep* __t, const allocator_type& __a) : _Base(__t, __a) {}
01203   _Rope_base(const allocator_type& __a) : _Base(__a) {}
01204 };    
01205 
01206 
01207 template <class _CharT, class _Alloc>
01208 class rope : public _Rope_base<_CharT,_Alloc> {
01209     public:
01210         typedef _CharT value_type;
01211         typedef ptrdiff_t difference_type;
01212         typedef size_t size_type;
01213         typedef _CharT const_reference;
01214         typedef const _CharT* const_pointer;
01215         typedef _Rope_iterator<_CharT,_Alloc> iterator;
01216         typedef _Rope_const_iterator<_CharT,_Alloc> const_iterator;
01217         typedef _Rope_char_ref_proxy<_CharT,_Alloc> reference;
01218         typedef _Rope_char_ptr_proxy<_CharT,_Alloc> pointer;
01219 
01220         friend class _Rope_iterator<_CharT,_Alloc>;
01221         friend class _Rope_const_iterator<_CharT,_Alloc>;
01222         friend struct _Rope_RopeRep<_CharT,_Alloc>;
01223         friend class _Rope_iterator_base<_CharT,_Alloc>;
01224         friend class _Rope_char_ptr_proxy<_CharT,_Alloc>;
01225         friend class _Rope_char_ref_proxy<_CharT,_Alloc>;
01226         friend struct _Rope_RopeSubstring<_CharT,_Alloc>;
01227 
01228     protected:
01229         typedef _Rope_base<_CharT,_Alloc> _Base;
01230         typedef typename _Base::allocator_type allocator_type;
01231         using _Base::_M_tree_ptr;
01232         typedef __GC_CONST _CharT* _Cstrptr;
01233 
01234         static _CharT _S_empty_c_str[1];
01235 
01236         static bool _S_is0(_CharT __c) { return __c == _S_eos((_CharT*)0); }
01237         enum { _S_copy_max = 23 };
01238                 // For strings shorter than _S_copy_max, we copy to
01239                 // concatenate.
01240 
01241         typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep;
01242         typedef _Rope_RopeConcatenation<_CharT,_Alloc> _RopeConcatenation;
01243         typedef _Rope_RopeLeaf<_CharT,_Alloc> _RopeLeaf;
01244         typedef _Rope_RopeFunction<_CharT,_Alloc> _RopeFunction;
01245         typedef _Rope_RopeSubstring<_CharT,_Alloc> _RopeSubstring;
01246 
01247         // Retrieve a character at the indicated position.
01248         static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
01249 
01250 #       ifndef __GC
01251             // Obtain a pointer to the character at the indicated position.
01252             // The pointer can be used to change the character.
01253             // If such a pointer cannot be produced, as is frequently the
01254             // case, 0 is returned instead.
01255             // (Returns nonzero only if all nodes in the path have a refcount
01256             // of 1.)
01257             static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
01258 #       endif
01259 
01260         static bool _S_apply_to_pieces(
01261                                 // should be template parameter
01262                                 _Rope_char_consumer<_CharT>& __c,
01263                                 const _RopeRep* __r,
01264                                 size_t __begin, size_t __end);
01265                                 // begin and end are assumed to be in range.
01266 
01267 #       ifndef __GC
01268           static void _S_unref(_RopeRep* __t)
01269           {
01270               _RopeRep::_S_unref(__t);
01271           }
01272           static void _S_ref(_RopeRep* __t)
01273           {
01274               _RopeRep::_S_ref(__t);
01275           }
01276 #       else /* __GC */
01277           static void _S_unref(_RopeRep*) {}
01278           static void _S_ref(_RopeRep*) {}
01279 #       endif
01280 
01281 
01282 #       ifdef __GC
01283             typedef _Rope_RopeRep<_CharT,_Alloc>* _Self_destruct_ptr;
01284 #       else
01285             typedef _Rope_self_destruct_ptr<_CharT,_Alloc> _Self_destruct_ptr;
01286 #       endif
01287 
01288         // _Result is counted in refcount.
01289         static _RopeRep* _S_substring(_RopeRep* __base,
01290                                     size_t __start, size_t __endp1);
01291 
01292         static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
01293                                           const _CharT* __iter, size_t __slen);
01294                 // Concatenate rope and char ptr, copying __s.
01295                 // Should really take an arbitrary iterator.
01296                 // Result is counted in refcount.
01297         static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,
01298                                           const _CharT* __iter, size_t __slen)
01299                 // As above, but one reference to __r is about to be
01300                 // destroyed.  Thus the pieces may be recycled if all
01301                 // relevent reference counts are 1.
01302 #           ifdef __GC
01303                 // We can't really do anything since refcounts are unavailable.
01304                 { return _S_concat_char_iter(__r, __iter, __slen); }
01305 #           else
01306                 ;
01307 #           endif
01308 
01309         static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
01310                 // General concatenation on _RopeRep.  _Result
01311                 // has refcount of 1.  Adjusts argument refcounts.
01312 
01313    public:
01314         void apply_to_pieces( size_t __begin, size_t __end,
01315                               _Rope_char_consumer<_CharT>& __c) const {
01316             _S_apply_to_pieces(__c, _M_tree_ptr, __begin, __end);
01317         }
01318 
01319 
01320    protected:
01321 
01322         static size_t _S_rounded_up_size(size_t __n) {
01323             return _RopeLeaf::_S_rounded_up_size(__n);
01324         }
01325 
01326         static size_t _S_allocated_capacity(size_t __n) {
01327             if (_S_is_basic_char_type((_CharT*)0)) {
01328                 return _S_rounded_up_size(__n) - 1;
01329             } else {
01330                 return _S_rounded_up_size(__n);
01331             }
01332         }
01333                 
01334         // Allocate and construct a RopeLeaf using the supplied allocator
01335         // Takes ownership of s instead of copying.
01336         static _RopeLeaf* _S_new_RopeLeaf(__GC_CONST _CharT *__s,
01337                                           size_t __size, allocator_type __a)
01338         {
01339             _RopeLeaf* __space = _LAllocator(__a).allocate(1);
01340             return new(__space) _RopeLeaf(__s, __size, __a);
01341         }
01342 
01343         static _RopeConcatenation* _S_new_RopeConcatenation(
01344                         _RopeRep* __left, _RopeRep* __right,
01345                         allocator_type __a)
01346         {
01347             _RopeConcatenation* __space = _CAllocator(__a).allocate(1);
01348             return new(__space) _RopeConcatenation(__left, __right, __a);
01349         }
01350 
01351         static _RopeFunction* _S_new_RopeFunction(char_producer<_CharT>* __f,
01352                 size_t __size, bool __d, allocator_type __a)
01353         {
01354             _RopeFunction* __space = _FAllocator(__a).allocate(1);
01355             return new(__space) _RopeFunction(__f, __size, __d, __a);
01356         }
01357 
01358         static _RopeSubstring* _S_new_RopeSubstring(
01359                 _Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,
01360                 size_t __l, allocator_type __a)
01361         {
01362             _RopeSubstring* __space = _SAllocator(__a).allocate(1);
01363             return new(__space) _RopeSubstring(__b, __s, __l, __a);
01364         }
01365 
01366           static
01367           _RopeLeaf* _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,
01368                        size_t __size, allocator_type __a)
01369 #         define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \
01370                 _S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a)     
01371         {
01372             if (0 == __size) return 0;
01373             _CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
01374 
01375             uninitialized_copy_n(__s, __size, __buf);
01376             _S_cond_store_eos(__buf[__size]);
01377             __STL_TRY {
01378               return _S_new_RopeLeaf(__buf, __size, __a);
01379             }
01380             __STL_UNWIND(_RopeRep::__STL_FREE_STRING(__buf, __size, __a))
01381         }
01382             
01383 
01384         // Concatenation of nonempty strings.
01385         // Always builds a concatenation node.
01386         // Rebalances if the result is too deep.
01387         // Result has refcount 1.
01388         // Does not increment left and right ref counts even though
01389         // they are referenced.
01390         static _RopeRep*
01391         _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
01392 
01393         // Concatenation helper functions
01394         static _RopeLeaf*
01395         _S_leaf_concat_char_iter(_RopeLeaf* __r,
01396                                  const _CharT* __iter, size_t __slen);
01397                 // Concatenate by copying leaf.
01398                 // should take an arbitrary iterator
01399                 // result has refcount 1.
01400 #       ifndef __GC
01401           static _RopeLeaf* _S_destr_leaf_concat_char_iter
01402                         (_RopeLeaf* __r, const _CharT* __iter, size_t __slen);
01403           // A version that potentially clobbers __r if __r->_M_ref_count == 1.
01404 #       endif
01405 
01406         private:
01407 
01408         static size_t _S_char_ptr_len(const _CharT* __s);
01409                         // slightly generalized strlen
01410 
01411         rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
01412           : _Base(__t,__a) { }
01413 
01414 
01415         // Copy __r to the _CharT buffer.
01416         // Returns __buffer + __r->_M_size.
01417         // Assumes that buffer is uninitialized.
01418         static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);
01419 
01420         // Again, with explicit starting position and length.
01421         // Assumes that buffer is uninitialized.
01422         static _CharT* _S_flatten(_RopeRep* __r,
01423                                   size_t __start, size_t __len,
01424                                   _CharT* __buffer);
01425 
01426         static const unsigned long 
01427           _S_min_len[_RopeRep::_S_max_rope_depth + 1];
01428 
01429         static bool _S_is_balanced(_RopeRep* __r)
01430                 { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
01431 
01432         static bool _S_is_almost_balanced(_RopeRep* __r)
01433                 { return (__r->_M_depth == 0 ||
01434                           __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
01435 
01436         static bool _S_is_roughly_balanced(_RopeRep* __r)
01437                 { return (__r->_M_depth <= 1 ||
01438                           __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
01439 
01440         // Assumes the result is not empty.
01441         static _RopeRep* _S_concat_and_set_balanced(_RopeRep* __left,
01442                                                      _RopeRep* __right)
01443         {
01444             _RopeRep* __result = _S_concat(__left, __right);
01445             if (_S_is_balanced(__result)) __result->_M_is_balanced = true;
01446             return __result;
01447         }
01448 
01449         // The basic rebalancing operation.  Logically copies the
01450         // rope.  The result has refcount of 1.  The client will
01451         // usually decrement the reference count of __r.
01452         // The result is within height 2 of balanced by the above
01453         // definition.
01454         static _RopeRep* _S_balance(_RopeRep* __r);
01455 
01456         // Add all unbalanced subtrees to the forest of balanceed trees.
01457         // Used only by balance.
01458         static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);
01459         
01460         // Add __r to forest, assuming __r is already balanced.
01461         static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
01462 
01463         // Print to stdout, exposing structure
01464         static void _S_dump(_RopeRep* __r, int __indent = 0);
01465 
01466         // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.
01467         static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);
01468 
01469    public:
01470         bool empty() const { return 0 == _M_tree_ptr; }
01471 
01472         // Comparison member function.  This is public only for those
01473         // clients that need a ternary comparison.  Others
01474         // should use the comparison operators below.
01475         int compare(const rope& __y) const {
01476             return _S_compare(_M_tree_ptr, __y._M_tree_ptr);
01477         }
01478 
01479         rope(const _CharT* __s, const allocator_type& __a = allocator_type())
01480         : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
01481                                                  __a),__a)
01482         { }
01483 
01484         rope(const _CharT* __s, size_t __len,
01485              const allocator_type& __a = allocator_type())
01486         : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, __a), __a)
01487         { }
01488 
01489         // Should perhaps be templatized with respect to the iterator type
01490         // and use Sequence_buffer.  (It should perhaps use sequence_buffer
01491         // even now.)
01492         rope(const _CharT *__s, const _CharT *__e,
01493              const allocator_type& __a = allocator_type())
01494         : _Base(__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, __a), __a)
01495         { }
01496 
01497         rope(const const_iterator& __s, const const_iterator& __e,
01498              const allocator_type& __a = allocator_type())
01499         : _Base(_S_substring(__s._M_root, __s._M_current_pos,
01500                              __e._M_current_pos), __a)
01501         { }
01502 
01503         rope(const iterator& __s, const iterator& __e,
01504              const allocator_type& __a = allocator_type())
01505         : _Base(_S_substring(__s._M_root, __s._M_current_pos,
01506                              __e._M_current_pos), __a)
01507         { }
01508 
01509         rope(_CharT __c, const allocator_type& __a = allocator_type())
01510         : _Base(__a)
01511         {
01512             _CharT* __buf = _Data_allocate(_S_rounded_up_size(1));
01513 
01514             construct(__buf, __c);
01515             __STL_TRY {
01516                 _M_tree_ptr = _S_new_RopeLeaf(__buf, 1, __a);
01517             }
01518             __STL_UNWIND(_RopeRep::__STL_FREE_STRING(__buf, 1, __a))
01519         }
01520 
01521         rope(size_t __n, _CharT __c,
01522              const allocator_type& __a = allocator_type());
01523 
01524         rope(const allocator_type& __a = allocator_type())
01525         : _Base(0, __a) {}
01526 
01527         // Construct a rope from a function that can compute its members
01528         rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn,
01529              const allocator_type& __a = allocator_type())
01530             : _Base(__a)
01531         {
01532             _M_tree_ptr = (0 == __len) ?
01533                0 : _S_new_RopeFunction(__fn, __len, __delete_fn, __a);
01534         }
01535 
01536         rope(const rope& __x, const allocator_type& __a = allocator_type())
01537         : _Base(__x._M_tree_ptr, __a)
01538         {
01539             _S_ref(_M_tree_ptr);
01540         }
01541 
01542         ~rope()
01543         {
01544             _S_unref(_M_tree_ptr);
01545         }
01546 
01547         rope& operator=(const rope& __x)
01548         {
01549             _RopeRep* __old = _M_tree_ptr;
01550             __stl_assert(get_allocator() == __x.get_allocator());
01551             _M_tree_ptr = __x._M_tree_ptr;
01552             _S_ref(_M_tree_ptr);
01553             _S_unref(__old);
01554             return(*this);
01555         }
01556 
01557         void clear()
01558         {
01559             _S_unref(_M_tree_ptr);
01560             _M_tree_ptr = 0;
01561         }
01562 
01563         void push_back(_CharT __x)
01564         {
01565             _RopeRep* __old = _M_tree_ptr;
01566             _M_tree_ptr = _S_destr_concat_char_iter(_M_tree_ptr, &__x, 1);
01567             _S_unref(__old);
01568         }
01569 
01570         void pop_back()
01571         {
01572             _RopeRep* __old = _M_tree_ptr;
01573             _M_tree_ptr = 
01574               _S_substring(_M_tree_ptr, 0, _M_tree_ptr->_M_size - 1);
01575             _S_unref(__old);
01576         }
01577 
01578         _CharT back() const
01579         {
01580             return _S_fetch(_M_tree_ptr, _M_tree_ptr->_M_size - 1);
01581         }
01582 
01583         void push_front(_CharT __x)
01584         {
01585             _RopeRep* __old = _M_tree_ptr;
01586             _RopeRep* __left =
01587               __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, get_allocator());
01588             __STL_TRY {
01589               _M_tree_ptr = _S_concat(__left, _M_tree_ptr);
01590               _S_unref(__old);
01591               _S_unref(__left);
01592             }
01593             __STL_UNWIND(_S_unref(__left))
01594         }
01595 
01596         void pop_front()
01597         {
01598             _RopeRep* __old = _M_tree_ptr;
01599             _M_tree_ptr = _S_substring(_M_tree_ptr, 1, _M_tree_ptr->_M_size);
01600             _S_unref(__old);
01601         }
01602 
01603         _CharT front() const
01604         {
01605             return _S_fetch(_M_tree_ptr, 0);
01606         }
01607 
01608         void balance()
01609         {
01610             _RopeRep* __old = _M_tree_ptr;
01611             _M_tree_ptr = _S_balance(_M_tree_ptr);
01612             _S_unref(__old);
01613         }
01614 
01615         void copy(_CharT* __buffer) const {
01616             destroy(__buffer, __buffer + size());
01617             _S_flatten(_M_tree_ptr, __buffer);
01618         }
01619 
01620         // This is the copy function from the standard, but
01621         // with the arguments reordered to make it consistent with the
01622         // rest of the interface.
01623         // Note that this guaranteed not to compile if the draft standard
01624         // order is assumed.
01625         size_type copy(size_type __pos, size_type __n, _CharT* __buffer) const 
01626         {
01627             size_t __size = size();
01628             size_t __len = (__pos + __n > __size? __size - __pos : __n);
01629 
01630             destroy(__buffer, __buffer + __len);
01631             _S_flatten(_M_tree_ptr, __pos, __len, __buffer);
01632             return __len;
01633         }
01634 
01635         // Print to stdout, exposing structure.  May be useful for
01636         // performance debugging.
01637         void dump() {
01638             _S_dump(_M_tree_ptr);
01639         }
01640 
01641         // Convert to 0 terminated string in new allocated memory.
01642         // Embedded 0s in the input do not terminate the copy.
01643         const _CharT* c_str() const;
01644 
01645         // As above, but lso use the flattened representation as the
01646         // the new rope representation.
01647         const _CharT* replace_with_c_str();
01648 
01649         // Reclaim memory for the c_str generated flattened string.
01650         // Intentionally undocumented, since it's hard to say when this
01651         // is safe for multiple threads.
01652         void delete_c_str () {
01653             if (0 == _M_tree_ptr) return;
01654             if (_RopeRep::_S_leaf == _M_tree_ptr->_M_tag && 
01655                 ((_RopeLeaf*)_M_tree_ptr)->_M_data == 
01656                       _M_tree_ptr->_M_c_string) {
01657                 // Representation shared
01658                 return;
01659             }
01660 #           ifndef __GC
01661               _M_tree_ptr->_M_free_c_string();
01662 #           endif
01663             _M_tree_ptr->_M_c_string = 0;
01664         }
01665 
01666         _CharT operator[] (size_type __pos) const {
01667             return _S_fetch(_M_tree_ptr, __pos);
01668         }
01669 
01670         _CharT at(size_type __pos) const {
01671            // if (__pos >= size()) throw out_of_range;  // XXX
01672            return (*this)[__pos];
01673         }
01674 
01675         const_iterator begin() const {
01676             return(const_iterator(_M_tree_ptr, 0));
01677         }
01678 
01679         // An easy way to get a const iterator from a non-const container.
01680         const_iterator const_begin() const {
01681             return(const_iterator(_M_tree_ptr, 0));
01682         }
01683 
01684         const_iterator end() const {
01685             return(const_iterator(_M_tree_ptr, size()));
01686         }
01687 
01688         const_iterator const_end() const {
01689             return(const_iterator(_M_tree_ptr, size()));
01690         }
01691 
01692         size_type size() const { 
01693             return(0 == _M_tree_ptr? 0 : _M_tree_ptr->_M_size);
01694         }
01695 
01696         size_type length() const {
01697             return size();
01698         }
01699 
01700         size_type max_size() const {
01701             return _S_min_len[_RopeRep::_S_max_rope_depth-1] - 1;
01702             //  Guarantees that the result can be sufficirntly
01703             //  balanced.  Longer ropes will probably still work,
01704             //  but it's harder to make guarantees.
01705         }
01706 
01707         typedef reverse_iterator<const_iterator> const_reverse_iterator;
01708 
01709         const_reverse_iterator rbegin() const {
01710             return const_reverse_iterator(end());
01711         }
01712 
01713         const_reverse_iterator const_rbegin() const {
01714             return const_reverse_iterator(end());
01715         }
01716 
01717         const_reverse_iterator rend() const {
01718             return const_reverse_iterator(begin());
01719         }
01720 
01721         const_reverse_iterator const_rend() const {
01722             return const_reverse_iterator(begin());
01723         }
01724 
01725         template<class _CharT2, class _Alloc2>
01726         friend rope<_CharT2,_Alloc2>
01727         operator+ (const rope<_CharT2,_Alloc2>& __left,
01728                    const rope<_CharT2,_Alloc2>& __right);
01729         
01730         template<class _CharT2, class _Alloc2>
01731         friend rope<_CharT2,_Alloc2>
01732         operator+ (const rope<_CharT2,_Alloc2>& __left,
01733                    const _CharT2* __right);
01734         
01735         template<class _CharT2, class _Alloc2>
01736         friend rope<_CharT2,_Alloc2>
01737         operator+ (const rope<_CharT2,_Alloc2>& __left, _CharT2 __right);
01738         // The symmetric cases are intentionally omitted, since they're presumed
01739         // to be less common, and we don't handle them as well.
01740 
01741         // The following should really be templatized.
01742         // The first argument should be an input iterator or
01743         // forward iterator with value_type _CharT.
01744         rope& append(const _CharT* __iter, size_t __n) {
01745             _RopeRep* __result = 
01746               _S_destr_concat_char_iter(_M_tree_ptr, __iter, __n);
01747             _S_unref(_M_tree_ptr);
01748             _M_tree_ptr = __result;
01749             return *this;
01750         }
01751 
01752         rope& append(const _CharT* __c_string) {
01753             size_t __len = _S_char_ptr_len(__c_string);
01754             append(__c_string, __len);
01755             return(*this);
01756         }
01757 
01758         rope& append(const _CharT* __s, const _CharT* __e) {
01759             _RopeRep* __result =
01760                 _S_destr_concat_char_iter(_M_tree_ptr, __s, __e - __s);
01761             _S_unref(_M_tree_ptr);
01762             _M_tree_ptr = __result;
01763             return *this;
01764         }
01765 
01766         rope& append(const_iterator __s, const_iterator __e) {
01767             __stl_assert(__s._M_root == __e._M_root);
01768             __stl_assert(get_allocator() == __s._M_root->get_allocator());
01769             _Self_destruct_ptr __appendee(_S_substring(
01770               __s._M_root, __s._M_current_pos, __e._M_current_pos));
01771             _RopeRep* __result = 
01772               _S_concat(_M_tree_ptr, (_RopeRep*)__appendee);
01773             _S_unref(_M_tree_ptr);
01774             _M_tree_ptr = __result;
01775             return *this;
01776         }
01777 
01778         rope& append(_CharT __c) {
01779             _RopeRep* __result = 
01780               _S_destr_concat_char_iter(_M_tree_ptr, &__c, 1);
01781             _S_unref(_M_tree_ptr);
01782             _M_tree_ptr = __result;
01783             return *this;
01784         }
01785 
01786         rope& append() { return append(_CharT()); }  // XXX why?
01787 
01788         rope& append(const rope& __y) {
01789             __stl_assert(__y.get_allocator() == get_allocator());
01790             _RopeRep* __result = _S_concat(_M_tree_ptr, __y._M_tree_ptr);
01791             _S_unref(_M_tree_ptr);
01792             _M_tree_ptr = __result;
01793             return *this;
01794         }
01795 
01796         rope& append(size_t __n, _CharT __c) {
01797             rope<_CharT,_Alloc> __last(__n, __c);
01798             return append(__last);
01799         }
01800 
01801         void swap(rope& __b) {
01802             __stl_assert(get_allocator() == __b.get_allocator());
01803             _RopeRep* __tmp = _M_tree_ptr;
01804             _M_tree_ptr = __b._M_tree_ptr;
01805             __b._M_tree_ptr = __tmp;
01806         }
01807 
01808 
01809     protected:
01810         // Result is included in refcount.
01811         static _RopeRep* replace(_RopeRep* __old, size_t __pos1,
01812                                   size_t __pos2, _RopeRep* __r) {
01813             if (0 == __old) { _S_ref(__r); return __r; }
01814             _Self_destruct_ptr __left(
01815               _S_substring(__old, 0, __pos1));
01816             _Self_destruct_ptr __right(
01817               _S_substring(__old, __pos2, __old->_M_size));
01818             _RopeRep* __result;
01819 
01820             __stl_assert(__old->get_allocator() == __r->get_allocator());
01821             if (0 == __r) {
01822                 __result = _S_concat(__left, __right);
01823             } else {
01824                 _Self_destruct_ptr __left_result(_S_concat(__left, __r));
01825                 __result = _S_concat(__left_result, __right);
01826             }
01827             return __result;
01828         }
01829 
01830     public:
01831         void insert(size_t __p, const rope& __r) {
01832             _RopeRep* __result = 
01833               replace(_M_tree_ptr, __p, __p, __r._M_tree_ptr);
01834             __stl_assert(get_allocator() == __r.get_allocator());
01835             _S_unref(_M_tree_ptr);
01836             _M_tree_ptr = __result;
01837         }
01838 
01839         void insert(size_t __p, size_t __n, _CharT __c) {
01840             rope<_CharT,_Alloc> __r(__n,__c);
01841             insert(__p, __r);
01842         }
01843 
01844         void insert(size_t __p, const _CharT* __i, size_t __n) {
01845             _Self_destruct_ptr __left(_S_substring(_M_tree_ptr, 0, __p));
01846             _Self_destruct_ptr __right(_S_substring(_M_tree_ptr, __p, size()));
01847             _Self_destruct_ptr __left_result(
01848               _S_concat_char_iter(__left, __i, __n));
01849                 // _S_ destr_concat_char_iter should be safe here.
01850                 // But as it stands it's probably not a win, since __left
01851                 // is likely to have additional references.
01852             _RopeRep* __result = _S_concat(__left_result, __right);
01853             _S_unref(_M_tree_ptr);
01854             _M_tree_ptr = __result;
01855         }
01856 
01857         void insert(size_t __p, const _CharT* __c_string) {
01858             insert(__p, __c_string, _S_char_ptr_len(__c_string));
01859         }
01860 
01861         void insert(size_t __p, _CharT __c) {
01862             insert(__p, &__c, 1);
01863         }
01864 
01865         void insert(size_t __p) {
01866             _CharT __c = _CharT();
01867             insert(__p, &__c, 1);
01868         }
01869 
01870         void insert(size_t __p, const _CharT* __i, const _CharT* __j) {
01871             rope __r(__i, __j);
01872             insert(__p, __r);
01873         }
01874 
01875         void insert(size_t __p, const const_iterator& __i,
01876                               const const_iterator& __j) {
01877             rope __r(__i, __j);
01878             insert(__p, __r);
01879         }
01880 
01881         void insert(size_t __p, const iterator& __i,
01882                               const iterator& __j) {
01883             rope __r(__i, __j);
01884             insert(__p, __r);
01885         }
01886 
01887         // (position, length) versions of replace operations:
01888 
01889         void replace(size_t __p, size_t __n, const rope& __r) {
01890             _RopeRep* __result = 
01891               replace(_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);
01892             _S_unref(_M_tree_ptr);
01893             _M_tree_ptr = __result;
01894         }
01895 
01896         void replace(size_t __p, size_t __n, 
01897                      const _CharT* __i, size_t __i_len) {
01898             rope __r(__i, __i_len);
01899             replace(__p, __n, __r);
01900         }
01901 
01902         void replace(size_t __p, size_t __n, _CharT __c) {
01903             rope __r(__c);
01904             replace(__p, __n, __r);
01905         }
01906 
01907         void replace(size_t __p, size_t __n, const _CharT* __c_string) {
01908             rope __r(__c_string);
01909             replace(__p, __n, __r);
01910         }
01911 
01912         void replace(size_t __p, size_t __n, 
01913                      const _CharT* __i, const _CharT* __j) {
01914             rope __r(__i, __j);
01915             replace(__p, __n, __r);
01916         }
01917 
01918         void replace(size_t __p, size_t __n,
01919                      const const_iterator& __i, const const_iterator& __j) {
01920             rope __r(__i, __j);
01921             replace(__p, __n, __r);
01922         }
01923 
01924         void replace(size_t __p, size_t __n,
01925                      const iterator& __i, const iterator& __j) {
01926             rope __r(__i, __j);
01927             replace(__p, __n, __r);
01928         }
01929 
01930         // Single character variants:
01931         void replace(size_t __p, _CharT __c) {
01932             iterator __i(this, __p);
01933             *__i = __c;
01934         }
01935 
01936         void replace(size_t __p, const rope& __r) {
01937             replace(__p, 1, __r);
01938         }
01939 
01940         void replace(size_t __p, const _CharT* __i, size_t __i_len) {
01941             replace(__p, 1, __i, __i_len);
01942         }
01943 
01944         void replace(size_t __p, const _CharT* __c_string) {
01945             replace(__p, 1, __c_string);
01946         }
01947 
01948         void replace(size_t __p, const _CharT* __i, const _CharT* __j) {
01949             replace(__p, 1, __i, __j);
01950         }
01951 
01952         void replace(size_t __p, const const_iterator& __i,
01953                                const const_iterator& __j) {
01954             replace(__p, 1, __i, __j);
01955         }
01956 
01957         void replace(size_t __p, const iterator& __i,
01958                                const iterator& __j) {
01959             replace(__p, 1, __i, __j);
01960         }
01961 
01962         // Erase, (position, size) variant.
01963         void erase(size_t __p, size_t __n) {
01964             _RopeRep* __result = replace(_M_tree_ptr, __p, __p + __n, 0);
01965             _S_unref(_M_tree_ptr);
01966             _M_tree_ptr = __result;
01967         }
01968 
01969         // Erase, single character
01970         void erase(size_t __p) {
01971             erase(__p, __p + 1);
01972         }
01973 
01974         // Insert, iterator variants.  
01975         iterator insert(const iterator& __p, const rope& __r)
01976                 { insert(__p.index(), __r); return __p; }
01977         iterator insert(const iterator& __p, size_t __n, _CharT __c)
01978                 { insert(__p.index(), __n, __c); return __p; }
01979         iterator insert(const iterator& __p, _CharT __c) 
01980                 { insert(__p.index(), __c); return __p; }
01981         iterator insert(const iterator& __p ) 
01982                 { insert(__p.index()); return __p; }
01983         iterator insert(const iterator& __p, const _CharT* c_string) 
01984                 { insert(__p.index(), c_string); return __p; }
01985         iterator insert(const iterator& __p, const _CharT* __i, size_t __n)
01986                 { insert(__p.index(), __i, __n); return __p; }
01987         iterator insert(const iterator& __p, const _CharT* __i, 
01988                         const _CharT* __j)
01989                 { insert(__p.index(), __i, __j);  return __p; }
01990         iterator insert(const iterator& __p,
01991                         const const_iterator& __i, const const_iterator& __j)
01992                 { insert(__p.index(), __i, __j); return __p; }
01993         iterator insert(const iterator& __p,
01994                         const iterator& __i, const iterator& __j)
01995                 { insert(__p.index(), __i, __j); return __p; }
01996 
01997         // Replace, range variants.
01998         void replace(const iterator& __p, const iterator& __q,
01999                      const rope& __r)
02000                 { replace(__p.index(), __q.index() - __p.index(), __r); }
02001         void replace(const iterator& __p, const iterator& __q, _CharT __c)
02002                 { replace(__p.index(), __q.index() - __p.index(), __c); }
02003         void replace(const iterator& __p, const iterator& __q,
02004                      const _CharT* __c_string)
02005                 { replace(__p.index(), __q.index() - __p.index(), __c_string); }
02006         void replace(const iterator& __p, const iterator& __q,
02007                      const _CharT* __i, size_t __n)
02008                 { replace(__p.index(), __q.index() - __p.index(), __i, __n); }
02009         void replace(const iterator& __p, const iterator& __q,
02010                      const _CharT* __i, const _CharT* __j)
02011                 { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
02012         void replace(const iterator& __p, const iterator& __q,
02013                      const const_iterator& __i, const const_iterator& __j)
02014                 { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
02015         void replace(const iterator& __p, const iterator& __q,
02016                      const iterator& __i, const iterator& __j)
02017                 { replace(__p.index(), __q.index() - __p.index(), __i, __j); }
02018 
02019         // Replace, iterator variants.
02020         void replace(const iterator& __p, const rope& __r)
02021                 { replace(__p.index(), __r); }
02022         void replace(const iterator& __p, _CharT __c)
02023                 { replace(__p.index(), __c); }
02024         void replace(const iterator& __p, const _CharT* __c_string)
02025                 { replace(__p.index(), __c_string); }
02026         void replace(const iterator& __p, const _CharT* __i, size_t __n)
02027                 { replace(__p.index(), __i, __n); }
02028         void replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
02029                 { replace(__p.index(), __i, __j); }
02030         void replace(const iterator& __p, const_iterator __i, 
02031                      const_iterator __j)
02032                 { replace(__p.index(), __i, __j); }
02033         void replace(const iterator& __p, iterator __i, iterator __j)
02034                 { replace(__p.index(), __i, __j); }
02035 
02036         // Iterator and range variants of erase
02037         iterator erase(const iterator& __p, const iterator& __q) {
02038             size_t __p_index = __p.index();
02039             erase(__p_index, __q.index() - __p_index);
02040             return iterator(this, __p_index);
02041         }
02042         iterator erase(const iterator& __p) {
02043             size_t __p_index = __p.index();
02044             erase(__p_index, 1);
02045             return iterator(this, __p_index);
02046         }
02047 
02048         rope substr(size_t __start, size_t __len = 1) const {
02049             return rope<_CharT,_Alloc>(
02050                         _S_substring(_M_tree_ptr, __start, __start + __len));
02051         }
02052 
02053         rope substr(iterator __start, iterator __end) const {
02054             return rope<_CharT,_Alloc>(
02055                 _S_substring(_M_tree_ptr, __start.index(), __end.index()));
02056         }
02057         
02058         rope substr(iterator __start) const {
02059             size_t __pos = __start.index();
02060             return rope<_CharT,_Alloc>(
02061                         _S_substring(_M_tree_ptr, __pos, __pos + 1));
02062         }
02063         
02064         rope substr(const_iterator __start, const_iterator __end) const {
02065             // This might eventually take advantage of the cache in the
02066             // iterator.
02067             return rope<_CharT,_Alloc>(
02068               _S_substring(_M_tree_ptr, __start.index(), __end.index()));
02069         }
02070 
02071         rope<_CharT,_Alloc> substr(const_iterator __start) {
02072             size_t __pos = __start.index();
02073             return rope<_CharT,_Alloc>(
02074               _S_substring(_M_tree_ptr, __pos, __pos + 1));
02075         }
02076 
02077         static const size_type npos;
02078 
02079         size_type find(_CharT __c, size_type __pos = 0) const;
02080         size_type find(const _CharT* __s, size_type __pos = 0) const {
02081             size_type __result_pos;
02082             const_iterator __result = search(const_begin() + __pos, const_end(),
02083                                            __s, __s + _S_char_ptr_len(__s));
02084             __result_pos = __result.index();
02085 #           ifndef __STL_OLD_ROPE_SEMANTICS
02086                 if (__result_pos == size()) __result_pos = npos;
02087 #           endif
02088             return __result_pos;
02089         }
02090 
02091         iterator mutable_begin() {
02092             return(iterator(this, 0));
02093         }
02094 
02095         iterator mutable_end() {
02096             return(iterator(this, size()));
02097         }
02098 
02099         typedef reverse_iterator<iterator> reverse_iterator;
02100 
02101         reverse_iterator mutable_rbegin() {
02102             return reverse_iterator(mutable_end());
02103         }
02104 
02105         reverse_iterator mutable_rend() {
02106             return reverse_iterator(mutable_begin());
02107         }
02108 
02109         reference mutable_reference_at(size_type __pos) {
02110             return reference(this, __pos);
02111         }
02112 
02113 #       ifdef __STD_STUFF
02114             reference operator[] (size_type __pos) {
02115                 return _char_ref_proxy(this, __pos);
02116             }
02117 
02118             reference at(size_type __pos) {
02119                 // if (__pos >= size()) throw out_of_range;  // XXX
02120                 return (*this)[__pos];
02121             }
02122 
02123             void resize(size_type __n, _CharT __c) {}
02124             void resize(size_type __n) {}
02125             void reserve(size_type __res_arg = 0) {}
02126             size_type capacity() const {
02127                 return max_size();
02128             }
02129 
02130           // Stuff below this line is dangerous because it's error prone.
02131           // I would really like to get rid of it.
02132             // copy function with funny arg ordering.
02133               size_type copy(_CharT* __buffer, size_type __n, 
02134                              size_type __pos = 0) const {
02135                 return copy(__pos, __n, __buffer);
02136               }
02137 
02138             iterator end() { return mutable_end(); }
02139 
02140             iterator begin() { return mutable_begin(); }
02141 
02142             reverse_iterator rend() { return mutable_rend(); }
02143 
02144             reverse_iterator rbegin() { return mutable_rbegin(); }
02145 
02146 #       else
02147 
02148             const_iterator end() { return const_end(); }
02149 
02150             const_iterator begin() { return const_begin(); }
02151 
02152             const_reverse_iterator rend() { return const_rend(); }
02153   
02154             const_reverse_iterator rbegin() { return const_rbegin(); }
02155 
02156 #       endif
02157         
02158 };
02159 
02160 template <class _CharT, class _Alloc>
02161 const rope<_CharT, _Alloc>::size_type rope<_CharT, _Alloc>::npos =
02162                         (size_type)(-1);
02163 
02164 template <class _CharT, class _Alloc>
02165 inline bool operator== (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02166                         const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02167   return (__x._M_current_pos == __y._M_current_pos && 
02168           __x._M_root == __y._M_root);
02169 }
02170 
02171 template <class _CharT, class _Alloc>
02172 inline bool operator< (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02173                        const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02174   return (__x._M_current_pos < __y._M_current_pos);
02175 }
02176 
02177 template <class _CharT, class _Alloc>
02178 inline bool operator!= (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02179                         const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02180   return !(__x == __y);
02181 }
02182 
02183 template <class _CharT, class _Alloc>
02184 inline bool operator> (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02185                        const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02186   return __y < __x;
02187 }
02188 
02189 template <class _CharT, class _Alloc>
02190 inline bool operator<= (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02191                         const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02192   return !(__y < __x);
02193 }
02194 
02195 template <class _CharT, class _Alloc>
02196 inline bool operator>= (const _Rope_const_iterator<_CharT,_Alloc>& __x,
02197                         const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02198   return !(__x < __y);
02199 }
02200 
02201 template <class _CharT, class _Alloc>
02202 inline ptrdiff_t operator-(const _Rope_const_iterator<_CharT,_Alloc>& __x,
02203                            const _Rope_const_iterator<_CharT,_Alloc>& __y) {
02204   return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos;
02205 }
02206 
02207 template <class _CharT, class _Alloc>
02208 inline _Rope_const_iterator<_CharT,_Alloc>
02209 operator-(const _Rope_const_iterator<_CharT,_Alloc>& __x, ptrdiff_t __n) {
02210   return _Rope_const_iterator<_CharT,_Alloc>(
02211             __x._M_root, __x._M_current_pos - __n);
02212 }
02213 
02214 template <class _CharT, class _Alloc>
02215 inline _Rope_const_iterator<_CharT,_Alloc>
02216 operator+(const _Rope_const_iterator<_CharT,_Alloc>& __x, ptrdiff_t __n) {
02217   return _Rope_const_iterator<_CharT,_Alloc>(
02218            __x._M_root, __x._M_current_pos + __n);
02219 }
02220 
02221 template <class _CharT, class _Alloc>
02222 inline _Rope_const_iterator<_CharT,_Alloc>
02223 operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT,_Alloc>& __x) {
02224   return _Rope_const_iterator<_CharT,_Alloc>(
02225            __x._M_root, __x._M_current_pos + __n);
02226 }
02227 
02228 template <class _CharT, class _Alloc>
02229 inline bool operator== (const _Rope_iterator<_CharT,_Alloc>& __x,
02230                         const _Rope_iterator<_CharT,_Alloc>& __y) {
02231   return (__x._M_current_pos == __y._M_current_pos && 
02232           __x._M_root_rope == __y._M_root_rope);
02233 }
02234 
02235 template <class _CharT, class _Alloc>
02236 inline bool operator< (const _Rope_iterator<_CharT,_Alloc>& __x,
02237                        const _Rope_iterator<_CharT,_Alloc>& __y) {
02238   return (__x._M_current_pos < __y._M_current_pos);
02239 }
02240 
02241 template <class _CharT, class _Alloc>
02242 inline bool operator!= (const _Rope_iterator<_CharT,_Alloc>& __x,
02243                         const _Rope_iterator<_CharT,_Alloc>& __y) {
02244   return !(__x == __y);
02245 }
02246 
02247 template <class _CharT, class _Alloc>
02248 inline bool operator> (const _Rope_iterator<_CharT,_Alloc>& __x,
02249                        const _Rope_iterator<_CharT,_Alloc>& __y) {
02250   return __y < __x;
02251 }
02252 
02253 template <class _CharT, class _Alloc>
02254 inline bool operator<= (const _Rope_iterator<_CharT,_Alloc>& __x,
02255                         const _Rope_iterator<_CharT,_Alloc>& __y) {
02256   return !(__y < __x);
02257 }
02258 
02259 template <class _CharT, class _Alloc>
02260 inline bool operator>= (const _Rope_iterator<_CharT,_Alloc>& __x,
02261                         const _Rope_iterator<_CharT,_Alloc>& __y) {
02262   return !(__x < __y);
02263 }
02264 
02265 template <class _CharT, class _Alloc>
02266 inline ptrdiff_t operator-(const _Rope_iterator<_CharT,_Alloc>& __x,
02267                            const _Rope_iterator<_CharT,_Alloc>& __y) {
02268   return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos;
02269 }
02270 
02271 template <class _CharT, class _Alloc>
02272 inline _Rope_iterator<_CharT,_Alloc>
02273 operator-(const _Rope_iterator<_CharT,_Alloc>& __x,
02274           ptrdiff_t __n) {
02275   return _Rope_iterator<_CharT,_Alloc>(
02276     __x._M_root_rope, __x._M_current_pos - __n);
02277 }
02278 
02279 template <class _CharT, class _Alloc>
02280 inline _Rope_iterator<_CharT,_Alloc>
02281 operator+(const _Rope_iterator<_CharT,_Alloc>& __x,
02282           ptrdiff_t __n) {
02283   return _Rope_iterator<_CharT,_Alloc>(
02284     __x._M_root_rope, __x._M_current_pos + __n);
02285 }
02286 
02287 template <class _CharT, class _Alloc>
02288 inline _Rope_iterator<_CharT,_Alloc>
02289 operator+(ptrdiff_t __n, const _Rope_iterator<_CharT,_Alloc>& __x) {
02290   return _Rope_iterator<_CharT,_Alloc>(
02291     __x._M_root_rope, __x._M_current_pos + __n);
02292 }
02293 
02294 template <class _CharT, class _Alloc>
02295 inline
02296 rope<_CharT,_Alloc>
02297 operator+ (const rope<_CharT,_Alloc>& __left,
02298            const rope<_CharT,_Alloc>& __right)
02299 {
02300     __stl_assert(__left.get_allocator() == __right.get_allocator());
02301     return rope<_CharT,_Alloc>(
02302       rope<_CharT,_Alloc>::_S_concat(__left._M_tree_ptr, __right._M_tree_ptr));
02303     // Inlining this should make it possible to keep __left and
02304     // __right in registers.
02305 }
02306 
02307 template <class _CharT, class _Alloc>
02308 inline
02309 rope<_CharT,_Alloc>&
02310 operator+= (rope<_CharT,_Alloc>& __left, 
02311       const rope<_CharT,_Alloc>& __right)
02312 {
02313     __left.append(__right);
02314     return __left;
02315 }
02316 
02317 template <class _CharT, class _Alloc>
02318 inline
02319 rope<_CharT,_Alloc>
02320 operator+ (const rope<_CharT,_Alloc>& __left,
02321            const _CharT* __right) {
02322     size_t __rlen = rope<_CharT,_Alloc>::_S_char_ptr_len(__right);
02323     return rope<_CharT,_Alloc>(
02324       rope<_CharT,_Alloc>::_S_concat_char_iter(
02325         __left._M_tree_ptr, __right, __rlen)); 
02326 }
02327 
02328 template <class _CharT, class _Alloc>
02329 inline
02330 rope<_CharT,_Alloc>&
02331 operator+= (rope<_CharT,_Alloc>& __left,
02332             const _CharT* __right) {
02333     __left.append(__right);
02334     return __left;
02335 }
02336 
02337 template <class _CharT, class _Alloc>
02338 inline
02339 rope<_CharT,_Alloc>
02340 operator+ (const rope<_CharT,_Alloc>& __left, _CharT __right) {
02341     return rope<_CharT,_Alloc>(
02342       rope<_CharT,_Alloc>::_S_concat_char_iter(
02343         __left._M_tree_ptr, &__right, 1));
02344 }
02345 
02346 template <class _CharT, class _Alloc>
02347 inline
02348 rope<_CharT,_Alloc>&
02349 operator+= (rope<_CharT,_Alloc>& __left, _CharT __right) {
02350     __left.append(__right);
02351     return __left;
02352 }
02353 
02354 template <class _CharT, class _Alloc>
02355 bool
02356 operator< (const rope<_CharT,_Alloc>& __left, 
02357            const rope<_CharT,_Alloc>& __right) {
02358     return __left.compare(__right) < 0;
02359 }
02360         
02361 template <class _CharT, class _Alloc>
02362 bool
02363 operator== (const rope<_CharT,_Alloc>& __left, 
02364             const rope<_CharT,_Alloc>& __right) {
02365     return __left.compare(__right) == 0;
02366 }
02367 
02368 template <class _CharT, class _Alloc>
02369 inline bool operator== (const _Rope_char_ptr_proxy<_CharT,_Alloc>& __x,
02370                         const _Rope_char_ptr_proxy<_CharT,_Alloc>& __y) {
02371         return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root);
02372 }
02373 
02374 template <class _CharT, class _Alloc>
02375 inline bool
02376 operator!= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) {
02377   return !(__x == __y);
02378 }
02379 
02380 template <class _CharT, class _Alloc>
02381 inline bool
02382 operator> (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) {
02383   return __y < __x;
02384 }
02385 
02386 template <class _CharT, class _Alloc>
02387 inline bool
02388 operator<= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) {
02389   return !(__y < __x);
02390 }
02391 
02392 template <class _CharT, class _Alloc>
02393 inline bool
02394 operator>= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) {
02395   return !(__x < __y);
02396 }
02397 
02398 template <class _CharT, class _Alloc>
02399 inline bool operator!= (const _Rope_char_ptr_proxy<_CharT,_Alloc>& __x,
02400                         const _Rope_char_ptr_proxy<_CharT,_Alloc>& __y) {
02401   return !(__x == __y);
02402 }
02403 
02404 template<class _CharT, class _Traits, class _Alloc>
02405 basic_ostream<_CharT, _Traits>& operator<<
02406                                         (basic_ostream<_CharT, _Traits>& __o,
02407                                          const rope<_CharT, _Alloc>& __r);
02408 
02409 typedef rope<char> crope;
02410 typedef rope<wchar_t> wrope;
02411 
02412 inline crope::reference __mutable_reference_at(crope& __c, size_t __i)
02413 {
02414     return __c.mutable_reference_at(__i);
02415 }
02416 
02417 inline wrope::reference __mutable_reference_at(wrope& __c, size_t __i)
02418 {
02419     return __c.mutable_reference_at(__i);
02420 }
02421 
02422 template <class _CharT, class _Alloc>
02423 inline void swap(rope<_CharT,_Alloc>& __x, rope<_CharT,_Alloc>& __y) {
02424   __x.swap(__y);
02425 }
02426 
02427 // Hash functions should probably be revisited later:
02428 template<> struct hash<crope>
02429 {
02430   size_t operator()(const crope& __str) const
02431   {
02432     size_t __size = __str.size();
02433 
02434     if (0 == __size) return 0;
02435     return 13*__str[0] + 5*__str[__size - 1] + __size;
02436   }
02437 };
02438 
02439 
02440 template<> struct hash<wrope>
02441 {
02442   size_t operator()(const wrope& __str) const
02443   {
02444     size_t __size = __str.size();
02445 
02446     if (0 == __size) return 0;
02447     return 13*__str[0] + 5*__str[__size - 1] + __size;
02448   }
02449 };
02450 
02451 } // namespace std
02452 
02453 # include <ext/ropeimpl.h>
02454 
02455 # endif /* __SGI_STL_INTERNAL_ROPE_H */
02456 
02457 // Local Variables:
02458 // mode:C++
02459 // End:

Generated at Tue May 1 16:28:39 2001 for libstdc++-v3 by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001