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