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