btrfs: [] on the end of a struct field is a variable length array.
[haiku.git] / headers / cpp / stl_hashtable.h
blobc0354fa38e7dca772b78bfcb319092d17a9e958f
1 /*
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.
14 * Copyright (c) 1994
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>
41 #include <stl_algo.h>
42 #include <stl_uninitialized.h>
43 #include <stl_function.h>
44 #include <stl_vector.h>
45 #include <stl_hash_fun.h>
47 __STL_BEGIN_NAMESPACE
49 template <class _Val>
50 struct _Hashtable_node
52 _Hashtable_node* _M_next;
53 _Val _M_val;
54 };
56 template <class _Val, class _Key, class _HashFcn,
57 class _ExtractKey, class _EqualKey, class _Alloc = alloc>
58 class hashtable;
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>
72 _Hashtable;
73 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
74 _ExtractKey, _EqualKey, _Alloc>
75 iterator;
76 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
77 _ExtractKey, _EqualKey, _Alloc>
78 const_iterator;
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;
88 _Node* _M_cur;
89 _Hashtable* _M_ht;
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>
111 _Hashtable;
112 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
113 _ExtractKey,_EqualKey,_Alloc>
114 iterator;
115 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
116 _ExtractKey, _EqualKey, _Alloc>
117 const_iterator;
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;
127 const _Node* _M_cur;
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>
170 class hashtable;
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>
187 class hashtable {
188 public:
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; }
204 private:
205 typedef _Hashtable_node<_Val> _Node;
207 #ifdef __STL_USE_STD_ALLOCATORS
208 public:
209 typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
210 allocator_type get_allocator() const { return _M_node_allocator; }
211 private:
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 */
217 public:
218 typedef _Alloc allocator_type;
219 allocator_type get_allocator() const { return allocator_type(); }
220 private:
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 */
227 private:
228 hasher _M_hash;
229 key_equal _M_equals;
230 _ExtractKey _M_get_key;
231 vector<_Node*,_Alloc> _M_buckets;
232 size_type _M_num_elements;
234 public:
235 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
236 iterator;
237 typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
238 _Alloc>
239 const_iterator;
241 friend struct
242 _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
243 friend struct
244 _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
246 public:
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)
253 _M_hash(__hf),
254 _M_equals(__eql),
255 _M_get_key(__ext),
256 _M_buckets(__a),
257 _M_num_elements(0)
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)
267 _M_hash(__hf),
268 _M_equals(__eql),
269 _M_get_key(_ExtractKey()),
270 _M_buckets(__a),
271 _M_num_elements(0)
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()),
282 _M_num_elements(0)
284 _M_copy_from(__ht);
287 #undef __HASH_ALLOC_INIT
289 hashtable& operator= (const hashtable& __ht)
291 if (&__ht != this) {
292 clear();
293 _M_hash = __ht._M_hash;
294 _M_equals = __ht._M_equals;
295 _M_get_key = __ht._M_get_key;
296 _M_copy_from(__ht);
298 return *this;
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);
316 iterator begin()
318 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
319 if (_M_buckets[__n])
320 return iterator(_M_buckets[__n], this);
321 return end();
324 iterator end() { return iterator(0, this); }
326 const_iterator begin() const
328 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
329 if (_M_buckets[__n])
330 return const_iterator(_M_buckets[__n], this);
331 return end();
334 const_iterator end() const { return const_iterator(0, this); }
336 friend bool
337 operator== __STL_NULL_TMPL_ARGS (const hashtable&, const hashtable&);
339 public:
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)
350 __result += 1;
351 return __result;
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,
384 input_iterator_tag)
386 for ( ; __f != __l; ++__f)
387 insert_unique(*__f);
390 template <class _InputIterator>
391 void insert_equal(_InputIterator __f, _InputIterator __l,
392 input_iterator_tag)
394 for ( ; __f != __l; ++__f)
395 insert_equal(*__f);
398 template <class _ForwardIterator>
399 void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
400 forward_iterator_tag)
402 size_type __n = 0;
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)
413 size_type __n = 0;
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)
439 size_type __n = 0;
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)
448 size_type __n = 0;
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);
461 _Node* __first;
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))
487 ++__result;
488 return __result;
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);
505 void clear();
507 private:
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);
516 _M_num_elements = 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();
542 __n->_M_next = 0;
543 __STL_TRY {
544 construct(&__n->_M_val, __obj);
545 return __n;
547 __STL_UNWIND(_M_put_node(__n));
550 void _M_delete_node(_Node* __n)
552 destroy(&__n->_M_val);
553 _M_put_node(__n);
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,
564 class _All>
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;
570 if (!_M_cur) {
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];
575 return *this;
578 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
579 class _All>
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;
584 ++*this;
585 return __tmp;
588 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
589 class _All>
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;
595 if (!_M_cur) {
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];
600 return *this;
603 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
604 class _All>
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;
609 ++*this;
610 return __tmp;
613 #ifndef __STL_CLASS_PARTIAL_SPECIALIZATION
615 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
616 class _All>
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,
624 class _All>
625 inline _Val*
626 value_type(const _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
628 return (_Val*) 0;
631 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
632 class _All>
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,
640 class _All>
641 inline forward_iterator_tag
642 iterator_category(const _Hashtable_const_iterator<_Val,_Key,_HF,
643 _ExK,_EqK,_All>&)
645 return forward_iterator_tag();
648 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
649 class _All>
650 inline _Val*
651 value_type(const _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&)
653 return (_Val*) 0;
656 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
657 class _All>
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())
672 return false;
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)
680 return false;
682 return true;
685 #ifdef __STL_FUNCTION_TMPL_PARTIAL_ORDER
687 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
688 class _All>
689 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
690 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
691 __ht1.swap(__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;
712 ++_M_num_elements;
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;
729 ++_M_num_elements;
730 return iterator(__tmp, this);
733 _Node* __tmp = _M_new_node(__obj);
734 __tmp->_M_next = __first;
735 _M_buckets[__n] = __tmp;
736 ++_M_num_elements;
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;
756 ++_M_num_elements;
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)
774 if (_M_buckets[__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] ;
792 __first;
793 __first = __first->_M_next) {
794 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
795 for (const _Node* __cur = __first->_M_next;
796 __cur;
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)
802 if (_M_buckets[__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;
819 if (__first) {
820 _Node* __cur = __first;
821 _Node* __next = __cur->_M_next;
822 while (__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;
827 ++__erased;
828 --_M_num_elements;
830 else {
831 __cur = __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);
838 ++__erased;
839 --_M_num_elements;
842 return __erased;
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];
852 if (__cur == __p) {
853 _M_buckets[__n] = __cur->_M_next;
854 _M_delete_node(__cur);
855 --_M_num_elements;
857 else {
858 _Node* __next = __cur->_M_next;
859 while (__next) {
860 if (__next == __p) {
861 __cur->_M_next = __next->_M_next;
862 _M_delete_node(__next);
863 --_M_num_elements;
864 break;
866 else {
867 __cur = __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)
885 return;
886 else if (__f_bucket == __l_bucket)
887 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
888 else {
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>
898 inline void
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>
909 inline void
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);
923 if (__n > __old_n) {
924 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
925 _M_buckets.get_allocator());
926 __STL_TRY {
927 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
928 _Node* __first = _M_buckets[__bucket];
929 while (__first) {
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
940 catch(...) {
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;
948 throw;
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);
962 else {
963 _Node* __next;
964 for (__next = __cur->_M_next;
965 __next != __first;
966 __cur = __next, __next = __cur->_M_next)
968 while (__next) {
969 __cur->_M_next = __next->_M_next;
970 _M_delete_node(__next);
971 __next = __cur->_M_next;
972 --_M_num_elements;
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);
985 __cur = __next;
986 _M_buckets[__n] = __cur;
987 --_M_num_elements;
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];
996 while (__cur != 0) {
997 _Node* __next = __cur->_M_next;
998 _M_delete_node(__cur);
999 __cur = __next;
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)
1011 _M_buckets.clear();
1012 _M_buckets.reserve(__ht._M_buckets.size());
1013 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
1014 __STL_TRY {
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;
1021 __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());
1033 __STL_END_NAMESPACE
1035 #endif /* __SGI_STL_INTERNAL_HASHTABLE_H */
1037 // Local Variables:
1038 // mode:C++
1039 // End: