From 46f70e9901ad8ee996a746d1f5f830618d200901 Mon Sep 17 00:00:00 2001 From: Emmanuel Fleury Date: Tue, 28 May 2019 09:46:20 +0200 Subject: [PATCH] Adding a function g_array_copy() to glib/garray.c Original code from Simon van der Linden Close issue #236 --- docs/reference/glib/glib-sections.txt | 1 + glib/garray.c | 28 ++++++++++++++ glib/garray.h | 2 + glib/tests/array-test.c | 53 +++++++++++++++++++++++++++ 4 files changed, 84 insertions(+) diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 058000e16..2ab5b17fa 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -2611,6 +2611,7 @@ g_string_chunk_free GArray g_array_new g_array_sized_new +g_array_copy g_array_ref g_array_unref g_array_get_element_size diff --git a/glib/garray.c b/glib/garray.c index 2b7957a92..2b35a9e0e 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -999,6 +999,34 @@ g_ptr_array_sized_new (guint reserved_size) return (GPtrArray*) array; } +/** + * g_array_copy: + * @array: A #GArray. + * + * Create a shallow copy of a #GArray. If the array elements consist of + * pointers to data, the pointers are copied but the actual data is not. + * + * Returns: (transfer container): A copy of @array. + * + * Since: 2.62 + **/ +GArray * +g_array_copy (GArray *array) +{ + GRealArray *rarray = (GRealArray *) array; + GRealArray *new_rarray; + + g_return_val_if_fail (rarray != NULL, NULL); + + new_rarray = + (GRealArray *) g_array_sized_new (rarray->zero_terminated, rarray->clear, + rarray->elt_size, rarray->len); + new_rarray->len = rarray->len; + memcpy (new_rarray->data, rarray->data, rarray->alloc); + + return (GArray *) new_rarray; +} + /** * g_ptr_array_new_with_free_func: * @element_free_func: (nullable): A function to free elements with diff --git a/glib/garray.h b/glib/garray.h index e97718b74..c4ec4aeaa 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -75,6 +75,8 @@ GArray* g_array_sized_new (gboolean zero_terminated, gboolean clear_, guint element_size, guint reserved_size); +GLIB_AVAILABLE_IN_2_62 +GArray* g_array_copy (GArray *array); GLIB_AVAILABLE_IN_ALL gchar* g_array_free (GArray *array, gboolean free_segment); diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index 217ef9274..b896b2d16 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -466,6 +466,58 @@ int_compare (gconstpointer p1, gconstpointer p2) return *i1 - *i2; } +static void +array_copy (gconstpointer test_data) +{ + GArray *array, *array_copy; + gsize i; + const ArrayTestData *config = test_data; + const gsize array_size = 100; + + /* Testing degenerated cases */ + if (g_test_undefined ()) + { + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion*!= NULL*"); + array = g_array_copy (NULL); + g_test_assert_expected_messages (); + + g_assert_null (array); + } + + /* Testing simple copy */ + array = g_array_new (config->zero_terminated, config->clear_, sizeof (gint)); + + for (i = 0; i < array_size; i++) + g_array_append_val (array, i); + + array_copy = g_array_copy (array); + + /* Check internal data */ + for (i = 0; i < array_size; i++) + g_assert_cmpuint (g_array_index (array, gint, i), ==, + g_array_index (array_copy, gint, i)); + + /* Check internal parameters ('zero_terminated' flag) */ + if (config->zero_terminated) + { + const gint *data = (const gint *) array_copy->data; + g_assert_cmpint (data[array_copy->len], ==, 0); + } + + /* Check internal parameters ('clear' flag) */ + if (config->clear_) + { + g_array_set_size (array_copy, array_copy->len + 5); + for (i = array_copy->len; i < array_copy->len + 5; i++) + g_assert_cmpint (g_array_index (array_copy, gint, i), ==, 0); + } + + /* Clean-up */ + g_array_unref (array); + g_array_unref (array_copy); +} + static int int_compare_data (gconstpointer p1, gconstpointer p2, gpointer data) { @@ -1506,6 +1558,7 @@ main (int argc, char *argv[]) add_array_test ("/array/remove-index", &array_configurations[i], array_remove_index); add_array_test ("/array/remove-index-fast", &array_configurations[i], array_remove_index_fast); add_array_test ("/array/remove-range", &array_configurations[i], array_remove_range); + add_array_test ("/array/copy", &array_configurations[i], array_copy); add_array_test ("/array/sort", &array_configurations[i], array_sort); add_array_test ("/array/sort-with-data", &array_configurations[i], array_sort_with_data); }