From 6360c62ec2a0ccfb66346daa3566930111685598 Mon Sep 17 00:00:00 2001 Message-Id: <6360c62ec2a0ccfb66346daa3566930111685598@dist-git> From: Peter Krempa Date: Tue, 2 Aug 2016 13:41:44 +0200 Subject: [PATCH] util: qemu: Allow nested objects in JSON -> commandline generator Move the iterator of objects to the recursive function so that nested objects are supported by flattening the structure with '.' delimiters. (cherry picked from commit cd86d6f4656d01894141840531d61595e40e4682) https://bugzilla.redhat.com/show_bug.cgi?id=1134878 [JSON backing] https://bugzilla.redhat.com/show_bug.cgi?id=1247521 [gluster multi-host] --- src/util/virqemu.c | 70 ++++++++++++++++++++++++++++++++++----------- tests/qemucommandutiltest.c | 8 ++++++ 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/src/util/virqemu.c b/src/util/virqemu.c index 99c14c2..df665ad 100644 --- a/src/util/virqemu.c +++ b/src/util/virqemu.c @@ -26,11 +26,49 @@ #include "virerror.h" #include "virlog.h" #include "virqemu.h" +#include "virstring.h" +#include "viralloc.h" #define VIR_FROM_THIS VIR_FROM_NONE VIR_LOG_INIT("util.qemu"); +struct virQEMUCommandLineJSONIteratorData { + const char *prefix; + virBufferPtr buf; +}; + + +static int +virQEMUBuildCommandLineJSONRecurse(const char *key, + const virJSONValue *value, + virBufferPtr buf, + bool nested); + +/* internal iterator to handle nested object formatting */ +static int +virQEMUBuildCommandLineJSONIterate(const char *key, + const virJSONValue *value, + void *opaque) +{ + struct virQEMUCommandLineJSONIteratorData *data = opaque; + char *tmpkey = NULL; + int ret = -1; + + if (data->prefix) { + if (virAsprintf(&tmpkey, "%s.%s", data->prefix, key) < 0) + return -1; + + ret = virQEMUBuildCommandLineJSONRecurse(tmpkey, value, data->buf, false); + + VIR_FREE(tmpkey); + } else { + ret = virQEMUBuildCommandLineJSONRecurse(key, value, data->buf, false); + } + + return ret; +} + static int virQEMUBuildCommandLineJSONRecurse(const char *key, @@ -38,12 +76,19 @@ virQEMUBuildCommandLineJSONRecurse(const char *key, virBufferPtr buf, bool nested) { + struct virQEMUCommandLineJSONIteratorData data = { key, buf }; virJSONValuePtr elem; virBitmapPtr bitmap = NULL; ssize_t pos = -1; ssize_t end; size_t i; + if (!key && value->type != VIR_JSON_TYPE_OBJECT) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("only JSON objects can be top level")); + return -1; + } + switch ((virJSONType) value->type) { case VIR_JSON_TYPE_STRING: virBufferAsprintf(buf, ",%s=", key); @@ -96,10 +141,15 @@ virQEMUBuildCommandLineJSONRecurse(const char *key, break; case VIR_JSON_TYPE_OBJECT: + if (virJSONValueObjectForeachKeyValue(value, + virQEMUBuildCommandLineJSONIterate, + &data) < 0) + return -1; + break; + case VIR_JSON_TYPE_NULL: virReportError(VIR_ERR_INTERNAL_ERROR, "%s", - _("NULL and OBJECT JSON types can't be converted to " - "commandline string")); + _("NULL JSON type can't be converted to commandline")); return -1; } @@ -108,15 +158,6 @@ virQEMUBuildCommandLineJSONRecurse(const char *key, } -static int -virQEMUBuildCommandLineJSONIterate(const char *key, - const virJSONValue *value, - void *opaque) -{ - return virQEMUBuildCommandLineJSONRecurse(key, value, opaque, false); -} - - /** * virQEMUBuildCommandLineJSON: * @value: json object containing the value @@ -131,12 +172,7 @@ int virQEMUBuildCommandLineJSON(const virJSONValue *value, virBufferPtr buf) { - if (virJSONValueObjectForeachKeyValue(value, - virQEMUBuildCommandLineJSONIterate, - buf) < 0) - return -1; - - return 0; + return virQEMUBuildCommandLineJSONRecurse(NULL, value, buf, false); } diff --git a/tests/qemucommandutiltest.c b/tests/qemucommandutiltest.c index 8299462..4872ea3 100644 --- a/tests/qemucommandutiltest.c +++ b/tests/qemucommandutiltest.c @@ -117,6 +117,14 @@ mymain(void) "array=bleah,array=qwerty,array=1"); DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"boolean\":true,\"hyphen-name\":1234,\"some_string\":\"bleah\"}", "boolean=yes,hyphen-name=1234,some_string=bleah"); + DO_TEST_COMMAND_OBJECT_FROM_JSON("{\"nest\": {\"boolean\":true," + "\"hyphen-name\":1234," + "\"some_string\":\"bleah\"," + "\"bleah\":\"bl,eah\"" + "}" + "}", + "nest.boolean=yes,nest.hyphen-name=1234," + "nest.some_string=bleah,nest.bleah=bl,,eah"); return ret; -- 2.9.2