garray: Add g_ptr_array_find[_with_equal_func]()

Partially based on telepathy-glib’s tp_g_ptr_array_contains(), and a
patch by Xavier Claessens <xavier.claessens@collabora.co.uk>.

Test cases included.

https://bugzilla.gnome.org/show_bug.cgi?id=698064
This commit is contained in:
Philip Withnall 2013-04-15 15:04:34 +02:00 committed by Philip Withnall
parent 42a8e952ef
commit f6f6b3d83c
4 changed files with 142 additions and 0 deletions

View File

@ -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
</SECTION>

View File

@ -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 elements 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 elements 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

View File

@ -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,

View File

@ -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);