1 // Hashtable implementation used by containers -*- C++ -*- 2 3 // Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 4 // Free Software Foundation, Inc. 5 // 6 // This file is part of the GNU ISO C++ Library. This library is free 7 // software; you can redistribute it and/or modify it under the 8 // terms of the GNU General Public License as published by the 9 // Free Software Foundation; either version 3, or (at your option) 10 // any later version. 11 12 // This library is distributed in the hope that it will be useful, 13 // but WITHOUT ANY WARRANTY; without even the implied warranty of 14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 // GNU General Public License for more details. 16 17 // Under Section 7 of GPL version 3, you are granted additional 18 // permissions described in the GCC Runtime Library Exception, version 19 // 3.1, as published by the Free Software Foundation. 20 21 // You should have received a copy of the GNU General Public License and 22 // a copy of the GCC Runtime Library Exception along with this program; 23 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 24 // <http://www.gnu.org/licenses/>. 25 26 /* 27 * Copyright (c) 1996,1997 28 * Silicon Graphics Computer Systems, Inc. 29 * 30 * Permission to use, copy, modify, distribute and sell this software 31 * and its documentation for any purpose is hereby granted without fee, 32 * provided that the above copyright notice appear in all copies and 33 * that both that copyright notice and this permission notice appear 34 * in supporting documentation. Silicon Graphics makes no 35 * representations about the suitability of this software for any 36 * purpose. It is provided "as is" without express or implied warranty. 37 * 38 * 39 * Copyright (c) 1994 40 * Hewlett-Packard Company 41 * 42 * Permission to use, copy, modify, distribute and sell this software 43 * and its documentation for any purpose is hereby granted without fee, 44 * provided that the above copyright notice appear in all copies and 45 * that both that copyright notice and this permission notice appear 46 * in supporting documentation. Hewlett-Packard Company makes no 47 * representations about the suitability of this software for any 48 * purpose. It is provided "as is" without express or implied warranty. 49 * 50 */ 51 52 /** @file backward/hashtable.h 53 * This file is a GNU extension to the Standard C++ Library (possibly 54 * containing extensions from the HP/SGI STL subset). 55 */ 56 57 #ifndef _HASHTABLE_H 58 #define _HASHTABLE_H 1 59 60 // Hashtable class, used to implement the hashed associative containers 61 // hash_set, hash_map, hash_multiset, and hash_multimap. 62 63 #include <vector> 64 #include <iterator> 65 #include <algorithm> 66 #include <bits/stl_function.h> 67 #include <backward/hash_fun.h> 68 69 _GLIBCXX_BEGIN_NAMESPACE(__gnu_cxx) 70 71 using std::size_t; 72 using std::ptrdiff_t; 73 using std::forward_iterator_tag; 74 using std::input_iterator_tag; 75 using std::_Construct; 76 using std::_Destroy; 77 using std::distance; 78 using std::vector; 79 using std::pair; 80 using std::__iterator_category; 81 82 template<class _Val> 83 struct _Hashtable_node 84 { 85 _Hashtable_node* _M_next; 86 _Val _M_val; 87 }; 88 89 template<class _Val, class _Key, class _HashFcn, class _ExtractKey, 90 class _EqualKey, class _Alloc = std::allocator<_Val> > 91 class hashtable; 92 93 template<class _Val, class _Key, class _HashFcn, 94 class _ExtractKey, class _EqualKey, class _Alloc> 95 struct _Hashtable_iterator; 96 97 template<class _Val, class _Key, class _HashFcn, 98 class _ExtractKey, class _EqualKey, class _Alloc> 99 struct _Hashtable_const_iterator; 100 101 template<class _Val, class _Key, class _HashFcn, 102 class _ExtractKey, class _EqualKey, class _Alloc> 103 struct _Hashtable_iterator 104 { 105 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> 106 _Hashtable; 107 typedef _Hashtable_iterator<_Val, _Key, _HashFcn, 108 _ExtractKey, _EqualKey, _Alloc> 109 iterator; 110 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 111 _ExtractKey, _EqualKey, _Alloc> 112 const_iterator; 113 typedef _Hashtable_node<_Val> _Node; 114 typedef forward_iterator_tag iterator_category; 115 typedef _Val value_type; 116 typedef ptrdiff_t difference_type; 117 typedef size_t size_type; 118 typedef _Val& reference; 119 typedef _Val* pointer; 120 121 _Node* _M_cur; 122 _Hashtable* _M_ht; 123 124 _Hashtable_iterator(_Node* __n, _Hashtable* __tab) 125 : _M_cur(__n), _M_ht(__tab) { } 126 127 _Hashtable_iterator() 128 : _M_cur(0), _M_ht(0) { } 129 130 reference 131 operator*() const 132 { return _M_cur->_M_val; } 133 134 pointer 135 operator->() const 136 { return &(operator*()); } 137 138 iterator& 139 operator++(); 140 141 iterator 142 operator++(int); 143 144 bool 145 operator==(const iterator& __it) const 146 { return _M_cur == __it._M_cur; } 147 148 bool 149 operator!=(const iterator& __it) const 150 { return _M_cur != __it._M_cur; } 151 }; 152 153 template<class _Val, class _Key, class _HashFcn, 154 class _ExtractKey, class _EqualKey, class _Alloc> 155 struct _Hashtable_const_iterator 156 { 157 typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> 158 _Hashtable; 159 typedef _Hashtable_iterator<_Val,_Key,_HashFcn, 160 _ExtractKey,_EqualKey,_Alloc> 161 iterator; 162 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, 163 _ExtractKey, _EqualKey, _Alloc> 164 const_iterator; 165 typedef _Hashtable_node<_Val> _Node; 166 167 typedef forward_iterator_tag iterator_category; 168 typedef _Val value_type; 169 typedef ptrdiff_t difference_type; 170 typedef size_t size_type; 171 typedef const _Val& reference; 172 typedef const _Val* pointer; 173 174 const _Node* _M_cur; 175 const _Hashtable* _M_ht; 176 177 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) 178 : _M_cur(__n), _M_ht(__tab) { } 179 180 _Hashtable_const_iterator() { } 181 182 _Hashtable_const_iterator(const iterator& __it) 183 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { } 184 185 reference 186 operator*() const 187 { return _M_cur->_M_val; } 188 189 pointer 190 operator->() const 191 { return &(operator*()); } 192 193 const_iterator& 194 operator++(); 195 196 const_iterator 197 operator++(int); 198 199 bool 200 operator==(const const_iterator& __it) const 201 { return _M_cur == __it._M_cur; } 202 203 bool 204 operator!=(const const_iterator& __it) const 205 { return _M_cur != __it._M_cur; } 206 }; 207 208 // Note: assumes long is at least 32 bits. 209 enum { _S_num_primes = 29 }; 210 211 static const unsigned long __stl_prime_list[_S_num_primes] = 212 { 213 5ul, 53ul, 97ul, 193ul, 389ul, 214 769ul, 1543ul, 3079ul, 6151ul, 12289ul, 215 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, 216 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, 217 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, 218 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul 219 }; 220 221 inline unsigned long 222 __stl_next_prime(unsigned long __n) 223 { 224 const unsigned long* __first = __stl_prime_list; 225 const unsigned long* __last = __stl_prime_list + (int)_S_num_primes; 226 const unsigned long* pos = std::lower_bound(__first, __last, __n); 227 return pos == __last ? *(__last - 1) : *pos; 228 } 229 230 // Forward declaration of operator==. 231 template<class _Val, class _Key, class _HF, class _Ex, 232 class _Eq, class _All> 233 class hashtable; 234 235 template<class _Val, class _Key, class _HF, class _Ex, 236 class _Eq, class _All> 237 bool 238 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, 239 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2); 240 241 // Hashtables handle allocators a bit differently than other 242 // containers do. If we're using standard-conforming allocators, then 243 // a hashtable unconditionally has a member variable to hold its 244 // allocator, even if it so happens that all instances of the 245 // allocator type are identical. This is because, for hashtables, 246 // this extra storage is negligible. Additionally, a base class 247 // wouldn't serve any other purposes; it wouldn't, for example, 248 // simplify the exception-handling code. 249 template<class _Val, class _Key, class _HashFcn, 250 class _ExtractKey, class _EqualKey, class _Alloc> 251 class hashtable 252 { 253 public: 254 typedef _Key key_type; 255 typedef _Val value_type; 256 typedef _HashFcn hasher; 257 typedef _EqualKey key_equal; 258 259 typedef size_t size_type; 260 typedef ptrdiff_t difference_type; 261 typedef value_type* pointer; 262 typedef const value_type* const_pointer; 263 typedef value_type& reference; 264 typedef const value_type& const_reference; 265 266 hasher 267 hash_funct() const 268 { return _M_hash; } 269 270 key_equal 271 key_eq() const 272 { return _M_equals; } 273 274 private: 275 typedef _Hashtable_node<_Val> _Node; 276 277 public: 278 typedef typename _Alloc::template rebind<value_type>::other allocator_type; 279 allocator_type 280 get_allocator() const 281 { return _M_node_allocator; } 282 283 private: 284 typedef typename _Alloc::template rebind<_Node>::other _Node_Alloc; 285 typedef typename _Alloc::template rebind<_Node*>::other _Nodeptr_Alloc; 286 typedef vector<_Node*, _Nodeptr_Alloc> _Vector_type; 287 288 _Node_Alloc _M_node_allocator; 289 290 _Node* 291 _M_get_node() 292 { return _M_node_allocator.allocate(1); } 293 294 void 295 _M_put_node(_Node* __p) 296 { _M_node_allocator.deallocate(__p, 1); } 297 298 private: 299 hasher _M_hash; 300 key_equal _M_equals; 301 _ExtractKey _M_get_key; 302 _Vector_type _M_buckets; 303 size_type _M_num_elements; 304 305 public: 306 typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, 307 _EqualKey, _Alloc> 308 iterator; 309 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, 310 _EqualKey, _Alloc> 311 const_iterator; 312 313 friend struct 314 _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>; 315 316 friend struct 317 _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, 318 _EqualKey, _Alloc>; 319 320 public: 321 hashtable(size_type __n, const _HashFcn& __hf, 322 const _EqualKey& __eql, const _ExtractKey& __ext, 323 const allocator_type& __a = allocator_type()) 324 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), 325 _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0) 326 { _M_initialize_buckets(__n); } 327 328 hashtable(size_type __n, const _HashFcn& __hf, 329 const _EqualKey& __eql, 330 const allocator_type& __a = allocator_type()) 331 : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), 332 _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0) 333 { _M_initialize_buckets(__n); } 334 335 hashtable(const hashtable& __ht) 336 : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash), 337 _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key), 338 _M_buckets(__ht.get_allocator()), _M_num_elements(0) 339 { _M_copy_from(__ht); } 340 341 hashtable& 342 operator= (const hashtable& __ht) 343 { 344 if (&__ht != this) 345 { 346 clear(); 347 _M_hash = __ht._M_hash; 348 _M_equals = __ht._M_equals; 349 _M_get_key = __ht._M_get_key; 350 _M_copy_from(__ht); 351 } 352 return *this; 353 } 354 355 ~hashtable() 356 { clear(); } 357 358 size_type 359 size() const 360 { return _M_num_elements; } 361 362 size_type 363 max_size() const 364 { return size_type(-1); } 365 366 bool 367 empty() const 368 { return size() == 0; } 369 370 void 371 swap(hashtable& __ht) 372 { 373 std::swap(_M_hash, __ht._M_hash); 374 std::swap(_M_equals, __ht._M_equals); 375 std::swap(_M_get_key, __ht._M_get_key); 376 _M_buckets.swap(__ht._M_buckets); 377 std::swap(_M_num_elements, __ht._M_num_elements); 378 } 379 380 iterator 381 begin() 382 { 383 for (size_type __n = 0; __n < _M_buckets.size(); ++__n) 384 if (_M_buckets[__n]) 385 return iterator(_M_buckets[__n], this); 386 return end(); 387 } 388 389 iterator 390 end() 391 { return iterator(0, this); } 392 393 const_iterator 394 begin() const 395 { 396 for (size_type __n = 0; __n < _M_buckets.size(); ++__n) 397 if (_M_buckets[__n]) 398 return const_iterator(_M_buckets[__n], this); 399 return end(); 400 } 401 402 const_iterator 403 end() const 404 { return const_iterator(0, this); } 405 406 template<class _Vl, class _Ky, class _HF, class _Ex, class _Eq, 407 class _Al> 408 friend bool 409 operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&, 410 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&); 411 412 public: 413 size_type 414 bucket_count() const 415 { return _M_buckets.size(); } 416 417 size_type 418 max_bucket_count() const 419 { return __stl_prime_list[(int)_S_num_primes - 1]; } 420 421 size_type 422 elems_in_bucket(size_type __bucket) const 423 { 424 size_type __result = 0; 425 for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next) 426 __result += 1; 427 return __result; 428 } 429 430 pair<iterator, bool> 431 insert_unique(const value_type& __obj) 432 { 433 resize(_M_num_elements + 1); 434 return insert_unique_noresize(__obj); 435 } 436 437 iterator 438 insert_equal(const value_type& __obj) 439 { 440 resize(_M_num_elements + 1); 441 return insert_equal_noresize(__obj); 442 } 443 444 pair<iterator, bool> 445 insert_unique_noresize(const value_type& __obj); 446 447 iterator 448 insert_equal_noresize(const value_type& __obj); 449 450 template<class _InputIterator> 451 void 452 insert_unique(_InputIterator __f, _InputIterator __l) 453 { insert_unique(__f, __l, __iterator_category(__f)); } 454 455 template<class _InputIterator> 456 void 457 insert_equal(_InputIterator __f, _InputIterator __l) 458 { insert_equal(__f, __l, __iterator_category(__f)); } 459 460 template<class _InputIterator> 461 void 462 insert_unique(_InputIterator __f, _InputIterator __l, 463 input_iterator_tag) 464 { 465 for ( ; __f != __l; ++__f) 466 insert_unique(*__f); 467 } 468 469 template<class _InputIterator> 470 void 471 insert_equal(_InputIterator __f, _InputIterator __l, 472 input_iterator_tag) 473 { 474 for ( ; __f != __l; ++__f) 475 insert_equal(*__f); 476 } 477 478 template<class _ForwardIterator> 479 void 480 insert_unique(_ForwardIterator __f, _ForwardIterator __l, 481 forward_iterator_tag) 482 { 483 size_type __n = distance(__f, __l); 484 resize(_M_num_elements + __n); 485 for ( ; __n > 0; --__n, ++__f) 486 insert_unique_noresize(*__f); 487 } 488 489 template<class _ForwardIterator> 490 void 491 insert_equal(_ForwardIterator __f, _ForwardIterator __l, 492 forward_iterator_tag) 493 { 494 size_type __n = distance(__f, __l); 495 resize(_M_num_elements + __n); 496 for ( ; __n > 0; --__n, ++__f) 497 insert_equal_noresize(*__f); 498 } 499 500 reference 501 find_or_insert(const value_type& __obj); 502 503 iterator 504 find(const key_type& __key) 505 { 506 size_type __n = _M_bkt_num_key(__key); 507 _Node* __first; 508 for (__first = _M_buckets[__n]; 509 __first && !_M_equals(_M_get_key(__first->_M_val), __key); 510 __first = __first->_M_next) 511 { } 512 return iterator(__first, this); 513 } 514 515 const_iterator 516 find(const key_type& __key) const 517 { 518 size_type __n = _M_bkt_num_key(__key); 519 const _Node* __first; 520 for (__first = _M_buckets[__n]; 521 __first && !_M_equals(_M_get_key(__first->_M_val), __key); 522 __first = __first->_M_next) 523 { } 524 return const_iterator(__first, this); 525 } 526 527 size_type 528 count(const key_type& __key) const 529 { 530 const size_type __n = _M_bkt_num_key(__key); 531 size_type __result = 0; 532 533 for (const _Node* __cur = _M_buckets[__n]; __cur; 534 __cur = __cur->_M_next) 535 if (_M_equals(_M_get_key(__cur->_M_val), __key)) 536 ++__result; 537 return __result; 538 } 539 540 pair<iterator, iterator> 541 equal_range(const key_type& __key); 542 543 pair<const_iterator, const_iterator> 544 equal_range(const key_type& __key) const; 545 546 size_type 547 erase(const key_type& __key); 548 549 void 550 erase(const iterator& __it); 551 552 void 553 erase(iterator __first, iterator __last); 554 555 void 556 erase(const const_iterator& __it); 557 558 void 559 erase(const_iterator __first, const_iterator __last); 560 561 void 562 resize(size_type __num_elements_hint); 563 564 void 565 clear(); 566 567 private: 568 size_type 569 _M_next_size(size_type __n) const 570 { return __stl_next_prime(__n); } 571 572 void 573 _M_initialize_buckets(size_type __n) 574 { 575 const size_type __n_buckets = _M_next_size(__n); 576 _M_buckets.reserve(__n_buckets); 577 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); 578 _M_num_elements = 0; 579 } 580 581 size_type 582 _M_bkt_num_key(const key_type& __key) const 583 { return _M_bkt_num_key(__key, _M_buckets.size()); } 584 585 size_type 586 _M_bkt_num(const value_type& __obj) const 587 { return _M_bkt_num_key(_M_get_key(__obj)); } 588 589 size_type 590 _M_bkt_num_key(const key_type& __key, size_t __n) const 591 { return _M_hash(__key) % __n; } 592 593 size_type 594 _M_bkt_num(const value_type& __obj, size_t __n) const 595 { return _M_bkt_num_key(_M_get_key(__obj), __n); } 596 597 _Node* 598 _M_new_node(const value_type& __obj) 599 { 600 _Node* __n = _M_get_node(); 601 __n->_M_next = 0; 602 __try 603 { 604 this->get_allocator().construct(&__n->_M_val, __obj); 605 return __n; 606 } 607 __catch(...) 608 { 609 _M_put_node(__n); 610 __throw_exception_again; 611 } 612 } 613 614 void 615 _M_delete_node(_Node* __n) 616 { 617 this->get_allocator().destroy(&__n->_M_val); 618 _M_put_node(__n); 619 } 620 621 void 622 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); 623 624 void 625 _M_erase_bucket(const size_type __n, _Node* __last); 626 627 void 628 _M_copy_from(const hashtable& __ht); 629 }; 630 631 template<class _Val, class _Key, class _HF, class _ExK, class _EqK, 632 class _All> 633 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& 634 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: 635 operator++() 636 { 637 const _Node* __old = _M_cur; 638 _M_cur = _M_cur->_M_next; 639 if (!_M_cur) 640 { 641 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); 642 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) 643 _M_cur = _M_ht->_M_buckets[__bucket]; 644 } 645 return *this; 646 } 647 648 template<class _Val, class _Key, class _HF, class _ExK, class _EqK, 649 class _All> 650 inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> 651 _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: 652 operator++(int) 653 { 654 iterator __tmp = *this; 655 ++*this; 656 return __tmp; 657 } 658 659 template<class _Val, class _Key, class _HF, class _ExK, class _EqK, 660 class _All> 661 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& 662 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: 663 operator++() 664 { 665 const _Node* __old = _M_cur; 666 _M_cur = _M_cur->_M_next; 667 if (!_M_cur) 668 { 669 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); 670 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) 671 _M_cur = _M_ht->_M_buckets[__bucket]; 672 } 673 return *this; 674 } 675 676 template<class _Val, class _Key, class _HF, class _ExK, class _EqK, 677 class _All> 678 inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> 679 _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: 680 operator++(int) 681 { 682 const_iterator __tmp = *this; 683 ++*this; 684 return __tmp; 685 } 686 687 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 688 bool 689 operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, 690 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) 691 { 692 typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node; 693 694 if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) 695 return false; 696 697 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) 698 { 699 _Node* __cur1 = __ht1._M_buckets[__n]; 700 _Node* __cur2 = __ht2._M_buckets[__n]; 701 // Check same length of lists 702 for (; __cur1 && __cur2; 703 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) 704 { } 705 if (__cur1 || __cur2) 706 return false; 707 // Now check one's elements are in the other 708 for (__cur1 = __ht1._M_buckets[__n] ; __cur1; 709 __cur1 = __cur1->_M_next) 710 { 711 bool _found__cur1 = false; 712 for (__cur2 = __ht2._M_buckets[__n]; 713 __cur2; __cur2 = __cur2->_M_next) 714 { 715 if (__cur1->_M_val == __cur2->_M_val) 716 { 717 _found__cur1 = true; 718 break; 719 } 720 } 721 if (!_found__cur1) 722 return false; 723 } 724 } 725 return true; 726 } 727 728 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 729 inline bool 730 operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, 731 const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) 732 { return !(__ht1 == __ht2); } 733 734 template<class _Val, class _Key, class _HF, class _Extract, class _EqKey, 735 class _All> 736 inline void 737 swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, 738 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) 739 { __ht1.swap(__ht2); } 740 741 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 742 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, bool> 743 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 744 insert_unique_noresize(const value_type& __obj) 745 { 746 const size_type __n = _M_bkt_num(__obj); 747 _Node* __first = _M_buckets[__n]; 748 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 pair<iterator, bool>(iterator(__cur, this), false); 752 753 _Node* __tmp = _M_new_node(__obj); 754 __tmp->_M_next = __first; 755 _M_buckets[__n] = __tmp; 756 ++_M_num_elements; 757 return pair<iterator, bool>(iterator(__tmp, this), true); 758 } 759 760 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 761 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator 762 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 763 insert_equal_noresize(const value_type& __obj) 764 { 765 const size_type __n = _M_bkt_num(__obj); 766 _Node* __first = _M_buckets[__n]; 767 768 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 769 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) 770 { 771 _Node* __tmp = _M_new_node(__obj); 772 __tmp->_M_next = __cur->_M_next; 773 __cur->_M_next = __tmp; 774 ++_M_num_elements; 775 return iterator(__tmp, this); 776 } 777 778 _Node* __tmp = _M_new_node(__obj); 779 __tmp->_M_next = __first; 780 _M_buckets[__n] = __tmp; 781 ++_M_num_elements; 782 return iterator(__tmp, this); 783 } 784 785 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 786 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference 787 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 788 find_or_insert(const value_type& __obj) 789 { 790 resize(_M_num_elements + 1); 791 792 size_type __n = _M_bkt_num(__obj); 793 _Node* __first = _M_buckets[__n]; 794 795 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) 796 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) 797 return __cur->_M_val; 798 799 _Node* __tmp = _M_new_node(__obj); 800 __tmp->_M_next = __first; 801 _M_buckets[__n] = __tmp; 802 ++_M_num_elements; 803 return __tmp->_M_val; 804 } 805 806 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 807 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator, 808 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator> 809 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 810 equal_range(const key_type& __key) 811 { 812 typedef pair<iterator, iterator> _Pii; 813 const size_type __n = _M_bkt_num_key(__key); 814 815 for (_Node* __first = _M_buckets[__n]; __first; 816 __first = __first->_M_next) 817 if (_M_equals(_M_get_key(__first->_M_val), __key)) 818 { 819 for (_Node* __cur = __first->_M_next; __cur; 820 __cur = __cur->_M_next) 821 if (!_M_equals(_M_get_key(__cur->_M_val), __key)) 822 return _Pii(iterator(__first, this), iterator(__cur, this)); 823 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) 824 if (_M_buckets[__m]) 825 return _Pii(iterator(__first, this), 826 iterator(_M_buckets[__m], this)); 827 return _Pii(iterator(__first, this), end()); 828 } 829 return _Pii(end(), end()); 830 } 831 832 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 833 pair<typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator, 834 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator> 835 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 836 equal_range(const key_type& __key) const 837 { 838 typedef pair<const_iterator, const_iterator> _Pii; 839 const size_type __n = _M_bkt_num_key(__key); 840 841 for (const _Node* __first = _M_buckets[__n]; __first; 842 __first = __first->_M_next) 843 { 844 if (_M_equals(_M_get_key(__first->_M_val), __key)) 845 { 846 for (const _Node* __cur = __first->_M_next; __cur; 847 __cur = __cur->_M_next) 848 if (!_M_equals(_M_get_key(__cur->_M_val), __key)) 849 return _Pii(const_iterator(__first, this), 850 const_iterator(__cur, this)); 851 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) 852 if (_M_buckets[__m]) 853 return _Pii(const_iterator(__first, this), 854 const_iterator(_M_buckets[__m], this)); 855 return _Pii(const_iterator(__first, this), end()); 856 } 857 } 858 return _Pii(end(), end()); 859 } 860 861 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 862 typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type 863 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 864 erase(const key_type& __key) 865 { 866 const size_type __n = _M_bkt_num_key(__key); 867 _Node* __first = _M_buckets[__n]; 868 _Node* __saved_slot = 0; 869 size_type __erased = 0; 870 871 if (__first) 872 { 873 _Node* __cur = __first; 874 _Node* __next = __cur->_M_next; 875 while (__next) 876 { 877 if (_M_equals(_M_get_key(__next->_M_val), __key)) 878 { 879 if (&_M_get_key(__next->_M_val) != &__key) 880 { 881 __cur->_M_next = __next->_M_next; 882 _M_delete_node(__next); 883 __next = __cur->_M_next; 884 ++__erased; 885 --_M_num_elements; 886 } 887 else 888 { 889 __saved_slot = __cur; 890 __cur = __next; 891 __next = __cur->_M_next; 892 } 893 } 894 else 895 { 896 __cur = __next; 897 __next = __cur->_M_next; 898 } 899 } 900 if (_M_equals(_M_get_key(__first->_M_val), __key)) 901 { 902 _M_buckets[__n] = __first->_M_next; 903 _M_delete_node(__first); 904 ++__erased; 905 --_M_num_elements; 906 } 907 if (__saved_slot) 908 { 909 __next = __saved_slot->_M_next; 910 __saved_slot->_M_next = __next->_M_next; 911 _M_delete_node(__next); 912 ++__erased; 913 --_M_num_elements; 914 } 915 } 916 return __erased; 917 } 918 919 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 920 void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 921 erase(const iterator& __it) 922 { 923 _Node* __p = __it._M_cur; 924 if (__p) 925 { 926 const size_type __n = _M_bkt_num(__p->_M_val); 927 _Node* __cur = _M_buckets[__n]; 928 929 if (__cur == __p) 930 { 931 _M_buckets[__n] = __cur->_M_next; 932 _M_delete_node(__cur); 933 --_M_num_elements; 934 } 935 else 936 { 937 _Node* __next = __cur->_M_next; 938 while (__next) 939 { 940 if (__next == __p) 941 { 942 __cur->_M_next = __next->_M_next; 943 _M_delete_node(__next); 944 --_M_num_elements; 945 break; 946 } 947 else 948 { 949 __cur = __next; 950 __next = __cur->_M_next; 951 } 952 } 953 } 954 } 955 } 956 957 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 958 void 959 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 960 erase(iterator __first, iterator __last) 961 { 962 size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) 963 : _M_buckets.size(); 964 965 size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) 966 : _M_buckets.size(); 967 968 if (__first._M_cur == __last._M_cur) 969 return; 970 else if (__f_bucket == __l_bucket) 971 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); 972 else 973 { 974 _M_erase_bucket(__f_bucket, __first._M_cur, 0); 975 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) 976 _M_erase_bucket(__n, 0); 977 if (__l_bucket != _M_buckets.size()) 978 _M_erase_bucket(__l_bucket, __last._M_cur); 979 } 980 } 981 982 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 983 inline void 984 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 985 erase(const_iterator __first, const_iterator __last) 986 { 987 erase(iterator(const_cast<_Node*>(__first._M_cur), 988 const_cast<hashtable*>(__first._M_ht)), 989 iterator(const_cast<_Node*>(__last._M_cur), 990 const_cast<hashtable*>(__last._M_ht))); 991 } 992 993 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 994 inline void 995 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 996 erase(const const_iterator& __it) 997 { erase(iterator(const_cast<_Node*>(__it._M_cur), 998 const_cast<hashtable*>(__it._M_ht))); } 999 1000 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 1001 void 1002 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 1003 resize(size_type __num_elements_hint) 1004 { 1005 const size_type __old_n = _M_buckets.size(); 1006 if (__num_elements_hint > __old_n) 1007 { 1008 const size_type __n = _M_next_size(__num_elements_hint); 1009 if (__n > __old_n) 1010 { 1011 _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); 1012 __try 1013 { 1014 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) 1015 { 1016 _Node* __first = _M_buckets[__bucket]; 1017 while (__first) 1018 { 1019 size_type __new_bucket = _M_bkt_num(__first->_M_val, 1020 __n); 1021 _M_buckets[__bucket] = __first->_M_next; 1022 __first->_M_next = __tmp[__new_bucket]; 1023 __tmp[__new_bucket] = __first; 1024 __first = _M_buckets[__bucket]; 1025 } 1026 } 1027 _M_buckets.swap(__tmp); 1028 } 1029 __catch(...) 1030 { 1031 for (size_type __bucket = 0; __bucket < __tmp.size(); 1032 ++__bucket) 1033 { 1034 while (__tmp[__bucket]) 1035 { 1036 _Node* __next = __tmp[__bucket]->_M_next; 1037 _M_delete_node(__tmp[__bucket]); 1038 __tmp[__bucket] = __next; 1039 } 1040 } 1041 __throw_exception_again; 1042 } 1043 } 1044 } 1045 } 1046 1047 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 1048 void 1049 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 1050 _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) 1051 { 1052 _Node* __cur = _M_buckets[__n]; 1053 if (__cur == __first) 1054 _M_erase_bucket(__n, __last); 1055 else 1056 { 1057 _Node* __next; 1058 for (__next = __cur->_M_next; 1059 __next != __first; 1060 __cur = __next, __next = __cur->_M_next) 1061 ; 1062 while (__next != __last) 1063 { 1064 __cur->_M_next = __next->_M_next; 1065 _M_delete_node(__next); 1066 __next = __cur->_M_next; 1067 --_M_num_elements; 1068 } 1069 } 1070 } 1071 1072 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 1073 void 1074 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 1075 _M_erase_bucket(const size_type __n, _Node* __last) 1076 { 1077 _Node* __cur = _M_buckets[__n]; 1078 while (__cur != __last) 1079 { 1080 _Node* __next = __cur->_M_next; 1081 _M_delete_node(__cur); 1082 __cur = __next; 1083 _M_buckets[__n] = __cur; 1084 --_M_num_elements; 1085 } 1086 } 1087 1088 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 1089 void 1090 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 1091 clear() 1092 { 1093 if (_M_num_elements == 0) 1094 return; 1095 1096 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) 1097 { 1098 _Node* __cur = _M_buckets[__i]; 1099 while (__cur != 0) 1100 { 1101 _Node* __next = __cur->_M_next; 1102 _M_delete_node(__cur); 1103 __cur = __next; 1104 } 1105 _M_buckets[__i] = 0; 1106 } 1107 _M_num_elements = 0; 1108 } 1109 1110 template<class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All> 1111 void 1112 hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: 1113 _M_copy_from(const hashtable& __ht) 1114 { 1115 _M_buckets.clear(); 1116 _M_buckets.reserve(__ht._M_buckets.size()); 1117 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); 1118 __try 1119 { 1120 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { 1121 const _Node* __cur = __ht._M_buckets[__i]; 1122 if (__cur) 1123 { 1124 _Node* __local_copy = _M_new_node(__cur->_M_val); 1125 _M_buckets[__i] = __local_copy; 1126 1127 for (_Node* __next = __cur->_M_next; 1128 __next; 1129 __cur = __next, __next = __cur->_M_next) 1130 { 1131 __local_copy->_M_next = _M_new_node(__next->_M_val); 1132 __local_copy = __local_copy->_M_next; 1133 } 1134 } 1135 } 1136 _M_num_elements = __ht._M_num_elements; 1137 } 1138 __catch(...) 1139 { 1140 clear(); 1141 __throw_exception_again; 1142 } 1143 } 1144 1145 _GLIBCXX_END_NAMESPACE 1146 1147 #endif 1148