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