ptr_map.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. #define PTR_MAP_ENABLE_MULTI_MAP 1
  2. template <typename K, typename V>
  3. struct PtrMapEntry {
  4. static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size");
  5. u32 hash;
  6. MapIndex next;
  7. K key;
  8. V value;
  9. };
  10. template <typename K, typename V>
  11. struct PtrMap {
  12. Slice<MapIndex> hashes;
  13. Array<PtrMapEntry<K, V> > entries;
  14. };
  15. template <typename K>
  16. u32 ptr_map_hash_key(K key) {
  17. return gb_fnv32a(&key, gb_size_of(key));
  18. }
  19. template <typename K, typename V> void map_init (PtrMap<K, V> *h, gbAllocator a, isize capacity = 16);
  20. template <typename K, typename V> void map_destroy (PtrMap<K, V> *h);
  21. template <typename K, typename V> V * map_get (PtrMap<K, V> *h, K key);
  22. template <typename K, typename V> void map_set (PtrMap<K, V> *h, K key, V const &value);
  23. template <typename K, typename V> void map_remove (PtrMap<K, V> *h, K key);
  24. template <typename K, typename V> void map_clear (PtrMap<K, V> *h);
  25. template <typename K, typename V> void map_grow (PtrMap<K, V> *h);
  26. template <typename K, typename V> void map_rehash (PtrMap<K, V> *h, isize new_count);
  27. template <typename K, typename V> void map_reserve (PtrMap<K, V> *h, isize cap);
  28. #if PTR_MAP_ENABLE_MULTI_MAP
  29. // Mutlivalued map procedure
  30. template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key);
  31. template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e);
  32. template <typename K, typename V> isize multi_map_count (PtrMap<K, V> *h, K key);
  33. template <typename K, typename V> void multi_map_get_all (PtrMap<K, V> *h, K key, V *items);
  34. template <typename K, typename V> void multi_map_insert (PtrMap<K, V> *h, K key, V const &value);
  35. template <typename K, typename V> void multi_map_remove (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e);
  36. template <typename K, typename V> void multi_map_remove_all(PtrMap<K, V> *h, K key);
  37. #endif
  38. template <typename K, typename V>
  39. gb_inline void map_init(PtrMap<K, V> *h, gbAllocator a, isize capacity) {
  40. capacity = next_pow2_isize(capacity);
  41. slice_init(&h->hashes, a, capacity);
  42. array_init(&h->entries, a, 0, capacity);
  43. for (isize i = 0; i < capacity; i++) {
  44. h->hashes.data[i] = MAP_SENTINEL;
  45. }
  46. }
  47. template <typename K, typename V>
  48. gb_inline void map_destroy(PtrMap<K, V> *h) {
  49. slice_free(&h->hashes, h->entries.allocator);
  50. array_free(&h->entries);
  51. }
  52. template <typename K, typename V>
  53. gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) {
  54. PtrMapEntry<K, V> e = {};
  55. e.hash = ptr_map_hash_key(key);
  56. e.key = key;
  57. e.next = MAP_SENTINEL;
  58. array_add(&h->entries, e);
  59. return cast(MapIndex)(h->entries.count-1);
  60. }
  61. template <typename K, typename V>
  62. gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) {
  63. MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
  64. if (h->hashes.count == 0) {
  65. return fr;
  66. }
  67. u32 hash = ptr_map_hash_key(key);
  68. fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1));
  69. fr.entry_index = h->hashes.data[fr.hash_index];
  70. while (fr.entry_index != MAP_SENTINEL) {
  71. if (h->entries.data[fr.entry_index].key == key) {
  72. return fr;
  73. }
  74. fr.entry_prev = fr.entry_index;
  75. fr.entry_index = h->entries.data[fr.entry_index].next;
  76. }
  77. return fr;
  78. }
  79. template <typename K, typename V>
  80. gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
  81. MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
  82. if (h->hashes.count == 0) {
  83. return fr;
  84. }
  85. fr.hash_index = cast(MapIndex)(e->hash & (h->hashes.count-1));
  86. fr.entry_index = h->hashes.data[fr.hash_index];
  87. while (fr.entry_index != MAP_SENTINEL) {
  88. if (&h->entries.data[fr.entry_index] == e) {
  89. return fr;
  90. }
  91. fr.entry_prev = fr.entry_index;
  92. fr.entry_index = h->entries.data[fr.entry_index].next;
  93. }
  94. return fr;
  95. }
  96. template <typename K, typename V>
  97. gb_internal b32 map__full(PtrMap<K, V> *h) {
  98. return 0.75f * h->hashes.count <= h->entries.count;
  99. }
  100. template <typename K, typename V>
  101. gb_inline void map_grow(PtrMap<K, V> *h) {
  102. isize new_count = gb_max(h->hashes.count<<1, 16);
  103. map_rehash(h, new_count);
  104. }
  105. template <typename K, typename V>
  106. void map_reset_entries(PtrMap<K, V> *h) {
  107. for (isize i = 0; i < h->hashes.count; i++) {
  108. h->hashes.data[i] = MAP_SENTINEL;
  109. }
  110. for (isize i = 0; i < h->entries.count; i++) {
  111. MapFindResult fr;
  112. PtrMapEntry<K, V> *e = &h->entries.data[i];
  113. e->next = MAP_SENTINEL;
  114. fr = map__find_from_entry(h, e);
  115. if (fr.entry_prev == MAP_SENTINEL) {
  116. h->hashes[fr.hash_index] = cast(MapIndex)i;
  117. } else {
  118. h->entries[fr.entry_prev].next = cast(MapIndex)i;
  119. }
  120. }
  121. }
  122. template <typename K, typename V>
  123. void map_reserve(PtrMap<K, V> *h, isize cap) {
  124. array_reserve(&h->entries, cap);
  125. if (h->entries.count*2 < h->hashes.count) {
  126. return;
  127. }
  128. slice_resize(&h->hashes, h->entries.allocator, cap*2);
  129. map_reset_entries(h);
  130. }
  131. template <typename K, typename V>
  132. void map_rehash(PtrMap<K, V> *h, isize new_count) {
  133. map_reserve(h, new_count);
  134. }
  135. template <typename K, typename V>
  136. V *map_get(PtrMap<K, V> *h, K key) {
  137. isize index = map__find(h, key).entry_index;
  138. if (index != MAP_SENTINEL) {
  139. return &h->entries.data[index].value;
  140. }
  141. return nullptr;
  142. }
  143. template <typename K, typename V>
  144. V &map_must_get(PtrMap<K, V> *h, K key) {
  145. isize index = map__find(h, key).entry_index;
  146. GB_ASSERT(index != MAP_SENTINEL);
  147. return h->entries.data[index].value;
  148. }
  149. template <typename K, typename V>
  150. void map_set(PtrMap<K, V> *h, K key, V const &value) {
  151. MapIndex index;
  152. MapFindResult fr;
  153. if (h->hashes.count == 0) {
  154. map_grow(h);
  155. }
  156. fr = map__find(h, key);
  157. if (fr.entry_index != MAP_SENTINEL) {
  158. index = fr.entry_index;
  159. } else {
  160. index = map__add_entry(h, key);
  161. if (fr.entry_prev != MAP_SENTINEL) {
  162. h->entries.data[fr.entry_prev].next = index;
  163. } else {
  164. h->hashes.data[fr.hash_index] = index;
  165. }
  166. }
  167. h->entries.data[index].value = value;
  168. if (map__full(h)) {
  169. map_grow(h);
  170. }
  171. }
  172. template <typename K, typename V>
  173. void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) {
  174. MapFindResult last;
  175. if (fr.entry_prev == MAP_SENTINEL) {
  176. h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next;
  177. } else {
  178. h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next;
  179. }
  180. if (fr.entry_index == h->entries.count-1) {
  181. array_pop(&h->entries);
  182. return;
  183. }
  184. h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
  185. array_pop(&h->entries);
  186. last = map__find(h, h->entries.data[fr.entry_index].key);
  187. if (last.entry_prev != MAP_SENTINEL) {
  188. h->entries.data[last.entry_prev].next = fr.entry_index;
  189. } else {
  190. h->hashes.data[last.hash_index] = fr.entry_index;
  191. }
  192. }
  193. template <typename K, typename V>
  194. void map_remove(PtrMap<K, V> *h, K key) {
  195. MapFindResult fr = map__find(h, key);
  196. if (fr.entry_index != MAP_SENTINEL) {
  197. map__erase(h, fr);
  198. }
  199. }
  200. template <typename K, typename V>
  201. gb_inline void map_clear(PtrMap<K, V> *h) {
  202. array_clear(&h->entries);
  203. for (isize i = 0; i < h->hashes.count; i++) {
  204. h->hashes.data[i] = MAP_SENTINEL;
  205. }
  206. }
  207. #if PTR_MAP_ENABLE_MULTI_MAP
  208. template <typename K, typename V>
  209. PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, HashKey const &key) {
  210. isize i = map__find(h, key).entry_index;
  211. if (i == MAP_SENTINEL) {
  212. return nullptr;
  213. }
  214. return &h->entries.data[i];
  215. }
  216. template <typename K, typename V>
  217. PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
  218. isize i = e->next;
  219. while (i != MAP_SENTINEL) {
  220. if (hash_key_equal(h->entries.data[i].key, e->key)) {
  221. return &h->entries.data[i];
  222. }
  223. i = h->entries.data[i].next;
  224. }
  225. return nullptr;
  226. }
  227. template <typename K, typename V>
  228. isize multi_map_count(PtrMap<K, V> *h, HashKey const &key) {
  229. isize count = 0;
  230. PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
  231. while (e != nullptr) {
  232. count++;
  233. e = multi_map_find_next(h, e);
  234. }
  235. return count;
  236. }
  237. template <typename K, typename V>
  238. void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) {
  239. isize i = 0;
  240. PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
  241. while (e != nullptr) {
  242. items[i++] = e->value;
  243. e = multi_map_find_next(h, e);
  244. }
  245. }
  246. template <typename K, typename V>
  247. void multi_map_insert(PtrMap<K, V> *h, K key, V const &value) {
  248. MapFindResult fr;
  249. MapIndex i;
  250. if (h->hashes.count == 0) {
  251. map_grow(h);
  252. }
  253. // Make
  254. fr = map__find(h, key);
  255. i = map__add_entry(h, key);
  256. if (fr.entry_prev == MAP_SENTINEL) {
  257. h->hashes.data[fr.hash_index] = i;
  258. } else {
  259. h->entries.data[fr.entry_prev].next = i;
  260. }
  261. h->entries.data[i].next = fr.entry_index;
  262. h->entries.data[i].value = value;
  263. // Grow if needed
  264. if (map__full(h)) {
  265. map_grow(h);
  266. }
  267. }
  268. template <typename K, typename V>
  269. void multi_map_remove(PtrMap<K, V> *h, HashKey const &key, PtrMapEntry<K, V> *e) {
  270. MapFindResult fr = map__find_from_entry(h, e);
  271. if (fr.entry_index != MAP_SENTINEL) {
  272. map__erase(h, fr);
  273. }
  274. }
  275. template <typename K, typename V>
  276. void multi_map_remove_all(PtrMap<K, V> *h, HashKey const &key) {
  277. while (map_get(h, key) != nullptr) {
  278. map_remove(h, key);
  279. }
  280. }
  281. #endif