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