ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.