xref: /openbmc/qemu/qapi/qapi-visit-core.c (revision 7a1bfee6)
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 "qapi/qmp/qerror.h"
18 #include "qapi/visitor.h"
19 #include "qapi/visitor-impl.h"
20 #include "trace.h"
21 
22 void visit_complete(Visitor *v, void *opaque)
23 {
24     assert(v->type != VISITOR_OUTPUT || v->complete);
25     trace_visit_complete(v, opaque);
26     if (v->complete) {
27         v->complete(v, opaque);
28     }
29 }
30 
31 void visit_free(Visitor *v)
32 {
33     trace_visit_free(v);
34     if (v) {
35         v->free(v);
36     }
37 }
38 
39 void visit_start_struct(Visitor *v, const char *name, void **obj,
40                         size_t size, Error **errp)
41 {
42     Error *err = NULL;
43 
44     trace_visit_start_struct(v, name, obj, size);
45     if (obj) {
46         assert(size);
47         assert(!(v->type & VISITOR_OUTPUT) || *obj);
48     }
49     v->start_struct(v, name, obj, size, &err);
50     if (obj && (v->type & VISITOR_INPUT)) {
51         assert(!err != !*obj);
52     }
53     error_propagate(errp, err);
54 }
55 
56 void visit_check_struct(Visitor *v, Error **errp)
57 {
58     trace_visit_check_struct(v);
59     if (v->check_struct) {
60         v->check_struct(v, errp);
61     }
62 }
63 
64 void visit_end_struct(Visitor *v, void **obj)
65 {
66     trace_visit_end_struct(v, obj);
67     v->end_struct(v, obj);
68 }
69 
70 void visit_start_list(Visitor *v, const char *name, GenericList **list,
71                       size_t size, Error **errp)
72 {
73     Error *err = NULL;
74 
75     assert(!list || size >= sizeof(GenericList));
76     trace_visit_start_list(v, name, list, size);
77     v->start_list(v, name, list, size, &err);
78     if (list && (v->type & VISITOR_INPUT)) {
79         assert(!(err && *list));
80     }
81     error_propagate(errp, err);
82 }
83 
84 GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
85 {
86     assert(tail && size >= sizeof(GenericList));
87     trace_visit_next_list(v, tail, size);
88     return v->next_list(v, tail, size);
89 }
90 
91 void visit_check_list(Visitor *v, Error **errp)
92 {
93     trace_visit_check_list(v);
94     if (v->check_list) {
95         v->check_list(v, errp);
96     }
97 }
98 
99 void visit_end_list(Visitor *v, void **obj)
100 {
101     trace_visit_end_list(v, obj);
102     v->end_list(v, obj);
103 }
104 
105 void visit_start_alternate(Visitor *v, const char *name,
106                            GenericAlternate **obj, size_t size,
107                            Error **errp)
108 {
109     Error *err = NULL;
110 
111     assert(obj && size >= sizeof(GenericAlternate));
112     assert(!(v->type & VISITOR_OUTPUT) || *obj);
113     trace_visit_start_alternate(v, name, obj, size);
114     if (v->start_alternate) {
115         v->start_alternate(v, name, obj, size, &err);
116     }
117     if (v->type & VISITOR_INPUT) {
118         assert(v->start_alternate && !err != !*obj);
119     }
120     error_propagate(errp, err);
121 }
122 
123 void visit_end_alternate(Visitor *v, void **obj)
124 {
125     trace_visit_end_alternate(v, obj);
126     if (v->end_alternate) {
127         v->end_alternate(v, obj);
128     }
129 }
130 
131 bool visit_optional(Visitor *v, const char *name, bool *present)
132 {
133     trace_visit_optional(v, name, present);
134     if (v->optional) {
135         v->optional(v, name, present);
136     }
137     return *present;
138 }
139 
140 bool visit_is_input(Visitor *v)
141 {
142     return v->type == VISITOR_INPUT;
143 }
144 
145 bool visit_is_dealloc(Visitor *v)
146 {
147     return v->type == VISITOR_DEALLOC;
148 }
149 
150 void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
151 {
152     assert(obj);
153     trace_visit_type_int(v, name, obj);
154     v->type_int64(v, name, obj, errp);
155 }
156 
157 static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
158                              uint64_t max, const char *type, Error **errp)
159 {
160     Error *err = NULL;
161     uint64_t value = *obj;
162 
163     assert(v->type == VISITOR_INPUT || value <= max);
164 
165     v->type_uint64(v, name, &value, &err);
166     if (err) {
167         error_propagate(errp, err);
168     } else if (value > max) {
169         assert(v->type == VISITOR_INPUT);
170         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
171                    name ? name : "null", type);
172     } else {
173         *obj = value;
174     }
175 }
176 
177 void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
178                       Error **errp)
179 {
180     uint64_t value;
181 
182     trace_visit_type_uint8(v, name, obj);
183     value = *obj;
184     visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
185     *obj = value;
186 }
187 
188 void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
189                        Error **errp)
190 {
191     uint64_t value;
192 
193     trace_visit_type_uint16(v, name, obj);
194     value = *obj;
195     visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
196     *obj = value;
197 }
198 
199 void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
200                        Error **errp)
201 {
202     uint64_t value;
203 
204     trace_visit_type_uint32(v, name, obj);
205     value = *obj;
206     visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
207     *obj = value;
208 }
209 
210 void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
211                        Error **errp)
212 {
213     assert(obj);
214     trace_visit_type_uint64(v, name, obj);
215     v->type_uint64(v, name, obj, errp);
216 }
217 
218 static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
219                             int64_t min, int64_t max, const char *type,
220                             Error **errp)
221 {
222     Error *err = NULL;
223     int64_t value = *obj;
224 
225     assert(v->type == VISITOR_INPUT || (value >= min && value <= max));
226 
227     v->type_int64(v, name, &value, &err);
228     if (err) {
229         error_propagate(errp, err);
230     } else if (value < min || value > max) {
231         assert(v->type == VISITOR_INPUT);
232         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
233                    name ? name : "null", type);
234     } else {
235         *obj = value;
236     }
237 }
238 
239 void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
240 {
241     int64_t value;
242 
243     trace_visit_type_int8(v, name, obj);
244     value = *obj;
245     visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
246     *obj = value;
247 }
248 
249 void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
250                       Error **errp)
251 {
252     int64_t value;
253 
254     trace_visit_type_int16(v, name, obj);
255     value = *obj;
256     visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
257     *obj = value;
258 }
259 
260 void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
261                       Error **errp)
262 {
263     int64_t value;
264 
265     trace_visit_type_int32(v, name, obj);
266     value = *obj;
267     visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
268     *obj = value;
269 }
270 
271 void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
272                       Error **errp)
273 {
274     assert(obj);
275     trace_visit_type_int64(v, name, obj);
276     v->type_int64(v, name, obj, errp);
277 }
278 
279 void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
280                      Error **errp)
281 {
282     assert(obj);
283     trace_visit_type_size(v, name, obj);
284     if (v->type_size) {
285         v->type_size(v, name, obj, errp);
286     } else {
287         v->type_uint64(v, name, obj, errp);
288     }
289 }
290 
291 void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
292 {
293     assert(obj);
294     trace_visit_type_bool(v, name, obj);
295     v->type_bool(v, name, obj, errp);
296 }
297 
298 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
299 {
300     Error *err = NULL;
301 
302     assert(obj);
303     /* TODO: Fix callers to not pass NULL when they mean "", so that we
304      * can enable:
305     assert(!(v->type & VISITOR_OUTPUT) || *obj);
306      */
307     trace_visit_type_str(v, name, obj);
308     v->type_str(v, name, obj, &err);
309     if (v->type & VISITOR_INPUT) {
310         assert(!err != !*obj);
311     }
312     error_propagate(errp, err);
313 }
314 
315 void visit_type_number(Visitor *v, const char *name, double *obj,
316                        Error **errp)
317 {
318     assert(obj);
319     trace_visit_type_number(v, name, obj);
320     v->type_number(v, name, obj, errp);
321 }
322 
323 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
324 {
325     Error *err = NULL;
326 
327     assert(obj);
328     assert(v->type != VISITOR_OUTPUT || *obj);
329     trace_visit_type_any(v, name, obj);
330     v->type_any(v, name, obj, &err);
331     if (v->type == VISITOR_INPUT) {
332         assert(!err != !*obj);
333     }
334     error_propagate(errp, err);
335 }
336 
337 void visit_type_null(Visitor *v, const char *name, QNull **obj,
338                      Error **errp)
339 {
340     trace_visit_type_null(v, name, obj);
341     v->type_null(v, name, obj, errp);
342 }
343 
344 static void output_type_enum(Visitor *v, const char *name, int *obj,
345                              const QEnumLookup *lookup, Error **errp)
346 {
347     int value = *obj;
348     char *enum_str;
349 
350     enum_str = (char *)qapi_enum_lookup(lookup, value);
351     visit_type_str(v, name, &enum_str, errp);
352 }
353 
354 static void input_type_enum(Visitor *v, const char *name, int *obj,
355                             const QEnumLookup *lookup, Error **errp)
356 {
357     Error *local_err = NULL;
358     int64_t value;
359     char *enum_str;
360 
361     visit_type_str(v, name, &enum_str, &local_err);
362     if (local_err) {
363         error_propagate(errp, local_err);
364         return;
365     }
366 
367     value = qapi_enum_parse(lookup, enum_str, -1, NULL);
368     if (value < 0) {
369         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
370         g_free(enum_str);
371         return;
372     }
373 
374     g_free(enum_str);
375     *obj = value;
376 }
377 
378 void visit_type_enum(Visitor *v, const char *name, int *obj,
379                      const QEnumLookup *lookup, Error **errp)
380 {
381     assert(obj && lookup);
382     trace_visit_type_enum(v, name, obj);
383     switch (v->type) {
384     case VISITOR_INPUT:
385         input_type_enum(v, name, obj, lookup, errp);
386         break;
387     case VISITOR_OUTPUT:
388         output_type_enum(v, name, obj, lookup, errp);
389         break;
390     case VISITOR_CLONE:
391         /* nothing further to do, scalar value was already copied by
392          * g_memdup() during visit_start_*() */
393         break;
394     case VISITOR_DEALLOC:
395         /* nothing to deallocate for a scalar */
396         break;
397     }
398 }
399