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