home *** CD-ROM | disk | FTP | other *** search
/ Programmer Plus 2007 / Programmer-Plus-2007.iso / Programming / Compilers / digital marsC compier / dm / stl / stl_hashtable.h < prev    next >
Encoding:
C/C++ Source or Header  |  2000-06-08  |  32.3 KB  |  1,055 lines

  1. /*
  2.  * Copyright (c) 1996,1997
  3.  * Silicon Graphics Computer Systems, Inc.
  4.  *
  5.  * Permission to use, copy, modify, distribute and sell this software
  6.  * and its documentation for any purpose is hereby granted without fee,
  7.  * provided that the above copyright notice appear in all copies and
  8.  * that both that copyright notice and this permission notice appear
  9.  * in supporting documentation.  Silicon Graphics makes no
  10.  * representations about the suitability of this software for any
  11.  * purpose.  It is provided "as is" without express or implied warranty.
  12.  *
  13.  *
  14.  * Copyright (c) 1994
  15.  * Hewlett-Packard Company
  16.  *
  17.  * Permission to use, copy, modify, distribute and sell this software
  18.  * and its documentation for any purpose is hereby granted without fee,
  19.  * provided that the above copyright notice appear in all copies and
  20.  * that both that copyright notice and this permission notice appear
  21.  * in supporting documentation.  Hewlett-Packard Company makes no
  22.  * representations about the suitability of this software for any
  23.  * purpose.  It is provided "as is" without express or implied warranty.
  24.  *
  25.  */
  26.  
  27. /* NOTE: This is an internal header file, included by other STL headers.
  28.  *   You should not attempt to use it directly.
  29.  */
  30.  
  31. #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
  32. #define __SGI_STL_INTERNAL_HASHTABLE_H
  33.  
  34. // Hashtable class, used to implement the hashed associative containers
  35. // hash_set, hash_map, hash_multiset, and hash_multimap.
  36.  
  37. #include <stl_algobase.h>
  38. #include <stl_alloc.h>
  39. #include <stl_construct.h>
  40. #include <stl_tempbuf.h>
  41. #include <stl_algo.h>
  42. #include <stl_uninitialized.h>
  43. #include <stl_function.h>
  44. #include <stl_vector.h>
  45. #include <stl_hash_fun.h>
  46.  
  47. __STL_BEGIN_NAMESPACE
  48.  
  49. template <class _Val>
  50. struct _Hashtable_node
  51. {
  52.   _Hashtable_node* _M_next;
  53.   _Val _M_val;
  54. };  
  55.  
  56. template <class _Val, class _Key, class _HashFcn,
  57.           class _ExtractKey, class _EqualKey, class _Alloc = alloc>
  58. class hashtable;
  59.  
  60. template <class _Val, class _Key, class _HashFcn,
  61.           class _ExtractKey, class _EqualKey, class _Alloc>
  62. struct _Hashtable_iterator;
  63.  
  64. template <class _Val, class _Key, class _HashFcn,
  65.           class _ExtractKey, class _EqualKey, class _Alloc>
  66. struct _Hashtable_const_iterator;
  67.  
  68. template <class _Val, class _Key, class _HashFcn,
  69.           class _ExtractKey, class _EqualKey, class _Alloc>
  70. struct _Hashtable_iterator {
  71.   typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
  72.           _Hashtable;
  73.   typedef _Hashtable_iterator<_Val, _Key, _HashFcn, 
  74.                               _ExtractKey, _EqualKey, _Alloc>
  75.           iterator;
  76.   typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 
  77.                                     _ExtractKey, _EqualKey, _Alloc>
  78.           const_iterator;
  79.   typedef _Hashtable_node<_Val> _Node;
  80.  
  81.   typedef forward_iterator_tag iterator_category;
  82.   typedef _Val value_type;
  83.   typedef ptrdiff_t difference_type;
  84.   typedef size_t size_type;
  85.   typedef _Val& reference;
  86.   typedef _Val* pointer;
  87.  
  88.   _Node* _M_cur;
  89.   _Hashtable* _M_ht;
  90.  
  91.   _Hashtable_iterator(_Node* __n, _Hashtable* __tab) 
  92.     : _M_cur(__n), _M_ht(__tab) {}
  93.   _Hashtable_iterator() {}
  94.   reference operator*() const { return _M_cur->_M_val; }
  95. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  96.   pointer operator->() const { return &(operator*()); }
  97. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  98.   iterator& operator++();
  99.   iterator operator++(int);
  100.   bool operator==(const iterator& __it) const
  101.     { return _M_cur == __it._M_cur; }
  102.   bool operator!=(const iterator& __it) const
  103.     { return _M_cur != __it._M_cur; }
  104. };
  105.  
  106.  
  107. template <class _Val, class _Key, class _HashFcn,
  108.           class _ExtractKey, class _EqualKey, class _Alloc>
  109. struct _Hashtable_const_iterator {
  110.   typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
  111.           _Hashtable;
  112.   typedef _Hashtable_iterator<_Val,_Key,_HashFcn, 
  113.                               _ExtractKey,_EqualKey,_Alloc>
  114.           iterator;
  115.   typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 
  116.                                     _ExtractKey, _EqualKey, _Alloc>
  117.           const_iterator;
  118.   typedef _Hashtable_node<_Val> _Node;
  119.  
  120.   typedef forward_iterator_tag iterator_category;
  121.   typedef _Val value_type;
  122.   typedef ptrdiff_t difference_type;
  123.   typedef size_t size_type;
  124.   typedef const _Val& reference;
  125.   typedef const _Val* pointer;
  126.  
  127.   const _Node* _M_cur;
  128.   const _Hashtable* _M_ht;
  129.  
  130.   _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
  131.     : _M_cur(__n), _M_ht(__tab) {}
  132.   _Hashtable_const_iterator() {}
  133.   _Hashtable_const_iterator(const iterator& __it) 
  134.     : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
  135.   reference operator*() const { return _M_cur->_M_val; }
  136. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  137.   pointer operator->() const { return &(operator*()); }
  138. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  139.   const_iterator& operator++();
  140.   const_iterator operator++(int);
  141.   bool operator==(const const_iterator& __it) const 
  142.     { return _M_cur == __it._M_cur; }
  143.   bool operator!=(const const_iterator& __it) const 
  144.     { return _M_cur != __it._M_cur; }
  145. };
  146.  
  147. // Note: assumes long is at least 32 bits.
  148. enum { __stl_num_primes = 28 };
  149.  
  150. static const unsigned long __stl_prime_list[__stl_num_primes] =
  151. {
  152.   53ul,         97ul,         193ul,       389ul,       769ul,
  153.   1543ul,       3079ul,       6151ul,      12289ul,     24593ul,
  154.   49157ul,      98317ul,      196613ul,    393241ul,    786433ul,
  155.   1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul,
  156.   50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul, 
  157.   1610612741ul, 3221225473ul, 4294967291ul
  158. };
  159.  
  160. inline unsigned long __stl_next_prime(unsigned long __n)
  161. {
  162.   const unsigned long* __first = __stl_prime_list;
  163.   const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
  164.   const unsigned long* pos = lower_bound(__first, __last, __n);
  165.   return pos == __last ? *(__last - 1) : *pos;
  166. }
  167.  
  168. // Forward declaration of operator==.
  169.  
  170. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  171. class hashtable;
  172.  
  173. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  174. bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
  175.                 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
  176.  
  177.  
  178. // Hashtables handle allocators a bit differently than other containers
  179. //  do.  If we're using standard-conforming allocators, then a hashtable
  180. //  unconditionally has a member variable to hold its allocator, even if
  181. //  it so happens that all instances of the allocator type are identical.
  182. // This is because, for hashtables, this extra storage is negligible.  
  183. //  Additionally, a base class wouldn't serve any other purposes; it 
  184. //  wouldn't, for example, simplify the exception-handling code.
  185.  
  186. template <class _Val, class _Key, class _HashFcn,
  187.           class _ExtractKey, class _EqualKey, class _Alloc>
  188. class hashtable {
  189. public:
  190.   typedef _Key key_type;
  191.   typedef _Val value_type;
  192.   typedef _HashFcn hasher;
  193.   typedef _EqualKey key_equal;
  194.  
  195.   typedef size_t            size_type;
  196.   typedef ptrdiff_t         difference_type;
  197.   typedef value_type*       pointer;
  198.   typedef const value_type* const_pointer;
  199.   typedef value_type&       reference;
  200.   typedef const value_type& const_reference;
  201.  
  202.   hasher hash_funct() const { return _M_hash; }
  203.   key_equal key_eq() const { return _M_equals; }
  204.  
  205. private:
  206.   typedef _Hashtable_node<_Val> _Node;
  207.  
  208. #ifdef __STL_USE_STD_ALLOCATORS
  209. public:
  210.   typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
  211.   allocator_type get_allocator() const { return _M_node_allocator; }
  212. private:
  213.   typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
  214.   _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
  215.   void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
  216. # define __HASH_ALLOC_INIT(__a) _M_node_allocator(__a), 
  217. #else /* __STL_USE_STD_ALLOCATORS */
  218. public:
  219.   typedef _Alloc allocator_type;
  220.   allocator_type get_allocator() const { return allocator_type(); }
  221. private:
  222.   typedef simple_alloc<_Node, _Alloc> _M_node_allocator_type;
  223.   _Node* _M_get_node() { return _M_node_allocator_type::allocate(1); }
  224.   void _M_put_node(_Node* __p) { _M_node_allocator_type::deallocate(__p, 1); }
  225. # define __HASH_ALLOC_INIT(__a)
  226. #endif /* __STL_USE_STD_ALLOCATORS */
  227.  
  228. private:
  229.   hasher                _M_hash;
  230.   key_equal             _M_equals;
  231.   _ExtractKey           _M_get_key;
  232.   vector<_Node*,_Alloc> _M_buckets;
  233.   size_type             _M_num_elements;
  234.  
  235. public:
  236.   typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
  237.           iterator;
  238.   typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
  239.                                     _Alloc>
  240.           const_iterator;
  241.  
  242.   friend struct
  243.   _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
  244.   friend struct
  245.   _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
  246.  
  247. public:
  248.   hashtable(size_type __n,
  249.             const _HashFcn&    __hf,
  250.             const _EqualKey&   __eql,
  251.             const _ExtractKey& __ext,
  252.             const allocator_type& __a = allocator_type())
  253.     : __HASH_ALLOC_INIT(__a)
  254.       _M_hash(__hf),
  255.       _M_equals(__eql),
  256.       _M_get_key(__ext),
  257.       _M_buckets(__a),
  258.       _M_num_elements(0)
  259.   {
  260.     _M_initialize_buckets(__n);
  261.   }
  262.  
  263.   hashtable(size_type __n,
  264.             const _HashFcn&    __hf,
  265.             const _EqualKey&   __eql,
  266.             const allocator_type& __a = allocator_type())
  267.     : __HASH_ALLOC_INIT(__a)
  268.       _M_hash(__hf),
  269.       _M_equals(__eql),
  270.       _M_get_key(_ExtractKey()),
  271.       _M_buckets(__a),
  272.       _M_num_elements(0)
  273.   {
  274.     _M_initialize_buckets(__n);
  275.   }
  276.  
  277.   hashtable(const hashtable& __ht)
  278.     : __HASH_ALLOC_INIT(__ht.get_allocator())
  279.       _M_hash(__ht._M_hash),
  280.       _M_equals(__ht._M_equals),
  281.       _M_get_key(__ht._M_get_key),
  282.       _M_buckets(__ht.get_allocator()),
  283.       _M_num_elements(0)
  284.   {
  285.     _M_copy_from(__ht);
  286.   }
  287.  
  288. #undef __HASH_ALLOC_INIT
  289.  
  290.   hashtable& operator= (const hashtable& __ht)
  291.   {
  292.     if (&__ht != this) {
  293.       clear();
  294.       _M_hash = __ht._M_hash;
  295.       _M_equals = __ht._M_equals;
  296.       _M_get_key = __ht._M_get_key;
  297.       _M_copy_from(__ht);
  298.     }
  299.     return *this;
  300.   }
  301.  
  302.   ~hashtable() { clear(); }
  303.  
  304.   size_type size() const { return _M_num_elements; }
  305.   size_type max_size() const { return size_type(-1); }
  306.   bool empty() const { return size() == 0; }
  307.  
  308.   void swap(hashtable& __ht)
  309.   {
  310.     __STD::swap(_M_hash, __ht._M_hash);
  311.     __STD::swap(_M_equals, __ht._M_equals);
  312.     __STD::swap(_M_get_key, __ht._M_get_key);
  313.     _M_buckets.swap(__ht._M_buckets);
  314.     __STD::swap(_M_num_elements, __ht._M_num_elements);
  315.   }
  316.  
  317.   iterator begin()
  318.   { 
  319.     for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
  320.       if (_M_buckets[__n])
  321.         return iterator(_M_buckets[__n], this);
  322.     return end();
  323.   }
  324.  
  325.   iterator end() { return iterator(0, this); }
  326.  
  327.   const_iterator begin() const
  328.   {
  329.     for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
  330.       if (_M_buckets[__n])
  331.         return const_iterator(_M_buckets[__n], this);
  332.     return end();
  333.   }
  334.  
  335.   const_iterator end() const { return const_iterator(0, this); }
  336.  
  337. #ifdef __STL_MEMBER_TEMPLATES
  338.   template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
  339.   friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
  340.                           const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
  341. #else /* __STL_MEMBER_TEMPLATES */
  342.   friend bool __STD_QUALIFIER
  343.   operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
  344. #endif /* __STL_MEMBER_TEMPLATES */
  345.  
  346. public:
  347.  
  348.   size_type bucket_count() const { return _M_buckets.size(); }
  349.  
  350.   size_type max_bucket_count() const
  351.     { return __stl_prime_list[(int)__stl_num_primes - 1]; } 
  352.  
  353.   size_type elems_in_bucket(size_type __bucket) const
  354.   {
  355.     size_type __result = 0;
  356.     for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
  357.       __result += 1;
  358.     return __result;
  359.   }
  360.  
  361.   pair<iterator, bool> insert_unique(const value_type& __obj)
  362.   {
  363.     resize(_M_num_elements + 1);
  364.     return insert_unique_noresize(__obj);
  365.   }
  366.  
  367.   iterator insert_equal(const value_type& __obj)
  368.   {
  369.     resize(_M_num_elements + 1);
  370.     return insert_equal_noresize(__obj);
  371.   }
  372.  
  373.   pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
  374.   iterator insert_equal_noresize(const value_type& __obj);
  375.  
  376. #ifdef __STL_MEMBER_TEMPLATES
  377.   template <class _InputIterator>
  378.   void insert_unique(_InputIterator __f, _InputIterator __l)
  379.   {
  380.     insert_unique(__f, __l, __ITERATOR_CATEGORY(__f));
  381.   }
  382.  
  383.   template <class _InputIterator>
  384.   void insert_equal(_InputIterator __f, _InputIterator __l)
  385.   {
  386.     insert_equal(__f, __l, __ITERATOR_CATEGORY(__f));
  387.   }
  388.  
  389.   template <class _InputIterator>
  390.   void insert_unique(_InputIterator __f, _InputIterator __l,
  391.                      input_iterator_tag)
  392.   {
  393.     for ( ; __f != __l; ++__f)
  394.       insert_unique(*__f);
  395.   }
  396.  
  397.   template <class _InputIterator>
  398.   void insert_equal(_InputIterator __f, _InputIterator __l,
  399.                     input_iterator_tag)
  400.   {
  401.     for ( ; __f != __l; ++__f)
  402.       insert_equal(*__f);
  403.   }
  404.  
  405.   template <class _ForwardIterator>
  406.   void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
  407.                      forward_iterator_tag)
  408.   {
  409.     size_type __n = 0;
  410.     distance(__f, __l, __n);
  411.     resize(_M_num_elements + __n);
  412.     for ( ; __n > 0; --__n, ++__f)
  413.       insert_unique_noresize(*__f);
  414.   }
  415.  
  416.   template <class _ForwardIterator>
  417.   void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
  418.                     forward_iterator_tag)
  419.   {
  420.     size_type __n = 0;
  421.     distance(__f, __l, __n);
  422.     resize(_M_num_elements + __n);
  423.     for ( ; __n > 0; --__n, ++__f)
  424.       insert_equal_noresize(*__f);
  425.   }
  426.  
  427. #else /* __STL_MEMBER_TEMPLATES */
  428.   void insert_unique(const value_type* __f, const value_type* __l)
  429.   {
  430.     size_type __n = __l - __f;
  431.     resize(_M_num_elements + __n);
  432.     for ( ; __n > 0; --__n, ++__f)
  433.       insert_unique_noresize(*__f);
  434.   }
  435.  
  436.   void insert_equal(const value_type* __f, const value_type* __l)
  437.   {
  438.     size_type __n = __l - __f;
  439.     resize(_M_num_elements + __n);
  440.     for ( ; __n > 0; --__n, ++__f)
  441.       insert_equal_noresize(*__f);
  442.   }
  443.  
  444.   void insert_unique(const_iterator __f, const_iterator __l)
  445.   {
  446.     size_type __n = 0;
  447.     distance(__f, __l, __n);
  448.     resize(_M_num_elements + __n);
  449.     for ( ; __n > 0; --__n, ++__f)
  450.       insert_unique_noresize(*__f);
  451.   }
  452.  
  453.   void insert_equal(const_iterator __f, const_iterator __l)
  454.   {
  455.     size_type __n = 0;
  456.     distance(__f, __l, __n);
  457.     resize(_M_num_elements + __n);
  458.     for ( ; __n > 0; --__n, ++__f)
  459.       insert_equal_noresize(*__f);
  460.   }
  461. #endif /*__STL_MEMBER_TEMPLATES */
  462.  
  463.   reference find_or_insert(const value_type& __obj);
  464.  
  465.   iterator find(const key_type& __key) 
  466.   {
  467.     size_type __n = _M_bkt_num_key(__key);
  468.     _Node* __first;
  469.     for ( __first = _M_buckets[__n];
  470.           __first && !_M_equals(_M_get_key(__first->_M_val), __key);
  471.           __first = __first->_M_next)
  472.       {}
  473.     return iterator(__first, this);
  474.   } 
  475.  
  476.   const_iterator find(const key_type& __key) const
  477.   {
  478.     size_type __n = _M_bkt_num_key(__key);
  479.     const _Node* __first;
  480.     for ( __first = _M_buckets[__n];
  481.           __first && !_M_equals(_M_get_key(__first->_M_val), __key);
  482.           __first = __first->_M_next)
  483.       {}
  484.     return const_iterator(__first, this);
  485.   } 
  486.  
  487.   size_type count(const key_type& __key) const
  488.   {
  489.     const size_type __n = _M_bkt_num_key(__key);
  490.     size_type __result = 0;
  491.  
  492.     for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
  493.       if (_M_equals(_M_get_key(__cur->_M_val), __key))
  494.         ++__result;
  495.     return __result;
  496.   }
  497.  
  498.   pair<iterator, iterator> 
  499.   equal_range(const key_type& __key);
  500.  
  501.   pair<const_iterator, const_iterator> 
  502.   equal_range(const key_type& __key) const;
  503.  
  504.   size_type erase(const key_type& __key);
  505.   void erase(const iterator& __it);
  506.   void erase(iterator __first, iterator __last);
  507.  
  508.   void erase(const const_iterator& __it);
  509.   void erase(const_iterator __first, const_iterator __last);
  510.  
  511.   void resize(size_type __num_elements_hint);
  512.   void clear();
  513.  
  514. private:
  515.   size_type _M_next_size(size_type __n) const
  516.     { return __stl_next_prime(__n); }
  517.  
  518.   void _M_initialize_buckets(size_type __n)
  519.   {
  520.     const size_type __n_buckets = _M_next_size(__n);
  521.     _M_buckets.reserve(__n_buckets);
  522.     _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
  523.     _M_num_elements = 0;
  524.   }
  525.  
  526.   size_type _M_bkt_num_key(const key_type& __key) const
  527.   {
  528.     return _M_bkt_num_key(__key, _M_buckets.size());
  529.   }
  530.  
  531.   size_type _M_bkt_num(const value_type& __obj) const
  532.   {
  533.     return _M_bkt_num_key(_M_get_key(__obj));
  534.   }
  535.  
  536.   size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
  537.   {
  538.     return _M_hash(__key) % __n;
  539.   }
  540.  
  541.   size_type _M_bkt_num(const value_type& __obj, size_t __n) const
  542.   {
  543.     return _M_bkt_num_key(_M_get_key(__obj), __n);
  544.   }
  545.  
  546.   _Node* _M_new_node(const value_type& __obj)
  547.   {
  548.     _Node* __n = _M_get_node();
  549.     __n->_M_next = 0;
  550.     __STL_TRY {
  551.       construct(&__n->_M_val, __obj);
  552.       return __n;
  553.     }
  554.     __STL_UNWIND(_M_put_node(__n));
  555.   }
  556.   
  557.   void _M_delete_node(_Node* __n)
  558.   {
  559.     destroy(&__n->_M_val);
  560.     _M_put_node(__n);
  561.   }
  562.  
  563.   void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
  564.   void _M_erase_bucket(const size_type __n, _Node* __last);
  565.  
  566.   void _M_copy_from(const hashtable& __ht);
  567.  
  568. };
  569.  
  570. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  571.           class _All>
  572. _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
  573. _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
  574. {
  575.   const _Node* __old = _M_cur;
  576.   _M_cur = _M_cur->_M_next;
  577.   if (!_M_cur) {
  578.     size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
  579.     while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
  580.       _M_cur = _M_ht->_M_buckets[__bucket];
  581.   }
  582.   return *this;
  583. }
  584.  
  585. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  586.           class _All>
  587. inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
  588. _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
  589. {
  590.   iterator __tmp = *this;
  591.   ++*this;
  592.   return __tmp;
  593. }
  594.  
  595. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  596.           class _All>
  597. _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
  598. _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
  599. {
  600.   const _Node* __old = _M_cur;
  601.   _M_cur = _M_cur->_M_next;
  602.   if (!_M_cur) {
  603.     size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
  604.     while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
  605.       _M_cur = _M_ht->_M_buckets[__bucket];
  606.   }
  607.   return *this;
  608. }
  609.  
  610. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  611.           class _All>
  612. inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
  613. _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
  614. {
  615.   const_iterator __tmp = *this;
  616.   ++*this;
  617.   return __tmp;
  618. }
  619.  
  620. #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
  621.  
  622. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  623.           class _All>
  624. inline forward_iterator_tag
  625. iterator_category(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
  626. {
  627.   return forward_iterator_tag();
  628. }
  629.  
  630. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  631.           class _All>
  632. inline _Val* 
  633. value_type(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
  634. {
  635.   return (_Val*) 0;
  636. }
  637.  
  638. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  639.           class _All>
  640. inline hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*
  641. distance_type(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
  642. {
  643.   return (hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*) 0;
  644. }
  645.  
  646. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  647.           class _All>
  648. inline forward_iterator_tag
  649. iterator_category(const _Hashtable_const_iterator<_Val,_Key,_HF,
  650.                                                   _ExK,_EqK,_All>&)
  651. {
  652.   return forward_iterator_tag();
  653. }
  654.  
  655. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  656.           class _All>
  657. inline _Val* 
  658. value_type(const _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
  659. {
  660.   return (_Val*) 0;
  661. }
  662.  
  663. template <class _Val, class _Key, class _HF, class _ExK, class _EqK, 
  664.           class _All>
  665. inline hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*
  666. distance_type(const _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
  667. {
  668.   return (hashtable<_Val,_Key,_HF,_ExK,_EqK,_All>::difference_type*) 0;
  669. }
  670.  
  671. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
  672.  
  673. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  674. bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
  675.                 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
  676. {
  677.   typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
  678.   if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
  679.     return false;
  680.   for (int __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
  681.     _Node* __cur1 = __ht1._M_buckets[__n];
  682.     _Node* __cur2 = __ht2._M_buckets[__n];
  683.     for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
  684.           __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
  685.       {}
  686.     if (__cur1 || __cur2)
  687.       return false;
  688.   }
  689.   return true;
  690. }  
  691.  
  692. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  693.  
  694. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  695. inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
  696.                        const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
  697.   return !(__ht1 == __ht2);
  698. }
  699.  
  700. template <class _Val, class _Key, class _HF, class _Extract, class _EqKey, 
  701.           class _All>
  702. inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
  703.                  hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
  704.   __ht1.swap(__ht2);
  705. }
  706.  
  707. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  708.  
  709.  
  710. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  711. pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool> 
  712. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  713.   ::insert_unique_noresize(const value_type& __obj)
  714. {
  715.   const size_type __n = _M_bkt_num(__obj);
  716.   _Node* __first = _M_buckets[__n];
  717.  
  718.   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 
  719.     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
  720.       return pair<iterator, bool>(iterator(__cur, this), false);
  721.  
  722.   _Node* __tmp = _M_new_node(__obj);
  723.   __tmp->_M_next = __first;
  724.   _M_buckets[__n] = __tmp;
  725.   ++_M_num_elements;
  726.   return pair<iterator, bool>(iterator(__tmp, this), true);
  727. }
  728.  
  729. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  730. typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator 
  731. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  732.   ::insert_equal_noresize(const value_type& __obj)
  733. {
  734.   const size_type __n = _M_bkt_num(__obj);
  735.   _Node* __first = _M_buckets[__n];
  736.  
  737.   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 
  738.     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
  739.       _Node* __tmp = _M_new_node(__obj);
  740.       __tmp->_M_next = __cur->_M_next;
  741.       __cur->_M_next = __tmp;
  742.       ++_M_num_elements;
  743.       return iterator(__tmp, this);
  744.     }
  745.  
  746.   _Node* __tmp = _M_new_node(__obj);
  747.   __tmp->_M_next = __first;
  748.   _M_buckets[__n] = __tmp;
  749.   ++_M_num_elements;
  750.   return iterator(__tmp, this);
  751. }
  752.  
  753. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  754. typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference 
  755. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
  756. {
  757.   resize(_M_num_elements + 1);
  758.  
  759.   size_type __n = _M_bkt_num(__obj);
  760.   _Node* __first = _M_buckets[__n];
  761.  
  762.   for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
  763.     if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
  764.       return __cur->_M_val;
  765.  
  766.   _Node* __tmp = _M_new_node(__obj);
  767.   __tmp->_M_next = __first;
  768.   _M_buckets[__n] = __tmp;
  769.   ++_M_num_elements;
  770.   return __tmp->_M_val;
  771. }
  772.  
  773. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  774. pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
  775.      typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator> 
  776. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
  777. {
  778.   typedef pair<iterator, iterator> _Pii;
  779.   const size_type __n = _M_bkt_num_key(__key);
  780.  
  781.   for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
  782.     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
  783.       for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
  784.         if (!_M_equals(_M_get_key(__cur->_M_val), __key))
  785.           return _Pii(iterator(__first, this), iterator(__cur, this));
  786.       for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
  787.         if (_M_buckets[__m])
  788.           return _Pii(iterator(__first, this),
  789.                      iterator(_M_buckets[__m], this));
  790.       return _Pii(iterator(__first, this), end());
  791.     }
  792.   return _Pii(end(), end());
  793. }
  794.  
  795. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  796. pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator, 
  797.      typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator> 
  798. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  799.   ::equal_range(const key_type& __key) const
  800. {
  801.   typedef pair<const_iterator, const_iterator> _Pii;
  802.   const size_type __n = _M_bkt_num_key(__key);
  803.  
  804.   for (const _Node* __first = _M_buckets[__n] ;
  805.        __first; 
  806.        __first = __first->_M_next) {
  807.     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
  808.       for (const _Node* __cur = __first->_M_next;
  809.            __cur;
  810.            __cur = __cur->_M_next)
  811.         if (!_M_equals(_M_get_key(__cur->_M_val), __key))
  812.           return _Pii(const_iterator(__first, this),
  813.                       const_iterator(__cur, this));
  814.       for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
  815.         if (_M_buckets[__m])
  816.           return _Pii(const_iterator(__first, this),
  817.                       const_iterator(_M_buckets[__m], this));
  818.       return _Pii(const_iterator(__first, this), end());
  819.     }
  820.   }
  821.   return _Pii(end(), end());
  822. }
  823.  
  824. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  825. typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type 
  826. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
  827. {
  828.   const size_type __n = _M_bkt_num_key(__key);
  829.   _Node* __first = _M_buckets[__n];
  830.   size_type __erased = 0;
  831.  
  832.   if (__first) {
  833.     _Node* __cur = __first;
  834.     _Node* __next = __cur->_M_next;
  835.     while (__next) {
  836.       if (_M_equals(_M_get_key(__next->_M_val), __key)) {
  837.         __cur->_M_next = __next->_M_next;
  838.         _M_delete_node(__next);
  839.         __next = __cur->_M_next;
  840.         ++__erased;
  841.         --_M_num_elements;
  842.       }
  843.       else {
  844.         __cur = __next;
  845.         __next = __cur->_M_next;
  846.       }
  847.     }
  848.     if (_M_equals(_M_get_key(__first->_M_val), __key)) {
  849.       _M_buckets[__n] = __first->_M_next;
  850.       _M_delete_node(__first);
  851.       ++__erased;
  852.       --_M_num_elements;
  853.     }
  854.   }
  855.   return __erased;
  856. }
  857.  
  858. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  859. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
  860. {
  861.   _Node* __p = __it._M_cur;
  862.   if (__p) {
  863.     const size_type __n = _M_bkt_num(__p->_M_val);
  864.     _Node* __cur = _M_buckets[__n];
  865.  
  866.     if (__cur == __p) {
  867.       _M_buckets[__n] = __cur->_M_next;
  868.       _M_delete_node(__cur);
  869.       --_M_num_elements;
  870.     }
  871.     else {
  872.       _Node* __next = __cur->_M_next;
  873.       while (__next) {
  874.         if (__next == __p) {
  875.           __cur->_M_next = __next->_M_next;
  876.           _M_delete_node(__next);
  877.           --_M_num_elements;
  878.           break;
  879.         }
  880.         else {
  881.           __cur = __next;
  882.           __next = __cur->_M_next;
  883.         }
  884.       }
  885.     }
  886.   }
  887. }
  888.  
  889. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  890. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  891.   ::erase(iterator __first, iterator __last)
  892. {
  893.   size_type __f_bucket = __first._M_cur ? 
  894.     _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
  895.   size_type __l_bucket = __last._M_cur ? 
  896.     _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
  897.  
  898.   if (__first._M_cur == __last._M_cur)
  899.     return;
  900.   else if (__f_bucket == __l_bucket)
  901.     _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
  902.   else {
  903.     _M_erase_bucket(__f_bucket, __first._M_cur, 0);
  904.     for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
  905.       _M_erase_bucket(__n, 0);
  906.     if (__l_bucket != _M_buckets.size())
  907.       _M_erase_bucket(__l_bucket, __last._M_cur);
  908.   }
  909. }
  910.  
  911. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  912. inline void
  913. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
  914.                                              const_iterator __last)
  915. {
  916.   erase(iterator(const_cast<_Node*>(__first._M_cur),
  917.                  const_cast<hashtable*>(__first._M_ht)),
  918.         iterator(const_cast<_Node*>(__last._M_cur),
  919.                  const_cast<hashtable*>(__last._M_ht)));
  920. }
  921.  
  922. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  923. inline void
  924. hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
  925. {
  926.   erase(iterator(const_cast<_Node*>(__it._M_cur),
  927.                  const_cast<hashtable*>(__it._M_ht)));
  928. }
  929.  
  930. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  931. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  932.   ::resize(size_type __num_elements_hint)
  933. {
  934.   const size_type __old_n = _M_buckets.size();
  935.   if (__num_elements_hint > __old_n) {
  936.     const size_type __n = _M_next_size(__num_elements_hint);
  937.     if (__n > __old_n) {
  938.       vector<_Node*, _All> __tmp(__n, (_Node*)(0),
  939.                                  _M_buckets.get_allocator());
  940.       __STL_TRY {
  941.         for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
  942.           _Node* __first = _M_buckets[__bucket];
  943.           while (__first) {
  944.             size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
  945.             _M_buckets[__bucket] = __first->_M_next;
  946.             __first->_M_next = __tmp[__new_bucket];
  947.             __tmp[__new_bucket] = __first;
  948.             __first = _M_buckets[__bucket];          
  949.           }
  950.         }
  951.         _M_buckets.swap(__tmp);
  952.       }
  953. #         ifdef __STL_USE_EXCEPTIONS
  954.       catch(...) {
  955.         for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
  956.           while (__tmp[__bucket]) {
  957.             _Node* __next = __tmp[__bucket]->_M_next;
  958.             _M_delete_node(__tmp[__bucket]);
  959.             __tmp[__bucket] = __next;
  960.           }
  961.         }
  962.         throw;
  963.       }
  964. #         endif /* __STL_USE_EXCEPTIONS */
  965.     }
  966.   }
  967. }
  968.  
  969. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  970. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  971.   ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
  972. {
  973.   _Node* __cur = _M_buckets[__n];
  974.   if (__cur == __first)
  975.     _M_erase_bucket(__n, __last);
  976.   else {
  977.     _Node* __next;
  978.     for (__next = __cur->_M_next; 
  979.          __next != __first; 
  980.          __cur = __next, __next = __cur->_M_next)
  981.       ;
  982.     while (__next != __last) {
  983.       __cur->_M_next = __next->_M_next;
  984.       _M_delete_node(__next);
  985.       __next = __cur->_M_next;
  986.       --_M_num_elements;
  987.     }
  988.   }
  989. }
  990.  
  991. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  992. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  993.   ::_M_erase_bucket(const size_type __n, _Node* __last)
  994. {
  995.   _Node* __cur = _M_buckets[__n];
  996.   while (__cur != __last) {
  997.     _Node* __next = __cur->_M_next;
  998.     _M_delete_node(__cur);
  999.     __cur = __next;
  1000.     _M_buckets[__n] = __cur;
  1001.     --_M_num_elements;
  1002.   }
  1003. }
  1004.  
  1005. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  1006. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
  1007. {
  1008.   for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
  1009.     _Node* __cur = _M_buckets[__i];
  1010.     while (__cur != 0) {
  1011.       _Node* __next = __cur->_M_next;
  1012.       _M_delete_node(__cur);
  1013.       __cur = __next;
  1014.     }
  1015.     _M_buckets[__i] = 0;
  1016.   }
  1017.   _M_num_elements = 0;
  1018. }
  1019.  
  1020.     
  1021. template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
  1022. void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
  1023.   ::_M_copy_from(const hashtable& __ht)
  1024. {
  1025.   _M_buckets.clear();
  1026.   _M_buckets.reserve(__ht._M_buckets.size());
  1027.   _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
  1028.   __STL_TRY {
  1029.     for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
  1030.       const _Node* __cur = __ht._M_buckets[__i];
  1031.       if (__cur) {
  1032.         _Node* __copy = _M_new_node(__cur->_M_val);
  1033.         _M_buckets[__i] = __copy;
  1034.  
  1035.         for (_Node* __next = __cur->_M_next; 
  1036.              __next; 
  1037.              __cur = __next, __next = __cur->_M_next) {
  1038.           __copy->_M_next = _M_new_node(__next->_M_val);
  1039.           __copy = __copy->_M_next;
  1040.         }
  1041.       }
  1042.     }
  1043.     _M_num_elements = __ht._M_num_elements;
  1044.   }
  1045.   __STL_UNWIND(clear());
  1046. }
  1047.  
  1048. __STL_END_NAMESPACE
  1049.  
  1050. #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
  1051.  
  1052. // Local Variables:
  1053. // mode:C++
  1054. // End:
  1055.