Faster version of virJSONValueFromString(virJSONValueToString()).
Signed-off-by: Martin Kletzander <mkletzan(a)redhat.com>
---
src/libvirt_private.syms | 1 +
src/util/virjson.c | 65 ++++++++++++++++++++++++++-
src/util/virjson.h | 4 +-
tests/jsontest.c | 111 +++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 179 insertions(+), 2 deletions(-)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index aafc385..0335313 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1573,6 +1573,7 @@ virJSONValueArrayAppend;
virJSONValueArrayGet;
virJSONValueArraySize;
virJSONValueArraySteal;
+virJSONValueCopy;
virJSONValueFree;
virJSONValueFromString;
virJSONValueGetArrayAsBitmap;
diff --git a/src/util/virjson.c b/src/util/virjson.c
index c8d761f..40ec613 100644
--- a/src/util/virjson.c
+++ b/src/util/virjson.c
@@ -1,7 +1,7 @@
/*
* virjson.c: JSON object parsing/formatting
*
- * Copyright (C) 2009-2010, 2012-2013 Red Hat, Inc.
+ * Copyright (C) 2009-2010, 2012-2015 Red Hat, Inc.
* Copyright (C) 2009 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -1233,6 +1233,69 @@ virJSONValueObjectForeachKeyValue(virJSONValuePtr object,
}
+virJSONValuePtr
+virJSONValueCopy(virJSONValuePtr in)
+{
+ size_t i;
+ virJSONValuePtr out = NULL;
+
+ if (!in)
+ return NULL;
+
+ switch ((virJSONType) in->type) {
+ case VIR_JSON_TYPE_OBJECT:
+ out = virJSONValueNewObject();
+ if (!out)
+ return NULL;
+ for (i = 0; i < in->data.object.npairs; i++) {
+ virJSONValuePtr val = NULL;
+ if (!(val = virJSONValueCopy(in->data.object.pairs[i].value)))
+ goto error;
+ if (virJSONValueObjectAppend(out, in->data.object.pairs[i].key,
+ val) < 0) {
+ virJSONValueFree(val);
+ goto error;
+ }
+ }
+ break;
+ case VIR_JSON_TYPE_ARRAY:
+ out = virJSONValueNewArray();
+ if (!out)
+ return NULL;
+ for (i = 0; i < in->data.array.nvalues; i++) {
+ virJSONValuePtr val = NULL;
+ if (!(val = virJSONValueCopy(in->data.array.values[i])))
+ goto error;
+ if (virJSONValueArrayAppend(out, val) < 0) {
+ virJSONValueFree(val);
+ goto error;
+ }
+ }
+ break;
+
+ /* No need to error out in the following cases */
+ case VIR_JSON_TYPE_STRING:
+ out = virJSONValueNewString(in->data.string);
+ break;
+ case VIR_JSON_TYPE_NUMBER:
+ out = virJSONValueNewNumber(in->data.number);
+ break;
+ case VIR_JSON_TYPE_BOOLEAN:
+ out = virJSONValueNewBoolean(in->data.boolean);
+ break;
+ case VIR_JSON_TYPE_NULL:
+ out = virJSONValueNewNull();
+ break;
+ }
+
+ return out;
+
+ error:
+ virJSONValueFree(out);
+ return NULL;
+}
+
+
#if WITH_YAJL
static int
virJSONParserInsertValue(virJSONParserPtr parser,
diff --git a/src/util/virjson.h b/src/util/virjson.h
index 9bb7461..e871b2e 100644
--- a/src/util/virjson.h
+++ b/src/util/virjson.h
@@ -1,7 +1,7 @@
/*
* virjson.h: JSON object parsing/formatting
*
- * Copyright (C) 2009, 2012-2013 Red Hat, Inc.
+ * Copyright (C) 2009, 2012-2015 Red Hat, Inc.
* Copyright (C) 2009 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -165,4 +165,6 @@ int virJSONValueObjectForeachKeyValue(virJSONValuePtr object,
virJSONValueObjectIteratorFunc cb,
void *opaque);
+virJSONValuePtr virJSONValueCopy(virJSONValuePtr in);
+
#endif /* __VIR_JSON_H_ */
diff --git a/tests/jsontest.c b/tests/jsontest.c
index a2a42e3..fca960f 100644
--- a/tests/jsontest.c
+++ b/tests/jsontest.c
@@ -131,6 +131,91 @@ testJSONAddRemove(const void *data)
static int
+testJSONCopy(const void *data)
+{
+ const struct testInfo *info = data;
+ virJSONValuePtr json = NULL;
+ virJSONValuePtr jsonCopy = NULL;
+ char *result = NULL;
+ char *resultCopy = NULL;
+ int ret = -1;
+
+ json = virJSONValueFromString(info->doc);
+ if (!json) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to parse %s\n", info->doc);
+ ret = -1;
+ goto cleanup;
+ }
+
+ jsonCopy = virJSONValueCopy(json);
+ if (!jsonCopy) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to copy JSON data\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ result = virJSONValueToString(json, false);
+ if (!result) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to format original JSON data\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ resultCopy = virJSONValueToString(json, false);
+ if (!resultCopy) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to format copied JSON data\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (STRNEQ(result, resultCopy)) {
+ if (virTestGetVerbose())
+ virtTestDifference(stderr, result, resultCopy);
+ ret = -1;
+ goto cleanup;
+ }
+
+ VIR_FREE(result);
+ VIR_FREE(resultCopy);
+
+ result = virJSONValueToString(json, true);
+ if (!result) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to format original JSON data\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ resultCopy = virJSONValueToString(json, true);
+ if (!resultCopy) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "Failed to format copied JSON data\n");
+ ret = -1;
+ goto cleanup;
+ }
+
+ if (STRNEQ(result, resultCopy)) {
+ if (virTestGetVerbose())
+ virtTestDifference(stderr, result, resultCopy);
+ ret = -1;
+ goto cleanup;
+ }
+
+ ret = 0;
+ cleanup:
+ VIR_FREE(result);
+ VIR_FREE(resultCopy);
+ virJSONValueFree(json);
+ virJSONValueFree(jsonCopy);
+ return ret;
+}
+
+
+static int
mymain(void)
{
int ret = 0;
@@ -192,6 +277,32 @@ mymain(void)
DO_TEST_FULL("add and remove", AddRemove,
"[ 1 ]", NULL, false);
+ DO_TEST_FULL("copy and free", Copy,
+ "{\"return\": [{\"name\": \"quit\"},
{\"name\": \"eject\"},"
+ "{\"name\": \"change\"}, {\"name\":
\"screendump\"},"
+ "{\"name\": \"stop\"}, {\"name\":
\"cont\"}, {\"name\": "
+ "\"system_reset\"}, {\"name\":
\"system_powerdown\"}, "
+ "{\"name\": \"device_add\"},
{\"name\": \"device_del\"}, "
+ "{\"name\": \"cpu\"}, {\"name\":
\"memsave\"}, {\"name\": "
+ "\"pmemsave\"}, {\"name\":
\"migrate\"}, {\"name\": "
+ "\"migrate_cancel\"}, {\"name\":
\"migrate_set_speed\"},"
+ "{\"name\": \"client_migrate_info\"},
{\"name\": "
+ "\"migrate_set_downtime\"}, {\"name\":
\"netdev_add\"}, "
+ "{\"name\": \"netdev_del\"},
{\"name\": \"block_resize\"},"
+ "{\"name\": \"balloon\"}, {\"name\":
\"set_link\"}, {\"name\":"
+ "\"getfd\"}, {\"name\": \"closefd\"},
{\"name\": \"block_passwd\"},"
+ "{\"name\": \"set_password\"},
{\"name\": \"expire_password\"},"
+ "{\"name\": \"qmp_capabilities\"},
{\"name\": "
+ "\"human-monitor-command\"}, {\"name\":
\"query-version\"},"
+ "{\"name\": \"query-commands\"},
{\"name\": \"query-chardev\"},"
+ "{\"name\": \"query-block\"},
{\"name\": \"query-blockstats\"}, "
+ "{\"name\": \"query-cpus\"},
{\"name\": \"query-pci\"}, {\"name\":"
+ "\"query-kvm\"}, {\"name\":
\"query-status\"}, {\"name\": "
+ "\"query-mice\"}, {\"name\":
\"query-vnc\"}, {\"name\": "
+ "\"query-spice\"}, {\"name\":
\"query-name\"}, {\"name\": "
+ "\"query-uuid\"}, {\"name\":
\"query-migrate\"}, {\"name\": "
+ "\"query-balloon\"}], \"id\":
\"libvirt-2\"}", NULL, true);
+
DO_TEST_PARSE("almost nothing", "[]");
DO_TEST_PARSE_FAIL("nothing", "");
--
2.3.5