]> git.proxmox.com Git - mirror_qemu.git/blob - qapi/qapi-visit-core.c
qapi: Split visit_end_struct() into pieces
[mirror_qemu.git] / qapi / qapi-visit-core.c
1 /*
2 * Core Definitions for QAPI Visitor Classes
3 *
4 * Copyright (C) 2012-2016 Red Hat, Inc.
5 * Copyright IBM, Corp. 2011
6 *
7 * Authors:
8 * Anthony Liguori <aliguori@us.ibm.com>
9 *
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.
12 *
13 */
14
15 #include "qemu/osdep.h"
16 #include "qapi/error.h"
17 #include "qemu-common.h"
18 #include "qapi/qmp/qobject.h"
19 #include "qapi/qmp/qerror.h"
20 #include "qapi/visitor.h"
21 #include "qapi/visitor-impl.h"
22
23 void visit_start_struct(Visitor *v, const char *name, void **obj,
24 size_t size, Error **errp)
25 {
26 Error *err = NULL;
27
28 if (obj) {
29 assert(size);
30 assert(v->type != VISITOR_OUTPUT || *obj);
31 }
32 v->start_struct(v, name, obj, size, &err);
33 if (obj && v->type == VISITOR_INPUT) {
34 assert(!err != !*obj);
35 }
36 error_propagate(errp, err);
37 }
38
39 void visit_check_struct(Visitor *v, Error **errp)
40 {
41 if (v->check_struct) {
42 v->check_struct(v, errp);
43 }
44 }
45
46 void visit_end_struct(Visitor *v)
47 {
48 v->end_struct(v);
49 }
50
51 void visit_start_list(Visitor *v, const char *name, Error **errp)
52 {
53 v->start_list(v, name, errp);
54 }
55
56 GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
57 {
58 assert(list && size >= sizeof(GenericList));
59 return v->next_list(v, list, size);
60 }
61
62 void visit_end_list(Visitor *v)
63 {
64 v->end_list(v);
65 }
66
67 void visit_start_alternate(Visitor *v, const char *name,
68 GenericAlternate **obj, size_t size,
69 bool promote_int, Error **errp)
70 {
71 Error *err = NULL;
72
73 assert(obj && size >= sizeof(GenericAlternate));
74 assert(v->type != VISITOR_OUTPUT || *obj);
75 if (v->start_alternate) {
76 v->start_alternate(v, name, obj, size, promote_int, &err);
77 }
78 if (v->type == VISITOR_INPUT) {
79 assert(v->start_alternate && !err != !*obj);
80 }
81 error_propagate(errp, err);
82 }
83
84 void visit_end_alternate(Visitor *v)
85 {
86 if (v->end_alternate) {
87 v->end_alternate(v);
88 }
89 }
90
91 bool visit_optional(Visitor *v, const char *name, bool *present)
92 {
93 if (v->optional) {
94 v->optional(v, name, present);
95 }
96 return *present;
97 }
98
99 void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
100 {
101 assert(obj);
102 v->type_int64(v, name, obj, errp);
103 }
104
105 static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
106 uint64_t max, const char *type, Error **errp)
107 {
108 Error *err = NULL;
109 uint64_t value = *obj;
110
111 v->type_uint64(v, name, &value, &err);
112 if (err) {
113 error_propagate(errp, err);
114 } else if (value > max) {
115 error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
116 name ? name : "null", type);
117 } else {
118 *obj = value;
119 }
120 }
121
122 void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
123 Error **errp)
124 {
125 uint64_t value = *obj;
126 visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
127 *obj = value;
128 }
129
130 void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
131 Error **errp)
132 {
133 uint64_t value = *obj;
134 visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
135 *obj = value;
136 }
137
138 void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
139 Error **errp)
140 {
141 uint64_t value = *obj;
142 visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
143 *obj = value;
144 }
145
146 void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
147 Error **errp)
148 {
149 assert(obj);
150 v->type_uint64(v, name, obj, errp);
151 }
152
153 static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
154 int64_t min, int64_t max, const char *type,
155 Error **errp)
156 {
157 Error *err = NULL;
158 int64_t value = *obj;
159
160 v->type_int64(v, name, &value, &err);
161 if (err) {
162 error_propagate(errp, err);
163 } else if (value < min || value > max) {
164 error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
165 name ? name : "null", type);
166 } else {
167 *obj = value;
168 }
169 }
170
171 void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
172 {
173 int64_t value = *obj;
174 visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
175 *obj = value;
176 }
177
178 void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
179 Error **errp)
180 {
181 int64_t value = *obj;
182 visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
183 *obj = value;
184 }
185
186 void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
187 Error **errp)
188 {
189 int64_t value = *obj;
190 visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
191 *obj = value;
192 }
193
194 void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
195 Error **errp)
196 {
197 assert(obj);
198 v->type_int64(v, name, obj, errp);
199 }
200
201 void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
202 Error **errp)
203 {
204 assert(obj);
205 if (v->type_size) {
206 v->type_size(v, name, obj, errp);
207 } else {
208 v->type_uint64(v, name, obj, errp);
209 }
210 }
211
212 void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
213 {
214 assert(obj);
215 v->type_bool(v, name, obj, errp);
216 }
217
218 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
219 {
220 Error *err = NULL;
221
222 assert(obj);
223 /* TODO: Fix callers to not pass NULL when they mean "", so that we
224 * can enable:
225 assert(v->type != VISITOR_OUTPUT || *obj);
226 */
227 v->type_str(v, name, obj, &err);
228 if (v->type == VISITOR_INPUT) {
229 assert(!err != !*obj);
230 }
231 error_propagate(errp, err);
232 }
233
234 void visit_type_number(Visitor *v, const char *name, double *obj,
235 Error **errp)
236 {
237 assert(obj);
238 v->type_number(v, name, obj, errp);
239 }
240
241 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
242 {
243 Error *err = NULL;
244
245 assert(obj);
246 assert(v->type != VISITOR_OUTPUT || *obj);
247 v->type_any(v, name, obj, &err);
248 if (v->type == VISITOR_INPUT) {
249 assert(!err != !*obj);
250 }
251 error_propagate(errp, err);
252 }
253
254 void visit_type_null(Visitor *v, const char *name, Error **errp)
255 {
256 v->type_null(v, name, errp);
257 }
258
259 static void output_type_enum(Visitor *v, const char *name, int *obj,
260 const char *const strings[], Error **errp)
261 {
262 int i = 0;
263 int value = *obj;
264 char *enum_str;
265
266 while (strings[i++] != NULL);
267 if (value < 0 || value >= i - 1) {
268 error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
269 return;
270 }
271
272 enum_str = (char *)strings[value];
273 visit_type_str(v, name, &enum_str, errp);
274 }
275
276 static void input_type_enum(Visitor *v, const char *name, int *obj,
277 const char *const strings[], Error **errp)
278 {
279 Error *local_err = NULL;
280 int64_t value = 0;
281 char *enum_str;
282
283 visit_type_str(v, name, &enum_str, &local_err);
284 if (local_err) {
285 error_propagate(errp, local_err);
286 return;
287 }
288
289 while (strings[value] != NULL) {
290 if (strcmp(strings[value], enum_str) == 0) {
291 break;
292 }
293 value++;
294 }
295
296 if (strings[value] == NULL) {
297 error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
298 g_free(enum_str);
299 return;
300 }
301
302 g_free(enum_str);
303 *obj = value;
304 }
305
306 void visit_type_enum(Visitor *v, const char *name, int *obj,
307 const char *const strings[], Error **errp)
308 {
309 assert(obj && strings);
310 if (v->type == VISITOR_INPUT) {
311 input_type_enum(v, name, obj, strings, errp);
312 } else if (v->type == VISITOR_OUTPUT) {
313 output_type_enum(v, name, obj, strings, errp);
314 }
315 }