1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
5 // This file is part of the GNU ISO C++ Library. This library is free
6 // software; you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the
8 // Free Software Foundation; either version 2, or (at your option)
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // You should have received a copy of the GNU General Public License along
17 // with this library; see the file COPYING. If not, write to the Free
18 // Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307,
21 // As a special exception, you may use this file as part of a free software
22 // library without restriction. Specifically, if other files instantiate
23 // templates or use macros or inline functions from this file, or you compile
24 // this file and link it with other files to produce an executable, this
25 // file does not by itself cause the resulting executable to be covered by
26 // the GNU General Public License. This exception does not however
27 // invalidate any other reasons why the executable file might be covered by
28 // the GNU General Public License.
31 * Copyright (c) 1996,1997
32 * Silicon Graphics Computer Systems, Inc.
34 * Permission to use, copy, modify, distribute and sell this software
35 * and its documentation for any purpose is hereby granted without fee,
36 * provided that the above copyright notice appear in all copies and
37 * that both that copyright notice and this permission notice appear
38 * in supporting documentation. Silicon Graphics makes no
39 * representations about the suitability of this software for any
40 * purpose. It is provided "as is" without express or implied warranty.
44 * Hewlett-Packard Company
46 * Permission to use, copy, modify, distribute and sell this software
47 * and its documentation for any purpose is hereby granted without fee,
48 * provided that the above copyright notice appear in all copies and
49 * that both that copyright notice and this permission notice appear
50 * in supporting documentation. Hewlett-Packard Company makes no
51 * representations about the suitability of this software for any
52 * purpose. It is provided "as is" without express or implied warranty.
56 /** @file ext/hashtable.h
57 * This file is a GNU extension to the Standard C++ Library (possibly
58 * containing extensions from the HP/SGI STL subset). You should only
59 * include this header if you are using GCC 3 or later.
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.
70 #include <bits/stl_algo.h>
71 #include <bits/stl_function.h>
72 #include <ext/hash_fun.h>
78 using std::forward_iterator_tag;
79 using std::input_iterator_tag;
80 using std::_Alloc_traits;
81 using std::_Construct;
86 using std::__iterator_category;
89 struct _Hashtable_node
91 _Hashtable_node* _M_next;
95 template <class _Val, class _Key, class _HashFcn,
96 class _ExtractKey, class _EqualKey, class _Alloc = std::__alloc>
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 {
110 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
112 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
113 _ExtractKey, _EqualKey, _Alloc>
115 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
116 _ExtractKey, _EqualKey, _Alloc>
118 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) {}
132 _Hashtable_iterator() {}
133 reference operator*() const { return _M_cur->_M_val; }
134 pointer operator->() const { return &(operator*()); }
135 iterator& operator++();
136 iterator operator++(int);
137 bool operator==(const iterator& __it) const
138 { return _M_cur == __it._M_cur; }
139 bool operator!=(const iterator& __it) const
140 { return _M_cur != __it._M_cur; }
144 template <class _Val, class _Key, class _HashFcn,
145 class _ExtractKey, class _EqualKey, class _Alloc>
146 struct _Hashtable_const_iterator {
147 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
149 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
150 _ExtractKey,_EqualKey,_Alloc>
152 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
153 _ExtractKey, _EqualKey, _Alloc>
155 typedef _Hashtable_node<_Val> _Node;
157 typedef forward_iterator_tag iterator_category;
158 typedef _Val value_type;
159 typedef ptrdiff_t difference_type;
160 typedef size_t size_type;
161 typedef const _Val& reference;
162 typedef const _Val* pointer;
165 const _Hashtable* _M_ht;
167 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
168 : _M_cur(__n), _M_ht(__tab) {}
169 _Hashtable_const_iterator() {}
170 _Hashtable_const_iterator(const iterator& __it)
171 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
172 reference operator*() const { return _M_cur->_M_val; }
173 pointer operator->() const { return &(operator*()); }
174 const_iterator& operator++();
175 const_iterator operator++(int);
176 bool operator==(const const_iterator& __it) const
177 { return _M_cur == __it._M_cur; }
178 bool operator!=(const const_iterator& __it) const
179 { return _M_cur != __it._M_cur; }
182 // Note: assumes long is at least 32 bits.
183 enum { _S_num_primes = 28 };
185 static const unsigned long __stl_prime_list[_S_num_primes] =
187 53ul, 97ul, 193ul, 389ul, 769ul,
188 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
189 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
190 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
191 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
192 1610612741ul, 3221225473ul, 4294967291ul
195 inline unsigned long __stl_next_prime(unsigned long __n)
197 const unsigned long* __first = __stl_prime_list;
198 const unsigned long* __last = __stl_prime_list + (int)_S_num_primes;
199 const unsigned long* pos = std::lower_bound(__first, __last, __n);
200 return pos == __last ? *(__last - 1) : *pos;
203 // Forward declaration of operator==.
205 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
208 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
209 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
210 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
213 // Hashtables handle allocators a bit differently than other
214 // containers do. If we're using standard-conforming allocators, then
215 // a hashtable unconditionally has a member variable to hold its
216 // allocator, even if it so happens that all instances of the
217 // allocator type are identical. This is because, for hashtables,
218 // this extra storage is negligible. Additionally, a base class
219 // wouldn't serve any other purposes; it wouldn't, for example,
220 // simplify the exception-handling code.
222 template <class _Val, class _Key, class _HashFcn,
223 class _ExtractKey, class _EqualKey, class _Alloc>
226 typedef _Key key_type;
227 typedef _Val value_type;
228 typedef _HashFcn hasher;
229 typedef _EqualKey key_equal;
231 typedef size_t size_type;
232 typedef ptrdiff_t difference_type;
233 typedef value_type* pointer;
234 typedef const value_type* const_pointer;
235 typedef value_type& reference;
236 typedef const value_type& const_reference;
238 hasher hash_funct() const { return _M_hash; }
239 key_equal key_eq() const { return _M_equals; }
242 typedef _Hashtable_node<_Val> _Node;
245 typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
246 allocator_type get_allocator() const { return _M_node_allocator; }
248 typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
249 _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
250 void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
255 _ExtractKey _M_get_key;
256 vector<_Node*,_Alloc> _M_buckets;
257 size_type _M_num_elements;
260 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
262 typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
267 _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
269 _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
272 hashtable(size_type __n,
273 const _HashFcn& __hf,
274 const _EqualKey& __eql,
275 const _ExtractKey& __ext,
276 const allocator_type& __a = allocator_type())
277 : _M_node_allocator(__a),
284 _M_initialize_buckets(__n);
287 hashtable(size_type __n,
288 const _HashFcn& __hf,
289 const _EqualKey& __eql,
290 const allocator_type& __a = allocator_type())
291 : _M_node_allocator(__a),
294 _M_get_key(_ExtractKey()),
298 _M_initialize_buckets(__n);
301 hashtable(const hashtable& __ht)
302 : _M_node_allocator(__ht.get_allocator()),
303 _M_hash(__ht._M_hash),
304 _M_equals(__ht._M_equals),
305 _M_get_key(__ht._M_get_key),
306 _M_buckets(__ht.get_allocator()),
312 hashtable& operator= (const hashtable& __ht)
316 _M_hash = __ht._M_hash;
317 _M_equals = __ht._M_equals;
318 _M_get_key = __ht._M_get_key;
324 ~hashtable() { clear(); }
326 size_type size() const { return _M_num_elements; }
327 size_type max_size() const { return size_type(-1); }
328 bool empty() const { return size() == 0; }
330 void swap(hashtable& __ht)
332 std::swap(_M_hash, __ht._M_hash);
333 std::swap(_M_equals, __ht._M_equals);
334 std::swap(_M_get_key, __ht._M_get_key);
335 _M_buckets.swap(__ht._M_buckets);
336 std::swap(_M_num_elements, __ht._M_num_elements);
341 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
343 return iterator(_M_buckets[__n], this);
347 iterator end() { return iterator(0, this); }
349 const_iterator begin() const
351 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
353 return const_iterator(_M_buckets[__n], this);
357 const_iterator end() const { return const_iterator(0, this); }
359 template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
360 friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
361 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
364 size_type bucket_count() const { return _M_buckets.size(); }
366 size_type max_bucket_count() const
367 { return __stl_prime_list[(int)_S_num_primes - 1]; }
369 size_type elems_in_bucket(size_type __bucket) const
371 size_type __result = 0;
372 for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
377 pair<iterator, bool> insert_unique(const value_type& __obj)
379 resize(_M_num_elements + 1);
380 return insert_unique_noresize(__obj);
383 iterator insert_equal(const value_type& __obj)
385 resize(_M_num_elements + 1);
386 return insert_equal_noresize(__obj);
389 pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
390 iterator insert_equal_noresize(const value_type& __obj);
392 template <class _InputIterator>
393 void insert_unique(_InputIterator __f, _InputIterator __l)
395 insert_unique(__f, __l, __iterator_category(__f));
398 template <class _InputIterator>
399 void insert_equal(_InputIterator __f, _InputIterator __l)
401 insert_equal(__f, __l, __iterator_category(__f));
404 template <class _InputIterator>
405 void insert_unique(_InputIterator __f, _InputIterator __l,
408 for ( ; __f != __l; ++__f)
412 template <class _InputIterator>
413 void insert_equal(_InputIterator __f, _InputIterator __l,
416 for ( ; __f != __l; ++__f)
420 template <class _ForwardIterator>
421 void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
422 forward_iterator_tag)
424 size_type __n = distance(__f, __l);
425 resize(_M_num_elements + __n);
426 for ( ; __n > 0; --__n, ++__f)
427 insert_unique_noresize(*__f);
430 template <class _ForwardIterator>
431 void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
432 forward_iterator_tag)
434 size_type __n = distance(__f, __l);
435 resize(_M_num_elements + __n);
436 for ( ; __n > 0; --__n, ++__f)
437 insert_equal_noresize(*__f);
440 reference find_or_insert(const value_type& __obj);
442 iterator find(const key_type& __key)
444 size_type __n = _M_bkt_num_key(__key);
446 for ( __first = _M_buckets[__n];
447 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
448 __first = __first->_M_next)
450 return iterator(__first, this);
453 const_iterator find(const key_type& __key) const
455 size_type __n = _M_bkt_num_key(__key);
456 const _Node* __first;
457 for ( __first = _M_buckets[__n];
458 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
459 __first = __first->_M_next)
461 return const_iterator(__first, this);
464 size_type count(const key_type& __key) const
466 const size_type __n = _M_bkt_num_key(__key);
467 size_type __result = 0;
469 for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
470 if (_M_equals(_M_get_key(__cur->_M_val), __key))
475 pair<iterator, iterator>
476 equal_range(const key_type& __key);
478 pair<const_iterator, const_iterator>
479 equal_range(const key_type& __key) const;
481 size_type erase(const key_type& __key);
482 void erase(const iterator& __it);
483 void erase(iterator __first, iterator __last);
485 void erase(const const_iterator& __it);
486 void erase(const_iterator __first, const_iterator __last);
488 void resize(size_type __num_elements_hint);
492 size_type _M_next_size(size_type __n) const
493 { return __stl_next_prime(__n); }
495 void _M_initialize_buckets(size_type __n)
497 const size_type __n_buckets = _M_next_size(__n);
498 _M_buckets.reserve(__n_buckets);
499 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
503 size_type _M_bkt_num_key(const key_type& __key) const
505 return _M_bkt_num_key(__key, _M_buckets.size());
508 size_type _M_bkt_num(const value_type& __obj) const
510 return _M_bkt_num_key(_M_get_key(__obj));
513 size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
515 return _M_hash(__key) % __n;
518 size_type _M_bkt_num(const value_type& __obj, size_t __n) const
520 return _M_bkt_num_key(_M_get_key(__obj), __n);
523 _Node* _M_new_node(const value_type& __obj)
525 _Node* __n = _M_get_node();
528 _Construct(&__n->_M_val, __obj);
534 __throw_exception_again;
538 void _M_delete_node(_Node* __n)
540 _Destroy(&__n->_M_val);
544 void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
545 void _M_erase_bucket(const size_type __n, _Node* __last);
547 void _M_copy_from(const hashtable& __ht);
551 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
553 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
554 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
556 const _Node* __old = _M_cur;
557 _M_cur = _M_cur->_M_next;
559 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
560 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
561 _M_cur = _M_ht->_M_buckets[__bucket];
566 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
568 inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
569 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
571 iterator __tmp = *this;
576 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
578 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
579 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
581 const _Node* __old = _M_cur;
582 _M_cur = _M_cur->_M_next;
584 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
585 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
586 _M_cur = _M_ht->_M_buckets[__bucket];
591 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
593 inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
594 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
596 const_iterator __tmp = *this;
601 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
602 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
603 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
605 typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
606 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
608 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
609 _Node* __cur1 = __ht1._M_buckets[__n];
610 _Node* __cur2 = __ht2._M_buckets[__n];
611 // Check same length of lists
612 for ( ; __cur1 && __cur2;
613 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
615 if (__cur1 || __cur2)
617 // Now check one's elements are in the other
618 for (__cur1 = __ht1._M_buckets[__n] ; __cur1; __cur1 = __cur1->_M_next)
620 bool _found__cur1 = false;
621 for (_Node* __cur2 = __ht2._M_buckets[__n];
622 __cur2; __cur2 = __cur2->_M_next)
624 if (__cur1->_M_val == __cur2->_M_val)
637 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
638 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
639 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
640 return !(__ht1 == __ht2);
643 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
645 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
646 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
651 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
652 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
653 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
654 ::insert_unique_noresize(const value_type& __obj)
656 const size_type __n = _M_bkt_num(__obj);
657 _Node* __first = _M_buckets[__n];
659 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
660 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
661 return pair<iterator, bool>(iterator(__cur, this), false);
663 _Node* __tmp = _M_new_node(__obj);
664 __tmp->_M_next = __first;
665 _M_buckets[__n] = __tmp;
667 return pair<iterator, bool>(iterator(__tmp, this), true);
670 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
671 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
672 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
673 ::insert_equal_noresize(const value_type& __obj)
675 const size_type __n = _M_bkt_num(__obj);
676 _Node* __first = _M_buckets[__n];
678 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
679 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
680 _Node* __tmp = _M_new_node(__obj);
681 __tmp->_M_next = __cur->_M_next;
682 __cur->_M_next = __tmp;
684 return iterator(__tmp, this);
687 _Node* __tmp = _M_new_node(__obj);
688 __tmp->_M_next = __first;
689 _M_buckets[__n] = __tmp;
691 return iterator(__tmp, this);
694 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
695 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
696 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
698 resize(_M_num_elements + 1);
700 size_type __n = _M_bkt_num(__obj);
701 _Node* __first = _M_buckets[__n];
703 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
704 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
705 return __cur->_M_val;
707 _Node* __tmp = _M_new_node(__obj);
708 __tmp->_M_next = __first;
709 _M_buckets[__n] = __tmp;
711 return __tmp->_M_val;
714 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
715 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
716 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
717 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
719 typedef pair<iterator, iterator> _Pii;
720 const size_type __n = _M_bkt_num_key(__key);
722 for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
723 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
724 for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
725 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
726 return _Pii(iterator(__first, this), iterator(__cur, this));
727 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
729 return _Pii(iterator(__first, this),
730 iterator(_M_buckets[__m], this));
731 return _Pii(iterator(__first, this), end());
733 return _Pii(end(), end());
736 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
737 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
738 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
739 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
740 ::equal_range(const key_type& __key) const
742 typedef pair<const_iterator, const_iterator> _Pii;
743 const size_type __n = _M_bkt_num_key(__key);
745 for (const _Node* __first = _M_buckets[__n] ;
747 __first = __first->_M_next) {
748 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
749 for (const _Node* __cur = __first->_M_next;
751 __cur = __cur->_M_next)
752 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
753 return _Pii(const_iterator(__first, this),
754 const_iterator(__cur, this));
755 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
757 return _Pii(const_iterator(__first, this),
758 const_iterator(_M_buckets[__m], this));
759 return _Pii(const_iterator(__first, this), end());
762 return _Pii(end(), end());
765 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
766 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
767 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
769 const size_type __n = _M_bkt_num_key(__key);
770 _Node* __first = _M_buckets[__n];
771 size_type __erased = 0;
774 _Node* __cur = __first;
775 _Node* __next = __cur->_M_next;
777 if (_M_equals(_M_get_key(__next->_M_val), __key)) {
778 __cur->_M_next = __next->_M_next;
779 _M_delete_node(__next);
780 __next = __cur->_M_next;
786 __next = __cur->_M_next;
789 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
790 _M_buckets[__n] = __first->_M_next;
791 _M_delete_node(__first);
799 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
800 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
802 _Node* __p = __it._M_cur;
804 const size_type __n = _M_bkt_num(__p->_M_val);
805 _Node* __cur = _M_buckets[__n];
808 _M_buckets[__n] = __cur->_M_next;
809 _M_delete_node(__cur);
813 _Node* __next = __cur->_M_next;
816 __cur->_M_next = __next->_M_next;
817 _M_delete_node(__next);
823 __next = __cur->_M_next;
830 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
831 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
832 ::erase(iterator __first, iterator __last)
834 size_type __f_bucket = __first._M_cur ?
835 _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
836 size_type __l_bucket = __last._M_cur ?
837 _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
839 if (__first._M_cur == __last._M_cur)
841 else if (__f_bucket == __l_bucket)
842 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
844 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
845 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
846 _M_erase_bucket(__n, 0);
847 if (__l_bucket != _M_buckets.size())
848 _M_erase_bucket(__l_bucket, __last._M_cur);
852 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
854 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
855 const_iterator __last)
857 erase(iterator(const_cast<_Node*>(__first._M_cur),
858 const_cast<hashtable*>(__first._M_ht)),
859 iterator(const_cast<_Node*>(__last._M_cur),
860 const_cast<hashtable*>(__last._M_ht)));
863 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
865 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
867 erase(iterator(const_cast<_Node*>(__it._M_cur),
868 const_cast<hashtable*>(__it._M_ht)));
871 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
872 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
873 ::resize(size_type __num_elements_hint)
875 const size_type __old_n = _M_buckets.size();
876 if (__num_elements_hint > __old_n) {
877 const size_type __n = _M_next_size(__num_elements_hint);
879 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
880 _M_buckets.get_allocator());
882 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
883 _Node* __first = _M_buckets[__bucket];
885 size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
886 _M_buckets[__bucket] = __first->_M_next;
887 __first->_M_next = __tmp[__new_bucket];
888 __tmp[__new_bucket] = __first;
889 __first = _M_buckets[__bucket];
892 _M_buckets.swap(__tmp);
895 for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
896 while (__tmp[__bucket]) {
897 _Node* __next = __tmp[__bucket]->_M_next;
898 _M_delete_node(__tmp[__bucket]);
899 __tmp[__bucket] = __next;
902 __throw_exception_again;
908 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
909 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
910 ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
912 _Node* __cur = _M_buckets[__n];
913 if (__cur == __first)
914 _M_erase_bucket(__n, __last);
917 for (__next = __cur->_M_next;
919 __cur = __next, __next = __cur->_M_next)
921 while (__next != __last) {
922 __cur->_M_next = __next->_M_next;
923 _M_delete_node(__next);
924 __next = __cur->_M_next;
930 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
931 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
932 ::_M_erase_bucket(const size_type __n, _Node* __last)
934 _Node* __cur = _M_buckets[__n];
935 while (__cur != __last) {
936 _Node* __next = __cur->_M_next;
937 _M_delete_node(__cur);
939 _M_buckets[__n] = __cur;
944 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
945 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
947 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
948 _Node* __cur = _M_buckets[__i];
950 _Node* __next = __cur->_M_next;
951 _M_delete_node(__cur);
960 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
961 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
962 ::_M_copy_from(const hashtable& __ht)
965 _M_buckets.reserve(__ht._M_buckets.size());
966 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
968 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
969 const _Node* __cur = __ht._M_buckets[__i];
971 _Node* __local_copy = _M_new_node(__cur->_M_val);
972 _M_buckets[__i] = __local_copy;
974 for (_Node* __next = __cur->_M_next;
976 __cur = __next, __next = __cur->_M_next) {
977 __local_copy->_M_next = _M_new_node(__next->_M_val);
978 __local_copy = __local_copy->_M_next;
982 _M_num_elements = __ht._M_num_elements;
987 __throw_exception_again;
990 } // namespace __gnu_cxx