]> Git Repo - qemu.git/blame - qapi/qapi-visit-core.c
qapi: Generalize struct member policy checking
[qemu.git] / qapi / qapi-visit-core.c
CommitLineData
2345c77c
MR
1/*
2 * Core Definitions for QAPI Visitor Classes
3 *
7c91aabd 4 * Copyright (C) 2012-2016 Red Hat, Inc.
2345c77c
MR
5 * Copyright IBM, Corp. 2011
6 *
7 * Authors:
8 * Anthony Liguori <[email protected]>
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
cbf21151 15#include "qemu/osdep.h"
da34e65c 16#include "qapi/error.h"
7b1b5d19
PB
17#include "qapi/qmp/qerror.h"
18#include "qapi/visitor.h"
19#include "qapi/visitor-impl.h"
ebfd93b6 20#include "trace.h"
2345c77c 21
ed29bb28
MA
22/* Zero-initialization must result in default policy */
23QEMU_BUILD_BUG_ON(COMPAT_POLICY_INPUT_ACCEPT || COMPAT_POLICY_OUTPUT_ACCEPT);
24
25
3b098d56
EB
26void visit_complete(Visitor *v, void *opaque)
27{
28 assert(v->type != VISITOR_OUTPUT || v->complete);
ebfd93b6 29 trace_visit_complete(v, opaque);
3b098d56
EB
30 if (v->complete) {
31 v->complete(v, opaque);
32 }
33}
34
2c0ef9f4
EB
35void visit_free(Visitor *v)
36{
ebfd93b6 37 trace_visit_free(v);
2c0ef9f4
EB
38 if (v) {
39 v->free(v);
40 }
41}
42
012d4c96 43bool visit_start_struct(Visitor *v, const char *name, void **obj,
337283df 44 size_t size, Error **errp)
2345c77c 45{
7b3cb803 46 bool ok;
e58d695e 47
ebfd93b6 48 trace_visit_start_struct(v, name, obj, size);
adfb264c
EB
49 if (obj) {
50 assert(size);
a15fcc3c 51 assert(!(v->type & VISITOR_OUTPUT) || *obj);
adfb264c 52 }
7b3cb803 53 ok = v->start_struct(v, name, obj, size, errp);
a15fcc3c 54 if (obj && (v->type & VISITOR_INPUT)) {
7b3cb803 55 assert(ok != !*obj);
e58d695e 56 }
7b3cb803 57 return ok;
2345c77c
MR
58}
59
012d4c96 60bool visit_check_struct(Visitor *v, Error **errp)
2345c77c 61{
ebfd93b6 62 trace_visit_check_struct(v);
012d4c96 63 return v->check_struct ? v->check_struct(v, errp) : true;
15c2f669
EB
64}
65
1158bb2a 66void visit_end_struct(Visitor *v, void **obj)
15c2f669 67{
ebfd93b6 68 trace_visit_end_struct(v, obj);
1158bb2a 69 v->end_struct(v, obj);
2345c77c
MR
70}
71
012d4c96 72bool visit_start_list(Visitor *v, const char *name, GenericList **list,
d9f62dde 73 size_t size, Error **errp)
2345c77c 74{
7b3cb803 75 bool ok;
d9f62dde
EB
76
77 assert(!list || size >= sizeof(GenericList));
ebfd93b6 78 trace_visit_start_list(v, name, list, size);
7b3cb803 79 ok = v->start_list(v, name, list, size, errp);
a15fcc3c 80 if (list && (v->type & VISITOR_INPUT)) {
7b3cb803 81 assert(ok || !*list);
d9f62dde 82 }
7b3cb803 83 return ok;
2345c77c
MR
84}
85
d9f62dde 86GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size)
2345c77c 87{
d9f62dde 88 assert(tail && size >= sizeof(GenericList));
ebfd93b6 89 trace_visit_next_list(v, tail, size);
d9f62dde 90 return v->next_list(v, tail, size);
2345c77c
MR
91}
92
012d4c96 93bool visit_check_list(Visitor *v, Error **errp)
a4a1c70d
MA
94{
95 trace_visit_check_list(v);
012d4c96 96 return v->check_list ? v->check_list(v, errp) : true;
a4a1c70d
MA
97}
98
1158bb2a 99void visit_end_list(Visitor *v, void **obj)
2345c77c 100{
ebfd93b6 101 trace_visit_end_list(v, obj);
1158bb2a 102 v->end_list(v, obj);
2345c77c
MR
103}
104
012d4c96 105bool visit_start_alternate(Visitor *v, const char *name,
dbf11922 106 GenericAlternate **obj, size_t size,
60390d2d 107 Error **errp)
2345c77c 108{
7b3cb803 109 bool ok;
e58d695e 110
dbf11922 111 assert(obj && size >= sizeof(GenericAlternate));
a15fcc3c 112 assert(!(v->type & VISITOR_OUTPUT) || *obj);
60390d2d 113 trace_visit_start_alternate(v, name, obj, size);
7b3cb803
MA
114 if (!v->start_alternate) {
115 assert(!(v->type & VISITOR_INPUT));
116 return true;
e58d695e 117 }
7b3cb803 118 ok = v->start_alternate(v, name, obj, size, errp);
a15fcc3c 119 if (v->type & VISITOR_INPUT) {
7b3cb803 120 assert(ok != !*obj);
dbf11922 121 }
7b3cb803 122 return ok;
dbf11922
EB
123}
124
1158bb2a 125void visit_end_alternate(Visitor *v, void **obj)
dbf11922 126{
ebfd93b6 127 trace_visit_end_alternate(v, obj);
dbf11922 128 if (v->end_alternate) {
1158bb2a 129 v->end_alternate(v, obj);
2345c77c
MR
130 }
131}
132
dbf11922 133bool visit_optional(Visitor *v, const char *name, bool *present)
69dd62df 134{
ebfd93b6 135 trace_visit_optional(v, name, present);
dbf11922
EB
136 if (v->optional) {
137 v->optional(v, name, present);
69dd62df 138 }
dbf11922 139 return *present;
69dd62df
KW
140}
141
a1307285
MA
142bool visit_policy_reject(Visitor *v, const char *name,
143 unsigned special_features, Error **errp)
db291641 144{
a1307285
MA
145 trace_visit_policy_reject(v, name);
146 if (v->policy_reject) {
147 return v->policy_reject(v, name, special_features, errp);
db291641 148 }
a1307285 149 return false;
db291641
MA
150}
151
a1307285
MA
152bool visit_policy_skip(Visitor *v, const char *name,
153 unsigned special_features)
91fa93e5 154{
a1307285
MA
155 trace_visit_policy_skip(v, name);
156 if (v->policy_skip) {
157 return v->policy_skip(v, name, special_features);
91fa93e5 158 }
a1307285 159 return false;
91fa93e5
MA
160}
161
ed29bb28
MA
162void visit_set_policy(Visitor *v, CompatPolicy *policy)
163{
164 v->compat_policy = *policy;
165}
166
68ab47e4
EB
167bool visit_is_input(Visitor *v)
168{
169 return v->type == VISITOR_INPUT;
170}
171
8e08bf4e
MA
172bool visit_is_dealloc(Visitor *v)
173{
174 return v->type == VISITOR_DEALLOC;
175}
176
012d4c96 177bool visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
2345c77c 178{
adfb264c 179 assert(obj);
ebfd93b6 180 trace_visit_type_int(v, name, obj);
012d4c96 181 return v->type_int64(v, name, obj, errp);
2345c77c
MR
182}
183
012d4c96 184static bool visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
04e070d2
EB
185 uint64_t max, const char *type, Error **errp)
186{
04e070d2
EB
187 uint64_t value = *obj;
188
faad584a
MA
189 assert(v->type == VISITOR_INPUT || value <= max);
190
012d4c96
MA
191 if (!v->type_uint64(v, name, &value, errp)) {
192 return false;
193 }
194 if (value > max) {
faad584a 195 assert(v->type == VISITOR_INPUT);
04e070d2
EB
196 error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
197 name ? name : "null", type);
012d4c96 198 return false;
4e27e819 199 }
012d4c96
MA
200 *obj = value;
201 return true;
4e27e819
MR
202}
203
012d4c96 204bool visit_type_uint8(Visitor *v, const char *name, uint8_t *obj,
51e72bc1 205 Error **errp)
4e27e819 206{
ebfd93b6 207 uint64_t value;
012d4c96 208 bool ok;
ebfd93b6
DB
209
210 trace_visit_type_uint8(v, name, obj);
211 value = *obj;
012d4c96 212 ok = visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp);
04e070d2 213 *obj = value;
012d4c96 214 return ok;
4e27e819
MR
215}
216
012d4c96 217bool visit_type_uint16(Visitor *v, const char *name, uint16_t *obj,
04e070d2 218 Error **errp)
4e27e819 219{
ebfd93b6 220 uint64_t value;
012d4c96 221 bool ok;
ebfd93b6
DB
222
223 trace_visit_type_uint16(v, name, obj);
224 value = *obj;
012d4c96 225 ok = visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp);
04e070d2 226 *obj = value;
012d4c96 227 return ok;
04e070d2 228}
297a3646 229
012d4c96 230bool visit_type_uint32(Visitor *v, const char *name, uint32_t *obj,
04e070d2
EB
231 Error **errp)
232{
ebfd93b6 233 uint64_t value;
012d4c96 234 bool ok;
ebfd93b6
DB
235
236 trace_visit_type_uint32(v, name, obj);
237 value = *obj;
012d4c96 238 ok = visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp);
04e070d2 239 *obj = value;
012d4c96 240 return ok;
4e27e819
MR
241}
242
012d4c96 243bool visit_type_uint64(Visitor *v, const char *name, uint64_t *obj,
04e070d2 244 Error **errp)
4e27e819 245{
adfb264c 246 assert(obj);
ebfd93b6 247 trace_visit_type_uint64(v, name, obj);
012d4c96 248 return v->type_uint64(v, name, obj, errp);
4e27e819
MR
249}
250
012d4c96 251static bool visit_type_intN(Visitor *v, int64_t *obj, const char *name,
04e070d2
EB
252 int64_t min, int64_t max, const char *type,
253 Error **errp)
4e27e819 254{
04e070d2 255 int64_t value = *obj;
297a3646 256
faad584a
MA
257 assert(v->type == VISITOR_INPUT || (value >= min && value <= max));
258
012d4c96
MA
259 if (!v->type_int64(v, name, &value, errp)) {
260 return false;
261 }
262 if (value < min || value > max) {
faad584a 263 assert(v->type == VISITOR_INPUT);
04e070d2
EB
264 error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
265 name ? name : "null", type);
012d4c96 266 return false;
4e27e819 267 }
012d4c96
MA
268 *obj = value;
269 return true;
4e27e819
MR
270}
271
012d4c96 272bool visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp)
4e27e819 273{
ebfd93b6 274 int64_t value;
012d4c96 275 bool ok;
ebfd93b6
DB
276
277 trace_visit_type_int8(v, name, obj);
278 value = *obj;
012d4c96 279 ok = visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp);
04e070d2 280 *obj = value;
012d4c96 281 return ok;
04e070d2 282}
297a3646 283
012d4c96 284bool visit_type_int16(Visitor *v, const char *name, int16_t *obj,
51e72bc1 285 Error **errp)
04e070d2 286{
ebfd93b6 287 int64_t value;
012d4c96 288 bool ok;
ebfd93b6
DB
289
290 trace_visit_type_int16(v, name, obj);
291 value = *obj;
012d4c96
MA
292 ok = visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t",
293 errp);
04e070d2 294 *obj = value;
012d4c96 295 return ok;
4e27e819
MR
296}
297
012d4c96 298bool visit_type_int32(Visitor *v, const char *name, int32_t *obj,
51e72bc1 299 Error **errp)
4e27e819 300{
ebfd93b6 301 int64_t value;
012d4c96 302 bool ok;
ebfd93b6
DB
303
304 trace_visit_type_int32(v, name, obj);
305 value = *obj;
012d4c96
MA
306 ok = visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t",
307 errp);
04e070d2 308 *obj = value;
012d4c96 309 return ok;
4e27e819
MR
310}
311
012d4c96 312bool visit_type_int64(Visitor *v, const char *name, int64_t *obj,
51e72bc1 313 Error **errp)
4e27e819 314{
adfb264c 315 assert(obj);
ebfd93b6 316 trace_visit_type_int64(v, name, obj);
012d4c96 317 return v->type_int64(v, name, obj, errp);
4e27e819
MR
318}
319
012d4c96 320bool visit_type_size(Visitor *v, const char *name, uint64_t *obj,
51e72bc1 321 Error **errp)
092705d4 322{
adfb264c 323 assert(obj);
ebfd93b6 324 trace_visit_type_size(v, name, obj);
297a3646 325 if (v->type_size) {
012d4c96 326 return v->type_size(v, name, obj, errp);
092705d4 327 }
012d4c96 328 return v->type_uint64(v, name, obj, errp);
092705d4
LE
329}
330
012d4c96 331bool visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp)
2345c77c 332{
adfb264c 333 assert(obj);
ebfd93b6 334 trace_visit_type_bool(v, name, obj);
012d4c96 335 return v->type_bool(v, name, obj, errp);
2345c77c
MR
336}
337
012d4c96 338bool visit_type_str(Visitor *v, const char *name, char **obj, Error **errp)
2345c77c 339{
7b3cb803 340 bool ok;
e58d695e
EB
341
342 assert(obj);
adfb264c
EB
343 /* TODO: Fix callers to not pass NULL when they mean "", so that we
344 * can enable:
a15fcc3c 345 assert(!(v->type & VISITOR_OUTPUT) || *obj);
adfb264c 346 */
ebfd93b6 347 trace_visit_type_str(v, name, obj);
7b3cb803 348 ok = v->type_str(v, name, obj, errp);
a15fcc3c 349 if (v->type & VISITOR_INPUT) {
7b3cb803 350 assert(ok != !*obj);
e58d695e 351 }
7b3cb803 352 return ok;
2345c77c
MR
353}
354
012d4c96 355bool visit_type_number(Visitor *v, const char *name, double *obj,
51e72bc1 356 Error **errp)
2345c77c 357{
adfb264c 358 assert(obj);
ebfd93b6 359 trace_visit_type_number(v, name, obj);
012d4c96 360 return v->type_number(v, name, obj, errp);
2345c77c 361}
0f71a1e0 362
012d4c96 363bool visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp)
28770e05 364{
012d4c96 365 bool ok;
e58d695e
EB
366
367 assert(obj);
adfb264c 368 assert(v->type != VISITOR_OUTPUT || *obj);
ebfd93b6 369 trace_visit_type_any(v, name, obj);
012d4c96 370 ok = v->type_any(v, name, obj, errp);
e58d695e 371 if (v->type == VISITOR_INPUT) {
012d4c96 372 assert(ok != !*obj);
e58d695e 373 }
012d4c96 374 return ok;
28770e05
MA
375}
376
012d4c96 377bool visit_type_null(Visitor *v, const char *name, QNull **obj,
d2f95f4d 378 Error **errp)
3bc97fd5 379{
d2f95f4d 380 trace_visit_type_null(v, name, obj);
012d4c96 381 return v->type_null(v, name, obj, errp);
3bc97fd5
EB
382}
383
012d4c96 384static bool output_type_enum(Visitor *v, const char *name, int *obj,
f7abe0ec 385 const QEnumLookup *lookup, Error **errp)
0f71a1e0 386{
0f71a1e0
PB
387 int value = *obj;
388 char *enum_str;
389
f7abe0ec 390 enum_str = (char *)qapi_enum_lookup(lookup, value);
012d4c96 391 return visit_type_str(v, name, &enum_str, errp);
0f71a1e0
PB
392}
393
012d4c96 394static bool input_type_enum(Visitor *v, const char *name, int *obj,
f7abe0ec 395 const QEnumLookup *lookup, Error **errp)
0f71a1e0 396{
113e47ae 397 int64_t value;
aa237044 398 g_autofree char *enum_str = NULL;
0f71a1e0 399
012d4c96
MA
400 if (!visit_type_str(v, name, &enum_str, errp)) {
401 return false;
0f71a1e0
PB
402 }
403
f7abe0ec 404 value = qapi_enum_parse(lookup, enum_str, -1, NULL);
113e47ae 405 if (value < 0) {
ea29331b
MA
406 error_setg(errp, "Parameter '%s' does not accept value '%s'",
407 name ? name : "null", enum_str);
012d4c96 408 return false;
0f71a1e0
PB
409 }
410
aa237044
MA
411 if (lookup->flags && (lookup->flags[value] & QAPI_ENUM_DEPRECATED)) {
412 switch (v->compat_policy.deprecated_input) {
413 case COMPAT_POLICY_INPUT_ACCEPT:
414 break;
415 case COMPAT_POLICY_INPUT_REJECT:
416 error_setg(errp, "Deprecated value '%s' disabled by policy",
417 enum_str);
418 return false;
419 case COMPAT_POLICY_INPUT_CRASH:
420 default:
421 abort();
422 }
423 }
424
0f71a1e0 425 *obj = value;
012d4c96 426 return true;
0f71a1e0 427}
983f52d4 428
012d4c96 429bool visit_type_enum(Visitor *v, const char *name, int *obj,
f7abe0ec 430 const QEnumLookup *lookup, Error **errp)
983f52d4 431{
f7abe0ec 432 assert(obj && lookup);
6514532f 433 trace_visit_type_enum(v, name, obj);
a15fcc3c
EB
434 switch (v->type) {
435 case VISITOR_INPUT:
012d4c96 436 return input_type_enum(v, name, obj, lookup, errp);
a15fcc3c 437 case VISITOR_OUTPUT:
012d4c96 438 return output_type_enum(v, name, obj, lookup, errp);
a15fcc3c
EB
439 case VISITOR_CLONE:
440 /* nothing further to do, scalar value was already copied by
441 * g_memdup() during visit_start_*() */
012d4c96 442 return true;
a15fcc3c
EB
443 case VISITOR_DEALLOC:
444 /* nothing to deallocate for a scalar */
012d4c96
MA
445 return true;
446 default:
447 abort();
983f52d4
EB
448 }
449}
This page took 0.658928 seconds and 4 git commands to generate.