A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
пре 18 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. }