root / qapi / qmp-input-visitor.c @ 0056c093
History | View | Annotate | Download (6.6 kB)
1 |
/*
|
---|---|
2 |
* Input Visitor
|
3 |
*
|
4 |
* Copyright IBM, Corp. 2011
|
5 |
*
|
6 |
* Authors:
|
7 |
* Anthony Liguori <aliguori@us.ibm.com>
|
8 |
*
|
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.
|
11 |
*
|
12 |
*/
|
13 |
|
14 |
#include "qmp-input-visitor.h" |
15 |
#include "qapi/qapi-visit-impl.h" |
16 |
#include "qemu-queue.h" |
17 |
#include "qemu-common.h" |
18 |
#include "qemu-objects.h" |
19 |
#include "qerror.h" |
20 |
|
21 |
#define QIV_STACK_SIZE 1024 |
22 |
|
23 |
typedef struct StackObject |
24 |
{ |
25 |
const QObject *obj;
|
26 |
const QListEntry *entry;
|
27 |
} StackObject; |
28 |
|
29 |
struct QmpInputVisitor
|
30 |
{ |
31 |
Visitor visitor; |
32 |
QObject *obj; |
33 |
StackObject stack[QIV_STACK_SIZE]; |
34 |
int nb_stack;
|
35 |
}; |
36 |
|
37 |
static QmpInputVisitor *to_qiv(Visitor *v)
|
38 |
{ |
39 |
return container_of(v, QmpInputVisitor, visitor);
|
40 |
} |
41 |
|
42 |
static const QObject *qmp_input_get_object(QmpInputVisitor *qiv, |
43 |
const char *name) |
44 |
{ |
45 |
const QObject *qobj;
|
46 |
|
47 |
if (qiv->nb_stack == 0) { |
48 |
qobj = qiv->obj; |
49 |
} else {
|
50 |
qobj = qiv->stack[qiv->nb_stack - 1].obj;
|
51 |
} |
52 |
|
53 |
if (qobj) {
|
54 |
if (name && qobject_type(qobj) == QTYPE_QDICT) {
|
55 |
return qdict_get(qobject_to_qdict(qobj), name);
|
56 |
} else if (qiv->nb_stack > 0 && qobject_type(qobj) == QTYPE_QLIST) { |
57 |
return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry); |
58 |
} |
59 |
} |
60 |
|
61 |
return qobj;
|
62 |
} |
63 |
|
64 |
static void qmp_input_push(QmpInputVisitor *qiv, const QObject *obj, Error **errp) |
65 |
{ |
66 |
qiv->stack[qiv->nb_stack].obj = obj; |
67 |
if (qobject_type(obj) == QTYPE_QLIST) {
|
68 |
qiv->stack[qiv->nb_stack].entry = qlist_first(qobject_to_qlist(obj)); |
69 |
} |
70 |
qiv->nb_stack++; |
71 |
|
72 |
if (qiv->nb_stack >= QIV_STACK_SIZE) {
|
73 |
error_set(errp, QERR_BUFFER_OVERRUN); |
74 |
return;
|
75 |
} |
76 |
} |
77 |
|
78 |
static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp) |
79 |
{ |
80 |
qiv->nb_stack--; |
81 |
if (qiv->nb_stack < 0) { |
82 |
error_set(errp, QERR_BUFFER_OVERRUN); |
83 |
return;
|
84 |
} |
85 |
} |
86 |
|
87 |
static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind, |
88 |
const char *name, size_t size, Error **errp) |
89 |
{ |
90 |
QmpInputVisitor *qiv = to_qiv(v); |
91 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
92 |
|
93 |
if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
|
94 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
95 |
"QDict");
|
96 |
return;
|
97 |
} |
98 |
|
99 |
qmp_input_push(qiv, qobj, errp); |
100 |
if (error_is_set(errp)) {
|
101 |
return;
|
102 |
} |
103 |
|
104 |
if (obj) {
|
105 |
*obj = g_malloc0(size); |
106 |
} |
107 |
} |
108 |
|
109 |
static void qmp_input_end_struct(Visitor *v, Error **errp) |
110 |
{ |
111 |
QmpInputVisitor *qiv = to_qiv(v); |
112 |
|
113 |
qmp_input_pop(qiv, errp); |
114 |
} |
115 |
|
116 |
static void qmp_input_start_list(Visitor *v, const char *name, Error **errp) |
117 |
{ |
118 |
QmpInputVisitor *qiv = to_qiv(v); |
119 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
120 |
|
121 |
if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
|
122 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
123 |
"list");
|
124 |
return;
|
125 |
} |
126 |
|
127 |
qmp_input_push(qiv, qobj, errp); |
128 |
} |
129 |
|
130 |
static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
|
131 |
Error **errp) |
132 |
{ |
133 |
QmpInputVisitor *qiv = to_qiv(v); |
134 |
GenericList *entry; |
135 |
StackObject *so = &qiv->stack[qiv->nb_stack - 1];
|
136 |
|
137 |
if (so->entry == NULL) { |
138 |
return NULL; |
139 |
} |
140 |
|
141 |
entry = g_malloc0(sizeof(*entry));
|
142 |
if (*list) {
|
143 |
so->entry = qlist_next(so->entry); |
144 |
if (so->entry == NULL) { |
145 |
g_free(entry); |
146 |
return NULL; |
147 |
} |
148 |
(*list)->next = entry; |
149 |
} |
150 |
|
151 |
return entry;
|
152 |
} |
153 |
|
154 |
static void qmp_input_end_list(Visitor *v, Error **errp) |
155 |
{ |
156 |
QmpInputVisitor *qiv = to_qiv(v); |
157 |
|
158 |
qmp_input_pop(qiv, errp); |
159 |
} |
160 |
|
161 |
static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name, |
162 |
Error **errp) |
163 |
{ |
164 |
QmpInputVisitor *qiv = to_qiv(v); |
165 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
166 |
|
167 |
if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
|
168 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
169 |
"integer");
|
170 |
return;
|
171 |
} |
172 |
|
173 |
*obj = qint_get_int(qobject_to_qint(qobj)); |
174 |
} |
175 |
|
176 |
static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name, |
177 |
Error **errp) |
178 |
{ |
179 |
QmpInputVisitor *qiv = to_qiv(v); |
180 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
181 |
|
182 |
if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
|
183 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
184 |
"boolean");
|
185 |
return;
|
186 |
} |
187 |
|
188 |
*obj = qbool_get_int(qobject_to_qbool(qobj)); |
189 |
} |
190 |
|
191 |
static void qmp_input_type_str(Visitor *v, char **obj, const char *name, |
192 |
Error **errp) |
193 |
{ |
194 |
QmpInputVisitor *qiv = to_qiv(v); |
195 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
196 |
|
197 |
if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
|
198 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
199 |
"string");
|
200 |
return;
|
201 |
} |
202 |
|
203 |
*obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj))); |
204 |
} |
205 |
|
206 |
static void qmp_input_type_number(Visitor *v, double *obj, const char *name, |
207 |
Error **errp) |
208 |
{ |
209 |
QmpInputVisitor *qiv = to_qiv(v); |
210 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
211 |
|
212 |
if (!qobj || qobject_type(qobj) != QTYPE_QFLOAT) {
|
213 |
error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
|
214 |
"double");
|
215 |
return;
|
216 |
} |
217 |
|
218 |
*obj = qfloat_get_double(qobject_to_qfloat(qobj)); |
219 |
} |
220 |
|
221 |
static void qmp_input_start_optional(Visitor *v, bool *present, |
222 |
const char *name, Error **errp) |
223 |
{ |
224 |
QmpInputVisitor *qiv = to_qiv(v); |
225 |
const QObject *qobj = qmp_input_get_object(qiv, name);
|
226 |
|
227 |
if (!qobj) {
|
228 |
*present = false;
|
229 |
return;
|
230 |
} |
231 |
|
232 |
*present = true;
|
233 |
} |
234 |
|
235 |
Visitor *qmp_input_get_visitor(QmpInputVisitor *v) |
236 |
{ |
237 |
return &v->visitor;
|
238 |
} |
239 |
|
240 |
void qmp_input_visitor_cleanup(QmpInputVisitor *v)
|
241 |
{ |
242 |
qobject_decref(v->obj); |
243 |
g_free(v); |
244 |
} |
245 |
|
246 |
QmpInputVisitor *qmp_input_visitor_new(QObject *obj) |
247 |
{ |
248 |
QmpInputVisitor *v; |
249 |
|
250 |
v = g_malloc0(sizeof(*v));
|
251 |
|
252 |
v->visitor.start_struct = qmp_input_start_struct; |
253 |
v->visitor.end_struct = qmp_input_end_struct; |
254 |
v->visitor.start_list = qmp_input_start_list; |
255 |
v->visitor.next_list = qmp_input_next_list; |
256 |
v->visitor.end_list = qmp_input_end_list; |
257 |
v->visitor.type_enum = input_type_enum; |
258 |
v->visitor.type_int = qmp_input_type_int; |
259 |
v->visitor.type_bool = qmp_input_type_bool; |
260 |
v->visitor.type_str = qmp_input_type_str; |
261 |
v->visitor.type_number = qmp_input_type_number; |
262 |
v->visitor.start_optional = qmp_input_start_optional; |
263 |
|
264 |
v->obj = obj; |
265 |
qobject_incref(v->obj); |
266 |
|
267 |
return v;
|
268 |
} |