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