> Signed-off-by: Marc-AndrĂ© Lureau <[email protected]>
> Signed-off-by: Markus Armbruster <[email protected]>
> Message-ID: <[email protected]>
> ---
>  include/qom/object.h | 74 ++++++++++++++++++++++++++++++++++++
>  qom/object.c         | 89 +++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 158 insertions(+), 5 deletions(-)
>
> diff --git a/include/qom/object.h b/include/qom/object.h
> index 365d819d35a3..ce9375f37af9 100644
> --- a/include/qom/object.h
> +++ b/include/qom/object.h
> @@ -2006,6 +2006,80 @@ ObjectProperty 
> *object_class_property_add_enum(ObjectClass *klass,
>                                      int (*get)(Object *, Error **),
>                                      void (*set)(Object *, int, Error **));
>  
> +/**
> + * struct QapiEnumProp: Descriptor for a property backed by a QAPI enum type
> + *
> + * Binds a QOM object property to a QAPI enum, providing automatic
> + * string<->int conversion through QAPI visitors and optional
> + * default-value initialization during object instance init.
> + *
> + * Use the QAPI_ENUM_PROP() macro to construct instances inline.
> + *
> + * @name: property name exposed on the QOM object
> + * @description: human-readable description (shown in ``-device help``, etc.)
> + * @default_value: initial enum value applied via @set during instance init,
> + *                 or -1 (the QAPI_ENUM_PROP default) to skip initialization
> + * @qapi_type: pointer to the generated QAPITypeInfo for the enum
> + *             (provides the string<->int lookup table)
> + * @get: getter that returns the current enum value as int, or -1 on error
> + * @set: setter that receives the enum value as int; %NULL for read-only 
> props
> + */
> +typedef struct QapiEnumProp {
> +    const char *name;
> +    const char *description;
> +    const int default_value;
> +    const QAPITypeInfo *qapi_type;
> +    int (*get)(Object *, Error **);
> +    void (*set)(Object *, int, Error **);
> +} QapiEnumProp;
> +
> +#define QAPI_ENUM_PROP(...) ({                                           \
> +    static const QapiEnumProp _prop = {                                  \
> +        .default_value = -1, __VA_ARGS__                                 \
> +    };                                                                   \
> +    &_prop; })
> +
> +/**
> + * object_property_add_qapi_enum:
> + * @obj: the object to add a property to
> + * @prop: property descriptor
> + *
> + * Add an enum property with QAPI type association.
> + *
> + * Returns: The newly added property on success, or %NULL on failure.
> + */
> +ObjectProperty *
> +object_property_add_qapi_enum(Object *obj, const QapiEnumProp *prop);
> +
> +/**
> + * object_class_property_add_qapi_enum:
> + * @klass: the class object to add a property to
> + * @prop: property descriptor
> + *
> + * Add an enum property with QAPI type association.
> + *
> + * Use the QAPI_ENUM_PROP() macro to construct the property descriptor
> + * inline. If .default_value is not set, the property is not initialized
> + * (default_value is -1). Otherwise, the setter is called with
> + * default_value during object instance init.
> + *
> + * Example::
> + *
> + *   object_class_property_add_qapi_enum(oc, QAPI_ENUM_PROP(
> + *       .name = "policy",
> + *       .description = "Set the NUMA policy",
> + *       .default_value = HOST_MEM_POLICY_DEFAULT,
> + *       .qapi_type = &HostMemPolicy_type_info,
> + *       .get = my_get_policy,
> + *       .set = my_set_policy,
> + *   ));
> + *
> + * Returns: The newly added property on success, or %NULL on failure.
> + */
> +ObjectProperty *
> +object_class_property_add_qapi_enum(ObjectClass *klass,
> +                                    const QapiEnumProp *prop);
> +
>  /**
>   * object_property_add_qapi:
>   * @obj: the object to add a property to
> diff --git a/qom/object.c b/qom/object.c
> index bebbfc43556d..c1aa2b96fcc2 100644
> --- a/qom/object.c
> +++ b/qom/object.c
> @@ -1219,7 +1219,7 @@ static void object_class_foreach_tramp(gpointer key, 
> gpointer value,
>          return;
>      }
>  
> -    if (data->implements_type && 
> +    if (data->implements_type &&
>          !object_class_dynamic_cast(k, data->implements_type)) {
>          return;
>      }
> @@ -1786,7 +1786,6 @@ int object_property_get_enum(Object *obj, const char 
> *name,
>      char *str;
>      int ret;
>      ObjectProperty *prop = object_property_find_err(obj, name, errp);
> -    EnumProperty *enumprop;
>  
>      if (prop == NULL) {
>          return -1;
> @@ -1799,14 +1798,17 @@ int object_property_get_enum(Object *obj, const char 
> *name,
>          return -1;
>      }
>  
> -    enumprop = prop->opaque;
> -
>      str = object_property_get_str(obj, name, errp);
>      if (!str) {
>          return -1;
>      }
>  
> -    ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
> +    if (prop->qapi_type) {
> +        ret = qapi_enum_parse(prop->qapi_type->lookup, str, -1, errp);
> +    } else {
> +        EnumProperty *enumprop = prop->opaque;
> +        ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
> +    }
>      g_free(str);
>  
>      return ret;
> @@ -2609,6 +2611,83 @@ object_class_property_add_enum(ObjectClass *klass, 
> const char *name,
>                                       prop);
>  }
>  
> +static void get_qapi_enum(Object *obj, Visitor *v, const char *name,
> +                          void *opaque, Error **errp)
> +{
> +    const QapiEnumProp *prop = opaque;
> +    int value;
> +    Error *err = NULL;
> +
> +    value = prop->get(obj, &err);

It could assert (value != -1 || err)

-- 
Marc-AndrĂ© Lureau <[email protected]>


Reply via email to