htable.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /**
  2. * Hash table implementation.
  3. *
  4. * This code is hack...ahem, built upon rhashmap:
  5. * https://github.com/rmind/rhashmap
  6. *
  7. * After trying several hash map implementations, none met all the requirements
  8. * (small, single-file; accept arbitrarily-sized elements; no undebuggable
  9. * macro spaghetti; reasonably fast), so I decided to expand an existing
  10. * library and adapt it to a data type agnostic model.
  11. *
  12. * This table stores keys and optionally values in a contiguous array of
  13. * arbitrary, but fixed, data sizes. For small keys / values of unusual size,
  14. * this is convenient because it avoids creating (and having to manage) a
  15. * pointer for each key and value. The data types are set by casting on
  16. * retrieval.
  17. *
  18. * For larger or variably-sized keys or values, or ones that are not convenient
  19. * to copy into the table, pointers can obviously be used by specifying ptr_t
  20. * key and/or value size.
  21. */
  22. #ifndef _LSUP_HTABLE_H
  23. #define _LSUP_HTABLE_H
  24. #include "core.h"
  25. /* Max number of entries in the table and hash size. */
  26. /*
  27. * This allows a table size limited to size_t, which is probably much more than
  28. * any current system would want to handle in memory.
  29. */
  30. #if defined(HTABLE_HUGE_SIZE)
  31. typedef size_t ht_hash_t;
  32. typedef size_t htsize_t;
  33. #define HTSIZE_MAX SIZE_MAX
  34. /*
  35. * This allows max UINT_MAX entries (4,294,967,295) and a large hash size to
  36. * take full advantage of a very large table.
  37. */
  38. #elif defined(HTABLE_BIG_SIZE)
  39. typedef size_t ht_hash_t;
  40. typedef uint32_t htsize_t;
  41. #define HTSIZE_MAX UINT32_MAX
  42. /*
  43. * This allows max UINT_MAX entries but the hash size is smaller, thus it is
  44. * only recommended for up to a few million entries.
  45. */
  46. #else
  47. typedef uint32_t ht_hash_t;
  48. typedef uint32_t htsize_t;
  49. #define HTSIZE_MAX UINT32_MAX
  50. #endif
  51. // Size of key entries. With HTABLE_BIG_KEY it is 65535 (64Kb). Otherwise,
  52. // it is 256 bytes.
  53. #ifdef HTABLE_BIG_KEY
  54. typedef uint16_t ksize_t;
  55. #else
  56. typedef uint8_t ksize_t;
  57. #endif
  58. // Size of value entries. With HTABLE_BIG_VAL it is 65535 (64Kb). Otherwise,
  59. // it is 256 bytes. For values that may be larger than 64 Kb, use pointers.
  60. #ifdef HTABLE_BIG_VAL
  61. typedef uint16_t vsize_t;
  62. #else
  63. typedef uint8_t vsize_t;
  64. #endif
  65. /**
  66. * Key hashing function.
  67. *
  68. * Takes a void pointer, a key length and a seed.
  69. */
  70. typedef uint64_t (*key_hash_fn_t)(
  71. const void *key, ksize_t size, uint64_t seed);
  72. /**
  73. * Key equality function (true: keys are equal).
  74. *
  75. * Takes two void pointers and a key length (which is constant within the
  76. * hash table).
  77. */
  78. typedef bool (*key_eq_fn_t)(const void *a, const void *b, ksize_t size);
  79. /**
  80. * Hash table type.
  81. *
  82. * By default it should keep a good performance up to a few million entries
  83. * due to its small hash size.
  84. *
  85. * If compiled with -DHTABLE_BIG_SIZE it supports up to UINT_MAX entries (~4
  86. * billions on most modern machines) for very large in-memory graphs.
  87. *
  88. * If compiled with -DHTABLE_HUGE_SIZE it supports up to SIZE_MAX entries
  89. * (probably more then you will ever want to load in memory).
  90. */
  91. typedef struct htable_t LSUP_HTable;
  92. LSUP_rc
  93. LSUP_htable_new(
  94. htsize_t size, ksize_t ksize, vsize_t vsize,
  95. key_hash_fn_t key_hash_fn, key_eq_fn_t key_eq_fn, LSUP_HTable **ht);
  96. LSUP_rc
  97. LSUP_htable_copy(const LSUP_HTable *src, LSUP_HTable **dest);
  98. LSUP_rc
  99. LSUP_htable_resize(LSUP_HTable *ht, htsize_t newsize);
  100. htsize_t
  101. LSUP_htable_capacity(LSUP_HTable *ht);
  102. htsize_t
  103. LSUP_htable_size(LSUP_HTable *ht);
  104. LSUP_rc
  105. LSUP_htable_insert(LSUP_HTable *ht, const void *key, const void *val);
  106. LSUP_rc
  107. LSUP_htable_put(LSUP_HTable *ht, const void *key, const void *val);
  108. /**
  109. * @brief Test the existence of a given key and find its value.
  110. *
  111. * @param LSUP_HTable ht[in]: Hash table or set.
  112. *
  113. * @param const void *key[in]: Key to look up.
  114. *
  115. * @param void *val[out]: Pointer to be set to the address of the value found
  116. * at the key address, if any. The memory pointed to is owned by the hash
  117. * table. If NULL is passed, or if the hash table is a set, the value is never
  118. * populated.
  119. *
  120. * @return int: LSUP_OK if the key is found; LSUP_NORESULT if the key is not
  121. * found; a negative value on error.
  122. */
  123. LSUP_rc
  124. LSUP_htable_get(const LSUP_HTable *ht, const void *key, void **val);
  125. /*
  126. * Remove the given key.
  127. *
  128. * @param LSUP_HTable ht[in]: Hash table or set.
  129. *
  130. * @param const void *key[in]: Key to remove.
  131. *
  132. * @return int: LSUP_OK if the key was removed; LSUP_NOACTION if it was not
  133. * found.
  134. *
  135. */
  136. LSUP_rc
  137. LSUP_htable_remove(LSUP_HTable *ht, const void *key);
  138. /**
  139. * Iterate over a hashmap or set.
  140. *
  141. * @param LSUP_HTable ht[in]: Hash table or set.
  142. *
  143. * @param htsize_t *cur[in]: an integer used as a cursor. Each successful
  144. * iteration of the function increases this value by 1. So the correct use
  145. * for this is to initialize a htsize_t variable to zero and passing its
  146. * pointer in a loop until necessary.
  147. *
  148. * @param void *key[out]: Pointer to be populated with the next key found.
  149. *
  150. * @param void **valp[out]: Pointer to the found value address. This can be
  151. * used as a normal lvalue. It may be NULL for sets or if the value is not
  152. * needed.
  153. *
  154. * @return int: LSUP_OK if the key is found; LSUP_END if the end of the data
  155. * is reached.
  156. */
  157. LSUP_rc
  158. LSUP_htable_iter(LSUP_HTable *ht, htsize_t *cur, void **keyp, void **valp);
  159. /*
  160. * Free the memory used by the hash table.
  161. *
  162. * It is the responsibility of the caller to free data pointed to if pointers
  163. * were used for keys or values.
  164. */
  165. void LSUP_htable_free(LSUP_HTable *ht);
  166. #endif