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