Parcourir la source

Add bitfield routines

Signed-hostap: Jouni Malinen <j@w1.fi>
Jouni Malinen il y a 12 ans
Parent
commit
bdb112d35f
5 fichiers modifiés avec 206 ajouts et 0 suppressions
  1. 1 0
      src/utils/Makefile
  2. 89 0
      src/utils/bitfield.c
  3. 21 0
      src/utils/bitfield.h
  4. 5 0
      tests/Makefile
  5. 90 0
      tests/test-bitfield.c

+ 1 - 0
src/utils/Makefile

@@ -14,6 +14,7 @@ CFLAGS += -DCONFIG_IPV6
 
 LIB_OBJS= \
 	base64.o \
+	bitfield.o \
 	common.o \
 	ip_addr.o \
 	radiotap.o \

+ 89 - 0
src/utils/bitfield.c

@@ -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;
+}

+ 21 - 0
src/utils/bitfield.h

@@ -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 */

+ 5 - 0
tests/Makefile

@@ -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

+ 90 - 0
tests/test-bitfield.c

@@ -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;
+}