bst_vector.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "ik/bst_vector.h"
  2. #include "ik/memory.h"
  3. #include <assert.h>
  4. #include <string.h>
  5. const uint32_t BST_VECTOR_INVALID_HASH = (uint32_t)-1;
  6. /* ------------------------------------------------------------------------- */
  7. bstv_t*
  8. bstv_create(void)
  9. {
  10. bstv_t* bstv;
  11. if (!(bstv = (bstv_t*)MALLOC(sizeof *bstv)))
  12. return NULL;
  13. bstv_construct(bstv);
  14. return bstv;
  15. }
  16. /* ------------------------------------------------------------------------- */
  17. void
  18. bstv_construct(bstv_t* bstv)
  19. {
  20. assert(bstv);
  21. ordered_vector_construct(&bstv->vector, sizeof(bstv_hash_value_t));
  22. }
  23. /* ------------------------------------------------------------------------- */
  24. void
  25. bstv_destroy(bstv_t* bstv)
  26. {
  27. assert(bstv);
  28. bstv_clear_free(bstv);
  29. FREE(bstv);
  30. }
  31. /* ------------------------------------------------------------------------- */
  32. /* algorithm taken from GNU GCC stdlibc++'s lower_bound function, line 2121 in stl_algo.h */
  33. /* https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a02014.html */
  34. static bstv_hash_value_t*
  35. bstv_find_lower_bound(const bstv_t* bstv, uint32_t hash)
  36. {
  37. uint32_t half;
  38. bstv_hash_value_t* middle;
  39. bstv_hash_value_t* data;
  40. uint32_t len;
  41. assert(bstv);
  42. data = (bstv_hash_value_t*)bstv->vector.data;
  43. len = bstv->vector.count;
  44. /* if (the vector has no data, return NULL */
  45. if (!len)
  46. return NULL;
  47. while (len > 0)
  48. {
  49. half = len >> 1;
  50. middle = data + half;
  51. if (middle->hash < hash)
  52. {
  53. data = middle;
  54. ++data;
  55. len = len - half - 1;
  56. }
  57. else
  58. len = half;
  59. }
  60. /* if ("data" is pointing outside of the valid elements in the vector, also return NULL */
  61. if ((intptr_t)data >= (intptr_t)bstv->vector.data + (intptr_t)bstv->vector.count * (intptr_t)bstv->vector.element_size)
  62. return NULL;
  63. else
  64. return data;
  65. }
  66. /* ------------------------------------------------------------------------- */
  67. int
  68. bstv_insert(bstv_t* bstv, uint32_t hash, void* value)
  69. {
  70. bstv_hash_value_t* emplaced_data;
  71. bstv_hash_value_t* lower_bound;
  72. assert(bstv);
  73. /* don't insert reserved hashes */
  74. if (hash == BST_VECTOR_INVALID_HASH)
  75. return -1;
  76. /* lookup location in bstv to insert */
  77. lower_bound = bstv_find_lower_bound(bstv, hash);
  78. if (lower_bound && lower_bound->hash == hash)
  79. return 1;
  80. /* either push back or insert, depending on whether there is already data
  81. * in the bstv */
  82. if (!lower_bound)
  83. emplaced_data = (bstv_hash_value_t*)ordered_vector_push_emplace(&bstv->vector);
  84. else
  85. emplaced_data = ordered_vector_insert_emplace(&bstv->vector,
  86. lower_bound - (bstv_hash_value_t*)bstv->vector.data);
  87. if (!emplaced_data)
  88. return -1;
  89. memset(emplaced_data, 0, sizeof *emplaced_data);
  90. emplaced_data->hash = hash;
  91. emplaced_data->value = value;
  92. return 0;
  93. }
  94. /* ------------------------------------------------------------------------- */
  95. void
  96. bstv_set(bstv_t* bstv, uint32_t hash, void* value)
  97. {
  98. bstv_hash_value_t* data;
  99. assert(bstv);
  100. data = bstv_find_lower_bound(bstv, hash);
  101. if (data && data->hash == hash)
  102. data->value = value;
  103. }
  104. /* ------------------------------------------------------------------------- */
  105. void*
  106. bstv_find(const bstv_t* bstv, uint32_t hash)
  107. {
  108. void** result = bstv_find_ptr(bstv, hash);
  109. return result == NULL ? NULL : *result;
  110. }
  111. /* ------------------------------------------------------------------------- */
  112. void**
  113. bstv_find_ptr(const bstv_t* bstv, uint32_t hash)
  114. {
  115. bstv_hash_value_t* data;
  116. assert(bstv);
  117. data = bstv_find_lower_bound(bstv, hash);
  118. if (!data || data->hash != hash)
  119. return NULL;
  120. return &data->value;
  121. }
  122. /* ------------------------------------------------------------------------- */
  123. uint32_t
  124. bstv_find_element(const bstv_t* bstv, const void* value)
  125. {
  126. assert(bstv);
  127. ORDERED_VECTOR_FOR_EACH(&bstv->vector, bstv_hash_value_t, kv)
  128. if (kv->value == value)
  129. return kv->hash;
  130. ORDERED_VECTOR_END_EACH
  131. return BST_VECTOR_INVALID_HASH;
  132. }
  133. /* ------------------------------------------------------------------------- */
  134. void*
  135. bstv_get_any_element(const bstv_t* bstv)
  136. {
  137. bstv_hash_value_t* kv;
  138. assert(bstv);
  139. kv = (bstv_hash_value_t*)ordered_vector_back(&bstv->vector);
  140. if (kv)
  141. return kv->value;
  142. return NULL;
  143. }
  144. /* ------------------------------------------------------------------------- */
  145. int
  146. bstv_hash_exists(bstv_t* bstv, uint32_t hash)
  147. {
  148. bstv_hash_value_t* data;
  149. assert(bstv);
  150. data = bstv_find_lower_bound(bstv, hash);
  151. if (data && data->hash == hash)
  152. return 0;
  153. return -1;
  154. }
  155. /* ------------------------------------------------------------------------- */
  156. uint32_t
  157. bstv_find_unused_hash(bstv_t* bstv)
  158. {
  159. uint32_t i = 0;
  160. assert(bstv);
  161. BSTV_FOR_EACH(bstv, void, key, value)
  162. if (i != key)
  163. break;
  164. ++i;
  165. BSTV_END_EACH
  166. return i;
  167. }
  168. /* ------------------------------------------------------------------------- */
  169. void*
  170. bstv_erase(bstv_t* bstv, uint32_t hash)
  171. {
  172. void* value;
  173. bstv_hash_value_t* data;
  174. assert(bstv);
  175. data = bstv_find_lower_bound(bstv, hash);
  176. if (!data || data->hash != hash)
  177. return NULL;
  178. value = data->value;
  179. ordered_vector_erase_element(&bstv->vector, (DATA_POINTER_TYPE*)data);
  180. return value;
  181. }
  182. /* ------------------------------------------------------------------------- */
  183. void*
  184. bstv_erase_element(bstv_t* bstv, void* value)
  185. {
  186. void* data;
  187. uint32_t hash;
  188. assert(bstv);
  189. hash = bstv_find_element(bstv, value);
  190. if (hash == BST_VECTOR_INVALID_HASH)
  191. return NULL;
  192. data = bstv_find_lower_bound(bstv, hash);
  193. ordered_vector_erase_element(&bstv->vector, (DATA_POINTER_TYPE*)data);
  194. return value;
  195. }
  196. /* ------------------------------------------------------------------------- */
  197. void
  198. bstv_clear(bstv_t* bstv)
  199. {
  200. assert(bstv);
  201. ordered_vector_clear(&bstv->vector);
  202. }
  203. /* ------------------------------------------------------------------------- */
  204. void bstv_clear_free(bstv_t* bstv)
  205. {
  206. assert(bstv);
  207. ordered_vector_clear_free(&bstv->vector);
  208. }