home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 April / PCWorld_2000-04_cd.bin / Software / Servis / Devc / _SETUP.6 / Group15 / stl_rope.h < prev    next >
C/C++ Source or Header  |  1999-11-07  |  94KB  |  2,542 lines

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