[glib: 3/5] Adding g_ptr_array_extend() function to glib/garray.c



commit 43ad244df2196de22484ef1e04aebbac1560388c
Author: Emmanuel Fleury <emmanuel fleury u-bordeaux fr>
Date:   Wed Jun 19 12:40:27 2019 +0200

    Adding g_ptr_array_extend() function to glib/garray.c
    
    Related to issue #269

 docs/reference/glib/glib-sections.txt |   1 +
 glib/garray.c                         |  51 +++++++++++++++
 glib/garray.h                         |   5 ++
 glib/tests/array-test.c               | 119 ++++++++++++++++++++++++++++++++++
 4 files changed, 176 insertions(+)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index 0be2e5244..a408dc238 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2644,6 +2644,7 @@ g_ptr_array_set_free_func
 g_ptr_array_ref
 g_ptr_array_unref
 g_ptr_array_add
+g_ptr_array_extend
 g_ptr_array_insert
 g_ptr_array_remove
 g_ptr_array_remove_index
diff --git a/glib/garray.c b/glib/garray.c
index b4773721a..f81b2c2c9 100644
--- a/glib/garray.c
+++ b/glib/garray.c
@@ -1538,6 +1538,57 @@ g_ptr_array_add (GPtrArray *array,
   rarray->pdata[rarray->len++] = data;
 }
 
+/**
+ * g_ptr_array_extend:
+ * @array_to_extend: a #GPtrArray.
+ * @array: (transfer none): a #GPtrArray to add to the end of @array_to_extend.
+ * @func: (nullable): a copy function used to copy every element in the array
+ * @user_data: user data passed to the copy function @func, or %NULL
+ *
+ * Adds all pointers of @array to the end of the array @array_to_extend.
+ * The array will grow in size automatically if needed. @array_to_extend is
+ * modified in-place.
+ *
+ * @func, as a #GCopyFunc, takes two arguments, the data to be copied
+ * and a @user_data pointer. On common processor architectures, it's safe to
+ * pass %NULL as @user_data if the copy function takes only one argument. You
+ * may get compiler warnings from this though if compiling with GCC’s
+ * `-Wcast-function-type` warning.
+ *
+ * If @func is %NULL, then only the pointers (and not what they are
+ * pointing to) are copied to the new #GPtrArray.
+ *
+ * Since: 2.62
+ **/
+void
+g_ptr_array_extend (GPtrArray  *array_to_extend,
+                    GPtrArray  *array,
+                    GCopyFunc   func,
+                    gpointer    user_data)
+{
+  GRealPtrArray *rarray_to_extend = (GRealPtrArray *) array_to_extend;
+  gsize i;
+
+  g_return_if_fail (array_to_extend != NULL);
+  g_return_if_fail (array != NULL);
+
+  g_ptr_array_maybe_expand (rarray_to_extend, array->len);
+
+  if (func != NULL)
+    {
+      for (i = 0; i < array->len; i++)
+        rarray_to_extend->pdata[i + rarray_to_extend->len] =
+          func (array->pdata[i], user_data);
+    }
+  else
+    {
+      memcpy (rarray_to_extend->pdata + rarray_to_extend->len, array->pdata,
+              array->len * sizeof (*array->pdata));
+    }
+
+  rarray_to_extend->len += array->len;
+}
+
 /**
  * g_ptr_array_insert:
  * @array: a #GPtrArray
diff --git a/glib/garray.h b/glib/garray.h
index a92c7cd66..bfa586e88 100644
--- a/glib/garray.h
+++ b/glib/garray.h
@@ -177,6 +177,11 @@ GPtrArray *g_ptr_array_remove_range       (GPtrArray        *array,
 GLIB_AVAILABLE_IN_ALL
 void       g_ptr_array_add                (GPtrArray        *array,
                                           gpointer          data);
+GLIB_AVAILABLE_IN_2_62
+void g_ptr_array_extend                   (GPtrArray        *array_to_extend,
+                                           GPtrArray        *array,
+                                           GCopyFunc         func,
+                                           gpointer          user_data);
 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 a07ff2a28..e79e7e453 100644
--- a/glib/tests/array-test.c
+++ b/glib/tests/array-test.c
@@ -824,6 +824,124 @@ pointer_array_copy (void)
   g_free (array_test);
 }
 
+/* Test the g_ptr_array_extend() function */
+static void
+pointer_array_extend (void)
+{
+  GPtrArray *ptr_array, *ptr_array2;
+  gsize i;
+  const gsize array_size = 100;
+  gsize *array_test = g_malloc (array_size * sizeof (gsize));
+
+  if (g_test_undefined ())
+    {
+      /* Testing degenerated cases */
+      ptr_array = g_ptr_array_sized_new (0);
+      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                             "*assertion*!= NULL*");
+      g_ptr_array_extend (NULL, ptr_array, NULL, NULL);
+      g_test_assert_expected_messages ();
+
+      g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL,
+                             "*assertion*!= NULL*");
+      g_ptr_array_extend (ptr_array, NULL, NULL, NULL);
+      g_test_assert_expected_messages ();
+
+      g_ptr_array_unref (ptr_array);
+    }
+
+  /* Initializing array_test */
+  for (i = 0; i < array_size; i++)
+    array_test[i] = i;
+
+  /* Testing extend with array of size zero */
+  ptr_array = g_ptr_array_sized_new (0);
+  ptr_array2 = g_ptr_array_sized_new (0);
+
+  g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
+
+  g_assert_cmpuint (ptr_array->len, ==, 0);
+  g_assert_cmpuint (ptr_array2->len, ==, 0);
+
+  g_ptr_array_unref (ptr_array);
+  g_ptr_array_unref (ptr_array2);
+
+  /* Testing extend an array of size zero */
+  ptr_array = g_ptr_array_sized_new (array_size);
+  ptr_array2 = g_ptr_array_sized_new (0);
+
+  for (i = 0; i < array_size; i++)
+    {
+      g_ptr_array_add (ptr_array, &array_test[i]);
+    }
+
+  g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
+
+  for (i = 0; i < array_size; i++)
+    g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
+
+  g_ptr_array_unref (ptr_array);
+  g_ptr_array_unref (ptr_array2);
+
+  /* Testing extend an array of size zero */
+  ptr_array = g_ptr_array_sized_new (0);
+  ptr_array2 = g_ptr_array_sized_new (array_size);
+
+  for (i = 0; i < array_size; i++)
+    {
+      g_ptr_array_add (ptr_array2, &array_test[i]);
+    }
+
+  g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
+
+  for (i = 0; i < array_size; i++)
+    g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
+
+  g_ptr_array_unref (ptr_array);
+  g_ptr_array_unref (ptr_array2);
+
+  /* Testing simple extend */
+  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 (ptr_array, ptr_array2, NULL, NULL);
+
+  for (i = 0; i < array_size; i++)
+    g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
+
+  g_ptr_array_unref (ptr_array);
+  g_ptr_array_unref (ptr_array2);
+
+  /* Testing extend with GCopyFunc */
+  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 (ptr_array, ptr_array2, ptr_array_copy_func, NULL);
+
+  for (i = 0; i < array_size; i++)
+    g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
+
+  /* Clean-up memory */
+  for (i = array_size / 2; i < array_size; i++)
+    g_free (g_ptr_array_index (ptr_array, i));
+
+  g_ptr_array_unref (ptr_array);
+  g_ptr_array_unref (ptr_array2);
+  g_free (array_test);
+}
+
 static gint
 ptr_compare (gconstpointer p1, gconstpointer p2)
 {
@@ -1341,6 +1459,7 @@ main (int argc, char *argv[])
   g_test_add_func ("/pointerarray/ref-count", pointer_array_ref_count);
   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/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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]