| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362 |
- /* Licensed under LGPLv2.1+ - see LICENSE file for details */
- #ifndef CCAN_JSET_H
- #define CCAN_JSET_H
- #include "config.h"
- #include <ccan/compiler/compiler.h>
- #include <ccan/tcon/tcon.h>
- #include <Judy.h>
- #include <stdbool.h>
- #include <assert.h>
- /**
- * struct jset - private definition of a jset.
- *
- * It's exposed here so you can put it in your structures and so we can
- * supply inline functions.
- */
- struct jset {
- void *judy;
- JError_t err;
- const char *errstr;
- };
- /**
- * JSET_MEMBERS - declare members for a type-specific jset.
- * @type: type for this set to contain, or void * for any pointer.
- *
- * Example:
- * struct jset_long {
- * JSET_MEMBERS(long);
- * };
- */
- #define JSET_MEMBERS(type) \
- struct jset raw; \
- TCON(type canary)
- /**
- * jset_new - create a new, empty jset.
- * @type: the tcon-containing type to allocate.
- *
- * Example:
- * struct jset_long {
- * JSET_MEMBERS(long);
- * } *set = jset_new(struct jset_long);
- *
- * if (!set)
- * errx(1, "Failed to allocate set");
- */
- #define jset_new(type) ((type *)jset_new_(sizeof(type)))
- /**
- * jset_free - destroy a jset.
- * @set: the set returned from jset_new.
- *
- * Example:
- * jset_free(set);
- */
- #define jset_free(set) jset_free_(&(set)->raw)
- /**
- * jset_error - test for an error in the a previous jset_ operation.
- * @set: the set to test.
- *
- * Under normal circumstances, return NULL to indicate no error has occurred.
- * Otherwise, it will return a string containing the error. This string
- * can only be freed by jset_free() on the set.
- *
- * Other than out-of-memory, errors are caused by memory corruption or
- * interface misuse.
- *
- * Example:
- * const char *errstr;
- *
- * errstr = jset_error(set);
- * if (errstr)
- * errx(1, "Woah, error on newly created set?! %s", errstr);
- */
- #define jset_error(set) \
- jset_error_(&(set)->raw)
- /**
- * jset_raw - unwrap the typed set and check the type
- * @set: the typed jset
- * @expr: the expression to check the type against (not evaluated)
- *
- * This macro usually causes the compiler to emit a warning if the
- * variable is of an unexpected type. It is used internally where we
- * need to access the raw underlying jset.
- */
- #define jset_raw(set, expr) (&tcon_check((set), canary, (expr))->raw)
- /**
- * jset_test - test a bit in the bitset.
- * @set: bitset from jset_new
- * @index: the index to test
- *
- * Returns true if jset_set() has been done on this index, false otherwise.
- *
- * Example:
- * assert(!jset_test(set, 0));
- */
- #define jset_test(set, index) \
- jset_test_(jset_raw((set), (index)), (unsigned long)(index))
- /**
- * jset_set - set a bit in the bitset.
- * @set: bitset from jset_new
- * @index: the index to set
- *
- * Returns false if it was already set (ie. nothing changed)
- *
- * Example:
- * if (jset_set(set, 0))
- * err(1, "Bit 0 was already set?!");
- */
- #define jset_set(set, index) \
- jset_set_(jset_raw((set), (index)), (unsigned long)(index))
- /**
- * jset_clear - clear a bit in the bitset.
- * @set: bitset from jset_new
- * @index: the index to set
- *
- * Returns the old bit value (ie. false if nothing changed).
- *
- * Example:
- * if (jset_clear(set, 0))
- * err(1, "Bit 0 was already clear?!");
- */
- #define jset_clear(set, index) \
- jset_clear_(jset_raw((set), (index)), (unsigned long)(index))
- /**
- * jset_count - get population of bitset.
- * @set: bitset from jset_new
- *
- * Example:
- * // We expect 1000 entries.
- * assert(jset_count(set) == 1000);
- */
- #define jset_count(set) \
- jset_popcount_(&(set)->raw, 0, -1UL)
- /**
- * jset_popcount - get population of (some part of) bitset.
- * @set: bitset from jset_new
- * @start: first index to count
- * @end_incl: last index to count (use -1 for end).
- *
- * Example:
- * assert(jset_popcount(set, 0, 1000) <= jset_popcount(set, 0, 2000));
- */
- #define jset_popcount(set, start, end_incl) \
- jset_popcount_(jset_raw((set), (start) ? (start) : (end_incl)), \
- (unsigned long)(start), (unsigned long)(end_incl))
- /**
- * jset_nth - return the index of the nth bit which is set.
- * @set: bitset from jset_new
- * @n: which bit we are interested in (0-based)
- * @invalid: what to return if n >= set population
- *
- * This normally returns the nth bit in the set, and often there is a
- * convenient known-invalid value (ie. something which is never in the
- * set). Otherwise, and a wrapper function like this can be used:
- *
- * static bool jset_nth_index(struct jset *set,
- * unsigned long n, unsigned long *idx)
- * {
- * // Zero might be valid, if it's first in set.
- * if (n == 0 && jset_test(set, 0)) {
- * *idx = 0;
- * return true;
- * }
- * *idx = jset_nth(set, n, 0);
- * return (*idx != 0);
- * }
- *
- * Example:
- * unsigned long i, val;
- *
- * // We know 0 isn't in set.
- * assert(!jset_test(set, 0));
- * for (i = 0; (val = jset_nth(set, i, 0)) != 0; i++) {
- * assert(jset_popcount(set, 0, val) == i);
- * printf("Value %lu = %lu\n", i, val);
- * }
- */
- #define jset_nth(set, n, invalid) \
- tcon_cast((set), canary, \
- jset_nth_(jset_raw((set), (invalid)), \
- (n), (unsigned long)(invalid)))
- /**
- * jset_first - return the first bit which is set (must not contain 0).
- * @set: bitset from jset_new
- *
- * This is equivalent to jset_nth(set, 0, 0). ie. useful only if 0
- * isn't in your set.
- *
- * Example:
- * assert(!jset_test(set, 0));
- * printf("Set contents (increasing order):");
- * for (i = jset_first(set); i; i = jset_next(set, i))
- * printf(" %lu", i);
- * printf("\n");
- */
- #define jset_first(set) \
- tcon_cast((set), canary, jset_first_(&(set)->raw))
- /**
- * jset_next - return the next bit which is set (must not contain 0).
- * @set: bitset from jset_new
- * @prev: previous index
- *
- * This is usually used to find an adjacent index which is set, after
- * jset_first.
- */
- #define jset_next(set, prev) \
- tcon_cast((set), canary, jset_next_(&(set)->raw, (unsigned long)(prev)))
- /**
- * jset_last - return the last bit which is set (must not contain 0).
- * @set: bitset from jset_new
- *
- * Example:
- * assert(!jset_test(set, 0));
- * printf("Set contents (decreasing order):");
- * for (i = jset_last(set); i; i = jset_prev(set, i))
- * printf(" %lu", i);
- * printf("\n");
- */
- #define jset_last(set) \
- tcon_cast((set), canary, jset_last_(&(set)->raw))
- /**
- * jset_prev - return the previous bit which is set (must not contain 0).
- * @set: bitset from jset_new
- * @prev: previous index
- *
- * This is usually used to find an adjacent bit which is set, after
- * jset_last.
- */
- #define jset_prev(set, prev) \
- tcon_cast((set), canary, jset_prev_(&(set)->raw, (unsigned long)(prev)))
- /**
- * jset_first_clear - return the first bit which is unset
- * @set: bitset from jset_new
- *
- * This allows for iterating the inverse of the bitmap; only returns 0 if the
- * set is full.
- */
- #define jset_first_clear(set) \
- tcon_cast((set), canary, jset_next_clear_(&(set)->raw, 0))
- #define jset_next_clear(set, prev) \
- tcon_cast((set), canary, jset_next_clear_(&(set)->raw, \
- (unsigned long)(prev)))
- #define jset_last_clear(set) \
- tcon_cast((set), canary, jset_last_clear_(&(set)->raw))
- #define jset_prev_clear(set, prev) \
- tcon_cast((set), canary, jset_prev_clear_(&(set)->raw, \
- (unsigned long)(prev)))
- /* Raw functions */
- struct jset *jset_new_(size_t size);
- void jset_free_(const struct jset *set);
- const char *COLD jset_error_str_(struct jset *set);
- static inline const char *jset_error_(struct jset *set)
- {
- if (JU_ERRNO(&set->err) <= JU_ERRNO_NFMAX)
- return NULL;
- return jset_error_str_(set);
- }
- static inline bool jset_test_(const struct jset *set, unsigned long index)
- {
- return Judy1Test(set->judy, index, (JError_t *)&set->err);
- }
- static inline bool jset_set_(struct jset *set, unsigned long index)
- {
- return Judy1Set(&set->judy, index, &set->err);
- }
- static inline bool jset_clear_(struct jset *set, unsigned long index)
- {
- return Judy1Unset(&set->judy, index, &set->err);
- }
- static inline unsigned long jset_popcount_(const struct jset *set,
- unsigned long start,
- unsigned long end_incl)
- {
- return Judy1Count(set->judy, start, end_incl, (JError_t *)&set->err);
- }
- static inline unsigned long jset_nth_(const struct jset *set,
- unsigned long n, unsigned long invalid)
- {
- unsigned long index;
- if (!Judy1ByCount(set->judy, n+1, &index, (JError_t *)&set->err))
- index = invalid;
- return index;
- }
- static inline unsigned long jset_first_(const struct jset *set)
- {
- unsigned long index = 0;
- if (!Judy1First(set->judy, &index, (JError_t *)&set->err))
- index = 0;
- else
- assert(index != 0);
- return index;
- }
- static inline unsigned long jset_next_(const struct jset *set,
- unsigned long prev)
- {
- if (!Judy1Next(set->judy, &prev, (JError_t *)&set->err))
- prev = 0;
- else
- assert(prev != 0);
- return prev;
- }
- static inline unsigned long jset_last_(const struct jset *set)
- {
- unsigned long index = -1;
- if (!Judy1Last(set->judy, &index, (JError_t *)&set->err))
- index = 0;
- else
- assert(index != 0);
- return index;
- }
- static inline unsigned long jset_prev_(const struct jset *set,
- unsigned long prev)
- {
- if (!Judy1Prev(set->judy, &prev, (JError_t *)&set->err))
- prev = 0;
- else
- assert(prev != 0);
- return prev;
- }
- static inline unsigned long jset_next_clear_(const struct jset *set,
- unsigned long prev)
- {
- if (!Judy1NextEmpty(set->judy, &prev, (JError_t *)&set->err))
- prev = 0;
- else
- assert(prev != 0);
- return prev;
- }
- static inline unsigned long jset_last_clear_(const struct jset *set)
- {
- unsigned long index = -1;
- if (!Judy1LastEmpty(set->judy, &index, (JError_t *)&set->err))
- index = 0;
- return index;
- }
- static inline unsigned long jset_prev_clear_(const struct jset *set,
- unsigned long prev)
- {
- if (!Judy1PrevEmpty(set->judy, &prev, (JError_t *)&set->err))
- prev = 0;
- return prev;
- }
- #endif /* CCAN_JSET_H */
|