From 6360c62ec2a0ccfb66346daa3566930111685598 Mon Sep 17 00:00:00 2001
Message-Id: <6360c62ec2a0ccfb66346daa3566930111685598@dist-git>
From: Peter Krempa <pkrempa@redhat.com>
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