00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #ifndef _HASHTABLE_H
00031 #define _HASHTABLE_H 1
00032
00033 #pragma GCC system_header
00034
00035 #include <bits/hashtable_policy.h>
00036
00037 namespace std
00038 {
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 template<typename _Key, typename _Value, typename _Allocator,
00097 typename _ExtractKey, typename _Equal,
00098 typename _H1, typename _H2, typename _Hash,
00099 typename _RehashPolicy,
00100 bool __cache_hash_code,
00101 bool __constant_iterators,
00102 bool __unique_keys>
00103 class _Hashtable
00104 : public __detail::_Rehash_base<_RehashPolicy,
00105 _Hashtable<_Key, _Value, _Allocator,
00106 _ExtractKey,
00107 _Equal, _H1, _H2, _Hash,
00108 _RehashPolicy,
00109 __cache_hash_code,
00110 __constant_iterators,
00111 __unique_keys> >,
00112 public __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00113 _H1, _H2, _Hash, __cache_hash_code>,
00114 public __detail::_Map_base<_Key, _Value, _ExtractKey, __unique_keys,
00115 _Hashtable<_Key, _Value, _Allocator,
00116 _ExtractKey,
00117 _Equal, _H1, _H2, _Hash,
00118 _RehashPolicy,
00119 __cache_hash_code,
00120 __constant_iterators,
00121 __unique_keys> >,
00122 public __detail::_Equality_base<_ExtractKey, __unique_keys,
00123 _Hashtable<_Key, _Value, _Allocator,
00124 _ExtractKey,
00125 _Equal, _H1, _H2, _Hash,
00126 _RehashPolicy,
00127 __cache_hash_code,
00128 __constant_iterators,
00129 __unique_keys> >
00130 {
00131 public:
00132 typedef _Allocator allocator_type;
00133 typedef _Value value_type;
00134 typedef _Key key_type;
00135 typedef _Equal key_equal;
00136
00137
00138 typedef typename _Allocator::pointer pointer;
00139 typedef typename _Allocator::const_pointer const_pointer;
00140 typedef typename _Allocator::reference reference;
00141 typedef typename _Allocator::const_reference const_reference;
00142
00143 typedef std::size_t size_type;
00144 typedef std::ptrdiff_t difference_type;
00145 typedef __detail::_Node_iterator<value_type, __constant_iterators,
00146 __cache_hash_code>
00147 local_iterator;
00148 typedef __detail::_Node_const_iterator<value_type,
00149 __constant_iterators,
00150 __cache_hash_code>
00151 const_local_iterator;
00152
00153 typedef __detail::_Hashtable_iterator<value_type, __constant_iterators,
00154 __cache_hash_code>
00155 iterator;
00156 typedef __detail::_Hashtable_const_iterator<value_type,
00157 __constant_iterators,
00158 __cache_hash_code>
00159 const_iterator;
00160
00161 template<typename _Key2, typename _Value2, typename _Ex2, bool __unique2,
00162 typename _Hashtable2>
00163 friend struct __detail::_Map_base;
00164
00165 private:
00166 typedef __detail::_Hash_node<_Value, __cache_hash_code> _Node;
00167 typedef typename _Allocator::template rebind<_Node>::other
00168 _Node_allocator_type;
00169 typedef typename _Allocator::template rebind<_Node*>::other
00170 _Bucket_allocator_type;
00171
00172 typedef typename _Allocator::template rebind<_Value>::other
00173 _Value_allocator_type;
00174
00175 _Node_allocator_type _M_node_allocator;
00176 _Node** _M_buckets;
00177 size_type _M_bucket_count;
00178 size_type _M_begin_bucket_index;
00179 size_type _M_element_count;
00180 _RehashPolicy _M_rehash_policy;
00181
00182 _Node*
00183 _M_allocate_node(const value_type& __v);
00184
00185 void
00186 _M_deallocate_node(_Node* __n);
00187
00188 void
00189 _M_deallocate_nodes(_Node**, size_type);
00190
00191 _Node**
00192 _M_allocate_buckets(size_type __n);
00193
00194 void
00195 _M_deallocate_buckets(_Node**, size_type __n);
00196
00197 public:
00198
00199 _Hashtable(size_type __bucket_hint,
00200 const _H1&, const _H2&, const _Hash&,
00201 const _Equal&, const _ExtractKey&,
00202 const allocator_type&);
00203
00204 template<typename _InputIterator>
00205 _Hashtable(_InputIterator __first, _InputIterator __last,
00206 size_type __bucket_hint,
00207 const _H1&, const _H2&, const _Hash&,
00208 const _Equal&, const _ExtractKey&,
00209 const allocator_type&);
00210
00211 _Hashtable(const _Hashtable&);
00212
00213 _Hashtable(_Hashtable&&);
00214
00215 _Hashtable&
00216 operator=(const _Hashtable& __ht)
00217 {
00218 _Hashtable __tmp(__ht);
00219 this->swap(__tmp);
00220 return *this;
00221 }
00222
00223 _Hashtable&
00224 operator=(_Hashtable&& __ht)
00225 {
00226
00227
00228 this->clear();
00229 this->swap(__ht);
00230 return *this;
00231 }
00232
00233 ~_Hashtable();
00234
00235 void swap(_Hashtable&);
00236
00237
00238 iterator
00239 begin()
00240 { return iterator(_M_buckets + _M_begin_bucket_index); }
00241
00242 const_iterator
00243 begin() const
00244 { return const_iterator(_M_buckets + _M_begin_bucket_index); }
00245
00246 iterator
00247 end()
00248 { return iterator(_M_buckets + _M_bucket_count); }
00249
00250 const_iterator
00251 end() const
00252 { return const_iterator(_M_buckets + _M_bucket_count); }
00253
00254 const_iterator
00255 cbegin() const
00256 { return const_iterator(_M_buckets + _M_begin_bucket_index); }
00257
00258 const_iterator
00259 cend() const
00260 { return const_iterator(_M_buckets + _M_bucket_count); }
00261
00262 size_type
00263 size() const
00264 { return _M_element_count; }
00265
00266 bool
00267 empty() const
00268 { return size() == 0; }
00269
00270 allocator_type
00271 get_allocator() const
00272 { return allocator_type(_M_node_allocator); }
00273
00274 _Value_allocator_type
00275 _M_get_Value_allocator() const
00276 { return _Value_allocator_type(_M_node_allocator); }
00277
00278 size_type
00279 max_size() const
00280 { return _M_node_allocator.max_size(); }
00281
00282
00283 key_equal
00284 key_eq() const
00285 { return this->_M_eq; }
00286
00287
00288
00289
00290 size_type
00291 bucket_count() const
00292 { return _M_bucket_count; }
00293
00294 size_type
00295 max_bucket_count() const
00296 { return max_size(); }
00297
00298 size_type
00299 bucket_size(size_type __n) const
00300 { return std::distance(begin(__n), end(__n)); }
00301
00302 size_type
00303 bucket(const key_type& __k) const
00304 {
00305 return this->_M_bucket_index(__k, this->_M_hash_code(__k),
00306 bucket_count());
00307 }
00308
00309 local_iterator
00310 begin(size_type __n)
00311 { return local_iterator(_M_buckets[__n]); }
00312
00313 local_iterator
00314 end(size_type)
00315 { return local_iterator(0); }
00316
00317 const_local_iterator
00318 begin(size_type __n) const
00319 { return const_local_iterator(_M_buckets[__n]); }
00320
00321 const_local_iterator
00322 end(size_type) const
00323 { return const_local_iterator(0); }
00324
00325
00326 const_local_iterator
00327 cbegin(size_type __n) const
00328 { return const_local_iterator(_M_buckets[__n]); }
00329
00330 const_local_iterator
00331 cend(size_type) const
00332 { return const_local_iterator(0); }
00333
00334 float
00335 load_factor() const
00336 {
00337 return static_cast<float>(size()) / static_cast<float>(bucket_count());
00338 }
00339
00340
00341
00342
00343
00344 const _RehashPolicy&
00345 __rehash_policy() const
00346 { return _M_rehash_policy; }
00347
00348 void
00349 __rehash_policy(const _RehashPolicy&);
00350
00351
00352 iterator
00353 find(const key_type& __k);
00354
00355 const_iterator
00356 find(const key_type& __k) const;
00357
00358 size_type
00359 count(const key_type& __k) const;
00360
00361 std::pair<iterator, iterator>
00362 equal_range(const key_type& __k);
00363
00364 std::pair<const_iterator, const_iterator>
00365 equal_range(const key_type& __k) const;
00366
00367 private:
00368
00369
00370
00371
00372 typedef typename std::conditional<__unique_keys,
00373 std::pair<iterator, bool>,
00374 iterator>::type
00375 _Insert_Return_Type;
00376
00377 typedef typename std::conditional<__unique_keys,
00378 std::_Select1st<_Insert_Return_Type>,
00379 std::_Identity<_Insert_Return_Type>
00380 >::type
00381 _Insert_Conv_Type;
00382
00383 _Node*
00384 _M_find_node(_Node*, const key_type&,
00385 typename _Hashtable::_Hash_code_type) const;
00386
00387 iterator
00388 _M_insert_bucket(const value_type&, size_type,
00389 typename _Hashtable::_Hash_code_type);
00390
00391 std::pair<iterator, bool>
00392 _M_insert(const value_type&, std::true_type);
00393
00394 iterator
00395 _M_insert(const value_type&, std::false_type);
00396
00397 public:
00398
00399 _Insert_Return_Type
00400 insert(const value_type& __v)
00401 { return _M_insert(__v, std::integral_constant<bool,
00402 __unique_keys>()); }
00403
00404 iterator
00405 insert(const_iterator, const value_type& __v)
00406 { return iterator(_Insert_Conv_Type()(this->insert(__v))); }
00407
00408 template<typename _InputIterator>
00409 void
00410 insert(_InputIterator __first, _InputIterator __last);
00411
00412 void
00413 insert(initializer_list<value_type> __l)
00414 { this->insert(__l.begin(), __l.end()); }
00415
00416 iterator
00417 erase(const_iterator);
00418
00419 size_type
00420 erase(const key_type&);
00421
00422 iterator
00423 erase(const_iterator, const_iterator);
00424
00425 void
00426 clear();
00427
00428
00429 void rehash(size_type __n);
00430
00431
00432
00433
00434 private:
00435
00436 void _M_rehash(size_type __n);
00437 };
00438
00439
00440
00441 template<typename _Key, typename _Value,
00442 typename _Allocator, typename _ExtractKey, typename _Equal,
00443 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00444 bool __chc, bool __cit, bool __uk>
00445 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00446 _H1, _H2, _Hash, _RehashPolicy,
00447 __chc, __cit, __uk>::_Node*
00448 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00449 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00450 _M_allocate_node(const value_type& __v)
00451 {
00452 _Node* __n = _M_node_allocator.allocate(1);
00453 __try
00454 {
00455 _M_node_allocator.construct(__n, __v);
00456 __n->_M_next = 0;
00457 return __n;
00458 }
00459 __catch(...)
00460 {
00461 _M_node_allocator.deallocate(__n, 1);
00462 __throw_exception_again;
00463 }
00464 }
00465
00466 template<typename _Key, typename _Value,
00467 typename _Allocator, typename _ExtractKey, typename _Equal,
00468 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00469 bool __chc, bool __cit, bool __uk>
00470 void
00471 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00472 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00473 _M_deallocate_node(_Node* __n)
00474 {
00475 _M_node_allocator.destroy(__n);
00476 _M_node_allocator.deallocate(__n, 1);
00477 }
00478
00479 template<typename _Key, typename _Value,
00480 typename _Allocator, typename _ExtractKey, typename _Equal,
00481 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00482 bool __chc, bool __cit, bool __uk>
00483 void
00484 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00485 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00486 _M_deallocate_nodes(_Node** __array, size_type __n)
00487 {
00488 for (size_type __i = 0; __i < __n; ++__i)
00489 {
00490 _Node* __p = __array[__i];
00491 while (__p)
00492 {
00493 _Node* __tmp = __p;
00494 __p = __p->_M_next;
00495 _M_deallocate_node(__tmp);
00496 }
00497 __array[__i] = 0;
00498 }
00499 }
00500
00501 template<typename _Key, typename _Value,
00502 typename _Allocator, typename _ExtractKey, typename _Equal,
00503 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00504 bool __chc, bool __cit, bool __uk>
00505 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00506 _H1, _H2, _Hash, _RehashPolicy,
00507 __chc, __cit, __uk>::_Node**
00508 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00509 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00510 _M_allocate_buckets(size_type __n)
00511 {
00512 _Bucket_allocator_type __alloc(_M_node_allocator);
00513
00514
00515
00516 _Node** __p = __alloc.allocate(__n + 1);
00517 std::fill(__p, __p + __n, (_Node*) 0);
00518 __p[__n] = reinterpret_cast<_Node*>(0x1000);
00519 return __p;
00520 }
00521
00522 template<typename _Key, typename _Value,
00523 typename _Allocator, typename _ExtractKey, typename _Equal,
00524 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00525 bool __chc, bool __cit, bool __uk>
00526 void
00527 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00528 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00529 _M_deallocate_buckets(_Node** __p, size_type __n)
00530 {
00531 _Bucket_allocator_type __alloc(_M_node_allocator);
00532 __alloc.deallocate(__p, __n + 1);
00533 }
00534
00535 template<typename _Key, typename _Value,
00536 typename _Allocator, typename _ExtractKey, typename _Equal,
00537 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00538 bool __chc, bool __cit, bool __uk>
00539 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00540 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00541 _Hashtable(size_type __bucket_hint,
00542 const _H1& __h1, const _H2& __h2, const _Hash& __h,
00543 const _Equal& __eq, const _ExtractKey& __exk,
00544 const allocator_type& __a)
00545 : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
00546 __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00547 _H1, _H2, _Hash, __chc>(__exk, __eq,
00548 __h1, __h2, __h),
00549 __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
00550 _M_node_allocator(__a),
00551 _M_bucket_count(0),
00552 _M_element_count(0),
00553 _M_rehash_policy()
00554 {
00555 _M_bucket_count = _M_rehash_policy._M_next_bkt(__bucket_hint);
00556 _M_buckets = _M_allocate_buckets(_M_bucket_count);
00557 _M_begin_bucket_index = _M_bucket_count;
00558 }
00559
00560 template<typename _Key, typename _Value,
00561 typename _Allocator, typename _ExtractKey, typename _Equal,
00562 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00563 bool __chc, bool __cit, bool __uk>
00564 template<typename _InputIterator>
00565 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00566 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00567 _Hashtable(_InputIterator __f, _InputIterator __l,
00568 size_type __bucket_hint,
00569 const _H1& __h1, const _H2& __h2, const _Hash& __h,
00570 const _Equal& __eq, const _ExtractKey& __exk,
00571 const allocator_type& __a)
00572 : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(),
00573 __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00574 _H1, _H2, _Hash, __chc>(__exk, __eq,
00575 __h1, __h2, __h),
00576 __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(),
00577 _M_node_allocator(__a),
00578 _M_bucket_count(0),
00579 _M_element_count(0),
00580 _M_rehash_policy()
00581 {
00582 _M_bucket_count = std::max(_M_rehash_policy._M_next_bkt(__bucket_hint),
00583 _M_rehash_policy.
00584 _M_bkt_for_elements(__detail::
00585 __distance_fw(__f,
00586 __l)));
00587 _M_buckets = _M_allocate_buckets(_M_bucket_count);
00588 _M_begin_bucket_index = _M_bucket_count;
00589 __try
00590 {
00591 for (; __f != __l; ++__f)
00592 this->insert(*__f);
00593 }
00594 __catch(...)
00595 {
00596 clear();
00597 _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00598 __throw_exception_again;
00599 }
00600 }
00601
00602 template<typename _Key, typename _Value,
00603 typename _Allocator, typename _ExtractKey, typename _Equal,
00604 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00605 bool __chc, bool __cit, bool __uk>
00606 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00607 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00608 _Hashtable(const _Hashtable& __ht)
00609 : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
00610 __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00611 _H1, _H2, _Hash, __chc>(__ht),
00612 __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
00613 _M_node_allocator(__ht._M_node_allocator),
00614 _M_bucket_count(__ht._M_bucket_count),
00615 _M_begin_bucket_index(__ht._M_begin_bucket_index),
00616 _M_element_count(__ht._M_element_count),
00617 _M_rehash_policy(__ht._M_rehash_policy)
00618 {
00619 _M_buckets = _M_allocate_buckets(_M_bucket_count);
00620 __try
00621 {
00622 for (size_type __i = 0; __i < __ht._M_bucket_count; ++__i)
00623 {
00624 _Node* __n = __ht._M_buckets[__i];
00625 _Node** __tail = _M_buckets + __i;
00626 while (__n)
00627 {
00628 *__tail = _M_allocate_node(__n->_M_v);
00629 this->_M_copy_code(*__tail, __n);
00630 __tail = &((*__tail)->_M_next);
00631 __n = __n->_M_next;
00632 }
00633 }
00634 }
00635 __catch(...)
00636 {
00637 clear();
00638 _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00639 __throw_exception_again;
00640 }
00641 }
00642
00643 template<typename _Key, typename _Value,
00644 typename _Allocator, typename _ExtractKey, typename _Equal,
00645 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00646 bool __chc, bool __cit, bool __uk>
00647 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00648 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00649 _Hashtable(_Hashtable&& __ht)
00650 : __detail::_Rehash_base<_RehashPolicy, _Hashtable>(__ht),
00651 __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00652 _H1, _H2, _Hash, __chc>(__ht),
00653 __detail::_Map_base<_Key, _Value, _ExtractKey, __uk, _Hashtable>(__ht),
00654 _M_node_allocator(__ht._M_node_allocator),
00655 _M_buckets(__ht._M_buckets),
00656 _M_bucket_count(__ht._M_bucket_count),
00657 _M_begin_bucket_index(__ht._M_begin_bucket_index),
00658 _M_element_count(__ht._M_element_count),
00659 _M_rehash_policy(__ht._M_rehash_policy)
00660 {
00661 size_type __n_bkt = __ht._M_rehash_policy._M_next_bkt(0);
00662 __ht._M_buckets = __ht._M_allocate_buckets(__n_bkt);
00663 __ht._M_bucket_count = __n_bkt;
00664 __ht._M_begin_bucket_index = __ht._M_bucket_count;
00665 __ht._M_element_count = 0;
00666 __ht._M_rehash_policy = _RehashPolicy();
00667 }
00668
00669 template<typename _Key, typename _Value,
00670 typename _Allocator, typename _ExtractKey, typename _Equal,
00671 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00672 bool __chc, bool __cit, bool __uk>
00673 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00674 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00675 ~_Hashtable()
00676 {
00677 clear();
00678 _M_deallocate_buckets(_M_buckets, _M_bucket_count);
00679 }
00680
00681 template<typename _Key, typename _Value,
00682 typename _Allocator, typename _ExtractKey, typename _Equal,
00683 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00684 bool __chc, bool __cit, bool __uk>
00685 void
00686 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00687 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00688 swap(_Hashtable& __x)
00689 {
00690
00691
00692
00693 __detail::_Hash_code_base<_Key, _Value, _ExtractKey, _Equal,
00694 _H1, _H2, _Hash, __chc>::_M_swap(__x);
00695
00696
00697
00698 std::__alloc_swap<_Node_allocator_type>::_S_do_it(_M_node_allocator,
00699 __x._M_node_allocator);
00700
00701 std::swap(_M_rehash_policy, __x._M_rehash_policy);
00702 std::swap(_M_buckets, __x._M_buckets);
00703 std::swap(_M_bucket_count, __x._M_bucket_count);
00704 std::swap(_M_begin_bucket_index, __x._M_begin_bucket_index);
00705 std::swap(_M_element_count, __x._M_element_count);
00706 }
00707
00708 template<typename _Key, typename _Value,
00709 typename _Allocator, typename _ExtractKey, typename _Equal,
00710 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00711 bool __chc, bool __cit, bool __uk>
00712 void
00713 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00714 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00715 __rehash_policy(const _RehashPolicy& __pol)
00716 {
00717 _M_rehash_policy = __pol;
00718 size_type __n_bkt = __pol._M_bkt_for_elements(_M_element_count);
00719 if (__n_bkt > _M_bucket_count)
00720 _M_rehash(__n_bkt);
00721 }
00722
00723 template<typename _Key, typename _Value,
00724 typename _Allocator, typename _ExtractKey, typename _Equal,
00725 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00726 bool __chc, bool __cit, bool __uk>
00727 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00728 _H1, _H2, _Hash, _RehashPolicy,
00729 __chc, __cit, __uk>::iterator
00730 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00731 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00732 find(const key_type& __k)
00733 {
00734 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00735 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00736 _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
00737 return __p ? iterator(__p, _M_buckets + __n) : this->end();
00738 }
00739
00740 template<typename _Key, typename _Value,
00741 typename _Allocator, typename _ExtractKey, typename _Equal,
00742 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00743 bool __chc, bool __cit, bool __uk>
00744 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00745 _H1, _H2, _Hash, _RehashPolicy,
00746 __chc, __cit, __uk>::const_iterator
00747 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00748 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00749 find(const key_type& __k) const
00750 {
00751 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00752 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00753 _Node* __p = _M_find_node(_M_buckets[__n], __k, __code);
00754 return __p ? const_iterator(__p, _M_buckets + __n) : this->end();
00755 }
00756
00757 template<typename _Key, typename _Value,
00758 typename _Allocator, typename _ExtractKey, typename _Equal,
00759 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00760 bool __chc, bool __cit, bool __uk>
00761 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00762 _H1, _H2, _Hash, _RehashPolicy,
00763 __chc, __cit, __uk>::size_type
00764 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00765 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00766 count(const key_type& __k) const
00767 {
00768 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00769 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00770 std::size_t __result = 0;
00771 for (_Node* __p = _M_buckets[__n]; __p; __p = __p->_M_next)
00772 if (this->_M_compare(__k, __code, __p))
00773 ++__result;
00774 return __result;
00775 }
00776
00777 template<typename _Key, typename _Value,
00778 typename _Allocator, typename _ExtractKey, typename _Equal,
00779 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00780 bool __chc, bool __cit, bool __uk>
00781 std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00782 _ExtractKey, _Equal, _H1,
00783 _H2, _Hash, _RehashPolicy,
00784 __chc, __cit, __uk>::iterator,
00785 typename _Hashtable<_Key, _Value, _Allocator,
00786 _ExtractKey, _Equal, _H1,
00787 _H2, _Hash, _RehashPolicy,
00788 __chc, __cit, __uk>::iterator>
00789 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00790 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00791 equal_range(const key_type& __k)
00792 {
00793 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00794 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00795 _Node** __head = _M_buckets + __n;
00796 _Node* __p = _M_find_node(*__head, __k, __code);
00797
00798 if (__p)
00799 {
00800 _Node* __p1 = __p->_M_next;
00801 for (; __p1; __p1 = __p1->_M_next)
00802 if (!this->_M_compare(__k, __code, __p1))
00803 break;
00804
00805 iterator __first(__p, __head);
00806 iterator __last(__p1, __head);
00807 if (!__p1)
00808 __last._M_incr_bucket();
00809 return std::make_pair(__first, __last);
00810 }
00811 else
00812 return std::make_pair(this->end(), this->end());
00813 }
00814
00815 template<typename _Key, typename _Value,
00816 typename _Allocator, typename _ExtractKey, typename _Equal,
00817 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00818 bool __chc, bool __cit, bool __uk>
00819 std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00820 _ExtractKey, _Equal, _H1,
00821 _H2, _Hash, _RehashPolicy,
00822 __chc, __cit, __uk>::const_iterator,
00823 typename _Hashtable<_Key, _Value, _Allocator,
00824 _ExtractKey, _Equal, _H1,
00825 _H2, _Hash, _RehashPolicy,
00826 __chc, __cit, __uk>::const_iterator>
00827 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00828 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00829 equal_range(const key_type& __k) const
00830 {
00831 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00832 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00833 _Node** __head = _M_buckets + __n;
00834 _Node* __p = _M_find_node(*__head, __k, __code);
00835
00836 if (__p)
00837 {
00838 _Node* __p1 = __p->_M_next;
00839 for (; __p1; __p1 = __p1->_M_next)
00840 if (!this->_M_compare(__k, __code, __p1))
00841 break;
00842
00843 const_iterator __first(__p, __head);
00844 const_iterator __last(__p1, __head);
00845 if (!__p1)
00846 __last._M_incr_bucket();
00847 return std::make_pair(__first, __last);
00848 }
00849 else
00850 return std::make_pair(this->end(), this->end());
00851 }
00852
00853
00854
00855 template<typename _Key, typename _Value,
00856 typename _Allocator, typename _ExtractKey, typename _Equal,
00857 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00858 bool __chc, bool __cit, bool __uk>
00859 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey,
00860 _Equal, _H1, _H2, _Hash, _RehashPolicy,
00861 __chc, __cit, __uk>::_Node*
00862 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00863 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00864 _M_find_node(_Node* __p, const key_type& __k,
00865 typename _Hashtable::_Hash_code_type __code) const
00866 {
00867 for (; __p; __p = __p->_M_next)
00868 if (this->_M_compare(__k, __code, __p))
00869 return __p;
00870 return false;
00871 }
00872
00873
00874 template<typename _Key, typename _Value,
00875 typename _Allocator, typename _ExtractKey, typename _Equal,
00876 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00877 bool __chc, bool __cit, bool __uk>
00878 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00879 _H1, _H2, _Hash, _RehashPolicy,
00880 __chc, __cit, __uk>::iterator
00881 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00882 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00883 _M_insert_bucket(const value_type& __v, size_type __n,
00884 typename _Hashtable::_Hash_code_type __code)
00885 {
00886 std::pair<bool, std::size_t> __do_rehash
00887 = _M_rehash_policy._M_need_rehash(_M_bucket_count,
00888 _M_element_count, 1);
00889
00890
00891
00892 _Node* __new_node = _M_allocate_node(__v);
00893
00894 __try
00895 {
00896 if (__do_rehash.first)
00897 {
00898 const key_type& __k = this->_M_extract(__v);
00899 __n = this->_M_bucket_index(__k, __code, __do_rehash.second);
00900 _M_rehash(__do_rehash.second);
00901 }
00902
00903 __new_node->_M_next = _M_buckets[__n];
00904 this->_M_store_code(__new_node, __code);
00905 _M_buckets[__n] = __new_node;
00906 ++_M_element_count;
00907 if (__n < _M_begin_bucket_index)
00908 _M_begin_bucket_index = __n;
00909 return iterator(__new_node, _M_buckets + __n);
00910 }
00911 __catch(...)
00912 {
00913 _M_deallocate_node(__new_node);
00914 __throw_exception_again;
00915 }
00916 }
00917
00918
00919 template<typename _Key, typename _Value,
00920 typename _Allocator, typename _ExtractKey, typename _Equal,
00921 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00922 bool __chc, bool __cit, bool __uk>
00923 std::pair<typename _Hashtable<_Key, _Value, _Allocator,
00924 _ExtractKey, _Equal, _H1,
00925 _H2, _Hash, _RehashPolicy,
00926 __chc, __cit, __uk>::iterator, bool>
00927 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00928 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00929 _M_insert(const value_type& __v, std::true_type)
00930 {
00931 const key_type& __k = this->_M_extract(__v);
00932 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00933 size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00934
00935 if (_Node* __p = _M_find_node(_M_buckets[__n], __k, __code))
00936 return std::make_pair(iterator(__p, _M_buckets + __n), false);
00937 return std::make_pair(_M_insert_bucket(__v, __n, __code), true);
00938 }
00939
00940
00941 template<typename _Key, typename _Value,
00942 typename _Allocator, typename _ExtractKey, typename _Equal,
00943 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00944 bool __chc, bool __cit, bool __uk>
00945 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00946 _H1, _H2, _Hash, _RehashPolicy,
00947 __chc, __cit, __uk>::iterator
00948 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00949 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00950 _M_insert(const value_type& __v, std::false_type)
00951 {
00952 std::pair<bool, std::size_t> __do_rehash
00953 = _M_rehash_policy._M_need_rehash(_M_bucket_count,
00954 _M_element_count, 1);
00955 if (__do_rehash.first)
00956 _M_rehash(__do_rehash.second);
00957
00958 const key_type& __k = this->_M_extract(__v);
00959 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
00960 size_type __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
00961
00962
00963 _Node* __prev = _M_find_node(_M_buckets[__n], __k, __code);
00964 _Node* __new_node = _M_allocate_node(__v);
00965
00966 if (__prev)
00967 {
00968 __new_node->_M_next = __prev->_M_next;
00969 __prev->_M_next = __new_node;
00970 }
00971 else
00972 {
00973 __new_node->_M_next = _M_buckets[__n];
00974 _M_buckets[__n] = __new_node;
00975 if (__n < _M_begin_bucket_index)
00976 _M_begin_bucket_index = __n;
00977 }
00978 this->_M_store_code(__new_node, __code);
00979
00980 ++_M_element_count;
00981 return iterator(__new_node, _M_buckets + __n);
00982 }
00983
00984 template<typename _Key, typename _Value,
00985 typename _Allocator, typename _ExtractKey, typename _Equal,
00986 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
00987 bool __chc, bool __cit, bool __uk>
00988 template<typename _InputIterator>
00989 void
00990 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
00991 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
00992 insert(_InputIterator __first, _InputIterator __last)
00993 {
00994 size_type __n_elt = __detail::__distance_fw(__first, __last);
00995 std::pair<bool, std::size_t> __do_rehash
00996 = _M_rehash_policy._M_need_rehash(_M_bucket_count,
00997 _M_element_count, __n_elt);
00998 if (__do_rehash.first)
00999 _M_rehash(__do_rehash.second);
01000
01001 for (; __first != __last; ++__first)
01002 this->insert(*__first);
01003 }
01004
01005 template<typename _Key, typename _Value,
01006 typename _Allocator, typename _ExtractKey, typename _Equal,
01007 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01008 bool __chc, bool __cit, bool __uk>
01009 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01010 _H1, _H2, _Hash, _RehashPolicy,
01011 __chc, __cit, __uk>::iterator
01012 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01013 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01014 erase(const_iterator __it)
01015 {
01016 iterator __result(__it._M_cur_node, __it._M_cur_bucket);
01017 ++__result;
01018
01019 _Node* __cur = *__it._M_cur_bucket;
01020 if (__cur == __it._M_cur_node)
01021 {
01022 *__it._M_cur_bucket = __cur->_M_next;
01023
01024
01025
01026 if (!_M_buckets[_M_begin_bucket_index])
01027 _M_begin_bucket_index = __result._M_cur_bucket - _M_buckets;
01028 }
01029 else
01030 {
01031 _Node* __next = __cur->_M_next;
01032 while (__next != __it._M_cur_node)
01033 {
01034 __cur = __next;
01035 __next = __cur->_M_next;
01036 }
01037 __cur->_M_next = __next->_M_next;
01038 }
01039
01040 _M_deallocate_node(__it._M_cur_node);
01041 --_M_element_count;
01042
01043 return __result;
01044 }
01045
01046 template<typename _Key, typename _Value,
01047 typename _Allocator, typename _ExtractKey, typename _Equal,
01048 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01049 bool __chc, bool __cit, bool __uk>
01050 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01051 _H1, _H2, _Hash, _RehashPolicy,
01052 __chc, __cit, __uk>::size_type
01053 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01054 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01055 erase(const key_type& __k)
01056 {
01057 typename _Hashtable::_Hash_code_type __code = this->_M_hash_code(__k);
01058 std::size_t __n = this->_M_bucket_index(__k, __code, _M_bucket_count);
01059 size_type __result = 0;
01060
01061 _Node** __slot = _M_buckets + __n;
01062 while (*__slot && !this->_M_compare(__k, __code, *__slot))
01063 __slot = &((*__slot)->_M_next);
01064
01065 _Node** __saved_slot = 0;
01066 while (*__slot && this->_M_compare(__k, __code, *__slot))
01067 {
01068
01069
01070
01071 if (std::__addressof(this->_M_extract((*__slot)->_M_v))
01072 != std::__addressof(__k))
01073 {
01074 _Node* __p = *__slot;
01075 *__slot = __p->_M_next;
01076 _M_deallocate_node(__p);
01077 --_M_element_count;
01078 ++__result;
01079 }
01080 else
01081 {
01082 __saved_slot = __slot;
01083 __slot = &((*__slot)->_M_next);
01084 }
01085 }
01086
01087 if (__saved_slot)
01088 {
01089 _Node* __p = *__saved_slot;
01090 *__saved_slot = __p->_M_next;
01091 _M_deallocate_node(__p);
01092 --_M_element_count;
01093 ++__result;
01094 }
01095
01096
01097
01098 if (!_M_buckets[_M_begin_bucket_index])
01099 {
01100 if (!_M_element_count)
01101 _M_begin_bucket_index = _M_bucket_count;
01102 else
01103 {
01104 ++_M_begin_bucket_index;
01105 while (!_M_buckets[_M_begin_bucket_index])
01106 ++_M_begin_bucket_index;
01107 }
01108 }
01109
01110 return __result;
01111 }
01112
01113
01114
01115
01116 template<typename _Key, typename _Value,
01117 typename _Allocator, typename _ExtractKey, typename _Equal,
01118 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01119 bool __chc, bool __cit, bool __uk>
01120 typename _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01121 _H1, _H2, _Hash, _RehashPolicy,
01122 __chc, __cit, __uk>::iterator
01123 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01124 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01125 erase(const_iterator __first, const_iterator __last)
01126 {
01127 while (__first != __last)
01128 __first = this->erase(__first);
01129 return iterator(__last._M_cur_node, __last._M_cur_bucket);
01130 }
01131
01132 template<typename _Key, typename _Value,
01133 typename _Allocator, typename _ExtractKey, typename _Equal,
01134 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01135 bool __chc, bool __cit, bool __uk>
01136 void
01137 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01138 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01139 clear()
01140 {
01141 _M_deallocate_nodes(_M_buckets, _M_bucket_count);
01142 _M_element_count = 0;
01143 _M_begin_bucket_index = _M_bucket_count;
01144 }
01145
01146 template<typename _Key, typename _Value,
01147 typename _Allocator, typename _ExtractKey, typename _Equal,
01148 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01149 bool __chc, bool __cit, bool __uk>
01150 void
01151 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01152 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01153 rehash(size_type __n)
01154 {
01155 _M_rehash(std::max(_M_rehash_policy._M_next_bkt(__n),
01156 _M_rehash_policy._M_bkt_for_elements(_M_element_count
01157 + 1)));
01158 }
01159
01160 template<typename _Key, typename _Value,
01161 typename _Allocator, typename _ExtractKey, typename _Equal,
01162 typename _H1, typename _H2, typename _Hash, typename _RehashPolicy,
01163 bool __chc, bool __cit, bool __uk>
01164 void
01165 _Hashtable<_Key, _Value, _Allocator, _ExtractKey, _Equal,
01166 _H1, _H2, _Hash, _RehashPolicy, __chc, __cit, __uk>::
01167 _M_rehash(size_type __n)
01168 {
01169 _Node** __new_array = _M_allocate_buckets(__n);
01170 __try
01171 {
01172 _M_begin_bucket_index = __n;
01173 for (size_type __i = 0; __i < _M_bucket_count; ++__i)
01174 while (_Node* __p = _M_buckets[__i])
01175 {
01176 std::size_t __new_index = this->_M_bucket_index(__p, __n);
01177 _M_buckets[__i] = __p->_M_next;
01178 __p->_M_next = __new_array[__new_index];
01179 __new_array[__new_index] = __p;
01180 if (__new_index < _M_begin_bucket_index)
01181 _M_begin_bucket_index = __new_index;
01182 }
01183 _M_deallocate_buckets(_M_buckets, _M_bucket_count);
01184 _M_bucket_count = __n;
01185 _M_buckets = __new_array;
01186 }
01187 __catch(...)
01188 {
01189
01190
01191
01192
01193 _M_deallocate_nodes(__new_array, __n);
01194 _M_deallocate_buckets(__new_array, __n);
01195 _M_deallocate_nodes(_M_buckets, _M_bucket_count);
01196 _M_element_count = 0;
01197 _M_begin_bucket_index = _M_bucket_count;
01198 __throw_exception_again;
01199 }
01200 }
01201 }
01202
01203 #endif // _HASHTABLE_H