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