diff options
author | Jason Ekstrand <[email protected]> | 2015-08-15 09:30:40 -0700 |
---|---|---|
committer | Jason Ekstrand <[email protected]> | 2015-08-18 17:48:28 -0700 |
commit | 7c8e53f1bee370c1a8a0c640313c12df220f4114 (patch) | |
tree | 386ce26b61fa0f007896bf740540bd423d185a4a /src | |
parent | 6ff3341fc77c8e22a62505eb374938db3c95144f (diff) |
util/bitset: Add a BITSET_FOREACH_SET macro
Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/util/bitset.h | 36 |
1 files changed, 36 insertions, 0 deletions
diff --git a/src/util/bitset.h b/src/util/bitset.h index febcddefd97..c452819414f 100644 --- a/src/util/bitset.h +++ b/src/util/bitset.h @@ -96,4 +96,40 @@ __bitset_ffs(const BITSET_WORD *x, int n) #define BITSET_FFS(x) __bitset_ffs(x, ARRAY_SIZE(x)) +static inline unsigned +__bitset_next_set(unsigned i, BITSET_WORD *tmp, + BITSET_WORD *set, unsigned size) +{ + unsigned bit, word; + + /* NOTE: The initial conditions for this function are very specific. At + * the start of the loop, the tmp variable must be set to *set and the + * initial i value set to 0. This way, if there is a bit set in the first + * word, we ignore the i-value and just grab that bit (so 0 is ok, even + * though 0 may be returned). If the first word is 0, then the value of + * `word` will be 0 and we will go on to look at the second word. + */ + word = BITSET_BITWORD(i); + while (*tmp == 0) { + word++; + + if (word >= BITSET_WORDS(size)) + return size; + + *tmp = set[word]; + } + + /* Find the next set bit in the non-zero word */ + bit = ffs(*tmp) - 1; + + /* Unset the bit */ + *tmp &= ~(1ull << bit); + + return word * BITSET_WORDBITS + bit; +} + +#define BITSET_FOREACH_SET(__i, __tmp, __set, __size) \ + for (__tmp = *(__set), __i = 0; \ + (__i = __bitset_next_set(__i, &__tmp, __set, __size)) < __size;) + #endif |