stl_hashtable.h

00001 /*
00002  * Copyright (c) 1996,1997
00003  * Silicon Graphics Computer Systems, Inc.
00004  *
00005  * Permission to use, copy, modify, distribute and sell this software
00006  * and its documentation for any purpose is hereby granted without fee,
00007  * provided that the above copyright notice appear in all copies and
00008  * that both that copyright notice and this permission notice appear
00009  * in supporting documentation.  Silicon Graphics makes no
00010  * representations about the suitability of this software for any
00011  * purpose.  It is provided "as is" without express or implied warranty.
00012  *
00013  *
00014  * Copyright (c) 1994
00015  * Hewlett-Packard Company
00016  *
00017  * Permission to use, copy, modify, distribute and sell this software
00018  * and its documentation for any purpose is hereby granted without fee,
00019  * provided that the above copyright notice appear in all copies and
00020  * that both that copyright notice and this permission notice appear
00021  * in supporting documentation.  Hewlett-Packard Company makes no
00022  * representations about the suitability of this software for any
00023  * purpose.  It is provided "as is" without express or implied warranty.
00024  *
00025  */
00026 
00027 /* NOTE: This is an internal header file, included by other STL headers.
00028  *   You should not attempt to use it directly.
00029  */
00030 
00031 #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
00032 #define __SGI_STL_INTERNAL_HASHTABLE_H
00033 
00034 // Hashtable class, used to implement the hashed associative containers
00035 // hash_set, hash_map, hash_multiset, and hash_multimap.
00036 
00037 #include <stl_algobase.h>
00038 #include <stl_alloc.h>
00039 #include <stl_construct.h>
00040 #include <stl_tempbuf.h>
00041 #include <stl_algo.h>
00042 #include <stl_uninitialized.h>
00043 #include <stl_function.h>
00044 #include <stl_vector.h>
00045 #include <stl_hash_fun.h>
00046 
00047 __STL_BEGIN_NAMESPACE
00048 
00049 template <class _Val>
00050 struct _Hashtable_node
00051 {
00052   _Hashtable_node* _M_next;
00053   _Val _M_val;
00054 };  
00055 
00056 template <class _Val, class _Key, class _HashFcn,
00057           class _ExtractKey, class _EqualKey, class _Alloc = alloc>
00058 class hashtable;
00059 
00060 template <class _Val, class _Key, class _HashFcn,
00061           class _ExtractKey, class _EqualKey, class _Alloc>
00062 struct _Hashtable_iterator;
00063 
00064 template <class _Val, class _Key, class _HashFcn,
00065           class _ExtractKey, class _EqualKey, class _Alloc>
00066 struct _Hashtable_const_iterator;
00067 
00068 template <class _Val, class _Key, class _HashFcn,
00069           class _ExtractKey, class _EqualKey, class _Alloc>
00070 struct _Hashtable_iterator {
00071   typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00072           _Hashtable;
00073   typedef _Hashtable_iterator<_Val, _Key, _HashFcn, 
00074                               _ExtractKey, _EqualKey, _Alloc>
00075           iterator;
00076   typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 
00077                                     _ExtractKey, _EqualKey, _Alloc>
00078           const_iterator;
00079   typedef _Hashtable_node<_Val> _Node;
00080 
00081   typedef forward_iterator_tag iterator_category;
00082   typedef _Val value_type;
00083   typedef ptrdiff_t difference_type;
00084   typedef size_t size_type;
00085   typedef _Val& reference;
00086   typedef _Val* pointer;
00087 
00088   _Node* _M_cur;
00089   _Hashtable* _M_ht;
00090 
00091   _Hashtable_iterator(_Node* __n, _Hashtable* __tab) 
00092     : _M_cur(__n), _M_ht(__tab) {}
00093   _Hashtable_iterator() {}
00094   reference operator*() const { return _M_cur->_M_val; }
00095 #ifndef __SGI_STL_NO_ARROW_OPERATOR
00096   pointer operator->() const { return &(operator*()); }
00097 #endif /* __SGI_STL_NO_ARROW_OPERATOR */
00098   iterator& operator++();
00099   iterator operator++(int);
00100   bool operator==(const iterator& __it) const
00101     { return _M_cur == __it._M_cur; }
00102   bool operator!=(const iterator& __it) const
00103     { return _M_cur != __it._M_cur; }
00104 };
00105 
00106 
00107 template <class _Val, class _Key, class _HashFcn,
00108           class _ExtractKey, class _EqualKey, class _Alloc>
00109 struct _Hashtable_const_iterator {
00110   typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00111           _Hashtable;
00112   typedef _Hashtable_iterator<_Val,_Key,_HashFcn, 
00113                               _ExtractKey,_EqualKey,_Alloc>
00114           iterator;
00115   typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 
00116                                     _ExtractKey, _EqualKey, _Alloc>
00117           const_iterator;
00118   typedef _Hashtable_node<_Val> _Node;
00119 
00120   typedef forward_iterator_tag iterator_category;
00121   typedef _Val value_type;
00122   typedef ptrdiff_t difference_type;
00123   typedef size_t size_type;
00124   typedef const _Val& reference;
00125   typedef const _Val* pointer;
00126 
00127   const _Node* _M_cur;
00128   const _Hashtable* _M_ht;
00129 
00130   _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
00131     : _M_cur(__n), _M_ht(__tab) {}
00132   _Hashtable_const_iterator() {}
00133   _Hashtable_const_iterator(const iterator& __it) 
00134     : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
00135   reference operator*() const { return _M_cur->_M_val; }
00136 #ifndef __SGI_STL_NO_ARROW_OPERATOR
00137   pointer operator->() const { return &(operator*()); }
00138 #endif /* __SGI_STL_NO_ARROW_OPERATOR */
00139   const_iterator& operator++();
00140   const_iterator operator++(int);
00141   bool operator==(const const_iterator& __it) const 
00142     { return _M_cur == __it._M_cur; }
00143   bool operator!=(const const_iterator& __it) const 
00144     { return _M_cur != __it._M_cur; }
00145 };
00146 
00147 // Note: assumes long is at least 32 bits.
00148 enum { __stl_num_primes = 28 };
00149 
00150 static const unsigned long __stl_prime_list[__stl_num_primes] =
00151 {
00152   53ul,         97ul,         193ul,       389ul,       769ul,
00153   1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
00154   49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
00155   1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
00156   50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul, 
00157   1610612741ul, 3221225473ul, 4294967291ul
00158 };
00159 
00160 inline unsigned long __stl_next_prime(unsigned long __n)
00161 {
00162   const unsigned long* __first = __stl_prime_list;
00163   const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
00164   const unsigned long* pos = lower_bound(__first, __last, __n);
00165   return pos == __last ? *(__last - 1) : *pos;
00166 }
00167 
00168 // Forward declaration of operator==.
00169 
00170 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00171 class hashtable;
00172 
00173 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00174 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00175                 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
00176 
00177 
00178 // Hashtables handle allocators a bit differently than other containers
00179 //  do.  If we're using standard-conforming allocators, then a hashtable
00180 //  unconditionally has a member variable to hold its allocator, even if
00181 //  it so happens that all instances of the allocator type are identical.
00182 // This is because, for hashtables, this extra storage is negligible.  
00183 //  Additionally, a base class wouldn't serve any other purposes; it 
00184 //  wouldn't, for example, simplify the exception-handling code.
00185 
00186 template <class _Val, class _Key, class _HashFcn,
00187           class _ExtractKey, class _EqualKey, class _Alloc>
00188 class hashtable {
00189 public:
00190   typedef _Key key_type;
00191   typedef _Val value_type;
00192   typedef _HashFcn hasher;
00193   typedef _EqualKey key_equal;
00194 
00195   typedef size_t            size_type;
00196   typedef ptrdiff_t         difference_type;
00197   typedef value_type*       pointer;
00198   typedef const value_type* const_pointer;
00199   typedef value_type&       reference;
00200   typedef const value_type& const_reference;
00201 
00202   hasher hash_funct() const { return _M_hash; }
00203   key_equal key_eq() const { return _M_equals; }
00204 
00205 private:
00206   typedef _Hashtable_node<_Val> _Node;
00207 
00208 #ifdef __STL_USE_STD_ALLOCATORS
00209 public:
00210   typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
00211   allocator_type get_allocator() const { return _M_node_allocator; }
00212 private:
00213   typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
00214   _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
00215   void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
00216 # define __HASH_ALLOC_INIT(__a) _M_node_allocator(__a), 
00217 #else /* __STL_USE_STD_ALLOCATORS */
00218 public:
00219   typedef _Alloc allocator_type;
00220   allocator_type get_allocator() const { return allocator_type(); }
00221 private:
00222   typedef simple_alloc<_Node, _Alloc> _M_node_allocator_type;
00223   _Node* _M_get_node() { return _M_node_allocator_type::allocate(1); }
00224   void _M_put_node(_Node* __p) { _M_node_allocator_type::deallocate(__p, 1); }
00225 # define __HASH_ALLOC_INIT(__a)
00226 #endif /* __STL_USE_STD_ALLOCATORS */
00227 
00228 private:
00229   hasher                _M_hash;
00230   key_equal             _M_equals;
00231   _ExtractKey           _M_get_key;
00232   vector<_Node*,_Alloc> _M_buckets;
00233   size_type             _M_num_elements;
00234 
00235 public:
00236   typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00237           iterator;
00238   typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
00239                                     _Alloc>
00240           const_iterator;
00241 
00242   friend struct
00243   _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
00244   friend struct
00245   _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
00246 
00247 public:
00248   hashtable(size_type __n,
00249             const _HashFcn&    __hf,
00250             const _EqualKey&   __eql,
00251             const _ExtractKey& __ext,
00252             const allocator_type& __a = allocator_type())
00253     : __HASH_ALLOC_INIT(__a)
00254       _M_hash(__hf),
00255       _M_equals(__eql),
00256       _M_get_key(__ext),
00257       _M_buckets(__a),
00258       _M_num_elements(0)
00259   {
00260     _M_initialize_buckets(__n);
00261   }
00262 
00263   hashtable(size_type __n,
00264             const _HashFcn&    __hf,
00265             const _EqualKey&   __eql,
00266             const allocator_type& __a = allocator_type())
00267     : __HASH_ALLOC_INIT(__a)
00268       _M_hash(__hf),
00269       _M_equals(__eql),
00270       _M_get_key(_ExtractKey()),
00271       _M_buckets(__a),
00272       _M_num_elements(0)
00273   {
00274     _M_initialize_buckets(__n);
00275   }
00276 
00277   hashtable(const hashtable& __ht)
00278     : __HASH_ALLOC_INIT(__ht.get_allocator())
00279       _M_hash(__ht._M_hash),
00280       _M_equals(__ht._M_equals),
00281       _M_get_key(__ht._M_get_key),
00282       _M_buckets(__ht.get_allocator()),
00283       _M_num_elements(0)
00284   {
00285     _M_copy_from(__ht);
00286   }
00287 
00288 #undef __HASH_ALLOC_INIT
00289 
00290   hashtable& operator= (const hashtable& __ht)
00291   {
00292     if (&__ht != this) {
00293       clear();
00294       _M_hash = __ht._M_hash;
00295       _M_equals = __ht._M_equals;
00296       _M_get_key = __ht._M_get_key;
00297       _M_copy_from(__ht);
00298     }
00299     return *this;
00300   }
00301 
00302   ~hashtable() { clear(); }
00303 
00304   size_type size() const { return _M_num_elements; }
00305   size_type max_size() const { return size_type(-1); }
00306   bool empty() const { return size() == 0; }
00307 
00308   void swap(hashtable& __ht)
00309   {
00310     __STD::swap(_M_hash, __ht._M_hash);
00311     __STD::swap(_M_equals, __ht._M_equals);
00312     __STD::swap(_M_get_key, __ht._M_get_key);
00313     _M_buckets.swap(__ht._M_buckets);
00314     __STD::swap(_M_num_elements, __ht._M_num_elements);
00315   }
00316 
00317   iterator begin()
00318   { 
00319     for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
00320       if (_M_buckets[__n])
00321         return iterator(_M_buckets[__n], this);
00322     return end();
00323   }
00324 
00325   iterator end() { return iterator(0, this); }
00326 
00327   const_iterator begin() const
00328   {
00329     for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
00330       if (_M_buckets[__n])
00331         return const_iterator(_M_buckets[__n], this);
00332     return end();
00333   }
00334 
00335   const_iterator end() const { return const_iterator(0, this); }
00336 
00337 #ifdef __STL_MEMBER_TEMPLATES
00338   template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
00339   friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
00340                           const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
00341 #else /* __STL_MEMBER_TEMPLATES */
00342   friend bool __STD_QUALIFIER
00343   operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
00344 #endif /* __STL_MEMBER_TEMPLATES */
00345 
00346 public:
00347 
00348   size_type bucket_count() const { return _M_buckets.size(); }
00349 
00350   size_type max_bucket_count() const
00351     { return __stl_prime_list[(int)__stl_num_primes - 1]; } 
00352 
00353   size_type elems_in_bucket(size_type __bucket) const
00354   {
00355     size_type __result = 0;
00356     for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
00357       __result += 1;
00358     return __result;
00359   }
00360 
00361   pair<iterator, bool> insert_unique(const value_type& __obj)
00362   {
00363     resize(_M_num_elements + 1);
00364     return insert_unique_noresize(__obj);
00365   }
00366 
00367   iterator insert_equal(const value_type& __obj)
00368   {
00369     resize(_M_num_elements + 1);
00370     return insert_equal_noresize(__obj);
00371   }
00372 
00373   pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
00374   iterator insert_equal_noresize(const value_type& __obj);
00375  
00376 #ifdef __STL_MEMBER_TEMPLATES
00377   template <class _InputIterator>
00378   void insert_unique(_InputIterator __f, _InputIterator __l)
00379   {
00380     insert_unique(__f, __l, __ITERATOR_CATEGORY(__f));
00381   }
00382 
00383   template <class _InputIterator>
00384   void insert_equal(_InputIterator __f, _InputIterator __l)
00385   {
00386     insert_equal(__f, __l, __ITERATOR_CATEGORY(__f));
00387   }
00388 
00389   template <class _InputIterator>
00390   void insert_unique(_InputIterator __f, _InputIterator __l,
00391                      input_iterator_tag)
00392   {
00393     for ( ; __f != __l; ++__f)
00394       insert_unique(*__f);
00395   }
00396 
00397   template <class _InputIterator>
00398   void insert_equal(_InputIterator __f, _InputIterator __l,
00399                     input_iterator_tag)
00400   {
00401     for ( ; __f != __l; ++__f)
00402       insert_equal(*__f);
00403   }
00404 
00405   template <class _ForwardIterator>
00406   void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
00407                      forward_iterator_tag)
00408   {
00409     size_type __n = 0;
00410     distance(__f, __l, __n);
00411     resize(_M_num_elements + __n);
00412     for ( ; __n > 0; --__n, ++__f)
00413       insert_unique_noresize(*__f);
00414   }
00415 
00416   template <class _ForwardIterator>
00417   void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
00418                     forward_iterator_tag)
00419   {
00420     size_type __n = 0;
00421     distance(__f, __l, __n);
00422     resize(_M_num_elements + __n);
00423     for ( ; __n > 0; --__n, ++__f)
00424       insert_equal_noresize(*__f);
00425   }
00426 
00427 #else /* __STL_MEMBER_TEMPLATES */
00428   void insert_unique(const value_type* __f, const value_type* __l)
00429   {
00430     size_type __n = __l - __f;
00431     resize(_M_num_elements + __n);
00432     for ( ; __n > 0; --__n, ++__f)
00433       insert_unique_noresize(*__f);
00434   }
00435 
00436   void insert_equal(const value_type* __f, const value_type* __l)
00437   {
00438     size_type __n = __l - __f;
00439     resize(_M_num_elements + __n);
00440     for ( ; __n > 0; --__n, ++__f)
00441       insert_equal_noresize(*__f);
00442   }
00443 
00444   void insert_unique(const_iterator __f, const_iterator __l)
00445   {
00446     size_type __n = 0;
00447     distance(__f, __l, __n);
00448     resize(_M_num_elements + __n);
00449     for ( ; __n > 0; --__n, ++__f)
00450       insert_unique_noresize(*__f);
00451   }
00452 
00453   void insert_equal(const_iterator __f, const_iterator __l)
00454   {
00455     size_type __n = 0;
00456     distance(__f, __l, __n);
00457     resize(_M_num_elements + __n);
00458     for ( ; __n > 0; --__n, ++__f)
00459       insert_equal_noresize(*__f);
00460   }
00461 #endif /*__STL_MEMBER_TEMPLATES */
00462 
00463   reference find_or_insert(const value_type& __obj);
00464 
00465   iterator find(const key_type& __key) 
00466   {
00467     size_type __n = _M_bkt_num_key(__key);
00468     _Node* __first;
00469     for ( __first = _M_buckets[__n];
00470           __first && !_M_equals(_M_get_key(__first->_M_val), __key);
00471           __first = __first->_M_next)
00472       {}
00473     return iterator(__first, this);
00474   } 
00475 
00476   const_iterator find(const key_type& __key) const
00477   {
00478     size_type __n = _M_bkt_num_key(__key);
00479     const _Node* __first;
00480     for ( __first = _M_buckets[__n];
00481           __first && !_M_equals(_M_get_key(__first->_M_val), __key);
00482           __first = __first->_M_next)
00483       {}
00484     return const_iterator(__first, this);
00485   } 
00486 
00487   size_type count(const key_type& __key) const
00488   {
00489     const size_type __n = _M_bkt_num_key(__key);
00490     size_type __result = 0;
00491 
00492     for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
00493       if (_M_equals(_M_get_key(__cur->_M_val), __key))
00494         ++__result;
00495     return __result;
00496   }
00497 
00498   pair<iterator, iterator> 
00499   equal_range(const key_type& __key);
00500 
00501   pair<const_iterator, const_iterator> 
00502   equal_range(const key_type& __key) const;
00503 
00504   size_type erase(const key_type& __key);
00505   void erase(const iterator& __it);
00506   void erase(iterator __first, iterator __last);
00507 
00508   void erase(const const_iterator& __it);
00509   void erase(const_iterator __first, const_iterator __last);
00510 
00511   void resize(size_type __num_elements_hint);
00512   void clear();
00513 
00514 private:
00515   size_type _M_next_size(size_type __n) const
00516     { return __stl_next_prime(__n); }
00517 
00518   void _M_initialize_buckets(size_type __n)
00519   {
00520     const size_type __n_buckets = _M_next_size(__n);
00521     _M_buckets.reserve(__n_buckets);
00522     _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
00523     _M_num_elements = 0;
00524   }
00525 
00526   size_type _M_bkt_num_key(const key_type& __key) const
00527   {
00528     return _M_bkt_num_key(__key, _M_buckets.size());
00529   }
00530 
00531   size_type _M_bkt_num(const value_type& __obj) const
00532   {
00533     return _M_bkt_num_key(_M_get_key(__obj));
00534   }
00535 
00536   size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
00537   {
00538     return _M_hash(__key) % __n;
00539   }
00540 
00541   size_type _M_bkt_num(const value_type& __obj, size_t __n) const
00542   {
00543     return _M_bkt_num_key(_M_get_key(__obj), __n);
00544   }
00545 
00546   _Node* _M_new_node(const value_type& __obj)
00547   {
00548     _Node* __n = _M_get_node();
00549     __n->_M_next = 0;
00550     __STL_TRY {
00551       construct(&__n->_M_val, __obj);
00552       return __n;
00553     }
00554     __STL_UNWIND(_M_put_node(__n));
00555   }
00556   
00557   void _M_delete_node(_Node* __n)
00558   {
00559     destroy(&__n->_M_val);
00560     _M_put_node(__n);
00561   }
00562 
00563   void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
00564   void _M_erase_bucket(const size_type __n, _Node* __last);
00565 
00566   void _M_copy_from(const hashtable& __ht);
00567 
00568 };
00569 
00570 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00571           class _All>
00572 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
00573 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
00574 {
00575   const _Node* __old = _M_cur;
00576   _M_cur = _M_cur->_M_next;
00577   if (!_M_cur) {
00578     size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
00579     while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
00580       _M_cur = _M_ht->_M_buckets[__bucket];
00581   }
00582   return *this;
00583 }
00584 
00585 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00586           class _All>
00587 inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
00588 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
00589 {
00590   iterator __tmp = *this;
00591   ++*this;
00592   return __tmp;
00593 }
00594 
00595 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00596           class _All>
00597 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
00598 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
00599 {
00600   const _Node* __old = _M_cur;
00601   _M_cur = _M_cur->_M_next;
00602   if (!_M_cur) {
00603     size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
00604     while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
00605       _M_cur = _M_ht->_M_buckets[__bucket];
00606   }
00607   return *this;
00608 }
00609 
00610 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00611           class _All>
00612 inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
00613 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
00614 {
00615   const_iterator __tmp = *this;
00616   ++*this;
00617   return __tmp;
00618 }
00619 
00620 #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
00621 
00622 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00623           class _All>
00624 inline forward_iterator_tag
00625 iterator_category(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
00626 {
00627   return forward_iterator_tag();
00628 }
00629 
00630 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00631           class _All>
00632 inline _Val* 
00633 value_type(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
00634 {
00635   return (_Val*) 0;
00636 }
00637 
00638 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00639           class _All>
00640 inline hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*
00641 distance_type(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
00642 {
00643   return (hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*) 0;
00644 }
00645 
00646 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00647           class _All>
00648 inline forward_iterator_tag
00649 iterator_category(const _Hashtable_const_iterator<_Val,_Key,_HF,
00650                                                   _ExK,_EqK,_All>&)
00651 {
00652   return forward_iterator_tag();
00653 }
00654 
00655 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00656           class _All>
00657 inline _Val* 
00658 value_type(const _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
00659 {
00660   return (_Val*) 0;
00661 }
00662 
00663 template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
00664           class _All>
00665 inline hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*
00666 distance_type(const _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
00667 {
00668   return (hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*) 0;
00669 }
00670 
00671 #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
00672 
00673 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00674 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00675                 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
00676 {
00677   typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
00678   if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
00679     return false;
00680   for (int __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
00681     _Node* __cur1 = __ht1._M_buckets[__n];
00682     _Node* __cur2 = __ht2._M_buckets[__n];
00683     for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
00684           __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
00685       {}
00686     if (__cur1 || __cur2)
00687       return false;
00688   }
00689   return true;
00690 }  
00691 
00692 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
00693 
00694 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00695 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00696                        const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
00697   return !(__ht1 == __ht2);
00698 }
00699 
00700 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey, 
00701           class _All>
00702 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
00703                  hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
00704   __ht1.swap(__ht2);
00705 }
00706 
00707 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
00708 
00709 
00710 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00711 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool> 
00712 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00713   ::insert_unique_noresize(const value_type& __obj)
00714 {
00715   const size_type __n = _M_bkt_num(__obj);
00716   _Node* __first = _M_buckets[__n];
00717 
00718   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 
00719     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
00720       return pair<iterator, bool>(iterator(__cur, this), false);
00721 
00722   _Node* __tmp = _M_new_node(__obj);
00723   __tmp->_M_next = __first;
00724   _M_buckets[__n] = __tmp;
00725   ++_M_num_elements;
00726   return pair<iterator, bool>(iterator(__tmp, this), true);
00727 }
00728 
00729 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00730 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator 
00731 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00732   ::insert_equal_noresize(const value_type& __obj)
00733 {
00734   const size_type __n = _M_bkt_num(__obj);
00735   _Node* __first = _M_buckets[__n];
00736 
00737   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 
00738     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
00739       _Node* __tmp = _M_new_node(__obj);
00740       __tmp->_M_next = __cur->_M_next;
00741       __cur->_M_next = __tmp;
00742       ++_M_num_elements;
00743       return iterator(__tmp, this);
00744     }
00745 
00746   _Node* __tmp = _M_new_node(__obj);
00747   __tmp->_M_next = __first;
00748   _M_buckets[__n] = __tmp;
00749   ++_M_num_elements;
00750   return iterator(__tmp, this);
00751 }
00752 
00753 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00754 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference 
00755 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
00756 {
00757   resize(_M_num_elements + 1);
00758 
00759   size_type __n = _M_bkt_num(__obj);
00760   _Node* __first = _M_buckets[__n];
00761 
00762   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
00763     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
00764       return __cur->_M_val;
00765 
00766   _Node* __tmp = _M_new_node(__obj);
00767   __tmp->_M_next = __first;
00768   _M_buckets[__n] = __tmp;
00769   ++_M_num_elements;
00770   return __tmp->_M_val;
00771 }
00772 
00773 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00774 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
00775      typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator> 
00776 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
00777 {
00778   typedef pair<iterator, iterator> _Pii;
00779   const size_type __n = _M_bkt_num_key(__key);
00780 
00781   for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
00782     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00783       for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
00784         if (!_M_equals(_M_get_key(__cur->_M_val), __key))
00785           return _Pii(iterator(__first, this), iterator(__cur, this));
00786       for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
00787         if (_M_buckets[__m])
00788           return _Pii(iterator(__first, this),
00789                      iterator(_M_buckets[__m], this));
00790       return _Pii(iterator(__first, this), end());
00791     }
00792   return _Pii(end(), end());
00793 }
00794 
00795 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00796 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator, 
00797      typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator> 
00798 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00799   ::equal_range(const key_type& __key) const
00800 {
00801   typedef pair<const_iterator, const_iterator> _Pii;
00802   const size_type __n = _M_bkt_num_key(__key);
00803 
00804   for (const _Node* __first = _M_buckets[__n] ;
00805        __first; 
00806        __first = __first->_M_next) {
00807     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00808       for (const _Node* __cur = __first->_M_next;
00809            __cur;
00810            __cur = __cur->_M_next)
00811         if (!_M_equals(_M_get_key(__cur->_M_val), __key))
00812           return _Pii(const_iterator(__first, this),
00813                       const_iterator(__cur, this));
00814       for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
00815         if (_M_buckets[__m])
00816           return _Pii(const_iterator(__first, this),
00817                       const_iterator(_M_buckets[__m], this));
00818       return _Pii(const_iterator(__first, this), end());
00819     }
00820   }
00821   return _Pii(end(), end());
00822 }
00823 
00824 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00825 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type 
00826 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
00827 {
00828   const size_type __n = _M_bkt_num_key(__key);
00829   _Node* __first = _M_buckets[__n];
00830   size_type __erased = 0;
00831 
00832   if (__first) {
00833     _Node* __cur = __first;
00834     _Node* __next = __cur->_M_next;
00835     while (__next) {
00836       if (_M_equals(_M_get_key(__next->_M_val), __key)) {
00837         __cur->_M_next = __next->_M_next;
00838         _M_delete_node(__next);
00839         __next = __cur->_M_next;
00840         ++__erased;
00841         --_M_num_elements;
00842       }
00843       else {
00844         __cur = __next;
00845         __next = __cur->_M_next;
00846       }
00847     }
00848     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00849       _M_buckets[__n] = __first->_M_next;
00850       _M_delete_node(__first);
00851       ++__erased;
00852       --_M_num_elements;
00853     }
00854   }
00855   return __erased;
00856 }
00857 
00858 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00859 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
00860 {
00861   _Node* __p = __it._M_cur;
00862   if (__p) {
00863     const size_type __n = _M_bkt_num(__p->_M_val);
00864     _Node* __cur = _M_buckets[__n];
00865 
00866     if (__cur == __p) {
00867       _M_buckets[__n] = __cur->_M_next;
00868       _M_delete_node(__cur);
00869       --_M_num_elements;
00870     }
00871     else {
00872       _Node* __next = __cur->_M_next;
00873       while (__next) {
00874         if (__next == __p) {
00875           __cur->_M_next = __next->_M_next;
00876           _M_delete_node(__next);
00877           --_M_num_elements;
00878           break;
00879         }
00880         else {
00881           __cur = __next;
00882           __next = __cur->_M_next;
00883         }
00884       }
00885     }
00886   }
00887 }
00888 
00889 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00890 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00891   ::erase(iterator __first, iterator __last)
00892 {
00893   size_type __f_bucket = __first._M_cur ? 
00894     _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
00895   size_type __l_bucket = __last._M_cur ? 
00896     _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
00897 
00898   if (__first._M_cur == __last._M_cur)
00899     return;
00900   else if (__f_bucket == __l_bucket)
00901     _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
00902   else {
00903     _M_erase_bucket(__f_bucket, __first._M_cur, 0);
00904     for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
00905       _M_erase_bucket(__n, 0);
00906     if (__l_bucket != _M_buckets.size())
00907       _M_erase_bucket(__l_bucket, __last._M_cur);
00908   }
00909 }
00910 
00911 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00912 inline void
00913 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
00914                                              const_iterator __last)
00915 {
00916   erase(iterator(const_cast<_Node*>(__first._M_cur),
00917                  const_cast<hashtable*>(__first._M_ht)),
00918         iterator(const_cast<_Node*>(__last._M_cur),
00919                  const_cast<hashtable*>(__last._M_ht)));
00920 }
00921 
00922 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00923 inline void
00924 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
00925 {
00926   erase(iterator(const_cast<_Node*>(__it._M_cur),
00927                  const_cast<hashtable*>(__it._M_ht)));
00928 }
00929 
00930 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00931 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00932   ::resize(size_type __num_elements_hint)
00933 {
00934   const size_type __old_n = _M_buckets.size();
00935   if (__num_elements_hint > __old_n) {
00936     const size_type __n = _M_next_size(__num_elements_hint);
00937     if (__n > __old_n) {
00938       vector<_Node*, _All> __tmp(__n, (_Node*)(0),
00939                                  _M_buckets.get_allocator());
00940       __STL_TRY {
00941         for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
00942           _Node* __first = _M_buckets[__bucket];
00943           while (__first) {
00944             size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
00945             _M_buckets[__bucket] = __first->_M_next;
00946             __first->_M_next = __tmp[__new_bucket];
00947             __tmp[__new_bucket] = __first;
00948             __first = _M_buckets[__bucket];          
00949           }
00950         }
00951         _M_buckets.swap(__tmp);
00952       }
00953 #         ifdef __STL_USE_EXCEPTIONS
00954       catch(...) {
00955         for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
00956           while (__tmp[__bucket]) {
00957             _Node* __next = __tmp[__bucket]->_M_next;
00958             _M_delete_node(__tmp[__bucket]);
00959             __tmp[__bucket] = __next;
00960           }
00961         }
00962         throw;
00963       }
00964 #         endif /* __STL_USE_EXCEPTIONS */
00965     }
00966   }
00967 }
00968 
00969 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00970 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00971   ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
00972 {
00973   _Node* __cur = _M_buckets[__n];
00974   if (__cur == __first)
00975     _M_erase_bucket(__n, __last);
00976   else {
00977     _Node* __next;
00978     for (__next = __cur->_M_next; 
00979          __next != __first; 
00980          __cur = __next, __next = __cur->_M_next)
00981       ;
00982     while (__next != __last) {
00983       __cur->_M_next = __next->_M_next;
00984       _M_delete_node(__next);
00985       __next = __cur->_M_next;
00986       --_M_num_elements;
00987     }
00988   }
00989 }
00990 
00991 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00992 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00993   ::_M_erase_bucket(const size_type __n, _Node* __last)
00994 {
00995   _Node* __cur = _M_buckets[__n];
00996   while (__cur != __last) {
00997     _Node* __next = __cur->_M_next;
00998     _M_delete_node(__cur);
00999     __cur = __next;
01000     _M_buckets[__n] = __cur;
01001     --_M_num_elements;
01002   }
01003 }
01004 
01005 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
01006 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
01007 {
01008   for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
01009     _Node* __cur = _M_buckets[__i];
01010     while (__cur != 0) {
01011       _Node* __next = __cur->_M_next;
01012       _M_delete_node(__cur);
01013       __cur = __next;
01014     }
01015     _M_buckets[__i] = 0;
01016   }
01017   _M_num_elements = 0;
01018 }
01019 
01020     
01021 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
01022 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
01023   ::_M_copy_from(const hashtable& __ht)
01024 {
01025   _M_buckets.clear();
01026   _M_buckets.reserve(__ht._M_buckets.size());
01027   _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
01028   __STL_TRY {
01029     for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
01030       const _Node* __cur = __ht._M_buckets[__i];
01031       if (__cur) {
01032         _Node* __copy = _M_new_node(__cur->_M_val);
01033         _M_buckets[__i] = __copy;
01034 
01035         for (_Node* __next = __cur->_M_next; 
01036              __next; 
01037              __cur = __next, __next = __cur->_M_next) {
01038           __copy->_M_next = _M_new_node(__next->_M_val);
01039           __copy = __copy->_M_next;
01040         }
01041       }
01042     }
01043     _M_num_elements = __ht._M_num_elements;
01044   }
01045   __STL_UNWIND(clear());
01046 }
01047 
01048 __STL_END_NAMESPACE
01049 
01050 #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
01051 
01052 // Local Variables:
01053 // mode:C++
01054 // End:

Generated on Mon Jun 5 10:20:44 2006 for Intelligence.kdevelop by  doxygen 1.4.6