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