/*
* virjson.c: JSON object parsing/formatting
*
- * Copyright (C) 2009-2010, 2012 Red Hat, Inc.
+ * Copyright (C) 2009-2010, 2012-2013 Red Hat, Inc.
* Copyright (C) 2009 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
return object->data.object.pairs[n].key;
}
+/* Remove the key-value pair tied to @key out of @object. If @value is
+ * not NULL, the dropped value object is returned instead of freed.
+ * Returns 1 on success, 0 if no key was found, and -1 on error. */
+int
+virJSONValueObjectRemoveKey(virJSONValuePtr object, const char *key,
+ virJSONValuePtr *value)
+{
+ int i;
+
+ if (value)
+ *value = NULL;
+
+ if (object->type != VIR_JSON_TYPE_OBJECT)
+ return -1;
+
+ for (i = 0 ; i < object->data.object.npairs ; i++) {
+ if (STREQ(object->data.object.pairs[i].key, key)) {
+ if (value) {
+ *value = object->data.object.pairs[i].value;
+ object->data.object.pairs[i].value = NULL;
+ }
+ VIR_FREE(object->data.object.pairs[i].key);
+ virJSONValueFree(object->data.object.pairs[i].value);
+ VIR_DELETE_ELEMENT(object->data.object.pairs, i,
+ object->data.object.npairs);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
virJSONValuePtr virJSONValueObjectGetValue(virJSONValuePtr object, unsigned int n)
{
if (object->type != VIR_JSON_TYPE_OBJECT)
/*
* virjson.h: JSON object parsing/formatting
*
- * Copyright (C) 2009, 2012 Red Hat, Inc.
+ * Copyright (C) 2009, 2012-2013 Red Hat, Inc.
* Copyright (C) 2009 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
};
struct _virJSONObject {
- unsigned int npairs;
+ size_t npairs;
virJSONObjectPairPtr pairs;
};
struct _virJSONArray {
- unsigned int nvalues;
+ size_t nvalues;
virJSONValuePtr *values;
};
int virJSONValueObjectAppendBoolean(virJSONValuePtr object, const char *key, int boolean);
int virJSONValueObjectAppendNull(virJSONValuePtr object, const char *key);
+int virJSONValueObjectRemoveKey(virJSONValuePtr object, const char *key,
+ virJSONValuePtr *value)
+ ATTRIBUTE_NONNULL(1) ATTRIBUTE_NONNULL(2);
+
virJSONValuePtr virJSONValueFromString(const char *jsonstring);
char *virJSONValueToString(virJSONValuePtr object,
bool pretty);
struct testInfo {
const char *doc;
+ const char *expect;
bool pass;
};
}
+static int
+testJSONAddRemove(const void *data)
+{
+ const struct testInfo *info = data;
+ virJSONValuePtr json;
+ virJSONValuePtr name;
+ char *result = NULL;
+ int ret = -1;
+
+ json = virJSONValueFromString(info->doc);
+
+ switch (virJSONValueObjectRemoveKey(json, "name", &name)) {
+ case 1:
+ if (!info->pass) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "should not remove from non-object %s\n",
+ info->doc);
+ goto cleanup;
+ }
+ break;
+ case -1:
+ if (!info->pass)
+ ret = 0;
+ else if (virTestGetVerbose())
+ fprintf(stderr, "Fail to recognize non-object %s\n", info->doc);
+ goto cleanup;
+ default:
+ if (virTestGetVerbose())
+ fprintf(stderr, "unexpected result when removing from %s\n",
+ info->doc);
+ goto cleanup;
+ }
+ if (STRNEQ_NULLABLE(virJSONValueGetString(name), "sample")) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "unexpected value after removing name: %s\n",
+ NULLSTR(virJSONValueGetString(name)));
+ goto cleanup;
+ }
+ if (virJSONValueObjectRemoveKey(json, "name", NULL)) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "%s",
+ "unexpected success when removing missing key\n");
+ goto cleanup;
+ }
+ if (virJSONValueObjectAppendString(json, "newname", "foo") < 0) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "%s", "unexpected failure adding new key\n");
+ goto cleanup;
+ }
+ if (!(result = virJSONValueToString(json, false))) {
+ if (virTestGetVerbose())
+ fprintf(stderr, "%s", "failed to stringize result\n");
+ goto cleanup;
+ }
+ if (STRNEQ(info->expect, result)) {
+ if (virTestGetVerbose())
+ virtTestDifference(stderr, info->expect, result);
+ goto cleanup;
+ }
+ ret = 0;
+
+cleanup:
+ virJSONValueFree(json);
+ virJSONValueFree(name);
+ VIR_FREE(result);
+ return ret;
+}
+
+
static int
mymain(void)
{
int ret = 0;
-#define DO_TEST_FULL(name, cmd, doc, pass) \
+#define DO_TEST_FULL(name, cmd, doc, expect, pass) \
do { \
- struct testInfo info = { doc, pass }; \
+ struct testInfo info = { doc, expect, pass }; \
if (virtTestRun(name, 1, testJSON ## cmd, &info) < 0) \
ret = -1; \
} while (0)
#define DO_TEST_PARSE(name, doc) \
- DO_TEST_FULL(name, FromString, doc, true)
+ DO_TEST_FULL(name, FromString, doc, NULL, true)
DO_TEST_PARSE("Simple", "{\"return\": {}, \"id\": \"libvirt-1\"}");
DO_TEST_PARSE("NotSoSimple", "{\"QMP\": {\"version\": {\"qemu\":"
"\"query-uuid\"}, {\"name\": \"query-migrate\"}, {\"name\": "
"\"query-balloon\"}], \"id\": \"libvirt-2\"}");
+ DO_TEST_FULL("add and remove", AddRemove,
+ "{\"name\": \"sample\", \"value\": true}",
+ "{\"value\":true,\"newname\":\"foo\"}",
+ true);
+ DO_TEST_FULL("add and remove", AddRemove,
+ "[ 1 ]", NULL, false);
+
return (ret == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}