Index: share/man/man9/Makefile =================================================================== --- share/man/man9/Makefile +++ share/man/man9/Makefile @@ -623,6 +623,8 @@ bitset.9 BIT_FFS.9 \ bitset.9 BIT_FFS_AT.9 \ bitset.9 BIT_FLS.9 \ + bitset.9 BIT_FOREACH_SET.9 \ + bitset.9 BIT_FOREACH_CLR.9 \ bitset.9 BIT_COUNT.9 \ bitset.9 BIT_SUBSET.9 \ bitset.9 BIT_OVERLAP.9 \ Index: share/man/man9/bitset.9 =================================================================== --- share/man/man9/bitset.9 +++ share/man/man9/bitset.9 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd December 31, 2020 +.Dd September 20, 2021 .Dt BITSET 9 .Os .Sh NAME @@ -45,6 +45,8 @@ .Nm BIT_FFS , .Nm BIT_FFS_AT , .Nm BIT_FLS , +.Nm BIT_FOREACH_SET , +.Nm BIT_FOREACH_CLR , .Nm BIT_COUNT , .Nm BIT_SUBSET , .Nm BIT_OVERLAP , @@ -92,9 +94,10 @@ .Fn BIT_FFS_AT "const SETSIZE" "struct STRUCTNAME *bitset" "long start" .Ft long .Fn BIT_FLS "const SETSIZE" "struct STRUCTNAME *bitset" +.Fn BIT_FOREACH_SET "const SETSIZE" "int i" "const struct STRUCTNAME *bitset" +.Fn BIT_FOREACH_CLR "const SETSIZE" "int i" "const struct STRUCTNAME *bitset" .Ft long .Fn BIT_COUNT "const SETSIZE" "struct STRUCTNAME *bitset" -.\" .Ft bool .Fo BIT_SUBSET .Fa "const SETSIZE" "struct STRUCTNAME *haystack" "struct STRUCTNAME *needle" @@ -329,6 +332,25 @@ macro, you must subtract one from the result. .Pp The +.Fn BIT_FOREACH_SET +macro can be used to iterate over all set bits in +.Fa bitset . +The index variable +.Fa i +must have been declared with type +.Ft int , +and upon each iteration +.Fa i +is set to the index of successive set bits. +The value of +.Fa i +after the loop terminates is undefined. +Similarly, +.Fn BIT_FOREACH_CLR +iterates over all clear bits in +.Fa bitset . +.Pp +The .Fn BIT_COUNT macro returns the total number of set bits in .Fa bitset . Index: sys/sys/bitset.h =================================================================== --- sys/sys/bitset.h +++ sys/sys/bitset.h @@ -271,6 +271,16 @@ __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_SET(_s, i, p) _BIT_FOREACH(_s, i, p, ) +#define BIT_FOREACH_CLR(_s, i, p) _BIT_FOREACH(_s, i, p, ~) + #define BITSET_T_INITIALIZER(x) \ { .__bits = { x } }