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