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