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" 22ebfd93b6SDaniel P. Berrange #include "trace.h" 232345c77cSMichael Roth 243b098d56SEric Blake void visit_complete(Visitor *v, void *opaque) 253b098d56SEric Blake { 263b098d56SEric Blake assert(v->type != VISITOR_OUTPUT || v->complete); 27ebfd93b6SDaniel P. Berrange trace_visit_complete(v, opaque); 283b098d56SEric Blake if (v->complete) { 293b098d56SEric Blake v->complete(v, opaque); 303b098d56SEric Blake } 313b098d56SEric Blake } 323b098d56SEric Blake 332c0ef9f4SEric Blake void visit_free(Visitor *v) 342c0ef9f4SEric Blake { 35ebfd93b6SDaniel P. Berrange trace_visit_free(v); 362c0ef9f4SEric Blake if (v) { 372c0ef9f4SEric Blake v->free(v); 382c0ef9f4SEric Blake } 392c0ef9f4SEric Blake } 402c0ef9f4SEric Blake 4151e72bc1SEric Blake void visit_start_struct(Visitor *v, const char *name, void **obj, 42337283dfSEric Blake size_t size, Error **errp) 432345c77cSMichael Roth { 44e58d695eSEric Blake Error *err = NULL; 45e58d695eSEric Blake 46ebfd93b6SDaniel P. Berrange trace_visit_start_struct(v, name, obj, size); 47adfb264cSEric Blake if (obj) { 48adfb264cSEric Blake assert(size); 49a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 50adfb264cSEric Blake } 51e58d695eSEric Blake v->start_struct(v, name, obj, size, &err); 52a15fcc3cSEric Blake if (obj && (v->type & VISITOR_INPUT)) { 53e58d695eSEric Blake assert(!err != !*obj); 54e58d695eSEric Blake } 55e58d695eSEric Blake error_propagate(errp, err); 562345c77cSMichael Roth } 572345c77cSMichael Roth 5815c2f669SEric Blake void visit_check_struct(Visitor *v, Error **errp) 592345c77cSMichael Roth { 60ebfd93b6SDaniel P. Berrange trace_visit_check_struct(v); 6115c2f669SEric Blake if (v->check_struct) { 6215c2f669SEric Blake v->check_struct(v, errp); 6315c2f669SEric Blake } 6415c2f669SEric Blake } 6515c2f669SEric Blake 661158bb2aSEric Blake void visit_end_struct(Visitor *v, void **obj) 6715c2f669SEric Blake { 68ebfd93b6SDaniel P. Berrange trace_visit_end_struct(v, obj); 691158bb2aSEric Blake v->end_struct(v, obj); 702345c77cSMichael Roth } 712345c77cSMichael Roth 72d9f62ddeSEric Blake void visit_start_list(Visitor *v, const char *name, GenericList **list, 73d9f62ddeSEric Blake size_t size, Error **errp) 742345c77cSMichael Roth { 75d9f62ddeSEric Blake Error *err = NULL; 76d9f62ddeSEric Blake 77d9f62ddeSEric Blake assert(!list || size >= sizeof(GenericList)); 78ebfd93b6SDaniel P. Berrange trace_visit_start_list(v, name, list, size); 79d9f62ddeSEric Blake v->start_list(v, name, list, size, &err); 80a15fcc3cSEric Blake if (list && (v->type & VISITOR_INPUT)) { 81d9f62ddeSEric Blake assert(!(err && *list)); 82d9f62ddeSEric Blake } 83d9f62ddeSEric Blake error_propagate(errp, err); 842345c77cSMichael Roth } 852345c77cSMichael Roth 86d9f62ddeSEric Blake GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size) 872345c77cSMichael Roth { 88d9f62ddeSEric Blake assert(tail && size >= sizeof(GenericList)); 89ebfd93b6SDaniel P. Berrange trace_visit_next_list(v, tail, size); 90d9f62ddeSEric Blake return v->next_list(v, tail, size); 912345c77cSMichael Roth } 922345c77cSMichael Roth 93a4a1c70dSMarkus Armbruster void visit_check_list(Visitor *v, Error **errp) 94a4a1c70dSMarkus Armbruster { 95a4a1c70dSMarkus Armbruster trace_visit_check_list(v); 96a4a1c70dSMarkus Armbruster if (v->check_list) { 97a4a1c70dSMarkus Armbruster v->check_list(v, errp); 98a4a1c70dSMarkus Armbruster } 99a4a1c70dSMarkus Armbruster } 100a4a1c70dSMarkus Armbruster 1011158bb2aSEric Blake void visit_end_list(Visitor *v, void **obj) 1022345c77cSMichael Roth { 103ebfd93b6SDaniel P. Berrange trace_visit_end_list(v, obj); 1041158bb2aSEric Blake v->end_list(v, obj); 1052345c77cSMichael Roth } 1062345c77cSMichael Roth 107dbf11922SEric Blake void visit_start_alternate(Visitor *v, const char *name, 108dbf11922SEric Blake GenericAlternate **obj, size_t size, 109*60390d2dSMarc-André Lureau Error **errp) 110dbf11922SEric Blake { 111e58d695eSEric Blake Error *err = NULL; 112e58d695eSEric Blake 113dbf11922SEric Blake assert(obj && size >= sizeof(GenericAlternate)); 114a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 115*60390d2dSMarc-André Lureau trace_visit_start_alternate(v, name, obj, size); 116dbf11922SEric Blake if (v->start_alternate) { 117*60390d2dSMarc-André Lureau v->start_alternate(v, name, obj, size, &err); 118dbf11922SEric Blake } 119a15fcc3cSEric Blake if (v->type & VISITOR_INPUT) { 120e58d695eSEric Blake assert(v->start_alternate && !err != !*obj); 121e58d695eSEric Blake } 122e58d695eSEric Blake error_propagate(errp, err); 123dbf11922SEric Blake } 124dbf11922SEric Blake 1251158bb2aSEric Blake void visit_end_alternate(Visitor *v, void **obj) 126dbf11922SEric Blake { 127ebfd93b6SDaniel P. Berrange trace_visit_end_alternate(v, obj); 128dbf11922SEric Blake if (v->end_alternate) { 1291158bb2aSEric Blake v->end_alternate(v, obj); 130dbf11922SEric Blake } 131dbf11922SEric Blake } 132dbf11922SEric Blake 13351e72bc1SEric Blake bool visit_optional(Visitor *v, const char *name, bool *present) 1342345c77cSMichael Roth { 135ebfd93b6SDaniel P. Berrange trace_visit_optional(v, name, present); 136297a3646SMarkus Armbruster if (v->optional) { 1370b2a0d6bSEric Blake v->optional(v, name, present); 1382345c77cSMichael Roth } 13929637a6eSEric Blake return *present; 1402345c77cSMichael Roth } 1412345c77cSMichael Roth 14268ab47e4SEric Blake bool visit_is_input(Visitor *v) 14368ab47e4SEric Blake { 14468ab47e4SEric Blake return v->type == VISITOR_INPUT; 14568ab47e4SEric Blake } 14668ab47e4SEric Blake 14751e72bc1SEric Blake void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) 1482345c77cSMichael Roth { 149adfb264cSEric Blake assert(obj); 150ebfd93b6SDaniel P. Berrange trace_visit_type_int(v, name, obj); 1510b2a0d6bSEric Blake v->type_int64(v, name, obj, errp); 1522345c77cSMichael Roth } 1532345c77cSMichael Roth 15404e070d2SEric Blake static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, 15504e070d2SEric Blake uint64_t max, const char *type, Error **errp) 15604e070d2SEric Blake { 15704e070d2SEric Blake Error *err = NULL; 15804e070d2SEric Blake uint64_t value = *obj; 15904e070d2SEric Blake 1600b2a0d6bSEric Blake v->type_uint64(v, name, &value, &err); 16104e070d2SEric Blake if (err) { 16204e070d2SEric Blake error_propagate(errp, err); 16304e070d2SEric Blake } else if (value > max) { 16404e070d2SEric Blake error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 16504e070d2SEric Blake name ? name : "null", type); 16604e070d2SEric Blake } else { 16704e070d2SEric Blake *obj = value; 16804e070d2SEric Blake } 16904e070d2SEric Blake } 17004e070d2SEric Blake 17151e72bc1SEric Blake void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, 17251e72bc1SEric Blake Error **errp) 1734e27e819SMichael Roth { 174ebfd93b6SDaniel P. Berrange uint64_t value; 175ebfd93b6SDaniel P. Berrange 176ebfd93b6SDaniel P. Berrange trace_visit_type_uint8(v, name, obj); 177ebfd93b6SDaniel P. Berrange value = *obj; 17804e070d2SEric Blake visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); 1794e27e819SMichael Roth *obj = value; 1804e27e819SMichael Roth } 1814e27e819SMichael Roth 18251e72bc1SEric Blake void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, 18304e070d2SEric Blake Error **errp) 1844e27e819SMichael Roth { 185ebfd93b6SDaniel P. Berrange uint64_t value; 186ebfd93b6SDaniel P. Berrange 187ebfd93b6SDaniel P. Berrange trace_visit_type_uint16(v, name, obj); 188ebfd93b6SDaniel P. Berrange value = *obj; 18904e070d2SEric Blake visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); 1904e27e819SMichael Roth *obj = value; 1914e27e819SMichael Roth } 1924e27e819SMichael Roth 19351e72bc1SEric Blake void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, 19404e070d2SEric Blake Error **errp) 1954e27e819SMichael Roth { 196ebfd93b6SDaniel P. Berrange uint64_t value; 197ebfd93b6SDaniel P. Berrange 198ebfd93b6SDaniel P. Berrange trace_visit_type_uint32(v, name, obj); 199ebfd93b6SDaniel P. Berrange value = *obj; 20004e070d2SEric Blake visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); 2014e27e819SMichael Roth *obj = value; 2024e27e819SMichael Roth } 2034e27e819SMichael Roth 20451e72bc1SEric Blake void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, 20504e070d2SEric Blake Error **errp) 2064e27e819SMichael Roth { 207adfb264cSEric Blake assert(obj); 208ebfd93b6SDaniel P. Berrange trace_visit_type_uint64(v, name, obj); 2090b2a0d6bSEric Blake v->type_uint64(v, name, obj, errp); 2104e27e819SMichael Roth } 2114e27e819SMichael Roth 21204e070d2SEric Blake static void visit_type_intN(Visitor *v, int64_t *obj, const char *name, 21304e070d2SEric Blake int64_t min, int64_t max, const char *type, 21404e070d2SEric Blake Error **errp) 2154e27e819SMichael Roth { 21604e070d2SEric Blake Error *err = NULL; 21704e070d2SEric Blake int64_t value = *obj; 218297a3646SMarkus Armbruster 2190b2a0d6bSEric Blake v->type_int64(v, name, &value, &err); 22004e070d2SEric Blake if (err) { 22104e070d2SEric Blake error_propagate(errp, err); 22204e070d2SEric Blake } else if (value < min || value > max) { 223c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 22404e070d2SEric Blake name ? name : "null", type); 22504e070d2SEric Blake } else { 2264e27e819SMichael Roth *obj = value; 2274e27e819SMichael Roth } 2284e27e819SMichael Roth } 2294e27e819SMichael Roth 23051e72bc1SEric Blake void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) 23104e070d2SEric Blake { 232ebfd93b6SDaniel P. Berrange int64_t value; 233ebfd93b6SDaniel P. Berrange 234ebfd93b6SDaniel P. Berrange trace_visit_type_int8(v, name, obj); 235ebfd93b6SDaniel P. Berrange value = *obj; 23604e070d2SEric Blake visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); 23704e070d2SEric Blake *obj = value; 23804e070d2SEric Blake } 23904e070d2SEric Blake 24051e72bc1SEric Blake void visit_type_int16(Visitor *v, const char *name, int16_t *obj, 24151e72bc1SEric Blake Error **errp) 2424e27e819SMichael Roth { 243ebfd93b6SDaniel P. Berrange int64_t value; 244ebfd93b6SDaniel P. Berrange 245ebfd93b6SDaniel P. Berrange trace_visit_type_int16(v, name, obj); 246ebfd93b6SDaniel P. Berrange value = *obj; 24704e070d2SEric Blake visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp); 2484e27e819SMichael Roth *obj = value; 2494e27e819SMichael Roth } 2504e27e819SMichael Roth 25151e72bc1SEric Blake void visit_type_int32(Visitor *v, const char *name, int32_t *obj, 25251e72bc1SEric Blake Error **errp) 2534e27e819SMichael Roth { 254ebfd93b6SDaniel P. Berrange int64_t value; 255ebfd93b6SDaniel P. Berrange 256ebfd93b6SDaniel P. Berrange trace_visit_type_int32(v, name, obj); 257ebfd93b6SDaniel P. Berrange value = *obj; 25804e070d2SEric Blake visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp); 2594e27e819SMichael Roth *obj = value; 2604e27e819SMichael Roth } 2614e27e819SMichael Roth 26251e72bc1SEric Blake void visit_type_int64(Visitor *v, const char *name, int64_t *obj, 26351e72bc1SEric Blake Error **errp) 2644e27e819SMichael Roth { 265adfb264cSEric Blake assert(obj); 266ebfd93b6SDaniel P. Berrange trace_visit_type_int64(v, name, obj); 2670b2a0d6bSEric Blake v->type_int64(v, name, obj, errp); 2684e27e819SMichael Roth } 2694e27e819SMichael Roth 27051e72bc1SEric Blake void visit_type_size(Visitor *v, const char *name, uint64_t *obj, 27151e72bc1SEric Blake Error **errp) 272092705d4SLaszlo Ersek { 273adfb264cSEric Blake assert(obj); 274ebfd93b6SDaniel P. Berrange trace_visit_type_size(v, name, obj); 275b8877962SVasilis Liaskovitis if (v->type_size) { 2760b2a0d6bSEric Blake v->type_size(v, name, obj, errp); 277b8877962SVasilis Liaskovitis } else { 2780b2a0d6bSEric Blake v->type_uint64(v, name, obj, errp); 279b8877962SVasilis Liaskovitis } 280092705d4SLaszlo Ersek } 281092705d4SLaszlo Ersek 28251e72bc1SEric Blake void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) 2832345c77cSMichael Roth { 284adfb264cSEric Blake assert(obj); 285ebfd93b6SDaniel P. Berrange trace_visit_type_bool(v, name, obj); 2860b2a0d6bSEric Blake v->type_bool(v, name, obj, errp); 2872345c77cSMichael Roth } 2882345c77cSMichael Roth 28951e72bc1SEric Blake void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) 2902345c77cSMichael Roth { 291e58d695eSEric Blake Error *err = NULL; 292e58d695eSEric Blake 293e58d695eSEric Blake assert(obj); 294adfb264cSEric Blake /* TODO: Fix callers to not pass NULL when they mean "", so that we 295adfb264cSEric Blake * can enable: 296a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 297adfb264cSEric Blake */ 298ebfd93b6SDaniel P. Berrange trace_visit_type_str(v, name, obj); 299e58d695eSEric Blake v->type_str(v, name, obj, &err); 300a15fcc3cSEric Blake if (v->type & VISITOR_INPUT) { 301e58d695eSEric Blake assert(!err != !*obj); 302e58d695eSEric Blake } 303e58d695eSEric Blake error_propagate(errp, err); 3042345c77cSMichael Roth } 3052345c77cSMichael Roth 30651e72bc1SEric Blake void visit_type_number(Visitor *v, const char *name, double *obj, 30751e72bc1SEric Blake Error **errp) 3082345c77cSMichael Roth { 309adfb264cSEric Blake assert(obj); 310ebfd93b6SDaniel P. Berrange trace_visit_type_number(v, name, obj); 3110b2a0d6bSEric Blake v->type_number(v, name, obj, errp); 3122345c77cSMichael Roth } 3130f71a1e0SPaolo Bonzini 31451e72bc1SEric Blake void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) 31528770e05SMarkus Armbruster { 316e58d695eSEric Blake Error *err = NULL; 317e58d695eSEric Blake 318e58d695eSEric Blake assert(obj); 319adfb264cSEric Blake assert(v->type != VISITOR_OUTPUT || *obj); 320ebfd93b6SDaniel P. Berrange trace_visit_type_any(v, name, obj); 321e58d695eSEric Blake v->type_any(v, name, obj, &err); 322e58d695eSEric Blake if (v->type == VISITOR_INPUT) { 323e58d695eSEric Blake assert(!err != !*obj); 324e58d695eSEric Blake } 325e58d695eSEric Blake error_propagate(errp, err); 32628770e05SMarkus Armbruster } 32728770e05SMarkus Armbruster 3283bc97fd5SEric Blake void visit_type_null(Visitor *v, const char *name, Error **errp) 3293bc97fd5SEric Blake { 330ebfd93b6SDaniel P. Berrange trace_visit_type_null(v, name); 3313bc97fd5SEric Blake v->type_null(v, name, errp); 3323bc97fd5SEric Blake } 3333bc97fd5SEric Blake 334983f52d4SEric Blake static void output_type_enum(Visitor *v, const char *name, int *obj, 335337283dfSEric Blake const char *const strings[], Error **errp) 3360f71a1e0SPaolo Bonzini { 3370f71a1e0SPaolo Bonzini int i = 0; 3380f71a1e0SPaolo Bonzini int value = *obj; 3390f71a1e0SPaolo Bonzini char *enum_str; 3400f71a1e0SPaolo Bonzini 3410f71a1e0SPaolo Bonzini while (strings[i++] != NULL); 3420f71a1e0SPaolo Bonzini if (value < 0 || value >= i - 1) { 343c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null"); 3440f71a1e0SPaolo Bonzini return; 3450f71a1e0SPaolo Bonzini } 3460f71a1e0SPaolo Bonzini 3470f71a1e0SPaolo Bonzini enum_str = (char *)strings[value]; 34851e72bc1SEric Blake visit_type_str(v, name, &enum_str, errp); 3490f71a1e0SPaolo Bonzini } 3500f71a1e0SPaolo Bonzini 351983f52d4SEric Blake static void input_type_enum(Visitor *v, const char *name, int *obj, 352337283dfSEric Blake const char *const strings[], Error **errp) 3530f71a1e0SPaolo Bonzini { 354297a3646SMarkus Armbruster Error *local_err = NULL; 3550f71a1e0SPaolo Bonzini int64_t value = 0; 3560f71a1e0SPaolo Bonzini char *enum_str; 3570f71a1e0SPaolo Bonzini 35851e72bc1SEric Blake visit_type_str(v, name, &enum_str, &local_err); 359297a3646SMarkus Armbruster if (local_err) { 360297a3646SMarkus Armbruster error_propagate(errp, local_err); 3610f71a1e0SPaolo Bonzini return; 3620f71a1e0SPaolo Bonzini } 3630f71a1e0SPaolo Bonzini 3640f71a1e0SPaolo Bonzini while (strings[value] != NULL) { 3650f71a1e0SPaolo Bonzini if (strcmp(strings[value], enum_str) == 0) { 3660f71a1e0SPaolo Bonzini break; 3670f71a1e0SPaolo Bonzini } 3680f71a1e0SPaolo Bonzini value++; 3690f71a1e0SPaolo Bonzini } 3700f71a1e0SPaolo Bonzini 3710f71a1e0SPaolo Bonzini if (strings[value] == NULL) { 372c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER, enum_str); 3730f71a1e0SPaolo Bonzini g_free(enum_str); 3740f71a1e0SPaolo Bonzini return; 3750f71a1e0SPaolo Bonzini } 3760f71a1e0SPaolo Bonzini 3770f71a1e0SPaolo Bonzini g_free(enum_str); 3780f71a1e0SPaolo Bonzini *obj = value; 3790f71a1e0SPaolo Bonzini } 380983f52d4SEric Blake 381983f52d4SEric Blake void visit_type_enum(Visitor *v, const char *name, int *obj, 382983f52d4SEric Blake const char *const strings[], Error **errp) 383983f52d4SEric Blake { 384adfb264cSEric Blake assert(obj && strings); 3856514532fSStefan Hajnoczi trace_visit_type_enum(v, name, obj); 386a15fcc3cSEric Blake switch (v->type) { 387a15fcc3cSEric Blake case VISITOR_INPUT: 388983f52d4SEric Blake input_type_enum(v, name, obj, strings, errp); 389a15fcc3cSEric Blake break; 390a15fcc3cSEric Blake case VISITOR_OUTPUT: 391983f52d4SEric Blake output_type_enum(v, name, obj, strings, errp); 392a15fcc3cSEric Blake break; 393a15fcc3cSEric Blake case VISITOR_CLONE: 394a15fcc3cSEric Blake /* nothing further to do, scalar value was already copied by 395a15fcc3cSEric Blake * g_memdup() during visit_start_*() */ 396a15fcc3cSEric Blake break; 397a15fcc3cSEric Blake case VISITOR_DEALLOC: 398a15fcc3cSEric Blake /* nothing to deallocate for a scalar */ 399a15fcc3cSEric Blake break; 400983f52d4SEric Blake } 401983f52d4SEric Blake } 402