%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file dk4bf.h Bit fields. */ #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif /** Bit field structure. */ typedef struct { unsigned char *d; /**< Data buffer. */ size_t s; /**< Number of bits in the array. */ } dk4_bit_field_t; #ifdef __cplusplus extern "C" { #endif /** Open bit field. @param sz Size of the bit field (number of bits). @param erp Error report, may be NULL. @return Pointer to new bit field on success, NULL on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if sz is 0, - DK4_E_MEMORY_ALLOCATION_FAILED
if not enough memory was available. */ dk4_bit_field_t * dk4bf_open(size_t sz, dk4_er_t *erp); /** Set one bit in a bit field. @param dptr Bit field. @param bitno Index of bit to modify. @param val Bit value. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr is 0 or bitno is outside the bit field size. */ int dk4bf_set(dk4_bit_field_t *dptr, size_t bitno, int val, dk4_er_t *erp); /** Retrieve one value from bit field. @param dptr Address of result variable. @param bfptr Bit field. @param bitno Number of bit to obtain. @param erp Error report, may be NULL. @return 1 on success (dptr set), 0 on error (dptr unchanged). Error codes: - DK4_E_INVALID_ARGUMENTS
if dptr or bfptr is NULL or bitno is outside the bit field size. */ int dk4bf_get(int *dptr, dk4_bit_field_t *bfptr, size_t bitno, dk4_er_t *erp); /** Close bit field. @param ptr Pointer to bit field previously opened using dk4bf_open(). */ void dk4bf_close(dk4_bit_field_t *ptr); #ifdef __cplusplus } #endif %% module #include "dk4bf.h" #include "dk4mem.h" $!trace-include /** Position of single bits within a byte. */ static const unsigned char dk4bf_bits_in_byte[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; dk4_bit_field_t * dk4bf_open(size_t sz, dk4_er_t *erp) { dk4_bit_field_t *back = NULL; size_t bsz; if (0 < sz) { back = dk4mem_new(dk4_bit_field_t,1,erp); if (NULL != back) { back->s = sz; bsz = sz / 8; if (0 != (sz % 8)) { bsz++; } back->d = dk4mem_new(unsigned char,bsz,erp); if (NULL == back->d) { dk4bf_close(back); back = NULL; } } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4bf_set(dk4_bit_field_t *dptr, size_t bitno, int val, dk4_er_t *erp) { size_t bytei; /* Byte index */ size_t biti; /* Bit index */ int back = 0; if (NULL != dptr) { if (bitno < dptr->s) { bytei = bitno / 8; biti = bitno % 8; if (0 != val) { (dptr->d)[bytei] |= dk4bf_bits_in_byte[biti]; } else { (dptr->d)[bytei] &= (~(dk4bf_bits_in_byte[biti])); } back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } int dk4bf_get(int *dptr, dk4_bit_field_t *bfptr, size_t bitno, dk4_er_t *erp) { size_t bytei; /* Byte index */ size_t biti; /* Bit index within byte */ int back = 0; if ((NULL != dptr) && (NULL != bfptr)) { if (bitno < bfptr->s) { bytei = bitno / 8; biti = bitno % 8; if (0x00 != (((bfptr->d)[bytei]) & (dk4bf_bits_in_byte[biti]))) { *dptr = 1; } else { *dptr = 0; } back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } return back; } void dk4bf_close(dk4_bit_field_t *ptr) { if (NULL != ptr) { dk4mem_release(ptr->d); dk4mem_free(ptr); } }