Whole document tree
    

Whole document tree

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

Generated on Mon Apr 8 03:11:40 2002 for libstdc++-v3 Source by doxygen1.2.15