ht.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #ifndef HT_H
  2. #define HT_H
  3. #include <stdint.h>
  4. #include <stddef.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "da.h"
  8. #ifndef typeof
  9. #define typeof __typeof__
  10. #endif
  11. #define CONCAT(a, b) CONCAT_INNER(a, b)
  12. #define CONCAT_INNER(a, b) a ## b
  13. #define UNIQUE_NAME(base) CONCAT(base, __COUNTER__)
  14. typedef uint64_t (*ht_hash_func)(const char *, size_t);
  15. uint64_t ht_default_hash(const char *str, size_t str_size);
  16. #define HT_DEF_STRUCT(type, name) \
  17. struct name##_item { \
  18. struct { \
  19. const char *data; \
  20. size_t size; \
  21. } key_str; \
  22. uint64_t key; \
  23. type data; \
  24. void *next; \
  25. }; \
  26. struct name { \
  27. struct name##_item *items; \
  28. size_t size; \
  29. size_t cap; \
  30. DA_DEF_STRUCT_ITEM(uint64_t, keys); \
  31. ht_hash_func hash; \
  32. size_t collisions; \
  33. }
  34. #define HT_DEF_STRUCT_ITEM(type, name) \
  35. struct { \
  36. struct { \
  37. uint64_t key; \
  38. type data; \
  39. void *next; \
  40. } *items; \
  41. size_t size; \
  42. size_t cap; \
  43. ht_hash_func hash; \
  44. } name
  45. #define HT_CREATE(ht, init_cap) \
  46. do { \
  47. (ht).cap = (init_cap); \
  48. (ht).size = 0; \
  49. (ht).items = calloc((ht).cap, sizeof(*(ht).items)); \
  50. (ht).hash = ht_default_hash; \
  51. DA_CREATE((ht).keys); \
  52. } while(0)
  53. #define _HT_DESTROY(ht, _t, _hi) \
  54. do{ \
  55. void *_t = NULL; \
  56. for ( i = 0; i < (ht).cap; ++i ) { \
  57. typeof(*(ht).items) *_hi = &(ht).items[i]; \
  58. while( _hi->next != NULL ) { \
  59. _t = _hi; \
  60. _hi = _hi->next; \
  61. free(_t); \
  62. } \
  63. } \
  64. free((ht).items); \
  65. free((ht).keys.items); \
  66. } while(0)
  67. #define HT_DESTROY(ht) \
  68. _HT_DESTROY(ht, UNIQUE_NAME(_t), UNIQUE_NAME(_hi))
  69. #define _HT_INC_CAP(ht, _ht, _it, _i, _j, _k) \
  70. do { \
  71. typeof((ht)) _ht = {0}; \
  72. HT_CREATE(_ht, (ht).cap*2); \
  73. for ( size_t _i = 0; _i < (ht).keys.size; ++_i ) { \
  74. uint64_t _k = (ht).keys.items[_i]; \
  75. typeof(*(ht).items) _hi = (ht).items[_k % (ht).cap]; \
  76. uint64_t _j = 0; \
  77. while( _hi.key != _k) { \
  78. _hi = (ht).items[(_k + ++_j) % (ht).cap]; \
  79. } \
  80. typeof(*_ht.items) *_it = &_ht.items[_hi.key \
  81. % _ht.cap]; \
  82. _j = _hi.key; \
  83. while ( _it->key != 0 && _it->key != _hi.key ) { \
  84. _it = &_ht.items[(++_j) % _ht.cap]; \
  85. ++_ht.collisions; \
  86. } \
  87. DA_APPEND(_ht.keys, _hi.key); \
  88. _it->key_str.data = _hi.key_str.data; \
  89. _it->key_str.size = _hi.key_str.size; \
  90. _it->key = _hi.key; \
  91. _it->data = _hi.data; \
  92. _it->next = NULL; \
  93. ++_ht.size; \
  94. } \
  95. HT_DESTROY(ht); \
  96. (ht) = _ht; \
  97. } while(0)
  98. #define HT_INC_CAP(ht) \
  99. _HT_INC_CAP(ht, UNIQUE_NAME(_ht), UNIQUE_NAME(_it), \
  100. UNIQUE_NAME(_i), UNIQUE_NAME(_j), UNIQUE_NAME(_k))
  101. #include <stdio.h>
  102. #define _HT_SET(ht, _key, _key_size, val, _k, _it, _i) \
  103. do { \
  104. if ( (ht).size + 1 >= (ht).cap ) { \
  105. HT_INC_CAP(ht); \
  106. } \
  107. uint64_t _k = (ht).hash((_key), (_key_size)); \
  108. typeof(*(ht).items) *_it = &(ht).items[_k % (ht).cap]; \
  109. uint64_t _i = _k; \
  110. while ( _it->key != 0 && _it->key != _k ) { \
  111. _it = &(ht).items[(++_i) % (ht).cap]; \
  112. ++(ht).collisions; \
  113. } \
  114. if ( _it->key == _k ) { \
  115. _it->data = val; \
  116. break; \
  117. } \
  118. DA_APPEND((ht).keys, _k); \
  119. _it->key_str.data = _key; \
  120. _it->key_str.size = _key_size; \
  121. _it->key = _k; \
  122. _it->data = val; \
  123. _it->next = NULL; \
  124. ++(ht).size; \
  125. } while(0)
  126. #define HT_SET(ht, key, key_size, val) \
  127. _HT_SET(ht, key, key_size, val, \
  128. UNIQUE_NAME(_k), UNIQUE_NAME(_it), UNIQUE_NAME(_i))
  129. #define _HT_GET(ht, _key, _key_size, ret, _k, _it) \
  130. do { \
  131. uint64_t _k = (ht).hash((_key), (_key_size)); \
  132. typeof(*(ht).items) *_it = &(ht).items[_k % (ht).cap]; \
  133. (ret) = _it->data; \
  134. } while(0)
  135. #define HT_GET(ht, key, key_size, ret) \
  136. _HT_GET(ht, key, key_size, ret, UNIQUE_NAME(_k), UNIQUE_NAME(_it))
  137. #if defined(HT_IMP) || defined(IMP)
  138. uint64_t
  139. ht_default_hash(const char *str, size_t str_size)
  140. {
  141. uint64_t k = (uint64_t)((char)str[0]) << 56;
  142. k |= (((uint64_t) (str[1 * (str_size > 1)])) << 48);
  143. k |= (((uint64_t) (str[2 * (str_size > 2)])) << 40);
  144. k |= (((uint64_t) (str[3 * (str_size > 3)])) << 32);
  145. k |= (((uint64_t) (str[(str_size-4) * (str_size >= 4)])) << 24);
  146. k |= (((uint64_t) (str[(str_size-3) * (str_size >= 3)])) << 16);
  147. k |= (((uint64_t) (str[(str_size-2) * (str_size >= 2)])) << 8);
  148. k |= (((uint64_t) (str[(str_size-1) * (str_size >= 1)])) << 0);
  149. return k + ((uint64_t)str[4 * (str_size > 4)] * 31)
  150. + ((uint64_t)str[(str_size-5) * (str_size >= 5)] * 13)
  151. + ((uint64_t)str[str_size/2] * 41);
  152. /* static uint8_t _primes_list[] = { */
  153. /* 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, */
  154. /* 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, */
  155. /* 131, 137, 139, 149, 151, 157, 163, 167, 173 */
  156. /* }; */
  157. /* static uint8_t _primes_list_size = 8; */
  158. /* uint64_t max = UINT64_MAX >> 1; */
  159. /* uint64_t ret = 1; */
  160. /* uint8_t p = 0; */
  161. /* size_t i = 0; */
  162. /* uint8_t b = 0; */
  163. /* for ( i = 0; i < str_size; ++i ) { */
  164. /* b = (uint8_t)str[i]; */
  165. /* p = _primes_list[(i + b) & _primes_list_size]; */
  166. /* ret = (ret * (b * p)) % max; */
  167. /* } */
  168. /* return ret; */
  169. }
  170. #endif /* defined(HT_IMP) || defined(IMP) */
  171. #undef CONCAT
  172. #undef CONCAT_INNER
  173. #undef UNIQUE_NAME
  174. #endif