blob: 67236c275f64e52f8d29b60105baa14f361e4da7 [file] [log] [blame]
/***************************************************************************
*
* _tree.h - Declarations for the Standard Library tree classes
*
* This is an internal header file used to implement the C++ Standard
* Library. It should never be #included directly by a program.
*
* $Id$
*
***************************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* Copyright 1994-2006 Rogue Wave Software.
*
***************************************************************************
*
* Copyright (c) 1994
* Hewlett-Packard Company
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Hewlett-Packard Company makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
*
**************************************************************************/
/***************************************************************************
*
* Red-black tree class, designed for use in implementing associative
* containers (set, multiset, map, and multimap). The insertion and
* deletion algorithms are based on those in Cormen, Leiserson, and
* Rivest, Introduction to Algorithms (MIT Press, 1990), except that:
*
* (1) the header cell is maintained with links not only to the root
* but also to the leftmost node of the tree, to enable constant time
* begin(), and to the rightmost node of the tree, to enable linear time
* performance when used with the generic set algorithms (set_union,
* etc.);
*
* (2) when a node being deleted has two children its successor node
* is relinked into its place, rather than copied, so that the only
* iterators invalidated are those referring to the deleted node.
*
**************************************************************************/
#ifndef _RWSTD_RW_TREE_H_INCLUDED
#define _RWSTD_RW_TREE_H_INCLUDED
#ifndef _RWSTD_RW_ALGOBASE_H_INCLUDED
# include <rw/_algobase.h>
#endif // _RWSTD_RW_ALGOBASE_H_INCLUDED
#ifndef _RWSTD_RW_ITERATOR_H_INCLUDED
# include <rw/_iterator.h>
#endif // _RWSTD_RW_ITERATOR_H_INCLUDED
_RWSTD_NAMESPACE (__rw) {
template <class _Alloc, class _Val, class _Key, class _KeyOf>
struct __rw_rb_tree_node
{
enum _C_color_t { _C_red, _C_black };
typedef _Val& reference;
typedef _Alloc allocator_type;
typedef _RWSTD_REBIND (allocator_type, __rw_rb_tree_node) _C_node_alloc_t;
typedef _RWSTD_REBIND (allocator_type, _Key) _C_key_alloc_t;
typedef _TYPENAME _C_node_alloc_t::pointer _C_link_t;
typedef _TYPENAME _C_key_alloc_t::const_reference _C_const_key_ref;
_C_color_t _C_color;
_C_link_t _C_parent;
_C_link_t _C_child [2]; // left (0) and right (1) children
_Val _C_value;
static _C_link_t _C_minmax (_C_link_t __lnk, bool __do_max) {
_RWSTD_ASSERT (_C_link_t () != __lnk);
while (_C_link_t () != __lnk->_C_child [__do_max])
__lnk = __lnk->_C_child [__do_max];
return __lnk;
}
static _C_link_t _C_min (_C_link_t __lnk) {
return _C_minmax (__lnk, false);
}
static _C_link_t _C_max (_C_link_t __lnk) {
return _C_minmax (__lnk, true);
}
_C_const_key_ref _C_key () const {
return _KeyOf ()(_C_value);
}
};
// iterator implements inorder traversal; i.e., nodes are visited
// recursively in this order: left subtree, root, right subtree
template <class _TypeT, class _DiffT,
class _Pointer, class _Reference, class _Node>
class __rw_tree_iter
: public _STD::iterator <_STD::bidirectional_iterator_tag,
_TypeT, _DiffT, _Pointer, _Reference>
{
typedef _STD::iterator <_STD::bidirectional_iterator_tag,
_TypeT, _DiffT, _Pointer, _Reference> _C_iter_base;
public:
typedef _TYPENAME _C_iter_base::value_type value_type;
typedef _TYPENAME _C_iter_base::difference_type difference_type;
typedef _TYPENAME _C_iter_base::pointer pointer;
typedef _TYPENAME _C_iter_base::reference reference;
typedef _TYPENAME _C_iter_base::iterator_category iterator_category;
typedef _Node _C_node_t;
typedef _TYPENAME _C_node_t::allocator_type allocator_type;
typedef _TYPENAME _C_node_t::_C_link_t _C_link_t;
typedef const value_type* const_pointer;
typedef const value_type& const_reference;
typedef __rw_tree_iter<_TypeT, _DiffT, value_type*, value_type&, _C_node_t>
_C_iterator;
_C_link_t _C_node;
__rw_tree_iter () { /* empty */ }
// no copy ctor other than the one below is defined
// will use a compiler generated one if __rw_tree_iter != _C_iterator
__rw_tree_iter (const _C_iterator &__rhs)
: _C_node (__rhs._C_node) { }
template <class _Ptr, class _Ref>
__rw_tree_iter (const __rw_tree_iter<_TypeT, _DiffT, _Ptr, _Ref, _Node>&
__rhs)
: _C_node (__rhs._C_node) { }
__rw_tree_iter (_C_link_t __lnk)
: _C_node (__lnk) {}
#ifdef SNI
difference_type operator- (const __rw_tree_iter&) const {
return 0;
}
#endif
__rw_tree_iter& operator++ () {
if (_C_link_t () != _C_node->_C_child [1]) {
_C_node = _C_node_t::_C_min (_C_node->_C_child [1]);
}
else {
_C_link_t __tmp = _C_node->_C_parent;
while (_C_node == __tmp->_C_child [1]) {
_C_node = __tmp;
__tmp = __tmp->_C_parent;
}
if (_C_node->_C_child [1] != __tmp)
_C_node = __tmp;
}
return *this;
}
__rw_tree_iter& operator-- () {
if ( _C_node->_C_color == _C_node_t::_C_red
&& _C_node->_C_parent->_C_parent == _C_node)
//
// Check for header.
//
_C_node = _C_node->_C_child [1]; // Return rightmost.
else if (_C_link_t () != _C_node->_C_child [0]) {
_C_node = _C_node_t::_C_max (_C_node->_C_child [0]);
}
else {
_C_link_t __tmp = _C_node->_C_parent;
while (_C_node == __tmp->_C_child [0]) {
_C_node = __tmp;
__tmp = __tmp->_C_parent;
}
_C_node = __tmp;
}
return *this;
}
__rw_tree_iter operator++ (int) {
__rw_tree_iter __tmp (*this);
return ++*this, __tmp;
}
__rw_tree_iter operator-- (int) {
__rw_tree_iter __tmp (*this);
return --*this, __tmp;
}
reference operator* () const {
return _C_node->_C_value;
}
_RWSTD_OPERATOR_ARROW (pointer operator-> () const);
};
#define _RWSTD_TREE_ITER(n) \
__rw_tree_iter <_TypeT, _DiffT, _Ptr##n, _Ref##n, _Node>
template <class _TypeT, class _DiffT,
class _Ptr1, class _Ref1, class _Ptr2, class _Ref2, class _Node>
inline bool
operator== (const _RWSTD_TREE_ITER (1) &__lhs,
const _RWSTD_TREE_ITER (2) &__rhs)
{
return __lhs._C_node == __rhs._C_node;
}
template <class _TypeT, class _DiffT,
class _Ptr1, class _Ref1, class _Ptr2, class _Ref2, class _Node>
inline bool
operator!= (const _RWSTD_TREE_ITER (1) &__lhs,
const _RWSTD_TREE_ITER (2) &__rhs)
{
return !(__lhs == __rhs);
}
#undef _RWSTD_TREE_ITER
// for convenience
#undef _ITER_NODE
#define _ITER_NODE(it) (_ITER_BASE (it)._C_node)
_EXPORT
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
class __rb_tree : private _Alloc
{
private:
typedef __rw_rb_tree_node<_Alloc,_Val,_Key,_KeyOf> _C_node_t;
typedef _RWSTD_ALLOC_TYPE (_Alloc,_Val) _C_val_alloc_t;
typedef _RWSTD_REBIND (_Alloc, _Key) _C_key_alloc_t;
typedef _RWSTD_REBIND (_Alloc, _C_node_t) _C_node_alloc_t;
typedef _TYPENAME _C_node_alloc_t::pointer _C_link_t;
public:
typedef _Key key_type;
typedef _Val value_type;
typedef _Comp key_compare;
typedef _Alloc allocator_type;
typedef _TYPENAME _C_val_alloc_t::pointer pointer;
typedef _TYPENAME _C_val_alloc_t::const_pointer const_pointer;
typedef _TYPENAME allocator_type::size_type size_type;
typedef _TYPENAME allocator_type::difference_type difference_type;
typedef _TYPENAME _C_val_alloc_t::reference reference;
typedef _TYPENAME _C_val_alloc_t::const_reference const_reference;
private:
typedef __rw_tree_iter<value_type, difference_type, pointer,
reference, _C_node_t> _C_tree_iter;
typedef __rw_tree_iter<value_type, difference_type, const_pointer,
const_reference, _C_node_t> _C_tree_citer;
public:
#ifndef _RWSTD_NO_DEBUG_ITER
typedef __rw_debug_iter <__rb_tree, _C_tree_iter, _C_tree_iter>
iterator;
typedef __rw_debug_iter <__rb_tree, _C_tree_citer, _C_tree_iter>
const_iterator;
iterator _C_make_iter (_C_link_t __node) {
return iterator (*this, _C_tree_iter (__node));
}
const_iterator _C_make_iter (_C_link_t __node) const {
return const_iterator (*this, _C_tree_citer (__node));
}
#else // if defined (_RWSTD_NO_DEBUG_ITER)
typedef _C_tree_iter iterator;
typedef _C_tree_citer const_iterator;
iterator _C_make_iter (_C_link_t __node) {
return iterator (__node);
}
const_iterator _C_make_iter (_C_link_t __node) const {
return const_iterator (__node);
}
#endif // _RWSTD_NO_DEBUG_ITER
private:
#ifdef _RWSTD_NO_NESTED_CLASS_ACCESS
// allow _C_node_buf access to __rb_tree's private type(s)
// if the resolution of cwg issue 45 is not yet implemented
struct _C_node_buf;
friend struct _C_node_buf;
#endif // _RWSTD_NO_NESTED_CLASS_ACCESS
struct _C_node_buf {
typedef _RWSTD_REBIND (allocator_type, _C_node_buf) _C_buf_alloc_t;
typedef _TYPENAME _C_buf_alloc_t::pointer _C_buf_ptr_t;
_C_buf_ptr_t _C_next_buffer;
size_type size;
_C_link_t _C_buffer;
};
typedef _TYPENAME _C_node_buf::_C_buf_alloc_t _C_buf_alloc_t;
typedef _TYPENAME _C_node_buf::_C_buf_ptr_t _C_buf_ptr_t;
_C_buf_ptr_t _C_buf_list;
_C_link_t _C_free_list;
_C_link_t _C_next_avail;
_C_link_t _C_last;
void _C_add_new_buffer ();
void _C_deallocate_buffers ();
//
// Return a node from the free list or new storage
//
_C_link_t _C_get_link () {
_C_link_t __tmp = _C_free_list;
_C_link_t __tmp2 = (void*)_C_free_list ?
(_C_free_list = _RWSTD_STATIC_CAST (_C_link_t,(_C_free_list->_C_child [1])), __tmp)
: (_C_next_avail == _C_last ? (_C_add_new_buffer (), _C_next_avail++)
: _C_next_avail++);
__tmp2->_C_parent = 0;
__tmp2->_C_child [0] = 0;
__tmp2->_C_child [1] = 0;
__tmp2->_C_color = _C_node_t::_C_red;
return __tmp2;
}
//
// Return a node from the free list or new storage with
// the _Val __v constructed on it. Every call to _C_get_node
// must eventually be followed by a call to _C_put_node.
//
_C_link_t _C_get_node (const_reference __v) {
_C_link_t __tmp2 = _C_get_link ();
_TRY {
_RWSTD_VALUE_ALLOC (_C_val_alloc_t, *this,
construct (_RWSTD_VALUE_ALLOC (_C_val_alloc_t, *this,
address (__tmp2->_C_value)),
__v));
}
_CATCH (...) {
_C_put_node (__tmp2, false);
_RETHROW;
}
return __tmp2;
}
_C_link_t _C_get_node () {
return _C_get_link ();
}
//
// Return a node to the free list and destroy the value in it.
//
void _C_put_node (_C_link_t __p, bool __destroy = true) {
__p->_C_child [1] = _C_free_list;
if (__destroy) {
_RWSTD_VALUE_ALLOC (_C_val_alloc_t, *this,
destroy (_RWSTD_VALUE_ALLOC (_C_val_alloc_t, *this,
address (__p->_C_value))));
}
_C_free_list = __p;
}
private:
// _C_end is end()
// tree root is _C_end->_C_parent
// the leftmost node, i.e., begin(), is _C_end->_C_child [0]
// the rightmost node, i.e., end() - 1, is _C_end->_C_child [1]
// all three pointers are null (0) when the tree is empty
// both child pointers of each leaf node are null (0)
// the parent pointer of the root node points to *_C_end
_C_link_t _C_end;
size_type _C_size; // number of nodes
key_compare _C_cmp; // comparison object
public:
#ifndef _RWSTD_NO_CLASS_PARTIAL_SPEC
typedef _STD::reverse_iterator<const_iterator> const_reverse_iterator;
typedef _STD::reverse_iterator<iterator> reverse_iterator;
#else // if defined (_RWSTD_NO_CLASS_PARTIAL_SPEC)
typedef std::reverse_iterator<const_iterator,
_STD::bidirectional_iterator_tag, value_type,
const_reference, const_pointer, difference_type>
const_reverse_iterator;
typedef std::reverse_iterator<iterator,
_STD::bidirectional_iterator_tag, value_type,
reference, pointer, difference_type>
reverse_iterator;
#endif // _RWSTD_NO_CLASS_PARTIAL_SPEC
private:
iterator _C_insert (_C_link_t, _C_link_t, const value_type&);
_C_link_t _C_copy (_C_link_t, _C_link_t);
void _C_erase (_C_link_t);
void _C_erase_leaf (_C_link_t);
void _C_init () {
_C_buf_list = 0;
_C_free_list =
_C_next_avail =
_C_last = 0;
_C_end = _C_get_node ();
_C_end->_C_parent = 0;
_C_end->_C_child [0] =
_C_end->_C_child [1] = _C_end;
}
public:
__rb_tree (const key_compare& = key_compare (),
const allocator_type& = allocator_type ());
template<class _InputIter>
__rb_tree (_InputIter __first, _InputIter __last,
const key_compare &__cmp,
const allocator_type &__alloc, bool __dup)
: allocator_type (__alloc), _C_buf_list (0),
_C_end (0), _C_size (0),
_C_cmp (__cmp) {
_C_init ();
_TRY {
insert (__first, __last, __dup);
}
_CATCH (...) {
_C_deallocate_buffers ();
_RETHROW;
}
}
__rb_tree (const __rb_tree&);
~__rb_tree ();
__rb_tree& operator= (const __rb_tree&);
key_compare key_comp () const {
return _C_cmp;
}
_C_val_alloc_t get_allocator () const {
return _C_val_alloc_t (*this);
}
iterator begin () {
return _C_make_iter (_C_end->_C_child [0]);
}
const_iterator begin () const {
return _C_make_iter (_C_end->_C_child [0]);
}
iterator end () {
return _C_make_iter (_C_end);
}
const_iterator end () const {
return _C_make_iter (_C_end);
}
reverse_iterator rbegin () {
return reverse_iterator (end ());
}
reverse_iterator rend () {
return reverse_iterator (begin ());
}
const_reverse_iterator rbegin () const {
return const_reverse_iterator (end ());
}
const_reverse_iterator rend () const {
return const_reverse_iterator (begin ());
}
bool empty () const {
return 0 == _C_size;
}
size_type size () const {
return _C_size;
}
size_type max_size () const {
return _C_node_alloc_t (*this).max_size ();
}
void swap (__rb_tree &__rhs) {
if (get_allocator () == __rhs.get_allocator ()) {
_STD::swap (_C_buf_list, __rhs._C_buf_list);
_STD::swap (_C_free_list, __rhs._C_free_list);
_STD::swap (_C_next_avail, __rhs._C_next_avail);
_STD::swap (_C_last, __rhs._C_last);
_STD::swap (_C_end, __rhs._C_end);
_STD::swap (_C_size, __rhs._C_size);
_STD::swap (_C_cmp, __rhs._C_cmp);
}
else {
__rb_tree __tmp = *this;
*this = __rhs;
__rhs = __tmp;
}
}
void _C_insert (const value_type&, _STD::pair<iterator, bool>&, bool);
_STD::pair<iterator, bool>
insert (const value_type &__val, bool __dup) {
_STD::pair<iterator, bool> __ret;
return _C_insert (__val, __ret, __dup), __ret;
}
iterator insert (iterator, const value_type&, bool);
template<class _Iterator>
void insert (_Iterator __first, _Iterator __last, bool __dup) {
for (; __first != __last; ++__first)
insert (*__first, __dup);
}
iterator erase (iterator);
size_type erase (const key_type&);
iterator erase (iterator, iterator);
// MSVC 6.0 thinks S<const T*> is the same as S<T*>...
#if !defined (_MSC_VER) || _MSC_VER > 1300
// map and set's iterator may be defined to be tree::const_iterator
iterator insert (const_iterator __it, const value_type &__x, bool __dup) {
return insert (_C_make_iter (_ITER_NODE (__it)), __x, __dup);
}
// map and set's iterator may be defined to be tree::const_iterator
iterator erase (const_iterator __it) {
return erase (_C_make_iter (_ITER_NODE (__it)));
}
// map and set's iterator may be defined to be tree::const_iterator
iterator erase (const_iterator __first, const_iterator __last) {
return erase (_C_make_iter (_ITER_NODE (__first)),
_C_make_iter (_ITER_NODE (__last)));
}
#endif // _MSC_VER <= 1300
void erase (const key_type*, const key_type*);
void clear () {
erase (begin (), end ());
}
iterator find (const key_type&);
const_iterator find (const key_type& __key) const {
return _RWSTD_CONST_CAST (__rb_tree*, this)->find (__key);
}
size_type count (const key_type&) const;
iterator lower_bound (const key_type&);
const_iterator lower_bound (const key_type& __key) const {
return _RWSTD_CONST_CAST (__rb_tree*, this)->lower_bound (__key);
}
iterator upper_bound (const key_type&);
const_iterator upper_bound (const key_type& __key) const {
return _RWSTD_CONST_CAST (__rb_tree*, this)->upper_bound (__key);
}
_STD::pair<iterator, iterator> equal_range (const key_type&);
_STD::pair<const_iterator, const_iterator>
equal_range (const key_type& __key) const {
_STD::pair<iterator, iterator> __tmp =
_RWSTD_CONST_CAST (__rb_tree*, this)->equal_range (__key);
return _STD::pair<const_iterator, const_iterator>
(__tmp.first, __tmp.second);
}
#ifndef _RWSTD_NO_OPTIMIZE_SPEED
void _C_rol (_C_link_t);
void _C_ror (_C_link_t);
#else // if defined (_RWSTD_NO_OPTIMIZE_SPEED)
void _C_rotate (_C_link_t, bool);
#endif // _RWSTD_NO_OPTIMIZE_SPEED
size_type _C_level (const_iterator) const;
// depth guaranteed to be <= 2 * log2(size() + 1)
size_type _C_depth (const_iterator, size_type* = 0) const;
size_type _C_depth () const {
return _C_depth (_C_make_iter (_C_end->_C_parent));
}
};
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline bool
operator== (const __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>& __lhs,
const __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>& __rhs)
{
return __lhs.size () == __rhs.size ()
&& _STD::equal (__lhs.begin (), __lhs.end (), __rhs.begin ());
}
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline bool
operator< (const __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>& __lhs,
const __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>& __rhs)
{
return _STD::lexicographical_compare (__lhs.begin (), __lhs.end (),
__rhs.begin (), __rhs.end ());
}
template <class _Key,class _Val,class _KeyOf,class _Comp,class _Alloc>
inline void
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
_C_erase_leaf (_C_link_t __lnk)
{
// remove a leaf node from the tree
const _C_link_t __parent = __lnk->_C_parent;
if (__parent == _C_end) {
_C_end->_C_parent = 0;
_C_end->_C_child [0] =
_C_end->_C_child [1] = __parent;
}
#ifndef _RWSTD_NO_OPTIMIZE_SPEED
else if (__parent->_C_child [0] == __lnk) {
__parent->_C_child [0] = 0;
if (_C_end->_C_child [0] == __lnk)
_C_end->_C_child [0] = __parent;
}
else {
__parent->_C_child [1] = 0;
if (_C_end->_C_child [1] == __lnk)
_C_end->_C_child [1] = __parent;
}
#else // if !defined (_RWSTD_NO_OPTIMIZE_SPEED)
else {
const bool __right = __parent->_C_child [0] != __lnk;
__parent->_C_child [__right] = 0;
if (_C_end->_C_child [__right] == __lnk)
_C_end->_C_child [__right] = __parent;
}
#endif // _RWSTD_NO_OPTIMIZE_SPEED
}
#ifndef _RWSTD_NO_OPTIMIZE_SPEED
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline void
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
_C_rol (_C_link_t __lnk)
{
_RWSTD_ASSERT (_C_link_t () != __lnk);
_C_link_t __tmp = __lnk->_C_child [1];
__lnk->_C_child [1] = __tmp->_C_child [0];
if (_C_link_t () != __tmp->_C_child [0])
__tmp->_C_child [0]->_C_parent = __lnk;
__tmp->_C_parent = __lnk->_C_parent;
if (__lnk == _C_end->_C_parent)
_C_end->_C_parent = __tmp;
else if (__lnk == __lnk->_C_parent->_C_child [0])
__lnk->_C_parent->_C_child [0] = __tmp;
else
__lnk->_C_parent->_C_child [1] = __tmp;
__tmp->_C_child [0] = __lnk;
__lnk->_C_parent = __tmp;
}
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline void
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
_C_ror (_C_link_t __lnk)
{
_RWSTD_ASSERT (_C_link_t () != __lnk);
_C_link_t __tmp = __lnk->_C_child [0];
__lnk->_C_child [0] = __tmp->_C_child [1];
if (_C_link_t () != __tmp->_C_child [1])
__tmp->_C_child [1]->_C_parent = __lnk;
__tmp->_C_parent = __lnk->_C_parent;
if (__lnk == _C_end->_C_parent)
_C_end->_C_parent = __tmp;
else if (__lnk == __lnk->_C_parent->_C_child [1])
__lnk->_C_parent->_C_child [1] = __tmp;
else
__lnk->_C_parent->_C_child [0] = __tmp;
__tmp->_C_child [1] = __lnk;
__lnk->_C_parent = __tmp;
}
#else // if defined (_RWSTD_NO_OPTIMIZE_SPEED)
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline void
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
_C_rotate (_C_link_t __lnk, bool __right)
{
_RWSTD_ASSERT (_C_link_t () != __lnk);
_C_link_t __tmp = __lnk->_C_child [!__right];
__lnk->_C_child [!__right] = __tmp->_C_child [__right];
if (_C_link_t () != __tmp->_C_child [__right])
__tmp->_C_child [__right]->_C_parent = __lnk;
__tmp->_C_parent = __lnk->_C_parent;
if (__lnk == _C_end->_C_parent)
_C_end->_C_parent = __tmp;
else {
const bool __rt = __lnk == __lnk->_C_parent->_C_child [1];
__lnk->_C_parent->_C_child [__rt] = __tmp;
}
__tmp->_C_child [__right] = __lnk;
__lnk->_C_parent = __tmp;
}
#endif // _RWSTD_NO_OPTIMIZE_SPEED
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline void __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
erase (const _Key* __first, const _Key* __last)
{
for (; __first != __last; ++__first)
erase (*__first);
}
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline _TYPENAME __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::size_type
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
count (const _Key& __k) const
{
_STD::pair<const_iterator, const_iterator> __p = equal_range (__k);
size_type __n = _DISTANCE (__p.first, __p.second, size_type);
return __n;
}
#define _RWSTD_RB_TREE_ITER \
_TYPENAME __rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::iterator
template <class _Key, class _Val, class _KeyOf, class _Comp, class _Alloc>
inline _STD::pair<_RWSTD_RB_TREE_ITER , _RWSTD_RB_TREE_ITER >
__rb_tree<_Key, _Val, _KeyOf, _Comp, _Alloc>::
equal_range (const _Key& __k)
{
return _STD::pair<iterator, iterator>(lower_bound (__k), upper_bound(__k));
}
#undef _RWSTD_RB_TREE_ITER
} // namespace __rw
#ifdef _RWSTD_NO_IMPLICIT_INCLUSION
# include <rw/_tree.cc>
#endif
#endif // _RWSTD_RW_TREE_H_INCLUDED