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