2 * Copyright (c) 1996,1997
3 * Silicon Graphics Computer Systems, Inc.
5 * Permission to use, copy, modify, distribute and sell this software
6 * and its documentation for any purpose is hereby granted without fee,
7 * provided that the above copyright notice appear in all copies and
8 * that both that copyright notice and this permission notice appear
9 * in supporting documentation. Silicon Graphics makes no
10 * representations about the suitability of this software for any
11 * purpose. It is provided "as is" without express or implied warranty.
15 * Hewlett-Packard Company
17 * Permission to use, copy, modify, distribute and sell this software
18 * and its documentation for any purpose is hereby granted without fee,
19 * provided that the above copyright notice appear in all copies and
20 * that both that copyright notice and this permission notice appear
21 * in supporting documentation. Hewlett-Packard Company makes no
22 * representations about the suitability of this software for any
23 * purpose. It is provided "as is" without express or implied warranty.
27 /* NOTE: This is an internal header file, included by other STL headers.
28 * You should not attempt to use it directly.
31 #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
32 #define __SGI_STL_INTERNAL_HASHTABLE_H
34 // Hashtable class, used to implement the hashed associative containers
35 // hash_set, hash_map, hash_multiset, and hash_multimap.
37 #include <stl_algobase.h>
38 #include <stl_alloc.h>
39 #include <stl_construct.h>
40 #include <stl_tempbuf.h>
42 #include <stl_uninitialized.h>
43 #include <stl_function.h>
44 #include <stl_vector.h>
45 #include <stl_hash_fun.h>
50 struct _Hashtable_node
52 _Hashtable_node
* _M_next
;
56 template <class _Val
, class _Key
, class _HashFcn
,
57 class _ExtractKey
, class _EqualKey
, class _Alloc
= alloc
>
60 template <class _Val
, class _Key
, class _HashFcn
,
61 class _ExtractKey
, class _EqualKey
, class _Alloc
>
62 struct _Hashtable_iterator
;
64 template <class _Val
, class _Key
, class _HashFcn
,
65 class _ExtractKey
, class _EqualKey
, class _Alloc
>
66 struct _Hashtable_const_iterator
;
68 template <class _Val
, class _Key
, class _HashFcn
,
69 class _ExtractKey
, class _EqualKey
, class _Alloc
>
70 struct _Hashtable_iterator
{
71 typedef hashtable
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
73 typedef _Hashtable_iterator
<_Val
, _Key
, _HashFcn
,
74 _ExtractKey
, _EqualKey
, _Alloc
>
76 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
77 _ExtractKey
, _EqualKey
, _Alloc
>
79 typedef _Hashtable_node
<_Val
> _Node
;
81 typedef forward_iterator_tag iterator_category
;
82 typedef _Val value_type
;
83 typedef ptrdiff_t difference_type
;
84 typedef size_t size_type
;
85 typedef _Val
& reference
;
86 typedef _Val
* pointer
;
91 _Hashtable_iterator(_Node
* __n
, _Hashtable
* __tab
)
92 : _M_cur(__n
), _M_ht(__tab
) {}
93 _Hashtable_iterator() {}
94 reference
operator*() const { return _M_cur
->_M_val
; }
95 #ifndef __SGI_STL_NO_ARROW_OPERATOR
96 pointer
operator->() const { return &(operator*()); }
97 #endif /* __SGI_STL_NO_ARROW_OPERATOR */
98 iterator
& operator++();
99 iterator
operator++(int);
100 bool operator==(const iterator
& __it
) const
101 { return _M_cur
== __it
._M_cur
; }
102 bool operator!=(const iterator
& __it
) const
103 { return _M_cur
!= __it
._M_cur
; }
107 template <class _Val
, class _Key
, class _HashFcn
,
108 class _ExtractKey
, class _EqualKey
, class _Alloc
>
109 struct _Hashtable_const_iterator
{
110 typedef hashtable
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
112 typedef _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,
113 _ExtractKey
,_EqualKey
,_Alloc
>
115 typedef _Hashtable_const_iterator
<_Val
, _Key
, _HashFcn
,
116 _ExtractKey
, _EqualKey
, _Alloc
>
118 typedef _Hashtable_node
<_Val
> _Node
;
120 typedef forward_iterator_tag iterator_category
;
121 typedef _Val value_type
;
122 typedef ptrdiff_t difference_type
;
123 typedef size_t size_type
;
124 typedef const _Val
& reference
;
125 typedef const _Val
* pointer
;
128 const _Hashtable
* _M_ht
;
130 _Hashtable_const_iterator(const _Node
* __n
, const _Hashtable
* __tab
)
131 : _M_cur(__n
), _M_ht(__tab
) {}
132 _Hashtable_const_iterator() {}
133 _Hashtable_const_iterator(const iterator
& __it
)
134 : _M_cur(__it
._M_cur
), _M_ht(__it
._M_ht
) {}
135 reference
operator*() const { return _M_cur
->_M_val
; }
136 #ifndef __SGI_STL_NO_ARROW_OPERATOR
137 pointer
operator->() const { return &(operator*()); }
138 #endif /* __SGI_STL_NO_ARROW_OPERATOR */
139 const_iterator
& operator++();
140 const_iterator
operator++(int);
141 bool operator==(const const_iterator
& __it
) const
142 { return _M_cur
== __it
._M_cur
; }
143 bool operator!=(const const_iterator
& __it
) const
144 { return _M_cur
!= __it
._M_cur
; }
147 // Note: assumes long is at least 32 bits.
148 static const int __stl_num_primes
= 28;
149 static const unsigned long __stl_prime_list
[__stl_num_primes
] =
151 53ul, 97ul, 193ul, 389ul, 769ul,
152 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
153 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
154 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
155 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
156 1610612741ul, 3221225473ul, 4294967291ul
159 inline unsigned long __stl_next_prime(unsigned long __n
)
161 const unsigned long* __first
= __stl_prime_list
;
162 const unsigned long* __last
= __stl_prime_list
+ __stl_num_primes
;
163 const unsigned long* pos
= lower_bound(__first
, __last
, __n
);
164 return pos
== __last
? *(__last
- 1) : *pos
;
167 // Forward declaration of operator==.
169 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
172 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
173 bool operator==(const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht1
,
174 const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht2
);
177 // Hashtables handle allocators a bit differently than other containers
178 // do. If we're using standard-conforming allocators, then a hashtable
179 // unconditionally has a member variable to hold its allocator, even if
180 // it so happens that all instances of the allocator type are identical.
181 // This is because, for hashtables, this extra storage is negligible.
182 // Additionally, a base class wouldn't serve any other purposes; it
183 // wouldn't, for example, simplify the exception-handling code.
185 template <class _Val
, class _Key
, class _HashFcn
,
186 class _ExtractKey
, class _EqualKey
, class _Alloc
>
189 typedef _Key key_type
;
190 typedef _Val value_type
;
191 typedef _HashFcn hasher
;
192 typedef _EqualKey key_equal
;
194 typedef size_t size_type
;
195 typedef ptrdiff_t difference_type
;
196 typedef value_type
* pointer
;
197 typedef const value_type
* const_pointer
;
198 typedef value_type
& reference
;
199 typedef const value_type
& const_reference
;
201 hasher
hash_funct() const { return _M_hash
; }
202 key_equal
key_eq() const { return _M_equals
; }
205 typedef _Hashtable_node
<_Val
> _Node
;
207 #ifdef __STL_USE_STD_ALLOCATORS
209 typedef typename _Alloc_traits
<_Val
,_Alloc
>::allocator_type allocator_type
;
210 allocator_type
get_allocator() const { return _M_node_allocator
; }
212 typename _Alloc_traits
<_Node
, _Alloc
>::allocator_type _M_node_allocator
;
213 _Node
* _M_get_node() { return _M_node_allocator
.allocate(1); }
214 void _M_put_node(_Node
* __p
) { _M_node_allocator
.deallocate(__p
, 1); }
215 # define __HASH_ALLOC_INIT(__a) _M_node_allocator(__a),
216 #else /* __STL_USE_STD_ALLOCATORS */
218 typedef _Alloc allocator_type
;
219 allocator_type
get_allocator() const { return allocator_type(); }
221 typedef simple_alloc
<_Node
, _Alloc
> _M_node_allocator_type
;
222 _Node
* _M_get_node() { return _M_node_allocator_type::allocate(1); }
223 void _M_put_node(_Node
* __p
) { _M_node_allocator_type::deallocate(__p
, 1); }
224 # define __HASH_ALLOC_INIT(__a)
225 #endif /* __STL_USE_STD_ALLOCATORS */
230 _ExtractKey _M_get_key
;
231 vector
<_Node
*,_Alloc
> _M_buckets
;
232 size_type _M_num_elements
;
235 typedef _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>
237 typedef _Hashtable_const_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,
242 _Hashtable_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>;
244 _Hashtable_const_iterator
<_Val
,_Key
,_HashFcn
,_ExtractKey
,_EqualKey
,_Alloc
>;
247 hashtable(size_type __n
,
248 const _HashFcn
& __hf
,
249 const _EqualKey
& __eql
,
250 const _ExtractKey
& __ext
,
251 const allocator_type
& __a
= allocator_type())
252 : __HASH_ALLOC_INIT(__a
)
259 _M_initialize_buckets(__n
);
262 hashtable(size_type __n
,
263 const _HashFcn
& __hf
,
264 const _EqualKey
& __eql
,
265 const allocator_type
& __a
= allocator_type())
266 : __HASH_ALLOC_INIT(__a
)
269 _M_get_key(_ExtractKey()),
273 _M_initialize_buckets(__n
);
276 hashtable(const hashtable
& __ht
)
277 : __HASH_ALLOC_INIT(__ht
.get_allocator())
278 _M_hash(__ht
._M_hash
),
279 _M_equals(__ht
._M_equals
),
280 _M_get_key(__ht
._M_get_key
),
281 _M_buckets(__ht
.get_allocator()),
287 #undef __HASH_ALLOC_INIT
289 hashtable
& operator= (const hashtable
& __ht
)
293 _M_hash
= __ht
._M_hash
;
294 _M_equals
= __ht
._M_equals
;
295 _M_get_key
= __ht
._M_get_key
;
301 ~hashtable() { clear(); }
303 size_type
size() const { return _M_num_elements
; }
304 size_type
max_size() const { return size_type(-1); }
305 bool empty() const { return size() == 0; }
307 void swap(hashtable
& __ht
)
309 __STD::swap(_M_hash
, __ht
._M_hash
);
310 __STD::swap(_M_equals
, __ht
._M_equals
);
311 __STD::swap(_M_get_key
, __ht
._M_get_key
);
312 _M_buckets
.swap(__ht
._M_buckets
);
313 __STD::swap(_M_num_elements
, __ht
._M_num_elements
);
318 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
320 return iterator(_M_buckets
[__n
], this);
324 iterator
end() { return iterator(0, this); }
326 const_iterator
begin() const
328 for (size_type __n
= 0; __n
< _M_buckets
.size(); ++__n
)
330 return const_iterator(_M_buckets
[__n
], this);
334 const_iterator
end() const { return const_iterator(0, this); }
337 operator== __STL_NULL_TMPL_ARGS (const hashtable
&, const hashtable
&);
341 size_type
bucket_count() const { return _M_buckets
.size(); }
343 size_type
max_bucket_count() const
344 { return __stl_prime_list
[__stl_num_primes
- 1]; }
346 size_type
elems_in_bucket(size_type __bucket
) const
348 size_type __result
= 0;
349 for (_Node
* __cur
= _M_buckets
[__bucket
]; __cur
; __cur
= __cur
->_M_next
)
354 pair
<iterator
, bool> insert_unique(const value_type
& __obj
)
356 resize(_M_num_elements
+ 1);
357 return insert_unique_noresize(__obj
);
360 iterator
insert_equal(const value_type
& __obj
)
362 resize(_M_num_elements
+ 1);
363 return insert_equal_noresize(__obj
);
366 pair
<iterator
, bool> insert_unique_noresize(const value_type
& __obj
);
367 iterator
insert_equal_noresize(const value_type
& __obj
);
369 #ifdef __STL_MEMBER_TEMPLATES
370 template <class _InputIterator
>
371 void insert_unique(_InputIterator __f
, _InputIterator __l
)
373 insert_unique(__f
, __l
, __ITERATOR_CATEGORY(__f
));
376 template <class _InputIterator
>
377 void insert_equal(_InputIterator __f
, _InputIterator __l
)
379 insert_equal(__f
, __l
, __ITERATOR_CATEGORY(__f
));
382 template <class _InputIterator
>
383 void insert_unique(_InputIterator __f
, _InputIterator __l
,
386 for ( ; __f
!= __l
; ++__f
)
390 template <class _InputIterator
>
391 void insert_equal(_InputIterator __f
, _InputIterator __l
,
394 for ( ; __f
!= __l
; ++__f
)
398 template <class _ForwardIterator
>
399 void insert_unique(_ForwardIterator __f
, _ForwardIterator __l
,
400 forward_iterator_tag
)
403 distance(__f
, __l
, __n
);
404 resize(_M_num_elements
+ __n
);
405 for ( ; __n
> 0; --__n
, ++__f
)
406 insert_unique_noresize(*__f
);
409 template <class _ForwardIterator
>
410 void insert_equal(_ForwardIterator __f
, _ForwardIterator __l
,
411 forward_iterator_tag
)
414 distance(__f
, __l
, __n
);
415 resize(_M_num_elements
+ __n
);
416 for ( ; __n
> 0; --__n
, ++__f
)
417 insert_equal_noresize(*__f
);
420 #else /* __STL_MEMBER_TEMPLATES */
421 void insert_unique(const value_type
* __f
, const value_type
* __l
)
423 size_type __n
= __l
- __f
;
424 resize(_M_num_elements
+ __n
);
425 for ( ; __n
> 0; --__n
, ++__f
)
426 insert_unique_noresize(*__f
);
429 void insert_equal(const value_type
* __f
, const value_type
* __l
)
431 size_type __n
= __l
- __f
;
432 resize(_M_num_elements
+ __n
);
433 for ( ; __n
> 0; --__n
, ++__f
)
434 insert_equal_noresize(*__f
);
437 void insert_unique(const_iterator __f
, const_iterator __l
)
440 distance(__f
, __l
, __n
);
441 resize(_M_num_elements
+ __n
);
442 for ( ; __n
> 0; --__n
, ++__f
)
443 insert_unique_noresize(*__f
);
446 void insert_equal(const_iterator __f
, const_iterator __l
)
449 distance(__f
, __l
, __n
);
450 resize(_M_num_elements
+ __n
);
451 for ( ; __n
> 0; --__n
, ++__f
)
452 insert_equal_noresize(*__f
);
454 #endif /*__STL_MEMBER_TEMPLATES */
456 reference
find_or_insert(const value_type
& __obj
);
458 iterator
find(const key_type
& __key
)
460 size_type __n
= _M_bkt_num_key(__key
);
462 for ( __first
= _M_buckets
[__n
];
463 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
464 __first
= __first
->_M_next
)
466 return iterator(__first
, this);
469 const_iterator
find(const key_type
& __key
) const
471 size_type __n
= _M_bkt_num_key(__key
);
472 const _Node
* __first
;
473 for ( __first
= _M_buckets
[__n
];
474 __first
&& !_M_equals(_M_get_key(__first
->_M_val
), __key
);
475 __first
= __first
->_M_next
)
477 return const_iterator(__first
, this);
480 size_type
count(const key_type
& __key
) const
482 const size_type __n
= _M_bkt_num_key(__key
);
483 size_type __result
= 0;
485 for (const _Node
* __cur
= _M_buckets
[__n
]; __cur
; __cur
= __cur
->_M_next
)
486 if (_M_equals(_M_get_key(__cur
->_M_val
), __key
))
491 pair
<iterator
, iterator
>
492 equal_range(const key_type
& __key
);
494 pair
<const_iterator
, const_iterator
>
495 equal_range(const key_type
& __key
) const;
497 size_type
erase(const key_type
& __key
);
498 void erase(const iterator
& __it
);
499 void erase(iterator __first
, iterator __last
);
501 void erase(const const_iterator
& __it
);
502 void erase(const_iterator __first
, const_iterator __last
);
504 void resize(size_type __num_elements_hint
);
508 size_type
_M_next_size(size_type __n
) const
509 { return __stl_next_prime(__n
); }
511 void _M_initialize_buckets(size_type __n
)
513 const size_type __n_buckets
= _M_next_size(__n
);
514 _M_buckets
.reserve(__n_buckets
);
515 _M_buckets
.insert(_M_buckets
.end(), __n_buckets
, (_Node
*) 0);
519 size_type
_M_bkt_num_key(const key_type
& __key
) const
521 return _M_bkt_num_key(__key
, _M_buckets
.size());
524 size_type
_M_bkt_num(const value_type
& __obj
) const
526 return _M_bkt_num_key(_M_get_key(__obj
));
529 size_type
_M_bkt_num_key(const key_type
& __key
, size_t __n
) const
531 return _M_hash(__key
) % __n
;
534 size_type
_M_bkt_num(const value_type
& __obj
, size_t __n
) const
536 return _M_bkt_num_key(_M_get_key(__obj
), __n
);
539 _Node
* _M_new_node(const value_type
& __obj
)
541 _Node
* __n
= _M_get_node();
544 construct(&__n
->_M_val
, __obj
);
547 __STL_UNWIND(_M_put_node(__n
));
550 void _M_delete_node(_Node
* __n
)
552 destroy(&__n
->_M_val
);
556 void _M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
);
557 void _M_erase_bucket(const size_type __n
, _Node
* __last
);
559 void _M_copy_from(const hashtable
& __ht
);
563 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
565 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&
566 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++()
568 const _Node
* __old
= _M_cur
;
569 _M_cur
= _M_cur
->_M_next
;
571 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
572 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
573 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
578 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
580 inline _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>
581 _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++(int)
583 iterator __tmp
= *this;
588 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
590 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&
591 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++()
593 const _Node
* __old
= _M_cur
;
594 _M_cur
= _M_cur
->_M_next
;
596 size_type __bucket
= _M_ht
->_M_bkt_num(__old
->_M_val
);
597 while (!_M_cur
&& ++__bucket
< _M_ht
->_M_buckets
.size())
598 _M_cur
= _M_ht
->_M_buckets
[__bucket
];
603 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
605 inline _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>
606 _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::operator++(int)
608 const_iterator __tmp
= *this;
613 #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
615 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
617 inline forward_iterator_tag
618 iterator_category(const _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&)
620 return forward_iterator_tag();
623 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
626 value_type(const _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&)
631 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
633 inline hashtable
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::difference_type
*
634 distance_type(const _Hashtable_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&)
636 return (hashtable
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::difference_type
*) 0;
639 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
641 inline forward_iterator_tag
642 iterator_category(const _Hashtable_const_iterator
<_Val
,_Key
,_HF
,
645 return forward_iterator_tag();
648 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
651 value_type(const _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&)
656 template <class _Val
, class _Key
, class _HF
, class _ExK
, class _EqK
,
658 inline hashtable
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::difference_type
*
659 distance_type(const _Hashtable_const_iterator
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>&)
661 return (hashtable
<_Val
,_Key
,_HF
,_ExK
,_EqK
,_All
>::difference_type
*) 0;
664 #endif /* __STL_CLASS_PARTIAL_SPECIALIZATION */
666 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
667 inline bool operator==(const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht1
,
668 const hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>& __ht2
)
670 typedef typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::_Node _Node
;
671 if (__ht1
._M_buckets
.size() != __ht2
._M_buckets
.size())
673 for (int __n
= 0; __n
< __ht1
._M_buckets
.size(); ++__n
) {
674 _Node
* __cur1
= __ht1
._M_buckets
[__n
];
675 _Node
* __cur2
= __ht2
._M_buckets
[__n
];
676 for ( ; __cur1
&& __cur2
&& __cur1
->_M_val
== __cur2
->_M_val
;
677 __cur1
= __cur1
->_M_next
, __cur2
= __cur2
->_M_next
)
679 if (__cur1
|| __cur2
)
685 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
687 template <class _Val
, class _Key
, class _HF
, class _Extract
, class _EqKey
,
689 inline void swap(hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht1
,
690 hashtable
<_Val
, _Key
, _HF
, _Extract
, _EqKey
, _All
>& __ht2
) {
694 #endif /* __STL_FUNCTION_TMPL_PARTIAL_ORDER */
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
, bool>
699 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
700 ::insert_unique_noresize(const value_type
& __obj
)
702 const size_type __n
= _M_bkt_num(__obj
);
703 _Node
* __first
= _M_buckets
[__n
];
705 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
706 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
707 return pair
<iterator
, bool>(iterator(__cur
, this), false);
709 _Node
* __tmp
= _M_new_node(__obj
);
710 __tmp
->_M_next
= __first
;
711 _M_buckets
[__n
] = __tmp
;
713 return pair
<iterator
, bool>(iterator(__tmp
, this), true);
716 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
717 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
718 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
719 ::insert_equal_noresize(const value_type
& __obj
)
721 const size_type __n
= _M_bkt_num(__obj
);
722 _Node
* __first
= _M_buckets
[__n
];
724 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
725 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
))) {
726 _Node
* __tmp
= _M_new_node(__obj
);
727 __tmp
->_M_next
= __cur
->_M_next
;
728 __cur
->_M_next
= __tmp
;
730 return iterator(__tmp
, this);
733 _Node
* __tmp
= _M_new_node(__obj
);
734 __tmp
->_M_next
= __first
;
735 _M_buckets
[__n
] = __tmp
;
737 return iterator(__tmp
, this);
740 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
741 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::reference
742 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::find_or_insert(const value_type
& __obj
)
744 resize(_M_num_elements
+ 1);
746 size_type __n
= _M_bkt_num(__obj
);
747 _Node
* __first
= _M_buckets
[__n
];
749 for (_Node
* __cur
= __first
; __cur
; __cur
= __cur
->_M_next
)
750 if (_M_equals(_M_get_key(__cur
->_M_val
), _M_get_key(__obj
)))
751 return __cur
->_M_val
;
753 _Node
* __tmp
= _M_new_node(__obj
);
754 __tmp
->_M_next
= __first
;
755 _M_buckets
[__n
] = __tmp
;
757 return __tmp
->_M_val
;
760 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
761 pair
<typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
,
762 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::iterator
>
763 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::equal_range(const key_type
& __key
)
765 typedef pair
<iterator
, iterator
> _Pii
;
766 const size_type __n
= _M_bkt_num_key(__key
);
768 for (_Node
* __first
= _M_buckets
[__n
]; __first
; __first
= __first
->_M_next
)
769 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
770 for (_Node
* __cur
= __first
->_M_next
; __cur
; __cur
= __cur
->_M_next
)
771 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
772 return _Pii(iterator(__first
, this), iterator(__cur
, this));
773 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
775 return _Pii(iterator(__first
, this),
776 iterator(_M_buckets
[__m
], this));
777 return _Pii(iterator(__first
, this), end());
779 return _Pii(end(), end());
782 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
783 pair
<typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::const_iterator
,
784 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::const_iterator
>
785 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
786 ::equal_range(const key_type
& __key
) const
788 typedef pair
<const_iterator
, const_iterator
> _Pii
;
789 const size_type __n
= _M_bkt_num_key(__key
);
791 for (const _Node
* __first
= _M_buckets
[__n
] ;
793 __first
= __first
->_M_next
) {
794 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
795 for (const _Node
* __cur
= __first
->_M_next
;
797 __cur
= __cur
->_M_next
)
798 if (!_M_equals(_M_get_key(__cur
->_M_val
), __key
))
799 return _Pii(const_iterator(__first
, this),
800 const_iterator(__cur
, this));
801 for (size_type __m
= __n
+ 1; __m
< _M_buckets
.size(); ++__m
)
803 return _Pii(const_iterator(__first
, this),
804 const_iterator(_M_buckets
[__m
], this));
805 return _Pii(const_iterator(__first
, this), end());
808 return _Pii(end(), end());
811 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
812 typename hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::size_type
813 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const key_type
& __key
)
815 const size_type __n
= _M_bkt_num_key(__key
);
816 _Node
* __first
= _M_buckets
[__n
];
817 size_type __erased
= 0;
820 _Node
* __cur
= __first
;
821 _Node
* __next
= __cur
->_M_next
;
823 if (_M_equals(_M_get_key(__next
->_M_val
), __key
)) {
824 __cur
->_M_next
= __next
->_M_next
;
825 _M_delete_node(__next
);
826 __next
= __cur
->_M_next
;
832 __next
= __cur
->_M_next
;
835 if (_M_equals(_M_get_key(__first
->_M_val
), __key
)) {
836 _M_buckets
[__n
] = __first
->_M_next
;
837 _M_delete_node(__first
);
845 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
846 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const iterator
& __it
)
848 if (_Node
* const __p
= __it
._M_cur
) {
849 const size_type __n
= _M_bkt_num(__p
->_M_val
);
850 _Node
* __cur
= _M_buckets
[__n
];
853 _M_buckets
[__n
] = __cur
->_M_next
;
854 _M_delete_node(__cur
);
858 _Node
* __next
= __cur
->_M_next
;
861 __cur
->_M_next
= __next
->_M_next
;
862 _M_delete_node(__next
);
868 __next
= __cur
->_M_next
;
875 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
876 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
877 ::erase(iterator __first
, iterator __last
)
879 size_type __f_bucket
= __first
._M_cur
?
880 _M_bkt_num(__first
._M_cur
->_M_val
) : _M_buckets
.size();
881 size_type __l_bucket
= __last
._M_cur
?
882 _M_bkt_num(__last
._M_cur
->_M_val
) : _M_buckets
.size();
884 if (__first
._M_cur
== __last
._M_cur
)
886 else if (__f_bucket
== __l_bucket
)
887 _M_erase_bucket(__f_bucket
, __first
._M_cur
, __last
._M_cur
);
889 _M_erase_bucket(__f_bucket
, __first
._M_cur
, 0);
890 for (size_type __n
= __f_bucket
+ 1; __n
< __l_bucket
; ++__n
)
891 _M_erase_bucket(__n
, 0);
892 if (__l_bucket
!= _M_buckets
.size())
893 _M_erase_bucket(__l_bucket
, __last
._M_cur
);
897 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
899 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const_iterator __first
,
900 const_iterator __last
)
902 erase(iterator(const_cast<_Node
*>(__first
._M_cur
),
903 const_cast<hashtable
*>(__first
._M_ht
)),
904 iterator(const_cast<_Node
*>(__last
._M_cur
),
905 const_cast<hashtable
*>(__last
._M_ht
)));
908 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
910 hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::erase(const const_iterator
& __it
)
912 erase(iterator(const_cast<_Node
*>(__it
._M_cur
),
913 const_cast<hashtable
*>(__it
._M_ht
)));
916 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
917 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
918 ::resize(size_type __num_elements_hint
)
920 const size_type __old_n
= _M_buckets
.size();
921 if (__num_elements_hint
> __old_n
) {
922 const size_type __n
= _M_next_size(__num_elements_hint
);
924 vector
<_Node
*, _All
> __tmp(__n
, (_Node
*)(0),
925 _M_buckets
.get_allocator());
927 for (size_type __bucket
= 0; __bucket
< __old_n
; ++__bucket
) {
928 _Node
* __first
= _M_buckets
[__bucket
];
930 size_type __new_bucket
= _M_bkt_num(__first
->_M_val
, __n
);
931 _M_buckets
[__bucket
] = __first
->_M_next
;
932 __first
->_M_next
= __tmp
[__new_bucket
];
933 __tmp
[__new_bucket
] = __first
;
934 __first
= _M_buckets
[__bucket
];
937 _M_buckets
.swap(__tmp
);
939 # ifdef __STL_USE_EXCEPTIONS
941 for (size_type __bucket
= 0; __bucket
< __tmp
.size(); ++__bucket
) {
942 while (__tmp
[__bucket
]) {
943 _Node
* __next
= __tmp
[__bucket
]->_M_next
;
944 _M_delete_node(__tmp
[__bucket
]);
945 __tmp
[__bucket
] = __next
;
950 # endif /* __STL_USE_EXCEPTIONS */
955 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
956 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
957 ::_M_erase_bucket(const size_type __n
, _Node
* __first
, _Node
* __last
)
959 _Node
* __cur
= _M_buckets
[__n
];
960 if (__cur
== __first
)
961 _M_erase_bucket(__n
, __last
);
964 for (__next
= __cur
->_M_next
;
966 __cur
= __next
, __next
= __cur
->_M_next
)
969 __cur
->_M_next
= __next
->_M_next
;
970 _M_delete_node(__next
);
971 __next
= __cur
->_M_next
;
977 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
978 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
979 ::_M_erase_bucket(const size_type __n
, _Node
* __last
)
981 _Node
* __cur
= _M_buckets
[__n
];
982 while (__cur
!= __last
) {
983 _Node
* __next
= __cur
->_M_next
;
984 _M_delete_node(__cur
);
986 _M_buckets
[__n
] = __cur
;
991 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
992 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>::clear()
994 for (size_type __i
= 0; __i
< _M_buckets
.size(); ++__i
) {
995 _Node
* __cur
= _M_buckets
[__i
];
997 _Node
* __next
= __cur
->_M_next
;
998 _M_delete_node(__cur
);
1001 _M_buckets
[__i
] = 0;
1003 _M_num_elements
= 0;
1007 template <class _Val
, class _Key
, class _HF
, class _Ex
, class _Eq
, class _All
>
1008 void hashtable
<_Val
,_Key
,_HF
,_Ex
,_Eq
,_All
>
1009 ::_M_copy_from(const hashtable
& __ht
)
1012 _M_buckets
.reserve(__ht
._M_buckets
.size());
1013 _M_buckets
.insert(_M_buckets
.end(), __ht
._M_buckets
.size(), (_Node
*) 0);
1015 for (size_type __i
= 0; __i
< __ht
._M_buckets
.size(); ++__i
) {
1016 if (const _Node
* __cur
= __ht
._M_buckets
[__i
]) {
1017 _Node
* ___copy
= _M_new_node(__cur
->_M_val
);
1018 _M_buckets
[__i
] = ___copy
;
1020 for (_Node
* __next
= __cur
->_M_next
;
1022 __cur
= __next
, __next
= __cur
->_M_next
) {
1023 ___copy
->_M_next
= _M_new_node(__next
->_M_val
);
1024 ___copy
= ___copy
->_M_next
;
1028 _M_num_elements
= __ht
._M_num_elements
;
1030 __STL_UNWIND(clear());
1035 #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */