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