Faster version of virJSONValueFromString(virJSONValueToString()). Signed-off-by: Martin Kletzander <mkletzan@xxxxxxxxxx> --- 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 15e71d5..883331f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -1582,6 +1582,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 f070649..c080946 100644 --- a/tests/jsontest.c +++ b/tests/jsontest.c @@ -119,6 +119,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; @@ -180,6 +265,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.4.0 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list