OSDN Git Service

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