1%% options 2 3copyright owner = Dirk Krause 4copyright year = 2015-xxxx 5SPDX-License-Identifier: BSD-3-Clause 6 7 8 9%% header 10 11/** @file dk4bf.h Bit fields. 12*/ 13 14#ifndef DK4CONF_H_INCLUDED 15#if DK4_BUILDING_DKTOOLS4 16#include "dk4conf.h" 17#else 18#include <dktools-4/dk4conf.h> 19#endif 20#endif 21 22#ifndef DK4ERROR_H_INCLUDED 23#if DK4_BUILDING_DKTOOLS4 24#include <libdk4base/dk4error.h> 25#else 26#include <dktools-4/dk4error.h> 27#endif 28#endif 29 30 31/** Bit field structure. 32*/ 33typedef struct { 34 unsigned char *d; /**< Data buffer. */ 35 size_t s; /**< Number of bits in the array. */ 36} dk4_bit_field_t; 37 38#ifdef __cplusplus 39extern "C" { 40#endif 41 42/** Open bit field. 43 @param sz Size of the bit field (number of bits). 44 @param erp Error report, may be NULL. 45 @return Pointer to new bit field on success, NULL on error. 46 47 Error codes: 48 - DK4_E_INVALID_ARGUMENTS<br> 49 if sz is 0, 50 - DK4_E_MEMORY_ALLOCATION_FAILED<br> 51 if not enough memory was available. 52*/ 53dk4_bit_field_t * 54 55dk4bf_open(size_t sz, dk4_er_t *erp); 56 57/** Set one bit in a bit field. 58 @param dptr Bit field. 59 @param bitno Index of bit to modify. 60 @param val Bit value. 61 @param erp Error report, may be NULL. 62 @return 1 on success, 0 on error. 63 64 Error codes: 65 - DK4_E_INVALID_ARGUMENTS<br> 66 if dptr is 0 or bitno is outside the bit field size. 67*/ 68int 69 70dk4bf_set(dk4_bit_field_t *dptr, size_t bitno, int val, dk4_er_t *erp); 71 72/** Retrieve one value from bit field. 73 @param dptr Address of result variable. 74 @param bfptr Bit field. 75 @param bitno Number of bit to obtain. 76 @param erp Error report, may be NULL. 77 @return 1 on success (dptr set), 0 on error (dptr unchanged). 78 79 Error codes: 80 - DK4_E_INVALID_ARGUMENTS<br> 81 if dptr or bfptr is NULL or bitno is outside the bit field size. 82*/ 83int 84 85dk4bf_get(int *dptr, dk4_bit_field_t const *bfptr, size_t bitno, dk4_er_t *erp); 86 87/** Close bit field. 88 @param ptr Pointer to bit field previously opened using 89 dk4bf_open(). 90*/ 91void 92 93dk4bf_close(dk4_bit_field_t *ptr); 94 95#ifdef __cplusplus 96} 97#endif 98 99 100 101%% module 102 103#include "dk4conf.h" 104 105#if DK4_HAVE_ASSERT_H 106#ifndef ASSERT_H_INCLUDED 107#include <assert.h> 108#define ASSERT_H_INCLUDED 1 109#endif 110#endif 111 112#include <libdk4c/dk4bf.h> 113#include <libdk4base/dk4mem.h> 114 115 116 117$!trace-include 118 119 120 121/** Position of single bits within a byte. 122*/ 123static const unsigned char dk4bf_bits_in_byte[] = { 124 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 125}; 126 127 128 129dk4_bit_field_t * 130 131dk4bf_open(size_t sz, dk4_er_t *erp) 132{ 133 dk4_bit_field_t *back = NULL; 134 size_t bsz; 135#if DK4_USE_ASSERT 136 assert(0 < sz); 137#endif 138 if (0 < sz) { 139 back = dk4mem_new(dk4_bit_field_t,1,erp); 140 if (NULL != back) { 141 back->s = sz; 142 bsz = sz / 8; 143 if (0 != (sz % 8)) { 144 bsz++; 145 } 146 back->d = dk4mem_new(unsigned char,bsz,erp); 147 if (NULL == back->d) { 148 dk4bf_close(back); 149 back = NULL; 150 } 151 } 152 } else { 153 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 154 } 155 return back; 156} 157 158 159 160int 161 162dk4bf_set(dk4_bit_field_t *dptr, size_t bitno, int val, dk4_er_t *erp) 163{ 164 size_t bytei; /* Byte index */ 165 size_t biti; /* Bit index */ 166 int back = 0; 167#if DK4_USE_ASSERT 168 assert(NULL != dptr); 169#endif 170 if (NULL != dptr) { 171 if (bitno < dptr->s) { 172 bytei = bitno / 8; 173 biti = bitno % 8; 174 if (0 != val) { 175 (dptr->d)[bytei] |= dk4bf_bits_in_byte[biti]; 176 } else { 177#if VERSION_BEFORE_20210729 178 (dptr->d)[bytei] &= (~(dk4bf_bits_in_byte[biti])); 179#else 180 (dptr->d)[bytei] = (unsigned char)( 181 ((dptr->d)[bytei]) & (~(dk4bf_bits_in_byte[biti])) 182 ); 183#endif 184 } 185 back = 1; 186 } else { 187 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 188 } 189 } else { 190 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 191 } 192 return back; 193} 194 195 196 197int 198 199dk4bf_get(int *dptr, dk4_bit_field_t const *bfptr, size_t bitno, dk4_er_t *erp) 200{ 201 size_t bytei; /* Byte index */ 202 size_t biti; /* Bit index within byte */ 203 int back = 0; 204#if DK4_USE_ASSERT 205 assert(NULL != dptr); 206 assert(NULL != bfptr); 207#endif 208 if ((NULL != dptr) && (NULL != bfptr)) { 209 if (bitno < bfptr->s) { 210 bytei = bitno / 8; 211 biti = bitno % 8; 212 if (0x00 != (((bfptr->d)[bytei]) & (dk4bf_bits_in_byte[biti]))) { 213 *dptr = 1; 214 } else { 215 *dptr = 0; 216 } 217 back = 1; 218 } else { 219 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 220 } 221 } else { 222 dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); 223 } 224 return back; 225} 226 227 228 229void 230 231dk4bf_close(dk4_bit_field_t *ptr) 232{ 233#if DK4_USE_ASSERT 234 assert(NULL != ptr); 235#endif 236 if (NULL != ptr) { 237 dk4mem_release(ptr->d); 238 dk4mem_free(ptr); 239 } 240} 241 242