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