HashMap.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. #include "core/HashMap.h"
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include "core/Utility.h"
  5. static bool isInvalidKey(const CoreHashMap* m, const void* key) {
  6. const char* c = key;
  7. for(size_t i = m->keySize; i > 0; i--) {
  8. if(*(c++) != 0) {
  9. return false;
  10. }
  11. }
  12. return true;
  13. }
  14. static void* getKey(const CoreHashMap* m, size_t index) {
  15. return (char*)m->keys + m->keySize * index;
  16. }
  17. static void* getValue(const CoreHashMap* m, size_t index) {
  18. return (char*)m->values + m->valueSize * index;
  19. }
  20. static size_t searchSlot(CoreHashMap* m, const void* key) {
  21. size_t rehashFactor = 2;
  22. while(true) {
  23. coreRehashHashMap(m, m->entries * rehashFactor + 1);
  24. if(isInvalidKey(m, key)) {
  25. return m->capacity - 1;
  26. }
  27. size_t baseHash = m->hasher(key, m->keySize) * 514685581u;
  28. size_t end = m->capacity - 2;
  29. // rehash on bad clustering
  30. for(size_t i = 0; i <= 5; i++) {
  31. size_t hash = (baseHash + i) & end;
  32. void* keyEntry = getKey(m, hash);
  33. if(isInvalidKey(m, keyEntry) ||
  34. m->equal(keyEntry, key, m->keySize)) {
  35. return hash;
  36. }
  37. }
  38. rehashFactor *= 2;
  39. }
  40. }
  41. static void* searchValue(const CoreHashMap* m, const void* key) {
  42. if(m->capacity != 0) {
  43. if(isInvalidKey(m, key)) {
  44. size_t i = m->capacity - 1;
  45. return isInvalidKey(m, getKey(m, i)) ? getValue(m, i) : nullptr;
  46. }
  47. size_t baseHash = m->hasher(key, m->keySize) * 514685581u;
  48. size_t end = m->capacity - 2;
  49. for(size_t i = 0; i <= end; i++) {
  50. size_t hash = (baseHash + i) & end;
  51. void* keyEntry = getKey(m, hash);
  52. if(m->equal(keyEntry, key, m->keySize)) {
  53. return getValue(m, hash);
  54. } else if(isInvalidKey(m, keyEntry)) {
  55. return nullptr;
  56. }
  57. }
  58. }
  59. return nullptr;
  60. }
  61. static size_t roundUp2(size_t n) {
  62. size_t w = 1;
  63. while(w < n) {
  64. w *= 2;
  65. }
  66. return w;
  67. }
  68. void coreDestroyHashMap(CoreHashMap* m) {
  69. coreFree(m->keys);
  70. coreFree(m->values);
  71. *m = (CoreHashMap){0};
  72. }
  73. void coreRehashHashMap(CoreHashMap* m, size_t minCapacity) {
  74. if(minCapacity <= m->capacity) {
  75. return;
  76. }
  77. size_t l = roundUp2(coreMaxSize(minCapacity, 8lu)) + 1;
  78. CoreHashMap map =
  79. CORE_HASH_MAP(m->keySize, m->valueSize, m->hasher, m->equal);
  80. size_t keyBytes = l * m->keySize;
  81. map.keys = coreAllocate(l * m->keySize);
  82. memset(map.keys, 0, keyBytes);
  83. memset(getKey(&map, l - 1), 1, m->keySize);
  84. map.values = coreAllocate(l * m->valueSize);
  85. map.capacity = l;
  86. size_t length = m->capacity;
  87. if(length > 0) {
  88. length--;
  89. for(size_t i = 0; i < length; i++) {
  90. void* keyEntry = getKey(m, i);
  91. if(!isInvalidKey(m, keyEntry)) {
  92. coreHashMapPutPointer(&map, keyEntry, getValue(m, i));
  93. }
  94. }
  95. void* keyEntry = getKey(m, length);
  96. if(isInvalidKey(m, keyEntry)) {
  97. coreHashMapPutPointer(&map, keyEntry, getValue(m, length));
  98. }
  99. }
  100. coreSwapHashMap(&map, m);
  101. coreDestroyHashMap(&map);
  102. }
  103. void* coreHashMapPutPointer(CoreHashMap* m, const void* key,
  104. const void* value) {
  105. size_t index = searchSlot(m, key);
  106. void* keyEntry = getKey(m, index);
  107. if(m->equal(keyEntry, key, m->keySize)) {
  108. void* v = getValue(m, index);
  109. memcpy(v, value, m->valueSize);
  110. return v;
  111. }
  112. void* v = getValue(m, index);
  113. memcpy(v, value, m->valueSize);
  114. m->entries++;
  115. memcpy(keyEntry, key, m->keySize);
  116. return v;
  117. }
  118. void* coreHashMapSearchPointer(CoreHashMap* m, const void* key) {
  119. return searchValue(m, key);
  120. }
  121. const void* coreHashMapSearchPointerC(const CoreHashMap* m, const void* key) {
  122. return searchValue(m, key);
  123. }
  124. bool coreHashMapContainsPointer(const CoreHashMap* m, const void* key) {
  125. return coreHashMapSearchPointerC(m, key) != nullptr;
  126. }
  127. void coreClearHashMap(CoreHashMap* m) {
  128. if(m->keys == nullptr) {
  129. return;
  130. }
  131. m->entries = 0;
  132. memset(m->keys, 0, m->capacity * m->keySize);
  133. memset(getKey(m, m->capacity - 1), 1, m->keySize);
  134. }
  135. bool coreHashMapRemovePointer(CoreHashMap* m, const void* key) {
  136. // ToDo: This is a very slow remove
  137. CoreHashMap n =
  138. CORE_HASH_MAP(m->keySize, m->valueSize, m->hasher, m->equal);
  139. CoreHashMapIterator i = CORE_HASH_MAP_ITERATOR(m);
  140. bool r = false;
  141. while(true) {
  142. CoreHashMapNode* node = coreHashMapNext(&i);
  143. if(node == nullptr) {
  144. break;
  145. }
  146. if(!m->equal(key, node->key, n.keySize)) {
  147. coreHashMapPutPointer(&n, node->key, node->value);
  148. } else {
  149. r = true;
  150. }
  151. }
  152. coreSwapHashMap(&n, m);
  153. coreDestroyHashMap(&n);
  154. return r;
  155. }
  156. size_t coreToStringHashMap(const CoreHashMap* m, char* buffer, size_t n,
  157. CoreToString keyString, CoreToString valueString) {
  158. size_t w = 0;
  159. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "["));
  160. char* end = getKey(m, m->capacity);
  161. char* key = m->keys;
  162. char* value = m->values;
  163. bool notFirst = false;
  164. while(key != end) {
  165. if(isInvalidKey(m, key) == (key + m->keySize == end)) {
  166. if(notFirst) {
  167. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, ", "));
  168. }
  169. notFirst = true;
  170. coreStringAdd(&w, &buffer, &n, keyString(key, buffer, n));
  171. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, " = "));
  172. coreStringAdd(&w, &buffer, &n, valueString(value, buffer, n));
  173. }
  174. key += m->keySize;
  175. value += m->valueSize;
  176. }
  177. coreStringAddI(&w, &buffer, &n, snprintf(buffer, n, "]"));
  178. return w;
  179. }
  180. void coreSwapHashMap(CoreHashMap* a, CoreHashMap* b) {
  181. CoreHashMap tmp = *a;
  182. *a = *b;
  183. *b = tmp;
  184. }
  185. size_t coreHashString(const void* key, size_t n) {
  186. if(n != sizeof(char*)) {
  187. return 0;
  188. }
  189. const char* s = *(const char* const*)key;
  190. size_t h = 0;
  191. while(*s != '\0') {
  192. h = 2120251889lu * h + (size_t)(*(s++));
  193. }
  194. return h;
  195. }
  196. size_t coreHash(const void* key, size_t n) {
  197. size_t h = 0;
  198. if(n <= sizeof(size_t)) {
  199. memcpy(&h, key, n);
  200. return h;
  201. }
  202. const char* cKey = key;
  203. while(n > 0) {
  204. size_t m = 0;
  205. if(n >= sizeof(size_t)) {
  206. memcpy(&m, cKey, sizeof(size_t));
  207. cKey += sizeof(size_t);
  208. n -= sizeof(size_t);
  209. } else {
  210. memcpy(&m, cKey, n);
  211. cKey += n;
  212. n = 0;
  213. }
  214. h ^= m;
  215. }
  216. return h;
  217. }
  218. bool coreEqual(const void* keyA, const void* keyB, size_t n) {
  219. return memcmp(keyA, keyB, n) == 0;
  220. }
  221. CoreHashMapNode* coreHashMapNext(CoreHashMapIterator* mi) {
  222. const CoreHashMap* m = mi->map;
  223. mi->index++;
  224. size_t end = m->capacity - 1;
  225. while(mi->index < m->capacity) {
  226. void* key = getKey(m, mi->index);
  227. if(isInvalidKey(m, key) == (mi->index == end)) {
  228. mi->node.key = key;
  229. mi->node.value = getValue(m, mi->index);
  230. return &mi->node;
  231. }
  232. mi->index++;
  233. }
  234. return nullptr;
  235. }