btrfs-progs: add json formatter for escaped string
Add formatter type 'str' where the string must be escaped, e.g. paths or internal data. Otherwise plain %s can be printed if it's known that there are no special characters. Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
6ecaa3ee4f
commit
ecbb6a7fcd
|
@ -40,6 +40,48 @@ static void print_uuid(const u8 *uuid)
|
|||
}
|
||||
}
|
||||
|
||||
static void print_escaped(const char *str)
|
||||
{
|
||||
while (*str) {
|
||||
switch (*str) {
|
||||
case '\b': /* 0x08 */
|
||||
putchar('\\');
|
||||
putchar('b');
|
||||
break;
|
||||
case '\t': /* 0x09 */
|
||||
putchar('\\');
|
||||
putchar('t');
|
||||
break;
|
||||
case '\n': /* 0x0a */
|
||||
putchar('\\');
|
||||
putchar('n');
|
||||
break;
|
||||
case '\f': /* 0x0c */
|
||||
putchar('\\');
|
||||
putchar('f');
|
||||
break;
|
||||
case '\r': /* 0x0d */
|
||||
putchar('\\');
|
||||
putchar('r');
|
||||
break;
|
||||
/* Other control characters from 0 .. 31 */
|
||||
case '\v': /* 0x0b */
|
||||
case 0x00 ... 0x07:
|
||||
case 0x0e ... 0x1f:
|
||||
printf("\\u%04x", *str);
|
||||
break;
|
||||
/* '/' (solidus) not escaped */
|
||||
case '"':
|
||||
case '\\':
|
||||
putchar('\\');
|
||||
/* fallthrough */
|
||||
default:
|
||||
putchar(*str);
|
||||
}
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
static void fmt_indent1(int indent)
|
||||
{
|
||||
while (indent--)
|
||||
|
@ -281,6 +323,10 @@ void fmt_print(struct format_ctx *fctx, const char* key, ...)
|
|||
|
||||
if (row->fmt[0] == '%') {
|
||||
vprintf(row->fmt, args);
|
||||
} else if (strcmp(row->fmt, "str") == 0) {
|
||||
const char *str = va_arg(args, const char *);
|
||||
|
||||
print_escaped(str);
|
||||
} else if (strcmp(row->fmt, "uuid") == 0) {
|
||||
const u8 *uuid = va_arg(args, const u8*);
|
||||
|
||||
|
|
|
@ -66,12 +66,38 @@ void test1()
|
|||
fmt_end(&fctx);
|
||||
}
|
||||
|
||||
/* Escaped strings */
|
||||
void test2_escape()
|
||||
{
|
||||
static const struct rowspec rows1[] = {
|
||||
{ .key = "devid", .fmt = "%llu", .out_text = "devid", .out_json = "devid" },
|
||||
{ .key = "path1", .fmt = "str", .out_text = "path1", .out_json = "path1" },
|
||||
{ .key = "path2", .fmt = "str", .out_text = "path2", .out_json = "path2" },
|
||||
ROWSPEC_END
|
||||
};
|
||||
struct format_ctx fctx;
|
||||
char control_chars[] = { [0] = '.', [0x20] = 0 };
|
||||
int i;
|
||||
|
||||
for (i = 1; i < 0x20; i++)
|
||||
control_chars[i] = i;
|
||||
|
||||
fmt_start(&fctx, rows1, 32, 0);
|
||||
fmt_print_start_group(&fctx, "device-info", JSON_TYPE_MAP);
|
||||
fmt_print(&fctx, "devid", 1);
|
||||
fmt_print(&fctx, "path1", "/fun\ny/p\th/\b/\\/\f\"quo\rte\"");
|
||||
fmt_print(&fctx, "path2", control_chars);
|
||||
fmt_print_end_group(&fctx, NULL);
|
||||
fmt_end(&fctx);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int testno;
|
||||
static void (*tests[])() = {
|
||||
test_simple_empty,
|
||||
test1,
|
||||
test2_escape,
|
||||
};
|
||||
|
||||
btrfs_config_init();
|
||||
|
|
Loading…
Reference in New Issue