mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-13 07:56:17 +01:00
garray: Add g_ptr_array_new_take_null_terminated()
Similar to g_ptr_array_new_take() but it also computes the length of a zero-terminated array.
This commit is contained in:
parent
14ded2ef94
commit
d5efa78a12
@ -2716,6 +2716,7 @@ g_ptr_array_copy
|
||||
g_ptr_array_new_full
|
||||
g_ptr_array_new_null_terminated
|
||||
g_ptr_array_new_take
|
||||
g_ptr_array_new_take_null_terminated
|
||||
g_ptr_array_set_free_func
|
||||
g_ptr_array_is_null_terminated
|
||||
g_ptr_array_ref
|
||||
|
@ -1197,6 +1197,52 @@ g_ptr_array_new_take (gpointer *data,
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_new_take_null_terminated: (skip)
|
||||
* @data: (array zero-terminated=1) (transfer full) (nullable): an array
|
||||
* of pointers, %NULL terminated, or %NULL for an empty array
|
||||
* @element_free_func: (nullable): a function to free elements on @array
|
||||
* destruction or %NULL
|
||||
*
|
||||
* Creates a new #GPtrArray with @data as pointers, computing the length of it
|
||||
* and setting the reference count to 1.
|
||||
*
|
||||
* This avoids having to copy such data manually.
|
||||
*
|
||||
* The length is calculated by iterating through @data until the first %NULL
|
||||
* element is found.
|
||||
*
|
||||
* It also sets @element_free_func for freeing each element when the array is
|
||||
* destroyed either via g_ptr_array_unref(), when g_ptr_array_free() is called
|
||||
* with @free_segment set to %TRUE or when removing elements.
|
||||
*
|
||||
* Do not use it if the @data length is greater than %G_MAXUINT. #GPtrArray
|
||||
* stores the length of its data in #guint, which may be shorter than
|
||||
* #gsize.
|
||||
*
|
||||
* Returns: (transfer full): A new #GPtrArray
|
||||
*
|
||||
* Since: 2.76
|
||||
*/
|
||||
GPtrArray *
|
||||
g_ptr_array_new_take_null_terminated (gpointer *data,
|
||||
GDestroyNotify element_free_func)
|
||||
{
|
||||
GPtrArray *array;
|
||||
gsize len = 0;
|
||||
|
||||
if (data != NULL)
|
||||
{
|
||||
for (gsize i = 0; data[i] != NULL; ++i)
|
||||
len += 1;
|
||||
}
|
||||
|
||||
array = g_ptr_array_new_take (g_steal_pointer (&data), len, element_free_func);
|
||||
((GRealPtrArray *)array)->null_terminated = TRUE;
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
/**
|
||||
* g_ptr_array_steal:
|
||||
* @array: a #GPtrArray.
|
||||
|
@ -162,6 +162,9 @@ 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_2_76
|
||||
GPtrArray* g_ptr_array_new_take_null_terminated (gpointer *data,
|
||||
GDestroyNotify element_free_func);
|
||||
GLIB_AVAILABLE_IN_ALL
|
||||
gpointer* g_ptr_array_free (GPtrArray *array,
|
||||
gboolean free_seg);
|
||||
|
@ -1154,6 +1154,174 @@ pointer_array_new_take_with_free_func (void)
|
||||
g_free (old_pdata_copy);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_new_take_null_terminated (void)
|
||||
{
|
||||
const size_t array_size = 10000;
|
||||
GPtrArray *gparray;
|
||||
gpointer *pdata;
|
||||
gpointer *old_pdata_copy;
|
||||
gsize len;
|
||||
|
||||
gparray = g_ptr_array_new_null_terminated (array_size, NULL, TRUE);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
|
||||
for (size_t i = 0; i < array_size; i++)
|
||||
g_ptr_array_add (gparray, GUINT_TO_POINTER (i + 1));
|
||||
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
pdata = g_ptr_array_steal (gparray, &len);
|
||||
g_assert_cmpuint (array_size, ==, len);
|
||||
g_assert_nonnull (pdata);
|
||||
g_clear_pointer (&gparray, g_ptr_array_unref);
|
||||
|
||||
old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
|
||||
gparray = g_ptr_array_new_take_null_terminated (g_steal_pointer (&pdata), NULL);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size);
|
||||
|
||||
g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 1);
|
||||
g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 11);
|
||||
|
||||
g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
|
||||
gparray->pdata, array_size * sizeof (gpointer));
|
||||
|
||||
g_ptr_array_add (gparray, GUINT_TO_POINTER (55));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_assert_cmpuint (gparray->len, ==, array_size + 2);
|
||||
g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 33);
|
||||
g_assert_cmpuint (
|
||||
GPOINTER_TO_UINT (g_ptr_array_index (gparray, gparray->len - 1)), ==, 55);
|
||||
|
||||
g_ptr_array_remove_index (gparray, 0);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size + 1);
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_ptr_array_remove_index (gparray, gparray->len - 1);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size);
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
|
||||
gparray->pdata, array_size * sizeof (gpointer));
|
||||
|
||||
g_ptr_array_unref (gparray);
|
||||
g_free (old_pdata_copy);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_new_take_null_terminated_empty (void)
|
||||
{
|
||||
GPtrArray *gparray;
|
||||
const gpointer *data = (gpointer []) { NULL };
|
||||
|
||||
gparray = g_ptr_array_new_take_null_terminated (
|
||||
g_memdup2 (data, sizeof (gpointer)), NULL);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
g_assert_cmpuint (gparray->len, ==, 0);
|
||||
|
||||
g_clear_pointer (&gparray, g_ptr_array_unref);
|
||||
|
||||
gparray = g_ptr_array_new_take_null_terminated (NULL, NULL);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
g_assert_cmpuint (gparray->len, ==, 0);
|
||||
|
||||
g_clear_pointer (&gparray, g_ptr_array_unref);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_new_take_null_terminated_with_free_func (void)
|
||||
{
|
||||
const size_t array_size = 10000;
|
||||
GPtrArray *gparray;
|
||||
gpointer *pdata;
|
||||
gpointer *old_pdata_copy;
|
||||
gsize len;
|
||||
|
||||
gparray = g_ptr_array_new_null_terminated (array_size, g_free, TRUE);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
|
||||
for (size_t i = 0; i < array_size; i++)
|
||||
g_ptr_array_add (gparray, g_strdup_printf ("%" G_GSIZE_FORMAT, i));
|
||||
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
pdata = g_ptr_array_steal (gparray, &len);
|
||||
g_assert_cmpuint (array_size, ==, len);
|
||||
g_assert_nonnull (pdata);
|
||||
g_clear_pointer (&gparray, g_ptr_array_unref);
|
||||
|
||||
old_pdata_copy = g_memdup2 (pdata, len * sizeof (gpointer));
|
||||
gparray = g_ptr_array_new_take_null_terminated (g_steal_pointer (&pdata), g_free);
|
||||
g_assert_true (g_ptr_array_is_null_terminated (gparray));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size);
|
||||
|
||||
g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "0");
|
||||
g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 101), ==, "101");
|
||||
|
||||
g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
|
||||
gparray->pdata, array_size * sizeof (gpointer));
|
||||
|
||||
g_ptr_array_add (gparray, g_strdup_printf ("%d", 55));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33));
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_assert_cmpuint (gparray->len, ==, array_size + 2);
|
||||
g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, 0), ==, "33");
|
||||
g_assert_cmpstr (
|
||||
(const char *) g_ptr_array_index (gparray, gparray->len - 1), ==, "55");
|
||||
|
||||
g_ptr_array_remove_index (gparray, 0);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size + 1);
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_ptr_array_remove_index (gparray, gparray->len - 1);
|
||||
g_assert_cmpuint (gparray->len, ==, array_size);
|
||||
assert_ptr_array_null_terminated (gparray, TRUE);
|
||||
|
||||
g_assert_cmpmem (old_pdata_copy, array_size * sizeof (gpointer),
|
||||
gparray->pdata, array_size * sizeof (gpointer));
|
||||
|
||||
g_ptr_array_unref (gparray);
|
||||
g_free (old_pdata_copy);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_new_take_null_terminated_from_gstrv (void)
|
||||
{
|
||||
GPtrArray *gparray;
|
||||
char *joined;
|
||||
|
||||
gparray = g_ptr_array_new_take_null_terminated (
|
||||
(gpointer) g_strsplit ("A.dot.separated.string", ".", -1), g_free);
|
||||
|
||||
g_assert_cmpstr (
|
||||
(const char *) g_ptr_array_index (gparray, 0), ==, "A");
|
||||
g_assert_cmpstr (
|
||||
(const char *) g_ptr_array_index (gparray, 1), ==, "dot");
|
||||
g_assert_cmpstr (
|
||||
(const char *) g_ptr_array_index (gparray, 2), ==, "separated");
|
||||
g_assert_cmpstr (
|
||||
(const char *) g_ptr_array_index (gparray, 3), ==, "string");
|
||||
|
||||
g_assert_null (g_ptr_array_index (gparray, 4));
|
||||
|
||||
joined = g_strjoinv (".", (char **) gparray->pdata);
|
||||
g_assert_cmpstr (joined, ==, "A.dot.separated.string");
|
||||
|
||||
g_ptr_array_unref (gparray);
|
||||
g_free (joined);
|
||||
}
|
||||
|
||||
static void
|
||||
pointer_array_ref_count (gconstpointer test_data)
|
||||
{
|
||||
@ -2331,6 +2499,10 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/pointerarray/new-take/empty", pointer_array_new_take_empty);
|
||||
g_test_add_func ("/pointerarray/new-take/overflow", pointer_array_new_take_overflow);
|
||||
g_test_add_func ("/pointerarray/new-take/with-free-func", pointer_array_new_take_with_free_func);
|
||||
g_test_add_func ("/pointerarray/new-take-null-terminated", pointer_array_new_take_null_terminated);
|
||||
g_test_add_func ("/pointerarray/new-take-null-terminated/empty", pointer_array_new_take_null_terminated_empty);
|
||||
g_test_add_func ("/pointerarray/new-take-null-terminated/with-free-func", pointer_array_new_take_null_terminated_with_free_func);
|
||||
g_test_add_func ("/pointerarray/new-take-null-terminated/from-gstrv", pointer_array_new_take_null_terminated_from_gstrv);
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user