]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/include/ext/hashtable.h
mklibgcc.in: Propagate .note.GNU-stack section if needed into the .hidden assembly...
[thirdparty/gcc.git] / libstdc++-v3 / include / ext / hashtable.h
1 // Hashtable implementation used by containers -*- C++ -*-
2
3 // Copyright (C) 2001, 2002, 2003 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.
10
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.
15
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.
20
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.
29
30 /*
31 * Copyright (c) 1996,1997
32 * Silicon Graphics Computer Systems, Inc.
33 *
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.
41 *
42 *
43 * Copyright (c) 1994
44 * Hewlett-Packard Company
45 *
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.
53 *
54 */
55
56 /** @file ext/hashtable.h
57 * This file is a GNU extension to the Standard C++ Library (possibly
58 * containing extensions from the HP/SGI STL subset). You should only
59 * include this header if you are using GCC 3 or later.
60 */
61
62 #ifndef _HASHTABLE_H
63 #define _HASHTABLE_H 1
64
65 // Hashtable class, used to implement the hashed associative containers
66 // hash_set, hash_map, hash_multiset, and hash_multimap.
67
68 #include <vector>
69 #include <iterator>
70 #include <bits/stl_algo.h>
71 #include <bits/stl_function.h>
72 #include <ext/hash_fun.h>
73
74 namespace __gnu_cxx
75 {
76 using std::size_t;
77 using std::ptrdiff_t;
78 using std::forward_iterator_tag;
79 using std::input_iterator_tag;
80 using std::_Alloc_traits;
81 using std::_Construct;
82 using std::_Destroy;
83 using std::distance;
84 using std::vector;
85 using std::pair;
86 using std::__iterator_category;
87
88 template <class _Val>
89 struct _Hashtable_node
90 {
91 _Hashtable_node* _M_next;
92 _Val _M_val;
93 };
94
95 template <class _Val, class _Key, class _HashFcn,
96 class _ExtractKey, class _EqualKey, class _Alloc = std::__alloc>
97 class hashtable;
98
99 template <class _Val, class _Key, class _HashFcn,
100 class _ExtractKey, class _EqualKey, class _Alloc>
101 struct _Hashtable_iterator;
102
103 template <class _Val, class _Key, class _HashFcn,
104 class _ExtractKey, class _EqualKey, class _Alloc>
105 struct _Hashtable_const_iterator;
106
107 template <class _Val, class _Key, class _HashFcn,
108 class _ExtractKey, class _EqualKey, class _Alloc>
109 struct _Hashtable_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;
119
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 _Val& reference;
125 typedef _Val* pointer;
126
127 _Node* _M_cur;
128 _Hashtable* _M_ht;
129
130 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
131 : _M_cur(__n), _M_ht(__tab) {}
132 _Hashtable_iterator() {}
133 reference operator*() const { return _M_cur->_M_val; }
134 pointer operator->() const { return &(operator*()); }
135 iterator& operator++();
136 iterator operator++(int);
137 bool operator==(const iterator& __it) const
138 { return _M_cur == __it._M_cur; }
139 bool operator!=(const iterator& __it) const
140 { return _M_cur != __it._M_cur; }
141 };
142
143
144 template <class _Val, class _Key, class _HashFcn,
145 class _ExtractKey, class _EqualKey, class _Alloc>
146 struct _Hashtable_const_iterator {
147 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
148 _Hashtable;
149 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
150 _ExtractKey,_EqualKey,_Alloc>
151 iterator;
152 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
153 _ExtractKey, _EqualKey, _Alloc>
154 const_iterator;
155 typedef _Hashtable_node<_Val> _Node;
156
157 typedef forward_iterator_tag iterator_category;
158 typedef _Val value_type;
159 typedef ptrdiff_t difference_type;
160 typedef size_t size_type;
161 typedef const _Val& reference;
162 typedef const _Val* pointer;
163
164 const _Node* _M_cur;
165 const _Hashtable* _M_ht;
166
167 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
168 : _M_cur(__n), _M_ht(__tab) {}
169 _Hashtable_const_iterator() {}
170 _Hashtable_const_iterator(const iterator& __it)
171 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
172 reference operator*() const { return _M_cur->_M_val; }
173 pointer operator->() const { return &(operator*()); }
174 const_iterator& operator++();
175 const_iterator operator++(int);
176 bool operator==(const const_iterator& __it) const
177 { return _M_cur == __it._M_cur; }
178 bool operator!=(const const_iterator& __it) const
179 { return _M_cur != __it._M_cur; }
180 };
181
182 // Note: assumes long is at least 32 bits.
183 enum { _S_num_primes = 28 };
184
185 static const unsigned long __stl_prime_list[_S_num_primes] =
186 {
187 53ul, 97ul, 193ul, 389ul, 769ul,
188 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
189 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
190 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
191 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
192 1610612741ul, 3221225473ul, 4294967291ul
193 };
194
195 inline unsigned long __stl_next_prime(unsigned long __n)
196 {
197 const unsigned long* __first = __stl_prime_list;
198 const unsigned long* __last = __stl_prime_list + (int)_S_num_primes;
199 const unsigned long* pos = std::lower_bound(__first, __last, __n);
200 return pos == __last ? *(__last - 1) : *pos;
201 }
202
203 // Forward declaration of operator==.
204
205 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
206 class hashtable;
207
208 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
209 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
210 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
211
212
213 // Hashtables handle allocators a bit differently than other
214 // containers do. If we're using standard-conforming allocators, then
215 // a hashtable unconditionally has a member variable to hold its
216 // allocator, even if it so happens that all instances of the
217 // allocator type are identical. This is because, for hashtables,
218 // this extra storage is negligible. Additionally, a base class
219 // wouldn't serve any other purposes; it wouldn't, for example,
220 // simplify the exception-handling code.
221
222 template <class _Val, class _Key, class _HashFcn,
223 class _ExtractKey, class _EqualKey, class _Alloc>
224 class hashtable {
225 public:
226 typedef _Key key_type;
227 typedef _Val value_type;
228 typedef _HashFcn hasher;
229 typedef _EqualKey key_equal;
230
231 typedef size_t size_type;
232 typedef ptrdiff_t difference_type;
233 typedef value_type* pointer;
234 typedef const value_type* const_pointer;
235 typedef value_type& reference;
236 typedef const value_type& const_reference;
237
238 hasher hash_funct() const { return _M_hash; }
239 key_equal key_eq() const { return _M_equals; }
240
241 private:
242 typedef _Hashtable_node<_Val> _Node;
243
244 public:
245 typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
246 allocator_type get_allocator() const { return _M_node_allocator; }
247 private:
248 typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
249 _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
250 void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
251
252 private:
253 hasher _M_hash;
254 key_equal _M_equals;
255 _ExtractKey _M_get_key;
256 vector<_Node*,_Alloc> _M_buckets;
257 size_type _M_num_elements;
258
259 public:
260 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
261 iterator;
262 typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
263 _Alloc>
264 const_iterator;
265
266 friend struct
267 _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
268 friend struct
269 _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
270
271 public:
272 hashtable(size_type __n,
273 const _HashFcn& __hf,
274 const _EqualKey& __eql,
275 const _ExtractKey& __ext,
276 const allocator_type& __a = allocator_type())
277 : _M_node_allocator(__a),
278 _M_hash(__hf),
279 _M_equals(__eql),
280 _M_get_key(__ext),
281 _M_buckets(__a),
282 _M_num_elements(0)
283 {
284 _M_initialize_buckets(__n);
285 }
286
287 hashtable(size_type __n,
288 const _HashFcn& __hf,
289 const _EqualKey& __eql,
290 const allocator_type& __a = allocator_type())
291 : _M_node_allocator(__a),
292 _M_hash(__hf),
293 _M_equals(__eql),
294 _M_get_key(_ExtractKey()),
295 _M_buckets(__a),
296 _M_num_elements(0)
297 {
298 _M_initialize_buckets(__n);
299 }
300
301 hashtable(const hashtable& __ht)
302 : _M_node_allocator(__ht.get_allocator()),
303 _M_hash(__ht._M_hash),
304 _M_equals(__ht._M_equals),
305 _M_get_key(__ht._M_get_key),
306 _M_buckets(__ht.get_allocator()),
307 _M_num_elements(0)
308 {
309 _M_copy_from(__ht);
310 }
311
312 hashtable& operator= (const hashtable& __ht)
313 {
314 if (&__ht != this) {
315 clear();
316 _M_hash = __ht._M_hash;
317 _M_equals = __ht._M_equals;
318 _M_get_key = __ht._M_get_key;
319 _M_copy_from(__ht);
320 }
321 return *this;
322 }
323
324 ~hashtable() { clear(); }
325
326 size_type size() const { return _M_num_elements; }
327 size_type max_size() const { return size_type(-1); }
328 bool empty() const { return size() == 0; }
329
330 void swap(hashtable& __ht)
331 {
332 std::swap(_M_hash, __ht._M_hash);
333 std::swap(_M_equals, __ht._M_equals);
334 std::swap(_M_get_key, __ht._M_get_key);
335 _M_buckets.swap(__ht._M_buckets);
336 std::swap(_M_num_elements, __ht._M_num_elements);
337 }
338
339 iterator begin()
340 {
341 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
342 if (_M_buckets[__n])
343 return iterator(_M_buckets[__n], this);
344 return end();
345 }
346
347 iterator end() { return iterator(0, this); }
348
349 const_iterator begin() const
350 {
351 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
352 if (_M_buckets[__n])
353 return const_iterator(_M_buckets[__n], this);
354 return end();
355 }
356
357 const_iterator end() const { return const_iterator(0, this); }
358
359 template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
360 friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
361 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
362 public:
363
364 size_type bucket_count() const { return _M_buckets.size(); }
365
366 size_type max_bucket_count() const
367 { return __stl_prime_list[(int)_S_num_primes - 1]; }
368
369 size_type elems_in_bucket(size_type __bucket) const
370 {
371 size_type __result = 0;
372 for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
373 __result += 1;
374 return __result;
375 }
376
377 pair<iterator, bool> insert_unique(const value_type& __obj)
378 {
379 resize(_M_num_elements + 1);
380 return insert_unique_noresize(__obj);
381 }
382
383 iterator insert_equal(const value_type& __obj)
384 {
385 resize(_M_num_elements + 1);
386 return insert_equal_noresize(__obj);
387 }
388
389 pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
390 iterator insert_equal_noresize(const value_type& __obj);
391
392 template <class _InputIterator>
393 void insert_unique(_InputIterator __f, _InputIterator __l)
394 {
395 insert_unique(__f, __l, __iterator_category(__f));
396 }
397
398 template <class _InputIterator>
399 void insert_equal(_InputIterator __f, _InputIterator __l)
400 {
401 insert_equal(__f, __l, __iterator_category(__f));
402 }
403
404 template <class _InputIterator>
405 void insert_unique(_InputIterator __f, _InputIterator __l,
406 input_iterator_tag)
407 {
408 for ( ; __f != __l; ++__f)
409 insert_unique(*__f);
410 }
411
412 template <class _InputIterator>
413 void insert_equal(_InputIterator __f, _InputIterator __l,
414 input_iterator_tag)
415 {
416 for ( ; __f != __l; ++__f)
417 insert_equal(*__f);
418 }
419
420 template <class _ForwardIterator>
421 void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
422 forward_iterator_tag)
423 {
424 size_type __n = distance(__f, __l);
425 resize(_M_num_elements + __n);
426 for ( ; __n > 0; --__n, ++__f)
427 insert_unique_noresize(*__f);
428 }
429
430 template <class _ForwardIterator>
431 void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
432 forward_iterator_tag)
433 {
434 size_type __n = distance(__f, __l);
435 resize(_M_num_elements + __n);
436 for ( ; __n > 0; --__n, ++__f)
437 insert_equal_noresize(*__f);
438 }
439
440 reference find_or_insert(const value_type& __obj);
441
442 iterator find(const key_type& __key)
443 {
444 size_type __n = _M_bkt_num_key(__key);
445 _Node* __first;
446 for ( __first = _M_buckets[__n];
447 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
448 __first = __first->_M_next)
449 {}
450 return iterator(__first, this);
451 }
452
453 const_iterator find(const key_type& __key) const
454 {
455 size_type __n = _M_bkt_num_key(__key);
456 const _Node* __first;
457 for ( __first = _M_buckets[__n];
458 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
459 __first = __first->_M_next)
460 {}
461 return const_iterator(__first, this);
462 }
463
464 size_type count(const key_type& __key) const
465 {
466 const size_type __n = _M_bkt_num_key(__key);
467 size_type __result = 0;
468
469 for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
470 if (_M_equals(_M_get_key(__cur->_M_val), __key))
471 ++__result;
472 return __result;
473 }
474
475 pair<iterator, iterator>
476 equal_range(const key_type& __key);
477
478 pair<const_iterator, const_iterator>
479 equal_range(const key_type& __key) const;
480
481 size_type erase(const key_type& __key);
482 void erase(const iterator& __it);
483 void erase(iterator __first, iterator __last);
484
485 void erase(const const_iterator& __it);
486 void erase(const_iterator __first, const_iterator __last);
487
488 void resize(size_type __num_elements_hint);
489 void clear();
490
491 private:
492 size_type _M_next_size(size_type __n) const
493 { return __stl_next_prime(__n); }
494
495 void _M_initialize_buckets(size_type __n)
496 {
497 const size_type __n_buckets = _M_next_size(__n);
498 _M_buckets.reserve(__n_buckets);
499 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
500 _M_num_elements = 0;
501 }
502
503 size_type _M_bkt_num_key(const key_type& __key) const
504 {
505 return _M_bkt_num_key(__key, _M_buckets.size());
506 }
507
508 size_type _M_bkt_num(const value_type& __obj) const
509 {
510 return _M_bkt_num_key(_M_get_key(__obj));
511 }
512
513 size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
514 {
515 return _M_hash(__key) % __n;
516 }
517
518 size_type _M_bkt_num(const value_type& __obj, size_t __n) const
519 {
520 return _M_bkt_num_key(_M_get_key(__obj), __n);
521 }
522
523 _Node* _M_new_node(const value_type& __obj)
524 {
525 _Node* __n = _M_get_node();
526 __n->_M_next = 0;
527 try {
528 _Construct(&__n->_M_val, __obj);
529 return __n;
530 }
531 catch(...)
532 {
533 _M_put_node(__n);
534 __throw_exception_again;
535 }
536 }
537
538 void _M_delete_node(_Node* __n)
539 {
540 _Destroy(&__n->_M_val);
541 _M_put_node(__n);
542 }
543
544 void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
545 void _M_erase_bucket(const size_type __n, _Node* __last);
546
547 void _M_copy_from(const hashtable& __ht);
548
549 };
550
551 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
552 class _All>
553 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
554 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
555 {
556 const _Node* __old = _M_cur;
557 _M_cur = _M_cur->_M_next;
558 if (!_M_cur) {
559 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
560 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
561 _M_cur = _M_ht->_M_buckets[__bucket];
562 }
563 return *this;
564 }
565
566 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
567 class _All>
568 inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
569 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
570 {
571 iterator __tmp = *this;
572 ++*this;
573 return __tmp;
574 }
575
576 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
577 class _All>
578 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
579 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
580 {
581 const _Node* __old = _M_cur;
582 _M_cur = _M_cur->_M_next;
583 if (!_M_cur) {
584 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
585 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
586 _M_cur = _M_ht->_M_buckets[__bucket];
587 }
588 return *this;
589 }
590
591 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
592 class _All>
593 inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
594 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
595 {
596 const_iterator __tmp = *this;
597 ++*this;
598 return __tmp;
599 }
600
601 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
602 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
603 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
604 {
605 typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
606 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
607 return false;
608 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
609 _Node* __cur1 = __ht1._M_buckets[__n];
610 _Node* __cur2 = __ht2._M_buckets[__n];
611 // Check same length of lists
612 for ( ; __cur1 && __cur2;
613 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
614 {}
615 if (__cur1 || __cur2)
616 return false;
617 // Now check one's elements are in the other
618 for (__cur1 = __ht1._M_buckets[__n] ; __cur1; __cur1 = __cur1->_M_next)
619 {
620 bool _found__cur1 = false;
621 for (_Node* __cur2 = __ht2._M_buckets[__n];
622 __cur2; __cur2 = __cur2->_M_next)
623 {
624 if (__cur1->_M_val == __cur2->_M_val)
625 {
626 _found__cur1 = true;
627 break;
628 }
629 }
630 if (!_found__cur1)
631 return false;
632 }
633 }
634 return true;
635 }
636
637 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
638 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
639 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
640 return !(__ht1 == __ht2);
641 }
642
643 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
644 class _All>
645 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
646 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
647 __ht1.swap(__ht2);
648 }
649
650
651 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
652 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
653 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
654 ::insert_unique_noresize(const value_type& __obj)
655 {
656 const size_type __n = _M_bkt_num(__obj);
657 _Node* __first = _M_buckets[__n];
658
659 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
660 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
661 return pair<iterator, bool>(iterator(__cur, this), false);
662
663 _Node* __tmp = _M_new_node(__obj);
664 __tmp->_M_next = __first;
665 _M_buckets[__n] = __tmp;
666 ++_M_num_elements;
667 return pair<iterator, bool>(iterator(__tmp, this), true);
668 }
669
670 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
671 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
672 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
673 ::insert_equal_noresize(const value_type& __obj)
674 {
675 const size_type __n = _M_bkt_num(__obj);
676 _Node* __first = _M_buckets[__n];
677
678 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
679 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
680 _Node* __tmp = _M_new_node(__obj);
681 __tmp->_M_next = __cur->_M_next;
682 __cur->_M_next = __tmp;
683 ++_M_num_elements;
684 return iterator(__tmp, this);
685 }
686
687 _Node* __tmp = _M_new_node(__obj);
688 __tmp->_M_next = __first;
689 _M_buckets[__n] = __tmp;
690 ++_M_num_elements;
691 return iterator(__tmp, this);
692 }
693
694 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
695 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
696 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
697 {
698 resize(_M_num_elements + 1);
699
700 size_type __n = _M_bkt_num(__obj);
701 _Node* __first = _M_buckets[__n];
702
703 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
704 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
705 return __cur->_M_val;
706
707 _Node* __tmp = _M_new_node(__obj);
708 __tmp->_M_next = __first;
709 _M_buckets[__n] = __tmp;
710 ++_M_num_elements;
711 return __tmp->_M_val;
712 }
713
714 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
715 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
716 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
717 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
718 {
719 typedef pair<iterator, iterator> _Pii;
720 const size_type __n = _M_bkt_num_key(__key);
721
722 for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
723 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
724 for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
725 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
726 return _Pii(iterator(__first, this), iterator(__cur, this));
727 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
728 if (_M_buckets[__m])
729 return _Pii(iterator(__first, this),
730 iterator(_M_buckets[__m], this));
731 return _Pii(iterator(__first, this), end());
732 }
733 return _Pii(end(), end());
734 }
735
736 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
737 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
738 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
739 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
740 ::equal_range(const key_type& __key) const
741 {
742 typedef pair<const_iterator, const_iterator> _Pii;
743 const size_type __n = _M_bkt_num_key(__key);
744
745 for (const _Node* __first = _M_buckets[__n] ;
746 __first;
747 __first = __first->_M_next) {
748 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
749 for (const _Node* __cur = __first->_M_next;
750 __cur;
751 __cur = __cur->_M_next)
752 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
753 return _Pii(const_iterator(__first, this),
754 const_iterator(__cur, this));
755 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
756 if (_M_buckets[__m])
757 return _Pii(const_iterator(__first, this),
758 const_iterator(_M_buckets[__m], this));
759 return _Pii(const_iterator(__first, this), end());
760 }
761 }
762 return _Pii(end(), end());
763 }
764
765 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
766 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
767 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
768 {
769 const size_type __n = _M_bkt_num_key(__key);
770 _Node* __first = _M_buckets[__n];
771 size_type __erased = 0;
772
773 if (__first) {
774 _Node* __cur = __first;
775 _Node* __next = __cur->_M_next;
776 while (__next) {
777 if (_M_equals(_M_get_key(__next->_M_val), __key)) {
778 __cur->_M_next = __next->_M_next;
779 _M_delete_node(__next);
780 __next = __cur->_M_next;
781 ++__erased;
782 --_M_num_elements;
783 }
784 else {
785 __cur = __next;
786 __next = __cur->_M_next;
787 }
788 }
789 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
790 _M_buckets[__n] = __first->_M_next;
791 _M_delete_node(__first);
792 ++__erased;
793 --_M_num_elements;
794 }
795 }
796 return __erased;
797 }
798
799 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
800 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
801 {
802 _Node* __p = __it._M_cur;
803 if (__p) {
804 const size_type __n = _M_bkt_num(__p->_M_val);
805 _Node* __cur = _M_buckets[__n];
806
807 if (__cur == __p) {
808 _M_buckets[__n] = __cur->_M_next;
809 _M_delete_node(__cur);
810 --_M_num_elements;
811 }
812 else {
813 _Node* __next = __cur->_M_next;
814 while (__next) {
815 if (__next == __p) {
816 __cur->_M_next = __next->_M_next;
817 _M_delete_node(__next);
818 --_M_num_elements;
819 break;
820 }
821 else {
822 __cur = __next;
823 __next = __cur->_M_next;
824 }
825 }
826 }
827 }
828 }
829
830 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
831 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
832 ::erase(iterator __first, iterator __last)
833 {
834 size_type __f_bucket = __first._M_cur ?
835 _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
836 size_type __l_bucket = __last._M_cur ?
837 _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
838
839 if (__first._M_cur == __last._M_cur)
840 return;
841 else if (__f_bucket == __l_bucket)
842 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
843 else {
844 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
845 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
846 _M_erase_bucket(__n, 0);
847 if (__l_bucket != _M_buckets.size())
848 _M_erase_bucket(__l_bucket, __last._M_cur);
849 }
850 }
851
852 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
853 inline void
854 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
855 const_iterator __last)
856 {
857 erase(iterator(const_cast<_Node*>(__first._M_cur),
858 const_cast<hashtable*>(__first._M_ht)),
859 iterator(const_cast<_Node*>(__last._M_cur),
860 const_cast<hashtable*>(__last._M_ht)));
861 }
862
863 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
864 inline void
865 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
866 {
867 erase(iterator(const_cast<_Node*>(__it._M_cur),
868 const_cast<hashtable*>(__it._M_ht)));
869 }
870
871 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
872 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
873 ::resize(size_type __num_elements_hint)
874 {
875 const size_type __old_n = _M_buckets.size();
876 if (__num_elements_hint > __old_n) {
877 const size_type __n = _M_next_size(__num_elements_hint);
878 if (__n > __old_n) {
879 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
880 _M_buckets.get_allocator());
881 try {
882 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
883 _Node* __first = _M_buckets[__bucket];
884 while (__first) {
885 size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
886 _M_buckets[__bucket] = __first->_M_next;
887 __first->_M_next = __tmp[__new_bucket];
888 __tmp[__new_bucket] = __first;
889 __first = _M_buckets[__bucket];
890 }
891 }
892 _M_buckets.swap(__tmp);
893 }
894 catch(...) {
895 for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
896 while (__tmp[__bucket]) {
897 _Node* __next = __tmp[__bucket]->_M_next;
898 _M_delete_node(__tmp[__bucket]);
899 __tmp[__bucket] = __next;
900 }
901 }
902 __throw_exception_again;
903 }
904 }
905 }
906 }
907
908 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
909 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
910 ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
911 {
912 _Node* __cur = _M_buckets[__n];
913 if (__cur == __first)
914 _M_erase_bucket(__n, __last);
915 else {
916 _Node* __next;
917 for (__next = __cur->_M_next;
918 __next != __first;
919 __cur = __next, __next = __cur->_M_next)
920 ;
921 while (__next != __last) {
922 __cur->_M_next = __next->_M_next;
923 _M_delete_node(__next);
924 __next = __cur->_M_next;
925 --_M_num_elements;
926 }
927 }
928 }
929
930 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
931 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
932 ::_M_erase_bucket(const size_type __n, _Node* __last)
933 {
934 _Node* __cur = _M_buckets[__n];
935 while (__cur != __last) {
936 _Node* __next = __cur->_M_next;
937 _M_delete_node(__cur);
938 __cur = __next;
939 _M_buckets[__n] = __cur;
940 --_M_num_elements;
941 }
942 }
943
944 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
945 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
946 {
947 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
948 _Node* __cur = _M_buckets[__i];
949 while (__cur != 0) {
950 _Node* __next = __cur->_M_next;
951 _M_delete_node(__cur);
952 __cur = __next;
953 }
954 _M_buckets[__i] = 0;
955 }
956 _M_num_elements = 0;
957 }
958
959
960 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
961 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
962 ::_M_copy_from(const hashtable& __ht)
963 {
964 _M_buckets.clear();
965 _M_buckets.reserve(__ht._M_buckets.size());
966 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
967 try {
968 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
969 const _Node* __cur = __ht._M_buckets[__i];
970 if (__cur) {
971 _Node* __local_copy = _M_new_node(__cur->_M_val);
972 _M_buckets[__i] = __local_copy;
973
974 for (_Node* __next = __cur->_M_next;
975 __next;
976 __cur = __next, __next = __cur->_M_next) {
977 __local_copy->_M_next = _M_new_node(__next->_M_val);
978 __local_copy = __local_copy->_M_next;
979 }
980 }
981 }
982 _M_num_elements = __ht._M_num_elements;
983 }
984 catch(...)
985 {
986 clear();
987 __throw_exception_again;
988 }
989 }
990 } // namespace __gnu_cxx
991
992 #endif