]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Add bitfield routines
authorJouni Malinen <j@w1.fi>
Sat, 16 Mar 2013 16:12:39 +0000 (18:12 +0200)
committerJouni Malinen <j@w1.fi>
Sat, 27 Apr 2013 19:16:40 +0000 (22:16 +0300)
Signed-hostap: Jouni Malinen <j@w1.fi>

src/utils/Makefile
src/utils/bitfield.c [new file with mode: 0644]
src/utils/bitfield.h [new file with mode: 0644]
tests/Makefile
tests/test-bitfield.c [new file with mode: 0644]

index 0f1f191099953f7f80f16c70518d6725595c57a8..940b4d8f1c57e12f360b24e3ccf6658f0edb78a1 100644 (file)
@@ -14,6 +14,7 @@ CFLAGS += -DCONFIG_IPV6
 
 LIB_OBJS= \
        base64.o \
+       bitfield.o \
        common.o \
        ip_addr.o \
        radiotap.o \
diff --git a/src/utils/bitfield.c b/src/utils/bitfield.c
new file mode 100644 (file)
index 0000000..f90e4be
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "includes.h"
+
+#include "common.h"
+#include "bitfield.h"
+
+
+struct bitfield {
+       u8 *bits;
+       size_t max_bits;
+};
+
+
+struct bitfield * bitfield_alloc(size_t max_bits)
+{
+       struct bitfield *bf;
+
+       bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
+       if (bf == NULL)
+               return NULL;
+       bf->bits = (u8 *) (bf + 1);
+       bf->max_bits = max_bits;
+       return bf;
+}
+
+
+void bitfield_free(struct bitfield *bf)
+{
+       os_free(bf);
+}
+
+
+void bitfield_set(struct bitfield *bf, size_t bit)
+{
+       if (bit >= bf->max_bits)
+               return;
+       bf->bits[bit / 8] |= BIT(bit % 8);
+}
+
+
+void bitfield_clear(struct bitfield *bf, size_t bit)
+{
+       if (bit >= bf->max_bits)
+               return;
+       bf->bits[bit / 8] &= ~BIT(bit % 8);
+}
+
+
+int bitfield_is_set(struct bitfield *bf, size_t bit)
+{
+       if (bit >= bf->max_bits)
+               return 0;
+       return !!(bf->bits[bit / 8] & BIT(bit % 8));
+}
+
+
+static int first_zero(u8 val)
+{
+       int i;
+       for (i = 0; i < 8; i++) {
+               if (!(val & 0x01))
+                       return i;
+               val >>= 1;
+       }
+       return -1;
+}
+
+
+int bitfield_get_first_zero(struct bitfield *bf)
+{
+       size_t i;
+       for (i = 0; i <= (bf->max_bits + 7) / 8; i++) {
+               if (bf->bits[i] != 0xff)
+                       break;
+       }
+       if (i > (bf->max_bits + 7) / 8)
+               return -1;
+       i = i * 8 + first_zero(bf->bits[i]);
+       if (i >= bf->max_bits)
+               return -1;
+       return i;
+}
diff --git a/src/utils/bitfield.h b/src/utils/bitfield.h
new file mode 100644 (file)
index 0000000..7050a20
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * Bitfield
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#ifndef BITFIELD_H
+#define BITFIELD_H
+
+struct bitfield;
+
+struct bitfield * bitfield_alloc(size_t max_bits);
+void bitfield_free(struct bitfield *bf);
+void bitfield_set(struct bitfield *bf, size_t bit);
+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);
+
+#endif /* BITFIELD_H */
index cccc3dcb032f0144e2427ddc6588ecee8418a33c..80341a11147db6470a8eda4ac1b7726ed417bbeb 100644 (file)
@@ -1,4 +1,5 @@
 TESTS=test-base64 test-md4 test-md5 test-milenage test-ms_funcs \
+       test-bitfield \
        test-printf \
        test-sha1 \
        test-sha256 test-aes test-asn1 test-x509 test-x509v3 test-list test-rc4
@@ -47,6 +48,9 @@ test-asn1: test-asn1.o $(LIBS)
 test-base64: test-base64.o $(LIBS)
        $(LDO) $(LDFLAGS) -o $@ $^
 
+test-bitfield: test-bitfield.o $(LIBS)
+       $(LDO) $(LDFLAGS) -o $@ $^
+
 test-https: test-https.o $(LIBS)
        $(LDO) $(LDFLAGS) -o $@ $< $(LLIBS)
 
@@ -86,6 +90,7 @@ test-x509v3: test-x509v3.o $(LIBS)
 
 run-tests: $(TESTS)
        ./test-aes
+       ./test-bitfield
        ./test-list
        ./test-md4
        ./test-md5
diff --git a/tests/test-bitfield.c b/tests/test-bitfield.c
new file mode 100644 (file)
index 0000000..aff1790
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * bitfield unit tests
+ * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "utils/includes.h"
+#include "utils/bitfield.h"
+
+int main(int argc, char *argv[])
+{
+       struct bitfield *bf;
+       int i;
+       int errors = 0;
+
+       bf = bitfield_alloc(123);
+       if (bf == NULL)
+               return -1;
+
+       for (i = 0; i < 123; i++) {
+               if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
+                       errors++;
+               if (i > 0 && bitfield_is_set(bf, i - 1))
+                       errors++;
+               bitfield_set(bf, i);
+               if (!bitfield_is_set(bf, i))
+                       errors++;
+               bitfield_clear(bf, i);
+               if (bitfield_is_set(bf, i))
+                       errors++;
+       }
+
+       for (i = 123; i < 200; i++) {
+               if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
+                       errors++;
+               if (i > 0 && bitfield_is_set(bf, i - 1))
+                       errors++;
+               bitfield_set(bf, i);
+               if (bitfield_is_set(bf, i))
+                       errors++;
+               bitfield_clear(bf, i);
+               if (bitfield_is_set(bf, i))
+                       errors++;
+       }
+
+       for (i = 0; i < 123; i++) {
+               if (bitfield_is_set(bf, i) || bitfield_is_set(bf, i + 1))
+                       errors++;
+               bitfield_set(bf, i);
+               if (!bitfield_is_set(bf, i))
+                       errors++;
+       }
+
+       for (i = 0; i < 123; i++) {
+               if (!bitfield_is_set(bf, i))
+                       errors++;
+               bitfield_clear(bf, i);
+               if (bitfield_is_set(bf, i))
+                       errors++;
+       }
+
+       for (i = 0; i < 123; i++) {
+               if (bitfield_get_first_zero(bf) != i)
+                       errors++;
+               bitfield_set(bf, i);
+       }
+       if (bitfield_get_first_zero(bf) != -1)
+               errors++;
+       for (i = 0; i < 123; i++) {
+               if (!bitfield_is_set(bf, i))
+                       errors++;
+               bitfield_clear(bf, i);
+               if (bitfield_get_first_zero(bf) != i)
+                       errors++;
+               bitfield_set(bf, i);
+       }
+       if (bitfield_get_first_zero(bf) != -1)
+               errors++;
+
+       bitfield_free(bf);
+
+       if (errors) {
+               printf("%d test(s) failed\n", errors);
+               return -1;
+       }
+
+       return 0;
+}