Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

stl_hashtable.h

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

Generated at Tue May 1 16:28:39 2001 for libstdc++-v3 by doxygen1.2.6 written by Dimitri van Heesch, © 1997-2001