libnm: add direct property type "flags"

"flags" are a g_param_spec_flags() and correspond to G_TYPE_FLAGS type.
They are internally stored as guint, and exported on D-Bus as "u" (32 bit
integer).
This commit is contained in:
Thomas Haller 2021-10-20 10:53:39 +02:00
parent 3e6c18e9af
commit 093f434cd0
No known key found for this signature in database
GPG key ID: 29C2366E4DFC5728
6 changed files with 190 additions and 4 deletions

View file

@ -292,6 +292,7 @@ extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_boolean;
extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_int32;
extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_uint32;
extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_string;
extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_flags;
extern const NMSettInfoPropertType nm_sett_info_propert_type_direct_mac_address;
NMSettingVerifyResult
@ -659,6 +660,66 @@ _nm_properties_override(GArray *properties_override, const NMSettInfoProperty *p
/*****************************************************************************/
#define _nm_setting_property_define_direct_flags(properties_override, \
obj_properties, \
prop_name, \
prop_id, \
gtype_flags, \
default_value, \
param_flags, \
private_struct_type, \
private_struct_field, \
... /* extra NMSettInfoProperty fields */) \
G_STMT_START \
{ \
GParamSpec *_param_spec; \
\
G_STATIC_ASSERT( \
!NM_FLAGS_ANY((param_flags), \
~(NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_INFERRABLE))); \
\
_param_spec = \
g_param_spec_flags("" prop_name "", \
"", \
"", \
(gtype_flags), \
(default_value), \
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | (param_flags)); \
\
(obj_properties)[(prop_id)] = _param_spec; \
\
_nm_properties_override_gobj( \
(properties_override), \
_param_spec, \
&nm_sett_info_propert_type_direct_flags, \
.direct_offset = \
NM_STRUCT_OFFSET_ENSURE_TYPE(guint, private_struct_type, private_struct_field), \
__VA_ARGS__); \
} \
G_STMT_END
/*****************************************************************************/
#define _nm_setting_property_define_direct_secret_flags(properties_override, \
obj_properties, \
prop_name, \
prop_id, \
private_struct_type, \
private_struct_field, \
... /* extra NMSettInfoProperty fields */) \
_nm_setting_property_define_direct_flags((properties_override), \
(obj_properties), \
prop_name, \
(prop_id), \
NM_TYPE_SETTING_SECRET_FLAGS, \
NM_SETTING_SECRET_FLAG_NONE, \
NM_SETTING_PARAM_NONE, \
private_struct_type, \
private_struct_field, \
##__VA_ARGS__)
/*****************************************************************************/
#define _nm_setting_property_define_direct_mac_address(properties_override, \
obj_properties, \
prop_name, \

View file

@ -744,6 +744,14 @@ _nm_setting_property_get_property_direct(GObject * object,
g_value_set_uint(value, *p_val);
return;
}
case NM_VALUE_TYPE_FLAGS:
{
const guint *p_val =
_nm_setting_get_private(setting, sett_info, property_info->direct_offset);
g_value_set_flags(value, *p_val);
return;
}
case NM_VALUE_TYPE_STRING:
{
const char *const *p_val =
@ -823,6 +831,17 @@ _nm_setting_property_set_property_direct(GObject * object,
nm_assert(*p_val == v);
goto out_notify;
}
case NM_VALUE_TYPE_FLAGS:
{
guint *p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
guint v;
v = g_value_get_flags(value);
if (*p_val == v)
return;
*p_val = v;
goto out_notify;
}
case NM_VALUE_TYPE_STRING:
if (!_property_direct_set_string(
property_info,
@ -900,6 +919,17 @@ _init_direct(NMSetting *setting)
*p_val = def_val;
break;
}
case NM_VALUE_TYPE_FLAGS:
{
guint *p_val =
_nm_setting_get_private(setting, sett_info, property_info->direct_offset);
guint def_val;
def_val = NM_G_PARAM_SPEC_GET_DEFAULT_FLAGS(property_info->param_spec);
nm_assert(*p_val == 0);
*p_val = def_val;
break;
}
case NM_VALUE_TYPE_STRING:
nm_assert(!NM_G_PARAM_SPEC_GET_DEFAULT_STRING(property_info->param_spec));
nm_assert(!(
@ -937,6 +967,7 @@ _finalize_direct(NMSetting *setting)
case NM_VALUE_TYPE_BOOL:
case NM_VALUE_TYPE_INT32:
case NM_VALUE_TYPE_UINT32:
case NM_VALUE_TYPE_FLAGS:
break;
case NM_VALUE_TYPE_STRING:
{
@ -991,6 +1022,17 @@ _nm_setting_property_to_dbus_fcn_direct(_NM_SETT_INFO_PROP_TO_DBUS_FCN_ARGS _nm_
return NULL;
return g_variant_new_uint32(val);
}
case NM_VALUE_TYPE_FLAGS:
{
guint val;
val =
*((guint *) _nm_setting_get_private(setting, sett_info, property_info->direct_offset));
if (!property_info->to_dbus_including_default
&& val == NM_G_PARAM_SPEC_GET_DEFAULT_FLAGS(property_info->param_spec))
return NULL;
return g_variant_new_uint32(val);
}
case NM_VALUE_TYPE_STRING:
{
const char *val;
@ -1224,6 +1266,35 @@ _nm_setting_property_from_dbus_fcn_direct(_NM_SETT_INFO_PROP_FROM_DBUS_FCN_ARGS
*p_val = v;
goto out_notify;
}
case NM_VALUE_TYPE_FLAGS:
{
const GParamSpecFlags *param_spec;
guint * p_val;
guint v;
param_spec = NM_G_PARAM_SPEC_CAST_FLAGS(property_info->param_spec);
if (g_variant_is_of_type(value, G_VARIANT_TYPE_UINT32)) {
G_STATIC_ASSERT(sizeof(guint) >= sizeof(guint32));
v = g_variant_get_uint32(value);
} else {
if (!_variant_get_value_transform(property_info,
value,
G_TYPE_FROM_CLASS(param_spec->flags_class),
g_value_get_flags,
&v))
goto out_error_wrong_dbus_type;
}
p_val = _nm_setting_get_private(setting, sett_info, property_info->direct_offset);
if (*p_val == v)
goto out_unchanged;
if ((v & param_spec->flags_class->mask) != v)
goto out_error_param_spec_validation;
*p_val = v;
goto out_notify;
}
case NM_VALUE_TYPE_STRING:
{
gs_free char *v_free = NULL;
@ -2144,6 +2215,8 @@ _nm_setting_property_compare_fcn_direct(_NM_SETT_INFO_PROP_COMPARE_FCN_ARGS _nm_
return *((const gint32 *) p_a) == *((const gint32 *) p_b);
case NM_VALUE_TYPE_UINT32:
return *((const guint32 *) p_a) == *((const guint32 *) p_b);
case NM_VALUE_TYPE_FLAGS:
return *((const guint *) p_a) == *((const guint *) p_b);
case NM_VALUE_TYPE_STRING:
return nm_streq0(*((const char *const *) p_a), *((const char *const *) p_b));
default:
@ -3198,6 +3271,15 @@ const NMSettInfoPropertType nm_sett_info_propert_type_direct_string =
.from_dbus_is_full = TRUE,
.from_dbus_direct_allow_transform = TRUE);
const NMSettInfoPropertType nm_sett_info_propert_type_direct_flags =
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(G_VARIANT_TYPE_UINT32,
.direct_type = NM_VALUE_TYPE_FLAGS,
.compare_fcn = _nm_setting_property_compare_fcn_direct,
.to_dbus_fcn = _nm_setting_property_to_dbus_fcn_direct,
.from_dbus_fcn = _nm_setting_property_from_dbus_fcn_direct,
.from_dbus_is_full = TRUE,
.from_dbus_direct_allow_transform = TRUE);
const NMSettInfoPropertType nm_sett_info_propert_type_direct_mac_address =
NM_SETT_INFO_PROPERT_TYPE_DBUS_INIT(
G_VARIANT_TYPE_BYTESTRING,

View file

@ -4489,6 +4489,24 @@ test_setting_metadata(void)
g_assert_cmpint(pspec->maximum, <=, (guint64) G_MAXUINT32);
can_set_including_default = TRUE;
} else if (sip->property_type->direct_type == NM_VALUE_TYPE_FLAGS) {
const GParamSpecFlags *pspec;
g_assert(sip->property_type == &nm_sett_info_propert_type_direct_flags);
g_assert(g_variant_type_equal(sip->property_type->dbus_type, "u"));
g_assert(sip->property_type->to_dbus_fcn
== _nm_setting_property_to_dbus_fcn_direct);
g_assert(sip->param_spec);
g_assert(g_type_is_a(sip->param_spec->value_type, G_TYPE_FLAGS));
g_assert(sip->param_spec->value_type != G_TYPE_FLAGS);
pspec = NM_G_PARAM_SPEC_CAST_FLAGS(sip->param_spec);
g_assert_cmpint(pspec->flags_class->mask, !=, 0);
g_assert_cmpint(pspec->default_value,
==,
pspec->flags_class->mask & pspec->default_value);
can_set_including_default = TRUE;
} else if (sip->property_type->direct_type == NM_VALUE_TYPE_STRING) {
if (sip->property_type == &nm_sett_info_propert_type_direct_mac_address) {

View file

@ -380,6 +380,7 @@ nm_value_type_to_json(NMValueType value_type, GString *gstr, gconstpointer p_fie
nm_json_gstr_append_uint64(gstr, *((const guint32 *) p_field));
return;
case NM_VALUE_TYPE_UINT:
case NM_VALUE_TYPE_FLAGS:
nm_json_gstr_append_uint64(gstr, *((const guint *) p_field));
return;
case NM_VALUE_TYPE_UINT64:
@ -413,6 +414,7 @@ nm_value_type_from_json(const NMJsonVt * vt,
case NM_VALUE_TYPE_UINT32:
return (nm_jansson_json_as_uint32(vt, elem, out_val) > 0);
case NM_VALUE_TYPE_UINT:
case NM_VALUE_TYPE_FLAGS:
return (nm_jansson_json_as_uint(vt, elem, out_val) > 0);
case NM_VALUE_TYPE_UINT64:
return (nm_jansson_json_as_uint64(vt, elem, out_val) > 0);

View file

@ -1450,6 +1450,14 @@ GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char *
((const _c_type *) _param_spec); \
})
#define _NM_G_PARAM_SPEC_CAST_IS_A(param_spec, _value_type, _c_type) \
({ \
const GParamSpec *const _param_spec = (param_spec); \
\
nm_assert(!_param_spec || g_type_is_a(_param_spec->value_type, _value_type)); \
((const _c_type *) _param_spec); \
})
#define NM_G_PARAM_SPEC_CAST_BOOLEAN(param_spec) \
_NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_BOOLEAN, GParamSpecBoolean)
#define NM_G_PARAM_SPEC_CAST_INT(param_spec) \
@ -1458,6 +1466,8 @@ GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char *
_NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT, GParamSpecUInt)
#define NM_G_PARAM_SPEC_CAST_UINT64(param_spec) \
_NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT64, GParamSpecUInt64)
#define NM_G_PARAM_SPEC_CAST_FLAGS(param_spec) \
_NM_G_PARAM_SPEC_CAST_IS_A(param_spec, G_TYPE_FLAGS, GParamSpecFlags)
#define NM_G_PARAM_SPEC_CAST_STRING(param_spec) \
_NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_STRING, GParamSpecString)
@ -1469,6 +1479,8 @@ GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char *
(NM_G_PARAM_SPEC_CAST_UINT(NM_ENSURE_NOT_NULL(param_spec))->default_value)
#define NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(param_spec) \
(NM_G_PARAM_SPEC_CAST_UINT64(NM_ENSURE_NOT_NULL(param_spec))->default_value)
#define NM_G_PARAM_SPEC_GET_DEFAULT_FLAGS(param_spec) \
(NM_G_PARAM_SPEC_CAST_FLAGS(NM_ENSURE_NOT_NULL(param_spec))->default_value)
#define NM_G_PARAM_SPEC_GET_DEFAULT_STRING(param_spec) \
(NM_G_PARAM_SPEC_CAST_STRING(NM_ENSURE_NOT_NULL(param_spec))->default_value)

View file

@ -16,7 +16,13 @@ typedef enum _nm_packed {
NM_VALUE_TYPE_UINT32 = 6,
NM_VALUE_TYPE_UINT = 7,
NM_VALUE_TYPE_UINT64 = 8,
NM_VALUE_TYPE_STRING = 9,
/* Flags are for G_TYPE_FLAGS. That is, internally they are tracked
* as a guint, they have a g_param_spec_flags() property and they are
* serialized on D-Bus as "u". */
NM_VALUE_TYPE_FLAGS = 9,
NM_VALUE_TYPE_STRING = 10,
} NMValueType;
/*****************************************************************************/
@ -92,6 +98,7 @@ nm_value_type_cmp(NMValueType value_type, gconstpointer p_a, gconstpointer p_b)
NM_CMP_DIRECT(*((const guint32 *) p_a), *((const guint32 *) p_b));
return 0;
case NM_VALUE_TYPE_UINT:
case NM_VALUE_TYPE_FLAGS:
NM_CMP_DIRECT(*((const guint *) p_a), *((const guint *) p_b));
return 0;
case NM_VALUE_TYPE_UINT64:
@ -133,6 +140,7 @@ nm_value_type_copy(NMValueType value_type, gpointer dst, gconstpointer src)
(*((guint32 *) dst) = *((const guint32 *) src));
return;
case NM_VALUE_TYPE_UINT:
case NM_VALUE_TYPE_FLAGS:
(*((guint *) dst) = *((const guint *) src));
return;
case NM_VALUE_TYPE_UINT64:
@ -186,7 +194,8 @@ nm_value_type_get_from_variant(NMValueType value_type,
case NM_VALUE_TYPE_INT:
case NM_VALUE_TYPE_UINT:
/* "int" and "uint" also does not have a defined variant type, because it's not
case NM_VALUE_TYPE_FLAGS:
/* These types don't have a defined variant type, because it's not
* clear how many bits we would need. */
/* fall-through */
@ -219,7 +228,8 @@ nm_value_type_to_variant(NMValueType value_type, gconstpointer src)
case NM_VALUE_TYPE_INT:
case NM_VALUE_TYPE_UINT:
/* "int" and "uint" also does not have a defined variant type, because it's not
case NM_VALUE_TYPE_FLAGS:
/* These types don't have a defined variant type, because it's not
* clear how many bits we would need. */
/* fall-through */
@ -250,7 +260,8 @@ nm_value_type_get_variant_type(NMValueType value_type)
case NM_VALUE_TYPE_INT:
case NM_VALUE_TYPE_UINT:
/* "int" and "uint" also does not have a defined variant type, because it's not
case NM_VALUE_TYPE_FLAGS:
/* These types don't have a defined variant type, because it's not
* clear how many bits we would need. */
/* fall-through */