usb-bot: hotplug support
[qemu/kevin.git] / qapi / qmp-output-visitor.c
blob4d3cf78333bbcb88ea88f242568a5ecbccf1f605
1 /*
2 * Core Definitions for QAPI/QMP Command Registry
4 * Copyright (C) 2012-2016 Red Hat, Inc.
5 * Copyright IBM, Corp. 2011
7 * Authors:
8 * Anthony Liguori <aliguori@us.ibm.com>
10 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
11 * See the COPYING.LIB file in the top-level directory.
15 #include "qemu/osdep.h"
16 #include "qapi/qmp-output-visitor.h"
17 #include "qapi/visitor-impl.h"
18 #include "qemu/queue.h"
19 #include "qemu-common.h"
20 #include "qapi/qmp/types.h"
22 typedef struct QStackEntry
24 QObject *value;
25 QTAILQ_ENTRY(QStackEntry) node;
26 } QStackEntry;
28 typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
30 struct QmpOutputVisitor
32 Visitor visitor;
33 QStack stack; /* Stack of containers that haven't yet been finished */
34 QObject *root; /* Root of the output visit */
37 #define qmp_output_add(qov, name, value) \
38 qmp_output_add_obj(qov, name, QOBJECT(value))
39 #define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
41 static QmpOutputVisitor *to_qov(Visitor *v)
43 return container_of(v, QmpOutputVisitor, visitor);
46 /* Push @value onto the stack of current QObjects being built */
47 static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value)
49 QStackEntry *e = g_malloc0(sizeof(*e));
51 assert(qov->root);
52 assert(value);
53 e->value = value;
54 QTAILQ_INSERT_HEAD(&qov->stack, e, node);
57 /* Pop a value off the stack of QObjects being built, and return it. */
58 static QObject *qmp_output_pop(QmpOutputVisitor *qov)
60 QStackEntry *e = QTAILQ_FIRST(&qov->stack);
61 QObject *value;
63 assert(e);
64 QTAILQ_REMOVE(&qov->stack, e, node);
65 value = e->value;
66 assert(value);
67 g_free(e);
68 return value;
71 /* Add @value to the current QObject being built.
72 * If the stack is visiting a dictionary or list, @value is now owned
73 * by that container. Otherwise, @value is now the root. */
74 static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name,
75 QObject *value)
77 QStackEntry *e = QTAILQ_FIRST(&qov->stack);
78 QObject *cur = e ? e->value : NULL;
80 if (!cur) {
81 /* Don't allow reuse of visitor on more than one root */
82 assert(!qov->root);
83 qov->root = value;
84 } else {
85 switch (qobject_type(cur)) {
86 case QTYPE_QDICT:
87 assert(name);
88 qdict_put_obj(qobject_to_qdict(cur), name, value);
89 break;
90 case QTYPE_QLIST:
91 assert(!name);
92 qlist_append_obj(qobject_to_qlist(cur), value);
93 break;
94 default:
95 g_assert_not_reached();
100 static void qmp_output_start_struct(Visitor *v, const char *name, void **obj,
101 size_t unused, Error **errp)
103 QmpOutputVisitor *qov = to_qov(v);
104 QDict *dict = qdict_new();
106 qmp_output_add(qov, name, dict);
107 qmp_output_push(qov, dict);
110 static void qmp_output_end_struct(Visitor *v)
112 QmpOutputVisitor *qov = to_qov(v);
113 QObject *value = qmp_output_pop(qov);
114 assert(qobject_type(value) == QTYPE_QDICT);
117 static void qmp_output_start_list(Visitor *v, const char *name,
118 GenericList **listp, size_t size,
119 Error **errp)
121 QmpOutputVisitor *qov = to_qov(v);
122 QList *list = qlist_new();
124 qmp_output_add(qov, name, list);
125 qmp_output_push(qov, list);
128 static GenericList *qmp_output_next_list(Visitor *v, GenericList *tail,
129 size_t size)
131 return tail->next;
134 static void qmp_output_end_list(Visitor *v)
136 QmpOutputVisitor *qov = to_qov(v);
137 QObject *value = qmp_output_pop(qov);
138 assert(qobject_type(value) == QTYPE_QLIST);
141 static void qmp_output_type_int64(Visitor *v, const char *name, int64_t *obj,
142 Error **errp)
144 QmpOutputVisitor *qov = to_qov(v);
145 qmp_output_add(qov, name, qint_from_int(*obj));
148 static void qmp_output_type_uint64(Visitor *v, const char *name, uint64_t *obj,
149 Error **errp)
151 /* FIXME: QMP outputs values larger than INT64_MAX as negative */
152 QmpOutputVisitor *qov = to_qov(v);
153 qmp_output_add(qov, name, qint_from_int(*obj));
156 static void qmp_output_type_bool(Visitor *v, const char *name, bool *obj,
157 Error **errp)
159 QmpOutputVisitor *qov = to_qov(v);
160 qmp_output_add(qov, name, qbool_from_bool(*obj));
163 static void qmp_output_type_str(Visitor *v, const char *name, char **obj,
164 Error **errp)
166 QmpOutputVisitor *qov = to_qov(v);
167 if (*obj) {
168 qmp_output_add(qov, name, qstring_from_str(*obj));
169 } else {
170 qmp_output_add(qov, name, qstring_from_str(""));
174 static void qmp_output_type_number(Visitor *v, const char *name, double *obj,
175 Error **errp)
177 QmpOutputVisitor *qov = to_qov(v);
178 qmp_output_add(qov, name, qfloat_from_double(*obj));
181 static void qmp_output_type_any(Visitor *v, const char *name, QObject **obj,
182 Error **errp)
184 QmpOutputVisitor *qov = to_qov(v);
185 qobject_incref(*obj);
186 qmp_output_add_obj(qov, name, *obj);
189 static void qmp_output_type_null(Visitor *v, const char *name, Error **errp)
191 QmpOutputVisitor *qov = to_qov(v);
192 qmp_output_add_obj(qov, name, qnull());
195 /* Finish building, and return the root object.
196 * The root object is never null. The caller becomes the object's
197 * owner, and should use qobject_decref() when done with it. */
198 QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
200 /* A visit must have occurred, with each start paired with end. */
201 assert(qov->root && QTAILQ_EMPTY(&qov->stack));
203 qobject_incref(qov->root);
204 return qov->root;
207 Visitor *qmp_output_get_visitor(QmpOutputVisitor *v)
209 return &v->visitor;
212 void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
214 QStackEntry *e, *tmp;
216 QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) {
217 QTAILQ_REMOVE(&v->stack, e, node);
218 g_free(e);
221 qobject_decref(v->root);
222 g_free(v);
225 QmpOutputVisitor *qmp_output_visitor_new(void)
227 QmpOutputVisitor *v;
229 v = g_malloc0(sizeof(*v));
231 v->visitor.type = VISITOR_OUTPUT;
232 v->visitor.start_struct = qmp_output_start_struct;
233 v->visitor.end_struct = qmp_output_end_struct;
234 v->visitor.start_list = qmp_output_start_list;
235 v->visitor.next_list = qmp_output_next_list;
236 v->visitor.end_list = qmp_output_end_list;
237 v->visitor.type_int64 = qmp_output_type_int64;
238 v->visitor.type_uint64 = qmp_output_type_uint64;
239 v->visitor.type_bool = qmp_output_type_bool;
240 v->visitor.type_str = qmp_output_type_str;
241 v->visitor.type_number = qmp_output_type_number;
242 v->visitor.type_any = qmp_output_type_any;
243 v->visitor.type_null = qmp_output_type_null;
245 QTAILQ_INIT(&v->stack);
247 return v;