1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001 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 /* NOTE: This is an internal header file, included by other STL headers.
57 * You should not attempt to use it directly.
60 #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
61 #define __SGI_STL_INTERNAL_HASHTABLE_H
63 // Hashtable class, used to implement the hashed associative containers
64 // hash_set, hash_map, hash_multiset, and hash_multimap.
66 #include <bits/stl_algobase.h>
67 #include <bits/stl_alloc.h>
68 #include <bits/stl_construct.h>
69 #include <bits/stl_tempbuf.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 struct _Hashtable_node
82 _Hashtable_node* _M_next;
86 template <class _Val, class _Key, class _HashFcn,
87 class _ExtractKey, class _EqualKey, class _Alloc = alloc>
90 template <class _Val, class _Key, class _HashFcn,
91 class _ExtractKey, class _EqualKey, class _Alloc>
92 struct _Hashtable_iterator;
94 template <class _Val, class _Key, class _HashFcn,
95 class _ExtractKey, class _EqualKey, class _Alloc>
96 struct _Hashtable_const_iterator;
98 template <class _Val, class _Key, class _HashFcn,
99 class _ExtractKey, class _EqualKey, class _Alloc>
100 struct _Hashtable_iterator {
101 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
103 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
104 _ExtractKey, _EqualKey, _Alloc>
106 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
107 _ExtractKey, _EqualKey, _Alloc>
109 typedef _Hashtable_node<_Val> _Node;
111 typedef forward_iterator_tag iterator_category;
112 typedef _Val value_type;
113 typedef ptrdiff_t difference_type;
114 typedef size_t size_type;
115 typedef _Val& reference;
116 typedef _Val* pointer;
121 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
122 : _M_cur(__n), _M_ht(__tab) {}
123 _Hashtable_iterator() {}
124 reference operator*() const { return _M_cur->_M_val; }
125 pointer operator->() const { return &(operator*()); }
126 iterator& operator++();
127 iterator operator++(int);
128 bool operator==(const iterator& __it) const
129 { return _M_cur == __it._M_cur; }
130 bool operator!=(const iterator& __it) const
131 { return _M_cur != __it._M_cur; }
135 template <class _Val, class _Key, class _HashFcn,
136 class _ExtractKey, class _EqualKey, class _Alloc>
137 struct _Hashtable_const_iterator {
138 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
140 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
141 _ExtractKey,_EqualKey,_Alloc>
143 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
144 _ExtractKey, _EqualKey, _Alloc>
146 typedef _Hashtable_node<_Val> _Node;
148 typedef forward_iterator_tag iterator_category;
149 typedef _Val value_type;
150 typedef ptrdiff_t difference_type;
151 typedef size_t size_type;
152 typedef const _Val& reference;
153 typedef const _Val* pointer;
156 const _Hashtable* _M_ht;
158 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
159 : _M_cur(__n), _M_ht(__tab) {}
160 _Hashtable_const_iterator() {}
161 _Hashtable_const_iterator(const iterator& __it)
162 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
163 reference operator*() const { return _M_cur->_M_val; }
164 pointer operator->() const { return &(operator*()); }
165 const_iterator& operator++();
166 const_iterator operator++(int);
167 bool operator==(const const_iterator& __it) const
168 { return _M_cur == __it._M_cur; }
169 bool operator!=(const const_iterator& __it) const
170 { return _M_cur != __it._M_cur; }
173 // Note: assumes long is at least 32 bits.
174 enum { __stl_num_primes = 28 };
176 static const unsigned long __stl_prime_list[__stl_num_primes] =
178 53ul, 97ul, 193ul, 389ul, 769ul,
179 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
180 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
181 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
182 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
183 1610612741ul, 3221225473ul, 4294967291ul
186 inline unsigned long __stl_next_prime(unsigned long __n)
188 const unsigned long* __first = __stl_prime_list;
189 const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
190 const unsigned long* pos = lower_bound(__first, __last, __n);
191 return pos == __last ? *(__last - 1) : *pos;
194 // Forward declaration of operator==.
196 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
199 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
200 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
201 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
204 // Hashtables handle allocators a bit differently than other containers
205 // do. If we're using standard-conforming allocators, then a hashtable
206 // unconditionally has a member variable to hold its allocator, even if
207 // it so happens that all instances of the allocator type are identical.
208 // This is because, for hashtables, this extra storage is negligible.
209 // Additionally, a base class wouldn't serve any other purposes; it
210 // wouldn't, for example, simplify the exception-handling code.
212 template <class _Val, class _Key, class _HashFcn,
213 class _ExtractKey, class _EqualKey, class _Alloc>
216 typedef _Key key_type;
217 typedef _Val value_type;
218 typedef _HashFcn hasher;
219 typedef _EqualKey key_equal;
221 typedef size_t size_type;
222 typedef ptrdiff_t difference_type;
223 typedef value_type* pointer;
224 typedef const value_type* const_pointer;
225 typedef value_type& reference;
226 typedef const value_type& const_reference;
228 hasher hash_funct() const { return _M_hash; }
229 key_equal key_eq() const { return _M_equals; }
232 typedef _Hashtable_node<_Val> _Node;
235 typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
236 allocator_type get_allocator() const { return _M_node_allocator; }
238 typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
239 _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
240 void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
245 _ExtractKey _M_get_key;
246 vector<_Node*,_Alloc> _M_buckets;
247 size_type _M_num_elements;
250 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
252 typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
257 _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
259 _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
262 hashtable(size_type __n,
263 const _HashFcn& __hf,
264 const _EqualKey& __eql,
265 const _ExtractKey& __ext,
266 const allocator_type& __a = allocator_type())
267 : _M_node_allocator(__a),
274 _M_initialize_buckets(__n);
277 hashtable(size_type __n,
278 const _HashFcn& __hf,
279 const _EqualKey& __eql,
280 const allocator_type& __a = allocator_type())
281 : _M_node_allocator(__a),
284 _M_get_key(_ExtractKey()),
288 _M_initialize_buckets(__n);
291 hashtable(const hashtable& __ht)
292 : _M_node_allocator(__ht.get_allocator()),
293 _M_hash(__ht._M_hash),
294 _M_equals(__ht._M_equals),
295 _M_get_key(__ht._M_get_key),
296 _M_buckets(__ht.get_allocator()),
302 hashtable& operator= (const hashtable& __ht)
306 _M_hash = __ht._M_hash;
307 _M_equals = __ht._M_equals;
308 _M_get_key = __ht._M_get_key;
314 ~hashtable() { clear(); }
316 size_type size() const { return _M_num_elements; }
317 size_type max_size() const { return size_type(-1); }
318 bool empty() const { return size() == 0; }
320 void swap(hashtable& __ht)
322 std::swap(_M_hash, __ht._M_hash);
323 std::swap(_M_equals, __ht._M_equals);
324 std::swap(_M_get_key, __ht._M_get_key);
325 _M_buckets.swap(__ht._M_buckets);
326 std::swap(_M_num_elements, __ht._M_num_elements);
331 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
333 return iterator(_M_buckets[__n], this);
337 iterator end() { return iterator(0, this); }
339 const_iterator begin() const
341 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
343 return const_iterator(_M_buckets[__n], this);
347 const_iterator end() const { return const_iterator(0, this); }
349 template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
350 friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
351 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
354 size_type bucket_count() const { return _M_buckets.size(); }
356 size_type max_bucket_count() const
357 { return __stl_prime_list[(int)__stl_num_primes - 1]; }
359 size_type elems_in_bucket(size_type __bucket) const
361 size_type __result = 0;
362 for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
367 pair<iterator, bool> insert_unique(const value_type& __obj)
369 resize(_M_num_elements + 1);
370 return insert_unique_noresize(__obj);
373 iterator insert_equal(const value_type& __obj)
375 resize(_M_num_elements + 1);
376 return insert_equal_noresize(__obj);
379 pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
380 iterator insert_equal_noresize(const value_type& __obj);
382 template <class _InputIterator>
383 void insert_unique(_InputIterator __f, _InputIterator __l)
385 insert_unique(__f, __l, __iterator_category(__f));
388 template <class _InputIterator>
389 void insert_equal(_InputIterator __f, _InputIterator __l)
391 insert_equal(__f, __l, __iterator_category(__f));
394 template <class _InputIterator>
395 void insert_unique(_InputIterator __f, _InputIterator __l,
398 for ( ; __f != __l; ++__f)
402 template <class _InputIterator>
403 void insert_equal(_InputIterator __f, _InputIterator __l,
406 for ( ; __f != __l; ++__f)
410 template <class _ForwardIterator>
411 void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
412 forward_iterator_tag)
415 distance(__f, __l, __n);
416 resize(_M_num_elements + __n);
417 for ( ; __n > 0; --__n, ++__f)
418 insert_unique_noresize(*__f);
421 template <class _ForwardIterator>
422 void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
423 forward_iterator_tag)
426 distance(__f, __l, __n);
427 resize(_M_num_elements + __n);
428 for ( ; __n > 0; --__n, ++__f)
429 insert_equal_noresize(*__f);
432 reference find_or_insert(const value_type& __obj);
434 iterator find(const key_type& __key)
436 size_type __n = _M_bkt_num_key(__key);
438 for ( __first = _M_buckets[__n];
439 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
440 __first = __first->_M_next)
442 return iterator(__first, this);
445 const_iterator find(const key_type& __key) const
447 size_type __n = _M_bkt_num_key(__key);
448 const _Node* __first;
449 for ( __first = _M_buckets[__n];
450 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
451 __first = __first->_M_next)
453 return const_iterator(__first, this);
456 size_type count(const key_type& __key) const
458 const size_type __n = _M_bkt_num_key(__key);
459 size_type __result = 0;
461 for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
462 if (_M_equals(_M_get_key(__cur->_M_val), __key))
467 pair<iterator, iterator>
468 equal_range(const key_type& __key);
470 pair<const_iterator, const_iterator>
471 equal_range(const key_type& __key) const;
473 size_type erase(const key_type& __key);
474 void erase(const iterator& __it);
475 void erase(iterator __first, iterator __last);
477 void erase(const const_iterator& __it);
478 void erase(const_iterator __first, const_iterator __last);
480 void resize(size_type __num_elements_hint);
484 size_type _M_next_size(size_type __n) const
485 { return __stl_next_prime(__n); }
487 void _M_initialize_buckets(size_type __n)
489 const size_type __n_buckets = _M_next_size(__n);
490 _M_buckets.reserve(__n_buckets);
491 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
495 size_type _M_bkt_num_key(const key_type& __key) const
497 return _M_bkt_num_key(__key, _M_buckets.size());
500 size_type _M_bkt_num(const value_type& __obj) const
502 return _M_bkt_num_key(_M_get_key(__obj));
505 size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
507 return _M_hash(__key) % __n;
510 size_type _M_bkt_num(const value_type& __obj, size_t __n) const
512 return _M_bkt_num_key(_M_get_key(__obj), __n);
515 _Node* _M_new_node(const value_type& __obj)
517 _Node* __n = _M_get_node();
520 construct(&__n->_M_val, __obj);
523 __STL_UNWIND(_M_put_node(__n));
526 void _M_delete_node(_Node* __n)
528 destroy(&__n->_M_val);
532 void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
533 void _M_erase_bucket(const size_type __n, _Node* __last);
535 void _M_copy_from(const hashtable& __ht);
539 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
541 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
542 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
544 const _Node* __old = _M_cur;
545 _M_cur = _M_cur->_M_next;
547 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
548 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
549 _M_cur = _M_ht->_M_buckets[__bucket];
554 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
556 inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
557 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
559 iterator __tmp = *this;
564 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
566 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
567 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
569 const _Node* __old = _M_cur;
570 _M_cur = _M_cur->_M_next;
572 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
573 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
574 _M_cur = _M_ht->_M_buckets[__bucket];
579 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
581 inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
582 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
584 const_iterator __tmp = *this;
589 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
590 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
591 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
593 typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
594 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
596 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
597 _Node* __cur1 = __ht1._M_buckets[__n];
598 _Node* __cur2 = __ht2._M_buckets[__n];
599 for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
600 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
602 if (__cur1 || __cur2)
608 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
609 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
610 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
611 return !(__ht1 == __ht2);
614 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
616 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
617 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
622 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
623 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
624 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
625 ::insert_unique_noresize(const value_type& __obj)
627 const size_type __n = _M_bkt_num(__obj);
628 _Node* __first = _M_buckets[__n];
630 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
631 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
632 return pair<iterator, bool>(iterator(__cur, this), false);
634 _Node* __tmp = _M_new_node(__obj);
635 __tmp->_M_next = __first;
636 _M_buckets[__n] = __tmp;
638 return pair<iterator, bool>(iterator(__tmp, this), true);
641 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
642 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
643 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
644 ::insert_equal_noresize(const value_type& __obj)
646 const size_type __n = _M_bkt_num(__obj);
647 _Node* __first = _M_buckets[__n];
649 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
650 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
651 _Node* __tmp = _M_new_node(__obj);
652 __tmp->_M_next = __cur->_M_next;
653 __cur->_M_next = __tmp;
655 return iterator(__tmp, this);
658 _Node* __tmp = _M_new_node(__obj);
659 __tmp->_M_next = __first;
660 _M_buckets[__n] = __tmp;
662 return iterator(__tmp, this);
665 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
666 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
667 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
669 resize(_M_num_elements + 1);
671 size_type __n = _M_bkt_num(__obj);
672 _Node* __first = _M_buckets[__n];
674 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
675 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
676 return __cur->_M_val;
678 _Node* __tmp = _M_new_node(__obj);
679 __tmp->_M_next = __first;
680 _M_buckets[__n] = __tmp;
682 return __tmp->_M_val;
685 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
686 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
687 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
688 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
690 typedef pair<iterator, iterator> _Pii;
691 const size_type __n = _M_bkt_num_key(__key);
693 for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
694 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
695 for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
696 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
697 return _Pii(iterator(__first, this), iterator(__cur, this));
698 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
700 return _Pii(iterator(__first, this),
701 iterator(_M_buckets[__m], this));
702 return _Pii(iterator(__first, this), end());
704 return _Pii(end(), end());
707 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
708 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
709 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
710 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
711 ::equal_range(const key_type& __key) const
713 typedef pair<const_iterator, const_iterator> _Pii;
714 const size_type __n = _M_bkt_num_key(__key);
716 for (const _Node* __first = _M_buckets[__n] ;
718 __first = __first->_M_next) {
719 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
720 for (const _Node* __cur = __first->_M_next;
722 __cur = __cur->_M_next)
723 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
724 return _Pii(const_iterator(__first, this),
725 const_iterator(__cur, this));
726 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
728 return _Pii(const_iterator(__first, this),
729 const_iterator(_M_buckets[__m], this));
730 return _Pii(const_iterator(__first, this), end());
733 return _Pii(end(), end());
736 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
737 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
738 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
740 const size_type __n = _M_bkt_num_key(__key);
741 _Node* __first = _M_buckets[__n];
742 size_type __erased = 0;
745 _Node* __cur = __first;
746 _Node* __next = __cur->_M_next;
748 if (_M_equals(_M_get_key(__next->_M_val), __key)) {
749 __cur->_M_next = __next->_M_next;
750 _M_delete_node(__next);
751 __next = __cur->_M_next;
757 __next = __cur->_M_next;
760 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
761 _M_buckets[__n] = __first->_M_next;
762 _M_delete_node(__first);
770 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
771 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
773 _Node* __p = __it._M_cur;
775 const size_type __n = _M_bkt_num(__p->_M_val);
776 _Node* __cur = _M_buckets[__n];
779 _M_buckets[__n] = __cur->_M_next;
780 _M_delete_node(__cur);
784 _Node* __next = __cur->_M_next;
787 __cur->_M_next = __next->_M_next;
788 _M_delete_node(__next);
794 __next = __cur->_M_next;
801 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
802 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
803 ::erase(iterator __first, iterator __last)
805 size_type __f_bucket = __first._M_cur ?
806 _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
807 size_type __l_bucket = __last._M_cur ?
808 _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
810 if (__first._M_cur == __last._M_cur)
812 else if (__f_bucket == __l_bucket)
813 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
815 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
816 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
817 _M_erase_bucket(__n, 0);
818 if (__l_bucket != _M_buckets.size())
819 _M_erase_bucket(__l_bucket, __last._M_cur);
823 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
825 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
826 const_iterator __last)
828 erase(iterator(const_cast<_Node*>(__first._M_cur),
829 const_cast<hashtable*>(__first._M_ht)),
830 iterator(const_cast<_Node*>(__last._M_cur),
831 const_cast<hashtable*>(__last._M_ht)));
834 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
836 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
838 erase(iterator(const_cast<_Node*>(__it._M_cur),
839 const_cast<hashtable*>(__it._M_ht)));
842 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
843 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
844 ::resize(size_type __num_elements_hint)
846 const size_type __old_n = _M_buckets.size();
847 if (__num_elements_hint > __old_n) {
848 const size_type __n = _M_next_size(__num_elements_hint);
850 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
851 _M_buckets.get_allocator());
853 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
854 _Node* __first = _M_buckets[__bucket];
856 size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
857 _M_buckets[__bucket] = __first->_M_next;
858 __first->_M_next = __tmp[__new_bucket];
859 __tmp[__new_bucket] = __first;
860 __first = _M_buckets[__bucket];
863 _M_buckets.swap(__tmp);
865 # ifdef __STL_USE_EXCEPTIONS
867 for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
868 while (__tmp[__bucket]) {
869 _Node* __next = __tmp[__bucket]->_M_next;
870 _M_delete_node(__tmp[__bucket]);
871 __tmp[__bucket] = __next;
876 # endif /* __STL_USE_EXCEPTIONS */
881 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
882 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
883 ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
885 _Node* __cur = _M_buckets[__n];
886 if (__cur == __first)
887 _M_erase_bucket(__n, __last);
890 for (__next = __cur->_M_next;
892 __cur = __next, __next = __cur->_M_next)
894 while (__next != __last) {
895 __cur->_M_next = __next->_M_next;
896 _M_delete_node(__next);
897 __next = __cur->_M_next;
903 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
904 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
905 ::_M_erase_bucket(const size_type __n, _Node* __last)
907 _Node* __cur = _M_buckets[__n];
908 while (__cur != __last) {
909 _Node* __next = __cur->_M_next;
910 _M_delete_node(__cur);
912 _M_buckets[__n] = __cur;
917 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
918 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
920 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
921 _Node* __cur = _M_buckets[__i];
923 _Node* __next = __cur->_M_next;
924 _M_delete_node(__cur);
933 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
934 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
935 ::_M_copy_from(const hashtable& __ht)
938 _M_buckets.reserve(__ht._M_buckets.size());
939 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
941 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
942 const _Node* __cur = __ht._M_buckets[__i];
944 _Node* __local_copy = _M_new_node(__cur->_M_val);
945 _M_buckets[__i] = __local_copy;
947 for (_Node* __next = __cur->_M_next;
949 __cur = __next, __next = __cur->_M_next) {
950 __local_copy->_M_next = _M_new_node(__next->_M_val);
951 __local_copy = __local_copy->_M_next;
955 _M_num_elements = __ht._M_num_elements;
957 __STL_UNWIND(clear());
962 #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */