From 0675703af08d69e2edab545bb8fa97d5cf049d42 Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Wed, 19 Jun 2019 12:42:08 +0200 Subject: [PATCH] Adding g_ptr_array_extend_and_steal() function to glib/garray.c --- docs/reference/glib/glib-sections.txt | 1 + glib/garray.c | 32 +++++++++++++++ glib/garray.h | 3 ++ glib/tests/array-test.c | 58 +++++++++++++++++++++++++++ 4 files changed, 94 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index a408dc238..058000e16 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2645,6 +2645,7 @@ g_ptr_array_ref g_ptr_array_unref g_ptr_array_add g_ptr_array_extend +g_ptr_array_extend_and_steal g_ptr_array_insert g_ptr_array_remove g_ptr_array_remove_index diff --git a/glib/garray.c b/glib/garray.c index f81b2c2c9..2b7957a92 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -1589,6 +1589,38 @@ g_ptr_array_extend (GPtrArray *array_to_extend, rarray_to_extend->len += array->len; } +/** + * g_ptr_array_extend_and_steal: + * @array_to_extend: (transfer none): a #GPtrArray. + * @array: (transfer container): a #GPtrArray to add to the end of + * @array_to_extend. + * + * Adds all the pointers in @array to the end of @array_to_extend, transferring + * ownership of each element from @array to @array_to_extend and modifying + * @array_to_extend in-place. @array is then freed. + * + * As with g_ptr_array_free(), @array will be destroyed if its reference count + * is 1. If its reference count is higher, it will be decremented and the + * length of @array set to zero. + * + * Since: 2.62 + **/ +void +g_ptr_array_extend_and_steal (GPtrArray *array_to_extend, + GPtrArray *array) +{ + gpointer *pdata; + + g_ptr_array_extend (array_to_extend, array, NULL, NULL); + + /* Get rid of @array without triggering the GDestroyNotify attached + * to the elements moved from @array to @array_to_extend. */ + pdata = g_steal_pointer (&array->pdata); + array->len = 0; + g_ptr_array_unref (array); + g_free (pdata); +} + /** * g_ptr_array_insert: * @array: a #GPtrArray diff --git a/glib/garray.h b/glib/garray.h index bfa586e88..e97718b74 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -182,6 +182,9 @@ void g_ptr_array_extend (GPtrArray *array_to_extend, GPtrArray *array, GCopyFunc func, gpointer user_data); +GLIB_AVAILABLE_IN_2_62 +void g_ptr_array_extend_and_steal (GPtrArray *array_to_extend, + GPtrArray *array); GLIB_AVAILABLE_IN_2_40 void g_ptr_array_insert (GPtrArray *array, gint index_, diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index e79e7e453..217ef9274 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -942,6 +942,63 @@ pointer_array_extend (void) g_free (array_test); } +/* Test the g_ptr_array_extend_and_steal() function */ +static void +pointer_array_extend_and_steal (void) +{ + GPtrArray *ptr_array, *ptr_array2, *ptr_array3; + gsize i; + const gsize array_size = 100; + gsize *array_test = g_malloc (array_size * sizeof (gsize)); + + /* Initializing array_test */ + for (i = 0; i < array_size; i++) + array_test[i] = i; + + /* Testing simple extend_and_steal() */ + ptr_array = g_ptr_array_sized_new (array_size / 2); + ptr_array2 = g_ptr_array_sized_new (array_size / 2); + + for (i = 0; i < array_size / 2; i++) + { + g_ptr_array_add (ptr_array, &array_test[i]); + g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]); + } + + g_ptr_array_extend_and_steal (ptr_array, ptr_array2); + + for (i = 0; i < array_size; i++) + g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i); + + g_ptr_array_free (ptr_array, TRUE); + + /* Testing extend_and_steal() with a pending reference to stolen array */ + ptr_array = g_ptr_array_sized_new (array_size / 2); + ptr_array2 = g_ptr_array_sized_new (array_size / 2); + + for (i = 0; i < array_size / 2; i++) + { + g_ptr_array_add (ptr_array, &array_test[i]); + g_ptr_array_add (ptr_array2, &array_test[i + (array_size / 2)]); + } + + ptr_array3 = g_ptr_array_ref (ptr_array2); + + g_ptr_array_extend_and_steal (ptr_array, ptr_array2); + + for (i = 0; i < array_size; i++) + g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i); + + g_assert_cmpuint (ptr_array3->len, ==, 0); + g_assert_null (ptr_array3->pdata); + + g_ptr_array_free (ptr_array, TRUE); + g_ptr_array_free (ptr_array3, TRUE); + + /* Final memory clean-up */ + g_free (array_test); +} + static gint ptr_compare (gconstpointer p1, gconstpointer p2) { @@ -1460,6 +1517,7 @@ main (int argc, char *argv[]) g_test_add_func ("/pointerarray/free-func", pointer_array_free_func); g_test_add_func ("/pointerarray/array_copy", pointer_array_copy); g_test_add_func ("/pointerarray/array_extend", pointer_array_extend); + g_test_add_func ("/pointerarray/array_extend_and_steal", pointer_array_extend_and_steal); 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);