Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 

224 rindas
7.3 KiB

  1. #pragma once
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include "types.hpp"
  6. #include "arraylist.hpp"
  7. u32 hm_hash(char* str) {
  8. u32 value = str[0] << 7;
  9. s32 i = 0;
  10. while (str[i]) {
  11. value = (10000003 * value) ^ str[i++];
  12. }
  13. return value ^ i;
  14. }
  15. u32 hm_hash(void* ptr) {
  16. return ((u64)ptr * 2654435761) % 4294967296;
  17. }
  18. inline bool hm_objects_match(char* a, char* b) {
  19. return strcmp(a, b) == 0;
  20. }
  21. inline bool hm_objects_match(void* a, void* b) {
  22. return a == b;
  23. }
  24. #define for_hash_map(hm) \
  25. if (decltype((hm).data[0].original) key = 0); else \
  26. if (decltype((hm).data[0].object) value = 0); else \
  27. for(u32 index = 0; index < (hm).current_capacity; ++index) \
  28. if (!((!(hm).data[index].deleted) && \
  29. (key = (hm).data[index].original) && \
  30. (value = (hm).data[index].object))); else
  31. template <typename key_type, typename value_type>
  32. struct Hash_Map {
  33. u32 current_capacity;
  34. u32 cell_count;
  35. struct HM_Cell {
  36. key_type original;
  37. u64 hash;
  38. bool deleted;
  39. value_type object;
  40. }* data;
  41. Hash_Map(u32 initial_capacity = 8) {
  42. current_capacity = initial_capacity;
  43. cell_count = 0;
  44. data = (HM_Cell*)calloc(initial_capacity, sizeof(HM_Cell));
  45. }
  46. ~Hash_Map() {
  47. free(data);
  48. data = nullptr;
  49. }
  50. Hash_Map(Hash_Map<key_type, value_type>& other) = delete;
  51. Hash_Map(const Hash_Map<key_type, value_type>& other) = delete;
  52. Hash_Map(Hash_Map<key_type, value_type>&& other) {
  53. data = other.data;
  54. cell_count = other.cell_count;
  55. current_capacity = other.current_capacity;
  56. other.data = nullptr;
  57. }
  58. s32 get_index_of_living_cell_if_it_exists(key_type key, u64 hash_val) {
  59. // s32 index = hash_val & (current_capacity - 1);
  60. s32 index = hash_val % current_capacity;
  61. HM_Cell cell = data[index];
  62. /* test if cell exists at that index */
  63. if (cell.original) {
  64. /* check if strings match */
  65. if (hm_objects_match(key, cell.original)) {
  66. /* we found it, now check it it is deleted: */
  67. if (cell.deleted) {
  68. /* we found it but it was deleted, we */
  69. /* dont have to check for collisions then */
  70. return -1;
  71. } else {
  72. /* we found it and it is not deleted */
  73. return index;
  74. }
  75. } else {
  76. /* strings dont match, this means we have */
  77. /* a collision. We just search forward */
  78. for (u32 i = 0; i < current_capacity; ++i) {
  79. u32 new_idx = (i + index) % current_capacity;
  80. cell = data[new_idx];
  81. if (!cell.original)
  82. return -1;
  83. if (!hm_objects_match(key, cell.original))
  84. continue;
  85. if (cell.deleted)
  86. continue;
  87. return new_idx;
  88. }
  89. /* not or only deleted cells found */
  90. return -1;
  91. }
  92. } else {
  93. /* no cell exists at this index so the item was never in the */
  94. /* hashmap. Either it would be there or be ther and 'deleted' */
  95. /* or another item would be there and therefore a collistion */
  96. /* would exist */
  97. return -1;
  98. }
  99. }
  100. bool key_exists(key_type key) {
  101. return get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key)) != -1;
  102. }
  103. key_type search_key_to_object(value_type v) {
  104. for (u32 i = 0; i < current_capacity; ++i) {
  105. if (data[i].object == v && !data[i].deleted)
  106. return data[i].original;
  107. }
  108. return nullptr;
  109. }
  110. Array_List<key_type> get_all_keys() {
  111. Array_List<key_type> ret;
  112. ret.alloc();
  113. // QUESTION(Felix): Does it make sense to
  114. // ret.reserve(this->cell_count)?
  115. for (u32 i = 0; i < current_capacity; ++i) {
  116. if (data[i].original && !data[i].deleted)
  117. ret.append(data[i].original);
  118. }
  119. return ret;
  120. }
  121. value_type get_object(key_type key, u64 hash_val) {
  122. s32 index = get_index_of_living_cell_if_it_exists(key, hash_val);
  123. if (index != -1) {
  124. return data[index].object;
  125. }
  126. return 0;
  127. }
  128. value_type get_object(key_type key) {
  129. return get_object(key, hm_hash((key_type)key));
  130. }
  131. void delete_object(key_type key) {
  132. s32 index = get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key));
  133. if (index != -1) {
  134. data[index].deleted = true;
  135. }
  136. }
  137. void set_object(key_type key, value_type obj, u64 hash_val) {
  138. u32 index = hash_val % current_capacity;
  139. /* if we the desired cell is just empty, write to it and done :) */
  140. if (!data[index].original) {
  141. /* insert new cell into desired slot */
  142. ++cell_count;
  143. } else {
  144. if (hm_objects_match(key, data[index].original)) {
  145. /* overwrite object with same key, dont increment cell */
  146. /* count */
  147. } else {
  148. /* collision, check resize */
  149. if ((cell_count*1.0f / current_capacity) > 0.666f) {
  150. auto old_data = data;
  151. data = (HM_Cell*)calloc(current_capacity*4, sizeof(HM_Cell));
  152. cell_count = 0;
  153. current_capacity *= 4;
  154. /* insert all old items again */
  155. for (u32 i = 0; i < current_capacity/4; ++i) {
  156. auto cell = old_data[i];
  157. if (cell.original) {
  158. set_object(cell.original, cell.object, cell.hash);
  159. }
  160. }
  161. free(old_data);
  162. index = hash_val % current_capacity;
  163. }
  164. ++cell_count;
  165. /* search for empty slot for new cell starting at desired index; */
  166. /* preventing gotos using lambdas! */
  167. [&]{
  168. for (u32 i = index; i < current_capacity; ++i) {
  169. if (!data[i].original ||
  170. hm_objects_match(data[i].original, key))
  171. {
  172. index = i;
  173. return;
  174. }
  175. }
  176. for (u32 i = 0; i < index; ++i) {
  177. if (!data[i].original ||
  178. hm_objects_match(data[i].original, key))
  179. {
  180. index = i;
  181. return;
  182. }
  183. }
  184. }();
  185. }
  186. }
  187. data[index].deleted = false;
  188. data[index].original = key;
  189. data[index].hash = hash_val;
  190. data[index].object = obj;
  191. }
  192. void set_object(key_type key, value_type obj) {
  193. u64 hash_val = hm_hash((key_type)key);
  194. set_object(key, obj, hash_val);
  195. }
  196. };