summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Withnall <philip@tecnocode.co.uk>2019-10-07 13:07:56 +0000
committerPhilip Withnall <philip@tecnocode.co.uk>2019-10-07 13:07:56 +0000
commit038ec3de31b0aa78aaed002dbd12a51cd059b932 (patch)
tree619b5457caad11219db9b6fbb4352400ff1b3921
parentc88f106471c9495a10f2359613252c511156db29 (diff)
parent7bada8394dae1128558734fb655a5abb529a630c (diff)
downloadglib-038ec3de31b0aa78aaed002dbd12a51cd059b932.tar.gz
Merge branch 'add_array_steal_function' into 'master'
Add g_array_steal(), g_ptr_array_steal() and g_byte_array_steal() Closes #285 See merge request GNOME/glib!1019
-rw-r--r--docs/reference/glib/glib-sections.txt3
-rw-r--r--glib/garray.c113
-rw-r--r--glib/garray.h9
-rw-r--r--glib/tests/array-test.c134
4 files changed, 258 insertions, 1 deletions
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index c67af683d..08ff50ac2 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -2805,6 +2805,7 @@ g_string_chunk_free
<FILE>arrays</FILE>
GArray
g_array_new
+g_array_steal
g_array_sized_new
g_array_copy
g_array_ref
@@ -2833,6 +2834,7 @@ g_array_free
<FILE>arrays_pointer</FILE>
GPtrArray
g_ptr_array_new
+g_ptr_array_steal
g_ptr_array_sized_new
g_ptr_array_new_with_free_func
g_ptr_array_copy
@@ -2868,6 +2870,7 @@ g_ptr_array_find_with_equal_func
<SUBSECTION>
GByteArray
g_byte_array_new
+g_byte_array_steal
g_byte_array_new_take
g_byte_array_sized_new
g_byte_array_ref
diff --git a/glib/garray.c b/glib/garray.c
index 4be4988cb..2e8dd0b6b 100644
--- a/glib/garray.c
+++ b/glib/garray.c
@@ -166,6 +166,57 @@ g_array_new (gboolean zero_terminated,
}
/**
+ * g_array_steal:
+ * @array: a #GArray.
+ * @len: (optional) (out caller-allocates): pointer to retrieve the number of
+ * elements of the original array
+ *
+ * Frees the data in the array and resets the size to zero, while
+ * the underlying array is preserved for use elsewhere and returned
+ * to the caller.
+ *
+ * If the array was created with the @zero_terminate property
+ * set to %TRUE, the returned data is zero terminated too.
+ *
+ * If array elements contain dynamically-allocated memory,
+ * the array elements should also be freed by the caller.
+ *
+ * A short example of use:
+ * |[<!-- language="C" -->
+ * ...
+ * gpointer data;
+ * gsize data_len;
+ * data = g_array_steal (some_array, &data_len);
+ * ...
+ * ]|
+
+ * Returns: (transfer full): the element data, which should be
+ * freed using g_free().
+ *
+ * Since: 2.64
+ */
+gpointer
+g_array_steal (GArray *array,
+ gsize *len)
+{
+ GRealArray *rarray;
+ gpointer segment;
+
+ g_return_val_if_fail (array != NULL, NULL);
+
+ rarray = (GRealArray *) array;
+ segment = (gpointer) rarray->data;
+
+ if (len != NULL)
+ *len = rarray->len;
+
+ rarray->data = NULL;
+ rarray->len = 0;
+ rarray->alloc = 0;
+ return segment;
+}
+
+/**
* g_array_sized_new:
* @zero_terminated: %TRUE if the array should have an extra element at
* the end with all bits cleared
@@ -1014,6 +1065,46 @@ g_ptr_array_new (void)
}
/**
+ * g_ptr_array_steal:
+ * @array: a #GPtrArray.
+ * @len: (optional) (out caller-allocates): pointer to retrieve the number of
+ * elements of the original array
+ *
+ * Frees the data in the array and resets the size to zero, while
+ * the underlying array is preserved for use elsewhere and returned
+ * to the caller.
+ *
+ * Even if set, the #GDestroyNotify function will never be called
+ * on the current contents of the array and the caller is
+ * responsible for freeing the array elements.
+ *
+ * Returns: (transfer full): the element data, which should be
+ * freed using g_free().
+ *
+ * Since: 2.64
+ */
+gpointer *
+g_ptr_array_steal (GPtrArray *array,
+ gsize *len)
+{
+ GRealPtrArray *rarray;
+ gpointer *segment;
+
+ g_return_val_if_fail (array != NULL, NULL);
+
+ rarray = (GRealPtrArray *) array;
+ segment = (gpointer *) rarray->pdata;
+
+ if (len != NULL)
+ *len = rarray->len;
+
+ rarray->pdata = NULL;
+ rarray->len = 0;
+ rarray->alloc = 0;
+ return segment;
+}
+
+/**
* g_ptr_array_copy:
* @array: #GPtrArray to duplicate
* @func: (nullable): a copy function used to copy every element in the array
@@ -2073,6 +2164,28 @@ g_byte_array_new (void)
}
/**
+ * g_byte_array_steal:
+ * @array: a #GByteArray.
+ * @len: (optional) (out caller-allocates): pointer to retrieve the number of
+ * elements of the original array
+ *
+ * Frees the data in the array and resets the size to zero, while
+ * the underlying array is preserved for use elsewhere and returned
+ * to the caller.
+ *
+ * Returns: (transfer full): the element data, which should be
+ * freed using g_free().
+ *
+ * Since: 2.64
+ */
+guint8 *
+g_byte_array_steal (GByteArray *array,
+ gsize *len)
+{
+ return (guint8 *) g_array_steal ((GArray *) array, len);
+}
+
+/**
* g_byte_array_new_take:
* @data: (transfer full) (array length=len): byte data for the array
* @len: length of @data
diff --git a/glib/garray.h b/glib/garray.h
index 3e7ce7732..67131b5b3 100644
--- a/glib/garray.h
+++ b/glib/garray.h
@@ -70,6 +70,9 @@ GLIB_AVAILABLE_IN_ALL
GArray* g_array_new (gboolean zero_terminated,
gboolean clear_,
guint element_size);
+GLIB_AVAILABLE_IN_2_64
+gpointer g_array_steal (GArray *array,
+ gsize *len);
GLIB_AVAILABLE_IN_ALL
GArray* g_array_sized_new (gboolean zero_terminated,
gboolean clear_,
@@ -137,6 +140,9 @@ GLIB_AVAILABLE_IN_ALL
GPtrArray* g_ptr_array_new (void);
GLIB_AVAILABLE_IN_ALL
GPtrArray* g_ptr_array_new_with_free_func (GDestroyNotify element_free_func);
+GLIB_AVAILABLE_IN_2_64
+gpointer* g_ptr_array_steal (GPtrArray *array,
+ gsize *len);
GLIB_AVAILABLE_IN_2_62
GPtrArray *g_ptr_array_copy (GPtrArray *array,
GCopyFunc func,
@@ -227,6 +233,9 @@ GByteArray* g_byte_array_new (void);
GLIB_AVAILABLE_IN_ALL
GByteArray* g_byte_array_new_take (guint8 *data,
gsize len);
+GLIB_AVAILABLE_IN_2_64
+guint8* g_byte_array_steal (GByteArray *array,
+ gsize *len);
GLIB_AVAILABLE_IN_ALL
GByteArray* g_byte_array_sized_new (guint reserved_size);
GLIB_AVAILABLE_IN_ALL
diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c
index b26704e25..01372a030 100644
--- a/glib/tests/array-test.c
+++ b/glib/tests/array-test.c
@@ -140,6 +140,57 @@ array_new_zero_terminated (void)
g_free (out_str);
}
+/* Check g_array_steal() function */
+static void
+array_steal (void)
+{
+ const guint array_size = 10000;
+ GArray *garray;
+ gint *adata;
+ guint i;
+ gsize len, past_len;
+
+ garray = g_array_new (FALSE, FALSE, sizeof (gint));
+ adata = (gint *) g_array_steal (garray, NULL);
+ g_assert_null (adata);
+
+ adata = (gint *) g_array_steal (garray, &len);
+ g_assert_null (adata);
+ g_assert_cmpint (len, ==, 0);
+
+ for (i = 0; i < array_size; i++)
+ g_array_append_val (garray, i);
+
+ for (i = 0; i < array_size; i++)
+ g_assert_cmpint (g_array_index (garray, gint, i), ==, i);
+
+
+ past_len = garray->len;
+ adata = (gint *) g_array_steal (garray, &len);
+ for (i = 0; i < array_size; i++)
+ g_assert_cmpint (adata[i], ==, i);
+
+ g_assert_cmpint (past_len, ==, len);
+ g_assert_cmpint (garray->len, ==, 0);
+
+ g_array_append_val (garray, i);
+
+ g_assert_cmpint (adata[0], ==, 0);
+ g_assert_cmpint (g_array_index (garray, gint, 0), ==, array_size);
+ g_assert_cmpint (garray->len, ==, 1);
+
+ g_array_remove_index (garray, 0);
+
+ for (i = 0; i < array_size; i++)
+ g_array_append_val (garray, i);
+
+ g_assert_cmpint (garray->len, ==, array_size);
+ g_assert_cmpmem (adata, array_size * sizeof (gint),
+ garray->data, array_size * sizeof (gint));
+ g_free (adata);
+ g_array_free (garray, TRUE);
+}
+
/* Check that g_array_append_val() works correctly for various #GArray
* configurations. */
static void
@@ -760,6 +811,49 @@ test_array_binary_search (void)
g_array_free (garray, TRUE);
}
+/* Check g_ptr_array_steal() function */
+static void
+pointer_array_steal (void)
+{
+ const guint array_size = 10000;
+ GPtrArray *gparray;
+ gpointer *pdata;
+ guint i;
+ gsize len, past_len;
+
+ gparray = g_ptr_array_new ();
+ pdata = g_ptr_array_steal (gparray, NULL);
+ g_assert_null (pdata);
+
+ pdata = g_ptr_array_steal (gparray, &len);
+ g_assert_null (pdata);
+ g_assert_cmpint (len, ==, 0);
+
+ for (i = 0; i < array_size; i++)
+ g_ptr_array_add (gparray, GINT_TO_POINTER (i));
+
+ past_len = gparray->len;
+ pdata = g_ptr_array_steal (gparray, &len);
+ g_assert_cmpint (gparray->len, ==, 0);
+ g_assert_cmpint (past_len, ==, len);
+ g_ptr_array_add (gparray, GINT_TO_POINTER (10));
+
+ g_assert_cmpint ((gsize) pdata[0], ==, (gsize) GINT_TO_POINTER (0));
+ g_assert_cmpint ((gsize) g_ptr_array_index (gparray, 0), ==,
+ (gsize) GINT_TO_POINTER (10));
+ g_assert_cmpint (gparray->len, ==, 1);
+
+ g_ptr_array_remove_index (gparray, 0);
+
+ for (i = 0; i < array_size; i++)
+ g_ptr_array_add (gparray, GINT_TO_POINTER (i));
+ g_assert_cmpmem (pdata, array_size * sizeof (gpointer),
+ gparray->pdata, array_size * sizeof (gpointer));
+ g_free (pdata);
+
+ g_ptr_array_free (gparray, TRUE);
+}
+
static void
pointer_array_add (void)
{
@@ -1318,7 +1412,7 @@ steal_destroy_notify (gpointer data)
/* 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)
+pointer_array_steal_index (void)
{
guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
gpointer out1, out2;
@@ -1362,6 +1456,41 @@ pointer_array_steal (void)
}
static void
+byte_array_steal (void)
+{
+ const guint array_size = 10000;
+ GByteArray *gbarray;
+ guint8 *bdata;
+ guint i;
+ gsize len, past_len;
+
+ gbarray = g_byte_array_new ();
+ bdata = g_byte_array_steal (gbarray, NULL);
+ g_assert_cmpint ((gsize) bdata, ==, (gsize) gbarray->data);
+ g_free (bdata);
+
+ for (i = 0; i < array_size; i++)
+ g_byte_array_append (gbarray, (guint8 *) "abcd", 4);
+
+ past_len = gbarray->len;
+ bdata = g_byte_array_steal (gbarray, &len);
+
+ g_assert_cmpint (len, ==, past_len);
+ g_assert_cmpint (gbarray->len, ==, 0);
+
+ g_byte_array_append (gbarray, (guint8 *) "@", 1);
+
+ g_assert_cmpint (bdata[0], ==, 'a');
+ g_assert_cmpint (gbarray->data[0], ==, '@');
+ g_assert_cmpint (gbarray->len, ==, 1);
+
+ g_byte_array_remove_index (gbarray, 0);
+
+ g_free (bdata);
+ g_byte_array_free (gbarray, TRUE);
+}
+
+static void
byte_array_append (void)
{
GByteArray *gbarray;
@@ -1679,6 +1808,7 @@ main (int argc, char *argv[])
/* array tests */
g_test_add_func ("/array/new/zero-terminated", array_new_zero_terminated);
g_test_add_func ("/array/ref-count", array_ref_count);
+ g_test_add_func ("/array/steal", array_steal);
g_test_add_func ("/array/clear-func", array_clear_func);
g_test_add_func ("/array/binary-search", test_array_binary_search);
@@ -1711,8 +1841,10 @@ main (int argc, char *argv[])
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);
+ g_test_add_func ("/pointerarray/steal_index", pointer_array_steal_index);
/* byte arrays */
+ g_test_add_func ("/bytearray/steal", byte_array_steal);
g_test_add_func ("/bytearray/append", byte_array_append);
g_test_add_func ("/bytearray/prepend", byte_array_prepend);
g_test_add_func ("/bytearray/remove", byte_array_remove);