Merge branch 'zero_terminate_null' into 'main'

garray: Support unallocated zero terminated arrays

See merge request GNOME/glib!4684
This commit is contained in:
Philip Withnall
2025-07-12 14:56:48 +00:00
2 changed files with 64 additions and 7 deletions

View File

@@ -198,7 +198,9 @@ g_array_new_take (gpointer data,
/**
* g_array_new_take_zero_terminated: (skip)
* @data: (array zero-terminated=1): an array of elements of @element_size
* @data: (array zero-terminated=1) (transfer full) (nullable): an array
* of elements of @element_size, %NULL terminated,
* or %NULL for an empty array
* @clear: %TRUE if #GArray elements should be automatically cleared
* to 0 when they are allocated
* @element_size: the size of each element in bytes
@@ -271,8 +273,9 @@ g_array_new_take_zero_terminated (gpointer data,
* 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.
* Note that if the array was created with the @zero_terminate
* property set to %TRUE, this may still return %NULL if the length
* of the array was zero and data was not yet allocated.
*
* If array elements contain dynamically-allocated memory,
* the array elements should also be freed by the caller.
@@ -770,11 +773,12 @@ g_array_set_size (GArray *farray,
}
else if (length < array->len)
g_array_remove_range (farray, length, array->len - length);
array->len = length;
g_array_zero_terminate (array);
if (G_LIKELY (array->data != NULL))
g_array_zero_terminate (array);
return farray;
}
@@ -881,6 +885,9 @@ g_array_remove_range (GArray *farray,
g_return_val_if_fail (index_ <= G_MAXUINT - length, NULL);
g_return_val_if_fail (index_ + length <= array->len, NULL);
if (length == 0)
return farray;
if (array->clear_func != NULL)
{
guint i;

View File

@@ -100,6 +100,20 @@ array_set_size (gconstpointer test_data)
g_array_unref (garray);
}
/* Check that unallocated zero terminated arrays can be set to size 0. */
static void
array_set_size_zero_terminated_null (void)
{
GArray *garray;
garray = g_array_new_take_zero_terminated(NULL, FALSE, sizeof (gchar));
g_array_set_size (garray, 0);
g_assert_cmpuint (garray->len, ==, 0);
g_array_free (garray, TRUE);
}
/* As with array_set_size(), but with a sized array. */
static void
array_set_size_sized (gconstpointer test_data)
@@ -307,6 +321,24 @@ array_new_take_zero_terminated (void)
g_clear_pointer (&old_data_copy, g_free);
}
/* Check that a non-existing array becomes a zero-terminated one when requested. */
static void
array_new_take_zero_terminated_null (void)
{
GArray *garray;
gchar *out_str = NULL;
gsize len;
garray = g_array_new_take_zero_terminated (NULL, FALSE, sizeof (gchar));
g_assert_cmpuint (garray->len, ==, 0);
out_str = g_array_steal (garray, &len);
g_assert_cmpstr (out_str, ==, NULL);
g_assert_cmpuint (len, ==, 0);
g_free (out_str);
}
static void
array_new_take_overflow (void)
{
@@ -673,6 +705,21 @@ array_remove_range (gconstpointer test_data)
g_array_free (garray, TRUE);
}
/* Check that g_array_remove_range() works with a zero terminated array
* without any data. */
static void
array_remove_range_zero_terminated_null (void)
{
GArray *garray;
garray = g_array_new_take_zero_terminated(NULL, FALSE, sizeof (gchar));
g_array_remove_range (garray, 0, 0);
g_assert_cmpuint (garray->len, ==, 0);
g_array_free (garray, TRUE);
}
static void
array_ref_count (void)
{
@@ -3194,6 +3241,7 @@ main (int argc, char *argv[])
g_test_add_func ("/array/new/take/empty", array_new_take_empty);
g_test_add_func ("/array/new/take/overflow", array_new_take_overflow);
g_test_add_func ("/array/new/take-zero-terminated", array_new_take_zero_terminated);
g_test_add_func ("/array/new/take-zero-terminated/null", array_new_take_zero_terminated_null);
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);
@@ -3201,6 +3249,8 @@ main (int argc, char *argv[])
g_test_add_func ("/array/copy-sized", test_array_copy_sized);
g_test_add_func ("/array/overflow-append-vals", array_overflow_append_vals);
g_test_add_func ("/array/overflow-set-size", array_overflow_set_size);
g_test_add_func ("/array/remove-range/zero-terminated-null", array_remove_range_zero_terminated_null);
g_test_add_func ("/array/set-size/zero-terminated-null", array_set_size_zero_terminated_null);
for (i = 0; i < G_N_ELEMENTS (array_configurations); i++)
{