Whole document tree
    

Whole document tree

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

Generated on Mon Apr 8 03:11:44 2002 for libstdc++-v3 Source by doxygen1.2.15