mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 15:06:14 +01:00
Add g_array_steal(), g_ptr_array_steal() and g_byte_array_steal()
Closes issue #285
This commit is contained in:
parent
c08e7b9364
commit
7bada8394d
@ -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
|
||||
|
113
glib/garray.c
113
glib/garray.c
@ -165,6 +165,57 @@ g_array_new (gboolean zero_terminated,
|
||||
return g_array_sized_new (zero_terminated, clear, elt_size, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -1013,6 +1064,46 @@ g_ptr_array_new (void)
|
||||
return g_ptr_array_sized_new (0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -2002,6 +2093,28 @@ g_byte_array_new (void)
|
||||
return (GByteArray *)g_array_sized_new (FALSE, FALSE, 1, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
@ -1361,6 +1455,41 @@ pointer_array_steal (void)
|
||||
g_assert_cmpuint (i4, ==, 1);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user