xref: /qemu/qapi/qapi-visit-core.c (revision e58d695e6c3a5cfa0aa2fc91b87ade017ef28b05)
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 {
26*e58d695eSEric Blake     Error *err = NULL;
27*e58d695eSEric Blake 
28*e58d695eSEric Blake     v->start_struct(v, name, obj, size, &err);
29*e58d695eSEric Blake     if (obj && v->type == VISITOR_INPUT) {
30*e58d695eSEric Blake         assert(!err != !*obj);
31*e58d695eSEric Blake     }
32*e58d695eSEric Blake     error_propagate(errp, err);
332345c77cSMichael Roth }
342345c77cSMichael Roth 
352345c77cSMichael Roth void visit_end_struct(Visitor *v, Error **errp)
362345c77cSMichael Roth {
372345c77cSMichael Roth     v->end_struct(v, errp);
382345c77cSMichael Roth }
392345c77cSMichael Roth 
402345c77cSMichael Roth void visit_start_list(Visitor *v, const char *name, Error **errp)
412345c77cSMichael Roth {
422345c77cSMichael Roth     v->start_list(v, name, errp);
432345c77cSMichael Roth }
442345c77cSMichael Roth 
45e65d89bfSEric Blake GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
462345c77cSMichael Roth {
47e65d89bfSEric Blake     assert(list && size >= sizeof(GenericList));
48e65d89bfSEric Blake     return v->next_list(v, list, size);
492345c77cSMichael Roth }
502345c77cSMichael Roth 
5108f9541dSEric Blake void visit_end_list(Visitor *v)
522345c77cSMichael Roth {
5308f9541dSEric Blake     v->end_list(v);
542345c77cSMichael Roth }
552345c77cSMichael Roth 
56dbf11922SEric Blake void visit_start_alternate(Visitor *v, const char *name,
57dbf11922SEric Blake                            GenericAlternate **obj, size_t size,
58dbf11922SEric Blake                            bool promote_int, Error **errp)
59dbf11922SEric Blake {
60*e58d695eSEric Blake     Error *err = NULL;
61*e58d695eSEric Blake 
62dbf11922SEric Blake     assert(obj && size >= sizeof(GenericAlternate));
63dbf11922SEric Blake     if (v->start_alternate) {
64*e58d695eSEric Blake         v->start_alternate(v, name, obj, size, promote_int, &err);
65dbf11922SEric Blake     }
66*e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
67*e58d695eSEric Blake         assert(v->start_alternate && !err != !*obj);
68*e58d695eSEric Blake     }
69*e58d695eSEric Blake     error_propagate(errp, err);
70dbf11922SEric Blake }
71dbf11922SEric Blake 
72dbf11922SEric Blake void visit_end_alternate(Visitor *v)
73dbf11922SEric Blake {
74dbf11922SEric Blake     if (v->end_alternate) {
75dbf11922SEric Blake         v->end_alternate(v);
76dbf11922SEric Blake     }
77dbf11922SEric Blake }
78dbf11922SEric Blake 
7951e72bc1SEric Blake bool visit_optional(Visitor *v, const char *name, bool *present)
802345c77cSMichael Roth {
81297a3646SMarkus Armbruster     if (v->optional) {
820b2a0d6bSEric Blake         v->optional(v, name, present);
832345c77cSMichael Roth     }
8429637a6eSEric Blake     return *present;
852345c77cSMichael Roth }
862345c77cSMichael Roth 
8751e72bc1SEric Blake void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
882345c77cSMichael Roth {
890b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
902345c77cSMichael Roth }
912345c77cSMichael Roth 
9204e070d2SEric Blake static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
9304e070d2SEric Blake                              uint64_t max, const char *type, Error **errp)
9404e070d2SEric Blake {
9504e070d2SEric Blake     Error *err = NULL;
9604e070d2SEric Blake     uint64_t value = *obj;
9704e070d2SEric Blake 
980b2a0d6bSEric Blake     v->type_uint64(v, name, &value, &err);
9904e070d2SEric Blake     if (err) {
10004e070d2SEric Blake         error_propagate(errp, err);
10104e070d2SEric Blake     } else if (value > max) {
10204e070d2SEric Blake         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
10304e070d2SEric Blake                    name ? name : "null", type);
10404e070d2SEric Blake     } else {
10504e070d2SEric Blake         *obj = value;
10604e070d2SEric Blake     }
10704e070d2SEric Blake }
10804e070d2SEric Blake 
10951e72bc1SEric Blake void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
11051e72bc1SEric Blake                       Error **errp)
1114e27e819SMichael Roth {
11204e070d2SEric Blake     uint64_t value = *obj;
11304e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
1144e27e819SMichael Roth     *obj = value;
1154e27e819SMichael Roth }
1164e27e819SMichael Roth 
11751e72bc1SEric Blake void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
11804e070d2SEric Blake                        Error **errp)
1194e27e819SMichael Roth {
12004e070d2SEric Blake     uint64_t value = *obj;
12104e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
1224e27e819SMichael Roth     *obj = value;
1234e27e819SMichael Roth }
1244e27e819SMichael Roth 
12551e72bc1SEric Blake void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
12604e070d2SEric Blake                        Error **errp)
1274e27e819SMichael Roth {
12804e070d2SEric Blake     uint64_t value = *obj;
12904e070d2SEric Blake     visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
1304e27e819SMichael Roth     *obj = value;
1314e27e819SMichael Roth }
1324e27e819SMichael Roth 
13351e72bc1SEric Blake void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
13404e070d2SEric Blake                        Error **errp)
1354e27e819SMichael Roth {
1360b2a0d6bSEric Blake     v->type_uint64(v, name, obj, errp);
1374e27e819SMichael Roth }
1384e27e819SMichael Roth 
13904e070d2SEric Blake static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
14004e070d2SEric Blake                             int64_t min, int64_t max, const char *type,
14104e070d2SEric Blake                             Error **errp)
1424e27e819SMichael Roth {
14304e070d2SEric Blake     Error *err = NULL;
14404e070d2SEric Blake     int64_t value = *obj;
145297a3646SMarkus Armbruster 
1460b2a0d6bSEric Blake     v->type_int64(v, name, &value, &err);
14704e070d2SEric Blake     if (err) {
14804e070d2SEric Blake         error_propagate(errp, err);
14904e070d2SEric Blake     } else if (value < min || value > max) {
150c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
15104e070d2SEric Blake                    name ? name : "null", type);
15204e070d2SEric Blake     } else {
1534e27e819SMichael Roth         *obj = value;
1544e27e819SMichael Roth     }
1554e27e819SMichael Roth }
1564e27e819SMichael Roth 
15751e72bc1SEric Blake void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
15804e070d2SEric Blake {
15904e070d2SEric Blake     int64_t value = *obj;
16004e070d2SEric Blake     visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
16104e070d2SEric Blake     *obj = value;
16204e070d2SEric Blake }
16304e070d2SEric Blake 
16451e72bc1SEric Blake void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
16551e72bc1SEric Blake                       Error **errp)
1664e27e819SMichael Roth {
16704e070d2SEric Blake     int64_t value = *obj;
16804e070d2SEric Blake     visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
1694e27e819SMichael Roth     *obj = value;
1704e27e819SMichael Roth }
1714e27e819SMichael Roth 
17251e72bc1SEric Blake void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
17351e72bc1SEric Blake                       Error **errp)
1744e27e819SMichael Roth {
17504e070d2SEric Blake     int64_t value = *obj;
17604e070d2SEric Blake     visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
1774e27e819SMichael Roth     *obj = value;
1784e27e819SMichael Roth }
1794e27e819SMichael Roth 
18051e72bc1SEric Blake void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
18151e72bc1SEric Blake                       Error **errp)
1824e27e819SMichael Roth {
1830b2a0d6bSEric Blake     v->type_int64(v, name, obj, errp);
1844e27e819SMichael Roth }
1854e27e819SMichael Roth 
18651e72bc1SEric Blake void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
18751e72bc1SEric Blake                      Error **errp)
188092705d4SLaszlo Ersek {
189b8877962SVasilis Liaskovitis     if (v->type_size) {
1900b2a0d6bSEric Blake         v->type_size(v, name, obj, errp);
191b8877962SVasilis Liaskovitis     } else {
1920b2a0d6bSEric Blake         v->type_uint64(v, name, obj, errp);
193b8877962SVasilis Liaskovitis     }
194092705d4SLaszlo Ersek }
195092705d4SLaszlo Ersek 
19651e72bc1SEric Blake void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
1972345c77cSMichael Roth {
1980b2a0d6bSEric Blake     v->type_bool(v, name, obj, errp);
1992345c77cSMichael Roth }
2002345c77cSMichael Roth 
20151e72bc1SEric Blake void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
2022345c77cSMichael Roth {
203*e58d695eSEric Blake     Error *err = NULL;
204*e58d695eSEric Blake 
205*e58d695eSEric Blake     assert(obj);
206*e58d695eSEric Blake     v->type_str(v, name, obj, &err);
207*e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
208*e58d695eSEric Blake         assert(!err != !*obj);
209*e58d695eSEric Blake     }
210*e58d695eSEric Blake     error_propagate(errp, err);
2112345c77cSMichael Roth }
2122345c77cSMichael Roth 
21351e72bc1SEric Blake void visit_type_number(Visitor *v, const char *name, double *obj,
21451e72bc1SEric Blake                        Error **errp)
2152345c77cSMichael Roth {
2160b2a0d6bSEric Blake     v->type_number(v, name, obj, errp);
2172345c77cSMichael Roth }
2180f71a1e0SPaolo Bonzini 
21951e72bc1SEric Blake void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
22028770e05SMarkus Armbruster {
221*e58d695eSEric Blake     Error *err = NULL;
222*e58d695eSEric Blake 
223*e58d695eSEric Blake     assert(obj);
224*e58d695eSEric Blake     v->type_any(v, name, obj, &err);
225*e58d695eSEric Blake     if (v->type == VISITOR_INPUT) {
226*e58d695eSEric Blake         assert(!err != !*obj);
227*e58d695eSEric Blake     }
228*e58d695eSEric Blake     error_propagate(errp, err);
22928770e05SMarkus Armbruster }
23028770e05SMarkus Armbruster 
231983f52d4SEric Blake static void output_type_enum(Visitor *v, const char *name, int *obj,
232337283dfSEric Blake                              const char *const strings[], Error **errp)
2330f71a1e0SPaolo Bonzini {
2340f71a1e0SPaolo Bonzini     int i = 0;
2350f71a1e0SPaolo Bonzini     int value = *obj;
2360f71a1e0SPaolo Bonzini     char *enum_str;
2370f71a1e0SPaolo Bonzini 
2380f71a1e0SPaolo Bonzini     while (strings[i++] != NULL);
2390f71a1e0SPaolo Bonzini     if (value < 0 || value >= i - 1) {
240c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
2410f71a1e0SPaolo Bonzini         return;
2420f71a1e0SPaolo Bonzini     }
2430f71a1e0SPaolo Bonzini 
2440f71a1e0SPaolo Bonzini     enum_str = (char *)strings[value];
24551e72bc1SEric Blake     visit_type_str(v, name, &enum_str, errp);
2460f71a1e0SPaolo Bonzini }
2470f71a1e0SPaolo Bonzini 
248983f52d4SEric Blake static void input_type_enum(Visitor *v, const char *name, int *obj,
249337283dfSEric Blake                             const char *const strings[], Error **errp)
2500f71a1e0SPaolo Bonzini {
251297a3646SMarkus Armbruster     Error *local_err = NULL;
2520f71a1e0SPaolo Bonzini     int64_t value = 0;
2530f71a1e0SPaolo Bonzini     char *enum_str;
2540f71a1e0SPaolo Bonzini 
25551e72bc1SEric Blake     visit_type_str(v, name, &enum_str, &local_err);
256297a3646SMarkus Armbruster     if (local_err) {
257297a3646SMarkus Armbruster         error_propagate(errp, local_err);
2580f71a1e0SPaolo Bonzini         return;
2590f71a1e0SPaolo Bonzini     }
2600f71a1e0SPaolo Bonzini 
2610f71a1e0SPaolo Bonzini     while (strings[value] != NULL) {
2620f71a1e0SPaolo Bonzini         if (strcmp(strings[value], enum_str) == 0) {
2630f71a1e0SPaolo Bonzini             break;
2640f71a1e0SPaolo Bonzini         }
2650f71a1e0SPaolo Bonzini         value++;
2660f71a1e0SPaolo Bonzini     }
2670f71a1e0SPaolo Bonzini 
2680f71a1e0SPaolo Bonzini     if (strings[value] == NULL) {
269c6bd8c70SMarkus Armbruster         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
2700f71a1e0SPaolo Bonzini         g_free(enum_str);
2710f71a1e0SPaolo Bonzini         return;
2720f71a1e0SPaolo Bonzini     }
2730f71a1e0SPaolo Bonzini 
2740f71a1e0SPaolo Bonzini     g_free(enum_str);
2750f71a1e0SPaolo Bonzini     *obj = value;
2760f71a1e0SPaolo Bonzini }
277983f52d4SEric Blake 
278983f52d4SEric Blake void visit_type_enum(Visitor *v, const char *name, int *obj,
279983f52d4SEric Blake                      const char *const strings[], Error **errp)
280983f52d4SEric Blake {
281983f52d4SEric Blake     assert(strings);
282983f52d4SEric Blake     if (v->type == VISITOR_INPUT) {
283983f52d4SEric Blake         input_type_enum(v, name, obj, strings, errp);
284983f52d4SEric Blake     } else if (v->type == VISITOR_OUTPUT) {
285983f52d4SEric Blake         output_type_enum(v, name, obj, strings, errp);
286983f52d4SEric Blake     }
287983f52d4SEric Blake }
288