A clone of btpd with my configuration changes.
No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

225 líneas
4.5 KiB

  1. #include <stdlib.h>
  2. #include <inttypes.h>
  3. #include "hashtable.h"
  4. struct _htbl {
  5. int (*eq)(const void *, const void *);
  6. uint32_t (*hash)(const void *);
  7. struct _any **buckets;
  8. size_t buckcnt;
  9. size_t size;
  10. size_t keyoff;
  11. size_t chainoff;
  12. float ratio;
  13. };
  14. #define KEYP(tbl, o) ((void *)(o) + (tbl)->keyoff)
  15. #define CHAINP(tbl, o) *(struct _any **)((void *)(o) + (tbl)->chainoff)
  16. struct _htbl *
  17. _htbl_create(float ratio, int (*eq)(const void *, const void *),
  18. uint32_t (*hash)(const void *), size_t keyoff, size_t chainoff)
  19. {
  20. struct _htbl *tbl = calloc(1, sizeof(*tbl));
  21. if (tbl == NULL)
  22. return NULL;
  23. tbl->size = 0;
  24. tbl->buckcnt = 1;
  25. tbl->ratio = ratio;
  26. tbl->keyoff = keyoff;
  27. tbl->chainoff = chainoff;
  28. tbl->hash = hash;
  29. tbl->eq = eq;
  30. tbl->buckets = calloc(tbl->buckcnt, sizeof(*tbl->buckets));
  31. if (tbl->buckets == NULL) {
  32. free(tbl);
  33. return NULL;
  34. }
  35. return tbl;
  36. }
  37. void
  38. _htbl_free(struct _htbl *tbl)
  39. {
  40. free(tbl->buckets);
  41. free(tbl);
  42. }
  43. static struct _any *
  44. bucket_rev(struct _htbl *tbl, struct _any *p, struct _any *n)
  45. {
  46. while (n != NULL) {
  47. struct _any *s = CHAINP(tbl, n);
  48. CHAINP(tbl, n) = p;
  49. p = n;
  50. n = s;
  51. }
  52. return p;
  53. }
  54. static void
  55. bucket_insert(struct _htbl *tbl, struct _any *o)
  56. {
  57. size_t bi = tbl->hash(KEYP(tbl, o)) % tbl->buckcnt;
  58. CHAINP(tbl, o) = tbl->buckets[bi];
  59. tbl->buckets[bi] = o;
  60. }
  61. static void
  62. _htbl_grow(struct _htbl *tbl)
  63. {
  64. size_t ncnt = 2 * tbl->buckcnt + 1;
  65. size_t ocnt = tbl->buckcnt;
  66. struct _any **obuckets = tbl->buckets;
  67. struct _any **nbuckets = calloc(ncnt, sizeof(*nbuckets));
  68. if (nbuckets == NULL)
  69. return;
  70. tbl->buckcnt = ncnt;
  71. tbl->buckets = nbuckets;
  72. for (size_t i = 0; i < ocnt; i++) {
  73. struct _any *o = bucket_rev(tbl, NULL, obuckets[i]);
  74. while (o != NULL) {
  75. struct _any *s = CHAINP(tbl, o);
  76. bucket_insert(tbl, o);
  77. o = s;
  78. }
  79. }
  80. free(obuckets);
  81. }
  82. void
  83. _htbl_insert(struct _htbl *tbl, struct _any *o)
  84. {
  85. bucket_insert(tbl, o);
  86. tbl->size++;
  87. if (tbl->size > tbl->buckcnt * tbl->ratio)
  88. _htbl_grow(tbl);
  89. }
  90. struct _any *
  91. _htbl_find(struct _htbl *tbl, const void *key)
  92. {
  93. struct _any *ret;
  94. size_t bi = tbl->hash(key) % tbl->buckcnt;
  95. for (ret = tbl->buckets[bi]; ret != NULL; ret = CHAINP(tbl, ret))
  96. if (tbl->eq(KEYP(tbl, ret), key))
  97. return ret;
  98. return NULL;
  99. }
  100. struct _any *
  101. _htbl_remove(struct _htbl *tbl, const void *key)
  102. {
  103. size_t bi = tbl->hash(key) % tbl->buckcnt;
  104. struct _any **p = &tbl->buckets[bi], *o = tbl->buckets[bi];
  105. while (o != NULL && !tbl->eq(KEYP(tbl, o), key)) {
  106. p = &CHAINP(tbl, o);
  107. o = *p;
  108. }
  109. if (o != NULL) {
  110. *p = CHAINP(tbl, o);
  111. tbl->size--;
  112. }
  113. return o;
  114. }
  115. void
  116. _htbl_fillv(struct _htbl *tbl, struct _any **v)
  117. {
  118. size_t vi = 0;
  119. size_t bi = 0;
  120. struct _any *o = tbl->buckets[bi];
  121. while (vi < tbl->size) {
  122. while (o == NULL) {
  123. bi++;
  124. o = tbl->buckets[bi];
  125. }
  126. v[vi] = o;
  127. vi++;
  128. o = CHAINP(tbl, o);
  129. }
  130. }
  131. struct _any **
  132. _htbl_tov(struct _htbl *tbl)
  133. {
  134. struct _any **v = malloc(sizeof(*v));
  135. if (v != NULL)
  136. _htbl_fillv(tbl, v);
  137. return v;
  138. }
  139. size_t
  140. _htbl_size(struct _htbl *tbl)
  141. {
  142. return tbl->size;
  143. }
  144. static void
  145. iter_next_bucket(struct htbl_iter *it)
  146. {
  147. while (it->tbl->buckets[it->bi] == NULL)
  148. it->bi++;
  149. it->obj = it->tbl->buckets[it->bi];
  150. it->ptr = &it->tbl->buckets[it->bi];
  151. }
  152. struct _any *
  153. _htbl_iter_first(struct _htbl *tbl, struct htbl_iter *it)
  154. {
  155. if (tbl->size == 0)
  156. return NULL;
  157. it->tbl = tbl;
  158. it->cnt = 1;
  159. it->bi = 0;
  160. iter_next_bucket(it);
  161. return it->obj;
  162. }
  163. struct _any *
  164. _htbl_iter_next(struct htbl_iter *it)
  165. {
  166. struct _any *tmp;
  167. if (it->cnt == it->tbl->size)
  168. return NULL;
  169. it->cnt++;
  170. if ((tmp = CHAINP(it->tbl, it->obj)) != NULL) {
  171. it->ptr = &CHAINP(it->tbl, it->obj);
  172. it->obj = tmp;
  173. } else {
  174. it->bi++;
  175. iter_next_bucket(it);
  176. }
  177. return it->obj;
  178. }
  179. #include <stdio.h>
  180. struct _any *
  181. _htbl_iter_del(struct htbl_iter *it)
  182. {
  183. struct _any *tmp;
  184. it->tbl->size--;
  185. if (it->cnt > it->tbl->size) {
  186. *it->ptr = NULL;
  187. return NULL;
  188. }
  189. if ((tmp = CHAINP(it->tbl, it->obj)) != NULL) {
  190. *it->ptr = tmp;
  191. it->obj = tmp;
  192. } else {
  193. *it->ptr = NULL;
  194. it->bi++;
  195. iter_next_bucket(it);
  196. }
  197. return it->obj;
  198. }