A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

176 lignes
3.5 KiB

  1. #include <stdlib.h>
  2. #include <stdint.h>
  3. #include "hashtable.h"
  4. #define KEYP(tbl, o) ((o) + (tbl)->keyoff)
  5. #define CHAINP(tbl, o) *((void **)((o) + (tbl)->chainoff))
  6. struct _htbl {
  7. int (*eq)(const void *, const void *);
  8. uint32_t (*hash)(const void *);
  9. void **buckets;
  10. size_t buckcnt;
  11. size_t size;
  12. size_t keyoff;
  13. size_t chainoff;
  14. };
  15. struct _htbl *
  16. _htbl_create(int (*eq)(const void *, const void *),
  17. uint32_t (*hash)(const void *), size_t keyoff, size_t chainoff)
  18. {
  19. struct _htbl *tbl = calloc(1, sizeof(*tbl));
  20. if (tbl == NULL)
  21. return NULL;
  22. tbl->size = 0;
  23. tbl->buckcnt = 1;
  24. tbl->keyoff = keyoff;
  25. tbl->chainoff = chainoff;
  26. tbl->hash = hash;
  27. tbl->eq = eq;
  28. tbl->buckets = calloc(tbl->buckcnt, sizeof(*tbl->buckets));
  29. if (tbl->buckets == NULL) {
  30. free(tbl);
  31. return NULL;
  32. }
  33. return tbl;
  34. }
  35. void
  36. _htbl_free(struct _htbl *tbl)
  37. {
  38. free(tbl->buckets);
  39. free(tbl);
  40. }
  41. static void *
  42. bucket_rev(struct _htbl *tbl, void *p, void *n)
  43. {
  44. while (n != NULL) {
  45. void *s = CHAINP(tbl, n);
  46. CHAINP(tbl, n) = p;
  47. p = n;
  48. n = s;
  49. }
  50. return p;
  51. }
  52. static void
  53. bucket_insert(struct _htbl *tbl, void *o)
  54. {
  55. size_t bi = tbl->hash(KEYP(tbl, o)) % tbl->buckcnt;
  56. CHAINP(tbl, o) = tbl->buckets[bi];
  57. tbl->buckets[bi] = o;
  58. }
  59. static void
  60. _htbl_grow(struct _htbl *tbl)
  61. {
  62. size_t ncnt = 2 * tbl->buckcnt + 1;
  63. size_t ocnt = tbl->buckcnt;
  64. void **obuckets = tbl->buckets;
  65. void **nbuckets = calloc(ncnt, sizeof(*nbuckets));
  66. if (nbuckets == NULL)
  67. return;
  68. tbl->buckcnt = ncnt;
  69. tbl->buckets = nbuckets;
  70. for (size_t i = 0; i < ocnt; i++) {
  71. void *o = bucket_rev(tbl, NULL, obuckets[i]);
  72. while (o != NULL) {
  73. void *s = CHAINP(tbl, o);
  74. bucket_insert(tbl, o);
  75. o = s;
  76. }
  77. }
  78. free(obuckets);
  79. }
  80. void
  81. _htbl_insert(struct _htbl *tbl, void *o)
  82. {
  83. bucket_insert(tbl, o);
  84. tbl->size++;
  85. if (tbl->size > tbl->buckcnt * 4 / 5)
  86. _htbl_grow(tbl);
  87. }
  88. void *
  89. _htbl_find(struct _htbl *tbl, const void *key)
  90. {
  91. size_t bi = tbl->hash(key) % tbl->buckcnt;
  92. for (void *ret = tbl->buckets[bi]; ret != NULL; ret = CHAINP(tbl, ret))
  93. if (tbl->eq(KEYP(tbl, ret), key))
  94. return ret;
  95. return NULL;
  96. }
  97. void *
  98. _htbl_remove(struct _htbl *tbl, const void *key)
  99. {
  100. size_t bi = tbl->hash(key) % tbl->buckcnt;
  101. void *p = NULL, *o = tbl->buckets[bi];
  102. while (o != NULL && !tbl->eq(KEYP(tbl, o), key)) {
  103. p = o;
  104. o = CHAINP(tbl, o);
  105. }
  106. if (o != NULL) {
  107. if (p == NULL)
  108. tbl->buckets[bi] = CHAINP(tbl, o);
  109. else
  110. CHAINP(tbl, p) = CHAINP(tbl, o);
  111. tbl->size--;
  112. }
  113. return o;
  114. }
  115. void
  116. _htbl_tov(struct _htbl *tbl, void **v)
  117. {
  118. size_t vi = 0;
  119. size_t bi = 0;
  120. void *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. size_t
  132. _htbl_size(struct _htbl *tbl)
  133. {
  134. return tbl->size;
  135. }
  136. void
  137. _htbl_iter_init(struct _htbl *tbl, struct htbl_iter *it)
  138. {
  139. it->tbl = tbl;
  140. it->bi = 0;
  141. it->cnt = 0;
  142. it->obj = NULL;
  143. }
  144. void *
  145. _htbl_iter_next(struct htbl_iter *it)
  146. {
  147. if (it->cnt == it->tbl->size)
  148. return NULL;
  149. it->obj = it->cnt == 0 ?
  150. it->tbl->buckets[it->bi] : CHAINP(it->tbl, it->obj);
  151. while (it->obj == NULL) {
  152. it->bi++;
  153. it->obj = it->tbl->buckets[it->bi];
  154. }
  155. it->cnt++;
  156. return it->obj;
  157. }