ivshmem: Implement shm=... with a memory backend
[qemu/kevin.git] / qapi / qmp-input-visitor.c
blobe6598327c32ee35e37aa3ad9cc54fcceae951141
1 /*
2 * Input Visitor
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-input-visitor.h"
17 #include "qapi/visitor-impl.h"
18 #include "qemu/queue.h"
19 #include "qemu-common.h"
20 #include "qapi/qmp/types.h"
21 #include "qapi/qmp/qerror.h"
23 #define QIV_STACK_SIZE 1024
25 typedef struct StackObject
27 QObject *obj;
28 const QListEntry *entry;
29 GHashTable *h;
30 } StackObject;
32 struct QmpInputVisitor
34 Visitor visitor;
35 StackObject stack[QIV_STACK_SIZE];
36 int nb_stack;
37 bool strict;
40 static QmpInputVisitor *to_qiv(Visitor *v)
42 return container_of(v, QmpInputVisitor, visitor);
45 static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
46 const char *name,
47 bool consume)
49 QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
51 if (qobj) {
52 if (name && qobject_type(qobj) == QTYPE_QDICT) {
53 if (qiv->stack[qiv->nb_stack - 1].h && consume) {
54 g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
56 return qdict_get(qobject_to_qdict(qobj), name);
57 } else if (qiv->stack[qiv->nb_stack - 1].entry) {
58 return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
62 return qobj;
65 static void qdict_add_key(const char *key, QObject *obj, void *opaque)
67 GHashTable *h = opaque;
68 g_hash_table_insert(h, (gpointer) key, NULL);
71 static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
73 GHashTable *h;
75 if (qiv->nb_stack >= QIV_STACK_SIZE) {
76 error_setg(errp, "An internal buffer overran");
77 return;
80 qiv->stack[qiv->nb_stack].obj = obj;
81 qiv->stack[qiv->nb_stack].entry = NULL;
82 qiv->stack[qiv->nb_stack].h = NULL;
84 if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
85 h = g_hash_table_new(g_str_hash, g_str_equal);
86 qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
87 qiv->stack[qiv->nb_stack].h = h;
90 qiv->nb_stack++;
94 static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
96 assert(qiv->nb_stack > 0);
98 if (qiv->strict) {
99 GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
100 if (top_ht) {
101 GHashTableIter iter;
102 const char *key;
104 g_hash_table_iter_init(&iter, top_ht);
105 if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
106 error_setg(errp, QERR_QMP_EXTRA_MEMBER, key);
108 g_hash_table_unref(top_ht);
112 qiv->nb_stack--;
115 static void qmp_input_start_struct(Visitor *v, const char *name, void **obj,
116 size_t size, Error **errp)
118 QmpInputVisitor *qiv = to_qiv(v);
119 QObject *qobj = qmp_input_get_object(qiv, name, true);
120 Error *err = NULL;
122 if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
123 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
124 "QDict");
125 return;
128 qmp_input_push(qiv, qobj, &err);
129 if (err) {
130 error_propagate(errp, err);
131 return;
134 if (obj) {
135 *obj = g_malloc0(size);
139 static void qmp_input_end_struct(Visitor *v, Error **errp)
141 QmpInputVisitor *qiv = to_qiv(v);
143 qmp_input_pop(qiv, errp);
146 static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
148 QmpInputVisitor *qiv = to_qiv(v);
149 QObject *qobj = qmp_input_get_object(qiv, name, true);
151 if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
152 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
153 "list");
154 return;
157 qmp_input_push(qiv, qobj, errp);
160 static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
161 size_t size)
163 QmpInputVisitor *qiv = to_qiv(v);
164 GenericList *entry;
165 StackObject *so = &qiv->stack[qiv->nb_stack - 1];
166 bool first;
168 if (so->entry == NULL) {
169 so->entry = qlist_first(qobject_to_qlist(so->obj));
170 first = true;
171 } else {
172 so->entry = qlist_next(so->entry);
173 first = false;
176 if (so->entry == NULL) {
177 return NULL;
180 entry = g_malloc0(size);
181 if (first) {
182 *list = entry;
183 } else {
184 (*list)->next = entry;
187 return entry;
190 static void qmp_input_end_list(Visitor *v)
192 QmpInputVisitor *qiv = to_qiv(v);
194 qmp_input_pop(qiv, &error_abort);
197 static void qmp_input_start_alternate(Visitor *v, const char *name,
198 GenericAlternate **obj, size_t size,
199 bool promote_int, Error **errp)
201 QmpInputVisitor *qiv = to_qiv(v);
202 QObject *qobj = qmp_input_get_object(qiv, name, false);
204 if (!qobj) {
205 *obj = NULL;
206 error_setg(errp, QERR_MISSING_PARAMETER, name ? name : "null");
207 return;
209 *obj = g_malloc0(size);
210 (*obj)->type = qobject_type(qobj);
211 if (promote_int && (*obj)->type == QTYPE_QINT) {
212 (*obj)->type = QTYPE_QFLOAT;
216 static void qmp_input_type_int64(Visitor *v, const char *name, int64_t *obj,
217 Error **errp)
219 QmpInputVisitor *qiv = to_qiv(v);
220 QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
222 if (!qint) {
223 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
224 "integer");
225 return;
228 *obj = qint_get_int(qint);
231 static void qmp_input_type_uint64(Visitor *v, const char *name, uint64_t *obj,
232 Error **errp)
234 /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
235 QmpInputVisitor *qiv = to_qiv(v);
236 QInt *qint = qobject_to_qint(qmp_input_get_object(qiv, name, true));
238 if (!qint) {
239 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
240 "integer");
241 return;
244 *obj = qint_get_int(qint);
247 static void qmp_input_type_bool(Visitor *v, const char *name, bool *obj,
248 Error **errp)
250 QmpInputVisitor *qiv = to_qiv(v);
251 QBool *qbool = qobject_to_qbool(qmp_input_get_object(qiv, name, true));
253 if (!qbool) {
254 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
255 "boolean");
256 return;
259 *obj = qbool_get_bool(qbool);
262 static void qmp_input_type_str(Visitor *v, const char *name, char **obj,
263 Error **errp)
265 QmpInputVisitor *qiv = to_qiv(v);
266 QString *qstr = qobject_to_qstring(qmp_input_get_object(qiv, name, true));
268 if (!qstr) {
269 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
270 "string");
271 return;
274 *obj = g_strdup(qstring_get_str(qstr));
277 static void qmp_input_type_number(Visitor *v, const char *name, double *obj,
278 Error **errp)
280 QmpInputVisitor *qiv = to_qiv(v);
281 QObject *qobj = qmp_input_get_object(qiv, name, true);
282 QInt *qint;
283 QFloat *qfloat;
285 qint = qobject_to_qint(qobj);
286 if (qint) {
287 *obj = qint_get_int(qobject_to_qint(qobj));
288 return;
291 qfloat = qobject_to_qfloat(qobj);
292 if (qfloat) {
293 *obj = qfloat_get_double(qobject_to_qfloat(qobj));
294 return;
297 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
298 "number");
301 static void qmp_input_type_any(Visitor *v, const char *name, QObject **obj,
302 Error **errp)
304 QmpInputVisitor *qiv = to_qiv(v);
305 QObject *qobj = qmp_input_get_object(qiv, name, true);
307 qobject_incref(qobj);
308 *obj = qobj;
311 static void qmp_input_optional(Visitor *v, const char *name, bool *present)
313 QmpInputVisitor *qiv = to_qiv(v);
314 QObject *qobj = qmp_input_get_object(qiv, name, true);
316 if (!qobj) {
317 *present = false;
318 return;
321 *present = true;
324 Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
326 return &v->visitor;
329 void qmp_input_visitor_cleanup(QmpInputVisitor *v)
331 qobject_decref(v->stack[0].obj);
332 g_free(v);
335 QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
337 QmpInputVisitor *v;
339 v = g_malloc0(sizeof(*v));
341 v->visitor.start_struct = qmp_input_start_struct;
342 v->visitor.end_struct = qmp_input_end_struct;
343 v->visitor.start_list = qmp_input_start_list;
344 v->visitor.next_list = qmp_input_next_list;
345 v->visitor.end_list = qmp_input_end_list;
346 v->visitor.start_alternate = qmp_input_start_alternate;
347 v->visitor.type_enum = input_type_enum;
348 v->visitor.type_int64 = qmp_input_type_int64;
349 v->visitor.type_uint64 = qmp_input_type_uint64;
350 v->visitor.type_bool = qmp_input_type_bool;
351 v->visitor.type_str = qmp_input_type_str;
352 v->visitor.type_number = qmp_input_type_number;
353 v->visitor.type_any = qmp_input_type_any;
354 v->visitor.optional = qmp_input_optional;
356 qmp_input_push(v, obj, NULL);
357 qobject_incref(obj);
359 return v;
362 QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj)
364 QmpInputVisitor *v;
366 v = qmp_input_visitor_new(obj);
367 v->strict = true;
369 return v;