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