/home/ntakagi/work/STLport-5.1.5/stlport/stl/_hashtable.cGo to the documentation of this file.00001 /* 00002 * Copyright (c) 1994 00003 * Hewlett-Packard Company 00004 * 00005 * Copyright (c) 1996,1997 00006 * Silicon Graphics Computer Systems, Inc. 00007 * 00008 * Copyright (c) 1997 00009 * Moscow Center for SPARC Technology 00010 * 00011 * Copyright (c) 1999 00012 * Boris Fomitchev 00013 * 00014 * This material is provided "as is", with absolutely no warranty expressed 00015 * or implied. Any use is at your own risk. 00016 * 00017 * Permission to use or copy this software for any purpose is hereby granted 00018 * without fee, provided the above notices are retained on all copies. 00019 * Permission to modify the code and to distribute modified code is granted, 00020 * provided the above notices are retained, and a notice that the code was 00021 * modified is included with the above copyright notice. 00022 * 00023 */ 00024 #ifndef _STLP_HASHTABLE_C 00025 #define _STLP_HASHTABLE_C 00026 00027 #ifndef _STLP_INTERNAL_HASHTABLE_H 00028 # include <stl/_hashtable.h> 00029 #endif 00030 00031 _STLP_BEGIN_NAMESPACE 00032 00033 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION) 00034 00035 _STLP_MOVE_TO_PRIV_NAMESPACE 00036 00037 # define __PRIME_LIST_BODY { \ 00038 7ul, 23ul, \ 00039 53ul, 97ul, 193ul, 389ul, 769ul, \ 00040 1543ul, 3079ul, 6151ul, 12289ul, 24593ul, \ 00041 49157ul, 98317ul, 196613ul, 393241ul, 786433ul, \ 00042 1572869ul, 3145739ul, 6291469ul, 12582917ul, 25165843ul, \ 00043 50331653ul, 100663319ul, 201326611ul, 402653189ul, 805306457ul,\ 00044 1610612741ul, 3221225473ul, 4294967291ul \ 00045 } 00046 00047 template <class _Dummy> 00048 size_t _STLP_CALL 00049 _Stl_prime<_Dummy>::_S_max_nb_buckets() { 00050 const size_t _list[] = __PRIME_LIST_BODY; 00051 # ifndef __MWERKS__ 00052 return _list[(sizeof(_list)/sizeof(_list[0])) - 1]; 00053 # else 00054 return _list[30/sizeof(size_t) - 1]; // stupid MWERKS! 00055 # endif 00056 } 00057 00058 template <class _Dummy> 00059 size_t _STLP_CALL 00060 _Stl_prime<_Dummy>::_S_next_size(size_t __n) { 00061 static const size_t _list[] = __PRIME_LIST_BODY; 00062 const size_t* __first = _list; 00063 # ifndef __MWERKS__ 00064 const size_t* __last = _list + (sizeof(_list)/sizeof(_list[0])); 00065 # else 00066 const size_t* __last = _list + (30/sizeof(size_t)); // stupid MWERKS 00067 # endif 00068 const size_t* pos = __lower_bound(__first, __last, __n, 00069 __less((size_t*)0), __less((size_t*)0), (ptrdiff_t*)0); 00070 return (pos == __last ? *(__last - 1) : *pos); 00071 } 00072 00073 # undef __PRIME_LIST_BODY 00074 00075 _STLP_MOVE_TO_STD_NAMESPACE 00076 00077 #endif 00078 00079 #if defined (_STLP_DEBUG) 00080 # define hashtable _STLP_NON_DBG_NAME(hashtable) 00081 _STLP_MOVE_TO_PRIV_NAMESPACE 00082 #endif 00083 00084 // fbp: these defines are for outline methods definitions. 00085 // needed to definitions to be portable. Should not be used in method bodies. 00086 00087 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG ) 00088 # define __size_type__ size_t 00089 # define size_type size_t 00090 # define value_type _Val 00091 # define key_type _Key 00092 # define __reference__ _Val& 00093 00094 # define __iterator__ _Ht_iterator<_Val, _STLP_HEADER_TYPENAME _Traits::_NonConstTraits, \ 00095 _Key, _HF, _ExK, _EqK, _All> 00096 # define __const_iterator__ _Ht_iterator<_Val, _STLP_HEADER_TYPENAME _Traits::_ConstTraits, \ 00097 _Key, _HF, _ExK, _EqK, _All> 00098 #else 00099 # define __size_type__ _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::size_type 00100 # define __reference__ _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::reference 00101 # define __iterator__ _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::iterator 00102 # define __const_iterator__ _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::const_iterator 00103 #endif 00104 00105 /* 00106 * This method is too difficult to implement for hashtable that do not 00107 * require a sorted operation on the stored type. 00108 template <class _Val, class _Key, class _HF, 00109 class _Traits, class _ExK, class _EqK, class _All> 00110 bool hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::_M_equal( 00111 const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht1, 00112 const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht2) { 00113 return __ht1._M_buckets == __ht2._M_buckets && 00114 __ht1._M_elems == __ht2._M_elems; 00115 } 00116 */ 00117 00118 /* Returns the iterator before the first iterator of the bucket __n and set 00119 * __n to the first previous bucket having the same first iterator as bucket 00120 * __n. 00121 */ 00122 template <class _Val, class _Key, class _HF, 00123 class _Traits, class _ExK, class _EqK, class _All> 00124 __iterator__ 00125 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00126 ::_M_before_begin(size_type &__n) const { 00127 return _S_before_begin(_M_elems, _M_buckets, __n); 00128 } 00129 00130 template <class _Val, class _Key, class _HF, 00131 class _Traits, class _ExK, class _EqK, class _All> 00132 __iterator__ 00133 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00134 ::_S_before_begin(const _ElemsCont& __elems, const _BucketVector& __buckets, 00135 size_type &__n) { 00136 _ElemsCont &__mutable_elems = __CONST_CAST(_ElemsCont&, __elems); 00137 typename _BucketVector::const_iterator __bpos(__buckets.begin() + __n); 00138 00139 _ElemsIte __pos(*__bpos); 00140 if (__pos == __mutable_elems.begin()) { 00141 __n = 0; 00142 return __mutable_elems.before_begin(); 00143 } 00144 00145 typename _BucketVector::const_iterator __bcur(__bpos); 00146 _BucketType *__pos_node = __pos._M_node; 00147 for (--__bcur; __pos_node == *__bcur; --__bcur); 00148 00149 __n = __bcur - __buckets.begin() + 1; 00150 _ElemsIte __cur(*__bcur); 00151 _ElemsIte __prev = __cur++; 00152 for (; __cur != __pos; ++__prev, ++__cur); 00153 return __prev; 00154 } 00155 00156 00157 template <class _Val, class _Key, class _HF, 00158 class _Traits, class _ExK, class _EqK, class _All> 00159 __iterator__ 00160 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00161 ::_M_insert_noresize(size_type __n, const value_type& __obj) { 00162 //We always insert this element as 1st in the bucket to not break 00163 //the elements order as equal elements must be kept next to each other. 00164 size_type __prev = __n; 00165 _ElemsIte __pos = _M_before_begin(__prev)._M_ite; 00166 00167 fill(_M_buckets.begin() + __prev, _M_buckets.begin() + __n + 1, 00168 _M_elems.insert_after(__pos, __obj)._M_node); 00169 ++_M_num_elements; 00170 return iterator(_ElemsIte(_M_buckets[__n])); 00171 } 00172 00173 template <class _Val, class _Key, class _HF, 00174 class _Traits, class _ExK, class _EqK, class _All> 00175 pair<__iterator__, bool> 00176 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00177 ::insert_unique_noresize(const value_type& __obj) { 00178 const size_type __n = _M_bkt_num(__obj); 00179 _ElemsIte __cur(_M_buckets[__n]); 00180 _ElemsIte __last(_M_buckets[__n + 1]); 00181 00182 if (__cur != __last) { 00183 for (; __cur != __last; ++__cur) { 00184 if (_M_equals(_M_get_key(*__cur), _M_get_key(__obj))) { 00185 //We check that equivalent keys have equals hash code as otherwise, on resize, 00186 //equivalent value might not be in the same bucket 00187 _STLP_ASSERT(_M_hash(_M_get_key(*__cur)) == _M_hash(_M_get_key(__obj))) 00188 return pair<iterator, bool>(iterator(__cur), false); 00189 } 00190 } 00191 /* Here we do not rely on the _M_insert_noresize method as we know 00192 * that we cannot break element orders, elements are unique, and 00193 * insertion after the first bucket element is faster than what is 00194 * done in _M_insert_noresize. 00195 */ 00196 __cur = _M_elems.insert_after(_ElemsIte(_M_buckets[__n]), __obj); 00197 ++_M_num_elements; 00198 return pair<iterator, bool>(iterator(__cur), true); 00199 } 00200 00201 return pair<iterator, bool>(_M_insert_noresize(__n, __obj), true); 00202 } 00203 00204 template <class _Val, class _Key, class _HF, 00205 class _Traits, class _ExK, class _EqK, class _All> 00206 __iterator__ 00207 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00208 ::insert_equal_noresize(const value_type& __obj) { 00209 const size_type __n = _M_bkt_num(__obj); 00210 { 00211 _ElemsIte __cur(_M_buckets[__n]); 00212 _ElemsIte __last(_M_buckets[__n + 1]); 00213 00214 for (; __cur != __last; ++__cur) { 00215 if (_M_equals(_M_get_key(*__cur), _M_get_key(__obj))) { 00216 //We check that equivalent keys have equals hash code as otherwise, on resize, 00217 //equivalent value might not be in the same bucket 00218 _STLP_ASSERT(_M_hash(_M_get_key(*__cur)) == _M_hash(_M_get_key(__obj))) 00219 ++_M_num_elements; 00220 return _M_elems.insert_after(__cur, __obj); 00221 } 00222 } 00223 } 00224 00225 return _M_insert_noresize(__n, __obj); 00226 } 00227 00228 template <class _Val, class _Key, class _HF, 00229 class _Traits, class _ExK, class _EqK, class _All> 00230 __reference__ 00231 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00232 ::_M_insert(const value_type& __obj) { 00233 resize(_M_num_elements + 1); 00234 return *insert_unique_noresize(__obj).first; 00235 } 00236 00237 /* 00238 template <class _Val, class _Key, class _HF, 00239 class _Traits, class _ExK, class _EqK, class _All> 00240 __reference__ 00241 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00242 ::find_or_insert(const value_type& __obj) { 00243 _Node* __first = _M_find(_M_get_key(__obj)); 00244 if (__first) 00245 return __first->_M_val; 00246 else 00247 return _M_insert(__obj); 00248 } 00249 */ 00250 00251 template <class _Val, class _Key, class _HF, 00252 class _Traits, class _ExK, class _EqK, class _All> 00253 __size_type__ 00254 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00255 ::erase(const key_type& __key) { 00256 const size_type __n = _M_bkt_num_key(__key); 00257 00258 _ElemsIte __cur(_M_buckets[__n]); 00259 _ElemsIte __last(_M_buckets[__n + 1]); 00260 if (__cur == __last) 00261 return 0; 00262 00263 size_type __erased = 0; 00264 if (_M_equals(_M_get_key(*__cur), __key)) { 00265 //We look for the pos before __cur: 00266 size_type __prev_b = __n; 00267 _ElemsIte __prev = _M_before_begin(__prev_b)._M_ite; 00268 do { 00269 __cur = _M_elems.erase_after(__prev); 00270 ++__erased; 00271 } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key)); 00272 fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1, __cur._M_node); 00273 } 00274 else { 00275 _ElemsIte __prev = __cur++; 00276 for (; __cur != __last; ++__prev, ++__cur) { 00277 if (_M_equals(_M_get_key(*__cur), __key)) { 00278 do { 00279 __cur = _M_elems.erase_after(__prev); 00280 ++__erased; 00281 } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key)); 00282 break; 00283 } 00284 } 00285 } 00286 00287 _M_num_elements -= __erased; 00288 return __erased; 00289 } 00290 00291 template <class _Val, class _Key, class _HF, 00292 class _Traits, class _ExK, class _EqK, class _All> 00293 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00294 ::erase(const_iterator __it) { 00295 const size_type __n = _M_bkt_num(*__it); 00296 _ElemsIte __cur(_M_buckets[__n]); 00297 00298 if (__cur == __it._M_ite) { 00299 size_type __prev_b = __n; 00300 _ElemsIte __prev = _M_before_begin(__prev_b)._M_ite; 00301 fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1, 00302 _M_elems.erase_after(__prev)._M_node); 00303 --_M_num_elements; 00304 } 00305 else { 00306 _ElemsIte __prev = __cur++; 00307 _ElemsIte __last(_M_buckets[__n + 1]); 00308 for (; __cur != __last; ++__prev, ++__cur) { 00309 if (__cur == __it._M_ite) { 00310 _M_elems.erase_after(__prev); 00311 --_M_num_elements; 00312 break; 00313 } 00314 } 00315 } 00316 } 00317 00318 template <class _Val, class _Key, class _HF, 00319 class _Traits, class _ExK, class _EqK, class _All> 00320 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00321 ::erase(const_iterator __first, const_iterator __last) { 00322 if (__first == __last) 00323 return; 00324 size_type __f_bucket = _M_bkt_num(*__first); 00325 size_type __l_bucket = __last != end() ? _M_bkt_num(*__last) : (_M_buckets.size() - 1); 00326 00327 _ElemsIte __cur(_M_buckets[__f_bucket]); 00328 _ElemsIte __prev; 00329 if (__cur == __first._M_ite) { 00330 __prev = _M_before_begin(__f_bucket)._M_ite; 00331 } 00332 else { 00333 _ElemsIte __last(_M_buckets[++__f_bucket]); 00334 __prev = __cur++; 00335 for (; (__cur != __last) && (__cur != __first._M_ite); ++__prev, ++__cur); 00336 } 00337 //We do not use the slist::erase_after method taking a range to count the 00338 //number of erased elements: 00339 while (__cur != __last._M_ite) { 00340 __cur = _M_elems.erase_after(__prev); 00341 --_M_num_elements; 00342 } 00343 fill(_M_buckets.begin() + __f_bucket, _M_buckets.begin() + __l_bucket + 1, __cur._M_node); 00344 } 00345 00346 template <class _Val, class _Key, class _HF, 00347 class _Traits, class _ExK, class _EqK, class _All> 00348 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00349 ::rehash(size_type __num_buckets_hint) { 00350 if ((bucket_count() >= __num_buckets_hint) && 00351 (max_load_factor() > load_factor())) 00352 return; 00353 00354 //Here if max_load_factor is lower than 1.0 the resulting value might not be representable 00355 //as a size_type. The result concerning the respect of the max_load_factor will then be 00356 //undefined. 00357 __num_buckets_hint = (max) (__num_buckets_hint, (size_type)((float)size() / max_load_factor())); 00358 size_type __num_buckets = _STLP_PRIV _Stl_prime_type::_S_next_size(__num_buckets_hint); 00359 _M_rehash(__num_buckets); 00360 } 00361 00362 template <class _Val, class _Key, class _HF, 00363 class _Traits, class _ExK, class _EqK, class _All> 00364 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00365 ::resize(size_type __num_elements_hint) { 00366 if (((float)__num_elements_hint / (float)bucket_count() <= max_load_factor()) && 00367 (max_load_factor() >= load_factor())) { 00368 return; 00369 } 00370 00371 size_type __num_buckets_hint = (size_type)((float)(max) (__num_elements_hint, size()) / max_load_factor()); 00372 size_type __num_buckets = _STLP_PRIV _Stl_prime_type::_S_next_size(__num_buckets_hint); 00373 #if defined (_STLP_DEBUG) 00374 _M_check(); 00375 #endif 00376 _M_rehash(__num_buckets); 00377 } 00378 00379 template <class _Val, class _Key, class _HF, 00380 class _Traits, class _ExK, class _EqK, class _All> 00381 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00382 ::_M_rehash(size_type __num_buckets) { 00383 _ElemsCont __tmp_elems(_M_elems.get_allocator()); 00384 _BucketVector __tmp(__num_buckets + 1, __STATIC_CAST(_BucketType*, 0), _M_buckets.get_allocator()); 00385 _ElemsIte __cur, __last(_M_elems.end()); 00386 while (!_M_elems.empty()) { 00387 __cur = _M_elems.begin(); 00388 size_type __new_bucket = _M_bkt_num(*__cur, __num_buckets); 00389 _ElemsIte __ite(__cur), __before_ite(__cur); 00390 for (++__ite; 00391 __ite != __last && _M_equals(_M_get_key(*__cur), _M_get_key(*__ite)); 00392 ++__ite, ++__before_ite); 00393 size_type __prev_bucket = __new_bucket; 00394 _ElemsIte __prev = _S_before_begin(__tmp_elems, __tmp, __prev_bucket)._M_ite; 00395 __tmp_elems.splice_after(__prev, _M_elems, _M_elems.before_begin(), __before_ite); 00396 fill(__tmp.begin() + __prev_bucket, __tmp.begin() + __new_bucket + 1, __cur._M_node); 00397 } 00398 _M_elems.swap(__tmp_elems); 00399 _M_buckets.swap(__tmp); 00400 } 00401 00402 #if defined (_STLP_DEBUG) 00403 template <class _Val, class _Key, class _HF, 00404 class _Traits, class _ExK, class _EqK, class _All> 00405 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::_M_check() const { 00406 //We check that hash code of stored keys haven't change and also that equivalent 00407 //relation hasn't been modified 00408 size_t __num_buckets = bucket_count(); 00409 for (size_t __b = 0; __b < __num_buckets; ++__b) { 00410 _ElemsIte __cur(_M_buckets[__b]), __last(_M_buckets[__b + 1]); 00411 _ElemsIte __fst(__cur), __snd(__cur); 00412 for (; __cur != __last; ++__cur) { 00413 _STLP_ASSERT( _M_bkt_num(*__cur, __num_buckets) == __b ) 00414 _STLP_ASSERT( !_M_equals(_M_get_key(*__fst), _M_get_key(*__cur)) || _M_equals(_M_get_key(*__snd), _M_get_key(*__cur)) ) 00415 if (__fst != __snd) 00416 ++__fst; 00417 if (__snd != __cur) 00418 ++__snd; 00419 } 00420 } 00421 } 00422 #endif 00423 00424 template <class _Val, class _Key, class _HF, 00425 class _Traits, class _ExK, class _EqK, class _All> 00426 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::clear() { 00427 _M_elems.clear(); 00428 _M_buckets.assign(_M_buckets.size(), __STATIC_CAST(_BucketType*, 0)); 00429 _M_num_elements = 0; 00430 } 00431 00432 template <class _Val, class _Key, class _HF, 00433 class _Traits, class _ExK, class _EqK, class _All> 00434 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All> 00435 ::_M_copy_from(const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht) { 00436 _M_elems.clear(); 00437 _M_elems.insert(_M_elems.end(), __ht._M_elems.begin(), __ht._M_elems.end()); 00438 _M_buckets.resize(__ht._M_buckets.size()); 00439 _ElemsConstIte __src(__ht._M_elems.begin()), __src_end(__ht._M_elems.end()); 00440 _ElemsIte __dst(_M_elems.begin()); 00441 typename _BucketVector::const_iterator __src_b(__ht._M_buckets.begin()), 00442 __src_end_b(__ht._M_buckets.end()); 00443 typename _BucketVector::iterator __dst_b(_M_buckets.begin()), __dst_end_b(_M_buckets.end()); 00444 for (; __src != __src_end; ++__src, ++__dst) { 00445 for (; __src_b != __src_end_b; ++__src_b, ++__dst_b) { 00446 if (*__src_b == __src._M_node) { 00447 *__dst_b = __dst._M_node; 00448 } 00449 else 00450 break; 00451 } 00452 } 00453 fill(__dst_b, __dst_end_b, __STATIC_CAST(_BucketType*, 0)); 00454 _M_num_elements = __ht._M_num_elements; 00455 _M_max_load_factor = __ht._M_max_load_factor; 00456 } 00457 00458 #undef __iterator__ 00459 #undef const_iterator 00460 #undef __size_type__ 00461 #undef __reference__ 00462 #undef size_type 00463 #undef value_type 00464 #undef key_type 00465 #undef __stl_num_primes 00466 00467 #if defined (_STLP_DEBUG) 00468 # undef hashtable 00469 _STLP_MOVE_TO_STD_NAMESPACE 00470 #endif 00471 00472 _STLP_END_NAMESPACE 00473 00474 #endif /* _STLP_HASHTABLE_C */ 00475 00476 // Local Variables: 00477 // mode:C++ 00478 // End:
Generated on Mon Mar 10 15:32:24 2008 by ![]() |