%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file dk4binenc.h Encode binary data to text.
*/
#include "dk4error.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Encode binary data to text.
Data is saved as text string including finalizing 0 byte
except for DK4_BINARY_TO_TEXT_ENCODING_NONE.
@param dptr Destination buffer address.
@param szdptr Destination buffer size.
@param sptr Source buffer address.
@param szsptr Source buffer size.
@param enc Encoding, one from
DK4_BINARY_TO_TEXT_ENCODING_NONE,
DK4_BINARY_TO_TEXT_ENCODING_HEX,
or DK4_BINARY_TO_TEXT_ENCODING_A85.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if dptr or sptr is NULL or szdptr or szsptr is 0 or an illegal
enc value was specified,
- DK4_E_BUFFER_TOO_SMALL
if the provided destination buffer is too small,
- DK4_E_MATH_OVERFLOW
if a mathematical overflow occured in size calculation
(required destination buffer size too large),
- DK4_E_ENCODING_FAILED
if encoding failed for a byte.
*/
int
dk4binenc(
char *dptr,
size_t szdptr,
const void *sptr,
size_t szsptr,
int enc,
dk4_er_t *erp
);
/** Find numeric encoding type for an encoding name.
@param name String containing encoding name.
@param erp Error report, may be NULL.
@return Non-negative numeric encoding type on success, -1 on error.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if name is NULL,
- DK4_E_SYNTAX
if name is not a valid encoding name.
*/
int
dk4binenc_choose_encoding(const dkChar *name, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
/** Message digest encodings.
*/
enum {
/** No encoding, use binary
data directly.
*/
DK4_BINARY_TO_TEXT_ENCODING_NONE = 0,
/** ASCII-Hex encoding.
*/
DK4_BINARY_TO_TEXT_ENCODING_HEX ,
/** ASCII-85 encoding.
*/
DK4_BINARY_TO_TEXT_ENCODING_A85
};
%% module
#include "dk4binenc.h"
#include "dk4mem.h"
#include "dk4memrs.h"
#include "dk4a85e.h"
#include "dk4maasz.h"
#include "dk4strd.h"
#include "dk4edstm.h"
$!trace-include
/** Hexadecimal digits.
*/
static const char dk4binenc_hex_digits[] = { "0123456789abcdef" };
/** Message digest type names.
Order must match the definition order in the enum in dk4md.h.
*/
static const dkChar * const dk4binenc_encoding_names[] = {
$!string-table macro=dkT
bin
binary
hex
hexa
hexadecimal
ascii-85
ascii85
a85
$!end
};
int
dk4binenc(
char *dptr,
size_t szdptr,
const void *sptr,
size_t szsptr,
int enc,
dk4_er_t *erp
)
{
dk4_a85_enc_t a85;
dk4_er_t maerr;
const unsigned char *ucptr;
const char *resptr;
size_t ressize;
size_t oused;
size_t noused;
int back = 0;
if ((NULL != dptr) && (NULL != sptr) && (0 < szdptr) && (0 < szsptr)) {
switch (enc) {
case DK4_BINARY_TO_TEXT_ENCODING_NONE : {
if (szdptr >= szsptr) {
DK4_MEMCPY(dptr, sptr, szsptr);
back = 1;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
}
} break;
case DK4_BINARY_TO_TEXT_ENCODING_HEX : {
oused = 0;
ucptr = (const unsigned char *)sptr;
while (szsptr--) {
dk4error_init(&maerr);
noused = dk4ma_size_t_add(oused, 2, &maerr);
if (DK4_E_NONE == maerr.ec) {
dptr[oused] =
dk4binenc_hex_digits[(size_t)((((unsigned)(*ucptr)) >> 4) & 0x0FU)];
dptr[oused+1] =
dk4binenc_hex_digits[(size_t)(((unsigned)(*ucptr)) & 0x0FU)];
oused = noused;
} else {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
goto finished;
}
ucptr++;
}
if (oused < szdptr) {
dptr[oused] = '\0';
back = 1;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
}
} break;
case DK4_BINARY_TO_TEXT_ENCODING_A85 : {
oused = 0;
ucptr = (const unsigned char *)sptr;
dk4a85_enc_init(&a85, 0, erp);
while(szsptr--) {
switch (dk4a85_enc_add(&a85, *(ucptr++), erp)) {
case DK4_EDSTM_FINISHED : {
resptr = NULL; ressize = 0;
(void)dk4a85_enc_output(&resptr, &ressize, &a85, NULL);
if ((NULL != resptr) && (0 < ressize)) {
dk4error_init(&maerr);
noused = dk4ma_size_t_add(oused, ressize, &maerr);
if (DK4_E_NONE == maerr.ec) {
if (noused < szdptr) {
DK4_MEMCPY(&(dptr[oused]), resptr, ressize);
oused = noused;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
goto finished;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
goto finished;
}
}
} break;
case DK4_EDSTM_ERROR : {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
goto finished;
} break;
}
}
switch (dk4a85_enc_finish(&a85, erp)) {
case DK4_EDSTM_FINISHED : {
resptr = NULL; ressize = 0;
(void)dk4a85_enc_output(&resptr, &ressize, &a85, NULL);
if ((NULL != resptr) && (0 < ressize)) {
dk4error_init(&maerr);
noused = dk4ma_size_t_add(oused, ressize, &maerr);
if (DK4_E_NONE == maerr.ec) {
if (noused < szdptr) {
DK4_MEMCPY(&(dptr[oused]), resptr, ressize);
oused = noused;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
goto finished;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_MATH_OVERFLOW);
goto finished;
}
}
} break;
case DK4_EDSTM_ERROR : {
dk4error_set_simple_error_code(erp, DK4_E_ENCODING_FAILED);
goto finished;
} break;
}
if (oused < szdptr) {
dptr[oused] = '\0';
back = 1;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
}
(void)dk4mem_reset_secure(&a85, sizeof(dk4_a85_enc_t), NULL);
} break;
default : {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} break;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
finished:
if ((NULL != dptr) && (0 == back)) { *dptr = '\0'; }
return back;
}
int
dk4binenc_choose_encoding(const dkChar *name, dk4_er_t *erp)
{
int back = -1;
if (NULL != name) {
switch (dk4str_array_index(dk4binenc_encoding_names, name, 0)) {
case 0: case 1: {
back = DK4_BINARY_TO_TEXT_ENCODING_NONE;
} break;
case 2: case 3: case 4: {
back = DK4_BINARY_TO_TEXT_ENCODING_HEX;
} break;
case 5: case 6: case 7: {
back = DK4_BINARY_TO_TEXT_ENCODING_A85;
} break;
}
if (-1 == back) {
dk4error_set_simple_error_code(erp, DK4_E_SYNTAX);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
}
return back;
}