stl_hashtable.h

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

Generated on Wed May 1 19:19:36 2002 for libstdc++-v3 Source by doxygen1.2.15