/** -*- C++ -*- ** ** KAI C++ Compiler ** ** Copyright (C) 1996-2001 Intel Corp. All rights reserved. ** ** KAI header file for class hash_set. ** Derived completely from ANSI draft. Unrelated to Modena's implementation. ** ** C.f **/ #ifndef __KAI_SET #define __KAI_SET #include #include /* For less */ #include /* For reverse_iterator */ #include /* For allocator */ #include #include /* For relops */ #include /* For swap */ #define __gnu_cxx std namespace std { template class hash_set; template class multihash_set; } namespace __kai { template struct hash_set_node: public rb_tree_node_base { public: const Key key; hash_set_node( const Key& k ) : key(k) {} }; // // Class hash_set_base implements functionality common to map and multimap. // template class hash_set_base: public rb_tree { private: static const size_t key_offhash_set = sizeof(rb_tree_node_base); public: // types: typedef Key key_type; typedef Key value_type; typedef Compare key_compare; typedef Compare value_compare; typedef Allocator allocator_type; typedef typename Allocator::reference reference; typedef typename Allocator::const_reference const_reference; typedef typename Allocator::size_type size_type; typedef typename Allocator::difference_type difference_type; typedef typename Allocator::pointer pointer; typedef typename Allocator::const_pointer const_pointer; typedef hash_set_node tree_node; protected: struct value_of_node { value_type& operator()( const rb_tree_node_base * node ) const { return const_cast(static_cast(node)->key); } }; // iterators: // typedef typename rb_tree::template iterator iterator; typedef typename rb_tree::template const_iterator const_iterator; typedef const_iterator iterator; typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; // construct/copy/destroy: hash_set_base( const Compare& comp ) : rb_tree(comp), value_allocator(), node_allocator() { __initialize(); } hash_set_base( const Compare& comp, const Allocator& allocator1 ) : rb_tree(comp), value_allocator(allocator1), node_allocator(allocator1) { __initialize(); }; hash_set_base( const hash_set_base& x ) : rb_tree (x.key_comparison), value_allocator(x.value_allocator), node_allocator(x.node_allocator) { __initialize(); cleanup2 c(this); __copy( x, key_offhash_set ); c.clear(); } ~hash_set_base() {__destroy();} void swap( hash_set_base& a ); protected: Allocator value_allocator; typename Allocator::template rebind::other node_allocator; private: struct cleanup; struct cleanup2; friend struct cleanup; friend struct cleanup2; class cleanup { tree_node* ptr; hash_set_base* const hash_set; public: cleanup( hash_set_base* s, tree_node* x ) : hash_set(s), ptr(x) {} void clear() {ptr = NULL;} ~cleanup() {if( ptr ) hash_set->node_allocator.deallocate(ptr,1);}; }; class cleanup2 { hash_set_base* hash_set; public: cleanup2( hash_set_base* s ) : hash_set(s) {} void clear() {hash_set = NULL;} ~cleanup2() {if(hash_set) hash_set->__destroy();} }; rb_tree_node_base * make_node( const void * key ); // Override rb_tree_node_base::make_node void destroy_node( __kai::rb_tree_node_base * node ); // Override rb_tree_node_base::destroy_node }; template const size_t hash_set_base::key_offhash_set; template __kai::rb_tree_node_base * hash_set_base::make_node( const void * key ) { tree_node * result = node_allocator.allocate(1); if( key ) { cleanup c(this,result); value_allocator.construct( const_cast(&result->key), *static_cast(key) ); c.clear(); } return result; } template void hash_set_base::destroy_node( __kai::rb_tree_node_base * node ) { __kai_assert( node ); tree_node * result = static_cast(node); if( result!=header ) { value_allocator.destroy( const_cast(&result->key) ); } node_allocator.deallocate( result,1 ); } template void hash_set_base::swap( hash_set_base& a ) { std::swap( value_allocator, a.value_allocator ); std::swap( node_allocator, a.node_allocator ); std::swap( key_comparison, a.key_comparison ); std::swap( *(rb_tree_base_data*)this, *(rb_tree_base_data*)&a ); } } // namespace __kai namespace std { template , class Allocator=allocator > class hash_set: private __kai::hash_set_base { // The KeyOffhash_set should be offhash_setof(hash_set_node,key)>, not the // constant, but EDG has not yet fixed front-end to handle this situation. private: typedef __kai::hash_set_base base; public: // [lib.hash_set.types] types: typedef typename base::key_type key_type; typedef typename base::value_type value_type; typedef typename base::key_compare key_compare; typedef typename base::value_compare value_compare; typedef typename base::allocator_type allocator_type; typedef typename base::reference reference; typedef typename base::const_reference const_reference; typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; typedef typename base::size_type size_type; typedef typename base::difference_type difference_type; typedef typename base::pointer pointer; typedef typename base::const_pointer const_pointer; typedef typename base::reverse_iterator reverse_iterator; typedef typename base::const_reverse_iterator const_reverse_iterator; // [23.3.3.1] construct/copy/destroy: explicit hash_set() : base(Compare()) {} explicit hash_set(const Compare& comp) : base(comp) {} explicit hash_set(const Compare& comp, const Allocator& a) : base(comp,a) {} template hash_set(InputIterator first, InputIterator last) : base(Compare()) { insert( first, last ); } template hash_set(InputIterator first, InputIterator last, const Compare& comp ) : base(comp) { insert( first, last ); } template hash_set(InputIterator first, InputIterator last, const Compare& comp, const Allocator& a ) : base(comp,a) { insert( first, last ); } hash_set( const hash_set& x) : base(x) { } allocator_type get_allocator() const {return Allocator(value_allocator);} hash_set& operator=(const hash_set& x) { __assign(x); return *this; } // iterators: iterator begin() {return iterator( extrema[LEFT] );} const_iterator begin() const {return const_iterator( extrema[LEFT] );} iterator end() {return iterator( header);} const_iterator end() const {return const_iterator( header );} reverse_iterator rbegin() {return reverse_iterator( header );} const_reverse_iterator rbegin() const {return const_reverse_iterator( header );} reverse_iterator rend() {return reverse_iterator( extrema[LEFT] );} const_reverse_iterator rend() const {return const_reverse_iterator ( extrema[LEFT] );} // capacity: bool empty() const {return node_count==0;} size_type size() const {return node_count;} size_type max_size() const {return node_allocator.max_size();} // modifiers: pair insert(const value_type& x) { bool success; tree_node * node = static_cast(__modify( x, &success, INSERT_MAYBE )); return pair(node,success); } iterator insert( iterator position, const value_type& x ) { return iterator( __insert_unique( position.__node, x, NULL )); } template void insert(InputIterator first, InputIterator last); void erase(iterator position) {__erase(position.__node);} size_type erase(const key_type& x) { bool missing; __modify( x, &missing, ERASE ); return !missing; } void erase(iterator first, iterator last) {__erase(first.__node,last.__node);} void swap( hash_set& a ) {base::swap(a);} void clear() {__clear();} // observers: key_compare key_comp() const {return key_comparison;} value_compare value_comp() const {return key_comparison;} // hash_set operations: #if KAI_NONSTD_SET iterator find(const key_type& x) { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return iterator( node ); } const_iterator find(const key_type& x) const { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return const_iterator( node ); } #else iterator find(const key_type& x) const { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return iterator( node ); } #endif /* KAI_NONSTD_SET */ size_type count(const key_type& x) const { return __search(x,__kai::rb_tree_base::FIND_MAYBE) != header; } // operations: iterator lower_bound(const key_type& x) const { tree_node * node = static_cast(__search(x,LOWER_BOUND)); return iterator(node); } iterator upper_bound(const key_type& x) const { tree_node * node = static_cast(__upper_bound(x)); return iterator(node); } #if KAI_NONSTD_SET iterator lower_bound(const key_type& x) { tree_node * node = static_cast(__search(x,LOWER_BOUND)); return iterator(node); } iterator upper_bound(const key_type& x) { tree_node * node = static_cast(__upper_bound(x)); return iterator(node); } #endif /* KAI_NONSTD_SET */ pair equal_range(const key_type& x) { pair<__kai::rb_tree_node_base*,__kai::rb_tree_node_base*> temp = __equal_range_unique(x); return make_pair(iterator(temp.first), iterator(temp.second)); }; pair equal_range(const key_type& x) const { pair<__kai::rb_tree_node_base*,__kai::rb_tree_node_base*> temp = const_cast(this)->__equal_range_unique(x); return make_pair(const_iterator(temp.first), const_iterator(temp.second)); } // KCC does not yet implement explicit qualification of template arguments, // so we have to be a bit broad in granting friendship. template friend bool operator==( const hash_set&, const hash_set& ); template friend bool operator!=( const hash_set&, const hash_set& ); template friend bool operator<( const hash_set&, const hash_set& ); template friend bool operator>( const hash_set&, const hash_set& ); template friend bool operator>=( const hash_set&, const hash_set& ); template friend bool operator<=( const hash_set&, const hash_set& ); }; template template void hash_set::insert(InputIterator first, InputIterator last) { // See note in corresponding map method about asymptotic running time. __kai::rb_tree_node_base * where = header; for( ; first!=last; first++ ) { __insert_unique( where, *first, &where ); } } // When EDG implements template template parameters, we can use the name // injection trick to factor out the commonality in operator== etc. // for map, multimap, hash_set, and multihash_set. Until then, we write them out longhand. template inline bool operator==( const hash_set& x, const hash_set& y ) { return x.size()==y.size() && x.__compare(y)==0; } template inline bool operator!=( const hash_set& x, const hash_set& y ) { return x.size()!=y.size() || x.__compare(y)!=0; } template inline bool operator<( const hash_set& x, const hash_set& y ) { return x.__compare(y) < 0; } template inline bool operator>( const hash_set& x, const hash_set& y ) { return x.__compare(y) > 0; } template inline bool operator>=( const hash_set& x, const hash_set& y ) { return x.__compare(y) >= 0; } template inline bool operator<=( const hash_set& x, const hash_set& y ) { return x.__compare(y) <= 0; } template inline void swap( hash_set& x, hash_set& y ) { x.swap(y); } //------------------------------------------------------------------------ // multihash_set //------------------------------------------------------------------------ template , class Allocator=allocator > class multihash_set: private __kai::hash_set_base { private: typedef __kai::hash_set_base base; public: // types: typedef typename base::key_type key_type; typedef typename base::value_type value_type; typedef typename base::key_compare key_compare; typedef typename base::value_compare value_compare; typedef typename base::allocator_type allocator_type; typedef typename base::reference reference; typedef typename base::const_reference const_reference; typedef typename base::iterator iterator; typedef typename base::const_iterator const_iterator; typedef typename base::size_type size_type; typedef typename base::difference_type difference_type; typedef typename base::pointer pointer; typedef typename base::const_pointer const_pointer; typedef typename base::reverse_iterator reverse_iterator; typedef typename base::const_reverse_iterator const_reverse_iterator; // construct/copy/destroy: explicit multihash_set() : base(Compare()) {} explicit multihash_set(const Compare& comp) : base(comp) {} explicit multihash_set(const Compare& comp, const Allocator& a ) : base(comp,a) {} template multihash_set(InputIterator first, InputIterator last) : base( Compare() ) { insert( first, last ); } template multihash_set(InputIterator first, InputIterator last, const Compare& comp ) : base(comp) { insert( first, last ); } template multihash_set(InputIterator first, InputIterator last, const Compare& comp, const Allocator& a) : base(comp,a) { insert( first, last ); } multihash_set( const multihash_set& x ) : base(x) {} multihash_set& operator=(const multihash_set& x) { __assign(x); return *this; } allocator_type get_allocator() const {return Allocator(value_allocator);} // iterators: iterator begin() {return iterator( extrema[LEFT] );} const_iterator begin() const {return const_iterator( extrema[LEFT] );} iterator end() {return iterator( header);} const_iterator end() const {return const_iterator( header );} reverse_iterator rbegin() {return reverse_iterator( header );} const_reverse_iterator rbegin() const {return const_reverse_iterator( header );} reverse_iterator rend() {return reverse_iterator( extrema[LEFT] );} const_reverse_iterator rend() const {return const_reverse_iterator ( extrema[LEFT] );} // capacity: bool empty() const {return node_count==0;} size_type size() const {return node_count;} size_type max_size() const {return node_allocator.max_size();} // modifiers: iterator insert(const value_type& x) { bool missing; return iterator( __modify( x, &missing, INSERT_ALWAYS ) ); } iterator insert(iterator position, const value_type& x) { return iterator( __insert_multi( position.__node, x, NULL )); } template void insert(InputIterator first, InputIterator last); void erase(iterator position) {__erase(position.__node);} size_type erase(const key_type& x) {return __erase(__search(x,LOWER_BOUND),__upper_bound(x));} void erase(iterator first, iterator last) {__erase(first.__node,last.__node);} void swap( multihash_set& a ) {base::swap(a);} void clear() {__clear();} // observers: key_compare key_comp() const {return key_comparison;} value_compare value_comp() const {return value_compare( key_comparison );} // operations: #if KAI_NONSTD_SET iterator find(const key_type& x) { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return iterator( node ); } const_iterator find(const key_type& x) const { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return const_iterator( node ); } #else iterator find(const key_type& x) const { tree_node * node = static_cast(__search(x,FIND_MAYBE)); return iterator( node ); } #endif /* KAI_NONSTD_SET */ size_type count(const key_type& x) const { return __count(x); } #if KAI_NONSTD_SET iterator lower_bound(const key_type& x) { tree_node * node = static_cast(__search(x,LOWER_BOUND)); return iterator(node); } const_iterator lower_bound(const key_type& x) const { tree_node * node = static_cast(__search(x,LOWER_BOUND)); return const_iterator(node); } iterator upper_bound(const key_type& x) { tree_node * node = static_cast(__upper_bound(x)); return iterator(node); } const_iterator upper_bound(const key_type& x) const { tree_node * node = static_cast(__upper_bound(x)); return const_iterator(node); } pair equal_range(const key_type& x) { return make_pair(lower_bound(x),upper_bound(x)); }; pair equal_range(const key_type& x) const { return make_pair(lower_bound(x),upper_bound(x)); } #else iterator lower_bound(const key_type& x) const { tree_node * node = static_cast(__search(x,LOWER_BOUND)); return iterator(node); } iterator upper_bound(const key_type& x) const { tree_node * node = static_cast(__upper_bound(x)); return iterator(node); } pair equal_range(const key_type& x) const { return make_pair(lower_bound(x),upper_bound(x)); }; #endif /* KAI_NONSTD_SET */ // KCC does not yet implement explicit qualification of template arguments, // so we have to be a bit broad in granting friendship. template friend bool operator==( const multihash_set&, const multihash_set& ); template friend bool operator!=( const multihash_set&, const multihash_set& ); template friend bool operator<( const multihash_set&, const multihash_set& ); template friend bool operator>( const multihash_set&, const multihash_set& ); template friend bool operator>=( const multihash_set&, const multihash_set& ); template friend bool operator<=( const multihash_set&, const multihash_set& ); }; // class multihash_set template template void multihash_set::insert(InputIterator first, InputIterator last) { // See comments for similar method in class hash_set. __kai::rb_tree_node_base * where = header; for( ; first!=last; first++ ) { __insert_multi( where, *first, &where ); } } template inline bool operator==( const multihash_set& x, const multihash_set& y ) { return x.size()==y.size() && x.__compare(y)==0; } template inline bool operator!=( const multihash_set& x, const multihash_set& y ) { return x.size()!=y.size() || x.__compare(y)!=0; } template inline bool operator<( const multihash_set& x, const multihash_set& y ) { return x.__compare(y) < 0; } template inline bool operator>( const multihash_set& x, const multihash_set& y ) { return x.__compare(y) > 0; } template inline bool operator>=( const multihash_set& x, const multihash_set& y ) { return x.__compare(y) >= 0; } template inline bool operator<=( const multihash_set& x, const multihash_set& y ) { return x.__compare(y) <= 0; } template inline void swap( multihash_set& x, multihash_set& y ) { x.swap(y); } } /* namespace std */ #endif /* __KAI_SET */