qemu

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

qobject-input-visitor.c (21552B)


      1 /*
      2  * Input Visitor
      3  *
      4  * Copyright (C) 2012-2017 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 <math.h>
     17 #include "qapi/compat-policy.h"
     18 #include "qapi/error.h"
     19 #include "qapi/qobject-input-visitor.h"
     20 #include "qapi/visitor-impl.h"
     21 #include "qemu/queue.h"
     22 #include "qapi/qmp/qjson.h"
     23 #include "qapi/qmp/qbool.h"
     24 #include "qapi/qmp/qdict.h"
     25 #include "qapi/qmp/qerror.h"
     26 #include "qapi/qmp/qlist.h"
     27 #include "qapi/qmp/qnull.h"
     28 #include "qapi/qmp/qnum.h"
     29 #include "qapi/qmp/qstring.h"
     30 #include "qemu/cutils.h"
     31 #include "qemu/keyval.h"
     32 
     33 typedef struct StackObject {
     34     const char *name;            /* Name of @obj in its parent, if any */
     35     QObject *obj;                /* QDict or QList being visited */
     36     void *qapi; /* sanity check that caller uses same pointer */
     37 
     38     GHashTable *h;              /* If @obj is QDict: unvisited keys */
     39     const QListEntry *entry;    /* If @obj is QList: unvisited tail */
     40     unsigned index;             /* If @obj is QList: list index of @entry */
     41 
     42     QSLIST_ENTRY(StackObject) node; /* parent */
     43 } StackObject;
     44 
     45 struct QObjectInputVisitor {
     46     Visitor visitor;
     47 
     48     /* Root of visit at visitor creation. */
     49     QObject *root;
     50     bool keyval;                /* Assume @root made with keyval_parse() */
     51 
     52     /* Stack of objects being visited (all entries will be either
     53      * QDict or QList). */
     54     QSLIST_HEAD(, StackObject) stack;
     55 
     56     GString *errname;           /* Accumulator for full_name() */
     57 };
     58 
     59 static QObjectInputVisitor *to_qiv(Visitor *v)
     60 {
     61     return container_of(v, QObjectInputVisitor, visitor);
     62 }
     63 
     64 /*
     65  * Find the full name of something @qiv is currently visiting.
     66  * @qiv is visiting something named @name in the stack of containers
     67  * @qiv->stack.
     68  * If @n is zero, return its full name.
     69  * If @n is positive, return the full name of the @n-th container
     70  * counting from the top.  The stack of containers must have at least
     71  * @n elements.
     72  * The returned string is valid until the next full_name_nth(@v) or
     73  * destruction of @v.
     74  */
     75 static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name,
     76                                  int n)
     77 {
     78     StackObject *so;
     79     char buf[32];
     80 
     81     if (qiv->errname) {
     82         g_string_truncate(qiv->errname, 0);
     83     } else {
     84         qiv->errname = g_string_new("");
     85     }
     86 
     87     QSLIST_FOREACH(so , &qiv->stack, node) {
     88         if (n) {
     89             n--;
     90         } else if (qobject_type(so->obj) == QTYPE_QDICT) {
     91             g_string_prepend(qiv->errname, name ?: "<anonymous>");
     92             g_string_prepend_c(qiv->errname, '.');
     93         } else {
     94             snprintf(buf, sizeof(buf),
     95                      qiv->keyval ? ".%u" : "[%u]",
     96                      so->index);
     97             g_string_prepend(qiv->errname, buf);
     98         }
     99         name = so->name;
    100     }
    101     assert(!n);
    102 
    103     if (name) {
    104         g_string_prepend(qiv->errname, name);
    105     } else if (qiv->errname->str[0] == '.') {
    106         g_string_erase(qiv->errname, 0, 1);
    107     } else if (!qiv->errname->str[0]) {
    108         return "<anonymous>";
    109     }
    110 
    111     return qiv->errname->str;
    112 }
    113 
    114 static const char *full_name(QObjectInputVisitor *qiv, const char *name)
    115 {
    116     return full_name_nth(qiv, name, 0);
    117 }
    118 
    119 static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
    120                                              const char *name,
    121                                              bool consume)
    122 {
    123     StackObject *tos;
    124     QObject *qobj;
    125     QObject *ret;
    126 
    127     if (QSLIST_EMPTY(&qiv->stack)) {
    128         /* Starting at root, name is ignored. */
    129         assert(qiv->root);
    130         return qiv->root;
    131     }
    132 
    133     /* We are in a container; find the next element. */
    134     tos = QSLIST_FIRST(&qiv->stack);
    135     qobj = tos->obj;
    136     assert(qobj);
    137 
    138     if (qobject_type(qobj) == QTYPE_QDICT) {
    139         assert(name);
    140         ret = qdict_get(qobject_to(QDict, qobj), name);
    141         if (tos->h && consume && ret) {
    142             bool removed = g_hash_table_remove(tos->h, name);
    143             assert(removed);
    144         }
    145     } else {
    146         assert(qobject_type(qobj) == QTYPE_QLIST);
    147         assert(!name);
    148         if (tos->entry) {
    149             ret = qlist_entry_obj(tos->entry);
    150             if (consume) {
    151                 tos->entry = qlist_next(tos->entry);
    152             }
    153         } else {
    154             ret = NULL;
    155         }
    156         if (consume) {
    157             tos->index++;
    158         }
    159     }
    160 
    161     return ret;
    162 }
    163 
    164 static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
    165                                          const char *name,
    166                                          bool consume, Error **errp)
    167 {
    168     QObject *obj = qobject_input_try_get_object(qiv, name, consume);
    169 
    170     if (!obj) {
    171         error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name));
    172     }
    173     return obj;
    174 }
    175 
    176 static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
    177                                             const char *name,
    178                                             Error **errp)
    179 {
    180     QObject *qobj;
    181     QString *qstr;
    182 
    183     qobj = qobject_input_get_object(qiv, name, true, errp);
    184     if (!qobj) {
    185         return NULL;
    186     }
    187 
    188     qstr = qobject_to(QString, qobj);
    189     if (!qstr) {
    190         switch (qobject_type(qobj)) {
    191         case QTYPE_QDICT:
    192         case QTYPE_QLIST:
    193             error_setg(errp, "Parameters '%s.*' are unexpected",
    194                        full_name(qiv, name));
    195             return NULL;
    196         default:
    197             /* Non-string scalar (should this be an assertion?) */
    198             error_setg(errp, "Internal error: parameter %s invalid",
    199                        full_name(qiv, name));
    200             return NULL;
    201         }
    202     }
    203 
    204     return qstring_get_str(qstr);
    205 }
    206 
    207 static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
    208                                             const char *name,
    209                                             QObject *obj, void *qapi)
    210 {
    211     GHashTable *h;
    212     StackObject *tos = g_new0(StackObject, 1);
    213     QDict *qdict = qobject_to(QDict, obj);
    214     QList *qlist = qobject_to(QList, obj);
    215     const QDictEntry *entry;
    216 
    217     assert(obj);
    218     tos->name = name;
    219     tos->obj = obj;
    220     tos->qapi = qapi;
    221 
    222     if (qdict) {
    223         h = g_hash_table_new(g_str_hash, g_str_equal);
    224         for (entry = qdict_first(qdict);
    225              entry;
    226              entry = qdict_next(qdict, entry)) {
    227             g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL);
    228         }
    229         tos->h = h;
    230     } else {
    231         assert(qlist);
    232         tos->entry = qlist_first(qlist);
    233         tos->index = -1;
    234     }
    235 
    236     QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
    237     return tos->entry;
    238 }
    239 
    240 
    241 static bool qobject_input_check_struct(Visitor *v, Error **errp)
    242 {
    243     QObjectInputVisitor *qiv = to_qiv(v);
    244     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    245     GHashTableIter iter;
    246     const char *key;
    247 
    248     assert(tos && !tos->entry);
    249 
    250     g_hash_table_iter_init(&iter, tos->h);
    251     if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
    252         error_setg(errp, "Parameter '%s' is unexpected",
    253                    full_name(qiv, key));
    254         return false;
    255     }
    256     return true;
    257 }
    258 
    259 static void qobject_input_stack_object_free(StackObject *tos)
    260 {
    261     if (tos->h) {
    262         g_hash_table_unref(tos->h);
    263     }
    264 
    265     g_free(tos);
    266 }
    267 
    268 static void qobject_input_pop(Visitor *v, void **obj)
    269 {
    270     QObjectInputVisitor *qiv = to_qiv(v);
    271     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    272 
    273     assert(tos && tos->qapi == obj);
    274     QSLIST_REMOVE_HEAD(&qiv->stack, node);
    275     qobject_input_stack_object_free(tos);
    276 }
    277 
    278 static bool qobject_input_start_struct(Visitor *v, const char *name, void **obj,
    279                                        size_t size, Error **errp)
    280 {
    281     QObjectInputVisitor *qiv = to_qiv(v);
    282     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    283 
    284     if (obj) {
    285         *obj = NULL;
    286     }
    287     if (!qobj) {
    288         return false;
    289     }
    290     if (qobject_type(qobj) != QTYPE_QDICT) {
    291         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    292                    full_name(qiv, name), "object");
    293         return false;
    294     }
    295 
    296     qobject_input_push(qiv, name, qobj, obj);
    297 
    298     if (obj) {
    299         *obj = g_malloc0(size);
    300     }
    301     return true;
    302 }
    303 
    304 static void qobject_input_end_struct(Visitor *v, void **obj)
    305 {
    306     QObjectInputVisitor *qiv = to_qiv(v);
    307     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    308 
    309     assert(qobject_type(tos->obj) == QTYPE_QDICT && tos->h);
    310     qobject_input_pop(v, obj);
    311 }
    312 
    313 
    314 static bool qobject_input_start_list(Visitor *v, const char *name,
    315                                      GenericList **list, size_t size,
    316                                      Error **errp)
    317 {
    318     QObjectInputVisitor *qiv = to_qiv(v);
    319     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    320     const QListEntry *entry;
    321 
    322     if (list) {
    323         *list = NULL;
    324     }
    325     if (!qobj) {
    326         return false;
    327     }
    328     if (qobject_type(qobj) != QTYPE_QLIST) {
    329         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    330                    full_name(qiv, name), "array");
    331         return false;
    332     }
    333 
    334     entry = qobject_input_push(qiv, name, qobj, list);
    335     if (entry && list) {
    336         *list = g_malloc0(size);
    337     }
    338     return true;
    339 }
    340 
    341 static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
    342                                             size_t size)
    343 {
    344     QObjectInputVisitor *qiv = to_qiv(v);
    345     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    346 
    347     assert(tos && qobject_to(QList, tos->obj));
    348 
    349     if (!tos->entry) {
    350         return NULL;
    351     }
    352     tail->next = g_malloc0(size);
    353     return tail->next;
    354 }
    355 
    356 static bool qobject_input_check_list(Visitor *v, Error **errp)
    357 {
    358     QObjectInputVisitor *qiv = to_qiv(v);
    359     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    360 
    361     assert(tos && qobject_to(QList, tos->obj));
    362 
    363     if (tos->entry) {
    364         error_setg(errp, "Only %u list elements expected in %s",
    365                    tos->index + 1, full_name_nth(qiv, NULL, 1));
    366         return false;
    367     }
    368     return true;
    369 }
    370 
    371 static void qobject_input_end_list(Visitor *v, void **obj)
    372 {
    373     QObjectInputVisitor *qiv = to_qiv(v);
    374     StackObject *tos = QSLIST_FIRST(&qiv->stack);
    375 
    376     assert(qobject_type(tos->obj) == QTYPE_QLIST && !tos->h);
    377     qobject_input_pop(v, obj);
    378 }
    379 
    380 static bool qobject_input_start_alternate(Visitor *v, const char *name,
    381                                           GenericAlternate **obj, size_t size,
    382                                           Error **errp)
    383 {
    384     QObjectInputVisitor *qiv = to_qiv(v);
    385     QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
    386 
    387     if (!qobj) {
    388         *obj = NULL;
    389         return false;
    390     }
    391     *obj = g_malloc0(size);
    392     (*obj)->type = qobject_type(qobj);
    393     return true;
    394 }
    395 
    396 static bool qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
    397                                      Error **errp)
    398 {
    399     QObjectInputVisitor *qiv = to_qiv(v);
    400     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    401     QNum *qnum;
    402 
    403     if (!qobj) {
    404         return false;
    405     }
    406     qnum = qobject_to(QNum, qobj);
    407     if (!qnum || !qnum_get_try_int(qnum, obj)) {
    408         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    409                    full_name(qiv, name), "integer");
    410         return false;
    411     }
    412     return true;
    413 }
    414 
    415 static bool qobject_input_type_int64_keyval(Visitor *v, const char *name,
    416                                             int64_t *obj, Error **errp)
    417 {
    418     QObjectInputVisitor *qiv = to_qiv(v);
    419     const char *str = qobject_input_get_keyval(qiv, name, errp);
    420 
    421     if (!str) {
    422         return false;
    423     }
    424 
    425     if (qemu_strtoi64(str, NULL, 0, obj) < 0) {
    426         /* TODO report -ERANGE more nicely */
    427         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
    428                    full_name(qiv, name), "integer");
    429         return false;
    430     }
    431     return true;
    432 }
    433 
    434 static bool qobject_input_type_uint64(Visitor *v, const char *name,
    435                                       uint64_t *obj, Error **errp)
    436 {
    437     QObjectInputVisitor *qiv = to_qiv(v);
    438     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    439     QNum *qnum;
    440     int64_t val;
    441 
    442     if (!qobj) {
    443         return false;
    444     }
    445     qnum = qobject_to(QNum, qobj);
    446     if (!qnum) {
    447         goto err;
    448     }
    449 
    450     if (qnum_get_try_uint(qnum, obj)) {
    451         return true;
    452     }
    453 
    454     /* Need to accept negative values for backward compatibility */
    455     if (qnum_get_try_int(qnum, &val)) {
    456         *obj = val;
    457         return true;
    458     }
    459 
    460 err:
    461     error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
    462                full_name(qiv, name), "uint64");
    463     return false;
    464 }
    465 
    466 static bool qobject_input_type_uint64_keyval(Visitor *v, const char *name,
    467                                              uint64_t *obj, Error **errp)
    468 {
    469     QObjectInputVisitor *qiv = to_qiv(v);
    470     const char *str = qobject_input_get_keyval(qiv, name, errp);
    471 
    472     if (!str) {
    473         return false;
    474     }
    475 
    476     if (qemu_strtou64(str, NULL, 0, obj) < 0) {
    477         /* TODO report -ERANGE more nicely */
    478         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
    479                    full_name(qiv, name), "integer");
    480         return false;
    481     }
    482     return true;
    483 }
    484 
    485 static bool qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
    486                                     Error **errp)
    487 {
    488     QObjectInputVisitor *qiv = to_qiv(v);
    489     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    490     QBool *qbool;
    491 
    492     if (!qobj) {
    493         return false;
    494     }
    495     qbool = qobject_to(QBool, qobj);
    496     if (!qbool) {
    497         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    498                    full_name(qiv, name), "boolean");
    499         return false;
    500     }
    501 
    502     *obj = qbool_get_bool(qbool);
    503     return true;
    504 }
    505 
    506 static bool qobject_input_type_bool_keyval(Visitor *v, const char *name,
    507                                            bool *obj, Error **errp)
    508 {
    509     QObjectInputVisitor *qiv = to_qiv(v);
    510     const char *str = qobject_input_get_keyval(qiv, name, errp);
    511 
    512     if (!str) {
    513         return false;
    514     }
    515 
    516     if (!qapi_bool_parse(name, str, obj, NULL)) {
    517         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
    518                    full_name(qiv, name), "'on' or 'off'");
    519         return false;
    520     }
    521     return true;
    522 }
    523 
    524 static bool qobject_input_type_str(Visitor *v, const char *name, char **obj,
    525                                    Error **errp)
    526 {
    527     QObjectInputVisitor *qiv = to_qiv(v);
    528     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    529     QString *qstr;
    530 
    531     *obj = NULL;
    532     if (!qobj) {
    533         return false;
    534     }
    535     qstr = qobject_to(QString, qobj);
    536     if (!qstr) {
    537         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    538                    full_name(qiv, name), "string");
    539         return false;
    540     }
    541 
    542     *obj = g_strdup(qstring_get_str(qstr));
    543     return true;
    544 }
    545 
    546 static bool qobject_input_type_str_keyval(Visitor *v, const char *name,
    547                                           char **obj, Error **errp)
    548 {
    549     QObjectInputVisitor *qiv = to_qiv(v);
    550     const char *str = qobject_input_get_keyval(qiv, name, errp);
    551 
    552     *obj = g_strdup(str);
    553     return !!str;
    554 }
    555 
    556 static bool qobject_input_type_number(Visitor *v, const char *name, double *obj,
    557                                       Error **errp)
    558 {
    559     QObjectInputVisitor *qiv = to_qiv(v);
    560     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    561     QNum *qnum;
    562 
    563     if (!qobj) {
    564         return false;
    565     }
    566     qnum = qobject_to(QNum, qobj);
    567     if (!qnum) {
    568         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    569                    full_name(qiv, name), "number");
    570         return false;
    571     }
    572 
    573     *obj = qnum_get_double(qnum);
    574     return true;
    575 }
    576 
    577 static bool qobject_input_type_number_keyval(Visitor *v, const char *name,
    578                                              double *obj, Error **errp)
    579 {
    580     QObjectInputVisitor *qiv = to_qiv(v);
    581     const char *str = qobject_input_get_keyval(qiv, name, errp);
    582     double val;
    583 
    584     if (!str) {
    585         return false;
    586     }
    587 
    588     if (qemu_strtod_finite(str, NULL, &val)) {
    589         /* TODO report -ERANGE more nicely */
    590         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    591                    full_name(qiv, name), "number");
    592         return false;
    593     }
    594 
    595     *obj = val;
    596     return true;
    597 }
    598 
    599 static bool qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
    600                                    Error **errp)
    601 {
    602     QObjectInputVisitor *qiv = to_qiv(v);
    603     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    604 
    605     *obj = NULL;
    606     if (!qobj) {
    607         return false;
    608     }
    609 
    610     *obj = qobject_ref(qobj);
    611     return true;
    612 }
    613 
    614 static bool qobject_input_type_null(Visitor *v, const char *name,
    615                                     QNull **obj, Error **errp)
    616 {
    617     QObjectInputVisitor *qiv = to_qiv(v);
    618     QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    619 
    620     *obj = NULL;
    621     if (!qobj) {
    622         return false;
    623     }
    624 
    625     if (qobject_type(qobj) != QTYPE_QNULL) {
    626         error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
    627                    full_name(qiv, name), "null");
    628         return false;
    629     }
    630     *obj = qnull();
    631     return true;
    632 }
    633 
    634 static bool qobject_input_type_size_keyval(Visitor *v, const char *name,
    635                                            uint64_t *obj, Error **errp)
    636 {
    637     QObjectInputVisitor *qiv = to_qiv(v);
    638     const char *str = qobject_input_get_keyval(qiv, name, errp);
    639 
    640     if (!str) {
    641         return false;
    642     }
    643 
    644     if (qemu_strtosz(str, NULL, obj) < 0) {
    645         /* TODO report -ERANGE more nicely */
    646         error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
    647                    full_name(qiv, name), "size");
    648         return false;
    649     }
    650     return true;
    651 }
    652 
    653 static void qobject_input_optional(Visitor *v, const char *name, bool *present)
    654 {
    655     QObjectInputVisitor *qiv = to_qiv(v);
    656     QObject *qobj = qobject_input_try_get_object(qiv, name, false);
    657 
    658     if (!qobj) {
    659         *present = false;
    660         return;
    661     }
    662 
    663     *present = true;
    664 }
    665 
    666 static bool qobject_input_policy_reject(Visitor *v, const char *name,
    667                                         unsigned special_features,
    668                                         Error **errp)
    669 {
    670     return !compat_policy_input_ok(special_features, &v->compat_policy,
    671                                    ERROR_CLASS_GENERIC_ERROR,
    672                                    "parameter", name, errp);
    673 }
    674 
    675 static void qobject_input_free(Visitor *v)
    676 {
    677     QObjectInputVisitor *qiv = to_qiv(v);
    678 
    679     while (!QSLIST_EMPTY(&qiv->stack)) {
    680         StackObject *tos = QSLIST_FIRST(&qiv->stack);
    681 
    682         QSLIST_REMOVE_HEAD(&qiv->stack, node);
    683         qobject_input_stack_object_free(tos);
    684     }
    685 
    686     qobject_unref(qiv->root);
    687     if (qiv->errname) {
    688         g_string_free(qiv->errname, TRUE);
    689     }
    690     g_free(qiv);
    691 }
    692 
    693 static QObjectInputVisitor *qobject_input_visitor_base_new(QObject *obj)
    694 {
    695     QObjectInputVisitor *v = g_malloc0(sizeof(*v));
    696 
    697     assert(obj);
    698 
    699     v->visitor.type = VISITOR_INPUT;
    700     v->visitor.start_struct = qobject_input_start_struct;
    701     v->visitor.check_struct = qobject_input_check_struct;
    702     v->visitor.end_struct = qobject_input_end_struct;
    703     v->visitor.start_list = qobject_input_start_list;
    704     v->visitor.next_list = qobject_input_next_list;
    705     v->visitor.check_list = qobject_input_check_list;
    706     v->visitor.end_list = qobject_input_end_list;
    707     v->visitor.start_alternate = qobject_input_start_alternate;
    708     v->visitor.optional = qobject_input_optional;
    709     v->visitor.policy_reject = qobject_input_policy_reject;
    710     v->visitor.free = qobject_input_free;
    711 
    712     v->root = qobject_ref(obj);
    713 
    714     return v;
    715 }
    716 
    717 Visitor *qobject_input_visitor_new(QObject *obj)
    718 {
    719     QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
    720 
    721     v->visitor.type_int64 = qobject_input_type_int64;
    722     v->visitor.type_uint64 = qobject_input_type_uint64;
    723     v->visitor.type_bool = qobject_input_type_bool;
    724     v->visitor.type_str = qobject_input_type_str;
    725     v->visitor.type_number = qobject_input_type_number;
    726     v->visitor.type_any = qobject_input_type_any;
    727     v->visitor.type_null = qobject_input_type_null;
    728 
    729     return &v->visitor;
    730 }
    731 
    732 Visitor *qobject_input_visitor_new_keyval(QObject *obj)
    733 {
    734     QObjectInputVisitor *v = qobject_input_visitor_base_new(obj);
    735 
    736     v->visitor.type_int64 = qobject_input_type_int64_keyval;
    737     v->visitor.type_uint64 = qobject_input_type_uint64_keyval;
    738     v->visitor.type_bool = qobject_input_type_bool_keyval;
    739     v->visitor.type_str = qobject_input_type_str_keyval;
    740     v->visitor.type_number = qobject_input_type_number_keyval;
    741     v->visitor.type_any = qobject_input_type_any;
    742     v->visitor.type_null = qobject_input_type_null;
    743     v->visitor.type_size = qobject_input_type_size_keyval;
    744     v->keyval = true;
    745 
    746     return &v->visitor;
    747 }
    748 
    749 Visitor *qobject_input_visitor_new_str(const char *str,
    750                                        const char *implied_key,
    751                                        Error **errp)
    752 {
    753     bool is_json = str[0] == '{';
    754     QObject *obj;
    755     QDict *args;
    756     Visitor *v;
    757 
    758     if (is_json) {
    759         obj = qobject_from_json(str, errp);
    760         if (!obj) {
    761             return NULL;
    762         }
    763         args = qobject_to(QDict, obj);
    764         assert(args);
    765         v = qobject_input_visitor_new(QOBJECT(args));
    766     } else {
    767         args = keyval_parse(str, implied_key, NULL, errp);
    768         if (!args) {
    769             return NULL;
    770         }
    771         v = qobject_input_visitor_new_keyval(QOBJECT(args));
    772     }
    773     qobject_unref(args);
    774 
    775     return v;
    776 }