mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
garray: Add g_ptr_array_steal_index*() functions
These make it easy to steal elements from pointer arrays without having the array’s GDestroyNotify called on them, similarly to what’s possible with g_hash_table_steal(). Signed-off-by: Philip Withnall <withnall@endlessm.com> https://bugzilla.gnome.org/show_bug.cgi?id=795376
This commit is contained in:
parent
e6200eaea2
commit
d0a48f26c7
@ -1194,7 +1194,8 @@ g_ptr_array_set_size (GPtrArray *array,
|
||||
static gpointer
|
||||
ptr_array_remove_index (GPtrArray *array,
|
||||
guint index_,
|
||||
gboolean fast)
|
||||
gboolean fast,
|
||||
gboolean free_element)
|
||||
{
|
||||
GRealPtrArray *rarray = (GRealPtrArray *) array;
|
||||
gpointer result;
|
||||
@ -1206,7 +1207,7 @@ ptr_array_remove_index (GPtrArray *array,
|
||||
|
||||
result = rarray->pdata[index_];
|
||||
|
||||
if (rarray->element_free_func != NULL)
|
||||
if (rarray->element_free_func != NULL && free_element)
|
||||
rarray->element_free_func (rarray->pdata[index_]);
|
||||
|
||||
if (index_ != rarray->len - 1 && !fast)
|
||||
@ -1240,7 +1241,7 @@ gpointer
|
||||
g_ptr_array_remove_index (GPtrArray *array,
|
||||
guint index_)
|
||||
{
|
||||
return ptr_array_remove_index (array, index_, FALSE);
|
||||
return ptr_array_remove_index (array, index_, FALSE, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1262,7 +1263,49 @@ gpointer
|
||||
g_ptr_array_remove_index_fast (GPtrArray *array,
|
||||
guint index_)
|
||||
{
|
||||
return ptr_array_remove_index (array, index_, TRUE);
|
||||
return ptr_array_remove_index (array, index_, TRUE, TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_steal_index:
|
||||
* @array: a #GPtrArray
|
||||
* @index_: the index of the pointer to steal
|
||||
*
|
||||
* Removes the pointer at the given index from the pointer array.
|
||||
* The following elements are moved down one place. The #GDestroyNotify for
|
||||
* @array is *not* called on the removed element; ownership is transferred to
|
||||
* the caller of this function.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the pointer which was removed
|
||||
* Since: 2.58
|
||||
*/
|
||||
gpointer
|
||||
g_ptr_array_steal_index (GPtrArray *array,
|
||||
guint index_)
|
||||
{
|
||||
return ptr_array_remove_index (array, index_, FALSE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_steal_index_fast:
|
||||
* @array: a #GPtrArray
|
||||
* @index_: the index of the pointer to steal
|
||||
*
|
||||
* Removes the pointer at the given index from the pointer array.
|
||||
* The last element in the array is used to fill in the space, so
|
||||
* this function does not preserve the order of the array. But it
|
||||
* is faster than g_ptr_array_steal_index(). The #GDestroyNotify for @array is
|
||||
* *not* called on the removed element; ownership is transferred to the caller
|
||||
* of this function.
|
||||
*
|
||||
* Returns: (transfer full) (nullable): the pointer which was removed
|
||||
* Since: 2.58
|
||||
*/
|
||||
gpointer
|
||||
g_ptr_array_steal_index_fast (GPtrArray *array,
|
||||
guint index_)
|
||||
{
|
||||
return ptr_array_remove_index (array, index_, TRUE, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -154,6 +154,12 @@ gpointer g_ptr_array_remove_index (GPtrArray *array,
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gpointer g_ptr_array_remove_index_fast (GPtrArray *array,
|
||||
guint index_);
|
||||
GLIB_AVAILABLE_IN_2_58
|
||||
gpointer g_ptr_array_steal_index (GPtrArray *array,
|
||||
guint index_);
|
||||
GLIB_AVAILABLE_IN_2_58
|
||||
gpointer g_ptr_array_steal_index_fast (GPtrArray *array,
|
||||
guint index_);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gboolean g_ptr_array_remove (GPtrArray *array,
|
||||
gpointer data);
|
||||
|
@ -658,6 +658,59 @@ pointer_array_find_non_empty (void)
|
||||
g_ptr_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
steal_destroy_notify (gpointer data)
|
||||
{
|
||||
guint *counter = data;
|
||||
*counter = *counter + 1;
|
||||
}
|
||||
|
||||
/* Test that g_ptr_array_steal_index() and g_ptr_array_steal_index_fast() can
|
||||
* remove elements from a pointer array without the #GDestroyNotify being called. */
|
||||
static void
|
||||
pointer_array_steal (void)
|
||||
{
|
||||
guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
|
||||
gpointer out1, out2;
|
||||
GPtrArray *array = g_ptr_array_new_with_free_func (steal_destroy_notify);
|
||||
|
||||
g_ptr_array_add (array, &i1);
|
||||
g_ptr_array_add (array, &i2);
|
||||
g_ptr_array_add (array, &i3);
|
||||
g_ptr_array_add (array, &i4);
|
||||
|
||||
g_assert_cmpuint (array->len, ==, 4);
|
||||
|
||||
/* Remove a single element. */
|
||||
out1 = g_ptr_array_steal_index (array, 0);
|
||||
g_assert_true (out1 == &i1);
|
||||
g_assert_cmpuint (i1, ==, 0); /* should not have been destroyed */
|
||||
|
||||
/* Following elements should have been moved down. */
|
||||
g_assert_cmpuint (array->len, ==, 3);
|
||||
g_assert_true (g_ptr_array_index (array, 0) == &i2);
|
||||
g_assert_true (g_ptr_array_index (array, 1) == &i3);
|
||||
g_assert_true (g_ptr_array_index (array, 2) == &i4);
|
||||
|
||||
/* Remove another element, quickly. */
|
||||
out2 = g_ptr_array_steal_index_fast (array, 0);
|
||||
g_assert_true (out2 == &i2);
|
||||
g_assert_cmpuint (i2, ==, 0); /* should not have been destroyed */
|
||||
|
||||
/* Last element should have been swapped in place. */
|
||||
g_assert_cmpuint (array->len, ==, 2);
|
||||
g_assert_true (g_ptr_array_index (array, 0) == &i4);
|
||||
g_assert_true (g_ptr_array_index (array, 1) == &i3);
|
||||
|
||||
/* Check that destroying the pointer array doesn’t affect the stolen elements. */
|
||||
g_ptr_array_unref (array);
|
||||
|
||||
g_assert_cmpuint (i1, ==, 0);
|
||||
g_assert_cmpuint (i2, ==, 0);
|
||||
g_assert_cmpuint (i3, ==, 1);
|
||||
g_assert_cmpuint (i4, ==, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
byte_array_append (void)
|
||||
{
|
||||
@ -970,6 +1023,7 @@ main (int argc, char *argv[])
|
||||
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);
|
||||
g_test_add_func ("/pointerarray/steal", pointer_array_steal);
|
||||
|
||||
/* byte arrays */
|
||||
g_test_add_func ("/bytearray/append", byte_array_append);
|
||||
|
Loading…
Reference in New Issue
Block a user