%% 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; }