mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-30 16:40:13 +01:00
libnm: support lookup of property-info by param-spec
We also need to find efficiently the property-info for a given GParamSpec. Add a lookup index for that.
This commit is contained in:
parent
102a1f5c31
commit
f1cb07e438
4 changed files with 146 additions and 4 deletions
|
|
@ -332,6 +332,10 @@ gboolean _nm_setting_property_is_regular_secret_flags(NMSetting * setting,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
const NMSettInfoProperty *
|
||||
_nm_sett_info_property_lookup_by_param_spec(const NMSettInfoSetting *sett_info,
|
||||
const GParamSpec * param_spec);
|
||||
|
||||
static inline GArray *
|
||||
_nm_sett_info_property_override_create_array_sized(guint reserved_size)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -263,6 +263,16 @@ _property_infos_sort(const NMSettInfoProperty *property_infos,
|
|||
return arr;
|
||||
}
|
||||
|
||||
static int
|
||||
_property_lookup_by_param_spec_sort(gconstpointer p_a, gconstpointer p_b, gpointer user_data)
|
||||
{
|
||||
const NMSettInfoPropertLookupByParamSpec *a = p_a;
|
||||
const NMSettInfoPropertLookupByParamSpec *b = p_b;
|
||||
|
||||
NM_CMP_DIRECT(a->param_spec_as_uint, b->param_spec_as_uint);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
_nm_setting_class_commit(NMSettingClass * setting_class,
|
||||
NMMetaSettingType meta_type,
|
||||
|
|
@ -271,10 +281,11 @@ _nm_setting_class_commit(NMSettingClass * setting_class,
|
|||
gint16 private_offset)
|
||||
{
|
||||
NMSettInfoSetting *sett_info;
|
||||
gs_free GParamSpec **property_specs = NULL;
|
||||
guint n_property_specs;
|
||||
guint override_len;
|
||||
guint i;
|
||||
gs_free GParamSpec ** property_specs = NULL;
|
||||
guint n_property_specs;
|
||||
NMSettInfoPropertLookupByParamSpec *lookup_by_iter;
|
||||
guint override_len;
|
||||
guint i;
|
||||
|
||||
nm_assert(NM_IS_SETTING_CLASS(setting_class));
|
||||
nm_assert(!setting_class->setting_info);
|
||||
|
|
@ -424,6 +435,33 @@ has_property_type:
|
|||
sett_info->property_infos_len,
|
||||
setting_class);
|
||||
|
||||
nm_assert(sett_info->property_infos_len < G_MAXUINT16);
|
||||
sett_info->property_lookup_by_param_spec_len = 0;
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
if (sett_info->property_infos[i].param_spec) {
|
||||
sett_info->property_lookup_by_param_spec_len++;
|
||||
}
|
||||
}
|
||||
sett_info->property_lookup_by_param_spec =
|
||||
g_new(NMSettInfoPropertLookupByParamSpec, sett_info->property_lookup_by_param_spec_len);
|
||||
lookup_by_iter =
|
||||
(NMSettInfoPropertLookupByParamSpec *) sett_info->property_lookup_by_param_spec;
|
||||
for (i = 0; i < sett_info->property_infos_len; i++) {
|
||||
const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
|
||||
|
||||
if (property_info->param_spec) {
|
||||
*(lookup_by_iter++) = (NMSettInfoPropertLookupByParamSpec){
|
||||
.param_spec_as_uint = (uintptr_t) ((gpointer) property_info->param_spec),
|
||||
.property_info = property_info,
|
||||
};
|
||||
}
|
||||
}
|
||||
g_qsort_with_data(sett_info->property_lookup_by_param_spec,
|
||||
sett_info->property_lookup_by_param_spec_len,
|
||||
sizeof(NMSettInfoPropertLookupByParamSpec),
|
||||
_property_lookup_by_param_spec_sort,
|
||||
NULL);
|
||||
|
||||
g_array_free(properties_override, TRUE);
|
||||
}
|
||||
|
||||
|
|
@ -473,6 +511,47 @@ _nm_setting_class_get_sett_info(NMSettingClass *setting_class)
|
|||
return sett_info;
|
||||
}
|
||||
|
||||
const NMSettInfoProperty *
|
||||
_nm_sett_info_property_lookup_by_param_spec(const NMSettInfoSetting *sett_info,
|
||||
const GParamSpec * param_spec)
|
||||
{
|
||||
NMSettInfoPropertLookupByParamSpec needle;
|
||||
int imin;
|
||||
int imax;
|
||||
int imid;
|
||||
int cmp;
|
||||
|
||||
nm_assert(sett_info);
|
||||
nm_assert(param_spec);
|
||||
|
||||
/* ensure that "int" is large enough to contain the index variables. */
|
||||
G_STATIC_ASSERT_EXPR(sizeof(int) > sizeof(sett_info->property_lookup_by_param_spec_len));
|
||||
|
||||
if (sett_info->property_lookup_by_param_spec_len == 0)
|
||||
return NULL;
|
||||
|
||||
needle.param_spec_as_uint = (uintptr_t) ((gpointer) param_spec);
|
||||
|
||||
imin = 0;
|
||||
imax = sett_info->property_lookup_by_param_spec_len - 1;
|
||||
while (imin <= imax) {
|
||||
imid = imin + (imax - imin) / 2;
|
||||
|
||||
cmp = _property_lookup_by_param_spec_sort(&sett_info->property_lookup_by_param_spec[imid],
|
||||
&needle,
|
||||
NULL);
|
||||
if (cmp == 0)
|
||||
return sett_info->property_lookup_by_param_spec[imid].property_info;
|
||||
|
||||
if (cmp < 0)
|
||||
imin = imid + 1;
|
||||
else
|
||||
imax = imid - 1;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -4388,6 +4388,9 @@ test_setting_metadata(void)
|
|||
guint prop_idx;
|
||||
gs_free GParamSpec **property_specs = NULL;
|
||||
guint n_property_specs;
|
||||
guint n_param_spec;
|
||||
guint i;
|
||||
guint j;
|
||||
|
||||
g_assert(sis);
|
||||
|
||||
|
|
@ -4418,6 +4421,8 @@ test_setting_metadata(void)
|
|||
|
||||
h_properties = g_hash_table_new(nm_str_hash, g_str_equal);
|
||||
|
||||
n_param_spec = 0;
|
||||
|
||||
for (prop_idx = 0; prop_idx < sis->property_infos_len; prop_idx++) {
|
||||
const NMSettInfoProperty *sip = &sis->property_infos[prop_idx];
|
||||
GArray * property_types_data;
|
||||
|
|
@ -4426,6 +4431,9 @@ test_setting_metadata(void)
|
|||
|
||||
g_assert(sip->name);
|
||||
|
||||
if (sip->param_spec)
|
||||
n_param_spec++;
|
||||
|
||||
if (prop_idx > 0)
|
||||
g_assert_cmpint(strcmp(sis->property_infos[prop_idx - 1].name, sip->name), <, 0);
|
||||
|
||||
|
|
@ -4587,6 +4595,44 @@ check_done:;
|
|||
g_assert_cmpstr(sis->property_infos[0].name, ==, NM_SETTING_NAME);
|
||||
} else
|
||||
g_assert_cmpint(meta_type, !=, NM_META_SETTING_TYPE_ETHTOOL);
|
||||
|
||||
g_assert_cmpint(n_param_spec, >, 0);
|
||||
g_assert_cmpint(n_param_spec, ==, sis->property_lookup_by_param_spec_len);
|
||||
g_assert(sis->property_lookup_by_param_spec);
|
||||
for (i = 0; i < sis->property_lookup_by_param_spec_len; i++) {
|
||||
const NMSettInfoPropertLookupByParamSpec *p = &sis->property_lookup_by_param_spec[i];
|
||||
guint n_found;
|
||||
|
||||
if (i > 0) {
|
||||
g_assert_cmpint(sis->property_lookup_by_param_spec[i - 1].param_spec_as_uint,
|
||||
<,
|
||||
p->param_spec_as_uint);
|
||||
}
|
||||
g_assert(p->property_info);
|
||||
g_assert(p->property_info >= sis->property_infos);
|
||||
g_assert(p->property_info < &sis->property_infos[sis->property_infos_len]);
|
||||
g_assert(p->property_info
|
||||
== &sis->property_infos[p->property_info - sis->property_infos]);
|
||||
|
||||
g_assert(p->property_info->param_spec);
|
||||
g_assert(p->param_spec_as_uint
|
||||
== ((uintptr_t) ((gpointer) p->property_info->param_spec)));
|
||||
|
||||
g_assert(_nm_sett_info_property_lookup_by_param_spec(sis, p->property_info->param_spec)
|
||||
== p->property_info);
|
||||
|
||||
n_found = 0;
|
||||
for (j = 0; j < sis->property_infos_len; j++) {
|
||||
const NMSettInfoProperty *pip2 = &sis->property_infos[j];
|
||||
|
||||
if (pip2->param_spec
|
||||
&& p->param_spec_as_uint == ((uintptr_t) ((gpointer) pip2->param_spec))) {
|
||||
g_assert(pip2 == p->property_info);
|
||||
n_found++;
|
||||
}
|
||||
}
|
||||
g_assert(n_found == 1);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
|||
|
|
@ -745,6 +745,15 @@ struct _NMSettInfoProperty {
|
|||
} to_dbus_data;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* we want to do binary search by "GParamSpec *", but unrelated pointers
|
||||
* are not directly comparable in C. No problem, we convert them to
|
||||
* uintptr_t for the search, that is guaranteed to work. */
|
||||
uintptr_t param_spec_as_uint;
|
||||
|
||||
const NMSettInfoProperty *property_info;
|
||||
} NMSettInfoPropertLookupByParamSpec;
|
||||
|
||||
typedef struct {
|
||||
const GVariantType *(*get_variant_type)(const struct _NMSettInfoSetting *sett_info,
|
||||
const char * name,
|
||||
|
|
@ -784,8 +793,12 @@ struct _NMSettInfoSetting {
|
|||
*/
|
||||
const NMSettInfoProperty *const *property_infos_sorted;
|
||||
|
||||
const NMSettInfoPropertLookupByParamSpec *property_lookup_by_param_spec;
|
||||
|
||||
guint property_infos_len;
|
||||
|
||||
guint16 property_lookup_by_param_spec_len;
|
||||
|
||||
/* the offset in bytes to get the private data from the @self pointer. */
|
||||
gint16 private_offset;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue