williamr@4: /* williamr@4: * williamr@4: * Copyright (c) 1994 williamr@4: * Hewlett-Packard Company williamr@4: * williamr@4: * Copyright (c) 1996,1997 williamr@4: * Silicon Graphics Computer Systems, Inc. williamr@4: * williamr@4: * Copyright (c) 1997 williamr@4: * Moscow Center for SPARC Technology williamr@4: * williamr@4: * Copyright (c) 1999 williamr@4: * Boris Fomitchev williamr@4: * williamr@4: * This material is provided "as is", with absolutely no warranty expressed williamr@4: * or implied. Any use is at your own risk. williamr@4: * williamr@4: * Permission to use or copy this software for any purpose is hereby granted williamr@4: * without fee, provided the above notices are retained on all copies. williamr@4: * Permission to modify the code and to distribute modified code is granted, williamr@4: * provided the above notices are retained, and a notice that the code was williamr@4: * modified is included with the above copyright notice. williamr@4: * williamr@4: */ williamr@4: williamr@4: /* NOTE: This is an internal header file, included by other STL headers. williamr@4: * You should not attempt to use it directly. williamr@4: */ williamr@4: williamr@4: #ifndef _STLP_INTERNAL_TREE_H williamr@4: #define _STLP_INTERNAL_TREE_H williamr@4: williamr@4: /* williamr@4: williamr@4: Red-black tree class, designed for use in implementing STL williamr@4: associative containers (set, multiset, map, and multimap). The williamr@4: insertion and deletion algorithms are based on those in Cormen, williamr@4: Leiserson, and Rivest, Introduction to Algorithms (MIT Press, 1990), williamr@4: except that williamr@4: williamr@4: (1) the header cell is maintained with links not only to the root williamr@4: but also to the leftmost node of the tree, to enable constant time williamr@4: begin(), and to the rightmost node of the tree, to enable linear time williamr@4: performance when used with the generic set algorithms (set_union, williamr@4: etc.); williamr@4: williamr@4: (2) when a node being deleted has two children its successor node is williamr@4: relinked into its place, rather than copied, so that the only williamr@4: iterators invalidated are those referring to the deleted node. williamr@4: williamr@4: */ williamr@4: williamr@4: #ifndef _STLP_INTERNAL_ALGOBASE_H williamr@4: # include williamr@4: #endif williamr@4: williamr@4: #ifndef _STLP_INTERNAL_ALLOC_H williamr@4: # include williamr@4: #endif williamr@4: williamr@4: #ifndef _STLP_INTERNAL_ITERATOR_H williamr@4: # include williamr@4: #endif williamr@4: williamr@4: #ifndef _STLP_INTERNAL_CONSTRUCT_H williamr@4: # include williamr@4: #endif williamr@4: williamr@4: #ifndef _STLP_INTERNAL_FUNCTION_BASE_H williamr@4: # include williamr@4: #endif williamr@4: williamr@4: _STLP_BEGIN_NAMESPACE williamr@4: williamr@4: _STLP_MOVE_TO_PRIV_NAMESPACE williamr@4: williamr@4: typedef bool _Rb_tree_Color_type; williamr@4: //const _Rb_tree_Color_type _S_rb_tree_red = false; williamr@4: //const _Rb_tree_Color_type _S_rb_tree_black = true; williamr@4: williamr@4: #define _S_rb_tree_red false williamr@4: #define _S_rb_tree_black true williamr@4: williamr@4: struct _Rb_tree_node_base { williamr@4: typedef _Rb_tree_Color_type _Color_type; williamr@4: typedef _Rb_tree_node_base* _Base_ptr; williamr@4: williamr@4: _Color_type _M_color; williamr@4: _Base_ptr _M_parent; williamr@4: _Base_ptr _M_left; williamr@4: _Base_ptr _M_right; williamr@4: williamr@4: static _Base_ptr _STLP_CALL _S_minimum(_Base_ptr __x) { williamr@4: while (__x->_M_left != 0) __x = __x->_M_left; williamr@4: return __x; williamr@4: } williamr@4: williamr@4: static _Base_ptr _STLP_CALL _S_maximum(_Base_ptr __x) { williamr@4: while (__x->_M_right != 0) __x = __x->_M_right; williamr@4: return __x; williamr@4: } williamr@4: }; williamr@4: williamr@4: template williamr@4: struct _Rb_tree_node : public _Rb_tree_node_base { williamr@4: _Value _M_value_field; williamr@4: __TRIVIAL_STUFF(_Rb_tree_node) williamr@4: }; williamr@4: williamr@4: struct _Rb_tree_base_iterator; williamr@4: williamr@4: template williamr@4: class _Rb_global { williamr@4: public: williamr@4: typedef _Rb_tree_node_base* _Base_ptr; williamr@4: // those used to be global functions williamr@4: static void _STLP_CALL _Rebalance(_Base_ptr __x, _Base_ptr& __root); williamr@4: static _Base_ptr _STLP_CALL _Rebalance_for_erase(_Base_ptr __z, williamr@4: _Base_ptr& __root, williamr@4: _Base_ptr& __leftmost, williamr@4: _Base_ptr& __rightmost); williamr@4: // those are from _Rb_tree_base_iterator - moved here to reduce code bloat williamr@4: // moved here to reduce code bloat without templatizing _Rb_tree_base_iterator williamr@4: static _Base_ptr _STLP_CALL _M_increment (_Base_ptr); williamr@4: static _Base_ptr _STLP_CALL _M_decrement (_Base_ptr); williamr@4: static void _STLP_CALL _Rotate_left (_Base_ptr __x, _Base_ptr& __root); williamr@4: static void _STLP_CALL _Rotate_right(_Base_ptr __x, _Base_ptr& __root); williamr@4: }; williamr@4: williamr@4: # if defined (_STLP_USE_TEMPLATE_EXPORT) williamr@4: _STLP_EXPORT_TEMPLATE_CLASS _Rb_global; williamr@4: # endif williamr@4: williamr@4: typedef _Rb_global _Rb_global_inst; williamr@4: williamr@4: struct _Rb_tree_base_iterator { williamr@4: typedef _Rb_tree_node_base* _Base_ptr; williamr@4: typedef bidirectional_iterator_tag iterator_category; williamr@4: typedef ptrdiff_t difference_type; williamr@4: _Base_ptr _M_node; williamr@4: _Rb_tree_base_iterator() : _M_node(0) {} williamr@4: _Rb_tree_base_iterator(_Base_ptr __x) : _M_node(__x) {} williamr@4: }; williamr@4: williamr@4: template williamr@4: struct _Rb_tree_iterator : public _Rb_tree_base_iterator { williamr@4: typedef _Value value_type; williamr@4: typedef typename _Traits::reference reference; williamr@4: typedef typename _Traits::pointer pointer; williamr@4: typedef _Rb_tree_iterator<_Value, _Traits> _Self; williamr@4: typedef _Rb_tree_node_base* _Base_ptr; williamr@4: typedef _Rb_tree_node<_Value>* _Link_type; williamr@4: williamr@4: typedef typename _Traits::_NonConstTraits _NonConstTraits; williamr@4: typedef _Rb_tree_iterator<_Value, _NonConstTraits> iterator; williamr@4: typedef typename _Traits::_ConstTraits _ConstTraits; williamr@4: typedef _Rb_tree_iterator<_Value, _ConstTraits> const_iterator; williamr@4: williamr@4: _Rb_tree_iterator() {} williamr@4: #if !defined (_STLP_DEBUG) williamr@4: /* In STL debug mode we need this constructor implicit for the pointer williamr@4: * specialization implementation. williamr@4: */ williamr@4: explicit williamr@4: #endif williamr@4: _Rb_tree_iterator(_Base_ptr __x) : _Rb_tree_base_iterator(__x) {} williamr@4: //copy constructor for iterator and constructor from iterator for const_iterator williamr@4: _Rb_tree_iterator(const iterator& __it) : _Rb_tree_base_iterator(__it._M_node) {} williamr@4: williamr@4: reference operator*() const { williamr@4: return __STATIC_CAST(_Link_type, _M_node)->_M_value_field; williamr@4: } williamr@4: williamr@4: _STLP_DEFINE_ARROW_OPERATOR williamr@4: williamr@4: _Self& operator++() { williamr@4: _M_node = _Rb_global_inst::_M_increment(_M_node); williamr@4: return *this; williamr@4: } williamr@4: _Self operator++(int) { williamr@4: _Self __tmp = *this; williamr@4: ++(*this); williamr@4: return __tmp; williamr@4: } williamr@4: williamr@4: _Self& operator--() { williamr@4: _M_node = _Rb_global_inst::_M_decrement(_M_node); williamr@4: return *this; williamr@4: } williamr@4: _Self operator--(int) { williamr@4: _Self __tmp = *this; williamr@4: --(*this); williamr@4: return __tmp; williamr@4: } williamr@4: williamr@4: bool operator == (const_iterator __rhs) const { williamr@4: return _M_node == __rhs._M_node; williamr@4: } williamr@4: bool operator != (const_iterator __rhs) const { williamr@4: return _M_node != __rhs._M_node; williamr@4: } williamr@4: }; williamr@4: williamr@4: #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) williamr@4: _STLP_MOVE_TO_STD_NAMESPACE williamr@4: template williamr@4: struct __type_traits<_STLP_PRIV _Rb_tree_iterator<_Value, _Traits> > { williamr@4: typedef __false_type has_trivial_default_constructor; williamr@4: typedef __true_type has_trivial_copy_constructor; williamr@4: typedef __true_type has_trivial_assignment_operator; williamr@4: typedef __true_type has_trivial_destructor; williamr@4: typedef __false_type is_POD_type; williamr@4: }; williamr@4: _STLP_MOVE_TO_PRIV_NAMESPACE williamr@4: #endif /* _STLP_CLASS_PARTIAL_SPECIALIZATION */ williamr@4: williamr@4: #if defined (_STLP_USE_OLD_HP_ITERATOR_QUERIES) williamr@4: _STLP_MOVE_TO_STD_NAMESPACE williamr@4: template williamr@4: inline _Value* value_type(const _STLP_PRIV _Rb_tree_iterator<_Value, _Traits>&) williamr@4: { return (_Value*)0; } williamr@4: inline bidirectional_iterator_tag iterator_category(const _STLP_PRIV _Rb_tree_base_iterator&) williamr@4: { return bidirectional_iterator_tag(); } williamr@4: inline ptrdiff_t* distance_type(const _STLP_PRIV _Rb_tree_base_iterator&) williamr@4: { return (ptrdiff_t*) 0; } williamr@4: _STLP_MOVE_TO_PRIV_NAMESPACE williamr@4: #endif /* _STLP_CLASS_PARTIAL_SPECIALIZATION */ williamr@4: williamr@4: // Base class to help EH williamr@4: williamr@4: template williamr@4: class _Rb_tree_base { williamr@4: public: williamr@4: typedef _Rb_tree_node_base _Node_base; williamr@4: typedef _Rb_tree_node<_Tp> _Node; williamr@4: _STLP_FORCE_ALLOCATORS(_Tp, _Alloc) williamr@4: typedef typename _Alloc_traits<_Tp, _Alloc>::allocator_type allocator_type; williamr@4: private: williamr@4: typedef _Rb_tree_base<_Tp, _Alloc> _Self; williamr@4: typedef typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator_type; williamr@4: typedef _STLP_alloc_proxy<_Node_base, _Node, _M_node_allocator_type> _AllocProxy; williamr@4: williamr@4: public: williamr@4: allocator_type get_allocator() const { williamr@4: return _STLP_CONVERT_ALLOCATOR(_M_header, _Tp); williamr@4: } williamr@4: williamr@4: protected: williamr@4: _Rb_tree_base(const allocator_type& __a) : williamr@4: _M_header(_STLP_CONVERT_ALLOCATOR(__a, _Node), _Node_base() ) { williamr@4: _M_empty_initialize(); williamr@4: } williamr@4: _Rb_tree_base(__move_source<_Self> src) : williamr@4: _M_header(__move_source<_AllocProxy>(src.get()._M_header)) { williamr@4: _M_rebind(&src.get()._M_header._M_data); williamr@4: src.get()._M_empty_initialize(); williamr@4: } williamr@4: void _M_empty_initialize() { williamr@4: _M_header._M_data._M_color = _S_rb_tree_red; // used to distinguish header from williamr@4: // __root, in iterator.operator++ williamr@4: _M_header._M_data._M_parent = 0; williamr@4: _M_header._M_data._M_left = &_M_header._M_data; williamr@4: _M_header._M_data._M_right = &_M_header._M_data; williamr@4: } williamr@4: williamr@4: void _M_rebind(_Node_base *__static_node) { williamr@4: if (_M_header._M_data._M_parent != 0) { williamr@4: _M_header._M_data._M_parent->_M_parent = &_M_header._M_data; williamr@4: } williamr@4: if (_M_header._M_data._M_right == __static_node) { williamr@4: _M_header._M_data._M_right = &_M_header._M_data; williamr@4: } williamr@4: if (_M_header._M_data._M_left == __static_node) { williamr@4: _M_header._M_data._M_left = &_M_header._M_data; williamr@4: } williamr@4: } williamr@4: williamr@4: _AllocProxy _M_header; williamr@4: }; williamr@4: williamr@4: #if defined (_STLP_DEBUG) williamr@4: # define _Rb_tree _STLP_NON_DBG_NAME(Rb_tree) williamr@4: #endif williamr@4: williamr@4: template williamr@4: class _Rb_tree : public _Rb_tree_base<_Value, _Alloc> { williamr@4: typedef _Rb_tree_base<_Value, _Alloc> _Base; williamr@4: typedef _Rb_tree<_Key, _Compare, _Value, _KeyOfValue, _Traits, _Alloc> _Self; williamr@4: protected: williamr@4: typedef _Rb_tree_node_base * _Base_ptr; williamr@4: typedef _Rb_tree_node<_Value> _Node; williamr@4: typedef _Node* _Link_type; williamr@4: typedef _Rb_tree_Color_type _Color_type; williamr@4: public: williamr@4: typedef _Key key_type; williamr@4: typedef _Value value_type; williamr@4: typedef typename _Traits::pointer pointer; williamr@4: typedef const value_type* const_pointer; williamr@4: typedef typename _Traits::reference reference; williamr@4: typedef const value_type& const_reference; williamr@4: typedef size_t size_type; williamr@4: typedef ptrdiff_t difference_type; williamr@4: typedef bidirectional_iterator_tag _Iterator_category; williamr@4: typedef typename _Base::allocator_type allocator_type; williamr@4: williamr@4: protected: williamr@4: williamr@4: _STLP_KEY_TYPE_FOR_CONT_EXT(key_type) williamr@4: _Base_ptr _M_create_node(const value_type& __x) { williamr@4: _Link_type __tmp = this->_M_header.allocate(1); williamr@4: _STLP_TRY { williamr@4: _Copy_Construct(&__tmp->_M_value_field, __x); williamr@4: } williamr@4: _STLP_UNWIND(this->_M_header.deallocate(__tmp,1)) williamr@4: _S_left(__tmp) = 0; williamr@4: _S_right(__tmp) = 0; williamr@4: return __tmp; williamr@4: } williamr@4: williamr@4: _Base_ptr _M_clone_node(_Base_ptr __x) { williamr@4: _Base_ptr __tmp = _M_create_node(_S_value(__x)); williamr@4: _S_color(__tmp) = _S_color(__x); williamr@4: return __tmp; williamr@4: } williamr@4: williamr@4: size_type _M_node_count; // keeps track of size of tree williamr@4: _Compare _M_key_compare; williamr@4: williamr@4: _Base_ptr _M_root() const williamr@4: { return this->_M_header._M_data._M_parent; } williamr@4: _Base_ptr _M_leftmost() const williamr@4: { return this->_M_header._M_data._M_left; } williamr@4: _Base_ptr _M_rightmost() const williamr@4: { return this->_M_header._M_data._M_right; } williamr@4: williamr@4: _Base_ptr& _M_root() williamr@4: { return this->_M_header._M_data._M_parent; } williamr@4: _Base_ptr& _M_leftmost() williamr@4: { return this->_M_header._M_data._M_left; } williamr@4: _Base_ptr& _M_rightmost() williamr@4: { return this->_M_header._M_data._M_right; } williamr@4: williamr@4: static _Base_ptr& _STLP_CALL _S_left(_Base_ptr __x) williamr@4: { return __x->_M_left; } williamr@4: static _Base_ptr& _STLP_CALL _S_right(_Base_ptr __x) williamr@4: { return __x->_M_right; } williamr@4: static _Base_ptr& _STLP_CALL _S_parent(_Base_ptr __x) williamr@4: { return __x->_M_parent; } williamr@4: static value_type& _STLP_CALL _S_value(_Base_ptr __x) williamr@4: { return __STATIC_CAST(_Link_type, __x)->_M_value_field; } williamr@4: static const _Key& _STLP_CALL _S_key(_Base_ptr __x) williamr@4: { return _KeyOfValue()(_S_value(__x));} williamr@4: static _Color_type& _STLP_CALL _S_color(_Base_ptr __x) williamr@4: { return (_Color_type&)(__x->_M_color); } williamr@4: williamr@4: static _Base_ptr _STLP_CALL _S_minimum(_Base_ptr __x) williamr@4: { return _Rb_tree_node_base::_S_minimum(__x); } williamr@4: williamr@4: static _Base_ptr _STLP_CALL _S_maximum(_Base_ptr __x) williamr@4: { return _Rb_tree_node_base::_S_maximum(__x); } williamr@4: williamr@4: public: williamr@4: typedef typename _Traits::_NonConstTraits _NonConstTraits; williamr@4: typedef typename _Traits::_ConstTraits _ConstTraits; williamr@4: typedef _Rb_tree_iterator iterator; williamr@4: typedef _Rb_tree_iterator const_iterator; williamr@4: _STLP_DECLARE_BIDIRECTIONAL_REVERSE_ITERATORS; williamr@4: williamr@4: private: williamr@4: iterator _M_insert(_Base_ptr __parent, const value_type& __val, _Base_ptr __on_left = 0, _Base_ptr __on_right = 0); williamr@4: _Base_ptr _M_copy(_Base_ptr __x, _Base_ptr __p); williamr@4: void _M_erase(_Base_ptr __x); williamr@4: williamr@4: public: williamr@4: // allocation/deallocation williamr@4: _Rb_tree() williamr@4: : _Rb_tree_base<_Value, _Alloc>(allocator_type()), _M_node_count(0), _M_key_compare(_Compare()) williamr@4: {} williamr@4: williamr@4: _Rb_tree(const _Compare& __comp) williamr@4: : _Rb_tree_base<_Value, _Alloc>(allocator_type()), _M_node_count(0), _M_key_compare(__comp) williamr@4: {} williamr@4: williamr@4: _Rb_tree(const _Compare& __comp, const allocator_type& __a) williamr@4: : _Rb_tree_base<_Value, _Alloc>(__a), _M_node_count(0), _M_key_compare(__comp) williamr@4: {} williamr@4: williamr@4: _Rb_tree(const _Self& __x) williamr@4: : _Rb_tree_base<_Value, _Alloc>(__x.get_allocator()), williamr@4: _M_node_count(0), _M_key_compare(__x._M_key_compare) { williamr@4: if (__x._M_root() != 0) { williamr@4: _S_color(&this->_M_header._M_data) = _S_rb_tree_red; williamr@4: _M_root() = _M_copy(__x._M_root(), &this->_M_header._M_data); williamr@4: _M_leftmost() = _S_minimum(_M_root()); williamr@4: _M_rightmost() = _S_maximum(_M_root()); williamr@4: } williamr@4: _M_node_count = __x._M_node_count; williamr@4: } williamr@4: williamr@4: _Rb_tree(__move_source<_Self> src) williamr@4: : _Rb_tree_base<_Value, _Alloc>(__move_source<_Base>(src.get())), williamr@4: _M_node_count(src.get()._M_node_count), williamr@4: _M_key_compare(_AsMoveSource(src.get()._M_key_compare)) { williamr@4: src.get()._M_node_count = 0; williamr@4: } williamr@4: williamr@4: ~_Rb_tree() { clear(); } williamr@4: _Self& operator=(const _Self& __x); williamr@4: williamr@4: public: williamr@4: // accessors: williamr@4: _Compare key_comp() const { return _M_key_compare; } williamr@4: williamr@4: iterator begin() { return iterator(_M_leftmost()); } williamr@4: const_iterator begin() const { return const_iterator(_M_leftmost()); } williamr@4: iterator end() { return iterator(&this->_M_header._M_data); } williamr@4: const_iterator end() const { return const_iterator(__CONST_CAST(_Base_ptr, &this->_M_header._M_data)); } williamr@4: williamr@4: reverse_iterator rbegin() { return reverse_iterator(end()); } williamr@4: const_reverse_iterator rbegin() const williamr@4: { return const_reverse_iterator(end()); } williamr@4: reverse_iterator rend() { return reverse_iterator(begin()); } williamr@4: const_reverse_iterator rend() const williamr@4: { return const_reverse_iterator(begin()); } williamr@4: bool empty() const { return _M_node_count == 0; } williamr@4: size_type size() const { return _M_node_count; } williamr@4: size_type max_size() const { return size_type(-1); } williamr@4: williamr@4: void swap(_Self& __t) { williamr@4: if (__t.empty()) { williamr@4: if (this->empty()) return; williamr@4: __t._M_header.swap(this->_M_header); williamr@4: __t._M_rebind(&this->_M_header._M_data); williamr@4: this->_M_empty_initialize(); williamr@4: } williamr@4: else if (this->empty()) { williamr@4: __t.swap(*this); williamr@4: return; williamr@4: } williamr@4: else { williamr@4: this->_M_header.swap(__t._M_header); williamr@4: this->_M_rebind(&__t._M_header._M_data); williamr@4: __t._M_rebind(&this->_M_header._M_data); williamr@4: } williamr@4: _STLP_STD::swap(_M_node_count, __t._M_node_count); williamr@4: _STLP_STD::swap(_M_key_compare, __t._M_key_compare); williamr@4: } williamr@4: williamr@4: public: williamr@4: // insert/erase williamr@4: pair insert_unique(const value_type& __x); williamr@4: iterator insert_equal(const value_type& __x); williamr@4: williamr@4: iterator insert_unique(iterator __pos, const value_type& __x); williamr@4: iterator insert_equal(iterator __pos, const value_type& __x); williamr@4: williamr@4: #if defined (_STLP_MEMBER_TEMPLATES) williamr@4: template void insert_equal(_II __first, _II __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_equal(*__first); williamr@4: } williamr@4: template void insert_unique(_II __first, _II __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_unique(*__first); williamr@4: } williamr@4: #else williamr@4: void insert_unique(const_iterator __first, const_iterator __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_unique(*__first); williamr@4: } williamr@4: void insert_unique(const value_type* __first, const value_type* __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_unique(*__first); williamr@4: } williamr@4: void insert_equal(const_iterator __first, const_iterator __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_equal(*__first); williamr@4: } williamr@4: void insert_equal(const value_type* __first, const value_type* __last) { williamr@4: for ( ; __first != __last; ++__first) williamr@4: insert_equal(*__first); williamr@4: } williamr@4: #endif williamr@4: williamr@4: void erase(iterator __pos) { williamr@4: _Base_ptr __x = _Rb_global_inst::_Rebalance_for_erase(__pos._M_node, williamr@4: this->_M_header._M_data._M_parent, williamr@4: this->_M_header._M_data._M_left, williamr@4: this->_M_header._M_data._M_right); williamr@4: _STLP_STD::_Destroy(&_S_value(__x)); williamr@4: this->_M_header.deallocate(__STATIC_CAST(_Link_type, __x), 1); williamr@4: --_M_node_count; williamr@4: } williamr@4: williamr@4: size_type erase(const key_type& __x) { williamr@4: pair __p = equal_range(__x); williamr@4: size_type __n = distance(__p.first, __p.second); williamr@4: erase(__p.first, __p.second); williamr@4: return __n; williamr@4: } williamr@4: williamr@4: size_type erase_unique(const key_type& __x) { williamr@4: iterator __i = find(__x); williamr@4: if (__i._M_node != &this->_M_header._M_data) { williamr@4: erase(__i); williamr@4: return 1; williamr@4: } williamr@4: return 0; williamr@4: } williamr@4: williamr@4: void erase(iterator __first, iterator __last) { williamr@4: if (__first._M_node == this->_M_header._M_data._M_left && // begin() williamr@4: __last._M_node == &this->_M_header._M_data) // end() williamr@4: clear(); williamr@4: else williamr@4: while (__first != __last) erase(__first++); williamr@4: } williamr@4: williamr@4: void erase(const key_type* __first, const key_type* __last) { williamr@4: while (__first != __last) erase(*__first++); williamr@4: } williamr@4: williamr@4: void clear() { williamr@4: if (_M_node_count != 0) { williamr@4: _M_erase(_M_root()); williamr@4: _M_leftmost() = &this->_M_header._M_data; williamr@4: _M_root() = 0; williamr@4: _M_rightmost() = &this->_M_header._M_data; williamr@4: _M_node_count = 0; williamr@4: } williamr@4: } williamr@4: williamr@4: public: williamr@4: // set operations: williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: iterator find(const _KT& __k) { return iterator(_M_find(__k)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: const_iterator find(const _KT& __k) const { return const_iterator(_M_find(__k)); } williamr@4: private: williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: _Base_ptr _M_find(const _KT& __k) const { williamr@4: _Base_ptr __y = __CONST_CAST(_Base_ptr, &this->_M_header._M_data); // Last node which is not less than __k. williamr@4: _Base_ptr __x = _M_root(); // Current node. williamr@4: williamr@4: while (__x != 0) williamr@4: if (!_M_key_compare(_S_key(__x), __k)) williamr@4: __y = __x, __x = _S_left(__x); williamr@4: else williamr@4: __x = _S_right(__x); williamr@4: williamr@4: if (__y != &this->_M_header._M_data) { williamr@4: if (_M_key_compare(__k, _S_key(__y))) { williamr@4: __y = __CONST_CAST(_Base_ptr, &this->_M_header._M_data); williamr@4: } williamr@4: } williamr@4: return __y; williamr@4: } williamr@4: williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: _Base_ptr _M_lower_bound(const _KT& __k) const { williamr@4: _Base_ptr __y = __CONST_CAST(_Base_ptr, &this->_M_header._M_data); /* Last node which is not less than __k. */ williamr@4: _Base_ptr __x = _M_root(); /* Current node. */ williamr@4: williamr@4: while (__x != 0) williamr@4: if (!_M_key_compare(_S_key(__x), __k)) williamr@4: __y = __x, __x = _S_left(__x); williamr@4: else williamr@4: __x = _S_right(__x); williamr@4: williamr@4: return __y; williamr@4: } williamr@4: williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: _Base_ptr _M_upper_bound(const _KT& __k) const { williamr@4: _Base_ptr __y = __CONST_CAST(_Base_ptr, &this->_M_header._M_data); /* Last node which is greater than __k. */ williamr@4: _Base_ptr __x = _M_root(); /* Current node. */ williamr@4: williamr@4: while (__x != 0) williamr@4: if (_M_key_compare(__k, _S_key(__x))) williamr@4: __y = __x, __x = _S_left(__x); williamr@4: else williamr@4: __x = _S_right(__x); williamr@4: williamr@4: return __y; williamr@4: } williamr@4: williamr@4: public: williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: size_type count(const _KT& __x) const { williamr@4: pair __p = equal_range(__x); williamr@4: return distance(__p.first, __p.second); williamr@4: } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: iterator lower_bound(const _KT& __x) { return iterator(_M_lower_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: const_iterator lower_bound(const _KT& __x) const { return const_iterator(_M_lower_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: iterator upper_bound(const _KT& __x) { return iterator(_M_upper_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: const_iterator upper_bound(const _KT& __x) const { return const_iterator(_M_upper_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: pair equal_range(const _KT& __x) williamr@4: { return pair(lower_bound(__x), upper_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: pair equal_range(const _KT& __x) const williamr@4: { return pair(lower_bound(__x), upper_bound(__x)); } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: pair equal_range_unique(const _KT& __x) { williamr@4: pair __p; williamr@4: __p.second = lower_bound(__x); williamr@4: if (__p.second._M_node != &this->_M_header._M_data && williamr@4: !_M_key_compare(__x, _S_key(__p.second._M_node))) { williamr@4: __p.first = __p.second++; williamr@4: } williamr@4: else { williamr@4: __p.first = __p.second; williamr@4: } williamr@4: return __p; williamr@4: } williamr@4: _STLP_TEMPLATE_FOR_CONT_EXT williamr@4: pair equal_range_unique(const _KT& __x) const { williamr@4: pair __p; williamr@4: __p.second = lower_bound(__x); williamr@4: if (__p.second._M_node != &this->_M_header._M_data && williamr@4: !_M_key_compare(__x, _S_key(__p.second._M_node))) { williamr@4: __p.first = __p.second++; williamr@4: } williamr@4: else { williamr@4: __p.first = __p.second; williamr@4: } williamr@4: return __p; williamr@4: } williamr@4: williamr@4: #if defined (_STLP_DEBUG) williamr@4: public: williamr@4: // Debugging. williamr@4: bool __rb_verify() const; williamr@4: #endif //_STLP_DEBUG williamr@4: }; williamr@4: williamr@4: #if defined (_STLP_DEBUG) williamr@4: # undef _Rb_tree williamr@4: #endif williamr@4: williamr@4: _STLP_MOVE_TO_STD_NAMESPACE williamr@4: williamr@4: _STLP_END_NAMESPACE williamr@4: williamr@4: #if !defined (_STLP_LINK_TIME_INSTANTIATION) williamr@4: # include williamr@4: #endif williamr@4: williamr@4: #if defined (_STLP_DEBUG) williamr@4: # include williamr@4: #endif williamr@4: williamr@4: _STLP_BEGIN_NAMESPACE williamr@4: williamr@4: #define _STLP_TEMPLATE_HEADER template williamr@4: #define _STLP_TEMPLATE_CONTAINER _STLP_PRIV _Rb_tree<_Key,_Compare,_Value,_KeyOfValue,_Traits,_Alloc> williamr@4: #include williamr@4: #undef _STLP_TEMPLATE_CONTAINER williamr@4: #undef _STLP_TEMPLATE_HEADER williamr@4: williamr@4: #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) williamr@4: template williamr@4: struct __move_traits<_STLP_PRIV _Rb_tree<_Key, _Compare, _Value, _KeyOfValue, _Traits, _Alloc> > williamr@4: : _STLP_PRIV __move_traits_help2<_Compare, _Alloc> {}; williamr@4: #endif williamr@4: williamr@4: _STLP_END_NAMESPACE williamr@4: williamr@4: #endif /* _STLP_INTERNAL_TREE_H */ williamr@4: williamr@4: // Local Variables: williamr@4: // mode:C++ williamr@4: // End: