[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH v6 12/15] qapi: Support pretty printing in JSON
From: |
Marc-André Lureau |
Subject: |
Re: [Qemu-devel] [PATCH v6 12/15] qapi: Support pretty printing in JSON output visitor |
Date: |
Tue, 11 Oct 2016 11:20:22 +0000 |
On Mon, Oct 10, 2016 at 5:44 PM Eric Blake <address@hidden> wrote:
> Add pretty printing, where the format intentionally matches that of
> qobject_to_json() (a later patch will then rework qobject-json.c to
> work on top of the JSON visitor). The trickiest part is probably
> that the testsuite now has to honor parameterization on whether
> pretty printing is enabled.
>
> Signed-off-by: Eric Blake <address@hidden>
>
> ---
> v6: tweak commit message, use of 'bool pretty' in testsuite
> [no v5 due to series split]
> v4: rebase to earlier changes, defer type_any() to later
> v3: rebase to earlier changes
> v2: rebase to earlier changes
> ---
> include/qapi/json-output-visitor.h | 5 +-
> qapi/json-output-visitor.c | 15 ++++-
> tests/test-json-output-visitor.c | 124
> +++++++++++++++++++++++++------------
> 3 files changed, 101 insertions(+), 43 deletions(-)
>
> diff --git a/include/qapi/json-output-visitor.h
> b/include/qapi/json-output-visitor.h
> index 41c79f4..94c9e0f 100644
> --- a/include/qapi/json-output-visitor.h
> +++ b/include/qapi/json-output-visitor.h
> @@ -21,8 +21,11 @@ typedef struct JsonOutputVisitor JsonOutputVisitor;
> * If everything else succeeds, pass @result to visit_complete() to
> * collect the result of the visit.
> *
> + * If @pretty, make the output legible with newlines and indentation;
> + * otherwise the output uses a single line.
> + *
> * For now, this cannot be used to visit the 'any' type.
> */
> -Visitor *json_output_visitor_new(char **result);
> +Visitor *json_output_visitor_new(bool pretty, char **result);
>
> #endif
> diff --git a/qapi/json-output-visitor.c b/qapi/json-output-visitor.c
> index 805154a..7d12879 100644
> --- a/qapi/json-output-visitor.c
> +++ b/qapi/json-output-visitor.c
> @@ -17,6 +17,7 @@
> struct JsonOutputVisitor {
> Visitor visitor;
> QString *str;
> + bool pretty;
> bool comma;
> unsigned int depth;
> char **result;
> @@ -30,10 +31,13 @@ static JsonOutputVisitor *to_jov(Visitor *v)
> static void json_output_name(JsonOutputVisitor *jov, const char *name)
> {
> if (jov->comma) {
> - qstring_append(jov->str, ", ");
> + qstring_append(jov->str, jov->pretty ? "," : ", ");
> } else {
> jov->comma = true;
> }
> + if (jov->pretty && jov->depth) {
> + qstring_append_printf(jov->str, "\n%*s", 4 * jov->depth, "");
> + }
> if (name && jov->depth) {
> qstring_append_json_string(jov->str, name);
> qstring_append(jov->str, ": ");
> @@ -57,6 +61,9 @@ static void json_output_end_struct(Visitor *v, void
> **obj)
>
> assert(jov->depth);
> jov->depth--;
> + if (jov->pretty) {
> + qstring_append_printf(jov->str, "\n%*s", 4 * jov->depth, "");
> + }
> qstring_append(jov->str, "}");
> jov->comma = true;
> }
> @@ -85,6 +92,9 @@ static void json_output_end_list(Visitor *v, void **obj)
>
> assert(jov->depth);
> jov->depth--;
> + if (jov->pretty) {
> + qstring_append_printf(jov->str, "\n%*s", 4 * jov->depth, "");
> + }
> qstring_append(jov->str, "]");
> jov->comma = true;
> }
> @@ -165,11 +175,12 @@ static void json_output_free(Visitor *v)
> g_free(jov);
> }
>
> -Visitor *json_output_visitor_new(char **result)
> +Visitor *json_output_visitor_new(bool pretty, char **result)
> {
> JsonOutputVisitor *v;
>
> v = g_malloc0(sizeof(*v));
> + v->pretty = pretty;
> v->result = result;
> *result = NULL;
> v->str = qstring_new();
> diff --git a/tests/test-json-output-visitor.c
> b/tests/test-json-output-visitor.c
> index 3c77a61..849cf2b 100644
> --- a/tests/test-json-output-visitor.c
> +++ b/tests/test-json-output-visitor.c
> @@ -24,13 +24,17 @@
>
> typedef struct TestOutputVisitorData {
> Visitor *ov;
> + bool pretty;
> char *str;
> } TestOutputVisitorData;
>
> static void visitor_output_setup(TestOutputVisitorData *data,
> - const void *unused)
> + const void *arg)
> {
> - data->ov = json_output_visitor_new(&data->str);
> + bool pretty = *(bool *)arg;
> +
>
Have you considered GPOINTER_TO_INT/GINT_TO_POINTER instead of pointers to
the stack frame?
either way, it's fine.
> + data->pretty = pretty;
> + data->ov = json_output_visitor_new(pretty, &data->str);
> g_assert(data->ov);
> }
>
> @@ -52,8 +56,10 @@ static const char *visitor_get(TestOutputVisitorData
> *data)
>
> static void visitor_reset(TestOutputVisitorData *data)
> {
> + bool pretty = data->pretty;
> +
> visitor_output_teardown(data, NULL);
> - visitor_output_setup(data, NULL);
> + visitor_output_setup(data, &pretty);
> }
>
> static void test_visitor_out_int(TestOutputVisitorData *data,
> @@ -161,8 +167,9 @@ static void
> test_visitor_out_struct(TestOutputVisitorData *data,
> }
>
> static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
> - const void *unused)
> + const void *arg)
> {
> + bool pretty = *(bool *)arg;
> int64_t value = 42;
> UserDefTwo *ud2;
> const char *string = "user def string";
> @@ -192,27 +199,51 @@ static void
> test_visitor_out_struct_nested(TestOutputVisitorData *data,
> visit_type_UserDefTwo(data->ov, "unused", &ud2, &error_abort);
>
> out = visitor_get(data);
> - g_assert_cmpstr(out, ==,
> - "{"
> - "\"string0\": \"forty two\", "
> - "\"dict1\": {"
> - "\"string1\": \"forty three\", "
> - "\"dict2\": {"
> - "\"userdef\": {"
> - "\"integer\": 42, "
> - "\"string\": \"user def string\""
> - "}, "
> - "\"string\": \"forty four\""
> - "}, "
> - "\"dict3\": {"
> - "\"userdef\": {"
> - "\"integer\": 42, "
> - "\"string\": \"user def string\""
> - "}, "
> - "\"string\": \"forty five\""
> - "}"
> - "}"
> - "}");
> + if (pretty) {
> + g_assert_cmpstr(out, ==,
> + "{\n"
> + " \"string0\": \"forty two\",\n"
> + " \"dict1\": {\n"
> + " \"string1\": \"forty three\",\n"
> + " \"dict2\": {\n"
> + " \"userdef\": {\n"
> + " \"integer\": 42,\n"
> + " \"string\": \"user def
> string\"\n"
> + " },\n"
> + " \"string\": \"forty four\"\n"
> + " },\n"
> + " \"dict3\": {\n"
> + " \"userdef\": {\n"
> + " \"integer\": 42,\n"
> + " \"string\": \"user def
> string\"\n"
> + " },\n"
> + " \"string\": \"forty five\"\n"
> + " }\n"
> + " }\n"
> + "}");
> + } else {
> + g_assert_cmpstr(out, ==,
> + "{"
> + "\"string0\": \"forty two\", "
> + "\"dict1\": {"
> + "\"string1\": \"forty three\", "
> + "\"dict2\": {"
> + "\"userdef\": {"
> + "\"integer\": 42, "
> + "\"string\": \"user def string\""
> + "}, "
> + "\"string\": \"forty four\""
> + "}, "
> + "\"dict3\": {"
> + "\"userdef\": {"
> + "\"integer\": 42, "
> + "\"string\": \"user def string\""
> + "}, "
> + "\"string\": \"forty five\""
> + "}"
> + "}"
> + "}");
> + }
> qapi_free_UserDefTwo(ud2);
> }
>
> @@ -346,36 +377,49 @@ static void
> test_visitor_out_null(TestOutputVisitorData *data,
> g_assert_cmpstr(out, ==, "null");
> }
>
> -static void output_visitor_test_add(const char *testpath,
> +static void output_visitor_test_add(const char *testpath, bool *data,
> void
> (*test_func)(TestOutputVisitorData *,
> const void *))
> {
> - g_test_add(testpath, TestOutputVisitorData, NULL,
> visitor_output_setup,
> + g_test_add(testpath, TestOutputVisitorData, data,
> visitor_output_setup,
> test_func, visitor_output_teardown);
> }
>
> int main(int argc, char **argv)
> {
> + bool plain = false;
> + bool pretty = true;
> +
> g_test_init(&argc, &argv, NULL);
>
> - output_visitor_test_add("/visitor/json/int", test_visitor_out_int);
> - output_visitor_test_add("/visitor/json/bool", test_visitor_out_bool);
> - output_visitor_test_add("/visitor/json/number",
> test_visitor_out_number);
> - output_visitor_test_add("/visitor/json/string",
> test_visitor_out_string);
> - output_visitor_test_add("/visitor/json/enum", test_visitor_out_enum);
> - output_visitor_test_add("/visitor/json/enum-errors",
> + output_visitor_test_add("/visitor/json/int", &plain,
> + test_visitor_out_int);
> + output_visitor_test_add("/visitor/json/bool", &plain,
> + test_visitor_out_bool);
> + output_visitor_test_add("/visitor/json/number", &plain,
> + test_visitor_out_number);
> + output_visitor_test_add("/visitor/json/string", &plain,
> + test_visitor_out_string);
> + output_visitor_test_add("/visitor/json/enum", &plain,
> + test_visitor_out_enum);
> + output_visitor_test_add("/visitor/json/enum-errors", &plain,
> test_visitor_out_enum_errors);
> - output_visitor_test_add("/visitor/json/struct",
> test_visitor_out_struct);
> - output_visitor_test_add("/visitor/json/struct-nested",
> + output_visitor_test_add("/visitor/json/struct", &plain,
> + test_visitor_out_struct);
> + output_visitor_test_add("/visitor/json/struct-nested", &plain,
> test_visitor_out_struct_nested);
> - output_visitor_test_add("/visitor/json/struct-errors",
> + output_visitor_test_add("/visitor/json-pretty/struct-nested", &pretty,
> + test_visitor_out_struct_nested);
> + output_visitor_test_add("/visitor/json/struct-errors", &plain,
> test_visitor_out_struct_errors);
> - output_visitor_test_add("/visitor/json/list", test_visitor_out_list);
> - output_visitor_test_add("/visitor/json/union-flat",
> + output_visitor_test_add("/visitor/json/list", &plain,
> + test_visitor_out_list);
> + output_visitor_test_add("/visitor/json/union-flat", &plain,
> test_visitor_out_union_flat);
> - output_visitor_test_add("/visitor/json/alternate",
> + output_visitor_test_add("/visitor/json/alternate", &plain,
> test_visitor_out_alternate);
> - output_visitor_test_add("/visitor/json/null", test_visitor_out_null);
> + output_visitor_test_add("/visitor/json/null", &plain,
> + test_visitor_out_null);
>
> g_test_run();
>
> --
> 2.7.4
>
>
> --
Marc-André Lureau
- [Qemu-devel] [PATCH v6 00/15] Add qapi-to-JSON visitor, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 01/15] qapi: Visitor documentation tweak, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 03/15] qapi: Factor out JSON string escaping, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 04/15] qapi: Factor out JSON number formatting, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 05/15] qapi: Add qstring_append_printf(), Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 06/15] qapi: Use qstring_append_chr() where appropriate, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 07/15] qstring: Add qstring_consume_str(), Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 02/15] qapi: Assert finite use of 'number', Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 12/15] qapi: Support pretty printing in JSON output visitor, Eric Blake, 2016/10/10
- Re: [Qemu-devel] [PATCH v6 12/15] qapi: Support pretty printing in JSON output visitor,
Marc-André Lureau <=
- [Qemu-devel] [PATCH v6 11/15] qapi: Add JSON output visitor, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 10/15] tests: Test qobject_to_json() pretty formatting, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 14/15] qapi: Add 'any' support to JSON output, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 13/15] qobject: Implement qobject_to_json() atop JSON visitor, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 09/15] qobject: Consolidate qobject_to_json() calls, Eric Blake, 2016/10/10
- [Qemu-devel] [PATCH v6 08/15] qstring: Add qstring_wrap_str(), Eric Blake, 2016/10/10