hash_map.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. #pragma once
  2. #include <types/allocator.hpp>
  3. #include <types/cplusplus.hpp>
  4. #include <types/list.hpp>
  5. #include <types/stdint.h>
  6. #include <types/types.h>
  7. #include <types/vector.hpp>
  8. namespace types {
  9. // taken from linux
  10. constexpr uint32_t GOLDEN_RATIO_32 = 0x61C88647;
  11. // constexpr uint64_t GOLDEN_RATIO_64 = 0x61C8864680B583EBull;
  12. static constexpr uint32_t _hash32(uint32_t val)
  13. {
  14. return val * GOLDEN_RATIO_32;
  15. }
  16. static constexpr uint32_t hash32(uint32_t val, uint32_t bits)
  17. {
  18. // higher bits are more random
  19. return _hash32(val) >> (32 - bits);
  20. }
  21. struct decimal_hash {
  22. static constexpr uint32_t hash(uint32_t val, uint32_t bits)
  23. {
  24. return hash32(val, bits);
  25. }
  26. };
  27. template <class Hasher, typename Value>
  28. struct hasher_traits {
  29. using hash_t = size_t;
  30. using length_t = size_t;
  31. static constexpr hash_t hash(Value val, length_t bits)
  32. {
  33. return Hasher::hash(val, bits);
  34. }
  35. };
  36. template <typename Key, typename Value, typename Hasher, template <typename _T> class Allocator = types::kernel_allocator>
  37. class hash_map {
  38. public:
  39. struct pair;
  40. template <typename Pointer>
  41. class iterator;
  42. using key_type = Key;
  43. using value_type = Value;
  44. using pair_type = pair;
  45. using size_type = size_t;
  46. using difference_type = ssize_t;
  47. using iterator_type = iterator<pair_type*>;
  48. using const_iterator_type = iterator<const pair_type*>;
  49. using bucket_type = list<pair, Allocator>;
  50. using bucket_array_type = vector<bucket_type, Allocator>;
  51. static constexpr size_type INITIAL_BUCKETS_ALLOCATED = 64;
  52. public:
  53. struct pair {
  54. pair(const key_type& _key, const value_type& _val)
  55. : key(_key)
  56. , value(_val)
  57. {
  58. }
  59. pair(key_type&& _key, const value_type& _val)
  60. : key(move(_key))
  61. , value(_val)
  62. {
  63. }
  64. pair(const key_type& _key, value_type&& _val)
  65. : key(_key)
  66. , value(move(_val))
  67. {
  68. }
  69. pair(key_type&& _key, value_type&& _val)
  70. : key(move(_key))
  71. , value(move(_val))
  72. {
  73. }
  74. bool operator==(const pair& p)
  75. {
  76. return key == p.key;
  77. }
  78. key_type key;
  79. value_type value;
  80. };
  81. template <typename Pointer>
  82. class iterator {
  83. public:
  84. using _Value = typename traits::remove_pointer<Pointer>::type;
  85. using Reference = typename traits::add_reference<_Value>::type;
  86. public:
  87. iterator(const iterator& iter) noexcept
  88. : p(iter.p)
  89. {
  90. }
  91. iterator(iterator&& iter) noexcept
  92. : p(iter.p)
  93. {
  94. iter.p = nullptr;
  95. }
  96. iterator& operator=(const iterator& iter)
  97. {
  98. p = iter.p;
  99. return *this;
  100. }
  101. explicit iterator(Pointer p) noexcept
  102. : p(p)
  103. {
  104. }
  105. bool operator==(const iterator& iter) noexcept
  106. {
  107. return this->p == iter.p;
  108. }
  109. bool operator!=(const iterator& iter) noexcept
  110. {
  111. return !(*this == iter);
  112. }
  113. Reference operator*() const noexcept
  114. {
  115. return *p;
  116. }
  117. Pointer operator->() const noexcept
  118. {
  119. return p;
  120. }
  121. protected:
  122. Pointer p;
  123. public:
  124. static inline iterator npos = iterator((Pointer)-1);
  125. };
  126. private:
  127. bucket_array_type buckets;
  128. protected:
  129. constexpr uint32_t hash_length(void) const
  130. {
  131. switch (buckets.capacity()) {
  132. case 32:
  133. return 5;
  134. case 64:
  135. return 6;
  136. case 128:
  137. return 7;
  138. case 256:
  139. return 8;
  140. // TODO
  141. default:
  142. return 9;
  143. }
  144. }
  145. public:
  146. explicit hash_map(void)
  147. : buckets(INITIAL_BUCKETS_ALLOCATED)
  148. {
  149. for (int i = 0; i < INITIAL_BUCKETS_ALLOCATED; ++i)
  150. buckets.emplace_back();
  151. }
  152. hash_map(const hash_map& v)
  153. : buckets(v.buckets)
  154. {
  155. }
  156. hash_map(hash_map&& v)
  157. : buckets(move(v))
  158. {
  159. }
  160. ~hash_map()
  161. {
  162. clear();
  163. }
  164. void insert(const pair& p)
  165. {
  166. auto hash_value = hasher_traits<Hasher, key_type>::hash(p.key, hash_length());
  167. buckets.at(hash_value).push_back(p);
  168. }
  169. void insert(pair&& p)
  170. {
  171. auto hash_value = hasher_traits<Hasher, key_type>::hash(p.key, hash_length());
  172. buckets.at(hash_value).push_back(move(p));
  173. }
  174. void insert(const key_type& key, const value_type& val)
  175. {
  176. insert(pair { key, val });
  177. }
  178. void remove(const key_type& key)
  179. {
  180. auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
  181. auto& bucket = buckets.at(hash_value);
  182. for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) {
  183. if (iter->key == key) {
  184. bucket.erase(iter);
  185. return;
  186. }
  187. }
  188. }
  189. iterator_type find(const key_type& key)
  190. {
  191. auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
  192. auto& bucket = buckets.at(hash_value);
  193. for (auto& item : bucket) {
  194. if (key == item.key)
  195. return iterator_type(&item);
  196. }
  197. return iterator_type::npos;
  198. }
  199. const_iterator_type find(const key_type& key) const
  200. {
  201. auto hash_value = hasher_traits<Hasher, key_type>::hash(key, hash_length());
  202. const auto& bucket = buckets.at(hash_value);
  203. for (const auto& item : bucket) {
  204. if (key == item.key)
  205. return const_iterator_type(&(*item));
  206. }
  207. return const_iterator_type::npos;
  208. }
  209. void clear(void)
  210. {
  211. buckets.clear();
  212. }
  213. };
  214. } // namespace types