epoc32/include/stdapis/stlportv5/stl/_hashtable.c
author William Roberts <williamr@symbian.org>
Wed, 31 Mar 2010 12:33:34 +0100
branchSymbian3
changeset 4 837f303aceeb
parent 3 e1b950c65cb4
permissions -rw-r--r--
Current Symbian^3 public API header files (from PDK 3.0.h)
This is the epoc32/include tree with the "platform" subtrees removed, and
all but a selected few mbg and rsg files removed.
     1 /*
     2  * Portions Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
     3  *
     4  * Copyright (c) 1994
     5  * Hewlett-Packard Company
     6  *
     7  * Copyright (c) 1996,1997
     8  * Silicon Graphics Computer Systems, Inc.
     9  *
    10  * Copyright (c) 1997
    11  * Moscow Center for SPARC Technology
    12  *
    13  * Copyright (c) 1999
    14  * Boris Fomitchev
    15  *
    16  * This material is provided "as is", with absolutely no warranty expressed
    17  * or implied. Any use is at your own risk.
    18  *
    19  * Permission to use or copy this software for any purpose is hereby granted
    20  * without fee, provided the above notices are retained on all copies.
    21  * Permission to modify the code and to distribute modified code is granted,
    22  * provided the above notices are retained, and a notice that the code was
    23  * modified is included with the above copyright notice.
    24  *
    25  */
    26 #ifndef _STLP_HASHTABLE_C
    27 #define _STLP_HASHTABLE_C
    28 
    29 #ifndef _STLP_INTERNAL_HASHTABLE_H
    30 #  include <stl/_hashtable.h>
    31 #endif
    32 
    33 _STLP_BEGIN_NAMESPACE
    34 
    35 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
    36 
    37 _STLP_MOVE_TO_PRIV_NAMESPACE
    38 
    39 #  define __PRIME_LIST_BODY { \
    40   7ul,          23ul, \
    41   53ul,         97ul,         193ul,       389ul,       769ul,      \
    42   1543ul,       3079ul,       6151ul,      12289ul,     24593ul,    \
    43   49157ul,      98317ul,      196613ul,    393241ul,    786433ul,   \
    44   1572869ul,    3145739ul,    6291469ul,   12582917ul,  25165843ul, \
    45   50331653ul,   100663319ul,  201326611ul, 402653189ul, 805306457ul,\
    46   1610612741ul, 3221225473ul, 4294967291ul  \
    47 }
    48 
    49 template <class _Dummy>
    50 size_t _STLP_CALL
    51 _Stl_prime<_Dummy>::_S_max_nb_buckets() {
    52   const size_t _list[] = __PRIME_LIST_BODY;
    53 #  ifndef __MWERKS__
    54   return _list[(sizeof(_list)/sizeof(_list[0])) - 1];
    55 #  else
    56   // it has to be 30 * (sizeof(_list[0]) to get the last element of the array
    57   return _list[30 * (sizeof(_list[0])/sizeof(size_t)) - 1]; // stupid MWERKS!
    58 #  endif
    59 }
    60 
    61 template <class _Dummy>
    62 size_t _STLP_CALL
    63 _Stl_prime<_Dummy>::_S_next_size(size_t __n) {
    64   static const size_t _list[] = __PRIME_LIST_BODY;
    65   const size_t* __first = _list;
    66 #  ifndef __MWERKS__
    67   const size_t* __last =  _list + (sizeof(_list)/sizeof(_list[0]));
    68 #  else
    69   // it has to be 30 * (sizeof(_list[0]) to get the last element of the array
    70   const size_t* __last =  _list + ((30*sizeof(_list[0]))/sizeof(size_t)); // stupid MWERKS
    71 #  endif
    72   const size_t* pos = __lower_bound(__first, __last, __n, 
    73                                     __less((size_t*)0), __less((size_t*)0), (ptrdiff_t*)0);
    74   return (pos == __last ? *(__last - 1) : *pos);
    75 }
    76 
    77 #  undef __PRIME_LIST_BODY
    78 
    79 _STLP_MOVE_TO_STD_NAMESPACE
    80 
    81 #endif
    82 
    83 #if defined (_STLP_DEBUG)
    84 #  define hashtable _STLP_NON_DBG_NAME(hashtable)
    85 _STLP_MOVE_TO_PRIV_NAMESPACE
    86 #endif
    87 
    88 // fbp: these defines are for outline methods definitions.
    89 // needed to definitions to be portable. Should not be used in method bodies.
    90 
    91 #if defined ( _STLP_NESTED_TYPE_PARAM_BUG )
    92 #  define __size_type__       size_t
    93 #  define size_type           size_t
    94 #  define value_type          _Val
    95 #  define key_type            _Key
    96 #  define __reference__       _Val&
    97 
    98 #  define __iterator__        _Ht_iterator<_Val, _STLP_HEADER_TYPENAME _Traits::_NonConstTraits, \
    99                                            _Key, _HF, _ExK, _EqK, _All>
   100 #  define __const_iterator__  _Ht_iterator<_Val, _STLP_HEADER_TYPENAME _Traits::_ConstTraits, \
   101                                            _Key, _HF, _ExK, _EqK, _All>
   102 #else
   103 #  define __size_type__       _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::size_type
   104 #  define __reference__       _STLP_TYPENAME_ON_RETURN_TYPE  hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::reference
   105 #  define __iterator__        _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::iterator
   106 #  define __const_iterator__  _STLP_TYPENAME_ON_RETURN_TYPE hashtable<_Val, _Key, _HF, _Traits, _ExK, _EqK, _All>::const_iterator
   107 #endif
   108 
   109 /*
   110  * This method is too difficult to implement for hashtable that do not
   111  * require a sorted operation on the stored type.
   112 template <class _Val, class _Key, class _HF,
   113           class _Traits, class _ExK, class _EqK, class _All>
   114 bool hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::_M_equal(
   115               const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht1,
   116               const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht2) {
   117   return __ht1._M_buckets == __ht2._M_buckets &&
   118          __ht1._M_elems == __ht2._M_elems;
   119 }
   120 */
   121 
   122 /* Returns the iterator before the first iterator of the bucket __n and set
   123  * __n to the first previous bucket having the same first iterator as bucket
   124  * __n.
   125  */
   126 template <class _Val, class _Key, class _HF,
   127           class _Traits, class _ExK, class _EqK, class _All>
   128 __iterator__
   129 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   130   ::_M_before_begin(size_type &__n) const {
   131   return _S_before_begin(_M_elems, _M_buckets, __n);
   132 }
   133 
   134 template <class _Val, class _Key, class _HF,
   135           class _Traits, class _ExK, class _EqK, class _All>
   136 __iterator__
   137 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   138   ::_S_before_begin(const _ElemsCont& __elems, const _BucketVector& __buckets,
   139                     size_type &__n) {
   140   _ElemsCont &__mutable_elems = __CONST_CAST(_ElemsCont&, __elems);
   141   typename _BucketVector::const_iterator __bpos(__buckets.begin() + __n);
   142 
   143   _ElemsIte __pos(*__bpos);
   144   if (__pos == __mutable_elems.begin()) {
   145     __n = 0;
   146     return __mutable_elems.before_begin();
   147   }
   148 
   149   typename _BucketVector::const_iterator __bcur(__bpos);
   150   _BucketType *__pos_node = __pos._M_node;
   151   for (--__bcur; __pos_node == *__bcur; --__bcur) {}
   152 
   153   __n = __bcur - __buckets.begin() + 1;
   154   _ElemsIte __cur(*__bcur);
   155   _ElemsIte __prev = __cur++;
   156   for (; __cur != __pos; ++__prev, ++__cur) {}
   157   return __prev;
   158 }
   159 
   160 
   161 template <class _Val, class _Key, class _HF,
   162           class _Traits, class _ExK, class _EqK, class _All>
   163 __iterator__
   164 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   165   ::_M_insert_noresize(size_type __n, const value_type& __obj) {
   166   //We always insert this element as 1st in the bucket to not break
   167   //the elements order as equal elements must be kept next to each other.
   168   size_type __prev = __n;
   169   _ElemsIte __pos = _M_before_begin(__prev)._M_ite;
   170 
   171   fill(_M_buckets.begin() + __prev, _M_buckets.begin() + __n + 1,
   172        _M_elems.insert_after(__pos, __obj)._M_node);
   173   ++_M_num_elements;
   174   return iterator(_ElemsIte(_M_buckets[__n]));
   175 }
   176 
   177 template <class _Val, class _Key, class _HF,
   178           class _Traits, class _ExK, class _EqK, class _All>
   179 pair<__iterator__, bool>
   180 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   181   ::insert_unique_noresize(const value_type& __obj) {
   182   const size_type __n = _M_bkt_num(__obj);
   183   _ElemsIte __cur(_M_buckets[__n]);
   184   _ElemsIte __last(_M_buckets[__n + 1]);
   185 
   186   if (__cur != __last) {
   187     for (; __cur != __last; ++__cur) {
   188       if (_M_equals(_M_get_key(*__cur), _M_get_key(__obj))) {
   189         //We check that equivalent keys have equals hash code as otherwise, on resize,
   190         //equivalent value might not be in the same bucket
   191         _STLP_ASSERT(_M_hash(_M_get_key(*__cur)) == _M_hash(_M_get_key(__obj)))
   192         return pair<iterator, bool>(iterator(__cur), false);
   193       }
   194     }
   195     /* Here we do not rely on the _M_insert_noresize method as we know
   196      * that we cannot break element orders, elements are unique, and
   197      * insertion after the first bucket element is faster than what is
   198      * done in _M_insert_noresize.
   199      */
   200     __cur = _M_elems.insert_after(_ElemsIte(_M_buckets[__n]), __obj);
   201     ++_M_num_elements;
   202     return pair<iterator, bool>(iterator(__cur), true);
   203   }
   204 
   205   return pair<iterator, bool>(_M_insert_noresize(__n, __obj), true);
   206 }
   207 
   208 template <class _Val, class _Key, class _HF,
   209           class _Traits, class _ExK, class _EqK, class _All>
   210 __iterator__
   211 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   212   ::insert_equal_noresize(const value_type& __obj) {
   213   const size_type __n = _M_bkt_num(__obj);
   214   {
   215     _ElemsIte __cur(_M_buckets[__n]);
   216     _ElemsIte __last(_M_buckets[__n + 1]);
   217 
   218     for (; __cur != __last; ++__cur) {
   219       if (_M_equals(_M_get_key(*__cur), _M_get_key(__obj))) {
   220         //We check that equivalent keys have equals hash code as otherwise, on resize,
   221         //equivalent value might not be in the same bucket
   222         _STLP_ASSERT(_M_hash(_M_get_key(*__cur)) == _M_hash(_M_get_key(__obj)))
   223         ++_M_num_elements;
   224         return _M_elems.insert_after(__cur, __obj);
   225       }
   226     }
   227   }
   228 
   229   return _M_insert_noresize(__n, __obj);
   230 }
   231 
   232 template <class _Val, class _Key, class _HF,
   233           class _Traits, class _ExK, class _EqK, class _All>
   234 __reference__
   235 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   236   ::_M_insert(const value_type& __obj) {
   237   resize(_M_num_elements + 1);
   238   return *insert_unique_noresize(__obj).first;
   239 }
   240 
   241 /*
   242 template <class _Val, class _Key, class _HF,
   243           class _Traits, class _ExK, class _EqK, class _All>
   244 __reference__
   245 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   246   ::find_or_insert(const value_type& __obj) {
   247   _Node* __first = _M_find(_M_get_key(__obj));
   248   if (__first)
   249     return __first->_M_val;
   250   else
   251     return _M_insert(__obj);
   252 }
   253 */
   254 
   255 template <class _Val, class _Key, class _HF,
   256           class _Traits, class _ExK, class _EqK, class _All>
   257 __size_type__
   258 hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   259   ::erase(const key_type& __key) {
   260   const size_type __n = _M_bkt_num_key(__key);
   261 
   262   _ElemsIte __cur(_M_buckets[__n]);
   263   _ElemsIte __last(_M_buckets[__n + 1]);
   264   if (__cur == __last)
   265     return 0;
   266 
   267   size_type __erased = 0;
   268   if (_M_equals(_M_get_key(*__cur), __key)) {
   269     //We look for the pos before __cur:
   270     size_type __prev_b = __n;
   271     _ElemsIte __prev = _M_before_begin(__prev_b)._M_ite;
   272     do {
   273       __cur = _M_elems.erase_after(__prev);
   274       ++__erased;
   275     } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key));
   276     fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1, __cur._M_node);
   277   }
   278   else {
   279     _ElemsIte __prev = __cur++;
   280     for (; __cur != __last; ++__prev, ++__cur) {
   281       if (_M_equals(_M_get_key(*__cur), __key)) {
   282         do {
   283           __cur = _M_elems.erase_after(__prev);
   284           ++__erased;
   285         } while ((__cur != __last) && _M_equals(_M_get_key(*__cur), __key));
   286         break;
   287       }
   288     }
   289   }
   290 
   291   _M_num_elements -= __erased;
   292   return __erased;
   293 }
   294 
   295 template <class _Val, class _Key, class _HF,
   296           class _Traits, class _ExK, class _EqK, class _All>
   297 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   298   ::erase(const_iterator __it) {
   299   const size_type __n = _M_bkt_num(*__it);
   300   _ElemsIte __cur(_M_buckets[__n]);
   301 
   302   if (__cur == __it._M_ite) {
   303     size_type __prev_b = __n;
   304     _ElemsIte __prev = _M_before_begin(__prev_b)._M_ite;
   305     fill(_M_buckets.begin() + __prev_b, _M_buckets.begin() + __n + 1,
   306          _M_elems.erase_after(__prev)._M_node);
   307     --_M_num_elements;
   308   }
   309   else {
   310     _ElemsIte __prev = __cur++;
   311     _ElemsIte __last(_M_buckets[__n + 1]);
   312     for (; __cur != __last; ++__prev, ++__cur) {
   313       if (__cur == __it._M_ite) {
   314         _M_elems.erase_after(__prev);
   315         --_M_num_elements;
   316         break;
   317       }
   318     }
   319   }
   320 }
   321 
   322 template <class _Val, class _Key, class _HF,
   323           class _Traits, class _ExK, class _EqK, class _All>
   324 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   325   ::erase(const_iterator __first, const_iterator __last) {
   326   if (__first == __last)
   327     return;
   328   size_type __f_bucket = _M_bkt_num(*__first);
   329   size_type __l_bucket = __last != end() ? _M_bkt_num(*__last) : (_M_buckets.size() - 1);
   330 
   331   _ElemsIte __cur(_M_buckets[__f_bucket]);
   332   _ElemsIte __prev;
   333   if (__cur == __first._M_ite) {
   334     __prev = _M_before_begin(__f_bucket)._M_ite;
   335   }
   336   else {
   337     _ElemsIte __last(_M_buckets[++__f_bucket]);
   338     __prev = __cur++;
   339     for (; (__cur != __last) && (__cur != __first._M_ite); ++__prev, ++__cur);
   340   }
   341   //We do not use the slist::erase_after method taking a range to count the
   342   //number of erased elements:
   343   while (__cur != __last._M_ite) {
   344     __cur = _M_elems.erase_after(__prev);
   345     --_M_num_elements;
   346   }
   347   fill(_M_buckets.begin() + __f_bucket, _M_buckets.begin() + __l_bucket + 1, __cur._M_node);
   348 }
   349 
   350 template <class _Val, class _Key, class _HF,
   351           class _Traits, class _ExK, class _EqK, class _All>
   352 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   353   ::rehash(size_type __num_buckets_hint) {
   354   if ((bucket_count() >= __num_buckets_hint) &&
   355       (max_load_factor() > load_factor()))
   356     return;
   357 
   358   //Here if max_load_factor is lower than 1.0 the resulting value might not be representable
   359   //as a size_type. The result concerning the respect of the max_load_factor will then be
   360   //undefined.
   361   __num_buckets_hint = (max) (__num_buckets_hint, (size_type)((float)size() / max_load_factor()));
   362   size_type __num_buckets = _STLP_PRIV _Stl_prime_type::_S_next_size(__num_buckets_hint);
   363   _M_rehash(__num_buckets);
   364 }
   365 
   366 template <class _Val, class _Key, class _HF,
   367           class _Traits, class _ExK, class _EqK, class _All>
   368 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   369   ::resize(size_type __num_elements_hint) {
   370   if (((float)__num_elements_hint / (float)bucket_count() <= max_load_factor()) &&
   371       (max_load_factor() >= load_factor())) {
   372     return;
   373   }
   374 
   375   size_type __num_buckets_hint = (size_type)((float)(max) (__num_elements_hint, size()) / max_load_factor());
   376   size_type __num_buckets = _STLP_PRIV _Stl_prime_type::_S_next_size(__num_buckets_hint);
   377 #if defined (_STLP_DEBUG)
   378   _M_check();
   379 #endif
   380   _M_rehash(__num_buckets);
   381 }
   382 
   383 template <class _Val, class _Key, class _HF,
   384           class _Traits, class _ExK, class _EqK, class _All>
   385 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   386   ::_M_rehash(size_type __num_buckets) {
   387   _ElemsCont __tmp_elems(_M_elems.get_allocator());
   388   _BucketVector __tmp(__num_buckets + 1, __STATIC_CAST(_BucketType*, 0), _M_buckets.get_allocator());
   389   _ElemsIte __cur, __last(_M_elems.end());
   390   while (!_M_elems.empty()) {
   391     __cur = _M_elems.begin();
   392     size_type __new_bucket = _M_bkt_num(*__cur, __num_buckets);
   393     _ElemsIte __ite(__cur), __before_ite(__cur);
   394     for (++__ite;
   395          __ite != __last && _M_equals(_M_get_key(*__cur), _M_get_key(*__ite));
   396          ++__ite, ++__before_ite) {}
   397     size_type __prev_bucket = __new_bucket;
   398     _ElemsIte  __prev = _S_before_begin(__tmp_elems, __tmp, __prev_bucket)._M_ite;
   399     __tmp_elems.splice_after(__prev, _M_elems, _M_elems.before_begin(), __before_ite);
   400     fill(__tmp.begin() + __prev_bucket, __tmp.begin() + __new_bucket + 1, __cur._M_node);
   401   }
   402   _M_elems.swap(__tmp_elems);
   403   _M_buckets.swap(__tmp);
   404 }
   405 
   406 #if defined (_STLP_DEBUG)
   407 template <class _Val, class _Key, class _HF,
   408           class _Traits, class _ExK, class _EqK, class _All>
   409 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::_M_check() const {
   410   //We check that hash code of stored keys haven't change and also that equivalent
   411   //relation hasn't been modified
   412   size_t __num_buckets = bucket_count();
   413   for (size_t __b = 0; __b < __num_buckets; ++__b) {
   414     _ElemsIte __cur(_M_buckets[__b]), __last(_M_buckets[__b + 1]);
   415     _ElemsIte __fst(__cur), __snd(__cur);
   416     for (; __cur != __last; ++__cur) {
   417       _STLP_ASSERT( _M_bkt_num(*__cur, __num_buckets) == __b )
   418       _STLP_ASSERT( !_M_equals(_M_get_key(*__fst), _M_get_key(*__cur)) || _M_equals(_M_get_key(*__snd), _M_get_key(*__cur)) )
   419       if (__fst != __snd)
   420         ++__fst;
   421       if (__snd != __cur)
   422         ++__snd;
   423     }
   424   }
   425 }
   426 #endif
   427 
   428 template <class _Val, class _Key, class _HF,
   429           class _Traits, class _ExK, class _EqK, class _All>
   430 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>::clear() {
   431   _M_elems.clear();
   432   _M_buckets.assign(_M_buckets.size(), __STATIC_CAST(_BucketType*, 0));
   433   _M_num_elements = 0;
   434 }
   435 
   436 template <class _Val, class _Key, class _HF,
   437           class _Traits, class _ExK, class _EqK, class _All>
   438 void hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>
   439   ::_M_copy_from(const hashtable<_Val,_Key,_HF,_Traits,_ExK,_EqK,_All>& __ht) {
   440   _M_elems.clear();
   441   _M_elems.insert(_M_elems.end(), __ht._M_elems.begin(), __ht._M_elems.end());
   442   _M_buckets.resize(__ht._M_buckets.size());
   443   _ElemsConstIte __src(__ht._M_elems.begin()), __src_end(__ht._M_elems.end());
   444   _ElemsIte __dst(_M_elems.begin());
   445   typename _BucketVector::const_iterator __src_b(__ht._M_buckets.begin()),
   446                                          __src_end_b(__ht._M_buckets.end());
   447   typename _BucketVector::iterator __dst_b(_M_buckets.begin()), __dst_end_b(_M_buckets.end());
   448   for (; __src != __src_end; ++__src, ++__dst) {
   449     for (; __src_b != __src_end_b; ++__src_b, ++__dst_b) {
   450       if (*__src_b == __src._M_node) {
   451         *__dst_b = __dst._M_node;
   452       }
   453       else
   454         break;
   455     }
   456   }
   457   fill(__dst_b, __dst_end_b, __STATIC_CAST(_BucketType*, 0));
   458   _M_num_elements = __ht._M_num_elements;
   459   _M_max_load_factor = __ht._M_max_load_factor;
   460 }
   461 
   462 #undef __iterator__
   463 #undef const_iterator
   464 #undef __size_type__
   465 #undef __reference__
   466 #undef size_type
   467 #undef value_type
   468 #undef key_type
   469 #undef __stl_num_primes
   470 
   471 #if defined (_STLP_DEBUG)
   472 #  undef hashtable
   473 _STLP_MOVE_TO_STD_NAMESPACE
   474 #endif
   475 
   476 _STLP_END_NAMESPACE
   477 
   478 #endif /*  _STLP_HASHTABLE_C */
   479 
   480 // Local Variables:
   481 // mode:C++
   482 // End: