1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001, 2002 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 stl_hashtable.h
57 * This is an internal header file, included by other library headers.
58 * You should not attempt to use it directly.
61 #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
62 #define __SGI_STL_INTERNAL_HASHTABLE_H
64 // Hashtable class, used to implement the hashed associative containers
65 // hash_set, hash_map, hash_multiset, and hash_multimap.
67 #include <bits/stl_algobase.h>
68 #include <bits/stl_alloc.h>
69 #include <bits/stl_construct.h>
70 #include <bits/stl_algo.h>
71 #include <bits/stl_uninitialized.h>
72 #include <bits/stl_function.h>
73 #include <bits/stl_vector.h>
74 #include <ext/stl_hash_fun.h>
80 using std::forward_iterator_tag;
81 using std::input_iterator_tag;
82 using std::_Alloc_traits;
83 using std::_Construct;
90 struct _Hashtable_node
92 _Hashtable_node* _M_next;
96 template <class _Val, class _Key, class _HashFcn,
97 class _ExtractKey, class _EqualKey, class _Alloc = std::__alloc>
100 template <class _Val, class _Key, class _HashFcn,
101 class _ExtractKey, class _EqualKey, class _Alloc>
102 struct _Hashtable_iterator;
104 template <class _Val, class _Key, class _HashFcn,
105 class _ExtractKey, class _EqualKey, class _Alloc>
106 struct _Hashtable_const_iterator;
108 template <class _Val, class _Key, class _HashFcn,
109 class _ExtractKey, class _EqualKey, class _Alloc>
110 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;
121 typedef forward_iterator_tag iterator_category;
122 typedef _Val value_type;
123 typedef ptrdiff_t difference_type;
124 typedef size_t size_type;
125 typedef _Val& reference;
126 typedef _Val* pointer;
131 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
132 : _M_cur(__n), _M_ht(__tab) {}
133 _Hashtable_iterator() {}
134 reference operator*() const { return _M_cur->_M_val; }
135 pointer operator->() const { return &(operator*()); }
136 iterator& operator++();
137 iterator operator++(int);
138 bool operator==(const iterator& __it) const
139 { return _M_cur == __it._M_cur; }
140 bool operator!=(const iterator& __it) const
141 { return _M_cur != __it._M_cur; }
145 template <class _Val, class _Key, class _HashFcn,
146 class _ExtractKey, class _EqualKey, class _Alloc>
147 struct _Hashtable_const_iterator {
148 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
150 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
151 _ExtractKey,_EqualKey,_Alloc>
153 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
154 _ExtractKey, _EqualKey, _Alloc>
156 typedef _Hashtable_node<_Val> _Node;
158 typedef forward_iterator_tag iterator_category;
159 typedef _Val value_type;
160 typedef ptrdiff_t difference_type;
161 typedef size_t size_type;
162 typedef const _Val& reference;
163 typedef const _Val* pointer;
166 const _Hashtable* _M_ht;
168 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
169 : _M_cur(__n), _M_ht(__tab) {}
170 _Hashtable_const_iterator() {}
171 _Hashtable_const_iterator(const iterator& __it)
172 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
173 reference operator*() const { return _M_cur->_M_val; }
174 pointer operator->() const { return &(operator*()); }
175 const_iterator& operator++();
176 const_iterator operator++(int);
177 bool operator==(const const_iterator& __it) const
178 { return _M_cur == __it._M_cur; }
179 bool operator!=(const const_iterator& __it) const
180 { return _M_cur != __it._M_cur; }
183 // Note: assumes long is at least 32 bits.
184 enum { __stl_num_primes = 28 };
186 static const unsigned long __stl_prime_list[__stl_num_primes] =
188 53ul, 97ul, 193ul, 389ul, 769ul,
189 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
190 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
191 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
192 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
193 1610612741ul, 3221225473ul, 4294967291ul
196 inline unsigned long __stl_next_prime(unsigned long __n)
198 const unsigned long* __first = __stl_prime_list;
199 const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
200 const unsigned long* pos = std::lower_bound(__first, __last, __n);
201 return pos == __last ? *(__last - 1) : *pos;
204 // Forward declaration of operator==.
206 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
209 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
210 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
211 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
214 // Hashtables handle allocators a bit differently than other containers
215 // do. If we're using standard-conforming allocators, then a hashtable
216 // unconditionally has a member variable to hold its allocator, even if
217 // it so happens that all instances of the allocator type are identical.
218 // This is because, for hashtables, this extra storage is negligible.
219 // Additionally, a base class wouldn't serve any other purposes; it
220 // wouldn't, for example, 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)__stl_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 for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
612 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
614 if (__cur1 || __cur2)
620 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
621 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
622 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
623 return !(__ht1 == __ht2);
626 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
628 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
629 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
634 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
635 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
636 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
637 ::insert_unique_noresize(const value_type& __obj)
639 const size_type __n = _M_bkt_num(__obj);
640 _Node* __first = _M_buckets[__n];
642 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
643 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
644 return pair<iterator, bool>(iterator(__cur, this), false);
646 _Node* __tmp = _M_new_node(__obj);
647 __tmp->_M_next = __first;
648 _M_buckets[__n] = __tmp;
650 return pair<iterator, bool>(iterator(__tmp, this), true);
653 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
654 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
655 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
656 ::insert_equal_noresize(const value_type& __obj)
658 const size_type __n = _M_bkt_num(__obj);
659 _Node* __first = _M_buckets[__n];
661 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
662 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
663 _Node* __tmp = _M_new_node(__obj);
664 __tmp->_M_next = __cur->_M_next;
665 __cur->_M_next = __tmp;
667 return iterator(__tmp, this);
670 _Node* __tmp = _M_new_node(__obj);
671 __tmp->_M_next = __first;
672 _M_buckets[__n] = __tmp;
674 return iterator(__tmp, this);
677 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
678 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
679 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
681 resize(_M_num_elements + 1);
683 size_type __n = _M_bkt_num(__obj);
684 _Node* __first = _M_buckets[__n];
686 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
687 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
688 return __cur->_M_val;
690 _Node* __tmp = _M_new_node(__obj);
691 __tmp->_M_next = __first;
692 _M_buckets[__n] = __tmp;
694 return __tmp->_M_val;
697 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
698 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
699 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
700 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
702 typedef pair<iterator, iterator> _Pii;
703 const size_type __n = _M_bkt_num_key(__key);
705 for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
706 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
707 for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
708 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
709 return _Pii(iterator(__first, this), iterator(__cur, this));
710 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
712 return _Pii(iterator(__first, this),
713 iterator(_M_buckets[__m], this));
714 return _Pii(iterator(__first, this), end());
716 return _Pii(end(), end());
719 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
720 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
721 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
722 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
723 ::equal_range(const key_type& __key) const
725 typedef pair<const_iterator, const_iterator> _Pii;
726 const size_type __n = _M_bkt_num_key(__key);
728 for (const _Node* __first = _M_buckets[__n] ;
730 __first = __first->_M_next) {
731 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
732 for (const _Node* __cur = __first->_M_next;
734 __cur = __cur->_M_next)
735 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
736 return _Pii(const_iterator(__first, this),
737 const_iterator(__cur, this));
738 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
740 return _Pii(const_iterator(__first, this),
741 const_iterator(_M_buckets[__m], this));
742 return _Pii(const_iterator(__first, this), end());
745 return _Pii(end(), end());
748 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
749 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
750 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
752 const size_type __n = _M_bkt_num_key(__key);
753 _Node* __first = _M_buckets[__n];
754 size_type __erased = 0;
757 _Node* __cur = __first;
758 _Node* __next = __cur->_M_next;
760 if (_M_equals(_M_get_key(__next->_M_val), __key)) {
761 __cur->_M_next = __next->_M_next;
762 _M_delete_node(__next);
763 __next = __cur->_M_next;
769 __next = __cur->_M_next;
772 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
773 _M_buckets[__n] = __first->_M_next;
774 _M_delete_node(__first);
782 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
783 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
785 _Node* __p = __it._M_cur;
787 const size_type __n = _M_bkt_num(__p->_M_val);
788 _Node* __cur = _M_buckets[__n];
791 _M_buckets[__n] = __cur->_M_next;
792 _M_delete_node(__cur);
796 _Node* __next = __cur->_M_next;
799 __cur->_M_next = __next->_M_next;
800 _M_delete_node(__next);
806 __next = __cur->_M_next;
813 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
814 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
815 ::erase(iterator __first, iterator __last)
817 size_type __f_bucket = __first._M_cur ?
818 _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
819 size_type __l_bucket = __last._M_cur ?
820 _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
822 if (__first._M_cur == __last._M_cur)
824 else if (__f_bucket == __l_bucket)
825 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
827 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
828 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
829 _M_erase_bucket(__n, 0);
830 if (__l_bucket != _M_buckets.size())
831 _M_erase_bucket(__l_bucket, __last._M_cur);
835 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
837 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
838 const_iterator __last)
840 erase(iterator(const_cast<_Node*>(__first._M_cur),
841 const_cast<hashtable*>(__first._M_ht)),
842 iterator(const_cast<_Node*>(__last._M_cur),
843 const_cast<hashtable*>(__last._M_ht)));
846 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
848 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
850 erase(iterator(const_cast<_Node*>(__it._M_cur),
851 const_cast<hashtable*>(__it._M_ht)));
854 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
855 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
856 ::resize(size_type __num_elements_hint)
858 const size_type __old_n = _M_buckets.size();
859 if (__num_elements_hint > __old_n) {
860 const size_type __n = _M_next_size(__num_elements_hint);
862 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
863 _M_buckets.get_allocator());
865 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
866 _Node* __first = _M_buckets[__bucket];
868 size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
869 _M_buckets[__bucket] = __first->_M_next;
870 __first->_M_next = __tmp[__new_bucket];
871 __tmp[__new_bucket] = __first;
872 __first = _M_buckets[__bucket];
875 _M_buckets.swap(__tmp);
878 for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
879 while (__tmp[__bucket]) {
880 _Node* __next = __tmp[__bucket]->_M_next;
881 _M_delete_node(__tmp[__bucket]);
882 __tmp[__bucket] = __next;
885 __throw_exception_again;
891 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
892 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
893 ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
895 _Node* __cur = _M_buckets[__n];
896 if (__cur == __first)
897 _M_erase_bucket(__n, __last);
900 for (__next = __cur->_M_next;
902 __cur = __next, __next = __cur->_M_next)
904 while (__next != __last) {
905 __cur->_M_next = __next->_M_next;
906 _M_delete_node(__next);
907 __next = __cur->_M_next;
913 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
914 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
915 ::_M_erase_bucket(const size_type __n, _Node* __last)
917 _Node* __cur = _M_buckets[__n];
918 while (__cur != __last) {
919 _Node* __next = __cur->_M_next;
920 _M_delete_node(__cur);
922 _M_buckets[__n] = __cur;
927 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
928 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
930 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
931 _Node* __cur = _M_buckets[__i];
933 _Node* __next = __cur->_M_next;
934 _M_delete_node(__cur);
943 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
944 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
945 ::_M_copy_from(const hashtable& __ht)
948 _M_buckets.reserve(__ht._M_buckets.size());
949 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
951 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
952 const _Node* __cur = __ht._M_buckets[__i];
954 _Node* __local_copy = _M_new_node(__cur->_M_val);
955 _M_buckets[__i] = __local_copy;
957 for (_Node* __next = __cur->_M_next;
959 __cur = __next, __next = __cur->_M_next) {
960 __local_copy->_M_next = _M_new_node(__next->_M_val);
961 __local_copy = __local_copy->_M_next;
965 _M_num_elements = __ht._M_num_elements;
970 __throw_exception_again;
974 } // namespace __gnu_cxx
976 #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */