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