bitset: Reimplement BIT_FOREACH_IS(SET|CLR)

Eliminate the nested loops and re-implement following a suggestion from
rlibby.

Add some simple regression tests.

Reviewed by:	rlibby, kib
MFC after:	2 weeks
Sponsored by:	The FreeBSD Foundation
Differential Revision:	https://reviews.freebsd.org/D32472
This commit is contained in:
Mark Johnston 2021-10-16 09:38:26 -04:00 committed by Sebastian Huber
parent 96ddb4055e
commit 27e8401c46
1 changed files with 25 additions and 6 deletions

View File

@ -274,12 +274,31 @@
__count; \
})
/* Non-destructively loop over all set or clear bits in the set. */
#define _BIT_FOREACH(_s, i, p, op) \
for (__size_t __i = 0; __i < __bitset_words(_s); __i++) \
for (long __j = op((p)->__bits[__i]), __b = ffsl(__j); \
(i = (__b - 1) + __i * _BITSET_BITS), __j != 0; \
__j &= ~(1l << i), __b = ffsl(__j))
#define _BIT_FOREACH_ADVANCE(_s, i, p, op) __extension__ ({ \
int __found; \
for (;;) { \
if (__bits != 0) { \
int __bit = ffsl(__bits) - 1; \
__bits &= ~(1ul << __bit); \
(i) = __i * _BITSET_BITS + __bit; \
__found = 1; \
break; \
} \
if (++__i == __bitset_words(_s)) { \
__found = 0; \
break; \
} \
__bits = op((p)->__bits[__i]); \
} \
__found != 0; \
})
/*
* Non-destructively loop over all set or clear bits in the set.
*/
#define _BIT_FOREACH(_s, i, p, op) \
for (long __i = -1, __bits = 0; \
_BIT_FOREACH_ADVANCE(_s, i, p, op); )
#define BIT_FOREACH_ISSET(_s, i, p) _BIT_FOREACH(_s, i, p, )
#define BIT_FOREACH_ISCLR(_s, i, p) _BIT_FOREACH(_s, i, p, ~)