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