OSDN Git Service

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