Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-10-25' into staging
QAPI patches for 2016-10-25
# gpg: Signature made Tue 25 Oct 2016 16:56:27 BST
# gpg: using RSA key 0x3870B400EB918653
# gpg: Good signature from "Markus Armbruster <armbru@redhat.com>"
# gpg: aka "Markus Armbruster <armbru@pond.sub.org>"
# Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653
* remotes/armbru/tags/pull-qapi-2016-10-25:
qdict: implement a qdict_crumple method for un-flattening a dict
qapi: don't pass two copies of TestInputVisitorData to tests
qapi: rename QmpOutputVisitor to QObjectOutputVisitor
qapi: rename QmpInputVisitor to QObjectInputVisitor
qapi: rename *qmp-*-visitor* to *qobject-*-visitor*
qapi: add trace events for visitor
trivial: Restore blank line in qapi-schema
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/Makefile.objs b/Makefile.objs
index 69fdd48..82e8a1e 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -162,3 +162,4 @@
trace-events-y += target-ppc/trace-events
trace-events-y += qom/trace-events
trace-events-y += linux-user/trace-events
+trace-events-y += qapi/trace-events
diff --git a/block/qapi.c b/block/qapi.c
index 50d3090..a62e862 100644
--- a/block/qapi.c
+++ b/block/qapi.c
@@ -29,7 +29,7 @@
#include "block/write-threshold.h"
#include "qmp-commands.h"
#include "qapi-visit.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/types.h"
#include "sysemu/block-backend.h"
#include "qemu/cutils.h"
@@ -691,7 +691,7 @@
ImageInfoSpecific *info_spec)
{
QObject *obj, *data;
- Visitor *v = qmp_output_visitor_new(&obj);
+ Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfoSpecific(v, NULL, &info_spec, &error_abort);
visit_complete(v, &obj);
diff --git a/blockdev.c b/blockdev.c
index 07ec733..d11a74f 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -43,7 +43,7 @@
#include "qapi/qmp/types.h"
#include "qapi-visit.h"
#include "qapi/qmp/qerror.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/util.h"
#include "sysemu/sysemu.h"
#include "block/block_int.h"
@@ -3776,7 +3776,7 @@
{
BlockDriverState *bs;
QObject *obj;
- Visitor *v = qmp_output_visitor_new(&obj);
+ Visitor *v = qobject_output_visitor_new(&obj);
QDict *qdict;
Error *local_err = NULL;
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 5d4c2cd..2841c51 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -1005,7 +1005,7 @@
Error *err = NULL;
Visitor *v;
- v = qmp_output_visitor_new(ret_out);
+ v = qobject_output_visitor_new(ret_out);
visit_type_UserDefOne(v, "unused", &ret_in, &err);
if (!err) {
visit_complete(v, ret_out);
@@ -1024,7 +1024,7 @@
Visitor *v;
UserDefOneList *arg1 = NULL;
- v = qmp_input_visitor_new(QOBJECT(args), true);
+ v = qobject_input_visitor_new(QOBJECT(args), true);
visit_start_struct(v, NULL, NULL, 0, &err);
if (err) {
goto out;
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 71b8eb0..fe9a4c5 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -73,6 +73,7 @@
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
void qdict_array_split(QDict *src, QList **dst);
int qdict_array_entries(QDict *src, const char *subqdict);
+QObject *qdict_crumple(const QDict *src, Error **errp);
void qdict_join(QDict *dest, QDict *src, bool overwrite);
diff --git a/include/qapi/qmp-input-visitor.h b/include/qapi/qobject-input-visitor.h
similarity index 64%
rename from include/qapi/qmp-input-visitor.h
rename to include/qapi/qobject-input-visitor.h
index f3ff5f3..cde328d 100644
--- a/include/qapi/qmp-input-visitor.h
+++ b/include/qapi/qobject-input-visitor.h
@@ -11,20 +11,20 @@
*
*/
-#ifndef QMP_INPUT_VISITOR_H
-#define QMP_INPUT_VISITOR_H
+#ifndef QOBJECT_INPUT_VISITOR_H
+#define QOBJECT_INPUT_VISITOR_H
#include "qapi/visitor.h"
#include "qapi/qmp/qobject.h"
-typedef struct QmpInputVisitor QmpInputVisitor;
+typedef struct QObjectInputVisitor QObjectInputVisitor;
/*
- * Return a new input visitor that converts QMP to QAPI.
+ * Return a new input visitor that converts a QObject to a QAPI object.
*
* Set @strict to reject a parse that doesn't consume all keys of a
* dictionary; otherwise excess input is ignored.
*/
-Visitor *qmp_input_visitor_new(QObject *obj, bool strict);
+Visitor *qobject_input_visitor_new(QObject *obj, bool strict);
#endif
diff --git a/include/qapi/qmp-output-visitor.h b/include/qapi/qobject-output-visitor.h
similarity index 66%
rename from include/qapi/qmp-output-visitor.h
rename to include/qapi/qobject-output-visitor.h
index 040fdda..8241877 100644
--- a/include/qapi/qmp-output-visitor.h
+++ b/include/qapi/qobject-output-visitor.h
@@ -11,20 +11,20 @@
*
*/
-#ifndef QMP_OUTPUT_VISITOR_H
-#define QMP_OUTPUT_VISITOR_H
+#ifndef QOBJECT_OUTPUT_VISITOR_H
+#define QOBJECT_OUTPUT_VISITOR_H
#include "qapi/visitor.h"
#include "qapi/qmp/qobject.h"
-typedef struct QmpOutputVisitor QmpOutputVisitor;
+typedef struct QObjectOutputVisitor QObjectOutputVisitor;
/*
- * Create a new QMP output visitor.
+ * Create a new QObject output visitor.
*
* If everything else succeeds, pass @result to visit_complete() to
* collect the result of the visit.
*/
-Visitor *qmp_output_visitor_new(QObject **result);
+Visitor *qobject_output_visitor_new(QObject **result);
#endif
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index 6c77a91..9bb6cba 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -25,14 +25,14 @@
* for doing work at each node of a QAPI graph; it can also be used
* for a virtual walk, where there is no actual QAPI C struct.
*
- * There are four kinds of visitor classes: input visitors (QMP,
+ * There are four kinds of visitor classes: input visitors (QObject,
* string, and QemuOpts) parse an external representation and build
- * the corresponding QAPI graph, output visitors (QMP and string) take
+ * the corresponding QAPI graph, output visitors (QObject and string) take
* a completed QAPI graph and generate an external representation, the
* dealloc visitor can take a QAPI graph (possibly partially
* constructed) and recursively free its resources, and the clone
* visitor performs a deep clone of one QAPI object to another. While
- * the dealloc and QMP input/output visitors are general, the string,
+ * the dealloc and QObject input/output visitors are general, the string,
* QemuOpts, and clone visitors have some implementation limitations;
* see the documentation for each visitor for more details on what it
* supports. Also, see visitor-impl.h for the callback contracts
diff --git a/monitor.c b/monitor.c
index b73a999..21dcfb2 100644
--- a/monitor.c
+++ b/monitor.c
@@ -950,7 +950,7 @@
* directly into QObject instead of first parsing it with
* visit_type_SchemaInfoList() into a SchemaInfoList, then marshal it
* to QObject with generated output marshallers, every time. Instead,
- * we do it in test-qmp-input-visitor.c, just to make sure
+ * we do it in test-qobject-input-visitor.c, just to make sure
* qapi-introspect.py's output actually conforms to the schema.
*/
static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
diff --git a/qapi-schema.json b/qapi-schema.json
index 5a8ec38..d6a43a1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -737,6 +737,7 @@
'*tls-hostname': 'str',
'*max-bandwidth': 'int',
'*downtime-limit': 'int'} }
+
##
# @query-migrate-parameters
#
diff --git a/qapi/Makefile.objs b/qapi/Makefile.objs
index 7ea4aeb..33906ff 100644
--- a/qapi/Makefile.objs
+++ b/qapi/Makefile.objs
@@ -1,5 +1,5 @@
-util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
-util-obj-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
+util-obj-y = qapi-visit-core.o qapi-dealloc-visitor.o qobject-input-visitor.o
+util-obj-y += qobject-output-visitor.o qmp-registry.o qmp-dispatch.o
util-obj-y += string-input-visitor.o string-output-visitor.o
util-obj-y += opts-visitor.o qapi-clone-visitor.o
util-obj-y += qmp-event.o
diff --git a/qapi/qapi-clone-visitor.c b/qapi/qapi-clone-visitor.c
index 0bb8216..34086cb 100644
--- a/qapi/qapi-clone-visitor.c
+++ b/qapi/qapi-clone-visitor.c
@@ -110,7 +110,7 @@
assert(qcv->depth);
/*
* Pointer was already cloned by g_memdup; create fresh copy.
- * Note that as long as qmp-output-visitor accepts NULL instead of
+ * Note that as long as qobject-output-visitor accepts NULL instead of
* "", then we must do likewise. However, we want to obey the
* input visitor semantics of never producing NULL when the empty
* string is intended.
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 55f5876..63bd97b 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -19,10 +19,12 @@
#include "qapi/qmp/qerror.h"
#include "qapi/visitor.h"
#include "qapi/visitor-impl.h"
+#include "trace.h"
void visit_complete(Visitor *v, void *opaque)
{
assert(v->type != VISITOR_OUTPUT || v->complete);
+ trace_visit_complete(v, opaque);
if (v->complete) {
v->complete(v, opaque);
}
@@ -30,6 +32,7 @@
void visit_free(Visitor *v)
{
+ trace_visit_free(v);
if (v) {
v->free(v);
}
@@ -40,6 +43,7 @@
{
Error *err = NULL;
+ trace_visit_start_struct(v, name, obj, size);
if (obj) {
assert(size);
assert(!(v->type & VISITOR_OUTPUT) || *obj);
@@ -53,6 +57,7 @@
void visit_check_struct(Visitor *v, Error **errp)
{
+ trace_visit_check_struct(v);
if (v->check_struct) {
v->check_struct(v, errp);
}
@@ -60,6 +65,7 @@
void visit_end_struct(Visitor *v, void **obj)
{
+ trace_visit_end_struct(v, obj);
v->end_struct(v, obj);
}
@@ -69,6 +75,7 @@
Error *err = NULL;
assert(!list || size >= sizeof(GenericList));
+ trace_visit_start_list(v, name, list, size);
v->start_list(v, name, list, size, &err);
if (list && (v->type & VISITOR_INPUT)) {
assert(!(err && *list));
@@ -79,11 +86,13 @@
GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
{
assert(tail && size >= sizeof(GenericList));
+ trace_visit_next_list(v, tail, size);
return v->next_list(v, tail, size);
}
void visit_end_list(Visitor *v, void **obj)
{
+ trace_visit_end_list(v, obj);
v->end_list(v, obj);
}
@@ -95,6 +104,7 @@
assert(obj && size >= sizeof(GenericAlternate));
assert(!(v->type & VISITOR_OUTPUT) || *obj);
+ trace_visit_start_alternate(v, name, obj, size, promote_int);
if (v->start_alternate) {
v->start_alternate(v, name, obj, size, promote_int, &err);
}
@@ -106,6 +116,7 @@
void visit_end_alternate(Visitor *v, void **obj)
{
+ trace_visit_end_alternate(v, obj);
if (v->end_alternate) {
v->end_alternate(v, obj);
}
@@ -113,6 +124,7 @@
bool visit_optional(Visitor *v, const char *name, bool *present)
{
+ trace_visit_optional(v, name, present);
if (v->optional) {
v->optional(v, name, present);
}
@@ -127,6 +139,7 @@
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
{
assert(obj);
+ trace_visit_type_int(v, name, obj);
v->type_int64(v, name, obj, errp);
}
@@ -150,7 +163,10 @@
void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint8(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
*obj = value;
}
@@ -158,7 +174,10 @@
void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint16(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
*obj = value;
}
@@ -166,7 +185,10 @@
void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
Error **errp)
{
- uint64_t value = *obj;
+ uint64_t value;
+
+ trace_visit_type_uint32(v, name, obj);
+ value = *obj;
visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
*obj = value;
}
@@ -175,6 +197,7 @@
Error **errp)
{
assert(obj);
+ trace_visit_type_uint64(v, name, obj);
v->type_uint64(v, name, obj, errp);
}
@@ -198,7 +221,10 @@
void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int8(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
*obj = value;
}
@@ -206,7 +232,10 @@
void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int16(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
*obj = value;
}
@@ -214,7 +243,10 @@
void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
Error **errp)
{
- int64_t value = *obj;
+ int64_t value;
+
+ trace_visit_type_int32(v, name, obj);
+ value = *obj;
visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
*obj = value;
}
@@ -223,6 +255,7 @@
Error **errp)
{
assert(obj);
+ trace_visit_type_int64(v, name, obj);
v->type_int64(v, name, obj, errp);
}
@@ -230,6 +263,7 @@
Error **errp)
{
assert(obj);
+ trace_visit_type_size(v, name, obj);
if (v->type_size) {
v->type_size(v, name, obj, errp);
} else {
@@ -240,6 +274,7 @@
void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
{
assert(obj);
+ trace_visit_type_bool(v, name, obj);
v->type_bool(v, name, obj, errp);
}
@@ -252,6 +287,7 @@
* can enable:
assert(!(v->type & VISITOR_OUTPUT) || *obj);
*/
+ trace_visit_type_str(v, name, obj);
v->type_str(v, name, obj, &err);
if (v->type & VISITOR_INPUT) {
assert(!err != !*obj);
@@ -263,6 +299,7 @@
Error **errp)
{
assert(obj);
+ trace_visit_type_number(v, name, obj);
v->type_number(v, name, obj, errp);
}
@@ -272,6 +309,7 @@
assert(obj);
assert(v->type != VISITOR_OUTPUT || *obj);
+ trace_visit_type_any(v, name, obj);
v->type_any(v, name, obj, &err);
if (v->type == VISITOR_INPUT) {
assert(!err != !*obj);
@@ -281,6 +319,7 @@
void visit_type_null(Visitor *v, const char *name, Error **errp)
{
+ trace_visit_type_null(v, name);
v->type_null(v, name, errp);
}
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
deleted file mode 100644
index 37a8e1f..0000000
--- a/qapi/qmp-input-visitor.c
+++ /dev/null
@@ -1,455 +0,0 @@
-/*
- * Input Visitor
- *
- * Copyright (C) 2012-2016 Red Hat, Inc.
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/error.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/visitor-impl.h"
-#include "qemu/queue.h"
-#include "qemu-common.h"
-#include "qapi/qmp/types.h"
-#include "qapi/qmp/qerror.h"
-
-#define QIV_STACK_SIZE 1024
-
-typedef struct StackObject
-{
- QObject *obj; /* Object being visited */
- void *qapi; /* sanity check that caller uses same pointer */
-
- GHashTable *h; /* If obj is dict: unvisited keys */
- const QListEntry *entry; /* If obj is list: unvisited tail */
-
- QSLIST_ENTRY(StackObject) node;
-} StackObject;
-
-struct QmpInputVisitor
-{
- Visitor visitor;
-
- /* Root of visit at visitor creation. */
- QObject *root;
-
- /* Stack of objects being visited (all entries will be either
- * QDict or QList). */
- QSLIST_HEAD(, StackObject) stack;
-
- /* True to reject parse in visit_end_struct() if unvisited keys remain. */
- bool strict;
-};
-
-static QmpInputVisitor *to_qiv(Visitor *v)
-{
- return container_of(v, QmpInputVisitor, visitor);
-}
-
-static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
- const char *name,
- bool consume, Error **errp)
-{
- StackObject *tos;
- QObject *qobj;
- QObject *ret;
-
- if (QSLIST_EMPTY(&qiv->stack)) {
- /* Starting at root, name is ignored. */
- assert(qiv->root);
- return qiv->root;
- }
-
- /* We are in a container; find the next element. */
- tos = QSLIST_FIRST(&qiv->stack);
- qobj = tos->obj;
- assert(qobj);
-
- if (qobject_type(qobj) == QTYPE_QDICT) {
- assert(name);
- ret = qdict_get(qobject_to_qdict(qobj), name);
- if (tos->h && consume && ret) {
- bool removed = g_hash_table_remove(tos->h, name);
- assert(removed);
- }
- if (!ret) {
- error_setg(errp, QERR_MISSING_PARAMETER, name);
- }
- } else {
- assert(qobject_type(qobj) == QTYPE_QLIST);
- assert(!name);
- ret = qlist_entry_obj(tos->entry);
- assert(ret);
- if (consume) {
- tos->entry = qlist_next(tos->entry);
- }
- }
-
- return ret;
-}
-
-static void qdict_add_key(const char *key, QObject *obj, void *opaque)
-{
- GHashTable *h = opaque;
- g_hash_table_insert(h, (gpointer) key, NULL);
-}
-
-static const QListEntry *qmp_input_push(QmpInputVisitor *qiv, QObject *obj,
- void *qapi, Error **errp)
-{
- GHashTable *h;
- StackObject *tos = g_new0(StackObject, 1);
-
- assert(obj);
- tos->obj = obj;
- tos->qapi = qapi;
-
- if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
- h = g_hash_table_new(g_str_hash, g_str_equal);
- qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
- tos->h = h;
- } else if (qobject_type(obj) == QTYPE_QLIST) {
- tos->entry = qlist_first(qobject_to_qlist(obj));
- }
-
- QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
- return tos->entry;
-}
-
-
-static void qmp_input_check_struct(Visitor *v, Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = QSLIST_FIRST(&qiv->stack);
-
- assert(tos && !tos->entry);
- if (qiv->strict) {
- GHashTable *const top_ht = tos->h;
- if (top_ht) {
- GHashTableIter iter;
- const char *key;
-
- g_hash_table_iter_init(&iter, top_ht);
- if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
- error_setg(errp, QERR_QMP_EXTRA_MEMBER, key);
- }
- }
- }
-}
-
-static void qmp_input_stack_object_free(StackObject *tos)
-{
- if (tos->h) {
- g_hash_table_unref(tos->h);
- }
-
- g_free(tos);
-}
-
-static void qmp_input_pop(Visitor *v, void **obj)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- StackObject *tos = QSLIST_FIRST(&qiv->stack);
-
- assert(tos && tos->qapi == obj);
- QSLIST_REMOVE_HEAD(&qiv->stack, node);
- qmp_input_stack_object_free(tos);
-}
-
-static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
- size_t size, Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- Error *err = NULL;
-
- if (obj) {
- *obj = NULL;
- }
- if (!qobj) {
- return;
- }
- if (qobject_type(qobj) != QTYPE_QDICT) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "QDict");
- return;
- }
-
- qmp_input_push(qiv, qobj, obj, &err);
- if (err) {
- error_propagate(errp, err);
- return;
- }
-
- if (obj) {
- *obj = g_malloc0(size);
- }
-}
-
-
-static void qmp_input_start_list(Visitor *v, const char *name,
- GenericList **list, size_t size, Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- const QListEntry *entry;
-
- if (!qobj) {
- return;
- }
- if (qobject_type(qobj) != QTYPE_QLIST) {
- if (list) {
- *list = NULL;
- }
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "list");
- return;
- }
-
- entry = qmp_input_push(qiv, qobj, list, errp);
- if (list) {
- if (entry) {
- *list = g_malloc0(size);
- } else {
- *list = NULL;
- }
- }
-}
-
-static GenericList *qmp_input_next_list(Visitor *v, GenericList *tail,
- size_t size)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- StackObject *so = QSLIST_FIRST(&qiv->stack);
-
- if (!so->entry) {
- return NULL;
- }
- tail->next = g_malloc0(size);
- return tail->next;
-}
-
-
-static void qmp_input_start_alternate(Visitor *v, const char *name,
- GenericAlternate **obj, size_t size,
- bool promote_int, Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, false, errp);
-
- if (!qobj) {
- *obj = NULL;
- return;
- }
- *obj = g_malloc0(size);
- (*obj)->type = qobject_type(qobj);
- if (promote_int && (*obj)->type == QTYPE_QINT) {
- (*obj)->type = QTYPE_QFLOAT;
- }
-}
-
-static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
- Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- QInt *qint;
-
- if (!qobj) {
- return;
- }
- qint = qobject_to_qint(qobj);
- if (!qint) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "integer");
- return;
- }
-
- *obj = qint_get_int(qint);
-}
-
-static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
- Error **errp)
-{
- /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- QInt *qint;
-
- if (!qobj) {
- return;
- }
- qint = qobject_to_qint(qobj);
- if (!qint) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "integer");
- return;
- }
-
- *obj = qint_get_int(qint);
-}
-
-static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
- Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- QBool *qbool;
-
- if (!qobj) {
- return;
- }
- qbool = qobject_to_qbool(qobj);
- if (!qbool) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "boolean");
- return;
- }
-
- *obj = qbool_get_bool(qbool);
-}
-
-static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
- Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- QString *qstr;
-
- *obj = NULL;
- if (!qobj) {
- return;
- }
- qstr = qobject_to_qstring(qobj);
- if (!qstr) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "string");
- return;
- }
-
- *obj = g_strdup(qstring_get_str(qstr));
-}
-
-static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
- Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
- QInt *qint;
- QFloat *qfloat;
-
- if (!qobj) {
- return;
- }
- qint = qobject_to_qint(qobj);
- if (qint) {
- *obj = qint_get_int(qobject_to_qint(qobj));
- return;
- }
-
- qfloat = qobject_to_qfloat(qobj);
- if (qfloat) {
- *obj = qfloat_get_double(qobject_to_qfloat(qobj));
- return;
- }
-
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "number");
-}
-
-static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,
- Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
-
- *obj = NULL;
- if (!qobj) {
- return;
- }
-
- qobject_incref(qobj);
- *obj = qobj;
-}
-
-static void qmp_input_type_null(Visitor *v, const char *name, Error **errp)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, true, errp);
-
- if (!qobj) {
- return;
- }
-
- if (qobject_type(qobj) != QTYPE_QNULL) {
- error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
- "null");
- }
-}
-
-static void qmp_input_optional(Visitor *v, const char *name, bool *present)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- QObject *qobj = qmp_input_get_object(qiv, name, false, NULL);
-
- if (!qobj) {
- *present = false;
- return;
- }
-
- *present = true;
-}
-
-static void qmp_input_free(Visitor *v)
-{
- QmpInputVisitor *qiv = to_qiv(v);
- while (!QSLIST_EMPTY(&qiv->stack)) {
- StackObject *tos = QSLIST_FIRST(&qiv->stack);
-
- QSLIST_REMOVE_HEAD(&qiv->stack, node);
- qmp_input_stack_object_free(tos);
- }
-
- qobject_decref(qiv->root);
- g_free(qiv);
-}
-
-Visitor *qmp_input_visitor_new(QObject *obj, bool strict)
-{
- QmpInputVisitor *v;
-
- assert(obj);
- v = g_malloc0(sizeof(*v));
-
- v->visitor.type = VISITOR_INPUT;
- v->visitor.start_struct = qmp_input_start_struct;
- v->visitor.check_struct = qmp_input_check_struct;
- v->visitor.end_struct = qmp_input_pop;
- v->visitor.start_list = qmp_input_start_list;
- v->visitor.next_list = qmp_input_next_list;
- v->visitor.end_list = qmp_input_pop;
- v->visitor.start_alternate = qmp_input_start_alternate;
- v->visitor.type_int64 = qmp_input_type_int64;
- v->visitor.type_uint64 = qmp_input_type_uint64;
- v->visitor.type_bool = qmp_input_type_bool;
- v->visitor.type_str = qmp_input_type_str;
- v->visitor.type_number = qmp_input_type_number;
- v->visitor.type_any = qmp_input_type_any;
- v->visitor.type_null = qmp_input_type_null;
- v->visitor.optional = qmp_input_optional;
- v->visitor.free = qmp_input_free;
- v->strict = strict;
-
- v->root = obj;
- qobject_incref(obj);
-
- return &v->visitor;
-}
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
deleted file mode 100644
index 9e3b67c..0000000
--- a/qapi/qmp-output-visitor.c
+++ /dev/null
@@ -1,256 +0,0 @@
-/*
- * Core Definitions for QAPI/QMP Command Registry
- *
- * Copyright (C) 2012-2016 Red Hat, Inc.
- * Copyright IBM, Corp. 2011
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/visitor-impl.h"
-#include "qemu/queue.h"
-#include "qemu-common.h"
-#include "qapi/qmp/types.h"
-
-typedef struct QStackEntry
-{
- QObject *value;
- void *qapi; /* sanity check that caller uses same pointer */
- QSLIST_ENTRY(QStackEntry) node;
-} QStackEntry;
-
-struct QmpOutputVisitor
-{
- Visitor visitor;
- QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
- QObject *root; /* Root of the output visit */
- QObject **result; /* User's storage location for result */
-};
-
-#define qmp_output_add(qov, name, value) \
- qmp_output_add_obj(qov, name, QOBJECT(value))
-#define qmp_output_push(qov, value, qapi) \
- qmp_output_push_obj(qov, QOBJECT(value), qapi)
-
-static QmpOutputVisitor *to_qov(Visitor *v)
-{
- return container_of(v, QmpOutputVisitor, visitor);
-}
-
-/* Push @value onto the stack of current QObjects being built */
-static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value,
- void *qapi)
-{
- QStackEntry *e = g_malloc0(sizeof(*e));
-
- assert(qov->root);
- assert(value);
- e->value = value;
- e->qapi = qapi;
- QSLIST_INSERT_HEAD(&qov->stack, e, node);
-}
-
-/* Pop a value off the stack of QObjects being built, and return it. */
-static QObject *qmp_output_pop(QmpOutputVisitor *qov, void *qapi)
-{
- QStackEntry *e = QSLIST_FIRST(&qov->stack);
- QObject *value;
-
- assert(e);
- assert(e->qapi == qapi);
- QSLIST_REMOVE_HEAD(&qov->stack, node);
- value = e->value;
- assert(value);
- g_free(e);
- return value;
-}
-
-/* Add @value to the current QObject being built.
- * If the stack is visiting a dictionary or list, @value is now owned
- * by that container. Otherwise, @value is now the root. */
-static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
- QObject *value)
-{
- QStackEntry *e = QSLIST_FIRST(&qov->stack);
- QObject *cur = e ? e->value : NULL;
-
- if (!cur) {
- /* Don't allow reuse of visitor on more than one root */
- assert(!qov->root);
- qov->root = value;
- } else {
- switch (qobject_type(cur)) {
- case QTYPE_QDICT:
- assert(name);
- qdict_put_obj(qobject_to_qdict(cur), name, value);
- break;
- case QTYPE_QLIST:
- assert(!name);
- qlist_append_obj(qobject_to_qlist(cur), value);
- break;
- default:
- g_assert_not_reached();
- }
- }
-}
-
-static void qmp_output_start_struct(Visitor *v, const char *name, void **obj,
- size_t unused, Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QDict *dict = qdict_new();
-
- qmp_output_add(qov, name, dict);
- qmp_output_push(qov, dict, obj);
-}
-
-static void qmp_output_end_struct(Visitor *v, void **obj)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QObject *value = qmp_output_pop(qov, obj);
- assert(qobject_type(value) == QTYPE_QDICT);
-}
-
-static void qmp_output_start_list(Visitor *v, const char *name,
- GenericList **listp, size_t size,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QList *list = qlist_new();
-
- qmp_output_add(qov, name, list);
- qmp_output_push(qov, list, listp);
-}
-
-static GenericList *qmp_output_next_list(Visitor *v, GenericList *tail,
- size_t size)
-{
- return tail->next;
-}
-
-static void qmp_output_end_list(Visitor *v, void **obj)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QObject *value = qmp_output_pop(qov, obj);
- assert(qobject_type(value) == QTYPE_QLIST);
-}
-
-static void qmp_output_type_int64(Visitor *v, const char *name, int64_t *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qint_from_int(*obj));
-}
-
-static void qmp_output_type_uint64(Visitor *v, const char *name, uint64_t *obj,
- Error **errp)
-{
- /* FIXME: QMP outputs values larger than INT64_MAX as negative */
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qint_from_int(*obj));
-}
-
-static void qmp_output_type_bool(Visitor *v, const char *name, bool *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qbool_from_bool(*obj));
-}
-
-static void qmp_output_type_str(Visitor *v, const char *name, char **obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- if (*obj) {
- qmp_output_add(qov, name, qstring_from_str(*obj));
- } else {
- qmp_output_add(qov, name, qstring_from_str(""));
- }
-}
-
-static void qmp_output_type_number(Visitor *v, const char *name, double *obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add(qov, name, qfloat_from_double(*obj));
-}
-
-static void qmp_output_type_any(Visitor *v, const char *name, QObject **obj,
- Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qobject_incref(*obj);
- qmp_output_add_obj(qov, name, *obj);
-}
-
-static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
-{
- QmpOutputVisitor *qov = to_qov(v);
- qmp_output_add_obj(qov, name, qnull());
-}
-
-/* Finish building, and return the root object.
- * The root object is never null. The caller becomes the object's
- * owner, and should use qobject_decref() when done with it. */
-static void qmp_output_complete(Visitor *v, void *opaque)
-{
- QmpOutputVisitor *qov = to_qov(v);
-
- /* A visit must have occurred, with each start paired with end. */
- assert(qov->root && QSLIST_EMPTY(&qov->stack));
- assert(opaque == qov->result);
-
- qobject_incref(qov->root);
- *qov->result = qov->root;
- qov->result = NULL;
-}
-
-static void qmp_output_free(Visitor *v)
-{
- QmpOutputVisitor *qov = to_qov(v);
- QStackEntry *e;
-
- while (!QSLIST_EMPTY(&qov->stack)) {
- e = QSLIST_FIRST(&qov->stack);
- QSLIST_REMOVE_HEAD(&qov->stack, node);
- g_free(e);
- }
-
- qobject_decref(qov->root);
- g_free(qov);
-}
-
-Visitor *qmp_output_visitor_new(QObject **result)
-{
- QmpOutputVisitor *v;
-
- v = g_malloc0(sizeof(*v));
-
- v->visitor.type = VISITOR_OUTPUT;
- v->visitor.start_struct = qmp_output_start_struct;
- v->visitor.end_struct = qmp_output_end_struct;
- v->visitor.start_list = qmp_output_start_list;
- v->visitor.next_list = qmp_output_next_list;
- v->visitor.end_list = qmp_output_end_list;
- v->visitor.type_int64 = qmp_output_type_int64;
- v->visitor.type_uint64 = qmp_output_type_uint64;
- v->visitor.type_bool = qmp_output_type_bool;
- v->visitor.type_str = qmp_output_type_str;
- v->visitor.type_number = qmp_output_type_number;
- v->visitor.type_any = qmp_output_type_any;
- v->visitor.type_null = qmp_output_type_null;
- v->visitor.complete = qmp_output_complete;
- v->visitor.free = qmp_output_free;
-
- *result = NULL;
- v->result = result;
-
- return &v->visitor;
-}
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
new file mode 100644
index 0000000..0063327
--- /dev/null
+++ b/qapi/qobject-input-visitor.c
@@ -0,0 +1,457 @@
+/*
+ * Input Visitor
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qemu-common.h"
+#include "qapi/qmp/types.h"
+#include "qapi/qmp/qerror.h"
+
+#define QIV_STACK_SIZE 1024
+
+typedef struct StackObject
+{
+ QObject *obj; /* Object being visited */
+ void *qapi; /* sanity check that caller uses same pointer */
+
+ GHashTable *h; /* If obj is dict: unvisited keys */
+ const QListEntry *entry; /* If obj is list: unvisited tail */
+
+ QSLIST_ENTRY(StackObject) node;
+} StackObject;
+
+struct QObjectInputVisitor
+{
+ Visitor visitor;
+
+ /* Root of visit at visitor creation. */
+ QObject *root;
+
+ /* Stack of objects being visited (all entries will be either
+ * QDict or QList). */
+ QSLIST_HEAD(, StackObject) stack;
+
+ /* True to reject parse in visit_end_struct() if unvisited keys remain. */
+ bool strict;
+};
+
+static QObjectInputVisitor *to_qiv(Visitor *v)
+{
+ return container_of(v, QObjectInputVisitor, visitor);
+}
+
+static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
+ const char *name,
+ bool consume, Error **errp)
+{
+ StackObject *tos;
+ QObject *qobj;
+ QObject *ret;
+
+ if (QSLIST_EMPTY(&qiv->stack)) {
+ /* Starting at root, name is ignored. */
+ assert(qiv->root);
+ return qiv->root;
+ }
+
+ /* We are in a container; find the next element. */
+ tos = QSLIST_FIRST(&qiv->stack);
+ qobj = tos->obj;
+ assert(qobj);
+
+ if (qobject_type(qobj) == QTYPE_QDICT) {
+ assert(name);
+ ret = qdict_get(qobject_to_qdict(qobj), name);
+ if (tos->h && consume && ret) {
+ bool removed = g_hash_table_remove(tos->h, name);
+ assert(removed);
+ }
+ if (!ret) {
+ error_setg(errp, QERR_MISSING_PARAMETER, name);
+ }
+ } else {
+ assert(qobject_type(qobj) == QTYPE_QLIST);
+ assert(!name);
+ ret = qlist_entry_obj(tos->entry);
+ assert(ret);
+ if (consume) {
+ tos->entry = qlist_next(tos->entry);
+ }
+ }
+
+ return ret;
+}
+
+static void qdict_add_key(const char *key, QObject *obj, void *opaque)
+{
+ GHashTable *h = opaque;
+ g_hash_table_insert(h, (gpointer) key, NULL);
+}
+
+static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
+ QObject *obj, void *qapi,
+ Error **errp)
+{
+ GHashTable *h;
+ StackObject *tos = g_new0(StackObject, 1);
+
+ assert(obj);
+ tos->obj = obj;
+ tos->qapi = qapi;
+
+ if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
+ h = g_hash_table_new(g_str_hash, g_str_equal);
+ qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
+ tos->h = h;
+ } else if (qobject_type(obj) == QTYPE_QLIST) {
+ tos->entry = qlist_first(qobject_to_qlist(obj));
+ }
+
+ QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
+ return tos->entry;
+}
+
+
+static void qobject_input_check_struct(Visitor *v, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(tos && !tos->entry);
+ if (qiv->strict) {
+ GHashTable *const top_ht = tos->h;
+ if (top_ht) {
+ GHashTableIter iter;
+ const char *key;
+
+ g_hash_table_iter_init(&iter, top_ht);
+ if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
+ error_setg(errp, QERR_QMP_EXTRA_MEMBER, key);
+ }
+ }
+ }
+}
+
+static void qobject_input_stack_object_free(StackObject *tos)
+{
+ if (tos->h) {
+ g_hash_table_unref(tos->h);
+ }
+
+ g_free(tos);
+}
+
+static void qobject_input_pop(Visitor *v, void **obj)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ assert(tos && tos->qapi == obj);
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qobject_input_stack_object_free(tos);
+}
+
+static void qobject_input_start_struct(Visitor *v, const char *name, void **obj,
+ size_t size, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ Error *err = NULL;
+
+ if (obj) {
+ *obj = NULL;
+ }
+ if (!qobj) {
+ return;
+ }
+ if (qobject_type(qobj) != QTYPE_QDICT) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "QDict");
+ return;
+ }
+
+ qobject_input_push(qiv, qobj, obj, &err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
+
+ if (obj) {
+ *obj = g_malloc0(size);
+ }
+}
+
+
+static void qobject_input_start_list(Visitor *v, const char *name,
+ GenericList **list, size_t size,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ const QListEntry *entry;
+
+ if (!qobj) {
+ return;
+ }
+ if (qobject_type(qobj) != QTYPE_QLIST) {
+ if (list) {
+ *list = NULL;
+ }
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "list");
+ return;
+ }
+
+ entry = qobject_input_push(qiv, qobj, list, errp);
+ if (list) {
+ if (entry) {
+ *list = g_malloc0(size);
+ } else {
+ *list = NULL;
+ }
+ }
+}
+
+static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ StackObject *so = QSLIST_FIRST(&qiv->stack);
+
+ if (!so->entry) {
+ return NULL;
+ }
+ tail->next = g_malloc0(size);
+ return tail->next;
+}
+
+
+static void qobject_input_start_alternate(Visitor *v, const char *name,
+ GenericAlternate **obj, size_t size,
+ bool promote_int, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
+
+ if (!qobj) {
+ *obj = NULL;
+ return;
+ }
+ *obj = g_malloc0(size);
+ (*obj)->type = qobject_type(qobj);
+ if (promote_int && (*obj)->type == QTYPE_QINT) {
+ (*obj)->type = QTYPE_QFLOAT;
+ }
+}
+
+static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QInt *qint;
+
+ if (!qobj) {
+ return;
+ }
+ qint = qobject_to_qint(qobj);
+ if (!qint) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "integer");
+ return;
+ }
+
+ *obj = qint_get_int(qint);
+}
+
+static void qobject_input_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QInt *qint;
+
+ if (!qobj) {
+ return;
+ }
+ qint = qobject_to_qint(qobj);
+ if (!qint) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "integer");
+ return;
+ }
+
+ *obj = qint_get_int(qint);
+}
+
+static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QBool *qbool;
+
+ if (!qobj) {
+ return;
+ }
+ qbool = qobject_to_qbool(qobj);
+ if (!qbool) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "boolean");
+ return;
+ }
+
+ *obj = qbool_get_bool(qbool);
+}
+
+static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QString *qstr;
+
+ *obj = NULL;
+ if (!qobj) {
+ return;
+ }
+ qstr = qobject_to_qstring(qobj);
+ if (!qstr) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "string");
+ return;
+ }
+
+ *obj = g_strdup(qstring_get_str(qstr));
+}
+
+static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+ QInt *qint;
+ QFloat *qfloat;
+
+ if (!qobj) {
+ return;
+ }
+ qint = qobject_to_qint(qobj);
+ if (qint) {
+ *obj = qint_get_int(qobject_to_qint(qobj));
+ return;
+ }
+
+ qfloat = qobject_to_qfloat(qobj);
+ if (qfloat) {
+ *obj = qfloat_get_double(qobject_to_qfloat(qobj));
+ return;
+ }
+
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "number");
+}
+
+static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
+ Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ *obj = NULL;
+ if (!qobj) {
+ return;
+ }
+
+ qobject_incref(qobj);
+ *obj = qobj;
+}
+
+static void qobject_input_type_null(Visitor *v, const char *name, Error **errp)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
+
+ if (!qobj) {
+ return;
+ }
+
+ if (qobject_type(qobj) != QTYPE_QNULL) {
+ error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "null");
+ }
+}
+
+static void qobject_input_optional(Visitor *v, const char *name, bool *present)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ QObject *qobj = qobject_input_get_object(qiv, name, false, NULL);
+
+ if (!qobj) {
+ *present = false;
+ return;
+ }
+
+ *present = true;
+}
+
+static void qobject_input_free(Visitor *v)
+{
+ QObjectInputVisitor *qiv = to_qiv(v);
+ while (!QSLIST_EMPTY(&qiv->stack)) {
+ StackObject *tos = QSLIST_FIRST(&qiv->stack);
+
+ QSLIST_REMOVE_HEAD(&qiv->stack, node);
+ qobject_input_stack_object_free(tos);
+ }
+
+ qobject_decref(qiv->root);
+ g_free(qiv);
+}
+
+Visitor *qobject_input_visitor_new(QObject *obj, bool strict)
+{
+ QObjectInputVisitor *v;
+
+ assert(obj);
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_INPUT;
+ v->visitor.start_struct = qobject_input_start_struct;
+ v->visitor.check_struct = qobject_input_check_struct;
+ v->visitor.end_struct = qobject_input_pop;
+ v->visitor.start_list = qobject_input_start_list;
+ v->visitor.next_list = qobject_input_next_list;
+ v->visitor.end_list = qobject_input_pop;
+ v->visitor.start_alternate = qobject_input_start_alternate;
+ v->visitor.type_int64 = qobject_input_type_int64;
+ v->visitor.type_uint64 = qobject_input_type_uint64;
+ v->visitor.type_bool = qobject_input_type_bool;
+ v->visitor.type_str = qobject_input_type_str;
+ v->visitor.type_number = qobject_input_type_number;
+ v->visitor.type_any = qobject_input_type_any;
+ v->visitor.type_null = qobject_input_type_null;
+ v->visitor.optional = qobject_input_optional;
+ v->visitor.free = qobject_input_free;
+ v->strict = strict;
+
+ v->root = obj;
+ qobject_incref(obj);
+
+ return &v->visitor;
+}
diff --git a/qapi/qobject-output-visitor.c b/qapi/qobject-output-visitor.c
new file mode 100644
index 0000000..8711270
--- /dev/null
+++ b/qapi/qobject-output-visitor.c
@@ -0,0 +1,254 @@
+/*
+ * Core Definitions for QAPI/QMP Command Registry
+ *
+ * Copyright (C) 2012-2016 Red Hat, Inc.
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/qobject-output-visitor.h"
+#include "qapi/visitor-impl.h"
+#include "qemu/queue.h"
+#include "qemu-common.h"
+#include "qapi/qmp/types.h"
+
+typedef struct QStackEntry {
+ QObject *value;
+ void *qapi; /* sanity check that caller uses same pointer */
+ QSLIST_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+struct QObjectOutputVisitor {
+ Visitor visitor;
+ QSLIST_HEAD(, QStackEntry) stack; /* Stack of unfinished containers */
+ QObject *root; /* Root of the output visit */
+ QObject **result; /* User's storage location for result */
+};
+
+#define qobject_output_add(qov, name, value) \
+ qobject_output_add_obj(qov, name, QOBJECT(value))
+#define qobject_output_push(qov, value, qapi) \
+ qobject_output_push_obj(qov, QOBJECT(value), qapi)
+
+static QObjectOutputVisitor *to_qov(Visitor *v)
+{
+ return container_of(v, QObjectOutputVisitor, visitor);
+}
+
+/* Push @value onto the stack of current QObjects being built */
+static void qobject_output_push_obj(QObjectOutputVisitor *qov, QObject *value,
+ void *qapi)
+{
+ QStackEntry *e = g_malloc0(sizeof(*e));
+
+ assert(qov->root);
+ assert(value);
+ e->value = value;
+ e->qapi = qapi;
+ QSLIST_INSERT_HEAD(&qov->stack, e, node);
+}
+
+/* Pop a value off the stack of QObjects being built, and return it. */
+static QObject *qobject_output_pop(QObjectOutputVisitor *qov, void *qapi)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *value;
+
+ assert(e);
+ assert(e->qapi == qapi);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ value = e->value;
+ assert(value);
+ g_free(e);
+ return value;
+}
+
+/* Add @value to the current QObject being built.
+ * If the stack is visiting a dictionary or list, @value is now owned
+ * by that container. Otherwise, @value is now the root. */
+static void qobject_output_add_obj(QObjectOutputVisitor *qov, const char *name,
+ QObject *value)
+{
+ QStackEntry *e = QSLIST_FIRST(&qov->stack);
+ QObject *cur = e ? e->value : NULL;
+
+ if (!cur) {
+ /* Don't allow reuse of visitor on more than one root */
+ assert(!qov->root);
+ qov->root = value;
+ } else {
+ switch (qobject_type(cur)) {
+ case QTYPE_QDICT:
+ assert(name);
+ qdict_put_obj(qobject_to_qdict(cur), name, value);
+ break;
+ case QTYPE_QLIST:
+ assert(!name);
+ qlist_append_obj(qobject_to_qlist(cur), value);
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ }
+}
+
+static void qobject_output_start_struct(Visitor *v, const char *name,
+ void **obj, size_t unused, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QDict *dict = qdict_new();
+
+ qobject_output_add(qov, name, dict);
+ qobject_output_push(qov, dict, obj);
+}
+
+static void qobject_output_end_struct(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QDICT);
+}
+
+static void qobject_output_start_list(Visitor *v, const char *name,
+ GenericList **listp, size_t size,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QList *list = qlist_new();
+
+ qobject_output_add(qov, name, list);
+ qobject_output_push(qov, list, listp);
+}
+
+static GenericList *qobject_output_next_list(Visitor *v, GenericList *tail,
+ size_t size)
+{
+ return tail->next;
+}
+
+static void qobject_output_end_list(Visitor *v, void **obj)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QObject *value = qobject_output_pop(qov, obj);
+ assert(qobject_type(value) == QTYPE_QLIST);
+}
+
+static void qobject_output_type_int64(Visitor *v, const char *name,
+ int64_t *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qobject_output_type_uint64(Visitor *v, const char *name,
+ uint64_t *obj, Error **errp)
+{
+ /* FIXME values larger than INT64_MAX become negative */
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qint_from_int(*obj));
+}
+
+static void qobject_output_type_bool(Visitor *v, const char *name, bool *obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qbool_from_bool(*obj));
+}
+
+static void qobject_output_type_str(Visitor *v, const char *name, char **obj,
+ Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ if (*obj) {
+ qobject_output_add(qov, name, qstring_from_str(*obj));
+ } else {
+ qobject_output_add(qov, name, qstring_from_str(""));
+ }
+}
+
+static void qobject_output_type_number(Visitor *v, const char *name,
+ double *obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add(qov, name, qfloat_from_double(*obj));
+}
+
+static void qobject_output_type_any(Visitor *v, const char *name,
+ QObject **obj, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_incref(*obj);
+ qobject_output_add_obj(qov, name, *obj);
+}
+
+static void qobject_output_type_null(Visitor *v, const char *name, Error **errp)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ qobject_output_add_obj(qov, name, qnull());
+}
+
+/* Finish building, and return the root object.
+ * The root object is never null. The caller becomes the object's
+ * owner, and should use qobject_decref() when done with it. */
+static void qobject_output_complete(Visitor *v, void *opaque)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+
+ /* A visit must have occurred, with each start paired with end. */
+ assert(qov->root && QSLIST_EMPTY(&qov->stack));
+ assert(opaque == qov->result);
+
+ qobject_incref(qov->root);
+ *qov->result = qov->root;
+ qov->result = NULL;
+}
+
+static void qobject_output_free(Visitor *v)
+{
+ QObjectOutputVisitor *qov = to_qov(v);
+ QStackEntry *e;
+
+ while (!QSLIST_EMPTY(&qov->stack)) {
+ e = QSLIST_FIRST(&qov->stack);
+ QSLIST_REMOVE_HEAD(&qov->stack, node);
+ g_free(e);
+ }
+
+ qobject_decref(qov->root);
+ g_free(qov);
+}
+
+Visitor *qobject_output_visitor_new(QObject **result)
+{
+ QObjectOutputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type = VISITOR_OUTPUT;
+ v->visitor.start_struct = qobject_output_start_struct;
+ v->visitor.end_struct = qobject_output_end_struct;
+ v->visitor.start_list = qobject_output_start_list;
+ v->visitor.next_list = qobject_output_next_list;
+ v->visitor.end_list = qobject_output_end_list;
+ v->visitor.type_int64 = qobject_output_type_int64;
+ v->visitor.type_uint64 = qobject_output_type_uint64;
+ v->visitor.type_bool = qobject_output_type_bool;
+ v->visitor.type_str = qobject_output_type_str;
+ v->visitor.type_number = qobject_output_type_number;
+ v->visitor.type_any = qobject_output_type_any;
+ v->visitor.type_null = qobject_output_type_null;
+ v->visitor.complete = qobject_output_complete;
+ v->visitor.free = qobject_output_free;
+
+ *result = NULL;
+ v->result = result;
+
+ return &v->visitor;
+}
diff --git a/qapi/trace-events b/qapi/trace-events
new file mode 100644
index 0000000..2c5d3bc
--- /dev/null
+++ b/qapi/trace-events
@@ -0,0 +1,33 @@
+# qapi-visit-core.c
+visit_free(void *v) "v=%p"
+visit_complete(void *v, void *opaque) "v=%p opaque=%p"
+
+visit_start_struct(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_check_struct(void *v) "v=%p"
+visit_end_struct(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_list(void *v, const char *name, void *obj, size_t size) "v=%p name=%s obj=%p size=%zu"
+visit_next_list(void *v, void *tail, size_t size) "v=%p tail=%p size=%zu"
+visit_end_list(void *v, void *obj) "v=%p obj=%p"
+
+visit_start_alternate(void *v, const char *name, void *obj, size_t size, bool promote_int) "v=%p name=%s obj=%p size=%zu promote_int=%d"
+visit_end_alternate(void *v, void *obj) "v=%p obj=%p"
+
+visit_optional(void *v, const char *name, bool *present) "v=%p name=%s present=%p"
+
+visit_type_enum(void *v, const char *name, int *obj) "v=%p name=%s obj=%p"
+visit_type_int(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint8(void *v, const char *name, uint8_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint16(void *v, const char *name, uint16_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint32(void *v, const char *name, uint32_t *obj) "v=%p name=%s obj=%p"
+visit_type_uint64(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_int8(void *v, const char *name, int8_t *obj) "v=%p name=%s obj=%p"
+visit_type_int16(void *v, const char *name, int16_t *obj) "v=%p name=%s obj=%p"
+visit_type_int32(void *v, const char *name, int32_t *obj) "v=%p name=%s obj=%p"
+visit_type_int64(void *v, const char *name, int64_t *obj) "v=%p name=%s obj=%p"
+visit_type_size(void *v, const char *name, uint64_t *obj) "v=%p name=%s obj=%p"
+visit_type_bool(void *v, const char *name, bool *obj) "v=%p name=%s obj=%p"
+visit_type_str(void *v, const char *name, char **obj) "v=%p name=%s obj=%p"
+visit_type_number(void *v, const char *name, double *obj) "v=%p name=%s obj=%p"
+visit_type_any(void *v, const char *name, void *obj) "v=%p name=%s obj=%p"
+visit_type_null(void *v, const char *name) "v=%p name=%s"
diff --git a/qemu-img.c b/qemu-img.c
index ab395a9..afcd51f 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -25,7 +25,7 @@
#include "qemu-version.h"
#include "qapi/error.h"
#include "qapi-visit.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qjson.h"
#include "qemu/cutils.h"
@@ -500,7 +500,7 @@
{
QString *str;
QObject *obj;
- Visitor *v = qmp_output_visitor_new(&obj);
+ Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageCheck(v, NULL, &check, &error_abort);
visit_complete(v, &obj);
@@ -2193,7 +2193,7 @@
{
QString *str;
QObject *obj;
- Visitor *v = qmp_output_visitor_new(&obj);
+ Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfoList(v, NULL, &list, &error_abort);
visit_complete(v, &obj);
@@ -2209,7 +2209,7 @@
{
QString *str;
QObject *obj;
- Visitor *v = qmp_output_visitor_new(&obj);
+ Visitor *v = qobject_output_visitor_new(&obj);
visit_type_ImageInfo(v, NULL, &info, &error_abort);
visit_complete(v, &obj);
diff --git a/qmp.c b/qmp.c
index b3ba9ef..a06cb7b 100644
--- a/qmp.c
+++ b/qmp.c
@@ -31,7 +31,7 @@
#include "qom/qom-qobject.h"
#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qobject.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "hw/boards.h"
#include "qom/object_interfaces.h"
#include "hw/mem/pc-dimm.h"
@@ -675,7 +675,7 @@
pdict = qdict_new();
}
- v = qmp_input_visitor_new(QOBJECT(pdict), true);
+ v = qobject_input_visitor_new(QOBJECT(pdict), true);
obj = user_creatable_add_type(type, id, pdict, v, errp);
visit_free(v);
if (obj) {
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 60f158c..197b0fb 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -17,6 +17,7 @@
#include "qapi/qmp/qbool.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/qobject.h"
+#include "qapi/error.h"
#include "qemu/queue.h"
#include "qemu-common.h"
#include "qemu/cutils.h"
@@ -684,6 +685,282 @@
}
/**
+ * qdict_split_flat_key:
+ * @key: the key string to split
+ * @prefix: non-NULL pointer to hold extracted prefix
+ * @suffix: non-NULL pointer to remaining suffix
+ *
+ * Given a flattened key such as 'foo.0.bar', split it into two parts
+ * at the first '.' separator. Allows double dot ('..') to escape the
+ * normal separator.
+ *
+ * e.g.
+ * 'foo.0.bar' -> prefix='foo' and suffix='0.bar'
+ * 'foo..0.bar' -> prefix='foo.0' and suffix='bar'
+ *
+ * The '..' sequence will be unescaped in the returned 'prefix'
+ * string. The 'suffix' string will be left in escaped format, so it
+ * can be fed back into the qdict_split_flat_key() key as the input
+ * later.
+ *
+ * The caller is responsible for freeing the string returned in @prefix
+ * using g_free().
+ */
+static void qdict_split_flat_key(const char *key, char **prefix,
+ const char **suffix)
+{
+ const char *separator;
+ size_t i, j;
+
+ /* Find first '.' separator, but if there is a pair '..'
+ * that acts as an escape, so skip over '..' */
+ separator = NULL;
+ do {
+ if (separator) {
+ separator += 2;
+ } else {
+ separator = key;
+ }
+ separator = strchr(separator, '.');
+ } while (separator && separator[1] == '.');
+
+ if (separator) {
+ *prefix = g_strndup(key, separator - key);
+ *suffix = separator + 1;
+ } else {
+ *prefix = g_strdup(key);
+ *suffix = NULL;
+ }
+
+ /* Unescape the '..' sequence into '.' */
+ for (i = 0, j = 0; (*prefix)[i] != '\0'; i++, j++) {
+ if ((*prefix)[i] == '.') {
+ assert((*prefix)[i + 1] == '.');
+ i++;
+ }
+ (*prefix)[j] = (*prefix)[i];
+ }
+ (*prefix)[j] = '\0';
+}
+
+/**
+ * qdict_is_list:
+ * @maybe_list: dict to check if keys represent list elements.
+ *
+ * Determine whether all keys in @maybe_list are valid list elements.
+ * If @maybe_list is non-zero in length and all the keys look like
+ * valid list indexes, this will return 1. If @maybe_list is zero
+ * length or all keys are non-numeric then it will return 0 to indicate
+ * it is a normal qdict. If there is a mix of numeric and non-numeric
+ * keys, or the list indexes are non-contiguous, an error is reported.
+ *
+ * Returns: 1 if a valid list, 0 if a dict, -1 on error
+ */
+static int qdict_is_list(QDict *maybe_list, Error **errp)
+{
+ const QDictEntry *ent;
+ ssize_t len = 0;
+ ssize_t max = -1;
+ int is_list = -1;
+ int64_t val;
+
+ for (ent = qdict_first(maybe_list); ent != NULL;
+ ent = qdict_next(maybe_list, ent)) {
+
+ if (qemu_strtoll(ent->key, NULL, 10, &val) == 0) {
+ if (is_list == -1) {
+ is_list = 1;
+ } else if (!is_list) {
+ error_setg(errp,
+ "Cannot mix list and non-list keys");
+ return -1;
+ }
+ len++;
+ if (val > max) {
+ max = val;
+ }
+ } else {
+ if (is_list == -1) {
+ is_list = 0;
+ } else if (is_list) {
+ error_setg(errp,
+ "Cannot mix list and non-list keys");
+ return -1;
+ }
+ }
+ }
+
+ if (is_list == -1) {
+ assert(!qdict_size(maybe_list));
+ is_list = 0;
+ }
+
+ /* NB this isn't a perfect check - e.g. it won't catch
+ * a list containing '1', '+1', '01', '3', but that
+ * does not matter - we've still proved that the
+ * input is a list. It is up the caller to do a
+ * stricter check if desired */
+ if (len != (max + 1)) {
+ error_setg(errp, "List indices are not contiguous, "
+ "saw %zd elements but %zd largest index",
+ len, max);
+ return -1;
+ }
+
+ return is_list;
+}
+
+/**
+ * qdict_crumple:
+ * @src: the original flat dictionary (only scalar values) to crumple
+ *
+ * Takes a flat dictionary whose keys use '.' separator to indicate
+ * nesting, and values are scalars, and crumples it into a nested
+ * structure.
+ *
+ * To include a literal '.' in a key name, it must be escaped as '..'
+ *
+ * For example, an input of:
+ *
+ * { 'foo.0.bar': 'one', 'foo.0.wizz': '1',
+ * 'foo.1.bar': 'two', 'foo.1.wizz': '2' }
+ *
+ * will result in an output of:
+ *
+ * {
+ * 'foo': [
+ * { 'bar': 'one', 'wizz': '1' },
+ * { 'bar': 'two', 'wizz': '2' }
+ * ],
+ * }
+ *
+ * The following scenarios in the input dict will result in an
+ * error being returned:
+ *
+ * - Any values in @src are non-scalar types
+ * - If keys in @src imply that a particular level is both a
+ * list and a dict. e.g., "foo.0.bar" and "foo.eek.bar".
+ * - If keys in @src imply that a particular level is a list,
+ * but the indices are non-contiguous. e.g. "foo.0.bar" and
+ * "foo.2.bar" without any "foo.1.bar" present.
+ * - If keys in @src represent list indexes, but are not in
+ * the "%zu" format. e.g. "foo.+0.bar"
+ *
+ * Returns: either a QDict or QList for the nested data structure, or NULL
+ * on error
+ */
+QObject *qdict_crumple(const QDict *src, Error **errp)
+{
+ const QDictEntry *ent;
+ QDict *two_level, *multi_level = NULL;
+ QObject *dst = NULL, *child;
+ size_t i;
+ char *prefix = NULL;
+ const char *suffix = NULL;
+ int is_list;
+
+ two_level = qdict_new();
+
+ /* Step 1: split our totally flat dict into a two level dict */
+ for (ent = qdict_first(src); ent != NULL; ent = qdict_next(src, ent)) {
+ if (qobject_type(ent->value) == QTYPE_QDICT ||
+ qobject_type(ent->value) == QTYPE_QLIST) {
+ error_setg(errp, "Value %s is not a scalar",
+ ent->key);
+ goto error;
+ }
+
+ qdict_split_flat_key(ent->key, &prefix, &suffix);
+
+ child = qdict_get(two_level, prefix);
+ if (suffix) {
+ if (child) {
+ if (qobject_type(child) != QTYPE_QDICT) {
+ error_setg(errp, "Key %s prefix is already set as a scalar",
+ prefix);
+ goto error;
+ }
+ } else {
+ child = QOBJECT(qdict_new());
+ qdict_put_obj(two_level, prefix, child);
+ }
+ qobject_incref(ent->value);
+ qdict_put_obj(qobject_to_qdict(child), suffix, ent->value);
+ } else {
+ if (child) {
+ error_setg(errp, "Key %s prefix is already set as a dict",
+ prefix);
+ goto error;
+ }
+ qobject_incref(ent->value);
+ qdict_put_obj(two_level, prefix, ent->value);
+ }
+
+ g_free(prefix);
+ prefix = NULL;
+ }
+
+ /* Step 2: optionally process the two level dict recursively
+ * into a multi-level dict */
+ multi_level = qdict_new();
+ for (ent = qdict_first(two_level); ent != NULL;
+ ent = qdict_next(two_level, ent)) {
+
+ if (qobject_type(ent->value) == QTYPE_QDICT) {
+ child = qdict_crumple(qobject_to_qdict(ent->value), errp);
+ if (!child) {
+ goto error;
+ }
+
+ qdict_put_obj(multi_level, ent->key, child);
+ } else {
+ qobject_incref(ent->value);
+ qdict_put_obj(multi_level, ent->key, ent->value);
+ }
+ }
+ QDECREF(two_level);
+ two_level = NULL;
+
+ /* Step 3: detect if we need to turn our dict into list */
+ is_list = qdict_is_list(multi_level, errp);
+ if (is_list < 0) {
+ goto error;
+ }
+
+ if (is_list) {
+ dst = QOBJECT(qlist_new());
+
+ for (i = 0; i < qdict_size(multi_level); i++) {
+ char *key = g_strdup_printf("%zu", i);
+
+ child = qdict_get(multi_level, key);
+ g_free(key);
+
+ if (!child) {
+ error_setg(errp, "Missing list index %zu", i);
+ goto error;
+ }
+
+ qobject_incref(child);
+ qlist_append_obj(qobject_to_qlist(dst), child);
+ }
+ QDECREF(multi_level);
+ multi_level = NULL;
+ } else {
+ dst = QOBJECT(multi_level);
+ }
+
+ return dst;
+
+ error:
+ g_free(prefix);
+ QDECREF(multi_level);
+ QDECREF(two_level);
+ qobject_decref(dst);
+ return NULL;
+}
+
+/**
* qdict_array_entries(): Returns the number of direct array entries if the
* sub-QDict of src specified by the prefix in subqdict (or src itself for
* prefix == "") is valid as an array, i.e. the length of the created list if
diff --git a/qom/object_interfaces.c b/qom/object_interfaces.c
index bf59846..ded4d84 100644
--- a/qom/object_interfaces.c
+++ b/qom/object_interfaces.c
@@ -3,7 +3,7 @@
#include "qom/object_interfaces.h"
#include "qemu/module.h"
#include "qapi-visit.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/opts-visitor.h"
void user_creatable_complete(Object *obj, Error **errp)
diff --git a/qom/qom-qobject.c b/qom/qom-qobject.c
index c225abc..447e4a0 100644
--- a/qom/qom-qobject.c
+++ b/qom/qom-qobject.c
@@ -15,15 +15,15 @@
#include "qom/object.h"
#include "qom/qom-qobject.h"
#include "qapi/visitor.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
void object_property_set_qobject(Object *obj, QObject *value,
const char *name, Error **errp)
{
Visitor *v;
/* TODO: Should we reject, rather than ignore, excess input? */
- v = qmp_input_visitor_new(value, false);
+ v = qobject_input_visitor_new(value, false);
object_property_set(obj, v, name, errp);
visit_free(v);
}
@@ -35,7 +35,7 @@
Error *local_err = NULL;
Visitor *v;
- v = qmp_output_visitor_new(&ret);
+ v = qobject_output_visitor_new(&ret);
object_property_get(obj, v, name, &local_err);
if (!local_err) {
visit_complete(v, &ret);
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 2f603b0..09e8467 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -68,7 +68,7 @@
Error *err = NULL;
Visitor *v;
- v = qmp_output_visitor_new(ret_out);
+ v = qobject_output_visitor_new(ret_out);
visit_type_%(c_name)s(v, "unused", &ret_in, &err);
if (!err) {
visit_complete(v, ret_out);
@@ -130,7 +130,7 @@
push_indent()
ret += mcgen('''
- v = qmp_input_visitor_new(QOBJECT(args), true);
+ v = qobject_input_visitor_new(QOBJECT(args), true);
visit_start_struct(v, NULL, NULL, 0, &err);
if (err) {
goto out;
@@ -293,8 +293,8 @@
#include "qapi/qmp/types.h"
#include "qapi/qmp/dispatch.h"
#include "qapi/visitor.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "qapi/dealloc-visitor.h"
#include "%(prefix)sqapi-types.h"
#include "%(prefix)sqapi-visit.h"
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 38d8211..f4eb7f8 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -98,7 +98,7 @@
if arg_type and not arg_type.is_empty():
ret += mcgen('''
- v = qmp_output_visitor_new(&obj);
+ v = qobject_output_visitor_new(&obj);
''')
if not arg_type.is_implicit():
ret += mcgen('''
@@ -209,7 +209,7 @@
#include "qemu-common.h"
#include "%(prefix)sqapi-event.h"
#include "%(prefix)sqapi-visit.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/qmp-event.h"
''',
diff --git a/target-s390x/cpu_models.c b/target-s390x/cpu_models.c
index 3ff6a70..c1e729d 100644
--- a/target-s390x/cpu_models.c
+++ b/target-s390x/cpu_models.c
@@ -17,7 +17,7 @@
#include "qapi/visitor.h"
#include "qemu/error-report.h"
#include "qapi/qmp/qerror.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "qapi/qmp/qbool.h"
#ifndef CONFIG_USER_ONLY
#include "sysemu/arch_init.h"
@@ -345,7 +345,7 @@
}
if (qdict) {
- visitor = qmp_input_visitor_new(info->props, true);
+ visitor = qobject_input_visitor_new(info->props, true);
visit_start_struct(visitor, NULL, NULL, 0, errp);
if (*errp) {
object_unref(obj);
diff --git a/tests/.gitignore b/tests/.gitignore
index 9f3d2ee..4aec8bc 100644
--- a/tests/.gitignore
+++ b/tests/.gitignore
@@ -59,11 +59,11 @@
test-qmp-commands
test-qmp-commands.h
test-qmp-event
-test-qmp-input-strict
-test-qmp-input-visitor
+test-qobject-input-strict
+test-qobject-input-visitor
test-qmp-introspect.[ch]
test-qmp-marshal.c
-test-qmp-output-visitor
+test-qobject-output-visitor
test-rcu-list
test-replication
test-rfifolock
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 73931d1..cd058ef 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -22,13 +22,13 @@
gcov-files-check-qnull-y = qobject/qnull.c
check-unit-y += tests/check-qjson$(EXESUF)
gcov-files-check-qjson-y = qobject/qjson.c
-check-unit-y += tests/test-qmp-output-visitor$(EXESUF)
-gcov-files-test-qmp-output-visitor-y = qapi/qmp-output-visitor.c
+check-unit-y += tests/test-qobject-output-visitor$(EXESUF)
+gcov-files-test-qobject-output-visitor-y = qapi/qobject-output-visitor.c
check-unit-y += tests/test-clone-visitor$(EXESUF)
gcov-files-test-clone-visitor-y = qapi/qapi-clone-visitor.c
-check-unit-y += tests/test-qmp-input-visitor$(EXESUF)
-gcov-files-test-qmp-input-visitor-y = qapi/qmp-input-visitor.c
-check-unit-y += tests/test-qmp-input-strict$(EXESUF)
+check-unit-y += tests/test-qobject-input-visitor$(EXESUF)
+gcov-files-test-qobject-input-visitor-y = qapi/qobject-input-visitor.c
+check-unit-y += tests/test-qobject-input-strict$(EXESUF)
check-unit-y += tests/test-qmp-commands$(EXESUF)
gcov-files-test-qmp-commands-y = qapi/qmp-dispatch.c
check-unit-y += tests/test-string-input-visitor$(EXESUF)
@@ -452,9 +452,9 @@
tests/check-qlist.o tests/check-qfloat.o tests/check-qnull.o \
tests/check-qjson.o \
tests/test-coroutine.o tests/test-string-output-visitor.o \
- tests/test-string-input-visitor.o tests/test-qmp-output-visitor.o \
+ tests/test-string-input-visitor.o tests/test-qobject-output-visitor.o \
tests/test-clone-visitor.o \
- tests/test-qmp-input-visitor.o tests/test-qmp-input-strict.o \
+ tests/test-qobject-input-visitor.o tests/test-qobject-input-strict.o \
tests/test-qmp-commands.o tests/test-visitor-serialization.o \
tests/test-x86-cpuid.o tests/test-mul64.o tests/test-int128.o \
tests/test-opts-visitor.o tests/test-qmp-event.o \
@@ -558,10 +558,10 @@
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)
tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y)
tests/test-qmp-event$(EXESUF): tests/test-qmp-event.o $(test-qapi-obj-y)
-tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y)
+tests/test-qobject-output-visitor$(EXESUF): tests/test-qobject-output-visitor.o $(test-qapi-obj-y)
tests/test-clone-visitor$(EXESUF): tests/test-clone-visitor.o $(test-qapi-obj-y)
-tests/test-qmp-input-visitor$(EXESUF): tests/test-qmp-input-visitor.o $(test-qapi-obj-y)
-tests/test-qmp-input-strict$(EXESUF): tests/test-qmp-input-strict.o $(test-qapi-obj-y)
+tests/test-qobject-input-visitor$(EXESUF): tests/test-qobject-input-visitor.o $(test-qapi-obj-y)
+tests/test-qobject-input-strict$(EXESUF): tests/test-qobject-input-strict.o $(test-qapi-obj-y)
tests/test-qmp-commands$(EXESUF): tests/test-qmp-commands.o tests/test-qmp-marshal.o $(test-qapi-obj-y)
tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(test-qapi-obj-y)
tests/test-opts-visitor$(EXESUF): tests/test-opts-visitor.o $(test-qapi-obj-y)
diff --git a/tests/check-qdict.c b/tests/check-qdict.c
index 42da1e6..07b1c79 100644
--- a/tests/check-qdict.c
+++ b/tests/check-qdict.c
@@ -14,6 +14,7 @@
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qstring.h"
+#include "qapi/error.h"
#include "qemu-common.h"
/*
@@ -412,7 +413,6 @@
QDECREF(test_dict);
-
/*
* Test the split of
*
@@ -518,7 +518,6 @@
dict1 = qdict_new();
dict2 = qdict_new();
-
/* Test everything once without overwrite and once with */
do
{
@@ -528,7 +527,6 @@
g_assert(qdict_size(dict1) == 0);
g_assert(qdict_size(dict2) == 0);
-
/* First iteration: Test movement */
/* Second iteration: Test empty source and non-empty destination */
qdict_put(dict2, "foo", qint_from_int(42));
@@ -542,7 +540,6 @@
g_assert(qdict_get_int(dict1, "foo") == 42);
}
-
/* Test non-empty source and destination without conflict */
qdict_put(dict2, "bar", qint_from_int(23));
@@ -554,7 +551,6 @@
g_assert(qdict_get_int(dict1, "foo") == 42);
g_assert(qdict_get_int(dict1, "bar") == 23);
-
/* Test conflict */
qdict_put(dict2, "foo", qint_from_int(84));
@@ -570,7 +566,6 @@
g_assert(qdict_get_int(dict2, "foo") == 84);
}
-
/* Check the references */
g_assert(qdict_get(dict1, "foo")->refcnt == 1);
g_assert(qdict_get(dict1, "bar")->refcnt == 1);
@@ -579,7 +574,6 @@
g_assert(qdict_get(dict2, "foo")->refcnt == 1);
}
-
/* Clean up */
qdict_del(dict1, "foo");
qdict_del(dict1, "bar");
@@ -590,11 +584,152 @@
}
while (overwrite ^= true);
-
QDECREF(dict1);
QDECREF(dict2);
}
+static void qdict_crumple_test_recursive(void)
+{
+ QDict *src, *dst, *rule, *vnc, *acl, *listen;
+ QObject *child, *res;
+ QList *rules;
+
+ src = qdict_new();
+ qdict_put(src, "vnc.listen.addr", qstring_from_str("127.0.0.1"));
+ qdict_put(src, "vnc.listen.port", qstring_from_str("5901"));
+ qdict_put(src, "vnc.acl.rules.0.match", qstring_from_str("fred"));
+ qdict_put(src, "vnc.acl.rules.0.policy", qstring_from_str("allow"));
+ qdict_put(src, "vnc.acl.rules.1.match", qstring_from_str("bob"));
+ qdict_put(src, "vnc.acl.rules.1.policy", qstring_from_str("deny"));
+ qdict_put(src, "vnc.acl.default", qstring_from_str("deny"));
+ qdict_put(src, "vnc.acl..name", qstring_from_str("acl0"));
+ qdict_put(src, "vnc.acl.rule..name", qstring_from_str("acl0"));
+
+ res = qdict_crumple(src, &error_abort);
+
+ g_assert_cmpint(qobject_type(res), ==, QTYPE_QDICT);
+
+ dst = qobject_to_qdict(res);
+
+ g_assert_cmpint(qdict_size(dst), ==, 1);
+
+ child = qdict_get(dst, "vnc");
+ g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
+ vnc = qobject_to_qdict(child);
+
+ child = qdict_get(vnc, "listen");
+ g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
+ listen = qobject_to_qdict(child);
+ g_assert_cmpstr("127.0.0.1", ==, qdict_get_str(listen, "addr"));
+ g_assert_cmpstr("5901", ==, qdict_get_str(listen, "port"));
+
+ child = qdict_get(vnc, "acl");
+ g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
+ acl = qobject_to_qdict(child);
+
+ child = qdict_get(acl, "rules");
+ g_assert_cmpint(qobject_type(child), ==, QTYPE_QLIST);
+ rules = qobject_to_qlist(child);
+ g_assert_cmpint(qlist_size(rules), ==, 2);
+
+ rule = qobject_to_qdict(qlist_pop(rules));
+ g_assert_cmpint(qdict_size(rule), ==, 2);
+ g_assert_cmpstr("fred", ==, qdict_get_str(rule, "match"));
+ g_assert_cmpstr("allow", ==, qdict_get_str(rule, "policy"));
+ QDECREF(rule);
+
+ rule = qobject_to_qdict(qlist_pop(rules));
+ g_assert_cmpint(qdict_size(rule), ==, 2);
+ g_assert_cmpstr("bob", ==, qdict_get_str(rule, "match"));
+ g_assert_cmpstr("deny", ==, qdict_get_str(rule, "policy"));
+ QDECREF(rule);
+
+ /* With recursive crumpling, we should see all names unescaped */
+ g_assert_cmpstr("acl0", ==, qdict_get_str(vnc, "acl.name"));
+ child = qdict_get(vnc, "acl");
+ g_assert_cmpint(qobject_type(child), ==, QTYPE_QDICT);
+ acl = qdict_get_qdict(vnc, "acl");
+ g_assert_cmpstr("acl0", ==, qdict_get_str(acl, "rule.name"));
+
+ QDECREF(src);
+ QDECREF(dst);
+}
+
+static void qdict_crumple_test_empty(void)
+{
+ QDict *src, *dst;
+
+ src = qdict_new();
+
+ dst = (QDict *)qdict_crumple(src, &error_abort);
+
+ g_assert_cmpint(qdict_size(dst), ==, 0);
+
+ QDECREF(src);
+ QDECREF(dst);
+}
+
+static void qdict_crumple_test_bad_inputs(void)
+{
+ QDict *src;
+ Error *error = NULL;
+
+ src = qdict_new();
+ /* rule.0 can't be both a string and a dict */
+ qdict_put(src, "rule.0", qstring_from_str("fred"));
+ qdict_put(src, "rule.0.policy", qstring_from_str("allow"));
+
+ g_assert(qdict_crumple(src, &error) == NULL);
+ g_assert(error != NULL);
+ error_free(error);
+ error = NULL;
+ QDECREF(src);
+
+ src = qdict_new();
+ /* rule can't be both a list and a dict */
+ qdict_put(src, "rule.0", qstring_from_str("fred"));
+ qdict_put(src, "rule.a", qstring_from_str("allow"));
+
+ g_assert(qdict_crumple(src, &error) == NULL);
+ g_assert(error != NULL);
+ error_free(error);
+ error = NULL;
+ QDECREF(src);
+
+ src = qdict_new();
+ /* The input should be flat, ie no dicts or lists */
+ qdict_put(src, "rule.a", qdict_new());
+ qdict_put(src, "rule.b", qstring_from_str("allow"));
+
+ g_assert(qdict_crumple(src, &error) == NULL);
+ g_assert(error != NULL);
+ error_free(error);
+ error = NULL;
+ QDECREF(src);
+
+ src = qdict_new();
+ /* List indexes must not have gaps */
+ qdict_put(src, "rule.0", qstring_from_str("deny"));
+ qdict_put(src, "rule.3", qstring_from_str("allow"));
+
+ g_assert(qdict_crumple(src, &error) == NULL);
+ g_assert(error != NULL);
+ error_free(error);
+ error = NULL;
+ QDECREF(src);
+
+ src = qdict_new();
+ /* List indexes must be in %zu format */
+ qdict_put(src, "rule.0", qstring_from_str("deny"));
+ qdict_put(src, "rule.+1", qstring_from_str("allow"));
+
+ g_assert(qdict_crumple(src, &error) == NULL);
+ g_assert(error != NULL);
+ error_free(error);
+ error = NULL;
+ QDECREF(src);
+}
+
/*
* Errors test-cases
*/
@@ -742,6 +877,13 @@
g_test_add_func("/errors/put_exists", qdict_put_exists_test);
g_test_add_func("/errors/get_not_exists", qdict_get_not_exists_test);
+ g_test_add_func("/public/crumple/recursive",
+ qdict_crumple_test_recursive);
+ g_test_add_func("/public/crumple/empty",
+ qdict_crumple_test_empty);
+ g_test_add_func("/public/crumple/bad_inputs",
+ qdict_crumple_test_bad_inputs);
+
/* The Big one */
if (g_test_slow()) {
g_test_add_func("/stress/test", qdict_stress_test);
diff --git a/tests/check-qnull.c b/tests/check-qnull.c
index dc906b1..b50bb8a 100644
--- a/tests/check-qnull.c
+++ b/tests/check-qnull.c
@@ -10,8 +10,8 @@
#include "qapi/qmp/qobject.h"
#include "qemu-common.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/error.h"
/*
@@ -47,12 +47,12 @@
g_assert(qnull_.refcnt == 1);
obj = qnull();
- v = qmp_input_visitor_new(obj, true);
+ v = qobject_input_visitor_new(obj, true);
qobject_decref(obj);
visit_type_null(v, NULL, &error_abort);
visit_free(v);
- v = qmp_output_visitor_new(&obj);
+ v = qobject_output_visitor_new(&obj);
visit_type_null(v, NULL, &error_abort);
visit_complete(v, &obj);
g_assert(obj == &qnull_);
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 81cbe54..ff94481 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -4,7 +4,7 @@
#include "test-qmp-commands.h"
#include "qapi/qmp/dispatch.h"
#include "qemu/module.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "tests/test-qapi-types.h"
#include "tests/test-qapi-visit.h"
@@ -244,7 +244,7 @@
ud2_dict = qdict_new();
qdict_put_obj(ud2_dict, "string0", QOBJECT(qstring_from_str(text)));
- v = qmp_input_visitor_new(QOBJECT(ud2_dict), true);
+ v = qobject_input_visitor_new(QOBJECT(ud2_dict), true);
visit_type_UserDefTwo(v, NULL, &ud2, &err);
visit_free(v);
QDECREF(ud2_dict);
diff --git a/tests/test-qmp-input-strict.c b/tests/test-qobject-input-strict.c
similarity index 98%
rename from tests/test-qmp-input-strict.c
rename to tests/test-qobject-input-strict.c
index d87f8b8..4087ea3 100644
--- a/tests/test-qmp-input-strict.c
+++ b/tests/test-qobject-input-strict.c
@@ -1,5 +1,5 @@
/*
- * QMP Input Visitor unit-tests (strict mode).
+ * QObject Input Visitor unit-tests (strict mode).
*
* Copyright (C) 2011-2012, 2015 Red Hat Inc.
*
@@ -15,7 +15,7 @@
#include "qemu-common.h"
#include "qapi/error.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
@@ -53,7 +53,7 @@
data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
- data->qiv = qmp_input_visitor_new(data->obj, true);
+ data->qiv = qobject_input_visitor_new(data->obj, true);
g_assert(data->qiv);
return data->qiv;
}
diff --git a/tests/test-qmp-input-visitor.c b/tests/test-qobject-input-visitor.c
similarity index 91%
rename from tests/test-qmp-input-visitor.c
rename to tests/test-qobject-input-visitor.c
index f583dce..26c5012 100644
--- a/tests/test-qmp-input-visitor.c
+++ b/tests/test-qobject-input-visitor.c
@@ -1,5 +1,5 @@
/*
- * QMP Input Visitor unit-tests.
+ * QObject Input Visitor unit-tests.
*
* Copyright (C) 2011-2016 Red Hat Inc.
*
@@ -14,7 +14,7 @@
#include "qemu-common.h"
#include "qapi/error.h"
-#include "qapi/qmp-input-visitor.h"
+#include "qapi/qobject-input-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
@@ -49,7 +49,7 @@
data->obj = qobject_from_jsonv(json_string, ap);
g_assert(data->obj);
- data->qiv = qmp_input_visitor_new(data->obj, false);
+ data->qiv = qobject_input_visitor_new(data->obj, false);
g_assert(data->qiv);
return data->qiv;
}
@@ -747,10 +747,11 @@
}
static void input_visitor_test_add(const char *testpath,
- TestInputVisitorData *data,
- void (*test_func)(TestInputVisitorData *data, const void *user_data))
+ const void *user_data,
+ void (*test_func)(TestInputVisitorData *data,
+ const void *user_data))
{
- g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+ g_test_add(testpath, TestInputVisitorData, user_data, NULL, test_func,
visitor_input_teardown);
}
@@ -833,77 +834,64 @@
int main(int argc, char **argv)
{
- TestInputVisitorData in_visitor_data;
-
g_test_init(&argc, &argv, NULL);
input_visitor_test_add("/visitor/input/int",
- &in_visitor_data, test_visitor_in_int);
+ NULL, test_visitor_in_int);
input_visitor_test_add("/visitor/input/int_overflow",
- &in_visitor_data, test_visitor_in_int_overflow);
+ NULL, test_visitor_in_int_overflow);
input_visitor_test_add("/visitor/input/bool",
- &in_visitor_data, test_visitor_in_bool);
+ NULL, test_visitor_in_bool);
input_visitor_test_add("/visitor/input/number",
- &in_visitor_data, test_visitor_in_number);
+ NULL, test_visitor_in_number);
input_visitor_test_add("/visitor/input/string",
- &in_visitor_data, test_visitor_in_string);
+ NULL, test_visitor_in_string);
input_visitor_test_add("/visitor/input/enum",
- &in_visitor_data, test_visitor_in_enum);
+ NULL, test_visitor_in_enum);
input_visitor_test_add("/visitor/input/struct",
- &in_visitor_data, test_visitor_in_struct);
+ NULL, test_visitor_in_struct);
input_visitor_test_add("/visitor/input/struct-nested",
- &in_visitor_data, test_visitor_in_struct_nested);
+ NULL, test_visitor_in_struct_nested);
input_visitor_test_add("/visitor/input/list",
- &in_visitor_data, test_visitor_in_list);
+ NULL, test_visitor_in_list);
input_visitor_test_add("/visitor/input/any",
- &in_visitor_data, test_visitor_in_any);
+ NULL, test_visitor_in_any);
input_visitor_test_add("/visitor/input/null",
- &in_visitor_data, test_visitor_in_null);
+ NULL, test_visitor_in_null);
input_visitor_test_add("/visitor/input/union-flat",
- &in_visitor_data, test_visitor_in_union_flat);
+ NULL, test_visitor_in_union_flat);
input_visitor_test_add("/visitor/input/alternate",
- &in_visitor_data, test_visitor_in_alternate);
+ NULL, test_visitor_in_alternate);
input_visitor_test_add("/visitor/input/errors",
- &in_visitor_data, test_visitor_in_errors);
+ NULL, test_visitor_in_errors);
input_visitor_test_add("/visitor/input/wrong-type",
- &in_visitor_data, test_visitor_in_wrong_type);
+ NULL, test_visitor_in_wrong_type);
input_visitor_test_add("/visitor/input/alternate-number",
- &in_visitor_data, test_visitor_in_alternate_number);
+ NULL, test_visitor_in_alternate_number);
input_visitor_test_add("/visitor/input/native_list/int",
- &in_visitor_data,
- test_visitor_in_native_list_int);
+ NULL, test_visitor_in_native_list_int);
input_visitor_test_add("/visitor/input/native_list/int8",
- &in_visitor_data,
- test_visitor_in_native_list_int8);
+ NULL, test_visitor_in_native_list_int8);
input_visitor_test_add("/visitor/input/native_list/int16",
- &in_visitor_data,
- test_visitor_in_native_list_int16);
+ NULL, test_visitor_in_native_list_int16);
input_visitor_test_add("/visitor/input/native_list/int32",
- &in_visitor_data,
- test_visitor_in_native_list_int32);
+ NULL, test_visitor_in_native_list_int32);
input_visitor_test_add("/visitor/input/native_list/int64",
- &in_visitor_data,
- test_visitor_in_native_list_int64);
+ NULL, test_visitor_in_native_list_int64);
input_visitor_test_add("/visitor/input/native_list/uint8",
- &in_visitor_data,
- test_visitor_in_native_list_uint8);
+ NULL, test_visitor_in_native_list_uint8);
input_visitor_test_add("/visitor/input/native_list/uint16",
- &in_visitor_data,
- test_visitor_in_native_list_uint16);
+ NULL, test_visitor_in_native_list_uint16);
input_visitor_test_add("/visitor/input/native_list/uint32",
- &in_visitor_data,
- test_visitor_in_native_list_uint32);
+ NULL, test_visitor_in_native_list_uint32);
input_visitor_test_add("/visitor/input/native_list/uint64",
- &in_visitor_data,
- test_visitor_in_native_list_uint64);
+ NULL, test_visitor_in_native_list_uint64);
input_visitor_test_add("/visitor/input/native_list/bool",
- &in_visitor_data, test_visitor_in_native_list_bool);
+ NULL, test_visitor_in_native_list_bool);
input_visitor_test_add("/visitor/input/native_list/str",
- &in_visitor_data,
- test_visitor_in_native_list_string);
+ NULL, test_visitor_in_native_list_string);
input_visitor_test_add("/visitor/input/native_list/number",
- &in_visitor_data,
- test_visitor_in_native_list_number);
+ NULL, test_visitor_in_native_list_number);
g_test_run();
diff --git a/tests/test-qmp-output-visitor.c b/tests/test-qobject-output-visitor.c
similarity index 99%
rename from tests/test-qmp-output-visitor.c
rename to tests/test-qobject-output-visitor.c
index 513d71f..4e2d79c 100644
--- a/tests/test-qmp-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -1,5 +1,5 @@
/*
- * QMP Output Visitor unit-tests.
+ * QObject Output Visitor unit-tests.
*
* Copyright (C) 2011-2016 Red Hat Inc.
*
@@ -14,7 +14,7 @@
#include "qemu-common.h"
#include "qapi/error.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "test-qapi-types.h"
#include "test-qapi-visit.h"
#include "qapi/qmp/types.h"
@@ -28,7 +28,7 @@
static void visitor_output_setup(TestOutputVisitorData *data,
const void *unused)
{
- data->ov = qmp_output_visitor_new(&data->obj);
+ data->ov = qobject_output_visitor_new(&data->obj);
g_assert(data->ov);
}
diff --git a/tests/test-string-input-visitor.c b/tests/test-string-input-visitor.c
index a679fbc..7f10e25 100644
--- a/tests/test-string-input-visitor.c
+++ b/tests/test-string-input-visitor.c
@@ -4,7 +4,7 @@
* Copyright (C) 2012 Red Hat Inc.
*
* Authors:
- * Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
+ * Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-input-visitor)
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 444844a..e736db3 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -4,7 +4,7 @@
* Copyright (C) 2012 Red Hat Inc.
*
* Authors:
- * Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
+ * Paolo Bonzini <pbonzini@redhat.com> (based on test-qobject-output-visitor)
*
* This work is licensed under the terms of the GNU GPL, version 2 or later.
* See the COPYING file in the top-level directory.
diff --git a/tests/test-visitor-serialization.c b/tests/test-visitor-serialization.c
index dba4670..66b2b1c 100644
--- a/tests/test-visitor-serialization.c
+++ b/tests/test-visitor-serialization.c
@@ -20,8 +20,8 @@
#include "qapi/error.h"
#include "qapi/qmp/types.h"
#include "qapi/qmp/qjson.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi/string-input-visitor.h"
#include "qapi/string-output-visitor.h"
#include "qapi-types.h"
@@ -1022,7 +1022,7 @@
{
QmpSerializeData *d = g_malloc0(sizeof(*d));
- d->qov = qmp_output_visitor_new(&d->obj);
+ d->qov = qobject_output_visitor_new(&d->obj);
visit(d->qov, &native_in, errp);
*datap = d;
}
@@ -1040,7 +1040,7 @@
obj = qobject_from_json(qstring_get_str(output_json));
QDECREF(output_json);
- d->qiv = qmp_input_visitor_new(obj, true);
+ d->qiv = qobject_input_visitor_new(obj, true);
qobject_decref(obj_orig);
qobject_decref(obj);
visit(d->qiv, native_out, errp);
diff --git a/util/qemu-sockets.c b/util/qemu-sockets.c
index 6db48b3..4cef549 100644
--- a/util/qemu-sockets.c
+++ b/util/qemu-sockets.c
@@ -21,8 +21,8 @@
#include "qapi/error.h"
#include "qemu/sockets.h"
#include "qemu/main-loop.h"
-#include "qapi/qmp-input-visitor.h"
-#include "qapi/qmp-output-visitor.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qobject-output-visitor.h"
#include "qapi-visit.h"
#include "qemu/cutils.h"