epoc32/include/stdapis/stlportv5/stl/_tree.c
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:27:01 +0100
branchSymbian2
changeset 3 e1b950c65cb4
parent 2 epoc32/include/stdapis/stlport/stl/_tree.c@2fe1408b6811
child 4 837f303aceeb
permissions -rw-r--r--
Attempt to represent the S^2->S^3 header reorganisation as a series of "hg rename" operations
williamr@2
     1
/*
williamr@2
     2
 *
williamr@2
     3
 *
williamr@2
     4
 * Copyright (c) 1994
williamr@2
     5
 * Hewlett-Packard Company
williamr@2
     6
 *
williamr@2
     7
 * Copyright (c) 1996,1997
williamr@2
     8
 * Silicon Graphics Computer Systems, Inc.
williamr@2
     9
 *
williamr@2
    10
 * Copyright (c) 1997
williamr@2
    11
 * Moscow Center for SPARC Technology
williamr@2
    12
 *
williamr@2
    13
 * Copyright (c) 1999 
williamr@2
    14
 * Boris Fomitchev
williamr@2
    15
 *
williamr@2
    16
 * This material is provided "as is", with absolutely no warranty expressed
williamr@2
    17
 * or implied. Any use is at your own risk.
williamr@2
    18
 *
williamr@2
    19
 * Permission to use or copy this software for any purpose is hereby granted 
williamr@2
    20
 * without fee, provided the above notices are retained on all copies.
williamr@2
    21
 * Permission to modify the code and to distribute modified code is granted,
williamr@2
    22
 * provided the above notices are retained, and a notice that the code was
williamr@2
    23
 * modified is included with the above copyright notice.
williamr@2
    24
 *
williamr@2
    25
 * Modified CRP 7/10/00 for improved conformance / efficiency on insert_unique /
williamr@2
    26
 * insert_equal with valid hint -- efficiency is improved all around, and it is
williamr@2
    27
 * should now be standard conforming for complexity on insert point immediately
williamr@2
    28
 * after hint (amortized constant time).
williamr@2
    29
 *
williamr@2
    30
 */
williamr@2
    31
#ifndef _STLP_TREE_C
williamr@2
    32
#define _STLP_TREE_C
williamr@2
    33
williamr@2
    34
#ifndef _STLP_INTERNAL_TREE_H
williamr@2
    35
# include <stl/_tree.h>
williamr@2
    36
#endif
williamr@2
    37
williamr@2
    38
// fbp: these defines are for outline methods definitions.
williamr@2
    39
// needed for definitions to be portable. Should not be used in method bodies.
williamr@2
    40
# if defined  ( _STLP_NESTED_TYPE_PARAM_BUG )
williamr@2
    41
#  define __iterator__        _Rb_tree_iterator<_Value, _Nonconst_traits<_Value> > 
williamr@2
    42
#  define __size_type__       size_t
williamr@2
    43
#  define iterator __iterator__
williamr@2
    44
# else
williamr@2
    45
#  define __iterator__  _STLP_TYPENAME_ON_RETURN_TYPE _Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc>::iterator
williamr@2
    46
#  define __size_type__  _STLP_TYPENAME_ON_RETURN_TYPE _Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc>::size_type
williamr@2
    47
# endif
williamr@2
    48
williamr@2
    49
#if defined ( _STLP_DEBUG)
williamr@2
    50
#  define _Rb_tree __WORKAROUND_DBG_RENAME(Rb_tree)
williamr@2
    51
#endif
williamr@2
    52
williamr@2
    53
_STLP_BEGIN_NAMESPACE
williamr@2
    54
williamr@2
    55
# if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
williamr@2
    56
williamr@2
    57
template <class _Dummy> void _STLP_CALL
williamr@2
    58
_Rb_global<_Dummy>::_Rotate_left(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
williamr@2
    59
{
williamr@2
    60
  _Rb_tree_node_base* __y = __x->_M_right;
williamr@2
    61
  __x->_M_right = __y->_M_left;
williamr@2
    62
  if (__y->_M_left !=0)
williamr@2
    63
    __y->_M_left->_M_parent = __x;
williamr@2
    64
  __y->_M_parent = __x->_M_parent;
williamr@2
    65
williamr@2
    66
  if (__x == __root)
williamr@2
    67
    __root = __y;
williamr@2
    68
  else if (__x == __x->_M_parent->_M_left)
williamr@2
    69
    __x->_M_parent->_M_left = __y;
williamr@2
    70
  else
williamr@2
    71
    __x->_M_parent->_M_right = __y;
williamr@2
    72
  __y->_M_left = __x;
williamr@2
    73
  __x->_M_parent = __y;
williamr@2
    74
}
williamr@2
    75
williamr@2
    76
template <class _Dummy> void _STLP_CALL 
williamr@2
    77
_Rb_global<_Dummy>::_Rotate_right(_Rb_tree_node_base* __x, _Rb_tree_node_base*& __root)
williamr@2
    78
{
williamr@2
    79
  _Rb_tree_node_base* __y = __x->_M_left;
williamr@2
    80
  __x->_M_left = __y->_M_right;
williamr@2
    81
  if (__y->_M_right != 0)
williamr@2
    82
    __y->_M_right->_M_parent = __x;
williamr@2
    83
  __y->_M_parent = __x->_M_parent;
williamr@2
    84
williamr@2
    85
  if (__x == __root)
williamr@2
    86
    __root = __y;
williamr@2
    87
  else if (__x == __x->_M_parent->_M_right)
williamr@2
    88
    __x->_M_parent->_M_right = __y;
williamr@2
    89
  else
williamr@2
    90
    __x->_M_parent->_M_left = __y;
williamr@2
    91
  __y->_M_right = __x;
williamr@2
    92
  __x->_M_parent = __y;
williamr@2
    93
}
williamr@2
    94
williamr@2
    95
template <class _Dummy> void _STLP_CALL
williamr@2
    96
_Rb_global<_Dummy>::_Rebalance(_Rb_tree_node_base* __x, 
williamr@2
    97
			       _Rb_tree_node_base*& __root)
williamr@2
    98
{
williamr@2
    99
  __x->_M_color = _S_rb_tree_red;
williamr@2
   100
  while (__x != __root && __x->_M_parent->_M_color == _S_rb_tree_red) {
williamr@2
   101
    if (__x->_M_parent == __x->_M_parent->_M_parent->_M_left) {
williamr@2
   102
      _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_right;
williamr@2
   103
      if (__y && __y->_M_color == _S_rb_tree_red) {
williamr@2
   104
        __x->_M_parent->_M_color = _S_rb_tree_black;
williamr@2
   105
        __y->_M_color = _S_rb_tree_black;
williamr@2
   106
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
williamr@2
   107
        __x = __x->_M_parent->_M_parent;
williamr@2
   108
      }
williamr@2
   109
      else {
williamr@2
   110
        if (__x == __x->_M_parent->_M_right) {
williamr@2
   111
          __x = __x->_M_parent;
williamr@2
   112
          _Rotate_left(__x, __root);
williamr@2
   113
        }
williamr@2
   114
        __x->_M_parent->_M_color = _S_rb_tree_black;
williamr@2
   115
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
williamr@2
   116
        _Rotate_right(__x->_M_parent->_M_parent, __root);
williamr@2
   117
      }
williamr@2
   118
    }
williamr@2
   119
    else {
williamr@2
   120
      _Rb_tree_node_base* __y = __x->_M_parent->_M_parent->_M_left;
williamr@2
   121
      if (__y && __y->_M_color == _S_rb_tree_red) {
williamr@2
   122
        __x->_M_parent->_M_color = _S_rb_tree_black;
williamr@2
   123
        __y->_M_color = _S_rb_tree_black;
williamr@2
   124
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
williamr@2
   125
        __x = __x->_M_parent->_M_parent;
williamr@2
   126
      }
williamr@2
   127
      else {
williamr@2
   128
        if (__x == __x->_M_parent->_M_left) {
williamr@2
   129
          __x = __x->_M_parent;
williamr@2
   130
          _Rotate_right(__x, __root);
williamr@2
   131
        }
williamr@2
   132
        __x->_M_parent->_M_color = _S_rb_tree_black;
williamr@2
   133
        __x->_M_parent->_M_parent->_M_color = _S_rb_tree_red;
williamr@2
   134
        _Rotate_left(__x->_M_parent->_M_parent, __root);
williamr@2
   135
      }
williamr@2
   136
    }
williamr@2
   137
  }
williamr@2
   138
  __root->_M_color = _S_rb_tree_black;
williamr@2
   139
}
williamr@2
   140
williamr@2
   141
template <class _Dummy> _Rb_tree_node_base* _STLP_CALL
williamr@2
   142
_Rb_global<_Dummy>::_Rebalance_for_erase(_Rb_tree_node_base* __z,
williamr@2
   143
					 _Rb_tree_node_base*& __root,
williamr@2
   144
					 _Rb_tree_node_base*& __leftmost,
williamr@2
   145
					 _Rb_tree_node_base*& __rightmost)
williamr@2
   146
{
williamr@2
   147
  _Rb_tree_node_base* __y = __z;
williamr@2
   148
  _Rb_tree_node_base* __x = 0;
williamr@2
   149
  _Rb_tree_node_base* __x_parent = 0;
williamr@2
   150
  if (__y->_M_left == 0)     // __z has at most one non-null child. y == z.
williamr@2
   151
    __x = __y->_M_right;     // __x might be null.
williamr@2
   152
  else
williamr@2
   153
    if (__y->_M_right == 0)  // __z has exactly one non-null child. y == z.
williamr@2
   154
      __x = __y->_M_left;    // __x is not null.
williamr@2
   155
    else {                   // __z has two non-null children.  Set __y to
williamr@2
   156
      __y = __y->_M_right;   //   __z's successor.  __x might be null.
williamr@2
   157
      while (__y->_M_left != 0)
williamr@2
   158
        __y = __y->_M_left;
williamr@2
   159
      __x = __y->_M_right;
williamr@2
   160
    }
williamr@2
   161
  if (__y != __z) {          // relink y in place of z.  y is z's successor
williamr@2
   162
    __z->_M_left->_M_parent = __y; 
williamr@2
   163
    __y->_M_left = __z->_M_left;
williamr@2
   164
    if (__y != __z->_M_right) {
williamr@2
   165
      __x_parent = __y->_M_parent;
williamr@2
   166
      if (__x) __x->_M_parent = __y->_M_parent;
williamr@2
   167
      __y->_M_parent->_M_left = __x;      // __y must be a child of _M_left
williamr@2
   168
      __y->_M_right = __z->_M_right;
williamr@2
   169
      __z->_M_right->_M_parent = __y;
williamr@2
   170
    }
williamr@2
   171
    else
williamr@2
   172
      __x_parent = __y;  
williamr@2
   173
    if (__root == __z)
williamr@2
   174
      __root = __y;
williamr@2
   175
    else if (__z->_M_parent->_M_left == __z)
williamr@2
   176
      __z->_M_parent->_M_left = __y;
williamr@2
   177
    else 
williamr@2
   178
      __z->_M_parent->_M_right = __y;
williamr@2
   179
    __y->_M_parent = __z->_M_parent;
williamr@2
   180
    _STLP_STD::swap(__y->_M_color, __z->_M_color);
williamr@2
   181
    __y = __z;
williamr@2
   182
    // __y now points to node to be actually deleted
williamr@2
   183
  }
williamr@2
   184
  else {                        // __y == __z
williamr@2
   185
    __x_parent = __y->_M_parent;
williamr@2
   186
    if (__x) __x->_M_parent = __y->_M_parent;   
williamr@2
   187
    if (__root == __z)
williamr@2
   188
      __root = __x;
williamr@2
   189
    else 
williamr@2
   190
      if (__z->_M_parent->_M_left == __z)
williamr@2
   191
        __z->_M_parent->_M_left = __x;
williamr@2
   192
      else
williamr@2
   193
        __z->_M_parent->_M_right = __x;
williamr@2
   194
    if (__leftmost == __z) 
williamr@2
   195
      if (__z->_M_right == 0)        // __z->_M_left must be null also
williamr@2
   196
        __leftmost = __z->_M_parent;
williamr@2
   197
    // makes __leftmost == _M_header if __z == __root
williamr@2
   198
      else
williamr@2
   199
        __leftmost = _Rb_tree_node_base::_S_minimum(__x);
williamr@2
   200
    if (__rightmost == __z)  
williamr@2
   201
      if (__z->_M_left == 0)         // __z->_M_right must be null also
williamr@2
   202
        __rightmost = __z->_M_parent;  
williamr@2
   203
    // makes __rightmost == _M_header if __z == __root
williamr@2
   204
      else                      // __x == __z->_M_left
williamr@2
   205
        __rightmost = _Rb_tree_node_base::_S_maximum(__x);
williamr@2
   206
  }
williamr@2
   207
  if (__y->_M_color != _S_rb_tree_red) { 
williamr@2
   208
    while (__x != __root && (__x == 0 || __x->_M_color == _S_rb_tree_black))
williamr@2
   209
      if (__x == __x_parent->_M_left) {
williamr@2
   210
        _Rb_tree_node_base* __w = __x_parent->_M_right;
williamr@2
   211
        if (__w->_M_color == _S_rb_tree_red) {
williamr@2
   212
          __w->_M_color = _S_rb_tree_black;
williamr@2
   213
          __x_parent->_M_color = _S_rb_tree_red;
williamr@2
   214
          _Rotate_left(__x_parent, __root);
williamr@2
   215
          __w = __x_parent->_M_right;
williamr@2
   216
        }
williamr@2
   217
        if ((__w->_M_left == 0 || 
williamr@2
   218
             __w->_M_left->_M_color == _S_rb_tree_black) && (__w->_M_right == 0 || 
williamr@2
   219
             __w->_M_right->_M_color == _S_rb_tree_black)) {
williamr@2
   220
          __w->_M_color = _S_rb_tree_red;
williamr@2
   221
          __x = __x_parent;
williamr@2
   222
          __x_parent = __x_parent->_M_parent;
williamr@2
   223
        } else {
williamr@2
   224
          if (__w->_M_right == 0 || 
williamr@2
   225
              __w->_M_right->_M_color == _S_rb_tree_black) {
williamr@2
   226
            if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
williamr@2
   227
            __w->_M_color = _S_rb_tree_red;
williamr@2
   228
            _Rotate_right(__w, __root);
williamr@2
   229
            __w = __x_parent->_M_right;
williamr@2
   230
          }
williamr@2
   231
          __w->_M_color = __x_parent->_M_color;
williamr@2
   232
          __x_parent->_M_color = _S_rb_tree_black;
williamr@2
   233
          if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
williamr@2
   234
          _Rotate_left(__x_parent, __root);
williamr@2
   235
          break;
williamr@2
   236
        }
williamr@2
   237
      } else {                  // same as above, with _M_right <-> _M_left.
williamr@2
   238
        _Rb_tree_node_base* __w = __x_parent->_M_left;
williamr@2
   239
        if (__w->_M_color == _S_rb_tree_red) {
williamr@2
   240
          __w->_M_color = _S_rb_tree_black;
williamr@2
   241
          __x_parent->_M_color = _S_rb_tree_red;
williamr@2
   242
          _Rotate_right(__x_parent, __root);
williamr@2
   243
          __w = __x_parent->_M_left;
williamr@2
   244
        }
williamr@2
   245
        if ((__w->_M_right == 0 || 
williamr@2
   246
             __w->_M_right->_M_color == _S_rb_tree_black) && (__w->_M_left == 0 || 
williamr@2
   247
             __w->_M_left->_M_color == _S_rb_tree_black)) {
williamr@2
   248
          __w->_M_color = _S_rb_tree_red;
williamr@2
   249
          __x = __x_parent;
williamr@2
   250
          __x_parent = __x_parent->_M_parent;
williamr@2
   251
        } else {
williamr@2
   252
          if (__w->_M_left == 0 || 
williamr@2
   253
              __w->_M_left->_M_color == _S_rb_tree_black) {
williamr@2
   254
            if (__w->_M_right) __w->_M_right->_M_color = _S_rb_tree_black;
williamr@2
   255
            __w->_M_color = _S_rb_tree_red;
williamr@2
   256
            _Rotate_left(__w, __root);
williamr@2
   257
            __w = __x_parent->_M_left;
williamr@2
   258
          }
williamr@2
   259
          __w->_M_color = __x_parent->_M_color;
williamr@2
   260
          __x_parent->_M_color = _S_rb_tree_black;
williamr@2
   261
          if (__w->_M_left) __w->_M_left->_M_color = _S_rb_tree_black;
williamr@2
   262
          _Rotate_right(__x_parent, __root);
williamr@2
   263
          break;
williamr@2
   264
        }
williamr@2
   265
      }
williamr@2
   266
    if (__x) __x->_M_color = _S_rb_tree_black;
williamr@2
   267
  }
williamr@2
   268
  return __y;
williamr@2
   269
}
williamr@2
   270
williamr@2
   271
template <class _Dummy> _Rb_tree_node_base* _STLP_CALL
williamr@2
   272
_Rb_global<_Dummy>::_M_decrement(_Rb_tree_node_base* _M_node)
williamr@2
   273
{
williamr@2
   274
  if (_M_node->_M_color == _S_rb_tree_red && _M_node->_M_parent->_M_parent == _M_node)
williamr@2
   275
    _M_node = _M_node->_M_right;
williamr@2
   276
  else if (_M_node->_M_left != 0) {
williamr@2
   277
    _Base_ptr __y = _M_node->_M_left;
williamr@2
   278
    while (__y->_M_right != 0)
williamr@2
   279
      __y = __y->_M_right;
williamr@2
   280
    _M_node = __y;
williamr@2
   281
  }
williamr@2
   282
  else {
williamr@2
   283
    _Base_ptr __y = _M_node->_M_parent;
williamr@2
   284
    while (_M_node == __y->_M_left) {
williamr@2
   285
      _M_node = __y;
williamr@2
   286
      __y = __y->_M_parent;
williamr@2
   287
    }
williamr@2
   288
    _M_node = __y;
williamr@2
   289
  }
williamr@2
   290
  return _M_node;
williamr@2
   291
}
williamr@2
   292
williamr@2
   293
template <class _Dummy> _Rb_tree_node_base* _STLP_CALL
williamr@2
   294
_Rb_global<_Dummy>::_M_increment(_Rb_tree_node_base* _M_node)
williamr@2
   295
{
williamr@2
   296
  if (_M_node->_M_right != 0) {
williamr@2
   297
    _M_node = _M_node->_M_right;
williamr@2
   298
    while (_M_node->_M_left != 0)
williamr@2
   299
      _M_node = _M_node->_M_left;
williamr@2
   300
  }
williamr@2
   301
  else {
williamr@2
   302
    _Base_ptr __y = _M_node->_M_parent;
williamr@2
   303
    while (_M_node == __y->_M_right) {
williamr@2
   304
      _M_node = __y;
williamr@2
   305
      __y = __y->_M_parent;
williamr@2
   306
    }
williamr@2
   307
    if (_M_node->_M_right != __y)
williamr@2
   308
      _M_node = __y;
williamr@2
   309
  }
williamr@2
   310
  return _M_node;
williamr@2
   311
}
williamr@2
   312
williamr@2
   313
#endif /* defined (__BUILDING_STLPORT) || ! defined (_STLP_OWN_IOSTREAMS) */
williamr@2
   314
williamr@2
   315
williamr@2
   316
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   317
          class _Compare, class _Alloc> _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::operator=(const _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>& __x)
williamr@2
   318
{
williamr@2
   319
  if (this != &__x) {
williamr@2
   320
                                // Note that _Key may be a constant type.
williamr@2
   321
    clear();
williamr@2
   322
    _M_node_count = 0;
williamr@2
   323
    _M_key_compare = __x._M_key_compare;        
williamr@2
   324
    if (__x._M_root() == 0) {
williamr@2
   325
      _M_root() = 0;
williamr@2
   326
      _M_leftmost() = this->_M_header._M_data;
williamr@2
   327
      _M_rightmost() = this->_M_header._M_data;
williamr@2
   328
    }
williamr@2
   329
    else {
williamr@2
   330
      _M_root() = _M_copy(__x._M_root(), this->_M_header._M_data);
williamr@2
   331
      _M_leftmost() = _S_minimum(_M_root());
williamr@2
   332
      _M_rightmost() = _S_maximum(_M_root());
williamr@2
   333
      _M_node_count = __x._M_node_count;
williamr@2
   334
    }
williamr@2
   335
  }
williamr@2
   336
  return *this;
williamr@2
   337
}
williamr@2
   338
williamr@2
   339
// CRP 7/10/00 inserted argument __w_, which is another hint (meant to
williamr@2
   340
// act like __x_ and ignore a portion of the if conditions -- specify
williamr@2
   341
// __w_ != 0 to bypass comparison as false or __x_ != 0 to bypass
williamr@2
   342
// comparison as true)
williamr@2
   343
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   344
          class _Compare, class _Alloc> __iterator__ 
williamr@2
   345
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::_M_insert(_Rb_tree_node_base* __x_, _Rb_tree_node_base* __y_, const _Value& __v,
williamr@2
   346
  _Rb_tree_node_base* __w_)
williamr@2
   347
{
williamr@2
   348
  _Link_type __w = (_Link_type) __w_;
williamr@2
   349
  _Link_type __x = (_Link_type) __x_;
williamr@2
   350
  _Link_type __y = (_Link_type) __y_;
williamr@2
   351
  _Link_type __z;
williamr@2
   352
williamr@2
   353
  if ( __y == this->_M_header._M_data ||
williamr@2
   354
       ( __w == 0 && // If w != 0, the remainder fails to false
williamr@2
   355
         ( __x != 0 ||     // If x != 0, the remainder succeeds to true
williamr@2
   356
           _M_key_compare( _KeyOfValue()(__v), _S_key(__y) ) )
williamr@2
   357
	 )
williamr@2
   358
       ) {
williamr@2
   359
    
williamr@2
   360
    __z = _M_create_node(__v);
williamr@2
   361
    _S_left(__y) = __z;               // also makes _M_leftmost() = __z 
williamr@2
   362
                                      //    when __y == _M_header
williamr@2
   363
    if (__y == this->_M_header._M_data) {
williamr@2
   364
      _M_root() = __z;
williamr@2
   365
      _M_rightmost() = __z;
williamr@2
   366
    }
williamr@2
   367
    else if (__y == _M_leftmost())
williamr@2
   368
      _M_leftmost() = __z;   // maintain _M_leftmost() pointing to min node
williamr@2
   369
  }
williamr@2
   370
  else {
williamr@2
   371
    __z = _M_create_node(__v);
williamr@2
   372
    _S_right(__y) = __z;
williamr@2
   373
    if (__y == _M_rightmost())
williamr@2
   374
      _M_rightmost() = __z;  // maintain _M_rightmost() pointing to max node
williamr@2
   375
  }
williamr@2
   376
  _S_parent(__z) = __y;
williamr@2
   377
  _S_left(__z) = 0;
williamr@2
   378
  _S_right(__z) = 0;
williamr@2
   379
  _Rb_global_inst::_Rebalance(__z, this->_M_header._M_data->_M_parent);
williamr@2
   380
  ++_M_node_count;
williamr@2
   381
  return iterator(__z);
williamr@2
   382
}
williamr@2
   383
williamr@2
   384
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   385
          class _Compare, class _Alloc> __iterator__
williamr@2
   386
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::insert_equal(const _Value& __v)
williamr@2
   387
{
williamr@2
   388
  _Link_type __y = this->_M_header._M_data;
williamr@2
   389
  _Link_type __x = _M_root();
williamr@2
   390
  while (__x != 0) {
williamr@2
   391
    __y = __x;
williamr@2
   392
    __x = _M_key_compare(_KeyOfValue()(__v), _S_key(__x)) ? 
williamr@2
   393
            _S_left(__x) : _S_right(__x);
williamr@2
   394
  }
williamr@2
   395
  return _M_insert(__x, __y, __v);
williamr@2
   396
}
williamr@2
   397
williamr@2
   398
williamr@2
   399
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   400
          class _Compare, class _Alloc> pair< _Rb_tree_iterator<_Value, _Nonconst_traits<_Value> >, bool> _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::insert_unique(const _Value& __v)
williamr@2
   401
{
williamr@2
   402
  _Link_type __y = this->_M_header._M_data;
williamr@2
   403
  _Link_type __x = _M_root();
williamr@2
   404
  bool __comp = true;
williamr@2
   405
  while (__x != 0) {
williamr@2
   406
    __y = __x;
williamr@2
   407
    __comp = _M_key_compare(_KeyOfValue()(__v), _S_key(__x));
williamr@2
   408
    __x = __comp ? _S_left(__x) : _S_right(__x);
williamr@2
   409
  }
williamr@2
   410
  iterator __j = iterator(__y);   
williamr@2
   411
  if (__comp)
williamr@2
   412
    if (__j == begin())     
williamr@2
   413
      return pair<iterator,bool>(_M_insert(/* __x*/ __y, __y, __v), true);
williamr@2
   414
    else
williamr@2
   415
      --__j;
williamr@2
   416
  if (_M_key_compare(_S_key(__j._M_node), _KeyOfValue()(__v)))
williamr@2
   417
    return pair<iterator,bool>(_M_insert(__x, __y, __v), true);
williamr@2
   418
  return pair<iterator,bool>(__j, false);
williamr@2
   419
}
williamr@2
   420
williamr@2
   421
// Modifications CRP 7/10/00 as noted to improve conformance and
williamr@2
   422
// efficiency.
williamr@2
   423
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   424
          class _Compare, class _Alloc> __iterator__ 
williamr@2
   425
_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> ::insert_unique(iterator __position, const _Value& __v)
williamr@2
   426
{
williamr@2
   427
  if (__position._M_node == this->_M_header._M_data->_M_left) { // begin()
williamr@2
   428
williamr@2
   429
    // if the container is empty, fall back on insert_unique.
williamr@2
   430
    if (size() <= 0)
williamr@2
   431
      return insert_unique(__v).first;
williamr@2
   432
williamr@2
   433
    if ( _M_key_compare(_KeyOfValue()(__v), _S_key(__position._M_node)))
williamr@2
   434
      return _M_insert(__position._M_node, __position._M_node, __v);
williamr@2
   435
    // first argument just needs to be non-null 
williamr@2
   436
    else
williamr@2
   437
      {
williamr@2
   438
	bool __comp_pos_v = _M_key_compare( _S_key(__position._M_node), _KeyOfValue()(__v) );
williamr@2
   439
	
williamr@2
   440
	if (__comp_pos_v == false)  // compare > and compare < both false so compare equal
williamr@2
   441
	  return __position;
williamr@2
   442
	//Below __comp_pos_v == true
williamr@2
   443
williamr@2
   444
	// Standard-conformance - does the insertion point fall immediately AFTER
williamr@2
   445
	// the hint?
williamr@2
   446
	iterator __after = __position;
williamr@2
   447
	++__after;
williamr@2
   448
williamr@2
   449
	// Check for only one member -- in that case, __position points to itself,
williamr@2
   450
	// and attempting to increment will cause an infinite loop.
williamr@2
   451
	if (__after._M_node == this->_M_header._M_data)
williamr@2
   452
	  // Check guarantees exactly one member, so comparison was already
williamr@2
   453
	  // performed and we know the result; skip repeating it in _M_insert
williamr@2
   454
	  // by specifying a non-zero fourth argument.
williamr@2
   455
	  return _M_insert(0, __position._M_node, __v, __position._M_node);
williamr@2
   456
		
williamr@2
   457
	
williamr@2
   458
	// All other cases:
williamr@2
   459
	
williamr@2
   460
	// Optimization to catch insert-equivalent -- save comparison results,
williamr@2
   461
	// and we get this for free.
williamr@2
   462
	if(_M_key_compare( _KeyOfValue()(__v), _S_key(__after._M_node) )) {
williamr@2
   463
	  if (_S_right(__position._M_node) == 0)
williamr@2
   464
	    return _M_insert(0, __position._M_node, __v, __position._M_node);
williamr@2
   465
	  else
williamr@2
   466
	    return _M_insert(__after._M_node, __after._M_node, __v);
williamr@2
   467
	} else {
williamr@2
   468
	    return insert_unique(__v).first;
williamr@2
   469
	}
williamr@2
   470
      }
williamr@2
   471
williamr@2
   472
  } else if (__position._M_node == this->_M_header._M_data) { // end()
williamr@2
   473
    if (_M_key_compare(_S_key(_M_rightmost()), _KeyOfValue()(__v)))
williamr@2
   474
      // pass along to _M_insert that it can skip comparing
williamr@2
   475
      // v, Key ; since compare Key, v was true, compare v, Key must be false.
williamr@2
   476
      return _M_insert(0, _M_rightmost(), __v, __position._M_node); // Last argument only needs to be non-null
williamr@2
   477
    else
williamr@2
   478
      return insert_unique(__v).first;
williamr@2
   479
  } else {
williamr@2
   480
    iterator __before = __position;
williamr@2
   481
    --__before;
williamr@2
   482
    
williamr@2
   483
    bool __comp_v_pos = _M_key_compare(_KeyOfValue()(__v), _S_key(__position._M_node));
williamr@2
   484
williamr@2
   485
    if (__comp_v_pos
williamr@2
   486
      && _M_key_compare( _S_key(__before._M_node), _KeyOfValue()(__v) )) {
williamr@2
   487
williamr@2
   488
      if (_S_right(__before._M_node) == 0)
williamr@2
   489
        return _M_insert(0, __before._M_node, __v, __before._M_node); // Last argument only needs to be non-null
williamr@2
   490
      else
williamr@2
   491
        return _M_insert(__position._M_node, __position._M_node, __v);
williamr@2
   492
    // first argument just needs to be non-null 
williamr@2
   493
    } else
williamr@2
   494
      {
williamr@2
   495
	// Does the insertion point fall immediately AFTER the hint?
williamr@2
   496
	iterator __after = __position;
williamr@2
   497
	++__after;
williamr@2
   498
	
williamr@2
   499
	// Optimization to catch equivalent cases and avoid unnecessary comparisons
williamr@2
   500
	bool __comp_pos_v = !__comp_v_pos;  // Stored this result earlier
williamr@2
   501
	// If the earlier comparison was true, this comparison doesn't need to be
williamr@2
   502
	// performed because it must be false.  However, if the earlier comparison
williamr@2
   503
	// was false, we need to perform this one because in the equal case, both will
williamr@2
   504
	// be false.
williamr@2
   505
	if (!__comp_v_pos) __comp_pos_v = _M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v));
williamr@2
   506
	
williamr@2
   507
	if ( (!__comp_v_pos) // comp_v_pos true implies comp_v_pos false
williamr@2
   508
	     && __comp_pos_v
williamr@2
   509
	     && (__after._M_node == this->_M_header._M_data ||
williamr@2
   510
	        _M_key_compare( _KeyOfValue()(__v), _S_key(__after._M_node) ))) {
williamr@2
   511
	  
williamr@2
   512
	  if (_S_right(__position._M_node) == 0)
williamr@2
   513
	    return _M_insert(0, __position._M_node, __v, __position._M_node);
williamr@2
   514
	  else
williamr@2
   515
	    return _M_insert(__after._M_node, __after._M_node, __v);
williamr@2
   516
	} else {
williamr@2
   517
	  // Test for equivalent case
williamr@2
   518
	  if (__comp_v_pos == __comp_pos_v)
williamr@2
   519
	    return __position;
williamr@2
   520
	  else
williamr@2
   521
	    return insert_unique(__v).first;
williamr@2
   522
	}
williamr@2
   523
      }
williamr@2
   524
  }
williamr@2
   525
}
williamr@2
   526
williamr@2
   527
williamr@2
   528
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   529
          class _Compare, class _Alloc> __iterator__ 
williamr@2
   530
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::insert_equal(iterator __position, const _Value& __v)
williamr@2
   531
{
williamr@2
   532
  if (__position._M_node == this->_M_header._M_data->_M_left) { // begin()
williamr@2
   533
williamr@2
   534
    // Check for zero members
williamr@2
   535
    if (size() <= 0)
williamr@2
   536
        return insert_equal(__v);
williamr@2
   537
williamr@2
   538
    if (!_M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v)))
williamr@2
   539
      return _M_insert(__position._M_node, __position._M_node, __v);
williamr@2
   540
    else    {
williamr@2
   541
      // Check for only one member
williamr@2
   542
      if (__position._M_node->_M_left == __position._M_node)
williamr@2
   543
        // Unlike insert_unique, can't avoid doing a comparison here.
williamr@2
   544
        return _M_insert(0, __position._M_node, __v);
williamr@2
   545
                
williamr@2
   546
      // All other cases:
williamr@2
   547
      // Standard-conformance - does the insertion point fall immediately AFTER
williamr@2
   548
      // the hint?
williamr@2
   549
      iterator __after = __position;
williamr@2
   550
      ++__after;
williamr@2
   551
      
williamr@2
   552
      // Already know that compare(pos, v) must be true!
williamr@2
   553
      // Therefore, we want to know if compare(after, v) is false.
williamr@2
   554
      // (i.e., we now pos < v, now we want to know if v <= after)
williamr@2
   555
      // If not, invalid hint.
williamr@2
   556
      if ( __after._M_node==this->_M_header._M_data ||
williamr@2
   557
	   !_M_key_compare( _S_key(__after._M_node), _KeyOfValue()(__v) ) ) {
williamr@2
   558
        if (_S_right(__position._M_node) == 0)
williamr@2
   559
          return _M_insert(0, __position._M_node, __v, __position._M_node);
williamr@2
   560
        else
williamr@2
   561
          return _M_insert(__after._M_node, __after._M_node, __v);
williamr@2
   562
      } else // Invalid hint
williamr@2
   563
        return insert_equal(__v);
williamr@2
   564
    }
williamr@2
   565
  } else if (__position._M_node == this->_M_header._M_data) {// end()
williamr@2
   566
    if (!_M_key_compare(_KeyOfValue()(__v), _S_key(_M_rightmost())))
williamr@2
   567
      return _M_insert(0, _M_rightmost(), __v, __position._M_node); // Last argument only needs to be non-null
williamr@2
   568
    else
williamr@2
   569
      return insert_equal(__v);
williamr@2
   570
  } else {
williamr@2
   571
    iterator __before = __position;
williamr@2
   572
    --__before;
williamr@2
   573
    // store the result of the comparison between pos and v so
williamr@2
   574
    // that we don't have to do it again later.  Note that this reverses the shortcut
williamr@2
   575
    // on the if, possibly harming efficiency in comparisons; I think the harm will
williamr@2
   576
    // be negligible, and to do what I want to do (save the result of a comparison so
williamr@2
   577
    // that it can be re-used) there is no alternative.  Test here is for before <= v <= pos.
williamr@2
   578
    bool __comp_pos_v = _M_key_compare(_S_key(__position._M_node), _KeyOfValue()(__v));
williamr@2
   579
    if (!__comp_pos_v
williamr@2
   580
        && !_M_key_compare(_KeyOfValue()(__v), _S_key(__before._M_node))) {
williamr@2
   581
      if (_S_right(__before._M_node) == 0)
williamr@2
   582
        return _M_insert(0, __before._M_node, __v, __before._M_node); // Last argument only needs to be non-null
williamr@2
   583
      else
williamr@2
   584
        return _M_insert(__position._M_node, __position._M_node, __v);
williamr@2
   585
    } else  {
williamr@2
   586
      // Does the insertion point fall immediately AFTER the hint?
williamr@2
   587
      // Test for pos < v <= after
williamr@2
   588
      iterator __after = __position;
williamr@2
   589
      ++__after;
williamr@2
   590
      
williamr@2
   591
      if (__comp_pos_v
williamr@2
   592
	  && ( __after._M_node==this->_M_header._M_data 
williamr@2
   593
	       || !_M_key_compare( _S_key(__after._M_node), _KeyOfValue()(__v) ) ) ) {
williamr@2
   594
        if (_S_right(__position._M_node) == 0)
williamr@2
   595
          return _M_insert(0, __position._M_node, __v, __position._M_node);
williamr@2
   596
        else
williamr@2
   597
          return _M_insert(__after._M_node, __after._M_node, __v);
williamr@2
   598
      } else // Invalid hint
williamr@2
   599
        return insert_equal(__v);
williamr@2
   600
    }
williamr@2
   601
  }
williamr@2
   602
}
williamr@2
   603
williamr@2
   604
template <class _Key, class _Value, class _KeyOfValue, class _Compare, class _Alloc> _Rb_tree_node<_Value>* 
williamr@2
   605
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::_M_copy(_Rb_tree_node<_Value>* __x, _Rb_tree_node<_Value>* __p)
williamr@2
   606
{
williamr@2
   607
                        // structural copy.  __x and __p must be non-null.
williamr@2
   608
  _STLP_LEAVE_VOLATILE _Link_type __top = _M_clone_node(__x);
williamr@2
   609
  __top->_M_parent = __p;
williamr@2
   610
  
williamr@2
   611
  _STLP_TRY {
williamr@2
   612
    if (__x->_M_right)
williamr@2
   613
      __top->_M_right = _M_copy(_S_right(__x), __top);
williamr@2
   614
    __p = __top;
williamr@2
   615
    __x = _S_left(__x);
williamr@2
   616
williamr@2
   617
    while (__x != 0) {
williamr@2
   618
      _Link_type __y = _M_clone_node(__x);
williamr@2
   619
      __p->_M_left = __y;
williamr@2
   620
      __y->_M_parent = __p;
williamr@2
   621
      if (__x->_M_right)
williamr@2
   622
        __y->_M_right = _M_copy(_S_right(__x), __y);
williamr@2
   623
      __p = __y;
williamr@2
   624
      __x = _S_left(__x);
williamr@2
   625
    }
williamr@2
   626
  }
williamr@2
   627
  _STLP_UNWIND(_M_erase(__top));
williamr@2
   628
williamr@2
   629
  return __top;
williamr@2
   630
}
williamr@2
   631
williamr@2
   632
// this has to stay out-of-line : it's recursive
williamr@2
   633
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   634
          class _Compare, class _Alloc> void 
williamr@2
   635
_Rb_tree<_Key,_Value,_KeyOfValue,
williamr@2
   636
  _Compare,_Alloc>::_M_erase(_Rb_tree_node<_Value>* __x)
williamr@2
   637
{
williamr@2
   638
                                // erase without rebalancing
williamr@2
   639
  while (__x != 0) {
williamr@2
   640
    _M_erase(_S_right(__x));
williamr@2
   641
    _Link_type __y = _S_left(__x);
williamr@2
   642
    _STLP_STD::_Destroy(&__x->_M_value_field);
williamr@2
   643
    this->_M_header.deallocate(__x,1);
williamr@2
   644
    __x = __y;
williamr@2
   645
  }
williamr@2
   646
}
williamr@2
   647
williamr@2
   648
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   649
          class _Compare, class _Alloc> __size_type__ 
williamr@2
   650
_Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc> ::count(const _Key& __k) const
williamr@2
   651
{
williamr@2
   652
  pair<const_iterator, const_iterator> __p = equal_range(__k);
williamr@2
   653
  size_type __n = distance(__p.first, __p.second);
williamr@2
   654
  return __n;
williamr@2
   655
}
williamr@2
   656
williamr@2
   657
inline int 
williamr@2
   658
__black_count(_Rb_tree_node_base* __node, _Rb_tree_node_base* __root)
williamr@2
   659
{
williamr@2
   660
  if (__node == 0)
williamr@2
   661
    return 0;
williamr@2
   662
  else {
williamr@2
   663
    int __bc = __node->_M_color == _S_rb_tree_black ? 1 : 0;
williamr@2
   664
    if (__node == __root)
williamr@2
   665
      return __bc;
williamr@2
   666
    else
williamr@2
   667
      return __bc + __black_count(__node->_M_parent, __root);
williamr@2
   668
  }
williamr@2
   669
}
williamr@2
   670
williamr@2
   671
template <class _Key, class _Value, class _KeyOfValue, 
williamr@2
   672
          class _Compare, class _Alloc> bool _Rb_tree<_Key,_Value,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const
williamr@2
   673
{
williamr@2
   674
  if (_M_node_count == 0 || begin() == end())
williamr@2
   675
    return _M_node_count == 0 && begin() == end() && this->_M_header._M_data->_M_left == this->_M_header._M_data
williamr@2
   676
      && this->_M_header._M_data->_M_right == this->_M_header._M_data;
williamr@2
   677
  
williamr@2
   678
  int __len = __black_count(_M_leftmost(), _M_root());
williamr@2
   679
  for (const_iterator __it = begin(); __it != end(); ++__it) {
williamr@2
   680
    _Link_type __x = (_Link_type) __it._M_node;
williamr@2
   681
    _Link_type __L = _S_left(__x);
williamr@2
   682
    _Link_type __R = _S_right(__x);
williamr@2
   683
williamr@2
   684
    if (__x->_M_color == _S_rb_tree_red)
williamr@2
   685
      if ((__L && __L->_M_color == _S_rb_tree_red) ||
williamr@2
   686
          (__R && __R->_M_color == _S_rb_tree_red))
williamr@2
   687
        return false;
williamr@2
   688
williamr@2
   689
    if (__L && _M_key_compare(_S_key(__x), _S_key(__L)))
williamr@2
   690
      return false;
williamr@2
   691
    if (__R && _M_key_compare(_S_key(__R), _S_key(__x)))
williamr@2
   692
      return false;
williamr@2
   693
williamr@2
   694
    if (!__L && !__R && __black_count(__x, _M_root()) != __len)
williamr@2
   695
      return false;
williamr@2
   696
  }
williamr@2
   697
williamr@2
   698
  if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root()))
williamr@2
   699
    return false;
williamr@2
   700
  if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root()))
williamr@2
   701
    return false;
williamr@2
   702
williamr@2
   703
  return true;
williamr@2
   704
}
williamr@2
   705
_STLP_END_NAMESPACE
williamr@2
   706
williamr@2
   707
# undef __iterator__        
williamr@2
   708
# undef iterator
williamr@2
   709
# undef __size_type__  
williamr@2
   710
williamr@2
   711
#endif /*  _STLP_TREE_C */
williamr@2
   712
williamr@2
   713
// Local Variables:
williamr@2
   714
// mode:C++
williamr@2
   715
// End: