gparam: Remove pspec_list_remove_overridden_and_redirected()

Instead of collecting more pspecs than we need, just don't add them to
the list(s) in the first place.
This commit is contained in:
Timm Bäder 2020-12-31 09:43:16 +01:00
parent 2bd8626885
commit 423bfa87d5

View File

@ -1203,52 +1203,30 @@ pspec_compare_id (gconstpointer a,
return strcmp (pspec1->name, pspec2->name); return strcmp (pspec1->name, pspec2->name);
} }
static inline GSList* static inline gboolean
pspec_list_remove_overridden_and_redirected (GSList *plist, should_list_pspec (GParamSpec *pspec,
GHashTable *ht, GType owner_type,
GType owner_type, GHashTable *ht)
guint *n_p)
{ {
GSList *rlist = NULL; GParamSpec *found;
while (plist) /* Remove paramspecs that are redirected, and also paramspecs
* that have are overridden by non-redirected properties.
* The idea is to get the single paramspec for each name that
* best corresponds to what the application sees.
*/
if (g_param_spec_get_redirect_target (pspec))
return FALSE;
found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
if (found != pspec)
{ {
GSList *tmp = plist->next; GParamSpec *redirect = g_param_spec_get_redirect_target (found);
GParamSpec *pspec = plist->data; if (redirect != pspec)
GParamSpec *found; return FALSE;
gboolean remove = FALSE;
/* Remove paramspecs that are redirected, and also paramspecs
* that have are overridden by non-redirected properties.
* The idea is to get the single paramspec for each name that
* best corresponds to what the application sees.
*/
if (g_param_spec_get_redirect_target (pspec))
remove = TRUE;
else
{
found = param_spec_ht_lookup (ht, pspec->name, owner_type, TRUE);
if (found != pspec)
{
GParamSpec *redirect = g_param_spec_get_redirect_target (found);
if (redirect != pspec)
remove = TRUE;
}
}
if (remove)
{
g_slist_free_1 (plist);
}
else
{
plist->next = rlist;
rlist = plist;
*n_p += 1;
}
plist = tmp;
} }
return rlist;
return TRUE;
} }
static void static void
@ -1260,18 +1238,23 @@ pool_depth_list (gpointer key,
gpointer *data = user_data; gpointer *data = user_data;
GSList **slists = data[0]; GSList **slists = data[0];
GType owner_type = (GType) data[1]; GType owner_type = (GType) data[1];
GHashTable *ht = data[2];
int *count = data[3];
if (g_type_is_a (owner_type, pspec->owner_type)) if (g_type_is_a (owner_type, pspec->owner_type) &&
should_list_pspec (pspec, owner_type, ht))
{ {
if (G_TYPE_IS_INTERFACE (pspec->owner_type)) if (G_TYPE_IS_INTERFACE (pspec->owner_type))
{ {
slists[0] = g_slist_prepend (slists[0], pspec); slists[0] = g_slist_prepend (slists[0], pspec);
*count = *count + 1;
} }
else else
{ {
guint d = g_type_depth (pspec->owner_type); guint d = g_type_depth (pspec->owner_type);
slists[d - 1] = g_slist_prepend (slists[d - 1], pspec); slists[d - 1] = g_slist_prepend (slists[d - 1], pspec);
*count = *count + 1;
} }
} }
} }
@ -1294,9 +1277,15 @@ pool_depth_list_for_interface (gpointer key,
gpointer *data = user_data; gpointer *data = user_data;
GSList **slists = data[0]; GSList **slists = data[0];
GType owner_type = (GType) data[1]; GType owner_type = (GType) data[1];
GHashTable *ht = data[2];
int *count = data[3];
if (pspec->owner_type == owner_type) if (pspec->owner_type == owner_type &&
slists[0] = g_slist_prepend (slists[0], pspec); should_list_pspec (pspec, owner_type, ht))
{
slists[0] = g_slist_prepend (slists[0], pspec);
*count = *count + 1;
}
} }
/** /**
@ -1319,29 +1308,29 @@ g_param_spec_pool_list (GParamSpecPool *pool,
{ {
GParamSpec **pspecs, **p; GParamSpec **pspecs, **p;
GSList **slists, *node; GSList **slists, *node;
gpointer data[2]; gpointer data[4];
guint d, i; guint d, i;
int n_pspecs = 0;
g_return_val_if_fail (pool != NULL, NULL); g_return_val_if_fail (pool != NULL, NULL);
g_return_val_if_fail (owner_type > 0, NULL); g_return_val_if_fail (owner_type > 0, NULL);
g_return_val_if_fail (n_pspecs_p != NULL, NULL); g_return_val_if_fail (n_pspecs_p != NULL, NULL);
g_mutex_lock (&pool->mutex); g_mutex_lock (&pool->mutex);
*n_pspecs_p = 0;
d = g_type_depth (owner_type); d = g_type_depth (owner_type);
slists = g_new0 (GSList*, d); slists = g_new0 (GSList*, d);
data[0] = slists; data[0] = slists;
data[1] = (gpointer) owner_type; data[1] = (gpointer) owner_type;
data[2] = pool->hash_table;
data[3] = &n_pspecs;
g_hash_table_foreach (pool->hash_table, g_hash_table_foreach (pool->hash_table,
G_TYPE_IS_INTERFACE (owner_type) ? G_TYPE_IS_INTERFACE (owner_type) ?
pool_depth_list_for_interface : pool_depth_list_for_interface :
pool_depth_list, pool_depth_list,
&data); &data);
for (i = 0; i < d; i++) pspecs = g_new (GParamSpec*, n_pspecs + 1);
slists[i] = pspec_list_remove_overridden_and_redirected (slists[i], pool->hash_table, owner_type, n_pspecs_p);
pspecs = g_new (GParamSpec*, *n_pspecs_p + 1);
p = pspecs; p = pspecs;
for (i = 0; i < d; i++) for (i = 0; i < d; i++)
{ {
@ -1354,10 +1343,11 @@ g_param_spec_pool_list (GParamSpecPool *pool,
g_free (slists); g_free (slists);
g_mutex_unlock (&pool->mutex); g_mutex_unlock (&pool->mutex);
*n_pspecs_p = n_pspecs;
return pspecs; return pspecs;
} }
/* --- auxiliary functions --- */ /* --- auxiliary functions --- */
typedef struct typedef struct
{ {