OSDN Git Service

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