1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
4 // Free Software Foundation, Inc.
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 2, or (at your option)
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.
17 // You should have received a copy of the GNU General Public License along
18 // with this library; see the file COPYING. If not, write to the Free
19 // Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
22 // As a special exception, you may use this file as part of a free software
23 // library without restriction. Specifically, if other files instantiate
24 // templates or use macros or inline functions from this file, or you compile
25 // this file and link it with other files to produce an executable, this
26 // file does not by itself cause the resulting executable to be covered by
27 // the GNU General Public License. This exception does not however
28 // invalidate any other reasons why the executable file might be covered by
29 // the GNU General Public License.
32 * Copyright (c) 1996,1997
33 * Silicon Graphics Computer Systems, Inc.
35 * Permission to use, copy, modify, distribute and sell this software
36 * and its documentation for any purpose is hereby granted without fee,
37 * provided that the above copyright notice appear in all copies and
38 * that both that copyright notice and this permission notice appear
39 * in supporting documentation. Silicon Graphics makes no
40 * representations about the suitability of this software for any
41 * purpose. It is provided "as is" without express or implied warranty.
45 * Hewlett-Packard Company
47 * Permission to use, copy, modify, distribute and sell this software
48 * and its documentation for any purpose is hereby granted without fee,
49 * provided that the above copyright notice appear in all copies and
50 * that both that copyright notice and this permission notice appear
51 * in supporting documentation. Hewlett-Packard Company makes no
52 * representations about the suitability of this software for any
53 * purpose. It is provided "as is" without express or implied warranty.
57 /** @file profile/hashtable.h copied from backward/hashtable.h
58 * This file is a GNU extension to the Standard C++ Library (possibly
59 * containing extensions from the HP/SGI STL subset).
63 #define _HASHTABLE_H 1
65 // Hashtable class, used to implement the hashed associative containers
66 // hash_set, hash_map, hash_multiset, and hash_multimap.
67 // Skip instrumentation on vector.
71 #include <bits/stl_function.h>
72 #include <backward/hash_fun.h>
73 #include <profile/base.h>
75 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx)
79 using std::forward_iterator_tag;
80 using std::input_iterator_tag;
81 using std::_Construct;
84 using std::_GLIBCXX_STD_D::vector;
86 using std::__iterator_category;
89 struct _Hashtable_node
91 _Hashtable_node* _M_next;
95 template<class _Val, class _Key, class _HashFcn, class _ExtractKey,
96 class _EqualKey, class _Alloc = std::allocator<_Val> >
99 template<class _Val, class _Key, class _HashFcn,
100 class _ExtractKey, class _EqualKey, class _Alloc>
101 struct _Hashtable_iterator;
103 template<class _Val, class _Key, class _HashFcn,
104 class _ExtractKey, class _EqualKey, class _Alloc>
105 struct _Hashtable_const_iterator;
107 template<class _Val, class _Key, class _HashFcn,
108 class _ExtractKey, class _EqualKey, class _Alloc>
109 struct _Hashtable_iterator
111 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
113 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
114 _ExtractKey, _EqualKey, _Alloc>
116 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
117 _ExtractKey, _EqualKey, _Alloc>
119 typedef _Hashtable_node<_Val> _Node;
120 typedef forward_iterator_tag iterator_category;
121 typedef _Val value_type;
122 typedef ptrdiff_t difference_type;
123 typedef size_t size_type;
124 typedef _Val& reference;
125 typedef _Val* pointer;
130 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
131 : _M_cur(__n), _M_ht(__tab) { }
133 _Hashtable_iterator() { }
137 { return _M_cur->_M_val; }
141 { return &(operator*()); }
150 operator==(const iterator& __it) const
151 { return _M_cur == __it._M_cur; }
154 operator!=(const iterator& __it) const
155 { return _M_cur != __it._M_cur; }
158 template<class _Val, class _Key, class _HashFcn,
159 class _ExtractKey, class _EqualKey, class _Alloc>
160 struct _Hashtable_const_iterator
162 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
164 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
165 _ExtractKey,_EqualKey,_Alloc>
167 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
168 _ExtractKey, _EqualKey, _Alloc>
170 typedef _Hashtable_node<_Val> _Node;
172 typedef forward_iterator_tag iterator_category;
173 typedef _Val value_type;
174 typedef ptrdiff_t difference_type;
175 typedef size_t size_type;
176 typedef const _Val& reference;
177 typedef const _Val* pointer;
180 const _Hashtable* _M_ht;
182 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
183 : _M_cur(__n), _M_ht(__tab) { }
185 _Hashtable_const_iterator() { }
187 _Hashtable_const_iterator(const iterator& __it)
188 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { }
192 { return _M_cur->_M_val; }
196 { return &(operator*()); }
205 operator==(const const_iterator& __it) const
206 { return _M_cur == __it._M_cur; }
209 operator!=(const const_iterator& __it) const
210 { return _M_cur != __it._M_cur; }
213 // Note: assumes long is at least 32 bits.
214 enum { _S_num_primes = 28 };
216 static const unsigned long __stl_prime_list[_S_num_primes] =
218 53ul, 97ul, 193ul, 389ul, 769ul,
219 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
220 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
221 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
222 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
223 1610612741ul, 3221225473ul, 4294967291ul
227 __stl_next_prime(unsigned long __n)
229 const unsigned long* __first = __stl_prime_list;
230 const unsigned long* __last = __stl_prime_list + (int)_S_num_primes;
231 const unsigned long* pos = std::lower_bound(__first, __last, __n);
232 return pos == __last ? *(__last - 1) : *pos;
235 // Forward declaration of operator==.
236 template<class _Val, class _Key, class _HF, class _Ex,
237 class _Eq, class _All>
240 template<class _Val, class _Key, class _HF, class _Ex,
241 class _Eq, class _All>
243 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
244 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
246 // Hashtables handle allocators a bit differently than other
247 // containers do. If we're using standard-conforming allocators, then
248 // a hashtable unconditionally has a member variable to hold its
249 // allocator, even if it so happens that all instances of the
250 // allocator type are identical. This is because, for hashtables,
251 // this extra storage is negligible. Additionally, a base class
252 // wouldn't serve any other purposes; it wouldn't, for example,
253 // simplify the exception-handling code.
254 template<class _Val, class _Key, class _HashFcn,
255 class _ExtractKey, class _EqualKey, class _Alloc>
259 typedef _Key key_type;
260 typedef _Val value_type;
261 typedef _HashFcn hasher;
262 typedef _EqualKey key_equal;
264 typedef size_t size_type;
265 typedef ptrdiff_t difference_type;
266 typedef value_type* pointer;
267 typedef const value_type* const_pointer;
268 typedef value_type& reference;
269 typedef const value_type& const_reference;
277 { return _M_equals; }
280 typedef _Hashtable_node<_Val> _Node;
283 typedef typename _Alloc::template rebind<value_type>::other allocator_type;
285 get_allocator() const
286 { return _M_node_allocator; }
289 typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc;
290 typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc;
291 typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type;
293 _Node_Alloc _M_node_allocator;
297 { return _M_node_allocator.allocate(1); }
300 _M_put_node(_Node* __p)
301 { _M_node_allocator.deallocate(__p, 1); }
306 _ExtractKey _M_get_key;
307 _Vector_type _M_buckets;
308 size_type _M_num_elements;
311 typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
314 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
319 _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>;
322 _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
326 hashtable(size_type __n, const _HashFcn& __hf,
327 const _EqualKey& __eql, const _ExtractKey& __ext,
328 const allocator_type& __a = allocator_type())
329 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
330 _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0)
331 { _M_initialize_buckets(__n); }
333 hashtable(size_type __n, const _HashFcn& __hf,
334 const _EqualKey& __eql,
335 const allocator_type& __a = allocator_type())
336 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
337 _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0)
338 { _M_initialize_buckets(__n); }
340 hashtable(const hashtable& __ht)
341 : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash),
342 _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key),
343 _M_buckets(__ht.get_allocator()), _M_num_elements(0)
344 { _M_copy_from(__ht); }
347 operator= (const hashtable& __ht)
352 _M_hash = __ht._M_hash;
353 _M_equals = __ht._M_equals;
354 _M_get_key = __ht._M_get_key;
365 { return _M_num_elements; }
369 { return size_type(-1); }
373 { return size() == 0; }
376 swap(hashtable& __ht)
378 std::swap(_M_hash, __ht._M_hash);
379 std::swap(_M_equals, __ht._M_equals);
380 std::swap(_M_get_key, __ht._M_get_key);
381 _M_buckets.swap(__ht._M_buckets);
382 std::swap(_M_num_elements, __ht._M_num_elements);
388 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
390 return iterator(_M_buckets[__n], this);
396 { return iterator(0, this); }
401 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
403 return const_iterator(_M_buckets[__n], this);
409 { return const_iterator(0, this); }
411 template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq,
414 operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
415 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
420 { return _M_buckets.size(); }
423 max_bucket_count() const
424 { return __stl_prime_list[(int)_S_num_primes - 1]; }
427 elems_in_bucket(size_type __bucket) const
429 size_type __result = 0;
430 for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next)
436 insert_unique(const value_type& __obj)
438 resize(_M_num_elements + 1);
439 return insert_unique_noresize(__obj);
443 insert_equal(const value_type& __obj)
445 resize(_M_num_elements + 1);
446 return insert_equal_noresize(__obj);
450 insert_unique_noresize(const value_type& __obj);
453 insert_equal_noresize(const value_type& __obj);
455 template<class _InputIterator>
457 insert_unique(_InputIterator __f, _InputIterator __l)
458 { insert_unique(__f, __l, __iterator_category(__f)); }
460 template<class _InputIterator>
462 insert_equal(_InputIterator __f, _InputIterator __l)
463 { insert_equal(__f, __l, __iterator_category(__f)); }
465 template<class _InputIterator>
467 insert_unique(_InputIterator __f, _InputIterator __l,
470 for ( ; __f != __l; ++__f)
474 template<class _InputIterator>
476 insert_equal(_InputIterator __f, _InputIterator __l,
479 for ( ; __f != __l; ++__f)
483 template<class _ForwardIterator>
485 insert_unique(_ForwardIterator __f, _ForwardIterator __l,
486 forward_iterator_tag)
488 size_type __n = distance(__f, __l);
489 resize(_M_num_elements + __n);
490 for ( ; __n > 0; --__n, ++__f)
491 insert_unique_noresize(*__f);
494 template<class _ForwardIterator>
496 insert_equal(_ForwardIterator __f, _ForwardIterator __l,
497 forward_iterator_tag)
499 size_type __n = distance(__f, __l);
500 resize(_M_num_elements + __n);
501 for ( ; __n > 0; --__n, ++__f)
502 insert_equal_noresize(*__f);
506 find_or_insert(const value_type& __obj);
509 find(const key_type& __key)
511 size_type __n = _M_bkt_num_key(__key);
513 for (__first = _M_buckets[__n];
514 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
515 __first = __first->_M_next)
517 return iterator(__first, this);
521 find(const key_type& __key) const
523 size_type __n = _M_bkt_num_key(__key);
524 const _Node* __first;
525 for (__first = _M_buckets[__n];
526 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
527 __first = __first->_M_next)
529 return const_iterator(__first, this);
533 count(const key_type& __key) const
535 const size_type __n = _M_bkt_num_key(__key);
536 size_type __result = 0;
538 for (const _Node* __cur = _M_buckets[__n]; __cur;
539 __cur = __cur->_M_next)
540 if (_M_equals(_M_get_key(__cur->_M_val), __key))
545 pair<iterator, iterator>
546 equal_range(const key_type& __key);
548 pair<const_iterator, const_iterator>
549 equal_range(const key_type& __key) const;
552 erase(const key_type& __key);
555 erase(const iterator& __it);
558 erase(iterator __first, iterator __last);
561 erase(const const_iterator& __it);
564 erase(const_iterator __first, const_iterator __last);
567 resize(size_type __num_elements_hint);
574 _M_next_size(size_type __n) const
575 { return __stl_next_prime(__n); }
578 _M_initialize_buckets(size_type __n)
580 const size_type __n_buckets = _M_next_size(__n);
581 _M_buckets.reserve(__n_buckets);
582 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
584 __profcxx_hashtable_construct(this, __n_buckets);
585 __profcxx_hashtable_construct2(this);
589 _M_bkt_num_key(const key_type& __key) const
590 { return _M_bkt_num_key(__key, _M_buckets.size()); }
593 _M_bkt_num(const value_type& __obj) const
594 { return _M_bkt_num_key(_M_get_key(__obj)); }
597 _M_bkt_num_key(const key_type& __key, size_t __n) const
598 { return _M_hash(__key) % __n; }
601 _M_bkt_num(const value_type& __obj, size_t __n) const
602 { return _M_bkt_num_key(_M_get_key(__obj), __n); }
605 _M_new_node(const value_type& __obj)
607 _Node* __n = _M_get_node();
611 this->get_allocator().construct(&__n->_M_val, __obj);
617 __throw_exception_again;
622 _M_delete_node(_Node* __n)
624 this->get_allocator().destroy(&__n->_M_val);
629 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
632 _M_erase_bucket(const size_type __n, _Node* __last);
635 _M_copy_from(const hashtable& __ht);
638 template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
640 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
641 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
644 const _Node* __old = _M_cur;
645 _M_cur = _M_cur->_M_next;
648 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
649 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
650 _M_cur = _M_ht->_M_buckets[__bucket];
655 template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
657 inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
658 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
661 iterator __tmp = *this;
666 template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
668 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
669 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
672 const _Node* __old = _M_cur;
673 _M_cur = _M_cur->_M_next;
676 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
677 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
678 _M_cur = _M_ht->_M_buckets[__bucket];
683 template<class _Val, class _Key, class _HF, class _ExK, class _EqK,
685 inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
686 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
689 const_iterator __tmp = *this;
694 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
696 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
697 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
699 typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
701 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
704 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n)
706 _Node* __cur1 = __ht1._M_buckets[__n];
707 _Node* __cur2 = __ht2._M_buckets[__n];
708 // Check same length of lists
709 for (; __cur1 && __cur2;
710 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
712 if (__cur1 || __cur2)
714 // Now check one's elements are in the other
715 for (__cur1 = __ht1._M_buckets[__n] ; __cur1;
716 __cur1 = __cur1->_M_next)
718 bool _found__cur1 = false;
719 for (__cur2 = __ht2._M_buckets[__n];
720 __cur2; __cur2 = __cur2->_M_next)
722 if (__cur1->_M_val == __cur2->_M_val)
735 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
737 operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
738 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
739 { return !(__ht1 == __ht2); }
741 template<class _Val, class _Key, class _HF, class _Extract, class _EqKey,
744 swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
745 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
746 { __ht1.swap(__ht2); }
748 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
749 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
750 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
751 insert_unique_noresize(const value_type& __obj)
753 const size_type __n = _M_bkt_num(__obj);
754 _Node* __first = _M_buckets[__n];
756 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
757 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
758 return pair<iterator, bool>(iterator(__cur, this), false);
760 _Node* __tmp = _M_new_node(__obj);
761 __tmp->_M_next = __first;
762 _M_buckets[__n] = __tmp;
764 return pair<iterator, bool>(iterator(__tmp, this), true);
767 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
768 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
769 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
770 insert_equal_noresize(const value_type& __obj)
772 const size_type __n = _M_bkt_num(__obj);
773 _Node* __first = _M_buckets[__n];
775 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
776 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
778 _Node* __tmp = _M_new_node(__obj);
779 __tmp->_M_next = __cur->_M_next;
780 __cur->_M_next = __tmp;
782 return iterator(__tmp, this);
785 _Node* __tmp = _M_new_node(__obj);
786 __tmp->_M_next = __first;
787 _M_buckets[__n] = __tmp;
789 return iterator(__tmp, this);
792 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
793 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
794 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
795 find_or_insert(const value_type& __obj)
797 resize(_M_num_elements + 1);
799 size_type __n = _M_bkt_num(__obj);
800 _Node* __first = _M_buckets[__n];
802 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
803 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
804 return __cur->_M_val;
806 _Node* __tmp = _M_new_node(__obj);
807 __tmp->_M_next = __first;
808 _M_buckets[__n] = __tmp;
810 return __tmp->_M_val;
813 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
814 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
815 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
816 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
817 equal_range(const key_type& __key)
819 typedef pair<iterator, iterator> _Pii;
820 const size_type __n = _M_bkt_num_key(__key);
822 for (_Node* __first = _M_buckets[__n]; __first;
823 __first = __first->_M_next)
824 if (_M_equals(_M_get_key(__first->_M_val), __key))
826 for (_Node* __cur = __first->_M_next; __cur;
827 __cur = __cur->_M_next)
828 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
829 return _Pii(iterator(__first, this), iterator(__cur, this));
830 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
832 return _Pii(iterator(__first, this),
833 iterator(_M_buckets[__m], this));
834 return _Pii(iterator(__first, this), end());
836 return _Pii(end(), end());
839 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
840 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
841 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
842 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
843 equal_range(const key_type& __key) const
845 typedef pair<const_iterator, const_iterator> _Pii;
846 const size_type __n = _M_bkt_num_key(__key);
848 for (const _Node* __first = _M_buckets[__n]; __first;
849 __first = __first->_M_next)
851 if (_M_equals(_M_get_key(__first->_M_val), __key))
853 for (const _Node* __cur = __first->_M_next; __cur;
854 __cur = __cur->_M_next)
855 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
856 return _Pii(const_iterator(__first, this),
857 const_iterator(__cur, this));
858 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
860 return _Pii(const_iterator(__first, this),
861 const_iterator(_M_buckets[__m], this));
862 return _Pii(const_iterator(__first, this), end());
865 return _Pii(end(), end());
868 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
869 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
870 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
871 erase(const key_type& __key)
873 const size_type __n = _M_bkt_num_key(__key);
874 _Node* __first = _M_buckets[__n];
875 size_type __erased = 0;
879 _Node* __cur = __first;
880 _Node* __next = __cur->_M_next;
883 if (_M_equals(_M_get_key(__next->_M_val), __key))
885 __cur->_M_next = __next->_M_next;
886 _M_delete_node(__next);
887 __next = __cur->_M_next;
894 __next = __cur->_M_next;
897 if (_M_equals(_M_get_key(__first->_M_val), __key))
899 _M_buckets[__n] = __first->_M_next;
900 _M_delete_node(__first);
908 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
909 void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
910 erase(const iterator& __it)
912 _Node* __p = __it._M_cur;
915 const size_type __n = _M_bkt_num(__p->_M_val);
916 _Node* __cur = _M_buckets[__n];
920 _M_buckets[__n] = __cur->_M_next;
921 _M_delete_node(__cur);
926 _Node* __next = __cur->_M_next;
931 __cur->_M_next = __next->_M_next;
932 _M_delete_node(__next);
939 __next = __cur->_M_next;
946 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
948 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
949 erase(iterator __first, iterator __last)
951 size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val)
954 size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val)
957 if (__first._M_cur == __last._M_cur)
959 else if (__f_bucket == __l_bucket)
960 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
963 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
964 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
965 _M_erase_bucket(__n, 0);
966 if (__l_bucket != _M_buckets.size())
967 _M_erase_bucket(__l_bucket, __last._M_cur);
971 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
973 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
974 erase(const_iterator __first, const_iterator __last)
976 erase(iterator(const_cast<_Node*>(__first._M_cur),
977 const_cast<hashtable*>(__first._M_ht)),
978 iterator(const_cast<_Node*>(__last._M_cur),
979 const_cast<hashtable*>(__last._M_ht)));
982 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
984 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
985 erase(const const_iterator& __it)
986 { erase(iterator(const_cast<_Node*>(__it._M_cur),
987 const_cast<hashtable*>(__it._M_ht))); }
989 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
991 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
992 resize(size_type __num_elements_hint)
994 const size_type __old_n = _M_buckets.size();
995 if (__num_elements_hint > __old_n)
997 const size_type __n = _M_next_size(__num_elements_hint);
1000 _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
1003 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket)
1005 _Node* __first = _M_buckets[__bucket];
1008 size_type __new_bucket = _M_bkt_num(__first->_M_val,
1010 _M_buckets[__bucket] = __first->_M_next;
1011 __first->_M_next = __tmp[__new_bucket];
1012 __tmp[__new_bucket] = __first;
1013 __first = _M_buckets[__bucket];
1016 _M_buckets.swap(__tmp);
1020 for (size_type __bucket = 0; __bucket < __tmp.size();
1023 while (__tmp[__bucket])
1025 _Node* __next = __tmp[__bucket]->_M_next;
1026 _M_delete_node(__tmp[__bucket]);
1027 __tmp[__bucket] = __next;
1030 __throw_exception_again;
1032 __profcxx_hashtable_resize(this, __num_elements_hint, __n);
1037 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1039 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1040 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
1042 _Node* __cur = _M_buckets[__n];
1043 if (__cur == __first)
1044 _M_erase_bucket(__n, __last);
1048 for (__next = __cur->_M_next;
1050 __cur = __next, __next = __cur->_M_next)
1052 while (__next != __last)
1054 __cur->_M_next = __next->_M_next;
1055 _M_delete_node(__next);
1056 __next = __cur->_M_next;
1062 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1064 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1065 _M_erase_bucket(const size_type __n, _Node* __last)
1067 _Node* __cur = _M_buckets[__n];
1068 while (__cur != __last)
1070 _Node* __next = __cur->_M_next;
1071 _M_delete_node(__cur);
1073 _M_buckets[__n] = __cur;
1078 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1080 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1083 size_type __hops=0, __lc = 0, __chain = 0;
1084 if (_M_num_elements != 0)
1085 __profcxx_hashtable_destruct(this, _M_buckets.size(), _M_num_elements);
1087 for (size_type __i = 0; __i < _M_buckets.size(); ++__i)
1089 _Node* __cur = _M_buckets[__i];
1092 _Node* __next = __cur->_M_next;
1093 _M_delete_node(__cur);
1096 // Compute the longest chain count.
1099 _M_buckets[__i] = 0;
1101 // Collect number of hops.
1103 __lc = __lc > __chain ? __lc : __chain;
1104 __hops += (__chain-1) * __chain / 2;
1108 if (_M_num_elements) {
1109 __profcxx_hashtable_destruct2(this, __lc, _M_num_elements, __hops);
1111 _M_num_elements = 0;
1114 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1116 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1117 _M_copy_from(const hashtable& __ht)
1120 _M_buckets.reserve(__ht._M_buckets.size());
1121 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
1124 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
1125 const _Node* __cur = __ht._M_buckets[__i];
1128 _Node* __local_copy = _M_new_node(__cur->_M_val);
1129 _M_buckets[__i] = __local_copy;
1131 for (_Node* __next = __cur->_M_next;
1133 __cur = __next, __next = __cur->_M_next)
1135 __local_copy->_M_next = _M_new_node(__next->_M_val);
1136 __local_copy = __local_copy->_M_next;
1140 _M_num_elements = __ht._M_num_elements;
1145 __throw_exception_again;
1149 _GLIBCXX_END_NAMESPACE