chxmapcommon_inl.h
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:13k
源码类别:

Symbian

开发平台:

C/C++

  1. /* ***** BEGIN LICENSE BLOCK ***** 
  2.  * Version: RCSL 1.0/RPSL 1.0 
  3.  *  
  4.  * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. 
  5.  *      
  6.  * The contents of this file, and the files included with this file, are 
  7.  * subject to the current version of the RealNetworks Public Source License 
  8.  * Version 1.0 (the "RPSL") available at 
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed 
  10.  * the file under the RealNetworks Community Source License Version 1.0 
  11.  * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, 
  12.  * in which case the RCSL will apply. You may also obtain the license terms 
  13.  * directly from RealNetworks.  You may not use this file except in 
  14.  * compliance with the RPSL or, if you have a valid RCSL with RealNetworks 
  15.  * applicable to this file, the RCSL.  Please see the applicable RPSL or 
  16.  * RCSL for the rights, obligations and limitations governing use of the 
  17.  * contents of the file.  
  18.  *  
  19.  * This file is part of the Helix DNA Technology. RealNetworks is the 
  20.  * developer of the Original Code and owns the copyrights in the portions 
  21.  * it created. 
  22.  *  
  23.  * This file, and the files included with this file, is distributed and made 
  24.  * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 
  25.  * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, 
  26.  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS 
  27.  * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 
  28.  * 
  29.  * Technology Compatibility Kit Test Suite(s) Location: 
  30.  *    http://www.helixcommunity.org/content/tck 
  31.  * 
  32.  * Contributor(s): 
  33.  *  
  34.  * ***** END LICENSE BLOCK ***** */ 
  35. #ifndef MAP_TYPE
  36. #error "Should only include this from specific CHXMap implementation!"
  37. #endif
  38. #ifndef MAP_ITERATOR_KEY_TYPE
  39. #define MAP_ITERATOR_KEY_TYPE key_type
  40. #endif
  41. #ifndef MAP_ITERATOR_KEY_GET
  42. #define MAP_ITERATOR_KEY_GET(k) k
  43. #endif
  44. #include "debug.h"
  45. #include "hxassert.h"
  46. #undef HX_ASSERT
  47. #define HX_ASSERT(x)
  48. // Implementation notes...
  49. //
  50. // * Data are stored in the m_items vector.
  51. // * The hash buckets/slots are stored in m_buckets.
  52. // * Each bucket is a vector of integer indices into the m_items vector.
  53. // * Rather than copying data around in m_items when an item is removed,
  54. //   the item is just marked as "free" and its index is added to the
  55. //   m_free vector.
  56. // * The returned POSITION values are 1-based indices into m_items.
  57. //   XXXSAB: This might be easier if it just passed out ptrs into the
  58. //           m_items data, but this method could survive a reallocation of
  59. //           the m_items vector (e.g. is something were added during
  60. //           iteration, but I don't think that's really supported).
  61. //
  62. #if defined(HELIX_CONFIG_LOW_HEAP_HASH_TABLE)
  63. #define HASH_TABLE_NUM_BUCKETS 1
  64. #define HASH_TABLE_BUCKET_SIZE 1
  65. #elif defined(HELIX_CONFIG_NOSTATICS)
  66. //XXXgfw revisit these numbers when we do symbian size reduction.
  67. //XXXgfw trade off between speed of lookups and size/fragmentation.
  68. #define HASH_TABLE_NUM_BUCKETS 10
  69. #define HASH_TABLE_BUCKET_SIZE 1
  70. #else
  71. #define HASH_TABLE_NUM_BUCKETS 101
  72. #define HASH_TABLE_BUCKET_SIZE 5
  73. #endif
  74. #if defined(HELIX_CONFIG_NOSTATICS)
  75. const ULONG32 MAP_TYPE::z_defaultNumBuckets = HASH_TABLE_NUM_BUCKETS;
  76. const ULONG32 MAP_TYPE::z_defaultChunkSize = 0;
  77. const ULONG32 MAP_TYPE::z_defaultBucketChunkSize = HASH_TABLE_BUCKET_SIZE;
  78. #else
  79. ULONG32 MAP_TYPE::z_defaultNumBuckets = HASH_TABLE_NUM_BUCKETS;
  80. ULONG32 MAP_TYPE::z_defaultChunkSize = 0;
  81. ULONG32 MAP_TYPE::z_defaultBucketChunkSize = HASH_TABLE_BUCKET_SIZE;
  82. #endif
  83. MAP_TYPE::Iterator::Iterator (ItemVec_t* pItems, int item) :
  84.     m_pItems(pItems), m_item(item),
  85.     m_key(MAP_ITERATOR_KEY_GET(key_nil())), m_val(val_nil())
  86. {
  87.     if (item < 0) m_item = pItems ? pItems->size() : 0;
  88. if (m_pItems)
  89. {
  90. GotoValid();
  91. if (m_item < m_pItems->size())
  92. {
  93. m_key = MAP_ITERATOR_KEY_GET((*m_pItems)[m_item].key);
  94. m_val = (*m_pItems)[m_item].val;
  95. }
  96. }
  97. }
  98. MAP_TYPE::Iterator& MAP_TYPE::Iterator::operator++()
  99. {
  100.     HX_ASSERT (m_pItems);
  101.     HX_ASSERT (m_item >= 0);
  102.     int s = m_pItems->size();
  103.     if (m_item < s)
  104.     {
  105.         ++m_item;
  106.         GotoValid();
  107.         if (m_item < s)
  108.         {
  109.             m_key = MAP_ITERATOR_KEY_GET((*m_pItems)[m_item].key);
  110.             m_val = (*m_pItems)[m_item].val;
  111.         }
  112.         else
  113.         {
  114.             m_key = MAP_ITERATOR_KEY_GET(key_nil());
  115.             m_val = val_nil();
  116.         }
  117.     }
  118.     return *this;
  119. }
  120. MAP_TYPE::Iterator MAP_TYPE::Iterator::operator++(int)
  121. {
  122.     HX_ASSERT (m_pItems);
  123.     HX_ASSERT (m_item >= 0);
  124.     Iterator ret (*this);
  125.     int s = m_pItems->size();
  126.     if (m_item < s)
  127.     {
  128.         ++m_item;
  129.         GotoValid();
  130.         if (m_item < s)
  131.         {
  132.             m_key = MAP_ITERATOR_KEY_GET((*m_pItems)[m_item].key);
  133.             m_val = (*m_pItems)[m_item].val;
  134.         }
  135.         else
  136.         {
  137.             m_key = MAP_ITERATOR_KEY_GET(key_nil());
  138.             m_val = val_nil();
  139.         }
  140.     }
  141.     return ret;
  142. }
  143. BOOL MAP_TYPE::Iterator::operator==(const Iterator& other) const
  144. {
  145.     return (m_pItems == other.m_pItems && m_item == other.m_item);
  146. }
  147. BOOL MAP_TYPE::Iterator::operator!=(const Iterator& other) const
  148. {
  149.     return (m_pItems != other.m_pItems || m_item != other.m_item);
  150. }
  151. MAP_TYPE::value_type MAP_TYPE::Iterator::operator*()
  152. {
  153.     return m_val;
  154. }
  155. MAP_TYPE::Iterator::iter_key_type MAP_TYPE::Iterator::get_key()
  156. {
  157.     return m_key;
  158. }
  159. void MAP_TYPE::Iterator::GotoValid()
  160. {
  161.     // Skip to the next item that is in use (i.e. not free)
  162.     while (m_item < m_pItems->size() && (*m_pItems)[m_item].bFree) ++m_item;
  163. }
  164. POSITION MAP_TYPE::Item2Pos(int item) const
  165. {
  166.     return (item >= 0 && item < m_items.size()) ? (POSITION)(item+1) : 0;
  167. }
  168. int MAP_TYPE::Pos2Item(POSITION pos) const
  169. {
  170.     return pos ? ((int)(PTR_INT)pos - 1) : m_items.size();
  171. }
  172. MAP_TYPE::MAP_TYPE(int chunkSize) :
  173.     m_hf(NULL),
  174.     m_numBuckets(z_defaultNumBuckets),
  175.     m_chunkSize(chunkSize),
  176.     m_bucketChunkSize(z_defaultBucketChunkSize)
  177. {
  178.     m_items.SetChunkSize(chunkSize);
  179.     ConstructTypeSpecifics();
  180. }
  181. MAP_TYPE::~MAP_TYPE()
  182. {
  183. }
  184. BOOL MAP_TYPE::LookupInBucket(
  185.     ULONG32 bucket, key_arg_type key, int& retItem) const
  186. {
  187.     const HlxMap::IntVec_t& rBucket = m_buckets[bucket];
  188.     int len = rBucket.size();
  189.     const int* pCur = &rBucket[0];
  190.     for (int i = 0; i < len; ++i, ++pCur)
  191.     {
  192.         if (IsKeyMatch(m_items[*pCur].key, key))
  193.         {
  194.             retItem = *pCur;
  195.             return TRUE;
  196.         }
  197.     }
  198.     return FALSE;
  199. }
  200. BOOL MAP_TYPE::Lookup(key_arg_type key, int& retItem) const
  201. {
  202.     if (m_buckets.empty()) return FALSE;
  203.     return LookupInBucket (HashKey(key) % m_buckets.size(), key, retItem);
  204. }
  205. MAP_TYPE::Item* MAP_TYPE::LookupItem(
  206.     ULONG32 bucket, key_arg_type key)
  207. {
  208.     if (!m_buckets.empty())
  209.     {
  210.         const HlxMap::IntVec_t& rBucket = m_buckets[bucket];
  211.         int len = rBucket.size();
  212.         const int* pCur = &rBucket[0];
  213.         for (int i = 0; i < len; ++i, ++pCur)
  214.         {
  215.             Item& item = m_items[*pCur];
  216.             if (IsKeyMatch(item.key, key))
  217.             {
  218.                 return &item;
  219.             }
  220.         }
  221.     }
  222.     return NULL;
  223. }
  224. BOOL MAP_TYPE::Lookup(key_arg_type key, value_ref_type value) const
  225. {
  226.     if (m_buckets.empty()) return FALSE;
  227.     const Item* pItem = LookupItem(HashKey(key) % m_buckets.size(), key);
  228.     if (!pItem) return FALSE;
  229.     value = pItem->val;
  230.     return TRUE;
  231. }
  232. POSITION MAP_TYPE::Lookup(key_arg_type key) const
  233. {
  234.     POSITION ret = 0;
  235.     int item;
  236.     if (Lookup(key, item)) ret = Item2Pos(item);
  237.     return ret;
  238. }
  239. BOOL MAP_TYPE::AddToBucket(
  240.     ULONG32 bucket, key_arg_type key, value_arg_type value, int& retItem)
  241. {
  242.     int idx = m_items.size();
  243.     if (m_free.empty())
  244.     {
  245.         m_items.push_back(Item(key, value, false));
  246.     }            
  247.     else
  248.     {
  249.         idx = m_free.back();
  250.         m_free.pop_back();
  251.         Item& rItem = m_items[idx];
  252.         rItem.key = key;
  253.         rItem.val = value;
  254.         rItem.bFree = false;
  255.     }
  256.     m_buckets[bucket].push_back(idx);
  257.     retItem = idx;
  258.     return TRUE;
  259. }
  260. MAP_TYPE::key_ref_type MAP_TYPE::GetKeyAt(POSITION pos) const
  261. {
  262.     int item = Pos2Item(pos);
  263.     HX_ASSERT (item >= 0 && item < m_items.size());
  264.     if (item > 0 && item < m_items.size()) return m_items[item].key;
  265.     return key_nil();
  266. }
  267. MAP_TYPE::value_const_ref_type MAP_TYPE::GetAt(POSITION pos) const
  268. {
  269.     int item = Pos2Item(pos);
  270.     HX_ASSERT (item >= 0 && item < m_items.size());
  271.     if (item > 0 && item < m_items.size()) return m_items[item].val;
  272.     return val_nil();
  273. }
  274. MAP_TYPE::value_ref_type MAP_TYPE::GetAt(POSITION pos)
  275. {
  276.     int item = Pos2Item(pos);
  277.     HX_ASSERT (item >= 0 && item < m_items.size());
  278.     if (item > 0 && item < m_items.size()) return m_items[item].val;
  279.     return val_nil();
  280. }
  281. MAP_TYPE::value_ref_type MAP_TYPE::operator[](key_arg_type key)
  282. {
  283.     if (m_buckets.empty())
  284.     {
  285.         if( HXR_OUTOFMEMORY == InitHashTable (m_numBuckets) )
  286.         {
  287.             // Don't know if caller knows to check for val_nil.
  288.             return val_nil();
  289.         }
  290.     }
  291.     ULONG32 bucket = HashKey(key) % m_buckets.size();
  292.     Item* pItem = LookupItem(bucket, key);
  293.     if (!pItem)
  294.     {
  295.         int itemIdx;
  296.         if (AddToBucket (bucket, key, val_nil(), itemIdx))
  297.         {
  298.             return m_items[itemIdx].val;
  299. }
  300.         else
  301.         {
  302.             // Now what?  Adding it failed...
  303.             return val_nil();
  304.         }
  305.     }
  306.     return pItem->val;
  307. }
  308. POSITION MAP_TYPE::SetAt(key_arg_type key, value_arg_type value)
  309. {
  310.     if (m_buckets.empty())
  311.     {
  312.         if( HXR_OUTOFMEMORY == InitHashTable (m_numBuckets) )
  313.         {
  314.             // Don't know if caller knows to check for 0.
  315.             return 0;
  316.         }
  317.     }
  318.     ULONG32 bucket = HashKey(key) % m_buckets.size();
  319.     int item;
  320.     if (LookupInBucket(bucket, key, item)) m_items[item].val = value;
  321.     else AddToBucket(bucket, key, value, item);
  322.     return Item2Pos(item);
  323. }
  324. POSITION MAP_TYPE::Remove(key_arg_type key)
  325. {
  326.     if (m_buckets.empty()) return 0;
  327.     int item = -1;
  328.     ULONG32 bucket = HashKey(key) % m_buckets.size();
  329.     HlxMap::IntVec_t& rBucket = m_buckets[bucket];
  330.     int len = rBucket.size();
  331.     int* pCur = &rBucket[0];
  332.     for (int i = 0; i < len; ++i, ++pCur)
  333.     {
  334.         if (IsKeyMatch(m_items[*pCur].key, key))
  335.         {
  336.             item = *pCur;
  337.             rBucket.zap(i);
  338.             m_free.push_back(item);
  339.             m_items[item].bFree = true;
  340.         }
  341.     }
  342.     // key not found
  343.     if (item < 0) return 0;
  344.     // Go to next valid item
  345.     int s = m_items.size();
  346.     ++item;
  347.     while (item < s && m_items[item].bFree) ++item;
  348.     if (item >= s) return 0;
  349.     return Item2Pos(item);
  350. }
  351. BOOL MAP_TYPE::RemoveKey(key_arg_type key)
  352. {
  353.     int countBefore = GetCount();
  354.     Remove(key);
  355.     return GetCount() < countBefore;
  356. }
  357. MAP_TYPE::Iterator MAP_TYPE::Erase(Iterator it)
  358. {
  359.     if (it.m_pItems && it.m_item >= 0 && it.m_item < it.m_pItems->size())
  360.     {
  361.         // POSITION is a 1-based index to m_items.
  362.         POSITION pos = Remove ((*it.m_pItems)[it.m_item].key);
  363.         if (pos) return Iterator (&m_items, Pos2Item(pos));
  364.     }
  365.     return End();
  366. }
  367. MAP_TYPE::Iterator MAP_TYPE::Find(key_arg_type key)
  368. {
  369.     int item;
  370.     if (Lookup(key, item)) return Iterator(&m_items, item);
  371.     return End();
  372. }
  373. void MAP_TYPE::RemoveAll()
  374. {
  375.     m_free.resize(0);
  376.     m_items.resize(0);
  377.     int len = m_buckets.size();
  378.     for (int i = 0; i < len; ++i) m_buckets[i].resize(0);
  379.     return;
  380. }
  381. POSITION MAP_TYPE::GetStartPosition() const
  382. {
  383.     if (GetCount() <= 0) return 0;
  384.     int s = m_items.size();
  385.     int item = 0;
  386.     const Item* pItem = &m_items[item];
  387.     while (item < s && pItem->bFree) ++item, ++pItem;
  388.     // Since GetCount() is > 0, we HAVE to find something here...
  389.     HX_ASSERT (item < s);
  390.     return Item2Pos(item);
  391. }
  392. #ifndef MAP_OVERRIDE_GETNEXTASSOC
  393. void MAP_TYPE::GetNextAssoc (POSITION& pos, key_type& key, value_type& value) const
  394. {
  395.     int item = Pos2Item(pos);
  396.     HX_ASSERT (item >= 0 && item < m_items.size());
  397.     const Item* pItem = &m_items[item];
  398.     key = pItem->key;
  399.     value = pItem->val;
  400.     // go to next valid item
  401.     int s = m_items.size();
  402.     ++item; ++pItem;
  403.     while (item < s && pItem->bFree) ++item, ++pItem;
  404.     if (item >= s)
  405.     {
  406.         // Hit the end...
  407.         pos = 0;
  408.     }
  409.     else
  410.     {
  411.         // Convert back to 1-based POSITION
  412.         pos = Item2Pos(item);
  413.     }
  414. }
  415. #endif /* MAP_OVERRIDE_GETNEXTASSOC */
  416. MAP_TYPE::Iterator MAP_TYPE::Begin()
  417. {
  418.     return Iterator (&m_items, 0);
  419. }
  420. MAP_TYPE::Iterator MAP_TYPE::End()
  421. {
  422.     return Iterator(&m_items, m_items.size());
  423. }
  424. HX_RESULT MAP_TYPE::InitHashTable(ULONG32 numBuckets, BOOL bAlloc)
  425. {
  426.     RemoveAll();
  427.     m_numBuckets = numBuckets;
  428.     HX_RESULT retVal = HXR_OK;
  429.     if (bAlloc)
  430.     {
  431.         retVal = m_buckets.Init((UINT16)numBuckets);
  432.         if( retVal != HXR_OUTOFMEMORY )
  433.         {
  434.             for (ULONG32 i = 0; i < numBuckets; ++i)
  435.                 m_buckets[i].SetChunkSize(m_bucketChunkSize);
  436.         }
  437.     }
  438.     return retVal;
  439. }