epoc32/include/stdapis/stlport/stl/_rope.c
author William Roberts <williamr@symbian.org>
Tue, 16 Mar 2010 16:12:26 +0000
branchSymbian2
changeset 2 2fe1408b6811
parent 0 061f57f2323e
permissions -rw-r--r--
Final list of Symbian^2 public API header files
williamr@2
     1
/*
williamr@2
     2
 * © Portions copyright (c) 2006-2007 Nokia Corporation.  All rights reserved.
williamr@2
     3
 * Copyright (c) 1996,1997
williamr@2
     4
 * Silicon Graphics Computer Systems, Inc.
williamr@2
     5
 *
williamr@2
     6
 * Copyright (c) 1999 
williamr@2
     7
 * Boris Fomitchev
williamr@2
     8
 *
williamr@2
     9
 * This material is provided "as is", with absolutely no warranty expressed
williamr@2
    10
 * or implied. Any use is at your own risk.
williamr@2
    11
 *
williamr@2
    12
 * Permission to use or copy this software for any purpose is hereby granted 
williamr@2
    13
 * without fee, provided the above notices are retained on all copies.
williamr@2
    14
 * Permission to modify the code and to distribute modified code is granted,
williamr@2
    15
 * provided the above notices are retained, and a notice that the code was
williamr@2
    16
 * modified is included with the above copyright notice.
williamr@2
    17
 *
williamr@2
    18
 */
williamr@2
    19
williamr@2
    20
/* NOTE: This is an internal header file, included by other STL headers.
williamr@2
    21
 *   You should not attempt to use it directly.
williamr@2
    22
 */
williamr@2
    23
williamr@2
    24
// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
williamr@2
    25
// if necessary.  Assumes path_end[leaf_index] and leaf_pos are correct.
williamr@2
    26
// Results in a valid buf_ptr if the iterator can be legitimately
williamr@2
    27
// dereferenced.
williamr@2
    28
# ifndef _STLP_ROPEIMPL_H
williamr@2
    29
# define _STLP_ROPEIMPL_H
williamr@2
    30
williamr@2
    31
#ifndef _STLP_INTERNAL_ROPE_H
williamr@2
    32
# include <stl/_rope.h>
williamr@2
    33
#endif
williamr@2
    34
williamr@2
    35
# ifndef _STLP_CSTDIO
williamr@2
    36
#  include <cstdio>
williamr@2
    37
# endif
williamr@2
    38
williamr@2
    39
#ifndef _STLP_IOSTREAM
williamr@2
    40
# include <iostream>
williamr@2
    41
#endif
williamr@2
    42
williamr@2
    43
# include <stl/_range_errors.h>
williamr@2
    44
williamr@2
    45
_STLP_BEGIN_NAMESPACE
williamr@2
    46
williamr@2
    47
# if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
williamr@2
    48
# define __allocator__ _Alloc
williamr@2
    49
# else
williamr@2
    50
# define __allocator__ allocator_type
williamr@2
    51
# endif
williamr@2
    52
williamr@2
    53
template<class _CharT, class _Alloc>
williamr@2
    54
_Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>* __r, size_t __pos)
williamr@2
    55
  : _Rope_iterator_base<_CharT,_Alloc>(__r->_M_tree_ptr._M_data, __pos),
williamr@2
    56
  _M_root_rope(__r) { _RopeRep::_S_ref(this->_M_root); }
williamr@2
    57
williamr@2
    58
template<class _CharT, class _Alloc>
williamr@2
    59
_Rope_iterator<_CharT, _Alloc>::_Rope_iterator(rope<_CharT,_Alloc>& __r, size_t __pos): 
williamr@2
    60
  _Rope_iterator_base<_CharT,_Alloc>(__r._M_tree_ptr._M_data, __pos), 
williamr@2
    61
  _M_root_rope(&__r) {
williamr@2
    62
  _RopeRep::_S_ref(this->_M_root); if (!(__r.empty()))_S_setcache(*this);
williamr@2
    63
}
williamr@2
    64
williamr@2
    65
template<class _CharT, class _Alloc>
williamr@2
    66
void 
williamr@2
    67
_Rope_RopeRep<_CharT, _Alloc>::_M_free_c_string()
williamr@2
    68
{
williamr@2
    69
  _CharT* __cstr = _M_c_string;
williamr@2
    70
  if (0 != __cstr) {
williamr@2
    71
    size_t _p_size = _M_size._M_data + 1;
williamr@2
    72
    _STLP_STD::_Destroy(__cstr, __cstr + _p_size);
williamr@2
    73
    _M_size.deallocate(__cstr, _p_size);
williamr@2
    74
  }
williamr@2
    75
}
williamr@2
    76
williamr@2
    77
williamr@2
    78
// Set buf_start, buf_end, and buf_ptr appropriately, filling tmp_buf
williamr@2
    79
// if necessary.  Assumes _M_path_end[leaf_index] and leaf_pos are correct.
williamr@2
    80
// Results in a valid buf_ptr if the iterator can be legitimately
williamr@2
    81
// dereferenced.
williamr@2
    82
template <class _CharT, class _Alloc>
williamr@2
    83
void _Rope_iterator_base<_CharT,_Alloc>::_S_setbuf( 
williamr@2
    84
  _Rope_iterator_base<_CharT,_Alloc>& __x)
williamr@2
    85
{
williamr@2
    86
    const _RopeRep* __leaf = __x._M_path_end[__x._M_leaf_index];
williamr@2
    87
    size_t __leaf_pos = __x._M_leaf_pos;
williamr@2
    88
    size_t __pos = __x._M_current_pos;
williamr@2
    89
williamr@2
    90
    switch(__leaf->_M_tag) {
williamr@2
    91
	case _RopeRep::_S_leaf:
williamr@2
    92
	    __x._M_buf_start = 
williamr@2
    93
	      ((_Rope_RopeLeaf<_CharT,_Alloc>*)__leaf)->_M_data;
williamr@2
    94
	    __x._M_buf_ptr = __x._M_buf_start + (__pos - __leaf_pos);
williamr@2
    95
	    __x._M_buf_end = __x._M_buf_start + __leaf->_M_size._M_data;
williamr@2
    96
	    break;
williamr@2
    97
	case _RopeRep::_S_function:
williamr@2
    98
	case _RopeRep::_S_substringfn:
williamr@2
    99
	    {
williamr@2
   100
		size_t __len = _S_iterator_buf_len;
williamr@2
   101
		size_t __buf_start_pos = __leaf_pos;
williamr@2
   102
		size_t __leaf_end = __leaf_pos + __leaf->_M_size._M_data;
williamr@2
   103
		char_producer<_CharT>* __fn =
williamr@2
   104
			((_Rope_RopeFunction<_CharT,_Alloc>*)__leaf)->_M_fn;
williamr@2
   105
williamr@2
   106
		if (__buf_start_pos + __len <= __pos) {
williamr@2
   107
		    __buf_start_pos = __pos - __len/4;
williamr@2
   108
		    if (__buf_start_pos + __len > __leaf_end) {
williamr@2
   109
			__buf_start_pos = __leaf_end - __len;
williamr@2
   110
		    }
williamr@2
   111
		}
williamr@2
   112
		if (__buf_start_pos + __len > __leaf_end) {
williamr@2
   113
		    __len = __leaf_end - __buf_start_pos;
williamr@2
   114
		}
williamr@2
   115
		(*__fn)(__buf_start_pos - __leaf_pos, __len, __x._M_tmp_buf);
williamr@2
   116
		__x._M_buf_ptr = __x._M_tmp_buf + (__pos - __buf_start_pos);
williamr@2
   117
		__x._M_buf_start = __x._M_tmp_buf;
williamr@2
   118
		__x._M_buf_end = __x._M_tmp_buf + __len;
williamr@2
   119
	    }
williamr@2
   120
	    break;
williamr@2
   121
	default:
williamr@2
   122
      _STLP_ASSERT(0)
williamr@2
   123
        ;
williamr@2
   124
    }
williamr@2
   125
}
williamr@2
   126
williamr@2
   127
// Set path and buffer inside a rope iterator.  We assume that 
williamr@2
   128
// pos and root are already set.
williamr@2
   129
template <class _CharT, class _Alloc>
williamr@2
   130
void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache
williamr@2
   131
(_Rope_iterator_base<_CharT,_Alloc>& __x)
williamr@2
   132
{
williamr@2
   133
    const _RopeRep* __path[_RopeRep::_S_max_rope_depth+1];
williamr@2
   134
    const _RopeRep* __curr_rope;
williamr@2
   135
    int __curr_depth = -1;  /* index into path    */
williamr@2
   136
    size_t __curr_start_pos = 0;
williamr@2
   137
    size_t __pos = __x._M_current_pos;
williamr@2
   138
    unsigned char __dirns = 0; // Bit vector marking right turns in the path
williamr@2
   139
williamr@2
   140
    _STLP_ASSERT(__pos <= __x._M_root->_M_size._M_data)
williamr@2
   141
    if (__pos >= __x._M_root->_M_size._M_data) {
williamr@2
   142
	__x._M_buf_ptr = 0;
williamr@2
   143
	return;
williamr@2
   144
    }
williamr@2
   145
    __curr_rope = __x._M_root;
williamr@2
   146
    if (0 != __curr_rope->_M_c_string) {
williamr@2
   147
	/* Treat the root as a leaf. */
williamr@2
   148
	__x._M_buf_start = __curr_rope->_M_c_string;
williamr@2
   149
	__x._M_buf_end = __curr_rope->_M_c_string + __curr_rope->_M_size._M_data;
williamr@2
   150
	__x._M_buf_ptr = __curr_rope->_M_c_string + __pos;
williamr@2
   151
	__x._M_path_end[0] = __curr_rope;
williamr@2
   152
	__x._M_leaf_index = 0;
williamr@2
   153
	__x._M_leaf_pos = 0;
williamr@2
   154
	return;
williamr@2
   155
    }
williamr@2
   156
    for(;;) {
williamr@2
   157
	++__curr_depth;
williamr@2
   158
	_STLP_ASSERT(__curr_depth <= _RopeRep::_S_max_rope_depth)
williamr@2
   159
	__path[__curr_depth] = __curr_rope;
williamr@2
   160
	switch(__curr_rope->_M_tag) {
williamr@2
   161
	  case _RopeRep::_S_leaf:
williamr@2
   162
	  case _RopeRep::_S_function:
williamr@2
   163
	  case _RopeRep::_S_substringfn:
williamr@2
   164
	    __x._M_leaf_pos = __curr_start_pos;
williamr@2
   165
	    goto done;
williamr@2
   166
	  case _RopeRep::_S_concat:
williamr@2
   167
	    {
williamr@2
   168
		_Rope_RopeConcatenation<_CharT,_Alloc>* __c =
williamr@2
   169
			(_Rope_RopeConcatenation<_CharT,_Alloc>*)__curr_rope;
williamr@2
   170
		_RopeRep* __left = __c->_M_left;
williamr@2
   171
		size_t __left_len = __left->_M_size._M_data;
williamr@2
   172
		
williamr@2
   173
		__dirns <<= 1;
williamr@2
   174
		if (__pos >= __curr_start_pos + __left_len) {
williamr@2
   175
		    __dirns |= 1;
williamr@2
   176
		    __curr_rope = __c->_M_right;
williamr@2
   177
		    __curr_start_pos += __left_len;
williamr@2
   178
		} else {
williamr@2
   179
		    __curr_rope = __left;
williamr@2
   180
		}
williamr@2
   181
	    }
williamr@2
   182
	    break;
williamr@2
   183
	}
williamr@2
   184
    }
williamr@2
   185
  done:
williamr@2
   186
    // Copy last section of path into _M_path_end.
williamr@2
   187
      {
williamr@2
   188
	int __i = -1;
williamr@2
   189
	int __j = __curr_depth + 1 - _S_path_cache_len;
williamr@2
   190
williamr@2
   191
	if (__j < 0) __j = 0;
williamr@2
   192
	while (__j <= __curr_depth) {
williamr@2
   193
	    __x._M_path_end[++__i] = __path[__j++];
williamr@2
   194
	}
williamr@2
   195
	__x._M_leaf_index = __i;
williamr@2
   196
      }
williamr@2
   197
      __x._M_path_directions = __dirns;
williamr@2
   198
      _S_setbuf(__x);
williamr@2
   199
}
williamr@2
   200
williamr@2
   201
// Specialized version of the above.  Assumes that
williamr@2
   202
// the path cache is valid for the previous position.
williamr@2
   203
template <class _CharT, class _Alloc>
williamr@2
   204
void _Rope_iterator_base<_CharT,_Alloc>::_S_setcache_for_incr
williamr@2
   205
(_Rope_iterator_base<_CharT,_Alloc>& __x)
williamr@2
   206
{
williamr@2
   207
    int __current_index = __x._M_leaf_index;
williamr@2
   208
    const _RopeRep* __current_node = __x._M_path_end[__current_index];
williamr@2
   209
    size_t __len = __current_node->_M_size._M_data;
williamr@2
   210
    size_t __node_start_pos = __x._M_leaf_pos;
williamr@2
   211
    unsigned char __dirns = __x._M_path_directions;
williamr@2
   212
    _Rope_RopeConcatenation<_CharT,_Alloc>* __c;
williamr@2
   213
williamr@2
   214
    _STLP_ASSERT(__x._M_current_pos <= __x._M_root->_M_size._M_data)
williamr@2
   215
    if (__x._M_current_pos - __node_start_pos < __len) {
williamr@2
   216
	/* More stuff in this leaf, we just didn't cache it. */
williamr@2
   217
	_S_setbuf(__x);
williamr@2
   218
	return;
williamr@2
   219
    }
williamr@2
   220
    _STLP_ASSERT(__node_start_pos + __len == __x._M_current_pos)
williamr@2
   221
    //  node_start_pos is starting position of last_node.
williamr@2
   222
    while (--__current_index >= 0) {
williamr@2
   223
	if (!(__dirns & 1) /* Path turned left */) 
williamr@2
   224
	  break;
williamr@2
   225
	__current_node = __x._M_path_end[__current_index];
williamr@2
   226
	__c = (_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node;
williamr@2
   227
	// Otherwise we were in the right child.  Thus we should pop
williamr@2
   228
	// the concatenation node.
williamr@2
   229
	__node_start_pos -= __c->_M_left->_M_size._M_data;
williamr@2
   230
	__dirns >>= 1;
williamr@2
   231
    }
williamr@2
   232
    if (__current_index < 0) {
williamr@2
   233
	// We underflowed the cache. Punt.
williamr@2
   234
	_S_setcache(__x);
williamr@2
   235
	return;
williamr@2
   236
    }
williamr@2
   237
    __current_node = __x._M_path_end[__current_index];
williamr@2
   238
    __c = (_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node;
williamr@2
   239
    // current_node is a concatenation node.  We are positioned on the first
williamr@2
   240
    // character in its right child.
williamr@2
   241
    // node_start_pos is starting position of current_node.
williamr@2
   242
    __node_start_pos += __c->_M_left->_M_size._M_data;
williamr@2
   243
    __current_node = __c->_M_right;
williamr@2
   244
    __x._M_path_end[++__current_index] = __current_node;
williamr@2
   245
    __dirns |= 1;
williamr@2
   246
    while (_RopeRep::_S_concat == __current_node->_M_tag) {
williamr@2
   247
	++__current_index;
williamr@2
   248
	if (_S_path_cache_len == __current_index) {
williamr@2
   249
	    int __i;
williamr@2
   250
	    for (__i = 0; __i < _S_path_cache_len-1; __i++) {
williamr@2
   251
		__x._M_path_end[__i] = __x._M_path_end[__i+1];
williamr@2
   252
	    }
williamr@2
   253
	    --__current_index;
williamr@2
   254
	}
williamr@2
   255
	__current_node =
williamr@2
   256
	    ((_Rope_RopeConcatenation<_CharT,_Alloc>*)__current_node)->_M_left;
williamr@2
   257
	__x._M_path_end[__current_index] = __current_node;
williamr@2
   258
	__dirns <<= 1;
williamr@2
   259
	// node_start_pos is unchanged.
williamr@2
   260
    }
williamr@2
   261
    __x._M_leaf_index = __current_index;
williamr@2
   262
    __x._M_leaf_pos = __node_start_pos;
williamr@2
   263
    __x._M_path_directions = __dirns;
williamr@2
   264
    _S_setbuf(__x);
williamr@2
   265
}
williamr@2
   266
williamr@2
   267
template <class _CharT, class _Alloc>
williamr@2
   268
void _Rope_iterator_base<_CharT,_Alloc>::_M_incr(size_t __n) {
williamr@2
   269
    _M_current_pos += __n;
williamr@2
   270
    if (0 != _M_buf_ptr) {
williamr@2
   271
        size_t __chars_left = _M_buf_end - _M_buf_ptr;
williamr@2
   272
        if (__chars_left > __n) {
williamr@2
   273
            _M_buf_ptr += __n;
williamr@2
   274
        } else if (__chars_left == __n) {
williamr@2
   275
            _M_buf_ptr += __n;
williamr@2
   276
            _S_setcache_for_incr(*this);
williamr@2
   277
        } else {
williamr@2
   278
            _M_buf_ptr = 0;
williamr@2
   279
        }
williamr@2
   280
    }
williamr@2
   281
}
williamr@2
   282
williamr@2
   283
template <class _CharT, class _Alloc>
williamr@2
   284
void _Rope_iterator_base<_CharT,_Alloc>::_M_decr(size_t __n) {
williamr@2
   285
    if (0 != _M_buf_ptr) {
williamr@2
   286
        size_t __chars_left = _M_buf_ptr - _M_buf_start;
williamr@2
   287
        if (__chars_left >= __n) {
williamr@2
   288
            _M_buf_ptr -= __n;
williamr@2
   289
        } else {
williamr@2
   290
            _M_buf_ptr = 0;
williamr@2
   291
        }
williamr@2
   292
    }
williamr@2
   293
    _M_current_pos -= __n;
williamr@2
   294
}
williamr@2
   295
williamr@2
   296
template <class _CharT, class _Alloc>
williamr@2
   297
void _Rope_iterator<_CharT,_Alloc>::_M_check() {
williamr@2
   298
    if (_M_root_rope->_M_tree_ptr._M_data != this->_M_root) {
williamr@2
   299
        // _Rope was modified.  Get things fixed up.
williamr@2
   300
        _RopeRep::_S_unref(this->_M_root);
williamr@2
   301
        this->_M_root = _M_root_rope->_M_tree_ptr._M_data;
williamr@2
   302
        _RopeRep::_S_ref(this->_M_root);
williamr@2
   303
        this->_M_buf_ptr = 0;
williamr@2
   304
    }
williamr@2
   305
}
williamr@2
   306
williamr@2
   307
# ifndef _GC
williamr@2
   308
//  There are several reasons for not doing this with virtual destructors
williamr@2
   309
//  and a class specific delete operator:
williamr@2
   310
//  - A class specific delete operator can't easily get access to
williamr@2
   311
//    allocator instances if we need them.
williamr@2
   312
//  - Any virtual function would need a 4 or byte vtable pointer;
williamr@2
   313
//    this only requires a one byte tag per object.
williamr@2
   314
template <class _CharT, class _Alloc>
williamr@2
   315
void _Rope_RopeRep<_CharT,_Alloc>::_M_free_tree()
williamr@2
   316
{
williamr@2
   317
    switch(_M_tag) {
williamr@2
   318
	case _S_leaf:
williamr@2
   319
	    {
williamr@2
   320
	      typedef _Rope_RopeLeaf<_CharT,_Alloc> _Rope_RopeLeaf_T;
williamr@2
   321
          _Rope_RopeLeaf_T* __l = (_Rope_RopeLeaf_T*)this;
williamr@2
   322
          _STLP_STD::_Destroy(__l); // ->_Rope_RopeLeaf<_CharT,_Alloc>::~_Rope_RopeLeaf();
williamr@2
   323
	      _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, _Rope_RopeLeaf_T).deallocate(__l, 1);
williamr@2
   324
	        break;
williamr@2
   325
	    }
williamr@2
   326
	case _S_concat:
williamr@2
   327
	    {
williamr@2
   328
               typedef _Rope_RopeConcatenation<_CharT,_Alloc> _Rope_RopeConcatenation_T;
williamr@2
   329
               _Rope_RopeConcatenation_T* __c  = (_Rope_RopeConcatenation_T*)this;
williamr@2
   330
               _STLP_STD::_Destroy(__c);
williamr@2
   331
               _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, 
williamr@2
   332
                               _Rope_RopeConcatenation_T).deallocate(__c, 1);
williamr@2
   333
	        break;
williamr@2
   334
	    }
williamr@2
   335
	case _S_function:
williamr@2
   336
	    {
williamr@2
   337
            typedef _Rope_RopeFunction<_CharT,_Alloc> _Rope_RopeFunctionT;
williamr@2
   338
              _Rope_RopeFunctionT* __f = (_Rope_RopeFunctionT*)this;
williamr@2
   339
              _STLP_STD::_Destroy(__f);
williamr@2
   340
              _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, 
williamr@2
   341
                                 _Rope_RopeFunctionT).deallocate(__f, 1);
williamr@2
   342
	        break;
williamr@2
   343
	    }
williamr@2
   344
	case _S_substringfn:
williamr@2
   345
	    {
williamr@2
   346
            typedef _Rope_RopeSubstring<_CharT,_Alloc> _Rope_RopeSubstring_T;
williamr@2
   347
              _Rope_RopeSubstring_T* __ss = (_Rope_RopeSubstring_T*)this;
williamr@2
   348
              _STLP_STD::_Destroy(__ss);
williamr@2
   349
              _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_size, 
williamr@2
   350
                              _Rope_RopeSubstring_T).deallocate(__ss, 1);
williamr@2
   351
		break;
williamr@2
   352
	    }
williamr@2
   353
    }
williamr@2
   354
}
williamr@2
   355
#endif
williamr@2
   356
williamr@2
   357
# if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
williamr@2
   358
#   define __RopeLeaf__ _Rope_RopeLeaf<_CharT,_Alloc>
williamr@2
   359
#   define __RopeRep__ _Rope_RopeRep<_CharT,_Alloc>
williamr@2
   360
#   define _RopeLeaf _Rope_RopeLeaf<_CharT,_Alloc>
williamr@2
   361
#   define _RopeRep _Rope_RopeRep<_CharT,_Alloc>
williamr@2
   362
#   define size_type size_t
williamr@2
   363
# else
williamr@2
   364
#   define __RopeLeaf__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeLeaf
williamr@2
   365
#   define __RopeRep__ _STLP_TYPENAME_ON_RETURN_TYPE rope<_CharT,_Alloc>::_RopeRep
williamr@2
   366
# endif
williamr@2
   367
williamr@2
   368
// Concatenate a C string onto a leaf rope by copying the rope data.
williamr@2
   369
// Used for short ropes.
williamr@2
   370
template <class _CharT, class _Alloc>
williamr@2
   371
__RopeLeaf__*
williamr@2
   372
rope<_CharT,_Alloc>::_S_leaf_concat_char_iter
williamr@2
   373
		(_RopeLeaf* __r, const _CharT* __iter, size_t __len)
williamr@2
   374
{
williamr@2
   375
    size_t __old_len = __r->_M_size._M_data;
williamr@2
   376
    _CharT* __new_data = __r->_M_size.allocate(_S_rounded_up_size(__old_len + __len));
williamr@2
   377
    _RopeLeaf* __result;
williamr@2
   378
    
williamr@2
   379
    uninitialized_copy_n(__r->_M_data, __old_len, __new_data);
williamr@2
   380
    uninitialized_copy_n(__iter, __len, __new_data + __old_len);
williamr@2
   381
    _S_cond_store_eos(__new_data[__old_len + __len]);
williamr@2
   382
    _STLP_TRY {
williamr@2
   383
	__result = _S_new_RopeLeaf(__new_data, __old_len + __len,
williamr@2
   384
				   __r->get_allocator());
williamr@2
   385
    }
williamr@2
   386
    _STLP_UNWIND(_RopeRep::_S_free_string(__new_data, __old_len + __len,
williamr@2
   387
					     __r->get_allocator()));
williamr@2
   388
    return __result;
williamr@2
   389
}
williamr@2
   390
williamr@2
   391
#ifndef __GC
williamr@2
   392
// As above, but it's OK to clobber original if refcount is 1
williamr@2
   393
template <class _CharT, class _Alloc>
williamr@2
   394
__RopeLeaf__*
williamr@2
   395
rope<_CharT,_Alloc>::_S_destr_leaf_concat_char_iter
williamr@2
   396
		(_RopeLeaf* __r, const _CharT* __iter, size_t __len)
williamr@2
   397
{
williamr@2
   398
    _STLP_ASSERT(__r->_M_ref_count >= 1)
williamr@2
   399
    if (__r->_M_ref_count > 1)
williamr@2
   400
      return _S_leaf_concat_char_iter(__r, __iter, __len);
williamr@2
   401
    size_t __old_len = __r->_M_size._M_data;
williamr@2
   402
    if (_S_allocated_capacity(__old_len) >= __old_len + __len) {
williamr@2
   403
	// The space has been partially initialized for the standard
williamr@2
   404
	// character types.  But that doesn't matter for those types.
williamr@2
   405
	uninitialized_copy_n(__iter, __len, __r->_M_data + __old_len);
williamr@2
   406
	if (_S_is_basic_char_type((_CharT*)0)) {
williamr@2
   407
	    _S_cond_store_eos(__r->_M_data[__old_len + __len]);
williamr@2
   408
	    _STLP_ASSERT(__r->_M_c_string == __r->_M_data)
williamr@2
   409
	} else if (__r->_M_c_string != __r->_M_data && 0 != __r->_M_c_string) {
williamr@2
   410
	    __r->_M_free_c_string();
williamr@2
   411
	    __r->_M_c_string = 0;
williamr@2
   412
	}
williamr@2
   413
	__r->_M_size._M_data = __old_len + __len;
williamr@2
   414
	_STLP_ASSERT(__r->_M_ref_count == 1)
williamr@2
   415
	__r->_M_ref_count = 2;
williamr@2
   416
	return __r;
williamr@2
   417
    } else {
williamr@2
   418
	_RopeLeaf* __result = _S_leaf_concat_char_iter(__r, __iter, __len);
williamr@2
   419
	_STLP_ASSERT(__result->_M_ref_count == 1)
williamr@2
   420
	return __result;
williamr@2
   421
    }
williamr@2
   422
}
williamr@2
   423
#endif
williamr@2
   424
williamr@2
   425
// Assumes left and right are not 0.
williamr@2
   426
// Does not increment (nor decrement on exception) child reference counts.
williamr@2
   427
// Result has ref count 1.
williamr@2
   428
template <class _CharT, class _Alloc>
williamr@2
   429
__RopeRep__*
williamr@2
   430
rope<_CharT,_Alloc>::_S_tree_concat (_RopeRep* __left, _RopeRep* __right)
williamr@2
   431
{
williamr@2
   432
    _RopeConcatenation* __result =
williamr@2
   433
      _S_new_RopeConcatenation(__left, __right, __left->get_allocator());
williamr@2
   434
    size_t __depth = __result->_M_depth;
williamr@2
   435
    
williamr@2
   436
    _STLP_ASSERT(__left->get_allocator() == __right->get_allocator())
williamr@2
   437
    if (__depth > 20 && (__result->_M_size._M_data < 1000 ||
williamr@2
   438
			 __depth > _RopeRep::_S_max_rope_depth)) {
williamr@2
   439
        _RopeRep* __balanced;
williamr@2
   440
      
williamr@2
   441
	_STLP_TRY {
williamr@2
   442
	   __balanced = _S_balance(__result);
williamr@2
   443
#          ifndef __GC
williamr@2
   444
	     if (__result != __balanced) {
williamr@2
   445
		_STLP_ASSERT(1 == __result->_M_ref_count
williamr@2
   446
			     && 1 == __balanced->_M_ref_count)
williamr@2
   447
	     }
williamr@2
   448
#          endif
williamr@2
   449
	   __result->_M_unref_nonnil();
williamr@2
   450
        }
williamr@2
   451
      _STLP_UNWIND((_STLP_CREATE_ALLOCATOR(allocator_type,(allocator_type&)__left->_M_size,
williamr@2
   452
                                    _RopeConcatenation).deallocate(__result,1)));
williamr@2
   453
		// In case of exception, we need to deallocate
williamr@2
   454
		// otherwise dangling result node.  But caller
williamr@2
   455
		// still owns its children.  Thus unref is
williamr@2
   456
		// inappropriate.
williamr@2
   457
	return __balanced;
williamr@2
   458
    } else {
williamr@2
   459
	return __result;
williamr@2
   460
    }
williamr@2
   461
}
williamr@2
   462
williamr@2
   463
template <class _CharT, class _Alloc>
williamr@2
   464
__RopeRep__*
williamr@2
   465
rope<_CharT,_Alloc>::_S_concat_char_iter
williamr@2
   466
		(_RopeRep* __r, const _CharT*__s, size_t __slen)
williamr@2
   467
{
williamr@2
   468
    _RopeRep* __result;
williamr@2
   469
    if (0 == __slen) {
williamr@2
   470
	_S_ref(__r);
williamr@2
   471
	return __r;
williamr@2
   472
    }
williamr@2
   473
    if (0 == __r)
williamr@2
   474
      return _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
williamr@2
   475
					      /* __r->get_allocator()*/ allocator_type() );
williamr@2
   476
    if (_RopeRep::_S_leaf == __r->_M_tag && 
williamr@2
   477
          __r->_M_size._M_data + __slen <= _S_copy_max) {
williamr@2
   478
	__result = _S_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
williamr@2
   479
#       ifndef __GC
williamr@2
   480
	  _STLP_ASSERT(1 == __result->_M_ref_count)
williamr@2
   481
#       endif
williamr@2
   482
	return __result;
williamr@2
   483
    }
williamr@2
   484
    if (_RopeRep::_S_concat == __r->_M_tag
williamr@2
   485
	&& _RopeRep::_S_leaf == ((_RopeConcatenation*)__r)->_M_right->_M_tag) {
williamr@2
   486
	_RopeLeaf* __right = 
williamr@2
   487
	  (_RopeLeaf* )(((_RopeConcatenation* )__r)->_M_right);
williamr@2
   488
	if (__right->_M_size._M_data + __slen <= _S_copy_max) {
williamr@2
   489
	  _RopeRep* __left = ((_RopeConcatenation*)__r)->_M_left;
williamr@2
   490
	  _RopeRep* __nright = 
williamr@2
   491
	    _S_leaf_concat_char_iter((_RopeLeaf*)__right, __s, __slen);
williamr@2
   492
	  __left->_M_ref_nonnil();
williamr@2
   493
	  _STLP_TRY {
williamr@2
   494
	    __result = _S_tree_concat(__left, __nright);
williamr@2
   495
          }
williamr@2
   496
	  _STLP_UNWIND(_S_unref(__left); _S_unref(__nright));
williamr@2
   497
#         ifndef __GC
williamr@2
   498
	    _STLP_ASSERT(1 == __result->_M_ref_count)
williamr@2
   499
#         endif
williamr@2
   500
	  return __result;
williamr@2
   501
	}
williamr@2
   502
    }
williamr@2
   503
    _RopeRep* __nright =
williamr@2
   504
      _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator());
williamr@2
   505
    _STLP_TRY {
williamr@2
   506
      __r->_M_ref_nonnil();
williamr@2
   507
      __result = _S_tree_concat(__r, __nright);
williamr@2
   508
    }
williamr@2
   509
    _STLP_UNWIND(_S_unref(__r); _S_unref(__nright));
williamr@2
   510
#   ifndef __GC
williamr@2
   511
      _STLP_ASSERT(1 == __result->_M_ref_count)
williamr@2
   512
#   endif
williamr@2
   513
    return __result;
williamr@2
   514
}
williamr@2
   515
williamr@2
   516
#ifndef __GC
williamr@2
   517
template <class _CharT, class _Alloc>
williamr@2
   518
__RopeRep__* 
williamr@2
   519
rope<_CharT,_Alloc>::_S_destr_concat_char_iter(
williamr@2
   520
  _RopeRep* __r, const _CharT* __s, size_t __slen)
williamr@2
   521
{
williamr@2
   522
    _RopeRep* __result;
williamr@2
   523
    if (0 == __r)
williamr@2
   524
      return _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen,
williamr@2
   525
					      /* __r-> */allocator_type());
williamr@2
   526
    size_t __count = __r->_M_ref_count;
williamr@2
   527
    size_t __orig_size = __r->_M_size._M_data;
williamr@2
   528
    _STLP_ASSERT(__count >= 1)
williamr@2
   529
    if (__count > 1) return _S_concat_char_iter(__r, __s, __slen);
williamr@2
   530
    if (0 == __slen) {
williamr@2
   531
	__r->_M_ref_count = 2;      // One more than before
williamr@2
   532
	return __r;
williamr@2
   533
    }
williamr@2
   534
    if (__orig_size + __slen <= _S_copy_max && 
williamr@2
   535
          _RopeRep::_S_leaf == __r->_M_tag) {
williamr@2
   536
	__result = _S_destr_leaf_concat_char_iter((_RopeLeaf*)__r, __s, __slen);
williamr@2
   537
	return __result;
williamr@2
   538
    }
williamr@2
   539
    if (_RopeRep::_S_concat == __r->_M_tag) {
williamr@2
   540
	_RopeLeaf* __right = (_RopeLeaf*)(((_RopeConcatenation*)__r)->_M_right);
williamr@2
   541
	if (_RopeRep::_S_leaf == __right->_M_tag
williamr@2
   542
	    && __right->_M_size._M_data + __slen <= _S_copy_max) {
williamr@2
   543
	  _RopeRep* __new_right = 
williamr@2
   544
	    _S_destr_leaf_concat_char_iter(__right, __s, __slen);
williamr@2
   545
	  if (__right == __new_right) {
williamr@2
   546
	      _STLP_ASSERT(__new_right->_M_ref_count == 2)
williamr@2
   547
	      __new_right->_M_ref_count = 1;
williamr@2
   548
	  } else {
williamr@2
   549
	      _STLP_ASSERT(__new_right->_M_ref_count >= 1)
williamr@2
   550
	      __right->_M_unref_nonnil();
williamr@2
   551
	  }
williamr@2
   552
	  _STLP_ASSERT(__r->_M_ref_count == 1)
williamr@2
   553
	  __r->_M_ref_count = 2;    // One more than before.
williamr@2
   554
      ((_RopeConcatenation*)__r)->_M_right = __new_right;
williamr@2
   555
      // E.Musser : moved below
williamr@2
   556
      //	  __r->_M_size._M_data = __orig_size + __slen;
williamr@2
   557
	  if (0 != __r->_M_c_string) {
williamr@2
   558
	      __r->_M_free_c_string();
williamr@2
   559
	      __r->_M_c_string = 0;
williamr@2
   560
	  }
williamr@2
   561
	  __r->_M_size._M_data = __orig_size + __slen;
williamr@2
   562
	  return __r;
williamr@2
   563
	}
williamr@2
   564
    }
williamr@2
   565
    _RopeRep* __right =
williamr@2
   566
      _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(__s, __slen, __r->get_allocator());
williamr@2
   567
    __r->_M_ref_nonnil();
williamr@2
   568
    _STLP_TRY {
williamr@2
   569
      __result = _S_tree_concat(__r, __right);
williamr@2
   570
    }
williamr@2
   571
    _STLP_UNWIND(_S_unref(__r); _S_unref(__right))
williamr@2
   572
    _STLP_ASSERT(1 == __result->_M_ref_count)
williamr@2
   573
    return __result;
williamr@2
   574
}
williamr@2
   575
#endif /* !__GC */
williamr@2
   576
williamr@2
   577
template <class _CharT, class _Alloc>
williamr@2
   578
__RopeRep__*
williamr@2
   579
rope<_CharT,_Alloc>::_S_concat_rep(_RopeRep* __left, _RopeRep* __right)
williamr@2
   580
{
williamr@2
   581
    if (0 == __left) {
williamr@2
   582
	_S_ref(__right);
williamr@2
   583
	return __right;
williamr@2
   584
    }
williamr@2
   585
    if (0 == __right) {
williamr@2
   586
	__left->_M_ref_nonnil();
williamr@2
   587
	return __left;
williamr@2
   588
    }
williamr@2
   589
    if (_RopeRep::_S_leaf == __right->_M_tag) {
williamr@2
   590
	if (_RopeRep::_S_leaf == __left->_M_tag) {
williamr@2
   591
	  if (__right->_M_size._M_data + __left->_M_size._M_data <= _S_copy_max) {
williamr@2
   592
	    return _S_leaf_concat_char_iter((_RopeLeaf*)__left,
williamr@2
   593
					 ((_RopeLeaf*)__right)->_M_data,
williamr@2
   594
					 __right->_M_size._M_data);
williamr@2
   595
	  }
williamr@2
   596
	} else if (_RopeRep::_S_concat == __left->_M_tag
williamr@2
   597
		   && _RopeRep::_S_leaf ==
williamr@2
   598
		      ((_RopeConcatenation*)__left)->_M_right->_M_tag) {
williamr@2
   599
	  _RopeLeaf* __leftright =
williamr@2
   600
		    (_RopeLeaf*)(((_RopeConcatenation*)__left)->_M_right); 
williamr@2
   601
	  if (__leftright->_M_size._M_data + __right->_M_size._M_data <= _S_copy_max) {
williamr@2
   602
	    _RopeRep* __leftleft = ((_RopeConcatenation*)__left)->_M_left;
williamr@2
   603
	    _RopeRep* __rest = _S_leaf_concat_char_iter(__leftright,
williamr@2
   604
					   ((_RopeLeaf*)__right)->_M_data,
williamr@2
   605
					   __right->_M_size._M_data);
williamr@2
   606
	    __leftleft->_M_ref_nonnil();
williamr@2
   607
	    _STLP_TRY {
williamr@2
   608
	      return(_S_tree_concat(__leftleft, __rest));
williamr@2
   609
            }
williamr@2
   610
	    _STLP_UNWIND(_S_unref(__leftleft); _S_unref(__rest))
williamr@2
   611
	  }
williamr@2
   612
	}
williamr@2
   613
    }
williamr@2
   614
    __left->_M_ref_nonnil();
williamr@2
   615
    __right->_M_ref_nonnil();
williamr@2
   616
    _STLP_TRY {
williamr@2
   617
      return(_S_tree_concat(__left, __right));
williamr@2
   618
    }
williamr@2
   619
    _STLP_UNWIND(_S_unref(__left); _S_unref(__right));
williamr@2
   620
#ifdef _STLP_THROW_RETURN_BUG
williamr@2
   621
	return 0;
williamr@2
   622
#endif
williamr@2
   623
}
williamr@2
   624
williamr@2
   625
template <class _CharT, class _Alloc>
williamr@2
   626
__RopeRep__*
williamr@2
   627
rope<_CharT,_Alloc>::_S_substring(_RopeRep* __base, 
williamr@2
   628
                               size_t __start, size_t __endp1)
williamr@2
   629
{
williamr@2
   630
    if (0 == __base) return 0;
williamr@2
   631
    size_t __len = __base->_M_size._M_data;
williamr@2
   632
    size_t __adj_endp1;
williamr@2
   633
    const size_t __lazy_threshold = 128;
williamr@2
   634
    
williamr@2
   635
    if (__endp1 >= __len) {
williamr@2
   636
	if (0 == __start) {
williamr@2
   637
	    __base->_M_ref_nonnil();
williamr@2
   638
	    return __base;
williamr@2
   639
	} else {
williamr@2
   640
	    __adj_endp1 = __len;
williamr@2
   641
	}
williamr@2
   642
    } else {
williamr@2
   643
	__adj_endp1 = __endp1;
williamr@2
   644
    }
williamr@2
   645
    switch(__base->_M_tag) {
williamr@2
   646
	case _RopeRep::_S_concat:
williamr@2
   647
	    {
williamr@2
   648
		_RopeConcatenation* __c = (_RopeConcatenation*)__base;
williamr@2
   649
		_RopeRep* __left = __c->_M_left;
williamr@2
   650
		_RopeRep* __right = __c->_M_right;
williamr@2
   651
		size_t __left_len = __left->_M_size._M_data;
williamr@2
   652
		_RopeRep* __result;
williamr@2
   653
williamr@2
   654
		if (__adj_endp1 <= __left_len) {
williamr@2
   655
		    return _S_substring(__left, __start, __endp1);
williamr@2
   656
		} else if (__start >= __left_len) {
williamr@2
   657
		    return _S_substring(__right, __start - __left_len,
williamr@2
   658
				  __adj_endp1 - __left_len);
williamr@2
   659
		}
williamr@2
   660
		_Self_destruct_ptr __left_result(
williamr@2
   661
		  _S_substring(__left, __start, __left_len));
williamr@2
   662
		_Self_destruct_ptr __right_result(
williamr@2
   663
		  _S_substring(__right, 0, __endp1 - __left_len));
williamr@2
   664
		_STLP_MPWFIX_TRY		//*TY 06/01/2000 - mpw forgets to call dtor on __left_result and __right_result without this try block
williamr@2
   665
		__result = _S_concat_rep(__left_result, __right_result);
williamr@2
   666
#               ifndef __GC
williamr@2
   667
		  _STLP_ASSERT(1 == __result->_M_ref_count)
williamr@2
   668
#               endif
williamr@2
   669
		return __result;
williamr@2
   670
		_STLP_MPWFIX_CATCH		//*TY 06/01/2000 - 
williamr@2
   671
	    }
williamr@2
   672
	case _RopeRep::_S_leaf:
williamr@2
   673
	    {
williamr@2
   674
		_RopeLeaf* __l = (_RopeLeaf*)__base;
williamr@2
   675
		_RopeLeaf* __result;
williamr@2
   676
		size_t __result_len;
williamr@2
   677
		if (__start >= __adj_endp1) return 0;
williamr@2
   678
		__result_len = __adj_endp1 - __start;
williamr@2
   679
		if (__result_len > __lazy_threshold) goto lazy;
williamr@2
   680
#               ifdef __GC
williamr@2
   681
		    const _CharT* __section = __l->_M_data + __start;
williamr@2
   682
		    __result = _S_new_RopeLeaf(__section, __result_len,
williamr@2
   683
					  __base->get_allocator());
williamr@2
   684
		    __result->_M_c_string = 0;  // Not eos terminated.
williamr@2
   685
#               else
williamr@2
   686
		    // We should sometimes create substring node instead.
williamr@2
   687
		    __result = _STLP_ROPE_FROM_UNOWNED_CHAR_PTR(
williamr@2
   688
					__l->_M_data + __start, __result_len,
williamr@2
   689
					__base->get_allocator());
williamr@2
   690
#               endif
williamr@2
   691
		return __result;
williamr@2
   692
	    }
williamr@2
   693
	case _RopeRep::_S_substringfn:
williamr@2
   694
	    // Avoid introducing multiple layers of substring nodes.
williamr@2
   695
	    {
williamr@2
   696
		_RopeSubstring* __old = (_RopeSubstring*)__base;
williamr@2
   697
		size_t __result_len;
williamr@2
   698
		if (__start >= __adj_endp1) return 0;
williamr@2
   699
		__result_len = __adj_endp1 - __start;
williamr@2
   700
		if (__result_len > __lazy_threshold) {
williamr@2
   701
		    _RopeSubstring* __result =
williamr@2
   702
			_S_new_RopeSubstring(__old->_M_base,
williamr@2
   703
					  __start + __old->_M_start,
williamr@2
   704
					  __adj_endp1 - __start,
williamr@2
   705
					  __base->get_allocator());
williamr@2
   706
		    return __result;
williamr@2
   707
williamr@2
   708
		} // *** else fall through: ***
williamr@2
   709
	    }
williamr@2
   710
	case _RopeRep::_S_function:
williamr@2
   711
	    {
williamr@2
   712
		_RopeFunction* __f = (_RopeFunction*)__base;
williamr@2
   713
		if (__start >= __adj_endp1) return 0;
williamr@2
   714
		size_t __result_len = __adj_endp1 - __start;
williamr@2
   715
williamr@2
   716
		if (__result_len > __lazy_threshold) goto lazy;
williamr@2
   717
		_CharT* __section = __base->_M_size.allocate(_S_rounded_up_size(__result_len));
williamr@2
   718
		_STLP_TRY {
williamr@2
   719
		  (*(__f->_M_fn))(__start, __result_len, __section);
williamr@2
   720
                }
williamr@2
   721
		_STLP_UNWIND(_RopeRep::_S_free_string(
williamr@2
   722
	               __section, __result_len, __base->get_allocator()));
williamr@2
   723
		_S_cond_store_eos(__section[__result_len]);
williamr@2
   724
		return _S_new_RopeLeaf(__section, __result_len,
williamr@2
   725
				       __base->get_allocator());
williamr@2
   726
	    }
williamr@2
   727
    }
williamr@2
   728
    /*NOTREACHED*/
williamr@2
   729
    _STLP_ASSERT(false)
williamr@2
   730
  lazy:
williamr@2
   731
    {
williamr@2
   732
	// Create substring node.
williamr@2
   733
	return _S_new_RopeSubstring(__base, __start, __adj_endp1 - __start,
williamr@2
   734
			       __base->get_allocator());
williamr@2
   735
    }
williamr@2
   736
}
williamr@2
   737
williamr@2
   738
template<class _CharT>
williamr@2
   739
class _Rope_flatten_char_consumer : public _Rope_char_consumer<_CharT> {
williamr@2
   740
    private:
williamr@2
   741
	_CharT* _M_buf_ptr;
williamr@2
   742
    public:
williamr@2
   743
	//  _CharT* _M_buffer;  // XXX not used
williamr@2
   744
williamr@2
   745
	_Rope_flatten_char_consumer(_CharT* __buffer) {
williamr@2
   746
	    _M_buf_ptr = __buffer;
williamr@2
   747
	};
williamr@2
   748
	~_Rope_flatten_char_consumer() {}
williamr@2
   749
	bool operator() (const _CharT* __leaf, size_t __n) {
williamr@2
   750
	    uninitialized_copy_n(__leaf, __n, _M_buf_ptr);
williamr@2
   751
	    _M_buf_ptr += __n;
williamr@2
   752
	    return true;
williamr@2
   753
	}
williamr@2
   754
};
williamr@2
   755
	    
williamr@2
   756
template<class _CharT>
williamr@2
   757
class _Rope_find_char_char_consumer : public _Rope_char_consumer<_CharT> {
williamr@2
   758
    private:
williamr@2
   759
	_CharT _M_pattern;
williamr@2
   760
    public:
williamr@2
   761
	size_t _M_count;  // Number of nonmatching characters
williamr@2
   762
	_Rope_find_char_char_consumer(_CharT __p) 
williamr@2
   763
	  : _M_pattern(__p), _M_count(0) {}
williamr@2
   764
	~_Rope_find_char_char_consumer() {}
williamr@2
   765
	bool operator() (const _CharT* __leaf, size_t __n) {
williamr@2
   766
	    size_t __i;
williamr@2
   767
	    for (__i = 0; __i < __n; __i++) {
williamr@2
   768
		if (__leaf[__i] == _M_pattern) {
williamr@2
   769
		    _M_count += __i; return false;
williamr@2
   770
		}
williamr@2
   771
	    }
williamr@2
   772
	    _M_count += __n; return true;
williamr@2
   773
	}
williamr@2
   774
};
williamr@2
   775
williamr@2
   776
#if !defined (_STLP_USE_NO_IOSTREAMS)	    
williamr@2
   777
#if defined (_STLP_USE_NEW_IOSTREAMS)
williamr@2
   778
  template<class _CharT, class _Traits>
williamr@2
   779
  // Here _CharT is both the stream and rope character type.
williamr@2
   780
#else
williamr@2
   781
 template<class _CharT>
williamr@2
   782
  // Here _CharT is the rope character type.  Unlike in the
williamr@2
   783
  // above case, we somewhat handle the case in which it doesn't
williamr@2
   784
  // match the stream character type, i.e. char.
williamr@2
   785
#endif
williamr@2
   786
class _Rope_insert_char_consumer : public _Rope_char_consumer<_CharT> {
williamr@2
   787
    private:
williamr@2
   788
#       if defined (_STLP_USE_NEW_IOSTREAMS)
williamr@2
   789
	  typedef basic_ostream<_CharT,_Traits> _Insert_ostream;
williamr@2
   790
#	else
williamr@2
   791
 	typedef ostream _Insert_ostream;
williamr@2
   792
#	endif
williamr@2
   793
	_Insert_ostream& _M_o;
williamr@2
   794
    public:
williamr@2
   795
	// _CharT* buffer;    // XXX not used
williamr@2
   796
	_Rope_insert_char_consumer(_Insert_ostream& __writer) 
williamr@2
   797
	  : _M_o(__writer) {};
williamr@2
   798
#if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
williamr@2
   799
  ~_Rope_insert_char_consumer();		//*TY 05/23/2000 - 
williamr@2
   800
#else		//*TY 05/23/2000 - 
williamr@2
   801
  ~_Rope_insert_char_consumer() {}
williamr@2
   802
#endif		//*TY 05/23/2000 - 
williamr@2
   803
		// Caller is presumed to own the ostream
williamr@2
   804
	bool operator() (const _CharT* __leaf, size_t __n);
williamr@2
   805
		// Returns true to continue traversal.
williamr@2
   806
};
williamr@2
   807
	    
williamr@2
   808
# if defined ( _STLP_USE_NEW_IOSTREAMS )
williamr@2
   809
#  if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
williamr@2
   810
  template<class _CharT, class _Traits>
williamr@2
   811
  _Rope_insert_char_consumer<_CharT, _Traits>::  ~_Rope_insert_char_consumer() {}
williamr@2
   812
#  endif		//*TY 05/23/2000 - 
williamr@2
   813
williamr@2
   814
  template<class _CharT, class _Traits>
williamr@2
   815
  bool _Rope_insert_char_consumer<_CharT, _Traits>::operator()
williamr@2
   816
					(const _CharT* __leaf, size_t __n)
williamr@2
   817
{
williamr@2
   818
    size_t __i;
williamr@2
   819
    //  We assume that formatting is set up correctly for each element.
williamr@2
   820
    for (__i = 0; __i < __n; __i++) _M_o.put(__leaf[__i]);
williamr@2
   821
    return true;
williamr@2
   822
}
williamr@2
   823
# else
williamr@2
   824
#  if defined(__MRC__)||(defined(__SC__) && !defined(__DMC__))		//*TY 05/23/2000 - added support for mpw compiler's trigger function approach to generate vtable
williamr@2
   825
  template<class _CharT>
williamr@2
   826
  _Rope_insert_char_consumer<_CharT>::  ~_Rope_insert_char_consumer() {}
williamr@2
   827
#  endif		//*TY 05/23/2000 - 
williamr@2
   828
williamr@2
   829
  template<class _CharT>
williamr@2
   830
  bool _Rope_insert_char_consumer<_CharT>::operator()
williamr@2
   831
					(const _CharT* __leaf, size_t __n)
williamr@2
   832
  {
williamr@2
   833
    size_t __i;
williamr@2
   834
    //  We assume that formatting is set up correctly for each element.
williamr@2
   835
    for (__i = 0; __i < __n; __i++) _M_o << __leaf[__i];
williamr@2
   836
    return true;
williamr@2
   837
  }
williamr@2
   838
williamr@2
   839
# if !defined (_STLP_NO_METHOD_SPECIALIZATION)
williamr@2
   840
_STLP_TEMPLATE_NULL
williamr@2
   841
inline bool 
williamr@2
   842
_Rope_insert_char_consumer<char>::operator()
williamr@2
   843
					(const char* __leaf, size_t __n)
williamr@2
   844
{
williamr@2
   845
    size_t __i;
williamr@2
   846
    for (__i = 0; __i < __n; __i++) _M_o.put(__leaf[__i]);
williamr@2
   847
    return true;
williamr@2
   848
}
williamr@2
   849
williamr@2
   850
#endif /* _STLP_METHOD_SPECIALIZATION */
williamr@2
   851
#endif /* _STLP_USE_NEW_IOSTREAM */
williamr@2
   852
#endif /* if !defined (_STLP_USE_NO_IOSTREAMS) */
williamr@2
   853
williamr@2
   854
template <class _CharT, class _Alloc>
williamr@2
   855
bool rope<_CharT, _Alloc>::_S_apply_to_pieces(
williamr@2
   856
				_Rope_char_consumer<_CharT>& __c,
williamr@2
   857
				const _RopeRep* __r,
williamr@2
   858
				size_t __begin, size_t __end)
williamr@2
   859
{
williamr@2
   860
    if (0 == __r) return true;
williamr@2
   861
    switch(__r->_M_tag) {
williamr@2
   862
	case _RopeRep::_S_concat:
williamr@2
   863
	    {
williamr@2
   864
		_RopeConcatenation* __conc = (_RopeConcatenation*)__r;
williamr@2
   865
		_RopeRep* __left =  __conc->_M_left;
williamr@2
   866
		size_t __left_len = __left->_M_size._M_data;
williamr@2
   867
		if (__begin < __left_len) {
williamr@2
   868
		    size_t __left_end = (min) (__left_len, __end);
williamr@2
   869
		    if (!_S_apply_to_pieces(__c, __left, __begin, __left_end))
williamr@2
   870
			return false;
williamr@2
   871
		}
williamr@2
   872
		if (__end > __left_len) {
williamr@2
   873
		    _RopeRep* __right =  __conc->_M_right;
williamr@2
   874
		    size_t __right_start = (max)(__left_len, __begin);
williamr@2
   875
		    if (!_S_apply_to_pieces(__c, __right,
williamr@2
   876
					 __right_start - __left_len,
williamr@2
   877
					 __end - __left_len)) {
williamr@2
   878
			return false;
williamr@2
   879
		    }
williamr@2
   880
		}
williamr@2
   881
	    }
williamr@2
   882
	    return true;
williamr@2
   883
	case _RopeRep::_S_leaf:
williamr@2
   884
	    {
williamr@2
   885
		_RopeLeaf* __l = (_RopeLeaf*)__r;
williamr@2
   886
		return __c.operator()(__l->_M_data + __begin, __end - __begin);
williamr@2
   887
	    }
williamr@2
   888
	case _RopeRep::_S_function:
williamr@2
   889
	case _RopeRep::_S_substringfn:
williamr@2
   890
	    {
williamr@2
   891
		_RopeFunction* __f = (_RopeFunction*)__r;
williamr@2
   892
		size_t __len = __end - __begin;
williamr@2
   893
#ifdef __SYMBIAN32__
williamr@2
   894
		bool __result = false;
williamr@2
   895
#else
williamr@2
   896
		bool __result;
williamr@2
   897
#endif
williamr@2
   898
		_CharT* __buffer =
williamr@2
   899
		  (_CharT*)__sgi_alloc::allocate(__len * sizeof(_CharT));
williamr@2
   900
		_STLP_TRY {
williamr@2
   901
		  (*(__f->_M_fn))(__begin, __len, __buffer);
williamr@2
   902
		  __result = __c.operator()(__buffer, __len);
williamr@2
   903
                  __sgi_alloc::deallocate(__buffer, __len * sizeof(_CharT));
williamr@2
   904
                }
williamr@2
   905
		_STLP_UNWIND((__sgi_alloc::deallocate(__buffer,
williamr@2
   906
						      __len * sizeof(_CharT))))
williamr@2
   907
		return __result;
williamr@2
   908
	    }
williamr@2
   909
	default:
williamr@2
   910
	    _STLP_ASSERT(false)
williamr@2
   911
	    /*NOTREACHED*/
williamr@2
   912
	    return false;
williamr@2
   913
    }
williamr@2
   914
}
williamr@2
   915
williamr@2
   916
template <class _CharT> inline bool _Rope_is_simple(_CharT*) { return false; }
williamr@2
   917
inline bool _Rope_is_simple(char*) { return true; }
williamr@2
   918
# ifdef _STLP_HAS_WCHAR_T
williamr@2
   919
inline bool _Rope_is_simple(wchar_t*) { return true; }
williamr@2
   920
# endif
williamr@2
   921
williamr@2
   922
#if !defined (_STLP_USE_NO_IOSTREAMS)
williamr@2
   923
#if defined (_STLP_USE_NEW_IOSTREAMS)
williamr@2
   924
  template<class _CharT, class _Traits>
williamr@2
   925
  inline void _Rope_fill(basic_ostream<_CharT, _Traits>& __o, size_t __n)
williamr@2
   926
#else
williamr@2
   927
inline void _Rope_fill(ostream& __o, size_t __n)
williamr@2
   928
#endif
williamr@2
   929
{
williamr@2
   930
    char __f = __o.fill();
williamr@2
   931
    size_t __i;
williamr@2
   932
williamr@2
   933
    for (__i = 0; __i < __n; __i++) __o.put(__f);
williamr@2
   934
}
williamr@2
   935
    
williamr@2
   936
#if defined (_STLP_USE_NEW_IOSTREAMS)
williamr@2
   937
  template<class _CharT, class _Traits, class _Alloc>
williamr@2
   938
  basic_ostream<_CharT, _Traits>& operator<<
williamr@2
   939
					(basic_ostream<_CharT, _Traits>& __o,
williamr@2
   940
					 const rope<_CharT, _Alloc>& __r)
williamr@2
   941
# else
williamr@2
   942
template<class _CharT, class _Alloc>
williamr@2
   943
ostream& operator<< (ostream& __o, const rope<_CharT, _Alloc>& __r)
williamr@2
   944
#endif
williamr@2
   945
{
williamr@2
   946
    size_t __w = __o.width();
williamr@2
   947
    bool __left = bool(__o.flags() & ios::left);
williamr@2
   948
    size_t __pad_len;
williamr@2
   949
    size_t __rope_len = __r.size();
williamr@2
   950
#   if defined (_STLP_USE_NEW_IOSTREAMS)
williamr@2
   951
      _Rope_insert_char_consumer<_CharT, _Traits> __c(__o);
williamr@2
   952
#   else
williamr@2
   953
    _Rope_insert_char_consumer<_CharT> __c(__o);
williamr@2
   954
#   endif
williamr@2
   955
    bool __is_simple = _Rope_is_simple((_CharT*)0);
williamr@2
   956
    
williamr@2
   957
    if (__rope_len < __w) {
williamr@2
   958
	__pad_len = __w - __rope_len;
williamr@2
   959
    } else {
williamr@2
   960
	__pad_len = 0;
williamr@2
   961
    }
williamr@2
   962
    if (!__is_simple) __o.width(__w/__rope_len);
williamr@2
   963
    _STLP_TRY {
williamr@2
   964
      if (__is_simple && !__left && __pad_len > 0) {
williamr@2
   965
	_Rope_fill(__o, __pad_len);
williamr@2
   966
      }
williamr@2
   967
      __r.apply_to_pieces(0, __r.size(), __c);
williamr@2
   968
      if (__is_simple && __left && __pad_len > 0) {
williamr@2
   969
	_Rope_fill(__o, __pad_len);
williamr@2
   970
      }
williamr@2
   971
      if (!__is_simple)
williamr@2
   972
        __o.width(__w);
williamr@2
   973
    }
williamr@2
   974
    _STLP_UNWIND(if (!__is_simple) __o.width(__w))
williamr@2
   975
    return __o;
williamr@2
   976
}
williamr@2
   977
williamr@2
   978
#endif /* NO_IOSTREAMS */
williamr@2
   979
williamr@2
   980
template <class _CharT, class _Alloc>
williamr@2
   981
_CharT*
williamr@2
   982
rope<_CharT,_Alloc>::_S_flatten(_RopeRep* __r,
williamr@2
   983
				 size_t __start, size_t __len,
williamr@2
   984
				 _CharT* __buffer)
williamr@2
   985
{
williamr@2
   986
    _Rope_flatten_char_consumer<_CharT> __c(__buffer);
williamr@2
   987
    _S_apply_to_pieces(__c, __r, __start, __start + __len);
williamr@2
   988
    return(__buffer + __len);
williamr@2
   989
}
williamr@2
   990
williamr@2
   991
template <class _CharT, class _Alloc>
williamr@2
   992
size_t
williamr@2
   993
rope<_CharT,_Alloc>::find(_CharT __pattern, size_t __start) const
williamr@2
   994
{
williamr@2
   995
    _Rope_find_char_char_consumer<_CharT> __c(__pattern);
williamr@2
   996
    _S_apply_to_pieces(__c, _M_tree_ptr._M_data, __start, size());
williamr@2
   997
    size_type __result_pos = __start + __c._M_count;
williamr@2
   998
#   ifndef _STLP_OLD_ROPE_SEMANTICS
williamr@2
   999
	if (__result_pos == size()) __result_pos = npos;
williamr@2
  1000
#   endif
williamr@2
  1001
    return __result_pos;
williamr@2
  1002
}
williamr@2
  1003
williamr@2
  1004
template <class _CharT, class _Alloc>
williamr@2
  1005
_CharT*
williamr@2
  1006
rope<_CharT,_Alloc>::_S_flatten(_Rope_RopeRep<_CharT, _Alloc>* __r, _CharT* __buffer)
williamr@2
  1007
{
williamr@2
  1008
    if (0 == __r) return __buffer;
williamr@2
  1009
    switch(__r->_M_tag) {
williamr@2
  1010
	case _RopeRep::_S_concat:
williamr@2
  1011
	    {
williamr@2
  1012
		_RopeConcatenation* __c = (_RopeConcatenation*)__r;
williamr@2
  1013
		_RopeRep* __left = __c->_M_left;
williamr@2
  1014
		_RopeRep* __right = __c->_M_right;
williamr@2
  1015
		_CharT* __rest = _S_flatten(__left, __buffer);
williamr@2
  1016
		return _S_flatten(__right, __rest);
williamr@2
  1017
	    }
williamr@2
  1018
	case _RopeRep::_S_leaf:
williamr@2
  1019
	    {
williamr@2
  1020
		_RopeLeaf* __l = (_RopeLeaf*)__r;
williamr@2
  1021
		return copy_n(__l->_M_data, __l->_M_size._M_data, __buffer).second;
williamr@2
  1022
	    }
williamr@2
  1023
	case _RopeRep::_S_function:
williamr@2
  1024
	case _RopeRep::_S_substringfn:
williamr@2
  1025
	    // We dont yet do anything with substring nodes.
williamr@2
  1026
	    // This needs to be fixed before ropefiles will work well.
williamr@2
  1027
	    {
williamr@2
  1028
		_RopeFunction* __f = (_RopeFunction*)__r;
williamr@2
  1029
		(*(__f->_M_fn))(0, __f->_M_size._M_data, __buffer);
williamr@2
  1030
		return __buffer + __f->_M_size._M_data;
williamr@2
  1031
	    }
williamr@2
  1032
	default:
williamr@2
  1033
	    _STLP_ASSERT(false)
williamr@2
  1034
	    /*NOTREACHED*/
williamr@2
  1035
	    return 0;
williamr@2
  1036
    }
williamr@2
  1037
}
williamr@2
  1038
williamr@2
  1039
williamr@2
  1040
// This needs work for _CharT != char
williamr@2
  1041
template <class _CharT, class _Alloc>
williamr@2
  1042
void
williamr@2
  1043
rope<_CharT,_Alloc>::_S_dump(_RopeRep* __r, int __indent)
williamr@2
  1044
{
williamr@2
  1045
    for (int __i = 0; __i < __indent; __i++) putchar(' ');
williamr@2
  1046
    if (0 == __r) {
williamr@2
  1047
      printf("NULL\n"); return;
williamr@2
  1048
    }
williamr@2
  1049
    if (_RopeRep::_S_concat == __r->_M_tag) {
williamr@2
  1050
	_RopeConcatenation* __c = (_RopeConcatenation*)__r;
williamr@2
  1051
	_RopeRep* __left = __c->_M_left;
williamr@2
  1052
	_RopeRep* __right = __c->_M_right;
williamr@2
  1053
williamr@2
  1054
#       ifdef __GC
williamr@2
  1055
	  printf("Concatenation %p (depth = %d, len = %ld, %s balanced)\n",
williamr@2
  1056
	    __r, __r->_M_depth, __r->_M_size._M_data, __r->_M_is_balanced? "" : "not");
williamr@2
  1057
#       else
williamr@2
  1058
	  printf("Concatenation %p (rc = %ld, depth = %d, "
williamr@2
  1059
	           "len = %ld, %s balanced)\n",
williamr@2
  1060
		 __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data,
williamr@2
  1061
		 __r->_M_is_balanced? "" : "not");
williamr@2
  1062
#       endif
williamr@2
  1063
	_S_dump(__left, __indent + 2);
williamr@2
  1064
	_S_dump(__right, __indent + 2);
williamr@2
  1065
	return;
williamr@2
  1066
    } else {
williamr@2
  1067
	const char* __kind;
williamr@2
  1068
williamr@2
  1069
	switch (__r->_M_tag) {
williamr@2
  1070
	    case _RopeRep::_S_leaf:
williamr@2
  1071
		__kind = "Leaf";
williamr@2
  1072
		break;
williamr@2
  1073
	    case _RopeRep::_S_function:
williamr@2
  1074
		__kind = "Function";
williamr@2
  1075
		break;
williamr@2
  1076
	    case _RopeRep::_S_substringfn:
williamr@2
  1077
		__kind = "Function representing substring";
williamr@2
  1078
		break;
williamr@2
  1079
	    default:
williamr@2
  1080
		__kind = "(corrupted kind field!)";
williamr@2
  1081
	}
williamr@2
  1082
#       ifdef __GC
williamr@2
  1083
	  printf("%s %p (depth = %d, len = %ld) ",
williamr@2
  1084
		 __kind, __r, __r->_M_depth, __r->_M_size._M_data);
williamr@2
  1085
#       else
williamr@2
  1086
	  printf("%s %p (rc = %ld, depth = %d, len = %ld) ",
williamr@2
  1087
		 __kind, __r, __r->_M_ref_count, __r->_M_depth, __r->_M_size._M_data);
williamr@2
  1088
#       endif
williamr@2
  1089
	if (_S_is_one_byte_char_type((_CharT*)0)) {
williamr@2
  1090
	    const int __max_len = 40;
williamr@2
  1091
	    _Self_destruct_ptr __prefix(_S_substring(__r, 0, __max_len));
williamr@2
  1092
	    _CharT __buffer[__max_len + 1];
williamr@2
  1093
	    bool __too_big = __r->_M_size._M_data > __prefix->_M_size._M_data;
williamr@2
  1094
williamr@2
  1095
	    _S_flatten(__prefix, __buffer);
williamr@2
  1096
	    __buffer[__prefix->_M_size._M_data] = _S_eos((_CharT*)0); 
williamr@2
  1097
	    printf("%s%s\n", 
williamr@2
  1098
	           (char*)__buffer, __too_big? "...\n" : "\n");
williamr@2
  1099
	} else {
williamr@2
  1100
	    printf("\n");
williamr@2
  1101
	}
williamr@2
  1102
    }
williamr@2
  1103
}
williamr@2
  1104
williamr@2
  1105
# define __ROPE_TABLE_BODY  = { \
williamr@2
  1106
/* 0 */1, /* 1 */2, /* 2 */3, /* 3 */5, /* 4 */8, /* 5 */13, /* 6 */21,         \
williamr@2
  1107
/* 7 */34, /* 8 */55, /* 9 */89, /* 10 */144, /* 11 */233, /* 12 */377,         \
williamr@2
  1108
/* 13 */610, /* 14 */987, /* 15 */1597, /* 16 */2584, /* 17 */4181,             \
williamr@2
  1109
/* 18 */6765ul, /* 19 */10946ul, /* 20 */17711ul, /* 21 */28657ul, /* 22 */46368ul,   \
williamr@2
  1110
/* 23 */75025ul, /* 24 */121393ul, /* 25 */196418ul, /* 26 */317811ul,                \
williamr@2
  1111
/* 27 */514229ul, /* 28 */832040ul, /* 29 */1346269ul, /* 30 */2178309ul,             \
williamr@2
  1112
/* 31 */3524578ul, /* 32 */5702887ul, /* 33 */9227465ul, /* 34 */14930352ul,          \
williamr@2
  1113
/* 35 */24157817ul, /* 36 */39088169ul, /* 37 */63245986ul, /* 38 */102334155ul,      \
williamr@2
  1114
/* 39 */165580141ul, /* 40 */267914296ul, /* 41 */433494437ul,                        \
williamr@2
  1115
/* 42 */701408733ul, /* 43 */1134903170ul, /* 44 */1836311903ul,                      \
williamr@2
  1116
/* 45 */2971215073ul }
williamr@2
  1117
williamr@2
  1118
# if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
williamr@2
  1119
template <class _CharT, class _Alloc>
williamr@2
  1120
const unsigned long
williamr@2
  1121
rope<_CharT,_Alloc>::_S_min_len[__ROPE_DEPTH_SIZE] __ROPE_TABLE_BODY ;
williamr@2
  1122
# else 
williamr@2
  1123
__DECLARE_INSTANCE(const unsigned long, 
williamr@2
  1124
                   crope::_S_min_len[__ROPE_DEPTH_SIZE],
williamr@2
  1125
                   __ROPE_TABLE_BODY);
williamr@2
  1126
#  ifndef _STLP_NO_WCHAR_T
williamr@2
  1127
__DECLARE_INSTANCE(const unsigned long, 
williamr@2
  1128
                   wrope::_S_min_len[__ROPE_DEPTH_SIZE],
williamr@2
  1129
                   __ROPE_TABLE_BODY);
williamr@2
  1130
#  endif
williamr@2
  1131
# endif
williamr@2
  1132
# undef __ROPE_DEPTH_SIZE
williamr@2
  1133
# undef __ROPE_MAX_DEPTH
williamr@2
  1134
# undef __ROPE_TABLE_BODY
williamr@2
  1135
williamr@2
  1136
// These are Fibonacci numbers < 2**32.
williamr@2
  1137
williamr@2
  1138
template <class _CharT, class _Alloc>
williamr@2
  1139
__RopeRep__*
williamr@2
  1140
rope<_CharT,_Alloc>::_S_balance(_RopeRep* __r)
williamr@2
  1141
{
williamr@2
  1142
    _RopeRep* __forest[_RopeRep::_S_max_rope_depth + 1];
williamr@2
  1143
    _RopeRep* __result = 0;
williamr@2
  1144
    int __i;
williamr@2
  1145
    // Invariant:
williamr@2
  1146
    // The concatenation of forest in descending order is equal to __r.
williamr@2
  1147
    // __forest[__i]._M_size._M_data >= _S_min_len[__i]
williamr@2
  1148
    // __forest[__i]._M_depth = __i
williamr@2
  1149
    // References from forest are included in refcount.
williamr@2
  1150
williamr@2
  1151
    for (__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i) 
williamr@2
  1152
      __forest[__i] = 0;
williamr@2
  1153
    _STLP_TRY {
williamr@2
  1154
      _S_add_to_forest(__r, __forest);
williamr@2
  1155
      for (__i = 0; __i <= _RopeRep::_S_max_rope_depth; ++__i) 
williamr@2
  1156
        if (0 != __forest[__i]) {
williamr@2
  1157
#	ifndef __GC
williamr@2
  1158
	  _Self_destruct_ptr __old(__result);
williamr@2
  1159
#	endif
williamr@2
  1160
	  __result = _S_concat_rep(__forest[__i], __result);
williamr@2
  1161
	__forest[__i]->_M_unref_nonnil();
williamr@2
  1162
#	if !defined(__GC) && defined(_STLP_USE_EXCEPTIONS)
williamr@2
  1163
	  __forest[__i] = 0;
williamr@2
  1164
#	endif
williamr@2
  1165
      }
williamr@2
  1166
    }
williamr@2
  1167
    _STLP_UNWIND(for(__i = 0; __i <= _RopeRep::_S_max_rope_depth; __i++)
williamr@2
  1168
		 _S_unref(__forest[__i]))
williamr@2
  1169
    if (__result->_M_depth > _RopeRep::_S_max_rope_depth) {
williamr@2
  1170
	__stl_throw_range_error("rope too long");
williamr@2
  1171
    }
williamr@2
  1172
    return(__result);
williamr@2
  1173
}
williamr@2
  1174
williamr@2
  1175
williamr@2
  1176
template <class _CharT, class _Alloc>
williamr@2
  1177
void
williamr@2
  1178
rope<_CharT,_Alloc>::_S_add_to_forest(_RopeRep* __r, _RopeRep** __forest)
williamr@2
  1179
{
williamr@2
  1180
    if (__r -> _M_is_balanced) {
williamr@2
  1181
	_S_add_leaf_to_forest(__r, __forest);
williamr@2
  1182
	return;
williamr@2
  1183
    }
williamr@2
  1184
    _STLP_ASSERT(__r->_M_tag == _RopeRep::_S_concat)
williamr@2
  1185
    {
williamr@2
  1186
	_RopeConcatenation* __c = (_RopeConcatenation*)__r;
williamr@2
  1187
williamr@2
  1188
	_S_add_to_forest(__c->_M_left, __forest);
williamr@2
  1189
	_S_add_to_forest(__c->_M_right, __forest);
williamr@2
  1190
    }
williamr@2
  1191
}
williamr@2
  1192
williamr@2
  1193
williamr@2
  1194
template <class _CharT, class _Alloc>
williamr@2
  1195
void
williamr@2
  1196
rope<_CharT,_Alloc>::_S_add_leaf_to_forest(_RopeRep* __r, _RopeRep** __forest)
williamr@2
  1197
{
williamr@2
  1198
    _RopeRep* __insertee;   		// included in refcount
williamr@2
  1199
    _RopeRep* __too_tiny = 0;    	// included in refcount
williamr@2
  1200
    int __i;  				// forest[0..__i-1] is empty
williamr@2
  1201
    size_t __s = __r->_M_size._M_data;
williamr@2
  1202
williamr@2
  1203
    for (__i = 0; __s >= _S_min_len[__i+1]/* not this bucket */; ++__i) {
williamr@2
  1204
	if (0 != __forest[__i]) {
williamr@2
  1205
#	    ifndef __GC
williamr@2
  1206
	      _Self_destruct_ptr __old(__too_tiny);
williamr@2
  1207
#	    endif
williamr@2
  1208
	    __too_tiny = _S_concat_and_set_balanced(__forest[__i], __too_tiny);
williamr@2
  1209
	    __forest[__i]->_M_unref_nonnil();
williamr@2
  1210
	    __forest[__i] = 0;
williamr@2
  1211
	}
williamr@2
  1212
    }
williamr@2
  1213
    {
williamr@2
  1214
#	ifndef __GC
williamr@2
  1215
	  _Self_destruct_ptr __old(__too_tiny);
williamr@2
  1216
#	endif
williamr@2
  1217
	__insertee = _S_concat_and_set_balanced(__too_tiny, __r);
williamr@2
  1218
    }
williamr@2
  1219
    // Too_tiny dead, and no longer included in refcount.
williamr@2
  1220
    // Insertee is live and included.
williamr@2
  1221
    _STLP_ASSERT(_S_is_almost_balanced(__insertee))
williamr@2
  1222
    _STLP_ASSERT(__insertee->_M_depth <= __r->_M_depth + 1)
williamr@2
  1223
    for (;; ++__i) {
williamr@2
  1224
	if (0 != __forest[__i]) {
williamr@2
  1225
#	    ifndef __GC
williamr@2
  1226
	      _Self_destruct_ptr __old(__insertee);
williamr@2
  1227
#	    endif
williamr@2
  1228
	    __insertee = _S_concat_and_set_balanced(__forest[__i], __insertee);
williamr@2
  1229
	    __forest[__i]->_M_unref_nonnil();
williamr@2
  1230
	    __forest[__i] = 0;
williamr@2
  1231
	    _STLP_ASSERT(_S_is_almost_balanced(__insertee))
williamr@2
  1232
	}
williamr@2
  1233
	_STLP_ASSERT(_S_min_len[__i] <= __insertee->_M_size._M_data)
williamr@2
  1234
	_STLP_ASSERT(__forest[__i] == 0)
williamr@2
  1235
	if (__i == _RopeRep::_S_max_rope_depth || 
williamr@2
  1236
	      __insertee->_M_size._M_data < _S_min_len[__i+1]) {
williamr@2
  1237
	    __forest[__i] = __insertee;
williamr@2
  1238
	    // refcount is OK since __insertee is now dead.
williamr@2
  1239
	    return;
williamr@2
  1240
	}
williamr@2
  1241
    }
williamr@2
  1242
}
williamr@2
  1243
williamr@2
  1244
template <class _CharT, class _Alloc>
williamr@2
  1245
_CharT
williamr@2
  1246
rope<_CharT,_Alloc>::_S_fetch(_RopeRep* __r, size_type __i)
williamr@2
  1247
{
williamr@2
  1248
    __GC_CONST _CharT* __cstr = __r->_M_c_string;
williamr@2
  1249
williamr@2
  1250
    _STLP_ASSERT(__i < __r->_M_size._M_data)
williamr@2
  1251
    if (0 != __cstr) return __cstr[__i]; 
williamr@2
  1252
    for(;;) {
williamr@2
  1253
      switch(__r->_M_tag) {
williamr@2
  1254
	case _RopeRep::_S_concat:
williamr@2
  1255
	    {
williamr@2
  1256
		_RopeConcatenation* __c = (_RopeConcatenation*)__r;
williamr@2
  1257
		_RopeRep* __left = __c->_M_left;
williamr@2
  1258
		size_t __left_len = __left->_M_size._M_data;
williamr@2
  1259
williamr@2
  1260
		if (__i >= __left_len) {
williamr@2
  1261
		    __i -= __left_len;
williamr@2
  1262
		    __r = __c->_M_right;
williamr@2
  1263
		} else {
williamr@2
  1264
		    __r = __left;
williamr@2
  1265
		}
williamr@2
  1266
	    }
williamr@2
  1267
	    break;
williamr@2
  1268
	case _RopeRep::_S_leaf:
williamr@2
  1269
	    {
williamr@2
  1270
		_RopeLeaf* __l = (_RopeLeaf*)__r;
williamr@2
  1271
		return __l->_M_data[__i];
williamr@2
  1272
	    }
williamr@2
  1273
	case _RopeRep::_S_function:
williamr@2
  1274
	case _RopeRep::_S_substringfn:
williamr@2
  1275
	    {
williamr@2
  1276
		_RopeFunction* __f = (_RopeFunction*)__r;
williamr@2
  1277
		_CharT __result;
williamr@2
  1278
williamr@2
  1279
		(*(__f->_M_fn))(__i, 1, &__result);
williamr@2
  1280
		return __result;
williamr@2
  1281
	    }
williamr@2
  1282
      }
williamr@2
  1283
    }
williamr@2
  1284
#if defined(_STLP_NEED_UNREACHABLE_RETURN)
williamr@2
  1285
    return 0;
williamr@2
  1286
#endif
williamr@2
  1287
}
williamr@2
  1288
williamr@2
  1289
# ifndef __GC
williamr@2
  1290
// Return a uniquely referenced character slot for the given
williamr@2
  1291
// position, or 0 if that's not possible.
williamr@2
  1292
template <class _CharT, class _Alloc>
williamr@2
  1293
_CharT*
williamr@2
  1294
rope<_CharT,_Alloc>::_S_fetch_ptr(_RopeRep* __r, size_type __i)
williamr@2
  1295
{
williamr@2
  1296
    _RopeRep* __clrstack[_RopeRep::_S_max_rope_depth];
williamr@2
  1297
    size_t __csptr = 0;
williamr@2
  1298
williamr@2
  1299
    for(;;) {
williamr@2
  1300
      if (__r->_M_ref_count > 1) return 0;
williamr@2
  1301
      switch(__r->_M_tag) {
williamr@2
  1302
	case _RopeRep::_S_concat:
williamr@2
  1303
	    {
williamr@2
  1304
		_RopeConcatenation* __c = (_RopeConcatenation*)__r;
williamr@2
  1305
		_RopeRep* __left = __c->_M_left;
williamr@2
  1306
		size_t __left_len = __left->_M_size._M_data;
williamr@2
  1307
williamr@2
  1308
		if (__c->_M_c_string != 0) __clrstack[__csptr++] = __c;
williamr@2
  1309
		if (__i >= __left_len) {
williamr@2
  1310
		    __i -= __left_len;
williamr@2
  1311
		    __r = __c->_M_right;
williamr@2
  1312
		} else {
williamr@2
  1313
		    __r = __left;
williamr@2
  1314
		}
williamr@2
  1315
	    }
williamr@2
  1316
	    break;
williamr@2
  1317
	case _RopeRep::_S_leaf:
williamr@2
  1318
	    {
williamr@2
  1319
		_RopeLeaf* __l = (_RopeLeaf*)__r;
williamr@2
  1320
		if (__l->_M_c_string != __l->_M_data && __l->_M_c_string != 0)
williamr@2
  1321
		    __clrstack[__csptr++] = __l;
williamr@2
  1322
		while (__csptr > 0) {
williamr@2
  1323
		    -- __csptr;
williamr@2
  1324
		    _RopeRep* __d = __clrstack[__csptr];
williamr@2
  1325
		    __d->_M_free_c_string();
williamr@2
  1326
		    __d->_M_c_string = 0;
williamr@2
  1327
		}
williamr@2
  1328
		return __l->_M_data + __i;
williamr@2
  1329
	    }
williamr@2
  1330
	case _RopeRep::_S_function:
williamr@2
  1331
	case _RopeRep::_S_substringfn:
williamr@2
  1332
	    return 0;
williamr@2
  1333
      }
williamr@2
  1334
    }
williamr@2
  1335
#if defined(_STLP_NEED_UNREACHABLE_RETURN)
williamr@2
  1336
    return 0;
williamr@2
  1337
#endif
williamr@2
  1338
williamr@2
  1339
}
williamr@2
  1340
# endif /* __GC */
williamr@2
  1341
williamr@2
  1342
// The following could be implemented trivially using
williamr@2
  1343
// lexicographical_compare_3way.
williamr@2
  1344
// We do a little more work to avoid dealing with rope iterators for
williamr@2
  1345
// flat strings.
williamr@2
  1346
template <class _CharT, class _Alloc>
williamr@2
  1347
int
williamr@2
  1348
rope<_CharT,_Alloc>::_S_compare (const _RopeRep* __left, 
williamr@2
  1349
                                 const _RopeRep* __right)
williamr@2
  1350
{
williamr@2
  1351
    size_t __left_len;
williamr@2
  1352
    size_t __right_len;
williamr@2
  1353
williamr@2
  1354
    if (0 == __right) return 0 != __left;
williamr@2
  1355
    if (0 == __left) return -1;
williamr@2
  1356
    __left_len = __left->_M_size._M_data;
williamr@2
  1357
    __right_len = __right->_M_size._M_data;
williamr@2
  1358
    if (_RopeRep::_S_leaf == __left->_M_tag) {
williamr@2
  1359
	_RopeLeaf* __l = (_RopeLeaf*) __left;
williamr@2
  1360
	if (_RopeRep::_S_leaf == __right->_M_tag) {
williamr@2
  1361
	    _RopeLeaf* __r = (_RopeLeaf*) __right;
williamr@2
  1362
	    return lexicographical_compare_3way(
williamr@2
  1363
			__l->_M_data, __l->_M_data + __left_len,
williamr@2
  1364
			__r->_M_data, __r->_M_data + __right_len);
williamr@2
  1365
	} else {
williamr@2
  1366
	    const_iterator __rstart(__right, 0);
williamr@2
  1367
	    const_iterator __rend(__right, __right_len);
williamr@2
  1368
	    return lexicographical_compare_3way(
williamr@2
  1369
			__l->_M_data, __l->_M_data + __left_len,
williamr@2
  1370
			__rstart, __rend);
williamr@2
  1371
	}
williamr@2
  1372
    } else {
williamr@2
  1373
	const_iterator __lstart(__left, 0);
williamr@2
  1374
	const_iterator __lend(__left, __left_len);
williamr@2
  1375
	if (_RopeRep::_S_leaf == __right->_M_tag) {
williamr@2
  1376
	    _RopeLeaf* __r = (_RopeLeaf*) __right;
williamr@2
  1377
	    return lexicographical_compare_3way(
williamr@2
  1378
				   __lstart, __lend,
williamr@2
  1379
				   __r->_M_data, __r->_M_data + __right_len);
williamr@2
  1380
	} else {
williamr@2
  1381
	    const_iterator __rstart(__right, 0);
williamr@2
  1382
	    const_iterator __rend(__right, __right_len);
williamr@2
  1383
	    return lexicographical_compare_3way(
williamr@2
  1384
				   __lstart, __lend,
williamr@2
  1385
				   __rstart, __rend);
williamr@2
  1386
	}
williamr@2
  1387
    }
williamr@2
  1388
}
williamr@2
  1389
williamr@2
  1390
// Assignment to reference proxies.
williamr@2
  1391
template <class _CharT, class _Alloc>
williamr@2
  1392
_Rope_char_ref_proxy<_CharT, _Alloc>&
williamr@2
  1393
_Rope_char_ref_proxy<_CharT, _Alloc>::operator= (_CharT __c) {
williamr@2
  1394
    _RopeRep* __old = _M_root->_M_tree_ptr._M_data;
williamr@2
  1395
#   ifndef __GC
williamr@2
  1396
	// First check for the case in which everything is uniquely
williamr@2
  1397
	// referenced.  In that case we can do this destructively.
williamr@2
  1398
	_CharT* __ptr = _My_rope::_S_fetch_ptr(__old, _M_pos);
williamr@2
  1399
	if (0 != __ptr) {
williamr@2
  1400
	    *__ptr = __c;
williamr@2
  1401
	    return *this;
williamr@2
  1402
	}
williamr@2
  1403
#   endif
williamr@2
  1404
    _Self_destruct_ptr __left(
williamr@2
  1405
      _My_rope::_S_substring(__old, 0, _M_pos));
williamr@2
  1406
    _Self_destruct_ptr __right(
williamr@2
  1407
      _My_rope::_S_substring(__old, _M_pos+1, __old->_M_size._M_data));
williamr@2
  1408
    _Self_destruct_ptr __result_left(
williamr@2
  1409
      _My_rope::_S_destr_concat_char_iter(__left, &__c, 1));
williamr@2
  1410
williamr@2
  1411
#   ifndef __GC
williamr@2
  1412
      _STLP_ASSERT(__left == __result_left || 1 == __result_left->_M_ref_count)
williamr@2
  1413
#   endif
williamr@2
  1414
    _RopeRep* __result =
williamr@2
  1415
      _My_rope::_S_concat_rep(__result_left, __right);
williamr@2
  1416
#   ifndef __GC
williamr@2
  1417
      _STLP_ASSERT(1 <= __result->_M_ref_count)
williamr@2
  1418
      _RopeRep::_S_unref(__old);
williamr@2
  1419
#   endif
williamr@2
  1420
    _M_root->_M_tree_ptr._M_data = __result;
williamr@2
  1421
    return *this;
williamr@2
  1422
}
williamr@2
  1423
williamr@2
  1424
template <class _CharT, class _Alloc>
williamr@2
  1425
_Rope_char_ptr_proxy<_CharT, _Alloc>
williamr@2
  1426
_Rope_char_ref_proxy<_CharT, _Alloc>::operator& () const {
williamr@2
  1427
    return _Rope_char_ptr_proxy<_CharT, _Alloc>(*this);
williamr@2
  1428
}
williamr@2
  1429
williamr@2
  1430
# if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
williamr@2
  1431
template<class _CharT, class _Alloc>
williamr@2
  1432
_CharT rope<_CharT,_Alloc>::_S_empty_c_str[1] = { _CharT() };
williamr@2
  1433
# else
williamr@2
  1434
__DECLARE_INSTANCE(char, crope::_S_empty_c_str[1], ={0});
williamr@2
  1435
# ifdef _STLP_HAS_WCHAR_T
williamr@2
  1436
__DECLARE_INSTANCE(wchar_t, wrope::_S_empty_c_str[1], ={0});
williamr@2
  1437
# endif /* _STLP_HAS_WCHAR_T */
williamr@2
  1438
# endif /* _STLP_STATIC_TEMPLATE_DATA */
williamr@2
  1439
// # endif
williamr@2
  1440
williamr@2
  1441
template<class _CharT, class _Alloc>
williamr@2
  1442
const _CharT* rope<_CharT,_Alloc>::c_str() const {
williamr@2
  1443
    if (0 == _M_tree_ptr._M_data) {
williamr@2
  1444
        _S_empty_c_str[0] = _S_eos((_CharT*)0);  // Possibly redundant,
williamr@2
  1445
					     // but probably fast.
williamr@2
  1446
        return _S_empty_c_str;
williamr@2
  1447
    }
williamr@2
  1448
    __GC_CONST _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string;
williamr@2
  1449
    if (0 != __old_c_string) return(__old_c_string);
williamr@2
  1450
    size_t __s = size();
williamr@2
  1451
   _CharT* __result = _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).allocate(__s + 1);
williamr@2
  1452
    _S_flatten(_M_tree_ptr._M_data, __result);
williamr@2
  1453
    __result[__s] = _S_eos((_CharT*)0);
williamr@2
  1454
#   ifdef __GC
williamr@2
  1455
	_M_tree_ptr._M_data->_M_c_string = __result;
williamr@2
  1456
#   else
williamr@2
  1457
      if ((__old_c_string = (__GC_CONST _CharT*)
williamr@2
  1458
	   _Atomic_swap((__stl_atomic_t *)(&(_M_tree_ptr._M_data->_M_c_string)),
williamr@2
  1459
			(__stl_atomic_t)__result)) != 0) {
williamr@2
  1460
	// It must have been added in the interim.  Hence it had to have been
williamr@2
  1461
	// separately allocated.  Deallocate the old copy, since we just
williamr@2
  1462
	// replaced it.
williamr@2
  1463
	_STLP_STD::_Destroy(__old_c_string, __old_c_string + __s + 1);
williamr@2
  1464
      _STLP_CREATE_ALLOCATOR(allocator_type,(const allocator_type&)_M_tree_ptr, _CharT).deallocate(__old_c_string, __s + 1);
williamr@2
  1465
      }
williamr@2
  1466
#   endif
williamr@2
  1467
    return(__result);
williamr@2
  1468
}
williamr@2
  1469
williamr@2
  1470
template<class _CharT, class _Alloc>
williamr@2
  1471
const _CharT* rope<_CharT,_Alloc>::replace_with_c_str() {
williamr@2
  1472
    if (0 == _M_tree_ptr._M_data) {
williamr@2
  1473
        _S_empty_c_str[0] = _S_eos((_CharT*)0);
williamr@2
  1474
        return _S_empty_c_str;
williamr@2
  1475
    }
williamr@2
  1476
    __GC_CONST _CharT* __old_c_string = _M_tree_ptr._M_data->_M_c_string;
williamr@2
  1477
    if (_RopeRep::_S_leaf == _M_tree_ptr._M_data->_M_tag && 0 != __old_c_string) {
williamr@2
  1478
	return(__old_c_string);
williamr@2
  1479
    }
williamr@2
  1480
    size_t __s = size();
williamr@2
  1481
    _CharT* __result = _M_tree_ptr.allocate(_S_rounded_up_size(__s));
williamr@2
  1482
    _S_flatten(_M_tree_ptr._M_data, __result);
williamr@2
  1483
    __result[__s] = _S_eos((_CharT*)0);
williamr@2
  1484
    _M_tree_ptr._M_data->_M_unref_nonnil();
williamr@2
  1485
    _M_tree_ptr._M_data = _S_new_RopeLeaf(__result, __s, get_allocator());
williamr@2
  1486
    return(__result);
williamr@2
  1487
}
williamr@2
  1488
williamr@2
  1489
// Algorithm specializations.  More should be added.
williamr@2
  1490
williamr@2
  1491
#ifndef _STLP_MSVC
williamr@2
  1492
// I couldn't get this to work with VC++
williamr@2
  1493
template<class _CharT,class _Alloc>
williamr@2
  1494
void
williamr@2
  1495
_Rope_rotate(_Rope_iterator<_CharT,_Alloc> __first,
williamr@2
  1496
              _Rope_iterator<_CharT,_Alloc> __middle,
williamr@2
  1497
              _Rope_iterator<_CharT,_Alloc> __last)
williamr@2
  1498
{
williamr@2
  1499
    _STLP_ASSERT(__first.container() == __middle.container()
williamr@2
  1500
                 && __middle.container() == __last.container())
williamr@2
  1501
    rope<_CharT,_Alloc>& __r(__first.container());
williamr@2
  1502
    rope<_CharT,_Alloc> __prefix = __r.substr(0, __first.index());
williamr@2
  1503
    rope<_CharT,_Alloc> __suffix = 
williamr@2
  1504
      __r.substr(__last.index(), __r.size() - __last.index());
williamr@2
  1505
    rope<_CharT,_Alloc> __part1 = 
williamr@2
  1506
      __r.substr(__middle.index(), __last.index() - __middle.index());
williamr@2
  1507
    rope<_CharT,_Alloc> __part2 = 
williamr@2
  1508
      __r.substr(__first.index(), __middle.index() - __first.index());
williamr@2
  1509
    __r = __prefix;
williamr@2
  1510
    __r += __part1;
williamr@2
  1511
    __r += __part2;
williamr@2
  1512
    __r += __suffix;
williamr@2
  1513
}
williamr@2
  1514
williamr@2
  1515
williamr@2
  1516
# if 0
williamr@2
  1517
// Probably not useful for several reasons:
williamr@2
  1518
// - for SGIs 7.1 compiler and probably some others,
williamr@2
  1519
//   this forces lots of rope<wchar_t, ...> instantiations, creating a
williamr@2
  1520
//   code bloat and compile time problem.  (Fixed in 7.2.)
williamr@2
  1521
// - wchar_t is 4 bytes wide on most UNIX platforms, making it unattractive
williamr@2
  1522
//   for unicode strings.  Unsigned short may be a better character
williamr@2
  1523
//   type.
williamr@2
  1524
inline void rotate(
williamr@2
  1525
		_Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __first,
williamr@2
  1526
                _Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __middle,
williamr@2
  1527
                _Rope_iterator<wchar_t,_STLP_DEFAULT_ALLOCATOR(char) > __last) {
williamr@2
  1528
    _Rope_rotate(__first, __middle, __last);
williamr@2
  1529
}
williamr@2
  1530
# endif
williamr@2
  1531
#endif /* _STLP_MSVC */
williamr@2
  1532
williamr@2
  1533
#   undef __RopeLeaf__ 
williamr@2
  1534
#   undef __RopeRep__ 
williamr@2
  1535
#   undef __RopeLeaf 
williamr@2
  1536
#   undef __RopeRep 
williamr@2
  1537
#   undef size_type
williamr@2
  1538
williamr@2
  1539
_STLP_END_NAMESPACE
williamr@2
  1540
williamr@2
  1541
# endif /* ROPEIMPL_H */
williamr@2
  1542
williamr@2
  1543
// Local Variables:
williamr@2
  1544
// mode:C++
williamr@2
  1545
// End: