[RFC v2 15/99] utils: Add few more functions to bitfield module
Andrei Otcheretianski
andrei.otcheretianski at intel.com
Tue Dec 23 03:51:19 PST 2025
From: Ilan Peer <ilan.peer at intel.com>
These would be used by the NAN logic.
Signed-off-by: Ilan Peer <ilan.peer at intel.com>
---
src/utils/bitfield.c | 158 +++++++++++++++++++++++++++++++++
src/utils/bitfield.h | 12 +++
src/utils/utils_module_tests.c | 75 +++++++++++++++-
3 files changed, 244 insertions(+), 1 deletion(-)
diff --git a/src/utils/bitfield.c b/src/utils/bitfield.c
index 8dcec3907e..d10936070a 100644
--- a/src/utils/bitfield.c
+++ b/src/utils/bitfield.c
@@ -87,3 +87,161 @@ int bitfield_get_first_zero(struct bitfield *bf)
return -1;
return i;
}
+
+
+struct bitfield * bitfield_alloc_data(const u8 *data, size_t len)
+{
+ struct bitfield *bf;
+
+ bf = os_zalloc(sizeof(*bf) + len);
+ if (!bf)
+ return NULL;
+
+ bf->bits = (u8 *)(bf + 1);
+ os_memcpy(bf->bits, data, len);
+
+ bf->max_bits = len * 8;
+ return bf;
+}
+
+
+struct bitfield * bitfield_dup(const struct bitfield *orig)
+{
+ struct bitfield *bf;
+
+ if (!orig)
+ return NULL;
+
+ bf = os_memdup(orig,
+ sizeof(*orig) + (orig->max_bits + 7) / 8);
+ if (!bf)
+ return NULL;
+
+ bf->bits = (u8 *)(bf + 1);
+
+ return bf;
+}
+
+
+int bitfield_union_in_place(struct bitfield *a, const struct bitfield *b)
+{
+ size_t i, upper;
+
+ if (!a || !b || a->max_bits < b->max_bits)
+ return -1;
+
+ upper = (b->max_bits + 7) / 8;
+
+ for (i = 0 ; i < upper; i++)
+ a->bits[i] |= b->bits[i];
+
+ return 0;
+}
+
+
+struct bitfield * bitfield_union(const struct bitfield *a,
+ const struct bitfield *b)
+{
+ struct bitfield *res;
+ int ret;
+
+ if (!a || !b)
+ return NULL;
+
+ if (a->max_bits > b->max_bits) {
+ res = bitfield_dup(a);
+ ret = bitfield_union_in_place(res, b);
+ } else {
+ res = bitfield_dup(b);
+ ret = bitfield_union_in_place(res, a);
+ }
+
+ if (!ret)
+ return res;
+
+ os_free(res);
+ return NULL;
+}
+
+
+int bitfield_intersect_in_place(struct bitfield *a,
+ const struct bitfield *b)
+{
+ size_t i, upper;
+
+ if (!a || !b)
+ return -1;
+
+ if (a->max_bits < b->max_bits)
+ upper = (a->max_bits + 7) / 8;
+ else
+ upper = (b->max_bits + 7) / 8;
+
+
+ for (i = 0 ; i < upper; i++)
+ a->bits[i] &= b->bits[i];
+
+ upper = (a->max_bits + 7) / 8;
+ for (; i < upper; i++)
+ a->bits[i] = 0;
+
+ return 0;
+}
+
+
+int bitfield_is_subset(const struct bitfield *a, struct bitfield *b)
+{
+ size_t i, upper;
+
+ if (!a || !b)
+ return -1;
+
+ if (a->max_bits < b->max_bits)
+ return 0;
+
+ upper = (b->max_bits + 7) / 8;
+
+ for (i = 0; i < upper; i++) {
+ u8 res = a->bits[i] & b->bits[i];
+
+ if (res != b->bits[i])
+ return 0;
+ }
+
+ return 1;
+}
+
+
+size_t bitfield_size(const struct bitfield *bf)
+{
+ if (!bf)
+ return 0;
+ return bf->max_bits;
+}
+
+
+int bitfield_intersects(const struct bitfield *a, const struct bitfield *b)
+{
+ size_t i, upper;
+
+ if (!a || !b)
+ return -1;
+
+ if (a->max_bits < b->max_bits)
+ upper = (a->max_bits + 7) / 8;
+ else
+ upper = (b->max_bits + 7) / 8;
+
+ for (i = 0; i < upper; i++)
+ if (a->bits[i] & b->bits[i])
+ return 1;
+
+ return 0;
+}
+
+
+void bitfield_dump(struct bitfield *bf, const char *title)
+{
+ wpa_printf(MSG_DEBUG, "bitfield: %s: max_bits=%zu", title, bf->max_bits);
+ wpa_hexdump(MSG_DEBUG, "bits: ", bf->bits, bf->max_bits / 8);
+}
diff --git a/src/utils/bitfield.h b/src/utils/bitfield.h
index 7050a208c8..5b805773d2 100644
--- a/src/utils/bitfield.h
+++ b/src/utils/bitfield.h
@@ -9,6 +9,8 @@
#ifndef BITFIELD_H
#define BITFIELD_H
+#include "utils/common.h"
+
struct bitfield;
struct bitfield * bitfield_alloc(size_t max_bits);
@@ -18,4 +20,14 @@ void bitfield_clear(struct bitfield *bf, size_t bit);
int bitfield_is_set(struct bitfield *bf, size_t bit);
int bitfield_get_first_zero(struct bitfield *bf);
+struct bitfield * bitfield_alloc_data(const u8 *data, size_t len);
+struct bitfield * bitfield_dup(const struct bitfield *orig);
+int bitfield_union_in_place(struct bitfield *a, const struct bitfield *b);
+struct bitfield * bitfield_union(const struct bitfield *a,
+ const struct bitfield *b);
+int bitfield_intersect_in_place(struct bitfield *a, const struct bitfield *b);
+int bitfield_is_subset(const struct bitfield *a, struct bitfield *b);
+size_t bitfield_size(const struct bitfield *bf);
+int bitfield_intersects(const struct bitfield *a, const struct bitfield *b);
+void bitfield_dump(struct bitfield *bf, const char *title);
#endif /* BITFIELD_H */
diff --git a/src/utils/utils_module_tests.c b/src/utils/utils_module_tests.c
index 365f21fb11..58343f86d7 100644
--- a/src/utils/utils_module_tests.c
+++ b/src/utils/utils_module_tests.c
@@ -127,10 +127,13 @@ static int printf_encode_decode_tests(void)
static int bitfield_tests(void)
{
- struct bitfield *bf;
+ struct bitfield *bf, *bf_a = NULL, *bf_b = NULL, *bf_c = NULL;
int i;
int errors = 0;
+ u8 data_a[4] = {0xff, 0x3f, 0x01, 0xf0};
+ u8 data_b[4] = {0xff, 0xc0, 0xfe, 0x0f};
+
wpa_printf(MSG_INFO, "bitfield tests");
bf = bitfield_alloc(123);
@@ -210,6 +213,76 @@ static int bitfield_tests(void)
errors++;
bitfield_free(bf);
+ bf_a = bitfield_alloc_data(data_a, sizeof(data_a));
+ if (!bf_a)
+ goto fail;
+
+ bf_b = bitfield_alloc_data(data_b, sizeof(data_b));
+ if (!bf_b)
+ goto fail;
+
+ bf_c = bitfield_dup(bf_a);
+ if (!bf_c)
+ goto fail;
+
+ /* test intersection */
+ if (bitfield_intersect_in_place(bf_c, bf_b))
+ goto fail;
+
+ for (i = 0; i < 8; i++)
+ if (!bitfield_is_set(bf_c, i))
+ goto fail;
+
+ for (; i < 32; i++)
+ if (bitfield_is_set(bf_c, i))
+ goto fail;
+
+ bitfield_free(bf_c);
+
+ /* test union */
+ bf_c = bitfield_union(bf_a, bf_b);
+ if (!bf_c)
+ goto fail;
+
+ if (!bitfield_intersects(bf_a, bf_c) ||
+ !bitfield_intersects(bf_b, bf_c) ||
+ !bitfield_intersects(bf_c, bf_a) ||
+ !bitfield_intersects(bf_c, bf_b) ||
+ !bitfield_intersects(bf_a, bf_b))
+ goto fail;
+
+ for (i = 0; i < 32; i++)
+ if (!bitfield_is_set(bf_c, i))
+ goto fail;
+
+ if (!bitfield_is_subset(bf_c, bf_a) ||
+ !bitfield_is_subset(bf_c, bf_b) ||
+ bitfield_is_subset(bf_a, bf_c) ||
+ bitfield_is_subset(bf_b, bf_c) ||
+ bitfield_is_subset(bf_a, bf_b))
+ goto fail;
+
+ /* test in place union */
+ if (bitfield_union_in_place(bf_a, bf_b))
+ goto fail;
+
+ if (bitfield_size(bf_a) != 32 ||
+ bitfield_size(bf_b) != 32 ||
+ bitfield_size(bf_c) != 32)
+ goto fail;
+
+ for (i = 0; i < 32; i++)
+ if (!bitfield_is_set(bf_c, i))
+ goto fail;
+ goto out;
+
+fail:
+ errors++;
+out:
+ bitfield_free(bf_a);
+ bitfield_free(bf_c);
+ bitfield_free(bf_b);
+
if (errors) {
wpa_printf(MSG_ERROR, "%d bitfield test(s) failed", errors);
return -1;
--
2.49.0
More information about the Hostap
mailing list