1e5b75505Sopenharmony_ci/*
2e5b75505Sopenharmony_ci * Bitfield
3e5b75505Sopenharmony_ci * Copyright (c) 2013, Jouni Malinen <j@w1.fi>
4e5b75505Sopenharmony_ci *
5e5b75505Sopenharmony_ci * This software may be distributed under the terms of the BSD license.
6e5b75505Sopenharmony_ci * See README for more details.
7e5b75505Sopenharmony_ci */
8e5b75505Sopenharmony_ci
9e5b75505Sopenharmony_ci#include "includes.h"
10e5b75505Sopenharmony_ci
11e5b75505Sopenharmony_ci#include "common.h"
12e5b75505Sopenharmony_ci#include "bitfield.h"
13e5b75505Sopenharmony_ci
14e5b75505Sopenharmony_ci
15e5b75505Sopenharmony_cistruct bitfield {
16e5b75505Sopenharmony_ci	u8 *bits;
17e5b75505Sopenharmony_ci	size_t max_bits;
18e5b75505Sopenharmony_ci};
19e5b75505Sopenharmony_ci
20e5b75505Sopenharmony_ci
21e5b75505Sopenharmony_cistruct bitfield * bitfield_alloc(size_t max_bits)
22e5b75505Sopenharmony_ci{
23e5b75505Sopenharmony_ci	struct bitfield *bf;
24e5b75505Sopenharmony_ci
25e5b75505Sopenharmony_ci	bf = os_zalloc(sizeof(*bf) + (max_bits + 7) / 8);
26e5b75505Sopenharmony_ci	if (bf == NULL)
27e5b75505Sopenharmony_ci		return NULL;
28e5b75505Sopenharmony_ci	bf->bits = (u8 *) (bf + 1);
29e5b75505Sopenharmony_ci	bf->max_bits = max_bits;
30e5b75505Sopenharmony_ci	return bf;
31e5b75505Sopenharmony_ci}
32e5b75505Sopenharmony_ci
33e5b75505Sopenharmony_ci
34e5b75505Sopenharmony_civoid bitfield_free(struct bitfield *bf)
35e5b75505Sopenharmony_ci{
36e5b75505Sopenharmony_ci	os_free(bf);
37e5b75505Sopenharmony_ci}
38e5b75505Sopenharmony_ci
39e5b75505Sopenharmony_ci
40e5b75505Sopenharmony_civoid bitfield_set(struct bitfield *bf, size_t bit)
41e5b75505Sopenharmony_ci{
42e5b75505Sopenharmony_ci	if (bit >= bf->max_bits)
43e5b75505Sopenharmony_ci		return;
44e5b75505Sopenharmony_ci	bf->bits[bit / 8] |= BIT(bit % 8);
45e5b75505Sopenharmony_ci}
46e5b75505Sopenharmony_ci
47e5b75505Sopenharmony_ci
48e5b75505Sopenharmony_civoid bitfield_clear(struct bitfield *bf, size_t bit)
49e5b75505Sopenharmony_ci{
50e5b75505Sopenharmony_ci	if (bit >= bf->max_bits)
51e5b75505Sopenharmony_ci		return;
52e5b75505Sopenharmony_ci	bf->bits[bit / 8] &= ~BIT(bit % 8);
53e5b75505Sopenharmony_ci}
54e5b75505Sopenharmony_ci
55e5b75505Sopenharmony_ci
56e5b75505Sopenharmony_ciint bitfield_is_set(struct bitfield *bf, size_t bit)
57e5b75505Sopenharmony_ci{
58e5b75505Sopenharmony_ci	if (bit >= bf->max_bits)
59e5b75505Sopenharmony_ci		return 0;
60e5b75505Sopenharmony_ci	return !!(bf->bits[bit / 8] & BIT(bit % 8));
61e5b75505Sopenharmony_ci}
62e5b75505Sopenharmony_ci
63e5b75505Sopenharmony_ci
64e5b75505Sopenharmony_cistatic int first_zero(u8 val)
65e5b75505Sopenharmony_ci{
66e5b75505Sopenharmony_ci	int i;
67e5b75505Sopenharmony_ci	for (i = 0; i < 8; i++) {
68e5b75505Sopenharmony_ci		if (!(val & 0x01))
69e5b75505Sopenharmony_ci			return i;
70e5b75505Sopenharmony_ci		val >>= 1;
71e5b75505Sopenharmony_ci	}
72e5b75505Sopenharmony_ci	return -1;
73e5b75505Sopenharmony_ci}
74e5b75505Sopenharmony_ci
75e5b75505Sopenharmony_ci
76e5b75505Sopenharmony_ciint bitfield_get_first_zero(struct bitfield *bf)
77e5b75505Sopenharmony_ci{
78e5b75505Sopenharmony_ci	size_t i;
79e5b75505Sopenharmony_ci	for (i = 0; i < (bf->max_bits + 7) / 8; i++) {
80e5b75505Sopenharmony_ci		if (bf->bits[i] != 0xff)
81e5b75505Sopenharmony_ci			break;
82e5b75505Sopenharmony_ci	}
83e5b75505Sopenharmony_ci	if (i == (bf->max_bits + 7) / 8)
84e5b75505Sopenharmony_ci		return -1;
85e5b75505Sopenharmony_ci	i = i * 8 + first_zero(bf->bits[i]);
86e5b75505Sopenharmony_ci	if (i >= bf->max_bits)
87e5b75505Sopenharmony_ci		return -1;
88e5b75505Sopenharmony_ci	return i;
89e5b75505Sopenharmony_ci}
90