From a85246af3be7afd253727d811e4ce719b77e633e Mon Sep 17 00:00:00 2001 From: Jason Francis Date: Sat, 12 Mar 2022 22:09:29 -0500 Subject: [PATCH] gio: Add g_list_store_find_with_equal_func_full() Fixes: #2447 --- docs/reference/gio/gio-sections-common.txt | 1 + docs/reference/glib/glib-sections.txt | 1 + gio/gliststore.c | 41 ++++++++++++++++++++-- gio/gliststore.h | 7 ++++ gio/tests/glistmodel.c | 23 ++++++++++++ glib/gtypes.h | 21 +++++++++++ 6 files changed, 92 insertions(+), 2 deletions(-) diff --git a/docs/reference/gio/gio-sections-common.txt b/docs/reference/gio/gio-sections-common.txt index 4e88a597e..383cfd1a1 100644 --- a/docs/reference/gio/gio-sections-common.txt +++ b/docs/reference/gio/gio-sections-common.txt @@ -4765,6 +4765,7 @@ g_list_store_splice g_list_store_sort g_list_store_find g_list_store_find_with_equal_func +g_list_store_find_with_equal_func_full G_TYPE_LIST_STORE diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 3532d28cb..2932313cd 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2875,6 +2875,7 @@ g_hash_table_new_full g_hash_table_new_similar GHashFunc GEqualFunc +GEqualFuncFull g_hash_table_insert g_hash_table_replace g_hash_table_add diff --git a/gio/gliststore.c b/gio/gliststore.c index da7d12ce5..65ff5d4e9 100644 --- a/gio/gliststore.c +++ b/gio/gliststore.c @@ -495,6 +495,14 @@ g_list_store_splice (GListStore *store, g_list_store_items_changed (store, position, n_removals, n_additions); } +static gboolean +simple_equal (gconstpointer a, + gconstpointer b, + gpointer equal_func) +{ + return ((GEqualFunc) equal_func) (a, b); +} + /** * g_list_store_find_with_equal_func: * @store: a #GListStore @@ -503,7 +511,7 @@ g_list_store_splice (GListStore *store, * @position: (out) (optional): the first position of @item, if it was found. * * Looks up the given @item in the list store by looping over the items and - * comparing them with @compare_func until the first occurrence of @item which + * comparing them with @equal_func until the first occurrence of @item which * matches. If @item was not found, then @position will not be set, and this * method will return %FALSE. * @@ -517,6 +525,35 @@ g_list_store_find_with_equal_func (GListStore *store, gpointer item, GEqualFunc equal_func, guint *position) +{ + g_return_val_if_fail (equal_func != NULL, FALSE); + + return g_list_store_find_with_equal_func_full (store, item, simple_equal, + equal_func, position); +} + +/** + * g_list_store_find_with_equal_func_full: + * @store: a #GListStore + * @item: (type GObject): an item + * @equal_func: (scope call): A custom equality check function + * @user_data: (closure): user data for @equal_func + * @position: (out) (optional): the first position of @item, if it was found. + * + * Like g_list_store_find_with_equal_func() but with an additional @user_data + * that is passed to @equal_func. + * + * Returns: Whether @store contains @item. If it was found, @position will be + * set to the position where @item occurred for the first time. + * + * Since: 2.74 + */ +gboolean +g_list_store_find_with_equal_func_full (GListStore *store, + gpointer item, + GEqualFuncFull equal_func, + gpointer user_data, + guint *position) { GSequenceIter *iter, *begin, *end; @@ -536,7 +573,7 @@ g_list_store_find_with_equal_func (GListStore *store, gpointer iter_item; iter_item = g_sequence_get (iter); - if (equal_func (iter_item, item)) + if (equal_func (iter_item, item, user_data)) { if (position) *position = g_sequence_iter_get_position (iter); diff --git a/gio/gliststore.h b/gio/gliststore.h index ef3b83951..aa5a7331c 100644 --- a/gio/gliststore.h +++ b/gio/gliststore.h @@ -83,6 +83,13 @@ gboolean g_list_store_find_with_equal_func (GListSt GEqualFunc equal_func, guint *position); +GLIB_AVAILABLE_IN_2_74 +gboolean g_list_store_find_with_equal_func_full (GListStore *store, + gpointer item, + GEqualFuncFull equal_func, + gpointer user_data, + guint *position); + G_END_DECLS #endif /* __G_LIST_STORE_H__ */ diff --git a/gio/tests/glistmodel.c b/gio/tests/glistmodel.c index e50969ead..a65c2f3b1 100644 --- a/gio/tests/glistmodel.c +++ b/gio/tests/glistmodel.c @@ -813,6 +813,18 @@ list_model_casecmp_action_by_name (gconstpointer a, g_action_get_name (G_ACTION (b))) == 0; } +static gboolean +list_model_casecmp_action_by_name_full (gconstpointer a, + gconstpointer b, + gpointer user_data) +{ + char buf[4]; + const char *suffix = user_data; + + g_snprintf (buf, sizeof buf, "%s%s", g_action_get_name (G_ACTION (b)), suffix); + return g_strcmp0 (g_action_get_name (G_ACTION (a)), buf) == 0; +} + /* Test if find() and find_with_equal_func() works */ static void test_store_find (void) @@ -866,6 +878,17 @@ test_store_find (void) g_assert_cmpint (position, ==, 2); g_clear_object (&other_item); + /* try to find element which should only work with custom equality check and string concat */ + other_item = g_simple_action_new ("c", NULL); + g_assert_false (g_list_store_find (store, other_item, NULL)); + g_assert_true (g_list_store_find_with_equal_func_full (store, + other_item, + list_model_casecmp_action_by_name_full, + "cc", + &position)); + g_assert_cmpint (position, ==, 3); + g_clear_object (&other_item); + for (i = 0; i < G_N_ELEMENTS (item_strs); i++) g_clear_object(&items[i]); g_clear_object (&store); diff --git a/glib/gtypes.h b/glib/gtypes.h index ea2a49057..3d8763df5 100644 --- a/glib/gtypes.h +++ b/glib/gtypes.h @@ -110,6 +110,27 @@ typedef gint (*GCompareDataFunc) (gconstpointer a, gpointer user_data); typedef gboolean (*GEqualFunc) (gconstpointer a, gconstpointer b); + +/** + * GEqualFuncFull: + * @a: a value + * @b: a value to compare with + * @user_data: user data provided by the caller + * + * Specifies the type of a function used to test two values for + * equality. The function should return %TRUE if both values are equal + * and %FALSE otherwise. + * + * This is a version of #GEqualFunc which provides a @user_data closure from + * the caller. + * + * Returns: %TRUE if @a = @b; %FALSE otherwise + * Since: 2.74 + */ +typedef gboolean (*GEqualFuncFull) (gconstpointer a, + gconstpointer b, + gpointer user_data); + typedef void (*GDestroyNotify) (gpointer data); typedef void (*GFunc) (gpointer data, gpointer user_data);