StrHashMap.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. #pragma once
  2. #include "DebugCommon.h"
  3. #include "BeefySysLib/util/BumpAllocator.h"
  4. NS_BF_DBG_BEGIN
  5. template <typename T>
  6. class StrHashMap
  7. {
  8. public:
  9. struct Entry
  10. {
  11. T mValue;
  12. Entry* mNext;
  13. int mHash;
  14. };
  15. struct Iterator
  16. {
  17. public:
  18. StrHashMap* mMap;
  19. Entry* mCurEntry;
  20. int mCurBucket;
  21. public:
  22. Iterator(StrHashMap* map)
  23. {
  24. mMap = map;
  25. mCurBucket = 0;
  26. mCurEntry = NULL;
  27. }
  28. Iterator& operator++()
  29. {
  30. if (mCurEntry != NULL)
  31. {
  32. mCurEntry = mCurEntry->mNext;
  33. if (mCurEntry != NULL)
  34. return *this;
  35. mCurBucket++;
  36. }
  37. if (mMap->mHashHeads == NULL)
  38. return *this; // At end
  39. while (mCurBucket < mMap->mHashSize)
  40. {
  41. mCurEntry = mMap->mHashHeads[mCurBucket];
  42. if (mCurEntry != NULL)
  43. return *this;
  44. mCurBucket++;
  45. }
  46. return *this; // At end
  47. }
  48. bool operator!=(const Iterator& itr) const
  49. {
  50. return ((itr.mCurEntry != mCurEntry) || (itr.mCurBucket != mCurBucket));
  51. }
  52. Entry* operator*()
  53. {
  54. return mCurEntry;
  55. }
  56. };
  57. public:
  58. int GetHash(const char* str)
  59. {
  60. int curHash = 0;
  61. const char* curHashPtr = str;
  62. while (*curHashPtr != 0)
  63. {
  64. char c = *curHashPtr;
  65. if (c != ' ')
  66. curHash = ((curHash ^ *curHashPtr) << 5) - curHash;
  67. curHashPtr++;
  68. }
  69. return curHash & 0x7FFFFFFF;
  70. }
  71. bool StrEqual(const char* strA, const char* strB)
  72. {
  73. const char* ptrA = strA;
  74. const char* ptrB = strB;
  75. while (true)
  76. {
  77. char ca;
  78. do { ca = *(strA++); } while (ca == ' ');
  79. char cb;
  80. do { cb = *(strB++); } while (cb == ' ');
  81. if (ca != cb)
  82. return false;
  83. if (ca == '\0')
  84. return true;
  85. }
  86. }
  87. public:
  88. Beefy::BumpAllocator mAlloc;
  89. Entry** mHashHeads;
  90. int mHashSize;
  91. int mCount;
  92. public:
  93. StrHashMap()
  94. {
  95. mHashHeads = NULL;
  96. mHashSize = 9973;
  97. mCount = 0;
  98. }
  99. void Insert(T value)
  100. {
  101. if (mHashHeads == NULL)
  102. mHashHeads = (Entry**)mAlloc.AllocBytes(sizeof(Entry*) * mHashSize, alignof(Entry*));
  103. int hash = GetHash(value->mName);
  104. int hashIdx = hash % mHashSize;
  105. Entry* headEntry = mHashHeads[hashIdx];
  106. Entry* newEntry = mAlloc.Alloc<Entry>();
  107. newEntry->mValue = value;
  108. newEntry->mNext = headEntry;
  109. newEntry->mHash = hash;
  110. mCount++;
  111. mHashHeads[hashIdx] = newEntry;
  112. }
  113. void Rehash(int newHashSize)
  114. {
  115. auto newHashHeads = (Entry**)mAlloc.AllocBytes(sizeof(Entry*) * newHashSize, alignof(Entry*));
  116. for (int hashIdx = 0; hashIdx < mHashSize; hashIdx++)
  117. {
  118. Entry* checkEntry = mHashHeads[hashIdx];
  119. while (checkEntry != NULL)
  120. {
  121. auto nextEntry = checkEntry->mNext;
  122. int newHashIdx = checkEntry->mHash % newHashSize;
  123. checkEntry->mNext = newHashHeads[newHashIdx];
  124. newHashHeads[newHashIdx] = checkEntry;
  125. checkEntry = nextEntry;
  126. }
  127. }
  128. mHashHeads = newHashHeads;
  129. mHashSize = newHashSize;
  130. }
  131. Entry* Find(const char* name)
  132. {
  133. if (mHashHeads == NULL)
  134. return NULL;
  135. // Make the lookup load reasonable
  136. if (mHashSize < mCount / 2)
  137. {
  138. Rehash(mCount / 2 + 123);
  139. }
  140. int hash = GetHash(name);
  141. int hashIdx = hash % mHashSize;
  142. Entry* checkEntry = mHashHeads[hashIdx];
  143. while (checkEntry != NULL)
  144. {
  145. if ((checkEntry->mHash == hash) && (StrEqual(name, checkEntry->mValue->mName)))
  146. return checkEntry;
  147. checkEntry = checkEntry->mNext;
  148. }
  149. return NULL;
  150. }
  151. void Clear()
  152. {
  153. mHashSize = 9973;
  154. mHashHeads = NULL;
  155. mAlloc.Clear();
  156. mCount = 0;
  157. }
  158. Iterator begin()
  159. {
  160. return ++Iterator(this);
  161. }
  162. Iterator end()
  163. {
  164. Iterator itr(this);
  165. itr.mCurBucket = mHashSize;
  166. return itr;
  167. }
  168. };
  169. NS_BF_DBG_END