xref: /qemu/qapi/qapi-visit-core.c (revision 15c2f669e3fb2bc97f7b42d1871f595c0ac24af8)
12345c77cSMichael Roth /*
22345c77cSMichael Roth  * Core Definitions for QAPI Visitor Classes
32345c77cSMichael Roth  *
47c91aabdSEric Blake  * Copyright (C) 2012-2016 Red Hat, Inc.
52345c77cSMichael Roth  * Copyright IBM, Corp. 2011
62345c77cSMichael Roth  *
72345c77cSMichael Roth  * Authors:
82345c77cSMichael Roth  *  Anthony Liguori   <aliguori@us.ibm.com>
92345c77cSMichael Roth  *
102345c77cSMichael Roth  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
112345c77cSMichael Roth  * See the COPYING.LIB file in the top-level directory.
122345c77cSMichael Roth  *
132345c77cSMichael Roth  */
142345c77cSMichael Roth 
15cbf21151SPeter Maydell #include "qemu/osdep.h"
16da34e65cSMarkus Armbruster #include "qapi/error.h"
1779ee7df8SPaolo Bonzini #include "qemu-common.h"
1869dd62dfSKevin Wolf #include "qapi/qmp/qobject.h"
197b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h"
207b1b5d19SPaolo Bonzini #include "qapi/visitor.h"
217b1b5d19SPaolo Bonzini #include "qapi/visitor-impl.h"
222345c77cSMichael Roth 
2351e72bc1SEric Blake void visit_start_struct(Visitor *v, const char *name, void **obj,
24337283dfSEric Blake                         size_t size, Error **errp)
252345c77cSMichael Roth {
26e58d695eSEric Blake     Error *err = NULL;
27e58d695eSEric Blake 
28adfb264cSEric Blake     if (obj) {
29adfb264cSEric Blake         assert(size);
30adfb264cSEric Blake         assert(v->type != VISITOR_OUTPUT || *obj);
31adfb264cSEric Blake     }
32e58d695eSEric Blake     v->start_struct(v, name, obj, size, &err);
33e58d695eSEric Blake     if (obj && v->type == VISITOR_INPUT) {
34e58d695eSEric Blake         assert(!err != !*obj);
35e58d695eSEric Blake     }
36e58d695eSEric Blake     error_propagate(errp, err);
372345c77cSMichael Roth }
382345c77cSMichael Roth 
39*15c2f669SEric Blake void visit_check_struct(Visitor *v, Error **errp)
402345c77cSMichael Roth {
41*15c2f669SEric Blake     if (v->check_struct) {
42*15c2f669SEric Blake         v->check_struct(v, errp);
43*15c2f669SEric Blake     }
44*15c2f669SEric Blake }
45*15c2f669SEric Blake 
46*15c2f669SEric Blake void visit_end_struct(Visitor *v)
47*15c2f669SEric Blake {
48*15c2f669SEric Blake     v->end_struct(v);
492345c77cSMichael Roth }
502345c77cSMichael Roth 
512345c77cSMichael Roth void visit_start_list(Visitor *v, const char *name, Error **errp)
522345c77cSMichael Roth {
532345c77cSMichael Roth     v->start_list(v, name, errp);
542345c77cSMichael Roth }
552345c77cSMichael Roth 
56e65d89bfSEric Blake GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
572345c77cSMichael Roth {
58e65d89bfSEric Blake     assert(list && size >= sizeof(GenericList));
59e65d89bfSEric Blake     return v->next_list(v, list, size);
602345c77cSMichael Roth }
612345c77cSMichael Roth 
6208f9541dSEric Blake void visit_end_list(Visitor *v)
632345c77cSMichael Roth {
6408f9541dSEric Blake     v->end_list(v);
652345c77cSMichael Roth }
662345c77cSMichael Roth 
67dbf11922SEric Blake void visit_start_alternate(Visitor *v, const char *name,
68dbf11922SEric Blake                            GenericAlternate **obj, size_t size,
69dbf11922SEric Blake                            bool promote_int, Error **errp)
70dbf11922SEric Blake {
71e58d695eSEric Blake     Error *err = NULL;
72e58d695eSEric Blake 
73dbf11922SEric Blake     assert(obj && size >= sizeof(GenericAlternate));
74adfb264cSEric Blake     assert(v->type != VISITOR_OUTPUT || *obj);
75dbf11922SEric Blake     if (v->start_alternate) {
76e58d695eSEric Blake         v->start_alternate(v, name, obj, size, promote_int, &err);
77dbf11922SEric Blake     }
78e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
79e58d695eSEric Blake         assert(v->start_alternate && !err != !*obj);
80e58d695eSEric Blake     }
81e58d695eSEric Blake     error_propagate(errp, err);
82dbf11922SEric Blake }
83dbf11922SEric Blake 
84dbf11922SEric Blake void visit_end_alternate(Visitor *v)
85dbf11922SEric Blake {
86dbf11922SEric Blake     if (v->end_alternate) {
87dbf11922SEric Blake         v->end_alternate(v);
88dbf11922SEric Blake     }
89dbf11922SEric Blake }
90dbf11922SEric Blake 
9151e72bc1SEric Blake bool visit_optional(Visitor *v, const char *name, bool *present)
922345c77cSMichael Roth {
93297a3646SMarkus Armbruster     if (v->optional) {
940b2a0d6bSEric Blake         v->optional(v, name, present);
952345c77cSMichael Roth     }
9629637a6eSEric Blake     return *present;
972345c77cSMichael Roth }
982345c77cSMichael Roth 
9951e72bc1SEric Blake void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
1002345c77cSMichael Roth {
101adfb264cSEric Blake     assert(obj);
1020b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
1032345c77cSMichael Roth }
1042345c77cSMichael Roth 
10504e070d2SEric Blake static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
10604e070d2SEric Blake                              uint64_t max, const char *type, Error **errp)
10704e070d2SEric Blake {
10804e070d2SEric Blake     Error *err = NULL;
10904e070d2SEric Blake     uint64_t value = *obj;
11004e070d2SEric Blake 
1110b2a0d6bSEric Blake     v->type_uint64(v, name, &value, &err);
11204e070d2SEric Blake     if (err) {
11304e070d2SEric Blake         error_propagate(errp, err);
11404e070d2SEric Blake     } else if (value > max) {
11504e070d2SEric Blake         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
11604e070d2SEric Blake                    name ? name : "null", type);
11704e070d2SEric Blake     } else {
11804e070d2SEric Blake         *obj = value;
11904e070d2SEric Blake     }
12004e070d2SEric Blake }
12104e070d2SEric Blake 
12251e72bc1SEric Blake void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
12351e72bc1SEric Blake                       Error **errp)
1244e27e819SMichael Roth {
12504e070d2SEric Blake     uint64_t value = *obj;
12604e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
1274e27e819SMichael Roth     *obj = value;
1284e27e819SMichael Roth }
1294e27e819SMichael Roth 
13051e72bc1SEric Blake void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
13104e070d2SEric Blake                        Error **errp)
1324e27e819SMichael Roth {
13304e070d2SEric Blake     uint64_t value = *obj;
13404e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
1354e27e819SMichael Roth     *obj = value;
1364e27e819SMichael Roth }
1374e27e819SMichael Roth 
13851e72bc1SEric Blake void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
13904e070d2SEric Blake                        Error **errp)
1404e27e819SMichael Roth {
14104e070d2SEric Blake     uint64_t value = *obj;
14204e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
1434e27e819SMichael Roth     *obj = value;
1444e27e819SMichael Roth }
1454e27e819SMichael Roth 
14651e72bc1SEric Blake void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
14704e070d2SEric Blake                        Error **errp)
1484e27e819SMichael Roth {
149adfb264cSEric Blake     assert(obj);
1500b2a0d6bSEric Blake     v->type_uint64(v, name, obj, errp);
1514e27e819SMichael Roth }
1524e27e819SMichael Roth 
15304e070d2SEric Blake static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
15404e070d2SEric Blake                             int64_t min, int64_t max, const char *type,
15504e070d2SEric Blake                             Error **errp)
1564e27e819SMichael Roth {
15704e070d2SEric Blake     Error *err = NULL;
15804e070d2SEric Blake     int64_t value = *obj;
159297a3646SMarkus Armbruster 
1600b2a0d6bSEric Blake     v->type_int64(v, name, &value, &err);
16104e070d2SEric Blake     if (err) {
16204e070d2SEric Blake         error_propagate(errp, err);
16304e070d2SEric Blake     } else if (value < min || value > max) {
164c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
16504e070d2SEric Blake                    name ? name : "null", type);
16604e070d2SEric Blake     } else {
1674e27e819SMichael Roth         *obj = value;
1684e27e819SMichael Roth     }
1694e27e819SMichael Roth }
1704e27e819SMichael Roth 
17151e72bc1SEric Blake void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
17204e070d2SEric Blake {
17304e070d2SEric Blake     int64_t value = *obj;
17404e070d2SEric Blake     visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
17504e070d2SEric Blake     *obj = value;
17604e070d2SEric Blake }
17704e070d2SEric Blake 
17851e72bc1SEric Blake void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
17951e72bc1SEric Blake                       Error **errp)
1804e27e819SMichael Roth {
18104e070d2SEric Blake     int64_t value = *obj;
18204e070d2SEric Blake     visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
1834e27e819SMichael Roth     *obj = value;
1844e27e819SMichael Roth }
1854e27e819SMichael Roth 
18651e72bc1SEric Blake void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
18751e72bc1SEric Blake                       Error **errp)
1884e27e819SMichael Roth {
18904e070d2SEric Blake     int64_t value = *obj;
19004e070d2SEric Blake     visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
1914e27e819SMichael Roth     *obj = value;
1924e27e819SMichael Roth }
1934e27e819SMichael Roth 
19451e72bc1SEric Blake void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
19551e72bc1SEric Blake                       Error **errp)
1964e27e819SMichael Roth {
197adfb264cSEric Blake     assert(obj);
1980b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
1994e27e819SMichael Roth }
2004e27e819SMichael Roth 
20151e72bc1SEric Blake void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
20251e72bc1SEric Blake                      Error **errp)
203092705d4SLaszlo Ersek {
204adfb264cSEric Blake     assert(obj);
205b8877962SVasilis Liaskovitis     if (v->type_size) {
2060b2a0d6bSEric Blake         v->type_size(v, name, obj, errp);
207b8877962SVasilis Liaskovitis     } else {
2080b2a0d6bSEric Blake         v->type_uint64(v, name, obj, errp);
209b8877962SVasilis Liaskovitis     }
210092705d4SLaszlo Ersek }
211092705d4SLaszlo Ersek 
21251e72bc1SEric Blake void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
2132345c77cSMichael Roth {
214adfb264cSEric Blake     assert(obj);
2150b2a0d6bSEric Blake     v->type_bool(v, name, obj, errp);
2162345c77cSMichael Roth }
2172345c77cSMichael Roth 
21851e72bc1SEric Blake void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
2192345c77cSMichael Roth {
220e58d695eSEric Blake     Error *err = NULL;
221e58d695eSEric Blake 
222e58d695eSEric Blake     assert(obj);
223adfb264cSEric Blake     /* TODO: Fix callers to not pass NULL when they mean "", so that we
224adfb264cSEric Blake      * can enable:
225adfb264cSEric Blake     assert(v->type != VISITOR_OUTPUT || *obj);
226adfb264cSEric Blake      */
227e58d695eSEric Blake     v->type_str(v, name, obj, &err);
228e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
229e58d695eSEric Blake         assert(!err != !*obj);
230e58d695eSEric Blake     }
231e58d695eSEric Blake     error_propagate(errp, err);
2322345c77cSMichael Roth }
2332345c77cSMichael Roth 
23451e72bc1SEric Blake void visit_type_number(Visitor *v, const char *name, double *obj,
23551e72bc1SEric Blake                        Error **errp)
2362345c77cSMichael Roth {
237adfb264cSEric Blake     assert(obj);
2380b2a0d6bSEric Blake     v->type_number(v, name, obj, errp);
2392345c77cSMichael Roth }
2400f71a1e0SPaolo Bonzini 
24151e72bc1SEric Blake void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
24228770e05SMarkus Armbruster {
243e58d695eSEric Blake     Error *err = NULL;
244e58d695eSEric Blake 
245e58d695eSEric Blake     assert(obj);
246adfb264cSEric Blake     assert(v->type != VISITOR_OUTPUT || *obj);
247e58d695eSEric Blake     v->type_any(v, name, obj, &err);
248e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
249e58d695eSEric Blake         assert(!err != !*obj);
250e58d695eSEric Blake     }
251e58d695eSEric Blake     error_propagate(errp, err);
25228770e05SMarkus Armbruster }
25328770e05SMarkus Armbruster 
2543bc97fd5SEric Blake void visit_type_null(Visitor *v, const char *name, Error **errp)
2553bc97fd5SEric Blake {
2563bc97fd5SEric Blake     v->type_null(v, name, errp);
2573bc97fd5SEric Blake }
2583bc97fd5SEric Blake 
259983f52d4SEric Blake static void output_type_enum(Visitor *v, const char *name, int *obj,
260337283dfSEric Blake                              const char *const strings[], Error **errp)
2610f71a1e0SPaolo Bonzini {
2620f71a1e0SPaolo Bonzini     int i = 0;
2630f71a1e0SPaolo Bonzini     int value = *obj;
2640f71a1e0SPaolo Bonzini     char *enum_str;
2650f71a1e0SPaolo Bonzini 
2660f71a1e0SPaolo Bonzini     while (strings[i++] != NULL);
2670f71a1e0SPaolo Bonzini     if (value < 0 || value >= i - 1) {
268c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
2690f71a1e0SPaolo Bonzini         return;
2700f71a1e0SPaolo Bonzini     }
2710f71a1e0SPaolo Bonzini 
2720f71a1e0SPaolo Bonzini     enum_str = (char *)strings[value];
27351e72bc1SEric Blake     visit_type_str(v, name, &enum_str, errp);
2740f71a1e0SPaolo Bonzini }
2750f71a1e0SPaolo Bonzini 
276983f52d4SEric Blake static void input_type_enum(Visitor *v, const char *name, int *obj,
277337283dfSEric Blake                             const char *const strings[], Error **errp)
2780f71a1e0SPaolo Bonzini {
279297a3646SMarkus Armbruster     Error *local_err = NULL;
2800f71a1e0SPaolo Bonzini     int64_t value = 0;
2810f71a1e0SPaolo Bonzini     char *enum_str;
2820f71a1e0SPaolo Bonzini 
28351e72bc1SEric Blake     visit_type_str(v, name, &enum_str, &local_err);
284297a3646SMarkus Armbruster     if (local_err) {
285297a3646SMarkus Armbruster         error_propagate(errp, local_err);
2860f71a1e0SPaolo Bonzini         return;
2870f71a1e0SPaolo Bonzini     }
2880f71a1e0SPaolo Bonzini 
2890f71a1e0SPaolo Bonzini     while (strings[value] != NULL) {
2900f71a1e0SPaolo Bonzini         if (strcmp(strings[value], enum_str) == 0) {
2910f71a1e0SPaolo Bonzini             break;
2920f71a1e0SPaolo Bonzini         }
2930f71a1e0SPaolo Bonzini         value++;
2940f71a1e0SPaolo Bonzini     }
2950f71a1e0SPaolo Bonzini 
2960f71a1e0SPaolo Bonzini     if (strings[value] == NULL) {
297c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
2980f71a1e0SPaolo Bonzini         g_free(enum_str);
2990f71a1e0SPaolo Bonzini         return;
3000f71a1e0SPaolo Bonzini     }
3010f71a1e0SPaolo Bonzini 
3020f71a1e0SPaolo Bonzini     g_free(enum_str);
3030f71a1e0SPaolo Bonzini     *obj = value;
3040f71a1e0SPaolo Bonzini }
305983f52d4SEric Blake 
306983f52d4SEric Blake void visit_type_enum(Visitor *v, const char *name, int *obj,
307983f52d4SEric Blake                      const char *const strings[], Error **errp)
308983f52d4SEric Blake {
309adfb264cSEric Blake     assert(obj && strings);
310983f52d4SEric Blake     if (v->type == VISITOR_INPUT) {
311983f52d4SEric Blake         input_type_enum(v, name, obj, strings, errp);
312983f52d4SEric Blake     } else if (v->type == VISITOR_OUTPUT) {
313983f52d4SEric Blake         output_type_enum(v, name, obj, strings, errp);
314983f52d4SEric Blake     }
315983f52d4SEric Blake }
316