1 // SGI's rope class -*- C++ -*-
3 // Copyright (C) 2001-2022 Free Software Foundation, Inc.
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)
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.
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.
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/>.
27 * Silicon Graphics Computer Systems, Inc.
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.
39 * This file is a GNU extension to the Standard C++ Library (possibly
40 * containing extensions from the HP/SGI STL subset).
46 #pragma GCC system_header
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>
60 # define __GC_CONST const
62 # define __GC_CONST // constant except for deallocation
65 #include <ext/memory> // For uninitialized_copy_n
67 namespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
69 _GLIBCXX_BEGIN_NAMESPACE_VERSION
73 enum { _S_max_rope_depth = 45 };
74 enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};
75 } // namespace __detail
77 // See libstdc++/36832.
78 template<typename _ForwardIterator, typename _Allocator>
80 _Destroy_const(_ForwardIterator __first,
81 _ForwardIterator __last, _Allocator __alloc)
83 for (; __first != __last; ++__first)
84 __alloc.destroy(&*__first);
87 template<typename _ForwardIterator, typename _Tp>
89 _Destroy_const(_ForwardIterator __first,
90 _ForwardIterator __last, std::allocator<_Tp>)
91 { std::_Destroy(__first, __last); }
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.
96 // The end-of-C-string character.
97 // This is what the draft standard says it should be.
98 template <class _CharT>
103 // Test for basic character types.
104 // For basic character types leaves having a trailing eos.
105 template <class _CharT>
107 _S_is_basic_char_type(_CharT*)
110 template <class _CharT>
112 _S_is_one_byte_char_type(_CharT*)
116 _S_is_basic_char_type(char*)
120 _S_is_one_byte_char_type(char*)
124 _S_is_basic_char_type(wchar_t*)
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>
131 _S_cond_store_eos(_CharT&) { }
134 _S_cond_store_eos(char& __c)
138 _S_cond_store_eos(wchar_t& __c)
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>
149 virtual ~char_producer() { }
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.
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.
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.
174 // Ignore warnings about std::iterator.
175 #pragma GCC diagnostic push
176 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
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>
183 typedef typename _Sequence::value_type value_type;
185 _Sequence* _M_prefix;
186 value_type _M_buffer[_Buf_sz];
187 std::size_t _M_buf_count;
193 _M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);
201 : _M_prefix(0), _M_buf_count(0) { }
203 sequence_buffer(const sequence_buffer& __x)
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);
210 // Non-const "copy" modifies the parameter - yuck
211 sequence_buffer(sequence_buffer& __x)
214 _M_prefix = __x._M_prefix;
218 sequence_buffer(_Sequence& __s)
219 : _M_prefix(&__s), _M_buf_count(0) { }
221 // Non-const "copy" modifies the parameter - yuck
223 operator=(sequence_buffer& __x)
226 _M_prefix = __x._M_prefix;
232 operator=(const sequence_buffer& __x)
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);
240 #if __cplusplus >= 201103L
241 sequence_buffer(sequence_buffer&& __x) : sequence_buffer(__x) { }
242 sequence_buffer& operator=(sequence_buffer&& __x) { return *this = __x; }
246 push_back(value_type __x)
248 if (_M_buf_count < _Buf_sz)
250 _M_buffer[_M_buf_count] = __x;
262 append(value_type* __s, std::size_t __len)
264 if (__len + _M_buf_count <= _Buf_sz)
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;
271 else if (0 == _M_buf_count)
272 _M_prefix->append(__s, __s + __len);
281 write(value_type* __s, std::size_t __len)
295 operator=(const value_type& __rhs)
313 #pragma GCC diagnostic pop
315 // The following should be treated as private, at least for now.
316 template<class _CharT>
317 class _Rope_char_consumer
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
324 // The symmetry with char_producer is accidental and temporary.
325 virtual ~_Rope_char_consumer() { }
328 operator()(const _CharT* __buffer, std::size_t __len) = 0;
331 // First a lot of forward declarations. The standard seems to require
332 // much stricter "declaration before use" than many of the implementations
334 template<class _CharT, class _Alloc = std::allocator<_CharT> >
337 template<class _CharT, class _Alloc>
338 struct _Rope_RopeConcatenation;
340 template<class _CharT, class _Alloc>
341 struct _Rope_RopeLeaf;
343 template<class _CharT, class _Alloc>
344 struct _Rope_RopeFunction;
346 template<class _CharT, class _Alloc>
347 struct _Rope_RopeSubstring;
349 template<class _CharT, class _Alloc>
350 class _Rope_iterator;
352 template<class _CharT, class _Alloc>
353 class _Rope_const_iterator;
355 template<class _CharT, class _Alloc>
356 class _Rope_char_ref_proxy;
358 template<class _CharT, class _Alloc>
359 class _Rope_char_ptr_proxy;
361 template<class _CharT, class _Alloc>
363 operator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
364 const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);
366 template<class _CharT, class _Alloc>
367 _Rope_const_iterator<_CharT, _Alloc>
368 operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
371 template<class _CharT, class _Alloc>
372 _Rope_const_iterator<_CharT, _Alloc>
373 operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
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);
381 template<class _CharT, class _Alloc>
383 operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,
384 const _Rope_const_iterator<_CharT, _Alloc>& __y);
386 template<class _CharT, class _Alloc>
388 operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,
389 const _Rope_const_iterator<_CharT, _Alloc>& __y);
391 template<class _CharT, class _Alloc>
393 operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
394 const _Rope_const_iterator<_CharT, _Alloc>& __y);
396 template<class _CharT, class _Alloc>
397 _Rope_iterator<_CharT, _Alloc>
398 operator-(const _Rope_iterator<_CharT, _Alloc>& __x, std::ptrdiff_t __n);
400 template<class _CharT, class _Alloc>
401 _Rope_iterator<_CharT, _Alloc>
402 operator+(const _Rope_iterator<_CharT, _Alloc>& __x, std::ptrdiff_t __n);
404 template<class _CharT, class _Alloc>
405 _Rope_iterator<_CharT, _Alloc>
406 operator+(std::ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);
408 template<class _CharT, class _Alloc>
410 operator==(const _Rope_iterator<_CharT, _Alloc>& __x,
411 const _Rope_iterator<_CharT, _Alloc>& __y);
413 template<class _CharT, class _Alloc>
415 operator<(const _Rope_iterator<_CharT, _Alloc>& __x,
416 const _Rope_iterator<_CharT, _Alloc>& __y);
418 template<class _CharT, class _Alloc>
420 operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
421 const _Rope_iterator<_CharT, _Alloc>& __y);
423 template<class _CharT, class _Alloc>
425 operator+(const rope<_CharT, _Alloc>& __left,
426 const rope<_CharT, _Alloc>& __right);
428 template<class _CharT, class _Alloc>
430 operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);
432 template<class _CharT, class _Alloc>
434 operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);
436 // Some helpers, so we can use power on ropes.
437 // See below for why this isn't local to the implementation.
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> >
450 operator()(const rope<_CharT, _Alloc>& __x,
451 const rope<_CharT, _Alloc>& __y)
452 { return __x + __y; }
454 #pragma GCC diagnostic pop
456 template <class _CharT, class _Alloc>
457 inline rope<_CharT, _Alloc>
458 identity_element(_Rope_Concat_fn<_CharT, _Alloc>)
459 { return rope<_CharT, _Alloc>(); }
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
465 struct _Refcount_Base
468 typedef std::size_t _RC_t;
470 // The data member _M_ref_count
474 #ifdef __GTHREAD_MUTEX_INIT
475 __gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT;
477 __gthread_mutex_t _M_ref_count_lock;
480 _Refcount_Base(_RC_t __n) : _M_ref_count(__n)
482 #ifndef __GTHREAD_MUTEX_INIT
483 #ifdef __GTHREAD_MUTEX_INIT_FUNCTION
484 __GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
486 #error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
491 #ifndef __GTHREAD_MUTEX_INIT
493 { __gthread_mutex_destroy(&_M_ref_count_lock); }
499 __gthread_mutex_lock(&_M_ref_count_lock);
501 __gthread_mutex_unlock(&_M_ref_count_lock);
507 __gthread_mutex_lock(&_M_ref_count_lock);
508 _RC_t __tmp = --_M_ref_count;
509 __gthread_mutex_unlock(&_M_ref_count_lock);
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
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.
528 // The internal data structure for representing a rope. This is
529 // private to the implementation. A rope is really just a pointer
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.
536 // Some of the static member functions of _RopeRep have identically
537 // named functions in rope that simply invoke the _RopeRep versions.
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)
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
557 #define __STATIC_IF_SGI_ALLOC /* not static */
559 template <class _CharT, class _Alloc>
560 struct _Rope_rep_base
563 typedef std::size_t size_type;
564 typedef _Alloc allocator_type;
567 get_allocator() const
568 { return *static_cast<const _Alloc*>(this); }
572 { return *static_cast<_Alloc*>(this); }
574 const allocator_type&
575 _M_get_allocator() const
576 { return *static_cast<const _Alloc*>(this); }
578 _Rope_rep_base(size_type __size, const allocator_type&)
579 : _M_size(__size) { }
583 # define __ROPE_DEFINE_ALLOC(_Tp, __name) \
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
594 template<class _CharT, class _Alloc>
596 : public _Rope_rep_base<_CharT, _Alloc>
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;
609 __gthread_mutex_t _M_c_string_lock;
611 /* Flattened version of string, if needed. */
613 /* If it's not 0, then the memory is owned */
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
619 typedef std::size_t size_type;
621 using _Rope_rep_base<_CharT, _Alloc>::get_allocator;
622 using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator;
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),
630 _M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
631 #ifdef __GTHREAD_MUTEX_INIT
634 { __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }
636 { __gthread_mutex_destroy (&_M_c_string_lock); }
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.
651 // Does nothing if __GC is defined.
653 void _M_free_c_string();
655 // Deallocate t. Assumes t is not 0.
668 _S_unref(_Rope_RopeRep* __t)
671 __t->_M_unref_nonnil();
675 _S_ref(_Rope_RopeRep* __t)
682 _S_free_if_unref(_Rope_RopeRep* __t)
684 if (0 != __t && 0 == __t->_M_ref_count)
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*) { }
696 operator=(const _Rope_RopeRep&);
698 _Rope_RopeRep(const _Rope_RopeRep&);
701 template<class _CharT, class _Alloc>
702 struct _Rope_RopeLeaf
703 : public _Rope_RopeRep<_CharT, _Alloc>
705 typedef std::size_t size_type;
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 };
714 _S_rounded_up_size(size_type __n)
716 size_type __size_with_eos;
718 if (_S_is_basic_char_type((_CharT*)0))
719 __size_with_eos = __n + 1;
721 __size_with_eos = __n;
723 return __size_with_eos;
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));
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
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)
743 if (_S_is_basic_char_type((_CharT *)0))
745 // already eos terminated.
746 this->_M_c_string = __d;
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:
753 ~_Rope_RopeLeaf() throw()
755 if (_M_data != this->_M_c_string)
756 this->_M_free_c_string();
758 this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());
763 operator=(const _Rope_RopeLeaf&);
765 _Rope_RopeLeaf(const _Rope_RopeLeaf&);
768 template<class _CharT, class _Alloc>
769 struct _Rope_RopeConcatenation
770 : public _Rope_RopeRep<_CharT, _Alloc>
773 _Rope_RopeRep<_CharT, _Alloc>* _M_left;
774 _Rope_RopeRep<_CharT, _Alloc>* _M_right;
776 typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
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,
786 __l->_M_size + __r->_M_size, __a),
787 _M_left(__l), _M_right(__r)
790 ~_Rope_RopeConcatenation() throw()
792 this->_M_free_c_string();
793 _M_left->_M_unref_nonnil();
794 _M_right->_M_unref_nonnil();
798 _Rope_RopeConcatenation&
799 operator=(const _Rope_RopeConcatenation&);
801 _Rope_RopeConcatenation(const _Rope_RopeConcatenation&);
804 template<class _CharT, class _Alloc>
805 struct _Rope_RopeFunction
806 : public _Rope_RopeRep<_CharT, _Alloc>
809 char_producer<_CharT>* _M_fn;
811 bool _M_delete_when_done; // Char_producer is owned by the
812 // rope and should be explicitly
813 // deleted when the rope becomes
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
822 _S_fn_finalization_proc(void * __tree, void *)
823 { delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
825 typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
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)
833 , _M_delete_when_done(__d)
839 GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::
840 _S_fn_finalization_proc, 0, 0, 0);
845 ~_Rope_RopeFunction() throw()
847 this->_M_free_c_string();
848 if (_M_delete_when_done)
854 operator=(const _Rope_RopeFunction&);
856 _Rope_RopeFunction(const _Rope_RopeFunction&);
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>
870 typedef std::size_t size_type;
872 // XXX this whole class should be rewritten.
873 _Rope_RopeRep<_CharT,_Alloc>* _M_base; // not 0
877 operator()(size_type __start_pos, size_type __req_len,
880 switch(_M_base->_M_tag)
882 case __detail::_S_function:
883 case __detail::_S_substringfn:
885 char_producer<_CharT>* __fn =
886 ((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;
887 (*__fn)(__start_pos + _M_start, __req_len, __buffer);
890 case __detail::_S_leaf:
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,
903 typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_type
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)
912 _M_base->_M_ref_nonnil();
914 this->_M_tag = __detail::_S_substringfn;
916 virtual ~_Rope_RopeSubstring() throw()
919 _M_base->_M_unref_nonnil();
920 // _M_free_c_string(); -- done by parent class
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
935 template<class _CharT, class _Alloc>
936 struct _Rope_self_destruct_ptr
938 _Rope_RopeRep<_CharT, _Alloc>* _M_ptr;
940 ~_Rope_self_destruct_ptr()
941 { _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
943 _Rope_self_destruct_ptr() : _M_ptr(0) { }
945 _Rope_self_destruct_ptr() { }
947 _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p)
950 _Rope_RopeRep<_CharT, _Alloc>&
954 _Rope_RopeRep<_CharT, _Alloc>*
958 operator _Rope_RopeRep<_CharT, _Alloc>*()
961 _Rope_self_destruct_ptr&
962 operator=(_Rope_RopeRep<_CharT, _Alloc>* __x)
963 { _M_ptr = __x; return *this; }
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
975 friend class rope<_CharT, _Alloc>;
976 friend class _Rope_iterator<_CharT, _Alloc>;
977 friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
979 typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
981 typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
983 typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
984 typedef rope<_CharT, _Alloc> _My_rope;
987 bool _M_current_valid;
988 _My_rope* _M_root; // The whole rope.
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) { }
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) { }
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) { }
1004 inline operator _CharT () const;
1006 _Rope_char_ref_proxy&
1007 operator=(_CharT __c);
1009 _Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const;
1011 _Rope_char_ref_proxy&
1012 operator=(const _Rope_char_ref_proxy& __c)
1013 { return operator=((_CharT)__c); }
1016 template<class _CharT, class __Alloc>
1018 swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,
1019 _Rope_char_ref_proxy <_CharT, __Alloc > __b)
1026 template<class _CharT, class _Alloc>
1027 class _Rope_char_ptr_proxy
1029 // XXX this class should be rewritten.
1030 friend class _Rope_char_ref_proxy<_CharT, _Alloc>;
1032 rope<_CharT,_Alloc>* _M_root; // The whole rope.
1034 _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x)
1035 : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1037 _Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x)
1038 : _M_pos(__x._M_pos), _M_root(__x._M_root) { }
1040 _Rope_char_ptr_proxy() { }
1042 _Rope_char_ptr_proxy(_CharT* __x)
1043 : _M_root(0), _M_pos(0) { }
1045 _Rope_char_ptr_proxy&
1046 operator=(const _Rope_char_ptr_proxy& __x)
1048 _M_pos = __x._M_pos;
1049 _M_root = __x._M_root;
1053 template<class _CharT2, class _Alloc2>
1055 operator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x,
1056 const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y);
1058 _Rope_char_ref_proxy<_CharT, _Alloc> operator*() const
1059 { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); }
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
1067 // Pointers from iterators are not included in reference counts.
1068 // Iterators are assumed to be thread private. Ropes can
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>
1078 friend class rope<_CharT, _Alloc>;
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.
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;
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
1121 static void _S_setcache(_Rope_iterator_base& __x);
1122 // Set buffer contents and
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() { }
1129 _Rope_iterator_base(_RopeRep* __root, std::size_t __pos)
1130 : _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }
1132 void _M_incr(std::size_t __n);
1133 void _M_decr(std::size_t __n);
1137 { return _M_current_pos; }
1139 _Rope_iterator_base(const _Rope_iterator_base& __x)
1141 if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf)
1145 _M_current_pos = __x._M_current_pos;
1146 _M_root = __x._M_root;
1151 #pragma GCC diagnostic pop
1153 template<class _CharT, class _Alloc>
1154 class _Rope_iterator;
1156 template<class _CharT, class _Alloc>
1157 class _Rope_const_iterator
1158 : public _Rope_iterator_base<_CharT, _Alloc>
1160 friend class rope<_CharT, _Alloc>;
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),
1167 // Only nonconst iterators modify root ref count
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;
1176 _Rope_const_iterator() { }
1178 _Rope_const_iterator(const _Rope_const_iterator& __x)
1179 : _Rope_iterator_base<_CharT,_Alloc>(__x) { }
1181 _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);
1183 _Rope_const_iterator(const rope<_CharT, _Alloc>& __r, std::size_t __pos)
1184 : _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { }
1186 _Rope_const_iterator&
1187 operator=(const _Rope_const_iterator& __x)
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;
1193 this->_M_current_pos = __x._M_current_pos;
1194 this->_M_root = __x._M_root;
1195 this->_M_buf_ptr = 0;
1203 if (0 == this->_M_buf_ptr)
1204 this->_S_setcache(*this);
1205 return *this->_M_buf_ptr;
1208 // Without this const version, Rope iterators do not meet the
1209 // requirements of an Input Iterator.
1213 return *const_cast<_Rope_const_iterator&>(*this);
1216 _Rope_const_iterator&
1219 __GC_CONST _CharT* __next;
1220 if (0 != this->_M_buf_ptr
1221 && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end)
1223 this->_M_buf_ptr = __next;
1224 ++this->_M_current_pos;
1231 _Rope_const_iterator&
1232 operator+=(std::ptrdiff_t __n)
1237 this->_M_decr(-__n);
1241 _Rope_const_iterator&
1248 _Rope_const_iterator&
1249 operator-=(std::ptrdiff_t __n)
1254 this->_M_incr(-__n);
1258 _Rope_const_iterator
1261 std::size_t __old_pos = this->_M_current_pos;
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?
1269 _Rope_const_iterator
1272 std::size_t __old_pos = this->_M_current_pos;
1274 return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);
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);
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);
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);
1293 operator[](std::size_t __n)
1294 { return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,
1295 this->_M_current_pos + __n); }
1297 template<class _CharT2, class _Alloc2>
1299 operator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1300 const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
1302 template<class _CharT2, class _Alloc2>
1304 operator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,
1305 const _Rope_const_iterator<_CharT2, _Alloc2>& __y);
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);
1313 template<class _CharT, class _Alloc>
1314 class _Rope_iterator
1315 : public _Rope_iterator_base<_CharT, _Alloc>
1317 friend class rope<_CharT, _Alloc>;
1319 typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep;
1320 rope<_CharT, _Alloc>* _M_root_rope;
1322 // root is treated as a cached version of this, and is used to
1323 // detect changes to the underlying rope.
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),
1331 { _RopeRep::_S_ref(this->_M_root);
1332 if (!(__r -> empty()))
1333 this->_S_setcache(*this);
1338 typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;
1339 typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer;
1341 rope<_CharT, _Alloc>&
1343 { return *_M_root_rope; }
1347 this->_M_root = 0; // Needed for reference counting.
1350 _Rope_iterator(const _Rope_iterator& __x)
1351 : _Rope_iterator_base<_CharT, _Alloc>(__x)
1353 _M_root_rope = __x._M_root_rope;
1354 _RopeRep::_S_ref(this->_M_root);
1357 _Rope_iterator(rope<_CharT, _Alloc>& __r, std::size_t __pos);
1360 { _RopeRep::_S_unref(this->_M_root); }
1363 operator=(const _Rope_iterator& __x)
1365 _RopeRep* __old = this->_M_root;
1367 _RopeRep::_S_ref(__x._M_root);
1368 if (0 != __x._M_buf_ptr && __x._M_buf_start != __x._M_tmp_buf)
1370 _M_root_rope = __x._M_root_rope;
1371 *(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;
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;
1380 _RopeRep::_S_unref(__old);
1388 if (0 == this->_M_buf_ptr)
1389 return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1390 this->_M_current_pos);
1392 return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1393 this->_M_current_pos,
1397 // See above comment.
1401 return *const_cast<_Rope_iterator&>(*this);
1412 operator+=(std::ptrdiff_t __n)
1417 this->_M_decr(-__n);
1429 operator-=(std::ptrdiff_t __n)
1434 this->_M_incr(-__n);
1441 std::size_t __old_pos = this->_M_current_pos;
1443 return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1449 std::size_t __old_pos = this->_M_current_pos;
1451 return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);
1455 operator[](std::ptrdiff_t __n)
1456 { return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,
1457 this->_M_current_pos
1460 template<class _CharT2, class _Alloc2>
1462 operator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1463 const _Rope_iterator<_CharT2, _Alloc2>& __y);
1465 template<class _CharT2, class _Alloc2>
1467 operator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,
1468 const _Rope_iterator<_CharT2, _Alloc2>& __y);
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);
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);
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);
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);
1492 template <class _CharT, class _Alloc>
1496 typedef _Alloc allocator_type;
1499 get_allocator() const
1500 { return *static_cast<const _Alloc*>(this); }
1504 { return *static_cast<_Alloc*>(this); }
1506 const allocator_type&
1507 _M_get_allocator() const
1508 { return *static_cast<const _Alloc*>(this); }
1510 typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;
1511 // The one in _Base may not be visible due to template rules.
1513 _Rope_base(_RopeRep* __t, const allocator_type&)
1514 : _M_tree_ptr(__t) { }
1516 _Rope_base(const allocator_type&) { }
1518 // The only data member of a rope:
1519 _RopeRep *_M_tree_ptr;
1521 #define __ROPE_DEFINE_ALLOC(_Tp, __name) \
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
1533 operator=(const _Rope_base&);
1535 _Rope_base(const _Rope_base&);
1539 * This is an SGI extension.
1540 * @ingroup SGIextensions
1543 template <class _CharT, class _Alloc>
1544 class rope : public _Rope_base<_CharT, _Alloc>
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;
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>;
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;
1573 static _CharT _S_empty_c_str[1];
1577 { return __c == _S_eos((_CharT*)0); }
1579 enum { _S_copy_max = 23 };
1580 // For strings shorter than _S_copy_max, we copy to
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;
1589 // Retrieve a character at the indicated position.
1590 static _CharT _S_fetch(_RopeRep* __r, size_type __pos);
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
1599 static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
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.
1611 _S_unref(_RopeRep* __t)
1612 { _RopeRep::_S_unref(__t); }
1615 _S_ref(_RopeRep* __t)
1616 { _RopeRep::_S_ref(__t); }
1619 static void _S_unref(_RopeRep*) { }
1620 static void _S_ref(_RopeRep*) { }
1624 typedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
1626 typedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
1629 // _Result is counted in refcount.
1630 static _RopeRep* _S_substring(_RopeRep* __base,
1631 size_type __start, size_type __endp1);
1633 static _RopeRep* _S_concat_char_iter(_RopeRep* __r,
1634 const _CharT* __iter,
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,
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.
1648 // We can't really do anything since refcounts are unavailable.
1649 { return _S_concat_char_iter(__r, __iter, __slen, __a); }
1654 static _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);
1655 // General concatenation on _RopeRep. _Result
1656 // has refcount of 1. Adjusts argument refcounts.
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); }
1667 _S_rounded_up_size(size_type __n)
1668 { return _RopeLeaf::_S_rounded_up_size(__n); }
1671 _S_allocated_capacity(size_type __n)
1673 if (_S_is_basic_char_type((_CharT*)0))
1674 return _S_rounded_up_size(__n) - 1;
1676 return _S_rounded_up_size(__n);
1680 // Allocate and construct a RopeLeaf using the supplied allocator
1681 // Takes ownership of s instead of copying.
1683 _S_new_RopeLeaf(__GC_CONST _CharT *__s,
1684 size_type __size, allocator_type& __a)
1686 _RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);
1687 return new(__space) _RopeLeaf(__s, __size, __a);
1690 static _RopeConcatenation*
1691 _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,
1692 allocator_type& __a)
1694 _RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);
1695 return new(__space) _RopeConcatenation(__left, __right, __a);
1698 static _RopeFunction*
1699 _S_new_RopeFunction(char_producer<_CharT>* __f,
1700 size_type __size, bool __d, allocator_type& __a)
1702 _RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);
1703 return new(__space) _RopeFunction(__f, __size, __d, __a);
1706 static _RopeSubstring*
1707 _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_type __s,
1708 size_type __l, allocator_type& __a)
1710 _RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);
1711 return new(__space) _RopeSubstring(__b, __s, __l, __a);
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)
1722 _CharT* __buf = __a.allocate(_S_rounded_up_size(__size));
1724 __uninitialized_copy_n_a(__s, __size, __buf, __a);
1725 _S_cond_store_eos(__buf[__size]);
1727 { return _S_new_RopeLeaf(__buf, __size, __a); }
1730 _RopeRep::__STL_FREE_STRING(__buf, __size, __a);
1731 __throw_exception_again;
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.
1742 _S_tree_concat(_RopeRep* __left, _RopeRep* __right);
1744 // Concatenation helper functions
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.
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.
1760 static size_type _S_char_ptr_len(const _CharT* __s);
1761 // slightly generalized strlen
1763 rope(_RopeRep* __t, const allocator_type& __a = allocator_type())
1764 : _Base(__t, __a) { }
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);
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,
1778 static const unsigned long
1779 _S_min_len[__detail::_S_max_rope_depth + 1];
1782 _S_is_balanced(_RopeRep* __r)
1783 { return (__r->_M_size >= _S_min_len[__r->_M_depth]); }
1786 _S_is_almost_balanced(_RopeRep* __r)
1787 { return (__r->_M_depth == 0
1788 || __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }
1791 _S_is_roughly_balanced(_RopeRep* __r)
1792 { return (__r->_M_depth <= 1
1793 || __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }
1795 // Assumes the result is not empty.
1797 _S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right)
1799 _RopeRep* __result = _S_concat(__left, __right);
1800 if (_S_is_balanced(__result))
1801 __result->_M_is_balanced = true;
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
1810 static _RopeRep* _S_balance(_RopeRep* __r);
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);
1816 // Add __r to forest, assuming __r is already balanced.
1817 static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);
1819 // Print to stdout, exposing structure
1820 static void _S_dump(_RopeRep* __r, int __indent = 0);
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);
1826 _GLIBCXX_NODISCARD bool
1828 { return 0 == this->_M_tree_ptr; }
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.
1834 compare(const rope& __y) const
1835 { return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }
1837 rope(const _CharT* __s, const allocator_type& __a = allocator_type())
1841 __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),
1842 _M_get_allocator());
1845 rope(const _CharT* __s, size_type __len,
1846 const allocator_type& __a = allocator_type())
1850 __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator());
1853 // Should perhaps be templatized with respect to the iterator type
1854 // and use Sequence_buffer. (It should perhaps use sequence_buffer
1856 rope(const _CharT* __s, const _CharT* __e,
1857 const allocator_type& __a = allocator_type())
1861 __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator());
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)
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)
1876 rope(_CharT __c, const allocator_type& __a = allocator_type())
1879 _CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));
1881 __alloc_traits<allocator_type>::construct(_M_get_allocator(),
1885 this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1,
1886 _M_get_allocator());
1890 _RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator());
1891 __throw_exception_again;
1895 rope(size_type __n, _CharT __c,
1896 const allocator_type& __a = allocator_type());
1898 rope(const allocator_type& __a = allocator_type())
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())
1906 this->_M_tree_ptr = (0 == __len)
1908 : _S_new_RopeFunction(__fn, __len, __delete_fn, _M_get_allocator());
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); }
1916 { _S_unref(this->_M_tree_ptr); }
1919 operator=(const rope& __x)
1921 _RopeRep* __old = this->_M_tree_ptr;
1922 this->_M_tree_ptr = __x._M_tree_ptr;
1923 _S_ref(this->_M_tree_ptr);
1931 _S_unref(this->_M_tree_ptr);
1932 this->_M_tree_ptr = 0;
1936 push_back(_CharT __x)
1938 allocator_type __a = _M_get_allocator();
1939 _RopeRep* __old = this->_M_tree_ptr;
1941 = _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1, __a);
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);
1956 { return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }
1959 push_front(_CharT __x)
1961 _RopeRep* __old = this->_M_tree_ptr;
1963 __STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator());
1966 this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);
1973 __throw_exception_again;
1980 _RopeRep* __old = this->_M_tree_ptr;
1982 = _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);
1988 { return _S_fetch(this->_M_tree_ptr, 0); }
1993 _RopeRep* __old = this->_M_tree_ptr;
1994 this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);
1999 copy(_CharT* __buffer) const
2001 _Destroy_const(__buffer, __buffer + size(), _M_get_allocator());
2002 _S_flatten(this->_M_tree_ptr, __buffer);
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.
2011 copy(size_type __pos, size_type __n, _CharT* __buffer) const
2013 size_type __size = size();
2014 size_type __len = (__pos + __n > __size? __size - __pos : __n);
2016 _Destroy_const(__buffer, __buffer + __len, _M_get_allocator());
2017 _S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);
2021 // Print to stdout, exposing structure. May be useful for
2022 // performance debugging.
2025 { _S_dump(this->_M_tree_ptr); }
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;
2031 // As above, but also use the flattened representation as
2032 // the new rope representation.
2033 const _CharT* replace_with_c_str();
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.
2041 if (0 == this->_M_tree_ptr)
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)
2047 // Representation shared
2051 this->_M_tree_ptr->_M_free_c_string();
2053 this->_M_tree_ptr->_M_c_string = 0;
2057 operator[] (size_type __pos) const
2058 { return _S_fetch(this->_M_tree_ptr, __pos); }
2061 at(size_type __pos) const
2063 // if (__pos >= size()) throw out_of_range; // XXX
2064 return (*this)[__pos];
2069 { return(const_iterator(this->_M_tree_ptr, 0)); }
2071 // An easy way to get a const iterator from a non-const container.
2074 { return(const_iterator(this->_M_tree_ptr, 0)); }
2078 { return(const_iterator(this->_M_tree_ptr, size())); }
2082 { return(const_iterator(this->_M_tree_ptr, size())); }
2086 { return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }
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.
2101 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
2103 const_reverse_iterator
2105 { return const_reverse_iterator(end()); }
2107 const_reverse_iterator
2108 const_rbegin() const
2109 { return const_reverse_iterator(end()); }
2111 const_reverse_iterator
2113 { return const_reverse_iterator(begin()); }
2115 const_reverse_iterator
2117 { return const_reverse_iterator(begin()); }
2119 template<class _CharT2, class _Alloc2>
2120 friend rope<_CharT2, _Alloc2>
2121 operator+(const rope<_CharT2, _Alloc2>& __left,
2122 const rope<_CharT2, _Alloc2>& __right);
2124 template<class _CharT2, class _Alloc2>
2125 friend rope<_CharT2, _Alloc2>
2126 operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);
2128 template<class _CharT2, class _Alloc2>
2129 friend rope<_CharT2, _Alloc2>
2130 operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);
2132 // The symmetric cases are intentionally omitted, since they're
2133 // presumed to be less common, and we don't handle them as well.
2135 // The following should really be templatized. The first
2136 // argument should be an input iterator or forward iterator with
2137 // value_type _CharT.
2139 append(const _CharT* __iter, size_type __n)
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;
2150 append(const _CharT* __c_string)
2152 size_type __len = _S_char_ptr_len(__c_string);
2153 append(__c_string, __len);
2158 append(const _CharT* __s, const _CharT* __e)
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;
2169 append(const_iterator __s, const_iterator __e)
2171 _Self_destruct_ptr __appendee(_S_substring(__s._M_root,
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;
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;
2194 { return append(_CharT()); } // XXX why?
2197 append(const rope& __y)
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;
2206 append(size_type __n, _CharT __c)
2208 rope<_CharT,_Alloc> __last(__n, __c);
2209 return append(__last);
2215 _RopeRep* __tmp = this->_M_tree_ptr;
2216 this->_M_tree_ptr = __b._M_tree_ptr;
2217 __b._M_tree_ptr = __tmp;
2221 // Result is included in refcount.
2223 replace(_RopeRep* __old, size_type __pos1,
2224 size_type __pos2, _RopeRep* __r)
2231 _Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));
2232 _Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));
2236 __result = _S_concat(__left, __right);
2239 _Self_destruct_ptr __left_result(_S_concat(__left, __r));
2240 __result = _S_concat(__left_result, __right);
2247 insert(size_type __p, const rope& __r)
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;
2256 insert(size_type __p, size_type __n, _CharT __c)
2258 rope<_CharT,_Alloc> __r(__n,__c);
2263 insert(size_type __p, const _CharT* __i, size_type __n)
2265 _Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));
2266 _Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,
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;
2279 insert(size_type __p, const _CharT* __c_string)
2280 { insert(__p, __c_string, _S_char_ptr_len(__c_string)); }
2283 insert(size_type __p, _CharT __c)
2284 { insert(__p, &__c, 1); }
2287 insert(size_type __p)
2289 _CharT __c = _CharT();
2290 insert(__p, &__c, 1);
2294 insert(size_type __p, const _CharT* __i, const _CharT* __j)
2301 insert(size_type __p, const const_iterator& __i,
2302 const const_iterator& __j)
2309 insert(size_type __p, const iterator& __i,
2310 const iterator& __j)
2316 // (position, length) versions of replace operations:
2319 replace(size_type __p, size_type __n, const rope& __r)
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;
2328 replace(size_type __p, size_type __n,
2329 const _CharT* __i, size_type __i_len)
2331 rope __r(__i, __i_len);
2332 replace(__p, __n, __r);
2336 replace(size_type __p, size_type __n, _CharT __c)
2339 replace(__p, __n, __r);
2343 replace(size_type __p, size_type __n, const _CharT* __c_string)
2345 rope __r(__c_string);
2346 replace(__p, __n, __r);
2350 replace(size_type __p, size_type __n,
2351 const _CharT* __i, const _CharT* __j)
2354 replace(__p, __n, __r);
2358 replace(size_type __p, size_type __n,
2359 const const_iterator& __i, const const_iterator& __j)
2362 replace(__p, __n, __r);
2366 replace(size_type __p, size_type __n,
2367 const iterator& __i, const iterator& __j)
2370 replace(__p, __n, __r);
2373 // Single character variants:
2375 replace(size_type __p, _CharT __c)
2377 iterator __i(this, __p);
2382 replace(size_type __p, const rope& __r)
2383 { replace(__p, 1, __r); }
2386 replace(size_type __p, const _CharT* __i, size_type __i_len)
2387 { replace(__p, 1, __i, __i_len); }
2390 replace(size_type __p, const _CharT* __c_string)
2391 { replace(__p, 1, __c_string); }
2394 replace(size_type __p, const _CharT* __i, const _CharT* __j)
2395 { replace(__p, 1, __i, __j); }
2398 replace(size_type __p, const const_iterator& __i,
2399 const const_iterator& __j)
2400 { replace(__p, 1, __i, __j); }
2403 replace(size_type __p, const iterator& __i,
2404 const iterator& __j)
2405 { replace(__p, 1, __i, __j); }
2407 // Erase, (position, size) variant.
2409 erase(size_type __p, size_type __n)
2411 _RopeRep* __result = replace(this->_M_tree_ptr, __p,
2413 _S_unref(this->_M_tree_ptr);
2414 this->_M_tree_ptr = __result;
2417 // Insert, iterator variants.
2419 insert(const iterator& __p, const rope& __r)
2421 insert(__p.index(), __r);
2426 insert(const iterator& __p, size_type __n, _CharT __c)
2428 insert(__p.index(), __n, __c);
2432 iterator insert(const iterator& __p, _CharT __c)
2434 insert(__p.index(), __c);
2439 insert(const iterator& __p )
2441 insert(__p.index());
2446 insert(const iterator& __p, const _CharT* c_string)
2448 insert(__p.index(), c_string);
2453 insert(const iterator& __p, const _CharT* __i, size_type __n)
2455 insert(__p.index(), __i, __n);
2460 insert(const iterator& __p, const _CharT* __i,
2463 insert(__p.index(), __i, __j);
2468 insert(const iterator& __p,
2469 const const_iterator& __i, const const_iterator& __j)
2471 insert(__p.index(), __i, __j);
2476 insert(const iterator& __p,
2477 const iterator& __i, const iterator& __j)
2479 insert(__p.index(), __i, __j);
2483 // Replace, range variants.
2485 replace(const iterator& __p, const iterator& __q, const rope& __r)
2486 { replace(__p.index(), __q.index() - __p.index(), __r); }
2489 replace(const iterator& __p, const iterator& __q, _CharT __c)
2490 { replace(__p.index(), __q.index() - __p.index(), __c); }
2493 replace(const iterator& __p, const iterator& __q,
2494 const _CharT* __c_string)
2495 { replace(__p.index(), __q.index() - __p.index(), __c_string); }
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); }
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); }
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); }
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); }
2517 // Replace, iterator variants.
2519 replace(const iterator& __p, const rope& __r)
2520 { replace(__p.index(), __r); }
2523 replace(const iterator& __p, _CharT __c)
2524 { replace(__p.index(), __c); }
2527 replace(const iterator& __p, const _CharT* __c_string)
2528 { replace(__p.index(), __c_string); }
2531 replace(const iterator& __p, const _CharT* __i, size_type __n)
2532 { replace(__p.index(), __i, __n); }
2535 replace(const iterator& __p, const _CharT* __i, const _CharT* __j)
2536 { replace(__p.index(), __i, __j); }
2539 replace(const iterator& __p, const_iterator __i, const_iterator __j)
2540 { replace(__p.index(), __i, __j); }
2543 replace(const iterator& __p, iterator __i, iterator __j)
2544 { replace(__p.index(), __i, __j); }
2546 // Iterator and range variants of erase
2548 erase(const iterator& __p, const iterator& __q)
2550 size_type __p_index = __p.index();
2551 erase(__p_index, __q.index() - __p_index);
2552 return iterator(this, __p_index);
2556 erase(const iterator& __p)
2558 size_type __p_index = __p.index();
2559 erase(__p_index, 1);
2560 return iterator(this, __p_index);
2564 substr(size_type __start, size_type __len = 1) const
2566 return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2572 substr(iterator __start, iterator __end) const
2574 return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2580 substr(iterator __start) const
2582 size_type __pos = __start.index();
2583 return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2588 substr(const_iterator __start, const_iterator __end) const
2590 // This might eventually take advantage of the cache in the
2592 return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2597 rope<_CharT, _Alloc>
2598 substr(const_iterator __start)
2600 size_type __pos = __start.index();
2601 return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,
2605 static const size_type npos;
2607 size_type find(_CharT __c, size_type __pos = 0) const;
2610 find(const _CharT* __s, size_type __pos = 0) const
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;
2621 return __result_pos;
2626 { return(iterator(this, 0)); }
2630 { return(iterator(this, size())); }
2632 typedef std::reverse_iterator<iterator> reverse_iterator;
2636 { return reverse_iterator(mutable_end()); }
2640 { return reverse_iterator(mutable_begin()); }
2643 mutable_reference_at(size_type __pos)
2644 { return reference(this, __pos); }
2648 operator[] (size_type __pos)
2649 { return _char_ref_proxy(this, __pos); }
2654 // if (__pos >= size()) throw out_of_range; // XXX
2655 return (*this)[__pos];
2658 void resize(size_type __n, _CharT __c) { }
2659 void resize(size_type __n) { }
2660 void reserve(size_type __res_arg = 0) { }
2664 { return max_size(); }
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.
2670 copy(_CharT* __buffer, size_type __n,
2671 size_type __pos = 0) const
2672 { return copy(__pos, __n, __buffer); }
2676 { return mutable_end(); }
2680 { return mutable_begin(); }
2684 { return mutable_rend(); }
2688 { return mutable_rbegin(); }
2693 { return const_end(); }
2697 { return const_begin(); }
2699 const_reverse_iterator
2701 { return const_rend(); }
2703 const_reverse_iterator
2705 { return const_rbegin(); }
2710 template <class _CharT, class _Alloc>
2711 const typename rope<_CharT, _Alloc>::size_type
2712 rope<_CharT, _Alloc>::npos = (size_type)(-1);
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); }
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); }
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); }
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; }
2735 template <class _CharT, class _Alloc>
2737 operator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2738 const _Rope_const_iterator<_CharT, _Alloc>& __y)
2739 { return !(__y < __x); }
2741 template <class _CharT, class _Alloc>
2743 operator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2744 const _Rope_const_iterator<_CharT, _Alloc>& __y)
2745 { return !(__x < __y); }
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)
2752 return (std::ptrdiff_t)__x._M_current_pos
2753 - (std::ptrdiff_t)__y._M_current_pos;
2756 template <class _CharT, class _Alloc>
2757 inline _Rope_const_iterator<_CharT, _Alloc>
2758 operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2760 { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2761 __x._M_current_pos - __n); }
2763 template <class _CharT, class _Alloc>
2764 inline _Rope_const_iterator<_CharT, _Alloc>
2765 operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,
2767 { return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,
2768 __x._M_current_pos + __n); }
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); }
2777 template <class _CharT, class _Alloc>
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); }
2784 template <class _CharT, class _Alloc>
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); }
2790 template <class _CharT, class _Alloc>
2792 operator!=(const _Rope_iterator<_CharT, _Alloc>& __x,
2793 const _Rope_iterator<_CharT, _Alloc>& __y)
2794 { return !(__x == __y); }
2796 template <class _CharT, class _Alloc>
2798 operator>(const _Rope_iterator<_CharT, _Alloc>& __x,
2799 const _Rope_iterator<_CharT, _Alloc>& __y)
2800 { return __y < __x; }
2802 template <class _CharT, class _Alloc>
2804 operator<=(const _Rope_iterator<_CharT, _Alloc>& __x,
2805 const _Rope_iterator<_CharT, _Alloc>& __y)
2806 { return !(__y < __x); }
2808 template <class _CharT, class _Alloc>
2810 operator>=(const _Rope_iterator<_CharT, _Alloc>& __x,
2811 const _Rope_iterator<_CharT, _Alloc>& __y)
2812 { return !(__x < __y); }
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); }
2821 template <class _CharT, class _Alloc>
2822 inline _Rope_iterator<_CharT, _Alloc>
2823 operator-(const _Rope_iterator<_CharT, _Alloc>& __x,
2825 { return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,
2826 __x._M_current_pos - __n); }
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); }
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); }
2840 template <class _CharT, class _Alloc>
2841 inline rope<_CharT, _Alloc>
2842 operator+(const rope<_CharT, _Alloc>& __left,
2843 const rope<_CharT, _Alloc>& __right)
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));
2852 template <class _CharT, class _Alloc>
2853 inline rope<_CharT, _Alloc>&
2854 operator+=(rope<_CharT, _Alloc>& __left,
2855 const rope<_CharT, _Alloc>& __right)
2857 __left.append(__right);
2861 template <class _CharT, class _Alloc>
2862 inline rope<_CharT, _Alloc>
2863 operator+(const rope<_CharT, _Alloc>& __left,
2864 const _CharT* __right)
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));
2873 template <class _CharT, class _Alloc>
2874 inline rope<_CharT, _Alloc>&
2875 operator+=(rope<_CharT, _Alloc>& __left,
2876 const _CharT* __right)
2878 __left.append(__right);
2882 template <class _CharT, class _Alloc>
2883 inline rope<_CharT, _Alloc>
2884 operator+(const rope<_CharT, _Alloc>& __left, _CharT __right)
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,
2892 template <class _CharT, class _Alloc>
2893 inline rope<_CharT, _Alloc>&
2894 operator+=(rope<_CharT, _Alloc>& __left, _CharT __right)
2896 __left.append(__right);
2900 template <class _CharT, class _Alloc>
2902 operator<(const rope<_CharT, _Alloc>& __left,
2903 const rope<_CharT, _Alloc>& __right)
2904 { return __left.compare(__right) < 0; }
2906 template <class _CharT, class _Alloc>
2908 operator==(const rope<_CharT, _Alloc>& __left,
2909 const rope<_CharT, _Alloc>& __right)
2910 { return __left.compare(__right) == 0; }
2912 template <class _CharT, class _Alloc>
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); }
2918 template <class _CharT, class _Alloc>
2920 operator!=(const rope<_CharT, _Alloc>& __x,
2921 const rope<_CharT, _Alloc>& __y)
2922 { return !(__x == __y); }
2924 template <class _CharT, class _Alloc>
2926 operator>(const rope<_CharT, _Alloc>& __x,
2927 const rope<_CharT, _Alloc>& __y)
2928 { return __y < __x; }
2930 template <class _CharT, class _Alloc>
2932 operator<=(const rope<_CharT, _Alloc>& __x,
2933 const rope<_CharT, _Alloc>& __y)
2934 { return !(__y < __x); }
2936 template <class _CharT, class _Alloc>
2938 operator>=(const rope<_CharT, _Alloc>& __x,
2939 const rope<_CharT, _Alloc>& __y)
2940 { return !(__x < __y); }
2942 template <class _CharT, class _Alloc>
2944 operator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,
2945 const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y)
2946 { return !(__x == __y); }
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);
2953 typedef rope<char> crope;
2954 typedef rope<wchar_t> wrope;
2956 inline crope::reference
2957 __mutable_reference_at(crope& __c, std::size_t __i)
2958 { return __c.mutable_reference_at(__i); }
2960 inline wrope::reference
2961 __mutable_reference_at(wrope& __c, std::size_t __i)
2962 { return __c.mutable_reference_at(__i); }
2964 template <class _CharT, class _Alloc>
2966 swap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y)
2969 _GLIBCXX_END_NAMESPACE_VERSION
2973 namespace std _GLIBCXX_VISIBILITY(default)
2975 _GLIBCXX_BEGIN_NAMESPACE_VERSION
2980 struct hash<__gnu_cxx::crope>
2983 operator()(const __gnu_cxx::crope& __str) const
2985 size_t __size = __str.size();
2988 return 13 * __str[0] + 5 * __str[__size - 1] + __size;
2994 struct hash<__gnu_cxx::wrope>
2997 operator()(const __gnu_cxx::wrope& __str) const
2999 size_t __size = __str.size();
3002 return 13 * __str[0] + 5 * __str[__size - 1] + __size;
3007 _GLIBCXX_END_NAMESPACE_VERSION
3010 # include <ext/ropeimpl.h>