%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file dk4ahd.h ASCIIHex decoder.
First initialize the decoder using the dk4ahex_dec_init() function.
Add text characters using the dk4ahex_dec_add() function.
The function returns DK4_EDSTM_ACCEPT if the text character was successfully
stored in the decoder without completing a byte.
The DK4_EDSTM_FINISHED return code indicates that a byte was finished, use
dk4ahex_output() to retrieve it.
The DK4_EDSTM_STOP return code indicates that an end of data (EOD) marker
was found.
After feeding all text characters into the decoder use dk4ahex_finish()
to check whether there is an unprocessed half-byte stored.
If the function returns DK4_EDSTM_FINISHED, use dk4ahex_output() to
retrieve the final byte.
Note: The call to dk4ahex_finish() is also necessary after
obtaining DK4_EDSTM_STOP from dk4ahex_dec_add().
*/
#include "dk4conf.h"
#include "dk4error.h"
/** ASCII-Hex decoder.
*/
typedef struct {
int cpos; /**< Current position. */
unsigned char obyte; /**< Output byte. */
} dk4_ahex_dec_t;
#ifdef __cplusplus
extern "C" {
#endif
/** Initialize decoder.
@param dec Decoder to initialize.
@param erp Error report, may be NULL.
*/
void
dk4ahex_dec_init(dk4_ahex_dec_t *dec, dk4_er_t *erp);
/** Add text character to decoder.
@param dec Decoder.
@param tc Text character to add.
@param erp Error report, may be NULL.
@return Action to take:
- DK4_EDSTM_ACCEPT
if the text was saved in the decoder, no action necessary.
- DK4_EDSTM_FINISHED
if a byte was completed, use dk4ahex_dec_output() to retrieve
the byte.
- DK4_EDSTM_STOP
if the end of data (EOD) marker was detected.
Use dk4ahex_finish() to check whether there is still data
in the decoder.
- DK4_EDSTM_ERROR
if an error occured.
*/
int
dk4ahex_dec_add(dk4_ahex_dec_t *dec, char tc, dk4_er_t *erp);
/** Check for final byte.
@param dec Decoder.
@param erp Error report, may be NULL.
@return Action to take, one from:
- DK4_EDSTM_ACCEPT
if there is no action necessary.
- DK4_EDSTM_FINISHED
if there is data available, use dk4ahex_dec_output() to retrieve
the byte.
- DK4_EDSTM_ERROR
if an error occured.
*/
int
dk4ahex_finish(dk4_ahex_dec_t *dec, dk4_er_t *erp);
/** Retrieve current decoder content.
@param dec Decoder.
@param erp Error report, may be NULL.
@return The current byte stored in the decoder.
*/
unsigned char
dk4ahex_output(dk4_ahex_dec_t *dec, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4ahd.h"
#include "dk4mem.h"
#include "dk4edstm.h"
$!trace-include
void
dk4ahex_dec_init(dk4_ahex_dec_t *dec, dk4_er_t *erp)
{
if (NULL != dec) {
DK4_MEMRES(dec, sizeof(dk4_ahex_dec_t));
dec->cpos = 0;
dec->obyte = 0x00;
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
}
int
dk4ahex_dec_add(dk4_ahex_dec_t *dec, char tc, dk4_er_t *erp)
{
int back = DK4_EDSTM_ERROR;
if (NULL != dec) {
switch (tc) {
case ' ' : case '\t' : case '\r' : case '\n' : case 0x00 : case 0x0C : {
back = DK4_EDSTM_ACCEPT;
} break;
case '>' : {
back = DK4_EDSTM_STOP;
} break;
case '0' : {
if (0 != dec->cpos) {
dec->cpos = 2;
} else {
dec->obyte = 0x00;
dec->cpos = 1;
}
} break;
case '1' : {
if (0 != dec->cpos) {
dec->obyte |= 0x01; dec->cpos = 2;
} else {
dec->obyte = 0x10; dec->cpos = 1;
}
} break;
case '2' : {
if (0 != dec->cpos) {
dec->obyte |= 0x02; dec->cpos = 2;
} else {
dec->obyte = 0x20; dec->cpos = 1;
}
} break;
case '3' : {
if (0 != dec->cpos) {
dec->obyte |= 0x03; dec->cpos = 2;
} else {
dec->obyte = 0x30; dec->cpos = 1;
}
} break;
case '4' : {
if (0 != dec->cpos) {
dec->obyte |= 0x04; dec->cpos = 2;
} else {
dec->obyte = 0x40; dec->cpos = 1;
}
} break;
case '5' : {
if (0 != dec->cpos) {
dec->obyte |= 0x05; dec->cpos = 2;
} else {
dec->obyte = 0x50; dec->cpos = 1;
}
} break;
case '6' : {
if (0 != dec->cpos) {
dec->obyte |= 0x06; dec->cpos = 2;
} else {
dec->obyte = 0x60; dec->cpos = 1;
}
} break;
case '7' : {
if (0 != dec->cpos) {
dec->obyte |= 0x07; dec->cpos = 2;
} else {
dec->obyte = 0x70; dec->cpos = 1;
}
} break;
case '8' : {
if (0 != dec->cpos) {
dec->obyte |= 0x08; dec->cpos = 2;
} else {
dec->obyte = 0x80; dec->cpos = 1;
}
} break;
case '9' : {
if (0 != dec->cpos) {
dec->obyte |= 0x09; dec->cpos = 2;
} else {
dec->obyte = 0x90; dec->cpos = 1;
}
} break;
case 'a' : case 'A' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0A; dec->cpos = 2;
} else {
dec->obyte = 0xA0; dec->cpos = 1;
}
} break;
case 'b' : case 'B' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0B; dec->cpos = 2;
} else {
dec->obyte = 0xB0; dec->cpos = 1;
}
} break;
case 'c' : case 'C' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0C; dec->cpos = 2;
} else {
dec->obyte = 0xC0; dec->cpos = 1;
}
} break;
case 'd' : case 'D' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0D; dec->cpos = 2;
} else {
dec->obyte = 0xD0; dec->cpos = 1;
}
} break;
case 'e' : case 'E' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0E; dec->cpos = 2;
} else {
dec->obyte = 0xE0; dec->cpos = 1;
}
} break;
case 'f' : case 'F' : {
if (0 != dec->cpos) {
dec->obyte |= 0x0F; dec->cpos = 2;
} else {
dec->obyte = 0xF0; dec->cpos = 1;
}
} break;
}
if (2 == dec->cpos) {
dec->cpos = 0;
back = DK4_EDSTM_FINISHED;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
int
dk4ahex_finish(dk4_ahex_dec_t *dec, dk4_er_t *erp)
{
int back = DK4_EDSTM_ERROR;
if (NULL != dec) {
switch (dec->cpos) {
case 1: {
back = DK4_EDSTM_FINISHED;
} break;
default : {
back = DK4_EDSTM_ACCEPT;
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}
unsigned char
dk4ahex_output(dk4_ahex_dec_t *dec, dk4_er_t *erp)
{
unsigned char back = 0x00;
if (NULL != dec) {
back = dec->obyte;
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}