qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

qapi-visit-core.c (11351B)


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