/*
* 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
}
+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,
}
+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)
{
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", "");