On Fri, 3 Jun 2011 17:33:09 -0500
Michael Roth<address@hidden> wrote:
Type of Visiter class that serves as the inverse of the input visiter:
it takes a series of native C types and uses their values to construct a
corresponding QObject. The command marshaling/dispatcher functions will
use this to convert the output of QMP functions into a QObject that can
be sent over the wire.
Signed-off-by: Michael Roth<address@hidden>
---
qapi/qmp-output-visiter.c | 180 +++++++++++++++++++++++++++++++++++++++++++++
qapi/qmp-output-visiter.h | 27 +++++++
2 files changed, 207 insertions(+), 0 deletions(-)
create mode 100644 qapi/qmp-output-visiter.c
create mode 100644 qapi/qmp-output-visiter.h
diff --git a/qapi/qmp-output-visiter.c b/qapi/qmp-output-visiter.c
new file mode 100644
index 0000000..4a7cb36
--- /dev/null
+++ b/qapi/qmp-output-visiter.c
@@ -0,0 +1,180 @@
+#include "qmp-output-visiter.h"
+#include "qemu-queue.h"
+#include "qemu-common.h"
+#include "qemu-objects.h"
+
+typedef struct QStackEntry
+{
+ QObject *value;
+ QTAILQ_ENTRY(QStackEntry) node;
+} QStackEntry;
+
+typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
+
+struct QmpOutputVisiter
+{
+ Visiter visiter;
+ QStack stack;
+};
+
+#define qmp_output_add(qov, name, value) qmp_output_add_obj(qov, name,
QOBJECT(value))
+#define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
+
+static QmpOutputVisiter *to_qov(Visiter *v)
+{
+ return container_of(v, QmpOutputVisiter, visiter);
+}
+
+static void qmp_output_push_obj(QmpOutputVisiter *qov, QObject *value)
+{
+ QStackEntry *e = qemu_mallocz(sizeof(*e));
+
+ e->value = value;
+ QTAILQ_INSERT_HEAD(&qov->stack, e, node);
+}
+
+static QObject *qmp_output_pop(QmpOutputVisiter *qov)
+{
+ QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+ QObject *value;
+ QTAILQ_REMOVE(&qov->stack, e, node);
+ value = e->value;
+ qemu_free(e);
+ return value;
+}
+
+static QObject *qmp_output_first(QmpOutputVisiter *qov)
+{
+ QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack);
+ return e->value;
+}
+
+static QObject *qmp_output_last(QmpOutputVisiter *qov)
+{
+ QStackEntry *e = QTAILQ_FIRST(&qov->stack);
+ return e->value;
+}
+
+static void qmp_output_add_obj(QmpOutputVisiter *qov, const char *name,
QObject *value)
+{
+ QObject *cur;
+
+ if (QTAILQ_EMPTY(&qov->stack)) {
+ qmp_output_push_obj(qov, value);
+ return;
+ }
+
+ cur = qmp_output_last(qov);
+
+ switch (qobject_type(cur)) {
+ case QTYPE_QDICT:
+ qdict_put_obj(qobject_to_qdict(cur), name, value);
+ break;
+ case QTYPE_QLIST:
+ qlist_append_obj(qobject_to_qlist(cur), value);
+ break;
+ default:
+ qobject_decref(qmp_output_pop(qov));
I'm not sure I understand when we should discard an item like this,
shouldn't this be an assert()?
+ qmp_output_push_obj(qov, value);
+ break;
+ }
+}
+
+static void qmp_output_start_struct(Visiter *v, void **obj, const char *kind,
const char *name, Error **errp)
+{
+ QmpOutputVisiter *qov = to_qov(v);
+ QDict *dict = qdict_new();
+
+ qmp_output_add(qov, name, dict);
This calls qmp_output_push() if the stack is empty...
+ qmp_output_push(qov, dict);
...then it's called again here, so the element is added twice,
is this expected?