xref: /openbmc/qemu/qapi/qapi-visit-core.c (revision fc471c18)
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     v->start_struct(v, name, obj, size, &err);
29     if (obj && v->type == VISITOR_INPUT) {
30         assert(!err != !*obj);
31     }
32     error_propagate(errp, err);
33 }
34 
35 void visit_end_struct(Visitor *v, Error **errp)
36 {
37     v->end_struct(v, errp);
38 }
39 
40 void visit_start_list(Visitor *v, const char *name, Error **errp)
41 {
42     v->start_list(v, name, errp);
43 }
44 
45 GenericList *visit_next_list(Visitor *v, GenericList **list, size_t size)
46 {
47     assert(list && size >= sizeof(GenericList));
48     return v->next_list(v, list, size);
49 }
50 
51 void visit_end_list(Visitor *v)
52 {
53     v->end_list(v);
54 }
55 
56 void visit_start_alternate(Visitor *v, const char *name,
57                            GenericAlternate **obj, size_t size,
58                            bool promote_int, Error **errp)
59 {
60     Error *err = NULL;
61 
62     assert(obj && size >= sizeof(GenericAlternate));
63     if (v->start_alternate) {
64         v->start_alternate(v, name, obj, size, promote_int, &err);
65     }
66     if (v->type == VISITOR_INPUT) {
67         assert(v->start_alternate && !err != !*obj);
68     }
69     error_propagate(errp, err);
70 }
71 
72 void visit_end_alternate(Visitor *v)
73 {
74     if (v->end_alternate) {
75         v->end_alternate(v);
76     }
77 }
78 
79 bool visit_optional(Visitor *v, const char *name, bool *present)
80 {
81     if (v->optional) {
82         v->optional(v, name, present);
83     }
84     return *present;
85 }
86 
87 void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
88 {
89     v->type_int64(v, name, obj, errp);
90 }
91 
92 static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
93                              uint64_t max, const char *type, Error **errp)
94 {
95     Error *err = NULL;
96     uint64_t value = *obj;
97 
98     v->type_uint64(v, name, &value, &err);
99     if (err) {
100         error_propagate(errp, err);
101     } else if (value > max) {
102         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
103                    name ? name : "null", type);
104     } else {
105         *obj = value;
106     }
107 }
108 
109 void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
110                       Error **errp)
111 {
112     uint64_t value = *obj;
113     visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
114     *obj = value;
115 }
116 
117 void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
118                        Error **errp)
119 {
120     uint64_t value = *obj;
121     visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
122     *obj = value;
123 }
124 
125 void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
126                        Error **errp)
127 {
128     uint64_t value = *obj;
129     visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
130     *obj = value;
131 }
132 
133 void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
134                        Error **errp)
135 {
136     v->type_uint64(v, name, obj, errp);
137 }
138 
139 static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
140                             int64_t min, int64_t max, const char *type,
141                             Error **errp)
142 {
143     Error *err = NULL;
144     int64_t value = *obj;
145 
146     v->type_int64(v, name, &value, &err);
147     if (err) {
148         error_propagate(errp, err);
149     } else if (value < min || value > max) {
150         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
151                    name ? name : "null", type);
152     } else {
153         *obj = value;
154     }
155 }
156 
157 void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
158 {
159     int64_t value = *obj;
160     visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
161     *obj = value;
162 }
163 
164 void visit_type_int16(Visitor *v, const char *name, int16_t *obj,
165                       Error **errp)
166 {
167     int64_t value = *obj;
168     visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp);
169     *obj = value;
170 }
171 
172 void visit_type_int32(Visitor *v, const char *name, int32_t *obj,
173                       Error **errp)
174 {
175     int64_t value = *obj;
176     visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp);
177     *obj = value;
178 }
179 
180 void visit_type_int64(Visitor *v, const char *name, int64_t *obj,
181                       Error **errp)
182 {
183     v->type_int64(v, name, obj, errp);
184 }
185 
186 void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
187                      Error **errp)
188 {
189     if (v->type_size) {
190         v->type_size(v, name, obj, errp);
191     } else {
192         v->type_uint64(v, name, obj, errp);
193     }
194 }
195 
196 void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
197 {
198     v->type_bool(v, name, obj, errp);
199 }
200 
201 void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
202 {
203     Error *err = NULL;
204 
205     assert(obj);
206     v->type_str(v, name, obj, &err);
207     if (v->type == VISITOR_INPUT) {
208         assert(!err != !*obj);
209     }
210     error_propagate(errp, err);
211 }
212 
213 void visit_type_number(Visitor *v, const char *name, double *obj,
214                        Error **errp)
215 {
216     v->type_number(v, name, obj, errp);
217 }
218 
219 void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
220 {
221     Error *err = NULL;
222 
223     assert(obj);
224     v->type_any(v, name, obj, &err);
225     if (v->type == VISITOR_INPUT) {
226         assert(!err != !*obj);
227     }
228     error_propagate(errp, err);
229 }
230 
231 static void output_type_enum(Visitor *v, const char *name, int *obj,
232                              const char *const strings[], Error **errp)
233 {
234     int i = 0;
235     int value = *obj;
236     char *enum_str;
237 
238     while (strings[i++] != NULL);
239     if (value < 0 || value >= i - 1) {
240         error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
241         return;
242     }
243 
244     enum_str = (char *)strings[value];
245     visit_type_str(v, name, &enum_str, errp);
246 }
247 
248 static void input_type_enum(Visitor *v, const char *name, int *obj,
249                             const char *const strings[], Error **errp)
250 {
251     Error *local_err = NULL;
252     int64_t value = 0;
253     char *enum_str;
254 
255     visit_type_str(v, name, &enum_str, &local_err);
256     if (local_err) {
257         error_propagate(errp, local_err);
258         return;
259     }
260 
261     while (strings[value] != NULL) {
262         if (strcmp(strings[value], enum_str) == 0) {
263             break;
264         }
265         value++;
266     }
267 
268     if (strings[value] == NULL) {
269         error_setg(errp, QERR_INVALID_PARAMETER, enum_str);
270         g_free(enum_str);
271         return;
272     }
273 
274     g_free(enum_str);
275     *obj = value;
276 }
277 
278 void visit_type_enum(Visitor *v, const char *name, int *obj,
279                      const char *const strings[], Error **errp)
280 {
281     assert(strings);
282     if (v->type == VISITOR_INPUT) {
283         input_type_enum(v, name, obj, strings, errp);
284     } else if (v->type == VISITOR_OUTPUT) {
285         output_type_enum(v, name, obj, strings, errp);
286     }
287 }
288