xref: /dragonfly/contrib/gcc-8.0/libstdc++-v3/include/backward/hashtable.h (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
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 
_GLIBCXX_VISIBILITY(default)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