chxmapcommon_inl.h
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:14k
源码类别:

Symbian

开发平台:

Visual C++

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