mirror of
https://github.com/isc-projects/bind9.git
synced 2026-05-22 01:56:00 -04:00
expose hex_decode APIs
Functions hex_decode_init(), hex_decode_char() and hex_decode_finish() are now exposed, as well as the context hex_decode_ctx_t. They now are respectively called isc_hex_decodeinit(), isc_hex_decodechar(), isc_hex_decodefinish() and isc_hex_decodectx_t. This enable to re-implement the functionality of isc_hex_decodestring() in contextes where the input is not a NULL-terminated string, but, for example, individual characters extracted (and avoid creating an intermediate buffer to store them). This also enable to decode a stream of hex characters where only hex characters are expected (i.e. no white spaces).
This commit is contained in:
parent
ac4cf4cce8
commit
e34dd2b73e
2 changed files with 72 additions and 24 deletions
|
|
@ -83,25 +83,15 @@ isc_hex_totext(isc_region_t *source, int wordlength, const char *wordbreak,
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
/*%
|
||||
* State of a hex decoding process in progress.
|
||||
*/
|
||||
typedef struct {
|
||||
int length; /*%< Desired length of binary data or -1 */
|
||||
isc_buffer_t *target; /*%< Buffer for resulting binary data */
|
||||
int digits; /*%< Number of buffered hex digits */
|
||||
int val[2];
|
||||
} hex_decode_ctx_t;
|
||||
|
||||
static void
|
||||
hex_decode_init(hex_decode_ctx_t *ctx, int length, isc_buffer_t *target) {
|
||||
void
|
||||
isc_hex_decodeinit(isc_hex_decodectx_t *ctx, int length, isc_buffer_t *target) {
|
||||
ctx->digits = 0;
|
||||
ctx->length = length;
|
||||
ctx->target = target;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
hex_decode_char(hex_decode_ctx_t *ctx, int c) {
|
||||
isc_result_t
|
||||
isc_hex_decodechar(isc_hex_decodectx_t *ctx, int c) {
|
||||
uint8_t hexval;
|
||||
|
||||
hexval = isc_hex_char(c);
|
||||
|
|
@ -126,8 +116,8 @@ hex_decode_char(hex_decode_ctx_t *ctx, int c) {
|
|||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
static isc_result_t
|
||||
hex_decode_finish(hex_decode_ctx_t *ctx) {
|
||||
isc_result_t
|
||||
isc_hex_decodefinish(isc_hex_decodectx_t *ctx) {
|
||||
if (ctx->length > 0) {
|
||||
return ISC_R_UNEXPECTEDEND;
|
||||
}
|
||||
|
|
@ -140,14 +130,14 @@ hex_decode_finish(hex_decode_ctx_t *ctx) {
|
|||
isc_result_t
|
||||
isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
|
||||
unsigned int before, after;
|
||||
hex_decode_ctx_t ctx;
|
||||
isc_hex_decodectx_t ctx;
|
||||
isc_textregion_t *tr;
|
||||
isc_token_t token;
|
||||
bool eol;
|
||||
|
||||
REQUIRE(length >= -2);
|
||||
|
||||
hex_decode_init(&ctx, length, target);
|
||||
isc_hex_decodeinit(&ctx, length, target);
|
||||
|
||||
before = isc_buffer_usedlength(target);
|
||||
while (ctx.length != 0) {
|
||||
|
|
@ -165,14 +155,14 @@ isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
|
|||
}
|
||||
tr = &token.value.as_textregion;
|
||||
for (i = 0; i < tr->length; i++) {
|
||||
RETERR(hex_decode_char(&ctx, tr->base[i]));
|
||||
RETERR(isc_hex_decodechar(&ctx, tr->base[i]));
|
||||
}
|
||||
}
|
||||
after = isc_buffer_usedlength(target);
|
||||
if (ctx.length < 0) {
|
||||
isc_lex_ungettoken(lexer, &token);
|
||||
}
|
||||
RETERR(hex_decode_finish(&ctx));
|
||||
RETERR(isc_hex_decodefinish(&ctx));
|
||||
if (length == -2 && before == after) {
|
||||
return ISC_R_UNEXPECTEDEND;
|
||||
}
|
||||
|
|
@ -181,9 +171,9 @@ isc_hex_tobuffer(isc_lex_t *lexer, isc_buffer_t *target, int length) {
|
|||
|
||||
isc_result_t
|
||||
isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
|
||||
hex_decode_ctx_t ctx;
|
||||
isc_hex_decodectx_t ctx;
|
||||
|
||||
hex_decode_init(&ctx, -1, target);
|
||||
isc_hex_decodeinit(&ctx, -1, target);
|
||||
for (;;) {
|
||||
int c = *cstr++;
|
||||
if (c == '\0') {
|
||||
|
|
@ -192,9 +182,9 @@ isc_hex_decodestring(const char *cstr, isc_buffer_t *target) {
|
|||
if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
|
||||
continue;
|
||||
}
|
||||
RETERR(hex_decode_char(&ctx, c));
|
||||
RETERR(isc_hex_decodechar(&ctx, c));
|
||||
}
|
||||
RETERR(hex_decode_finish(&ctx));
|
||||
RETERR(isc_hex_decodefinish(&ctx));
|
||||
return ISC_R_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,16 @@
|
|||
|
||||
#include <isc/types.h>
|
||||
|
||||
/*%
|
||||
* State of a hex decoding process in progress.
|
||||
*/
|
||||
typedef struct {
|
||||
int length; /*%< Desired length of binary data or -1 */
|
||||
isc_buffer_t *target; /*%< Buffer for resulting binary data */
|
||||
int digits; /*%< Number of buffered hex digits */
|
||||
int val[2];
|
||||
} isc_hex_decodectx_t;
|
||||
|
||||
/*
|
||||
* An `isc__hex_char` table entry is non-zero if the character is a hex digit;
|
||||
* You can subtract the table entry from the character to convert the hex digit
|
||||
|
|
@ -58,6 +68,54 @@ isc_hex_totext(isc_region_t *source, int wordlength, const char *wordbreak,
|
|||
* necessary.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The 3 following functions are internally used and wrapped by
|
||||
* `isc_hex_decodestring()`, which can be directly used for simpler cases.
|
||||
* However, for more complex cases (or cases which, for instance, must not have
|
||||
* white spaces, or if the input is not a null-terminated string) using those
|
||||
* lower-level API might be usefull.
|
||||
*/
|
||||
|
||||
void
|
||||
isc_hex_decodeinit(isc_hex_decodectx_t *ctx, int length, isc_buffer_t *target);
|
||||
/*!<
|
||||
* \brief Initialize the hex decoder context
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ctx' is non-null.
|
||||
*\li 'length' is the number of bytes that will have to be decoded
|
||||
*\li 'target' is the buffer which the decoded hex chars will be written to.
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_decodechar(isc_hex_decodectx_t *ctx, int c);
|
||||
/*!<
|
||||
* \brief Decode an individual hex character
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ctx' is non-null.
|
||||
*\li 'c' is the hexadecimal character to decode
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_BADHEX -- 'c' is not an hexadecimal char
|
||||
* \li #ISC_R_SUCCESS -- 'c' is decoded
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_decodefinish(isc_hex_decodectx_t *ctx);
|
||||
/*!<
|
||||
* \brief Verifies that all the decoded characters used the expected length
|
||||
* passed to `hex_decode_init()`
|
||||
*
|
||||
* Requires:
|
||||
*\li 'ctx' is non-null.
|
||||
*
|
||||
* Returns:
|
||||
* \li #ISC_R_UNEXPECTEDEND -- less bytes than expected has been decoded
|
||||
* \li #ISC_R_BADHEX -- last decoded character is not an hexadecimal one
|
||||
* \li #ISC_R_SUCCESS -- all the bytes are decoded as expected
|
||||
*/
|
||||
|
||||
isc_result_t
|
||||
isc_hex_decodestring(const char *cstr, isc_buffer_t *target);
|
||||
/*!<
|
||||
|
|
|
|||
Loading…
Reference in a new issue