util: add virJSONValueCopy

Faster version of virJSONValueFromString(virJSONValueToString()).

Signed-off-by: Martin Kletzander <mkletzan@redhat.com>
This commit is contained in:
Martin Kletzander 2014-08-21 12:23:41 +02:00
parent 366c22f2bc
commit d9a610f90c
4 changed files with 179 additions and 2 deletions

View File

@ -1585,6 +1585,7 @@ virJSONValueArrayAppend;
virJSONValueArrayGet;
virJSONValueArraySize;
virJSONValueArraySteal;
virJSONValueCopy;
virJSONValueFree;
virJSONValueFromString;
virJSONValueGetArrayAsBitmap;

View File

@ -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,

View File

@ -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_ */

View File

@ -118,6 +118,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)
{
@ -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", "");