diff options
author | Philip Withnall <philip@tecnocode.co.uk> | 2022-12-21 18:34:13 +0000 |
---|---|---|
committer | Philip Withnall <philip@tecnocode.co.uk> | 2022-12-21 18:34:13 +0000 |
commit | 5e378c775a79b61f307f2b780652745b528b4105 (patch) | |
tree | 4f598329109cbfd59b1de29f3ce23c5a4b98bea7 | |
parent | f64fc323106569349a091a68c9f45b68f9293ba4 (diff) | |
parent | 94c45f8fa246dc36a958649e62ce95c58785cde7 (diff) | |
download | glib-5e378c775a79b61f307f2b780652745b528b4105.tar.gz |
Merge branch 'ptr-array-new-take' into 'main'
garray: Add more G(Ptr)Array constructors to take or copy C arrays
See merge request GNOME/glib!3128
-rw-r--r-- | docs/reference/glib/glib-sections.txt.in | 6 | ||||
-rw-r--r-- | glib/garray.c | 338 | ||||
-rw-r--r-- | glib/garray.h | 27 | ||||
-rw-r--r-- | glib/tests/array-test.c | 842 |
4 files changed, 1211 insertions, 2 deletions
diff --git a/docs/reference/glib/glib-sections.txt.in b/docs/reference/glib/glib-sections.txt.in index ab7453e60..baf62ebfa 100644 --- a/docs/reference/glib/glib-sections.txt.in +++ b/docs/reference/glib/glib-sections.txt.in @@ -2684,6 +2684,8 @@ g_string_chunk_free <FILE>arrays</FILE> GArray g_array_new +g_array_new_take +g_array_new_take_zero_terminated g_array_steal g_array_sized_new g_array_copy @@ -2719,6 +2721,10 @@ 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_new_take +g_ptr_array_new_take_null_terminated +g_ptr_array_new_from_array +g_ptr_array_new_from_null_terminated_array g_ptr_array_set_free_func g_ptr_array_is_null_terminated g_ptr_array_ref diff --git a/glib/garray.c b/glib/garray.c index 0db46bf5f..3ba41a483 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -35,6 +35,7 @@ #include "garray.h" +#include "galloca.h" #include "gbytes.h" #include "ghash.h" #include "gslice.h" @@ -191,6 +192,119 @@ g_array_new (gboolean zero_terminated, } /** + * g_array_new_take: (skip) + * @data: (array length=len) (transfer full) (nullable): an array of + * elements of @element_size, or %NULL for an empty array + * @len: the number of elements in @data + * @clear: %TRUE if #GArray elements should be automatically cleared + * to 0 when they are allocated + * @element_size: the size of each element in bytes + * + * Creates a new #GArray with @data as array data, @len as length and a + * reference count of 1. + * + * This avoids having to copy the data manually, when it can just be + * inherited. @data will eventually be freed using g_free(), so must + * have been allocated with a suitable allocator. + * + * In case the elements need to be cleared when the array is freed, use + * g_array_set_clear_func() to set a #GDestroyNotify function to perform + * such task. + * + * Do not use it if @len or @element_size are greater than %G_MAXUINT. + * #GArray stores the length of its data in #guint, which may be shorter + * than #gsize. + * + * Returns: (transfer full): A new #GArray + * + * Since: 2.76 + */ +GArray * +g_array_new_take (gpointer data, + gsize len, + gboolean clear, + gsize element_size) +{ + GRealArray *rarray; + GArray *array; + + g_return_val_if_fail (data != NULL || len == 0, NULL); + g_return_val_if_fail (len <= G_MAXUINT, NULL); + g_return_val_if_fail (element_size <= G_MAXUINT, NULL); + + array = g_array_sized_new (FALSE, clear, element_size, 0); + rarray = (GRealArray *) array; + rarray->data = (guint8 *) g_steal_pointer (&data); + rarray->len = len; + rarray->elt_capacity = len; + + return array; +} + +/** + * g_array_new_take_zero_terminated: (skip) + * @data: (array zero-terminated=1): an array of elements of @element_size + * @clear: %TRUE if #GArray elements should be automatically cleared + * to 0 when they are allocated + * @element_size: the size of each element in bytes + * + * Creates a new #GArray with @data as array data, computing the length of it + * and setting the reference count to 1. + * + * This avoids having to copy the data manually, when it can just be + * inherited. @data will eventually be freed using g_free(), so must + * have been allocated with a suitable allocator. + * + * The length is calculated by iterating through @data until the first %NULL + * element is found. + * + * In case the elements need to be cleared when the array is freed, use + * g_array_set_clear_func() to set a #GDestroyNotify function to perform + * such task. + * + * Do not use it if @data length or @element_size are greater than %G_MAXUINT. + * #GArray stores the length of its data in #guint, which may be shorter + * than #gsize. + * + * Returns: (transfer full): A new #GArray + * + * Since: 2.76 + */ +GArray * +g_array_new_take_zero_terminated (gpointer data, + gboolean clear, + gsize element_size) +{ + GArray *array; + gsize len = 0; + + g_return_val_if_fail (element_size <= G_MAXUINT, NULL); + + if (data != NULL) + { + guint8 *array_data = data; + + for (gsize i = 0; ; ++i) + { + const guint8 *element_start = array_data + (i * element_size); + + if (*element_start == 0 && + memcmp (element_start, element_start + 1, element_size - 1) == 0) + break; + + len += 1; + } + } + + g_return_val_if_fail (len <= G_MAXUINT, NULL); + + array = g_array_new_take (data, len, clear, element_size); + ((GRealArray *)array)->zero_terminated = TRUE; + + return array; +} + +/** * g_array_steal: * @array: a #GArray. * @len: (optional) (out): pointer to retrieve the number of @@ -1072,7 +1186,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 */ + guint8 null_terminated : 1; /* always either 0 or 1, so it can be added to array lengths */ GDestroyNotify element_free_func; }; @@ -1151,6 +1265,226 @@ g_ptr_array_new (void) } /** + * g_ptr_array_new_take: (skip) + * @data: (array length=len) (transfer full) (nullable): an array of pointers, + * or %NULL for an empty array + * @len: the number of pointers in @data + * @element_free_func: (nullable): A function to free elements on @array + * destruction or %NULL + * + * Creates a new #GPtrArray with @data as pointers, @len as length and a + * reference count of 1. + * + * This avoids having to copy such data manually. @data will eventually be + * freed using g_free(), so must have been allocated with a suitable allocator. + * + * 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 @len 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 (gpointer *data, + gsize len, + GDestroyNotify element_free_func) +{ + GPtrArray *array; + GRealPtrArray *rarray; + + g_return_val_if_fail (data != NULL || len == 0, NULL); + g_return_val_if_fail (len <= G_MAXUINT, NULL); + + array = ptr_array_new (0, element_free_func, FALSE); + rarray = (GRealPtrArray *)array; + + rarray->pdata = g_steal_pointer (&data); + rarray->len = len; + rarray->alloc = len; + + 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. @data will eventually be + * freed using g_free(), so must have been allocated with a suitable allocator. + * + * 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; + } + + g_return_val_if_fail (len <= G_MAXUINT, NULL); + + array = g_ptr_array_new_take (g_steal_pointer (&data), len, element_free_func); + ((GRealPtrArray *)array)->null_terminated = TRUE; + + return array; +} + +static GPtrArray * +ptr_array_new_from_array (gpointer *data, + gsize len, + GCopyFunc copy_func, + gpointer copy_func_user_data, + GDestroyNotify element_free_func, + gboolean null_terminated) +{ + GPtrArray *array; + GRealPtrArray *rarray; + + g_assert (len <= G_MAXUINT); + + array = ptr_array_new (len, element_free_func, null_terminated); + rarray = (GRealPtrArray *)array; + + if (copy_func != NULL) + { + for (gsize i = 0; i < len; i++) + rarray->pdata[i] = copy_func (data[i], copy_func_user_data); + } + else + { + memcpy (rarray->pdata, data, len * sizeof (gpointer)); + } + + rarray->len = len; + + return array; +} + +/** + * g_ptr_array_new_from_array: (skip) + * @data: (array length=len) (transfer none) (nullable): an array of pointers, + * or %NULL for an empty array + * @len: the number of pointers in @data + * @copy_func: (nullable): a copy function used to copy every element in the + * array or %NULL. + * @copy_func_user_data: user data passed to @copy_func, or %NULL + * @element_free_func: (nullable): a function to free elements on @array + * destruction or %NULL + * + * Creates a new #GPtrArray, copying @len pointers from @data, and setting + * the array’s reference count to 1. + * + * This avoids having to manually add each element one by one. + * + * If @copy_func is provided, then it is used to copy each element before + * adding them to the new array. If it is %NULL then the pointers are copied + * directly. + * + * 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 @len 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_from_array (gpointer *data, + gsize len, + GCopyFunc copy_func, + gpointer copy_func_user_data, + GDestroyNotify element_free_func) +{ + g_return_val_if_fail (data != NULL || len == 0, NULL); + g_return_val_if_fail (len <= G_MAXUINT, NULL); + + return ptr_array_new_from_array ( + data, len, copy_func, copy_func_user_data, element_free_func, FALSE); +} + +/** + * g_ptr_array_new_from_null_terminated_array: (skip) + * @data: (array zero-terminated=1) (transfer none) (nullable): an array of + * pointers, %NULL terminated; or %NULL for an empty array + * @copy_func: (nullable): a copy function used to copy every element in the + * array or %NULL. + * @copy_func_user_data: user data passed to @copy_func, or %NULL + * @element_free_func: (nullable): a function to free elements on @array + * destruction or %NULL + * + * Creates a new #GPtrArray copying the pointers from @data after having + * computed the length of it and with a reference count of 1. + * This avoids having to manually add each element one by one. + * If @copy_func is provided, then it is used to copy the data in the new + * array. + * It also set @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 has more than %G_MAXUINT elements. #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_from_null_terminated_array (gpointer *data, + GCopyFunc copy_func, + gpointer copy_func_user_data, + GDestroyNotify element_free_func) +{ + gsize len = 0; + + if (data != NULL) + { + for (gsize i = 0; data[i] != NULL; ++i) + len += 1; + } + + g_return_val_if_fail (len <= G_MAXUINT, NULL); + + return ptr_array_new_from_array ( + data, len, copy_func, copy_func_user_data, element_free_func, TRUE); +} + +/** * g_ptr_array_steal: * @array: a #GPtrArray. * @len: (optional) (out): pointer to retrieve the number of @@ -2113,7 +2447,7 @@ g_ptr_array_insert (GPtrArray *array, * * Sorts the array, using @compare_func which should be a qsort()-style * comparison function (returns less than zero for first arg is less - * than second arg, zero for equal, greater than zero if irst arg is + * than second arg, zero for equal, greater than zero if first arg is * greater than second arg). * * Note that the comparison function for g_ptr_array_sort() doesn't diff --git a/glib/garray.h b/glib/garray.h index 2300e5f58..2ec10793b 100644 --- a/glib/garray.h +++ b/glib/garray.h @@ -72,6 +72,15 @@ GLIB_AVAILABLE_IN_ALL GArray* g_array_new (gboolean zero_terminated, gboolean clear_, guint element_size); +GLIB_AVAILABLE_IN_2_76 +GArray* g_array_new_take (gpointer data, + gsize len, + gboolean clear, + gsize element_size); +GLIB_AVAILABLE_IN_2_76 +GArray* g_array_new_take_zero_terminated (gpointer data, + gboolean clear, + gsize element_size); GLIB_AVAILABLE_IN_2_64 gpointer g_array_steal (GArray *array, gsize *len); @@ -142,6 +151,16 @@ 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_76 +GPtrArray* g_ptr_array_new_take (gpointer *data, + gsize len, + GDestroyNotify element_free_func); +GLIB_AVAILABLE_IN_2_76 +GPtrArray* g_ptr_array_new_from_array (gpointer *data, + gsize len, + GCopyFunc copy_func, + gpointer copy_func_user_data, + GDestroyNotify element_free_func); GLIB_AVAILABLE_IN_2_64 gpointer* g_ptr_array_steal (GPtrArray *array, gsize *len); @@ -158,6 +177,14 @@ 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_2_76 +GPtrArray* g_ptr_array_new_from_null_terminated_array (gpointer *data, + GCopyFunc copy_func, + gpointer copy_func_user_data, + GDestroyNotify element_free_func); GLIB_AVAILABLE_IN_ALL gpointer* g_ptr_array_free (GPtrArray *array, gboolean free_seg); diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c index cd617200a..72d6924ff 100644 --- a/glib/tests/array-test.c +++ b/glib/tests/array-test.c @@ -142,6 +142,196 @@ array_new_zero_terminated (void) g_free (out_str); } +static void +array_new_take (void) +{ + const size_t array_size = 10000; + GArray *garray; + gpointer *data; + gpointer *old_data_copy; + gsize len; + + garray = g_array_new (FALSE, FALSE, sizeof (size_t)); + for (size_t i = 0; i < array_size; i++) + g_array_append_val (garray, i); + + data = g_array_steal (garray, &len); + g_assert_cmpuint (array_size, ==, len); + g_assert_nonnull (data); + g_clear_pointer (&garray, g_array_unref); + + old_data_copy = g_memdup2 (data, len * sizeof (size_t)); + garray = g_array_new_take (g_steal_pointer (&data), len, FALSE, sizeof (size_t)); + g_assert_cmpuint (garray->len, ==, array_size); + + g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 0); + g_assert_cmpuint (g_array_index (garray, size_t, 10), ==, 10); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t), + garray->data, array_size * sizeof (size_t)); + + size_t val = 55; + g_array_append_val (garray, val); + val = 33; + g_array_prepend_val (garray, val); + + g_assert_cmpuint (garray->len, ==, array_size + 2); + g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 33); + g_assert_cmpuint (g_array_index (garray, size_t, garray->len - 1), ==, 55); + + g_array_remove_index (garray, 0); + g_assert_cmpuint (garray->len, ==, array_size + 1); + g_array_remove_index (garray, garray->len - 1); + g_assert_cmpuint (garray->len, ==, array_size); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t), + garray->data, array_size * sizeof (size_t)); + + g_array_unref (garray); + g_free (old_data_copy); +} + +static void +array_new_take_empty (void) +{ + GArray *garray; + size_t empty_array[] = {0}; + + garray = g_array_new_take ( + g_memdup2 (&empty_array, sizeof (size_t)), 0, FALSE, sizeof (size_t)); + g_assert_cmpuint (garray->len, ==, 0); + + g_clear_pointer (&garray, g_array_unref); + + garray = g_array_new_take (NULL, 0, FALSE, sizeof (size_t)); + g_assert_cmpuint (garray->len, ==, 0); + + g_clear_pointer (&garray, g_array_unref); +} + +static void +array_new_take_zero_terminated (void) +{ + size_t array_size = 10000; + GArray *garray; + gpointer *data; + gpointer *old_data_copy; + gsize len; + + garray = g_array_new (TRUE, FALSE, sizeof (size_t)); + for (size_t i = 1; i <= array_size; i++) + g_array_append_val (garray, i); + + data = g_array_steal (garray, &len); + g_assert_cmpuint (array_size, ==, len); + g_assert_nonnull (data); + g_clear_pointer (&garray, g_array_unref); + + old_data_copy = g_memdup2 (data, len * sizeof (size_t)); + garray = g_array_new_take_zero_terminated ( + g_steal_pointer (&data), FALSE, sizeof (size_t)); + g_assert_cmpuint (garray->len, ==, array_size); + g_assert_cmpuint (g_array_index (garray, size_t, garray->len), ==, 0); + + g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 1); + g_assert_cmpuint (g_array_index (garray, size_t, 10), ==, 11); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t), + garray->data, array_size * sizeof (size_t)); + + size_t val = 55; + g_array_append_val (garray, val); + val = 33; + g_array_prepend_val (garray, val); + + g_assert_cmpuint (garray->len, ==, array_size + 2); + g_assert_cmpuint (g_array_index (garray, size_t, 0), ==, 33); + g_assert_cmpuint (g_array_index (garray, size_t, garray->len - 1), ==, 55); + + g_array_remove_index (garray, 0); + g_assert_cmpuint (garray->len, ==, array_size + 1); + g_array_remove_index (garray, garray->len - 1); + g_assert_cmpuint (garray->len, ==, array_size); + g_assert_cmpuint (g_array_index (garray, size_t, garray->len), ==, 0); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (size_t), + garray->data, array_size * sizeof (size_t)); + + g_clear_pointer (&garray, g_array_unref); + g_clear_pointer (&old_data_copy, g_free); + + array_size = G_MAXUINT8; + garray = g_array_new (TRUE, FALSE, sizeof (guint8)); + for (guint8 i = 1; i < array_size; i++) + g_array_append_val (garray, i); + + val = G_MAXUINT8 / 2; + g_array_append_val (garray, val); + + data = g_array_steal (garray, &len); + g_assert_cmpuint (array_size, ==, len); + g_assert_nonnull (data); + g_clear_pointer (&garray, g_array_unref); + + old_data_copy = g_memdup2 (data, len * sizeof (guint8)); + garray = g_array_new_take_zero_terminated ( + g_steal_pointer (&data), FALSE, sizeof (guint8)); + g_assert_cmpuint (garray->len, ==, array_size); + g_assert_cmpuint (g_array_index (garray, guint8, garray->len), ==, 0); + + g_assert_cmpuint (g_array_index (garray, guint8, 0), ==, 1); + g_assert_cmpuint (g_array_index (garray, guint8, 10), ==, 11); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (guint8), + garray->data, array_size * sizeof (guint8)); + + val = 55; + g_array_append_val (garray, val); + val = 33; + g_array_prepend_val (garray, val); + + g_assert_cmpuint (garray->len, ==, array_size + 2); + g_assert_cmpuint (g_array_index (garray, guint8, 0), ==, 33); + g_assert_cmpuint (g_array_index (garray, guint8, garray->len - 1), ==, 55); + + g_array_remove_index (garray, 0); + g_assert_cmpuint (garray->len, ==, array_size + 1); + g_array_remove_index (garray, garray->len - 1); + g_assert_cmpuint (garray->len, ==, array_size); + g_assert_cmpuint (g_array_index (garray, guint8, garray->len), ==, 0); + + g_assert_cmpmem (old_data_copy, array_size * sizeof (guint8), + garray->data, array_size * sizeof (guint8)); + + g_clear_pointer (&garray, g_array_unref); + g_clear_pointer (&old_data_copy, g_free); +} + +static void +array_new_take_overflow (void) +{ +#if SIZE_WIDTH <= UINT_WIDTH + g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH."); +#else + if (!g_test_undefined ()) + return; + + /* Check for overflow should happen before data is accessed. */ + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'len <= G_MAXUINT' failed"); + g_assert_null ( + g_array_new_take ( + (gpointer) (int []) { 0 }, (gsize) G_MAXUINT + 1, FALSE, sizeof (int))); + g_test_assert_expected_messages (); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'element_size <= G_MAXUINT' failed"); + g_assert_null ( + g_array_new_take (NULL, 0, FALSE, (gsize) G_MAXUINT + 1)); + g_test_assert_expected_messages (); +#endif +} + /* Check g_array_steal() function */ static void array_steal (void) @@ -1014,6 +1204,638 @@ pointer_array_insert (void) } static void +pointer_array_new_take (void) +{ + const size_t array_size = 10000; + GPtrArray *gparray; + gpointer *pdata; + gpointer *old_pdata_copy; + gsize len; + + gparray = g_ptr_array_new (); + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (gparray, GUINT_TO_POINTER (i)); + + 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 (g_steal_pointer (&pdata), len, NULL); + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + g_assert_cmpuint (gparray->len, ==, array_size); + + g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 0); + g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 10); + + 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)); + g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33)); + + 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); + g_ptr_array_remove_index (gparray, gparray->len - 1); + g_assert_cmpuint (gparray->len, ==, array_size); + + 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_empty (void) +{ + GPtrArray *gparray; + gpointer empty_array[] = {0}; + + gparray = g_ptr_array_new_take ( + g_memdup2 (&empty_array, sizeof (gpointer)), 0, NULL); + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + g_assert_cmpuint (gparray->len, ==, 0); + + g_clear_pointer (&gparray, g_ptr_array_unref); + + gparray = g_ptr_array_new_take (NULL, 0, NULL); + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + g_assert_cmpuint (gparray->len, ==, 0); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*data*!=*NULL*||*len*==*0*"); + g_assert_null (g_ptr_array_new_take (NULL, 10, NULL)); + g_test_assert_expected_messages (); + + g_clear_pointer (&gparray, g_ptr_array_unref); +} + +static void +pointer_array_new_take_overflow (void) +{ +#if SIZE_WIDTH <= UINT_WIDTH + g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH."); +#else + if (!g_test_undefined ()) + return; + + /* Check for overflow should happen before data is accessed. */ + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'len <= G_MAXUINT' failed"); + g_assert_null (g_ptr_array_new_take ( + (gpointer []) { NULL }, (gsize) G_MAXUINT + 1, NULL)); + g_test_assert_expected_messages (); +#endif +} + +static void +pointer_array_new_take_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_with_free_func (g_free); + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (gparray, g_strdup_printf ("%" G_GSIZE_FORMAT, i)); + + 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 (g_steal_pointer (&pdata), len, g_free); + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + 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)); + g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33)); + + 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); + g_ptr_array_remove_index (gparray, gparray->len - 1); + g_assert_cmpuint (gparray->len, ==, array_size); + + 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 (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_new_from_array (void) +{ + const size_t array_size = 10000; + GPtrArray *source_array; + GPtrArray *gparray; + gpointer *old_pdata_copy; + + source_array = g_ptr_array_new (); + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (source_array, GUINT_TO_POINTER (i)); + + g_assert_cmpuint (array_size, ==, source_array->len); + g_assert_nonnull (source_array->pdata); + + gparray = g_ptr_array_new_from_array (source_array->pdata, source_array->len, + NULL, NULL, NULL); + + old_pdata_copy = + g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer)); + g_assert_nonnull (old_pdata_copy); + g_clear_pointer (&source_array, g_ptr_array_unref); + + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + g_assert_cmpuint (gparray->len, ==, array_size); + + g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 0)), ==, 0); + g_assert_cmpuint (GPOINTER_TO_UINT (g_ptr_array_index (gparray, 10)), ==, 10); + + 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)); + g_ptr_array_insert (gparray, 0, GUINT_TO_POINTER (33)); + + 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); + g_ptr_array_remove_index (gparray, gparray->len - 1); + g_assert_cmpuint (gparray->len, ==, array_size); + + 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_from_array_empty (void) +{ + GPtrArray *gparray; + gpointer empty_array[] = {0}; + + gparray = g_ptr_array_new_from_array (empty_array, 0, NULL, NULL, NULL); + g_assert_false (g_ptr_array_is_null_terminated (gparray)); + g_assert_cmpuint (gparray->len, ==, 0); + + g_clear_pointer (&gparray, g_ptr_array_unref); + + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*data*!=*NULL*||*len*==*0*"); + g_assert_null (g_ptr_array_new_from_array (NULL, 10, NULL, NULL, NULL)); + g_test_assert_expected_messages (); +} + +static void +pointer_array_new_from_array_overflow (void) +{ +#if SIZE_WIDTH <= UINT_WIDTH + g_test_skip ("Overflow test requires UINT_WIDTH > SIZE_WIDTH."); +#else + if (!g_test_undefined ()) + return; + + /* Check for overflow should happen before data is accessed. */ + g_test_expect_message (G_LOG_DOMAIN, G_LOG_LEVEL_CRITICAL, + "*assertion 'len <= G_MAXUINT' failed"); + g_assert_null (g_ptr_array_new_from_array ( + (gpointer []) { NULL }, (gsize) G_MAXUINT + 1, NULL, NULL, NULL)); + g_test_assert_expected_messages (); +#endif +} + +static void +pointer_array_new_from_array_with_copy_and_free_func (void) +{ + const size_t array_size = 10000; + GPtrArray *source_array; + GPtrArray *gparray; + gpointer *old_pdata_copy; + + source_array = g_ptr_array_new_with_free_func (g_free); + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (source_array, g_strdup_printf ("%" G_GSIZE_FORMAT, i)); + + g_assert_cmpuint (array_size, ==, source_array->len); + g_assert_nonnull (source_array->pdata); + + gparray = g_ptr_array_new_from_array (source_array->pdata, source_array->len, + (GCopyFunc) g_strdup, NULL, g_free); + + old_pdata_copy = + g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer)); + g_assert_nonnull (old_pdata_copy); + + for (size_t i = 0; i < gparray->len; i++) + { + g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==, + (const char *) old_pdata_copy[i]); + } + + g_clear_pointer (&source_array, g_ptr_array_unref); + + 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_ptr_array_add (gparray, g_strdup_printf ("%d", 55)); + g_ptr_array_insert (gparray, 0, g_strdup_printf ("%d", 33)); + + 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); + g_ptr_array_remove_index (gparray, gparray->len - 1); + g_assert_cmpuint (gparray->len, ==, array_size); + + g_ptr_array_unref (gparray); + g_free (old_pdata_copy); +} + +static void +pointer_array_new_from_null_terminated_array (void) +{ + const size_t array_size = 10000; + GPtrArray *source_array; + GPtrArray *gparray; + gpointer *old_pdata_copy; + + source_array = g_ptr_array_new_null_terminated (array_size, NULL, TRUE); + g_assert_true (g_ptr_array_is_null_terminated (source_array)); + + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (source_array, GUINT_TO_POINTER (i + 1)); + + g_assert_cmpuint (array_size, ==, source_array->len); + g_assert_nonnull (source_array->pdata); + + old_pdata_copy = + g_memdup2 (source_array->pdata, source_array->len * sizeof (gpointer)); + g_assert_nonnull (old_pdata_copy); + + gparray = g_ptr_array_new_from_null_terminated_array (source_array->pdata, + NULL, NULL, NULL); + g_assert_true (g_ptr_array_is_null_terminated (source_array)); + assert_ptr_array_null_terminated (gparray, TRUE); + + g_clear_pointer (&source_array, g_ptr_array_unref); + + g_assert_true (g_ptr_array_is_null_terminated (gparray)); + 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_from_null_terminated_array_empty (void) +{ + GPtrArray *gparray; + + gparray = g_ptr_array_new_from_null_terminated_array ( + (gpointer []) { NULL }, NULL, 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); + + gparray = g_ptr_array_new_from_null_terminated_array ( + NULL, NULL, 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_from_null_terminated_array_with_copy_and_free_func (void) +{ + const size_t array_size = 10000; + GPtrArray *source_array; + GPtrArray *gparray; + GStrv old_pdata_copy; + + source_array = g_ptr_array_new_null_terminated (array_size, g_free, TRUE); + g_assert_true (g_ptr_array_is_null_terminated (source_array)); + + for (size_t i = 0; i < array_size; i++) + g_ptr_array_add (source_array, g_strdup_printf ("%" G_GSIZE_FORMAT, i)); + + g_assert_cmpuint (array_size, ==, source_array->len); + g_assert_nonnull (source_array->pdata); + + old_pdata_copy = g_strdupv ((char **) source_array->pdata); + g_assert_cmpuint (g_strv_length (old_pdata_copy), ==, array_size); + g_assert_nonnull (old_pdata_copy); + g_clear_pointer (&source_array, g_ptr_array_unref); + + gparray = g_ptr_array_new_from_null_terminated_array ( + (gpointer* ) old_pdata_copy, (GCopyFunc) g_strdup, NULL, g_free); + g_assert_true (g_ptr_array_is_null_terminated (gparray)); + assert_ptr_array_null_terminated (gparray, TRUE); + + for (size_t i = 0; i < gparray->len; i++) + { + g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==, + (const char *) old_pdata_copy[i]); + } + + 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_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); + assert_ptr_array_null_terminated (gparray, TRUE); + g_assert_cmpuint (gparray->len, ==, array_size + 1); + + g_ptr_array_remove_index (gparray, gparray->len - 1); + assert_ptr_array_null_terminated (gparray, TRUE); + g_assert_cmpuint (gparray->len, ==, array_size); + + for (size_t i = 0; i < gparray->len; i++) + { + g_assert_cmpstr ((const char *) g_ptr_array_index (gparray, i), ==, + (const char *) old_pdata_copy[i]); + } + + g_ptr_array_unref (gparray); + g_strfreev (old_pdata_copy); +} + +static void +pointer_array_new_from_null_terminated_array_from_gstrv (void) +{ + GPtrArray *gparray; + GStrv strv; + char *joined; + + strv = g_strsplit ("A.dot.separated.string", ".", -1); + gparray = g_ptr_array_new_from_null_terminated_array ( + (gpointer) strv, NULL, NULL, NULL); + + g_assert_cmpstr ( + (const char *) g_ptr_array_index (gparray, 0), ==, "A"); + g_assert_true (g_ptr_array_index (gparray, 0) == strv[0]); + g_assert_cmpstr ( + (const char *) g_ptr_array_index (gparray, 1), ==, "dot"); + g_assert_true (g_ptr_array_index (gparray, 1) == strv[1]); + g_assert_cmpstr ( + (const char *) g_ptr_array_index (gparray, 2), ==, "separated"); + g_assert_true (g_ptr_array_index (gparray, 2) == strv[2]); + g_assert_cmpstr ( + (const char *) g_ptr_array_index (gparray, 3), ==, "string"); + g_assert_true (g_ptr_array_index (gparray, 3) == strv[3]); + + g_assert_null (strv[4]); + 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_strfreev (strv); + g_free (joined); +} + +static void pointer_array_ref_count (gconstpointer test_data) { const gboolean null_terminated = GPOINTER_TO_INT (test_data); @@ -2158,6 +2980,10 @@ main (int argc, char *argv[]) /* array tests */ g_test_add_func ("/array/new/zero-terminated", array_new_zero_terminated); + g_test_add_func ("/array/new/take", array_new_take); + 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/ref-count", array_ref_count); g_test_add_func ("/array/steal", array_steal); g_test_add_func ("/array/clear-func", array_clear_func); @@ -2186,6 +3012,22 @@ main (int argc, char *argv[]) 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/new-take", pointer_array_new_take); + 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_func ("/pointerarray/new-from-array", pointer_array_new_from_array); + g_test_add_func ("/pointerarray/new-from-array/empty", pointer_array_new_from_array_empty); + g_test_add_func ("/pointerarray/new-from-array/overflow", pointer_array_new_from_array_overflow); + g_test_add_func ("/pointerarray/new-from-array/with-copy-and-free-func", pointer_array_new_from_array_with_copy_and_free_func); + g_test_add_func ("/pointerarray/new-from-null-terminated-array", pointer_array_new_from_null_terminated_array); + g_test_add_func ("/pointerarray/new-from-null-terminated-array/empty", pointer_array_new_from_null_terminated_array_empty); + g_test_add_func ("/pointerarray/new-from-null-terminated-array/with-copy-and-free-func", pointer_array_new_from_null_terminated_array_with_copy_and_free_func); + g_test_add_func ("/pointerarray/new-from-null-terminated-array/from-gstrv", pointer_array_new_from_null_terminated_array_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); |