Array copying and extending in GLib 2.61.2

A slightly more in-depth post in the mini-series this time, about various new functions which Emmanuel Fleury has landed in GLib 2.61.2 (which is due to be released soon), based on some old but not-quite-finished patches from others.

There’s g_ptr_array_copy() and g_array_copy(); and also g_ptr_array_extend() and g_ptr_array_extend_and_steal().

g_ptr_array_copy() and g_array_copy() are obvious functions and it’s not clear why they haven’t been added before. They allow you to copy a GPtrArray or a GArray, including its contents.
When copying a GPtrArray, you pass in a GCopyFunc to copy each element (for example, by increasing its reference count). If the GCopyFunc is NULL, the element is copied by value.

For example,

g_autoptr(GPtrArray) object_array = g_ptr_array_new_with_free_func (g_object_unref);

for (gsize i = 0; i < 10; i++)
  g_ptr_array_add (object_array, create_new_object (i));

object_array_copy = g_ptr_array_copy (object_array, g_object_ref, NULL);
/* object_array and object_array_copy now contain copies of the same elements, but
 * modifying one array will not modify the other */

The g_ptr_array_extend() functions are used to join one array onto the end of another. This means you can turn the following code to join the GObject elements of array2 onto the end of array1 and ref them all:

for (gsize i = 0; i < array2->len; i++)
  g_ptr_array_add (array1, g_object_ref (g_ptr_array_index (array2, i)));

into

g_ptr_array_extend (array1, array2, g_object_ref, NULL);

If you no longer need array2, you can go further and use g_ptr_array_extend_and_steal() to avoid copying each element. This might be particularly beneficial when using string arrays, where each copy (a g_strdup()) is more expensive. So the following code:

g_autoptr(GPtrArray) array1 = g_ptr_array_new_with_free_func (g_free);
for (guint i = 0; i < 10; i++)
  g_ptr_array_add (array1, g_strdup_printf ("array1 %u", i));

g_autoptr(GPtrArray) array2 = g_ptr_array_new_with_free_func (g_free);
for (guint i = 100; i < 110; i++)
  g_ptr_array_add (array2, g_strdup_printf ("array2 %u", i));

for (gsize i = 0; i < array2->len; i++)
  g_ptr_array_add (array1, g_strdup (g_ptr_array_index (array2, i)));

would become:

g_autoptr(GPtrArray) array1 = g_ptr_array_new_with_free_func (g_free);
for (guint i = 0; i < 10; i++)
  g_ptr_array_add (array1, g_strdup_printf ("array1 %u", i));

g_autoptr(GPtrArray) array2 = g_ptr_array_new_with_free_func (g_free);
for (guint i = 100; i < 110; i++)
  g_ptr_array_add (array2, g_strdup_printf ("array2 %u", i));

g_ptr_array_extend_and_steal (array1, g_steal_pointer (&amp;array2));
/* array2 has now been destroyed */

One thought on “Array copying and extending in GLib 2.61.2

  1. Pingback: g_assert_finalize_object() in GLib 2.61.2 | drboblog

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.