%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file dk4bitsh.h Bit shifting.
*/
#include "dk4error.h"
/** Bit shifter.
*/
typedef struct {
int pos; /**< Current bit position. */
unsigned char obyte; /**< Output byte. */
} dk4_bit_shift_t;
#ifdef __cplusplus
extern "C" {
#endif
/** Initialize a bit shifter before using it.
@param bs Bit shifter to initialize.
@param erp Error report, may be NULL.
Error codes:
- DK4_E_INVALID_ARGUMENTS if bs is NULL.
*/
void
dk4bit_shift_init(dk4_bit_shift_t *bs, dk4_er_t *erp);
/** Add one byte.
@param bs Bit shifter.
@param bit Bit value, 0 or non-0.
@param erp Error report, may be NULL.
@return Action to take, one from:
- DK4_EDSTM_ACCEPT
if the bit was stored in the bit shifter. No action necessary.
- DK4_EDSTM_FINISHED
if one byte was completed by adding the bit.
Use dk4bit_shift_output() to retrieve the finished byte.
- DK4_EDSTM_ERROR
if an error occured.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if bs is NULL.
*/
int
dk4bit_shift_add(dk4_bit_shift_t *bs, int bit, dk4_er_t *erp);
/** Check for unused content in the bit shifter after adding all bits.
@param bs Bit shifter.
@param erp Error report, may be NULL.
@return Action to take, one from:
- DK4_EDSTM_ACCEPT
if no action is required.
- DK4_EDSTM_FINISHED
if significant bits are available for a byte.
Use dk4bit_shift_output() to retrieve the byte value.
- DK4_EDSTM_ERROR
if an error occured.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if bs is NULL.
*/
int
dk4bit_shift_finish(dk4_bit_shift_t *bs, dk4_er_t *erp);
/** Retrieve previous completed byte or final incomplete byte.
@param bs Bit shifter.
@param erp Error report, may be NULL.
@return Byte value consisting of the last bits added.
*/
unsigned char
dk4bit_shift_output(dk4_bit_shift_t *bs, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4bitsh.h"
#include "dk4edstm.h"
#include "dk4mem.h"
$!trace-include
void
dk4bit_shift_init(dk4_bit_shift_t *bs, dk4_er_t *erp)
{
if (NULL != bs) {
DK4_MEMRES(bs, sizeof(dk4_bit_shift_t));
bs->pos = 0;
bs->obyte = 0x00;
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
}
int
dk4bit_shift_add(dk4_bit_shift_t *bs, int bit, dk4_er_t *erp)
{
int back = DK4_EDSTM_ERROR;
if (NULL != bs) {
back = DK4_EDSTM_ACCEPT;
switch (bs->pos) {
case 0: {
if (0 != bit) { bs->obyte = 0x80; } else { bs->obyte = 0x00; }
bs->pos = 1;
} break;
case 1: {
if (0 != bit) { bs->obyte |= 0x40; }
bs->pos = 2;
} break;
case 2: {
if (0 != bit) { bs->obyte |= 0x20; }
bs->pos = 3;
} break;
case 3: {
if (0 != bit) { bs->obyte |= 0x10; }
bs->pos = 4;
} break;
case 4: {
if (0 != bit) { bs->obyte |= 0x08; }
bs->pos = 5;
} break;
case 5: {
if (0 != bit) { bs->obyte |= 0x04; }
bs->pos = 6;
} break;
case 6: {
if (0 != bit) { bs->obyte |= 0x02; }
bs->pos = 7;
} break;
case 7: {
if (0 != bit) { bs->obyte |= 0x01; }
bs->pos = 0;
back = DK4_EDSTM_FINISHED;
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
int
dk4bit_shift_finish(dk4_bit_shift_t *bs, dk4_er_t *erp)
{
int back = DK4_EDSTM_ERROR;
if (NULL != bs) {
if (0 != bs->pos) {
back = DK4_EDSTM_FINISHED;
} else {
back = DK4_EDSTM_ACCEPT;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
unsigned char
dk4bit_shift_output(dk4_bit_shift_t *bs, dk4_er_t *erp)
{
unsigned char back;
if (NULL != bs) {
back = bs->obyte;
} else {
back = 0x00;
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}