Skip to content

Commit

Permalink
Add %H
Browse files Browse the repository at this point in the history
PUBLISHED_FROM=8345a4602c0b1f2898a52872e6e1d4f86dac07ad
  • Loading branch information
cpq authored and cesantabot committed Dec 30, 2016
1 parent d3c11e0 commit 46dbb25
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 0 deletions.
31 changes: 31 additions & 0 deletions frozen.c
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,13 @@ static int b64rev(int c) {
}
}

static uint8_t hexdec(const char *s) {
#define HEXTOI(x) (x >= '0' && x <= '9' ? x - '0' : x - 'W')
int a = tolower(*(const unsigned char *) s);
int b = tolower(*(const unsigned char *) (s + 1));
return (HEXTOI(a) << 4) | HEXTOI(b);
}

static int b64enc(struct json_out *out, const unsigned char *p, int n) {
char buf[4];
int i, len = 0;
Expand Down Expand Up @@ -557,6 +564,16 @@ int json_vprintf(struct json_out *out, const char *fmt, va_list xap) {
int val = va_arg(ap, int);
const char *str = val ? "true" : "false";
len += out->printer(out, str, strlen(str));
} else if (fmt[1] == 'H') {
const char *hex = "0123456789abcdef";
int i, n = va_arg(ap, int);
const unsigned char *p = va_arg(ap, const unsigned char *);
len += out->printer(out, quote, 1);
for (i = 0; i < n; i++) {
len += out->printer(out, &hex[(p[i] >> 4) & 0xf], 1);
len += out->printer(out, &hex[p[i] & 0xf], 1);
}
len += out->printer(out, quote, 1);
} else if (fmt[1] == 'V') {
const unsigned char *p = va_arg(ap, const unsigned char *);
int n = va_arg(ap, int);
Expand Down Expand Up @@ -857,6 +874,19 @@ static void json_scanf_cb(void *callback_data, const char *name,
}
break;
}
case 'H': {
char **dst = (char **) info->user_data;
int i, len = token->len / 2;
*(int *) info->target = len;
if ((*dst = (char *) malloc(len + 1)) != NULL) {
for (i = 0; i < len; i++) {
(*dst)[i] = hexdec(token->ptr + 2 * i);
}
(*dst)[len] = '\0';
info->num_conversions++;
}
break;
}
case 'V': {
char **dst = (char **) info->target;
int len = token->len * 4 / 3 + 2;
Expand Down Expand Up @@ -897,6 +927,7 @@ int json_vscanf(const char *s, int len, const char *fmt, va_list ap) {
switch (fmt[i + 1]) {
case 'M':
case 'V':
case 'H':
info.user_data = va_arg(ap, void *);
/* FALLTHROUGH */
case 'B':
Expand Down
6 changes: 6 additions & 0 deletions frozen.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ typedef int (*json_printf_callback_t)(struct json_out *, va_list *ap);
* - `%Q` print quoted escaped string or `null`. Accepts a `const char *`.
* - `%.*Q` same as `%Q`, but with length. Accepts `int`, `const char *`
* - `%V` print quoted base64-encoded string. Accepts a `const char *`, `int`.
* - `%H` print quoted hex-encoded string. Accepts a `int`, `const char *`.
* - `%M` invokes a json_printf_callback_t function. That callback function
* can consume more parameters.
*
Expand Down Expand Up @@ -171,6 +172,11 @@ int json_printf_array(struct json_out *, va_list *ap);
* Result string is base64-decoded, malloced and NUL-terminated.
* The length of result string is stored in `int *` placeholder.
* Caller must free() the result.
* - %H: consumes `int *`, `char **`.
* Expects a hex-encoded string, e.g. "fa014f".
* Result string is hex-decoded, malloced and NUL-terminated.
* The length of the result string is stored in `int *` placeholder.
* Caller must free() the result.
* - %M: consumes custom scanning function pointer and
* `void *user_data` parameter - see json_scanner_t definition.
* - %T: consumes `struct json_token *`, fills it out with matched token.
Expand Down
17 changes: 17 additions & 0 deletions unit_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,13 @@ static const char *test_json_printf(void) {
ASSERT(strcmp(buf, "\"ACABIAIgYWJj\"") == 0);
}

{
struct json_out out = JSON_OUT_BUF(buf, sizeof(buf));
memset(buf, 0, sizeof(buf));
ASSERT(json_printf(&out, "%H", 9, "\x00 \x01 \x02 abc") > 0);
ASSERT(strcmp(buf, "\"002001200220616263\"") == 0);
}

return NULL;
}

Expand Down Expand Up @@ -499,6 +506,16 @@ static const char *test_scanf(void) {
free(result);
}

{
const char *str = "{a : \"61626320\" }";
int len = 0;
char *result = NULL;
ASSERT(json_scanf(str, strlen(str), "{a: %H}", &len, &result) == 1);
ASSERT(len == 4);
ASSERT(strcmp(result, "abc ") == 0);
free(result);
}

{
const char *str = "{a : \"0L/RgNC40LLQtdGC0Ys=\" }";
int len;
Expand Down

0 comments on commit 46dbb25

Please sign in to comment.