Annotation of qemu/qapi/qmp-input-visitor.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * Input Visitor
                      3:  *
                      4:  * Copyright IBM, Corp. 2011
                      5:  *
                      6:  * Authors:
                      7:  *  Anthony Liguori   <[email protected]>
                      8:  *
                      9:  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
                     10:  * See the COPYING.LIB file in the top-level directory.
                     11:  *
                     12:  */
                     13: 
                     14: #include "qmp-input-visitor.h"
1.1.1.3 ! root       15: #include "qapi/qapi-visit-impl.h"
1.1       root       16: #include "qemu-queue.h"
                     17: #include "qemu-common.h"
                     18: #include "qemu-objects.h"
                     19: #include "qerror.h"
                     20: 
                     21: #define QIV_STACK_SIZE 1024
                     22: 
                     23: typedef struct StackObject
                     24: {
1.1.1.3 ! root       25:     QObject *obj;
        !            26:     const QListEntry *entry;
        !            27:     GHashTable *h;
1.1       root       28: } StackObject;
                     29: 
                     30: struct QmpInputVisitor
                     31: {
                     32:     Visitor visitor;
                     33:     StackObject stack[QIV_STACK_SIZE];
                     34:     int nb_stack;
1.1.1.3 ! root       35:     bool strict;
1.1       root       36: };
                     37: 
                     38: static QmpInputVisitor *to_qiv(Visitor *v)
                     39: {
                     40:     return container_of(v, QmpInputVisitor, visitor);
                     41: }
                     42: 
1.1.1.3 ! root       43: static QObject *qmp_input_get_object(QmpInputVisitor *qiv,
        !            44:                                      const char *name)
1.1       root       45: {
1.1.1.3 ! root       46:     QObject *qobj = qiv->stack[qiv->nb_stack - 1].obj;
1.1       root       47: 
1.1.1.3 ! root       48:     if (qobj) {
        !            49:         if (name && qobject_type(qobj) == QTYPE_QDICT) {
        !            50:             if (qiv->stack[qiv->nb_stack - 1].h) {
        !            51:                 g_hash_table_remove(qiv->stack[qiv->nb_stack - 1].h, name);
        !            52:             }
        !            53:             return qdict_get(qobject_to_qdict(qobj), name);
        !            54:         } else if (qiv->stack[qiv->nb_stack - 1].entry) {
        !            55:             return qlist_entry_obj(qiv->stack[qiv->nb_stack - 1].entry);
        !            56:         }
1.1       root       57:     }
                     58: 
                     59:     return qobj;
                     60: }
                     61: 
1.1.1.3 ! root       62: static void qdict_add_key(const char *key, QObject *obj, void *opaque)
1.1       root       63: {
1.1.1.3 ! root       64:     GHashTable *h = opaque;
        !            65:     g_hash_table_insert(h, (gpointer) key, NULL);
        !            66: }
        !            67: 
        !            68: static void qmp_input_push(QmpInputVisitor *qiv, QObject *obj, Error **errp)
        !            69: {
        !            70:     GHashTable *h;
1.1       root       71: 
                     72:     if (qiv->nb_stack >= QIV_STACK_SIZE) {
                     73:         error_set(errp, QERR_BUFFER_OVERRUN);
                     74:         return;
                     75:     }
1.1.1.3 ! root       76: 
        !            77:     qiv->stack[qiv->nb_stack].obj = obj;
        !            78:     qiv->stack[qiv->nb_stack].entry = NULL;
        !            79:     qiv->stack[qiv->nb_stack].h = NULL;
        !            80: 
        !            81:     if (qiv->strict && qobject_type(obj) == QTYPE_QDICT) {
        !            82:         h = g_hash_table_new(g_str_hash, g_str_equal);
        !            83:         qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
        !            84:         qiv->stack[qiv->nb_stack].h = h;
        !            85:     }
        !            86: 
        !            87:     qiv->nb_stack++;
        !            88: }
        !            89: 
        !            90: /** Only for qmp_input_pop. */
        !            91: static gboolean always_true(gpointer key, gpointer val, gpointer user_pkey)
        !            92: {
        !            93:     *(const char **)user_pkey = (const char *)key;
        !            94:     return TRUE;
1.1       root       95: }
                     96: 
                     97: static void qmp_input_pop(QmpInputVisitor *qiv, Error **errp)
                     98: {
1.1.1.3 ! root       99:     assert(qiv->nb_stack > 0);
        !           100: 
        !           101:     if (qiv->strict) {
        !           102:         GHashTable * const top_ht = qiv->stack[qiv->nb_stack - 1].h;
        !           103:         if (top_ht) {
        !           104:             if (g_hash_table_size(top_ht)) {
        !           105:                 const char *key;
        !           106:                 g_hash_table_find(top_ht, always_true, &key);
        !           107:                 error_set(errp, QERR_QMP_EXTRA_MEMBER, key);
        !           108:             }
        !           109:             g_hash_table_unref(top_ht);
        !           110:         }
1.1       root      111:     }
1.1.1.3 ! root      112: 
        !           113:     qiv->nb_stack--;
1.1       root      114: }
                    115: 
                    116: static void qmp_input_start_struct(Visitor *v, void **obj, const char *kind,
                    117:                                    const char *name, size_t size, Error **errp)
                    118: {
                    119:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      120:     QObject *qobj = qmp_input_get_object(qiv, name);
        !           121:     Error *err = NULL;
1.1       root      122: 
                    123:     if (!qobj || qobject_type(qobj) != QTYPE_QDICT) {
                    124:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    125:                   "QDict");
                    126:         return;
                    127:     }
                    128: 
1.1.1.3 ! root      129:     qmp_input_push(qiv, qobj, &err);
        !           130:     if (err) {
        !           131:         error_propagate(errp, err);
1.1       root      132:         return;
                    133:     }
                    134: 
                    135:     if (obj) {
1.1.1.2   root      136:         *obj = g_malloc0(size);
1.1       root      137:     }
                    138: }
                    139: 
                    140: static void qmp_input_end_struct(Visitor *v, Error **errp)
                    141: {
                    142:     QmpInputVisitor *qiv = to_qiv(v);
                    143: 
                    144:     qmp_input_pop(qiv, errp);
                    145: }
                    146: 
                    147: static void qmp_input_start_list(Visitor *v, const char *name, Error **errp)
                    148: {
                    149:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      150:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      151: 
                    152:     if (!qobj || qobject_type(qobj) != QTYPE_QLIST) {
                    153:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    154:                   "list");
                    155:         return;
                    156:     }
                    157: 
                    158:     qmp_input_push(qiv, qobj, errp);
                    159: }
                    160: 
                    161: static GenericList *qmp_input_next_list(Visitor *v, GenericList **list,
                    162:                                         Error **errp)
                    163: {
                    164:     QmpInputVisitor *qiv = to_qiv(v);
                    165:     GenericList *entry;
                    166:     StackObject *so = &qiv->stack[qiv->nb_stack - 1];
1.1.1.3 ! root      167:     bool first;
        !           168: 
        !           169:     if (so->entry == NULL) {
        !           170:         so->entry = qlist_first(qobject_to_qlist(so->obj));
        !           171:         first = true;
        !           172:     } else {
        !           173:         so->entry = qlist_next(so->entry);
        !           174:         first = false;
        !           175:     }
1.1       root      176: 
                    177:     if (so->entry == NULL) {
                    178:         return NULL;
                    179:     }
                    180: 
1.1.1.2   root      181:     entry = g_malloc0(sizeof(*entry));
1.1.1.3 ! root      182:     if (first) {
        !           183:         *list = entry;
        !           184:     } else {
1.1       root      185:         (*list)->next = entry;
                    186:     }
                    187: 
                    188:     return entry;
                    189: }
                    190: 
                    191: static void qmp_input_end_list(Visitor *v, Error **errp)
                    192: {
                    193:     QmpInputVisitor *qiv = to_qiv(v);
                    194: 
                    195:     qmp_input_pop(qiv, errp);
                    196: }
                    197: 
                    198: static void qmp_input_type_int(Visitor *v, int64_t *obj, const char *name,
                    199:                                Error **errp)
                    200: {
                    201:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      202:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      203: 
                    204:     if (!qobj || qobject_type(qobj) != QTYPE_QINT) {
                    205:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    206:                   "integer");
                    207:         return;
                    208:     }
                    209: 
                    210:     *obj = qint_get_int(qobject_to_qint(qobj));
                    211: }
                    212: 
                    213: static void qmp_input_type_bool(Visitor *v, bool *obj, const char *name,
                    214:                                 Error **errp)
                    215: {
                    216:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      217:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      218: 
                    219:     if (!qobj || qobject_type(qobj) != QTYPE_QBOOL) {
                    220:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    221:                   "boolean");
                    222:         return;
                    223:     }
                    224: 
                    225:     *obj = qbool_get_int(qobject_to_qbool(qobj));
                    226: }
                    227: 
                    228: static void qmp_input_type_str(Visitor *v, char **obj, const char *name,
                    229:                                Error **errp)
                    230: {
                    231:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      232:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      233: 
                    234:     if (!qobj || qobject_type(qobj) != QTYPE_QSTRING) {
                    235:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
                    236:                   "string");
                    237:         return;
                    238:     }
                    239: 
1.1.1.2   root      240:     *obj = g_strdup(qstring_get_str(qobject_to_qstring(qobj)));
1.1       root      241: }
                    242: 
                    243: static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
                    244:                                   Error **errp)
                    245: {
                    246:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      247:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      248: 
1.1.1.3 ! root      249:     if (!qobj || (qobject_type(qobj) != QTYPE_QFLOAT &&
        !           250:         qobject_type(qobj) != QTYPE_QINT)) {
1.1       root      251:         error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
1.1.1.3 ! root      252:                   "number");
1.1       root      253:         return;
                    254:     }
                    255: 
1.1.1.3 ! root      256:     if (qobject_type(qobj) == QTYPE_QINT) {
        !           257:         *obj = qint_get_int(qobject_to_qint(qobj));
        !           258:     } else {
        !           259:         *obj = qfloat_get_double(qobject_to_qfloat(qobj));
1.1       root      260:     }
                    261: }
                    262: 
                    263: static void qmp_input_start_optional(Visitor *v, bool *present,
                    264:                                      const char *name, Error **errp)
                    265: {
                    266:     QmpInputVisitor *qiv = to_qiv(v);
1.1.1.3 ! root      267:     QObject *qobj = qmp_input_get_object(qiv, name);
1.1       root      268: 
                    269:     if (!qobj) {
                    270:         *present = false;
                    271:         return;
                    272:     }
                    273: 
                    274:     *present = true;
                    275: }
                    276: 
                    277: Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
                    278: {
                    279:     return &v->visitor;
                    280: }
                    281: 
                    282: void qmp_input_visitor_cleanup(QmpInputVisitor *v)
                    283: {
1.1.1.3 ! root      284:     qobject_decref(v->stack[0].obj);
1.1.1.2   root      285:     g_free(v);
1.1       root      286: }
                    287: 
                    288: QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
                    289: {
                    290:     QmpInputVisitor *v;
                    291: 
1.1.1.2   root      292:     v = g_malloc0(sizeof(*v));
1.1       root      293: 
                    294:     v->visitor.start_struct = qmp_input_start_struct;
                    295:     v->visitor.end_struct = qmp_input_end_struct;
                    296:     v->visitor.start_list = qmp_input_start_list;
                    297:     v->visitor.next_list = qmp_input_next_list;
                    298:     v->visitor.end_list = qmp_input_end_list;
1.1.1.3 ! root      299:     v->visitor.type_enum = input_type_enum;
1.1       root      300:     v->visitor.type_int = qmp_input_type_int;
                    301:     v->visitor.type_bool = qmp_input_type_bool;
                    302:     v->visitor.type_str = qmp_input_type_str;
                    303:     v->visitor.type_number = qmp_input_type_number;
                    304:     v->visitor.start_optional = qmp_input_start_optional;
                    305: 
1.1.1.3 ! root      306:     qmp_input_push(v, obj, NULL);
        !           307:     qobject_incref(obj);
        !           308: 
        !           309:     return v;
        !           310: }
        !           311: 
        !           312: QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj)
        !           313: {
        !           314:     QmpInputVisitor *v;
        !           315: 
        !           316:     v = qmp_input_visitor_new(obj);
        !           317:     v->strict = true;
1.1       root      318: 
                    319:     return v;
                    320: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.