qobject-input-visitor.c 18.6 KB
Newer Older
M
Michael Roth 已提交
1 2 3
/*
 * Input Visitor
 *
4
 * Copyright (C) 2012-2017 Red Hat, Inc.
M
Michael Roth 已提交
5 6 7 8 9 10 11 12 13 14
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 * See the COPYING.LIB file in the top-level directory.
 *
 */

P
Peter Maydell 已提交
15
#include "qemu/osdep.h"
16
#include "qapi/error.h"
17
#include "qapi/qobject-input-visitor.h"
18
#include "qapi/visitor-impl.h"
19
#include "qemu/queue.h"
M
Michael Roth 已提交
20
#include "qemu-common.h"
21 22
#include "qapi/qmp/types.h"
#include "qapi/qmp/qerror.h"
23
#include "qemu/cutils.h"
M
Michael Roth 已提交
24

25 26 27
typedef struct StackObject {
    const char *name;            /* Name of @obj in its parent, if any */
    QObject *obj;                /* QDict or QList being visited */
E
Eric Blake 已提交
28
    void *qapi; /* sanity check that caller uses same pointer */
E
Eric Blake 已提交
29

30 31 32
    GHashTable *h;              /* If @obj is QDict: unvisited keys */
    const QListEntry *entry;    /* If @obj is QList: unvisited tail */
    unsigned index;             /* If @obj is QList: list index of @entry */
33

34
    QSLIST_ENTRY(StackObject) node; /* parent */
M
Michael Roth 已提交
35 36
} StackObject;

37
struct QObjectInputVisitor {
M
Michael Roth 已提交
38
    Visitor visitor;
E
Eric Blake 已提交
39

40 41 42 43 44
    /* Root of visit at visitor creation. */
    QObject *root;

    /* Stack of objects being visited (all entries will be either
     * QDict or QList). */
45
    QSLIST_HEAD(, StackObject) stack;
E
Eric Blake 已提交
46

47
    GString *errname;           /* Accumulator for full_name() */
M
Michael Roth 已提交
48 49
};

50
static QObjectInputVisitor *to_qiv(Visitor *v)
M
Michael Roth 已提交
51
{
52
    return container_of(v, QObjectInputVisitor, visitor);
M
Michael Roth 已提交
53 54
}

55 56
static const char *full_name_nth(QObjectInputVisitor *qiv, const char *name,
                                 int n)
57 58 59 60 61 62 63 64 65 66 67
{
    StackObject *so;
    char buf[32];

    if (qiv->errname) {
        g_string_truncate(qiv->errname, 0);
    } else {
        qiv->errname = g_string_new("");
    }

    QSLIST_FOREACH(so , &qiv->stack, node) {
68 69 70 71
        if (n) {
            n--;
        } else if (qobject_type(so->obj) == QTYPE_QDICT) {
            g_string_prepend(qiv->errname, name ?: "<anonymous>");
72 73 74 75 76 77 78
            g_string_prepend_c(qiv->errname, '.');
        } else {
            snprintf(buf, sizeof(buf), "[%u]", so->index);
            g_string_prepend(qiv->errname, buf);
        }
        name = so->name;
    }
79
    assert(!n);
80 81 82 83 84

    if (name) {
        g_string_prepend(qiv->errname, name);
    } else if (qiv->errname->str[0] == '.') {
        g_string_erase(qiv->errname, 0, 1);
85
    } else if (!qiv->errname->str[0]) {
86 87 88 89 90 91
        return "<anonymous>";
    }

    return qiv->errname->str;
}

92 93 94 95 96
static const char *full_name(QObjectInputVisitor *qiv, const char *name)
{
    return full_name_nth(qiv, name, 0);
}

97 98 99
static QObject *qobject_input_try_get_object(QObjectInputVisitor *qiv,
                                             const char *name,
                                             bool consume)
M
Michael Roth 已提交
100
{
101 102
    StackObject *tos;
    QObject *qobj;
103
    QObject *ret;
E
Eric Blake 已提交
104

105
    if (QSLIST_EMPTY(&qiv->stack)) {
106
        /* Starting at root, name is ignored. */
107
        assert(qiv->root);
108 109 110 111
        return qiv->root;
    }

    /* We are in a container; find the next element. */
112
    tos = QSLIST_FIRST(&qiv->stack);
113
    qobj = tos->obj;
E
Eric Blake 已提交
114 115
    assert(qobj);

116 117
    if (qobject_type(qobj) == QTYPE_QDICT) {
        assert(name);
118 119 120 121
        ret = qdict_get(qobject_to_qdict(qobj), name);
        if (tos->h && consume && ret) {
            bool removed = g_hash_table_remove(tos->h, name);
            assert(removed);
122
        }
123
    } else {
E
Eric Blake 已提交
124
        assert(qobject_type(qobj) == QTYPE_QLIST);
125
        assert(!name);
126 127 128 129 130 131 132 133
        if (tos->entry) {
            ret = qlist_entry_obj(tos->entry);
            if (consume) {
                tos->entry = qlist_next(tos->entry);
            }
        } else {
            ret = NULL;
        }
134
        if (consume) {
135
            tos->index++;
136
        }
M
Michael Roth 已提交
137 138
    }

139
    return ret;
M
Michael Roth 已提交
140 141
}

142 143 144 145 146 147 148 149 150 151 152 153
static QObject *qobject_input_get_object(QObjectInputVisitor *qiv,
                                         const char *name,
                                         bool consume, Error **errp)
{
    QObject *obj = qobject_input_try_get_object(qiv, name, consume);

    if (!obj) {
        error_setg(errp, QERR_MISSING_PARAMETER, full_name(qiv, name));
    }
    return obj;
}

154 155 156 157 158 159
static void qdict_add_key(const char *key, QObject *obj, void *opaque)
{
    GHashTable *h = opaque;
    g_hash_table_insert(h, (gpointer) key, NULL);
}

160
static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
161
                                            const char *name,
162
                                            QObject *obj, void *qapi)
M
Michael Roth 已提交
163
{
164
    GHashTable *h;
165
    StackObject *tos = g_new0(StackObject, 1);
M
Michael Roth 已提交
166

E
Eric Blake 已提交
167
    assert(obj);
168
    tos->name = name;
E
Eric Blake 已提交
169
    tos->obj = obj;
E
Eric Blake 已提交
170
    tos->qapi = qapi;
171

172
    if (qobject_type(obj) == QTYPE_QDICT) {
173 174
        h = g_hash_table_new(g_str_hash, g_str_equal);
        qdict_iter(qobject_to_qdict(obj), qdict_add_key, h);
E
Eric Blake 已提交
175
        tos->h = h;
176 177
    } else {
        assert(qobject_type(obj) == QTYPE_QLIST);
178
        tos->entry = qlist_first(qobject_to_qlist(obj));
179
        tos->index = -1;
180 181
    }

182
    QSLIST_INSERT_HEAD(&qiv->stack, tos, node);
183
    return tos->entry;
M
Michael Roth 已提交
184 185
}

186

187
static void qobject_input_check_struct(Visitor *v, Error **errp)
M
Michael Roth 已提交
188
{
189
    QObjectInputVisitor *qiv = to_qiv(v);
190
    StackObject *tos = QSLIST_FIRST(&qiv->stack);
191 192
    GHashTableIter iter;
    const char *key;
193

194
    assert(tos && !tos->entry);
195 196 197 198 199

    g_hash_table_iter_init(&iter, tos->h);
    if (g_hash_table_iter_next(&iter, (void **)&key, NULL)) {
        error_setg(errp, "Parameter '%s' is unexpected",
                   full_name(qiv, key));
200 201 202
    }
}

203
static void qobject_input_stack_object_free(StackObject *tos)
204
{
205 206 207
    if (tos->h) {
        g_hash_table_unref(tos->h);
    }
208

209 210
    g_free(tos);
}
211

212
static void qobject_input_pop(Visitor *v, void **obj)
213
{
214
    QObjectInputVisitor *qiv = to_qiv(v);
215
    StackObject *tos = QSLIST_FIRST(&qiv->stack);
216

217 218
    assert(tos && tos->qapi == obj);
    QSLIST_REMOVE_HEAD(&qiv->stack, node);
219
    qobject_input_stack_object_free(tos);
M
Michael Roth 已提交
220 221
}

222 223
static void qobject_input_start_struct(Visitor *v, const char *name, void **obj,
                                       size_t size, Error **errp)
M
Michael Roth 已提交
224
{
225 226
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
M
Michael Roth 已提交
227

228 229 230
    if (obj) {
        *obj = NULL;
    }
231 232 233 234
    if (!qobj) {
        return;
    }
    if (qobject_type(qobj) != QTYPE_QDICT) {
235 236
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "object");
M
Michael Roth 已提交
237 238 239
        return;
    }

240
    qobject_input_push(qiv, name, qobj, obj);
M
Michael Roth 已提交
241 242

    if (obj) {
243
        *obj = g_malloc0(size);
M
Michael Roth 已提交
244 245 246 247
    }
}


248 249 250
static void qobject_input_start_list(Visitor *v, const char *name,
                                     GenericList **list, size_t size,
                                     Error **errp)
M
Michael Roth 已提交
251
{
252 253
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
254
    const QListEntry *entry;
M
Michael Roth 已提交
255

256 257 258
    if (list) {
        *list = NULL;
    }
259 260 261 262
    if (!qobj) {
        return;
    }
    if (qobject_type(qobj) != QTYPE_QLIST) {
263 264
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "array");
M
Michael Roth 已提交
265 266 267
        return;
    }

268
    entry = qobject_input_push(qiv, name, qobj, list);
269 270
    if (entry && list) {
        *list = g_malloc0(size);
271
    }
M
Michael Roth 已提交
272 273
}

274 275
static GenericList *qobject_input_next_list(Visitor *v, GenericList *tail,
                                            size_t size)
M
Michael Roth 已提交
276
{
277
    QObjectInputVisitor *qiv = to_qiv(v);
278 279 280
    StackObject *tos = QSLIST_FIRST(&qiv->stack);

    assert(tos && tos->obj && qobject_type(tos->obj) == QTYPE_QLIST);
M
Michael Roth 已提交
281

282
    if (!tos->entry) {
M
Michael Roth 已提交
283 284
        return NULL;
    }
285 286
    tail->next = g_malloc0(size);
    return tail->next;
M
Michael Roth 已提交
287 288
}

289 290 291 292 293 294 295 296 297 298 299 300 301
static void qobject_input_check_list(Visitor *v, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    StackObject *tos = QSLIST_FIRST(&qiv->stack);

    assert(tos && tos->obj && qobject_type(tos->obj) == QTYPE_QLIST);

    if (tos->entry) {
        error_setg(errp, "Only %u list elements expected in %s",
                   tos->index + 1, full_name_nth(qiv, NULL, 1));
    }
}

M
Michael Roth 已提交
302

303 304 305
static void qobject_input_start_alternate(Visitor *v, const char *name,
                                          GenericAlternate **obj, size_t size,
                                          bool promote_int, Error **errp)
K
Kevin Wolf 已提交
306
{
307 308
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, false, errp);
K
Kevin Wolf 已提交
309 310

    if (!qobj) {
311
        *obj = NULL;
K
Kevin Wolf 已提交
312 313
        return;
    }
314 315 316 317
    *obj = g_malloc0(size);
    (*obj)->type = qobject_type(qobj);
    if (promote_int && (*obj)->type == QTYPE_QINT) {
        (*obj)->type = QTYPE_QFLOAT;
318
    }
K
Kevin Wolf 已提交
319 320
}

321 322
static void qobject_input_type_int64(Visitor *v, const char *name, int64_t *obj,
                                     Error **errp)
M
Michael Roth 已提交
323
{
324 325
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
326
    QInt *qint;
M
Michael Roth 已提交
327

328 329 330 331
    if (!qobj) {
        return;
    }
    qint = qobject_to_qint(qobj);
332
    if (!qint) {
333 334
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "integer");
M
Michael Roth 已提交
335 336 337
        return;
    }

338
    *obj = qint_get_int(qint);
M
Michael Roth 已提交
339 340
}

341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365

static void qobject_input_type_int64_keyval(Visitor *v, const char *name,
                                            int64_t *obj, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    QString *qstr;

    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
    if (!qstr) {
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
        return;
    }

    if (qemu_strtoi64(qstring_get_str(qstr), NULL, 0, obj) < 0) {
        /* TODO report -ERANGE more nicely */
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                   full_name(qiv, name), "integer");
    }
}

366 367
static void qobject_input_type_uint64(Visitor *v, const char *name,
                                      uint64_t *obj, Error **errp)
368 369
{
    /* FIXME: qobject_to_qint mishandles values over INT64_MAX */
370 371
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
372
    QInt *qint;
373

374 375 376 377
    if (!qobj) {
        return;
    }
    qint = qobject_to_qint(qobj);
378
    if (!qint) {
379 380
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "integer");
381 382 383 384 385 386
        return;
    }

    *obj = qint_get_int(qint);
}

387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
static void qobject_input_type_uint64_keyval(Visitor *v, const char *name,
                                             uint64_t *obj, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    QString *qstr;

    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
    if (!qstr) {
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
        return;
    }

    if (qemu_strtou64(qstring_get_str(qstr), NULL, 0, obj) < 0) {
        /* TODO report -ERANGE more nicely */
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                   full_name(qiv, name), "integer");
    }
}

411 412
static void qobject_input_type_bool(Visitor *v, const char *name, bool *obj,
                                    Error **errp)
M
Michael Roth 已提交
413
{
414 415
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
416
    QBool *qbool;
M
Michael Roth 已提交
417

418 419 420 421
    if (!qobj) {
        return;
    }
    qbool = qobject_to_qbool(qobj);
422
    if (!qbool) {
423 424
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "boolean");
M
Michael Roth 已提交
425 426 427
        return;
    }

428
    *obj = qbool_get_bool(qbool);
M
Michael Roth 已提交
429 430
}

431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
static void qobject_input_type_bool_keyval(Visitor *v, const char *name,
                                           bool *obj, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    QString *qstr;
    const char *str;

    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
    if (!qstr) {
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
        return;
    }

    str = qstring_get_str(qstr);
    if (!strcmp(str, "on")) {
        *obj = true;
    } else if (!strcmp(str, "off")) {
        *obj = false;
    } else {
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                   full_name(qiv, name), "'on' or 'off'");
    }
}

460 461
static void qobject_input_type_str(Visitor *v, const char *name, char **obj,
                                   Error **errp)
M
Michael Roth 已提交
462
{
463 464
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
465
    QString *qstr;
M
Michael Roth 已提交
466

467 468 469 470 471
    *obj = NULL;
    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
472
    if (!qstr) {
473 474
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
M
Michael Roth 已提交
475 476 477
        return;
    }

478
    *obj = g_strdup(qstring_get_str(qstr));
M
Michael Roth 已提交
479 480
}

481 482
static void qobject_input_type_number(Visitor *v, const char *name, double *obj,
                                      Error **errp)
M
Michael Roth 已提交
483
{
484 485
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
486 487
    QInt *qint;
    QFloat *qfloat;
M
Michael Roth 已提交
488

489 490 491
    if (!qobj) {
        return;
    }
492 493 494
    qint = qobject_to_qint(qobj);
    if (qint) {
        *obj = qint_get_int(qobject_to_qint(qobj));
M
Michael Roth 已提交
495 496 497
        return;
    }

498 499
    qfloat = qobject_to_qfloat(qobj);
    if (qfloat) {
500
        *obj = qfloat_get_double(qobject_to_qfloat(qobj));
501
        return;
502
    }
503

504 505
    error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
               full_name(qiv, name), "number");
M
Michael Roth 已提交
506 507
}

508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
static void qobject_input_type_number_keyval(Visitor *v, const char *name,
                                             double *obj, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    QString *qstr;
    const char *str;
    char *endp;

    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
    if (!qstr) {
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
        return;
    }

    str = qstring_get_str(qstr);
    errno = 0;
    *obj = strtod(str, &endp);
    if (errno || endp == str || *endp) {
        /* TODO report -ERANGE more nicely */
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "number");
    }
}

537 538
static void qobject_input_type_any(Visitor *v, const char *name, QObject **obj,
                                   Error **errp)
539
{
540 541
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
542

543
    *obj = NULL;
544 545 546 547
    if (!qobj) {
        return;
    }

548 549 550 551
    qobject_incref(qobj);
    *obj = qobj;
}

552
static void qobject_input_type_null(Visitor *v, const char *name, Error **errp)
E
Eric Blake 已提交
553
{
554 555
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
556

557 558 559 560
    if (!qobj) {
        return;
    }

561
    if (qobject_type(qobj) != QTYPE_QNULL) {
562 563
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "null");
564
    }
E
Eric Blake 已提交
565 566
}

567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590
static void qobject_input_type_size_keyval(Visitor *v, const char *name,
                                           uint64_t *obj, Error **errp)
{
    QObjectInputVisitor *qiv = to_qiv(v);
    QObject *qobj = qobject_input_get_object(qiv, name, true, errp);
    QString *qstr;

    if (!qobj) {
        return;
    }
    qstr = qobject_to_qstring(qobj);
    if (!qstr) {
        error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
                   full_name(qiv, name), "string");
        return;
    }

    if (qemu_strtosz(qstring_get_str(qstr), NULL, obj) < 0) {
        /* TODO report -ERANGE more nicely */
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
                   full_name(qiv, name), "size");
    }
}

591
static void qobject_input_optional(Visitor *v, const char *name, bool *present)
M
Michael Roth 已提交
592
{
593
    QObjectInputVisitor *qiv = to_qiv(v);
594
    QObject *qobj = qobject_input_try_get_object(qiv, name, false);
M
Michael Roth 已提交
595 596 597 598 599 600 601 602 603

    if (!qobj) {
        *present = false;
        return;
    }

    *present = true;
}

604
static void qobject_input_free(Visitor *v)
E
Eric Blake 已提交
605
{
606
    QObjectInputVisitor *qiv = to_qiv(v);
607

608 609 610 611
    while (!QSLIST_EMPTY(&qiv->stack)) {
        StackObject *tos = QSLIST_FIRST(&qiv->stack);

        QSLIST_REMOVE_HEAD(&qiv->stack, node);
612
        qobject_input_stack_object_free(tos);
613
    }
E
Eric Blake 已提交
614

615
    qobject_decref(qiv->root);
616 617 618
    if (qiv->errname) {
        g_string_free(qiv->errname, TRUE);
    }
619
    g_free(qiv);
E
Eric Blake 已提交
620 621
}

622
Visitor *qobject_input_visitor_new(QObject *obj)
M
Michael Roth 已提交
623
{
624
    QObjectInputVisitor *v;
M
Michael Roth 已提交
625

626
    assert(obj);
627
    v = g_malloc0(sizeof(*v));
M
Michael Roth 已提交
628

629
    v->visitor.type = VISITOR_INPUT;
630 631 632 633 634
    v->visitor.start_struct = qobject_input_start_struct;
    v->visitor.check_struct = qobject_input_check_struct;
    v->visitor.end_struct = qobject_input_pop;
    v->visitor.start_list = qobject_input_start_list;
    v->visitor.next_list = qobject_input_next_list;
635
    v->visitor.check_list = qobject_input_check_list;
636 637 638 639 640 641 642 643 644 645 646
    v->visitor.end_list = qobject_input_pop;
    v->visitor.start_alternate = qobject_input_start_alternate;
    v->visitor.type_int64 = qobject_input_type_int64;
    v->visitor.type_uint64 = qobject_input_type_uint64;
    v->visitor.type_bool = qobject_input_type_bool;
    v->visitor.type_str = qobject_input_type_str;
    v->visitor.type_number = qobject_input_type_number;
    v->visitor.type_any = qobject_input_type_any;
    v->visitor.type_null = qobject_input_type_null;
    v->visitor.optional = qobject_input_optional;
    v->visitor.free = qobject_input_free;
M
Michael Roth 已提交
647

648
    v->root = obj;
649
    qobject_incref(obj);
M
Michael Roth 已提交
650

651
    return &v->visitor;
M
Michael Roth 已提交
652
}
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684

Visitor *qobject_input_visitor_new_keyval(QObject *obj)
{
    QObjectInputVisitor *v;

    v = g_malloc0(sizeof(*v));

    v->visitor.type = VISITOR_INPUT;
    v->visitor.start_struct = qobject_input_start_struct;
    v->visitor.check_struct = qobject_input_check_struct;
    v->visitor.end_struct = qobject_input_pop;
    v->visitor.start_list = qobject_input_start_list;
    v->visitor.next_list = qobject_input_next_list;
    v->visitor.check_list = qobject_input_check_list;
    v->visitor.end_list = qobject_input_pop;
    v->visitor.start_alternate = qobject_input_start_alternate;
    v->visitor.type_int64 = qobject_input_type_int64_keyval;
    v->visitor.type_uint64 = qobject_input_type_uint64_keyval;
    v->visitor.type_bool = qobject_input_type_bool_keyval;
    v->visitor.type_str = qobject_input_type_str;
    v->visitor.type_number = qobject_input_type_number_keyval;
    v->visitor.type_any = qobject_input_type_any;
    v->visitor.type_null = qobject_input_type_null;
    v->visitor.type_size = qobject_input_type_size_keyval;
    v->visitor.optional = qobject_input_optional;
    v->visitor.free = qobject_input_free;

    v->root = obj;
    qobject_incref(obj);

    return &v->visitor;
}