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" 177b1b5d19SPaolo Bonzini #include "qapi/qmp/qerror.h" 187b1b5d19SPaolo Bonzini #include "qapi/visitor.h" 197b1b5d19SPaolo Bonzini #include "qapi/visitor-impl.h" 20ebfd93b6SDaniel P. Berrange #include "trace.h" 212345c77cSMichael Roth 223b098d56SEric Blake void visit_complete(Visitor *v, void *opaque) 233b098d56SEric Blake { 243b098d56SEric Blake assert(v->type != VISITOR_OUTPUT || v->complete); 25ebfd93b6SDaniel P. Berrange trace_visit_complete(v, opaque); 263b098d56SEric Blake if (v->complete) { 273b098d56SEric Blake v->complete(v, opaque); 283b098d56SEric Blake } 293b098d56SEric Blake } 303b098d56SEric Blake 312c0ef9f4SEric Blake void visit_free(Visitor *v) 322c0ef9f4SEric Blake { 33ebfd93b6SDaniel P. Berrange trace_visit_free(v); 342c0ef9f4SEric Blake if (v) { 352c0ef9f4SEric Blake v->free(v); 362c0ef9f4SEric Blake } 372c0ef9f4SEric Blake } 382c0ef9f4SEric Blake 3951e72bc1SEric Blake void visit_start_struct(Visitor *v, const char *name, void **obj, 40337283dfSEric Blake size_t size, Error **errp) 412345c77cSMichael Roth { 42e58d695eSEric Blake Error *err = NULL; 43e58d695eSEric Blake 44ebfd93b6SDaniel P. Berrange trace_visit_start_struct(v, name, obj, size); 45adfb264cSEric Blake if (obj) { 46adfb264cSEric Blake assert(size); 47a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 48adfb264cSEric Blake } 49e58d695eSEric Blake v->start_struct(v, name, obj, size, &err); 50a15fcc3cSEric Blake if (obj && (v->type & VISITOR_INPUT)) { 51e58d695eSEric Blake assert(!err != !*obj); 52e58d695eSEric Blake } 53e58d695eSEric Blake error_propagate(errp, err); 542345c77cSMichael Roth } 552345c77cSMichael Roth 5615c2f669SEric Blake void visit_check_struct(Visitor *v, Error **errp) 572345c77cSMichael Roth { 58ebfd93b6SDaniel P. Berrange trace_visit_check_struct(v); 5915c2f669SEric Blake if (v->check_struct) { 6015c2f669SEric Blake v->check_struct(v, errp); 6115c2f669SEric Blake } 6215c2f669SEric Blake } 6315c2f669SEric Blake 641158bb2aSEric Blake void visit_end_struct(Visitor *v, void **obj) 6515c2f669SEric Blake { 66ebfd93b6SDaniel P. Berrange trace_visit_end_struct(v, obj); 671158bb2aSEric Blake v->end_struct(v, obj); 682345c77cSMichael Roth } 692345c77cSMichael Roth 70d9f62ddeSEric Blake void visit_start_list(Visitor *v, const char *name, GenericList **list, 71d9f62ddeSEric Blake size_t size, Error **errp) 722345c77cSMichael Roth { 73d9f62ddeSEric Blake Error *err = NULL; 74d9f62ddeSEric Blake 75d9f62ddeSEric Blake assert(!list || size >= sizeof(GenericList)); 76ebfd93b6SDaniel P. Berrange trace_visit_start_list(v, name, list, size); 77d9f62ddeSEric Blake v->start_list(v, name, list, size, &err); 78a15fcc3cSEric Blake if (list && (v->type & VISITOR_INPUT)) { 79d9f62ddeSEric Blake assert(!(err && *list)); 80d9f62ddeSEric Blake } 81d9f62ddeSEric Blake error_propagate(errp, err); 822345c77cSMichael Roth } 832345c77cSMichael Roth 84d9f62ddeSEric Blake GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size) 852345c77cSMichael Roth { 86d9f62ddeSEric Blake assert(tail && size >= sizeof(GenericList)); 87ebfd93b6SDaniel P. Berrange trace_visit_next_list(v, tail, size); 88d9f62ddeSEric Blake return v->next_list(v, tail, size); 892345c77cSMichael Roth } 902345c77cSMichael Roth 91a4a1c70dSMarkus Armbruster void visit_check_list(Visitor *v, Error **errp) 92a4a1c70dSMarkus Armbruster { 93a4a1c70dSMarkus Armbruster trace_visit_check_list(v); 94a4a1c70dSMarkus Armbruster if (v->check_list) { 95a4a1c70dSMarkus Armbruster v->check_list(v, errp); 96a4a1c70dSMarkus Armbruster } 97a4a1c70dSMarkus Armbruster } 98a4a1c70dSMarkus Armbruster 991158bb2aSEric Blake void visit_end_list(Visitor *v, void **obj) 1002345c77cSMichael Roth { 101ebfd93b6SDaniel P. Berrange trace_visit_end_list(v, obj); 1021158bb2aSEric Blake v->end_list(v, obj); 1032345c77cSMichael Roth } 1042345c77cSMichael Roth 105dbf11922SEric Blake void visit_start_alternate(Visitor *v, const char *name, 106dbf11922SEric Blake GenericAlternate **obj, size_t size, 10760390d2dSMarc-André Lureau Error **errp) 108dbf11922SEric Blake { 109e58d695eSEric Blake Error *err = NULL; 110e58d695eSEric Blake 111dbf11922SEric Blake assert(obj && size >= sizeof(GenericAlternate)); 112a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 11360390d2dSMarc-André Lureau trace_visit_start_alternate(v, name, obj, size); 114dbf11922SEric Blake if (v->start_alternate) { 11560390d2dSMarc-André Lureau v->start_alternate(v, name, obj, size, &err); 116dbf11922SEric Blake } 117a15fcc3cSEric Blake if (v->type & VISITOR_INPUT) { 118e58d695eSEric Blake assert(v->start_alternate && !err != !*obj); 119e58d695eSEric Blake } 120e58d695eSEric Blake error_propagate(errp, err); 121dbf11922SEric Blake } 122dbf11922SEric Blake 1231158bb2aSEric Blake void visit_end_alternate(Visitor *v, void **obj) 124dbf11922SEric Blake { 125ebfd93b6SDaniel P. Berrange trace_visit_end_alternate(v, obj); 126dbf11922SEric Blake if (v->end_alternate) { 1271158bb2aSEric Blake v->end_alternate(v, obj); 128dbf11922SEric Blake } 129dbf11922SEric Blake } 130dbf11922SEric Blake 13151e72bc1SEric Blake bool visit_optional(Visitor *v, const char *name, bool *present) 1322345c77cSMichael Roth { 133ebfd93b6SDaniel P. Berrange trace_visit_optional(v, name, present); 134297a3646SMarkus Armbruster if (v->optional) { 1350b2a0d6bSEric Blake v->optional(v, name, present); 1362345c77cSMichael Roth } 13729637a6eSEric Blake return *present; 1382345c77cSMichael Roth } 1392345c77cSMichael Roth 14068ab47e4SEric Blake bool visit_is_input(Visitor *v) 14168ab47e4SEric Blake { 14268ab47e4SEric Blake return v->type == VISITOR_INPUT; 14368ab47e4SEric Blake } 14468ab47e4SEric Blake 1458e08bf4eSMarkus Armbruster bool visit_is_dealloc(Visitor *v) 1468e08bf4eSMarkus Armbruster { 1478e08bf4eSMarkus Armbruster return v->type == VISITOR_DEALLOC; 1488e08bf4eSMarkus Armbruster } 1498e08bf4eSMarkus Armbruster 15051e72bc1SEric Blake void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp) 1512345c77cSMichael Roth { 152adfb264cSEric Blake assert(obj); 153ebfd93b6SDaniel P. Berrange trace_visit_type_int(v, name, obj); 1540b2a0d6bSEric Blake v->type_int64(v, name, obj, errp); 1552345c77cSMichael Roth } 1562345c77cSMichael Roth 15704e070d2SEric Blake static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name, 15804e070d2SEric Blake uint64_t max, const char *type, Error **errp) 15904e070d2SEric Blake { 16004e070d2SEric Blake Error *err = NULL; 16104e070d2SEric Blake uint64_t value = *obj; 16204e070d2SEric Blake 163*faad584aSMarkus Armbruster assert(v->type == VISITOR_INPUT || value <= max); 164*faad584aSMarkus Armbruster 1650b2a0d6bSEric Blake v->type_uint64(v, name, &value, &err); 16604e070d2SEric Blake if (err) { 16704e070d2SEric Blake error_propagate(errp, err); 16804e070d2SEric Blake } else if (value > max) { 169*faad584aSMarkus Armbruster assert(v->type == VISITOR_INPUT); 17004e070d2SEric Blake error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 17104e070d2SEric Blake name ? name : "null", type); 17204e070d2SEric Blake } else { 17304e070d2SEric Blake *obj = value; 17404e070d2SEric Blake } 17504e070d2SEric Blake } 17604e070d2SEric Blake 17751e72bc1SEric Blake void visit_type_uint8(Visitor *v, const char *name, uint8_t *obj, 17851e72bc1SEric Blake Error **errp) 1794e27e819SMichael Roth { 180ebfd93b6SDaniel P. Berrange uint64_t value; 181ebfd93b6SDaniel P. Berrange 182ebfd93b6SDaniel P. Berrange trace_visit_type_uint8(v, name, obj); 183ebfd93b6SDaniel P. Berrange value = *obj; 18404e070d2SEric Blake visit_type_uintN(v, &value, name, UINT8_MAX, "uint8_t", errp); 1854e27e819SMichael Roth *obj = value; 1864e27e819SMichael Roth } 1874e27e819SMichael Roth 18851e72bc1SEric Blake void visit_type_uint16(Visitor *v, const char *name, uint16_t *obj, 18904e070d2SEric Blake Error **errp) 1904e27e819SMichael Roth { 191ebfd93b6SDaniel P. Berrange uint64_t value; 192ebfd93b6SDaniel P. Berrange 193ebfd93b6SDaniel P. Berrange trace_visit_type_uint16(v, name, obj); 194ebfd93b6SDaniel P. Berrange value = *obj; 19504e070d2SEric Blake visit_type_uintN(v, &value, name, UINT16_MAX, "uint16_t", errp); 1964e27e819SMichael Roth *obj = value; 1974e27e819SMichael Roth } 1984e27e819SMichael Roth 19951e72bc1SEric Blake void visit_type_uint32(Visitor *v, const char *name, uint32_t *obj, 20004e070d2SEric Blake Error **errp) 2014e27e819SMichael Roth { 202ebfd93b6SDaniel P. Berrange uint64_t value; 203ebfd93b6SDaniel P. Berrange 204ebfd93b6SDaniel P. Berrange trace_visit_type_uint32(v, name, obj); 205ebfd93b6SDaniel P. Berrange value = *obj; 20604e070d2SEric Blake visit_type_uintN(v, &value, name, UINT32_MAX, "uint32_t", errp); 2074e27e819SMichael Roth *obj = value; 2084e27e819SMichael Roth } 2094e27e819SMichael Roth 21051e72bc1SEric Blake void visit_type_uint64(Visitor *v, const char *name, uint64_t *obj, 21104e070d2SEric Blake Error **errp) 2124e27e819SMichael Roth { 213adfb264cSEric Blake assert(obj); 214ebfd93b6SDaniel P. Berrange trace_visit_type_uint64(v, name, obj); 2150b2a0d6bSEric Blake v->type_uint64(v, name, obj, errp); 2164e27e819SMichael Roth } 2174e27e819SMichael Roth 21804e070d2SEric Blake static void visit_type_intN(Visitor *v, int64_t *obj, const char *name, 21904e070d2SEric Blake int64_t min, int64_t max, const char *type, 22004e070d2SEric Blake Error **errp) 2214e27e819SMichael Roth { 22204e070d2SEric Blake Error *err = NULL; 22304e070d2SEric Blake int64_t value = *obj; 224297a3646SMarkus Armbruster 225*faad584aSMarkus Armbruster assert(v->type == VISITOR_INPUT || (value >= min && value <= max)); 226*faad584aSMarkus Armbruster 2270b2a0d6bSEric Blake v->type_int64(v, name, &value, &err); 22804e070d2SEric Blake if (err) { 22904e070d2SEric Blake error_propagate(errp, err); 23004e070d2SEric Blake } else if (value < min || value > max) { 231*faad584aSMarkus Armbruster assert(v->type == VISITOR_INPUT); 232c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER_VALUE, 23304e070d2SEric Blake name ? name : "null", type); 23404e070d2SEric Blake } else { 2354e27e819SMichael Roth *obj = value; 2364e27e819SMichael Roth } 2374e27e819SMichael Roth } 2384e27e819SMichael Roth 23951e72bc1SEric Blake void visit_type_int8(Visitor *v, const char *name, int8_t *obj, Error **errp) 24004e070d2SEric Blake { 241ebfd93b6SDaniel P. Berrange int64_t value; 242ebfd93b6SDaniel P. Berrange 243ebfd93b6SDaniel P. Berrange trace_visit_type_int8(v, name, obj); 244ebfd93b6SDaniel P. Berrange value = *obj; 24504e070d2SEric Blake visit_type_intN(v, &value, name, INT8_MIN, INT8_MAX, "int8_t", errp); 24604e070d2SEric Blake *obj = value; 24704e070d2SEric Blake } 24804e070d2SEric Blake 24951e72bc1SEric Blake void visit_type_int16(Visitor *v, const char *name, int16_t *obj, 25051e72bc1SEric Blake Error **errp) 2514e27e819SMichael Roth { 252ebfd93b6SDaniel P. Berrange int64_t value; 253ebfd93b6SDaniel P. Berrange 254ebfd93b6SDaniel P. Berrange trace_visit_type_int16(v, name, obj); 255ebfd93b6SDaniel P. Berrange value = *obj; 25604e070d2SEric Blake visit_type_intN(v, &value, name, INT16_MIN, INT16_MAX, "int16_t", errp); 2574e27e819SMichael Roth *obj = value; 2584e27e819SMichael Roth } 2594e27e819SMichael Roth 26051e72bc1SEric Blake void visit_type_int32(Visitor *v, const char *name, int32_t *obj, 26151e72bc1SEric Blake Error **errp) 2624e27e819SMichael Roth { 263ebfd93b6SDaniel P. Berrange int64_t value; 264ebfd93b6SDaniel P. Berrange 265ebfd93b6SDaniel P. Berrange trace_visit_type_int32(v, name, obj); 266ebfd93b6SDaniel P. Berrange value = *obj; 26704e070d2SEric Blake visit_type_intN(v, &value, name, INT32_MIN, INT32_MAX, "int32_t", errp); 2684e27e819SMichael Roth *obj = value; 2694e27e819SMichael Roth } 2704e27e819SMichael Roth 27151e72bc1SEric Blake void visit_type_int64(Visitor *v, const char *name, int64_t *obj, 27251e72bc1SEric Blake Error **errp) 2734e27e819SMichael Roth { 274adfb264cSEric Blake assert(obj); 275ebfd93b6SDaniel P. Berrange trace_visit_type_int64(v, name, obj); 2760b2a0d6bSEric Blake v->type_int64(v, name, obj, errp); 2774e27e819SMichael Roth } 2784e27e819SMichael Roth 27951e72bc1SEric Blake void visit_type_size(Visitor *v, const char *name, uint64_t *obj, 28051e72bc1SEric Blake Error **errp) 281092705d4SLaszlo Ersek { 282adfb264cSEric Blake assert(obj); 283ebfd93b6SDaniel P. Berrange trace_visit_type_size(v, name, obj); 284b8877962SVasilis Liaskovitis if (v->type_size) { 2850b2a0d6bSEric Blake v->type_size(v, name, obj, errp); 286b8877962SVasilis Liaskovitis } else { 2870b2a0d6bSEric Blake v->type_uint64(v, name, obj, errp); 288b8877962SVasilis Liaskovitis } 289092705d4SLaszlo Ersek } 290092705d4SLaszlo Ersek 29151e72bc1SEric Blake void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp) 2922345c77cSMichael Roth { 293adfb264cSEric Blake assert(obj); 294ebfd93b6SDaniel P. Berrange trace_visit_type_bool(v, name, obj); 2950b2a0d6bSEric Blake v->type_bool(v, name, obj, errp); 2962345c77cSMichael Roth } 2972345c77cSMichael Roth 29851e72bc1SEric Blake void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp) 2992345c77cSMichael Roth { 300e58d695eSEric Blake Error *err = NULL; 301e58d695eSEric Blake 302e58d695eSEric Blake assert(obj); 303adfb264cSEric Blake /* TODO: Fix callers to not pass NULL when they mean "", so that we 304adfb264cSEric Blake * can enable: 305a15fcc3cSEric Blake assert(!(v->type & VISITOR_OUTPUT) || *obj); 306adfb264cSEric Blake */ 307ebfd93b6SDaniel P. Berrange trace_visit_type_str(v, name, obj); 308e58d695eSEric Blake v->type_str(v, name, obj, &err); 309a15fcc3cSEric Blake if (v->type & VISITOR_INPUT) { 310e58d695eSEric Blake assert(!err != !*obj); 311e58d695eSEric Blake } 312e58d695eSEric Blake error_propagate(errp, err); 3132345c77cSMichael Roth } 3142345c77cSMichael Roth 31551e72bc1SEric Blake void visit_type_number(Visitor *v, const char *name, double *obj, 31651e72bc1SEric Blake Error **errp) 3172345c77cSMichael Roth { 318adfb264cSEric Blake assert(obj); 319ebfd93b6SDaniel P. Berrange trace_visit_type_number(v, name, obj); 3200b2a0d6bSEric Blake v->type_number(v, name, obj, errp); 3212345c77cSMichael Roth } 3220f71a1e0SPaolo Bonzini 32351e72bc1SEric Blake void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp) 32428770e05SMarkus Armbruster { 325e58d695eSEric Blake Error *err = NULL; 326e58d695eSEric Blake 327e58d695eSEric Blake assert(obj); 328adfb264cSEric Blake assert(v->type != VISITOR_OUTPUT || *obj); 329ebfd93b6SDaniel P. Berrange trace_visit_type_any(v, name, obj); 330e58d695eSEric Blake v->type_any(v, name, obj, &err); 331e58d695eSEric Blake if (v->type == VISITOR_INPUT) { 332e58d695eSEric Blake assert(!err != !*obj); 333e58d695eSEric Blake } 334e58d695eSEric Blake error_propagate(errp, err); 33528770e05SMarkus Armbruster } 33628770e05SMarkus Armbruster 337d2f95f4dSMarkus Armbruster void visit_type_null(Visitor *v, const char *name, QNull **obj, 338d2f95f4dSMarkus Armbruster Error **errp) 3393bc97fd5SEric Blake { 340d2f95f4dSMarkus Armbruster trace_visit_type_null(v, name, obj); 341d2f95f4dSMarkus Armbruster v->type_null(v, name, obj, errp); 3423bc97fd5SEric Blake } 3433bc97fd5SEric Blake 344983f52d4SEric Blake static void output_type_enum(Visitor *v, const char *name, int *obj, 345f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, Error **errp) 3460f71a1e0SPaolo Bonzini { 3470f71a1e0SPaolo Bonzini int value = *obj; 3480f71a1e0SPaolo Bonzini char *enum_str; 3490f71a1e0SPaolo Bonzini 350f7abe0ecSMarc-André Lureau enum_str = (char *)qapi_enum_lookup(lookup, value); 35151e72bc1SEric Blake visit_type_str(v, name, &enum_str, errp); 3520f71a1e0SPaolo Bonzini } 3530f71a1e0SPaolo Bonzini 354983f52d4SEric Blake static void input_type_enum(Visitor *v, const char *name, int *obj, 355f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, Error **errp) 3560f71a1e0SPaolo Bonzini { 357297a3646SMarkus Armbruster Error *local_err = NULL; 358113e47aeSMarkus Armbruster int64_t value; 3590f71a1e0SPaolo Bonzini char *enum_str; 3600f71a1e0SPaolo Bonzini 36151e72bc1SEric Blake visit_type_str(v, name, &enum_str, &local_err); 362297a3646SMarkus Armbruster if (local_err) { 363297a3646SMarkus Armbruster error_propagate(errp, local_err); 3640f71a1e0SPaolo Bonzini return; 3650f71a1e0SPaolo Bonzini } 3660f71a1e0SPaolo Bonzini 367f7abe0ecSMarc-André Lureau value = qapi_enum_parse(lookup, enum_str, -1, NULL); 368113e47aeSMarkus Armbruster if (value < 0) { 369c6bd8c70SMarkus Armbruster error_setg(errp, QERR_INVALID_PARAMETER, enum_str); 3700f71a1e0SPaolo Bonzini g_free(enum_str); 3710f71a1e0SPaolo Bonzini return; 3720f71a1e0SPaolo Bonzini } 3730f71a1e0SPaolo Bonzini 3740f71a1e0SPaolo Bonzini g_free(enum_str); 3750f71a1e0SPaolo Bonzini *obj = value; 3760f71a1e0SPaolo Bonzini } 377983f52d4SEric Blake 378983f52d4SEric Blake void visit_type_enum(Visitor *v, const char *name, int *obj, 379f7abe0ecSMarc-André Lureau const QEnumLookup *lookup, Error **errp) 380983f52d4SEric Blake { 381f7abe0ecSMarc-André Lureau assert(obj && lookup); 3826514532fSStefan Hajnoczi trace_visit_type_enum(v, name, obj); 383a15fcc3cSEric Blake switch (v->type) { 384a15fcc3cSEric Blake case VISITOR_INPUT: 385f7abe0ecSMarc-André Lureau input_type_enum(v, name, obj, lookup, errp); 386a15fcc3cSEric Blake break; 387a15fcc3cSEric Blake case VISITOR_OUTPUT: 388f7abe0ecSMarc-André Lureau output_type_enum(v, name, obj, lookup, errp); 389a15fcc3cSEric Blake break; 390a15fcc3cSEric Blake case VISITOR_CLONE: 391a15fcc3cSEric Blake /* nothing further to do, scalar value was already copied by 392a15fcc3cSEric Blake * g_memdup() during visit_start_*() */ 393a15fcc3cSEric Blake break; 394a15fcc3cSEric Blake case VISITOR_DEALLOC: 395a15fcc3cSEric Blake /* nothing to deallocate for a scalar */ 396a15fcc3cSEric Blake break; 397983f52d4SEric Blake } 398983f52d4SEric Blake } 399