Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.
 
 
 
 

157 wiersze
5.7 KiB

  1. #pragma once
  2. #include <string.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include "types.hpp"
  6. #define for_hash_map(hm) \
  7. if (decltype(hm.data[0].original) key = 0); else \
  8. if (decltype(hm.data[0].object) value = 0); else \
  9. for(int index = 0; index < hm.current_capacity; ++index) \
  10. if (!((!hm.data[index].deleted) && \
  11. (key = hm.data[index].original) && \
  12. (value = hm.data[index].object))); else
  13. template <typename key_type, typename value_type>
  14. struct Hash_Map {
  15. int current_capacity;
  16. int cell_count;
  17. struct HM_Cell {
  18. key_type original;
  19. u64 hash;
  20. bool deleted;
  21. value_type object;
  22. }* data;
  23. Hash_Map(int initial_capacity = 8) {
  24. current_capacity = initial_capacity;
  25. cell_count = 0;
  26. data = (HM_Cell*)calloc(initial_capacity, sizeof(HM_Cell));
  27. }
  28. int get_index_of_living_cell_if_it_exists(key_type key, u64 hash_val) {
  29. // int index = hash_val & (current_capacity - 1);
  30. int index = hash_val % current_capacity;
  31. HM_Cell cell = data[index];
  32. /* test if cell exists at that index */
  33. if (cell.original) {
  34. /* check if strings match */
  35. if (hm_objects_match(key, cell.original)) {
  36. /* we found it, now check it it is deleted: */
  37. if (cell.deleted) {
  38. /* we found it but it was deleted, we */
  39. /* dont have to check for collisions then */
  40. return -1;
  41. } else {
  42. /* we found it and it is not deleted */
  43. return index;
  44. }
  45. } else {
  46. /* strings dont match, this means we have */
  47. /* a collision. We just search forward */
  48. for (int i = 0; i < current_capacity; ++i) {
  49. int new_idx = (i + index) % current_capacity;
  50. cell = data[new_idx];
  51. if (!cell.original)
  52. return -1;
  53. if (!hm_objects_match(key, cell.original))
  54. continue;
  55. if (cell.deleted)
  56. continue;
  57. return new_idx;
  58. }
  59. /* not or only deleted cells found */
  60. return -1;
  61. }
  62. } else {
  63. /* no cell exists at this index so the item was never in the */
  64. /* hashmap. Either it would be there or be ther and 'deleted' */
  65. /* or another item would be there and therefore a collistion */
  66. /* would exist */
  67. return -1;
  68. }
  69. }
  70. bool key_exists(key_type key) {
  71. return get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key)) != -1;
  72. }
  73. value_type get_object(key_type key) {
  74. int index = get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key));
  75. if (index != -1) {
  76. return data[index].object;
  77. }
  78. return 0;
  79. }
  80. void delete_object(key_type key) {
  81. int index = get_index_of_living_cell_if_it_exists(key, hm_hash((key_type)key));
  82. if (index != -1) {
  83. data[index].deleted = true;
  84. }
  85. }
  86. void set_object(key_type key, value_type obj) {
  87. u64 hash_val = hm_hash((key_type)key);
  88. int index = hash_val % current_capacity;
  89. /* if we the desired cell is just empty, write to it and done :) */
  90. if (!data[index].original) {
  91. /* insert new cell into desired slot */
  92. ++cell_count;
  93. } else {
  94. if (hm_objects_match(key, data[index].original)) {
  95. /* overwrite object with same key, dont increment cell */
  96. /* count */
  97. } else {
  98. /* collision, check resize */
  99. ++cell_count;
  100. if ((cell_count*1.0f / current_capacity) > 0.666f) {
  101. auto old_data = data;
  102. data = (HM_Cell*)calloc(current_capacity*4, sizeof(HM_Cell));
  103. cell_count = 0;
  104. current_capacity *= 4;
  105. /* insert all old items again */
  106. for (int i = 0; i < current_capacity/4; ++i) {
  107. auto cell = old_data[i];
  108. if (cell.original) {
  109. set_object(cell.original, cell.object);
  110. }
  111. }
  112. free(old_data);
  113. index = hash_val % current_capacity;
  114. }
  115. /* search for empty slot for new cell starting at desired index; */
  116. /* preventing gotos using lambdas! */
  117. [&]{
  118. for (int i = index; i < current_capacity; ++i) {
  119. if (!data[i].original ||
  120. hm_objects_match(data[i].original, key))
  121. {
  122. index = i;
  123. return;
  124. }
  125. }
  126. for (int i = 0; i < index; ++i) {
  127. if (!data[i].original ||
  128. hm_objects_match(data[i].original, key))
  129. {
  130. index = i;
  131. return;
  132. }
  133. }
  134. }();
  135. }
  136. }
  137. data[index].deleted = false;
  138. data[index].original = key;
  139. data[index].hash = hash_val;
  140. data[index].object = obj;
  141. }
  142. };