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