mirror of
https://github.com/cesanta/mongoose.git
synced 2025-01-18 06:54:00 +08:00
Add %V and %H specifiers for mg_snrpintf()
This commit is contained in:
parent
c446fe0c6d
commit
a68f3dc4eb
@ -2550,7 +2550,7 @@ standard function does, but in a predictable way that does not depend on
|
||||
the C library or the build environment. The return value can be larger
|
||||
than the buffer length `len`, in which case the overflow bytes are not printed.
|
||||
Mongoose library is often used to exchange data in JSON format, therefore a
|
||||
non-standard `%Q` specifier for formatting JSON strings is also supported.
|
||||
non-standard `%Q`, `%V`, `%H` specifiers for formatting JSON strings is also supported.
|
||||
|
||||
Parameters:
|
||||
- `buf` - Pointer to pointer to output buffer
|
||||
@ -2561,13 +2561,15 @@ Supported format specifiers:
|
||||
- `hhd`, `hd`, `d`, `ld`, `lld` - for `char`, `short`, `int`, `long`, `int64_t`
|
||||
- `hhu`, `hu`, `u`, `lu`, `llu` - same but for unsigned variants
|
||||
- `hhx`, `hx`, `x`, `lx`, `llx` - same, unsigned and hex output
|
||||
- `s` - for `char *`
|
||||
- `Q` - for `char *`, outputs double-quoted JSON-escaped string (extension)
|
||||
- `M` - for `size_t (*)(char *, size_t, va_list *)`, calls another print function (extension)
|
||||
- `g`, `f` - for `double`
|
||||
- `c` - for `char`
|
||||
- `%` - the `%` character itself
|
||||
- `p` - for any pointer, prints `0x.....` hex value
|
||||
- `s` - expect `char *`
|
||||
- `Q` - expect `char *`, outputs double-quoted JSON-escaped string (extension)
|
||||
- `H` - expect `int`, `void *`, outputs double-quoted hex string (extension)
|
||||
- `V` - expect `int`, `void *`, outputs double-quoted base64 string (extension)
|
||||
- `M` - expect `size_t (*)(char *, size_t, va_list *)`, calls another print function (extension)
|
||||
- `g`, `f` - expect `double`
|
||||
- `c` - expect `char`
|
||||
- `%` - expect `%` character itself
|
||||
- `p` - expect any pointer, prints `0x.....` hex value
|
||||
- `%X.Y` - optional width and precision modifiers
|
||||
- `%.*` - optional precision modifier specified as `int` argument
|
||||
|
||||
|
27
mongoose.c
27
mongoose.c
@ -4518,6 +4518,33 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
|
||||
int p = va_arg(*ap, int);
|
||||
if (n < len) buf[n] = (char) p;
|
||||
n++;
|
||||
} else if (c == 'H') {
|
||||
// Print hex-encoded double-quoted string
|
||||
size_t bl = (size_t) va_arg(*ap, int);
|
||||
uint8_t *p = va_arg(*ap, uint8_t *), dquote = '"';
|
||||
const char *hex = "0123456789abcdef";
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
for (j = 0; j < bl; j++) {
|
||||
n += mg_copys(buf, len, n, (char *) &hex[(p[j] >> 4) & 15], 1);
|
||||
n += mg_copys(buf, len, n, (char *) &hex[p[j] & 15], 1);
|
||||
}
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
} else if (c == 'V') {
|
||||
// Print base64-encoded double-quoted string
|
||||
size_t bl = (size_t) va_arg(*ap, int);
|
||||
uint8_t *p = va_arg(*ap, uint8_t *), dquote = '"';
|
||||
const char *t =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
for (j = 0; j < bl; j += 3) {
|
||||
uint8_t c1 = p[j], c2 = j + 1 < bl ? p[j + 1] : 0,
|
||||
c3 = j + 2 < bl ? p[j + 2] : 0;
|
||||
char tmp[4] = {t[c1 >> 2], t[(c1 & 3) << 4 | (c2 >> 4)], '=', '='};
|
||||
if (j + 1 < bl) tmp[2] = t[(c2 & 15) << 2 | (c3 >> 6)];
|
||||
if (j + 2 < bl) tmp[3] = t[c3 & 63];
|
||||
n += mg_copys(buf, len, n, tmp, sizeof(tmp));
|
||||
}
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
} else if (c == 's' || c == 'Q') {
|
||||
char *p = va_arg(*ap, char *);
|
||||
size_t (*fn)(char *, size_t, size_t, char *, size_t) =
|
||||
|
27
src/str.c
27
src/str.c
@ -397,6 +397,33 @@ size_t mg_vsnprintf(char *buf, size_t len, const char *fmt, va_list *ap) {
|
||||
int p = va_arg(*ap, int);
|
||||
if (n < len) buf[n] = (char) p;
|
||||
n++;
|
||||
} else if (c == 'H') {
|
||||
// Print hex-encoded double-quoted string
|
||||
size_t bl = (size_t) va_arg(*ap, int);
|
||||
uint8_t *p = va_arg(*ap, uint8_t *), dquote = '"';
|
||||
const char *hex = "0123456789abcdef";
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
for (j = 0; j < bl; j++) {
|
||||
n += mg_copys(buf, len, n, (char *) &hex[(p[j] >> 4) & 15], 1);
|
||||
n += mg_copys(buf, len, n, (char *) &hex[p[j] & 15], 1);
|
||||
}
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
} else if (c == 'V') {
|
||||
// Print base64-encoded double-quoted string
|
||||
size_t bl = (size_t) va_arg(*ap, int);
|
||||
uint8_t *p = va_arg(*ap, uint8_t *), dquote = '"';
|
||||
const char *t =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
for (j = 0; j < bl; j += 3) {
|
||||
uint8_t c1 = p[j], c2 = j + 1 < bl ? p[j + 1] : 0,
|
||||
c3 = j + 2 < bl ? p[j + 2] : 0;
|
||||
char tmp[4] = {t[c1 >> 2], t[(c1 & 3) << 4 | (c2 >> 4)], '=', '='};
|
||||
if (j + 1 < bl) tmp[2] = t[(c2 & 15) << 2 | (c3 >> 6)];
|
||||
if (j + 2 < bl) tmp[3] = t[c3 & 63];
|
||||
n += mg_copys(buf, len, n, tmp, sizeof(tmp));
|
||||
}
|
||||
n += mg_copys(buf, len, n, (char *) &dquote, 1);
|
||||
} else if (c == 's' || c == 'Q') {
|
||||
char *p = va_arg(*ap, char *);
|
||||
size_t (*fn)(char *, size_t, size_t, char *, size_t) =
|
||||
|
@ -1389,9 +1389,12 @@ static size_t pf2(char *buf, size_t len, va_list *ap) {
|
||||
}
|
||||
|
||||
static void test_str(void) {
|
||||
struct mg_str s = mg_strdup(mg_str("a"));
|
||||
ASSERT(mg_strcmp(s, mg_str("a")) == 0);
|
||||
free((void *) s.ptr);
|
||||
{
|
||||
struct mg_str s = mg_strdup(mg_str("a"));
|
||||
ASSERT(mg_strcmp(s, mg_str("a")) == 0);
|
||||
free((void *) s.ptr);
|
||||
}
|
||||
|
||||
ASSERT(mg_strcmp(mg_str(""), mg_str(NULL)) == 0);
|
||||
ASSERT(mg_strcmp(mg_str("a"), mg_str("b")) < 0);
|
||||
ASSERT(mg_strcmp(mg_str("b"), mg_str("a")) > 0);
|
||||
@ -1552,6 +1555,21 @@ static void test_str(void) {
|
||||
TESTDOUBLE("%g", -HUGE_VAL, "-inf");
|
||||
#endif
|
||||
}
|
||||
|
||||
{
|
||||
const char *expected = "[\"MA==\",\"MAo=\",\"MAr+\",\"MAr+Zw==\"]";
|
||||
char tmp[100], s[] = "0\n\xfeg";
|
||||
ASSERT(mg_snprintf(tmp, sizeof(tmp), "[%V,%V,%V,%V]", 1, s, 2, s, 3, s, 4,
|
||||
s) == 33);
|
||||
ASSERT(strcmp(tmp, expected) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
const char *expected = "\"002001200220616263\"";
|
||||
char tmp[100], s[] = "\x00 \x01 \x02 abc";
|
||||
ASSERT(mg_snprintf(tmp, sizeof(tmp), "%H", 9, s) == 20);
|
||||
ASSERT(strcmp(tmp, expected) == 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void fn1(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||
|
Loading…
Reference in New Issue
Block a user