/home/ntakagi/work/STLport-5.1.5/stlport/stl/_rope.hGo to the documentation of this file.00001 /* 00002 * 00003 * Copyright (c) 1996,1997 00004 * Silicon Graphics Computer Systems, Inc. 00005 * 00006 * Copyright (c) 1997 00007 * Moscow Center for SPARC Technology 00008 * 00009 * Copyright (c) 1999 00010 * Boris Fomitchev 00011 * 00012 * This material is provided "as is", with absolutely no warranty expressed 00013 * or implied. Any use is at your own risk. 00014 * 00015 * Permission to use or copy this software for any purpose is hereby granted 00016 * without fee, provided the above notices are retained on all copies. 00017 * Permission to modify the code and to distribute modified code is granted, 00018 * provided the above notices are retained, and a notice that the code was 00019 * modified is included with the above copyright notice. 00020 * 00021 */ 00022 00023 /* NOTE: This is an internal header file, included by other STL headers. 00024 * You should not attempt to use it directly. 00025 */ 00026 00027 // rope<_CharT,_Alloc> is a sequence of _CharT. 00028 // Ropes appear to be mutable, but update operations 00029 // really copy enough of the data structure to leave the original 00030 // valid. Thus ropes can be logically copied by just copying 00031 // a pointer value. 00032 00033 #ifndef _STLP_INTERNAL_ROPE_H 00034 #define _STLP_INTERNAL_ROPE_H 00035 00036 #ifndef _STLP_INTERNAL_ALGOBASE_H 00037 # include <stl/_algobase.h> 00038 #endif 00039 00040 #ifndef _STLP_IOSFWD 00041 # include <iosfwd> 00042 #endif 00043 00044 #ifndef _STLP_INTERNAL_ALLOC_H 00045 # include <stl/_alloc.h> 00046 #endif 00047 00048 #ifndef _STLP_INTERNAL_ITERATOR_H 00049 # include <stl/_iterator.h> 00050 #endif 00051 00052 #ifndef _STLP_INTERNAL_ALGO_H 00053 # include <stl/_algo.h> 00054 #endif 00055 00056 #ifndef _STLP_INTERNAL_FUNCTION_BASE_H 00057 # include <stl/_function_base.h> 00058 #endif 00059 00060 #ifndef _STLP_INTERNAL_NUMERIC_H 00061 # include <stl/_numeric.h> 00062 #endif 00063 00064 #ifndef _STLP_INTERNAL_HASH_FUN_H 00065 # include <stl/_hash_fun.h> 00066 #endif 00067 00068 #ifndef _STLP_CHAR_TRAITS_H 00069 # include <stl/char_traits.h> 00070 #endif 00071 00072 #ifndef _STLP_INTERNAL_THREADS_H 00073 # include <stl/_threads.h> 00074 #endif 00075 00076 #ifdef _STLP_SGI_THREADS 00077 # include <mutex.h> 00078 #endif 00079 00080 #ifndef _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE 00081 # define _STLP_CREATE_ALLOCATOR(__atype,__a, _Tp) (_Alloc_traits<_Tp,__atype>::create_allocator(__a)) 00082 #elif defined(__MRC__)||defined(__SC__) 00083 # define _STLP_CREATE_ALLOCATOR(__atype,__a, _Tp) __stl_alloc_create<_Tp,__atype>(__a,(_Tp*)0) 00084 #else 00085 # define _STLP_CREATE_ALLOCATOR(__atype,__a, _Tp) __stl_alloc_create(__a,(_Tp*)0) 00086 #endif 00087 00088 _STLP_BEGIN_NAMESPACE 00089 00090 // First a lot of forward declarations. The standard seems to require 00091 // much stricter "declaration before use" than many of the implementations 00092 // that preceded it. 00093 template<class _CharT, _STLP_DEFAULT_ALLOCATOR_SELECT(_CharT) > class rope; 00094 template<class _CharT, class _Alloc> struct _Rope_RopeConcatenation; 00095 template<class _CharT, class _Alloc> struct _Rope_RopeRep; 00096 template<class _CharT, class _Alloc> struct _Rope_RopeLeaf; 00097 template<class _CharT, class _Alloc> struct _Rope_RopeFunction; 00098 template<class _CharT, class _Alloc> struct _Rope_RopeSubstring; 00099 template<class _CharT, class _Alloc> class _Rope_iterator; 00100 template<class _CharT, class _Alloc> class _Rope_const_iterator; 00101 template<class _CharT, class _Alloc> class _Rope_char_ref_proxy; 00102 template<class _CharT, class _Alloc> class _Rope_char_ptr_proxy; 00103 00104 _STLP_MOVE_TO_PRIV_NAMESPACE 00105 00106 // Some helpers, so we can use the power algorithm on ropes. 00107 // See below for why this isn't local to the implementation. 00108 00109 // This uses a nonstandard refcount convention. 00110 // The result has refcount 0. 00111 template<class _CharT, class _Alloc> 00112 struct _Rope_Concat_fn 00113 : public binary_function<rope<_CharT,_Alloc>, rope<_CharT,_Alloc>, 00114 rope<_CharT,_Alloc> > { 00115 rope<_CharT,_Alloc> operator() (const rope<_CharT,_Alloc>& __x, 00116 const rope<_CharT,_Alloc>& __y) { 00117 return __x + __y; 00118 } 00119 }; 00120 00121 template <class _CharT, class _Alloc> 00122 inline 00123 rope<_CharT,_Alloc> 00124 __identity_element(_Rope_Concat_fn<_CharT, _Alloc>) 00125 { return rope<_CharT,_Alloc>(); } 00126 00127 _STLP_MOVE_TO_STD_NAMESPACE 00128 00129 // Store an eos 00130 template <class _CharT> 00131 inline void _S_construct_null_aux(_CharT *__p, const __true_type&) 00132 { *__p = 0; } 00133 00134 template <class _CharT> 00135 inline void _S_construct_null_aux(_CharT *__p, const __false_type&) 00136 { _STLP_STD::_Construct(__p); } 00137 00138 template <class _CharT> 00139 inline void _S_construct_null(_CharT *__p) { 00140 typedef typename _IsIntegral<_CharT>::_Ret _Char_Is_Integral; 00141 _S_construct_null_aux(__p, _Char_Is_Integral()); 00142 } 00143 00144 // char_producers are logically functions that generate a section of 00145 // a string. These can be converted to ropes. The resulting rope 00146 // invokes the char_producer on demand. This allows, for example, 00147 // files to be viewed as ropes without reading the entire file. 00148 template <class _CharT> 00149 class char_producer { 00150 public: 00151 virtual ~char_producer() {} 00152 virtual void operator()(size_t __start_pos, size_t __len, 00153 _CharT* __buffer) = 0; 00154 // Buffer should really be an arbitrary output iterator. 00155 // That way we could flatten directly into an ostream, etc. 00156 // This is thoroughly impossible, since iterator types don't 00157 // have runtime descriptions. 00158 }; 00159 00160 // Sequence buffers: 00161 // 00162 // Sequence must provide an append operation that appends an 00163 // array to the sequence. Sequence buffers are useful only if 00164 // appending an entire array is cheaper than appending element by element. 00165 // This is true for many string representations. 00166 // This should perhaps inherit from ostream<sequence::value_type> 00167 // and be implemented correspondingly, so that they can be used 00168 // for formatted. For the sake of portability, we don't do this yet. 00169 // 00170 // For now, sequence buffers behave as output iterators. But they also 00171 // behave a little like basic_ostringstream<sequence::value_type> and a 00172 // little like containers. 00173 00174 template<class _Sequence 00175 # if !(defined (_STLP_NON_TYPE_TMPL_PARAM_BUG) || \ 00176 defined ( _STLP_NO_DEFAULT_NON_TYPE_PARAM )) 00177 , size_t _Buf_sz = 100 00178 # if defined(__sgi) && !defined(__GNUC__) 00179 # define __TYPEDEF_WORKAROUND 00180 ,class _V = typename _Sequence::value_type 00181 # endif /* __sgi */ 00182 # endif /* _STLP_NON_TYPE_TMPL_PARAM_BUG */ 00183 > 00184 // The 3rd parameter works around a common compiler bug. 00185 class sequence_buffer : public iterator <output_iterator_tag, void, void, void, void> { 00186 public: 00187 # ifndef __TYPEDEF_WORKAROUND 00188 typedef typename _Sequence::value_type value_type; 00189 typedef sequence_buffer<_Sequence 00190 # if !(defined (_STLP_NON_TYPE_TMPL_PARAM_BUG) || \ 00191 defined ( _STLP_NO_DEFAULT_NON_TYPE_PARAM )) 00192 , _Buf_sz 00193 > _Self; 00194 # else /* _STLP_NON_TYPE_TMPL_PARAM_BUG */ 00195 > _Self; 00196 enum { _Buf_sz = 100}; 00197 # endif /* _STLP_NON_TYPE_TMPL_PARAM_BUG */ 00198 // # endif 00199 # else /* __TYPEDEF_WORKAROUND */ 00200 typedef _V value_type; 00201 typedef sequence_buffer<_Sequence, _Buf_sz, _V> _Self; 00202 # endif /* __TYPEDEF_WORKAROUND */ 00203 protected: 00204 _Sequence* _M_prefix; 00205 value_type _M_buffer[_Buf_sz]; 00206 size_t _M_buf_count; 00207 public: 00208 void flush() { 00209 _M_prefix->append(_M_buffer, _M_buffer + _M_buf_count); 00210 _M_buf_count = 0; 00211 } 00212 ~sequence_buffer() { flush(); } 00213 sequence_buffer() : _M_prefix(0), _M_buf_count(0) {} 00214 sequence_buffer(const _Self& __x) { 00215 _M_prefix = __x._M_prefix; 00216 _M_buf_count = __x._M_buf_count; 00217 copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer); 00218 } 00219 sequence_buffer(_Self& __x) { 00220 __x.flush(); 00221 _M_prefix = __x._M_prefix; 00222 _M_buf_count = 0; 00223 } 00224 sequence_buffer(_Sequence& __s) : _M_prefix(&__s), _M_buf_count(0) {} 00225 _Self& operator= (_Self& __x) { 00226 __x.flush(); 00227 _M_prefix = __x._M_prefix; 00228 _M_buf_count = 0; 00229 return *this; 00230 } 00231 _Self& operator= (const _Self& __x) { 00232 _M_prefix = __x._M_prefix; 00233 _M_buf_count = __x._M_buf_count; 00234 copy(__x._M_buffer, __x._M_buffer + __x._M_buf_count, _M_buffer); 00235 return *this; 00236 } 00237 void push_back(value_type __x) { 00238 if (_M_buf_count < _Buf_sz) { 00239 _M_buffer[_M_buf_count] = __x; 00240 ++_M_buf_count; 00241 } else { 00242 flush(); 00243 _M_buffer[0] = __x; 00244 _M_buf_count = 1; 00245 } 00246 } 00247 void append(const value_type *__s, size_t __len) { 00248 if (__len + _M_buf_count <= _Buf_sz) { 00249 size_t __i = _M_buf_count; 00250 size_t __j = 0; 00251 for (; __j < __len; __i++, __j++) { 00252 _M_buffer[__i] = __s[__j]; 00253 } 00254 _M_buf_count += __len; 00255 } else if (0 == _M_buf_count) { 00256 _M_prefix->append(__s, __s + __len); 00257 } else { 00258 flush(); 00259 append(__s, __len); 00260 } 00261 } 00262 _Self& write(const value_type *__s, size_t __len) { 00263 append(__s, __len); 00264 return *this; 00265 } 00266 _Self& put(value_type __x) { 00267 push_back(__x); 00268 return *this; 00269 } 00270 _Self& operator=(const value_type& __rhs) { 00271 push_back(__rhs); 00272 return *this; 00273 } 00274 _Self& operator*() { return *this; } 00275 _Self& operator++() { return *this; } 00276 _Self& operator++(int) { return *this; } 00277 }; 00278 00279 // The following should be treated as private, at least for now. 00280 template<class _CharT> 00281 class _Rope_char_consumer { 00282 #if !defined (_STLP_MEMBER_TEMPLATES) 00283 public: 00284 //Without member templates we have to use run-time parameterization. 00285 // The symmetry with char_producer is accidental and temporary. 00286 virtual ~_Rope_char_consumer() {} 00287 virtual bool operator()(const _CharT* __buffer, size_t __len) = 0; 00288 #endif 00289 }; 00290 00291 // 00292 // What follows should really be local to rope. Unfortunately, 00293 // that doesn't work, since it makes it impossible to define generic 00294 // equality on rope iterators. According to the draft standard, the 00295 // template parameters for such an equality operator cannot be inferred 00296 // from the occurence of a member class as a parameter. 00297 // (SGI compilers in fact allow this, but the __result wouldn't be 00298 // portable.) 00299 // Similarly, some of the static member functions are member functions 00300 // only to avoid polluting the global namespace, and to circumvent 00301 // restrictions on type inference for template functions. 00302 // 00303 00304 // 00305 // The internal data structure for representing a rope. This is 00306 // private to the implementation. A rope is really just a pointer 00307 // to one of these. 00308 // 00309 // A few basic functions for manipulating this data structure 00310 // are members of _RopeRep. Most of the more complex algorithms 00311 // are implemented as rope members. 00312 // 00313 // Some of the static member functions of _RopeRep have identically 00314 // named functions in rope that simply invoke the _RopeRep versions. 00315 // 00316 00317 template<class _CharT, class _Alloc> 00318 struct _Rope_RopeRep 00319 : public _Refcount_Base 00320 { 00321 typedef _Rope_RopeRep<_CharT, _Alloc> _Self; 00322 public: 00323 // 00324 // GAB: 11/09/05 00325 // 00326 // "__ROPE_DEPTH_SIZE" is set to one more then the "__ROPE_MAX_DEPTH". 00327 // This was originally just an addition of "__ROPE_MAX_DEPTH + 1" 00328 // but this addition causes the sunpro compiler to complain about 00329 // multiple declarations during the initialization of "_S_min_len". 00330 // Changed to be a fixed value and the sunpro compiler appears to 00331 // be happy??? 00332 // 00333 # define __ROPE_MAX_DEPTH 45 00334 # define __ROPE_DEPTH_SIZE 46 // __ROPE_MAX_DEPTH + 1 00335 enum { _S_max_rope_depth = __ROPE_MAX_DEPTH }; 00336 enum _Tag {_S_leaf, _S_concat, _S_substringfn, _S_function}; 00337 // Apparently needed by VC++ 00338 // The data fields of leaves are allocated with some 00339 // extra space, to accomodate future growth and for basic 00340 // character types, to hold a trailing eos character. 00341 enum { _S_alloc_granularity = 8 }; 00342 00343 _Tag _M_tag:8; 00344 bool _M_is_balanced:8; 00345 00346 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 00347 typedef typename _Alloc_traits<_CharT,_Alloc>::allocator_type allocator_type; 00348 00349 allocator_type get_allocator() const { return allocator_type(_M_size); } 00350 00351 unsigned char _M_depth; 00352 _CharT* _STLP_VOLATILE _M_c_string; 00353 _STLP_PRIV _STLP_alloc_proxy<size_t, _CharT, allocator_type> _M_size; 00354 00355 # ifdef _STLP_NO_ARROW_OPERATOR 00356 _Rope_RopeRep() : _Refcount_Base(1), _M_size(allocator_type(), 0) {} 00357 # endif 00358 00359 /* Flattened version of string, if needed. */ 00360 /* typically 0. */ 00361 /* If it's not 0, then the memory is owned */ 00362 /* by this node. */ 00363 /* In the case of a leaf, this may point to */ 00364 /* the same memory as the data field. */ 00365 _Rope_RopeRep(_Tag __t, unsigned char __d, bool __b, size_t _p_size, 00366 allocator_type __a) : 00367 _Refcount_Base(1), 00368 _M_tag(__t), _M_is_balanced(__b), _M_depth(__d), _M_c_string(0), _M_size(__a, _p_size) 00369 { } 00370 00371 typedef typename _AreSameUnCVTypes<_CharT, char>::_Ret _IsChar; 00372 # ifdef _STLP_HAS_WCHAR_T 00373 typedef typename _AreSameUnCVTypes<_CharT, wchar_t>::_Ret _IsWCharT; 00374 # else 00375 typedef __false_type _IsWCharT; 00376 # endif 00377 00378 typedef typename _Lor2<_IsChar, _IsWCharT>::_Ret _IsBasicCharType; 00379 00380 #if 0 00381 /* Please tell why this code is necessary if you uncomment it. 00382 * Problem with it is that rope implementation expect that _S_rounded_up_size(n) 00383 * returns a size > n in order to store the terminating null charater. When 00384 * instanciation type is not a char or wchar_t this is not guaranty resulting in 00385 * memory overrun. 00386 */ 00387 static size_t _S_rounded_up_size_aux(size_t __n, __true_type const& /*_IsBasicCharType*/) { 00388 // Allow slop for in-place expansion. 00389 return (__n + _S_alloc_granularity) & ~(_S_alloc_granularity - 1); 00390 } 00391 00392 static size_t _S_rounded_up_size_aux(size_t __n, __false_type const& /*_IsBasicCharType*/) { 00393 // Allow slop for in-place expansion. 00394 return (__n + _S_alloc_granularity - 1) & ~(_S_alloc_granularity - 1); 00395 } 00396 #endif 00397 // fbp : moved from RopeLeaf 00398 static size_t _S_rounded_up_size(size_t __n) 00399 //{ return _S_rounded_up_size_aux(__n, _IsBasicCharType()); } 00400 { return (__n + _S_alloc_granularity) & ~(_S_alloc_granularity - 1); } 00401 00402 static void _S_free_string( _CharT* __s, size_t __len, 00403 allocator_type __a) { 00404 _STLP_STD::_Destroy_Range(__s, __s + __len); 00405 // This has to be a static member, so this gets a bit messy 00406 # ifndef _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE 00407 __a.deallocate(__s, _S_rounded_up_size(__len)); //*ty 03/24/2001 - restored not to use __stl_alloc_rebind() since it is not defined under _STLP_MEMBER_TEMPLATE_CLASSES 00408 # else 00409 __stl_alloc_rebind (__a, (_CharT*)0).deallocate(__s, _S_rounded_up_size(__len)); 00410 # endif 00411 } 00412 00413 // Deallocate data section of a leaf. 00414 // This shouldn't be a member function. 00415 // But its hard to do anything else at the 00416 // moment, because it's templatized w.r.t. 00417 // an allocator. 00418 // Does nothing if __GC is defined. 00419 void _M_free_c_string(); 00420 void _M_free_tree(); 00421 // Deallocate t. Assumes t is not 0. 00422 void _M_unref_nonnil() { 00423 if (_M_decr() == 0) _M_free_tree(); 00424 } 00425 void _M_ref_nonnil() { 00426 _M_incr(); 00427 } 00428 static void _S_unref(_Self* __t) { 00429 if (0 != __t) { 00430 __t->_M_unref_nonnil(); 00431 } 00432 } 00433 static void _S_ref(_Self* __t) { 00434 if (0 != __t) __t->_M_incr(); 00435 } 00436 //static void _S_free_if_unref(_Self* __t) { 00437 // if (0 != __t && 0 == __t->_M_ref_count) __t->_M_free_tree(); 00438 //} 00439 }; 00440 00441 template<class _CharT, class _Alloc> 00442 struct _Rope_RopeLeaf : public _Rope_RopeRep<_CharT,_Alloc> { 00443 public: 00444 _CharT* _M_data; /* Not necessarily 0 terminated. */ 00445 /* The allocated size is */ 00446 /* _S_rounded_up_size(size), except */ 00447 /* in the GC case, in which it */ 00448 /* doesn't matter. */ 00449 private: 00450 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00451 typedef typename _RopeRep::_IsBasicCharType _IsBasicCharType; 00452 void _M_init(__true_type const& /*_IsBasicCharType*/) { 00453 this->_M_c_string = _M_data; 00454 } 00455 void _M_init(__false_type const& /*_IsBasicCharType*/) {} 00456 00457 public: 00458 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 00459 typedef typename _RopeRep::allocator_type allocator_type; 00460 00461 _Rope_RopeLeaf( _CharT* __d, size_t _p_size, allocator_type __a) 00462 : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_leaf, 0, true, _p_size, __a), 00463 _M_data(__d) { 00464 _STLP_ASSERT(_p_size > 0) 00465 _M_init(_IsBasicCharType()); 00466 } 00467 00468 # ifdef _STLP_NO_ARROW_OPERATOR 00469 _Rope_RopeLeaf() {} 00470 _Rope_RopeLeaf(const _Rope_RopeLeaf<_CharT, _Alloc>& ) {} 00471 # endif 00472 00473 // The constructor assumes that d has been allocated with 00474 // the proper allocator and the properly padded size. 00475 // In contrast, the destructor deallocates the data: 00476 ~_Rope_RopeLeaf() { 00477 if (_M_data != this->_M_c_string) { 00478 this->_M_free_c_string(); 00479 } 00480 _RopeRep::_S_free_string(_M_data, this->_M_size._M_data, this->get_allocator()); 00481 } 00482 }; 00483 00484 template<class _CharT, class _Alloc> 00485 struct _Rope_RopeConcatenation : public _Rope_RopeRep<_CharT, _Alloc> { 00486 private: 00487 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00488 00489 public: 00490 _RopeRep* _M_left; 00491 _RopeRep* _M_right; 00492 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 00493 typedef typename _RopeRep::allocator_type allocator_type; 00494 _Rope_RopeConcatenation(_RopeRep* __l, _RopeRep* __r, allocator_type __a) 00495 : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_concat, 00496 (max)(__l->_M_depth, __r->_M_depth) + 1, false, 00497 __l->_M_size._M_data + __r->_M_size._M_data, __a), _M_left(__l), _M_right(__r) 00498 {} 00499 # ifdef _STLP_NO_ARROW_OPERATOR 00500 _Rope_RopeConcatenation() {} 00501 _Rope_RopeConcatenation(const _Rope_RopeConcatenation<_CharT, _Alloc>&) {} 00502 # endif 00503 00504 ~_Rope_RopeConcatenation() { 00505 this->_M_free_c_string(); 00506 _M_left->_M_unref_nonnil(); 00507 _M_right->_M_unref_nonnil(); 00508 } 00509 }; 00510 00511 template <class _CharT, class _Alloc> 00512 struct _Rope_RopeFunction : public _Rope_RopeRep<_CharT, _Alloc> { 00513 private: 00514 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00515 public: 00516 char_producer<_CharT>* _M_fn; 00517 /* 00518 * Char_producer is owned by the 00519 * rope and should be explicitly 00520 * deleted when the rope becomes 00521 * inaccessible. 00522 */ 00523 bool _M_delete_when_done; 00524 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 00525 typedef typename _Rope_RopeRep<_CharT,_Alloc>::allocator_type allocator_type; 00526 # ifdef _STLP_NO_ARROW_OPERATOR 00527 _Rope_RopeFunction() {} 00528 _Rope_RopeFunction(const _Rope_RopeFunction<_CharT, _Alloc>& ) {} 00529 # endif 00530 00531 _Rope_RopeFunction(char_producer<_CharT>* __f, size_t _p_size, 00532 bool __d, allocator_type __a) 00533 : _Rope_RopeRep<_CharT,_Alloc>(_RopeRep::_S_function, 0, true, _p_size, __a), _M_fn(__f) 00534 , _M_delete_when_done(__d) 00535 { _STLP_ASSERT(_p_size > 0) } 00536 00537 ~_Rope_RopeFunction() { 00538 this->_M_free_c_string(); 00539 if (_M_delete_when_done) { 00540 delete _M_fn; 00541 } 00542 } 00543 }; 00544 00545 /* 00546 * Substring results are usually represented using just 00547 * concatenation nodes. But in the case of very long flat ropes 00548 * or ropes with a functional representation that isn't practical. 00549 * In that case, we represent the __result as a special case of 00550 * RopeFunction, whose char_producer points back to the rope itself. 00551 * In all cases except repeated substring operations and 00552 * deallocation, we treat the __result as a RopeFunction. 00553 */ 00554 template<class _CharT, class _Alloc> 00555 struct _Rope_RopeSubstring : public char_producer<_CharT>, public _Rope_RopeFunction<_CharT,_Alloc> { 00556 public: 00557 // XXX this whole class should be rewritten. 00558 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00559 _RopeRep *_M_base; // not 0 00560 size_t _M_start; 00561 /* virtual */ void operator()(size_t __start_pos, size_t __req_len, 00562 _CharT* __buffer) { 00563 typedef _Rope_RopeFunction<_CharT,_Alloc> _RopeFunction; 00564 typedef _Rope_RopeLeaf<_CharT,_Alloc> _RopeLeaf; 00565 switch (_M_base->_M_tag) { 00566 case _RopeRep::_S_function: 00567 case _RopeRep::_S_substringfn: 00568 { 00569 char_producer<_CharT>* __fn = 00570 __STATIC_CAST(_RopeFunction*, _M_base)->_M_fn; 00571 _STLP_ASSERT(__start_pos + __req_len <= this->_M_size._M_data) 00572 _STLP_ASSERT(_M_start + this->_M_size._M_data <= _M_base->_M_size._M_data) 00573 (*__fn)(__start_pos + _M_start, __req_len, __buffer); 00574 } 00575 break; 00576 case _RopeRep::_S_leaf: 00577 { 00578 _CharT* __s = 00579 __STATIC_CAST(_RopeLeaf*, _M_base)->_M_data; 00580 _STLP_PRIV __ucopy_n(__s + __start_pos + _M_start, __req_len, __buffer); 00581 } 00582 break; 00583 default: 00584 _STLP_ASSERT(false) 00585 ; 00586 } 00587 } 00588 00589 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 00590 typedef typename _RopeRep::allocator_type allocator_type; 00591 00592 _Rope_RopeSubstring(_RopeRep* __b, size_t __s, size_t __l, allocator_type __a) 00593 : _Rope_RopeFunction<_CharT,_Alloc>(this, __l, false, __a), 00594 _M_base(__b), _M_start(__s) { 00595 _STLP_ASSERT(__l > 0) 00596 _STLP_ASSERT(__s + __l <= __b->_M_size._M_data) 00597 _M_base->_M_ref_nonnil(); 00598 this->_M_tag = _RopeRep::_S_substringfn; 00599 } 00600 virtual ~_Rope_RopeSubstring() 00601 { _M_base->_M_unref_nonnil(); } 00602 }; 00603 00604 /* 00605 * Self-destructing pointers to Rope_rep. 00606 * These are not conventional smart pointers. Their 00607 * only purpose in life is to ensure that unref is called 00608 * on the pointer either at normal exit or if an exception 00609 * is raised. It is the caller's responsibility to 00610 * adjust reference counts when these pointers are initialized 00611 * or assigned to. (This convention significantly reduces 00612 * the number of potentially expensive reference count 00613 * updates.) 00614 */ 00615 template<class _CharT, class _Alloc> 00616 struct _Rope_self_destruct_ptr { 00617 _Rope_RopeRep<_CharT,_Alloc>* _M_ptr; 00618 ~_Rope_self_destruct_ptr() 00619 { _Rope_RopeRep<_CharT,_Alloc>::_S_unref(_M_ptr); } 00620 # ifdef _STLP_USE_EXCEPTIONS 00621 _Rope_self_destruct_ptr() : _M_ptr(0) {} 00622 # else 00623 _Rope_self_destruct_ptr() {} 00624 # endif 00625 _Rope_self_destruct_ptr(_Rope_RopeRep<_CharT,_Alloc>* __p) : _M_ptr(__p) {} 00626 _Rope_RopeRep<_CharT,_Alloc>& operator*() { return *_M_ptr; } 00627 _Rope_RopeRep<_CharT,_Alloc>* operator->() { return _M_ptr; } 00628 operator _Rope_RopeRep<_CharT,_Alloc>*() { return _M_ptr; } 00629 _Rope_self_destruct_ptr<_CharT, _Alloc>& 00630 operator= (_Rope_RopeRep<_CharT,_Alloc>* __x) 00631 { _M_ptr = __x; return *this; } 00632 }; 00633 00634 /* 00635 * Dereferencing a nonconst iterator has to return something 00636 * that behaves almost like a reference. It's not possible to 00637 * return an actual reference since assignment requires extra 00638 * work. And we would get into the same problems as with the 00639 * CD2 version of basic_string. 00640 */ 00641 template<class _CharT, class _Alloc> 00642 class _Rope_char_ref_proxy { 00643 typedef _Rope_char_ref_proxy<_CharT, _Alloc> _Self; 00644 friend class rope<_CharT,_Alloc>; 00645 friend class _Rope_iterator<_CharT,_Alloc>; 00646 friend class _Rope_char_ptr_proxy<_CharT,_Alloc>; 00647 typedef _Rope_self_destruct_ptr<_CharT,_Alloc> _Self_destruct_ptr; 00648 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00649 typedef rope<_CharT,_Alloc> _My_rope; 00650 size_t _M_pos; 00651 _CharT _M_current; 00652 bool _M_current_valid; 00653 _My_rope* _M_root; // The whole rope. 00654 public: 00655 _Rope_char_ref_proxy(_My_rope* __r, size_t __p) : 00656 _M_pos(__p), _M_current_valid(false), _M_root(__r) {} 00657 _Rope_char_ref_proxy(const _Self& __x) : 00658 _M_pos(__x._M_pos), _M_current_valid(false), _M_root(__x._M_root) {} 00659 // Don't preserve cache if the reference can outlive the 00660 // expression. We claim that's not possible without calling 00661 // a copy constructor or generating reference to a proxy 00662 // reference. We declare the latter to have undefined semantics. 00663 _Rope_char_ref_proxy(_My_rope* __r, size_t __p, _CharT __c) 00664 : _M_pos(__p), _M_current(__c), _M_current_valid(true), _M_root(__r) {} 00665 inline operator _CharT () const; 00666 _Self& operator= (_CharT __c); 00667 _Rope_char_ptr_proxy<_CharT, _Alloc> operator& () const; 00668 _Self& operator= (const _Self& __c) { 00669 return operator=((_CharT)__c); 00670 } 00671 }; 00672 00673 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER 00674 template<class _CharT, class __Alloc> 00675 inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a, 00676 _Rope_char_ref_proxy <_CharT, __Alloc > __b) { 00677 _CharT __tmp = __a; 00678 __a = __b; 00679 __b = __tmp; 00680 } 00681 #else 00682 // There is no really acceptable way to handle this. The default 00683 // definition of swap doesn't work for proxy references. 00684 // It can't really be made to work, even with ugly hacks, since 00685 // the only unusual operation it uses is the copy constructor, which 00686 // is needed for other purposes. We provide a macro for 00687 // full specializations, and instantiate the most common case. 00688 # define _ROPE_SWAP_SPECIALIZATION(_CharT, __Alloc) \ 00689 inline void swap(_Rope_char_ref_proxy <_CharT, __Alloc > __a, \ 00690 _Rope_char_ref_proxy <_CharT, __Alloc > __b) { \ 00691 _CharT __tmp = __a; \ 00692 __a = __b; \ 00693 __b = __tmp; \ 00694 } 00695 00696 _ROPE_SWAP_SPECIALIZATION(char,_STLP_DEFAULT_ALLOCATOR(char) ) 00697 00698 # ifndef _STLP_NO_WCHAR_T 00699 _ROPE_SWAP_SPECIALIZATION(wchar_t,_STLP_DEFAULT_ALLOCATOR(wchar_t) ) 00700 # endif 00701 00702 #endif /* !_STLP_FUNCTION_TMPL_PARTIAL_ORDER */ 00703 00704 template<class _CharT, class _Alloc> 00705 class _Rope_char_ptr_proxy { 00706 // XXX this class should be rewritten. 00707 public: 00708 typedef _Rope_char_ptr_proxy<_CharT, _Alloc> _Self; 00709 friend class _Rope_char_ref_proxy<_CharT,_Alloc>; 00710 size_t _M_pos; 00711 rope<_CharT,_Alloc>* _M_root; // The whole rope. 00712 00713 _Rope_char_ptr_proxy(const _Rope_char_ref_proxy<_CharT,_Alloc>& __x) 00714 : _M_pos(__x._M_pos), _M_root(__x._M_root) {} 00715 _Rope_char_ptr_proxy(const _Self& __x) 00716 : _M_pos(__x._M_pos), _M_root(__x._M_root) {} 00717 _Rope_char_ptr_proxy() {} 00718 _Rope_char_ptr_proxy(_CharT* __x) : _M_pos(0), _M_root(0) { 00719 _STLP_ASSERT(0 == __x) 00720 } 00721 _Self& operator= (const _Self& __x) { 00722 _M_pos = __x._M_pos; 00723 _M_root = __x._M_root; 00724 return *this; 00725 } 00726 00727 _Rope_char_ref_proxy<_CharT,_Alloc> operator*() const { 00728 return _Rope_char_ref_proxy<_CharT,_Alloc>(_M_root, _M_pos); 00729 } 00730 }; 00731 00732 00733 /* 00734 * Rope iterators: 00735 * Unlike in the C version, we cache only part of the stack 00736 * for rope iterators, since they must be efficiently copyable. 00737 * When we run out of cache, we have to reconstruct the iterator 00738 * value. 00739 * Pointers from iterators are not included in reference counts. 00740 * Iterators are assumed to be thread private. Ropes can 00741 * be shared. 00742 */ 00743 template<class _CharT, class _Alloc> 00744 class _Rope_iterator_base 00745 /* : public random_access_iterator<_CharT, ptrdiff_t> */ 00746 { 00747 friend class rope<_CharT,_Alloc>; 00748 typedef _Rope_iterator_base<_CharT, _Alloc> _Self; 00749 typedef _Rope_RopeConcatenation<_CharT,_Alloc> _RopeConcat; 00750 public: 00751 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00752 00753 enum { _S_path_cache_len = 4 }; // Must be <= 9 because of _M_path_direction. 00754 enum { _S_iterator_buf_len = 15 }; 00755 size_t _M_current_pos; 00756 // The whole rope. 00757 _RopeRep* _M_root; 00758 // Starting position for current leaf 00759 size_t _M_leaf_pos; 00760 // Buffer possibly containing current char. 00761 _CharT* _M_buf_start; 00762 // Pointer to current char in buffer, != 0 ==> buffer valid. 00763 _CharT* _M_buf_ptr; 00764 // One past __last valid char in buffer. 00765 _CharT* _M_buf_end; 00766 00767 // What follows is the path cache. We go out of our 00768 // way to make this compact. 00769 // Path_end contains the bottom section of the path from 00770 // the root to the current leaf. 00771 struct { 00772 # if defined (__BORLANDC__) && (__BORLANDC__ < 0x560) 00773 _RopeRep const*_M_data[4]; 00774 # else 00775 _RopeRep const*_M_data[_S_path_cache_len]; 00776 # endif 00777 } _M_path_end; 00778 // Last valid __pos in path_end; 00779 // _M_path_end[0] ... _M_path_end[_M_leaf_index-1] 00780 // point to concatenation nodes. 00781 int _M_leaf_index; 00782 // (_M_path_directions >> __i) & 1 is 1 00783 // if we got from _M_path_end[leaf_index - __i - 1] 00784 // to _M_path_end[leaf_index - __i] by going to the 00785 // __right. Assumes path_cache_len <= 9. 00786 unsigned char _M_path_directions; 00787 // Short buffer for surrounding chars. 00788 // This is useful primarily for 00789 // RopeFunctions. We put the buffer 00790 // here to avoid locking in the 00791 // multithreaded case. 00792 // The cached path is generally assumed to be valid 00793 // only if the buffer is valid. 00794 struct { 00795 # if defined (__BORLANDC__) && (__BORLANDC__ < 0x560) 00796 _CharT _M_data[15]; 00797 # else 00798 _CharT _M_data[_S_iterator_buf_len]; 00799 # endif 00800 } _M_tmp_buf; 00801 00802 // Set buffer contents given path cache. 00803 static void _S_setbuf(_Rope_iterator_base<_CharT, _Alloc>& __x); 00804 // Set buffer contents and path cache. 00805 static void _S_setcache(_Rope_iterator_base<_CharT, _Alloc>& __x); 00806 // As above, but assumes path cache is valid for previous posn. 00807 static void _S_setcache_for_incr(_Rope_iterator_base<_CharT, _Alloc>& __x); 00808 _Rope_iterator_base() {} 00809 _Rope_iterator_base(_RopeRep* __root, size_t __pos) 00810 : _M_current_pos(__pos),_M_root(__root), _M_buf_ptr(0) {} 00811 void _M_incr(size_t __n); 00812 void _M_decr(size_t __n); 00813 public: 00814 size_t index() const { return _M_current_pos; } 00815 private: 00816 void _M_copy_buf(const _Self& __x) { 00817 _M_tmp_buf = __x._M_tmp_buf; 00818 if (__x._M_buf_start == __x._M_tmp_buf._M_data) { 00819 _M_buf_start = _M_tmp_buf._M_data; 00820 _M_buf_end = _M_buf_start + (__x._M_buf_end - __x._M_buf_start); 00821 _M_buf_ptr = _M_buf_start + (__x._M_buf_ptr - __x._M_buf_start); 00822 } else { 00823 _M_buf_end = __x._M_buf_end; 00824 } 00825 } 00826 00827 public: 00828 _Rope_iterator_base(const _Self& __x) : 00829 _M_current_pos(__x._M_current_pos), 00830 _M_root(__x._M_root), 00831 _M_leaf_pos( __x._M_leaf_pos ), 00832 _M_buf_start(__x._M_buf_start), 00833 _M_buf_ptr(__x._M_buf_ptr), 00834 _M_path_end(__x._M_path_end), 00835 _M_leaf_index(__x._M_leaf_index), 00836 _M_path_directions(__x._M_path_directions) 00837 { 00838 if (0 != __x._M_buf_ptr) { 00839 _M_copy_buf(__x); 00840 } 00841 } 00842 _Self& operator = (const _Self& __x) 00843 { 00844 _M_current_pos = __x._M_current_pos; 00845 _M_root = __x._M_root; 00846 _M_buf_start = __x._M_buf_start; 00847 _M_buf_ptr = __x._M_buf_ptr; 00848 _M_path_end = __x._M_path_end; 00849 _M_leaf_index = __x._M_leaf_index; 00850 _M_path_directions = __x._M_path_directions; 00851 _M_leaf_pos = __x._M_leaf_pos; 00852 if (0 != __x._M_buf_ptr) { 00853 _M_copy_buf(__x); 00854 } 00855 return *this; 00856 } 00857 }; 00858 00859 template<class _CharT, class _Alloc> class _Rope_iterator; 00860 00861 template<class _CharT, class _Alloc> 00862 class _Rope_const_iterator : public _Rope_iterator_base<_CharT,_Alloc> { 00863 friend class rope<_CharT,_Alloc>; 00864 typedef _Rope_const_iterator<_CharT, _Alloc> _Self; 00865 typedef _Rope_iterator_base<_CharT,_Alloc> _Base; 00866 // protected: 00867 public: 00868 # ifndef _STLP_HAS_NO_NAMESPACES 00869 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00870 // The one from the base class may not be directly visible. 00871 # endif 00872 _Rope_const_iterator(const _RopeRep* __root, size_t __pos): 00873 _Rope_iterator_base<_CharT,_Alloc>(__CONST_CAST(_RopeRep*,__root), __pos) 00874 // Only nonconst iterators modify root ref count 00875 {} 00876 public: 00877 typedef _CharT reference; // Really a value. Returning a reference 00878 // Would be a mess, since it would have 00879 // to be included in refcount. 00880 typedef const _CharT* pointer; 00881 typedef _CharT value_type; 00882 typedef ptrdiff_t difference_type; 00883 typedef random_access_iterator_tag iterator_category; 00884 00885 public: 00886 _Rope_const_iterator() {} 00887 _Rope_const_iterator(const _Self& __x) : 00888 _Rope_iterator_base<_CharT,_Alloc>(__x) { } 00889 _Rope_const_iterator(const _Rope_iterator<_CharT,_Alloc>& __x): 00890 _Rope_iterator_base<_CharT,_Alloc>(__x) {} 00891 _Rope_const_iterator(const rope<_CharT,_Alloc>& __r, size_t __pos) : 00892 _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr._M_data, __pos) {} 00893 _Self& operator= (const _Self& __x) { 00894 _Base::operator=(__x); 00895 return *this; 00896 } 00897 reference operator*() { 00898 if (0 == this->_M_buf_ptr) 00899 #if !defined (__DMC__) 00900 _S_setcache(*this); 00901 #else 00902 { _Rope_iterator_base<_CharT, _Alloc>* __x = this; _S_setcache(*__x); } 00903 #endif 00904 return *(this->_M_buf_ptr); 00905 } 00906 _Self& operator++() { 00907 _CharT* __next; 00908 if (0 != this->_M_buf_ptr && (__next = this->_M_buf_ptr + 1) < this->_M_buf_end) { 00909 this->_M_buf_ptr = __next; 00910 ++this->_M_current_pos; 00911 } else { 00912 this->_M_incr(1); 00913 } 00914 return *this; 00915 } 00916 _Self& operator+=(ptrdiff_t __n) { 00917 if (__n >= 0) { 00918 this->_M_incr(__n); 00919 } else { 00920 this->_M_decr(-__n); 00921 } 00922 return *this; 00923 } 00924 _Self& operator--() { 00925 this->_M_decr(1); 00926 return *this; 00927 } 00928 _Self& operator-=(ptrdiff_t __n) { 00929 if (__n >= 0) { 00930 this->_M_decr(__n); 00931 } else { 00932 this->_M_incr(-__n); 00933 } 00934 return *this; 00935 } 00936 _Self operator++(int) { 00937 size_t __old_pos = this->_M_current_pos; 00938 this->_M_incr(1); 00939 return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos); 00940 // This makes a subsequent dereference expensive. 00941 // Perhaps we should instead copy the iterator 00942 // if it has a valid cache? 00943 } 00944 _Self operator--(int) { 00945 size_t __old_pos = this->_M_current_pos; 00946 this->_M_decr(1); 00947 return _Rope_const_iterator<_CharT,_Alloc>(this->_M_root, __old_pos); 00948 } 00949 inline reference operator[](size_t __n); 00950 }; 00951 00952 template<class _CharT, class _Alloc> 00953 class _Rope_iterator : public _Rope_iterator_base<_CharT,_Alloc> { 00954 friend class rope<_CharT,_Alloc>; 00955 typedef _Rope_iterator<_CharT, _Alloc> _Self; 00956 typedef _Rope_iterator_base<_CharT,_Alloc> _Base; 00957 typedef _Rope_RopeRep<_CharT,_Alloc> _RopeRep; 00958 00959 public: 00960 rope<_CharT,_Alloc>* _M_root_rope; 00961 // root is treated as a cached version of this, 00962 // and is used to detect changes to the underlying 00963 // rope. 00964 // Root is included in the reference count. 00965 // This is necessary so that we can detect changes reliably. 00966 // Unfortunately, it requires careful bookkeeping for the 00967 // nonGC case. 00968 _Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos); 00969 00970 void _M_check(); 00971 public: 00972 typedef _Rope_char_ref_proxy<_CharT,_Alloc> reference; 00973 typedef _Rope_char_ref_proxy<_CharT,_Alloc>* pointer; 00974 typedef _CharT value_type; 00975 typedef ptrdiff_t difference_type; 00976 typedef random_access_iterator_tag iterator_category; 00977 public: 00978 ~_Rope_iterator() { //*TY 5/6/00 - added dtor to balance reference count 00979 _RopeRep::_S_unref(this->_M_root); 00980 } 00981 00982 rope<_CharT,_Alloc>& container() { return *_M_root_rope; } 00983 _Rope_iterator() { 00984 this->_M_root = 0; // Needed for reference counting. 00985 } 00986 _Rope_iterator(const _Self& __x) : 00987 _Rope_iterator_base<_CharT,_Alloc>(__x) { 00988 _M_root_rope = __x._M_root_rope; 00989 _RopeRep::_S_ref(this->_M_root); 00990 } 00991 _Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos); 00992 _Self& operator= (const _Self& __x) { 00993 _RopeRep* __old = this->_M_root; 00994 _RopeRep::_S_ref(__x._M_root); 00995 _Base::operator=(__x); 00996 _M_root_rope = __x._M_root_rope; 00997 _RopeRep::_S_unref(__old); 00998 return *this; 00999 } 01000 reference operator*() { 01001 _M_check(); 01002 if (0 == this->_M_buf_ptr) { 01003 return reference(_M_root_rope, this->_M_current_pos); 01004 } else { 01005 return reference(_M_root_rope, this->_M_current_pos, *(this->_M_buf_ptr)); 01006 } 01007 } 01008 _Self& operator++() { 01009 this->_M_incr(1); 01010 return *this; 01011 } 01012 _Self& operator+=(ptrdiff_t __n) { 01013 if (__n >= 0) { 01014 this->_M_incr(__n); 01015 } else { 01016 this->_M_decr(-__n); 01017 } 01018 return *this; 01019 } 01020 _Self& operator--() { 01021 this->_M_decr(1); 01022 return *this; 01023 } 01024 _Self& operator-=(ptrdiff_t __n) { 01025 if (__n >= 0) { 01026 this->_M_decr(__n); 01027 } else { 01028 this->_M_incr(-__n); 01029 } 01030 return *this; 01031 } 01032 _Self operator++(int) { 01033 size_t __old_pos = this->_M_current_pos; 01034 this->_M_incr(1); 01035 return _Self(_M_root_rope, __old_pos); 01036 } 01037 _Self operator--(int) { 01038 size_t __old_pos = this->_M_current_pos; 01039 this->_M_decr(1); 01040 return _Self(_M_root_rope, __old_pos); 01041 } 01042 reference operator[](ptrdiff_t __n) { 01043 return reference(_M_root_rope, this->_M_current_pos + __n); 01044 } 01045 }; 01046 01047 # ifdef _STLP_USE_OLD_HP_ITERATOR_QUERIES 01048 template <class _CharT, class _Alloc> 01049 inline random_access_iterator_tag 01050 iterator_category(const _Rope_iterator<_CharT,_Alloc>&) { return random_access_iterator_tag();} 01051 template <class _CharT, class _Alloc> 01052 inline _CharT* value_type(const _Rope_iterator<_CharT,_Alloc>&) { return 0; } 01053 template <class _CharT, class _Alloc> 01054 inline ptrdiff_t* distance_type(const _Rope_iterator<_CharT,_Alloc>&) { return 0; } 01055 template <class _CharT, class _Alloc> 01056 inline random_access_iterator_tag 01057 iterator_category(const _Rope_const_iterator<_CharT,_Alloc>&) { return random_access_iterator_tag(); } 01058 template <class _CharT, class _Alloc> 01059 inline _CharT* value_type(const _Rope_const_iterator<_CharT,_Alloc>&) { return 0; } 01060 template <class _CharT, class _Alloc> 01061 inline ptrdiff_t* distance_type(const _Rope_const_iterator<_CharT,_Alloc>&) { return 0; } 01062 #endif /* _STLP_USE_OLD_HP_ITERATOR_QUERIES */ 01063 01064 template <class _CharT, class _Alloc, class _CharConsumer> 01065 bool _S_apply_to_pieces(_CharConsumer& __c, 01066 _Rope_RopeRep<_CharT, _Alloc> *__r, 01067 size_t __begin, size_t __end); 01068 // begin and end are assumed to be in range. 01069 01070 template <class _CharT, class _Alloc> 01071 class rope 01072 #if defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) 01073 : public __stlport_class<rope<_CharT, _Alloc> > 01074 #endif 01075 { 01076 typedef rope<_CharT,_Alloc> _Self; 01077 public: 01078 typedef _CharT value_type; 01079 typedef ptrdiff_t difference_type; 01080 typedef size_t size_type; 01081 typedef _CharT const_reference; 01082 typedef const _CharT* const_pointer; 01083 typedef _Rope_iterator<_CharT,_Alloc> iterator; 01084 typedef _Rope_const_iterator<_CharT,_Alloc> const_iterator; 01085 typedef _Rope_char_ref_proxy<_CharT,_Alloc> reference; 01086 typedef _Rope_char_ptr_proxy<_CharT,_Alloc> pointer; 01087 01088 friend class _Rope_iterator<_CharT,_Alloc>; 01089 friend class _Rope_const_iterator<_CharT,_Alloc>; 01090 friend struct _Rope_RopeRep<_CharT,_Alloc>; 01091 friend class _Rope_iterator_base<_CharT,_Alloc>; 01092 friend class _Rope_char_ptr_proxy<_CharT,_Alloc>; 01093 friend class _Rope_char_ref_proxy<_CharT,_Alloc>; 01094 friend struct _Rope_RopeSubstring<_CharT,_Alloc>; 01095 01096 _STLP_DECLARE_RANDOM_ACCESS_REVERSE_ITERATORS; 01097 01098 protected: 01099 typedef _CharT* _Cstrptr; 01100 01101 static _CharT _S_empty_c_str[1]; 01102 01103 enum { _S_copy_max = 23 }; 01104 // For strings shorter than _S_copy_max, we copy to 01105 // concatenate. 01106 01107 typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; 01108 typedef typename _RopeRep::_IsBasicCharType _IsBasicCharType; 01109 01110 public: 01111 _STLP_FORCE_ALLOCATORS(_CharT, _Alloc) 01112 typedef typename _Alloc_traits<_CharT,_Alloc>::allocator_type allocator_type; 01113 01114 public: 01115 // The only data member of a rope: 01116 _STLP_PRIV _STLP_alloc_proxy<_RopeRep*, _CharT, allocator_type> _M_tree_ptr; 01117 01118 public: 01119 allocator_type get_allocator() const { return allocator_type(_M_tree_ptr); } 01120 01121 public: 01122 typedef _Rope_RopeConcatenation<_CharT,_Alloc> _RopeConcatenation; 01123 typedef _Rope_RopeLeaf<_CharT,_Alloc> _RopeLeaf; 01124 typedef _Rope_RopeFunction<_CharT,_Alloc> _RopeFunction; 01125 typedef _Rope_RopeSubstring<_CharT,_Alloc> _RopeSubstring; 01126 01127 // Retrieve a character at the indicated position. 01128 static _CharT _S_fetch(_RopeRep* __r, size_type __pos); 01129 01130 // Obtain a pointer to the character at the indicated position. 01131 // The pointer can be used to change the character. 01132 // If such a pointer cannot be produced, as is frequently the 01133 // case, 0 is returned instead. 01134 // (Returns nonzero only if all nodes in the path have a refcount 01135 // of 1.) 01136 static _CharT* _S_fetch_ptr(_RopeRep* __r, size_type __pos); 01137 01138 static void _S_unref(_RopeRep* __t) { 01139 _RopeRep::_S_unref(__t); 01140 } 01141 static void _S_ref(_RopeRep* __t) { 01142 _RopeRep::_S_ref(__t); 01143 } 01144 01145 typedef _Rope_self_destruct_ptr<_CharT,_Alloc> _Self_destruct_ptr; 01146 01147 // _Result is counted in refcount. 01148 static _RopeRep* _S_substring(_RopeRep* __base, 01149 size_t __start, size_t __endp1); 01150 01151 static _RopeRep* _S_concat_char_iter(_RopeRep* __r, 01152 const _CharT* __iter, size_t __slen); 01153 // Concatenate rope and char ptr, copying __s. 01154 // Should really take an arbitrary iterator. 01155 // Result is counted in refcount. 01156 static _RopeRep* _S_destr_concat_char_iter(_RopeRep* __r, 01157 const _CharT* __iter, size_t __slen); 01158 // As above, but one reference to __r is about to be 01159 // destroyed. Thus the pieces may be recycled if all 01160 // relevent reference counts are 1. 01161 01162 // General concatenation on _RopeRep. _Result 01163 // has refcount of 1. Adjusts argument refcounts. 01164 static _RopeRep* _S_concat_rep(_RopeRep* __left, _RopeRep* __right); 01165 01166 public: 01167 #if defined (_STLP_MEMBER_TEMPLATES) 01168 template <class _CharConsumer> 01169 #else 01170 typedef _Rope_char_consumer<_CharT> _CharConsumer; 01171 #endif 01172 void apply_to_pieces(size_t __begin, size_t __end, 01173 _CharConsumer& __c) const 01174 { _S_apply_to_pieces(__c, _M_tree_ptr._M_data, __begin, __end); } 01175 01176 protected: 01177 01178 static size_t _S_rounded_up_size(size_t __n) 01179 { return _RopeRep::_S_rounded_up_size(__n); } 01180 01181 // Allocate and construct a RopeLeaf using the supplied allocator 01182 // Takes ownership of s instead of copying. 01183 static _RopeLeaf* _S_new_RopeLeaf(_CharT *__s, 01184 size_t _p_size, allocator_type __a) { 01185 _RopeLeaf* __space = _STLP_CREATE_ALLOCATOR(allocator_type, __a, 01186 _RopeLeaf).allocate(1); 01187 _STLP_TRY { 01188 _STLP_PLACEMENT_NEW(__space) _RopeLeaf(__s, _p_size, __a); 01189 } 01190 _STLP_UNWIND(_STLP_CREATE_ALLOCATOR(allocator_type,__a, 01191 _RopeLeaf).deallocate(__space, 1)) 01192 return __space; 01193 } 01194 01195 static _RopeConcatenation* _S_new_RopeConcatenation(_RopeRep* __left, _RopeRep* __right, 01196 allocator_type __a) { 01197 _RopeConcatenation* __space = _STLP_CREATE_ALLOCATOR(allocator_type, __a, 01198 _RopeConcatenation).allocate(1); 01199 return _STLP_PLACEMENT_NEW(__space) _RopeConcatenation(__left, __right, __a); 01200 } 01201 01202 static _RopeFunction* _S_new_RopeFunction(char_producer<_CharT>* __f, 01203 size_t _p_size, bool __d, allocator_type __a) { 01204 _RopeFunction* __space = _STLP_CREATE_ALLOCATOR(allocator_type, __a, 01205 _RopeFunction).allocate(1); 01206 return _STLP_PLACEMENT_NEW(__space) _RopeFunction(__f, _p_size, __d, __a); 01207 } 01208 01209 static _RopeSubstring* _S_new_RopeSubstring(_Rope_RopeRep<_CharT,_Alloc>* __b, size_t __s, 01210 size_t __l, allocator_type __a) { 01211 _RopeSubstring* __space = _STLP_CREATE_ALLOCATOR(allocator_type, __a, 01212 _RopeSubstring).allocate(1); 01213 return _STLP_PLACEMENT_NEW(__space) _RopeSubstring(__b, __s, __l, __a); 01214 } 01215 01216 static 01217 _RopeLeaf* _S_RopeLeaf_from_unowned_char_ptr(const _CharT *__s, 01218 size_t _p_size, allocator_type __a) { 01219 if (0 == _p_size) return 0; 01220 01221 _CharT* __buf = _STLP_CREATE_ALLOCATOR(allocator_type,__a, _CharT).allocate(_S_rounded_up_size(_p_size)); 01222 01223 _STLP_PRIV __ucopy_n(__s, _p_size, __buf); 01224 _S_construct_null(__buf + _p_size); 01225 01226 _STLP_TRY { 01227 return _S_new_RopeLeaf(__buf, _p_size, __a); 01228 } 01229 _STLP_UNWIND(_RopeRep::_S_free_string(__buf, _p_size, __a)) 01230 _STLP_RET_AFTER_THROW(0) 01231 } 01232 01233 01234 // Concatenation of nonempty strings. 01235 // Always builds a concatenation node. 01236 // Rebalances if the result is too deep. 01237 // Result has refcount 1. 01238 // Does not increment left and right ref counts even though 01239 // they are referenced. 01240 static _RopeRep* 01241 _S_tree_concat(_RopeRep* __left, _RopeRep* __right); 01242 01243 // Concatenation helper functions 01244 static _RopeLeaf* 01245 _S_leaf_concat_char_iter(_RopeLeaf* __r, 01246 const _CharT* __iter, size_t __slen); 01247 // Concatenate by copying leaf. 01248 // should take an arbitrary iterator 01249 // result has refcount 1. 01250 static _RopeLeaf* _S_destr_leaf_concat_char_iter 01251 (_RopeLeaf* __r, const _CharT* __iter, size_t __slen); 01252 // A version that potentially clobbers __r if __r->_M_ref_count == 1. 01253 01254 01255 // A helper function for exponentiating strings. 01256 // This uses a nonstandard refcount convention. 01257 // The result has refcount 0. 01258 typedef _STLP_PRIV _Rope_Concat_fn<_CharT,_Alloc> _Concat_fn; 01259 #if !defined (__GNUC__) || (__GNUC__ < 3) 01260 friend _Concat_fn; 01261 #else 01262 friend struct _STLP_PRIV _Rope_Concat_fn<_CharT,_Alloc>; 01263 #endif 01264 01265 public: 01266 static size_t _S_char_ptr_len(const _CharT* __s) { 01267 return char_traits<_CharT>::length(__s); 01268 } 01269 01270 public: /* for operators */ 01271 rope(_RopeRep* __t, const allocator_type& __a = allocator_type()) 01272 : _M_tree_ptr(__a, __t) { } 01273 private: 01274 // Copy __r to the _CharT buffer. 01275 // Returns __buffer + __r->_M_size._M_data. 01276 // Assumes that buffer is uninitialized. 01277 static _CharT* _S_flatten(_RopeRep* __r, _CharT* __buffer); 01278 01279 // Again, with explicit starting position and length. 01280 // Assumes that buffer is uninitialized. 01281 static _CharT* _S_flatten(_RopeRep* __r, 01282 size_t __start, size_t __len, 01283 _CharT* __buffer); 01284 01285 // fbp : HP aCC prohibits access to protected min_len from within static methods ( ?? ) 01286 public: 01287 static const unsigned long _S_min_len[__ROPE_DEPTH_SIZE]; 01288 protected: 01289 static bool _S_is_balanced(_RopeRep* __r) 01290 { return (__r->_M_size._M_data >= _S_min_len[__r->_M_depth]); } 01291 01292 static bool _S_is_almost_balanced(_RopeRep* __r) { 01293 return (__r->_M_depth == 0 || 01294 __r->_M_size._M_data >= _S_min_len[__r->_M_depth - 1]); 01295 } 01296 01297 static bool _S_is_roughly_balanced(_RopeRep* __r) { 01298 return (__r->_M_depth <= 1 || 01299 __r->_M_size._M_data >= _S_min_len[__r->_M_depth - 2]); 01300 } 01301 01302 // Assumes the result is not empty. 01303 static _RopeRep* _S_concat_and_set_balanced(_RopeRep* __left, 01304 _RopeRep* __right) { 01305 _RopeRep* __result = _S_concat_rep(__left, __right); 01306 if (_S_is_balanced(__result)) __result->_M_is_balanced = true; 01307 return __result; 01308 } 01309 01310 // The basic rebalancing operation. Logically copies the 01311 // rope. The result has refcount of 1. The client will 01312 // usually decrement the reference count of __r. 01313 // The result is within height 2 of balanced by the above 01314 // definition. 01315 static _RopeRep* _S_balance(_RopeRep* __r); 01316 01317 // Add all unbalanced subtrees to the forest of balanceed trees. 01318 // Used only by balance. 01319 static void _S_add_to_forest(_RopeRep*__r, _RopeRep** __forest); 01320 01321 // Add __r to forest, assuming __r is already balanced. 01322 static void _S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest); 01323 01324 #ifdef _STLP_DEBUG 01325 // Print to stdout, exposing structure 01326 static void _S_dump(_RopeRep* __r, int __indent = 0); 01327 #endif 01328 01329 // Return -1, 0, or 1 if __x < __y, __x == __y, or __x > __y resp. 01330 static int _S_compare(const _RopeRep* __x, const _RopeRep* __y); 01331 01332 void _STLP_FUNCTION_THROWS _M_throw_out_of_range() const; 01333 01334 void _M_reset(_RopeRep* __r) { 01335 //if (__r != _M_tree_ptr._M_data) { 01336 _S_unref(_M_tree_ptr._M_data); 01337 _M_tree_ptr._M_data = __r; 01338 //} 01339 } 01340 01341 public: 01342 bool empty() const { return 0 == _M_tree_ptr._M_data; } 01343 01344 // Comparison member function. This is public only for those 01345 // clients that need a ternary comparison. Others 01346 // should use the comparison operators below. 01347 int compare(const _Self& __y) const { 01348 return _S_compare(_M_tree_ptr._M_data, __y._M_tree_ptr._M_data); 01349 } 01350 01351 rope(const _CharT* __s, const allocator_type& __a = allocator_type()) 01352 : _M_tree_ptr(__a, _S_RopeLeaf_from_unowned_char_ptr(__s, _S_char_ptr_len(__s),__a)) 01353 {} 01354 01355 rope(const _CharT* __s, size_t __len, 01356 const allocator_type& __a = allocator_type()) 01357 : _M_tree_ptr(__a, (_S_RopeLeaf_from_unowned_char_ptr(__s, __len, __a))) 01358 {} 01359 01360 // Should perhaps be templatized with respect to the iterator type 01361 // and use Sequence_buffer. (It should perhaps use sequence_buffer 01362 // even now.) 01363 rope(const _CharT *__s, const _CharT *__e, 01364 const allocator_type& __a = allocator_type()) 01365 : _M_tree_ptr(__a, _S_RopeLeaf_from_unowned_char_ptr(__s, __e - __s, __a)) 01366 {} 01367 01368 rope(const const_iterator& __s, const const_iterator& __e, 01369 const allocator_type& __a = allocator_type()) 01370 : _M_tree_ptr(__a, _S_substring(__s._M_root, __s._M_current_pos, 01371 __e._M_current_pos)) 01372 {} 01373 01374 rope(const iterator& __s, const iterator& __e, 01375 const allocator_type& __a = allocator_type()) 01376 : _M_tree_ptr(__a, _S_substring(__s._M_root, __s._M_current_pos, 01377 __e._M_current_pos)) 01378 {} 01379 01380 rope(_CharT __c, const allocator_type& __a = allocator_type()) 01381 : _M_tree_ptr(__a, (_RopeRep*)0) { 01382 _CharT* __buf = _M_tree_ptr.allocate(_S_rounded_up_size(1)); 01383 01384 _Copy_Construct(__buf, __c); 01385 _S_construct_null(__buf + 1); 01386 01387 _STLP_TRY { 01388 _M_tree_ptr._M_data = _S_new_RopeLeaf(__buf, 1, __a); 01389 } 01390 _STLP_UNWIND(_RopeRep::_S_free_string(__buf, 1, __a)) 01391 } 01392 01393 rope(size_t __n, _CharT __c, 01394 const allocator_type& __a = allocator_type()): 01395 _M_tree_ptr(__a, (_RopeRep*)0) { 01396 if (0 == __n) 01397 return; 01398 01399 rope<_CharT,_Alloc> __result; 01400 # define __exponentiate_threshold size_t(32) 01401 _RopeRep* __remainder; 01402 rope<_CharT,_Alloc> __remainder_rope; 01403 01404 // gcc-2.7.2 bugs 01405 typedef _STLP_PRIV _Rope_Concat_fn<_CharT,_Alloc> _Concat_fn; 01406 01407 size_t __exponent = __n / __exponentiate_threshold; 01408 size_t __rest = __n % __exponentiate_threshold; 01409 if (0 == __rest) { 01410 __remainder = 0; 01411 } else { 01412 _CharT* __rest_buffer = _M_tree_ptr.allocate(_S_rounded_up_size(__rest)); 01413 uninitialized_fill_n(__rest_buffer, __rest, __c); 01414 _S_construct_null(__rest_buffer + __rest); 01415 _STLP_TRY { 01416 __remainder = _S_new_RopeLeaf(__rest_buffer, __rest, __a); 01417 } 01418 _STLP_UNWIND(_RopeRep::_S_free_string(__rest_buffer, __rest, __a)) 01419 } 01420 __remainder_rope._M_tree_ptr._M_data = __remainder; 01421 if (__exponent != 0) { 01422 _CharT* __base_buffer = _M_tree_ptr.allocate(_S_rounded_up_size(__exponentiate_threshold)); 01423 _RopeLeaf* __base_leaf; 01424 rope<_CharT,_Alloc> __base_rope; 01425 uninitialized_fill_n(__base_buffer, __exponentiate_threshold, __c); 01426 _S_construct_null(__base_buffer + __exponentiate_threshold); 01427 _STLP_TRY { 01428 __base_leaf = _S_new_RopeLeaf(__base_buffer, 01429 __exponentiate_threshold, __a); 01430 } 01431 _STLP_UNWIND(_RopeRep::_S_free_string(__base_buffer, 01432 __exponentiate_threshold, __a)) 01433 __base_rope._M_tree_ptr._M_data = __base_leaf; 01434 if (1 == __exponent) { 01435 __result = __base_rope; 01436 // One each for base_rope and __result 01437 //_STLP_ASSERT(2 == __result._M_tree_ptr._M_data->_M_ref_count) 01438 } else { 01439 __result = _STLP_PRIV __power(__base_rope, __exponent, _Concat_fn()); 01440 } 01441 if (0 != __remainder) { 01442 __result += __remainder_rope; 01443 } 01444 } else { 01445 __result = __remainder_rope; 01446 } 01447 _M_tree_ptr._M_data = __result._M_tree_ptr._M_data; 01448 _M_tree_ptr._M_data->_M_ref_nonnil(); 01449 # undef __exponentiate_threshold 01450 } 01451 01452 rope(const allocator_type& __a = allocator_type()) 01453 : _M_tree_ptr(__a, (_RopeRep*)0) {} 01454 01455 // Construct a rope from a function that can compute its members 01456 rope(char_producer<_CharT> *__fn, size_t __len, bool __delete_fn, 01457 const allocator_type& __a = allocator_type()) 01458 : _M_tree_ptr(__a, (_RopeRep*)0) { 01459 _M_tree_ptr._M_data = (0 == __len) ? 01460 0 : _S_new_RopeFunction(__fn, __len, __delete_fn, __a); 01461 } 01462 01463 rope(const _Self& __x) 01464 : _M_tree_ptr(__x._M_tree_ptr, __x._M_tree_ptr._M_data) { 01465 _S_ref(_M_tree_ptr._M_data); 01466 } 01467 01468 rope(__move_source<_Self> __src) 01469 : _M_tree_ptr(__src.get()._M_tree_ptr, __src.get()._M_tree_ptr._M_data) { 01470 __src.get()._M_tree_ptr._M_data = 0; 01471 } 01472 01473 ~rope() { 01474 _S_unref(_M_tree_ptr._M_data); 01475 } 01476 01477 _Self& operator=(const _Self& __x) { 01478 _STLP_ASSERT(get_allocator() == __x.get_allocator()) 01479 _S_ref(__x._M_tree_ptr._M_data); 01480 _M_reset(__x._M_tree_ptr._M_data); 01481 return *this; 01482 } 01483 01484 void clear() { 01485 _S_unref(_M_tree_ptr._M_data); 01486 _M_tree_ptr._M_data = 0; 01487 } 01488 void push_back(_CharT __x) { 01489 _M_reset(_S_destr_concat_char_iter(_M_tree_ptr._M_data, &__x, 1)); 01490 } 01491 01492 void pop_back() { 01493 _RopeRep* __old = _M_tree_ptr._M_data; 01494 _M_tree_ptr._M_data = 01495 _S_substring(_M_tree_ptr._M_data, 0, _M_tree_ptr._M_data->_M_size._M_data - 1); 01496 _S_unref(__old); 01497 } 01498 01499 _CharT back() const { 01500 return _S_fetch(_M_tree_ptr._M_data, _M_tree_ptr._M_data->_M_size._M_data - 1); 01501 } 01502 01503 void push_front(_CharT __x) { 01504 _RopeRep* __old = _M_tree_ptr._M_data; 01505 _RopeRep* __left = 01506 _S_RopeLeaf_from_unowned_char_ptr(&__x, 1, _M_tree_ptr); 01507 _STLP_TRY { 01508 _M_tree_ptr._M_data = _S_concat_rep(__left, _M_tree_ptr._M_data); 01509 _S_unref(__old); 01510 _S_unref(__left); 01511 } 01512 _STLP_UNWIND(_S_unref(__left)) 01513 } 01514 01515 void pop_front() { 01516 _RopeRep* __old = _M_tree_ptr._M_data; 01517 _M_tree_ptr._M_data = _S_substring(_M_tree_ptr._M_data, 1, _M_tree_ptr._M_data->_M_size._M_data); 01518 _S_unref(__old); 01519 } 01520 01521 _CharT front() const { 01522 return _S_fetch(_M_tree_ptr._M_data, 0); 01523 } 01524 01525 void balance() { 01526 _RopeRep* __old = _M_tree_ptr._M_data; 01527 _M_tree_ptr._M_data = _S_balance(_M_tree_ptr._M_data); 01528 _S_unref(__old); 01529 } 01530 01531 void copy(_CharT* __buffer) const { 01532 _STLP_STD::_Destroy_Range(__buffer, __buffer + size()); 01533 _S_flatten(_M_tree_ptr._M_data, __buffer); 01534 } 01535 01536 /* 01537 * This is the copy function from the standard, but 01538 * with the arguments reordered to make it consistent with the 01539 * rest of the interface. 01540 * Note that this guaranteed not to compile if the draft standard 01541 * order is assumed. 01542 */ 01543 size_type copy(size_type __pos, size_type __n, _CharT* __buffer) const { 01544 size_t _p_size = size(); 01545 size_t __len = (__pos + __n > _p_size? _p_size - __pos : __n); 01546 01547 _STLP_STD::_Destroy_Range(__buffer, __buffer + __len); 01548 _S_flatten(_M_tree_ptr._M_data, __pos, __len, __buffer); 01549 return __len; 01550 } 01551 01552 # ifdef _STLP_DEBUG 01553 // Print to stdout, exposing structure. May be useful for 01554 // performance debugging. 01555 void dump() { 01556 _S_dump(_M_tree_ptr._M_data); 01557 } 01558 # endif 01559 01560 // Convert to 0 terminated string in new allocated memory. 01561 // Embedded 0s in the input do not terminate the copy. 01562 const _CharT* c_str() const; 01563 01564 // As above, but also use the flattened representation as the 01565 // the new rope representation. 01566 const _CharT* replace_with_c_str(); 01567 01568 // Reclaim memory for the c_str generated flattened string. 01569 // Intentionally undocumented, since it's hard to say when this 01570 // is safe for multiple threads. 01571 void delete_c_str () { 01572 if (0 == _M_tree_ptr._M_data) return; 01573 if (_RopeRep::_S_leaf == _M_tree_ptr._M_data->_M_tag && 01574 ((_RopeLeaf*)_M_tree_ptr._M_data)->_M_data == 01575 _M_tree_ptr._M_data->_M_c_string) { 01576 // Representation shared 01577 return; 01578 } 01579 _M_tree_ptr._M_data->_M_free_c_string(); 01580 _M_tree_ptr._M_data->_M_c_string = 0; 01581 } 01582 01583 _CharT operator[] (size_type __pos) const { 01584 return _S_fetch(_M_tree_ptr._M_data, __pos); 01585 } 01586 01587 _CharT at(size_type __pos) const { 01588 if (__pos >= size()) _M_throw_out_of_range(); 01589 return (*this)[__pos]; 01590 } 01591 01592 const_iterator begin() const { 01593 return(const_iterator(_M_tree_ptr._M_data, 0)); 01594 } 01595 01596 // An easy way to get a const iterator from a non-const container. 01597 const_iterator const_begin() const { 01598 return(const_iterator(_M_tree_ptr._M_data, 0)); 01599 } 01600 01601 const_iterator end() const { 01602 return(const_iterator(_M_tree_ptr._M_data, size())); 01603 } 01604 01605 const_iterator const_end() const { 01606 return(const_iterator(_M_tree_ptr._M_data, size())); 01607 } 01608 01609 size_type size() const { 01610 return(0 == _M_tree_ptr._M_data? 0 : _M_tree_ptr._M_data->_M_size._M_data); 01611 } 01612 01613 size_type length() const { 01614 return size(); 01615 } 01616 01617 size_type max_size() const { 01618 return _S_min_len[__ROPE_MAX_DEPTH-1] - 1; 01619 // Guarantees that the result can be sufficiently 01620 // balanced. Longer ropes will probably still work, 01621 // but it's harder to make guarantees. 01622 } 01623 01624 const_reverse_iterator rbegin() const { 01625 return const_reverse_iterator(end()); 01626 } 01627 01628 const_reverse_iterator const_rbegin() const { 01629 return const_reverse_iterator(end()); 01630 } 01631 01632 const_reverse_iterator rend() const { 01633 return const_reverse_iterator(begin()); 01634 } 01635 01636 const_reverse_iterator const_rend() const { 01637 return const_reverse_iterator(begin()); 01638 } 01639 // The symmetric cases are intentionally omitted, since they're presumed 01640 // to be less common, and we don't handle them as well. 01641 01642 // The following should really be templatized. 01643 // The first argument should be an input iterator or 01644 // forward iterator with value_type _CharT. 01645 _Self& append(const _CharT* __iter, size_t __n) { 01646 _M_reset(_S_destr_concat_char_iter(_M_tree_ptr._M_data, __iter, __n)); 01647 return *this; 01648 } 01649 01650 _Self& append(const _CharT* __c_string) { 01651 size_t __len = _S_char_ptr_len(__c_string); 01652 append(__c_string, __len); 01653 return *this; 01654 } 01655 01656 _Self& append(const _CharT* __s, const _CharT* __e) { 01657 _M_reset(_S_destr_concat_char_iter(_M_tree_ptr._M_data, __s, __e - __s)); 01658 return *this; 01659 } 01660 01661 _Self& append(const_iterator __s, const_iterator __e) { 01662 _STLP_ASSERT(__s._M_root == __e._M_root) 01663 _STLP_ASSERT(get_allocator() == __s._M_root->get_allocator()) 01664 _Self_destruct_ptr __appendee(_S_substring(__s._M_root, __s._M_current_pos, __e._M_current_pos)); 01665 _M_reset(_S_concat_rep(_M_tree_ptr._M_data, (_RopeRep*)__appendee)); 01666 return *this; 01667 } 01668 01669 _Self& append(_CharT __c) { 01670 _M_reset(_S_destr_concat_char_iter(_M_tree_ptr._M_data, &__c, 1)); 01671 return *this; 01672 } 01673 01674 _Self& append() { return append(_CharT()); } // XXX why? 01675 01676 _Self& append(const _Self& __y) { 01677 _STLP_ASSERT(__y.get_allocator() == get_allocator()) 01678 _M_reset(_S_concat_rep(_M_tree_ptr._M_data, __y._M_tree_ptr._M_data)); 01679 return *this; 01680 } 01681 01682 _Self& append(size_t __n, _CharT __c) { 01683 rope<_CharT,_Alloc> __last(__n, __c); 01684 return append(__last); 01685 } 01686 01687 void swap(_Self& __b) { 01688 _M_tree_ptr.swap(__b._M_tree_ptr); 01689 } 01690 01691 protected: 01692 // Result is included in refcount. 01693 static _RopeRep* replace(_RopeRep* __old, size_t __pos1, 01694 size_t __pos2, _RopeRep* __r) { 01695 if (0 == __old) { _S_ref(__r); return __r; } 01696 _Self_destruct_ptr __left(_S_substring(__old, 0, __pos1)); 01697 _Self_destruct_ptr __right(_S_substring(__old, __pos2, __old->_M_size._M_data)); 01698 _STLP_MPWFIX_TRY //*TY 06/01/2000 - 01699 _RopeRep* __result; 01700 01701 if (0 == __r) { 01702 __result = _S_concat_rep(__left, __right); 01703 } else { 01704 _STLP_ASSERT(__old->get_allocator() == __r->get_allocator()) 01705 _Self_destruct_ptr __left_result(_S_concat_rep(__left, __r)); 01706 __result = _S_concat_rep(__left_result, __right); 01707 } 01708 return __result; 01709 _STLP_MPWFIX_CATCH //*TY 06/01/2000 - 01710 } 01711 01712 public: 01713 void insert(size_t __p, const _Self& __r) { 01714 if (__p > size()) _M_throw_out_of_range(); 01715 _STLP_ASSERT(get_allocator() == __r.get_allocator()) 01716 _M_reset(replace(_M_tree_ptr._M_data, __p, __p, __r._M_tree_ptr._M_data)); 01717 } 01718 01719 void insert(size_t __p, size_t __n, _CharT __c) { 01720 rope<_CharT,_Alloc> __r(__n,__c); 01721 insert(__p, __r); 01722 } 01723 01724 void insert(size_t __p, const _CharT* __i, size_t __n) { 01725 if (__p > size()) _M_throw_out_of_range(); 01726 _Self_destruct_ptr __left(_S_substring(_M_tree_ptr._M_data, 0, __p)); 01727 _Self_destruct_ptr __right(_S_substring(_M_tree_ptr._M_data, __p, size())); 01728 _Self_destruct_ptr __left_result( 01729 _S_concat_char_iter(__left, __i, __n)); 01730 // _S_ destr_concat_char_iter should be safe here. 01731 // But as it stands it's probably not a win, since __left 01732 // is likely to have additional references. 01733 _M_reset(_S_concat_rep(__left_result, __right)); 01734 } 01735 01736 void insert(size_t __p, const _CharT* __c_string) { 01737 insert(__p, __c_string, _S_char_ptr_len(__c_string)); 01738 } 01739 01740 void insert(size_t __p, _CharT __c) { 01741 insert(__p, &__c, 1); 01742 } 01743 01744 void insert(size_t __p) { 01745 _CharT __c = _CharT(); 01746 insert(__p, &__c, 1); 01747 } 01748 01749 void insert(size_t __p, const _CharT* __i, const _CharT* __j) { 01750 _Self __r(__i, __j); 01751 insert(__p, __r); 01752 } 01753 01754 void insert(size_t __p, const const_iterator& __i, 01755 const const_iterator& __j) { 01756 _Self __r(__i, __j); 01757 insert(__p, __r); 01758 } 01759 01760 void insert(size_t __p, const iterator& __i, 01761 const iterator& __j) { 01762 _Self __r(__i, __j); 01763 insert(__p, __r); 01764 } 01765 01766 // (position, length) versions of replace operations: 01767 void replace(size_t __p, size_t __n, const _Self& __r) { 01768 if (__p > size()) _M_throw_out_of_range(); 01769 _M_reset(replace(_M_tree_ptr._M_data, __p, __p + __n, __r._M_tree_ptr._M_data)); 01770 } 01771 01772 void replace(size_t __p, size_t __n, 01773 const _CharT* __i, size_t __i_len) { 01774 _Self __r(__i, __i_len); 01775 replace(__p, __n, __r); 01776 } 01777 01778 void replace(size_t __p, size_t __n, _CharT __c) { 01779 _Self __r(__c); 01780 replace(__p, __n, __r); 01781 } 01782 01783 void replace(size_t __p, size_t __n, const _CharT* __c_string) { 01784 _Self __r(__c_string); 01785 replace(__p, __n, __r); 01786 } 01787 01788 void replace(size_t __p, size_t __n, 01789 const _CharT* __i, const _CharT* __j) { 01790 _Self __r(__i, __j); 01791 replace(__p, __n, __r); 01792 } 01793 01794 void replace(size_t __p, size_t __n, 01795 const const_iterator& __i, const const_iterator& __j) { 01796 _Self __r(__i, __j); 01797 replace(__p, __n, __r); 01798 } 01799 01800 void replace(size_t __p, size_t __n, 01801 const iterator& __i, const iterator& __j) { 01802 _Self __r(__i, __j); 01803 replace(__p, __n, __r); 01804 } 01805 01806 // Single character variants: 01807 void replace(size_t __p, _CharT __c) { 01808 if (__p > size()) _M_throw_out_of_range(); 01809 iterator __i(this, __p); 01810 *__i = __c; 01811 } 01812 01813 void replace(size_t __p, const _Self& __r) { 01814 replace(__p, 1, __r); 01815 } 01816 01817 void replace(size_t __p, const _CharT* __i, size_t __i_len) { 01818 replace(__p, 1, __i, __i_len); 01819 } 01820 01821 void replace(size_t __p, const _CharT* __c_string) { 01822 replace(__p, 1, __c_string); 01823 } 01824 01825 void replace(size_t __p, const _CharT* __i, const _CharT* __j) { 01826 replace(__p, 1, __i, __j); 01827 } 01828 01829 void replace(size_t __p, const const_iterator& __i, 01830 const const_iterator& __j) { 01831 replace(__p, 1, __i, __j); 01832 } 01833 01834 void replace(size_t __p, const iterator& __i, 01835 const iterator& __j) { 01836 replace(__p, 1, __i, __j); 01837 } 01838 01839 // Erase, (position, size) variant. 01840 void erase(size_t __p, size_t __n) { 01841 if (__p > size()) _M_throw_out_of_range(); 01842 _M_reset(replace(_M_tree_ptr._M_data, __p, __p + __n, 0)); 01843 } 01844 01845 // Erase, single character 01846 void erase(size_t __p) { 01847 erase(__p, __p + 1); 01848 } 01849 01850 // Insert, iterator variants. 01851 iterator insert(const iterator& __p, const _Self& __r) 01852 { insert(__p.index(), __r); return __p; } 01853 iterator insert(const iterator& __p, size_t __n, _CharT __c) 01854 { insert(__p.index(), __n, __c); return __p; } 01855 iterator insert(const iterator& __p, _CharT __c) 01856 { insert(__p.index(), __c); return __p; } 01857 iterator insert(const iterator& __p ) 01858 { insert(__p.index()); return __p; } 01859 iterator insert(const iterator& __p, const _CharT* c_string) 01860 { insert(__p.index(), c_string); return __p; } 01861 iterator insert(const iterator& __p, const _CharT* __i, size_t __n) 01862 { insert(__p.index(), __i, __n); return __p; } 01863 iterator insert(const iterator& __p, const _CharT* __i, 01864 const _CharT* __j) 01865 { insert(__p.index(), __i, __j); return __p; } 01866 iterator insert(const iterator& __p, 01867 const const_iterator& __i, const const_iterator& __j) 01868 { insert(__p.index(), __i, __j); return __p; } 01869 iterator insert(const iterator& __p, 01870 const iterator& __i, const iterator& __j) 01871 { insert(__p.index(), __i, __j); return __p; } 01872 01873 // Replace, range variants. 01874 void replace(const iterator& __p, const iterator& __q, 01875 const _Self& __r) 01876 { replace(__p.index(), __q.index() - __p.index(), __r); } 01877 void replace(const iterator& __p, const iterator& __q, _CharT __c) 01878 { replace(__p.index(), __q.index() - __p.index(), __c); } 01879 void replace(const iterator& __p, const iterator& __q, 01880 const _CharT* __c_string) 01881 { replace(__p.index(), __q.index() - __p.index(), __c_string); } 01882 void replace(const iterator& __p, const iterator& __q, 01883 const _CharT* __i, size_t __n) 01884 { replace(__p.index(), __q.index() - __p.index(), __i, __n); } 01885 void replace(const iterator& __p, const iterator& __q, 01886 const _CharT* __i, const _CharT* __j) 01887 { replace(__p.index(), __q.index() - __p.index(), __i, __j); } 01888 void replace(const iterator& __p, const iterator& __q, 01889 const const_iterator& __i, const const_iterator& __j) 01890 { replace(__p.index(), __q.index() - __p.index(), __i, __j); } 01891 void replace(const iterator& __p, const iterator& __q, 01892 const iterator& __i, const iterator& __j) 01893 { replace(__p.index(), __q.index() - __p.index(), __i, __j); } 01894 01895 // Replace, iterator variants. 01896 void replace(const iterator& __p, const _Self& __r) 01897 { replace(__p.index(), __r); } 01898 void replace(const iterator& __p, _CharT __c) 01899 { replace(__p.index(), __c); } 01900 void replace(const iterator& __p, const _CharT* __c_string) 01901 { replace(__p.index(), __c_string); } 01902 void replace(const iterator& __p, const _CharT* __i, size_t __n) 01903 { replace(__p.index(), __i, __n); } 01904 void replace(const iterator& __p, const _CharT* __i, const _CharT* __j) 01905 { replace(__p.index(), __i, __j); } 01906 void replace(const iterator& __p, const_iterator __i, 01907 const_iterator __j) 01908 { replace(__p.index(), __i, __j); } 01909 void replace(const iterator& __p, iterator __i, iterator __j) 01910 { replace(__p.index(), __i, __j); } 01911 01912 // Iterator and range variants of erase 01913 iterator erase(const iterator& __p, const iterator& __q) { 01914 size_t __p_index = __p.index(); 01915 erase(__p_index, __q.index() - __p_index); 01916 return iterator(this, __p_index); 01917 } 01918 iterator erase(const iterator& __p) { 01919 size_t __p_index = __p.index(); 01920 erase(__p_index, 1); 01921 return iterator(this, __p_index); 01922 } 01923 01924 _Self substr(size_t __start, size_t __len = 1) const { 01925 if (__start > size()) _M_throw_out_of_range(); 01926 return rope<_CharT,_Alloc>(_S_substring(_M_tree_ptr._M_data, __start, __start + __len)); 01927 } 01928 01929 _Self substr(iterator __start, iterator __end) const { 01930 return rope<_CharT,_Alloc>(_S_substring(_M_tree_ptr._M_data, __start.index(), __end.index())); 01931 } 01932 01933 _Self substr(iterator __start) const { 01934 size_t __pos = __start.index(); 01935 return rope<_CharT,_Alloc>(_S_substring(_M_tree_ptr._M_data, __pos, __pos + 1)); 01936 } 01937 01938 _Self substr(const_iterator __start, const_iterator __end) const { 01939 // This might eventually take advantage of the cache in the 01940 // iterator. 01941 return rope<_CharT,_Alloc>(_S_substring(_M_tree_ptr._M_data, __start.index(), __end.index())); 01942 } 01943 01944 rope<_CharT,_Alloc> substr(const_iterator __start) { 01945 size_t __pos = __start.index(); 01946 return rope<_CharT,_Alloc>(_S_substring(_M_tree_ptr._M_data, __pos, __pos + 1)); 01947 } 01948 01949 #include <stl/_string_npos.h> 01950 01951 size_type find(const _Self& __s, size_type __pos = 0) const { 01952 if (__pos >= size()) 01953 # ifndef _STLP_OLD_ROPE_SEMANTICS 01954 return npos; 01955 # else 01956 return size(); 01957 # endif 01958 01959 size_type __result_pos; 01960 const_iterator __result = search(const_begin() + (ptrdiff_t)__pos, const_end(), __s.begin(), __s.end() ); 01961 __result_pos = __result.index(); 01962 # ifndef _STLP_OLD_ROPE_SEMANTICS 01963 if (__result_pos == size()) __result_pos = npos; 01964 # endif 01965 return __result_pos; 01966 } 01967 size_type find(_CharT __c, size_type __pos = 0) const; 01968 size_type find(const _CharT* __s, size_type __pos = 0) const { 01969 size_type __result_pos; 01970 const_iterator __result = search(const_begin() + (ptrdiff_t)__pos, const_end(), 01971 __s, __s + _S_char_ptr_len(__s)); 01972 __result_pos = __result.index(); 01973 # ifndef _STLP_OLD_ROPE_SEMANTICS 01974 if (__result_pos == size()) __result_pos = npos; 01975 # endif 01976 return __result_pos; 01977 } 01978 01979 iterator mutable_begin() { 01980 return(iterator(this, 0)); 01981 } 01982 01983 iterator mutable_end() { 01984 return(iterator(this, size())); 01985 } 01986 01987 reverse_iterator mutable_rbegin() { 01988 return reverse_iterator(mutable_end()); 01989 } 01990 01991 reverse_iterator mutable_rend() { 01992 return reverse_iterator(mutable_begin()); 01993 } 01994 01995 reference mutable_reference_at(size_type __pos) { 01996 return reference(this, __pos); 01997 } 01998 01999 # ifdef __STD_STUFF 02000 reference operator[] (size_type __pos) { 02001 return reference(this, __pos); 02002 } 02003 02004 reference at(size_type __pos) { 02005 if (__pos >= size()) _M_throw_out_of_range(); 02006 return (*this)[__pos]; 02007 } 02008 02009 void resize(size_type, _CharT) {} 02010 void resize(size_type) {} 02011 void reserve(size_type = 0) {} 02012 size_type capacity() const { 02013 return max_size(); 02014 } 02015 02016 // Stuff below this line is dangerous because it's error prone. 02017 // I would really like to get rid of it. 02018 // copy function with funny arg ordering. 02019 size_type copy(_CharT* __buffer, size_type __n, 02020 size_type __pos = 0) const { 02021 return copy(__pos, __n, __buffer); 02022 } 02023 02024 iterator end() { return mutable_end(); } 02025 02026 iterator begin() { return mutable_begin(); } 02027 02028 reverse_iterator rend() { return mutable_rend(); } 02029 02030 reverse_iterator rbegin() { return mutable_rbegin(); } 02031 02032 # else 02033 02034 const_iterator end() { return const_end(); } 02035 02036 const_iterator begin() { return const_begin(); } 02037 02038 const_reverse_iterator rend() { return const_rend(); } 02039 02040 const_reverse_iterator rbegin() { return const_rbegin(); } 02041 02042 # endif 02043 }; //class rope 02044 02045 #if !defined (_STLP_STATIC_CONST_INIT_BUG) 02046 # if defined (__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 96) 02047 template <class _CharT, class _Alloc> 02048 const size_t rope<_CharT, _Alloc>::npos = ~(size_t) 0; 02049 # endif 02050 #endif 02051 02052 template <class _CharT, class _Alloc> 02053 inline _CharT 02054 _Rope_const_iterator< _CharT, _Alloc>::operator[](size_t __n) 02055 { return rope<_CharT,_Alloc>::_S_fetch(this->_M_root, this->_M_current_pos + __n); } 02056 02057 template <class _CharT, class _Alloc> 02058 inline bool operator== (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02059 const _Rope_const_iterator<_CharT,_Alloc>& __y) { 02060 return (__x._M_current_pos == __y._M_current_pos && 02061 __x._M_root == __y._M_root); 02062 } 02063 02064 template <class _CharT, class _Alloc> 02065 inline bool operator< (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02066 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02067 { return (__x._M_current_pos < __y._M_current_pos); } 02068 02069 #ifdef _STLP_USE_SEPARATE_RELOPS_NAMESPACE 02070 02071 template <class _CharT, class _Alloc> 02072 inline bool operator!= (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02073 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02074 { return !(__x == __y); } 02075 02076 template <class _CharT, class _Alloc> 02077 inline bool operator> (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02078 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02079 { return __y < __x; } 02080 02081 template <class _CharT, class _Alloc> 02082 inline bool operator<= (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02083 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02084 { return !(__y < __x); } 02085 02086 template <class _CharT, class _Alloc> 02087 inline bool operator>= (const _Rope_const_iterator<_CharT,_Alloc>& __x, 02088 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02089 { return !(__x < __y); } 02090 02091 #endif /* _STLP_USE_SEPARATE_RELOPS_NAMESPACE */ 02092 02093 template <class _CharT, class _Alloc> 02094 inline ptrdiff_t operator-(const _Rope_const_iterator<_CharT,_Alloc>& __x, 02095 const _Rope_const_iterator<_CharT,_Alloc>& __y) 02096 { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; } 02097 02098 #if !defined( __MWERKS__ ) || __MWERKS__ >= 0x2000 // dwa 8/21/97 - "ambiguous access to overloaded function" bug. 02099 template <class _CharT, class _Alloc> 02100 inline _Rope_const_iterator<_CharT,_Alloc> 02101 operator-(const _Rope_const_iterator<_CharT,_Alloc>& __x, ptrdiff_t __n) 02102 { return _Rope_const_iterator<_CharT,_Alloc>(__x._M_root, __x._M_current_pos - __n); } 02103 # endif 02104 02105 template <class _CharT, class _Alloc> 02106 inline _Rope_const_iterator<_CharT,_Alloc> 02107 operator+(const _Rope_const_iterator<_CharT,_Alloc>& __x, ptrdiff_t __n) 02108 { return _Rope_const_iterator<_CharT,_Alloc>(__x._M_root, __x._M_current_pos + __n); } 02109 02110 template <class _CharT, class _Alloc> 02111 inline _Rope_const_iterator<_CharT,_Alloc> 02112 operator+(ptrdiff_t __n, const _Rope_const_iterator<_CharT,_Alloc>& __x) 02113 { return _Rope_const_iterator<_CharT,_Alloc>(__x._M_root, __x._M_current_pos + __n); } 02114 02115 template <class _CharT, class _Alloc> 02116 inline bool operator== (const _Rope_iterator<_CharT,_Alloc>& __x, 02117 const _Rope_iterator<_CharT,_Alloc>& __y) { 02118 return (__x._M_current_pos == __y._M_current_pos && 02119 __x._M_root_rope == __y._M_root_rope); 02120 } 02121 02122 template <class _CharT, class _Alloc> 02123 inline bool operator< (const _Rope_iterator<_CharT,_Alloc>& __x, 02124 const _Rope_iterator<_CharT,_Alloc>& __y) 02125 { return (__x._M_current_pos < __y._M_current_pos); } 02126 02127 #if defined (_STLP_USE_SEPARATE_RELOPS_NAMESPACE) 02128 template <class _CharT, class _Alloc> 02129 inline bool operator!= (const _Rope_iterator<_CharT,_Alloc>& __x, 02130 const _Rope_iterator<_CharT,_Alloc>& __y) 02131 { return !(__x == __y); } 02132 02133 template <class _CharT, class _Alloc> 02134 inline bool operator> (const _Rope_iterator<_CharT,_Alloc>& __x, 02135 const _Rope_iterator<_CharT,_Alloc>& __y) 02136 { return __y < __x; } 02137 02138 template <class _CharT, class _Alloc> 02139 inline bool operator<= (const _Rope_iterator<_CharT,_Alloc>& __x, 02140 const _Rope_iterator<_CharT,_Alloc>& __y) 02141 { return !(__y < __x); } 02142 02143 template <class _CharT, class _Alloc> 02144 inline bool operator>= (const _Rope_iterator<_CharT,_Alloc>& __x, 02145 const _Rope_iterator<_CharT,_Alloc>& __y) 02146 { return !(__x < __y); } 02147 #endif /* _STLP_USE_SEPARATE_RELOPS_NAMESPACE */ 02148 02149 template <class _CharT, class _Alloc> 02150 inline ptrdiff_t operator-(const _Rope_iterator<_CharT,_Alloc>& __x, 02151 const _Rope_iterator<_CharT,_Alloc>& __y) 02152 { return (ptrdiff_t)__x._M_current_pos - (ptrdiff_t)__y._M_current_pos; } 02153 02154 #if !defined( __MWERKS__ ) || __MWERKS__ >= 0x2000 // dwa 8/21/97 - "ambiguous access to overloaded function" bug. 02155 template <class _CharT, class _Alloc> 02156 inline _Rope_iterator<_CharT,_Alloc> 02157 operator-(const _Rope_iterator<_CharT,_Alloc>& __x, 02158 ptrdiff_t __n) { 02159 return _Rope_iterator<_CharT,_Alloc>(__x._M_root_rope, __x._M_current_pos - __n); 02160 } 02161 # endif 02162 02163 template <class _CharT, class _Alloc> 02164 inline _Rope_iterator<_CharT,_Alloc> 02165 operator+(const _Rope_iterator<_CharT,_Alloc>& __x, 02166 ptrdiff_t __n) { 02167 return _Rope_iterator<_CharT,_Alloc>(__x._M_root_rope, __x._M_current_pos + __n); 02168 } 02169 02170 template <class _CharT, class _Alloc> 02171 inline _Rope_iterator<_CharT,_Alloc> 02172 operator+(ptrdiff_t __n, const _Rope_iterator<_CharT,_Alloc>& __x) { 02173 return _Rope_iterator<_CharT,_Alloc>(__x._M_root_rope, __x._M_current_pos + __n); 02174 } 02175 02176 template <class _CharT, class _Alloc> 02177 inline rope<_CharT,_Alloc> 02178 operator+ (const rope<_CharT,_Alloc>& __left, 02179 const rope<_CharT,_Alloc>& __right) { 02180 _STLP_ASSERT(__left.get_allocator() == __right.get_allocator()) 02181 return rope<_CharT,_Alloc>(rope<_CharT,_Alloc>::_S_concat_rep(__left._M_tree_ptr._M_data, __right._M_tree_ptr._M_data)); 02182 // Inlining this should make it possible to keep __left and __right in registers. 02183 } 02184 02185 template <class _CharT, class _Alloc> 02186 inline rope<_CharT,_Alloc>& 02187 operator+= (rope<_CharT,_Alloc>& __left, 02188 const rope<_CharT,_Alloc>& __right) { 02189 __left.append(__right); 02190 return __left; 02191 } 02192 02193 template <class _CharT, class _Alloc> 02194 inline rope<_CharT,_Alloc> 02195 operator+ (const rope<_CharT,_Alloc>& __left, 02196 const _CharT* __right) { 02197 size_t __rlen = rope<_CharT,_Alloc>::_S_char_ptr_len(__right); 02198 return rope<_CharT,_Alloc>(rope<_CharT,_Alloc>::_S_concat_char_iter(__left._M_tree_ptr._M_data, __right, __rlen)); 02199 } 02200 02201 template <class _CharT, class _Alloc> 02202 inline rope<_CharT,_Alloc>& 02203 operator+= (rope<_CharT,_Alloc>& __left, 02204 const _CharT* __right) { 02205 __left.append(__right); 02206 return __left; 02207 } 02208 02209 template <class _CharT, class _Alloc> 02210 inline rope<_CharT,_Alloc> 02211 operator+ (const rope<_CharT,_Alloc>& __left, _CharT __right) { 02212 return rope<_CharT,_Alloc>(rope<_CharT,_Alloc>::_S_concat_char_iter(__left._M_tree_ptr._M_data, &__right, 1)); 02213 } 02214 02215 template <class _CharT, class _Alloc> 02216 inline rope<_CharT,_Alloc>& 02217 operator+= (rope<_CharT,_Alloc>& __left, _CharT __right) { 02218 __left.append(__right); 02219 return __left; 02220 } 02221 02222 template <class _CharT, class _Alloc> 02223 inline bool 02224 operator< (const rope<_CharT,_Alloc>& __left, 02225 const rope<_CharT,_Alloc>& __right) { 02226 return __left.compare(__right) < 0; 02227 } 02228 02229 template <class _CharT, class _Alloc> 02230 inline bool 02231 operator== (const rope<_CharT,_Alloc>& __left, 02232 const rope<_CharT,_Alloc>& __right) { 02233 return __left.compare(__right) == 0; 02234 } 02235 02236 #ifdef _STLP_USE_SEPARATE_RELOPS_NAMESPACE 02237 02238 template <class _CharT, class _Alloc> 02239 inline bool 02240 operator!= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) { 02241 return !(__x == __y); 02242 } 02243 02244 template <class _CharT, class _Alloc> 02245 inline bool 02246 operator> (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) { 02247 return __y < __x; 02248 } 02249 02250 template <class _CharT, class _Alloc> 02251 inline bool 02252 operator<= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) { 02253 return !(__y < __x); 02254 } 02255 02256 template <class _CharT, class _Alloc> 02257 inline bool 02258 operator>= (const rope<_CharT,_Alloc>& __x, const rope<_CharT,_Alloc>& __y) { 02259 return !(__x < __y); 02260 } 02261 02262 template <class _CharT, class _Alloc> 02263 inline bool operator!= (const _Rope_char_ptr_proxy<_CharT,_Alloc>& __x, 02264 const _Rope_char_ptr_proxy<_CharT,_Alloc>& __y) { 02265 return !(__x == __y); 02266 } 02267 02268 #endif /* _STLP_USE_SEPARATE_RELOPS_NAMESPACE */ 02269 02270 template <class _CharT, class _Alloc> 02271 inline bool operator== (const _Rope_char_ptr_proxy<_CharT,_Alloc>& __x, 02272 const _Rope_char_ptr_proxy<_CharT,_Alloc>& __y) { 02273 return (__x._M_pos == __y._M_pos && __x._M_root == __y._M_root); 02274 } 02275 02276 #if !defined (_STLP_USE_NO_IOSTREAMS) 02277 template<class _CharT, class _Traits, class _Alloc> 02278 basic_ostream<_CharT, _Traits>& operator<< (basic_ostream<_CharT, _Traits>& __o, 02279 const rope<_CharT, _Alloc>& __r); 02280 #endif 02281 02282 typedef rope<char, _STLP_DEFAULT_ALLOCATOR(char) > crope; 02283 #if defined (_STLP_HAS_WCHAR_T) 02284 typedef rope<wchar_t, _STLP_DEFAULT_ALLOCATOR(wchar_t) > wrope; 02285 #endif 02286 02287 inline crope::reference __mutable_reference_at(crope& __c, size_t __i) 02288 { return __c.mutable_reference_at(__i); } 02289 02290 #if defined (_STLP_HAS_WCHAR_T) 02291 inline wrope::reference __mutable_reference_at(wrope& __c, size_t __i) 02292 { return __c.mutable_reference_at(__i); } 02293 #endif 02294 02295 #if defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER) 02296 template <class _CharT, class _Alloc> 02297 inline void swap(rope<_CharT,_Alloc>& __x, rope<_CharT,_Alloc>& __y) 02298 { __x.swap(__y); } 02299 #else 02300 02301 inline void swap(crope& __x, crope& __y) { __x.swap(__y); } 02302 # ifdef _STLP_HAS_WCHAR_T // dwa 8/21/97 02303 inline void swap(wrope& __x, wrope& __y) { __x.swap(__y); } 02304 # endif 02305 02306 #endif /* _STLP_FUNCTION_TMPL_PARTIAL_ORDER */ 02307 02308 02309 // Hash functions should probably be revisited later: 02310 _STLP_TEMPLATE_NULL struct hash<crope> { 02311 size_t operator()(const crope& __str) const { 02312 size_t _p_size = __str.size(); 02313 02314 if (0 == _p_size) return 0; 02315 return 13*__str[0] + 5*__str[_p_size - 1] + _p_size; 02316 } 02317 }; 02318 02319 #if defined (_STLP_HAS_WCHAR_T) // dwa 8/21/97 02320 _STLP_TEMPLATE_NULL struct hash<wrope> { 02321 size_t operator()(const wrope& __str) const { 02322 size_t _p_size = __str.size(); 02323 02324 if (0 == _p_size) return 0; 02325 return 13*__str[0] + 5*__str[_p_size - 1] + _p_size; 02326 } 02327 }; 02328 #endif 02329 02330 #if (!defined (_STLP_MSVC) || (_STLP_MSVC >= 1310)) 02331 // I couldn't get this to work with VC++ 02332 template<class _CharT,class _Alloc> 02333 # if defined (__DMC__) && !defined (__PUT_STATIC_DATA_MEMBERS_HERE) 02334 extern 02335 # endif 02336 void _Rope_rotate(_Rope_iterator<_CharT, _Alloc> __first, 02337 _Rope_iterator<_CharT, _Alloc> __middle, 02338 _Rope_iterator<_CharT, _Alloc> __last); 02339 02340 inline void rotate(_Rope_iterator<char, _STLP_DEFAULT_ALLOCATOR(char) > __first, 02341 _Rope_iterator<char, _STLP_DEFAULT_ALLOCATOR(char) > __middle, 02342 _Rope_iterator<char, _STLP_DEFAULT_ALLOCATOR(char) > __last) 02343 { _Rope_rotate(__first, __middle, __last); } 02344 #endif 02345 02346 template <class _CharT, class _Alloc> 02347 inline _Rope_char_ref_proxy<_CharT, _Alloc>::operator _CharT () const { 02348 if (_M_current_valid) { 02349 return _M_current; 02350 } else { 02351 return _My_rope::_S_fetch(_M_root->_M_tree_ptr._M_data, _M_pos); 02352 } 02353 } 02354 02355 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 02356 template <class _CharT, class _Alloc> 02357 struct __move_traits<rope<_CharT, _Alloc> > { 02358 typedef __stlp_movable implemented; 02359 //Completness depends on the allocator: 02360 typedef typename __move_traits<_Alloc>::complete complete; 02361 }; 02362 #endif 02363 02364 _STLP_END_NAMESPACE 02365 02366 #if !defined (_STLP_LINK_TIME_INSTANTIATION) 02367 # include <stl/_rope.c> 02368 #endif 02369 02370 #endif /* _STLP_INTERNAL_ROPE_H */ 02371 02372 // Local Variables: 02373 // mode:C++ 02374 // End:
Generated on Mon Mar 10 15:32:33 2008 by ![]() |