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