Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygen_rope.c
Go to the documentation of this file.
00001 /* 00002 * Copyright (c) 1996,1997 00003 * Silicon Graphics Computer Systems, Inc. 00004 * 00005 * Copyright (c) 1999 00006 * Boris Fomitchev 00007 * 00008 * This material is provided "as is", with absolutely no warranty expressed 00009 * or implied. Any use is at your own risk. 00010 * 00011 * Permission to use or copy this software for any purpose is hereby granted 00012 * without fee, provided the above notices are retained on all copies. 00013 * Permission to modify the code and to distribute modified code is granted, 00014 * provided the above notices are retained, and a notice that the code was 00015 * modified is included with the above copyright notice. 00016 * 00017 */ 00018 00019 /* NOTE: This is an internal header file, included by other STL headers. 00020 * You should not attempt to use it directly. 00021 */ 00022 00023 // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf 00024 // if necessary. Assumes path_end[leaf_index] and leaf_pos are correct. 00025 // Results in a valid buf_ptr if the iterator can be legitimately 00026 // dereferenced. 00027 #ifndef _STLP_ROPEIMPL_H 00028 #define _STLP_ROPEIMPL_H 00029 00030 #ifndef _STLP_INTERNAL_ROPE_H 00031 # include <stl/_rope.h> 00032 #endif 00033 00034 #ifndef _STLP_INTERNAL_CSTDIO 00035 # include <stl/_cstdio.h> 00036 #endif 00037 00038 #if !defined (_STLP_USE_NO_IOSTREAMS) 00039 # ifndef _STLP_INTERNAL_OSTREAM_H 00040 # include <stl/_ostream.h> 00041 # endif 00042 00043 # ifndef _STLP_INTERNAL_ISTREAM 00044 # include <stl/_istream.h> 00045 # endif 00046 #endif 00047 00048 #include <stl/_range_errors.h> 00049 00050 _STLP_BEGIN_NAMESPACE 00051 00052 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) 00053 # define __allocator__ _Alloc 00054 #else 00055 # define __allocator__ allocator_type 00056 #endif 00057 00058 template<class _CharT, class _Alloc> 00059 _Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos) 00060 : _Rope_iterator_base<_CharT,_Alloc>(__r->_M_tree_ptr._M_data, __pos), 00061 _M_root_rope(__r) { _RopeRep::_S_ref(this->_M_root); } 00062 00063 template<class _CharT, class _Alloc> 00064 _Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos): 00065 _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr._M_data, __pos), 00066 _M_root_rope(&__r) { 00067 #if !defined (__DMC__) 00068 _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*this); 00069 #else 00070 _Rope_iterator_base<_CharT, _Alloc>* __x = this; 00071 _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*__x); 00072 #endif 00073 } 00074 00075 template<class _CharT, class _Alloc> 00076 void _Rope_RopeRep<_CharT, _Alloc>::_M_free_c_string() { 00077 _CharT* __cstr = _M_c_string; 00078 if (0 != __cstr) { 00079 size_t _p_size = _M_size._M_data + 1; 00080 _STLP_STD::_Destroy_Range(__cstr, __cstr + _p_size); 00081 _M_size.deallocate(__cstr, _p_size); 00082 } 00083 } 00084 00085 // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf 00086 // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct. 00087 // Results in a valid buf_ptr if the iterator can be legitimately 00088 // dereferenced. 00089 template <class _CharT, class _Alloc> 00090 void _Rope_iterator_base<_CharT,_Alloc>::_S_setbuf( 00091 _Rope_iterator_base<_CharT,_Alloc>& __x) { 00092 const _RopeRep* __leaf = __x._M_path_end._M_data[__x._M_leaf_index]; 00093 size_t __leaf_pos = __x._M_leaf_pos; 00094 size_t __pos = __x._M_current_pos; 00095 00096 switch(__leaf->_M_tag) { 00097 case _RopeRep::_S_leaf: 00098 typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf; 00099 __x._M_buf_start = __STATIC_CAST(const _RopeLeaf*, __leaf)->_M_data; 00100 __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos); 00101 __x._M_buf_end = __x._M_buf_start + __leaf->_M_size._M_data; 00102 break; 00103 case _RopeRep::_S_function: 00104 case _RopeRep::_S_substringfn: 00105 { 00106 size_t __len = _S_iterator_buf_len; 00107 size_t __buf_start_pos = __leaf_pos; 00108 size_t __leaf_end = __leaf_pos + __leaf->_M_size._M_data; 00109 typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction; 00110 char_producer<_CharT>* __fn = __STATIC_CAST(const _RopeFunction*, __leaf)->_M_fn; 00111 00112 if (__buf_start_pos + __len <= __pos) { 00113 __buf_start_pos = __pos - __len/4; 00114 if (__buf_start_pos + __len > __leaf_end) { 00115 __buf_start_pos = __leaf_end - __len; 00116 } 00117 } 00118 if (__buf_start_pos + __len > __leaf_end) { 00119 __len = __leaf_end - __buf_start_pos; 00120 } 00121 (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf._M_data); 00122 __x._M_buf_ptr = __x._M_tmp_buf._M_data + (__pos - __buf_start_pos); 00123 __x._M_buf_start = __x._M_tmp_buf._M_data; 00124 __x._M_buf_end = __x._M_tmp_buf._M_data + __len; 00125 } 00126 break; 00127 default: 00128 _STLP_ASSERT(0) 00129 ; 00130 } 00131 } 00132 00133 // Set path and buffer inside a rope iterator. We assume that 00134 // pos and root are already set. 00135 template <class _CharT, class _Alloc> 00136 void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache( 00137 _Rope_iterator_base<_CharT,_Alloc>& __x) { 00138 const _RopeRep* __path[_RopeRep::_S_max_rope_depth+1]; 00139 const _RopeRep* __curr_rope; 00140 int __curr_depth = -1; /* index into path */ 00141 size_t __curr_start_pos = 0; 00142 size_t __pos = __x._M_current_pos; 00143 unsigned char __dirns = 0; // Bit vector marking right turns in the path 00144 00145 _STLP_ASSERT(__pos <= __x._M_root->_M_size._M_data) 00146 if (__pos >= __x._M_root->_M_size._M_data) { 00147 __x._M_buf_ptr = 0; 00148 return; 00149 } 00150 __curr_rope = __x._M_root; 00151 if (0 != __curr_rope->_M_c_string) { 00152 /* Treat the root as a leaf. */ 00153 __x._M_buf_start = __curr_rope->_M_c_string; 00154 __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size._M_data; 00155 __x._M_buf_ptr = __curr_rope->_M_c_string + __pos; 00156 __x._M_path_end._M_data[0] = __curr_rope; 00157 __x._M_leaf_index = 0; 00158 __x._M_leaf_pos = 0; 00159 return; 00160 } 00161 for(;;) { 00162 ++__curr_depth; 00163 _STLP_ASSERT(__curr_depth <= _RopeRep::_S_max_rope_depth) 00164 __path[__curr_depth] = __curr_rope; 00165 switch(__curr_rope->_M_tag) { 00166 case _RopeRep::_S_leaf: 00167 case _RopeRep::_S_function: 00168 case _RopeRep::_S_substringfn: 00169 __x._M_leaf_pos = __curr_start_pos; 00170 goto done; 00171 case _RopeRep::_S_concat: 00172 { 00173 const _RopeConcat* __c = __STATIC_CAST(const _RopeConcat*, __curr_rope); 00174 _RopeRep* __left = __c->_M_left; 00175 size_t __left_len = __left->_M_size._M_data; 00176 00177 __dirns <<= 1; 00178 if (__pos >= __curr_start_pos + __left_len) { 00179 __dirns |= 1; 00180 __curr_rope = __c->_M_right; 00181 __curr_start_pos += __left_len; 00182 } else { 00183 __curr_rope = __left; 00184 } 00185 } 00186 break; 00187 } 00188 } 00189 done: 00190 // Copy last section of path into _M_path_end. 00191 { 00192 int __i = -1; 00193 int __j = __curr_depth + 1 - _S_path_cache_len; 00194 00195 if (__j < 0) __j = 0; 00196 while (__j <= __curr_depth) { 00197 __x._M_path_end._M_data[++__i] = __path[__j++]; 00198 } 00199 __x._M_leaf_index = __i; 00200 } 00201 __x._M_path_directions = __dirns; 00202 _S_setbuf(__x); 00203 } 00204 00205 // Specialized version of the above. Assumes that 00206 // the path cache is valid for the previous position. 00207 template <class _CharT, class _Alloc> 00208 void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache_for_incr( 00209 _Rope_iterator_base<_CharT,_Alloc>& __x) { 00210 int __current_index = __x._M_leaf_index; 00211 const _RopeRep* __current_node = __x._M_path_end._M_data[__current_index]; 00212 size_t __len = __current_node->_M_size._M_data; 00213 size_t __node_start_pos = __x._M_leaf_pos; 00214 unsigned char __dirns = __x._M_path_directions; 00215 const _RopeConcat* __c; 00216 00217 _STLP_ASSERT(__x._M_current_pos <= __x._M_root->_M_size._M_data) 00218 if (__x._M_current_pos - __node_start_pos < __len) { 00219 /* More stuff in this leaf, we just didn't cache it. */ 00220 _S_setbuf(__x); 00221 return; 00222 } 00223 _STLP_ASSERT(__node_start_pos + __len == __x._M_current_pos) 00224 // node_start_pos is starting position of last_node. 00225 while (--__current_index >= 0) { 00226 if (!(__dirns & 1) /* Path turned left */) 00227 break; 00228 __current_node = __x._M_path_end._M_data[__current_index]; 00229 __c = __STATIC_CAST(const _RopeConcat*, __current_node); 00230 // Otherwise we were in the right child. Thus we should pop 00231 // the concatenation node. 00232 __node_start_pos -= __c->_M_left->_M_size._M_data; 00233 __dirns >>= 1; 00234 } 00235 if (__current_index < 0) { 00236 // We underflowed the cache. Punt. 00237 _S_setcache(__x); 00238 return; 00239 } 00240 __current_node = __x._M_path_end._M_data[__current_index]; 00241 __c = __STATIC_CAST(const _RopeConcat*, __current_node); 00242 // current_node is a concatenation node. We are positioned on the first 00243 // character in its right child. 00244 // node_start_pos is starting position of current_node. 00245 __node_start_pos += __c->_M_left->_M_size._M_data; 00246 __current_node = __c->_M_right; 00247 __x._M_path_end._M_data[++__current_index] = __current_node; 00248 __dirns |= 1; 00249 while (_RopeRep::_S_concat == __current_node->_M_tag) { 00250 ++__current_index; 00251 if (_S_path_cache_len == __current_index) { 00252 int __i; 00253 for (__i = 0; __i < _S_path_cache_len-1; ++__i) { 00254 __x._M_path_end._M_data[__i] = __x._M_path_end._M_data[__i+1]; 00255 } 00256 --__current_index; 00257 } 00258 __current_node = __STATIC_CAST(const _RopeConcat*, __current_node)->_M_left; 00259 __x._M_path_end._M_data[__current_index] = __current_node; 00260 __dirns <<= 1; 00261 // node_start_pos is unchanged. 00262 } 00263 __x._M_leaf_index = __current_index; 00264 __x._M_leaf_pos = __node_start_pos; 00265 __x._M_path_directions = __dirns; 00266 _S_setbuf(__x); 00267 } 00268 00269 template <class _CharT, class _Alloc> 00270 void _Rope_iterator_base<_CharT,_Alloc>::_M_incr(size_t __n) { 00271 _M_current_pos += __n; 00272 if (0 != _M_buf_ptr) { 00273 size_t __chars_left = _M_buf_end - _M_buf_ptr; 00274 if (__chars_left > __n) { 00275 _M_buf_ptr += __n; 00276 } else if (__chars_left == __n) { 00277 _M_buf_ptr += __n; 00278 _S_setcache_for_incr(*this); 00279 } else { 00280 _M_buf_ptr = 0; 00281 } 00282 } 00283 } 00284 00285 template <class _CharT, class _Alloc> 00286 void _Rope_iterator_base<_CharT,_Alloc>::_M_decr(size_t __n) { 00287 if (0 != _M_buf_ptr) { 00288 size_t __chars_left = _M_buf_ptr - _M_buf_start; 00289 if (__chars_left >= __n) { 00290 _M_buf_ptr -= __n; 00291 } else { 00292 _M_buf_ptr = 0; 00293 } 00294 } 00295 _M_current_pos -= __n; 00296 } 00297 00298 template <class _CharT, class _Alloc> 00299 void _Rope_iterator<_CharT,_Alloc>::_M_check() { 00300 if (_M_root_rope->_M_tree_ptr._M_data != this->_M_root) { 00301 // _Rope was modified. Get things fixed up. 00302 _RopeRep::_S_unref(this->_M_root); 00303 this->_M_root = _M_root_rope->_M_tree_ptr._M_data; 00304 _RopeRep::_S_ref(this->_M_root); 00305 this->_M_buf_ptr = 0; 00306 } 00307 } 00308 00309 // There are several reasons for not doing this with virtual destructors 00310 // and a class specific delete operator: 00311 // - A class specific delete operator can't easily get access to 00312 // allocator instances if we need them. 00313 // - Any virtual function would need a 4 or byte vtable pointer; 00314 // this only requires a one byte tag per object. 00315 template <class _CharT, class _Alloc> 00316 void _Rope_RopeRep<_CharT,_Alloc>::_M_free_tree() { 00317 switch (_M_tag) { 00318 case _S_leaf: 00319 { 00320 typedef _Rope_RopeLeaf<_CharT, _Alloc> _RopeLeaf; 00321 _RopeLeaf* __l = __STATIC_CAST(_RopeLeaf*, this); 00322 _STLP_STD::_Destroy(__l); // ->_Rope_RopeLeaf<_CharT,_Alloc>::~_Rope_RopeLeaf(); 00323 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, 00324 _RopeLeaf).deallocate(__l, 1); 00325 break; 00326 } 00327 case _S_concat: 00328 { 00329 typedef _Rope_RopeConcatenation<_CharT, _Alloc> _RopeConcatenation; 00330 _RopeConcatenation* __c = __STATIC_CAST(_RopeConcatenation*, this); 00331 _STLP_STD::_Destroy(__c); 00332 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, 00333 _RopeConcatenation).deallocate(__c, 1); 00334 break; 00335 } 00336 case _S_function: 00337 { 00338 typedef _Rope_RopeFunction<_CharT, _Alloc> _RopeFunction; 00339 _RopeFunction* __f = __STATIC_CAST(_RopeFunction*, this); 00340 _STLP_STD::_Destroy(__f); 00341 _STLP_CREATE_ALLOCATOR(allocator_type, (const allocator_type&)_M_size, 00342 _RopeFunction).deallocate(__f, 1); 00343 break; 00344 } 00345 case _S_substringfn: 00346 { 00347 typedef _Rope_RopeSubstring<_CharT, _Alloc> _RopeSubstring; 00348 _RopeSubstring* __rss = __STATIC_CAST(_RopeSubstring*, this); 00349 _STLP_STD::_Destroy(__rss); 00350 _STLP_CREATE_ALLOCATOR(allocator_type, (const allocator_type&)_M_size, 00351 _RopeSubstring).deallocate(__rss, 1); 00352 break; 00353 } 00354 } 00355 } 00356 00357 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) 00358 # define __RopeLeaf__ _Rope_RopeLeaf<_CharT,_Alloc> 00359 # define __RopeRep__ _Rope_RopeRep<_CharT,_Alloc> 00360 # define _RopeLeaf _Rope_RopeLeaf<_CharT,_Alloc> 00361 # define _RopeRep _Rope_RopeRep<_CharT,_Alloc> 00362 # define size_type size_t 00363 # else 00364 # define __RopeLeaf__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeLeaf 00365 # define __RopeRep__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeRep 00366 # endif 00367 00368 template <class _CharT, class _Alloc> 00369 void rope<_CharT, _Alloc>::_M_throw_out_of_range() const { 00370 __stl_throw_out_of_range("rope"); 00371 } 00372 00373 // Concatenate a C string onto a leaf rope by copying the rope data. 00374 // Used for short ropes. 00375 template <class _CharT, class _Alloc> 00376 __RopeLeaf__* 00377 rope<_CharT,_Alloc>::_S_leaf_concat_char_iter ( 00378 _RopeLeaf* __r, const _CharT* __iter, size_t __len) { 00379 size_t __old_len = __r->_M_size._M_data; 00380 _CharT* __new_data = __r->_M_size.allocate(_S_rounded_up_size(__old_len + __len)); 00381 _RopeLeaf* __result; 00382 00383 _STLP_PRIV __ucopy_n(__r->_M_data, __old_len, __new_data); 00384 _STLP_PRIV __ucopy_n(__iter, __len, __new_data + __old_len); 00385 _S_construct_null(__new_data + __old_len + __len); 00386 _STLP_TRY { 00387 __result = _S_new_RopeLeaf(__new_data, __old_len + __len, __r->get_allocator()); 00388 } 00389 _STLP_UNWIND(_RopeRep::_S_free_string(__new_data, __old_len + __len, 00390 __r->get_allocator())) 00391 return __result; 00392 } 00393 00394 template <class _CharT, class _Alloc> 00395 void _Terminate_RopeLeaf(_Rope_RopeLeaf<_CharT,_Alloc> *__r, 00396 size_t __size, const __true_type& /*basic char type*/) { 00397 _S_construct_null(__r->_M_data + __size); 00398 _STLP_ASSERT(__r->_M_c_string == __r->_M_data) 00399 } 00400 00401 template <class _CharT, class _Alloc> 00402 void _Terminate_RopeLeaf(_Rope_RopeLeaf<_CharT,_Alloc> *__r, 00403 size_t, const __false_type& /*basic char type*/) { 00404 if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string) { 00405 __r->_M_free_c_string(); 00406 __r->_M_c_string = 0; 00407 } 00408 } 00409 00410 // As above, but it's OK to clobber original if refcount is 1 00411 template <class _CharT, class _Alloc> 00412 __RopeLeaf__* 00413 rope<_CharT,_Alloc>::_S_destr_leaf_concat_char_iter (_RopeLeaf* __r, const _CharT* __iter, size_t __len) { 00414 //_STLP_ASSERT(__r->_M_ref_count >= 1) 00415 if ( /* __r->_M_ref_count > 1 */ __r->_M_incr() > 2 ) { // - ptr 00416 __r->_M_decr(); // - ptr 00417 return _S_leaf_concat_char_iter(__r, __iter, __len); 00418 } 00419 __r->_M_decr(); // - ptr, __r->_M_ref_count == 1 or 0 00420 size_t __old_len = __r->_M_size._M_data; 00421 if (_S_rounded_up_size(__old_len) == _S_rounded_up_size(__old_len + __len)) { 00422 // The space has been partially initialized for the standard 00423 // character types. But that doesn't matter for those types. 00424 _STLP_PRIV __ucopy_n(__iter, __len, __r->_M_data + __old_len); 00425 _Terminate_RopeLeaf(__r, __old_len + __len, _IsBasicCharType()); 00426 __r->_M_size._M_data = __old_len + __len; 00427 // _STLP_ASSERT(__r->_M_ref_count == 1) 00428 // __r->_M_ref_count = 2; 00429 __r->_M_incr(); // i.e. __r->_M_ref_count = 2 00430 return __r; 00431 } else { 00432 _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len); 00433 //_STLP_ASSERT(__result->_M_ref_count == 1) 00434 return __result; 00435 } 00436 } 00437 00438 // Assumes left and right are not 0. 00439 // Does not increment (nor decrement on exception) child reference counts. 00440 // Result has ref count 1. 00441 template <class _CharT, class _Alloc> 00442 __RopeRep__* 00443 rope<_CharT,_Alloc>::_S_tree_concat (_RopeRep* __left, _RopeRep* __right) { 00444 _RopeConcatenation* __result = 00445 _S_new_RopeConcatenation(__left, __right, __left->get_allocator()); 00446 size_t __depth = __result->_M_depth; 00447 00448 _STLP_ASSERT(__left->get_allocator() == __right->get_allocator()) 00449 if (__depth > 20 && (__result->_M_size._M_data < 1000 || 00450 __depth > _RopeRep::_S_max_rope_depth)) { 00451 _RopeRep* __balanced; 00452 00453 _STLP_TRY { 00454 __balanced = _S_balance(__result); 00455 // _STLP_ASSERT(__result == __balanced || 00456 // 1 == __result->_M_ref_count && 00457 // 1 == __balanced->_M_ref_count) 00458 __result->_M_unref_nonnil(); 00459 } 00460 _STLP_UNWIND((_STLP_CREATE_ALLOCATOR(allocator_type,(allocator_type&)__left->_M_size, 00461 _RopeConcatenation).deallocate(__result,1))) 00462 // In case of exception, we need to deallocate 00463 // otherwise dangling result node. But caller 00464 // still owns its children. Thus unref is 00465 // inappropriate. 00466 return __balanced; 00467 } else { 00468 return __result; 00469 } 00470 } 00471 00472 template <class _CharT, class _Alloc> 00473 __RopeRep__* 00474 rope<_CharT,_Alloc>::_S_concat_char_iter (_RopeRep* __r, 00475 const _CharT*__s, size_t __slen) { 00476 _RopeRep* __result; 00477 if (0 == __slen) { 00478 _S_ref(__r); 00479 return __r; 00480 } 00481 if (0 == __r) 00482 return _S_RopeLeaf_from_unowned_char_ptr(__s, __slen, __r->get_allocator()); 00483 if (_RopeRep::_S_leaf == __r->_M_tag && 00484 __r->_M_size._M_data + __slen <= _S_copy_max) { 00485 __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen); 00486 // _STLP_ASSERT(1 == __result->_M_ref_count) 00487 return __result; 00488 } 00489 if (_RopeRep::_S_concat == __r->_M_tag && 00490 _RopeRep::_S_leaf == ((_RopeConcatenation*)__r)->_M_right->_M_tag) { 00491 _RopeLeaf* __right = (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right); 00492 if (__right->_M_size._M_data + __slen <= _S_copy_max) { 00493 _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left; 00494 _RopeRep* __nright = _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen); 00495 __left->_M_ref_nonnil(); 00496 _STLP_TRY { 00497 __result = _S_tree_concat(__left, __nright); 00498 } 00499 _STLP_UNWIND(_S_unref(__left); _S_unref(__nright)) 00500 // _STLP_ASSERT(1 == __result->_M_ref_count) 00501 return __result; 00502 } 00503 } 00504 _RopeRep* __nright = 00505 _S_RopeLeaf_from_unowned_char_ptr(__s, __slen, __r->get_allocator()); 00506 _STLP_TRY { 00507 __r->_M_ref_nonnil(); 00508 __result = _S_tree_concat(__r, __nright); 00509 } 00510 _STLP_UNWIND(_S_unref(__r); _S_unref(__nright)) 00511 // _STLP_ASSERT(1 == __result->_M_ref_count) 00512 return __result; 00513 } 00514 00515 template <class _CharT, class _Alloc> 00516 __RopeRep__* 00517 rope<_CharT,_Alloc>::_S_destr_concat_char_iter( 00518 _RopeRep* __r, const _CharT* __s, size_t __slen) { 00519 _RopeRep* __result; 00520 if (0 == __r) 00521 return _S_RopeLeaf_from_unowned_char_ptr(__s, __slen, 00522 __r->get_allocator()); 00523 // size_t __count = __r->_M_ref_count; 00524 size_t __orig_size = __r->_M_size._M_data; 00525 // _STLP_ASSERT(__count >= 1) 00526 if ( /* __count > 1 */ __r->_M_incr() > 2 ) { 00527 __r->_M_decr(); 00528 return _S_concat_char_iter(__r, __s, __slen); 00529 } 00530 if (0 == __slen) { 00531 return __r; 00532 } 00533 __r->_M_decr(); 00534 if (__orig_size + __slen <= _S_copy_max && _RopeRep::_S_leaf == __r->_M_tag) { 00535 return _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen); 00536 } 00537 if (_RopeRep::_S_concat == __r->_M_tag) { 00538 _RopeLeaf* __right = __STATIC_CAST(_RopeLeaf*, __STATIC_CAST(_RopeConcatenation*, __r)->_M_right); 00539 if (_RopeRep::_S_leaf == __right->_M_tag && 00540 __right->_M_size._M_data + __slen <= _S_copy_max) { 00541 _RopeRep* __new_right = _S_destr_leaf_concat_char_iter(__right, __s, __slen); 00542 if (__right == __new_right) { 00543 // _STLP_ASSERT(__new_right->_M_ref_count == 2) 00544 // __new_right->_M_ref_count = 1; 00545 __new_right->_M_decr(); 00546 } else { 00547 // _STLP_ASSERT(__new_right->_M_ref_count >= 1) 00548 __right->_M_unref_nonnil(); 00549 } 00550 // _STLP_ASSERT(__r->_M_ref_count == 1) 00551 // __r->_M_ref_count = 2; // One more than before. 00552 __r->_M_incr(); 00553 __STATIC_CAST(_RopeConcatenation*, __r)->_M_right = __new_right; 00554 // E.Musser : moved below 00555 // __r->_M_size._M_data = __orig_size + __slen; 00556 if (0 != __r->_M_c_string) { 00557 __r->_M_free_c_string(); 00558 __r->_M_c_string = 0; 00559 } 00560 __r->_M_size._M_data = __orig_size + __slen; 00561 return __r; 00562 } 00563 } 00564 _RopeRep* __right = 00565 _S_RopeLeaf_from_unowned_char_ptr(__s, __slen, __r->get_allocator()); 00566 __r->_M_ref_nonnil(); 00567 _STLP_TRY { 00568 __result = _S_tree_concat(__r, __right); 00569 } 00570 _STLP_UNWIND(_S_unref(__r); _S_unref(__right)) 00571 // _STLP_ASSERT(1 == __result->_M_ref_count) 00572 return __result; 00573 } 00574 00575 template <class _CharT, class _Alloc> 00576 __RopeRep__* 00577 rope<_CharT,_Alloc>::_S_concat_rep(_RopeRep* __left, _RopeRep* __right) { 00578 if (0 == __left) { 00579 _S_ref(__right); 00580 return __right; 00581 } 00582 if (0 == __right) { 00583 __left->_M_ref_nonnil(); 00584 return __left; 00585 } 00586 if (_RopeRep::_S_leaf == __right->_M_tag) { 00587 if (_RopeRep::_S_leaf == __left->_M_tag) { 00588 if (__right->_M_size._M_data + __left->_M_size._M_data <= _S_copy_max) { 00589 return _S_leaf_concat_char_iter(__STATIC_CAST(_RopeLeaf*, __left), 00590 __STATIC_CAST(_RopeLeaf*, __right)->_M_data, 00591 __right->_M_size._M_data); 00592 } 00593 } else if (_RopeRep::_S_concat == __left->_M_tag && 00594 _RopeRep::_S_leaf == __STATIC_CAST(_RopeConcatenation*, __left)->_M_right->_M_tag) { 00595 _RopeLeaf* __leftright = 00596 __STATIC_CAST(_RopeLeaf*, __STATIC_CAST(_RopeConcatenation*, __left)->_M_right); 00597 if (__leftright->_M_size._M_data + __right->_M_size._M_data <= _S_copy_max) { 00598 _RopeRep* __leftleft = __STATIC_CAST(_RopeConcatenation*, __left)->_M_left; 00599 _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright, 00600 __STATIC_CAST(_RopeLeaf*, __right)->_M_data, 00601 __right->_M_size._M_data); 00602 __leftleft->_M_ref_nonnil(); 00603 _STLP_TRY { 00604 return _S_tree_concat(__leftleft, __rest); 00605 } 00606 _STLP_UNWIND(_S_unref(__leftleft); _S_unref(__rest)) 00607 } 00608 } 00609 } 00610 __left->_M_ref_nonnil(); 00611 __right->_M_ref_nonnil(); 00612 _STLP_TRY { 00613 return _S_tree_concat(__left, __right); 00614 } 00615 _STLP_UNWIND(_S_unref(__left); _S_unref(__right)) 00616 _STLP_RET_AFTER_THROW(0) 00617 } 00618 00619 template <class _CharT, class _Alloc> 00620 __RopeRep__* 00621 rope<_CharT,_Alloc>::_S_substring(_RopeRep* __base, 00622 size_t __start, size_t __endp1) { 00623 if (0 == __base) return 0; 00624 size_t __len = __base->_M_size._M_data; 00625 size_t __adj_endp1; 00626 const size_t __lazy_threshold = 128; 00627 00628 if (__endp1 >= __len) { 00629 if (0 == __start) { 00630 __base->_M_ref_nonnil(); 00631 return __base; 00632 } else { 00633 __adj_endp1 = __len; 00634 } 00635 } else { 00636 __adj_endp1 = __endp1; 00637 } 00638 switch(__base->_M_tag) { 00639 case _RopeRep::_S_concat: 00640 { 00641 _RopeConcatenation* __c = __STATIC_CAST(_RopeConcatenation*, __base); 00642 _RopeRep* __left = __c->_M_left; 00643 _RopeRep* __right = __c->_M_right; 00644 size_t __left_len = __left->_M_size._M_data; 00645 _RopeRep* __result; 00646 00647 if (__adj_endp1 <= __left_len) { 00648 return _S_substring(__left, __start, __endp1); 00649 } else if (__start >= __left_len) { 00650 return _S_substring(__right, __start - __left_len, 00651 __adj_endp1 - __left_len); 00652 } 00653 _Self_destruct_ptr __left_result(_S_substring(__left, __start, __left_len)); 00654 _Self_destruct_ptr __right_result(_S_substring(__right, 0, __endp1 - __left_len)); 00655 _STLP_MPWFIX_TRY //*TY 06/01/2000 - mpw forgets to call dtor on __left_result and __right_result without this try block 00656 __result = _S_concat_rep(__left_result, __right_result); 00657 // _STLP_ASSERT(1 == __result->_M_ref_count) 00658 return __result; 00659 _STLP_MPWFIX_CATCH //*TY 06/01/2000 - 00660 } 00661 case _RopeRep::_S_leaf: 00662 { 00663 _RopeLeaf* __l = __STATIC_CAST(_RopeLeaf*, __base); 00664 _RopeLeaf* __result; 00665 size_t __result_len; 00666 if (__start >= __adj_endp1) return 0; 00667 __result_len = __adj_endp1 - __start; 00668 if (__result_len > __lazy_threshold) goto lazy; 00669 const _CharT* __section = __l->_M_data + __start; 00670 // We should sometimes create substring node instead. 00671 __result = _S_RopeLeaf_from_unowned_char_ptr(__section, __result_len, 00672 __base->get_allocator()); 00673 return __result; 00674 } 00675 case _RopeRep::_S_substringfn: 00676 // Avoid introducing multiple layers of substring nodes. 00677 { 00678 _RopeSubstring* __old = __STATIC_CAST(_RopeSubstring*, __base); 00679 size_t __result_len; 00680 if (__start >= __adj_endp1) return 0; 00681 __result_len = __adj_endp1 - __start; 00682 if (__result_len > __lazy_threshold) { 00683 _RopeSubstring* __result = _S_new_RopeSubstring(__old->_M_base, 00684 __start + __old->_M_start, 00685 __adj_endp1 - __start, 00686 __base->get_allocator()); 00687 return __result; 00688 } // *** else fall through: *** 00689 } 00690 case _RopeRep::_S_function: 00691 { 00692 _RopeFunction* __f = __STATIC_CAST(_RopeFunction*, __base); 00693 if (__start >= __adj_endp1) return 0; 00694 size_t __result_len = __adj_endp1 - __start; 00695 00696 if (__result_len > __lazy_threshold) goto lazy; 00697 _CharT* __section = __base->_M_size.allocate(_S_rounded_up_size(__result_len)); 00698 _STLP_TRY { 00699 (*(__f->_M_fn))(__start, __result_len, __section); 00700 } 00701 _STLP_UNWIND(_RopeRep::_S_free_string(__section, 00702 __result_len, __base->get_allocator())) 00703 _S_construct_null(__section + __result_len); 00704 return _S_new_RopeLeaf(__section, __result_len, 00705 __base->get_allocator()); 00706 } 00707 } 00708 /*NOTREACHED*/ 00709 _STLP_ASSERT(false) 00710 lazy: 00711 { 00712 // Create substring node. 00713 return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start, 00714 __base->get_allocator()); 00715 } 00716 } 00717 00718 template<class _CharT> 00719 class _Rope_flatten_char_consumer : public _Rope_char_consumer<_CharT> { 00720 private: 00721 _CharT* _M_buf_ptr; 00722 public: 00723 _Rope_flatten_char_consumer(_CharT* __buffer) { 00724 _M_buf_ptr = __buffer; 00725 } 00726 ~_Rope_flatten_char_consumer() {} 00727 bool operator() (const _CharT* __leaf, size_t __n) { 00728 _STLP_PRIV __ucopy_n(__leaf, __n, _M_buf_ptr); 00729 _M_buf_ptr += __n; 00730 return true; 00731 } 00732 }; 00733 00734 template<class _CharT> 00735 class _Rope_find_char_char_consumer : public _Rope_char_consumer<_CharT> { 00736 private: 00737 _CharT _M_pattern; 00738 public: 00739 size_t _M_count; // Number of nonmatching characters 00740 _Rope_find_char_char_consumer(_CharT __p) 00741 : _M_pattern(__p), _M_count(0) {} 00742 ~_Rope_find_char_char_consumer() {} 00743 bool operator() (const _CharT* __leaf, size_t __n) { 00744 size_t __i; 00745 for (__i = 0; __i < __n; ++__i) { 00746 if (__leaf[__i] == _M_pattern) { 00747 _M_count += __i; return false; 00748 } 00749 } 00750 _M_count += __n; return true; 00751 } 00752 }; 00753 00754 #if !defined (_STLP_USE_NO_IOSTREAMS) 00755 template<class _CharT, class _Traits> 00756 // Here _CharT is both the stream and rope character type. 00757 class _Rope_insert_char_consumer : public _Rope_char_consumer<_CharT> { 00758 private: 00759 typedef basic_ostream<_CharT,_Traits> _Insert_ostream; 00760 typedef _Rope_insert_char_consumer<_CharT,_Traits> _Self; 00761 _Insert_ostream& _M_o; 00762 00763 //explicitely defined as private to avoid warnings: 00764 _Self& operator = (_Self const&); 00765 public: 00766 _Rope_insert_char_consumer(_Insert_ostream& __writer) 00767 : _M_o(__writer) {} 00768 ~_Rope_insert_char_consumer() {} 00769 // Caller is presumed to own the ostream 00770 bool operator() (const _CharT* __leaf, size_t __n); 00771 // Returns true to continue traversal. 00772 }; 00773 00774 template<class _CharT, class _Traits> 00775 bool _Rope_insert_char_consumer<_CharT, _Traits>::operator() 00776 (const _CharT* __leaf, size_t __n) { 00777 size_t __i; 00778 // We assume that formatting is set up correctly for each element. 00779 for (__i = 0; __i < __n; ++__i) _M_o.put(__leaf[__i]); 00780 return true; 00781 } 00782 #endif /* !_STLP_USE_NO_IOSTREAMS */ 00783 00784 template <class _CharT, class _Alloc, class _CharConsumer> 00785 bool _S_apply_to_pieces(_CharConsumer& __c, 00786 _Rope_RopeRep<_CharT, _Alloc> * __r, 00787 size_t __begin, size_t __end) { 00788 typedef _Rope_RopeRep<_CharT, _Alloc> _RopeRep; 00789 typedef _Rope_RopeConcatenation<_CharT,_Alloc> _RopeConcatenation; 00790 typedef _Rope_RopeLeaf<_CharT,_Alloc> _RopeLeaf; 00791 typedef _Rope_RopeFunction<_CharT,_Alloc> _RopeFunction; 00792 00793 if (0 == __r) return true; 00794 switch(__r->_M_tag) { 00795 case _RopeRep::_S_concat: 00796 { 00797 _RopeConcatenation* __conc = __STATIC_CAST(_RopeConcatenation*, __r); 00798 _RopeRep* __left = __conc->_M_left; 00799 size_t __left_len = __left->_M_size._M_data; 00800 if (__begin < __left_len) { 00801 size_t __left_end = (min) (__left_len, __end); 00802 if (!_S_apply_to_pieces(__c, __left, __begin, __left_end)) 00803 return false; 00804 } 00805 if (__end > __left_len) { 00806 _RopeRep* __right = __conc->_M_right; 00807 size_t __right_start = (max)(__left_len, __begin); 00808 if (!_S_apply_to_pieces(__c, __right, 00809 __right_start - __left_len, 00810 __end - __left_len)) { 00811 return false; 00812 } 00813 } 00814 } 00815 return true; 00816 case _RopeRep::_S_leaf: 00817 { 00818 _RopeLeaf* __l = __STATIC_CAST(_RopeLeaf*, __r); 00819 return __c(__l->_M_data + __begin, __end - __begin); 00820 } 00821 case _RopeRep::_S_function: 00822 case _RopeRep::_S_substringfn: 00823 { 00824 _RopeFunction* __f = __STATIC_CAST(_RopeFunction*, __r); 00825 size_t __len = __end - __begin; 00826 bool __result; 00827 _CharT* __buffer = __r->get_allocator().allocate(__len); 00828 _STLP_TRY { 00829 (*(__f->_M_fn))(__begin, __len, __buffer); 00830 __result = __c(__buffer, __len); 00831 __r->get_allocator().deallocate(__buffer, __len); 00832 } 00833 _STLP_UNWIND((__r->get_allocator().deallocate(__buffer, __len))) 00834 return __result; 00835 } 00836 default: 00837 _STLP_ASSERT(false) 00838 /*NOTREACHED*/ 00839 return false; 00840 } 00841 } 00842 00843 #if !defined (_STLP_USE_NO_IOSTREAMS) 00844 template<class _CharT, class _Traits> 00845 inline void _Rope_fill(basic_ostream<_CharT, _Traits>& __o, streamsize __n) { 00846 char __f = __o.fill(); 00847 for (streamsize __i = 0; __i < __n; ++__i) __o.put(__f); 00848 } 00849 00850 template<class _CharT, class _Traits, class _Alloc> 00851 basic_ostream<_CharT, _Traits>& _S_io_get(basic_ostream<_CharT, _Traits>& __o, 00852 const rope<_CharT, _Alloc>& __r, const __true_type& /*_IsBasicCharType*/) { 00853 streamsize __w = __o.width(); 00854 const bool __left = (__o.flags() & ios::left) != 0; 00855 size_t __rope_len = __r.size(); 00856 _Rope_insert_char_consumer<_CharT, _Traits> __c(__o); 00857 00858 const bool __need_pad = (((sizeof(streamsize) > sizeof(size_t)) && (__STATIC_CAST(streamsize, __rope_len) < __w)) || 00859 ((sizeof(streamsize) <= sizeof(size_t)) && (__rope_len < __STATIC_CAST(size_t, __w)))); 00860 streamsize __pad_len = __need_pad ? __w - __rope_len : 0; 00861 00862 if (!__left && __pad_len > 0) { 00863 _Rope_fill(__o, __pad_len); 00864 } 00865 __r.apply_to_pieces(0, __rope_len, __c); 00866 if (__left && __pad_len > 0) { 00867 _Rope_fill(__o, __pad_len); 00868 } 00869 return __o; 00870 } 00871 00872 template<class _CharT, class _Traits, class _Alloc> 00873 basic_ostream<_CharT, _Traits>& _S_io_get(basic_ostream<_CharT, _Traits>& __o, 00874 const rope<_CharT, _Alloc>& __r, const __false_type& /*_IsBasicCharType*/) { 00875 streamsize __w = __o.width(); 00876 size_t __rope_len = __r.size(); 00877 _Rope_insert_char_consumer<_CharT, _Traits> __c(__o); 00878 00879 __o.width(__w /__rope_len); 00880 _STLP_TRY { 00881 __r.apply_to_pieces(0, __rope_len, __c); 00882 __o.width(__w); 00883 } 00884 _STLP_UNWIND(__o.width(__w)) 00885 return __o; 00886 } 00887 00888 template<class _CharT, class _Traits, class _Alloc> 00889 basic_ostream<_CharT, _Traits>& operator<<(basic_ostream<_CharT, _Traits>& __o, 00890 const rope<_CharT, _Alloc>& __r) { 00891 typedef typename _IsIntegral<_CharT>::_Ret _Char_Is_Integral; 00892 return _S_io_get(__o, __r, _Char_Is_Integral()); 00893 } 00894 #endif /* NO_IOSTREAMS */ 00895 00896 template <class _CharT, class _Alloc> 00897 _CharT* rope<_CharT,_Alloc>::_S_flatten(_RopeRep* __r, 00898 size_t __start, size_t __len, 00899 _CharT* __buffer) { 00900 _Rope_flatten_char_consumer<_CharT> __c(__buffer); 00901 _S_apply_to_pieces(__c, __r, __start, __start + __len); 00902 return(__buffer + __len); 00903 } 00904 00905 template <class _CharT, class _Alloc> 00906 size_t rope<_CharT,_Alloc>::find(_CharT __pattern, size_t __start) const { 00907 _Rope_find_char_char_consumer<_CharT> __c(__pattern); 00908 _S_apply_to_pieces(__c, _M_tree_ptr._M_data, __start, size()); 00909 size_type __result_pos = __start + __c._M_count; 00910 #ifndef _STLP_OLD_ROPE_SEMANTICS 00911 if (__result_pos == size()) __result_pos = npos; 00912 #endif 00913 return __result_pos; 00914 } 00915 00916 template <class _CharT, class _Alloc> 00917 _CharT* 00918 rope<_CharT,_Alloc>::_S_flatten(_Rope_RopeRep<_CharT, _Alloc>* __r, _CharT* __buffer) { 00919 if (0 == __r) return __buffer; 00920 switch(__r->_M_tag) { 00921 case _RopeRep::_S_concat: 00922 { 00923 _RopeConcatenation* __c = __STATIC_CAST(_RopeConcatenation*, __r); 00924 _RopeRep* __left = __c->_M_left; 00925 _RopeRep* __right = __c->_M_right; 00926 _CharT* __rest = _S_flatten(__left, __buffer); 00927 return _S_flatten(__right, __rest); 00928 } 00929 case _RopeRep::_S_leaf: 00930 { 00931 _RopeLeaf* __l = __STATIC_CAST(_RopeLeaf*, __r); 00932 return _STLP_PRIV __ucopy_n(__l->_M_data, __l->_M_size._M_data, __buffer).second; 00933 } 00934 case _RopeRep::_S_function: 00935 case _RopeRep::_S_substringfn: 00936 // We dont yet do anything with substring nodes. 00937 // This needs to be fixed before ropefiles will work well. 00938 { 00939 _RopeFunction* __f = __STATIC_CAST(_RopeFunction*, __r); 00940 (*(__f->_M_fn))(0, __f->_M_size._M_data, __buffer); 00941 return __buffer + __f->_M_size._M_data; 00942 } 00943 default: 00944 _STLP_ASSERT(false) 00945 /*NOTREACHED*/ 00946 return 0; 00947 } 00948 } 00949 00950 #ifdef _STLP_DEBUG 00951 // This needs work for _CharT != char 00952 template <class _CharT, class _Alloc> 00953 void rope<_CharT,_Alloc>::_S_dump(_RopeRep* __r, int __indent) { 00954 for (int __i = 0; __i < __indent; ++__i) putchar(' '); 00955 if (0 == __r) { 00956 printf("NULL\n"); return; 00957 } 00958 if (_RopeRep::_S_concat == __r->_M_tag) { 00959 _RopeConcatenation* __c = __STATIC_CAST(_RopeConcatenation*, __r); 00960 _RopeRep* __left = __c->_M_left; 00961 _RopeRep* __right = __c->_M_right; 00962 printf("Concatenation %p (rc = %ld, depth = %d, len = %ld, %s balanced)\n", 00963 __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data, 00964 __r->_M_is_balanced? "" : "not"); 00965 _S_dump(__left, __indent + 2); 00966 _S_dump(__right, __indent + 2); 00967 return; 00968 } 00969 else { 00970 const char* __kind; 00971 00972 switch (__r->_M_tag) { 00973 case _RopeRep::_S_leaf: 00974 __kind = "Leaf"; 00975 break; 00976 case _RopeRep::_S_function: 00977 __kind = "Function"; 00978 break; 00979 case _RopeRep::_S_substringfn: 00980 __kind = "Function representing substring"; 00981 break; 00982 default: 00983 __kind = "(corrupted kind field!)"; 00984 } 00985 printf("%s %p (rc = %ld, depth = %d, len = %ld) ", 00986 __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data); 00987 if (sizeof(_CharT) == 1) { 00988 const int __max_len = 40; 00989 _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len)); 00990 _CharT __buffer[__max_len + 1]; 00991 bool __too_big = __r->_M_size._M_data > __prefix->_M_size._M_data; 00992 00993 _S_flatten(__prefix, __buffer); 00994 __buffer[__prefix->_M_size._M_data] = _STLP_DEFAULT_CONSTRUCTED(_CharT); 00995 printf("%s%s\n", (char*)__buffer, __too_big? "...\n" : "\n"); 00996 } else { 00997 printf("\n"); 00998 } 00999 } 01000 } 01001 #endif /* _STLP_DEBUG */ 01002 01003 # define __ROPE_TABLE_BODY = { \ 01004 /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21, \ 01005 /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377, \ 01006 /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181, \ 01007 /* 18 */6765ul, /* 19 */10946ul, /* 20 */17711ul, /* 21 */28657ul, /* 22 */46368ul, \ 01008 /* 23 */75025ul, /* 24 */121393ul, /* 25 */196418ul, /* 26 */317811ul, \ 01009 /* 27 */514229ul, /* 28 */832040ul, /* 29 */1346269ul, /* 30 */2178309ul, \ 01010 /* 31 */3524578ul, /* 32 */5702887ul, /* 33 */9227465ul, /* 34 */14930352ul, \ 01011 /* 35 */24157817ul, /* 36 */39088169ul, /* 37 */63245986ul, /* 38 */102334155ul, \ 01012 /* 39 */165580141ul, /* 40 */267914296ul, /* 41 */433494437ul, \ 01013 /* 42 */701408733ul, /* 43 */1134903170ul, /* 44 */1836311903ul, \ 01014 /* 45 */2971215073ul } 01015 01016 template <class _CharT, class _Alloc> 01017 const unsigned long 01018 rope<_CharT,_Alloc>::_S_min_len[__ROPE_DEPTH_SIZE] __ROPE_TABLE_BODY; 01019 # undef __ROPE_DEPTH_SIZE 01020 # undef __ROPE_MAX_DEPTH 01021 # undef __ROPE_TABLE_BODY 01022 01023 // These are Fibonacci numbers < 2**32. 01024 01025 template <class _CharT, class _Alloc> 01026 __RopeRep__* rope<_CharT,_Alloc>::_S_balance(_RopeRep* __r) { 01027 _RopeRep* __forest[_RopeRep::_S_max_rope_depth + 1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 01028 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 01029 0,0,0,0,0,0}; 01030 _RopeRep* __result = 0; 01031 int __i; 01032 // Invariant: 01033 // The concatenation of forest in descending order is equal to __r. 01034 // __forest[__i]._M_size._M_data >= _S_min_len[__i] 01035 // __forest[__i]._M_depth = __i 01036 // References from forest are included in refcount. 01037 01038 _STLP_TRY { 01039 _S_add_to_forest(__r, __forest); 01040 for (__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i) 01041 if (0 != __forest[__i]) { 01042 _Self_destruct_ptr __old(__result); 01043 __result = _S_concat_rep(__forest[__i], __result); 01044 __forest[__i]->_M_unref_nonnil(); 01045 # ifdef _STLP_USE_EXCEPTIONS 01046 __forest[__i] = 0; 01047 # endif 01048 } 01049 } 01050 _STLP_UNWIND(for(__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i) 01051 _S_unref(__forest[__i])) 01052 if (__result->_M_depth > _RopeRep::_S_max_rope_depth) { 01053 __stl_throw_range_error("rope too long"); 01054 } 01055 return(__result); 01056 } 01057 01058 01059 template <class _CharT, class _Alloc> 01060 void 01061 rope<_CharT,_Alloc>::_S_add_to_forest(_RopeRep* __r, _RopeRep** __forest) 01062 { 01063 if (__r -> _M_is_balanced) { 01064 _S_add_leaf_to_forest(__r, __forest); 01065 return; 01066 } 01067 _STLP_ASSERT(__r->_M_tag == _RopeRep::_S_concat) 01068 { 01069 _RopeConcatenation* __c = (_RopeConcatenation*)__r; 01070 01071 _S_add_to_forest(__c->_M_left, __forest); 01072 _S_add_to_forest(__c->_M_right, __forest); 01073 } 01074 } 01075 01076 01077 template <class _CharT, class _Alloc> 01078 void 01079 rope<_CharT,_Alloc>::_S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest) 01080 { 01081 _RopeRep* __insertee; // included in refcount 01082 _RopeRep* __too_tiny = 0; // included in refcount 01083 int __i; // forest[0..__i-1] is empty 01084 size_t __s = __r->_M_size._M_data; 01085 01086 for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i) { 01087 if (0 != __forest[__i]) { 01088 _Self_destruct_ptr __old(__too_tiny); 01089 __too_tiny = _S_concat_and_set_balanced(__forest[__i], __too_tiny); 01090 __forest[__i]->_M_unref_nonnil(); 01091 __forest[__i] = 0; 01092 } 01093 } 01094 { 01095 _Self_destruct_ptr __old(__too_tiny); 01096 __insertee = _S_concat_and_set_balanced(__too_tiny, __r); 01097 } 01098 // Too_tiny dead, and no longer included in refcount. 01099 // Insertee is live and included. 01100 _STLP_ASSERT(_S_is_almost_balanced(__insertee)) 01101 _STLP_ASSERT(__insertee->_M_depth <= __r->_M_depth + 1) 01102 for (;; ++__i) { 01103 if (0 != __forest[__i]) { 01104 _Self_destruct_ptr __old(__insertee); 01105 __insertee = _S_concat_and_set_balanced(__forest[__i], __insertee); 01106 __forest[__i]->_M_unref_nonnil(); 01107 __forest[__i] = 0; 01108 _STLP_ASSERT(_S_is_almost_balanced(__insertee)) 01109 } 01110 _STLP_ASSERT(_S_min_len[__i] <= __insertee->_M_size._M_data) 01111 _STLP_ASSERT(__forest[__i] == 0) 01112 if (__i == _RopeRep::_S_max_rope_depth || 01113 __insertee->_M_size._M_data < _S_min_len[__i+1]) { 01114 __forest[__i] = __insertee; 01115 // refcount is OK since __insertee is now dead. 01116 return; 01117 } 01118 } 01119 } 01120 01121 template <class _CharT, class _Alloc> 01122 _CharT 01123 rope<_CharT,_Alloc>::_S_fetch(_RopeRep* __r, size_type __i) 01124 { 01125 _CharT* __cstr = __r->_M_c_string; 01126 01127 _STLP_ASSERT(__i < __r->_M_size._M_data) 01128 if (0 != __cstr) return __cstr[__i]; 01129 for(;;) { 01130 switch(__r->_M_tag) { 01131 case _RopeRep::_S_concat: 01132 { 01133 _RopeConcatenation* __c = (_RopeConcatenation*)__r; 01134 _RopeRep* __left = __c->_M_left; 01135 size_t __left_len = __left->_M_size._M_data; 01136 01137 if (__i >= __left_len) { 01138 __i -= __left_len; 01139 __r = __c->_M_right; 01140 } else { 01141 __r = __left; 01142 } 01143 } 01144 break; 01145 case _RopeRep::_S_leaf: 01146 { 01147 _RopeLeaf* __l = (_RopeLeaf*)__r; 01148 return __l->_M_data[__i]; 01149 } 01150 case _RopeRep::_S_function: 01151 case _RopeRep::_S_substringfn: 01152 { 01153 _RopeFunction* __f = (_RopeFunction*)__r; 01154 _CharT __result; 01155 01156 (*(__f->_M_fn))(__i, 1, &__result); 01157 return __result; 01158 } 01159 } 01160 } 01161 #if defined(_STLP_NEED_UNREACHABLE_RETURN) 01162 return 0; 01163 #endif 01164 } 01165 01166 // Return a uniquely referenced character slot for the given 01167 // position, or 0 if that's not possible. 01168 template <class _CharT, class _Alloc> 01169 _CharT* 01170 rope<_CharT,_Alloc>::_S_fetch_ptr(_RopeRep* __r, size_type __i) 01171 { 01172 _RopeRep* __clrstack[_RopeRep::_S_max_rope_depth]; 01173 size_t __csptr = 0; 01174 01175 for(;;) { 01176 // if (__r->_M_ref_count > 1) return 0; 01177 if ( __r->_M_incr() > 2 ) { 01178 __r->_M_decr(); 01179 return 0; 01180 } 01181 switch(__r->_M_tag) { 01182 case _RopeRep::_S_concat: 01183 { 01184 _RopeConcatenation* __c = (_RopeConcatenation*)__r; 01185 _RopeRep* __left = __c->_M_left; 01186 size_t __left_len = __left->_M_size._M_data; 01187 01188 if (__c->_M_c_string != 0) __clrstack[__csptr++] = __c; 01189 if (__i >= __left_len) { 01190 __i -= __left_len; 01191 __r = __c->_M_right; 01192 } else { 01193 __r = __left; 01194 } 01195 } 01196 break; 01197 case _RopeRep::_S_leaf: 01198 { 01199 _RopeLeaf* __l = (_RopeLeaf*)__r; 01200 if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0) 01201 __clrstack[__csptr++] = __l; 01202 while (__csptr > 0) { 01203 -- __csptr; 01204 _RopeRep* __d = __clrstack[__csptr]; 01205 __d->_M_free_c_string(); 01206 __d->_M_c_string = 0; 01207 } 01208 return __l->_M_data + __i; 01209 } 01210 case _RopeRep::_S_function: 01211 case _RopeRep::_S_substringfn: 01212 return 0; 01213 } 01214 } 01215 #if defined(_STLP_NEED_UNREACHABLE_RETURN) 01216 return 0; 01217 #endif 01218 01219 } 01220 01221 // The following could be implemented trivially using 01222 // lexicographical_compare_3way. 01223 // We do a little more work to avoid dealing with rope iterators for 01224 // flat strings. 01225 template <class _CharT, class _Alloc> 01226 int 01227 rope<_CharT,_Alloc>::_S_compare (const _RopeRep* __left, 01228 const _RopeRep* __right) { 01229 size_t __left_len; 01230 size_t __right_len; 01231 01232 if (0 == __right) return 0 != __left; 01233 if (0 == __left) return -1; 01234 __left_len = __left->_M_size._M_data; 01235 __right_len = __right->_M_size._M_data; 01236 if (_RopeRep::_S_leaf == __left->_M_tag) { 01237 const _RopeLeaf* __l = __STATIC_CAST(const _RopeLeaf*, __left); 01238 if (_RopeRep::_S_leaf == __right->_M_tag) { 01239 const _RopeLeaf* __r = __STATIC_CAST(const _RopeLeaf*, __right); 01240 return _STLP_PRIV __lexicographical_compare_3way(__l->_M_data, __l->_M_data + __left_len, 01241 __r->_M_data, __r->_M_data + __right_len); 01242 } 01243 else { 01244 const_iterator __rstart(__right, 0); 01245 const_iterator __rend(__right, __right_len); 01246 return _STLP_PRIV __lexicographical_compare_3way(__l->_M_data, __l->_M_data + __left_len, 01247 __rstart, __rend); 01248 } 01249 } 01250 else { 01251 const_iterator __lstart(__left, 0); 01252 const_iterator __lend(__left, __left_len); 01253 if (_RopeRep::_S_leaf == __right->_M_tag) { 01254 const _RopeLeaf* __r = __STATIC_CAST(const _RopeLeaf*, __right); 01255 return _STLP_PRIV __lexicographical_compare_3way(__lstart, __lend, 01256 __r->_M_data, __r->_M_data + __right_len); 01257 } 01258 else { 01259 const_iterator __rstart(__right, 0); 01260 const_iterator __rend(__right, __right_len); 01261 return _STLP_PRIV __lexicographical_compare_3way(__lstart, __lend, __rstart, __rend); 01262 } 01263 } 01264 } 01265 01266 // Assignment to reference proxies. 01267 template <class _CharT, class _Alloc> 01268 _Rope_char_ref_proxy<_CharT, _Alloc>& 01269 _Rope_char_ref_proxy<_CharT, _Alloc>::operator= (_CharT __c) { 01270 _RopeRep* __old = _M_root->_M_tree_ptr._M_data; 01271 // First check for the case in which everything is uniquely 01272 // referenced. In that case we can do this destructively. 01273 _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos); 01274 if (0 != __ptr) { 01275 *__ptr = __c; 01276 return *this; 01277 } 01278 _Self_destruct_ptr __left( 01279 _My_rope::_S_substring(__old, 0, _M_pos)); 01280 _Self_destruct_ptr __right( 01281 _My_rope::_S_substring(__old, _M_pos+1, __old->_M_size._M_data)); 01282 _Self_destruct_ptr __result_left( 01283 _My_rope::_S_destr_concat_char_iter(__left, &__c, 1)); 01284 01285 // _STLP_ASSERT(__left == __result_left || 1 == __result_left->_M_ref_count) 01286 _RopeRep* __result = 01287 _My_rope::_S_concat_rep(__result_left, __right); 01288 // _STLP_ASSERT(1 <= __result->_M_ref_count) 01289 _RopeRep::_S_unref(__old); 01290 _M_root->_M_tree_ptr._M_data = __result; 01291 return *this; 01292 } 01293 01294 template <class _CharT, class _Alloc> 01295 _Rope_char_ptr_proxy<_CharT, _Alloc> 01296 _Rope_char_ref_proxy<_CharT, _Alloc>::operator& () const { 01297 return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this); 01298 } 01299 01300 template<class _CharT, class _Alloc> 01301 _CharT rope<_CharT,_Alloc>::_S_empty_c_str[1] = { _CharT() }; 01302 // # endif 01303 01304 #if !defined (_STLP_STATIC_CONST_INIT_BUG) && !defined (_STLP_NO_STATIC_CONST_DEFINITION) 01305 template <class _CharT, class _Alloc> 01306 const size_t rope<_CharT, _Alloc>::npos; 01307 #endif 01308 01309 template<class _CharT, class _Alloc> 01310 const _CharT* rope<_CharT,_Alloc>::c_str() const { 01311 if (0 == _M_tree_ptr._M_data) { 01312 // Possibly redundant, but probably fast. 01313 _S_empty_c_str[0] = _STLP_DEFAULT_CONSTRUCTED(_CharT); 01314 return _S_empty_c_str; 01315 } 01316 _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string; 01317 if (0 != __old_c_string) return __old_c_string; 01318 size_t __s = size(); 01319 _CharT* __result = _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).allocate(__s + 1); 01320 _S_flatten(_M_tree_ptr._M_data, __result); 01321 _S_construct_null(__result + __s); 01322 __old_c_string = __STATIC_CAST(_CharT*, _Atomic_swap_ptr(__REINTERPRET_CAST(void* _STLP_VOLATILE*, &(_M_tree_ptr._M_data->_M_c_string)), 01323 __result)); 01324 if (0 != __old_c_string) { 01325 // It must have been added in the interim. Hence it had to have been 01326 // separately allocated. Deallocate the old copy, since we just 01327 // replaced it. 01328 _STLP_STD::_Destroy_Range(__old_c_string, __old_c_string + __s + 1); 01329 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).deallocate(__old_c_string, __s + 1); 01330 } 01331 return __result; 01332 } 01333 01334 template<class _CharT, class _Alloc> 01335 const _CharT* rope<_CharT,_Alloc>::replace_with_c_str() { 01336 if (0 == _M_tree_ptr._M_data) { 01337 _S_empty_c_str[0] = _STLP_DEFAULT_CONSTRUCTED(_CharT); 01338 return _S_empty_c_str; 01339 } 01340 _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string; 01341 if (_RopeRep::_S_leaf == _M_tree_ptr._M_data->_M_tag && 0 != __old_c_string) { 01342 return __old_c_string; 01343 } 01344 size_t __s = size(); 01345 _CharT* __result = _M_tree_ptr.allocate(_S_rounded_up_size(__s)); 01346 _S_flatten(_M_tree_ptr._M_data, __result); 01347 _S_construct_null(__result + __s); 01348 _M_tree_ptr._M_data->_M_unref_nonnil(); 01349 _M_tree_ptr._M_data = _S_new_RopeLeaf(__result, __s, _M_tree_ptr); 01350 return __result; 01351 } 01352 01353 // Algorithm specializations. More should be added. 01354 01355 #if (!defined (_STLP_MSVC) || (_STLP_MSVC >= 1310)) && !defined (__DMC__) 01356 // I couldn't get this to work with VC++ 01357 template<class _CharT,class _Alloc> 01358 void _Rope_rotate(_Rope_iterator<_CharT,_Alloc> __first, 01359 _Rope_iterator<_CharT,_Alloc> __middle, 01360 _Rope_iterator<_CharT,_Alloc> __last) { 01361 _STLP_ASSERT(__first.container() == __middle.container() && 01362 __middle.container() == __last.container()) 01363 rope<_CharT,_Alloc>& __r(__first.container()); 01364 rope<_CharT,_Alloc> __prefix = __r.substr(0, __first.index()); 01365 rope<_CharT,_Alloc> __suffix = 01366 __r.substr(__last.index(), __r.size() - __last.index()); 01367 rope<_CharT,_Alloc> __part1 = 01368 __r.substr(__middle.index(), __last.index() - __middle.index()); 01369 rope<_CharT,_Alloc> __part2 = 01370 __r.substr(__first.index(), __middle.index() - __first.index()); 01371 __r = __prefix; 01372 __r += __part1; 01373 __r += __part2; 01374 __r += __suffix; 01375 } 01376 01377 01378 # if 0 01379 // Probably not useful for several reasons: 01380 // - for SGIs 7.1 compiler and probably some others, 01381 // this forces lots of rope<wchar_t, ...> instantiations, creating a 01382 // code bloat and compile time problem. (Fixed in 7.2.) 01383 // - wchar_t is 4 bytes wide on most UNIX platforms, making it unattractive 01384 // for unicode strings. Unsigned short may be a better character 01385 // type. 01386 inline void rotate( 01387 _Rope_iterator<wchar_t, allocator<char> > __first, 01388 _Rope_iterator<wchar_t, allocator<char> > __middle, 01389 _Rope_iterator<wchar_t, allocator<char> > __last) { 01390 _Rope_rotate(__first, __middle, __last); 01391 } 01392 # endif 01393 #endif /* _STLP_MSVC */ 01394 01395 # undef __RopeLeaf__ 01396 # undef __RopeRep__ 01397 # undef __RopeLeaf 01398 # undef __RopeRep 01399 # undef size_type 01400 01401 _STLP_END_NAMESPACE 01402 01403 # endif /* ROPEIMPL_H */ 01404 01405 // Local Variables: 01406 // mode:C++ 01407 // End: Generated on Sun May 27 2012 04:29:21 for ReactOS by
1.7.6.1
|