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