root / qapi / qmp-output-visitor.c @ 25a70175
History | View | Annotate | Download (5.8 kB)
1 | e4e6aa14 | Michael Roth | /*
|
---|---|---|---|
2 | e4e6aa14 | Michael Roth | * Core Definitions for QAPI/QMP Command Registry
|
3 | e4e6aa14 | Michael Roth | *
|
4 | e4e6aa14 | Michael Roth | * Copyright IBM, Corp. 2011
|
5 | e4e6aa14 | Michael Roth | *
|
6 | e4e6aa14 | Michael Roth | * Authors:
|
7 | e4e6aa14 | Michael Roth | * Anthony Liguori <aliguori@us.ibm.com>
|
8 | e4e6aa14 | Michael Roth | *
|
9 | e4e6aa14 | Michael Roth | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
10 | e4e6aa14 | Michael Roth | * See the COPYING.LIB file in the top-level directory.
|
11 | e4e6aa14 | Michael Roth | *
|
12 | e4e6aa14 | Michael Roth | */
|
13 | e4e6aa14 | Michael Roth | |
14 | 7b1b5d19 | Paolo Bonzini | #include "qapi/qmp-output-visitor.h" |
15 | 7b1b5d19 | Paolo Bonzini | #include "qapi/visitor-impl.h" |
16 | 1de7afc9 | Paolo Bonzini | #include "qemu/queue.h" |
17 | e4e6aa14 | Michael Roth | #include "qemu-common.h" |
18 | 7b1b5d19 | Paolo Bonzini | #include "qapi/qmp/types.h" |
19 | 7b1b5d19 | Paolo Bonzini | #include "qapi/qmp/qerror.h" |
20 | e4e6aa14 | Michael Roth | |
21 | e4e6aa14 | Michael Roth | typedef struct QStackEntry |
22 | e4e6aa14 | Michael Roth | { |
23 | e4e6aa14 | Michael Roth | QObject *value; |
24 | e1bc2f7b | Michael Roth | bool is_list_head;
|
25 | e4e6aa14 | Michael Roth | QTAILQ_ENTRY(QStackEntry) node; |
26 | e4e6aa14 | Michael Roth | } QStackEntry; |
27 | e4e6aa14 | Michael Roth | |
28 | e4e6aa14 | Michael Roth | typedef QTAILQ_HEAD(QStack, QStackEntry) QStack;
|
29 | e4e6aa14 | Michael Roth | |
30 | e4e6aa14 | Michael Roth | struct QmpOutputVisitor
|
31 | e4e6aa14 | Michael Roth | { |
32 | e4e6aa14 | Michael Roth | Visitor visitor; |
33 | e4e6aa14 | Michael Roth | QStack stack; |
34 | e4e6aa14 | Michael Roth | }; |
35 | e4e6aa14 | Michael Roth | |
36 | e4e6aa14 | Michael Roth | #define qmp_output_add(qov, name, value) \
|
37 | e4e6aa14 | Michael Roth | qmp_output_add_obj(qov, name, QOBJECT(value)) |
38 | e4e6aa14 | Michael Roth | #define qmp_output_push(qov, value) qmp_output_push_obj(qov, QOBJECT(value))
|
39 | e4e6aa14 | Michael Roth | |
40 | e4e6aa14 | Michael Roth | static QmpOutputVisitor *to_qov(Visitor *v)
|
41 | e4e6aa14 | Michael Roth | { |
42 | e4e6aa14 | Michael Roth | return container_of(v, QmpOutputVisitor, visitor);
|
43 | e4e6aa14 | Michael Roth | } |
44 | e4e6aa14 | Michael Roth | |
45 | e4e6aa14 | Michael Roth | static void qmp_output_push_obj(QmpOutputVisitor *qov, QObject *value) |
46 | e4e6aa14 | Michael Roth | { |
47 | 7267c094 | Anthony Liguori | QStackEntry *e = g_malloc0(sizeof(*e));
|
48 | e4e6aa14 | Michael Roth | |
49 | e4e6aa14 | Michael Roth | e->value = value; |
50 | e1bc2f7b | Michael Roth | if (qobject_type(e->value) == QTYPE_QLIST) {
|
51 | e1bc2f7b | Michael Roth | e->is_list_head = true;
|
52 | e1bc2f7b | Michael Roth | } |
53 | e4e6aa14 | Michael Roth | QTAILQ_INSERT_HEAD(&qov->stack, e, node); |
54 | e4e6aa14 | Michael Roth | } |
55 | e4e6aa14 | Michael Roth | |
56 | e4e6aa14 | Michael Roth | static QObject *qmp_output_pop(QmpOutputVisitor *qov)
|
57 | e4e6aa14 | Michael Roth | { |
58 | e4e6aa14 | Michael Roth | QStackEntry *e = QTAILQ_FIRST(&qov->stack); |
59 | e4e6aa14 | Michael Roth | QObject *value; |
60 | e4e6aa14 | Michael Roth | QTAILQ_REMOVE(&qov->stack, e, node); |
61 | e4e6aa14 | Michael Roth | value = e->value; |
62 | 7267c094 | Anthony Liguori | g_free(e); |
63 | e4e6aa14 | Michael Roth | return value;
|
64 | e4e6aa14 | Michael Roth | } |
65 | e4e6aa14 | Michael Roth | |
66 | e4e6aa14 | Michael Roth | static QObject *qmp_output_first(QmpOutputVisitor *qov)
|
67 | e4e6aa14 | Michael Roth | { |
68 | e4e6aa14 | Michael Roth | QStackEntry *e = QTAILQ_LAST(&qov->stack, QStack); |
69 | e4e6aa14 | Michael Roth | return e->value;
|
70 | e4e6aa14 | Michael Roth | } |
71 | e4e6aa14 | Michael Roth | |
72 | e4e6aa14 | Michael Roth | static QObject *qmp_output_last(QmpOutputVisitor *qov)
|
73 | e4e6aa14 | Michael Roth | { |
74 | e4e6aa14 | Michael Roth | QStackEntry *e = QTAILQ_FIRST(&qov->stack); |
75 | e4e6aa14 | Michael Roth | return e->value;
|
76 | e4e6aa14 | Michael Roth | } |
77 | e4e6aa14 | Michael Roth | |
78 | e4e6aa14 | Michael Roth | static void qmp_output_add_obj(QmpOutputVisitor *qov, const char *name, |
79 | e4e6aa14 | Michael Roth | QObject *value) |
80 | e4e6aa14 | Michael Roth | { |
81 | e4e6aa14 | Michael Roth | QObject *cur; |
82 | e4e6aa14 | Michael Roth | |
83 | e4e6aa14 | Michael Roth | if (QTAILQ_EMPTY(&qov->stack)) {
|
84 | e4e6aa14 | Michael Roth | qmp_output_push_obj(qov, value); |
85 | e4e6aa14 | Michael Roth | return;
|
86 | e4e6aa14 | Michael Roth | } |
87 | e4e6aa14 | Michael Roth | |
88 | e4e6aa14 | Michael Roth | cur = qmp_output_last(qov); |
89 | e4e6aa14 | Michael Roth | |
90 | e4e6aa14 | Michael Roth | switch (qobject_type(cur)) {
|
91 | e4e6aa14 | Michael Roth | case QTYPE_QDICT:
|
92 | e4e6aa14 | Michael Roth | qdict_put_obj(qobject_to_qdict(cur), name, value); |
93 | e4e6aa14 | Michael Roth | break;
|
94 | e4e6aa14 | Michael Roth | case QTYPE_QLIST:
|
95 | e4e6aa14 | Michael Roth | qlist_append_obj(qobject_to_qlist(cur), value); |
96 | e4e6aa14 | Michael Roth | break;
|
97 | e4e6aa14 | Michael Roth | default:
|
98 | e4e6aa14 | Michael Roth | qobject_decref(qmp_output_pop(qov)); |
99 | e4e6aa14 | Michael Roth | qmp_output_push_obj(qov, value); |
100 | e4e6aa14 | Michael Roth | break;
|
101 | e4e6aa14 | Michael Roth | } |
102 | e4e6aa14 | Michael Roth | } |
103 | e4e6aa14 | Michael Roth | |
104 | e4e6aa14 | Michael Roth | static void qmp_output_start_struct(Visitor *v, void **obj, const char *kind, |
105 | e4e6aa14 | Michael Roth | const char *name, size_t unused, |
106 | e4e6aa14 | Michael Roth | Error **errp) |
107 | e4e6aa14 | Michael Roth | { |
108 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
109 | e4e6aa14 | Michael Roth | QDict *dict = qdict_new(); |
110 | e4e6aa14 | Michael Roth | |
111 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, dict); |
112 | e4e6aa14 | Michael Roth | qmp_output_push(qov, dict); |
113 | e4e6aa14 | Michael Roth | } |
114 | e4e6aa14 | Michael Roth | |
115 | e4e6aa14 | Michael Roth | static void qmp_output_end_struct(Visitor *v, Error **errp) |
116 | e4e6aa14 | Michael Roth | { |
117 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
118 | e4e6aa14 | Michael Roth | qmp_output_pop(qov); |
119 | e4e6aa14 | Michael Roth | } |
120 | e4e6aa14 | Michael Roth | |
121 | e4e6aa14 | Michael Roth | static void qmp_output_start_list(Visitor *v, const char *name, Error **errp) |
122 | e4e6aa14 | Michael Roth | { |
123 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
124 | e4e6aa14 | Michael Roth | QList *list = qlist_new(); |
125 | e4e6aa14 | Michael Roth | |
126 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, list); |
127 | e4e6aa14 | Michael Roth | qmp_output_push(qov, list); |
128 | e4e6aa14 | Michael Roth | } |
129 | e4e6aa14 | Michael Roth | |
130 | e1bc2f7b | Michael Roth | static GenericList *qmp_output_next_list(Visitor *v, GenericList **listp,
|
131 | e4e6aa14 | Michael Roth | Error **errp) |
132 | e4e6aa14 | Michael Roth | { |
133 | e1bc2f7b | Michael Roth | GenericList *list = *listp; |
134 | e1bc2f7b | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
135 | e1bc2f7b | Michael Roth | QStackEntry *e = QTAILQ_FIRST(&qov->stack); |
136 | e1bc2f7b | Michael Roth | |
137 | e1bc2f7b | Michael Roth | assert(e); |
138 | e1bc2f7b | Michael Roth | if (e->is_list_head) {
|
139 | e1bc2f7b | Michael Roth | e->is_list_head = false;
|
140 | e1bc2f7b | Michael Roth | return list;
|
141 | e1bc2f7b | Michael Roth | } |
142 | e1bc2f7b | Michael Roth | |
143 | e1bc2f7b | Michael Roth | return list ? list->next : NULL; |
144 | e4e6aa14 | Michael Roth | } |
145 | e4e6aa14 | Michael Roth | |
146 | e4e6aa14 | Michael Roth | static void qmp_output_end_list(Visitor *v, Error **errp) |
147 | e4e6aa14 | Michael Roth | { |
148 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
149 | e4e6aa14 | Michael Roth | qmp_output_pop(qov); |
150 | e4e6aa14 | Michael Roth | } |
151 | e4e6aa14 | Michael Roth | |
152 | e4e6aa14 | Michael Roth | static void qmp_output_type_int(Visitor *v, int64_t *obj, const char *name, |
153 | e4e6aa14 | Michael Roth | Error **errp) |
154 | e4e6aa14 | Michael Roth | { |
155 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
156 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, qint_from_int(*obj)); |
157 | e4e6aa14 | Michael Roth | } |
158 | e4e6aa14 | Michael Roth | |
159 | e4e6aa14 | Michael Roth | static void qmp_output_type_bool(Visitor *v, bool *obj, const char *name, |
160 | e4e6aa14 | Michael Roth | Error **errp) |
161 | e4e6aa14 | Michael Roth | { |
162 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
163 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, qbool_from_int(*obj)); |
164 | e4e6aa14 | Michael Roth | } |
165 | e4e6aa14 | Michael Roth | |
166 | e4e6aa14 | Michael Roth | static void qmp_output_type_str(Visitor *v, char **obj, const char *name, |
167 | e4e6aa14 | Michael Roth | Error **errp) |
168 | e4e6aa14 | Michael Roth | { |
169 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
170 | e4e6aa14 | Michael Roth | if (*obj) {
|
171 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, qstring_from_str(*obj)); |
172 | e4e6aa14 | Michael Roth | } else {
|
173 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, qstring_from_str(""));
|
174 | e4e6aa14 | Michael Roth | } |
175 | e4e6aa14 | Michael Roth | } |
176 | e4e6aa14 | Michael Roth | |
177 | e4e6aa14 | Michael Roth | static void qmp_output_type_number(Visitor *v, double *obj, const char *name, |
178 | e4e6aa14 | Michael Roth | Error **errp) |
179 | e4e6aa14 | Michael Roth | { |
180 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qov = to_qov(v); |
181 | e4e6aa14 | Michael Roth | qmp_output_add(qov, name, qfloat_from_double(*obj)); |
182 | e4e6aa14 | Michael Roth | } |
183 | e4e6aa14 | Michael Roth | |
184 | e4e6aa14 | Michael Roth | QObject *qmp_output_get_qobject(QmpOutputVisitor *qov) |
185 | e4e6aa14 | Michael Roth | { |
186 | e4e6aa14 | Michael Roth | QObject *obj = qmp_output_first(qov); |
187 | e4e6aa14 | Michael Roth | if (obj) {
|
188 | e4e6aa14 | Michael Roth | qobject_incref(obj); |
189 | e4e6aa14 | Michael Roth | } |
190 | e4e6aa14 | Michael Roth | return obj;
|
191 | e4e6aa14 | Michael Roth | } |
192 | e4e6aa14 | Michael Roth | |
193 | e4e6aa14 | Michael Roth | Visitor *qmp_output_get_visitor(QmpOutputVisitor *v) |
194 | e4e6aa14 | Michael Roth | { |
195 | e4e6aa14 | Michael Roth | return &v->visitor;
|
196 | e4e6aa14 | Michael Roth | } |
197 | e4e6aa14 | Michael Roth | |
198 | e4e6aa14 | Michael Roth | void qmp_output_visitor_cleanup(QmpOutputVisitor *v)
|
199 | e4e6aa14 | Michael Roth | { |
200 | e4e6aa14 | Michael Roth | QStackEntry *e, *tmp; |
201 | e4e6aa14 | Michael Roth | |
202 | f24582d6 | Laszlo Ersek | /* The bottom QStackEntry, if any, owns the root QObject. See the
|
203 | f24582d6 | Laszlo Ersek | * qmp_output_push_obj() invocations in qmp_output_add_obj(). */
|
204 | f24582d6 | Laszlo Ersek | QObject *root = QTAILQ_EMPTY(&v->stack) ? NULL : qmp_output_first(v);
|
205 | f24582d6 | Laszlo Ersek | |
206 | e4e6aa14 | Michael Roth | QTAILQ_FOREACH_SAFE(e, &v->stack, node, tmp) { |
207 | e4e6aa14 | Michael Roth | QTAILQ_REMOVE(&v->stack, e, node); |
208 | 7267c094 | Anthony Liguori | g_free(e); |
209 | e4e6aa14 | Michael Roth | } |
210 | e4e6aa14 | Michael Roth | |
211 | f24582d6 | Laszlo Ersek | qobject_decref(root); |
212 | 7267c094 | Anthony Liguori | g_free(v); |
213 | e4e6aa14 | Michael Roth | } |
214 | e4e6aa14 | Michael Roth | |
215 | e4e6aa14 | Michael Roth | QmpOutputVisitor *qmp_output_visitor_new(void)
|
216 | e4e6aa14 | Michael Roth | { |
217 | e4e6aa14 | Michael Roth | QmpOutputVisitor *v; |
218 | e4e6aa14 | Michael Roth | |
219 | 7267c094 | Anthony Liguori | v = g_malloc0(sizeof(*v));
|
220 | e4e6aa14 | Michael Roth | |
221 | e4e6aa14 | Michael Roth | v->visitor.start_struct = qmp_output_start_struct; |
222 | e4e6aa14 | Michael Roth | v->visitor.end_struct = qmp_output_end_struct; |
223 | e4e6aa14 | Michael Roth | v->visitor.start_list = qmp_output_start_list; |
224 | e4e6aa14 | Michael Roth | v->visitor.next_list = qmp_output_next_list; |
225 | e4e6aa14 | Michael Roth | v->visitor.end_list = qmp_output_end_list; |
226 | 0f71a1e0 | Paolo Bonzini | v->visitor.type_enum = output_type_enum; |
227 | e4e6aa14 | Michael Roth | v->visitor.type_int = qmp_output_type_int; |
228 | e4e6aa14 | Michael Roth | v->visitor.type_bool = qmp_output_type_bool; |
229 | e4e6aa14 | Michael Roth | v->visitor.type_str = qmp_output_type_str; |
230 | e4e6aa14 | Michael Roth | v->visitor.type_number = qmp_output_type_number; |
231 | e4e6aa14 | Michael Roth | |
232 | e4e6aa14 | Michael Roth | QTAILQ_INIT(&v->stack); |
233 | e4e6aa14 | Michael Roth | |
234 | e4e6aa14 | Michael Roth | return v;
|
235 | e4e6aa14 | Michael Roth | } |