mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-24 21:16:15 +01:00
Merge branch 'th/g-ptr-array-set-null-terminated' into 'main'
array: add support for g_ptr_array_null_terminated() See merge request GNOME/glib!1485
This commit is contained in:
commit
a922f2f2c7
@ -3028,7 +3028,9 @@ g_ptr_array_sized_new
|
||||
g_ptr_array_new_with_free_func
|
||||
g_ptr_array_copy
|
||||
g_ptr_array_new_full
|
||||
g_ptr_array_new_null_terminated
|
||||
g_ptr_array_set_free_func
|
||||
g_ptr_array_is_null_terminated
|
||||
g_ptr_array_ref
|
||||
g_ptr_array_unref
|
||||
g_ptr_array_add
|
||||
|
205
glib/garray.c
205
glib/garray.c
@ -1071,6 +1071,7 @@ struct _GRealPtrArray
|
||||
guint len;
|
||||
guint alloc;
|
||||
gatomicrefcount ref_count;
|
||||
guint8 null_terminated; /* always either 0 or 1, so it can be added to array lengths */
|
||||
GDestroyNotify element_free_func;
|
||||
};
|
||||
|
||||
@ -1090,9 +1091,17 @@ struct _GRealPtrArray
|
||||
static void g_ptr_array_maybe_expand (GRealPtrArray *array,
|
||||
guint len);
|
||||
|
||||
static void
|
||||
ptr_array_null_terminate (GRealPtrArray *rarray)
|
||||
{
|
||||
if (G_UNLIKELY (rarray->null_terminated))
|
||||
rarray->pdata[rarray->len] = NULL;
|
||||
}
|
||||
|
||||
static GPtrArray *
|
||||
ptr_array_new (guint reserved_size,
|
||||
GDestroyNotify element_free_func)
|
||||
GDestroyNotify element_free_func,
|
||||
gboolean null_terminated)
|
||||
{
|
||||
GRealPtrArray *array;
|
||||
|
||||
@ -1101,12 +1110,25 @@ ptr_array_new (guint reserved_size,
|
||||
array->pdata = NULL;
|
||||
array->len = 0;
|
||||
array->alloc = 0;
|
||||
array->null_terminated = null_terminated ? 1 : 0;
|
||||
array->element_free_func = element_free_func;
|
||||
|
||||
g_atomic_ref_count_init (&array->ref_count);
|
||||
|
||||
if (reserved_size != 0)
|
||||
g_ptr_array_maybe_expand (array, reserved_size);
|
||||
{
|
||||
if (G_LIKELY (reserved_size < G_MAXUINT) &&
|
||||
null_terminated)
|
||||
reserved_size++;
|
||||
g_ptr_array_maybe_expand (array, reserved_size);
|
||||
if (null_terminated)
|
||||
{
|
||||
/* don't use ptr_array_null_terminate(). It helps the compiler
|
||||
* to see when @null_terminated is false and thereby inline
|
||||
* ptr_array_new() and possibly remove the code entirely. */
|
||||
array->pdata[0] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return (GPtrArray *) array;
|
||||
}
|
||||
@ -1121,7 +1143,7 @@ ptr_array_new (guint reserved_size,
|
||||
GPtrArray*
|
||||
g_ptr_array_new (void)
|
||||
{
|
||||
return ptr_array_new (0, NULL);
|
||||
return ptr_array_new (0, NULL, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1134,6 +1156,10 @@ g_ptr_array_new (void)
|
||||
* the underlying array is preserved for use elsewhere and returned
|
||||
* to the caller.
|
||||
*
|
||||
* Note that if the array is %NULL terminated this may still return
|
||||
* %NULL if the length of the array was zero and pdata was not yet
|
||||
* allocated.
|
||||
*
|
||||
* 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.
|
||||
@ -1171,8 +1197,9 @@ g_ptr_array_new (void)
|
||||
* g_assert (chunk_buffer->len == 0);
|
||||
* ]|
|
||||
*
|
||||
* Returns: (transfer full): the element data, which should be
|
||||
* freed using g_free().
|
||||
* Returns: (transfer full) (nullable): the element data, which should be
|
||||
* freed using g_free(). This may be %NULL if the array doesn’t have any
|
||||
* elements (i.e. if `*len` is zero).
|
||||
*
|
||||
* Since: 2.64
|
||||
*/
|
||||
@ -1215,7 +1242,8 @@ g_ptr_array_steal (GPtrArray *array,
|
||||
* pointing to) are copied to the new #GPtrArray.
|
||||
*
|
||||
* The copy of @array will have the same #GDestroyNotify for its elements as
|
||||
* @array.
|
||||
* @array. The copy will also be %NULL terminated if (and only if) the source
|
||||
* array is.
|
||||
*
|
||||
* Returns: (transfer full): a deep copy of the initial #GPtrArray.
|
||||
*
|
||||
@ -1226,27 +1254,39 @@ g_ptr_array_copy (GPtrArray *array,
|
||||
GCopyFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
GRealPtrArray *rarray = (GRealPtrArray *) array;
|
||||
GPtrArray *new_array;
|
||||
|
||||
g_return_val_if_fail (array != NULL, NULL);
|
||||
|
||||
new_array = ptr_array_new (array->len,
|
||||
((GRealPtrArray *) array)->element_free_func);
|
||||
new_array = ptr_array_new (0,
|
||||
rarray->element_free_func,
|
||||
rarray->null_terminated);
|
||||
|
||||
if (func != NULL)
|
||||
if (rarray->alloc > 0)
|
||||
{
|
||||
guint i;
|
||||
g_ptr_array_maybe_expand ((GRealPtrArray *) new_array, array->len + rarray->null_terminated);
|
||||
|
||||
for (i = 0; i < array->len; i++)
|
||||
new_array->pdata[i] = func (array->pdata[i], user_data);
|
||||
}
|
||||
else if (array->len > 0)
|
||||
{
|
||||
memcpy (new_array->pdata, array->pdata,
|
||||
array->len * sizeof (*array->pdata));
|
||||
}
|
||||
if (array->len > 0)
|
||||
{
|
||||
if (func != NULL)
|
||||
{
|
||||
guint i;
|
||||
|
||||
new_array->len = array->len;
|
||||
for (i = 0; i < array->len; i++)
|
||||
new_array->pdata[i] = func (array->pdata[i], user_data);
|
||||
}
|
||||
else
|
||||
{
|
||||
memcpy (new_array->pdata, array->pdata,
|
||||
array->len * sizeof (*array->pdata));
|
||||
}
|
||||
|
||||
new_array->len = array->len;
|
||||
}
|
||||
|
||||
ptr_array_null_terminate (rarray);
|
||||
}
|
||||
|
||||
return new_array;
|
||||
}
|
||||
@ -1265,7 +1305,7 @@ g_ptr_array_copy (GPtrArray *array,
|
||||
GPtrArray*
|
||||
g_ptr_array_sized_new (guint reserved_size)
|
||||
{
|
||||
return ptr_array_new (reserved_size, NULL);
|
||||
return ptr_array_new (reserved_size, NULL, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1309,14 +1349,14 @@ g_array_copy (GArray *array)
|
||||
* either via g_ptr_array_unref(), when g_ptr_array_free() is called with
|
||||
* @free_segment set to %TRUE or when removing elements.
|
||||
*
|
||||
* Returns: A new #GPtrArray
|
||||
* Returns: (transfer full): A new #GPtrArray
|
||||
*
|
||||
* Since: 2.22
|
||||
*/
|
||||
GPtrArray*
|
||||
g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
|
||||
{
|
||||
return ptr_array_new (0, element_free_func);
|
||||
return ptr_array_new (0, element_free_func, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1333,7 +1373,7 @@ g_ptr_array_new_with_free_func (GDestroyNotify element_free_func)
|
||||
* g_ptr_array_unref(), when g_ptr_array_free() is called with
|
||||
* @free_segment set to %TRUE or when removing elements.
|
||||
*
|
||||
* Returns: A new #GPtrArray
|
||||
* Returns: (transfer full): A new #GPtrArray
|
||||
*
|
||||
* Since: 2.30
|
||||
*/
|
||||
@ -1341,7 +1381,45 @@ GPtrArray*
|
||||
g_ptr_array_new_full (guint reserved_size,
|
||||
GDestroyNotify element_free_func)
|
||||
{
|
||||
return ptr_array_new (reserved_size, element_free_func);
|
||||
return ptr_array_new (reserved_size, element_free_func, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_new_null_terminated:
|
||||
* @reserved_size: number of pointers preallocated.
|
||||
* If @null_terminated is %TRUE, the actually allocated
|
||||
* buffer size is @reserved_size plus 1, unless @reserved_size
|
||||
* is zero, in which case no initial buffer gets allocated.
|
||||
* @element_free_func: (nullable): A function to free elements with
|
||||
* destroy @array or %NULL
|
||||
* @null_terminated: whether to make the array as %NULL terminated.
|
||||
*
|
||||
* Like g_ptr_array_new_full() but also allows to set the array to
|
||||
* be %NULL terminated. A %NULL terminated pointer array has an
|
||||
* additional %NULL pointer after the last element, beyond the
|
||||
* current length.
|
||||
*
|
||||
* #GPtrArray created by other constructors are not automatically %NULL
|
||||
* terminated.
|
||||
*
|
||||
* Note that if the @array's length is zero and currently no
|
||||
* data array is allocated, then pdata will still be %NULL.
|
||||
* %GPtrArray will only %NULL terminate pdata, if an actual
|
||||
* array is allocated. It does not guarantee that an array
|
||||
* is always allocated. In other words, if the length is zero,
|
||||
* then pdata may either point to a %NULL terminated array of length
|
||||
* zero or be %NULL.
|
||||
*
|
||||
* Returns: (transfer full): A new #GPtrArray
|
||||
*
|
||||
* Since: 2.74
|
||||
*/
|
||||
GPtrArray *
|
||||
g_ptr_array_new_null_terminated (guint reserved_size,
|
||||
GDestroyNotify element_free_func,
|
||||
gboolean null_terminated)
|
||||
{
|
||||
return ptr_array_new (reserved_size, element_free_func, null_terminated);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1367,6 +1445,29 @@ g_ptr_array_set_free_func (GPtrArray *array,
|
||||
rarray->element_free_func = element_free_func;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_is_null_terminated:
|
||||
* @array: the #GPtrArray
|
||||
*
|
||||
* Gets whether the @array was constructed as %NULL-terminated.
|
||||
*
|
||||
* This will only return %TRUE for arrays constructed by passing %TRUE to the
|
||||
* `null_terminated` argument of g_ptr_array_new_null_terminated(). It will not
|
||||
* return %TRUE for normal arrays which have had a %NULL element appended to
|
||||
* them.
|
||||
*
|
||||
* Returns: %TRUE if the array is made to be %NULL terminated.
|
||||
*
|
||||
* Since: 2.74
|
||||
*/
|
||||
gboolean
|
||||
g_ptr_array_is_null_terminated (GPtrArray *array)
|
||||
{
|
||||
g_return_val_if_fail (array, FALSE);
|
||||
|
||||
return ((GRealPtrArray *) array)->null_terminated;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_ref:
|
||||
* @array: a #GPtrArray
|
||||
@ -1430,6 +1531,10 @@ g_ptr_array_unref (GPtrArray *array)
|
||||
* be freed separately if @free_seg is %TRUE and no #GDestroyNotify
|
||||
* function has been set for @array.
|
||||
*
|
||||
* Note that if the array is %NULL terminated and @free_seg is %FALSE
|
||||
* then this will always return an allocated %NULL terminated buffer.
|
||||
* If pdata is previously %NULL, a new buffer will be allocated.
|
||||
*
|
||||
* This function is not thread-safe. If using a #GPtrArray from multiple
|
||||
* threads, use only the atomic g_ptr_array_ref() and g_ptr_array_unref()
|
||||
* functions.
|
||||
@ -1485,7 +1590,11 @@ ptr_array_free (GPtrArray *array,
|
||||
segment = NULL;
|
||||
}
|
||||
else
|
||||
segment = rarray->pdata;
|
||||
{
|
||||
segment = rarray->pdata;
|
||||
if (!segment && rarray->null_terminated)
|
||||
segment = (gpointer *) g_new0 (char *, 1);
|
||||
}
|
||||
|
||||
if (flags & PRESERVE_WRAPPER)
|
||||
{
|
||||
@ -1556,8 +1665,14 @@ g_ptr_array_set_size (GPtrArray *array,
|
||||
if (length_unsigned > rarray->len)
|
||||
{
|
||||
guint i;
|
||||
g_ptr_array_maybe_expand (rarray, (length_unsigned - rarray->len));
|
||||
/* This is not
|
||||
|
||||
if (G_UNLIKELY (rarray->null_terminated) &&
|
||||
length_unsigned - rarray->len > G_MAXUINT - 1)
|
||||
g_error ("array would overflow");
|
||||
|
||||
g_ptr_array_maybe_expand (rarray, (length_unsigned - rarray->len) + rarray->null_terminated);
|
||||
|
||||
/* This is not
|
||||
* memset (array->pdata + array->len, 0,
|
||||
* sizeof (gpointer) * (length_unsigned - array->len));
|
||||
* to make it really portable. Remember (void*)NULL needn't be
|
||||
@ -1565,11 +1680,13 @@ g_ptr_array_set_size (GPtrArray *array,
|
||||
*/
|
||||
for (i = rarray->len; i < length_unsigned; i++)
|
||||
rarray->pdata[i] = NULL;
|
||||
|
||||
rarray->len = length_unsigned;
|
||||
|
||||
ptr_array_null_terminate (rarray);
|
||||
}
|
||||
else if (length_unsigned < rarray->len)
|
||||
g_ptr_array_remove_range (array, length_unsigned, rarray->len - length_unsigned);
|
||||
|
||||
rarray->len = length_unsigned;
|
||||
}
|
||||
|
||||
static gpointer
|
||||
@ -1599,7 +1716,7 @@ ptr_array_remove_index (GPtrArray *array,
|
||||
|
||||
rarray->len -= 1;
|
||||
|
||||
if (G_UNLIKELY (g_mem_gc_friendly))
|
||||
if (rarray->null_terminated || G_UNLIKELY (g_mem_gc_friendly))
|
||||
rarray->pdata[rarray->len] = NULL;
|
||||
|
||||
return result;
|
||||
@ -1715,7 +1832,10 @@ g_ptr_array_remove_range (GPtrArray *array,
|
||||
g_return_val_if_fail (rarray != NULL, NULL);
|
||||
g_return_val_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL), NULL);
|
||||
g_return_val_if_fail (index_ <= rarray->len, NULL);
|
||||
g_return_val_if_fail (index_ + length <= rarray->len, NULL);
|
||||
g_return_val_if_fail (length == 0 || index_ + length <= rarray->len, NULL);
|
||||
|
||||
if (length == 0)
|
||||
return array;
|
||||
|
||||
if (rarray->element_free_func != NULL)
|
||||
{
|
||||
@ -1736,6 +1856,8 @@ g_ptr_array_remove_range (GPtrArray *array,
|
||||
for (i = 0; i < length; i++)
|
||||
rarray->pdata[rarray->len + i] = NULL;
|
||||
}
|
||||
else
|
||||
ptr_array_null_terminate (rarray);
|
||||
|
||||
return array;
|
||||
}
|
||||
@ -1832,9 +1954,11 @@ g_ptr_array_add (GPtrArray *array,
|
||||
g_return_if_fail (rarray);
|
||||
g_return_if_fail (rarray->len == 0 || (rarray->len != 0 && rarray->pdata != NULL));
|
||||
|
||||
g_ptr_array_maybe_expand (rarray, 1);
|
||||
g_ptr_array_maybe_expand (rarray, 1u + rarray->null_terminated);
|
||||
|
||||
rarray->pdata[rarray->len++] = data;
|
||||
|
||||
ptr_array_null_terminate (rarray);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1857,6 +1981,8 @@ g_ptr_array_add (GPtrArray *array,
|
||||
* If @func is %NULL, then only the pointers (and not what they are
|
||||
* pointing to) are copied to the new #GPtrArray.
|
||||
*
|
||||
* Whether @array_to_extend is %NULL terminated stays unchanged by this function.
|
||||
*
|
||||
* Since: 2.62
|
||||
**/
|
||||
void
|
||||
@ -1870,7 +1996,14 @@ g_ptr_array_extend (GPtrArray *array_to_extend,
|
||||
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 (array->len == 0u)
|
||||
return;
|
||||
|
||||
if (G_UNLIKELY (array->len == G_MAXUINT) &&
|
||||
rarray_to_extend->null_terminated)
|
||||
g_error ("adding %u to array would overflow", array->len);
|
||||
|
||||
g_ptr_array_maybe_expand (rarray_to_extend, array->len + rarray_to_extend->null_terminated);
|
||||
|
||||
if (func != NULL)
|
||||
{
|
||||
@ -1887,6 +2020,8 @@ g_ptr_array_extend (GPtrArray *array_to_extend,
|
||||
}
|
||||
|
||||
rarray_to_extend->len += array->len;
|
||||
|
||||
ptr_array_null_terminate (rarray_to_extend);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1944,7 +2079,7 @@ g_ptr_array_insert (GPtrArray *array,
|
||||
g_return_if_fail (index_ >= -1);
|
||||
g_return_if_fail (index_ <= (gint)rarray->len);
|
||||
|
||||
g_ptr_array_maybe_expand (rarray, 1);
|
||||
g_ptr_array_maybe_expand (rarray, 1u + rarray->null_terminated);
|
||||
|
||||
if (index_ < 0)
|
||||
index_ = rarray->len;
|
||||
@ -1956,6 +2091,8 @@ g_ptr_array_insert (GPtrArray *array,
|
||||
|
||||
rarray->len++;
|
||||
rarray->pdata[index_] = data;
|
||||
|
||||
ptr_array_null_terminate (rarray);
|
||||
}
|
||||
|
||||
/* Please keep this doc-comment in sync with pointer_array_sort_example()
|
||||
|
@ -154,6 +154,10 @@ GPtrArray* g_ptr_array_sized_new (guint reserved_size);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
GPtrArray* g_ptr_array_new_full (guint reserved_size,
|
||||
GDestroyNotify element_free_func);
|
||||
GLIB_AVAILABLE_IN_2_74
|
||||
GPtrArray* g_ptr_array_new_null_terminated (guint reserved_size,
|
||||
GDestroyNotify element_free_func,
|
||||
gboolean null_terminated);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||
gboolean free_seg);
|
||||
@ -225,6 +229,8 @@ gboolean g_ptr_array_find_with_equal_func (GPtrArray *haystack,
|
||||
GEqualFunc equal_func,
|
||||
guint *index_);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_74
|
||||
gboolean g_ptr_array_is_null_terminated (GPtrArray *array);
|
||||
|
||||
/* Byte arrays, an array of guint8. Implemented as a GArray,
|
||||
* but type-safe.
|
||||
|
@ -886,6 +886,19 @@ array_overflow_set_size (void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
assert_ptr_array_null_terminated (GPtrArray *array, gboolean null_terminated)
|
||||
{
|
||||
g_assert_cmpint (null_terminated, ==, g_ptr_array_is_null_terminated (array));
|
||||
if (array->pdata)
|
||||
{
|
||||
if (null_terminated)
|
||||
g_assert_null (array->pdata[array->len]);
|
||||
}
|
||||
else
|
||||
g_assert_cmpint (array->len, ==, 0);
|
||||
}
|
||||
|
||||
/* Check g_ptr_array_steal() function */
|
||||
static void
|
||||
pointer_array_steal (void)
|
||||
@ -927,6 +940,30 @@ pointer_array_steal (void)
|
||||
g_free (pdata);
|
||||
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
|
||||
gparray = g_ptr_array_new_null_terminated (0, NULL, TRUE);
|
||||
pdata = g_ptr_array_steal (gparray, NULL);
|
||||
g_assert_null (pdata);
|
||||
g_ptr_array_unref (gparray);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_free_null_terminated (void)
|
||||
{
|
||||
GPtrArray *parray = NULL;
|
||||
gpointer *segment;
|
||||
|
||||
g_test_summary ("Check that g_ptr_array_free() on an empty array returns a NULL-terminated empty array");
|
||||
|
||||
parray = g_ptr_array_new_null_terminated (0, NULL, TRUE);
|
||||
g_assert_nonnull (parray);
|
||||
assert_ptr_array_null_terminated (parray, TRUE);
|
||||
|
||||
segment = g_ptr_array_free (parray, FALSE);
|
||||
g_assert_nonnull (segment);
|
||||
g_assert_null (segment[0]);
|
||||
|
||||
g_free (segment);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -977,16 +1014,26 @@ pointer_array_insert (void)
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_ref_count (void)
|
||||
pointer_array_ref_count (gconstpointer test_data)
|
||||
{
|
||||
const gboolean null_terminated = GPOINTER_TO_INT (test_data);
|
||||
GPtrArray *gparray;
|
||||
GPtrArray *gparray2;
|
||||
gint i;
|
||||
gint sum = 0;
|
||||
|
||||
gparray = g_ptr_array_new ();
|
||||
if (null_terminated)
|
||||
gparray = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
else
|
||||
gparray = g_ptr_array_new ();
|
||||
|
||||
assert_ptr_array_null_terminated (gparray, null_terminated);
|
||||
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_ptr_array_add (gparray, GINT_TO_POINTER (i));
|
||||
{
|
||||
g_ptr_array_add (gparray, GINT_TO_POINTER (i));
|
||||
assert_ptr_array_null_terminated (gparray, null_terminated);
|
||||
}
|
||||
|
||||
/* check we can ref, unref and still access the array */
|
||||
gparray2 = g_ptr_array_ref (gparray);
|
||||
@ -995,6 +1042,8 @@ pointer_array_ref_count (void)
|
||||
for (i = 0; i < 10000; i++)
|
||||
g_assert (g_ptr_array_index (gparray, i) == GINT_TO_POINTER (i));
|
||||
|
||||
assert_ptr_array_null_terminated (gparray, null_terminated);
|
||||
|
||||
g_ptr_array_foreach (gparray, sum_up, &sum);
|
||||
g_assert (sum == 49995000);
|
||||
|
||||
@ -1003,6 +1052,8 @@ pointer_array_ref_count (void)
|
||||
g_ptr_array_free (gparray, TRUE);
|
||||
|
||||
g_assert_cmpint (gparray2->len, ==, 0);
|
||||
assert_ptr_array_null_terminated (gparray, null_terminated);
|
||||
|
||||
g_ptr_array_unref (gparray2);
|
||||
}
|
||||
|
||||
@ -1108,8 +1159,9 @@ ptr_array_copy_func (gconstpointer src, gpointer userdata)
|
||||
|
||||
/* Test the g_ptr_array_copy() function */
|
||||
static void
|
||||
pointer_array_copy (void)
|
||||
pointer_array_copy (gconstpointer test_data)
|
||||
{
|
||||
const gboolean null_terminated = GPOINTER_TO_INT (test_data);
|
||||
GPtrArray *ptr_array, *ptr_array2;
|
||||
gsize i;
|
||||
const gsize array_size = 100;
|
||||
@ -1134,16 +1186,18 @@ pointer_array_copy (void)
|
||||
array_test[i] = i;
|
||||
|
||||
/* Test copy an empty array */
|
||||
ptr_array = g_ptr_array_sized_new (0);
|
||||
ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_copy (ptr_array, NULL, NULL);
|
||||
|
||||
g_assert_cmpuint (ptr_array2->len, ==, ptr_array->len);
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
g_ptr_array_unref (ptr_array);
|
||||
g_ptr_array_unref (ptr_array2);
|
||||
|
||||
/* Test simple copy */
|
||||
ptr_array = g_ptr_array_sized_new (array_size);
|
||||
ptr_array = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
|
||||
|
||||
for (i = 0; i < array_size; i++)
|
||||
g_ptr_array_add (ptr_array, &array_test[i]);
|
||||
@ -1158,6 +1212,9 @@ pointer_array_copy (void)
|
||||
g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), ==,
|
||||
(gsize) g_ptr_array_index (ptr_array2, i));
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
g_ptr_array_free (ptr_array2, TRUE);
|
||||
|
||||
/* Test copy through GCopyFunc */
|
||||
@ -1172,6 +1229,9 @@ pointer_array_copy (void)
|
||||
g_assert_cmpuint ((gsize) g_ptr_array_index (ptr_array, i), !=,
|
||||
(gsize) g_ptr_array_index (ptr_array2, i));
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
g_ptr_array_free (ptr_array2, TRUE);
|
||||
|
||||
/* Final cleanup */
|
||||
@ -1181,8 +1241,9 @@ pointer_array_copy (void)
|
||||
|
||||
/* Test the g_ptr_array_extend() function */
|
||||
static void
|
||||
pointer_array_extend (void)
|
||||
pointer_array_extend (gconstpointer test_data)
|
||||
{
|
||||
gboolean null_terminated = GPOINTER_TO_INT (test_data);
|
||||
GPtrArray *ptr_array, *ptr_array2;
|
||||
gsize i;
|
||||
const gsize array_size = 100;
|
||||
@ -1210,20 +1271,23 @@ pointer_array_extend (void)
|
||||
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);
|
||||
ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
|
||||
g_ptr_array_extend (ptr_array, ptr_array2, NULL, NULL);
|
||||
|
||||
g_assert_cmpuint (ptr_array->len, ==, 0);
|
||||
g_assert_cmpuint (ptr_array2->len, ==, 0);
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
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);
|
||||
ptr_array = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
|
||||
for (i = 0; i < array_size; i++)
|
||||
{
|
||||
@ -1235,12 +1299,15 @@ pointer_array_extend (void)
|
||||
for (i = 0; i < array_size; i++)
|
||||
g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
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);
|
||||
ptr_array = g_ptr_array_new_null_terminated (0, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_new_null_terminated (array_size, NULL, null_terminated);
|
||||
|
||||
for (i = 0; i < array_size; i++)
|
||||
{
|
||||
@ -1252,12 +1319,15 @@ pointer_array_extend (void)
|
||||
for (i = 0; i < array_size; i++)
|
||||
g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
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);
|
||||
ptr_array = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
|
||||
|
||||
for (i = 0; i < array_size / 2; i++)
|
||||
{
|
||||
@ -1270,12 +1340,15 @@ pointer_array_extend (void)
|
||||
for (i = 0; i < array_size; i++)
|
||||
g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
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);
|
||||
ptr_array = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
|
||||
ptr_array2 = g_ptr_array_new_null_terminated (array_size / 2, NULL, null_terminated);
|
||||
|
||||
for (i = 0; i < array_size / 2; i++)
|
||||
{
|
||||
@ -1288,6 +1361,9 @@ pointer_array_extend (void)
|
||||
for (i = 0; i < array_size; i++)
|
||||
g_assert_cmpuint (*((gsize *) g_ptr_array_index (ptr_array, i)), ==, i);
|
||||
|
||||
assert_ptr_array_null_terminated (ptr_array, null_terminated);
|
||||
assert_ptr_array_null_terminated (ptr_array2, null_terminated);
|
||||
|
||||
/* Clean-up memory */
|
||||
for (i = array_size / 2; i < array_size; i++)
|
||||
g_free (g_ptr_array_index (ptr_array, i));
|
||||
@ -1631,6 +1707,17 @@ pointer_array_find_non_empty (void)
|
||||
g_ptr_array_free (array, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_remove_range (void)
|
||||
{
|
||||
GPtrArray *parray = NULL;
|
||||
|
||||
/* Try removing an empty range. */
|
||||
parray = g_ptr_array_new ();
|
||||
g_ptr_array_remove_range (parray, 0, 0);
|
||||
g_ptr_array_unref (parray);
|
||||
}
|
||||
|
||||
static void
|
||||
steal_destroy_notify (gpointer data)
|
||||
{
|
||||
@ -1641,19 +1728,32 @@ 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_index (void)
|
||||
pointer_array_steal_index (gconstpointer test_data)
|
||||
{
|
||||
const gboolean null_terminated = GPOINTER_TO_INT (test_data);
|
||||
guint i1 = 0, i2 = 0, i3 = 0, i4 = 0;
|
||||
gpointer out1, out2;
|
||||
GPtrArray *array = g_ptr_array_new_with_free_func (steal_destroy_notify);
|
||||
GPtrArray *array;
|
||||
|
||||
if (null_terminated)
|
||||
array = g_ptr_array_new_null_terminated (0, steal_destroy_notify, null_terminated);
|
||||
else
|
||||
array = g_ptr_array_new_with_free_func (steal_destroy_notify);
|
||||
|
||||
assert_ptr_array_null_terminated (array, null_terminated);
|
||||
|
||||
g_ptr_array_add (array, &i1);
|
||||
g_ptr_array_add (array, &i2);
|
||||
|
||||
assert_ptr_array_null_terminated (array, null_terminated);
|
||||
|
||||
g_ptr_array_add (array, &i3);
|
||||
g_ptr_array_add (array, &i4);
|
||||
|
||||
g_assert_cmpuint (array->len, ==, 4);
|
||||
|
||||
assert_ptr_array_null_terminated (array, null_terminated);
|
||||
|
||||
/* Remove a single element. */
|
||||
out1 = g_ptr_array_steal_index (array, 0);
|
||||
g_assert_true (out1 == &i1);
|
||||
@ -1665,6 +1765,8 @@ pointer_array_steal_index (void)
|
||||
g_assert_true (g_ptr_array_index (array, 1) == &i3);
|
||||
g_assert_true (g_ptr_array_index (array, 2) == &i4);
|
||||
|
||||
assert_ptr_array_null_terminated (array, null_terminated);
|
||||
|
||||
/* Remove another element, quickly. */
|
||||
out2 = g_ptr_array_steal_index_fast (array, 0);
|
||||
g_assert_true (out2 == &i2);
|
||||
@ -1675,6 +1777,8 @@ pointer_array_steal_index (void)
|
||||
g_assert_true (g_ptr_array_index (array, 0) == &i4);
|
||||
g_assert_true (g_ptr_array_index (array, 1) == &i3);
|
||||
|
||||
assert_ptr_array_null_terminated (array, null_terminated);
|
||||
|
||||
/* Check that destroying the pointer array doesn’t affect the stolen elements. */
|
||||
g_ptr_array_unref (array);
|
||||
|
||||
@ -2079,12 +2183,16 @@ main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
/* pointer arrays */
|
||||
g_test_add_func ("/pointerarray/free/null-terminated", pointer_array_free_null_terminated);
|
||||
g_test_add_func ("/pointerarray/add", pointer_array_add);
|
||||
g_test_add_func ("/pointerarray/insert", pointer_array_insert);
|
||||
g_test_add_func ("/pointerarray/ref-count", pointer_array_ref_count);
|
||||
g_test_add_data_func ("/pointerarray/ref-count/not-null-terminated", GINT_TO_POINTER (0), pointer_array_ref_count);
|
||||
g_test_add_data_func ("/pointerarray/ref-count/null-terminated", GINT_TO_POINTER (1), 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_data_func ("/pointerarray/array_copy/not-null-terminated", GINT_TO_POINTER (0), pointer_array_copy);
|
||||
g_test_add_data_func ("/pointerarray/array_copy/null-terminated", GINT_TO_POINTER (1), pointer_array_copy);
|
||||
g_test_add_data_func ("/pointerarray/array_extend/not-null-terminated", GINT_TO_POINTER (0), pointer_array_extend);
|
||||
g_test_add_data_func ("/pointerarray/array_extend/null-terminated", GINT_TO_POINTER (1), pointer_array_extend);
|
||||
g_test_add_func ("/pointerarray/array_extend_and_steal", pointer_array_extend_and_steal);
|
||||
g_test_add_func ("/pointerarray/sort", pointer_array_sort);
|
||||
g_test_add_func ("/pointerarray/sort/example", pointer_array_sort_example);
|
||||
@ -2092,8 +2200,10 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/pointerarray/sort-with-data/example", pointer_array_sort_with_data_example);
|
||||
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/remove-range", pointer_array_remove_range);
|
||||
g_test_add_func ("/pointerarray/steal", pointer_array_steal);
|
||||
g_test_add_func ("/pointerarray/steal_index", pointer_array_steal_index);
|
||||
g_test_add_data_func ("/pointerarray/steal_index/not-null-terminated", GINT_TO_POINTER (0), pointer_array_steal_index);
|
||||
g_test_add_data_func ("/pointerarray/steal_index/null-terminated", GINT_TO_POINTER (1), pointer_array_steal_index);
|
||||
|
||||
/* byte arrays */
|
||||
g_test_add_func ("/bytearray/steal", byte_array_steal);
|
||||
|
Loading…
Reference in New Issue
Block a user