1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004 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::_Construct
;
85 using std::__iterator_category
;
88 struct _Hashtable_node
90 _Hashtable_node
* _M_next
;
94 template <class _Val
, class _Key
, class _HashFcn
, class _ExtractKey
,
95 class _EqualKey
, class _Alloc
= std::allocator
<_Val
> >
98 template <class _Val
, class _Key
, class _HashFcn
,
99 class _ExtractKey
, class _EqualKey
, class _Alloc
>
100 struct _Hashtable_iterator
;
102 template <class _Val
, class _Key
, class _HashFcn
,
103 class _ExtractKey
, class _EqualKey
, class _Alloc
>
104 struct _Hashtable_const_iterator
;
106 template <class _Val
, class _Key
, class _HashFcn
,
107 class _ExtractKey
, class _EqualKey
, class _Alloc
>
108 struct _Hashtable_iterator
{
109 typedef hashtable
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
111 typedef _Hashtable_iterator
<_Val
, _Key
, _HashFcn
,
112 _ExtractKey
, _EqualKey
, _Alloc
>
114 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
115 _ExtractKey
, _EqualKey
, _Alloc
>
117 typedef _Hashtable_node
<_Val
> _Node
;
119 typedef forward_iterator_tag iterator_category
;
120 typedef _Val value_type
;
121 typedef ptrdiff_t difference_type
;
122 typedef size_t size_type
;
123 typedef _Val
& reference
;
124 typedef _Val
* pointer
;
129 _Hashtable_iterator(_Node
* __n
, _Hashtable
* __tab
)
130 : _M_cur(__n
), _M_ht(__tab
) {}
131 _Hashtable_iterator() {}
132 reference
operator*() const { return _M_cur
->_M_val
; }
133 pointer
operator->() const { return &(operator*()); }
134 iterator
& operator++();
135 iterator
operator++(int);
136 bool operator==(const iterator
& __it
) const
137 { return _M_cur
== __it
._M_cur
; }
138 bool operator!=(const iterator
& __it
) const
139 { return _M_cur
!= __it
._M_cur
; }
143 template <class _Val
, class _Key
, class _HashFcn
,
144 class _ExtractKey
, class _EqualKey
, class _Alloc
>
145 struct _Hashtable_const_iterator
{
146 typedef hashtable
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
148 typedef _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,
149 _ExtractKey
,_EqualKey
,_Alloc
>
151 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
152 _ExtractKey
, _EqualKey
, _Alloc
>
154 typedef _Hashtable_node
<_Val
> _Node
;
156 typedef forward_iterator_tag iterator_category
;
157 typedef _Val value_type
;
158 typedef ptrdiff_t difference_type
;
159 typedef size_t size_type
;
160 typedef const _Val
& reference
;
161 typedef const _Val
* pointer
;
164 const _Hashtable
* _M_ht
;
166 _Hashtable_const_iterator(const _Node
* __n
, const _Hashtable
* __tab
)
167 : _M_cur(__n
), _M_ht(__tab
) {}
168 _Hashtable_const_iterator() {}
169 _Hashtable_const_iterator(const iterator
& __it
)
170 : _M_cur(__it
._M_cur
), _M_ht(__it
._M_ht
) {}
171 reference
operator*() const { return _M_cur
->_M_val
; }
172 pointer
operator->() const { return &(operator*()); }
173 const_iterator
& operator++();
174 const_iterator
operator++(int);
175 bool operator==(const const_iterator
& __it
) const
176 { return _M_cur
== __it
._M_cur
; }
177 bool operator!=(const const_iterator
& __it
) const
178 { return _M_cur
!= __it
._M_cur
; }
181 // Note: assumes long is at least 32 bits.
182 enum { _S_num_primes
= 28 };
184 static const unsigned long __stl_prime_list
[_S_num_primes
] =
186 53ul, 97ul, 193ul, 389ul, 769ul,
187 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
188 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
189 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
190 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
191 1610612741ul, 3221225473ul, 4294967291ul
194 inline unsigned long __stl_next_prime(unsigned long __n
)
196 const unsigned long* __first
= __stl_prime_list
;
197 const unsigned long* __last
= __stl_prime_list
+ (int)_S_num_primes
;
198 const unsigned long* pos
= std::lower_bound(__first
, __last
, __n
);
199 return pos
== __last
? *(__last
- 1) : *pos
;
202 // Forward declaration of operator==.
204 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
207 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
208 bool operator==(const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht1
,
209 const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht2
);
212 // Hashtables handle allocators a bit differently than other
213 // containers do. If we're using standard-conforming allocators, then
214 // a hashtable unconditionally has a member variable to hold its
215 // allocator, even if it so happens that all instances of the
216 // allocator type are identical. This is because, for hashtables,
217 // this extra storage is negligible. Additionally, a base class
218 // wouldn't serve any other purposes; it wouldn't, for example,
219 // simplify the exception-handling code.
221 template <class _Val
, class _Key
, class _HashFcn
,
222 class _ExtractKey
, class _EqualKey
, class _Alloc
>
225 typedef _Key key_type
;
226 typedef _Val value_type
;
227 typedef _HashFcn hasher
;
228 typedef _EqualKey key_equal
;
230 typedef size_t size_type
;
231 typedef ptrdiff_t difference_type
;
232 typedef value_type
* pointer
;
233 typedef const value_type
* const_pointer
;
234 typedef value_type
& reference
;
235 typedef const value_type
& const_reference
;
237 hasher
hash_funct() const { return _M_hash
; }
238 key_equal
key_eq() const { return _M_equals
; }
241 typedef _Hashtable_node
<_Val
> _Node
;
244 typedef _Alloc allocator_type
;
245 allocator_type
get_allocator() const { return _M_node_allocator
; }
247 typedef typename
_Alloc::template rebind
<_Node
>::other _Node_Alloc
;
248 typedef typename
_Alloc::template rebind
<_Node
*>::other _Nodeptr_Alloc
;
249 typedef vector
<_Node
*, _Nodeptr_Alloc
> _Vector_type
;
251 _Node_Alloc _M_node_allocator
;
252 _Node
* _M_get_node() { return _M_node_allocator
.allocate(1); }
253 void _M_put_node(_Node
* __p
) { _M_node_allocator
.deallocate(__p
, 1); }
258 _ExtractKey _M_get_key
;
259 _Vector_type _M_buckets
;
260 size_type _M_num_elements
;
263 typedef _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
265 typedef _Hashtable_const_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,
270 _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>;
272 _Hashtable_const_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>;
275 hashtable(size_type __n
,
276 const _HashFcn
& __hf
,
277 const _EqualKey
& __eql
,
278 const _ExtractKey
& __ext
,
279 const allocator_type
& __a
= allocator_type())
280 : _M_node_allocator(__a
),
287 _M_initialize_buckets(__n
);
290 hashtable(size_type __n
,
291 const _HashFcn
& __hf
,
292 const _EqualKey
& __eql
,
293 const allocator_type
& __a
= allocator_type())
294 : _M_node_allocator(__a
),
297 _M_get_key(_ExtractKey()),
301 _M_initialize_buckets(__n
);
304 hashtable(const hashtable
& __ht
)
305 : _M_node_allocator(__ht
.get_allocator()),
306 _M_hash(__ht
._M_hash
),
307 _M_equals(__ht
._M_equals
),
308 _M_get_key(__ht
._M_get_key
),
309 _M_buckets(__ht
.get_allocator()),
315 hashtable
& operator= (const hashtable
& __ht
)
319 _M_hash
= __ht
._M_hash
;
320 _M_equals
= __ht
._M_equals
;
321 _M_get_key
= __ht
._M_get_key
;
327 ~hashtable() { clear(); }
329 size_type
size() const { return _M_num_elements
; }
330 size_type
max_size() const { return size_type(-1); }
331 bool empty() const { return size() == 0; }
333 void swap(hashtable
& __ht
)
335 std::swap(_M_hash
, __ht
._M_hash
);
336 std::swap(_M_equals
, __ht
._M_equals
);
337 std::swap(_M_get_key
, __ht
._M_get_key
);
338 _M_buckets
.swap(__ht
._M_buckets
);
339 std::swap(_M_num_elements
, __ht
._M_num_elements
);
344 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
346 return iterator(_M_buckets
[__n
], this);
350 iterator
end() { return iterator(0, this); }
352 const_iterator
begin() const
354 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
356 return const_iterator(_M_buckets
[__n
], this);
360 const_iterator
end() const { return const_iterator(0, this); }
362 template <class _Vl
, class _Ky
, class _HF
, class _Ex
, class _Eq
, class _Al
>
363 friend bool operator== (const hashtable
<_Vl
, _Ky
, _HF
, _Ex
, _Eq
, _Al
>&,
364 const hashtable
<_Vl
, _Ky
, _HF
, _Ex
, _Eq
, _Al
>&);
367 size_type
bucket_count() const { return _M_buckets
.size(); }
369 size_type
max_bucket_count() const
370 { return __stl_prime_list
[(int)_S_num_primes
- 1]; }
372 size_type
elems_in_bucket(size_type __bucket
) const
374 size_type __result
= 0;
375 for (_Node
* __cur
= _M_buckets
[__bucket
]; __cur
; __cur
= __cur
->_M_next
)
380 pair
<iterator
, bool> insert_unique(const value_type
& __obj
)
382 resize(_M_num_elements
+ 1);
383 return insert_unique_noresize(__obj
);
386 iterator
insert_equal(const value_type
& __obj
)
388 resize(_M_num_elements
+ 1);
389 return insert_equal_noresize(__obj
);
392 pair
<iterator
, bool> insert_unique_noresize(const value_type
& __obj
);
393 iterator
insert_equal_noresize(const value_type
& __obj
);
395 template <class _InputIterator
>
396 void insert_unique(_InputIterator __f
, _InputIterator __l
)
398 insert_unique(__f
, __l
, __iterator_category(__f
));
401 template <class _InputIterator
>
402 void insert_equal(_InputIterator __f
, _InputIterator __l
)
404 insert_equal(__f
, __l
, __iterator_category(__f
));
407 template <class _InputIterator
>
408 void insert_unique(_InputIterator __f
, _InputIterator __l
,
411 for ( ; __f
!= __l
; ++__f
)
415 template <class _InputIterator
>
416 void insert_equal(_InputIterator __f
, _InputIterator __l
,
419 for ( ; __f
!= __l
; ++__f
)
423 template <class _ForwardIterator
>
424 void insert_unique(_ForwardIterator __f
, _ForwardIterator __l
,
425 forward_iterator_tag
)
427 size_type __n
= distance(__f
, __l
);
428 resize(_M_num_elements
+ __n
);
429 for ( ; __n
> 0; --__n
, ++__f
)
430 insert_unique_noresize(*__f
);
433 template <class _ForwardIterator
>
434 void insert_equal(_ForwardIterator __f
, _ForwardIterator __l
,
435 forward_iterator_tag
)
437 size_type __n
= distance(__f
, __l
);
438 resize(_M_num_elements
+ __n
);
439 for ( ; __n
> 0; --__n
, ++__f
)
440 insert_equal_noresize(*__f
);
443 reference
find_or_insert(const value_type
& __obj
);
445 iterator
find(const key_type
& __key
)
447 size_type __n
= _M_bkt_num_key(__key
);
449 for ( __first
= _M_buckets
[__n
];
450 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
451 __first
= __first
->_M_next
)
453 return iterator(__first
, this);
456 const_iterator
find(const key_type
& __key
) const
458 size_type __n
= _M_bkt_num_key(__key
);
459 const _Node
* __first
;
460 for ( __first
= _M_buckets
[__n
];
461 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
462 __first
= __first
->_M_next
)
464 return const_iterator(__first
, this);
467 size_type
count(const key_type
& __key
) const
469 const size_type __n
= _M_bkt_num_key(__key
);
470 size_type __result
= 0;
472 for (const _Node
* __cur
= _M_buckets
[__n
]; __cur
; __cur
= __cur
->_M_next
)
473 if (_M_equals(_M_get_key(__cur
->_M_val
), __key
))
478 pair
<iterator
, iterator
>
479 equal_range(const key_type
& __key
);
481 pair
<const_iterator
, const_iterator
>
482 equal_range(const key_type
& __key
) const;
484 size_type
erase(const key_type
& __key
);
485 void erase(const iterator
& __it
);
486 void erase(iterator __first
, iterator __last
);
488 void erase(const const_iterator
& __it
);
489 void erase(const_iterator __first
, const_iterator __last
);
491 void resize(size_type __num_elements_hint
);
495 size_type
_M_next_size(size_type __n
) const
496 { return __stl_next_prime(__n
); }
498 void _M_initialize_buckets(size_type __n
)
500 const size_type __n_buckets
= _M_next_size(__n
);
501 _M_buckets
.reserve(__n_buckets
);
502 _M_buckets
.insert(_M_buckets
.end(), __n_buckets
, (_Node
*) 0);
506 size_type
_M_bkt_num_key(const key_type
& __key
) const
508 return _M_bkt_num_key(__key
, _M_buckets
.size());
511 size_type
_M_bkt_num(const value_type
& __obj
) const
513 return _M_bkt_num_key(_M_get_key(__obj
));
516 size_type
_M_bkt_num_key(const key_type
& __key
, size_t __n
) const
518 return _M_hash(__key
) % __n
;
521 size_type
_M_bkt_num(const value_type
& __obj
, size_t __n
) const
523 return _M_bkt_num_key(_M_get_key(__obj
), __n
);
526 _Node
* _M_new_node(const value_type
& __obj
)
528 _Node
* __n
= _M_get_node();
531 _Construct(&__n
->_M_val
, __obj
);
537 __throw_exception_again
;
541 void _M_delete_node(_Node
* __n
)
543 _Destroy(&__n
->_M_val
);
547 void _M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
);
548 void _M_erase_bucket(const size_type __n
, _Node
* __last
);
550 void _M_copy_from(const hashtable
& __ht
);
554 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
556 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&
557 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++()
559 const _Node
* __old
= _M_cur
;
560 _M_cur
= _M_cur
->_M_next
;
562 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
563 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
564 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
569 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
571 inline _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>
572 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++(int)
574 iterator __tmp
= *this;
579 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
581 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&
582 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++()
584 const _Node
* __old
= _M_cur
;
585 _M_cur
= _M_cur
->_M_next
;
587 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
588 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
589 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
594 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
596 inline _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>
597 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++(int)
599 const_iterator __tmp
= *this;
604 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
605 bool operator==(const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht1
,
606 const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht2
)
608 typedef typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::_Node _Node
;
609 if (__ht1
._M_buckets
.size() != __ht2
._M_buckets
.size())
611 for (size_t __n
= 0; __n
< __ht1
._M_buckets
.size(); ++__n
) {
612 _Node
* __cur1
= __ht1
._M_buckets
[__n
];
613 _Node
* __cur2
= __ht2
._M_buckets
[__n
];
614 // Check same length of lists
615 for ( ; __cur1
&& __cur2
;
616 __cur1
= __cur1
->_M_next
, __cur2
= __cur2
->_M_next
)
618 if (__cur1
|| __cur2
)
620 // Now check one's elements are in the other
621 for (__cur1
= __ht1
._M_buckets
[__n
] ; __cur1
; __cur1
= __cur1
->_M_next
)
623 bool _found__cur1
= false;
624 for (_Node
* __cur2
= __ht2
._M_buckets
[__n
];
625 __cur2
; __cur2
= __cur2
->_M_next
)
627 if (__cur1
->_M_val
== __cur2
->_M_val
)
640 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
641 inline bool operator!=(const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht1
,
642 const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht2
) {
643 return !(__ht1
== __ht2
);
646 template <class _Val
, class _Key
, class _HF
, class _Extract
, class _EqKey
,
648 inline void swap(hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht1
,
649 hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht2
) {
654 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
655 pair
<typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
, bool>
656 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
657 ::insert_unique_noresize(const value_type
& __obj
)
659 const size_type __n
= _M_bkt_num(__obj
);
660 _Node
* __first
= _M_buckets
[__n
];
662 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
663 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
664 return pair
<iterator
, bool>(iterator(__cur
, this), false);
666 _Node
* __tmp
= _M_new_node(__obj
);
667 __tmp
->_M_next
= __first
;
668 _M_buckets
[__n
] = __tmp
;
670 return pair
<iterator
, bool>(iterator(__tmp
, this), true);
673 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
674 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
675 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
676 ::insert_equal_noresize(const value_type
& __obj
)
678 const size_type __n
= _M_bkt_num(__obj
);
679 _Node
* __first
= _M_buckets
[__n
];
681 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
682 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
))) {
683 _Node
* __tmp
= _M_new_node(__obj
);
684 __tmp
->_M_next
= __cur
->_M_next
;
685 __cur
->_M_next
= __tmp
;
687 return iterator(__tmp
, this);
690 _Node
* __tmp
= _M_new_node(__obj
);
691 __tmp
->_M_next
= __first
;
692 _M_buckets
[__n
] = __tmp
;
694 return iterator(__tmp
, this);
697 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
698 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::reference
699 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::find_or_insert(const value_type
& __obj
)
701 resize(_M_num_elements
+ 1);
703 size_type __n
= _M_bkt_num(__obj
);
704 _Node
* __first
= _M_buckets
[__n
];
706 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
707 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
708 return __cur
->_M_val
;
710 _Node
* __tmp
= _M_new_node(__obj
);
711 __tmp
->_M_next
= __first
;
712 _M_buckets
[__n
] = __tmp
;
714 return __tmp
->_M_val
;
717 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
718 pair
<typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
,
719 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
>
720 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::equal_range(const key_type
& __key
)
722 typedef pair
<iterator
, iterator
> _Pii
;
723 const size_type __n
= _M_bkt_num_key(__key
);
725 for (_Node
* __first
= _M_buckets
[__n
]; __first
; __first
= __first
->_M_next
)
726 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
727 for (_Node
* __cur
= __first
->_M_next
; __cur
; __cur
= __cur
->_M_next
)
728 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
729 return _Pii(iterator(__first
, this), iterator(__cur
, this));
730 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
732 return _Pii(iterator(__first
, this),
733 iterator(_M_buckets
[__m
], this));
734 return _Pii(iterator(__first
, this), end());
736 return _Pii(end(), end());
739 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
740 pair
<typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::const_iterator
,
741 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::const_iterator
>
742 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
743 ::equal_range(const key_type
& __key
) const
745 typedef pair
<const_iterator
, const_iterator
> _Pii
;
746 const size_type __n
= _M_bkt_num_key(__key
);
748 for (const _Node
* __first
= _M_buckets
[__n
] ;
750 __first
= __first
->_M_next
) {
751 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
752 for (const _Node
* __cur
= __first
->_M_next
;
754 __cur
= __cur
->_M_next
)
755 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
756 return _Pii(const_iterator(__first
, this),
757 const_iterator(__cur
, this));
758 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
760 return _Pii(const_iterator(__first
, this),
761 const_iterator(_M_buckets
[__m
], this));
762 return _Pii(const_iterator(__first
, this), end());
765 return _Pii(end(), end());
768 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
769 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::size_type
770 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const key_type
& __key
)
772 const size_type __n
= _M_bkt_num_key(__key
);
773 _Node
* __first
= _M_buckets
[__n
];
774 size_type __erased
= 0;
777 _Node
* __cur
= __first
;
778 _Node
* __next
= __cur
->_M_next
;
780 if (_M_equals(_M_get_key(__next
->_M_val
), __key
)) {
781 __cur
->_M_next
= __next
->_M_next
;
782 _M_delete_node(__next
);
783 __next
= __cur
->_M_next
;
789 __next
= __cur
->_M_next
;
792 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
793 _M_buckets
[__n
] = __first
->_M_next
;
794 _M_delete_node(__first
);
802 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
803 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const iterator
& __it
)
805 _Node
* __p
= __it
._M_cur
;
807 const size_type __n
= _M_bkt_num(__p
->_M_val
);
808 _Node
* __cur
= _M_buckets
[__n
];
811 _M_buckets
[__n
] = __cur
->_M_next
;
812 _M_delete_node(__cur
);
816 _Node
* __next
= __cur
->_M_next
;
819 __cur
->_M_next
= __next
->_M_next
;
820 _M_delete_node(__next
);
826 __next
= __cur
->_M_next
;
833 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
834 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
835 ::erase(iterator __first
, iterator __last
)
837 size_type __f_bucket
= __first
._M_cur
?
838 _M_bkt_num(__first
._M_cur
->_M_val
) : _M_buckets
.size();
839 size_type __l_bucket
= __last
._M_cur
?
840 _M_bkt_num(__last
._M_cur
->_M_val
) : _M_buckets
.size();
842 if (__first
._M_cur
== __last
._M_cur
)
844 else if (__f_bucket
== __l_bucket
)
845 _M_erase_bucket(__f_bucket
, __first
._M_cur
, __last
._M_cur
);
847 _M_erase_bucket(__f_bucket
, __first
._M_cur
, 0);
848 for (size_type __n
= __f_bucket
+ 1; __n
< __l_bucket
; ++__n
)
849 _M_erase_bucket(__n
, 0);
850 if (__l_bucket
!= _M_buckets
.size())
851 _M_erase_bucket(__l_bucket
, __last
._M_cur
);
855 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
857 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const_iterator __first
,
858 const_iterator __last
)
860 erase(iterator(const_cast<_Node
*>(__first
._M_cur
),
861 const_cast<hashtable
*>(__first
._M_ht
)),
862 iterator(const_cast<_Node
*>(__last
._M_cur
),
863 const_cast<hashtable
*>(__last
._M_ht
)));
866 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
868 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const const_iterator
& __it
)
870 erase(iterator(const_cast<_Node
*>(__it
._M_cur
),
871 const_cast<hashtable
*>(__it
._M_ht
)));
874 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
875 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
876 ::resize(size_type __num_elements_hint
)
878 const size_type __old_n
= _M_buckets
.size();
879 if (__num_elements_hint
> __old_n
) {
880 const size_type __n
= _M_next_size(__num_elements_hint
);
882 _Vector_type
__tmp(__n
, (_Node
*)(0), _M_buckets
.get_allocator());
884 for (size_type __bucket
= 0; __bucket
< __old_n
; ++__bucket
) {
885 _Node
* __first
= _M_buckets
[__bucket
];
887 size_type __new_bucket
= _M_bkt_num(__first
->_M_val
, __n
);
888 _M_buckets
[__bucket
] = __first
->_M_next
;
889 __first
->_M_next
= __tmp
[__new_bucket
];
890 __tmp
[__new_bucket
] = __first
;
891 __first
= _M_buckets
[__bucket
];
894 _M_buckets
.swap(__tmp
);
897 for (size_type __bucket
= 0; __bucket
< __tmp
.size(); ++__bucket
) {
898 while (__tmp
[__bucket
]) {
899 _Node
* __next
= __tmp
[__bucket
]->_M_next
;
900 _M_delete_node(__tmp
[__bucket
]);
901 __tmp
[__bucket
] = __next
;
904 __throw_exception_again
;
910 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
911 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
912 ::_M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
)
914 _Node
* __cur
= _M_buckets
[__n
];
915 if (__cur
== __first
)
916 _M_erase_bucket(__n
, __last
);
919 for (__next
= __cur
->_M_next
;
921 __cur
= __next
, __next
= __cur
->_M_next
)
923 while (__next
!= __last
) {
924 __cur
->_M_next
= __next
->_M_next
;
925 _M_delete_node(__next
);
926 __next
= __cur
->_M_next
;
932 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
933 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
934 ::_M_erase_bucket(const size_type __n
, _Node
* __last
)
936 _Node
* __cur
= _M_buckets
[__n
];
937 while (__cur
!= __last
) {
938 _Node
* __next
= __cur
->_M_next
;
939 _M_delete_node(__cur
);
941 _M_buckets
[__n
] = __cur
;
946 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
947 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::clear()
949 for (size_type __i
= 0; __i
< _M_buckets
.size(); ++__i
) {
950 _Node
* __cur
= _M_buckets
[__i
];
952 _Node
* __next
= __cur
->_M_next
;
953 _M_delete_node(__cur
);
962 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
963 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
964 ::_M_copy_from(const hashtable
& __ht
)
967 _M_buckets
.reserve(__ht
._M_buckets
.size());
968 _M_buckets
.insert(_M_buckets
.end(), __ht
._M_buckets
.size(), (_Node
*) 0);
970 for (size_type __i
= 0; __i
< __ht
._M_buckets
.size(); ++__i
) {
971 const _Node
* __cur
= __ht
._M_buckets
[__i
];
973 _Node
* __local_copy
= _M_new_node(__cur
->_M_val
);
974 _M_buckets
[__i
] = __local_copy
;
976 for (_Node
* __next
= __cur
->_M_next
;
978 __cur
= __next
, __next
= __cur
->_M_next
) {
979 __local_copy
->_M_next
= _M_new_node(__next
->_M_val
);
980 __local_copy
= __local_copy
->_M_next
;
984 _M_num_elements
= __ht
._M_num_elements
;
989 __throw_exception_again
;
992 } // namespace __gnu_cxx