C++官方rope3000行源码

// SGI's rope class -*- C++ -*-// Copyright (C) 2001-2015 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>./** Copyright (c) 1997* Silicon Graphics Computer Systems, Inc.** Permission to use, copy, modify, distribute and sell this software* and its documentation for any purpose is hereby granted without fee,* provided that the above copyright notice appear in all copies and* that both that copyright notice and this permission notice appear* in supporting documentation.  Silicon Graphics makes no* representations about the suitability of this software for any* purpose.  It is provided "as is" without express or implied warranty.*//** @file ext/rope*  This file is a GNU extension to the Standard C++ Library (possibly*  containing extensions from the HP/SGI STL subset). */#ifndef _ROPE
#define _ROPE 1#pragma GCC system_header#include <algorithm>
#include <iosfwd>
#include <bits/stl_construct.h>
#include <bits/stl_uninitialized.h>
#include <bits/stl_function.h>
#include <bits/stl_numeric.h>
#include <bits/allocator.h>
#include <bits/gthr.h>
#include <tr1/functional># ifdef __GC
#   define __GC_CONST const
# else
#   define __GC_CONST// constant except for deallocation
# endif#include <ext/memory>// For uninitialized_copy_nnamespace __gnu_cxx _GLIBCXX_VISIBILITY(default)
{namespace __detail{enum { _S_max_rope_depth = 45 };enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function};} // namespace __detailusing std::size_t;using std::ptrdiff_t;using std::allocator;using std::_Destroy;_GLIBCXX_BEGIN_NAMESPACE_VERSION// See libstdc++/36832.template<typename _ForwardIterator, typename _Allocator>void_Destroy_const(_ForwardIterator __first,_ForwardIterator __last, _Allocator __alloc){for (; __first != __last; ++__first)__alloc.destroy(&*__first);}template<typename _ForwardIterator, typename _Tp>inline void_Destroy_const(_ForwardIterator __first,_ForwardIterator __last, allocator<_Tp>){ _Destroy(__first, __last); }// The _S_eos function is used for those functions that// convert to/from C-like strings to detect the end of the string.// The end-of-C-string character.// This is what the draft standard says it should be.template <class _CharT>inline _CharT_S_eos(_CharT*){ return _CharT(); }// Test for basic character types.// For basic character types leaves having a trailing eos.template <class _CharT>inline bool_S_is_basic_char_type(_CharT*){ return false; }template <class _CharT>inline bool_S_is_one_byte_char_type(_CharT*){ return false; }inline bool_S_is_basic_char_type(char*){ return true; }inline bool_S_is_one_byte_char_type(char*){ return true; }inline bool_S_is_basic_char_type(wchar_t*){ return true; }// Store an eos iff _CharT is a basic character type.// Do not reference _S_eos if it isn't.template <class _CharT>inline void_S_cond_store_eos(_CharT&) { }inline void_S_cond_store_eos(char& __c){ __c = 0; }inline void_S_cond_store_eos(wchar_t& __c){ __c = 0; }// char_producers are logically functions that generate a section of// a string.  These can be converted to ropes.  The resulting rope// invokes the char_producer on demand.  This allows, for example,// files to be viewed as ropes without reading the entire file.template <class _CharT>class char_producer{public:virtual ~char_producer() { };virtual voidoperator()(size_t __start_pos, size_t __len,_CharT* __buffer) = 0;// Buffer should really be an arbitrary output iterator.// That way we could flatten directly into an ostream, etc.// This is thoroughly impossible, since iterator types don't// have runtime descriptions.};// Sequence buffers://// Sequence must provide an append operation that appends an// array to the sequence.  Sequence buffers are useful only if// appending an entire array is cheaper than appending element by element.// This is true for many string representations.// This should  perhaps inherit from ostream<sequence::value_type>// and be implemented correspondingly, so that they can be used// for formatted.  For the sake of portability, we don't do this yet.//// For now, sequence buffers behave as output iterators.  But they also// behave a little like basic_ostringstream<sequence::value_type> and a// little like containers.template<class _Sequence, size_t _Buf_sz = 100>class sequence_buffer: public std::iterator<std::output_iterator_tag, void, void, void, void>{public:typedef typename _Sequence::value_type value_type;protected:_Sequence* _M_prefix;value_type _M_buffer[_Buf_sz];size_t     _M_buf_count;public:voidflush(){_M_prefix->append(_M_buffer, _M_buffer + _M_buf_count);_M_buf_count = 0;}~sequence_buffer(){ flush(); }sequence_buffer(): _M_prefix(0), _M_buf_count(0) { }sequence_buffer(const sequence_buffer& __x){_M_prefix = __x._M_prefix;_M_buf_count = __x._M_buf_count;std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);}sequence_buffer(sequence_buffer& __x){__x.flush();_M_prefix = __x._M_prefix;_M_buf_count = 0;}sequence_buffer(_Sequence& __s): _M_prefix(&__s), _M_buf_count(0) { }sequence_buffer&operator=(sequence_buffer& __x){__x.flush();_M_prefix = __x._M_prefix;_M_buf_count = 0;return *this;}sequence_buffer&operator=(const sequence_buffer& __x){_M_prefix = __x._M_prefix;_M_buf_count = __x._M_buf_count;std::copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer);return *this;}voidpush_back(value_type __x){if (_M_buf_count < _Buf_sz){_M_buffer[_M_buf_count] = __x;++_M_buf_count;}else{flush();_M_buffer[0] = __x;_M_buf_count = 1;}}voidappend(value_type* __s, size_t __len){if (__len + _M_buf_count <= _Buf_sz){size_t __i = _M_buf_count;for (size_t __j = 0; __j < __len; __i++, __j++)_M_buffer[__i] = __s[__j];_M_buf_count += __len;}else if (0 == _M_buf_count)_M_prefix->append(__s, __s + __len);else{flush();append(__s, __len);}}sequence_buffer&write(value_type* __s, size_t __len){append(__s, __len);return *this;}sequence_buffer&put(value_type __x){push_back(__x);return *this;}sequence_buffer&operator=(const value_type& __rhs){push_back(__rhs);return *this;}sequence_buffer&operator*(){ return *this; }sequence_buffer&operator++(){ return *this; }sequence_bufferoperator++(int){ return *this; }};// The following should be treated as private, at least for now.template<class _CharT>class _Rope_char_consumer{public:// If we had member templates, these should not be virtual.// For now we need to use run-time parametrization where// compile-time would do.  Hence this should all be private// for now.// The symmetry with char_producer is accidental and temporary.virtual ~_Rope_char_consumer() { };virtual booloperator()(const _CharT* __buffer, size_t __len) = 0;};// First a lot of forward declarations.  The standard seems to require// much stricter "declaration before use" than many of the implementations// that preceded it.template<class _CharT, class _Alloc = allocator<_CharT> >class rope;template<class _CharT, class _Alloc>struct _Rope_RopeConcatenation;template<class _CharT, class _Alloc>struct _Rope_RopeLeaf;template<class _CharT, class _Alloc>struct _Rope_RopeFunction;template<class _CharT, class _Alloc>struct _Rope_RopeSubstring;template<class _CharT, class _Alloc>class _Rope_iterator;template<class _CharT, class _Alloc>class _Rope_const_iterator;template<class _CharT, class _Alloc>class _Rope_char_ref_proxy;template<class _CharT, class _Alloc>class _Rope_char_ptr_proxy;template<class _CharT, class _Alloc>booloperator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>_Rope_const_iterator<_CharT, _Alloc>operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,ptrdiff_t __n);template<class _CharT, class _Alloc>_Rope_const_iterator<_CharT, _Alloc>operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x,ptrdiff_t __n);template<class _CharT, class _Alloc>_Rope_const_iterator<_CharT, _Alloc>operator+(ptrdiff_t __n,const _Rope_const_iterator<_CharT, _Alloc>& __x);template<class _CharT, class _Alloc>booloperator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>booloperator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>ptrdiff_toperator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>_Rope_iterator<_CharT, _Alloc>operator-(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);template<class _CharT, class _Alloc>_Rope_iterator<_CharT, _Alloc>operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n);template<class _CharT, class _Alloc>_Rope_iterator<_CharT, _Alloc>operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x);template<class _CharT, class _Alloc>booloperator==(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>booloperator<(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>ptrdiff_toperator-(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y);template<class _CharT, class _Alloc>rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left,const rope<_CharT, _Alloc>& __right);template<class _CharT, class _Alloc>rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left, const _CharT* __right);template<class _CharT, class _Alloc>rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left, _CharT __right);// Some helpers, so we can use power on ropes.// See below for why this isn't local to the implementation.// This uses a nonstandard refcount convention.// The result has refcount 0.template<class _CharT, class _Alloc>struct _Rope_Concat_fn: public std::binary_function<rope<_CharT, _Alloc>, rope<_CharT, _Alloc>,rope<_CharT, _Alloc> >{rope<_CharT, _Alloc>operator()(const rope<_CharT, _Alloc>& __x,const rope<_CharT, _Alloc>& __y){ return __x + __y; }};template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>identity_element(_Rope_Concat_fn<_CharT, _Alloc>){ return rope<_CharT, _Alloc>(); }// Class _Refcount_Base provides a type, _RC_t, a data member,// _M_ref_count, and member functions _M_incr and _M_decr, which perform// atomic preincrement/predecrement.  The constructor initializes// _M_ref_count.struct _Refcount_Base{// The type _RC_ttypedef size_t _RC_t;// The data member _M_ref_countvolatile _RC_t _M_ref_count;// Constructor
#ifdef __GTHREAD_MUTEX_INIT__gthread_mutex_t _M_ref_count_lock = __GTHREAD_MUTEX_INIT;
#else__gthread_mutex_t _M_ref_count_lock;
#endif_Refcount_Base(_RC_t __n) : _M_ref_count(__n){
#ifndef __GTHREAD_MUTEX_INIT
#ifdef __GTHREAD_MUTEX_INIT_FUNCTION__GTHREAD_MUTEX_INIT_FUNCTION (&_M_ref_count_lock);
#else
#error __GTHREAD_MUTEX_INIT or __GTHREAD_MUTEX_INIT_FUNCTION should be defined by gthr.h abstraction layer, report problem to libstdc++@gcc.gnu.org.
#endif
#endif}#ifndef __GTHREAD_MUTEX_INIT~_Refcount_Base(){ __gthread_mutex_destroy(&_M_ref_count_lock); }
#endifvoid_M_incr(){__gthread_mutex_lock(&_M_ref_count_lock);++_M_ref_count;__gthread_mutex_unlock(&_M_ref_count_lock);}_RC_t_M_decr(){__gthread_mutex_lock(&_M_ref_count_lock);volatile _RC_t __tmp = --_M_ref_count;__gthread_mutex_unlock(&_M_ref_count_lock);return __tmp;}};//// What follows should really be local to rope.  Unfortunately,// that doesn't work, since it makes it impossible to define generic// equality on rope iterators.  According to the draft standard, the// template parameters for such an equality operator cannot be inferred// from the occurrence of a member class as a parameter.// (SGI compilers in fact allow this, but the __result wouldn't be// portable.)// Similarly, some of the static member functions are member functions// only to avoid polluting the global namespace, and to circumvent// restrictions on type inference for template functions.////// The internal data structure for representing a rope.  This is// private to the implementation.  A rope is really just a pointer// to one of these.//// A few basic functions for manipulating this data structure// are members of _RopeRep.  Most of the more complex algorithms// are implemented as rope members.//// Some of the static member functions of _RopeRep have identically// named functions in rope that simply invoke the _RopeRep versions.#define __ROPE_DEFINE_ALLOCS(__a) \__ROPE_DEFINE_ALLOC(_CharT,_Data)/* character data */ \typedef _Rope_RopeConcatenation<_CharT,__a> __C; \__ROPE_DEFINE_ALLOC(__C,_C) \typedef _Rope_RopeLeaf<_CharT,__a> __L; \__ROPE_DEFINE_ALLOC(__L,_L) \typedef _Rope_RopeFunction<_CharT,__a> __F; \__ROPE_DEFINE_ALLOC(__F,_F) \typedef _Rope_RopeSubstring<_CharT,__a> __S; \__ROPE_DEFINE_ALLOC(__S,_S)//  Internal rope nodes potentially store a copy of the allocator//  instance used to allocate them.  This is mostly redundant.//  But the alternative would be to pass allocator instances around//  in some form to nearly all internal functions, since any pointer//  assignment may result in a zero reference count and thus require//  deallocation.#define __STATIC_IF_SGI_ALLOC/* not static */template <class _CharT, class _Alloc>struct _Rope_rep_base: public _Alloc{typedef _Alloc allocator_type;allocator_typeget_allocator() const{ return *static_cast<const _Alloc*>(this); }allocator_type&_M_get_allocator(){ return *static_cast<_Alloc*>(this); }const allocator_type&_M_get_allocator() const{ return *static_cast<const _Alloc*>(this); }_Rope_rep_base(size_t __size, const allocator_type&): _M_size(__size) { }size_t _M_size;# define __ROPE_DEFINE_ALLOC(_Tp, __name) \typedef typename \_Alloc::template rebind<_Tp>::other __name##Alloc; \static _Tp* __name##_allocate(size_t __n) \{ return __name##Alloc().allocate(__n); } \static void __name##_deallocate(_Tp *__p, size_t __n) \{ __name##Alloc().deallocate(__p, __n); }__ROPE_DEFINE_ALLOCS(_Alloc)
# undef __ROPE_DEFINE_ALLOC};template<class _CharT, class _Alloc>struct _Rope_RopeRep: public _Rope_rep_base<_CharT, _Alloc>
# ifndef __GC, _Refcount_Base
# endif{public:__detail::_Tag _M_tag:8;bool _M_is_balanced:8;unsigned char _M_depth;__GC_CONST _CharT* _M_c_string;
#ifdef __GTHREAD_MUTEX_INIT__gthread_mutex_t _M_c_string_lock = __GTHREAD_MUTEX_INIT;
#else__gthread_mutex_t _M_c_string_lock;
#endif/* Flattened version of string, if needed.  *//* typically 0.                             *//* If it's not 0, then the memory is owned  *//* by this node.                            *//* In the case of a leaf, this may point to *//* the same memory as the data field.       */typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_typeallocator_type;using _Rope_rep_base<_CharT, _Alloc>::get_allocator;using _Rope_rep_base<_CharT, _Alloc>::_M_get_allocator;_Rope_RopeRep(__detail::_Tag __t, int __d, bool __b, size_t __size,const allocator_type& __a): _Rope_rep_base<_CharT, _Alloc>(__size, __a),
#ifndef __GC_Refcount_Base(1),
#endif_M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0)
#ifdef __GTHREAD_MUTEX_INIT{ }
#else{ __GTHREAD_MUTEX_INIT_FUNCTION (&_M_c_string_lock); }~_Rope_RopeRep(){ __gthread_mutex_destroy (&_M_c_string_lock); }
#endif
#ifdef __GCvoid_M_incr () { }
#endifstatic void_S_free_string(__GC_CONST _CharT*, size_t __len,allocator_type& __a);
#define __STL_FREE_STRING(__s, __l, __a) _S_free_string(__s, __l, __a);// Deallocate data section of a leaf.// This shouldn't be a member function.// But its hard to do anything else at the// moment, because it's templatized w.r.t.// an allocator.// Does nothing if __GC is defined.
#ifndef __GCvoid _M_free_c_string();void _M_free_tree();// Deallocate t. Assumes t is not 0.void_M_unref_nonnil(){if (0 == _M_decr())_M_free_tree();}void_M_ref_nonnil(){ _M_incr(); }static void_S_unref(_Rope_RopeRep* __t){if (0 != __t)__t->_M_unref_nonnil();}static void_S_ref(_Rope_RopeRep* __t){if (0 != __t)__t->_M_incr();}static void_S_free_if_unref(_Rope_RopeRep* __t){if (0 != __t && 0 == __t->_M_ref_count)__t->_M_free_tree();}
#   else/* __GC */void _M_unref_nonnil() { }void _M_ref_nonnil() { }static void _S_unref(_Rope_RopeRep*) { }static void _S_ref(_Rope_RopeRep*) { }static void _S_free_if_unref(_Rope_RopeRep*) { }
#   endif
protected:_Rope_RopeRep&operator=(const _Rope_RopeRep&);_Rope_RopeRep(const _Rope_RopeRep&);};template<class _CharT, class _Alloc>struct _Rope_RopeLeaf: public _Rope_RopeRep<_CharT, _Alloc>{public:// Apparently needed by VC++// The data fields of leaves are allocated with some// extra space, to accommodate future growth and for basic// character types, to hold a trailing eos character.enum { _S_alloc_granularity = 8 };static size_t_S_rounded_up_size(size_t __n){size_t __size_with_eos;if (_S_is_basic_char_type((_CharT*)0))__size_with_eos = __n + 1;else__size_with_eos = __n;
#ifdef __GCreturn __size_with_eos;
#else// Allow slop for in-place expansion.return ((__size_with_eos + size_t(_S_alloc_granularity) - 1)&~ (size_t(_S_alloc_granularity) - 1));
#endif}__GC_CONST _CharT* _M_data; /* Not necessarily 0 terminated. *//* The allocated size is         *//* _S_rounded_up_size(size), except *//* in the GC case, in which it   *//* doesn't matter.               */typedef typename _Rope_rep_base<_CharT,_Alloc>::allocator_typeallocator_type;_Rope_RopeLeaf(__GC_CONST _CharT* __d, size_t __size,const allocator_type& __a): _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_leaf, 0, true,__size, __a), _M_data(__d){if (_S_is_basic_char_type((_CharT *)0)){// already eos terminated.this->_M_c_string = __d;}}// The constructor assumes that d has been allocated with// the proper allocator and the properly padded size.// In contrast, the destructor deallocates the data:
#ifndef __GC~_Rope_RopeLeaf() throw(){if (_M_data != this->_M_c_string)this->_M_free_c_string();this->__STL_FREE_STRING(_M_data, this->_M_size, this->_M_get_allocator());}
#endif
protected:_Rope_RopeLeaf&operator=(const _Rope_RopeLeaf&);_Rope_RopeLeaf(const _Rope_RopeLeaf&);};template<class _CharT, class _Alloc>struct _Rope_RopeConcatenation: public _Rope_RopeRep<_CharT, _Alloc>{public:_Rope_RopeRep<_CharT, _Alloc>* _M_left;_Rope_RopeRep<_CharT, _Alloc>* _M_right;typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_typeallocator_type;_Rope_RopeConcatenation(_Rope_RopeRep<_CharT, _Alloc>* __l,_Rope_RopeRep<_CharT, _Alloc>* __r,const allocator_type& __a): _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_concat,std::max(__l->_M_depth,__r->_M_depth) + 1,false,__l->_M_size + __r->_M_size, __a),_M_left(__l), _M_right(__r){ }
#ifndef __GC~_Rope_RopeConcatenation() throw(){this->_M_free_c_string();_M_left->_M_unref_nonnil();_M_right->_M_unref_nonnil();}
#endif
protected:_Rope_RopeConcatenation&operator=(const _Rope_RopeConcatenation&);_Rope_RopeConcatenation(const _Rope_RopeConcatenation&);};template<class _CharT, class _Alloc>struct _Rope_RopeFunction: public _Rope_RopeRep<_CharT, _Alloc>{public:char_producer<_CharT>* _M_fn;
#ifndef __GCbool _M_delete_when_done; // Char_producer is owned by the// rope and should be explicitly// deleted when the rope becomes// inaccessible.
#else// In the GC case, we either register the rope for// finalization, or not.  Thus the field is unnecessary;// the information is stored in the collector data structures.// We do need a finalization procedure to be invoked by the// collector.static void_S_fn_finalization_proc(void * __tree, void *){ delete ((_Rope_RopeFunction *)__tree) -> _M_fn; }
#endiftypedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_typeallocator_type;_Rope_RopeFunction(char_producer<_CharT>* __f, size_t __size,bool __d, const allocator_type& __a): _Rope_RopeRep<_CharT, _Alloc>(__detail::_S_function, 0, true, __size, __a), _M_fn(__f)
#ifndef __GC, _M_delete_when_done(__d)
#endif{
#ifdef __GCif (__d){GC_REGISTER_FINALIZER(this, _Rope_RopeFunction::_S_fn_finalization_proc, 0, 0, 0);}
#endif}
#ifndef __GC~_Rope_RopeFunction() throw(){this->_M_free_c_string();if (_M_delete_when_done)delete _M_fn;}
# endifprotected:_Rope_RopeFunction&operator=(const _Rope_RopeFunction&);_Rope_RopeFunction(const _Rope_RopeFunction&);};// Substring results are usually represented using just// concatenation nodes.  But in the case of very long flat ropes// or ropes with a functional representation that isn't practical.// In that case, we represent the __result as a special case of// RopeFunction, whose char_producer points back to the rope itself.// In all cases except repeated substring operations and// deallocation, we treat the __result as a RopeFunction.template<class _CharT, class _Alloc>struct _Rope_RopeSubstring: public _Rope_RopeFunction<_CharT, _Alloc>,public char_producer<_CharT>{public:// XXX this whole class should be rewritten._Rope_RopeRep<_CharT,_Alloc>* _M_base;      // not 0size_t _M_start;virtual voidoperator()(size_t __start_pos, size_t __req_len,_CharT* __buffer){switch(_M_base->_M_tag){case __detail::_S_function:case __detail::_S_substringfn:{char_producer<_CharT>* __fn =((_Rope_RopeFunction<_CharT,_Alloc>*)_M_base)->_M_fn;(*__fn)(__start_pos + _M_start, __req_len, __buffer);}break;case __detail::_S_leaf:{__GC_CONST _CharT* __s =((_Rope_RopeLeaf<_CharT,_Alloc>*)_M_base)->_M_data;uninitialized_copy_n(__s + __start_pos + _M_start, __req_len,__buffer);}break;default:break;}}typedef typename _Rope_rep_base<_CharT, _Alloc>::allocator_typeallocator_type;_Rope_RopeSubstring(_Rope_RopeRep<_CharT, _Alloc>* __b, size_t __s,size_t __l, const allocator_type& __a): _Rope_RopeFunction<_CharT, _Alloc>(this, __l, false, __a),char_producer<_CharT>(), _M_base(__b), _M_start(__s){
#ifndef __GC_M_base->_M_ref_nonnil();
#endifthis->_M_tag = __detail::_S_substringfn;}virtual ~_Rope_RopeSubstring() throw(){
#ifndef __GC_M_base->_M_unref_nonnil();// _M_free_c_string();  -- done by parent class
#endif}};// Self-destructing pointers to Rope_rep.// These are not conventional smart pointers.  Their// only purpose in life is to ensure that unref is called// on the pointer either at normal exit or if an exception// is raised.  It is the caller's responsibility to// adjust reference counts when these pointers are initialized// or assigned to.  (This convention significantly reduces// the number of potentially expensive reference count// updates.)
#ifndef __GCtemplate<class _CharT, class _Alloc>struct _Rope_self_destruct_ptr{_Rope_RopeRep<_CharT, _Alloc>* _M_ptr;~_Rope_self_destruct_ptr(){ _Rope_RopeRep<_CharT, _Alloc>::_S_unref(_M_ptr); }
#if __cpp_exceptions_Rope_self_destruct_ptr() : _M_ptr(0) { };
#else_Rope_self_destruct_ptr() { };
#endif_Rope_self_destruct_ptr(_Rope_RopeRep<_CharT, _Alloc>* __p): _M_ptr(__p) { }_Rope_RopeRep<_CharT, _Alloc>&operator*(){ return *_M_ptr; }_Rope_RopeRep<_CharT, _Alloc>*operator->(){ return _M_ptr; }operator _Rope_RopeRep<_CharT, _Alloc>*(){ return _M_ptr; }_Rope_self_destruct_ptr&operator=(_Rope_RopeRep<_CharT, _Alloc>* __x){ _M_ptr = __x; return *this; }};
#endif// Dereferencing a nonconst iterator has to return something// that behaves almost like a reference.  It's not possible to// return an actual reference since assignment requires extra// work.  And we would get into the same problems as with the// CD2 version of basic_string.template<class _CharT, class _Alloc>class _Rope_char_ref_proxy{friend class rope<_CharT, _Alloc>;friend class _Rope_iterator<_CharT, _Alloc>;friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;
#ifdef __GCtypedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
#elsetypedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
#endiftypedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;typedef rope<_CharT, _Alloc> _My_rope;size_t _M_pos;_CharT _M_current;bool _M_current_valid;_My_rope* _M_root;     // The whole rope.public:_Rope_char_ref_proxy(_My_rope* __r, size_t __p):  _M_pos(__p), _M_current(), _M_current_valid(false), _M_root(__r) { }_Rope_char_ref_proxy(const _Rope_char_ref_proxy& __x): _M_pos(__x._M_pos), _M_current(__x._M_current), _M_current_valid(false), _M_root(__x._M_root) { }// Don't preserve cache if the reference can outlive the// expression.  We claim that's not possible without calling// a copy constructor or generating reference to a proxy// reference.  We declare the latter to have undefined semantics._Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c): _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) { }inline operator _CharT () const;_Rope_char_ref_proxy&operator=(_CharT __c);_Rope_char_ptr_proxy<_CharT, _Alloc> operator&() const;_Rope_char_ref_proxy&operator=(const _Rope_char_ref_proxy& __c){ return operator=((_CharT)__c); }};template<class _CharT, class __Alloc>inline voidswap(_Rope_char_ref_proxy <_CharT, __Alloc > __a,_Rope_char_ref_proxy <_CharT, __Alloc > __b){_CharT __tmp = __a;__a = __b;__b = __tmp;}template<class _CharT, class _Alloc>class _Rope_char_ptr_proxy{// XXX this class should be rewritten.friend class _Rope_char_ref_proxy<_CharT, _Alloc>;size_t _M_pos;rope<_CharT,_Alloc>* _M_root;     // The whole rope.public:_Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x): _M_pos(__x._M_pos), _M_root(__x._M_root) { }_Rope_char_ptr_proxy(const _Rope_char_ptr_proxy& __x): _M_pos(__x._M_pos), _M_root(__x._M_root) { }_Rope_char_ptr_proxy() { }_Rope_char_ptr_proxy(_CharT* __x): _M_root(0), _M_pos(0) { }_Rope_char_ptr_proxy&operator=(const _Rope_char_ptr_proxy& __x){_M_pos = __x._M_pos;_M_root = __x._M_root;return *this;}template<class _CharT2, class _Alloc2>friend booloperator==(const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __x,const _Rope_char_ptr_proxy<_CharT2, _Alloc2>& __y);_Rope_char_ref_proxy<_CharT, _Alloc> operator*() const{ return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root, _M_pos); }};// Rope iterators:// Unlike in the C version, we cache only part of the stack// for rope iterators, since they must be efficiently copyable.// When we run out of cache, we have to reconstruct the iterator// value.// Pointers from iterators are not included in reference counts.// Iterators are assumed to be thread private.  Ropes can// be shared.template<class _CharT, class _Alloc>class _Rope_iterator_base: public std::iterator<std::random_access_iterator_tag, _CharT>{friend class rope<_CharT, _Alloc>;public:typedef _Alloc _allocator_type; // used in _Rope_rotate, VC++ workaroundtypedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;// Borland doesn't want this to be protected.protected:enum { _S_path_cache_len = 4 }; // Must be <= 9.enum { _S_iterator_buf_len = 15 };size_t _M_current_pos;_RopeRep* _M_root;     // The whole rope.size_t _M_leaf_pos;    // Starting position for current leaf__GC_CONST _CharT* _M_buf_start;// Buffer possibly// containing current char.__GC_CONST _CharT* _M_buf_ptr;// Pointer to current char in buffer.// != 0 ==> buffer valid.__GC_CONST _CharT* _M_buf_end;// One past __last valid char in buffer.// What follows is the path cache.  We go out of our// way to make this compact.// Path_end contains the bottom section of the path from// the root to the current leaf.const _RopeRep* _M_path_end[_S_path_cache_len];int _M_leaf_index;     // Last valid __pos in path_end;// _M_path_end[0] ... _M_path_end[leaf_index-1]// point to concatenation nodes.unsigned char _M_path_directions;// (path_directions >> __i) & 1 is 1// iff we got from _M_path_end[leaf_index - __i - 1]// to _M_path_end[leaf_index - __i] by going to the// __right. Assumes path_cache_len <= 9._CharT _M_tmp_buf[_S_iterator_buf_len];// Short buffer for surrounding chars.// This is useful primarily for// RopeFunctions.  We put the buffer// here to avoid locking in the// multithreaded case.// The cached path is generally assumed to be valid// only if the buffer is valid.static void _S_setbuf(_Rope_iterator_base& __x);// Set buffer contents given// path cache.static void _S_setcache(_Rope_iterator_base& __x);// Set buffer contents and// path cache.static void _S_setcache_for_incr(_Rope_iterator_base& __x);// As above, but assumes path// cache is valid for previous posn._Rope_iterator_base() { }_Rope_iterator_base(_RopeRep* __root, size_t __pos): _M_current_pos(__pos), _M_root(__root), _M_buf_ptr(0) { }void _M_incr(size_t __n);void _M_decr(size_t __n);public:size_tindex() const{ return _M_current_pos; }_Rope_iterator_base(const _Rope_iterator_base& __x){if (0 != __x._M_buf_ptr)*this = __x;else{_M_current_pos = __x._M_current_pos;_M_root = __x._M_root;_M_buf_ptr = 0;}}};template<class _CharT, class _Alloc>class _Rope_iterator;template<class _CharT, class _Alloc>class _Rope_const_iterator: public _Rope_iterator_base<_CharT, _Alloc>{friend class rope<_CharT, _Alloc>;protected:typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;// The one from the base class may not be directly visible._Rope_const_iterator(const _RopeRep* __root, size_t __pos): _Rope_iterator_base<_CharT, _Alloc>(const_cast<_RopeRep*>(__root),__pos)// Only nonconst iterators modify root ref count{ }public:typedef _CharT reference;   // Really a value.  Returning a reference// Would be a mess, since it would have// to be included in refcount.typedef const _CharT* pointer;public:_Rope_const_iterator() { };_Rope_const_iterator(const _Rope_const_iterator& __x): _Rope_iterator_base<_CharT,_Alloc>(__x) { }_Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x);_Rope_const_iterator(const rope<_CharT, _Alloc>& __r, size_t __pos): _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr, __pos) { }_Rope_const_iterator&operator=(const _Rope_const_iterator& __x){if (0 != __x._M_buf_ptr)*(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;else{this->_M_current_pos = __x._M_current_pos;this->_M_root = __x._M_root;this->_M_buf_ptr = 0;}return(*this);}referenceoperator*(){if (0 == this->_M_buf_ptr)this->_S_setcache(*this);return *this->_M_buf_ptr;}// Without this const version, Rope iterators do not meet the// requirements of an Input Iterator.referenceoperator*() const{return *const_cast<_Rope_const_iterator&>(*this);}_Rope_const_iterator&operator++(){__GC_CONST _CharT* __next;if (0 != this->_M_buf_ptr&& (__next = this->_M_buf_ptr + 1) < this->_M_buf_end){this->_M_buf_ptr = __next;++this->_M_current_pos;}elsethis->_M_incr(1);return *this;}_Rope_const_iterator&operator+=(ptrdiff_t __n){if (__n >= 0)this->_M_incr(__n);elsethis->_M_decr(-__n);return *this;}_Rope_const_iterator&operator--(){this->_M_decr(1);return *this;}_Rope_const_iterator&operator-=(ptrdiff_t __n){if (__n >= 0)this->_M_decr(__n);elsethis->_M_incr(-__n);return *this;}_Rope_const_iteratoroperator++(int){size_t __old_pos = this->_M_current_pos;this->_M_incr(1);return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);// This makes a subsequent dereference expensive.// Perhaps we should instead copy the iterator// if it has a valid cache?}_Rope_const_iteratoroperator--(int){size_t __old_pos = this->_M_current_pos;this->_M_decr(1);return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos);}template<class _CharT2, class _Alloc2>friend _Rope_const_iterator<_CharT2, _Alloc2>operator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,ptrdiff_t __n);template<class _CharT2, class _Alloc2>friend _Rope_const_iterator<_CharT2, _Alloc2>operator+(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,ptrdiff_t __n);template<class _CharT2, class _Alloc2>friend _Rope_const_iterator<_CharT2, _Alloc2>operator+(ptrdiff_t __n,const _Rope_const_iterator<_CharT2, _Alloc2>& __x);referenceoperator[](size_t __n){ return rope<_CharT, _Alloc>::_S_fetch(this->_M_root,this->_M_current_pos + __n); }template<class _CharT2, class _Alloc2>friend booloperator==(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,const _Rope_const_iterator<_CharT2, _Alloc2>& __y);template<class _CharT2, class _Alloc2>friend booloperator<(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,const _Rope_const_iterator<_CharT2, _Alloc2>& __y);template<class _CharT2, class _Alloc2>friend ptrdiff_toperator-(const _Rope_const_iterator<_CharT2, _Alloc2>& __x,const _Rope_const_iterator<_CharT2, _Alloc2>& __y);};template<class _CharT, class _Alloc>class _Rope_iterator: public _Rope_iterator_base<_CharT, _Alloc>{friend class rope<_CharT, _Alloc>;protected:typedef typename _Rope_iterator_base<_CharT, _Alloc>::_RopeRep _RopeRep;rope<_CharT, _Alloc>* _M_root_rope;// root is treated as a cached version of this, and is used to// detect changes to the underlying rope.// Root is included in the reference count.  This is necessary// so that we can detect changes reliably.  Unfortunately, it// requires careful bookkeeping for the nonGC case._Rope_iterator(rope<_CharT, _Alloc>* __r, size_t __pos): _Rope_iterator_base<_CharT, _Alloc>(__r->_M_tree_ptr, __pos),_M_root_rope(__r){ _RopeRep::_S_ref(this->_M_root);if (!(__r -> empty()))this->_S_setcache(*this);}void _M_check();public:typedef _Rope_char_ref_proxy<_CharT, _Alloc>  reference;typedef _Rope_char_ref_proxy<_CharT, _Alloc>* pointer;rope<_CharT, _Alloc>&container(){ return *_M_root_rope; }_Rope_iterator(){this->_M_root = 0;  // Needed for reference counting.};_Rope_iterator(const _Rope_iterator& __x): _Rope_iterator_base<_CharT, _Alloc>(__x){_M_root_rope = __x._M_root_rope;_RopeRep::_S_ref(this->_M_root);}_Rope_iterator(rope<_CharT, _Alloc>& __r, size_t __pos);~_Rope_iterator(){ _RopeRep::_S_unref(this->_M_root); }_Rope_iterator&operator=(const _Rope_iterator& __x){_RopeRep* __old = this->_M_root;_RopeRep::_S_ref(__x._M_root);if (0 != __x._M_buf_ptr){_M_root_rope = __x._M_root_rope;*(static_cast<_Rope_iterator_base<_CharT, _Alloc>*>(this)) = __x;}else{this->_M_current_pos = __x._M_current_pos;this->_M_root = __x._M_root;_M_root_rope = __x._M_root_rope;this->_M_buf_ptr = 0;}_RopeRep::_S_unref(__old);return(*this);}referenceoperator*(){_M_check();if (0 == this->_M_buf_ptr)return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,this->_M_current_pos);elsereturn _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,this->_M_current_pos,*this->_M_buf_ptr);}// See above comment.referenceoperator*() const{return *const_cast<_Rope_iterator&>(*this);}_Rope_iterator&operator++(){this->_M_incr(1);return *this;}_Rope_iterator&operator+=(ptrdiff_t __n){if (__n >= 0)this->_M_incr(__n);elsethis->_M_decr(-__n);return *this;}_Rope_iterator&operator--(){this->_M_decr(1);return *this;}_Rope_iterator&operator-=(ptrdiff_t __n){if (__n >= 0)this->_M_decr(__n);elsethis->_M_incr(-__n);return *this;}_Rope_iteratoroperator++(int){size_t __old_pos = this->_M_current_pos;this->_M_incr(1);return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);}_Rope_iteratoroperator--(int){size_t __old_pos = this->_M_current_pos;this->_M_decr(1);return _Rope_iterator<_CharT,_Alloc>(_M_root_rope, __old_pos);}referenceoperator[](ptrdiff_t __n){ return _Rope_char_ref_proxy<_CharT, _Alloc>(_M_root_rope,this->_M_current_pos+ __n); }template<class _CharT2, class _Alloc2>friend booloperator==(const _Rope_iterator<_CharT2, _Alloc2>& __x,const _Rope_iterator<_CharT2, _Alloc2>& __y);template<class _CharT2, class _Alloc2>friend booloperator<(const _Rope_iterator<_CharT2, _Alloc2>& __x,const _Rope_iterator<_CharT2, _Alloc2>& __y);template<class _CharT2, class _Alloc2>friend ptrdiff_toperator-(const _Rope_iterator<_CharT2, _Alloc2>& __x,const _Rope_iterator<_CharT2, _Alloc2>& __y);template<class _CharT2, class _Alloc2>friend _Rope_iterator<_CharT2, _Alloc2>operator-(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);template<class _CharT2, class _Alloc2>friend _Rope_iterator<_CharT2, _Alloc2>operator+(const _Rope_iterator<_CharT2, _Alloc2>& __x, ptrdiff_t __n);template<class _CharT2, class _Alloc2>friend _Rope_iterator<_CharT2, _Alloc2>operator+(ptrdiff_t __n, const _Rope_iterator<_CharT2, _Alloc2>& __x);};template <class _CharT, class _Alloc>struct _Rope_base: public _Alloc{typedef _Alloc allocator_type;allocator_typeget_allocator() const{ return *static_cast<const _Alloc*>(this); }allocator_type&_M_get_allocator(){ return *static_cast<_Alloc*>(this); }const allocator_type&_M_get_allocator() const{ return *static_cast<const _Alloc*>(this); }typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;// The one in _Base may not be visible due to template rules._Rope_base(_RopeRep* __t, const allocator_type&): _M_tree_ptr(__t) { }_Rope_base(const allocator_type&) { }// The only data member of a rope:_RopeRep *_M_tree_ptr;#define __ROPE_DEFINE_ALLOC(_Tp, __name) \typedef typename \_Alloc::template rebind<_Tp>::other __name##Alloc; \static _Tp* __name##_allocate(size_t __n) \{ return __name##Alloc().allocate(__n); } \static void __name##_deallocate(_Tp *__p, size_t __n) \{ __name##Alloc().deallocate(__p, __n); }__ROPE_DEFINE_ALLOCS(_Alloc)
#undef __ROPE_DEFINE_ALLOCprotected:_Rope_base&operator=(const _Rope_base&);_Rope_base(const _Rope_base&);};/***  This is an SGI extension.*  @ingroup SGIextensions*  @doctodo*/template <class _CharT, class _Alloc>class rope : public _Rope_base<_CharT, _Alloc>{public:typedef _CharT value_type;typedef ptrdiff_t difference_type;typedef size_t size_type;typedef _CharT const_reference;typedef const _CharT* const_pointer;typedef _Rope_iterator<_CharT, _Alloc> iterator;typedef _Rope_const_iterator<_CharT, _Alloc> const_iterator;typedef _Rope_char_ref_proxy<_CharT, _Alloc> reference;typedef _Rope_char_ptr_proxy<_CharT, _Alloc> pointer;friend class _Rope_iterator<_CharT, _Alloc>;friend class _Rope_const_iterator<_CharT, _Alloc>;friend struct _Rope_RopeRep<_CharT, _Alloc>;friend class _Rope_iterator_base<_CharT, _Alloc>;friend class _Rope_char_ptr_proxy<_CharT, _Alloc>;friend class _Rope_char_ref_proxy<_CharT, _Alloc>;friend struct _Rope_RopeSubstring<_CharT, _Alloc>;protected:typedef _Rope_base<_CharT, _Alloc> _Base;typedef typename _Base::allocator_type allocator_type;using _Base::_M_tree_ptr;using _Base::get_allocator;using _Base::_M_get_allocator;typedef __GC_CONST _CharT* _Cstrptr;static _CharT _S_empty_c_str[1];static bool_S_is0(_CharT __c){ return __c == _S_eos((_CharT*)0); }enum { _S_copy_max = 23 };// For strings shorter than _S_copy_max, we copy to// concatenate.typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep;typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation;typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf;typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction;typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring;// Retrieve a character at the indicated position.static _CharT _S_fetch(_RopeRep* __r, size_type __pos);#ifndef __GC// Obtain a pointer to the character at the indicated position.// The pointer can be used to change the character.// If such a pointer cannot be produced, as is frequently the// case, 0 is returned instead.// (Returns nonzero only if all nodes in the path have a refcount// of 1.)static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos);
#endifstatic bool_S_apply_to_pieces(// should be template parameter_Rope_char_consumer<_CharT>& __c,const _RopeRep* __r,size_t __begin, size_t __end);// begin and end are assumed to be in range.#ifndef __GCstatic void_S_unref(_RopeRep* __t){ _RopeRep::_S_unref(__t); }static void_S_ref(_RopeRep* __t){ _RopeRep::_S_ref(__t); }#else/* __GC */static void _S_unref(_RopeRep*) { }static void _S_ref(_RopeRep*) { }
#endif#ifdef __GCtypedef _Rope_RopeRep<_CharT, _Alloc>* _Self_destruct_ptr;
#elsetypedef _Rope_self_destruct_ptr<_CharT, _Alloc> _Self_destruct_ptr;
#endif// _Result is counted in refcount.static _RopeRep* _S_substring(_RopeRep* __base,size_t __start, size_t __endp1);static _RopeRep* _S_concat_char_iter(_RopeRep* __r,const _CharT* __iter, size_t __slen);// Concatenate rope and char ptr, copying __s.// Should really take an arbitrary iterator.// Result is counted in refcount.static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r,const _CharT* __iter,size_t __slen)// As above, but one reference to __r is about to be// destroyed.  Thus the pieces may be recycled if all// relevant reference counts are 1.
#ifdef __GC// We can't really do anything since refcounts are unavailable.{ return _S_concat_char_iter(__r, __iter, __slen); }
#else;
#endifstatic _RopeRep* _S_concat(_RopeRep* __left, _RopeRep* __right);// General concatenation on _RopeRep.  _Result// has refcount of 1.  Adjusts argument refcounts.public:voidapply_to_pieces(size_t __begin, size_t __end,_Rope_char_consumer<_CharT>& __c) const{ _S_apply_to_pieces(__c, this->_M_tree_ptr, __begin, __end); }protected:static size_t_S_rounded_up_size(size_t __n){ return _RopeLeaf::_S_rounded_up_size(__n); }static size_t_S_allocated_capacity(size_t __n){if (_S_is_basic_char_type((_CharT*)0))return _S_rounded_up_size(__n) - 1;elsereturn _S_rounded_up_size(__n);}// Allocate and construct a RopeLeaf using the supplied allocator// Takes ownership of s instead of copying.static _RopeLeaf*_S_new_RopeLeaf(__GC_CONST _CharT *__s,size_t __size, allocator_type& __a){_RopeLeaf* __space = typename _Base::_LAlloc(__a).allocate(1);return new(__space) _RopeLeaf(__s, __size, __a);}static _RopeConcatenation*_S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right,allocator_type& __a){_RopeConcatenation* __space = typename _Base::_CAlloc(__a).allocate(1);return new(__space) _RopeConcatenation(__left, __right, __a);}static _RopeFunction*_S_new_RopeFunction(char_producer<_CharT>* __f,size_t __size, bool __d, allocator_type& __a){_RopeFunction* __space = typename _Base::_FAlloc(__a).allocate(1);return new(__space) _RopeFunction(__f, __size, __d, __a);}static _RopeSubstring*_S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s,size_t __l, allocator_type& __a){_RopeSubstring* __space = typename _Base::_SAlloc(__a).allocate(1);return new(__space) _RopeSubstring(__b, __s, __l, __a);}static _RopeLeaf*_S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s,size_t __size, allocator_type& __a)
#define __STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __size, __a) \_S_RopeLeaf_from_unowned_char_ptr(__s, __size, __a){if (0 == __size)return 0;_CharT* __buf = __a.allocate(_S_rounded_up_size(__size));__uninitialized_copy_n_a(__s, __size, __buf, __a);_S_cond_store_eos(__buf[__size]);__try{ return _S_new_RopeLeaf(__buf, __size, __a); }__catch(...){_RopeRep::__STL_FREE_STRING(__buf, __size, __a);__throw_exception_again;}}// Concatenation of nonempty strings.// Always builds a concatenation node.// Rebalances if the result is too deep.// Result has refcount 1.// Does not increment left and right ref counts even though// they are referenced.static _RopeRep*_S_tree_concat(_RopeRep* __left, _RopeRep* __right);// Concatenation helper functionsstatic _RopeLeaf*_S_leaf_concat_char_iter(_RopeLeaf* __r,const _CharT* __iter, size_t __slen);// Concatenate by copying leaf.// should take an arbitrary iterator// result has refcount 1.
#ifndef __GCstatic _RopeLeaf*_S_destr_leaf_concat_char_iter(_RopeLeaf* __r,const _CharT* __iter, size_t __slen);// A version that potentially clobbers __r if __r->_M_ref_count == 1.
#endifprivate:static size_t _S_char_ptr_len(const _CharT* __s);// slightly generalized strlenrope(_RopeRep* __t, const allocator_type& __a = allocator_type()): _Base(__t, __a) { }// Copy __r to the _CharT buffer.// Returns __buffer + __r->_M_size.// Assumes that buffer is uninitialized.static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer);// Again, with explicit starting position and length.// Assumes that buffer is uninitialized.static _CharT* _S_flatten(_RopeRep* __r,size_t __start, size_t __len,_CharT* __buffer);static const unsigned long_S_min_len[__detail::_S_max_rope_depth + 1];static bool_S_is_balanced(_RopeRep* __r){ return (__r->_M_size >= _S_min_len[__r->_M_depth]); }static bool_S_is_almost_balanced(_RopeRep* __r){ return (__r->_M_depth == 0|| __r->_M_size >= _S_min_len[__r->_M_depth - 1]); }static bool_S_is_roughly_balanced(_RopeRep* __r){ return (__r->_M_depth <= 1|| __r->_M_size >= _S_min_len[__r->_M_depth - 2]); }// Assumes the result is not empty.static _RopeRep*_S_concat_and_set_balanced(_RopeRep* __left, _RopeRep* __right){_RopeRep* __result = _S_concat(__left, __right);if (_S_is_balanced(__result))__result->_M_is_balanced = true;return __result;}// The basic rebalancing operation.  Logically copies the// rope.  The result has refcount of 1.  The client will// usually decrement the reference count of __r.// The result is within height 2 of balanced by the above// definition.static _RopeRep* _S_balance(_RopeRep* __r);// Add all unbalanced subtrees to the forest of balanced trees.// Used only by balance.static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest);// Add __r to forest, assuming __r is already balanced.static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest);// Print to stdout, exposing structurestatic void _S_dump(_RopeRep* __r, int __indent = 0);// Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp.static int _S_compare(const _RopeRep* __x, const _RopeRep* __y);public:boolempty() const{ return 0 == this->_M_tree_ptr; }// Comparison member function.  This is public only for those// clients that need a ternary comparison.  Others// should use the comparison operators below.intcompare(const rope& __y) const{ return _S_compare(this->_M_tree_ptr, __y._M_tree_ptr); }rope(const _CharT* __s, const allocator_type& __a = allocator_type()): _Base(__a){this->_M_tree_ptr =__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, _S_char_ptr_len(__s),_M_get_allocator());}rope(const _CharT* __s, size_t __len,const allocator_type& __a = allocator_type()): _Base(__a){this->_M_tree_ptr =__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __len, _M_get_allocator());}// Should perhaps be templatized with respect to the iterator type// and use Sequence_buffer.  (It should perhaps use sequence_buffer// even now.)rope(const _CharT* __s, const _CharT* __e,const allocator_type& __a = allocator_type()): _Base(__a){this->_M_tree_ptr =__STL_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __e - __s, _M_get_allocator());}rope(const const_iterator& __s, const const_iterator& __e,const allocator_type& __a = allocator_type()): _Base(_S_substring(__s._M_root, __s._M_current_pos,__e._M_current_pos), __a){ }rope(const iterator& __s, const iterator& __e,const allocator_type& __a = allocator_type()): _Base(_S_substring(__s._M_root, __s._M_current_pos,__e._M_current_pos), __a){ }rope(_CharT __c, const allocator_type& __a = allocator_type()): _Base(__a){_CharT* __buf = this->_Data_allocate(_S_rounded_up_size(1));_M_get_allocator().construct(__buf, __c);__try{this->_M_tree_ptr = _S_new_RopeLeaf(__buf, 1,_M_get_allocator());}__catch(...){_RopeRep::__STL_FREE_STRING(__buf, 1, _M_get_allocator());__throw_exception_again;}}rope(size_t __n, _CharT __c,const allocator_type& __a = allocator_type());rope(const allocator_type& __a = allocator_type()): _Base(0, __a) { }// Construct a rope from a function that can compute its membersrope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn,const allocator_type& __a = allocator_type()): _Base(__a){this->_M_tree_ptr = (0 == __len)? 0: _S_new_RopeFunction(__fn, __len, __delete_fn, _M_get_allocator());}rope(const rope& __x, const allocator_type& __a = allocator_type()): _Base(__x._M_tree_ptr, __a){ _S_ref(this->_M_tree_ptr); }~rope() throw(){ _S_unref(this->_M_tree_ptr); }rope&operator=(const rope& __x){_RopeRep* __old = this->_M_tree_ptr;this->_M_tree_ptr = __x._M_tree_ptr;_S_ref(this->_M_tree_ptr);_S_unref(__old);return *this;}voidclear(){_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = 0;}voidpush_back(_CharT __x){_RopeRep* __old = this->_M_tree_ptr;this->_M_tree_ptr= _S_destr_concat_char_iter(this->_M_tree_ptr, &__x, 1);_S_unref(__old);}voidpop_back(){_RopeRep* __old = this->_M_tree_ptr;this->_M_tree_ptr = _S_substring(this->_M_tree_ptr,0, this->_M_tree_ptr->_M_size - 1);_S_unref(__old);}_CharTback() const{ return _S_fetch(this->_M_tree_ptr, this->_M_tree_ptr->_M_size - 1); }voidpush_front(_CharT __x){_RopeRep* __old = this->_M_tree_ptr;_RopeRep* __left =__STL_ROPE_FROM_UNOWNED_CHAR_PTR(&__x, 1, _M_get_allocator());__try{this->_M_tree_ptr = _S_concat(__left, this->_M_tree_ptr);_S_unref(__old);_S_unref(__left);}__catch(...){_S_unref(__left);__throw_exception_again;}}voidpop_front(){_RopeRep* __old = this->_M_tree_ptr;this->_M_tree_ptr= _S_substring(this->_M_tree_ptr, 1, this->_M_tree_ptr->_M_size);_S_unref(__old);}_CharTfront() const{ return _S_fetch(this->_M_tree_ptr, 0); }voidbalance(){_RopeRep* __old = this->_M_tree_ptr;this->_M_tree_ptr = _S_balance(this->_M_tree_ptr);_S_unref(__old);}voidcopy(_CharT* __buffer) const{_Destroy_const(__buffer, __buffer + size(), _M_get_allocator());_S_flatten(this->_M_tree_ptr, __buffer);}// This is the copy function from the standard, but// with the arguments reordered to make it consistent with the// rest of the interface.// Note that this guaranteed not to compile if the draft standard// order is assumed.size_typecopy(size_type __pos, size_type __n, _CharT* __buffer) const{size_t __size = size();size_t __len = (__pos + __n > __size? __size - __pos : __n);_Destroy_const(__buffer, __buffer + __len, _M_get_allocator());_S_flatten(this->_M_tree_ptr, __pos, __len, __buffer);return __len;}// Print to stdout, exposing structure.  May be useful for// performance debugging.voiddump(){ _S_dump(this->_M_tree_ptr); }// Convert to 0 terminated string in new allocated memory.// Embedded 0s in the input do not terminate the copy.const _CharT* c_str() const;// As above, but also use the flattened representation as// the new rope representation.const _CharT* replace_with_c_str();// Reclaim memory for the c_str generated flattened string.// Intentionally undocumented, since it's hard to say when this// is safe for multiple threads.voiddelete_c_str (){if (0 == this->_M_tree_ptr)return;if (__detail::_S_leaf == this->_M_tree_ptr->_M_tag &&((_RopeLeaf*)this->_M_tree_ptr)->_M_data ==this->_M_tree_ptr->_M_c_string){// Representation sharedreturn;}
#ifndef __GCthis->_M_tree_ptr->_M_free_c_string();
#endifthis->_M_tree_ptr->_M_c_string = 0;}_CharToperator[] (size_type __pos) const{ return _S_fetch(this->_M_tree_ptr, __pos); }_CharTat(size_type __pos) const{// if (__pos >= size()) throw out_of_range;  // XXXreturn (*this)[__pos];}const_iteratorbegin() const{ return(const_iterator(this->_M_tree_ptr, 0)); }// An easy way to get a const iterator from a non-const container.const_iteratorconst_begin() const{ return(const_iterator(this->_M_tree_ptr, 0)); }const_iteratorend() const{ return(const_iterator(this->_M_tree_ptr, size())); }const_iteratorconst_end() const{ return(const_iterator(this->_M_tree_ptr, size())); }size_typesize() const{  return(0 == this->_M_tree_ptr? 0 : this->_M_tree_ptr->_M_size); }size_typelength() const{ return size(); }size_typemax_size() const{return _S_min_len[int(__detail::_S_max_rope_depth) - 1] - 1;//  Guarantees that the result can be sufficiently//  balanced.  Longer ropes will probably still work,//  but it's harder to make guarantees.}typedef std::reverse_iterator<const_iterator> const_reverse_iterator;const_reverse_iteratorrbegin() const{ return const_reverse_iterator(end()); }const_reverse_iteratorconst_rbegin() const{ return const_reverse_iterator(end()); }const_reverse_iteratorrend() const{ return const_reverse_iterator(begin()); }const_reverse_iteratorconst_rend() const{ return const_reverse_iterator(begin()); }template<class _CharT2, class _Alloc2>friend rope<_CharT2, _Alloc2>operator+(const rope<_CharT2, _Alloc2>& __left,const rope<_CharT2, _Alloc2>& __right);template<class _CharT2, class _Alloc2>friend rope<_CharT2, _Alloc2>operator+(const rope<_CharT2, _Alloc2>& __left, const _CharT2* __right);template<class _CharT2, class _Alloc2>friend rope<_CharT2, _Alloc2>operator+(const rope<_CharT2, _Alloc2>& __left, _CharT2 __right);// The symmetric cases are intentionally omitted, since they're// presumed to be less common, and we don't handle them as well.// The following should really be templatized.  The first// argument should be an input iterator or forward iterator with// value_type _CharT.rope&append(const _CharT* __iter, size_t __n){_RopeRep* __result =_S_destr_concat_char_iter(this->_M_tree_ptr, __iter, __n);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;return *this;}rope&append(const _CharT* __c_string){size_t __len = _S_char_ptr_len(__c_string);append(__c_string, __len);return(*this);}rope&append(const _CharT* __s, const _CharT* __e){_RopeRep* __result =_S_destr_concat_char_iter(this->_M_tree_ptr, __s, __e - __s);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;return *this;}rope&append(const_iterator __s, const_iterator __e){_Self_destruct_ptr __appendee(_S_substring(__s._M_root,__s._M_current_pos,__e._M_current_pos));_RopeRep* __result = _S_concat(this->_M_tree_ptr, (_RopeRep*)__appendee);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;return *this;}rope&append(_CharT __c){_RopeRep* __result =_S_destr_concat_char_iter(this->_M_tree_ptr, &__c, 1);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;return *this;}rope&append(){ return append(_CharT()); }  // XXX why?rope&append(const rope& __y){_RopeRep* __result = _S_concat(this->_M_tree_ptr, __y._M_tree_ptr);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;return *this;}rope&append(size_t __n, _CharT __c){rope<_CharT,_Alloc> __last(__n, __c);return append(__last);}voidswap(rope& __b){_RopeRep* __tmp = this->_M_tree_ptr;this->_M_tree_ptr = __b._M_tree_ptr;__b._M_tree_ptr = __tmp;}protected:// Result is included in refcount.static _RopeRep*replace(_RopeRep* __old, size_t __pos1,size_t __pos2, _RopeRep* __r){if (0 == __old){_S_ref(__r);return __r;}_Self_destruct_ptr __left(_S_substring(__old, 0, __pos1));_Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size));_RopeRep* __result;if (0 == __r)__result = _S_concat(__left, __right);else{_Self_destruct_ptr __left_result(_S_concat(__left, __r));__result = _S_concat(__left_result, __right);}return __result;}public:voidinsert(size_t __p, const rope& __r){_RopeRep* __result =replace(this->_M_tree_ptr, __p, __p, __r._M_tree_ptr);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;}voidinsert(size_t __p, size_t __n, _CharT __c){rope<_CharT,_Alloc> __r(__n,__c);insert(__p, __r);}voidinsert(size_t __p, const _CharT* __i, size_t __n){_Self_destruct_ptr __left(_S_substring(this->_M_tree_ptr, 0, __p));_Self_destruct_ptr __right(_S_substring(this->_M_tree_ptr,__p, size()));_Self_destruct_ptr __left_result(_S_concat_char_iter(__left, __i, __n));// _S_ destr_concat_char_iter should be safe here.// But as it stands it's probably not a win, since __left// is likely to have additional references._RopeRep* __result = _S_concat(__left_result, __right);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;}voidinsert(size_t __p, const _CharT* __c_string){    insert(__p, __c_string, _S_char_ptr_len(__c_string)); }voidinsert(size_t __p, _CharT __c){ insert(__p, &__c, 1); }voidinsert(size_t __p){_CharT __c = _CharT();insert(__p, &__c, 1);}voidinsert(size_t __p, const _CharT* __i, const _CharT* __j){rope __r(__i, __j);insert(__p, __r);}voidinsert(size_t __p, const const_iterator& __i,const const_iterator& __j){rope __r(__i, __j);insert(__p, __r);}voidinsert(size_t __p, const iterator& __i,const iterator& __j){rope __r(__i, __j);insert(__p, __r);}// (position, length) versions of replace operations:voidreplace(size_t __p, size_t __n, const rope& __r){_RopeRep* __result =replace(this->_M_tree_ptr, __p, __p + __n, __r._M_tree_ptr);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;}voidreplace(size_t __p, size_t __n,const _CharT* __i, size_t __i_len){rope __r(__i, __i_len);replace(__p, __n, __r);}voidreplace(size_t __p, size_t __n, _CharT __c){rope __r(__c);replace(__p, __n, __r);}voidreplace(size_t __p, size_t __n, const _CharT* __c_string){rope __r(__c_string);replace(__p, __n, __r);}voidreplace(size_t __p, size_t __n,const _CharT* __i, const _CharT* __j){rope __r(__i, __j);replace(__p, __n, __r);}voidreplace(size_t __p, size_t __n,const const_iterator& __i, const const_iterator& __j){rope __r(__i, __j);replace(__p, __n, __r);}voidreplace(size_t __p, size_t __n,const iterator& __i, const iterator& __j){rope __r(__i, __j);replace(__p, __n, __r);}// Single character variants:voidreplace(size_t __p, _CharT __c){iterator __i(this, __p);*__i = __c;}voidreplace(size_t __p, const rope& __r){ replace(__p, 1, __r); }voidreplace(size_t __p, const _CharT* __i, size_t __i_len){ replace(__p, 1, __i, __i_len); }voidreplace(size_t __p, const _CharT* __c_string){ replace(__p, 1, __c_string); }voidreplace(size_t __p, const _CharT* __i, const _CharT* __j){    replace(__p, 1, __i, __j); }voidreplace(size_t __p, const const_iterator& __i,const const_iterator& __j){ replace(__p, 1, __i, __j); }voidreplace(size_t __p, const iterator& __i,const iterator& __j){ replace(__p, 1, __i, __j); }// Erase, (position, size) variant.voiderase(size_t __p, size_t __n){_RopeRep* __result = replace(this->_M_tree_ptr, __p,__p + __n, 0);_S_unref(this->_M_tree_ptr);this->_M_tree_ptr = __result;}// Erase, single charactervoiderase(size_t __p){ erase(__p, __p + 1); }// Insert, iterator variants.iteratorinsert(const iterator& __p, const rope& __r){insert(__p.index(), __r);return __p;}iteratorinsert(const iterator& __p, size_t __n, _CharT __c){insert(__p.index(), __n, __c);return __p;}iterator insert(const iterator& __p, _CharT __c){insert(__p.index(), __c);return __p;}iteratorinsert(const iterator& __p ){insert(__p.index());return __p;}iteratorinsert(const iterator& __p, const _CharT* c_string){insert(__p.index(), c_string);return __p;}iteratorinsert(const iterator& __p, const _CharT* __i, size_t __n){insert(__p.index(), __i, __n);return __p;}iteratorinsert(const iterator& __p, const _CharT* __i,const _CharT* __j){insert(__p.index(), __i, __j); return __p;}iteratorinsert(const iterator& __p,const const_iterator& __i, const const_iterator& __j){insert(__p.index(), __i, __j);return __p;}iteratorinsert(const iterator& __p,const iterator& __i, const iterator& __j){insert(__p.index(), __i, __j);return __p;}// Replace, range variants.voidreplace(const iterator& __p, const iterator& __q, const rope& __r){    replace(__p.index(), __q.index() - __p.index(), __r); }voidreplace(const iterator& __p, const iterator& __q, _CharT __c){ replace(__p.index(), __q.index() - __p.index(), __c); }voidreplace(const iterator& __p, const iterator& __q,const _CharT* __c_string){ replace(__p.index(), __q.index() - __p.index(), __c_string); }voidreplace(const iterator& __p, const iterator& __q,const _CharT* __i, size_t __n){ replace(__p.index(), __q.index() - __p.index(), __i, __n); }voidreplace(const iterator& __p, const iterator& __q,const _CharT* __i, const _CharT* __j){ replace(__p.index(), __q.index() - __p.index(), __i, __j); }voidreplace(const iterator& __p, const iterator& __q,const const_iterator& __i, const const_iterator& __j){ replace(__p.index(), __q.index() - __p.index(), __i, __j); }voidreplace(const iterator& __p, const iterator& __q,const iterator& __i, const iterator& __j){ replace(__p.index(), __q.index() - __p.index(), __i, __j); }// Replace, iterator variants.voidreplace(const iterator& __p, const rope& __r){ replace(__p.index(), __r); }voidreplace(const iterator& __p, _CharT __c){ replace(__p.index(), __c); }voidreplace(const iterator& __p, const _CharT* __c_string){ replace(__p.index(), __c_string); }voidreplace(const iterator& __p, const _CharT* __i, size_t __n){ replace(__p.index(), __i, __n); }voidreplace(const iterator& __p, const _CharT* __i, const _CharT* __j){ replace(__p.index(), __i, __j); }voidreplace(const iterator& __p, const_iterator __i, const_iterator __j){ replace(__p.index(), __i, __j); }voidreplace(const iterator& __p, iterator __i, iterator __j){ replace(__p.index(), __i, __j); }// Iterator and range variants of eraseiteratorerase(const iterator& __p, const iterator& __q){size_t __p_index = __p.index();erase(__p_index, __q.index() - __p_index);return iterator(this, __p_index);}iteratorerase(const iterator& __p){size_t __p_index = __p.index();erase(__p_index, 1);return iterator(this, __p_index);}ropesubstr(size_t __start, size_t __len = 1) const{return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,__start,__start + __len));}ropesubstr(iterator __start, iterator __end) const{return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,__start.index(),__end.index()));}ropesubstr(iterator __start) const{size_t __pos = __start.index();return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,__pos, __pos + 1));}ropesubstr(const_iterator __start, const_iterator __end) const{// This might eventually take advantage of the cache in the// iterator.return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,__start.index(),__end.index()));}rope<_CharT, _Alloc>substr(const_iterator __start){size_t __pos = __start.index();return rope<_CharT, _Alloc>(_S_substring(this->_M_tree_ptr,__pos, __pos + 1));}static const size_type npos;size_type find(_CharT __c, size_type __pos = 0) const;size_typefind(const _CharT* __s, size_type __pos = 0) const{size_type __result_pos;const_iterator __result =std::search(const_begin() + __pos, const_end(),__s, __s + _S_char_ptr_len(__s));__result_pos = __result.index();
#ifndef __STL_OLD_ROPE_SEMANTICSif (__result_pos == size())__result_pos = npos;
#endifreturn __result_pos;}iteratormutable_begin(){ return(iterator(this, 0)); }iteratormutable_end(){ return(iterator(this, size())); }typedef std::reverse_iterator<iterator> reverse_iterator;reverse_iteratormutable_rbegin(){ return reverse_iterator(mutable_end()); }reverse_iteratormutable_rend(){ return reverse_iterator(mutable_begin()); }referencemutable_reference_at(size_type __pos){ return reference(this, __pos); }#ifdef __STD_STUFFreferenceoperator[] (size_type __pos){ return _char_ref_proxy(this, __pos); }referenceat(size_type __pos){// if (__pos >= size()) throw out_of_range;  // XXXreturn (*this)[__pos];}void resize(size_type __n, _CharT __c) { }void resize(size_type __n) { }void reserve(size_type __res_arg = 0) { }size_typecapacity() const{ return max_size(); }// Stuff below this line is dangerous because it's error prone.// I would really like to get rid of it.// copy function with funny arg ordering.size_typecopy(_CharT* __buffer, size_type __n,size_type __pos = 0) const{ return copy(__pos, __n, __buffer); }iteratorend(){ return mutable_end(); }iteratorbegin(){ return mutable_begin(); }reverse_iteratorrend(){ return mutable_rend(); }reverse_iteratorrbegin(){ return mutable_rbegin(); }#elseconst_iteratorend(){ return const_end(); }const_iteratorbegin(){ return const_begin(); }const_reverse_iteratorrend(){ return const_rend(); }const_reverse_iteratorrbegin(){ return const_rbegin(); }#endif};template <class _CharT, class _Alloc>const typename rope<_CharT, _Alloc>::size_typerope<_CharT, _Alloc>::npos = (size_type)(-1);template <class _CharT, class _Alloc>inline bool operator==(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return (__x._M_current_pos == __y._M_current_pos&& __x._M_root == __y._M_root); }template <class _CharT, class _Alloc>inline bool operator<(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return (__x._M_current_pos < __y._M_current_pos); }template <class _CharT, class _Alloc>inline bool operator!=(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return !(__x == __y); }template <class _CharT, class _Alloc>inline bool operator>(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return __y < __x; }template <class _CharT, class _Alloc>inline booloperator<=(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return !(__y < __x); }template <class _CharT, class _Alloc>inline booloperator>=(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return !(__x < __y); }template <class _CharT, class _Alloc>inline ptrdiff_toperator-(const _Rope_const_iterator<_CharT, _Alloc>& __x,const _Rope_const_iterator<_CharT, _Alloc>& __y){ return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; }template <class _CharT, class _Alloc>inline _Rope_const_iterator<_CharT, _Alloc>operator-(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n){ return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,__x._M_current_pos - __n); }template <class _CharT, class _Alloc>inline _Rope_const_iterator<_CharT, _Alloc>operator+(const _Rope_const_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n){ return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,__x._M_current_pos + __n); }template <class _CharT, class _Alloc>inline _Rope_const_iterator<_CharT, _Alloc>operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT, _Alloc>& __x){ return _Rope_const_iterator<_CharT, _Alloc>(__x._M_root,__x._M_current_pos + __n); }template <class _CharT, class _Alloc>inline booloperator==(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){return (__x._M_current_pos == __y._M_current_pos&& __x._M_root_rope == __y._M_root_rope); }template <class _CharT, class _Alloc>inline booloperator<(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return (__x._M_current_pos < __y._M_current_pos); }template <class _CharT, class _Alloc>inline booloperator!=(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return !(__x == __y); }template <class _CharT, class _Alloc>inline booloperator>(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return __y < __x; }template <class _CharT, class _Alloc>inline booloperator<=(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return !(__y < __x); }template <class _CharT, class _Alloc>inline booloperator>=(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return !(__x < __y); }template <class _CharT, class _Alloc>inline ptrdiff_toperator-(const _Rope_iterator<_CharT, _Alloc>& __x,const _Rope_iterator<_CharT, _Alloc>& __y){ return ((ptrdiff_t)__x._M_current_pos- (ptrdiff_t)__y._M_current_pos); }template <class _CharT, class _Alloc>inline _Rope_iterator<_CharT, _Alloc>operator-(const _Rope_iterator<_CharT, _Alloc>& __x,ptrdiff_t __n){ return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,__x._M_current_pos - __n); }template <class _CharT, class _Alloc>inline _Rope_iterator<_CharT, _Alloc>operator+(const _Rope_iterator<_CharT, _Alloc>& __x, ptrdiff_t __n){ return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,__x._M_current_pos + __n); }template <class _CharT, class _Alloc>inline _Rope_iterator<_CharT, _Alloc>operator+(ptrdiff_t __n, const _Rope_iterator<_CharT, _Alloc>& __x){ return _Rope_iterator<_CharT, _Alloc>(__x._M_root_rope,__x._M_current_pos + __n); }template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left,const rope<_CharT, _Alloc>& __right){// Inlining this should make it possible to keep __left and// __right in registers.typedef rope<_CharT, _Alloc> rope_type;return rope_type(rope_type::_S_concat(__left._M_tree_ptr, __right._M_tree_ptr));}template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>&operator+=(rope<_CharT, _Alloc>& __left,const rope<_CharT, _Alloc>& __right){__left.append(__right);return __left;}template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left,const _CharT* __right){typedef rope<_CharT, _Alloc> rope_type;size_t __rlen = rope_type::_S_char_ptr_len(__right);return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,__right, __rlen));}template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>&operator+=(rope<_CharT, _Alloc>& __left,const _CharT* __right){__left.append(__right);return __left;}template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>operator+(const rope<_CharT, _Alloc>& __left, _CharT __right){typedef rope<_CharT, _Alloc> rope_type;return rope_type(rope_type::_S_concat_char_iter(__left._M_tree_ptr,&__right, 1));}template <class _CharT, class _Alloc>inline rope<_CharT, _Alloc>&operator+=(rope<_CharT, _Alloc>& __left, _CharT __right){__left.append(__right);return __left;}template <class _CharT, class _Alloc>booloperator<(const rope<_CharT, _Alloc>& __left,const rope<_CharT, _Alloc>& __right){ return __left.compare(__right) < 0; }template <class _CharT, class _Alloc>booloperator==(const rope<_CharT, _Alloc>& __left,const rope<_CharT, _Alloc>& __right){ return __left.compare(__right) == 0; }template <class _CharT, class _Alloc>inline booloperator==(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y){ return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); }template <class _CharT, class _Alloc>inline booloperator!=(const rope<_CharT, _Alloc>& __x,const rope<_CharT, _Alloc>& __y){ return !(__x == __y); }template <class _CharT, class _Alloc>inline booloperator>(const rope<_CharT, _Alloc>& __x,const rope<_CharT, _Alloc>& __y){ return __y < __x; }template <class _CharT, class _Alloc>inline booloperator<=(const rope<_CharT, _Alloc>& __x,const rope<_CharT, _Alloc>& __y){ return !(__y < __x); }template <class _CharT, class _Alloc>inline booloperator>=(const rope<_CharT, _Alloc>& __x,const rope<_CharT, _Alloc>& __y){ return !(__x < __y); }template <class _CharT, class _Alloc>inline booloperator!=(const _Rope_char_ptr_proxy<_CharT, _Alloc>& __x,const _Rope_char_ptr_proxy<_CharT, _Alloc>& __y){ return !(__x == __y); }template<class _CharT, class _Traits, class _Alloc>std::basic_ostream<_CharT, _Traits>&operator<<(std::basic_ostream<_CharT, _Traits>& __o,const rope<_CharT, _Alloc>& __r);typedef rope<char> crope;typedef rope<wchar_t> wrope;inline crope::reference__mutable_reference_at(crope& __c, size_t __i){ return __c.mutable_reference_at(__i); }inline wrope::reference__mutable_reference_at(wrope& __c, size_t __i){ return __c.mutable_reference_at(__i); }template <class _CharT, class _Alloc>inline voidswap(rope<_CharT, _Alloc>& __x, rope<_CharT, _Alloc>& __y){ __x.swap(__y); }_GLIBCXX_END_NAMESPACE_VERSION
} // namespacenamespace std _GLIBCXX_VISIBILITY(default)
{
namespace tr1
{
_GLIBCXX_BEGIN_NAMESPACE_VERSIONtemplate<>struct hash<__gnu_cxx::crope>{size_toperator()(const __gnu_cxx::crope& __str) const{size_t __size = __str.size();if (0 == __size)return 0;return 13 * __str[0] + 5 * __str[__size - 1] + __size;}};template<>struct hash<__gnu_cxx::wrope>{size_toperator()(const __gnu_cxx::wrope& __str) const{size_t __size = __str.size();if (0 == __size)return 0;return 13 * __str[0] + 5 * __str[__size - 1] + __size;}};_GLIBCXX_END_NAMESPACE_VERSION
} // namespace tr1
} // namespace std# include <ext/ropeimpl.h>#endif

C++官方自带可持久化平衡树rope的3000行源码相关推荐

  1. HTML期末大作业~ 蓝色版爱宠之家(5个页面)带留言板宠物 学生网页设计作业源码(HTML+CSS+JS)

    HTML期末大作业~ 蓝色版爱宠之家(5个页面)带留言板宠物 学生网页设计作业源码(HTML+CSS+JS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从 ...

  2. STM32 无刷电机BLDC 1KW带刹开发板 PDF原理图 源代码 MDK源码

    STM32 无刷电机BLDC 1KW带刹开发板 PDF原理图 源代码 MDK源码 BLDC开发板配套资料,开发板功率最高达1000W,带刹车功能,PID速度闭环,驱动带霍尔直流无刷电机,资料含PDF原 ...

  3. HTML期末大作业~ 蓝色版爱宠之家(5个页面)带留言板宠物 学生网页设计作业源码(HTML+CSS+JS)...

    HTML期末大作业~ 蓝色版爱宠之家(5个页面)带留言板宠物 学生网页设计作业源码(HTML+CSS+JS) 临近期末, 你还在为HTML网页设计结课作业,老师的作业要求感到头大?HTML网页作业无从 ...

  4. 【Python项目】你们还在冲会员看电影电视剧嘛?Python带你免费看电影电视剧资源 | 附源码

    前言 halo,包子们晚上好 很久没有更新啦,主要是小编这边最近有点小忙 今天给大家实现一个视频播放器,可以看任何电影,电视剧,不要再为以后看电视看电影而烦恼啦,今天是福利文章,相信我绝对有用 相关文 ...

  5. 安卓带步骤的手写签名(附源码)

    之前写的一个带笔画记录功能的安卓画板,最近才有时间写个博客好好介绍一下,参考了一些博客,最后使用了 kotlin 实现的,虽然用起来很爽,可是过了一段时间再看自己都有点懵,还好当时留下的注释非常多,有 ...

  6. <整理总结>H264/265码流数据包格式分析(带mp4v2封装H264/265为MP4的源码示例)

    H264/265码流数据包格式分析 前言: 一.H.264码流解析 I帧P帧B帧说明: 二.H.265码流解析 三.主要源码 前言: 最近在学习使用MP4v2将H264/H265码流以及AAC音频封装 ...

  7. 【无需服务器】工具箱组合微信带流量主超多功能小程序源码

    带流量主超多功能工具箱组合微信小程序源码 多功能工具箱微信小程序源码,无需服务器即可搭建,可以设置流量主赚取收益 链接 网盘源码.zip - 蓝奏云 背景 随着人们生活水平的提高,智能手机已经成为了我 ...

  8. 服务器端配置正方教务系统,手把手带你打造一个教务系统客户端(附源码)

    本篇博客主要和大家分享编写一个学校教务系统的客户端版本,主要是关于登录以及数据获取方面,结尾还会附上本人以前编写的客户端源代码,有兴趣的可以自行下载玩耍~ 阅读本文大概需要5分钟. 前言 好久没有更新 ...

  9. 一个Demo带你手把手进行Docker开发(内涵源码和视频讲解)

    微软.NET20周年特别活动盛大开启,51Aspx联合微软官方打造了一场的"云原生开发挑战赛",在这里大家可以聆听大牛的直播讲座.进行现场互动..NET专家答疑解惑,还可报名参加. ...

最新文章

  1. c# hdf5 写string_聊一聊C#8.0中的 await foreach
  2. 图片html代码查看器,360度全景商品图片查看器
  3. 人脸识别躲不过一张3D面具,安全风险到底有多大?
  4. leetcode :动态规划
  5. Linux的概念与体系 6. Linux文本流(转载)
  6. Django admin 继承user表后密码为明文,继承UserAdmin,重写其方法
  7. 精选|2019年1月R新包推荐
  8. linux上apache的安装
  9. c语言一个偶数用两个素数表示,用C语言(C99) 验证哥德巴赫猜想:一个不小于6的偶数必定能表示为两个素数之和。...
  10. 【机器学习】信息熵基础学习
  11. Java架构师-容器化(一):服务容器化技术-Docker、Cloud Foundry
  12. 【时空序列预测实战】风险时空预测?keras之ConvLSTM实战来搞定
  13. 开源的杀毒软件--ClamWin
  14. 直线检测论文(霍夫变换,LSD,DWP,L-CNN,AFM,HAWP,PPGNet,TP-LSD,M-LSD,LETR)
  15. web移动端开发-将网站分享朋友圈、微信空间、朋友圈功能
  16. 排班算法 java_【算法】基于优先级的排班算法实现
  17. 大话铁道部12306订票系统云架构
  18. go语言并发下载电影和视频,根据m3u8索引url下载视频.下载网页中的图片,可以从当前页向下搜索层数.
  19. U盘安装系统时需要用到的快捷启动热键一览 欢迎补充
  20. Qt FFmpeg 音视频播放器

热门文章

  1. 深度理解目标检测(MMdetection)-HOOK机制
  2. 只用一张训练图像进行图像的恢复
  3. 聊聊这两年学习slam啃过的书!
  4. 浏览器从输入url到页面加载完成发生了什么
  5. 从find_vma和find_vma_prev看内核
  6. 斗争程序猿(三十八)——历史朝代大学(两)——我与数据库的故事
  7. CSS 最核心的几个概念
  8. iOS 5与iOS 6的 low-memory 处理(转自cocoaChina)
  9. 摩根上调 思科股票评级至增持
  10. 为何python攀上数据科学巅峰?调查显示Python超越R