2 * Core Definitions for QAPI/QMP Command Registry
4 * Copyright IBM, Corp. 2011
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
14 #include "qapi/qmp-output-visitor.h"
15 #include "qapi/visitor-impl.h"
16 #include "qemu/queue.h"
17 #include "qemu-common.h"
18 #include "qapi/qmp/types.h"
20 typedef struct QStackEntry
24 QTAILQ_ENTRY(QStackEntry
) node
;
27 typedef QTAILQ_HEAD(QStack
, QStackEntry
) QStack
;
29 struct QmpOutputVisitor
35 #define qmp_output_add(qov, name, value) \
36 qmp_output_add_obj(qov, name, QOBJECT(value))
37 #define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
39 static QmpOutputVisitor
*to_qov(Visitor
*v
)
41 return container_of(v
, QmpOutputVisitor
, visitor
);
44 static void qmp_output_push_obj(QmpOutputVisitor
*qov
, QObject
*value
)
46 QStackEntry
*e
= g_malloc0(sizeof(*e
));
49 if (qobject_type(e
->value
) == QTYPE_QLIST
) {
50 e
->is_list_head
= true;
52 QTAILQ_INSERT_HEAD(&qov
->stack
, e
, node
);
55 static QObject
*qmp_output_pop(QmpOutputVisitor
*qov
)
57 QStackEntry
*e
= QTAILQ_FIRST(&qov
->stack
);
59 QTAILQ_REMOVE(&qov
->stack
, e
, node
);
65 static QObject
*qmp_output_first(QmpOutputVisitor
*qov
)
67 QStackEntry
*e
= QTAILQ_LAST(&qov
->stack
, QStack
);
70 * FIXME Wrong, because qmp_output_get_qobject() will increment
71 * the refcnt *again*. We need to think through how visitors
81 static QObject
*qmp_output_last(QmpOutputVisitor
*qov
)
83 QStackEntry
*e
= QTAILQ_FIRST(&qov
->stack
);
87 static void qmp_output_add_obj(QmpOutputVisitor
*qov
, const char *name
,
92 if (QTAILQ_EMPTY(&qov
->stack
)) {
93 qmp_output_push_obj(qov
, value
);
97 cur
= qmp_output_last(qov
);
99 switch (qobject_type(cur
)) {
101 qdict_put_obj(qobject_to_qdict(cur
), name
, value
);
104 qlist_append_obj(qobject_to_qlist(cur
), value
);
107 qobject_decref(qmp_output_pop(qov
));
108 qmp_output_push_obj(qov
, value
);
113 static void qmp_output_start_struct(Visitor
*v
, void **obj
, const char *kind
,
114 const char *name
, size_t unused
,
117 QmpOutputVisitor
*qov
= to_qov(v
);
118 QDict
*dict
= qdict_new();
120 qmp_output_add(qov
, name
, dict
);
121 qmp_output_push(qov
, dict
);
124 static void qmp_output_end_struct(Visitor
*v
, Error
**errp
)
126 QmpOutputVisitor
*qov
= to_qov(v
);
130 static void qmp_output_start_list(Visitor
*v
, const char *name
, Error
**errp
)
132 QmpOutputVisitor
*qov
= to_qov(v
);
133 QList
*list
= qlist_new();
135 qmp_output_add(qov
, name
, list
);
136 qmp_output_push(qov
, list
);
139 static GenericList
*qmp_output_next_list(Visitor
*v
, GenericList
**listp
,
142 GenericList
*list
= *listp
;
143 QmpOutputVisitor
*qov
= to_qov(v
);
144 QStackEntry
*e
= QTAILQ_FIRST(&qov
->stack
);
147 if (e
->is_list_head
) {
148 e
->is_list_head
= false;
152 return list
? list
->next
: NULL
;
155 static void qmp_output_end_list(Visitor
*v
, Error
**errp
)
157 QmpOutputVisitor
*qov
= to_qov(v
);
161 static void qmp_output_type_int(Visitor
*v
, int64_t *obj
, const char *name
,
164 QmpOutputVisitor
*qov
= to_qov(v
);
165 qmp_output_add(qov
, name
, qint_from_int(*obj
));
168 static void qmp_output_type_bool(Visitor
*v
, bool *obj
, const char *name
,
171 QmpOutputVisitor
*qov
= to_qov(v
);
172 qmp_output_add(qov
, name
, qbool_from_bool(*obj
));
175 static void qmp_output_type_str(Visitor
*v
, char **obj
, const char *name
,
178 QmpOutputVisitor
*qov
= to_qov(v
);
180 qmp_output_add(qov
, name
, qstring_from_str(*obj
));
182 qmp_output_add(qov
, name
, qstring_from_str(""));
186 static void qmp_output_type_number(Visitor
*v
, double *obj
, const char *name
,
189 QmpOutputVisitor
*qov
= to_qov(v
);
190 qmp_output_add(qov
, name
, qfloat_from_double(*obj
));
193 static void qmp_output_type_any(Visitor
*v
, QObject
**obj
, const char *name
,
196 QmpOutputVisitor
*qov
= to_qov(v
);
197 qobject_incref(*obj
);
198 qmp_output_add_obj(qov
, name
, *obj
);
201 QObject
*qmp_output_get_qobject(QmpOutputVisitor
*qov
)
203 QObject
*obj
= qmp_output_first(qov
);
210 Visitor
*qmp_output_get_visitor(QmpOutputVisitor
*v
)
215 void qmp_output_visitor_cleanup(QmpOutputVisitor
*v
)
217 QStackEntry
*e
, *tmp
;
219 /* The bottom QStackEntry, if any, owns the root QObject. See the
220 * qmp_output_push_obj() invocations in qmp_output_add_obj(). */
221 QObject
*root
= QTAILQ_EMPTY(&v
->stack
) ? NULL
: qmp_output_first(v
);
223 QTAILQ_FOREACH_SAFE(e
, &v
->stack
, node
, tmp
) {
224 QTAILQ_REMOVE(&v
->stack
, e
, node
);
228 qobject_decref(root
);
232 QmpOutputVisitor
*qmp_output_visitor_new(void)
236 v
= g_malloc0(sizeof(*v
));
238 v
->visitor
.start_struct
= qmp_output_start_struct
;
239 v
->visitor
.end_struct
= qmp_output_end_struct
;
240 v
->visitor
.start_list
= qmp_output_start_list
;
241 v
->visitor
.next_list
= qmp_output_next_list
;
242 v
->visitor
.end_list
= qmp_output_end_list
;
243 v
->visitor
.type_enum
= output_type_enum
;
244 v
->visitor
.type_int
= qmp_output_type_int
;
245 v
->visitor
.type_bool
= qmp_output_type_bool
;
246 v
->visitor
.type_str
= qmp_output_type_str
;
247 v
->visitor
.type_number
= qmp_output_type_number
;
248 v
->visitor
.type_any
= qmp_output_type_any
;
250 QTAILQ_INIT(&v
->stack
);