diff --git a/glib/garray.c b/glib/garray.c index bdbc5c173..b8fc5c36e 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -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; diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index df9d15bdc..4bcbae705 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -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++) {