summaryrefslogtreecommitdiffstats
path: root/src/util/bitset.h
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-08-15 09:30:40 -0700
committerJason Ekstrand <[email protected]>2015-08-18 17:48:28 -0700
commit7c8e53f1bee370c1a8a0c640313c12df220f4114 (patch)
tree386ce26b61fa0f007896bf740540bd423d185a4a /src/util/bitset.h
parent6ff3341fc77c8e22a62505eb374938db3c95144f (diff)
util/bitset: Add a BITSET_FOREACH_SET macro
Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/util/bitset.h')
-rw-r--r--src/util/bitset.h36
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