1#include <stdlib.h>
2#include <stdio.h>
3#include <stdbool.h>
4#include <string.h>
5#include <assert.h>
6#include <errors/errno.h>
7
8#include "bitfield.h"
9
10static inline uint8_t* get_offset(struct bitfield* b, size_t bit_number)
11{
12	assert(bit_number < BITFIELD_MAX);
13	uint8_t char_offset = bit_number / BITS_PER_CHAR;
14
15	return b->field + char_offset;
16}
17
18/**
19 * \brief Turns on a bit in the bit field.
20 *
21 * \param bitfield Pointer to the bit field
22 * \param bit_number Which bit to set
23 */
24void bitfield_on(struct bitfield* b, size_t bit_number)
25{
26	uint8_t* bitmask = get_offset(b, bit_number);
27	uint8_t bit_offset = bit_number % BITS_PER_CHAR;
28	*bitmask |= 1 << bit_offset;
29}
30
31
32/**
33 * \brief Turns off a bit in the bit field.
34 *
35 * \param bitfield Pointer to bitfield
36 * \param bit_number Which bit to unset
37 */
38void bitfield_off(struct bitfield* b, size_t bit_number)
39{
40	uint8_t* bitmask = get_offset(b, bit_number);
41	uint8_t bit_offset = bit_number % BITS_PER_CHAR;
42	*bitmask &= ~(1 << bit_offset);
43}
44
45/**
46 * \brief Gets the high/low of a specific bit in a bit field.
47 *
48 * \return value of the bit
49 */
50bool bitfield_get(struct bitfield* b, size_t bit_number)
51{
52	uint8_t* bitmask = get_offset(b, bit_number);
53	uint8_t bit_offset = bit_number % BITS_PER_CHAR;
54	return (*bitmask & (1 << bit_offset)) > 0;
55}
56
57static uint8_t compute_union(size_t index, struct bitfield** fields, size_t field_count)
58{
59	//printf("compute union at index: %lu\n", index);
60	uint8_t u = 0;
61	for (size_t i=0; i < field_count; i++) {
62		u |= fields[i]->field[index];
63	}
64
65	return u;
66}
67
68/**
69 * \brief Computes union for a given number of bitfields.
70 *
71 * TODO: This functions could be improved a lot by using
72 * word size instead of uint8.
73 *
74 * \param fields Array of pointers to bitfields
75 * \param field_count Number of bitfields
76 * \param last -1 to indicate a new run, last returned result otherwise.
77 */
78int32_t bitfield_union(struct bitfield** fields, size_t field_count, int32_t last)
79{
80	static uint8_t field_union;
81	static size_t current = 0;
82	if (last == -1) {
83		field_union = 0;
84		current = 0;
85	}
86
87	// Scan over whole bitfield
88	while(current < BITFIELD_MAX) {
89
90		// Compute union for next character
91		if (current % BITS_PER_CHAR == 0) {
92			field_union = compute_union(current/BITS_PER_CHAR, fields, field_count);
93		}
94
95		// Walk through character, output all the bits we find
96		for(size_t idx = (current % BITS_PER_CHAR); idx < BITS_PER_CHAR; idx++) {
97			//printf("bit: %lu is %d\n", idx, (field_union & (1 << idx)));
98			if ( (field_union & (1 << idx)) > 0) {
99				return current++;
100			}
101			else {
102				current++;
103			}
104		}
105	}
106
107	return -1;
108}
109
110/**
111 * \brief Prints the current bitfield up to
112 * a given number of bits.
113 *
114 * \param first where to start printing in the bitfield
115 * \param number_of_bits #bits printed beginning from first
116 */
117void print_bitfield(struct bitfield* b, size_t first, size_t number_of_bits) {
118	printf("Printing Bitfield from %zu to %zu:\n", first, first+number_of_bits-1);
119
120	for(size_t i=0; i<number_of_bits; i++) {
121		printf("%d", bitfield_get(b, first+i));
122		if((i+1) % 10 == 0)
123			printf("\n");
124	}
125}
126
127
128errval_t bitfield_create(struct bitfield** b)
129{
130	*b = calloc(1, sizeof(struct bitfield));
131	if (*b == NULL) {
132		return LIB_ERR_MALLOC_FAIL;
133	}
134
135	return SYS_ERR_OK;
136}
137
138
139#ifdef TEST_BITFIELD
140int main(int argc, char** argv)
141{
142	struct bitfield* b = malloc(sizeof(struct bitfield));
143	memset(b, 0, sizeof(struct bitfield));
144
145	*(uint64_t*)b->field = 0xffff;
146	struct bitfield* b2 = malloc(sizeof(struct bitfield));
147	memset(b2, 0, sizeof(struct bitfield));
148	*(uint64_t*)b2->field = 0xFFffffff0000;
149
150	struct bitfield* fields[2] = {b, b2};
151	size_t next = -1;
152	while( (next = bitfield_union(fields, 2, next)) != -1) {
153		printf("union found next: %lu\n", next);
154	}
155
156	//printf("before print\n");
157	//print_bitfield(b, 0, 1256);
158	//printf("\ndone.\n");
159
160	return 0;
161}
162#endif
163