Add bitfield routines

Signed-hostap: Jouni Malinen <j@w1.fi>
This commit is contained in:
Jouni Malinen 2013-03-16 18:12:39 +02:00
parent 04382f7d6f
commit bdb112d35f
5 changed files with 206 additions and 0 deletions

View file

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

89
src/utils/bitfield.c Normal file
View file

@ -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
src/utils/bitfield.h Normal file
View file

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

View 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

90
tests/test-bitfield.c Normal file
View file

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