qemu

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

qapi-forward-visitor.c (9365B)


      1 /*
      2  * Forward Visitor
      3  *
      4  * Copyright (C) 2021 Red Hat, Inc.
      5  *
      6  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
      7  * See the COPYING.LIB file in the top-level directory.
      8  *
      9  */
     10 
     11 #include "qemu/osdep.h"
     12 #include "qapi/compat-policy.h"
     13 #include "qapi/error.h"
     14 #include "qapi/forward-visitor.h"
     15 #include "qapi/visitor-impl.h"
     16 #include "qemu/queue.h"
     17 #include "qapi/qmp/qjson.h"
     18 #include "qapi/qmp/qbool.h"
     19 #include "qapi/qmp/qdict.h"
     20 #include "qapi/qmp/qerror.h"
     21 #include "qapi/qmp/qlist.h"
     22 #include "qapi/qmp/qnull.h"
     23 #include "qapi/qmp/qnum.h"
     24 #include "qapi/qmp/qstring.h"
     25 #include "qemu/cutils.h"
     26 
     27 struct ForwardFieldVisitor {
     28     Visitor visitor;
     29 
     30     Visitor *target;
     31     char *from;
     32     char *to;
     33 
     34     int depth;
     35 };
     36 
     37 static ForwardFieldVisitor *to_ffv(Visitor *v)
     38 {
     39     return container_of(v, ForwardFieldVisitor, visitor);
     40 }
     41 
     42 static bool forward_field_translate_name(ForwardFieldVisitor *v, const char **name,
     43                                          Error **errp)
     44 {
     45     if (v->depth) {
     46         return true;
     47     }
     48     if (g_str_equal(*name, v->from)) {
     49         *name = v->to;
     50         return true;
     51     }
     52     error_setg(errp, QERR_MISSING_PARAMETER, *name);
     53     return false;
     54 }
     55 
     56 static bool forward_field_check_struct(Visitor *v, Error **errp)
     57 {
     58     ForwardFieldVisitor *ffv = to_ffv(v);
     59 
     60     return visit_check_struct(ffv->target, errp);
     61 }
     62 
     63 static bool forward_field_start_struct(Visitor *v, const char *name, void **obj,
     64                                        size_t size, Error **errp)
     65 {
     66     ForwardFieldVisitor *ffv = to_ffv(v);
     67 
     68     if (!forward_field_translate_name(ffv, &name, errp)) {
     69         return false;
     70     }
     71     if (!visit_start_struct(ffv->target, name, obj, size, errp)) {
     72         return false;
     73     }
     74     ffv->depth++;
     75     return true;
     76 }
     77 
     78 static void forward_field_end_struct(Visitor *v, void **obj)
     79 {
     80     ForwardFieldVisitor *ffv = to_ffv(v);
     81 
     82     assert(ffv->depth);
     83     ffv->depth--;
     84     visit_end_struct(ffv->target, obj);
     85 }
     86 
     87 static bool forward_field_start_list(Visitor *v, const char *name,
     88                                      GenericList **list, size_t size,
     89                                      Error **errp)
     90 {
     91     ForwardFieldVisitor *ffv = to_ffv(v);
     92 
     93     if (!forward_field_translate_name(ffv, &name, errp)) {
     94         return false;
     95     }
     96     ffv->depth++;
     97     return visit_start_list(ffv->target, name, list, size, errp);
     98 }
     99 
    100 static GenericList *forward_field_next_list(Visitor *v, GenericList *tail,
    101                                             size_t size)
    102 {
    103     ForwardFieldVisitor *ffv = to_ffv(v);
    104 
    105     assert(ffv->depth);
    106     return visit_next_list(ffv->target, tail, size);
    107 }
    108 
    109 static bool forward_field_check_list(Visitor *v, Error **errp)
    110 {
    111     ForwardFieldVisitor *ffv = to_ffv(v);
    112 
    113     assert(ffv->depth);
    114     return visit_check_list(ffv->target, errp);
    115 }
    116 
    117 static void forward_field_end_list(Visitor *v, void **obj)
    118 {
    119     ForwardFieldVisitor *ffv = to_ffv(v);
    120 
    121     assert(ffv->depth);
    122     ffv->depth--;
    123     visit_end_list(ffv->target, obj);
    124 }
    125 
    126 static bool forward_field_start_alternate(Visitor *v, const char *name,
    127                                           GenericAlternate **obj, size_t size,
    128                                           Error **errp)
    129 {
    130     ForwardFieldVisitor *ffv = to_ffv(v);
    131 
    132     if (!forward_field_translate_name(ffv, &name, errp)) {
    133         return false;
    134     }
    135     /*
    136      * The name passed to start_alternate is used also in the visit_type_* calls
    137      * that retrieve the alternate's content; so, do not increase depth here.
    138      */
    139     return visit_start_alternate(ffv->target, name, obj, size, errp);
    140 }
    141 
    142 static void forward_field_end_alternate(Visitor *v, void **obj)
    143 {
    144     ForwardFieldVisitor *ffv = to_ffv(v);
    145 
    146     visit_end_alternate(ffv->target, obj);
    147 }
    148 
    149 static bool forward_field_type_int64(Visitor *v, const char *name, int64_t *obj,
    150                                      Error **errp)
    151 {
    152     ForwardFieldVisitor *ffv = to_ffv(v);
    153 
    154     if (!forward_field_translate_name(ffv, &name, errp)) {
    155         return false;
    156     }
    157     return visit_type_int64(ffv->target, name, obj, errp);
    158 }
    159 
    160 static bool forward_field_type_uint64(Visitor *v, const char *name,
    161                                       uint64_t *obj, Error **errp)
    162 {
    163     ForwardFieldVisitor *ffv = to_ffv(v);
    164 
    165     if (!forward_field_translate_name(ffv, &name, errp)) {
    166         return false;
    167     }
    168     return visit_type_uint64(ffv->target, name, obj, errp);
    169 }
    170 
    171 static bool forward_field_type_bool(Visitor *v, const char *name, bool *obj,
    172                                     Error **errp)
    173 {
    174     ForwardFieldVisitor *ffv = to_ffv(v);
    175 
    176     if (!forward_field_translate_name(ffv, &name, errp)) {
    177         return false;
    178     }
    179     return visit_type_bool(ffv->target, name, obj, errp);
    180 }
    181 
    182 static bool forward_field_type_str(Visitor *v, const char *name, char **obj,
    183                                    Error **errp)
    184 {
    185     ForwardFieldVisitor *ffv = to_ffv(v);
    186 
    187     if (!forward_field_translate_name(ffv, &name, errp)) {
    188         return false;
    189     }
    190     return visit_type_str(ffv->target, name, obj, errp);
    191 }
    192 
    193 static bool forward_field_type_size(Visitor *v, const char *name, uint64_t *obj,
    194                                     Error **errp)
    195 {
    196     ForwardFieldVisitor *ffv = to_ffv(v);
    197 
    198     if (!forward_field_translate_name(ffv, &name, errp)) {
    199         return false;
    200     }
    201     return visit_type_size(ffv->target, name, obj, errp);
    202 }
    203 
    204 static bool forward_field_type_number(Visitor *v, const char *name, double *obj,
    205                                       Error **errp)
    206 {
    207     ForwardFieldVisitor *ffv = to_ffv(v);
    208 
    209     if (!forward_field_translate_name(ffv, &name, errp)) {
    210         return false;
    211     }
    212     return visit_type_number(ffv->target, name, obj, errp);
    213 }
    214 
    215 static bool forward_field_type_any(Visitor *v, const char *name, QObject **obj,
    216                                    Error **errp)
    217 {
    218     ForwardFieldVisitor *ffv = to_ffv(v);
    219 
    220     if (!forward_field_translate_name(ffv, &name, errp)) {
    221         return false;
    222     }
    223     return visit_type_any(ffv->target, name, obj, errp);
    224 }
    225 
    226 static bool forward_field_type_null(Visitor *v, const char *name,
    227                                     QNull **obj, Error **errp)
    228 {
    229     ForwardFieldVisitor *ffv = to_ffv(v);
    230 
    231     if (!forward_field_translate_name(ffv, &name, errp)) {
    232         return false;
    233     }
    234     return visit_type_null(ffv->target, name, obj, errp);
    235 }
    236 
    237 static void forward_field_optional(Visitor *v, const char *name, bool *present)
    238 {
    239     ForwardFieldVisitor *ffv = to_ffv(v);
    240 
    241     if (!forward_field_translate_name(ffv, &name, NULL)) {
    242         *present = false;
    243         return;
    244     }
    245     visit_optional(ffv->target, name, present);
    246 }
    247 
    248 static bool forward_field_policy_reject(Visitor *v, const char *name,
    249                                         unsigned special_features,
    250                                         Error **errp)
    251 {
    252     ForwardFieldVisitor *ffv = to_ffv(v);
    253 
    254     if (!forward_field_translate_name(ffv, &name, errp)) {
    255         return true;
    256     }
    257     return visit_policy_reject(ffv->target, name, special_features, errp);
    258 }
    259 
    260 static bool forward_field_policy_skip(Visitor *v, const char *name,
    261                                       unsigned special_features)
    262 {
    263     ForwardFieldVisitor *ffv = to_ffv(v);
    264 
    265     if (!forward_field_translate_name(ffv, &name, NULL)) {
    266         return true;
    267     }
    268     return visit_policy_skip(ffv->target, name, special_features);
    269 }
    270 
    271 static void forward_field_complete(Visitor *v, void *opaque)
    272 {
    273     /*
    274      * Do nothing, the complete method will be called in due time
    275      * on the target visitor.
    276      */
    277 }
    278 
    279 static void forward_field_free(Visitor *v)
    280 {
    281     ForwardFieldVisitor *ffv = to_ffv(v);
    282 
    283     g_free(ffv->from);
    284     g_free(ffv->to);
    285     g_free(ffv);
    286 }
    287 
    288 Visitor *visitor_forward_field(Visitor *target, const char *from, const char *to)
    289 {
    290     ForwardFieldVisitor *v = g_new0(ForwardFieldVisitor, 1);
    291 
    292     /*
    293      * Clone and dealloc visitors don't use a name for the toplevel
    294      * visit, so they make no sense here.
    295      */
    296     assert(target->type == VISITOR_OUTPUT || target->type == VISITOR_INPUT);
    297 
    298     v->visitor.type = target->type;
    299     v->visitor.start_struct = forward_field_start_struct;
    300     v->visitor.check_struct = forward_field_check_struct;
    301     v->visitor.end_struct = forward_field_end_struct;
    302     v->visitor.start_list = forward_field_start_list;
    303     v->visitor.next_list = forward_field_next_list;
    304     v->visitor.check_list = forward_field_check_list;
    305     v->visitor.end_list = forward_field_end_list;
    306     v->visitor.start_alternate = forward_field_start_alternate;
    307     v->visitor.end_alternate = forward_field_end_alternate;
    308     v->visitor.type_int64 = forward_field_type_int64;
    309     v->visitor.type_uint64 = forward_field_type_uint64;
    310     v->visitor.type_size = forward_field_type_size;
    311     v->visitor.type_bool = forward_field_type_bool;
    312     v->visitor.type_str = forward_field_type_str;
    313     v->visitor.type_number = forward_field_type_number;
    314     v->visitor.type_any = forward_field_type_any;
    315     v->visitor.type_null = forward_field_type_null;
    316     v->visitor.optional = forward_field_optional;
    317     v->visitor.policy_reject = forward_field_policy_reject;
    318     v->visitor.policy_skip = forward_field_policy_skip;
    319     v->visitor.complete = forward_field_complete;
    320     v->visitor.free = forward_field_free;
    321 
    322     v->target = target;
    323     v->from = g_strdup(from);
    324     v->to = g_strdup(to);
    325 
    326     return &v->visitor;
    327 }