1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001-2017 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 3, 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 // Under Section 7 of GPL version 3, you are granted additional
17 // permissions described in the GCC Runtime Library Exception, version
18 // 3.1, as published by the Free Software Foundation.
20 // You should have received a copy of the GNU General Public License and
21 // a copy of the GCC Runtime Library Exception along with this program;
22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23 // <http://www.gnu.org/licenses/>.
26 * Copyright (c) 1996,1997
27 * Silicon Graphics Computer Systems, Inc.
29 * Permission to use, copy, modify, distribute and sell this software
30 * and its documentation for any purpose is hereby granted without fee,
31 * provided that the above copyright notice appear in all copies and
32 * that both that copyright notice and this permission notice appear
33 * in supporting documentation. Silicon Graphics makes no
34 * representations about the suitability of this software for any
35 * purpose. It is provided "as is" without express or implied warranty.
39 * Hewlett-Packard Company
41 * Permission to use, copy, modify, distribute and sell this software
42 * and its documentation for any purpose is hereby granted without fee,
43 * provided that the above copyright notice appear in all copies and
44 * that both that copyright notice and this permission notice appear
45 * in supporting documentation. Hewlett-Packard Company makes no
46 * representations about the suitability of this software for any
47 * purpose. It is provided "as is" without express or implied warranty.
51 /** @file backward/hashtable.h
52 * This file is a GNU extension to the Standard C++ Library (possibly
53 * containing extensions from the HP/SGI STL subset).
56 #ifndef _BACKWARD_HASHTABLE_H
57 #define _BACKWARD_HASHTABLE_H 1
59 // Hashtable class, used to implement the hashed associative containers
60 // hash_set, hash_map, hash_multiset, and hash_multimap.
65 #include <bits/stl_function.h>
66 #include <backward/hash_fun.h>
68 namespace __gnu_cxx
_GLIBCXX_VISIBILITY(default)
70 _GLIBCXX_BEGIN_NAMESPACE_VERSION
74 using std::forward_iterator_tag
;
75 using std::input_iterator_tag
;
76 using std::_Construct
;
81 using std::__iterator_category
;
84 struct _Hashtable_node
86 _Hashtable_node
* _M_next
;
90 template<class _Val
, class _Key
, class _HashFcn
, class _ExtractKey
,
91 class _EqualKey
, class _Alloc
= std::allocator
<_Val
> >
94 template<class _Val
, class _Key
, class _HashFcn
,
95 class _ExtractKey
, class _EqualKey
, class _Alloc
>
96 struct _Hashtable_iterator
;
98 template<class _Val
, class _Key
, class _HashFcn
,
99 class _ExtractKey
, class _EqualKey
, class _Alloc
>
100 struct _Hashtable_const_iterator
;
102 template<class _Val
, class _Key
, class _HashFcn
,
103 class _ExtractKey
, class _EqualKey
, class _Alloc
>
104 struct _Hashtable_iterator
106 typedef hashtable
<_Val
, _Key
, _HashFcn
, _ExtractKey
, _EqualKey
, _Alloc
>
108 typedef _Hashtable_iterator
<_Val
, _Key
, _HashFcn
,
109 _ExtractKey
, _EqualKey
, _Alloc
>
111 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
112 _ExtractKey
, _EqualKey
, _Alloc
>
114 typedef _Hashtable_node
<_Val
> _Node
;
115 typedef forward_iterator_tag iterator_category
;
116 typedef _Val value_type
;
117 typedef ptrdiff_t difference_type
;
118 typedef size_t size_type
;
119 typedef _Val
& reference
;
120 typedef _Val
* pointer
;
125 _Hashtable_iterator(_Node
* __n
, _Hashtable
* __tab
)
126 : _M_cur(__n
), _M_ht(__tab
) { }
128 _Hashtable_iterator() { }
132 { return _M_cur
->_M_val
; }
136 { return &(operator*()); }
145 operator==(const iterator
& __it
) const
146 { return _M_cur
== __it
._M_cur
; }
149 operator!=(const iterator
& __it
) const
150 { return _M_cur
!= __it
._M_cur
; }
153 template<class _Val
, class _Key
, class _HashFcn
,
154 class _ExtractKey
, class _EqualKey
, class _Alloc
>
155 struct _Hashtable_const_iterator
157 typedef hashtable
<_Val
, _Key
, _HashFcn
, _ExtractKey
, _EqualKey
, _Alloc
>
159 typedef _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,
160 _ExtractKey
,_EqualKey
,_Alloc
>
162 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
163 _ExtractKey
, _EqualKey
, _Alloc
>
165 typedef _Hashtable_node
<_Val
> _Node
;
167 typedef forward_iterator_tag iterator_category
;
168 typedef _Val value_type
;
169 typedef ptrdiff_t difference_type
;
170 typedef size_t size_type
;
171 typedef const _Val
& reference
;
172 typedef const _Val
* pointer
;
175 const _Hashtable
* _M_ht
;
177 _Hashtable_const_iterator(const _Node
* __n
, const _Hashtable
* __tab
)
178 : _M_cur(__n
), _M_ht(__tab
) { }
180 _Hashtable_const_iterator() { }
182 _Hashtable_const_iterator(const iterator
& __it
)
183 : _M_cur(__it
._M_cur
), _M_ht(__it
._M_ht
) { }
187 { return _M_cur
->_M_val
; }
191 { return &(operator*()); }
200 operator==(const const_iterator
& __it
) const
201 { return _M_cur
== __it
._M_cur
; }
204 operator!=(const const_iterator
& __it
) const
205 { return _M_cur
!= __it
._M_cur
; }
208 // Note: assumes long is at least 32 bits.
209 enum { _S_num_primes
= 29 };
211 template<typename _PrimeType
>
212 struct _Hashtable_prime_list
214 static const _PrimeType __stl_prime_list
[_S_num_primes
];
216 static const _PrimeType
*
220 template<typename _PrimeType
> const _PrimeType
221 _Hashtable_prime_list
<_PrimeType
>::__stl_prime_list
[_S_num_primes
] =
223 5ul, 53ul, 97ul, 193ul, 389ul,
224 769ul, 1543ul, 3079ul, 6151ul, 12289ul,
225 24593ul, 49157ul, 98317ul, 196613ul, 393241ul,
226 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul,
227 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul,
228 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul
231 template<class _PrimeType
> inline const _PrimeType
*
232 _Hashtable_prime_list
<_PrimeType
>::_S_get_prime_list()
234 return __stl_prime_list
;
238 __stl_next_prime(unsigned long __n
)
240 const unsigned long* __first
= _Hashtable_prime_list
<unsigned long>::_S_get_prime_list();
241 const unsigned long* __last
= __first
+ (int)_S_num_primes
;
242 const unsigned long* pos
= std::lower_bound(__first
, __last
, __n
);
243 return pos
== __last
? *(__last
- 1) : *pos
;
246 // Forward declaration of operator==.
247 template<class _Val
, class _Key
, class _HF
, class _Ex
,
248 class _Eq
, class _All
>
251 template<class _Val
, class _Key
, class _HF
, class _Ex
,
252 class _Eq
, class _All
>
254 operator==(const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht1
,
255 const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht2
);
257 // Hashtables handle allocators a bit differently than other
258 // containers do. If we're using standard-conforming allocators, then
259 // a hashtable unconditionally has a member variable to hold its
260 // allocator, even if it so happens that all instances of the
261 // allocator type are identical. This is because, for hashtables,
262 // this extra storage is negligible. Additionally, a base class
263 // wouldn't serve any other purposes; it wouldn't, for example,
264 // simplify the exception-handling code.
265 template<class _Val
, class _Key
, class _HashFcn
,
266 class _ExtractKey
, class _EqualKey
, class _Alloc
>
270 typedef _Key key_type
;
271 typedef _Val value_type
;
272 typedef _HashFcn hasher
;
273 typedef _EqualKey key_equal
;
275 typedef size_t size_type
;
276 typedef ptrdiff_t difference_type
;
277 typedef value_type
* pointer
;
278 typedef const value_type
* const_pointer
;
279 typedef value_type
& reference
;
280 typedef const value_type
& const_reference
;
288 { return _M_equals
; }
291 typedef _Hashtable_node
<_Val
> _Node
;
294 typedef typename
_Alloc::template rebind
<value_type
>::other allocator_type
;
296 get_allocator() const
297 { return _M_node_allocator
; }
300 typedef typename
_Alloc::template rebind
<_Node
>::other _Node_Alloc
;
301 typedef typename
_Alloc::template rebind
<_Node
*>::other _Nodeptr_Alloc
;
302 typedef vector
<_Node
*, _Nodeptr_Alloc
> _Vector_type
;
304 _Node_Alloc _M_node_allocator
;
308 { return _M_node_allocator
.allocate(1); }
311 _M_put_node(_Node
* __p
)
312 { _M_node_allocator
.deallocate(__p
, 1); }
317 _ExtractKey _M_get_key
;
318 _Vector_type _M_buckets
;
319 size_type _M_num_elements
;
322 typedef _Hashtable_iterator
<_Val
, _Key
, _HashFcn
, _ExtractKey
,
325 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
, _ExtractKey
,
330 _Hashtable_iterator
<_Val
, _Key
, _HashFcn
, _ExtractKey
, _EqualKey
, _Alloc
>;
333 _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
, _ExtractKey
,
337 hashtable(size_type __n
, const _HashFcn
& __hf
,
338 const _EqualKey
& __eql
, const _ExtractKey
& __ext
,
339 const allocator_type
& __a
= allocator_type())
340 : _M_node_allocator(__a
), _M_hash(__hf
), _M_equals(__eql
),
341 _M_get_key(__ext
), _M_buckets(__a
), _M_num_elements(0)
342 { _M_initialize_buckets(__n
); }
344 hashtable(size_type __n
, const _HashFcn
& __hf
,
345 const _EqualKey
& __eql
,
346 const allocator_type
& __a
= allocator_type())
347 : _M_node_allocator(__a
), _M_hash(__hf
), _M_equals(__eql
),
348 _M_get_key(_ExtractKey()), _M_buckets(__a
), _M_num_elements(0)
349 { _M_initialize_buckets(__n
); }
351 hashtable(const hashtable
& __ht
)
352 : _M_node_allocator(__ht
.get_allocator()), _M_hash(__ht
._M_hash
),
353 _M_equals(__ht
._M_equals
), _M_get_key(__ht
._M_get_key
),
354 _M_buckets(__ht
.get_allocator()), _M_num_elements(0)
355 { _M_copy_from(__ht
); }
358 operator= (const hashtable
& __ht
)
363 _M_hash
= __ht
._M_hash
;
364 _M_equals
= __ht
._M_equals
;
365 _M_get_key
= __ht
._M_get_key
;
376 { return _M_num_elements
; }
380 { return size_type(-1); }
384 { return size() == 0; }
387 swap(hashtable
& __ht
)
389 std::swap(_M_hash
, __ht
._M_hash
);
390 std::swap(_M_equals
, __ht
._M_equals
);
391 std::swap(_M_get_key
, __ht
._M_get_key
);
392 _M_buckets
.swap(__ht
._M_buckets
);
393 std::swap(_M_num_elements
, __ht
._M_num_elements
);
399 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
401 return iterator(_M_buckets
[__n
], this);
407 { return iterator(0, this); }
412 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
414 return const_iterator(_M_buckets
[__n
], this);
420 { return const_iterator(0, this); }
422 template<class _Vl
, class _Ky
, class _HF
, class _Ex
, class _Eq
,
425 operator==(const hashtable
<_Vl
, _Ky
, _HF
, _Ex
, _Eq
, _Al
>&,
426 const hashtable
<_Vl
, _Ky
, _HF
, _Ex
, _Eq
, _Al
>&);
431 { return _M_buckets
.size(); }
434 max_bucket_count() const
435 { return _Hashtable_prime_list
<unsigned long>::
436 _S_get_prime_list()[(int)_S_num_primes
- 1];
440 elems_in_bucket(size_type __bucket
) const
442 size_type __result
= 0;
443 for (_Node
* __n
= _M_buckets
[__bucket
]; __n
; __n
= __n
->_M_next
)
449 insert_unique(const value_type
& __obj
)
451 resize(_M_num_elements
+ 1);
452 return insert_unique_noresize(__obj
);
456 insert_equal(const value_type
& __obj
)
458 resize(_M_num_elements
+ 1);
459 return insert_equal_noresize(__obj
);
463 insert_unique_noresize(const value_type
& __obj
);
466 insert_equal_noresize(const value_type
& __obj
);
468 template<class _InputIterator
>
470 insert_unique(_InputIterator __f
, _InputIterator __l
)
471 { insert_unique(__f
, __l
, __iterator_category(__f
)); }
473 template<class _InputIterator
>
475 insert_equal(_InputIterator __f
, _InputIterator __l
)
476 { insert_equal(__f
, __l
, __iterator_category(__f
)); }
478 template<class _InputIterator
>
480 insert_unique(_InputIterator __f
, _InputIterator __l
,
483 for ( ; __f
!= __l
; ++__f
)
487 template<class _InputIterator
>
489 insert_equal(_InputIterator __f
, _InputIterator __l
,
492 for ( ; __f
!= __l
; ++__f
)
496 template<class _ForwardIterator
>
498 insert_unique(_ForwardIterator __f
, _ForwardIterator __l
,
499 forward_iterator_tag
)
501 size_type __n
= distance(__f
, __l
);
502 resize(_M_num_elements
+ __n
);
503 for ( ; __n
> 0; --__n
, ++__f
)
504 insert_unique_noresize(*__f
);
507 template<class _ForwardIterator
>
509 insert_equal(_ForwardIterator __f
, _ForwardIterator __l
,
510 forward_iterator_tag
)
512 size_type __n
= distance(__f
, __l
);
513 resize(_M_num_elements
+ __n
);
514 for ( ; __n
> 0; --__n
, ++__f
)
515 insert_equal_noresize(*__f
);
519 find_or_insert(const value_type
& __obj
);
522 find(const key_type
& __key
)
524 size_type __n
= _M_bkt_num_key(__key
);
526 for (__first
= _M_buckets
[__n
];
527 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
528 __first
= __first
->_M_next
)
530 return iterator(__first
, this);
534 find(const key_type
& __key
) const
536 size_type __n
= _M_bkt_num_key(__key
);
537 const _Node
* __first
;
538 for (__first
= _M_buckets
[__n
];
539 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
540 __first
= __first
->_M_next
)
542 return const_iterator(__first
, this);
546 count(const key_type
& __key
) const
548 const size_type __n
= _M_bkt_num_key(__key
);
549 size_type __result
= 0;
551 for (const _Node
* __cur
= _M_buckets
[__n
]; __cur
;
552 __cur
= __cur
->_M_next
)
553 if (_M_equals(_M_get_key(__cur
->_M_val
), __key
))
558 pair
<iterator
, iterator
>
559 equal_range(const key_type
& __key
);
561 pair
<const_iterator
, const_iterator
>
562 equal_range(const key_type
& __key
) const;
565 erase(const key_type
& __key
);
568 erase(const iterator
& __it
);
571 erase(iterator __first
, iterator __last
);
574 erase(const const_iterator
& __it
);
577 erase(const_iterator __first
, const_iterator __last
);
580 resize(size_type __num_elements_hint
);
587 _M_next_size(size_type __n
) const
588 { return __stl_next_prime(__n
); }
591 _M_initialize_buckets(size_type __n
)
593 const size_type __n_buckets
= _M_next_size(__n
);
594 _M_buckets
.reserve(__n_buckets
);
595 _M_buckets
.insert(_M_buckets
.end(), __n_buckets
, (_Node
*) 0);
600 _M_bkt_num_key(const key_type
& __key
) const
601 { return _M_bkt_num_key(__key
, _M_buckets
.size()); }
604 _M_bkt_num(const value_type
& __obj
) const
605 { return _M_bkt_num_key(_M_get_key(__obj
)); }
608 _M_bkt_num_key(const key_type
& __key
, size_t __n
) const
609 { return _M_hash(__key
) % __n
; }
612 _M_bkt_num(const value_type
& __obj
, size_t __n
) const
613 { return _M_bkt_num_key(_M_get_key(__obj
), __n
); }
616 _M_new_node(const value_type
& __obj
)
618 _Node
* __n
= _M_get_node();
622 this->get_allocator().construct(&__n
->_M_val
, __obj
);
628 __throw_exception_again
;
633 _M_delete_node(_Node
* __n
)
635 this->get_allocator().destroy(&__n
->_M_val
);
640 _M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
);
643 _M_erase_bucket(const size_type __n
, _Node
* __last
);
646 _M_copy_from(const hashtable
& __ht
);
649 template<class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
651 _Hashtable_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>&
652 _Hashtable_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>::
655 const _Node
* __old
= _M_cur
;
656 _M_cur
= _M_cur
->_M_next
;
659 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
660 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
661 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
666 template<class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
668 inline _Hashtable_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>
669 _Hashtable_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>::
672 iterator __tmp
= *this;
677 template<class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
679 _Hashtable_const_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>&
680 _Hashtable_const_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>::
683 const _Node
* __old
= _M_cur
;
684 _M_cur
= _M_cur
->_M_next
;
687 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
688 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
689 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
694 template<class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
696 inline _Hashtable_const_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>
697 _Hashtable_const_iterator
<_Val
, _Key
, _HF
, _ExK
, _EqK
, _All
>::
700 const_iterator __tmp
= *this;
705 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
707 operator==(const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht1
,
708 const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht2
)
710 typedef typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::_Node _Node
;
712 if (__ht1
._M_buckets
.size() != __ht2
._M_buckets
.size())
715 for (size_t __n
= 0; __n
< __ht1
._M_buckets
.size(); ++__n
)
717 _Node
* __cur1
= __ht1
._M_buckets
[__n
];
718 _Node
* __cur2
= __ht2
._M_buckets
[__n
];
719 // Check same length of lists
720 for (; __cur1
&& __cur2
;
721 __cur1
= __cur1
->_M_next
, __cur2
= __cur2
->_M_next
)
723 if (__cur1
|| __cur2
)
725 // Now check one's elements are in the other
726 for (__cur1
= __ht1
._M_buckets
[__n
] ; __cur1
;
727 __cur1
= __cur1
->_M_next
)
729 bool _found__cur1
= false;
730 for (__cur2
= __ht2
._M_buckets
[__n
];
731 __cur2
; __cur2
= __cur2
->_M_next
)
733 if (__cur1
->_M_val
== __cur2
->_M_val
)
746 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
748 operator!=(const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht1
,
749 const hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>& __ht2
)
750 { return !(__ht1
== __ht2
); }
752 template<class _Val
, class _Key
, class _HF
, class _Extract
, class _EqKey
,
755 swap(hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht1
,
756 hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht2
)
757 { __ht1
.swap(__ht2
); }
759 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
760 pair
<typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::iterator
, bool>
761 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
762 insert_unique_noresize(const value_type
& __obj
)
764 const size_type __n
= _M_bkt_num(__obj
);
765 _Node
* __first
= _M_buckets
[__n
];
767 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
768 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
769 return pair
<iterator
, bool>(iterator(__cur
, this), false);
771 _Node
* __tmp
= _M_new_node(__obj
);
772 __tmp
->_M_next
= __first
;
773 _M_buckets
[__n
] = __tmp
;
775 return pair
<iterator
, bool>(iterator(__tmp
, this), true);
778 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
779 typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::iterator
780 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
781 insert_equal_noresize(const value_type
& __obj
)
783 const size_type __n
= _M_bkt_num(__obj
);
784 _Node
* __first
= _M_buckets
[__n
];
786 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
787 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
789 _Node
* __tmp
= _M_new_node(__obj
);
790 __tmp
->_M_next
= __cur
->_M_next
;
791 __cur
->_M_next
= __tmp
;
793 return iterator(__tmp
, this);
796 _Node
* __tmp
= _M_new_node(__obj
);
797 __tmp
->_M_next
= __first
;
798 _M_buckets
[__n
] = __tmp
;
800 return iterator(__tmp
, this);
803 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
804 typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::reference
805 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
806 find_or_insert(const value_type
& __obj
)
808 resize(_M_num_elements
+ 1);
810 size_type __n
= _M_bkt_num(__obj
);
811 _Node
* __first
= _M_buckets
[__n
];
813 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
814 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
815 return __cur
->_M_val
;
817 _Node
* __tmp
= _M_new_node(__obj
);
818 __tmp
->_M_next
= __first
;
819 _M_buckets
[__n
] = __tmp
;
821 return __tmp
->_M_val
;
824 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
825 pair
<typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::iterator
,
826 typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::iterator
>
827 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
828 equal_range(const key_type
& __key
)
830 typedef pair
<iterator
, iterator
> _Pii
;
831 const size_type __n
= _M_bkt_num_key(__key
);
833 for (_Node
* __first
= _M_buckets
[__n
]; __first
;
834 __first
= __first
->_M_next
)
835 if (_M_equals(_M_get_key(__first
->_M_val
), __key
))
837 for (_Node
* __cur
= __first
->_M_next
; __cur
;
838 __cur
= __cur
->_M_next
)
839 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
840 return _Pii(iterator(__first
, this), iterator(__cur
, this));
841 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
843 return _Pii(iterator(__first
, this),
844 iterator(_M_buckets
[__m
], this));
845 return _Pii(iterator(__first
, this), end());
847 return _Pii(end(), end());
850 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
851 pair
<typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::const_iterator
,
852 typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::const_iterator
>
853 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
854 equal_range(const key_type
& __key
) const
856 typedef pair
<const_iterator
, const_iterator
> _Pii
;
857 const size_type __n
= _M_bkt_num_key(__key
);
859 for (const _Node
* __first
= _M_buckets
[__n
]; __first
;
860 __first
= __first
->_M_next
)
862 if (_M_equals(_M_get_key(__first
->_M_val
), __key
))
864 for (const _Node
* __cur
= __first
->_M_next
; __cur
;
865 __cur
= __cur
->_M_next
)
866 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
867 return _Pii(const_iterator(__first
, this),
868 const_iterator(__cur
, this));
869 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
871 return _Pii(const_iterator(__first
, this),
872 const_iterator(_M_buckets
[__m
], this));
873 return _Pii(const_iterator(__first
, this), end());
876 return _Pii(end(), end());
879 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
880 typename hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::size_type
881 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
882 erase(const key_type
& __key
)
884 const size_type __n
= _M_bkt_num_key(__key
);
885 _Node
* __first
= _M_buckets
[__n
];
886 _Node
* __saved_slot
= 0;
887 size_type __erased
= 0;
891 _Node
* __cur
= __first
;
892 _Node
* __next
= __cur
->_M_next
;
895 if (_M_equals(_M_get_key(__next
->_M_val
), __key
))
897 if (&_M_get_key(__next
->_M_val
) != &__key
)
899 __cur
->_M_next
= __next
->_M_next
;
900 _M_delete_node(__next
);
901 __next
= __cur
->_M_next
;
907 __saved_slot
= __cur
;
909 __next
= __cur
->_M_next
;
915 __next
= __cur
->_M_next
;
918 bool __delete_first
= _M_equals(_M_get_key(__first
->_M_val
), __key
);
921 __next
= __saved_slot
->_M_next
;
922 __saved_slot
->_M_next
= __next
->_M_next
;
923 _M_delete_node(__next
);
929 _M_buckets
[__n
] = __first
->_M_next
;
930 _M_delete_node(__first
);
938 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
939 void hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
940 erase(const iterator
& __it
)
942 _Node
* __p
= __it
._M_cur
;
945 const size_type __n
= _M_bkt_num(__p
->_M_val
);
946 _Node
* __cur
= _M_buckets
[__n
];
950 _M_buckets
[__n
] = __cur
->_M_next
;
951 _M_delete_node(__cur
);
956 _Node
* __next
= __cur
->_M_next
;
961 __cur
->_M_next
= __next
->_M_next
;
962 _M_delete_node(__next
);
969 __next
= __cur
->_M_next
;
976 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
978 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
979 erase(iterator __first
, iterator __last
)
981 size_type __f_bucket
= __first
._M_cur
? _M_bkt_num(__first
._M_cur
->_M_val
)
984 size_type __l_bucket
= __last
._M_cur
? _M_bkt_num(__last
._M_cur
->_M_val
)
987 if (__first
._M_cur
== __last
._M_cur
)
989 else if (__f_bucket
== __l_bucket
)
990 _M_erase_bucket(__f_bucket
, __first
._M_cur
, __last
._M_cur
);
993 _M_erase_bucket(__f_bucket
, __first
._M_cur
, 0);
994 for (size_type __n
= __f_bucket
+ 1; __n
< __l_bucket
; ++__n
)
995 _M_erase_bucket(__n
, 0);
996 if (__l_bucket
!= _M_buckets
.size())
997 _M_erase_bucket(__l_bucket
, __last
._M_cur
);
1001 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1003 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1004 erase(const_iterator __first
, const_iterator __last
)
1006 erase(iterator(const_cast<_Node
*>(__first
._M_cur
),
1007 const_cast<hashtable
*>(__first
._M_ht
)),
1008 iterator(const_cast<_Node
*>(__last
._M_cur
),
1009 const_cast<hashtable
*>(__last
._M_ht
)));
1012 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1014 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1015 erase(const const_iterator
& __it
)
1016 { erase(iterator(const_cast<_Node
*>(__it
._M_cur
),
1017 const_cast<hashtable
*>(__it
._M_ht
))); }
1019 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1021 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1022 resize(size_type __num_elements_hint
)
1024 const size_type __old_n
= _M_buckets
.size();
1025 if (__num_elements_hint
> __old_n
)
1027 const size_type __n
= _M_next_size(__num_elements_hint
);
1030 _Vector_type
__tmp(__n
, (_Node
*)(0), _M_buckets
.get_allocator());
1033 for (size_type __bucket
= 0; __bucket
< __old_n
; ++__bucket
)
1035 _Node
* __first
= _M_buckets
[__bucket
];
1038 size_type __new_bucket
= _M_bkt_num(__first
->_M_val
,
1040 _M_buckets
[__bucket
] = __first
->_M_next
;
1041 __first
->_M_next
= __tmp
[__new_bucket
];
1042 __tmp
[__new_bucket
] = __first
;
1043 __first
= _M_buckets
[__bucket
];
1046 _M_buckets
.swap(__tmp
);
1050 for (size_type __bucket
= 0; __bucket
< __tmp
.size();
1053 while (__tmp
[__bucket
])
1055 _Node
* __next
= __tmp
[__bucket
]->_M_next
;
1056 _M_delete_node(__tmp
[__bucket
]);
1057 __tmp
[__bucket
] = __next
;
1060 __throw_exception_again
;
1066 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1068 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1069 _M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
)
1071 _Node
* __cur
= _M_buckets
[__n
];
1072 if (__cur
== __first
)
1073 _M_erase_bucket(__n
, __last
);
1077 for (__next
= __cur
->_M_next
;
1079 __cur
= __next
, __next
= __cur
->_M_next
)
1081 while (__next
!= __last
)
1083 __cur
->_M_next
= __next
->_M_next
;
1084 _M_delete_node(__next
);
1085 __next
= __cur
->_M_next
;
1091 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1093 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1094 _M_erase_bucket(const size_type __n
, _Node
* __last
)
1096 _Node
* __cur
= _M_buckets
[__n
];
1097 while (__cur
!= __last
)
1099 _Node
* __next
= __cur
->_M_next
;
1100 _M_delete_node(__cur
);
1102 _M_buckets
[__n
] = __cur
;
1107 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1109 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1112 if (_M_num_elements
== 0)
1115 for (size_type __i
= 0; __i
< _M_buckets
.size(); ++__i
)
1117 _Node
* __cur
= _M_buckets
[__i
];
1120 _Node
* __next
= __cur
->_M_next
;
1121 _M_delete_node(__cur
);
1124 _M_buckets
[__i
] = 0;
1126 _M_num_elements
= 0;
1129 template<class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1131 hashtable
<_Val
, _Key
, _HF
, _Ex
, _Eq
, _All
>::
1132 _M_copy_from(const hashtable
& __ht
)
1135 _M_buckets
.reserve(__ht
._M_buckets
.size());
1136 _M_buckets
.insert(_M_buckets
.end(), __ht
._M_buckets
.size(), (_Node
*) 0);
1139 for (size_type __i
= 0; __i
< __ht
._M_buckets
.size(); ++__i
) {
1140 const _Node
* __cur
= __ht
._M_buckets
[__i
];
1143 _Node
* __local_copy
= _M_new_node(__cur
->_M_val
);
1144 _M_buckets
[__i
] = __local_copy
;
1146 for (_Node
* __next
= __cur
->_M_next
;
1148 __cur
= __next
, __next
= __cur
->_M_next
)
1150 __local_copy
->_M_next
= _M_new_node(__next
->_M_val
);
1151 __local_copy
= __local_copy
->_M_next
;
1155 _M_num_elements
= __ht
._M_num_elements
;
1160 __throw_exception_again
;
1164 _GLIBCXX_END_NAMESPACE_VERSION