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