merge: branch 'ih/direct_enum'

nm-setting: implement direct_enum as GObject property of type int

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/merge_requests/1861
This commit is contained in:
Íñigo Huguet 2024-02-20 14:50:17 +00:00
commit cc1b970e08
12 changed files with 301 additions and 115 deletions

View file

@ -1966,4 +1966,5 @@ global:
nm_setting_hsr_get_type;
nm_setting_hsr_new;
nm_setting_ip_config_get_dhcp_dscp;
nm_setting_get_enum_property_type;
} libnm_1_44_0;

View file

@ -769,7 +769,7 @@
/>
<property name="autoconnect-ports"
dbus-type="i"
gprop-type="NMTernary"
gprop-type="gint"
/>
<property name="autoconnect-priority"
dbus-type="i"

View file

@ -2655,7 +2655,7 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
* when this connection is activated.
* ---end---
*/
prop_idx = _nm_setting_property_define_direct_enum(
prop_idx = _nm_setting_property_define_direct_real_enum(
properties_override,
obj_properties,
NM_SETTING_CONNECTION_AUTOCONNECT_SLAVES,
@ -2776,16 +2776,16 @@ nm_setting_connection_class_init(NMSettingConnectionClass *klass)
* example: CONNECTION_METERED=yes
* ---end---
*/
_nm_setting_property_define_direct_enum(properties_override,
obj_properties,
NM_SETTING_CONNECTION_METERED,
PROP_METERED,
NM_TYPE_METERED,
NM_METERED_UNKNOWN,
NM_SETTING_PARAM_REAPPLY_IMMEDIATELY,
NULL,
NMSettingConnectionPrivate,
metered);
_nm_setting_property_define_direct_real_enum(properties_override,
obj_properties,
NM_SETTING_CONNECTION_METERED,
PROP_METERED,
NM_TYPE_METERED,
NM_METERED_UNKNOWN,
NM_SETTING_PARAM_REAPPLY_IMMEDIATELY,
NULL,
NMSettingConnectionPrivate,
metered);
/**
* NMSettingConnection:lldp:

View file

@ -6139,14 +6139,16 @@ _nm_sett_info_property_override_create_array_ip_config(int addr_family)
obj_properties[PROP_AUTO_ROUTE_EXT_GW],
&nm_sett_info_propert_type_direct_enum,
.direct_offset =
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw));
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, auto_route_ext_gw),
.direct_data.enum_gtype = NM_TYPE_TERNARY);
_nm_properties_override_gobj(
properties_override,
obj_properties[PROP_REPLACE_LOCAL_RULE],
&nm_sett_info_propert_type_direct_enum,
.direct_offset =
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule));
NM_STRUCT_OFFSET_ENSURE_TYPE(int, NMSettingIPConfigPrivate, replace_local_rule),
.direct_data.enum_gtype = NM_TYPE_TERNARY);
_nm_properties_override_gobj(
properties_override,

View file

@ -941,16 +941,16 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass)
* example: IPV6_PRIVACY=rfc3041 IPV6_PRIVACY_PREFER_PUBLIC_IP=yes
* ---end---
*/
_nm_setting_property_define_direct_enum(properties_override,
obj_properties,
NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
PROP_IP6_PRIVACY,
NM_TYPE_SETTING_IP6_CONFIG_PRIVACY,
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
NM_SETTING_PARAM_NONE,
NULL,
NMSettingIP6ConfigPrivate,
ip6_privacy);
_nm_setting_property_define_direct_real_enum(properties_override,
obj_properties,
NM_SETTING_IP6_CONFIG_IP6_PRIVACY,
PROP_IP6_PRIVACY,
NM_TYPE_SETTING_IP6_CONFIG_PRIVACY,
NM_SETTING_IP6_CONFIG_PRIVACY_UNKNOWN,
NM_SETTING_PARAM_NONE,
NULL,
NMSettingIP6ConfigPrivate,
ip6_privacy);
/**
* NMSettingIP6Config:addr-gen-mode:
@ -1215,7 +1215,7 @@ nm_setting_ip6_config_class_init(NMSettingIP6ConfigClass *klass)
NM_SETTING_PARAM_NONE,
NMSettingIP6ConfigPrivate,
dhcp_pd_hint,
.direct_set_fcn.set_string =
.direct_data.set_string =
_set_string_fcn_dhcp_pd_hint,
.direct_string_allow_empty = TRUE);

View file

@ -904,6 +904,13 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
/*****************************************************************************/
/* Define a direct property of type enum, but using `int` as type in the underlying
* GObject property. This is the preferred way to define enum properties because using
* real enums it is not possible to maintain backwards compatibility with clients
* using an old libnm (glib asserts against new values of the enum not being valid).
* The main difference from define_direct_real_enum is that this will accept any
* integer value, and we'll check that it's valid in #NMSetting::verify, as doing
* 'verify' is optional for clients. */
#define _nm_setting_property_define_direct_enum(properties_override, \
obj_properties, \
prop_name, \
@ -924,6 +931,58 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \
| NM_SETTING_PARAM_INFERRABLE))); \
\
nm_assert(G_TYPE_IS_ENUM(gtype_enum)); \
\
_param_spec = g_param_spec_int("" prop_name "", \
"", \
"", \
G_MININT32, \
G_MAXINT32, \
(default_value), \
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY \
| G_PARAM_STATIC_STRINGS | (param_flags)); \
\
(obj_properties)[(prop_id)] = _param_spec; \
_property_type = (property_type) ?: &nm_sett_info_propert_type_direct_enum; \
\
_nm_properties_override_gobj( \
(properties_override), \
_param_spec, \
_property_type, \
.direct_offset = \
NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field), \
.direct_data.enum_gtype = (gtype_enum), \
__VA_ARGS__); \
})
/*****************************************************************************/
/* Define an enum property using real enums in the GObject, not integers. Note that
* this is not backwards compatible because clients with old libnm will reject
* newer values of the enum. Generally you want to use define_direct_enum and use this
* one only for properties that already existed as real enums */
#define _nm_setting_property_define_direct_real_enum(properties_override, \
obj_properties, \
prop_name, \
prop_id, \
gtype_enum, \
default_value, \
param_flags, \
property_type, \
private_struct_type, \
private_struct_field, \
... /* extra NMSettInfoProperty fields */) \
({ \
GParamSpec *_param_spec; \
const NMSettInfoPropertType *_property_type; \
\
G_STATIC_ASSERT( \
!NM_FLAGS_ANY((param_flags), \
~(NM_SETTING_PARAM_REAPPLY_IMMEDIATELY | NM_SETTING_PARAM_FUZZY_IGNORE \
| NM_SETTING_PARAM_INFERRABLE))); \
\
nm_assert(G_TYPE_IS_ENUM(gtype_enum)); \
\
_param_spec = g_param_spec_enum("" prop_name "", \
"", \
"", \
@ -941,11 +1000,26 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
_property_type, \
.direct_offset = \
NM_STRUCT_OFFSET_ENSURE_TYPE(int, private_struct_type, private_struct_field), \
.direct_data.enum_gtype = (gtype_enum), \
__VA_ARGS__); \
})
/*****************************************************************************/
#define _nm_setting_property_is_valid_direct_enum(property_info) \
({ \
const NMSettInfoProperty *_property_info = (property_info); \
NMValueType direct_nmtype = _property_info->property_type->direct_type; \
GType direct_gtype = _property_info->direct_data.enum_gtype; \
GParamSpec *spec = _property_info->param_spec; \
GType spec_gtype = spec ? spec->value_type : G_TYPE_INVALID; \
\
direct_nmtype == NM_VALUE_TYPE_ENUM &&direct_gtype &&G_TYPE_IS_ENUM(direct_gtype) \
&& NM_IN_SET(spec_gtype, G_TYPE_INT, direct_gtype); \
})
/*****************************************************************************/
#define _nm_setting_property_define_direct_ternary_enum(properties_override, \
obj_properties, \
prop_name, \
@ -954,17 +1028,17 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
private_struct_type, \
private_struct_field, \
...) \
_nm_setting_property_define_direct_enum((properties_override), \
(obj_properties), \
prop_name, \
(prop_id), \
NM_TYPE_TERNARY, \
NM_TERNARY_DEFAULT, \
(param_flags), \
NULL, \
private_struct_type, \
private_struct_field, \
__VA_ARGS__)
_nm_setting_property_define_direct_real_enum((properties_override), \
(obj_properties), \
prop_name, \
(prop_id), \
NM_TYPE_TERNARY, \
NM_TERNARY_DEFAULT, \
(param_flags), \
NULL, \
private_struct_type, \
private_struct_field, \
__VA_ARGS__)
/*****************************************************************************/

View file

@ -2361,8 +2361,7 @@ nm_setting_wireguard_class_init(NMSettingWireGuardClass *klass)
NM_SETTING_PARAM_SECRET,
NMSettingWireGuard,
_priv.private_key,
.direct_set_fcn.set_string =
_set_string_fcn_public_key,
.direct_data.set_string = _set_string_fcn_public_key,
.direct_string_allow_empty = TRUE);
/**

View file

@ -684,10 +684,10 @@ _property_direct_set_string(const NMSettInfoSetting *sett_info,
+ (!!property_info->direct_string_is_refstr)
+ (property_info->direct_set_string_mac_address_len > 0)
+ (property_info->direct_set_string_ip_address_addr_family != 0))
<= (property_info->direct_set_fcn.set_string ? 0 : 1));
<= (property_info->direct_data.set_string ? 0 : 1));
if (property_info->direct_set_fcn.set_string) {
return property_info->direct_set_fcn.set_string(sett_info, property_info, setting, src);
if (property_info->direct_data.set_string) {
return property_info->direct_data.set_string(sett_info, property_info, setting, src);
}
dst = _nm_setting_get_private_field(setting, sett_info, property_info);
@ -826,7 +826,13 @@ _nm_setting_property_get_property_direct(GObject *object,
{
const int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
g_value_set_enum(value, *p_val);
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
if (G_TYPE_IS_ENUM(pspec->value_type))
g_value_set_enum(value, *p_val);
else
g_value_set_int(value, *p_val);
return;
}
case NM_VALUE_TYPE_FLAGS:
@ -961,7 +967,13 @@ _nm_setting_property_set_property_direct(GObject *object,
int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
int v;
v = g_value_get_enum(value);
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
if (G_TYPE_IS_ENUM(pspec->value_type))
v = g_value_get_enum(value);
else
v = g_value_get_int(value);
if (*p_val == v)
return;
*p_val = v;
@ -1097,7 +1109,13 @@ _init_direct(NMSetting *setting)
int *p_val = _nm_setting_get_private_field(setting, sett_info, property_info);
int def_val;
def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
if (G_TYPE_IS_ENUM(property_info->param_spec->value_type))
def_val = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
else
def_val = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec);
nm_assert(NM_IN_SET(*p_val, 0, property_info->direct_is_aliased_field ? def_val : 0));
*p_val = def_val;
break;
@ -1255,10 +1273,22 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_
{
int val;
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
val = *((int *) _nm_setting_get_private_field(setting, sett_info, property_info));
if (!property_info->to_dbus_including_default
&& val == NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec))
return NULL;
if (!property_info->to_dbus_including_default) {
int default_value;
if (G_TYPE_IS_ENUM(property_info->param_spec->value_type))
default_value = NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(property_info->param_spec);
else
default_value = NM_G_PARAM_SPEC_GET_DEFAULT_INT(property_info->param_spec);
if (val == default_value)
return NULL;
}
return nm_g_variant_maybe_singleton_i(val);
}
case NM_VALUE_TYPE_FLAGS:
@ -1434,7 +1464,10 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
GVariant *_value = (value); \
gboolean _success = FALSE; \
\
nm_assert(_property_info->param_spec->value_type == _gtype); \
nm_assert(_property_info->param_spec->value_type == _gtype \
|| (_property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM \
&& _property_info->direct_data.enum_gtype == _gtype)); \
\
if (_property_info->property_type->from_dbus_direct_allow_transform) { \
nm_auto_unset_gvalue GValue _gvalue = G_VALUE_INIT; \
\
@ -1585,21 +1618,20 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
}
case NM_VALUE_TYPE_ENUM:
{
const GParamSpecEnum *param_spec;
int *p_val;
int v;
int *p_val;
int v;
param_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec);
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
if (g_variant_is_of_type(value, G_VARIANT_TYPE_INT32)) {
G_STATIC_ASSERT(sizeof(int) >= sizeof(gint32));
v = g_variant_get_int32(value);
} else {
if (!_variant_get_value_transform(property_info,
value,
G_TYPE_FROM_CLASS(param_spec->enum_class),
g_value_get_flags,
&v))
GType gtype = G_TYPE_IS_ENUM(property_info->param_spec->value_type)
? property_info->param_spec->value_type
: G_TYPE_INT;
if (!_variant_get_value_transform(property_info, value, gtype, g_value_get_flags, &v))
goto out_error_wrong_dbus_type;
}
@ -1607,8 +1639,18 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
if (*p_val == v)
goto out_unchanged;
if (!g_enum_get_value(param_spec->enum_class, v))
goto out_error_param_spec_validation;
/* To avoid that clients with old libnm fails setting a newer value received
* from the daemon, do not validate here if the value is within range or not.
* Instead, do it in 'verify' that the client can ignore.
* However, some properties are implemented as real enums, mostly those that
* were originally implemented as such. Maintain the old behaviour on them. */
if (G_TYPE_IS_ENUM(property_info->param_spec->value_type)) {
const GParamSpecEnum *enum_spec = NM_G_PARAM_SPEC_CAST_ENUM(property_info->param_spec);
if (!g_enum_get_value(enum_spec->enum_class, v))
goto out_error_param_spec_validation;
}
*p_val = v;
goto out_notify;
}
@ -2443,7 +2485,6 @@ _verify_properties(NMSetting *setting, GError **error)
case NM_VALUE_TYPE_BOOL:
case NM_VALUE_TYPE_BYTES:
case NM_VALUE_TYPE_STRV:
case NM_VALUE_TYPE_ENUM:
case NM_VALUE_TYPE_FLAGS:
case NM_VALUE_TYPE_INT32:
case NM_VALUE_TYPE_INT64:
@ -2451,6 +2492,37 @@ _verify_properties(NMSetting *setting, GError **error)
case NM_VALUE_TYPE_UINT32:
case NM_VALUE_TYPE_UINT64:
break;
case NM_VALUE_TYPE_ENUM:
{
nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL;
int *val;
nm_assert(_nm_setting_property_is_valid_direct_enum(property_info));
enum_class = g_type_class_ref(property_info->direct_data.enum_gtype);
val = _nm_setting_get_private_field(setting, sett_info, property_info);
/* We validate here that the value is within the range of the enum, and not
* in the GObject property and/or DBus setters. This way, clients using an
* old libnm can accept new values added later to the enum, because clients
* are not required to 'verify' */
if (!g_enum_get_value(enum_class, *val)) {
g_set_error(error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_PROPERTY,
_("invalid value %d, expected %d-%d"),
*val,
enum_class->minimum,
enum_class->maximum);
g_prefix_error(error,
"%s.%s: ",
klass->setting_info->setting_name,
property_info->name);
return FALSE;
}
return TRUE;
}
case NM_VALUE_TYPE_STRING:
{
const char *val;
@ -4465,6 +4537,43 @@ nm_range_from_str(const char *str, GError **error)
return nm_range_new(start, end);
}
/**
* nm_setting_get_enum_property_type:
* @setting_type: the GType of the NMSetting instance
* @property_name: the name of the property
*
* Get the type of the enum that defines the values that the property accepts. It is only
* useful for properties configured to accept values from certain enum type, otherwise
* it will return %G_TYPE_INVALID. Note that flags (children of G_TYPE_FLAGS) are also
* considered enums.
*
* Note that the GObject property might be implemented as an integer, actually, and not
* as enum. Find out what underlying type is used, checking the #GParamSpec, before
* setting the GObject property.
*
* Returns: the enum's GType, or %G_TYPE_INVALID if the property is not of enum type
*
* Since: 1.46
*/
GType
nm_setting_get_enum_property_type(GType setting_type, const char *property_name)
{
nm_auto_unref_gtypeclass NMSettingClass *setting_class = g_type_class_ref(setting_type);
const NMSettInfoProperty *property_info;
GParamSpec *spec;
g_return_val_if_fail(NM_IS_SETTING_CLASS(setting_class), G_TYPE_INVALID);
property_info = _nm_setting_class_get_property_info(setting_class, property_name);
spec = property_info->param_spec;
if (spec && (G_TYPE_IS_ENUM(spec->value_type) || G_TYPE_IS_FLAGS(spec->value_type)))
return property_info->param_spec->value_type;
if (property_info->property_type->direct_type == NM_VALUE_TYPE_ENUM)
return property_info->direct_data.enum_gtype;
return G_TYPE_INVALID;
}
/*****************************************************************************/
static void

View file

@ -4565,7 +4565,7 @@ test_setting_metadata(void)
GArray *property_types_data;
guint prop_idx_val;
gboolean can_set_including_default = FALSE;
gboolean can_have_direct_set_fcn = FALSE;
gboolean can_have_direct_data = FALSE;
int n_special_options;
g_assert(sip->name);
@ -4662,18 +4662,35 @@ test_setting_metadata(void)
can_set_including_default = TRUE;
} else if (sip->property_type->direct_type == NM_VALUE_TYPE_ENUM) {
const GParamSpecEnum *pspec;
nm_auto_unref_gtypeclass GEnumClass *enum_class = NULL;
int default_value;
g_assert(_nm_setting_property_is_valid_direct_enum(sip));
g_assert(G_TYPE_IS_ENUM(sip->direct_data.enum_gtype));
g_assert(g_variant_type_equal(sip->property_type->dbus_type, "i"));
g_assert(sip->param_spec);
g_assert(g_type_is_a(sip->param_spec->value_type, G_TYPE_ENUM));
g_assert(sip->param_spec->value_type != G_TYPE_ENUM);
pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec);
g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type);
g_assert(g_enum_get_value(pspec->enum_class, pspec->default_value));
if (G_TYPE_IS_ENUM(sip->param_spec->value_type)) {
const GParamSpecEnum *pspec = NM_G_PARAM_SPEC_CAST_ENUM(sip->param_spec);
g_assert(sip->param_spec->value_type != G_TYPE_ENUM);
g_assert(G_TYPE_FROM_CLASS(pspec->enum_class) == sip->param_spec->value_type);
g_assert(sip->param_spec->value_type == sip->direct_data.enum_gtype);
default_value = pspec->default_value;
} else if (sip->param_spec->value_type == G_TYPE_INT) {
const GParamSpecInt *pspec = NM_G_PARAM_SPEC_CAST_INT(sip->param_spec);
default_value = pspec->default_value;
} else {
g_assert_not_reached();
}
enum_class = g_type_class_ref(sip->direct_data.enum_gtype);
g_assert(g_enum_get_value(enum_class, default_value));
can_set_including_default = TRUE;
can_have_direct_data = TRUE;
} else if (sip->property_type->direct_type == NM_VALUE_TYPE_FLAGS) {
const GParamSpecFlags *pspec;
@ -4703,7 +4720,7 @@ test_setting_metadata(void)
INFINIBAND_ALEN));
} else {
g_assert(g_variant_type_equal(sip->property_type->dbus_type, "s"));
can_have_direct_set_fcn = TRUE;
can_have_direct_data = TRUE;
}
g_assert(sip->param_spec);
g_assert(sip->param_spec->value_type == G_TYPE_STRING);
@ -4744,8 +4761,8 @@ test_setting_metadata(void)
g_assert(sip->property_type->direct_type == NM_VALUE_TYPE_STRING);
}
if (!can_have_direct_set_fcn)
g_assert(!sip->direct_set_fcn.set_string);
if (!can_have_direct_data)
g_assert(!sip->direct_data.set_string);
if (sip->property_type->direct_type == NM_VALUE_TYPE_NONE)
g_assert(!sip->direct_also_notify);

View file

@ -800,7 +800,13 @@ struct _NMSettInfoProperty {
const NMSettInfoProperty *property_info,
NMSetting *setting,
const char *src);
} direct_set_fcn;
/* We implement %NM_VALUE_TYPE_ENUM properties as integer GObject properties
* because using real enum triggers glib assertions when passing newer values to
* clients with old libnm. This defines the enum type that the direct_property of
* type %NM_VALUE_TYPE_ENUM will use. */
GType enum_gtype;
} direct_data;
/* For direct properties, this is the param_spec that also should be
* notified on changes. */

View file

@ -255,6 +255,9 @@ void nm_setting_option_clear_by_name(NMSetting *setting, NMUtilsPredicateStr pre
const GVariantType *nm_setting_get_dbus_property_type(NMSetting *setting,
const char *property_name);
NM_AVAILABLE_IN_1_46
GType nm_setting_get_enum_property_type(GType setting_type, const char *property_name);
/*****************************************************************************/
typedef struct _NMRange NMRange;

View file

@ -1073,7 +1073,6 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
{
GType gtype = 0;
const NMUtilsEnumValueInfo *value_infos = NULL;
gboolean has_gtype = FALSE;
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
gint64 v;
gboolean format_numeric = FALSE;
@ -1087,13 +1086,6 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
RETURN_UNSUPPORTED_GET_TYPE();
if (property_info->property_typ_data) {
if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
has_gtype = TRUE;
}
}
if (property_info->property_typ_data && get_type == NM_META_ACCESSOR_GET_TYPE_PRETTY
&& NM_FLAGS_ANY(property_info->property_typ_data->typ_flags,
NM_META_PROPERTY_TYP_FLAG_ENUM_GET_PRETTY_NUMERIC
@ -1136,18 +1128,12 @@ _get_fcn_gobject_enum(ARGS_GET_FCN)
nm_assert(format_text || format_numeric);
gtype = nm_meta_property_enum_get_type(property_info);
g_return_val_if_fail(gtype != G_TYPE_INVALID, NULL);
pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(setting), property_info->property_name);
g_return_val_if_fail(pspec, NULL);
if (has_gtype) {
/* if the property is already enum, don't set get_gtype: it's redundant and error prone */
g_return_val_if_fail(NM_IN_SET(pspec->value_type, G_TYPE_INT, G_TYPE_UINT), FALSE);
} else {
gtype = pspec->value_type;
}
g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), NULL);
g_value_init(&gval, pspec->value_type);
g_object_get_property(G_OBJECT(setting), property_info->property_name, &gval);
NM_SET_OUT(out_is_default, g_param_value_defaults(pspec, &gval));
@ -1255,17 +1241,19 @@ nm_meta_property_int_get_range(const NMMetaPropertyInfo *property_info,
GType
nm_meta_property_enum_get_type(const NMMetaPropertyInfo *property_info)
{
GType gtype = _property_get_spec(property_info)->value_type;
GType setting_gtype = property_info->setting_info->general->get_setting_gtype();
GType prop_gtype =
nm_setting_get_enum_property_type(setting_gtype, property_info->property_name);
if (property_info->property_typ_data
&& property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
/* if the property is already enum, don't set get_gtype: it's redundant and error prone */
g_return_val_if_fail(NM_IN_SET(gtype, G_TYPE_INT, G_TYPE_UINT), G_TYPE_INVALID);
g_return_val_if_fail(prop_gtype == G_TYPE_INVALID, G_TYPE_INVALID);
return property_info->property_typ_data->subtype.gobject_enum.get_gtype();
}
g_return_val_if_fail(G_TYPE_IS_ENUM(gtype) || G_TYPE_IS_FLAGS(gtype), G_TYPE_INVALID);
return gtype;
g_return_val_if_fail(G_TYPE_IS_ENUM(prop_gtype) || G_TYPE_IS_FLAGS(prop_gtype), G_TYPE_INVALID);
return prop_gtype;
}
/**
@ -1579,33 +1567,18 @@ _set_fcn_gobject_mac(ARGS_SET_FCN)
static gboolean
_set_fcn_gobject_enum(ARGS_SET_FCN)
{
GType gtype = 0;
GType gtype_prop;
gboolean has_gtype = FALSE;
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
GType gtype;
GType gtype_gobj;
nm_auto_unset_gvalue GValue gval = G_VALUE_INIT;
gboolean is_flags;
int v;
if (_SET_FCN_DO_RESET_DEFAULT_WITH_SUPPORTS_REMOVE(property_info, modifier, value))
return _gobject_property_reset_default(setting, property_info->property_name);
if (property_info->property_typ_data) {
if (property_info->property_typ_data->subtype.gobject_enum.get_gtype) {
gtype = property_info->property_typ_data->subtype.gobject_enum.get_gtype();
has_gtype = TRUE;
}
}
gtype = nm_meta_property_enum_get_type(property_info);
g_return_val_if_fail(gtype != G_TYPE_INVALID, FALSE);
gtype_prop = _gobject_property_get_gtype(G_OBJECT(setting), property_info->property_name);
if (has_gtype) {
/* if the property is already enum, don't set get_gtype: it's redundant and error prone */
g_return_val_if_fail(NM_IN_SET(gtype_prop, G_TYPE_INT, G_TYPE_UINT), FALSE);
} else {
gtype = gtype_prop;
}
g_return_val_if_fail(G_TYPE_IS_FLAGS(gtype) || G_TYPE_IS_ENUM(gtype), FALSE);
is_flags = G_TYPE_IS_FLAGS(gtype);
if (!_nm_utils_enum_from_str_full(
@ -1641,10 +1614,12 @@ _set_fcn_gobject_enum(ARGS_SET_FCN)
v = (int) (v_flag | ((guint) v));
}
g_value_init(&gval, gtype_prop);
if (gtype_prop == G_TYPE_INT)
gtype_gobj = _gobject_property_get_gtype(G_OBJECT(setting), property_info->property_name);
g_value_init(&gval, gtype_gobj);
if (gtype_gobj == G_TYPE_INT)
g_value_set_int(&gval, v);
else if (gtype_prop == G_TYPE_UINT)
else if (gtype_gobj == G_TYPE_UINT)
g_value_set_uint(&gval, v);
else if (is_flags)
g_value_set_flags(&gval, v);