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