Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

ropeimpl.h

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

Generated at Tue May 1 16:28:38 2001 for libstdc++-v3 by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001