2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
3 * Copyright (c) 1996,1997
4 * Silicon Graphics Computer Systems, Inc.
9 * This material is provided "as is", with absolutely no warranty expressed
10 * or implied. Any use is at your own risk.
12 * Permission to use or copy this software for any purpose is hereby granted
13 * without fee, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
20 /* NOTE: This is an internal header file, included by other STL headers.
21 * You should not attempt to use it directly.
24 // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
25 // if necessary. Assumes path_end[leaf_index] and leaf_pos are correct.
26 // Results in a valid buf_ptr if the iterator can be legitimately
28 # ifndef _STLP_ROPEIMPL_H
29 # define _STLP_ROPEIMPL_H
31 #ifndef _STLP_INTERNAL_ROPE_H
32 # include <stl/_rope.h>
39 #ifndef _STLP_IOSTREAM
43 # include <stl/_range_errors.h>
47 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
48 # define __allocator__ _Alloc
50 # define __allocator__ allocator_type
53 template<class _CharT, class _Alloc>
54 _Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos)
55 : _Rope_iterator_base<_CharT,_Alloc>(__r->_M_tree_ptr._M_data, __pos),
56 _M_root_rope(__r) { _RopeRep::_S_ref(this->_M_root); }
58 template<class _CharT, class _Alloc>
59 _Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos):
60 _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr._M_data, __pos),
62 _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*this);
65 template<class _CharT, class _Alloc>
67 _Rope_RopeRep<_CharT, _Alloc>::_M_free_c_string()
69 _CharT* __cstr = _M_c_string;
71 size_t _p_size = _M_size._M_data + 1;
72 _STLP_STD::_Destroy(__cstr, __cstr + _p_size);
73 _M_size.deallocate(__cstr, _p_size);
78 // Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
79 // if necessary. Assumes _M_path_end[leaf_index] and leaf_pos are correct.
80 // Results in a valid buf_ptr if the iterator can be legitimately
82 template <class _CharT, class _Alloc>
83 void _Rope_iterator_base<_CharT,_Alloc>::_S_setbuf(
84 _Rope_iterator_base<_CharT,_Alloc>& __x)
86 const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index];
87 size_t __leaf_pos = __x._M_leaf_pos;
88 size_t __pos = __x._M_current_pos;
90 switch(__leaf->_M_tag) {
91 case _RopeRep::_S_leaf:
93 ((_Rope_RopeLeaf<_CharT,_Alloc>*)__leaf)->_M_data;
94 __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos);
95 __x._M_buf_end = __x._M_buf_start + __leaf->_M_size._M_data;
97 case _RopeRep::_S_function:
98 case _RopeRep::_S_substringfn:
100 size_t __len = _S_iterator_buf_len;
101 size_t __buf_start_pos = __leaf_pos;
102 size_t __leaf_end = __leaf_pos + __leaf->_M_size._M_data;
103 char_producer<_CharT>* __fn =
104 ((_Rope_RopeFunction<_CharT,_Alloc>*)__leaf)->_M_fn;
106 if (__buf_start_pos + __len <= __pos) {
107 __buf_start_pos = __pos - __len/4;
108 if (__buf_start_pos + __len > __leaf_end) {
109 __buf_start_pos = __leaf_end - __len;
112 if (__buf_start_pos + __len > __leaf_end) {
113 __len = __leaf_end - __buf_start_pos;
115 (*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf);
116 __x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos);
117 __x._M_buf_start = __x._M_tmp_buf;
118 __x._M_buf_end = __x._M_tmp_buf + __len;
127 // Set path and buffer inside a rope iterator. We assume that
128 // pos and root are already set.
129 template <class _CharT, class _Alloc>
130 void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache
131 (_Rope_iterator_base<_CharT,_Alloc>& __x)
133 const _RopeRep* __path[_RopeRep::_S_max_rope_depth+1];
134 const _RopeRep* __curr_rope;
135 int __curr_depth = -1; /* index into path */
136 size_t __curr_start_pos = 0;
137 size_t __pos = __x._M_current_pos;
138 unsigned char __dirns = 0; // Bit vector marking right turns in the path
140 _STLP_ASSERT(__pos <= __x._M_root->_M_size._M_data)
141 if (__pos >= __x._M_root->_M_size._M_data) {
145 __curr_rope = __x._M_root;
146 if (0 != __curr_rope->_M_c_string) {
147 /* Treat the root as a leaf. */
148 __x._M_buf_start = __curr_rope->_M_c_string;
149 __x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size._M_data;
150 __x._M_buf_ptr = __curr_rope->_M_c_string + __pos;
151 __x._M_path_end[0] = __curr_rope;
152 __x._M_leaf_index = 0;
158 _STLP_ASSERT(__curr_depth <= _RopeRep::_S_max_rope_depth)
159 __path[__curr_depth] = __curr_rope;
160 switch(__curr_rope->_M_tag) {
161 case _RopeRep::_S_leaf:
162 case _RopeRep::_S_function:
163 case _RopeRep::_S_substringfn:
164 __x._M_leaf_pos = __curr_start_pos;
166 case _RopeRep::_S_concat:
168 _Rope_RopeConcatenation<_CharT,_Alloc>* __c =
169 (_Rope_RopeConcatenation<_CharT,_Alloc>*)__curr_rope;
170 _RopeRep* __left = __c->_M_left;
171 size_t __left_len = __left->_M_size._M_data;
174 if (__pos >= __curr_start_pos + __left_len) {
176 __curr_rope = __c->_M_right;
177 __curr_start_pos += __left_len;
179 __curr_rope = __left;
186 // Copy last section of path into _M_path_end.
189 int __j = __curr_depth + 1 - _S_path_cache_len;
191 if (__j < 0) __j = 0;
192 while (__j <= __curr_depth) {
193 __x._M_path_end[++__i] = __path[__j++];
195 __x._M_leaf_index = __i;
197 __x._M_path_directions = __dirns;
201 // Specialized version of the above. Assumes that
202 // the path cache is valid for the previous position.
203 template <class _CharT, class _Alloc>
204 void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache_for_incr
205 (_Rope_iterator_base<_CharT,_Alloc>& __x)
207 int __current_index = __x._M_leaf_index;
208 const _RopeRep* __current_node = __x._M_path_end[__current_index];
209 size_t __len = __current_node->_M_size._M_data;
210 size_t __node_start_pos = __x._M_leaf_pos;
211 unsigned char __dirns = __x._M_path_directions;
212 _Rope_RopeConcatenation<_CharT,_Alloc>* __c;
214 _STLP_ASSERT(__x._M_current_pos <= __x._M_root->_M_size._M_data)
215 if (__x._M_current_pos - __node_start_pos < __len) {
216 /* More stuff in this leaf, we just didn't cache it. */
220 _STLP_ASSERT(__node_start_pos + __len == __x._M_current_pos)
221 // node_start_pos is starting position of last_node.
222 while (--__current_index >= 0) {
223 if (!(__dirns & 1) /* Path turned left */)
225 __current_node = __x._M_path_end[__current_index];
226 __c = (_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node;
227 // Otherwise we were in the right child. Thus we should pop
228 // the concatenation node.
229 __node_start_pos -= __c->_M_left->_M_size._M_data;
232 if (__current_index < 0) {
233 // We underflowed the cache. Punt.
237 __current_node = __x._M_path_end[__current_index];
238 __c = (_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node;
239 // current_node is a concatenation node. We are positioned on the first
240 // character in its right child.
241 // node_start_pos is starting position of current_node.
242 __node_start_pos += __c->_M_left->_M_size._M_data;
243 __current_node = __c->_M_right;
244 __x._M_path_end[++__current_index] = __current_node;
246 while (_RopeRep::_S_concat == __current_node->_M_tag) {
248 if (_S_path_cache_len == __current_index) {
250 for (__i = 0; __i < _S_path_cache_len-1; __i++) {
251 __x._M_path_end[__i] = __x._M_path_end[__i+1];
256 ((_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node)->_M_left;
257 __x._M_path_end[__current_index] = __current_node;
259 // node_start_pos is unchanged.
261 __x._M_leaf_index = __current_index;
262 __x._M_leaf_pos = __node_start_pos;
263 __x._M_path_directions = __dirns;
267 template <class _CharT, class _Alloc>
268 void _Rope_iterator_base<_CharT,_Alloc>::_M_incr(size_t __n) {
269 _M_current_pos += __n;
270 if (0 != _M_buf_ptr) {
271 size_t __chars_left = _M_buf_end - _M_buf_ptr;
272 if (__chars_left > __n) {
274 } else if (__chars_left == __n) {
276 _S_setcache_for_incr(*this);
283 template <class _CharT, class _Alloc>
284 void _Rope_iterator_base<_CharT,_Alloc>::_M_decr(size_t __n) {
285 if (0 != _M_buf_ptr) {
286 size_t __chars_left = _M_buf_ptr - _M_buf_start;
287 if (__chars_left >= __n) {
293 _M_current_pos -= __n;
296 template <class _CharT, class _Alloc>
297 void _Rope_iterator<_CharT,_Alloc>::_M_check() {
298 if (_M_root_rope->_M_tree_ptr._M_data != this->_M_root) {
299 // _Rope was modified. Get things fixed up.
300 _RopeRep::_S_unref(this->_M_root);
301 this->_M_root = _M_root_rope->_M_tree_ptr._M_data;
302 _RopeRep::_S_ref(this->_M_root);
303 this->_M_buf_ptr = 0;
308 // There are several reasons for not doing this with virtual destructors
309 // and a class specific delete operator:
310 // - A class specific delete operator can't easily get access to
311 // allocator instances if we need them.
312 // - Any virtual function would need a 4 or byte vtable pointer;
313 // this only requires a one byte tag per object.
314 template <class _CharT, class _Alloc>
315 void _Rope_RopeRep<_CharT,_Alloc>::_M_free_tree()
320 typedef _Rope_RopeLeaf<_CharT,_Alloc> _Rope_RopeLeaf_T;
321 _Rope_RopeLeaf_T* __l = (_Rope_RopeLeaf_T*)this;
322 _STLP_STD::_Destroy(__l); // ->_Rope_RopeLeaf<_CharT,_Alloc>::~_Rope_RopeLeaf();
323 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, _Rope_RopeLeaf_T).deallocate(__l, 1);
328 typedef _Rope_RopeConcatenation<_CharT,_Alloc> _Rope_RopeConcatenation_T;
329 _Rope_RopeConcatenation_T* __c = (_Rope_RopeConcatenation_T*)this;
330 _STLP_STD::_Destroy(__c);
331 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size,
332 _Rope_RopeConcatenation_T).deallocate(__c, 1);
337 typedef _Rope_RopeFunction<_CharT,_Alloc> _Rope_RopeFunctionT;
338 _Rope_RopeFunctionT* __f = (_Rope_RopeFunctionT*)this;
339 _STLP_STD::_Destroy(__f);
340 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size,
341 _Rope_RopeFunctionT).deallocate(__f, 1);
346 typedef _Rope_RopeSubstring<_CharT,_Alloc> _Rope_RopeSubstring_T;
347 _Rope_RopeSubstring_T* __ss = (_Rope_RopeSubstring_T*)this;
348 _STLP_STD::_Destroy(__ss);
349 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size,
350 _Rope_RopeSubstring_T).deallocate(__ss, 1);
357 # if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
358 # define __RopeLeaf__ _Rope_RopeLeaf<_CharT,_Alloc>
359 # define __RopeRep__ _Rope_RopeRep<_CharT,_Alloc>
360 # define _RopeLeaf _Rope_RopeLeaf<_CharT,_Alloc>
361 # define _RopeRep _Rope_RopeRep<_CharT,_Alloc>
362 # define size_type size_t
364 # define __RopeLeaf__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeLeaf
365 # define __RopeRep__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeRep
368 // Concatenate a C string onto a leaf rope by copying the rope data.
369 // Used for short ropes.
370 template <class _CharT, class _Alloc>
372 rope<_CharT,_Alloc>::_S_leaf_concat_char_iter
373 (_RopeLeaf* __r, const _CharT* __iter, size_t __len)
375 size_t __old_len = __r->_M_size._M_data;
376 _CharT* __new_data = __r->_M_size.allocate(_S_rounded_up_size(__old_len + __len));
379 uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
380 uninitialized_copy_n(__iter, __len, __new_data + __old_len);
381 _S_cond_store_eos(__new_data[__old_len + __len]);
383 __result = _S_new_RopeLeaf(__new_data, __old_len + __len,
384 __r->get_allocator());
386 _STLP_UNWIND(_RopeRep::_S_free_string(__new_data, __old_len + __len,
387 __r->get_allocator()));
392 // As above, but it's OK to clobber original if refcount is 1
393 template <class _CharT, class _Alloc>
395 rope<_CharT,_Alloc>::_S_destr_leaf_concat_char_iter
396 (_RopeLeaf* __r, const _CharT* __iter, size_t __len)
398 _STLP_ASSERT(__r->_M_ref_count >= 1)
399 if (__r->_M_ref_count > 1)
400 return _S_leaf_concat_char_iter(__r, __iter, __len);
401 size_t __old_len = __r->_M_size._M_data;
402 if (_S_allocated_capacity(__old_len) >= __old_len + __len) {
403 // The space has been partially initialized for the standard
404 // character types. But that doesn't matter for those types.
405 uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len);
406 if (_S_is_basic_char_type((_CharT*)0)) {
407 _S_cond_store_eos(__r->_M_data[__old_len + __len]);
408 _STLP_ASSERT(__r->_M_c_string == __r->_M_data)
409 } else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string) {
410 __r->_M_free_c_string();
411 __r->_M_c_string = 0;
413 __r->_M_size._M_data = __old_len + __len;
414 _STLP_ASSERT(__r->_M_ref_count == 1)
415 __r->_M_ref_count = 2;
418 _RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len);
419 _STLP_ASSERT(__result->_M_ref_count == 1)
425 // Assumes left and right are not 0.
426 // Does not increment (nor decrement on exception) child reference counts.
427 // Result has ref count 1.
428 template <class _CharT, class _Alloc>
430 rope<_CharT,_Alloc>::_S_tree_concat (_RopeRep* __left, _RopeRep* __right)
432 _RopeConcatenation* __result =
433 _S_new_RopeConcatenation(__left, __right, __left->get_allocator());
434 size_t __depth = __result->_M_depth;
436 _STLP_ASSERT(__left->get_allocator() == __right->get_allocator())
437 if (__depth > 20 && (__result->_M_size._M_data < 1000 ||
438 __depth > _RopeRep::_S_max_rope_depth)) {
439 _RopeRep* __balanced;
442 __balanced = _S_balance(__result);
444 if (__result != __balanced) {
445 _STLP_ASSERT(1 == __result->_M_ref_count
446 && 1 == __balanced->_M_ref_count)
449 __result->_M_unref_nonnil();
451 _STLP_UNWIND((_STLP_CREATE_ALLOCATOR(allocator_type,(allocator_type&)__left->_M_size,
452 _RopeConcatenation).deallocate(__result,1)));
453 // In case of exception, we need to deallocate
454 // otherwise dangling result node. But caller
455 // still owns its children. Thus unref is
463 template <class _CharT, class _Alloc>
465 rope<_CharT,_Alloc>::_S_concat_char_iter
466 (_RopeRep* __r, const _CharT*__s, size_t __slen)
474 return _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
475 /* __r->get_allocator()*/ allocator_type() );
476 if (_RopeRep::_S_leaf == __r->_M_tag &&
477 __r->_M_size._M_data + __slen <= _S_copy_max) {
478 __result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
480 _STLP_ASSERT(1 == __result->_M_ref_count)
484 if (_RopeRep::_S_concat == __r->_M_tag
485 && _RopeRep::_S_leaf == ((_RopeConcatenation*)__r)->_M_right->_M_tag) {
487 (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right);
488 if (__right->_M_size._M_data + __slen <= _S_copy_max) {
489 _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left;
491 _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen);
492 __left->_M_ref_nonnil();
494 __result = _S_tree_concat(__left, __nright);
496 _STLP_UNWIND(_S_unref(__left); _S_unref(__nright));
498 _STLP_ASSERT(1 == __result->_M_ref_count)
504 _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator());
506 __r->_M_ref_nonnil();
507 __result = _S_tree_concat(__r, __nright);
509 _STLP_UNWIND(_S_unref(__r); _S_unref(__nright));
511 _STLP_ASSERT(1 == __result->_M_ref_count)
517 template <class _CharT, class _Alloc>
519 rope<_CharT,_Alloc>::_S_destr_concat_char_iter(
520 _RopeRep* __r, const _CharT* __s, size_t __slen)
524 return _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
525 /* __r-> */allocator_type());
526 size_t __count = __r->_M_ref_count;
527 size_t __orig_size = __r->_M_size._M_data;
528 _STLP_ASSERT(__count >= 1)
529 if (__count > 1) return _S_concat_char_iter(__r, __s, __slen);
531 __r->_M_ref_count = 2; // One more than before
534 if (__orig_size + __slen <= _S_copy_max &&
535 _RopeRep::_S_leaf == __r->_M_tag) {
536 __result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
539 if (_RopeRep::_S_concat == __r->_M_tag) {
540 _RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*)__r)->_M_right);
541 if (_RopeRep::_S_leaf == __right->_M_tag
542 && __right->_M_size._M_data + __slen <= _S_copy_max) {
543 _RopeRep* __new_right =
544 _S_destr_leaf_concat_char_iter(__right, __s, __slen);
545 if (__right == __new_right) {
546 _STLP_ASSERT(__new_right->_M_ref_count == 2)
547 __new_right->_M_ref_count = 1;
549 _STLP_ASSERT(__new_right->_M_ref_count >= 1)
550 __right->_M_unref_nonnil();
552 _STLP_ASSERT(__r->_M_ref_count == 1)
553 __r->_M_ref_count = 2; // One more than before.
554 ((_RopeConcatenation*)__r)->_M_right = __new_right;
555 // E.Musser : moved below
556 // __r->_M_size._M_data = __orig_size + __slen;
557 if (0 != __r->_M_c_string) {
558 __r->_M_free_c_string();
559 __r->_M_c_string = 0;
561 __r->_M_size._M_data = __orig_size + __slen;
566 _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator());
567 __r->_M_ref_nonnil();
569 __result = _S_tree_concat(__r, __right);
571 _STLP_UNWIND(_S_unref(__r); _S_unref(__right))
572 _STLP_ASSERT(1 == __result->_M_ref_count)
577 template <class _CharT, class _Alloc>
579 rope<_CharT,_Alloc>::_S_concat_rep(_RopeRep* __left, _RopeRep* __right)
586 __left->_M_ref_nonnil();
589 if (_RopeRep::_S_leaf == __right->_M_tag) {
590 if (_RopeRep::_S_leaf == __left->_M_tag) {
591 if (__right->_M_size._M_data + __left->_M_size._M_data <= _S_copy_max) {
592 return _S_leaf_concat_char_iter((_RopeLeaf*)__left,
593 ((_RopeLeaf*)__right)->_M_data,
594 __right->_M_size._M_data);
596 } else if (_RopeRep::_S_concat == __left->_M_tag
597 && _RopeRep::_S_leaf ==
598 ((_RopeConcatenation*)__left)->_M_right->_M_tag) {
599 _RopeLeaf* __leftright =
600 (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right);
601 if (__leftright->_M_size._M_data + __right->_M_size._M_data <= _S_copy_max) {
602 _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left;
603 _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright,
604 ((_RopeLeaf*)__right)->_M_data,
605 __right->_M_size._M_data);
606 __leftleft->_M_ref_nonnil();
608 return(_S_tree_concat(__leftleft, __rest));
610 _STLP_UNWIND(_S_unref(__leftleft); _S_unref(__rest))
614 __left->_M_ref_nonnil();
615 __right->_M_ref_nonnil();
617 return(_S_tree_concat(__left, __right));
619 _STLP_UNWIND(_S_unref(__left); _S_unref(__right));
620 #ifdef _STLP_THROW_RETURN_BUG
625 template <class _CharT, class _Alloc>
627 rope<_CharT,_Alloc>::_S_substring(_RopeRep* __base,
628 size_t __start, size_t __endp1)
630 if (0 == __base) return 0;
631 size_t __len = __base->_M_size._M_data;
633 const size_t __lazy_threshold = 128;
635 if (__endp1 >= __len) {
637 __base->_M_ref_nonnil();
643 __adj_endp1 = __endp1;
645 switch(__base->_M_tag) {
646 case _RopeRep::_S_concat:
648 _RopeConcatenation* __c = (_RopeConcatenation*)__base;
649 _RopeRep* __left = __c->_M_left;
650 _RopeRep* __right = __c->_M_right;
651 size_t __left_len = __left->_M_size._M_data;
654 if (__adj_endp1 <= __left_len) {
655 return _S_substring(__left, __start, __endp1);
656 } else if (__start >= __left_len) {
657 return _S_substring(__right, __start - __left_len,
658 __adj_endp1 - __left_len);
660 _Self_destruct_ptr __left_result(
661 _S_substring(__left, __start, __left_len));
662 _Self_destruct_ptr __right_result(
663 _S_substring(__right, 0, __endp1 - __left_len));
664 _STLP_MPWFIX_TRY //*TY 06/01/2000 - mpw forgets to call dtor on __left_result and __right_result without this try block
665 __result = _S_concat_rep(__left_result, __right_result);
667 _STLP_ASSERT(1 == __result->_M_ref_count)
670 _STLP_MPWFIX_CATCH //*TY 06/01/2000 -
672 case _RopeRep::_S_leaf:
674 _RopeLeaf* __l = (_RopeLeaf*)__base;
677 if (__start >= __adj_endp1) return 0;
678 __result_len = __adj_endp1 - __start;
679 if (__result_len > __lazy_threshold) goto lazy;
681 const _CharT* __section = __l->_M_data + __start;
682 __result = _S_new_RopeLeaf(__section, __result_len,
683 __base->get_allocator());
684 __result->_M_c_string = 0; // Not eos terminated.
686 // We should sometimes create substring node instead.
687 __result = _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(
688 __l->_M_data + __start, __result_len,
689 __base->get_allocator());
693 case _RopeRep::_S_substringfn:
694 // Avoid introducing multiple layers of substring nodes.
696 _RopeSubstring* __old = (_RopeSubstring*)__base;
698 if (__start >= __adj_endp1) return 0;
699 __result_len = __adj_endp1 - __start;
700 if (__result_len > __lazy_threshold) {
701 _RopeSubstring* __result =
702 _S_new_RopeSubstring(__old->_M_base,
703 __start + __old->_M_start,
704 __adj_endp1 - __start,
705 __base->get_allocator());
708 } // *** else fall through: ***
710 case _RopeRep::_S_function:
712 _RopeFunction* __f = (_RopeFunction*)__base;
713 if (__start >= __adj_endp1) return 0;
714 size_t __result_len = __adj_endp1 - __start;
716 if (__result_len > __lazy_threshold) goto lazy;
717 _CharT* __section = __base->_M_size.allocate(_S_rounded_up_size(__result_len));
719 (*(__f->_M_fn))(__start, __result_len, __section);
721 _STLP_UNWIND(_RopeRep::_S_free_string(
722 __section, __result_len, __base->get_allocator()));
723 _S_cond_store_eos(__section[__result_len]);
724 return _S_new_RopeLeaf(__section, __result_len,
725 __base->get_allocator());
732 // Create substring node.
733 return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start,
734 __base->get_allocator());
738 template<class _CharT>
739 class _Rope_flatten_char_consumer : public _Rope_char_consumer<_CharT> {
743 // _CharT* _M_buffer; // XXX not used
745 _Rope_flatten_char_consumer(_CharT* __buffer) {
746 _M_buf_ptr = __buffer;
748 ~_Rope_flatten_char_consumer() {}
749 bool operator() (const _CharT* __leaf, size_t __n) {
750 uninitialized_copy_n(__leaf, __n, _M_buf_ptr);
756 template<class _CharT>
757 class _Rope_find_char_char_consumer : public _Rope_char_consumer<_CharT> {
761 size_t _M_count; // Number of nonmatching characters
762 _Rope_find_char_char_consumer(_CharT __p)
763 : _M_pattern(__p), _M_count(0) {}
764 ~_Rope_find_char_char_consumer() {}
765 bool operator() (const _CharT* __leaf, size_t __n) {
767 for (__i = 0; __i < __n; __i++) {
768 if (__leaf[__i] == _M_pattern) {
769 _M_count += __i; return false;
772 _M_count += __n; return true;
776 #if !defined (_STLP_USE_NO_IOSTREAMS)
777 #if defined (_STLP_USE_NEW_IOSTREAMS)
778 template<class _CharT, class _Traits>
779 // Here _CharT is both the stream and rope character type.
781 template<class _CharT>
782 // Here _CharT is the rope character type. Unlike in the
783 // above case, we somewhat handle the case in which it doesn't
784 // match the stream character type, i.e. char.
786 class _Rope_insert_char_consumer : public _Rope_char_consumer<_CharT> {
788 # if defined (_STLP_USE_NEW_IOSTREAMS)
789 typedef basic_ostream<_CharT,_Traits> _Insert_ostream;
791 typedef ostream _Insert_ostream;
793 _Insert_ostream& _M_o;
795 // _CharT* buffer; // XXX not used
796 _Rope_insert_char_consumer(_Insert_ostream& __writer)
798 #if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
799 ~_Rope_insert_char_consumer(); //*TY 05/23/2000 -
800 #else //*TY 05/23/2000 -
801 ~_Rope_insert_char_consumer() {}
802 #endif //*TY 05/23/2000 -
803 // Caller is presumed to own the ostream
804 bool operator() (const _CharT* __leaf, size_t __n);
805 // Returns true to continue traversal.
808 # if defined ( _STLP_USE_NEW_IOSTREAMS )
809 # if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
810 template<class _CharT, class _Traits>
811 _Rope_insert_char_consumer<_CharT, _Traits>:: ~_Rope_insert_char_consumer() {}
812 # endif //*TY 05/23/2000 -
814 template<class _CharT, class _Traits>
815 bool _Rope_insert_char_consumer<_CharT, _Traits>::operator()
816 (const _CharT* __leaf, size_t __n)
819 // We assume that formatting is set up correctly for each element.
820 for (__i = 0; __i < __n; __i++) _M_o.put(__leaf[__i]);
824 # if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__)) //*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
825 template<class _CharT>
826 _Rope_insert_char_consumer<_CharT>:: ~_Rope_insert_char_consumer() {}
827 # endif //*TY 05/23/2000 -
829 template<class _CharT>
830 bool _Rope_insert_char_consumer<_CharT>::operator()
831 (const _CharT* __leaf, size_t __n)
834 // We assume that formatting is set up correctly for each element.
835 for (__i = 0; __i < __n; __i++) _M_o << __leaf[__i];
839 # if !defined (_STLP_NO_METHOD_SPECIALIZATION)
842 _Rope_insert_char_consumer<char>::operator()
843 (const char* __leaf, size_t __n)
846 for (__i = 0; __i < __n; __i++) _M_o.put(__leaf[__i]);
850 #endif /* _STLP_METHOD_SPECIALIZATION */
851 #endif /* _STLP_USE_NEW_IOSTREAM */
852 #endif /* if !defined (_STLP_USE_NO_IOSTREAMS) */
854 template <class _CharT, class _Alloc>
855 bool rope<_CharT, _Alloc>::_S_apply_to_pieces(
856 _Rope_char_consumer<_CharT>& __c,
858 size_t __begin, size_t __end)
860 if (0 == __r) return true;
861 switch(__r->_M_tag) {
862 case _RopeRep::_S_concat:
864 _RopeConcatenation* __conc = (_RopeConcatenation*)__r;
865 _RopeRep* __left = __conc->_M_left;
866 size_t __left_len = __left->_M_size._M_data;
867 if (__begin < __left_len) {
868 size_t __left_end = (min) (__left_len, __end);
869 if (!_S_apply_to_pieces(__c, __left, __begin, __left_end))
872 if (__end > __left_len) {
873 _RopeRep* __right = __conc->_M_right;
874 size_t __right_start = (max)(__left_len, __begin);
875 if (!_S_apply_to_pieces(__c, __right,
876 __right_start - __left_len,
877 __end - __left_len)) {
883 case _RopeRep::_S_leaf:
885 _RopeLeaf* __l = (_RopeLeaf*)__r;
886 return __c.operator()(__l->_M_data + __begin, __end - __begin);
888 case _RopeRep::_S_function:
889 case _RopeRep::_S_substringfn:
891 _RopeFunction* __f = (_RopeFunction*)__r;
892 size_t __len = __end - __begin;
894 bool __result = false;
899 (_CharT*)__sgi_alloc::allocate(__len * sizeof(_CharT));
901 (*(__f->_M_fn))(__begin, __len, __buffer);
902 __result = __c.operator()(__buffer, __len);
903 __sgi_alloc::deallocate(__buffer, __len * sizeof(_CharT));
905 _STLP_UNWIND((__sgi_alloc::deallocate(__buffer,
906 __len * sizeof(_CharT))))
916 template <class _CharT> inline bool _Rope_is_simple(_CharT*) { return false; }
917 inline bool _Rope_is_simple(char*) { return true; }
918 # ifdef _STLP_HAS_WCHAR_T
919 inline bool _Rope_is_simple(wchar_t*) { return true; }
922 #if !defined (_STLP_USE_NO_IOSTREAMS)
923 #if defined (_STLP_USE_NEW_IOSTREAMS)
924 template<class _CharT, class _Traits>
925 inline void _Rope_fill(basic_ostream<_CharT, _Traits>& __o, size_t __n)
927 inline void _Rope_fill(ostream& __o, size_t __n)
930 char __f = __o.fill();
933 for (__i = 0; __i < __n; __i++) __o.put(__f);
936 #if defined (_STLP_USE_NEW_IOSTREAMS)
937 template<class _CharT, class _Traits, class _Alloc>
938 basic_ostream<_CharT, _Traits>& operator<<
939 (basic_ostream<_CharT, _Traits>& __o,
940 const rope<_CharT, _Alloc>& __r)
942 template<class _CharT, class _Alloc>
943 ostream& operator<< (ostream& __o, const rope<_CharT, _Alloc>& __r)
946 size_t __w = __o.width();
947 bool __left = bool(__o.flags() & ios::left);
949 size_t __rope_len = __r.size();
950 # if defined (_STLP_USE_NEW_IOSTREAMS)
951 _Rope_insert_char_consumer<_CharT, _Traits> __c(__o);
953 _Rope_insert_char_consumer<_CharT> __c(__o);
955 bool __is_simple = _Rope_is_simple((_CharT*)0);
957 if (__rope_len < __w) {
958 __pad_len = __w - __rope_len;
962 if (!__is_simple) __o.width(__w/__rope_len);
964 if (__is_simple && !__left && __pad_len > 0) {
965 _Rope_fill(__o, __pad_len);
967 __r.apply_to_pieces(0, __r.size(), __c);
968 if (__is_simple && __left && __pad_len > 0) {
969 _Rope_fill(__o, __pad_len);
974 _STLP_UNWIND(if (!__is_simple) __o.width(__w))
978 #endif /* NO_IOSTREAMS */
980 template <class _CharT, class _Alloc>
982 rope<_CharT,_Alloc>::_S_flatten(_RopeRep* __r,
983 size_t __start, size_t __len,
986 _Rope_flatten_char_consumer<_CharT> __c(__buffer);
987 _S_apply_to_pieces(__c, __r, __start, __start + __len);
988 return(__buffer + __len);
991 template <class _CharT, class _Alloc>
993 rope<_CharT,_Alloc>::find(_CharT __pattern, size_t __start) const
995 _Rope_find_char_char_consumer<_CharT> __c(__pattern);
996 _S_apply_to_pieces(__c, _M_tree_ptr._M_data, __start, size());
997 size_type __result_pos = __start + __c._M_count;
998 # ifndef _STLP_OLD_ROPE_SEMANTICS
999 if (__result_pos == size()) __result_pos = npos;
1001 return __result_pos;
1004 template <class _CharT, class _Alloc>
1006 rope<_CharT,_Alloc>::_S_flatten(_Rope_RopeRep<_CharT, _Alloc>* __r, _CharT* __buffer)
1008 if (0 == __r) return __buffer;
1009 switch(__r->_M_tag) {
1010 case _RopeRep::_S_concat:
1012 _RopeConcatenation* __c = (_RopeConcatenation*)__r;
1013 _RopeRep* __left = __c->_M_left;
1014 _RopeRep* __right = __c->_M_right;
1015 _CharT* __rest = _S_flatten(__left, __buffer);
1016 return _S_flatten(__right, __rest);
1018 case _RopeRep::_S_leaf:
1020 _RopeLeaf* __l = (_RopeLeaf*)__r;
1021 return copy_n(__l->_M_data, __l->_M_size._M_data, __buffer).second;
1023 case _RopeRep::_S_function:
1024 case _RopeRep::_S_substringfn:
1025 // We dont yet do anything with substring nodes.
1026 // This needs to be fixed before ropefiles will work well.
1028 _RopeFunction* __f = (_RopeFunction*)__r;
1029 (*(__f->_M_fn))(0, __f->_M_size._M_data, __buffer);
1030 return __buffer + __f->_M_size._M_data;
1040 // This needs work for _CharT != char
1041 template <class _CharT, class _Alloc>
1043 rope<_CharT,_Alloc>::_S_dump(_RopeRep* __r, int __indent)
1045 for (int __i = 0; __i < __indent; __i++) putchar(' ');
1047 printf("NULL\n"); return;
1049 if (_RopeRep::_S_concat == __r->_M_tag) {
1050 _RopeConcatenation* __c = (_RopeConcatenation*)__r;
1051 _RopeRep* __left = __c->_M_left;
1052 _RopeRep* __right = __c->_M_right;
1055 printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
1056 __r, __r->_M_depth, __r->_M_size._M_data, __r->_M_is_balanced? "" : "not");
1058 printf("Concatenation %p (rc = %ld, depth = %d, "
1059 "len = %ld, %s balanced)\n",
1060 __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data,
1061 __r->_M_is_balanced? "" : "not");
1063 _S_dump(__left, __indent + 2);
1064 _S_dump(__right, __indent + 2);
1069 switch (__r->_M_tag) {
1070 case _RopeRep::_S_leaf:
1073 case _RopeRep::_S_function:
1074 __kind = "Function";
1076 case _RopeRep::_S_substringfn:
1077 __kind = "Function representing substring";
1080 __kind = "(corrupted kind field!)";
1083 printf("%s %p (depth = %d, len = %ld) ",
1084 __kind, __r, __r->_M_depth, __r->_M_size._M_data);
1086 printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
1087 __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data);
1089 if (_S_is_one_byte_char_type((_CharT*)0)) {
1090 const int __max_len = 40;
1091 _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len));
1092 _CharT __buffer[__max_len + 1];
1093 bool __too_big = __r->_M_size._M_data > __prefix->_M_size._M_data;
1095 _S_flatten(__prefix, __buffer);
1096 __buffer[__prefix->_M_size._M_data] = _S_eos((_CharT*)0);
1098 (char*)__buffer, __too_big? "...\n" : "\n");
1105 # define __ROPE_TABLE_BODY = { \
1106 /* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21, \
1107 /* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377, \
1108 /* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181, \
1109 /* 18 */6765ul, /* 19 */10946ul, /* 20 */17711ul, /* 21 */28657ul, /* 22 */46368ul, \
1110 /* 23 */75025ul, /* 24 */121393ul, /* 25 */196418ul, /* 26 */317811ul, \
1111 /* 27 */514229ul, /* 28 */832040ul, /* 29 */1346269ul, /* 30 */2178309ul, \
1112 /* 31 */3524578ul, /* 32 */5702887ul, /* 33 */9227465ul, /* 34 */14930352ul, \
1113 /* 35 */24157817ul, /* 36 */39088169ul, /* 37 */63245986ul, /* 38 */102334155ul, \
1114 /* 39 */165580141ul, /* 40 */267914296ul, /* 41 */433494437ul, \
1115 /* 42 */701408733ul, /* 43 */1134903170ul, /* 44 */1836311903ul, \
1116 /* 45 */2971215073ul }
1118 # if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
1119 template <class _CharT, class _Alloc>
1121 rope<_CharT,_Alloc>::_S_min_len[__ROPE_DEPTH_SIZE] __ROPE_TABLE_BODY ;
1123 __DECLARE_INSTANCE(const unsigned long,
1124 crope::_S_min_len[__ROPE_DEPTH_SIZE],
1126 # ifndef _STLP_NO_WCHAR_T
1127 __DECLARE_INSTANCE(const unsigned long,
1128 wrope::_S_min_len[__ROPE_DEPTH_SIZE],
1132 # undef __ROPE_DEPTH_SIZE
1133 # undef __ROPE_MAX_DEPTH
1134 # undef __ROPE_TABLE_BODY
1136 // These are Fibonacci numbers < 2**32.
1138 template <class _CharT, class _Alloc>
1140 rope<_CharT,_Alloc>::_S_balance(_RopeRep* __r)
1142 _RopeRep* __forest[_RopeRep::_S_max_rope_depth + 1];
1143 _RopeRep* __result = 0;
1146 // The concatenation of forest in descending order is equal to __r.
1147 // __forest[__i]._M_size._M_data >= _S_min_len[__i]
1148 // __forest[__i]._M_depth = __i
1149 // References from forest are included in refcount.
1151 for (__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i)
1154 _S_add_to_forest(__r, __forest);
1155 for (__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i)
1156 if (0 != __forest[__i]) {
1158 _Self_destruct_ptr __old(__result);
1160 __result = _S_concat_rep(__forest[__i], __result);
1161 __forest[__i]->_M_unref_nonnil();
1162 # if !defined(__GC) && defined(_STLP_USE_EXCEPTIONS)
1167 _STLP_UNWIND(for(__i = 0; __i <= _RopeRep::_S_max_rope_depth; __i++)
1168 _S_unref(__forest[__i]))
1169 if (__result->_M_depth > _RopeRep::_S_max_rope_depth) {
1170 __stl_throw_range_error("rope too long");
1176 template <class _CharT, class _Alloc>
1178 rope<_CharT,_Alloc>::_S_add_to_forest(_RopeRep* __r, _RopeRep** __forest)
1180 if (__r -> _M_is_balanced) {
1181 _S_add_leaf_to_forest(__r, __forest);
1184 _STLP_ASSERT(__r->_M_tag == _RopeRep::_S_concat)
1186 _RopeConcatenation* __c = (_RopeConcatenation*)__r;
1188 _S_add_to_forest(__c->_M_left, __forest);
1189 _S_add_to_forest(__c->_M_right, __forest);
1194 template <class _CharT, class _Alloc>
1196 rope<_CharT,_Alloc>::_S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest)
1198 _RopeRep* __insertee; // included in refcount
1199 _RopeRep* __too_tiny = 0; // included in refcount
1200 int __i; // forest[0..__i-1] is empty
1201 size_t __s = __r->_M_size._M_data;
1203 for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i) {
1204 if (0 != __forest[__i]) {
1206 _Self_destruct_ptr __old(__too_tiny);
1208 __too_tiny = _S_concat_and_set_balanced(__forest[__i], __too_tiny);
1209 __forest[__i]->_M_unref_nonnil();
1215 _Self_destruct_ptr __old(__too_tiny);
1217 __insertee = _S_concat_and_set_balanced(__too_tiny, __r);
1219 // Too_tiny dead, and no longer included in refcount.
1220 // Insertee is live and included.
1221 _STLP_ASSERT(_S_is_almost_balanced(__insertee))
1222 _STLP_ASSERT(__insertee->_M_depth <= __r->_M_depth + 1)
1224 if (0 != __forest[__i]) {
1226 _Self_destruct_ptr __old(__insertee);
1228 __insertee = _S_concat_and_set_balanced(__forest[__i], __insertee);
1229 __forest[__i]->_M_unref_nonnil();
1231 _STLP_ASSERT(_S_is_almost_balanced(__insertee))
1233 _STLP_ASSERT(_S_min_len[__i] <= __insertee->_M_size._M_data)
1234 _STLP_ASSERT(__forest[__i] == 0)
1235 if (__i == _RopeRep::_S_max_rope_depth ||
1236 __insertee->_M_size._M_data < _S_min_len[__i+1]) {
1237 __forest[__i] = __insertee;
1238 // refcount is OK since __insertee is now dead.
1244 template <class _CharT, class _Alloc>
1246 rope<_CharT,_Alloc>::_S_fetch(_RopeRep* __r, size_type __i)
1248 __GC_CONST _CharT* __cstr = __r->_M_c_string;
1250 _STLP_ASSERT(__i < __r->_M_size._M_data)
1251 if (0 != __cstr) return __cstr[__i];
1253 switch(__r->_M_tag) {
1254 case _RopeRep::_S_concat:
1256 _RopeConcatenation* __c = (_RopeConcatenation*)__r;
1257 _RopeRep* __left = __c->_M_left;
1258 size_t __left_len = __left->_M_size._M_data;
1260 if (__i >= __left_len) {
1262 __r = __c->_M_right;
1268 case _RopeRep::_S_leaf:
1270 _RopeLeaf* __l = (_RopeLeaf*)__r;
1271 return __l->_M_data[__i];
1273 case _RopeRep::_S_function:
1274 case _RopeRep::_S_substringfn:
1276 _RopeFunction* __f = (_RopeFunction*)__r;
1279 (*(__f->_M_fn))(__i, 1, &__result);
1284 #if defined(_STLP_NEED_UNREACHABLE_RETURN)
1290 // Return a uniquely referenced character slot for the given
1291 // position, or 0 if that's not possible.
1292 template <class _CharT, class _Alloc>
1294 rope<_CharT,_Alloc>::_S_fetch_ptr(_RopeRep* __r, size_type __i)
1296 _RopeRep* __clrstack[_RopeRep::_S_max_rope_depth];
1300 if (__r->_M_ref_count > 1) return 0;
1301 switch(__r->_M_tag) {
1302 case _RopeRep::_S_concat:
1304 _RopeConcatenation* __c = (_RopeConcatenation*)__r;
1305 _RopeRep* __left = __c->_M_left;
1306 size_t __left_len = __left->_M_size._M_data;
1308 if (__c->_M_c_string != 0) __clrstack[__csptr++] = __c;
1309 if (__i >= __left_len) {
1311 __r = __c->_M_right;
1317 case _RopeRep::_S_leaf:
1319 _RopeLeaf* __l = (_RopeLeaf*)__r;
1320 if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0)
1321 __clrstack[__csptr++] = __l;
1322 while (__csptr > 0) {
1324 _RopeRep* __d = __clrstack[__csptr];
1325 __d->_M_free_c_string();
1326 __d->_M_c_string = 0;
1328 return __l->_M_data + __i;
1330 case _RopeRep::_S_function:
1331 case _RopeRep::_S_substringfn:
1335 #if defined(_STLP_NEED_UNREACHABLE_RETURN)
1342 // The following could be implemented trivially using
1343 // lexicographical_compare_3way.
1344 // We do a little more work to avoid dealing with rope iterators for
1346 template <class _CharT, class _Alloc>
1348 rope<_CharT,_Alloc>::_S_compare (const _RopeRep* __left,
1349 const _RopeRep* __right)
1354 if (0 == __right) return 0 != __left;
1355 if (0 == __left) return -1;
1356 __left_len = __left->_M_size._M_data;
1357 __right_len = __right->_M_size._M_data;
1358 if (_RopeRep::_S_leaf == __left->_M_tag) {
1359 _RopeLeaf* __l = (_RopeLeaf*) __left;
1360 if (_RopeRep::_S_leaf == __right->_M_tag) {
1361 _RopeLeaf* __r = (_RopeLeaf*) __right;
1362 return lexicographical_compare_3way(
1363 __l->_M_data, __l->_M_data + __left_len,
1364 __r->_M_data, __r->_M_data + __right_len);
1366 const_iterator __rstart(__right, 0);
1367 const_iterator __rend(__right, __right_len);
1368 return lexicographical_compare_3way(
1369 __l->_M_data, __l->_M_data + __left_len,
1373 const_iterator __lstart(__left, 0);
1374 const_iterator __lend(__left, __left_len);
1375 if (_RopeRep::_S_leaf == __right->_M_tag) {
1376 _RopeLeaf* __r = (_RopeLeaf*) __right;
1377 return lexicographical_compare_3way(
1379 __r->_M_data, __r->_M_data + __right_len);
1381 const_iterator __rstart(__right, 0);
1382 const_iterator __rend(__right, __right_len);
1383 return lexicographical_compare_3way(
1390 // Assignment to reference proxies.
1391 template <class _CharT, class _Alloc>
1392 _Rope_char_ref_proxy<_CharT, _Alloc>&
1393 _Rope_char_ref_proxy<_CharT, _Alloc>::operator= (_CharT __c) {
1394 _RopeRep* __old = _M_root->_M_tree_ptr._M_data;
1396 // First check for the case in which everything is uniquely
1397 // referenced. In that case we can do this destructively.
1398 _CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos);
1404 _Self_destruct_ptr __left(
1405 _My_rope::_S_substring(__old, 0, _M_pos));
1406 _Self_destruct_ptr __right(
1407 _My_rope::_S_substring(__old, _M_pos+1, __old->_M_size._M_data));
1408 _Self_destruct_ptr __result_left(
1409 _My_rope::_S_destr_concat_char_iter(__left, &__c, 1));
1412 _STLP_ASSERT(__left == __result_left || 1 == __result_left->_M_ref_count)
1414 _RopeRep* __result =
1415 _My_rope::_S_concat_rep(__result_left, __right);
1417 _STLP_ASSERT(1 <= __result->_M_ref_count)
1418 _RopeRep::_S_unref(__old);
1420 _M_root->_M_tree_ptr._M_data = __result;
1424 template <class _CharT, class _Alloc>
1425 _Rope_char_ptr_proxy<_CharT, _Alloc>
1426 _Rope_char_ref_proxy<_CharT, _Alloc>::operator& () const {
1427 return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this);
1430 # if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
1431 template<class _CharT, class _Alloc>
1432 _CharT rope<_CharT,_Alloc>::_S_empty_c_str[1] = { _CharT() };
1434 __DECLARE_INSTANCE(char, crope::_S_empty_c_str[1], ={0});
1435 # ifdef _STLP_HAS_WCHAR_T
1436 __DECLARE_INSTANCE(wchar_t, wrope::_S_empty_c_str[1], ={0});
1437 # endif /* _STLP_HAS_WCHAR_T */
1438 # endif /* _STLP_STATIC_TEMPLATE_DATA */
1441 template<class _CharT, class _Alloc>
1442 const _CharT* rope<_CharT,_Alloc>::c_str() const {
1443 if (0 == _M_tree_ptr._M_data) {
1444 _S_empty_c_str[0] = _S_eos((_CharT*)0); // Possibly redundant,
1445 // but probably fast.
1446 return _S_empty_c_str;
1448 __GC_CONST _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string;
1449 if (0 != __old_c_string) return(__old_c_string);
1450 size_t __s = size();
1451 _CharT* __result = _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).allocate(__s + 1);
1452 _S_flatten(_M_tree_ptr._M_data, __result);
1453 __result[__s] = _S_eos((_CharT*)0);
1455 _M_tree_ptr._M_data->_M_c_string = __result;
1457 if ((__old_c_string = (__GC_CONST _CharT*)
1458 _Atomic_swap((__stl_atomic_t *)(&(_M_tree_ptr._M_data->_M_c_string)),
1459 (__stl_atomic_t)__result)) != 0) {
1460 // It must have been added in the interim. Hence it had to have been
1461 // separately allocated. Deallocate the old copy, since we just
1463 _STLP_STD::_Destroy(__old_c_string, __old_c_string + __s + 1);
1464 _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).deallocate(__old_c_string, __s + 1);
1470 template<class _CharT, class _Alloc>
1471 const _CharT* rope<_CharT,_Alloc>::replace_with_c_str() {
1472 if (0 == _M_tree_ptr._M_data) {
1473 _S_empty_c_str[0] = _S_eos((_CharT*)0);
1474 return _S_empty_c_str;
1476 __GC_CONST _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string;
1477 if (_RopeRep::_S_leaf == _M_tree_ptr._M_data->_M_tag && 0 != __old_c_string) {
1478 return(__old_c_string);
1480 size_t __s = size();
1481 _CharT* __result = _M_tree_ptr.allocate(_S_rounded_up_size(__s));
1482 _S_flatten(_M_tree_ptr._M_data, __result);
1483 __result[__s] = _S_eos((_CharT*)0);
1484 _M_tree_ptr._M_data->_M_unref_nonnil();
1485 _M_tree_ptr._M_data = _S_new_RopeLeaf(__result, __s, get_allocator());
1489 // Algorithm specializations. More should be added.
1492 // I couldn't get this to work with VC++
1493 template<class _CharT,class _Alloc>
1495 _Rope_rotate(_Rope_iterator<_CharT,_Alloc> __first,
1496 _Rope_iterator<_CharT,_Alloc> __middle,
1497 _Rope_iterator<_CharT,_Alloc> __last)
1499 _STLP_ASSERT(__first.container() == __middle.container()
1500 && __middle.container() == __last.container())
1501 rope<_CharT,_Alloc>& __r(__first.container());
1502 rope<_CharT,_Alloc> __prefix = __r.substr(0, __first.index());
1503 rope<_CharT,_Alloc> __suffix =
1504 __r.substr(__last.index(), __r.size() - __last.index());
1505 rope<_CharT,_Alloc> __part1 =
1506 __r.substr(__middle.index(), __last.index() - __middle.index());
1507 rope<_CharT,_Alloc> __part2 =
1508 __r.substr(__first.index(), __middle.index() - __first.index());
1517 // Probably not useful for several reasons:
1518 // - for SGIs 7.1 compiler and probably some others,
1519 // this forces lots of rope<wchar_t, ...> instantiations, creating a
1520 // code bloat and compile time problem. (Fixed in 7.2.)
1521 // - wchar_t is 4 bytes wide on most UNIX platforms, making it unattractive
1522 // for unicode strings. Unsigned short may be a better character
1525 _Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __first,
1526 _Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __middle,
1527 _Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __last) {
1528 _Rope_rotate(__first, __middle, __last);
1531 #endif /* _STLP_MSVC */
1533 # undef __RopeLeaf__
1541 # endif /* ROPEIMPL_H */