Merge from mainline (gomp-merge-2005-02-26).
[official-gcc.git] / libstdc++-v3 / include / ext / hashtable.h
blobfc9beb62d06a24681250778b04c690ca4c083f1e
1 // Hashtable implementation used by containers -*- C++ -*-
3 // Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
4 //
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)
9 // any later version.
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,
19 // USA.
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.
43 * Copyright (c) 1994
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).
61 #ifndef _HASHTABLE_H
62 #define _HASHTABLE_H 1
64 // Hashtable class, used to implement the hashed associative containers
65 // hash_set, hash_map, hash_multiset, and hash_multimap.
67 #include <vector>
68 #include <iterator>
69 #include <bits/stl_algo.h>
70 #include <bits/stl_function.h>
71 #include <ext/hash_fun.h>
73 namespace __gnu_cxx
75 using std::size_t;
76 using std::ptrdiff_t;
77 using std::forward_iterator_tag;
78 using std::input_iterator_tag;
79 using std::_Construct;
80 using std::_Destroy;
81 using std::distance;
82 using std::vector;
83 using std::pair;
84 using std::__iterator_category;
86 template <class _Val>
87 struct _Hashtable_node
89 _Hashtable_node* _M_next;
90 _Val _M_val;
93 template <class _Val, class _Key, class _HashFcn, class _ExtractKey,
94 class _EqualKey, class _Alloc = std::allocator<_Val> >
95 class hashtable;
97 template <class _Val, class _Key, class _HashFcn,
98 class _ExtractKey, class _EqualKey, class _Alloc>
99 struct _Hashtable_iterator;
101 template <class _Val, class _Key, class _HashFcn,
102 class _ExtractKey, class _EqualKey, class _Alloc>
103 struct _Hashtable_const_iterator;
105 template <class _Val, class _Key, class _HashFcn,
106 class _ExtractKey, class _EqualKey, class _Alloc>
107 struct _Hashtable_iterator
109 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
110 _Hashtable;
111 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
112 _ExtractKey, _EqualKey, _Alloc>
113 iterator;
114 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
115 _ExtractKey, _EqualKey, _Alloc>
116 const_iterator;
117 typedef _Hashtable_node<_Val> _Node;
118 typedef forward_iterator_tag iterator_category;
119 typedef _Val value_type;
120 typedef ptrdiff_t difference_type;
121 typedef size_t size_type;
122 typedef _Val& reference;
123 typedef _Val* pointer;
125 _Node* _M_cur;
126 _Hashtable* _M_ht;
128 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
129 : _M_cur(__n), _M_ht(__tab) {}
131 _Hashtable_iterator() {}
133 reference
134 operator*() const
135 { return _M_cur->_M_val; }
137 pointer
138 operator->() const
139 { return &(operator*()); }
141 iterator&
142 operator++();
144 iterator
145 operator++(int);
147 bool
148 operator==(const iterator& __it) const
149 { return _M_cur == __it._M_cur; }
151 bool
152 operator!=(const iterator& __it) const
153 { return _M_cur != __it._M_cur; }
156 template <class _Val, class _Key, class _HashFcn,
157 class _ExtractKey, class _EqualKey, class _Alloc>
158 struct _Hashtable_const_iterator
160 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>
161 _Hashtable;
162 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
163 _ExtractKey,_EqualKey,_Alloc>
164 iterator;
165 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
166 _ExtractKey, _EqualKey, _Alloc>
167 const_iterator;
168 typedef _Hashtable_node<_Val> _Node;
170 typedef forward_iterator_tag iterator_category;
171 typedef _Val value_type;
172 typedef ptrdiff_t difference_type;
173 typedef size_t size_type;
174 typedef const _Val& reference;
175 typedef const _Val* pointer;
177 const _Node* _M_cur;
178 const _Hashtable* _M_ht;
180 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
181 : _M_cur(__n), _M_ht(__tab) {}
183 _Hashtable_const_iterator() {}
185 _Hashtable_const_iterator(const iterator& __it)
186 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
188 reference
189 operator*() const
190 { return _M_cur->_M_val; }
192 pointer
193 operator->() const
194 { return &(operator*()); }
196 const_iterator&
197 operator++();
199 const_iterator
200 operator++(int);
202 bool
203 operator==(const const_iterator& __it) const
204 { return _M_cur == __it._M_cur; }
206 bool
207 operator!=(const const_iterator& __it) const
208 { return _M_cur != __it._M_cur; }
211 // Note: assumes long is at least 32 bits.
212 enum { _S_num_primes = 28 };
214 static const unsigned long __stl_prime_list[_S_num_primes] =
216 53ul, 97ul, 193ul, 389ul, 769ul,
217 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
218 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
219 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
220 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
221 1610612741ul, 3221225473ul, 4294967291ul
224 inline unsigned long
225 __stl_next_prime(unsigned long __n)
227 const unsigned long* __first = __stl_prime_list;
228 const unsigned long* __last = __stl_prime_list + (int)_S_num_primes;
229 const unsigned long* pos = std::lower_bound(__first, __last, __n);
230 return pos == __last ? *(__last - 1) : *pos;
233 // Forward declaration of operator==.
235 template <class _Val, class _Key, class _HF, class _Ex,
236 class _Eq, class _All>
237 class hashtable;
239 template <class _Val, class _Key, class _HF, class _Ex,
240 class _Eq, class _All>
241 bool
242 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
243 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2);
245 // Hashtables handle allocators a bit differently than other
246 // containers do. If we're using standard-conforming allocators, then
247 // a hashtable unconditionally has a member variable to hold its
248 // allocator, even if it so happens that all instances of the
249 // allocator type are identical. This is because, for hashtables,
250 // this extra storage is negligible. Additionally, a base class
251 // wouldn't serve any other purposes; it wouldn't, for example,
252 // simplify the exception-handling code.
254 template <class _Val, class _Key, class _HashFcn,
255 class _ExtractKey, class _EqualKey, class _Alloc>
256 class hashtable
258 public:
259 typedef _Key key_type;
260 typedef _Val value_type;
261 typedef _HashFcn hasher;
262 typedef _EqualKey key_equal;
264 typedef size_t size_type;
265 typedef ptrdiff_t difference_type;
266 typedef value_type* pointer;
267 typedef const value_type* const_pointer;
268 typedef value_type& reference;
269 typedef const value_type& const_reference;
271 hasher
272 hash_funct() const
273 { return _M_hash; }
275 key_equal
276 key_eq() const
277 { return _M_equals; }
279 private:
280 typedef _Hashtable_node<_Val> _Node;
282 public:
283 typedef typename _Alloc::template rebind<value_type>::other allocator_type;
284 allocator_type
285 get_allocator() const
286 { return _M_node_allocator; }
288 private:
289 typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc;
290 typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc;
291 typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type;
293 _Node_Alloc _M_node_allocator;
295 _Node*
296 _M_get_node()
297 { return _M_node_allocator.allocate(1); }
299 void
300 _M_put_node(_Node* __p)
301 { _M_node_allocator.deallocate(__p, 1); }
303 private:
304 hasher _M_hash;
305 key_equal _M_equals;
306 _ExtractKey _M_get_key;
307 _Vector_type _M_buckets;
308 size_type _M_num_elements;
310 public:
311 typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey,
312 _EqualKey, _Alloc>
313 iterator;
314 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
315 _EqualKey, _Alloc>
316 const_iterator;
318 friend struct
319 _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>;
321 friend struct
322 _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey,
323 _EqualKey, _Alloc>;
325 public:
326 hashtable(size_type __n, const _HashFcn& __hf,
327 const _EqualKey& __eql, const _ExtractKey& __ext,
328 const allocator_type& __a = allocator_type())
329 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
330 _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0)
331 { _M_initialize_buckets(__n); }
333 hashtable(size_type __n, const _HashFcn& __hf,
334 const _EqualKey& __eql,
335 const allocator_type& __a = allocator_type())
336 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql),
337 _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0)
338 { _M_initialize_buckets(__n); }
340 hashtable(const hashtable& __ht)
341 : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash),
342 _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key),
343 _M_buckets(__ht.get_allocator()), _M_num_elements(0)
344 { _M_copy_from(__ht); }
346 hashtable&
347 operator= (const hashtable& __ht)
349 if (&__ht != this)
351 clear();
352 _M_hash = __ht._M_hash;
353 _M_equals = __ht._M_equals;
354 _M_get_key = __ht._M_get_key;
355 _M_copy_from(__ht);
357 return *this;
360 ~hashtable()
361 { clear(); }
363 size_type
364 size() const
365 { return _M_num_elements; }
367 size_type
368 max_size() const
369 { return size_type(-1); }
371 bool
372 empty() const
373 { return size() == 0; }
375 void
376 swap(hashtable& __ht)
378 std::swap(_M_hash, __ht._M_hash);
379 std::swap(_M_equals, __ht._M_equals);
380 std::swap(_M_get_key, __ht._M_get_key);
381 _M_buckets.swap(__ht._M_buckets);
382 std::swap(_M_num_elements, __ht._M_num_elements);
385 iterator
386 begin()
388 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
389 if (_M_buckets[__n])
390 return iterator(_M_buckets[__n], this);
391 return end();
394 iterator
395 end()
396 { return iterator(0, this); }
398 const_iterator
399 begin() const
401 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
402 if (_M_buckets[__n])
403 return const_iterator(_M_buckets[__n], this);
404 return end();
407 const_iterator
408 end() const
409 { return const_iterator(0, this); }
411 template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq,
412 class _Al>
413 friend bool
414 operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
415 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
417 public:
418 size_type
419 bucket_count() const
420 { return _M_buckets.size(); }
422 size_type
423 max_bucket_count() const
424 { return __stl_prime_list[(int)_S_num_primes - 1]; }
426 size_type
427 elems_in_bucket(size_type __bucket) const
429 size_type __result = 0;
430 for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
431 __result += 1;
432 return __result;
435 pair<iterator, bool>
436 insert_unique(const value_type& __obj)
438 resize(_M_num_elements + 1);
439 return insert_unique_noresize(__obj);
442 iterator
443 insert_equal(const value_type& __obj)
445 resize(_M_num_elements + 1);
446 return insert_equal_noresize(__obj);
449 pair<iterator, bool>
450 insert_unique_noresize(const value_type& __obj);
452 iterator
453 insert_equal_noresize(const value_type& __obj);
455 template <class _InputIterator>
456 void
457 insert_unique(_InputIterator __f, _InputIterator __l)
458 { insert_unique(__f, __l, __iterator_category(__f)); }
460 template <class _InputIterator>
461 void
462 insert_equal(_InputIterator __f, _InputIterator __l)
463 { insert_equal(__f, __l, __iterator_category(__f)); }
465 template <class _InputIterator>
466 void
467 insert_unique(_InputIterator __f, _InputIterator __l,
468 input_iterator_tag)
470 for ( ; __f != __l; ++__f)
471 insert_unique(*__f);
474 template <class _InputIterator>
475 void
476 insert_equal(_InputIterator __f, _InputIterator __l,
477 input_iterator_tag)
479 for ( ; __f != __l; ++__f)
480 insert_equal(*__f);
483 template <class _ForwardIterator>
484 void
485 insert_unique(_ForwardIterator __f, _ForwardIterator __l,
486 forward_iterator_tag)
488 size_type __n = distance(__f, __l);
489 resize(_M_num_elements + __n);
490 for ( ; __n > 0; --__n, ++__f)
491 insert_unique_noresize(*__f);
494 template <class _ForwardIterator>
495 void
496 insert_equal(_ForwardIterator __f, _ForwardIterator __l,
497 forward_iterator_tag)
499 size_type __n = distance(__f, __l);
500 resize(_M_num_elements + __n);
501 for ( ; __n > 0; --__n, ++__f)
502 insert_equal_noresize(*__f);
505 reference
506 find_or_insert(const value_type& __obj);
508 iterator
509 find(const key_type& __key)
511 size_type __n = _M_bkt_num_key(__key);
512 _Node* __first;
513 for (__first = _M_buckets[__n];
514 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
515 __first = __first->_M_next)
517 return iterator(__first, this);
520 const_iterator
521 find(const key_type& __key) const
523 size_type __n = _M_bkt_num_key(__key);
524 const _Node* __first;
525 for (__first = _M_buckets[__n];
526 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
527 __first = __first->_M_next)
529 return const_iterator(__first, this);
532 size_type
533 count(const key_type& __key) const
535 const size_type __n = _M_bkt_num_key(__key);
536 size_type __result = 0;
538 for (const _Node* __cur = _M_buckets[__n]; __cur;
539 __cur = __cur->_M_next)
540 if (_M_equals(_M_get_key(__cur->_M_val), __key))
541 ++__result;
542 return __result;
545 pair<iterator, iterator>
546 equal_range(const key_type& __key);
548 pair<const_iterator, const_iterator>
549 equal_range(const key_type& __key) const;
551 size_type
552 erase(const key_type& __key);
554 void
555 erase(const iterator& __it);
557 void
558 erase(iterator __first, iterator __last);
560 void
561 erase(const const_iterator& __it);
563 void
564 erase(const_iterator __first, const_iterator __last);
566 void
567 resize(size_type __num_elements_hint);
569 void
570 clear();
572 private:
573 size_type
574 _M_next_size(size_type __n) const
575 { return __stl_next_prime(__n); }
577 void
578 _M_initialize_buckets(size_type __n)
580 const size_type __n_buckets = _M_next_size(__n);
581 _M_buckets.reserve(__n_buckets);
582 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
583 _M_num_elements = 0;
586 size_type
587 _M_bkt_num_key(const key_type& __key) const
588 { return _M_bkt_num_key(__key, _M_buckets.size()); }
590 size_type
591 _M_bkt_num(const value_type& __obj) const
592 { return _M_bkt_num_key(_M_get_key(__obj)); }
594 size_type
595 _M_bkt_num_key(const key_type& __key, size_t __n) const
596 { return _M_hash(__key) % __n; }
598 size_type
599 _M_bkt_num(const value_type& __obj, size_t __n) const
600 { return _M_bkt_num_key(_M_get_key(__obj), __n); }
602 _Node*
603 _M_new_node(const value_type& __obj)
605 _Node* __n = _M_get_node();
606 __n->_M_next = 0;
609 this->get_allocator().construct(&__n->_M_val, __obj);
610 return __n;
612 catch(...)
614 _M_put_node(__n);
615 __throw_exception_again;
619 void
620 _M_delete_node(_Node* __n)
622 this->get_allocator().destroy(&__n->_M_val);
623 _M_put_node(__n);
626 void
627 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
629 void
630 _M_erase_bucket(const size_type __n, _Node* __last);
632 void
633 _M_copy_from(const hashtable& __ht);
636 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
637 class _All>
638 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
639 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
640 operator++()
642 const _Node* __old = _M_cur;
643 _M_cur = _M_cur->_M_next;
644 if (!_M_cur)
646 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
647 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
648 _M_cur = _M_ht->_M_buckets[__bucket];
650 return *this;
653 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
654 class _All>
655 inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
656 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
657 operator++(int)
659 iterator __tmp = *this;
660 ++*this;
661 return __tmp;
664 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
665 class _All>
666 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>&
667 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
668 operator++()
670 const _Node* __old = _M_cur;
671 _M_cur = _M_cur->_M_next;
672 if (!_M_cur)
674 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
675 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
676 _M_cur = _M_ht->_M_buckets[__bucket];
678 return *this;
681 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
682 class _All>
683 inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>
684 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>::
685 operator++(int)
687 const_iterator __tmp = *this;
688 ++*this;
689 return __tmp;
692 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
693 bool
694 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
695 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
697 typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node;
699 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
700 return false;
702 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n)
704 _Node* __cur1 = __ht1._M_buckets[__n];
705 _Node* __cur2 = __ht2._M_buckets[__n];
706 // Check same length of lists
707 for (; __cur1 && __cur2;
708 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
710 if (__cur1 || __cur2)
711 return false;
712 // Now check one's elements are in the other
713 for (__cur1 = __ht1._M_buckets[__n] ; __cur1;
714 __cur1 = __cur1->_M_next)
716 bool _found__cur1 = false;
717 for (_Node* __cur2 = __ht2._M_buckets[__n];
718 __cur2; __cur2 = __cur2->_M_next)
720 if (__cur1->_M_val == __cur2->_M_val)
722 _found__cur1 = true;
723 break;
726 if (!_found__cur1)
727 return false;
730 return true;
733 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
734 inline bool
735 operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1,
736 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2)
737 { return !(__ht1 == __ht2); }
739 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
740 class _All>
741 inline void
742 swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
743 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2)
744 { __ht1.swap(__ht2); }
746 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
747 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool>
748 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
749 insert_unique_noresize(const value_type& __obj)
751 const size_type __n = _M_bkt_num(__obj);
752 _Node* __first = _M_buckets[__n];
754 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
755 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
756 return pair<iterator, bool>(iterator(__cur, this), false);
758 _Node* __tmp = _M_new_node(__obj);
759 __tmp->_M_next = __first;
760 _M_buckets[__n] = __tmp;
761 ++_M_num_elements;
762 return pair<iterator, bool>(iterator(__tmp, this), true);
765 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
766 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator
767 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
768 insert_equal_noresize(const value_type& __obj)
770 const size_type __n = _M_bkt_num(__obj);
771 _Node* __first = _M_buckets[__n];
773 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
774 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
776 _Node* __tmp = _M_new_node(__obj);
777 __tmp->_M_next = __cur->_M_next;
778 __cur->_M_next = __tmp;
779 ++_M_num_elements;
780 return iterator(__tmp, this);
783 _Node* __tmp = _M_new_node(__obj);
784 __tmp->_M_next = __first;
785 _M_buckets[__n] = __tmp;
786 ++_M_num_elements;
787 return iterator(__tmp, this);
790 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
791 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference
792 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
793 find_or_insert(const value_type& __obj)
795 resize(_M_num_elements + 1);
797 size_type __n = _M_bkt_num(__obj);
798 _Node* __first = _M_buckets[__n];
800 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
801 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
802 return __cur->_M_val;
804 _Node* __tmp = _M_new_node(__obj);
805 __tmp->_M_next = __first;
806 _M_buckets[__n] = __tmp;
807 ++_M_num_elements;
808 return __tmp->_M_val;
811 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
812 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator,
813 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator>
814 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
815 equal_range(const key_type& __key)
817 typedef pair<iterator, iterator> _Pii;
818 const size_type __n = _M_bkt_num_key(__key);
820 for (_Node* __first = _M_buckets[__n]; __first;
821 __first = __first->_M_next)
822 if (_M_equals(_M_get_key(__first->_M_val), __key))
824 for (_Node* __cur = __first->_M_next; __cur;
825 __cur = __cur->_M_next)
826 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
827 return _Pii(iterator(__first, this), iterator(__cur, this));
828 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
829 if (_M_buckets[__m])
830 return _Pii(iterator(__first, this),
831 iterator(_M_buckets[__m], this));
832 return _Pii(iterator(__first, this), end());
834 return _Pii(end(), end());
837 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
838 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator,
839 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator>
840 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
841 equal_range(const key_type& __key) const
843 typedef pair<const_iterator, const_iterator> _Pii;
844 const size_type __n = _M_bkt_num_key(__key);
846 for (const _Node* __first = _M_buckets[__n]; __first;
847 __first = __first->_M_next)
849 if (_M_equals(_M_get_key(__first->_M_val), __key))
851 for (const _Node* __cur = __first->_M_next; __cur;
852 __cur = __cur->_M_next)
853 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
854 return _Pii(const_iterator(__first, this),
855 const_iterator(__cur, this));
856 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
857 if (_M_buckets[__m])
858 return _Pii(const_iterator(__first, this),
859 const_iterator(_M_buckets[__m], this));
860 return _Pii(const_iterator(__first, this), end());
863 return _Pii(end(), end());
866 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
867 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type
868 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
869 erase(const key_type& __key)
871 const size_type __n = _M_bkt_num_key(__key);
872 _Node* __first = _M_buckets[__n];
873 size_type __erased = 0;
875 if (__first)
877 _Node* __cur = __first;
878 _Node* __next = __cur->_M_next;
879 while (__next)
881 if (_M_equals(_M_get_key(__next->_M_val), __key))
883 __cur->_M_next = __next->_M_next;
884 _M_delete_node(__next);
885 __next = __cur->_M_next;
886 ++__erased;
887 --_M_num_elements;
889 else
891 __cur = __next;
892 __next = __cur->_M_next;
895 if (_M_equals(_M_get_key(__first->_M_val), __key))
897 _M_buckets[__n] = __first->_M_next;
898 _M_delete_node(__first);
899 ++__erased;
900 --_M_num_elements;
903 return __erased;
906 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
907 void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
908 erase(const iterator& __it)
910 _Node* __p = __it._M_cur;
911 if (__p)
913 const size_type __n = _M_bkt_num(__p->_M_val);
914 _Node* __cur = _M_buckets[__n];
916 if (__cur == __p)
918 _M_buckets[__n] = __cur->_M_next;
919 _M_delete_node(__cur);
920 --_M_num_elements;
922 else
924 _Node* __next = __cur->_M_next;
925 while (__next)
927 if (__next == __p)
929 __cur->_M_next = __next->_M_next;
930 _M_delete_node(__next);
931 --_M_num_elements;
932 break;
934 else
936 __cur = __next;
937 __next = __cur->_M_next;
944 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
945 void
946 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
947 erase(iterator __first, iterator __last)
949 size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val)
950 : _M_buckets.size();
952 size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val)
953 : _M_buckets.size();
955 if (__first._M_cur == __last._M_cur)
956 return;
957 else if (__f_bucket == __l_bucket)
958 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
959 else
961 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
962 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
963 _M_erase_bucket(__n, 0);
964 if (__l_bucket != _M_buckets.size())
965 _M_erase_bucket(__l_bucket, __last._M_cur);
969 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
970 inline void
971 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
972 erase(const_iterator __first, const_iterator __last)
974 erase(iterator(const_cast<_Node*>(__first._M_cur),
975 const_cast<hashtable*>(__first._M_ht)),
976 iterator(const_cast<_Node*>(__last._M_cur),
977 const_cast<hashtable*>(__last._M_ht)));
980 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
981 inline void
982 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
983 erase(const const_iterator& __it)
984 { erase(iterator(const_cast<_Node*>(__it._M_cur),
985 const_cast<hashtable*>(__it._M_ht))); }
987 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
988 void
989 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
990 resize(size_type __num_elements_hint)
992 const size_type __old_n = _M_buckets.size();
993 if (__num_elements_hint > __old_n)
995 const size_type __n = _M_next_size(__num_elements_hint);
996 if (__n > __old_n)
998 _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator());
1001 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket)
1003 _Node* __first = _M_buckets[__bucket];
1004 while (__first)
1006 size_type __new_bucket = _M_bkt_num(__first->_M_val,
1007 __n);
1008 _M_buckets[__bucket] = __first->_M_next;
1009 __first->_M_next = __tmp[__new_bucket];
1010 __tmp[__new_bucket] = __first;
1011 __first = _M_buckets[__bucket];
1014 _M_buckets.swap(__tmp);
1016 catch(...)
1018 for (size_type __bucket = 0; __bucket < __tmp.size();
1019 ++__bucket)
1021 while (__tmp[__bucket])
1023 _Node* __next = __tmp[__bucket]->_M_next;
1024 _M_delete_node(__tmp[__bucket]);
1025 __tmp[__bucket] = __next;
1028 __throw_exception_again;
1034 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1035 void
1036 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1037 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
1039 _Node* __cur = _M_buckets[__n];
1040 if (__cur == __first)
1041 _M_erase_bucket(__n, __last);
1042 else
1044 _Node* __next;
1045 for (__next = __cur->_M_next;
1046 __next != __first;
1047 __cur = __next, __next = __cur->_M_next)
1049 while (__next != __last)
1051 __cur->_M_next = __next->_M_next;
1052 _M_delete_node(__next);
1053 __next = __cur->_M_next;
1054 --_M_num_elements;
1059 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1060 void
1061 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1062 _M_erase_bucket(const size_type __n, _Node* __last)
1064 _Node* __cur = _M_buckets[__n];
1065 while (__cur != __last)
1067 _Node* __next = __cur->_M_next;
1068 _M_delete_node(__cur);
1069 __cur = __next;
1070 _M_buckets[__n] = __cur;
1071 --_M_num_elements;
1075 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1076 void
1077 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1078 clear()
1080 for (size_type __i = 0; __i < _M_buckets.size(); ++__i)
1082 _Node* __cur = _M_buckets[__i];
1083 while (__cur != 0)
1085 _Node* __next = __cur->_M_next;
1086 _M_delete_node(__cur);
1087 __cur = __next;
1089 _M_buckets[__i] = 0;
1091 _M_num_elements = 0;
1094 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
1095 void
1096 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::
1097 _M_copy_from(const hashtable& __ht)
1099 _M_buckets.clear();
1100 _M_buckets.reserve(__ht._M_buckets.size());
1101 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
1104 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
1105 const _Node* __cur = __ht._M_buckets[__i];
1106 if (__cur)
1108 _Node* __local_copy = _M_new_node(__cur->_M_val);
1109 _M_buckets[__i] = __local_copy;
1111 for (_Node* __next = __cur->_M_next;
1112 __next;
1113 __cur = __next, __next = __cur->_M_next)
1115 __local_copy->_M_next = _M_new_node(__next->_M_val);
1116 __local_copy = __local_copy->_M_next;
1120 _M_num_elements = __ht._M_num_elements;
1122 catch(...)
1124 clear();
1125 __throw_exception_again;
1128 } // namespace __gnu_cxx
1130 #endif