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