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