2 * Core Definitions for QAPI/QMP Command Registry
4 * Copyright (C) 2012-2016 Red Hat, Inc.
5 * Copyright IBM, Corp. 2011
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/qobject-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 void *qapi
; /* sanity check that caller uses same pointer */
25 QSLIST_ENTRY(QStackEntry
) node
;
28 struct QObjectOutputVisitor
{
30 QSLIST_HEAD(, QStackEntry
) stack
; /* Stack of unfinished containers */
31 QObject
*root
; /* Root of the output visit */
32 QObject
**result
; /* User's storage location for result */
35 #define qobject_output_add(qov, name, value) \
36 qobject_output_add_obj(qov, name, QOBJECT(value))
37 #define qobject_output_push(qov, value, qapi) \
38 qobject_output_push_obj(qov, QOBJECT(value), qapi)
40 static QObjectOutputVisitor
*to_qov(Visitor
*v
)
42 return container_of(v
, QObjectOutputVisitor
, visitor
);
45 /* Push @value onto the stack of current QObjects being built */
46 static void qobject_output_push_obj(QObjectOutputVisitor
*qov
, QObject
*value
,
49 QStackEntry
*e
= g_malloc0(sizeof(*e
));
55 QSLIST_INSERT_HEAD(&qov
->stack
, e
, node
);
58 /* Pop a value off the stack of QObjects being built, and return it. */
59 static QObject
*qobject_output_pop(QObjectOutputVisitor
*qov
, void *qapi
)
61 QStackEntry
*e
= QSLIST_FIRST(&qov
->stack
);
65 assert(e
->qapi
== qapi
);
66 QSLIST_REMOVE_HEAD(&qov
->stack
, node
);
73 /* Add @value to the current QObject being built.
74 * If the stack is visiting a dictionary or list, @value is now owned
75 * by that container. Otherwise, @value is now the root. */
76 static void qobject_output_add_obj(QObjectOutputVisitor
*qov
, const char *name
,
79 QStackEntry
*e
= QSLIST_FIRST(&qov
->stack
);
80 QObject
*cur
= e
? e
->value
: NULL
;
83 /* Don't allow reuse of visitor on more than one root */
87 switch (qobject_type(cur
)) {
90 qdict_put_obj(qobject_to_qdict(cur
), name
, value
);
94 qlist_append_obj(qobject_to_qlist(cur
), value
);
97 g_assert_not_reached();
102 static void qobject_output_start_struct(Visitor
*v
, const char *name
,
103 void **obj
, size_t unused
, Error
**errp
)
105 QObjectOutputVisitor
*qov
= to_qov(v
);
106 QDict
*dict
= qdict_new();
108 qobject_output_add(qov
, name
, dict
);
109 qobject_output_push(qov
, dict
, obj
);
112 static void qobject_output_end_struct(Visitor
*v
, void **obj
)
114 QObjectOutputVisitor
*qov
= to_qov(v
);
115 QObject
*value
= qobject_output_pop(qov
, obj
);
116 assert(qobject_type(value
) == QTYPE_QDICT
);
119 static void qobject_output_start_list(Visitor
*v
, const char *name
,
120 GenericList
**listp
, size_t size
,
123 QObjectOutputVisitor
*qov
= to_qov(v
);
124 QList
*list
= qlist_new();
126 qobject_output_add(qov
, name
, list
);
127 qobject_output_push(qov
, list
, listp
);
130 static GenericList
*qobject_output_next_list(Visitor
*v
, GenericList
*tail
,
136 static void qobject_output_end_list(Visitor
*v
, void **obj
)
138 QObjectOutputVisitor
*qov
= to_qov(v
);
139 QObject
*value
= qobject_output_pop(qov
, obj
);
140 assert(qobject_type(value
) == QTYPE_QLIST
);
143 static void qobject_output_type_int64(Visitor
*v
, const char *name
,
144 int64_t *obj
, Error
**errp
)
146 QObjectOutputVisitor
*qov
= to_qov(v
);
147 qobject_output_add(qov
, name
, qnum_from_int(*obj
));
150 static void qobject_output_type_uint64(Visitor
*v
, const char *name
,
151 uint64_t *obj
, Error
**errp
)
153 QObjectOutputVisitor
*qov
= to_qov(v
);
154 qobject_output_add(qov
, name
, qnum_from_uint(*obj
));
157 static void qobject_output_type_bool(Visitor
*v
, const char *name
, bool *obj
,
160 QObjectOutputVisitor
*qov
= to_qov(v
);
161 qobject_output_add(qov
, name
, qbool_from_bool(*obj
));
164 static void qobject_output_type_str(Visitor
*v
, const char *name
, char **obj
,
167 QObjectOutputVisitor
*qov
= to_qov(v
);
169 qobject_output_add(qov
, name
, qstring_from_str(*obj
));
171 qobject_output_add(qov
, name
, qstring_from_str(""));
175 static void qobject_output_type_number(Visitor
*v
, const char *name
,
176 double *obj
, Error
**errp
)
178 QObjectOutputVisitor
*qov
= to_qov(v
);
179 qobject_output_add(qov
, name
, qnum_from_double(*obj
));
182 static void qobject_output_type_any(Visitor
*v
, const char *name
,
183 QObject
**obj
, Error
**errp
)
185 QObjectOutputVisitor
*qov
= to_qov(v
);
186 qobject_incref(*obj
);
187 qobject_output_add_obj(qov
, name
, *obj
);
190 static void qobject_output_type_null(Visitor
*v
, const char *name
, Error
**errp
)
192 QObjectOutputVisitor
*qov
= to_qov(v
);
193 qobject_output_add_obj(qov
, name
, qnull());
196 /* Finish building, and return the root object.
197 * The root object is never null. The caller becomes the object's
198 * owner, and should use qobject_decref() when done with it. */
199 static void qobject_output_complete(Visitor
*v
, void *opaque
)
201 QObjectOutputVisitor
*qov
= to_qov(v
);
203 /* A visit must have occurred, with each start paired with end. */
204 assert(qov
->root
&& QSLIST_EMPTY(&qov
->stack
));
205 assert(opaque
== qov
->result
);
207 qobject_incref(qov
->root
);
208 *qov
->result
= qov
->root
;
212 static void qobject_output_free(Visitor
*v
)
214 QObjectOutputVisitor
*qov
= to_qov(v
);
217 while (!QSLIST_EMPTY(&qov
->stack
)) {
218 e
= QSLIST_FIRST(&qov
->stack
);
219 QSLIST_REMOVE_HEAD(&qov
->stack
, node
);
223 qobject_decref(qov
->root
);
227 Visitor
*qobject_output_visitor_new(QObject
**result
)
229 QObjectOutputVisitor
*v
;
231 v
= g_malloc0(sizeof(*v
));
233 v
->visitor
.type
= VISITOR_OUTPUT
;
234 v
->visitor
.start_struct
= qobject_output_start_struct
;
235 v
->visitor
.end_struct
= qobject_output_end_struct
;
236 v
->visitor
.start_list
= qobject_output_start_list
;
237 v
->visitor
.next_list
= qobject_output_next_list
;
238 v
->visitor
.end_list
= qobject_output_end_list
;
239 v
->visitor
.type_int64
= qobject_output_type_int64
;
240 v
->visitor
.type_uint64
= qobject_output_type_uint64
;
241 v
->visitor
.type_bool
= qobject_output_type_bool
;
242 v
->visitor
.type_str
= qobject_output_type_str
;
243 v
->visitor
.type_number
= qobject_output_type_number
;
244 v
->visitor
.type_any
= qobject_output_type_any
;
245 v
->visitor
.type_null
= qobject_output_type_null
;
246 v
->visitor
.complete
= qobject_output_complete
;
247 v
->visitor
.free
= qobject_output_free
;