home *** CD-ROM | disk | FTP | other *** search
/ PC World 2000 January / PCWorld_2000-01_cd.bin / Software / Servis / Devc / _SETUP.4 / Group3 / stl_hashtable.h < prev    next >
C/C++ Source or Header  |  1998-03-08  |  27KB  |  949 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 Value>
  50. struct __hashtable_node
  51. {
  52.   __hashtable_node* next;
  53.   Value val;
  54. };  
  55.  
  56. template <class Value, class Key, class HashFcn,
  57.           class ExtractKey, class EqualKey, class Alloc = alloc>
  58. class hashtable;
  59.  
  60. template <class Value, class Key, class HashFcn,
  61.           class ExtractKey, class EqualKey, class Alloc>
  62. struct __hashtable_iterator;
  63.  
  64. template <class Value, class Key, class HashFcn,
  65.           class ExtractKey, class EqualKey, class Alloc>
  66. struct __hashtable_const_iterator;
  67.  
  68. template <class Value, class Key, class HashFcn,
  69.           class ExtractKey, class EqualKey, class Alloc>
  70. struct __hashtable_iterator {
  71.   typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
  72.           hashtable;
  73.   typedef __hashtable_iterator<Value, Key, HashFcn, 
  74.                                ExtractKey, EqualKey, Alloc>
  75.           iterator;
  76.   typedef __hashtable_const_iterator<Value, Key, HashFcn, 
  77.                                      ExtractKey, EqualKey, Alloc>
  78.           const_iterator;
  79.   typedef __hashtable_node<Value> node;
  80.  
  81.   typedef forward_iterator_tag iterator_category;
  82.   typedef Value value_type;
  83.   typedef ptrdiff_t difference_type;
  84.   typedef size_t size_type;
  85.   typedef Value& reference;
  86.   typedef Value* pointer;
  87.  
  88.   node* cur;
  89.   hashtable* ht;
  90.  
  91.   __hashtable_iterator(node* n, hashtable* tab) : cur(n), ht(tab) {}
  92.   __hashtable_iterator() {}
  93.   reference operator*() const { return cur->val; }
  94. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  95.   pointer operator->() const { return &(operator*()); }
  96. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  97.   iterator& operator++();
  98.   iterator operator++(int);
  99.   bool operator==(const iterator& it) const { return cur == it.cur; }
  100.   bool operator!=(const iterator& it) const { return cur != it.cur; }
  101. };
  102.  
  103.  
  104. template <class Value, class Key, class HashFcn,
  105.           class ExtractKey, class EqualKey, class Alloc>
  106. struct __hashtable_const_iterator {
  107.   typedef hashtable<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>
  108.           hashtable;
  109.   typedef __hashtable_iterator<Value, Key, HashFcn, 
  110.                                ExtractKey, EqualKey, Alloc>
  111.           iterator;
  112.   typedef __hashtable_const_iterator<Value, Key, HashFcn, 
  113.                                      ExtractKey, EqualKey, Alloc>
  114.           const_iterator;
  115.   typedef __hashtable_node<Value> node;
  116.  
  117.   typedef forward_iterator_tag iterator_category;
  118.   typedef Value value_type;
  119.   typedef ptrdiff_t difference_type;
  120.   typedef size_t size_type;
  121.   typedef const Value& reference;
  122.   typedef const Value* pointer;
  123.  
  124.   const node* cur;
  125.   const hashtable* ht;
  126.  
  127.   __hashtable_const_iterator(const node* n, const hashtable* tab)
  128.     : cur(n), ht(tab) {}
  129.   __hashtable_const_iterator() {}
  130.   __hashtable_const_iterator(const iterator& it) : cur(it.cur), ht(it.ht) {}
  131.   reference operator*() const { return cur->val; }
  132. #ifndef __SGI_STL_NO_ARROW_OPERATOR
  133.   pointer operator->() const { return &(operator*()); }
  134. #endif /* __SGI_STL_NO_ARROW_OPERATOR */
  135.   const_iterator& operator++();
  136.   const_iterator operator++(int);
  137.   bool operator==(const const_iterator& it) const { return cur == it.cur; }
  138.   bool operator!=(const const_iterator& it) const { return cur != it.cur; }
  139. };
  140.  
  141. // Note: assumes long is at least 32 bits.
  142. static const int __stl_num_primes = 28;
  143. static const unsigned long __stl_prime_list[__stl_num_primes] =
  144. {
  145.   53,         97,         193,       389,       769,
  146.   1543,       3079,       6151,      12289,     24593,
  147.   49157,      98317,      196613,    393241,    786433,
  148.   1572869,    3145739,    6291469,   12582917,  25165843,
  149.   50331653,   100663319,  201326611, 402653189, 805306457, 
  150.   1610612741, 3221225473, 4294967291
  151. };
  152.  
  153. inline unsigned long __stl_next_prime(unsigned long n)
  154. {
  155.   const unsigned long* first = __stl_prime_list;
  156.   const unsigned long* last = __stl_prime_list + __stl_num_primes;
  157.   const unsigned long* pos = lower_bound(first, last, n);
  158.   return pos == last ? *(last - 1) : *pos;
  159. }
  160.  
  161.  
  162. template <class Value, class Key, class HashFcn,
  163.           class ExtractKey, class EqualKey,
  164.           class Alloc>
  165. class hashtable {
  166. public:
  167.   typedef Key key_type;
  168.   typedef Value value_type;
  169.   typedef HashFcn hasher;
  170.   typedef EqualKey key_equal;
  171.  
  172.   typedef size_t            size_type;
  173.   typedef ptrdiff_t         difference_type;
  174.   typedef value_type*       pointer;
  175.   typedef const value_type* const_pointer;
  176.   typedef value_type&       reference;
  177.   typedef const value_type& const_reference;
  178.  
  179.   hasher hash_funct() const { return hash; }
  180.   key_equal key_eq() const { return equals; }
  181.  
  182. private:
  183.   hasher hash;
  184.   key_equal equals;
  185.   ExtractKey get_key;
  186.  
  187.   typedef __hashtable_node<Value> node;
  188.   typedef simple_alloc<node, Alloc> node_allocator;
  189.  
  190.   vector<node*,Alloc> buckets;
  191.   size_type num_elements;
  192.  
  193. public:
  194.   typedef __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, 
  195.                                Alloc>
  196.   iterator;
  197.  
  198.   typedef __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey,
  199.                                      Alloc>
  200.   const_iterator;
  201.  
  202.   friend struct
  203.   __hashtable_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
  204.   friend struct
  205.   __hashtable_const_iterator<Value, Key, HashFcn, ExtractKey, EqualKey, Alloc>;
  206.  
  207. public:
  208.   hashtable(size_type n,
  209.             const HashFcn&    hf,
  210.             const EqualKey&   eql,
  211.             const ExtractKey& ext)
  212.     : hash(hf), equals(eql), get_key(ext), num_elements(0)
  213.   {
  214.     initialize_buckets(n);
  215.   }
  216.  
  217.   hashtable(size_type n,
  218.             const HashFcn&    hf,
  219.             const EqualKey&   eql)
  220.     : hash(hf), equals(eql), get_key(ExtractKey()), num_elements(0)
  221.   {
  222.     initialize_buckets(n);
  223.   }
  224.  
  225.   hashtable(const hashtable& ht)
  226.     : hash(ht.hash), equals(ht.equals), get_key(ht.get_key), num_elements(0)
  227.   {
  228.     copy_from(ht);
  229.   }
  230.  
  231.   hashtable& operator= (const hashtable& ht)
  232.   {
  233.     if (&ht != this) {
  234.       clear();
  235.       hash = ht.hash;
  236.       equals = ht.equals;
  237.       get_key = ht.get_key;
  238.       copy_from(ht);
  239.     }
  240.     return *this;
  241.   }
  242.  
  243.   ~hashtable() { clear(); }
  244.  
  245.   size_type size() const { return num_elements; }
  246.   size_type max_size() const { return size_type(-1); }
  247.   bool empty() const { return size() == 0; }
  248.  
  249.   void swap(hashtable& ht)
  250.   {
  251.     __STD::swap(hash, ht.hash);
  252.     __STD::swap(equals, ht.equals);
  253.     __STD::swap(get_key, ht.get_key);
  254.     buckets.swap(ht.buckets);
  255.     __STD::swap(num_elements, ht.num_elements);
  256.   }
  257.  
  258.   iterator begin()
  259.   { 
  260.     for (size_type n = 0; n < buckets.size(); ++n)
  261.       if (buckets[n])
  262.         return iterator(buckets[n], this);
  263.     return end();
  264.   }
  265.  
  266.   iterator end() { return iterator(0, this); }
  267.  
  268.   const_iterator begin() const
  269.   {
  270.     for (size_type n = 0; n < buckets.size(); ++n)
  271.       if (buckets[n])
  272.         return const_iterator(buckets[n], this);
  273.     return end();
  274.   }
  275.  
  276.   const_iterator end() const { return const_iterator(0, this); }
  277.  
  278.   friend bool
  279.   operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
  280.  
  281. public:
  282.  
  283.   size_type bucket_count() const { return buckets.size(); }
  284.  
  285.   size_type max_bucket_count() const
  286.     { return __stl_prime_list[__stl_num_primes - 1]; } 
  287.  
  288.   size_type elems_in_bucket(size_type bucket) const
  289.   {
  290.     size_type result = 0;
  291.     for (node* cur = buckets[bucket]; cur; cur = cur->next)
  292.       result += 1;
  293.     return result;
  294.   }
  295.  
  296.   pair<iterator, bool> insert_unique(const value_type& obj)
  297.   {
  298.     resize(num_elements + 1);
  299.     return insert_unique_noresize(obj);
  300.   }
  301.  
  302.   iterator insert_equal(const value_type& obj)
  303.   {
  304.     resize(num_elements + 1);
  305.     return insert_equal_noresize(obj);
  306.   }
  307.  
  308.   pair<iterator, bool> insert_unique_noresize(const value_type& obj);
  309.   iterator insert_equal_noresize(const value_type& obj);
  310.  
  311. #ifdef __STL_MEMBER_TEMPLATES
  312.   template <class InputIterator>
  313.   void insert_unique(InputIterator f, InputIterator l)
  314.   {
  315.     insert_unique(f, l, iterator_category(f));
  316.   }
  317.  
  318.   template <class InputIterator>
  319.   void insert_equal(InputIterator f, InputIterator l)
  320.   {
  321.     insert_equal(f, l, iterator_category(f));
  322.   }
  323.  
  324.   template <class InputIterator>
  325.   void insert_unique(InputIterator f, InputIterator l,
  326.                      input_iterator_tag)
  327.   {
  328.     for ( ; f != l; ++f)
  329.       insert_unique(*f);
  330.   }
  331.  
  332.   template <class InputIterator>
  333.   void insert_equal(InputIterator f, InputIterator l,
  334.                     input_iterator_tag)
  335.   {
  336.     for ( ; f != l; ++f)
  337.       insert_equal(*f);
  338.   }
  339.  
  340.   template <class ForwardIterator>
  341.   void insert_unique(ForwardIterator f, ForwardIterator l,
  342.                      forward_iterator_tag)
  343.   {
  344.     size_type n = 0;
  345.     distance(f, l, n);
  346.     resize(num_elements + n);
  347.     for ( ; n > 0; --n, ++f)
  348.       insert_unique_noresize(*f);
  349.   }
  350.  
  351.   template <class ForwardIterator>
  352.   void insert_equal(ForwardIterator f, ForwardIterator l,
  353.                     forward_iterator_tag)
  354.   {
  355.     size_type n = 0;
  356.     distance(f, l, n);
  357.     resize(num_elements + n);
  358.     for ( ; n > 0; --n, ++f)
  359.       insert_equal_noresize(*f);
  360.   }
  361.  
  362. #else /* __STL_MEMBER_TEMPLATES */
  363.   void insert_unique(const value_type* f, const value_type* l)
  364.   {
  365.     size_type n = l - f;
  366.     resize(num_elements + n);
  367.     for ( ; n > 0; --n, ++f)
  368.       insert_unique_noresize(*f);
  369.   }
  370.  
  371.   void insert_equal(const value_type* f, const value_type* l)
  372.   {
  373.     size_type n = l - f;
  374.     resize(num_elements + n);
  375.     for ( ; n > 0; --n, ++f)
  376.       insert_equal_noresize(*f);
  377.   }
  378.  
  379.   void insert_unique(const_iterator f, const_iterator l)
  380.   {
  381.     size_type n = 0;
  382.     distance(f, l, n);
  383.     resize(num_elements + n);
  384.     for ( ; n > 0; --n, ++f)
  385.       insert_unique_noresize(*f);
  386.   }
  387.  
  388.   void insert_equal(const_iterator f, const_iterator l)
  389.   {
  390.     size_type n = 0;
  391.     distance(f, l, n);
  392.     resize(num_elements + n);
  393.     for ( ; n > 0; --n, ++f)
  394.       insert_equal_noresize(*f);
  395.   }
  396. #endif /*__STL_MEMBER_TEMPLATES */
  397.  
  398.   reference find_or_insert(const value_type& obj);
  399.  
  400.   iterator find(const key_type& key) 
  401.   {
  402.     size_type n = bkt_num_key(key);
  403.     node* first;
  404.     for ( first = buckets[n];
  405.           first && !equals(get_key(first->val), key);
  406.           first = first->next)
  407.       {}
  408.     return iterator(first, this);
  409.   } 
  410.  
  411.   const_iterator find(const key_type& key) const
  412.   {
  413.     size_type n = bkt_num_key(key);
  414.     const node* first;
  415.     for ( first = buckets[n];
  416.           first && !equals(get_key(first->val), key);
  417.           first = first->next)
  418.       {}
  419.     return const_iterator(first, this);
  420.   } 
  421.  
  422.   size_type count(const key_type& key) const
  423.   {
  424.     const size_type n = bkt_num_key(key);
  425.     size_type result = 0;
  426.  
  427.     for (const node* cur = buckets[n]; cur; cur = cur->next)
  428.       if (equals(get_key(cur->val), key))
  429.         ++result;
  430.     return result;
  431.   }
  432.  
  433.   pair<iterator, iterator> equal_range(const key_type& key);
  434.   pair<const_iterator, const_iterator> equal_range(const key_type& key) const;
  435.  
  436.   size_type erase(const key_type& key);
  437.   void erase(const iterator& it);
  438.   void erase(iterator first, iterator last);
  439.  
  440.   void erase(const const_iterator& it);
  441.   void erase(const_iterator first, const_iterator last);
  442.  
  443.   void resize(size_type num_elements_hint);
  444.   void clear();
  445.  
  446. private:
  447.   size_type next_size(size_type n) const { return __stl_next_prime(n); }
  448.  
  449.   void initialize_buckets(size_type n)
  450.   {
  451.     const size_type n_buckets = next_size(n);
  452.     buckets.reserve(n_buckets);
  453.     buckets.insert(buckets.end(), n_buckets, (node*) 0);
  454.     num_elements = 0;
  455.   }
  456.  
  457.   size_type bkt_num_key(const key_type& key) const
  458.   {
  459.     return bkt_num_key(key, buckets.size());
  460.   }
  461.  
  462.   size_type bkt_num(const value_type& obj) const
  463.   {
  464.     return bkt_num_key(get_key(obj));
  465.   }
  466.  
  467.   size_type bkt_num_key(const key_type& key, size_t n) const
  468.   {
  469.     return hash(key) % n;
  470.   }
  471.  
  472.   size_type bkt_num(const value_type& obj, size_t n) const
  473.   {
  474.     return bkt_num_key(get_key(obj), n);
  475.   }
  476.  
  477.   node* new_node(const value_type& obj)
  478.   {
  479.     node* n = node_allocator::allocate();
  480.     n->next = 0;
  481.     __STL_TRY {
  482.       construct(&n->val, obj);
  483.       return n;
  484.     }
  485.     __STL_UNWIND(node_allocator::deallocate(n));
  486.   }
  487.   
  488.   void delete_node(node* n)
  489.   {
  490.     destroy(&n->val);
  491.     node_allocator::deallocate(n);
  492.   }
  493.  
  494.   void erase_bucket(const size_type n, node* first, node* last);
  495.   void erase_bucket(const size_type n, node* last);
  496.  
  497.   void copy_from(const hashtable& ht);
  498.  
  499. };
  500.  
  501. template <class V, class K, class HF, class ExK, class EqK, class A>
  502. __hashtable_iterator<V, K, HF, ExK, EqK, A>&
  503. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++()
  504. {
  505.   const node* old = cur;
  506.   cur = cur->next;
  507.   if (!cur) {
  508.     size_type bucket = ht->bkt_num(old->val);
  509.     while (!cur && ++bucket < ht->buckets.size())
  510.       cur = ht->buckets[bucket];
  511.   }
  512.   return *this;
  513. }
  514.  
  515. template <class V, class K, class HF, class ExK, class EqK, class A>
  516. inline __hashtable_iterator<V, K, HF, ExK, EqK, A>
  517. __hashtable_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
  518. {
  519.   iterator tmp = *this;
  520.   ++*this;
  521.   return tmp;
  522. }
  523.  
  524. template <class V, class K, class HF, class ExK, class EqK, class A>
  525. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>&
  526. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++()
  527. {
  528.   const node* old = cur;
  529.   cur = cur->next;
  530.   if (!cur) {
  531.     size_type bucket = ht->bkt_num(old->val);
  532.     while (!cur && ++bucket < ht->buckets.size())
  533.       cur = ht->buckets[bucket];
  534.   }
  535.   return *this;
  536. }
  537.  
  538. template <class V, class K, class HF, class ExK, class EqK, class A>
  539. inline __hashtable_const_iterator<V, K, HF, ExK, EqK, A>
  540. __hashtable_const_iterator<V, K, HF, ExK, EqK, A>::operator++(int)
  541. {
  542.   const_iterator tmp = *this;
  543.   ++*this;
  544.   return tmp;
  545. }
  546.  
  547. #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
  548.  
  549. template <class V, class K, class HF, class ExK, class EqK, class All>
  550. inline forward_iterator_tag
  551. iterator_category(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  552. {
  553.   return forward_iterator_tag();
  554. }
  555.  
  556. template <class V, class K, class HF, class ExK, class EqK, class All>
  557. inline V* value_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  558. {
  559.   return (V*) 0;
  560. }
  561.  
  562. template <class V, class K, class HF, class ExK, class EqK, class All>
  563. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
  564. distance_type(const __hashtable_iterator<V, K, HF, ExK, EqK, All>&)
  565. {
  566.   return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
  567. }
  568.  
  569. template <class V, class K, class HF, class ExK, class EqK, class All>
  570. inline forward_iterator_tag
  571. iterator_category(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  572. {
  573.   return forward_iterator_tag();
  574. }
  575.  
  576. template <class V, class K, class HF, class ExK, class EqK, class All>
  577. inline V* 
  578. value_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  579. {
  580.   return (V*) 0;
  581. }
  582.  
  583. template <class V, class K, class HF, class ExK, class EqK, class All>
  584. inline hashtable<V, K, HF, ExK, EqK, All>::difference_type*
  585. distance_type(const __hashtable_const_iterator<V, K, HF, ExK, EqK, All>&)
  586. {
  587.   return (hashtable<V, K, HF, ExK, EqK, All>::difference_type*) 0;
  588. }
  589.  
  590. #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
  591.  
  592. template <class V, class K, class HF, class Ex, class Eq, class A>
  593. bool operator==(const hashtable<V, K, HF, Ex, Eq, A>& ht1,
  594.                 const hashtable<V, K, HF, Ex, Eq, A>& ht2)
  595. {
  596.   typedef typename hashtable<V, K, HF, Ex, Eq, A>::node node;
  597.   if (ht1.buckets.size() != ht2.buckets.size())
  598.     return false;
  599.   for (int n = 0; n < ht1.buckets.size(); ++n) {
  600.     node* cur1 = ht1.buckets[n];
  601.     node* cur2 = ht2.buckets[n];
  602.     for ( ; cur1 && cur2 && cur1->val == cur2->val;
  603.           cur1 = cur1->next, cur2 = cur2->next)
  604.       {}
  605.     if (cur1 || cur2)
  606.       return false;
  607.   }
  608.   return true;
  609. }  
  610.  
  611. #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
  612.  
  613. template <class Val, class Key, class HF, class Extract, class EqKey, class A>
  614. inline void swap(hashtable<Val, Key, HF, Extract, EqKey, A>& ht1,
  615.                  hashtable<Val, Key, HF, Extract, EqKey, A>& ht2) {
  616.   ht1.swap(ht2);
  617. }
  618.  
  619. #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
  620.  
  621.  
  622. template <class V, class K, class HF, class Ex, class Eq, class A>
  623. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator, bool> 
  624. hashtable<V, K, HF, Ex, Eq, A>::insert_unique_noresize(const value_type& obj)
  625. {
  626.   const size_type n = bkt_num(obj);
  627.   node* first = buckets[n];
  628.  
  629.   for (node* cur = first; cur; cur = cur->next) 
  630.     if (equals(get_key(cur->val), get_key(obj)))
  631.       return pair<iterator, bool>(iterator(cur, this), false);
  632.  
  633.   node* tmp = new_node(obj);
  634.   tmp->next = first;
  635.   buckets[n] = tmp;
  636.   ++num_elements;
  637.   return pair<iterator, bool>(iterator(tmp, this), true);
  638. }
  639.  
  640. template <class V, class K, class HF, class Ex, class Eq, class A>
  641. typename hashtable<V, K, HF, Ex, Eq, A>::iterator 
  642. hashtable<V, K, HF, Ex, Eq, A>::insert_equal_noresize(const value_type& obj)
  643. {
  644.   const size_type n = bkt_num(obj);
  645.   node* first = buckets[n];
  646.  
  647.   for (node* cur = first; cur; cur = cur->next) 
  648.     if (equals(get_key(cur->val), get_key(obj))) {
  649.       node* tmp = new_node(obj);
  650.       tmp->next = cur->next;
  651.       cur->next = tmp;
  652.       ++num_elements;
  653.       return iterator(tmp, this);
  654.     }
  655.  
  656.   node* tmp = new_node(obj);
  657.   tmp->next = first;
  658.   buckets[n] = tmp;
  659.   ++num_elements;
  660.   return iterator(tmp, this);
  661. }
  662.  
  663. template <class V, class K, class HF, class Ex, class Eq, class A>
  664. typename hashtable<V, K, HF, Ex, Eq, A>::reference 
  665. hashtable<V, K, HF, Ex, Eq, A>::find_or_insert(const value_type& obj)
  666. {
  667.   resize(num_elements + 1);
  668.  
  669.   size_type n = bkt_num(obj);
  670.   node* first = buckets[n];
  671.  
  672.   for (node* cur = first; cur; cur = cur->next)
  673.     if (equals(get_key(cur->val), get_key(obj)))
  674.       return cur->val;
  675.  
  676.   node* tmp = new_node(obj);
  677.   tmp->next = first;
  678.   buckets[n] = tmp;
  679.   ++num_elements;
  680.   return tmp->val;
  681. }
  682.  
  683. template <class V, class K, class HF, class Ex, class Eq, class A>
  684. pair<typename hashtable<V, K, HF, Ex, Eq, A>::iterator,
  685.      typename hashtable<V, K, HF, Ex, Eq, A>::iterator> 
  686. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key)
  687. {
  688.   typedef pair<iterator, iterator> pii;
  689.   const size_type n = bkt_num_key(key);
  690.  
  691.   for (node* first = buckets[n]; first; first = first->next) {
  692.     if (equals(get_key(first->val), key)) {
  693.       for (node* cur = first->next; cur; cur = cur->next)
  694.         if (!equals(get_key(cur->val), key))
  695.           return pii(iterator(first, this), iterator(cur, this));
  696.       for (size_type m = n + 1; m < buckets.size(); ++m)
  697.         if (buckets[m])
  698.           return pii(iterator(first, this),
  699.                      iterator(buckets[m], this));
  700.       return pii(iterator(first, this), end());
  701.     }
  702.   }
  703.   return pii(end(), end());
  704. }
  705.  
  706. template <class V, class K, class HF, class Ex, class Eq, class A>
  707. pair<typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator, 
  708.      typename hashtable<V, K, HF, Ex, Eq, A>::const_iterator> 
  709. hashtable<V, K, HF, Ex, Eq, A>::equal_range(const key_type& key) const
  710. {
  711.   typedef pair<const_iterator, const_iterator> pii;
  712.   const size_type n = bkt_num_key(key);
  713.  
  714.   for (const node* first = buckets[n] ; first; first = first->next) {
  715.     if (equals(get_key(first->val), key)) {
  716.       for (const node* cur = first->next; cur; cur = cur->next)
  717.         if (!equals(get_key(cur->val), key))
  718.           return pii(const_iterator(first, this),
  719.                      const_iterator(cur, this));
  720.       for (size_type m = n + 1; m < buckets.size(); ++m)
  721.         if (buckets[m])
  722.           return pii(const_iterator(first, this),
  723.                      const_iterator(buckets[m], this));
  724.       return pii(const_iterator(first, this), end());
  725.     }
  726.   }
  727.   return pii(end(), end());
  728. }
  729.  
  730. template <class V, class K, class HF, class Ex, class Eq, class A>
  731. typename hashtable<V, K, HF, Ex, Eq, A>::size_type 
  732. hashtable<V, K, HF, Ex, Eq, A>::erase(const key_type& key)
  733. {
  734.   const size_type n = bkt_num_key(key);
  735.   node* first = buckets[n];
  736.   size_type erased = 0;
  737.  
  738.   if (first) {
  739.     node* cur = first;
  740.     node* next = cur->next;
  741.     while (next) {
  742.       if (equals(get_key(next->val), key)) {
  743.         cur->next = next->next;
  744.         delete_node(next);
  745.         next = cur->next;
  746.         ++erased;
  747.         --num_elements;
  748.       }
  749.       else {
  750.         cur = next;
  751.         next = cur->next;
  752.       }
  753.     }
  754.     if (equals(get_key(first->val), key)) {
  755.       buckets[n] = first->next;
  756.       delete_node(first);
  757.       ++erased;
  758.       --num_elements;
  759.     }
  760.   }
  761.   return erased;
  762. }
  763.  
  764. template <class V, class K, class HF, class Ex, class Eq, class A>
  765. void hashtable<V, K, HF, Ex, Eq, A>::erase(const iterator& it)
  766. {
  767.   if (node* const p = it.cur) {
  768.     const size_type n = bkt_num(p->val);
  769.     node* cur = buckets[n];
  770.  
  771.     if (cur == p) {
  772.       buckets[n] = cur->next;
  773.       delete_node(cur);
  774.       --num_elements;
  775.     }
  776.     else {
  777.       node* next = cur->next;
  778.       while (next) {
  779.         if (next == p) {
  780.           cur->next = next->next;
  781.           delete_node(next);
  782.           --num_elements;
  783.           break;
  784.         }
  785.         else {
  786.           cur = next;
  787.           next = cur->next;
  788.         }
  789.       }
  790.     }
  791.   }
  792. }
  793.  
  794. template <class V, class K, class HF, class Ex, class Eq, class A>
  795. void hashtable<V, K, HF, Ex, Eq, A>::erase(iterator first, iterator last)
  796. {
  797.   size_type f_bucket = first.cur ? bkt_num(first.cur->val) : buckets.size();
  798.   size_type l_bucket = last.cur ? bkt_num(last.cur->val) : buckets.size();
  799.  
  800.   if (first.cur == last.cur)
  801.     return;
  802.   else if (f_bucket == l_bucket)
  803.     erase_bucket(f_bucket, first.cur, last.cur);
  804.   else {
  805.     erase_bucket(f_bucket, first.cur, 0);
  806.     for (size_type n = f_bucket + 1; n < l_bucket; ++n)
  807.       erase_bucket(n, 0);
  808.     if (l_bucket != buckets.size())
  809.       erase_bucket(l_bucket, last.cur);
  810.   }
  811. }
  812.  
  813. template <class V, class K, class HF, class Ex, class Eq, class A>
  814. inline void
  815. hashtable<V, K, HF, Ex, Eq, A>::erase(const_iterator first,
  816.                                       const_iterator last)
  817. {
  818.   erase(iterator(const_cast<node*>(first.cur),
  819.                  const_cast<hashtable*>(first.ht)),
  820.         iterator(const_cast<node*>(last.cur),
  821.                  const_cast<hashtable*>(last.ht)));
  822. }
  823.  
  824. template <class V, class K, class HF, class Ex, class Eq, class A>
  825. inline void
  826. hashtable<V, K, HF, Ex, Eq, A>::erase(const const_iterator& it)
  827. {
  828.   erase(iterator(const_cast<node*>(it.cur),
  829.                  const_cast<hashtable*>(it.ht)));
  830. }
  831.  
  832. template <class V, class K, class HF, class Ex, class Eq, class A>
  833. void hashtable<V, K, HF, Ex, Eq, A>::resize(size_type num_elements_hint)
  834. {
  835.   const size_type old_n = buckets.size();
  836.   if (num_elements_hint > old_n) {
  837.     const size_type n = next_size(num_elements_hint);
  838.     if (n > old_n) {
  839.       vector<node*, A> tmp(n, (node*) 0);
  840.       __STL_TRY {
  841.         for (size_type bucket = 0; bucket < old_n; ++bucket) {
  842.           node* first = buckets[bucket];
  843.           while (first) {
  844.             size_type new_bucket = bkt_num(first->val, n);
  845.             buckets[bucket] = first->next;
  846.             first->next = tmp[new_bucket];
  847.             tmp[new_bucket] = first;
  848.             first = buckets[bucket];          
  849.           }
  850.         }
  851.         buckets.swap(tmp);
  852.       }
  853. #         ifdef __STL_USE_EXCEPTIONS
  854.       catch(...) {
  855.         for (size_type bucket = 0; bucket < tmp.size(); ++bucket) {
  856.           while (tmp[bucket]) {
  857.             node* next = tmp[bucket]->next;
  858.             delete_node(tmp[bucket]);
  859.             tmp[bucket] = next;
  860.           }
  861.         }
  862.         throw;
  863.       }
  864. #         endif /* __STL_USE_EXCEPTIONS */
  865.     }
  866.   }
  867. }
  868.  
  869. template <class V, class K, class HF, class Ex, class Eq, class A>
  870. void hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, 
  871.                                                   node* first, node* last)
  872. {
  873.   node* cur = buckets[n];
  874.   if (cur == first)
  875.     erase_bucket(n, last);
  876.   else {
  877.     node* next;
  878.     for (next = cur->next; next != first; cur = next, next = cur->next)
  879.       ;
  880.     while (next) {
  881.       cur->next = next->next;
  882.       delete_node(next);
  883.       next = cur->next;
  884.       --num_elements;
  885.     }
  886.   }
  887. }
  888.  
  889. template <class V, class K, class HF, class Ex, class Eq, class A>
  890. void 
  891. hashtable<V, K, HF, Ex, Eq, A>::erase_bucket(const size_type n, node* last)
  892. {
  893.   node* cur = buckets[n];
  894.   while (cur != last) {
  895.     node* next = cur->next;
  896.     delete_node(cur);
  897.     cur = next;
  898.     buckets[n] = cur;
  899.     --num_elements;
  900.   }
  901. }
  902.  
  903. template <class V, class K, class HF, class Ex, class Eq, class A>
  904. void hashtable<V, K, HF, Ex, Eq, A>::clear()
  905. {
  906.   for (size_type i = 0; i < buckets.size(); ++i) {
  907.     node* cur = buckets[i];
  908.     while (cur != 0) {
  909.       node* next = cur->next;
  910.       delete_node(cur);
  911.       cur = next;
  912.     }
  913.     buckets[i] = 0;
  914.   }
  915.   num_elements = 0;
  916. }
  917.  
  918.     
  919. template <class V, class K, class HF, class Ex, class Eq, class A>
  920. void hashtable<V, K, HF, Ex, Eq, A>::copy_from(const hashtable& ht)
  921. {
  922.   buckets.clear();
  923.   buckets.reserve(ht.buckets.size());
  924.   buckets.insert(buckets.end(), ht.buckets.size(), (node*) 0);
  925.   __STL_TRY {
  926.     for (size_type i = 0; i < ht.buckets.size(); ++i) {
  927.       if (const node* cur = ht.buckets[i]) {
  928.         node* copy = new_node(cur->val);
  929.         buckets[i] = copy;
  930.  
  931.         for (node* next = cur->next; next; cur = next, next = cur->next) {
  932.           copy->next = new_node(next->val);
  933.           copy = copy->next;
  934.         }
  935.       }
  936.     }
  937.     num_elements = ht.num_elements;
  938.   }
  939.   __STL_UNWIND(clear());
  940. }
  941.  
  942. __STL_END_NAMESPACE
  943.  
  944. #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
  945.  
  946. // Local Variables:
  947. // mode:C++
  948. // End:
  949.