home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 14 / hacker14.iso / programacao / cwin / c.exe / $INSTDIR / include / c++ / ext / stl_hashtable.h < prev    next >
Encoding:
C/C++ Source or Header  |  2003-12-15  |  31.0 KB  |  1,000 lines

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