Commit 4732dcaf authored by Anthony Liguori's avatar Anthony Liguori
Browse files

Merge remote-tracking branch 'bonzini/qdev-props-for-anthony' into staging

* bonzini/qdev-props-for-anthony:
  qdev: drop unnecessary parse/print methods
  qdev: use built-in QOM string parser
  qdev: accept hex properties only if prefixed by 0x
  qdev: accept both strings and integers for PCI addresses
  qom: add generic string parsing/printing
  qapi: add tests for string-based visitors
  qapi: add string-based visitors
  qapi: drop qmp_input_end_optional
  qapi: allow sharing enum implementation across visitors
parents 017438ee 5cb9b56a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@ QMP/qmp-commands.txt
test-coroutine
test-qmp-input-visitor
test-qmp-output-visitor
test-string-input-visitor
test-string-output-visitor
fsdev/virtfs-proxy-helper.1
fsdev/virtfs-proxy-helper.pod
.gdbinit
+3 −2
Original line number Diff line number Diff line
@@ -412,8 +412,9 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
######################################################################
# qapi

qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
qapi-nested-y += qmp-registry.o qmp-dispatch.o
qapi-nested-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
qapi-nested-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
qapi-nested-y += string-input-visitor.o string-output-visitor.o
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))

common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y)
+39 −147
Original line number Diff line number Diff line
@@ -27,16 +27,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
}

/* Bit */
static int parse_bit(DeviceState *dev, Property *prop, const char *str)
{
    if (!strcasecmp(str, "on"))
        bit_prop_set(dev, prop, true);
    else if (!strcasecmp(str, "off"))
        bit_prop_set(dev, prop, false);
    else
        return -EINVAL;
    return 0;
}

static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
{
@@ -79,7 +69,6 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_bit = {
    .name  = "boolean",
    .legacy_name  = "on/off",
    .parse = parse_bit,
    .print = print_bit,
    .get   = get_bit,
    .set   = set_bit,
@@ -87,26 +76,6 @@ PropertyInfo qdev_prop_bit = {

/* --- 8bit integer --- */

static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
{
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    /* accept both hex and decimal */
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
    }

    return 0;
}

static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu8, *ptr);
}

static void get_int8(Object *obj, Visitor *v, void *opaque,
                     const char *name, Error **errp)
{
@@ -149,8 +118,6 @@ static void set_int8(Object *obj, Visitor *v, void *opaque,

PropertyInfo qdev_prop_uint8 = {
    .name  = "uint8",
    .parse = parse_uint8,
    .print = print_uint8,
    .get   = get_int8,
    .set   = set_int8,
    .min   = 0,
@@ -164,6 +131,10 @@ static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
    uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    if (str[0] != '0' || str[1] != 'x') {
        return -EINVAL;
    }

    *ptr = strtoul(str, &end, 16);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
@@ -191,26 +162,6 @@ PropertyInfo qdev_prop_hex8 = {

/* --- 16bit integer --- */

static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
{
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    /* accept both hex and decimal */
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
    }

    return 0;
}

static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu16, *ptr);
}

static void get_int16(Object *obj, Visitor *v, void *opaque,
                      const char *name, Error **errp)
{
@@ -253,8 +204,6 @@ static void set_int16(Object *obj, Visitor *v, void *opaque,

PropertyInfo qdev_prop_uint16 = {
    .name  = "uint16",
    .parse = parse_uint16,
    .print = print_uint16,
    .get   = get_int16,
    .set   = set_int16,
    .min   = 0,
@@ -263,26 +212,6 @@ PropertyInfo qdev_prop_uint16 = {

/* --- 32bit integer --- */

static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    /* accept both hex and decimal */
    *ptr = strtoul(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
    }

    return 0;
}

static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu32, *ptr);
}

static void get_int32(Object *obj, Visitor *v, void *opaque,
                      const char *name, Error **errp)
{
@@ -325,37 +254,14 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,

PropertyInfo qdev_prop_uint32 = {
    .name  = "uint32",
    .parse = parse_uint32,
    .print = print_uint32,
    .get   = get_int32,
    .set   = set_int32,
    .min   = 0,
    .max   = 0xFFFFFFFFULL,
};

static int parse_int32(DeviceState *dev, Property *prop, const char *str)
{
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    *ptr = strtol(str, &end, 10);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
    }

    return 0;
}

static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    int32_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRId32, *ptr);
}

PropertyInfo qdev_prop_int32 = {
    .name  = "int32",
    .parse = parse_int32,
    .print = print_int32,
    .get   = get_int32,
    .set   = set_int32,
    .min   = -0x80000000LL,
@@ -369,6 +275,10 @@ static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    if (str[0] != '0' || str[1] != 'x') {
        return -EINVAL;
    }

    *ptr = strtoul(str, &end, 16);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
@@ -396,26 +306,6 @@ PropertyInfo qdev_prop_hex32 = {

/* --- 64bit integer --- */

static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    /* accept both hex and decimal */
    *ptr = strtoull(str, &end, 0);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
    }

    return 0;
}

static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
    return snprintf(dest, len, "%" PRIu64, *ptr);
}

static void get_int64(Object *obj, Visitor *v, void *opaque,
                      const char *name, Error **errp)
{
@@ -443,8 +333,6 @@ static void set_int64(Object *obj, Visitor *v, void *opaque,

PropertyInfo qdev_prop_uint64 = {
    .name  = "uint64",
    .parse = parse_uint64,
    .print = print_uint64,
    .get   = get_int64,
    .set   = set_int64,
};
@@ -456,6 +344,10 @@ static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
    uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
    char *end;

    if (str[0] != '0' || str[1] != 'x') {
        return -EINVAL;
    }

    *ptr = strtoull(str, &end, 16);
    if ((*end != '\0') || (end == str)) {
        return -EINVAL;
@@ -737,19 +629,6 @@ PropertyInfo qdev_prop_netdev = {

/* --- vlan --- */

static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
{
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
    int id;

    if (sscanf(str, "%d", &id) != 1)
        return -EINVAL;
    *ptr = qemu_find_vlan(id, 1);
    if (*ptr == NULL)
        return -ENOENT;
    return 0;
}

static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
{
    VLANState **ptr = qdev_get_prop_ptr(dev, prop);
@@ -808,7 +687,6 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,

PropertyInfo qdev_prop_vlan = {
    .name  = "vlan",
    .parse = parse_vlan,
    .print = print_vlan,
    .get   = get_vlan,
    .set   = set_vlan,
@@ -943,25 +821,40 @@ PropertyInfo qdev_prop_losttickpolicy = {
/*
 * bus-local address, i.e. "$slot" or "$slot.$fn"
 */
static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
                          const char *name, Error **errp)
{
    DeviceState *dev = DEVICE(obj);
    Property *prop = opaque;
    uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
    unsigned int slot, fn, n;
    Error *local_err = NULL;
    char *str = (char *)"";

    if (dev->state != DEV_STATE_CREATED) {
        error_set(errp, QERR_PERMISSION_DENIED);
        return;
    }

    visit_type_str(v, &str, name, &local_err);
    if (local_err) {
        return set_int32(obj, v, opaque, name, errp);
    }

    if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
        fn = 0;
        if (sscanf(str, "%x%n", &slot, &n) != 1) {
            return -EINVAL;
            goto invalid;
        }
    }
    if (str[n] != '\0')
        return -EINVAL;
    if (fn > 7)
        return -EINVAL;
    if (slot > 31)
        return -EINVAL;
    if (str[n] != '\0' || fn > 7 || slot > 31) {
        goto invalid;
    }
    *ptr = slot << 3 | fn;
    return 0;
    return;

invalid:
    error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
}

static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
@@ -978,10 +871,9 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t
PropertyInfo qdev_prop_pci_devfn = {
    .name  = "int32",
    .legacy_name  = "pci-devfn",
    .parse = parse_pci_devfn,
    .print = print_pci_devfn,
    .get   = get_int32,
    .set   = set_int32,
    .set   = set_pci_devfn,
    /* FIXME: this should be -1...255, but the address is stored
     * into an uint32_t rather than int32_t.
     */
@@ -1054,9 +946,9 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)

    legacy_name = g_strdup_printf("legacy-%s", name);
    if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
        object_property_set_str(OBJECT(dev), value, legacy_name, &err);
        object_property_parse(OBJECT(dev), value, legacy_name, &err);
    } else {
        object_property_set_str(OBJECT(dev), value, name, &err);
        object_property_parse(OBJECT(dev), value, name, &err);
    }
    g_free(legacy_name);

+24 −0
Original line number Diff line number Diff line
@@ -729,6 +729,30 @@ int64_t object_property_get_int(Object *obj, const char *name,
void object_property_set(Object *obj, struct Visitor *v, const char *name,
                         struct Error **errp);

/**
 * object_property_parse:
 * @obj: the object
 * @string: the string that will be used to parse the property value.
 * @name: the name of the property
 * @errp: returns an error if this function fails
 *
 * Parses a string and writes the result into a property of an object.
 */
void object_property_parse(Object *obj, const char *string,
                           const char *name, struct Error **errp);

/**
 * object_property_print:
 * @obj: the object
 * @name: the name of the property
 * @errp: returns an error if this function fails
 *
 * Returns a string representation of the value of the property.  The
 * caller shall free the string.
 */
char *object_property_print(Object *obj, const char *name,
                            struct Error **errp);

/**
 * object_property_get_type:
 * @obj: the object
+51 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
 */

#include "qapi/qapi-visit-core.h"
#include "qapi/qapi-visit-impl.h"

void visit_start_handle(Visitor *v, void **obj, const char *kind,
                        const char *name, Error **errp)
@@ -116,3 +117,53 @@ void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
        v->type_number(v, obj, name, errp);
    }
}

void output_type_enum(Visitor *v, int *obj, const char *strings[],
                      const char *kind, const char *name,
                      Error **errp)
{
    int i = 0;
    int value = *obj;
    char *enum_str;

    assert(strings);
    while (strings[i++] != NULL);
    if (value < 0 || value >= i - 1) {
        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
        return;
    }

    enum_str = (char *)strings[value];
    visit_type_str(v, &enum_str, name, errp);
}

void input_type_enum(Visitor *v, int *obj, const char *strings[],
                     const char *kind, const char *name,
                     Error **errp)
{
    int64_t value = 0;
    char *enum_str;

    assert(strings);

    visit_type_str(v, &enum_str, name, errp);
    if (error_is_set(errp)) {
        return;
    }

    while (strings[value] != NULL) {
        if (strcmp(strings[value], enum_str) == 0) {
            break;
        }
        value++;
    }

    if (strings[value] == NULL) {
        error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
        g_free(enum_str);
        return;
    }

    g_free(enum_str);
    *obj = value;
}
Loading