/home/ntakagi/work/STLport-5.1.5/stlport/stl/_rope.h

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



Generated on Mon Mar 10 15:32:33 2008 by  doxygen 1.5.1