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 #ifndef __SGI_STL_INTERNAL_HASHTABLE_H
00032 #define __SGI_STL_INTERNAL_HASHTABLE_H
00033
00034
00035
00036
00037 #include <bits/stl_algobase.h>
00038 #include <bits/stl_alloc.h>
00039 #include <bits/stl_construct.h>
00040 #include <bits/stl_tempbuf.h>
00041 #include <bits/stl_algo.h>
00042 #include <bits/stl_uninitialized.h>
00043 #include <bits/stl_function.h>
00044 #include <bits/stl_vector.h>
00045 #include <ext/stl_hash_fun.h>
00046
00047 namespace std
00048 {
00049
00050 template <class _Val>
00051 struct _Hashtable_node
00052 {
00053 _Hashtable_node* _M_next;
00054 _Val _M_val;
00055 };
00056
00057 template <class _Val, class _Key, class _HashFcn,
00058 class _ExtractKey, class _EqualKey, class _Alloc = alloc>
00059 class hashtable;
00060
00061 template <class _Val, class _Key, class _HashFcn,
00062 class _ExtractKey, class _EqualKey, class _Alloc>
00063 struct _Hashtable_iterator;
00064
00065 template <class _Val, class _Key, class _HashFcn,
00066 class _ExtractKey, class _EqualKey, class _Alloc>
00067 struct _Hashtable_const_iterator;
00068
00069 template <class _Val, class _Key, class _HashFcn,
00070 class _ExtractKey, class _EqualKey, class _Alloc>
00071 struct _Hashtable_iterator {
00072 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00073 _Hashtable;
00074 typedef _Hashtable_iterator<_Val, _Key, _HashFcn,
00075 _ExtractKey, _EqualKey, _Alloc>
00076 iterator;
00077 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
00078 _ExtractKey, _EqualKey, _Alloc>
00079 const_iterator;
00080 typedef _Hashtable_node<_Val> _Node;
00081
00082 typedef forward_iterator_tag iterator_category;
00083 typedef _Val value_type;
00084 typedef ptrdiff_t difference_type;
00085 typedef size_t size_type;
00086 typedef _Val& reference;
00087 typedef _Val* pointer;
00088
00089 _Node* _M_cur;
00090 _Hashtable* _M_ht;
00091
00092 _Hashtable_iterator(_Node* __n, _Hashtable* __tab)
00093 : _M_cur(__n), _M_ht(__tab) {}
00094 _Hashtable_iterator() {}
00095 reference operator*() const { return _M_cur->_M_val; }
00096 pointer operator->() const { return &(operator*()); }
00097 iterator& operator++();
00098 iterator operator++(int);
00099 bool operator==(const iterator& __it) const
00100 { return _M_cur == __it._M_cur; }
00101 bool operator!=(const iterator& __it) const
00102 { return _M_cur != __it._M_cur; }
00103 };
00104
00105
00106 template <class _Val, class _Key, class _HashFcn,
00107 class _ExtractKey, class _EqualKey, class _Alloc>
00108 struct _Hashtable_const_iterator {
00109 typedef hashtable<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00110 _Hashtable;
00111 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,
00112 _ExtractKey,_EqualKey,_Alloc>
00113 iterator;
00114 typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn,
00115 _ExtractKey, _EqualKey, _Alloc>
00116 const_iterator;
00117 typedef _Hashtable_node<_Val> _Node;
00118
00119 typedef forward_iterator_tag iterator_category;
00120 typedef _Val value_type;
00121 typedef ptrdiff_t difference_type;
00122 typedef size_t size_type;
00123 typedef const _Val& reference;
00124 typedef const _Val* pointer;
00125
00126 const _Node* _M_cur;
00127 const _Hashtable* _M_ht;
00128
00129 _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab)
00130 : _M_cur(__n), _M_ht(__tab) {}
00131 _Hashtable_const_iterator() {}
00132 _Hashtable_const_iterator(const iterator& __it)
00133 : _M_cur(__it._M_cur), _M_ht(__it._M_ht) {}
00134 reference operator*() const { return _M_cur->_M_val; }
00135 pointer operator->() const { return &(operator*()); }
00136 const_iterator& operator++();
00137 const_iterator operator++(int);
00138 bool operator==(const const_iterator& __it) const
00139 { return _M_cur == __it._M_cur; }
00140 bool operator!=(const const_iterator& __it) const
00141 { return _M_cur != __it._M_cur; }
00142 };
00143
00144
00145 enum { __stl_num_primes = 28 };
00146
00147 static const unsigned long __stl_prime_list[__stl_num_primes] =
00148 {
00149 53ul, 97ul, 193ul, 389ul, 769ul,
00150 1543ul, 3079ul, 6151ul, 12289ul, 24593ul,
00151 49157ul, 98317ul, 196613ul, 393241ul, 786433ul,
00152 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul,
00153 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,
00154 1610612741ul, 3221225473ul, 4294967291ul
00155 };
00156
00157 inline unsigned long __stl_next_prime(unsigned long __n)
00158 {
00159 const unsigned long* __first = __stl_prime_list;
00160 const unsigned long* __last = __stl_prime_list + (int)__stl_num_primes;
00161 const unsigned long* pos = lower_bound(__first, __last, __n);
00162 return pos == __last ? *(__last - 1) : *pos;
00163 }
00164
00165
00166
00167 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00168 class hashtable;
00169
00170 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00171 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00172 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2);
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 template <class _Val, class _Key, class _HashFcn,
00184 class _ExtractKey, class _EqualKey, class _Alloc>
00185 class hashtable {
00186 public:
00187 typedef _Key key_type;
00188 typedef _Val value_type;
00189 typedef _HashFcn hasher;
00190 typedef _EqualKey key_equal;
00191
00192 typedef size_t size_type;
00193 typedef ptrdiff_t difference_type;
00194 typedef value_type* pointer;
00195 typedef const value_type* const_pointer;
00196 typedef value_type& reference;
00197 typedef const value_type& const_reference;
00198
00199 hasher hash_funct() const { return _M_hash; }
00200 key_equal key_eq() const { return _M_equals; }
00201
00202 private:
00203 typedef _Hashtable_node<_Val> _Node;
00204
00205 public:
00206 typedef typename _Alloc_traits<_Val,_Alloc>::allocator_type allocator_type;
00207 allocator_type get_allocator() const { return _M_node_allocator; }
00208 private:
00209 typename _Alloc_traits<_Node, _Alloc>::allocator_type _M_node_allocator;
00210 _Node* _M_get_node() { return _M_node_allocator.allocate(1); }
00211 void _M_put_node(_Node* __p) { _M_node_allocator.deallocate(__p, 1); }
00212
00213 private:
00214 hasher _M_hash;
00215 key_equal _M_equals;
00216 _ExtractKey _M_get_key;
00217 vector<_Node*,_Alloc> _M_buckets;
00218 size_type _M_num_elements;
00219
00220 public:
00221 typedef _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>
00222 iterator;
00223 typedef _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,
00224 _Alloc>
00225 const_iterator;
00226
00227 friend struct
00228 _Hashtable_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
00229 friend struct
00230 _Hashtable_const_iterator<_Val,_Key,_HashFcn,_ExtractKey,_EqualKey,_Alloc>;
00231
00232 public:
00233 hashtable(size_type __n,
00234 const _HashFcn& __hf,
00235 const _EqualKey& __eql,
00236 const _ExtractKey& __ext,
00237 const allocator_type& __a = allocator_type())
00238 : _M_node_allocator(__a),
00239 _M_hash(__hf),
00240 _M_equals(__eql),
00241 _M_get_key(__ext),
00242 _M_buckets(__a),
00243 _M_num_elements(0)
00244 {
00245 _M_initialize_buckets(__n);
00246 }
00247
00248 hashtable(size_type __n,
00249 const _HashFcn& __hf,
00250 const _EqualKey& __eql,
00251 const allocator_type& __a = allocator_type())
00252 : _M_node_allocator(__a),
00253 _M_hash(__hf),
00254 _M_equals(__eql),
00255 _M_get_key(_ExtractKey()),
00256 _M_buckets(__a),
00257 _M_num_elements(0)
00258 {
00259 _M_initialize_buckets(__n);
00260 }
00261
00262 hashtable(const hashtable& __ht)
00263 : _M_node_allocator(__ht.get_allocator()),
00264 _M_hash(__ht._M_hash),
00265 _M_equals(__ht._M_equals),
00266 _M_get_key(__ht._M_get_key),
00267 _M_buckets(__ht.get_allocator()),
00268 _M_num_elements(0)
00269 {
00270 _M_copy_from(__ht);
00271 }
00272
00273 hashtable& operator= (const hashtable& __ht)
00274 {
00275 if (&__ht != this) {
00276 clear();
00277 _M_hash = __ht._M_hash;
00278 _M_equals = __ht._M_equals;
00279 _M_get_key = __ht._M_get_key;
00280 _M_copy_from(__ht);
00281 }
00282 return *this;
00283 }
00284
00285 ~hashtable() { clear(); }
00286
00287 size_type size() const { return _M_num_elements; }
00288 size_type max_size() const { return size_type(-1); }
00289 bool empty() const { return size() == 0; }
00290
00291 void swap(hashtable& __ht)
00292 {
00293 std::swap(_M_hash, __ht._M_hash);
00294 std::swap(_M_equals, __ht._M_equals);
00295 std::swap(_M_get_key, __ht._M_get_key);
00296 _M_buckets.swap(__ht._M_buckets);
00297 std::swap(_M_num_elements, __ht._M_num_elements);
00298 }
00299
00300 iterator begin()
00301 {
00302 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
00303 if (_M_buckets[__n])
00304 return iterator(_M_buckets[__n], this);
00305 return end();
00306 }
00307
00308 iterator end() { return iterator(0, this); }
00309
00310 const_iterator begin() const
00311 {
00312 for (size_type __n = 0; __n < _M_buckets.size(); ++__n)
00313 if (_M_buckets[__n])
00314 return const_iterator(_M_buckets[__n], this);
00315 return end();
00316 }
00317
00318 const_iterator end() const { return const_iterator(0, this); }
00319
00320 template <class _Vl, class _Ky, class _HF, class _Ex, class _Eq, class _Al>
00321 friend bool operator== (const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&,
00322 const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&);
00323 public:
00324
00325 size_type bucket_count() const { return _M_buckets.size(); }
00326
00327 size_type max_bucket_count() const
00328 { return __stl_prime_list[(int)__stl_num_primes - 1]; }
00329
00330 size_type elems_in_bucket(size_type __bucket) const
00331 {
00332 size_type __result = 0;
00333 for (_Node* __cur = _M_buckets[__bucket]; __cur; __cur = __cur->_M_next)
00334 __result += 1;
00335 return __result;
00336 }
00337
00338 pair<iterator, bool> insert_unique(const value_type& __obj)
00339 {
00340 resize(_M_num_elements + 1);
00341 return insert_unique_noresize(__obj);
00342 }
00343
00344 iterator insert_equal(const value_type& __obj)
00345 {
00346 resize(_M_num_elements + 1);
00347 return insert_equal_noresize(__obj);
00348 }
00349
00350 pair<iterator, bool> insert_unique_noresize(const value_type& __obj);
00351 iterator insert_equal_noresize(const value_type& __obj);
00352
00353 template <class _InputIterator>
00354 void insert_unique(_InputIterator __f, _InputIterator __l)
00355 {
00356 insert_unique(__f, __l, __iterator_category(__f));
00357 }
00358
00359 template <class _InputIterator>
00360 void insert_equal(_InputIterator __f, _InputIterator __l)
00361 {
00362 insert_equal(__f, __l, __iterator_category(__f));
00363 }
00364
00365 template <class _InputIterator>
00366 void insert_unique(_InputIterator __f, _InputIterator __l,
00367 input_iterator_tag)
00368 {
00369 for ( ; __f != __l; ++__f)
00370 insert_unique(*__f);
00371 }
00372
00373 template <class _InputIterator>
00374 void insert_equal(_InputIterator __f, _InputIterator __l,
00375 input_iterator_tag)
00376 {
00377 for ( ; __f != __l; ++__f)
00378 insert_equal(*__f);
00379 }
00380
00381 template <class _ForwardIterator>
00382 void insert_unique(_ForwardIterator __f, _ForwardIterator __l,
00383 forward_iterator_tag)
00384 {
00385 size_type __n = 0;
00386 distance(__f, __l, __n);
00387 resize(_M_num_elements + __n);
00388 for ( ; __n > 0; --__n, ++__f)
00389 insert_unique_noresize(*__f);
00390 }
00391
00392 template <class _ForwardIterator>
00393 void insert_equal(_ForwardIterator __f, _ForwardIterator __l,
00394 forward_iterator_tag)
00395 {
00396 size_type __n = 0;
00397 distance(__f, __l, __n);
00398 resize(_M_num_elements + __n);
00399 for ( ; __n > 0; --__n, ++__f)
00400 insert_equal_noresize(*__f);
00401 }
00402
00403 reference find_or_insert(const value_type& __obj);
00404
00405 iterator find(const key_type& __key)
00406 {
00407 size_type __n = _M_bkt_num_key(__key);
00408 _Node* __first;
00409 for ( __first = _M_buckets[__n];
00410 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
00411 __first = __first->_M_next)
00412 {}
00413 return iterator(__first, this);
00414 }
00415
00416 const_iterator find(const key_type& __key) const
00417 {
00418 size_type __n = _M_bkt_num_key(__key);
00419 const _Node* __first;
00420 for ( __first = _M_buckets[__n];
00421 __first && !_M_equals(_M_get_key(__first->_M_val), __key);
00422 __first = __first->_M_next)
00423 {}
00424 return const_iterator(__first, this);
00425 }
00426
00427 size_type count(const key_type& __key) const
00428 {
00429 const size_type __n = _M_bkt_num_key(__key);
00430 size_type __result = 0;
00431
00432 for (const _Node* __cur = _M_buckets[__n]; __cur; __cur = __cur->_M_next)
00433 if (_M_equals(_M_get_key(__cur->_M_val), __key))
00434 ++__result;
00435 return __result;
00436 }
00437
00438 pair<iterator, iterator>
00439 equal_range(const key_type& __key);
00440
00441 pair<const_iterator, const_iterator>
00442 equal_range(const key_type& __key) const;
00443
00444 size_type erase(const key_type& __key);
00445 void erase(const iterator& __it);
00446 void erase(iterator __first, iterator __last);
00447
00448 void erase(const const_iterator& __it);
00449 void erase(const_iterator __first, const_iterator __last);
00450
00451 void resize(size_type __num_elements_hint);
00452 void clear();
00453
00454 private:
00455 size_type _M_next_size(size_type __n) const
00456 { return __stl_next_prime(__n); }
00457
00458 void _M_initialize_buckets(size_type __n)
00459 {
00460 const size_type __n_buckets = _M_next_size(__n);
00461 _M_buckets.reserve(__n_buckets);
00462 _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0);
00463 _M_num_elements = 0;
00464 }
00465
00466 size_type _M_bkt_num_key(const key_type& __key) const
00467 {
00468 return _M_bkt_num_key(__key, _M_buckets.size());
00469 }
00470
00471 size_type _M_bkt_num(const value_type& __obj) const
00472 {
00473 return _M_bkt_num_key(_M_get_key(__obj));
00474 }
00475
00476 size_type _M_bkt_num_key(const key_type& __key, size_t __n) const
00477 {
00478 return _M_hash(__key) % __n;
00479 }
00480
00481 size_type _M_bkt_num(const value_type& __obj, size_t __n) const
00482 {
00483 return _M_bkt_num_key(_M_get_key(__obj), __n);
00484 }
00485
00486 _Node* _M_new_node(const value_type& __obj)
00487 {
00488 _Node* __n = _M_get_node();
00489 __n->_M_next = 0;
00490 __STL_TRY {
00491 construct(&__n->_M_val, __obj);
00492 return __n;
00493 }
00494 __STL_UNWIND(_M_put_node(__n));
00495 }
00496
00497 void _M_delete_node(_Node* __n)
00498 {
00499 destroy(&__n->_M_val);
00500 _M_put_node(__n);
00501 }
00502
00503 void _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last);
00504 void _M_erase_bucket(const size_type __n, _Node* __last);
00505
00506 void _M_copy_from(const hashtable& __ht);
00507
00508 };
00509
00510 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
00511 class _All>
00512 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
00513 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
00514 {
00515 const _Node* __old = _M_cur;
00516 _M_cur = _M_cur->_M_next;
00517 if (!_M_cur) {
00518 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
00519 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
00520 _M_cur = _M_ht->_M_buckets[__bucket];
00521 }
00522 return *this;
00523 }
00524
00525 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
00526 class _All>
00527 inline _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
00528 _Hashtable_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
00529 {
00530 iterator __tmp = *this;
00531 ++*this;
00532 return __tmp;
00533 }
00534
00535 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
00536 class _All>
00537 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>&
00538 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++()
00539 {
00540 const _Node* __old = _M_cur;
00541 _M_cur = _M_cur->_M_next;
00542 if (!_M_cur) {
00543 size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val);
00544 while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size())
00545 _M_cur = _M_ht->_M_buckets[__bucket];
00546 }
00547 return *this;
00548 }
00549
00550 template <class _Val, class _Key, class _HF, class _ExK, class _EqK,
00551 class _All>
00552 inline _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>
00553 _Hashtable_const_iterator<_Val,_Key,_HF,_ExK,_EqK,_All>::operator++(int)
00554 {
00555 const_iterator __tmp = *this;
00556 ++*this;
00557 return __tmp;
00558 }
00559
00560 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00561 bool operator==(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00562 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2)
00563 {
00564 typedef typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::_Node _Node;
00565 if (__ht1._M_buckets.size() != __ht2._M_buckets.size())
00566 return false;
00567 for (size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) {
00568 _Node* __cur1 = __ht1._M_buckets[__n];
00569 _Node* __cur2 = __ht2._M_buckets[__n];
00570 for ( ; __cur1 && __cur2 && __cur1->_M_val == __cur2->_M_val;
00571 __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next)
00572 {}
00573 if (__cur1 || __cur2)
00574 return false;
00575 }
00576 return true;
00577 }
00578
00579 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00580 inline bool operator!=(const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht1,
00581 const hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>& __ht2) {
00582 return !(__ht1 == __ht2);
00583 }
00584
00585 template <class _Val, class _Key, class _HF, class _Extract, class _EqKey,
00586 class _All>
00587 inline void swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1,
00588 hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) {
00589 __ht1.swap(__ht2);
00590 }
00591
00592
00593 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00594 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator, bool>
00595 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00596 ::insert_unique_noresize(const value_type& __obj)
00597 {
00598 const size_type __n = _M_bkt_num(__obj);
00599 _Node* __first = _M_buckets[__n];
00600
00601 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
00602 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
00603 return pair<iterator, bool>(iterator(__cur, this), false);
00604
00605 _Node* __tmp = _M_new_node(__obj);
00606 __tmp->_M_next = __first;
00607 _M_buckets[__n] = __tmp;
00608 ++_M_num_elements;
00609 return pair<iterator, bool>(iterator(__tmp, this), true);
00610 }
00611
00612 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00613 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator
00614 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00615 ::insert_equal_noresize(const value_type& __obj)
00616 {
00617 const size_type __n = _M_bkt_num(__obj);
00618 _Node* __first = _M_buckets[__n];
00619
00620 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
00621 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) {
00622 _Node* __tmp = _M_new_node(__obj);
00623 __tmp->_M_next = __cur->_M_next;
00624 __cur->_M_next = __tmp;
00625 ++_M_num_elements;
00626 return iterator(__tmp, this);
00627 }
00628
00629 _Node* __tmp = _M_new_node(__obj);
00630 __tmp->_M_next = __first;
00631 _M_buckets[__n] = __tmp;
00632 ++_M_num_elements;
00633 return iterator(__tmp, this);
00634 }
00635
00636 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00637 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::reference
00638 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::find_or_insert(const value_type& __obj)
00639 {
00640 resize(_M_num_elements + 1);
00641
00642 size_type __n = _M_bkt_num(__obj);
00643 _Node* __first = _M_buckets[__n];
00644
00645 for (_Node* __cur = __first; __cur; __cur = __cur->_M_next)
00646 if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj)))
00647 return __cur->_M_val;
00648
00649 _Node* __tmp = _M_new_node(__obj);
00650 __tmp->_M_next = __first;
00651 _M_buckets[__n] = __tmp;
00652 ++_M_num_elements;
00653 return __tmp->_M_val;
00654 }
00655
00656 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00657 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator,
00658 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::iterator>
00659 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::equal_range(const key_type& __key)
00660 {
00661 typedef pair<iterator, iterator> _Pii;
00662 const size_type __n = _M_bkt_num_key(__key);
00663
00664 for (_Node* __first = _M_buckets[__n]; __first; __first = __first->_M_next)
00665 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00666 for (_Node* __cur = __first->_M_next; __cur; __cur = __cur->_M_next)
00667 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
00668 return _Pii(iterator(__first, this), iterator(__cur, this));
00669 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
00670 if (_M_buckets[__m])
00671 return _Pii(iterator(__first, this),
00672 iterator(_M_buckets[__m], this));
00673 return _Pii(iterator(__first, this), end());
00674 }
00675 return _Pii(end(), end());
00676 }
00677
00678 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00679 pair<typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator,
00680 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::const_iterator>
00681 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00682 ::equal_range(const key_type& __key) const
00683 {
00684 typedef pair<const_iterator, const_iterator> _Pii;
00685 const size_type __n = _M_bkt_num_key(__key);
00686
00687 for (const _Node* __first = _M_buckets[__n] ;
00688 __first;
00689 __first = __first->_M_next) {
00690 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00691 for (const _Node* __cur = __first->_M_next;
00692 __cur;
00693 __cur = __cur->_M_next)
00694 if (!_M_equals(_M_get_key(__cur->_M_val), __key))
00695 return _Pii(const_iterator(__first, this),
00696 const_iterator(__cur, this));
00697 for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m)
00698 if (_M_buckets[__m])
00699 return _Pii(const_iterator(__first, this),
00700 const_iterator(_M_buckets[__m], this));
00701 return _Pii(const_iterator(__first, this), end());
00702 }
00703 }
00704 return _Pii(end(), end());
00705 }
00706
00707 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00708 typename hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::size_type
00709 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const key_type& __key)
00710 {
00711 const size_type __n = _M_bkt_num_key(__key);
00712 _Node* __first = _M_buckets[__n];
00713 size_type __erased = 0;
00714
00715 if (__first) {
00716 _Node* __cur = __first;
00717 _Node* __next = __cur->_M_next;
00718 while (__next) {
00719 if (_M_equals(_M_get_key(__next->_M_val), __key)) {
00720 __cur->_M_next = __next->_M_next;
00721 _M_delete_node(__next);
00722 __next = __cur->_M_next;
00723 ++__erased;
00724 --_M_num_elements;
00725 }
00726 else {
00727 __cur = __next;
00728 __next = __cur->_M_next;
00729 }
00730 }
00731 if (_M_equals(_M_get_key(__first->_M_val), __key)) {
00732 _M_buckets[__n] = __first->_M_next;
00733 _M_delete_node(__first);
00734 ++__erased;
00735 --_M_num_elements;
00736 }
00737 }
00738 return __erased;
00739 }
00740
00741 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00742 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const iterator& __it)
00743 {
00744 _Node* __p = __it._M_cur;
00745 if (__p) {
00746 const size_type __n = _M_bkt_num(__p->_M_val);
00747 _Node* __cur = _M_buckets[__n];
00748
00749 if (__cur == __p) {
00750 _M_buckets[__n] = __cur->_M_next;
00751 _M_delete_node(__cur);
00752 --_M_num_elements;
00753 }
00754 else {
00755 _Node* __next = __cur->_M_next;
00756 while (__next) {
00757 if (__next == __p) {
00758 __cur->_M_next = __next->_M_next;
00759 _M_delete_node(__next);
00760 --_M_num_elements;
00761 break;
00762 }
00763 else {
00764 __cur = __next;
00765 __next = __cur->_M_next;
00766 }
00767 }
00768 }
00769 }
00770 }
00771
00772 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00773 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00774 ::erase(iterator __first, iterator __last)
00775 {
00776 size_type __f_bucket = __first._M_cur ?
00777 _M_bkt_num(__first._M_cur->_M_val) : _M_buckets.size();
00778 size_type __l_bucket = __last._M_cur ?
00779 _M_bkt_num(__last._M_cur->_M_val) : _M_buckets.size();
00780
00781 if (__first._M_cur == __last._M_cur)
00782 return;
00783 else if (__f_bucket == __l_bucket)
00784 _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur);
00785 else {
00786 _M_erase_bucket(__f_bucket, __first._M_cur, 0);
00787 for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n)
00788 _M_erase_bucket(__n, 0);
00789 if (__l_bucket != _M_buckets.size())
00790 _M_erase_bucket(__l_bucket, __last._M_cur);
00791 }
00792 }
00793
00794 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00795 inline void
00796 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const_iterator __first,
00797 const_iterator __last)
00798 {
00799 erase(iterator(const_cast<_Node*>(__first._M_cur),
00800 const_cast<hashtable*>(__first._M_ht)),
00801 iterator(const_cast<_Node*>(__last._M_cur),
00802 const_cast<hashtable*>(__last._M_ht)));
00803 }
00804
00805 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00806 inline void
00807 hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::erase(const const_iterator& __it)
00808 {
00809 erase(iterator(const_cast<_Node*>(__it._M_cur),
00810 const_cast<hashtable*>(__it._M_ht)));
00811 }
00812
00813 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00814 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00815 ::resize(size_type __num_elements_hint)
00816 {
00817 const size_type __old_n = _M_buckets.size();
00818 if (__num_elements_hint > __old_n) {
00819 const size_type __n = _M_next_size(__num_elements_hint);
00820 if (__n > __old_n) {
00821 vector<_Node*, _All> __tmp(__n, (_Node*)(0),
00822 _M_buckets.get_allocator());
00823 __STL_TRY {
00824 for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) {
00825 _Node* __first = _M_buckets[__bucket];
00826 while (__first) {
00827 size_type __new_bucket = _M_bkt_num(__first->_M_val, __n);
00828 _M_buckets[__bucket] = __first->_M_next;
00829 __first->_M_next = __tmp[__new_bucket];
00830 __tmp[__new_bucket] = __first;
00831 __first = _M_buckets[__bucket];
00832 }
00833 }
00834 _M_buckets.swap(__tmp);
00835 }
00836 # ifdef __STL_USE_EXCEPTIONS
00837 catch(...) {
00838 for (size_type __bucket = 0; __bucket < __tmp.size(); ++__bucket) {
00839 while (__tmp[__bucket]) {
00840 _Node* __next = __tmp[__bucket]->_M_next;
00841 _M_delete_node(__tmp[__bucket]);
00842 __tmp[__bucket] = __next;
00843 }
00844 }
00845 throw;
00846 }
00847 # endif
00848 }
00849 }
00850 }
00851
00852 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00853 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00854 ::_M_erase_bucket(const size_type __n, _Node* __first, _Node* __last)
00855 {
00856 _Node* __cur = _M_buckets[__n];
00857 if (__cur == __first)
00858 _M_erase_bucket(__n, __last);
00859 else {
00860 _Node* __next;
00861 for (__next = __cur->_M_next;
00862 __next != __first;
00863 __cur = __next, __next = __cur->_M_next)
00864 ;
00865 while (__next != __last) {
00866 __cur->_M_next = __next->_M_next;
00867 _M_delete_node(__next);
00868 __next = __cur->_M_next;
00869 --_M_num_elements;
00870 }
00871 }
00872 }
00873
00874 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00875 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00876 ::_M_erase_bucket(const size_type __n, _Node* __last)
00877 {
00878 _Node* __cur = _M_buckets[__n];
00879 while (__cur != __last) {
00880 _Node* __next = __cur->_M_next;
00881 _M_delete_node(__cur);
00882 __cur = __next;
00883 _M_buckets[__n] = __cur;
00884 --_M_num_elements;
00885 }
00886 }
00887
00888 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00889 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>::clear()
00890 {
00891 for (size_type __i = 0; __i < _M_buckets.size(); ++__i) {
00892 _Node* __cur = _M_buckets[__i];
00893 while (__cur != 0) {
00894 _Node* __next = __cur->_M_next;
00895 _M_delete_node(__cur);
00896 __cur = __next;
00897 }
00898 _M_buckets[__i] = 0;
00899 }
00900 _M_num_elements = 0;
00901 }
00902
00903
00904 template <class _Val, class _Key, class _HF, class _Ex, class _Eq, class _All>
00905 void hashtable<_Val,_Key,_HF,_Ex,_Eq,_All>
00906 ::_M_copy_from(const hashtable& __ht)
00907 {
00908 _M_buckets.clear();
00909 _M_buckets.reserve(__ht._M_buckets.size());
00910 _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0);
00911 __STL_TRY {
00912 for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) {
00913 const _Node* __cur = __ht._M_buckets[__i];
00914 if (__cur) {
00915 _Node* __local_copy = _M_new_node(__cur->_M_val);
00916 _M_buckets[__i] = __local_copy;
00917
00918 for (_Node* __next = __cur->_M_next;
00919 __next;
00920 __cur = __next, __next = __cur->_M_next) {
00921 __local_copy->_M_next = _M_new_node(__next->_M_val);
00922 __local_copy = __local_copy->_M_next;
00923 }
00924 }
00925 }
00926 _M_num_elements = __ht._M_num_elements;
00927 }
00928 __STL_UNWIND(clear());
00929 }
00930
00931 }
00932
00933 #endif
00934
00935
00936
00937