jset.h 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362
  1. /* Licensed under LGPLv2.1+ - see LICENSE file for details */
  2. #ifndef CCAN_JSET_H
  3. #define CCAN_JSET_H
  4. #include "config.h"
  5. #include <ccan/compiler/compiler.h>
  6. #include <ccan/tcon/tcon.h>
  7. #include <Judy.h>
  8. #include <stdbool.h>
  9. #include <assert.h>
  10. /**
  11. * struct jset - private definition of a jset.
  12. *
  13. * It's exposed here so you can put it in your structures and so we can
  14. * supply inline functions.
  15. */
  16. struct jset {
  17. void *judy;
  18. JError_t err;
  19. const char *errstr;
  20. };
  21. /**
  22. * JSET_MEMBERS - declare members for a type-specific jset.
  23. * @type: type for this set to contain, or void * for any pointer.
  24. *
  25. * Example:
  26. * struct jset_long {
  27. * JSET_MEMBERS(long);
  28. * };
  29. */
  30. #define JSET_MEMBERS(type) \
  31. struct jset raw; \
  32. TCON(type canary)
  33. /**
  34. * jset_new - create a new, empty jset.
  35. * @type: the tcon-containing type to allocate.
  36. *
  37. * Example:
  38. * struct jset_long {
  39. * JSET_MEMBERS(long);
  40. * } *set = jset_new(struct jset_long);
  41. *
  42. * if (!set)
  43. * errx(1, "Failed to allocate set");
  44. */
  45. #define jset_new(type) ((type *)jset_new_(sizeof(type)))
  46. /**
  47. * jset_free - destroy a jset.
  48. * @set: the set returned from jset_new.
  49. *
  50. * Example:
  51. * jset_free(set);
  52. */
  53. #define jset_free(set) jset_free_(&(set)->raw)
  54. /**
  55. * jset_error - test for an error in the a previous jset_ operation.
  56. * @set: the set to test.
  57. *
  58. * Under normal circumstances, return NULL to indicate no error has occurred.
  59. * Otherwise, it will return a string containing the error. This string
  60. * can only be freed by jset_free() on the set.
  61. *
  62. * Other than out-of-memory, errors are caused by memory corruption or
  63. * interface misuse.
  64. *
  65. * Example:
  66. * const char *errstr;
  67. *
  68. * errstr = jset_error(set);
  69. * if (errstr)
  70. * errx(1, "Woah, error on newly created set?! %s", errstr);
  71. */
  72. #define jset_error(set) \
  73. jset_error_(&(set)->raw)
  74. /**
  75. * jset_raw - unwrap the typed set and check the type
  76. * @set: the typed jset
  77. * @expr: the expression to check the type against (not evaluated)
  78. *
  79. * This macro usually causes the compiler to emit a warning if the
  80. * variable is of an unexpected type. It is used internally where we
  81. * need to access the raw underlying jset.
  82. */
  83. #define jset_raw(set, expr) (&tcon_check((set), canary, (expr))->raw)
  84. /**
  85. * jset_test - test a bit in the bitset.
  86. * @set: bitset from jset_new
  87. * @index: the index to test
  88. *
  89. * Returns true if jset_set() has been done on this index, false otherwise.
  90. *
  91. * Example:
  92. * assert(!jset_test(set, 0));
  93. */
  94. #define jset_test(set, index) \
  95. jset_test_(jset_raw((set), (index)), (unsigned long)(index))
  96. /**
  97. * jset_set - set a bit in the bitset.
  98. * @set: bitset from jset_new
  99. * @index: the index to set
  100. *
  101. * Returns false if it was already set (ie. nothing changed)
  102. *
  103. * Example:
  104. * if (jset_set(set, 0))
  105. * err(1, "Bit 0 was already set?!");
  106. */
  107. #define jset_set(set, index) \
  108. jset_set_(jset_raw((set), (index)), (unsigned long)(index))
  109. /**
  110. * jset_clear - clear a bit in the bitset.
  111. * @set: bitset from jset_new
  112. * @index: the index to set
  113. *
  114. * Returns the old bit value (ie. false if nothing changed).
  115. *
  116. * Example:
  117. * if (jset_clear(set, 0))
  118. * err(1, "Bit 0 was already clear?!");
  119. */
  120. #define jset_clear(set, index) \
  121. jset_clear_(jset_raw((set), (index)), (unsigned long)(index))
  122. /**
  123. * jset_count - get population of bitset.
  124. * @set: bitset from jset_new
  125. *
  126. * Example:
  127. * // We expect 1000 entries.
  128. * assert(jset_count(set) == 1000);
  129. */
  130. #define jset_count(set) \
  131. jset_popcount_(&(set)->raw, 0, -1UL)
  132. /**
  133. * jset_popcount - get population of (some part of) bitset.
  134. * @set: bitset from jset_new
  135. * @start: first index to count
  136. * @end_incl: last index to count (use -1 for end).
  137. *
  138. * Example:
  139. * assert(jset_popcount(set, 0, 1000) <= jset_popcount(set, 0, 2000));
  140. */
  141. #define jset_popcount(set, start, end_incl) \
  142. jset_popcount_(jset_raw((set), (start) ? (start) : (end_incl)), \
  143. (unsigned long)(start), (unsigned long)(end_incl))
  144. /**
  145. * jset_nth - return the index of the nth bit which is set.
  146. * @set: bitset from jset_new
  147. * @n: which bit we are interested in (0-based)
  148. * @invalid: what to return if n >= set population
  149. *
  150. * This normally returns the nth bit in the set, and often there is a
  151. * convenient known-invalid value (ie. something which is never in the
  152. * set). Otherwise, and a wrapper function like this can be used:
  153. *
  154. * static bool jset_nth_index(struct jset *set,
  155. * unsigned long n, unsigned long *idx)
  156. * {
  157. * // Zero might be valid, if it's first in set.
  158. * if (n == 0 && jset_test(set, 0)) {
  159. * *idx = 0;
  160. * return true;
  161. * }
  162. * *idx = jset_nth(set, n, 0);
  163. * return (*idx != 0);
  164. * }
  165. *
  166. * Example:
  167. * unsigned long i, val;
  168. *
  169. * // We know 0 isn't in set.
  170. * assert(!jset_test(set, 0));
  171. * for (i = 0; (val = jset_nth(set, i, 0)) != 0; i++) {
  172. * assert(jset_popcount(set, 0, val) == i);
  173. * printf("Value %lu = %lu\n", i, val);
  174. * }
  175. */
  176. #define jset_nth(set, n, invalid) \
  177. tcon_cast((set), canary, \
  178. jset_nth_(jset_raw((set), (invalid)), \
  179. (n), (unsigned long)(invalid)))
  180. /**
  181. * jset_first - return the first bit which is set (must not contain 0).
  182. * @set: bitset from jset_new
  183. *
  184. * This is equivalent to jset_nth(set, 0, 0). ie. useful only if 0
  185. * isn't in your set.
  186. *
  187. * Example:
  188. * assert(!jset_test(set, 0));
  189. * printf("Set contents (increasing order):");
  190. * for (i = jset_first(set); i; i = jset_next(set, i))
  191. * printf(" %lu", i);
  192. * printf("\n");
  193. */
  194. #define jset_first(set) \
  195. tcon_cast((set), canary, jset_first_(&(set)->raw))
  196. /**
  197. * jset_next - return the next bit which is set (must not contain 0).
  198. * @set: bitset from jset_new
  199. * @prev: previous index
  200. *
  201. * This is usually used to find an adjacent index which is set, after
  202. * jset_first.
  203. */
  204. #define jset_next(set, prev) \
  205. tcon_cast((set), canary, jset_next_(&(set)->raw, (unsigned long)(prev)))
  206. /**
  207. * jset_last - return the last bit which is set (must not contain 0).
  208. * @set: bitset from jset_new
  209. *
  210. * Example:
  211. * assert(!jset_test(set, 0));
  212. * printf("Set contents (decreasing order):");
  213. * for (i = jset_last(set); i; i = jset_prev(set, i))
  214. * printf(" %lu", i);
  215. * printf("\n");
  216. */
  217. #define jset_last(set) \
  218. tcon_cast((set), canary, jset_last_(&(set)->raw))
  219. /**
  220. * jset_prev - return the previous bit which is set (must not contain 0).
  221. * @set: bitset from jset_new
  222. * @prev: previous index
  223. *
  224. * This is usually used to find an adjacent bit which is set, after
  225. * jset_last.
  226. */
  227. #define jset_prev(set, prev) \
  228. tcon_cast((set), canary, jset_prev_(&(set)->raw, (unsigned long)(prev)))
  229. /**
  230. * jset_first_clear - return the first bit which is unset
  231. * @set: bitset from jset_new
  232. *
  233. * This allows for iterating the inverse of the bitmap; only returns 0 if the
  234. * set is full.
  235. */
  236. #define jset_first_clear(set) \
  237. tcon_cast((set), canary, jset_next_clear_(&(set)->raw, 0))
  238. #define jset_next_clear(set, prev) \
  239. tcon_cast((set), canary, jset_next_clear_(&(set)->raw, \
  240. (unsigned long)(prev)))
  241. #define jset_last_clear(set) \
  242. tcon_cast((set), canary, jset_last_clear_(&(set)->raw))
  243. #define jset_prev_clear(set, prev) \
  244. tcon_cast((set), canary, jset_prev_clear_(&(set)->raw, \
  245. (unsigned long)(prev)))
  246. /* Raw functions */
  247. struct jset *jset_new_(size_t size);
  248. void jset_free_(const struct jset *set);
  249. const char *COLD jset_error_str_(struct jset *set);
  250. static inline const char *jset_error_(struct jset *set)
  251. {
  252. if (JU_ERRNO(&set->err) <= JU_ERRNO_NFMAX)
  253. return NULL;
  254. return jset_error_str_(set);
  255. }
  256. static inline bool jset_test_(const struct jset *set, unsigned long index)
  257. {
  258. return Judy1Test(set->judy, index, (JError_t *)&set->err);
  259. }
  260. static inline bool jset_set_(struct jset *set, unsigned long index)
  261. {
  262. return Judy1Set(&set->judy, index, &set->err);
  263. }
  264. static inline bool jset_clear_(struct jset *set, unsigned long index)
  265. {
  266. return Judy1Unset(&set->judy, index, &set->err);
  267. }
  268. static inline unsigned long jset_popcount_(const struct jset *set,
  269. unsigned long start,
  270. unsigned long end_incl)
  271. {
  272. return Judy1Count(set->judy, start, end_incl, (JError_t *)&set->err);
  273. }
  274. static inline unsigned long jset_nth_(const struct jset *set,
  275. unsigned long n, unsigned long invalid)
  276. {
  277. unsigned long index;
  278. if (!Judy1ByCount(set->judy, n+1, &index, (JError_t *)&set->err))
  279. index = invalid;
  280. return index;
  281. }
  282. static inline unsigned long jset_first_(const struct jset *set)
  283. {
  284. unsigned long index = 0;
  285. if (!Judy1First(set->judy, &index, (JError_t *)&set->err))
  286. index = 0;
  287. else
  288. assert(index != 0);
  289. return index;
  290. }
  291. static inline unsigned long jset_next_(const struct jset *set,
  292. unsigned long prev)
  293. {
  294. if (!Judy1Next(set->judy, &prev, (JError_t *)&set->err))
  295. prev = 0;
  296. else
  297. assert(prev != 0);
  298. return prev;
  299. }
  300. static inline unsigned long jset_last_(const struct jset *set)
  301. {
  302. unsigned long index = -1;
  303. if (!Judy1Last(set->judy, &index, (JError_t *)&set->err))
  304. index = 0;
  305. else
  306. assert(index != 0);
  307. return index;
  308. }
  309. static inline unsigned long jset_prev_(const struct jset *set,
  310. unsigned long prev)
  311. {
  312. if (!Judy1Prev(set->judy, &prev, (JError_t *)&set->err))
  313. prev = 0;
  314. else
  315. assert(prev != 0);
  316. return prev;
  317. }
  318. static inline unsigned long jset_next_clear_(const struct jset *set,
  319. unsigned long prev)
  320. {
  321. if (!Judy1NextEmpty(set->judy, &prev, (JError_t *)&set->err))
  322. prev = 0;
  323. else
  324. assert(prev != 0);
  325. return prev;
  326. }
  327. static inline unsigned long jset_last_clear_(const struct jset *set)
  328. {
  329. unsigned long index = -1;
  330. if (!Judy1LastEmpty(set->judy, &index, (JError_t *)&set->err))
  331. index = 0;
  332. return index;
  333. }
  334. static inline unsigned long jset_prev_clear_(const struct jset *set,
  335. unsigned long prev)
  336. {
  337. if (!Judy1PrevEmpty(set->judy, &prev, (JError_t *)&set->err))
  338. prev = 0;
  339. return prev;
  340. }
  341. #endif /* CCAN_JSET_H */