A clone of btpd with my configuration changes.
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

176 rindas
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. }