Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

1167 lines
33KB

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