From f6f6b3d83c2abae8aac55c59339adcee919ab6e5 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Mon, 15 Apr 2013 15:04:34 +0200 Subject: [PATCH] garray: Add g_ptr_array_find[_with_equal_func]() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Partially based on telepathy-glib’s tp_g_ptr_array_contains(), and a patch by Xavier Claessens . Test cases included. https://bugzilla.gnome.org/show_bug.cgi?id=698064 --- docs/reference/glib/glib-sections.txt | 2 + glib/garray.c | 76 +++++++++++++++++++++++++++ glib/garray.h | 9 ++++ glib/tests/array-test.c | 55 +++++++++++++++++++ 4 files changed, 142 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 924d58f09..ca9e414d3 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2566,6 +2566,8 @@ g_ptr_array_set_size g_ptr_array_index g_ptr_array_free g_ptr_array_foreach +g_ptr_array_find +g_ptr_array_find_with_equal_func diff --git a/glib/garray.c b/glib/garray.c index ac7e58035..e4a45466d 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -34,6 +34,7 @@ #include "garray.h" #include "gbytes.h" +#include "ghash.h" #include "gslice.h" #include "gmem.h" #include "gtestutils.h" @@ -1511,6 +1512,81 @@ g_ptr_array_foreach (GPtrArray *array, (*func) (array->pdata[i], user_data); } +/** + * g_ptr_array_find: (skip) + * @haystack: pointer array to be searched + * @needle: pointer to look for + * @index_: (optional) (out caller-allocates): return location for the index of + * the element, if found + * + * Checks whether @needle exists in @haystack. If the element is found, %TRUE is + * returned and the element’s index is returned in @index_ (if non-%NULL). + * Otherwise, %FALSE is returned and @index_ is undefined. If @needle exists + * multiple times in @haystack, the index of the first instance is returned. + * + * This does pointer comparisons only. If you want to use more complex equality + * checks, such as string comparisons, use g_ptr_array_find_with_equal_func(). + * + * Returns: %TRUE if @needle is one of the elements of @haystack + * Since: 2.54 + */ +gboolean +g_ptr_array_find (GPtrArray *haystack, + gconstpointer needle, + guint *index_) +{ + return g_ptr_array_find_with_equal_func (haystack, needle, NULL, index_); +} + +/** + * g_ptr_array_find_with_equal_func: (skip) + * @haystack: pointer array to be searched + * @needle: pointer to look for + * @equal_func: (nullable): the function to call for each element, which should + * return %TRUE when the desired element is found; or %NULL to use pointer + * equality + * @index_: (optional) (out caller-allocates): return location for the index of + * the element, if found + * + * Checks whether @needle exists in @haystack, using the given @equal_func. + * If the element is found, %TRUE is returned and the element’s index is + * returned in @index_ (if non-%NULL). Otherwise, %FALSE is returned and @index_ + * is undefined. If @needle exists multiple times in @haystack, the index of + * the first instance is returned. + * + * @equal_func is called with the element from the array as its first parameter, + * and @needle as its second parameter. If @equal_func is %NULL, pointer + * equality is used. + * + * Returns: %TRUE if @needle is one of the elements of @haystack + * Since: 2.54 + */ +gboolean +g_ptr_array_find_with_equal_func (GPtrArray *haystack, + gconstpointer needle, + GEqualFunc equal_func, + guint *index_) +{ + guint i; + + g_return_val_if_fail (haystack != NULL, FALSE); + + if (equal_func == NULL) + equal_func = g_direct_equal; + + for (i = 0; i < haystack->len; i++) + { + if (equal_func (g_ptr_array_index (haystack, i), needle)) + { + if (index_ != NULL) + *index_ = i; + return TRUE; + } + } + + return FALSE; +} + /** * SECTION:arrays_byte * @title: Byte Arrays diff --git a/glib/garray.h b/glib/garray.h index 35e298faf..8b3b7980d 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -182,6 +182,15 @@ GLIB_AVAILABLE_IN_ALL void g_ptr_array_foreach (GPtrArray *array, GFunc func, gpointer user_data); +GLIB_AVAILABLE_IN_2_54 +gboolean g_ptr_array_find (GPtrArray *haystack, + gconstpointer needle, + guint *index_); +GLIB_AVAILABLE_IN_2_54 +gboolean g_ptr_array_find_with_equal_func (GPtrArray *haystack, + gconstpointer needle, + GEqualFunc equal_func, + guint *index_); /* Byte arrays, an array of guint8. Implemented as a GArray, diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index a0074d4c3..61851e0dc 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -547,6 +547,59 @@ pointer_array_sort_with_data (void) g_ptr_array_free (gparray, TRUE); } +static void +pointer_array_find_empty (void) +{ + GPtrArray *array; + guint idx; + + array = g_ptr_array_new (); + + g_assert_false (g_ptr_array_find (array, "some-value", NULL)); /* NULL index */ + g_assert_false (g_ptr_array_find (array, "some-value", &idx)); /* non-NULL index */ + g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, NULL)); /* NULL index */ + g_assert_false (g_ptr_array_find_with_equal_func (array, "some-value", g_str_equal, &idx)); /* NULL index */ + + g_ptr_array_free (array, TRUE); +} + +static void +pointer_array_find_non_empty (void) +{ + GPtrArray *array; + guint idx; + const gchar *str_pointer = "static-string"; + + array = g_ptr_array_new (); + + g_ptr_array_add (array, "some"); + g_ptr_array_add (array, "random"); + g_ptr_array_add (array, "values"); + g_ptr_array_add (array, "some"); + g_ptr_array_add (array, "duplicated"); + g_ptr_array_add (array, (gpointer) str_pointer); + + g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, NULL)); /* NULL index */ + g_assert_true (g_ptr_array_find_with_equal_func (array, "random", g_str_equal, &idx)); /* non-NULL index */ + g_assert_cmpuint (idx, ==, 1); + + g_assert_true (g_ptr_array_find_with_equal_func (array, "some", g_str_equal, &idx)); /* duplicate element */ + g_assert_cmpuint (idx, ==, 0); + + g_assert_false (g_ptr_array_find_with_equal_func (array, "nope", g_str_equal, NULL)); + + g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, g_str_equal, &idx)); + g_assert_cmpuint (idx, ==, 5); + idx = G_MAXUINT; + g_assert_true (g_ptr_array_find_with_equal_func (array, str_pointer, NULL, &idx)); /* NULL equal func */ + g_assert_cmpuint (idx, ==, 5); + idx = G_MAXUINT; + g_assert_true (g_ptr_array_find (array, str_pointer, &idx)); /* NULL equal func */ + g_assert_cmpuint (idx, ==, 5); + + g_ptr_array_free (array, TRUE); +} + static void byte_array_append (void) { @@ -854,6 +907,8 @@ main (int argc, char *argv[]) g_test_add_func ("/pointerarray/free-func", pointer_array_free_func); g_test_add_func ("/pointerarray/sort", pointer_array_sort); g_test_add_func ("/pointerarray/sort-with-data", pointer_array_sort_with_data); + g_test_add_func ("/pointerarray/find/empty", pointer_array_find_empty); + g_test_add_func ("/pointerarray/find/non-empty", pointer_array_find_non_empty); /* byte arrays */ g_test_add_func ("/bytearray/append", byte_array_append);