Skip to content
Snippets Groups Projects
Commit 79058b6d authored by Simon McVittie's avatar Simon McVittie
Browse files

utils: Add and test ptr_list_free_to_array


Inspired by g_ptr_array_free(., FALSE) and g_bytes_unref_to_array(),
this lets us convert a ptr_list into a raw array suitable for use
with qsort() and bsearch().

Signed-off-by: default avatarSimon McVittie <smcv@collabora.com>
parent a48eafa7
No related branches found
No related tags found
1 merge request!311Build capsule-capture-libs from a bundled copy of libcapsule
...@@ -134,6 +134,48 @@ test_build_filename (Fixture *f, ...@@ -134,6 +134,48 @@ test_build_filename (Fixture *f,
} }
} }
static void
test_ptr_list (Fixture *f,
gconstpointer data)
{
size_t n;
ptr_list *list;
void **array;
list = ptr_list_alloc (0);
ptr_list_push_ptr (list, (char *) "hello");
ptr_list_add_ptr (list, (char *) "world", g_str_equal);
ptr_list_add_ptr (list, (char *) "hello", g_str_equal); // duplicate, not added
ptr_list_add_ptr (list, (char *) "world", g_str_equal); // duplicate, not added
ptr_list_push_ptr (list, (char *) "hello");
ptr_list_push_ptr (list, NULL);
ptr_list_push_addr (list, 23);
g_assert_cmpstr (ptr_list_nth_ptr (list, 0), ==, "hello");
g_assert_cmpstr (ptr_list_nth_ptr (list, 1), ==, "world");
g_assert_cmpstr (ptr_list_nth_ptr (list, 2), ==, "hello");
g_assert_cmpstr (ptr_list_nth_ptr (list, 3), ==, NULL);
g_assert_cmpuint (GPOINTER_TO_SIZE (ptr_list_nth_ptr (list, 4)), ==, 23);
g_assert_cmpstr (ptr_list_nth_ptr (list, 5), ==, NULL);
g_assert_cmpstr (ptr_list_nth_ptr (list, 47), ==, NULL);
g_assert_true (ptr_list_contains (list, 23));
g_assert_true (ptr_list_contains (list, (ElfW(Addr)) ptr_list_nth_ptr (list, 1)));
g_assert_false (ptr_list_contains (list, 1));
array = ptr_list_free_to_array (list, &n);
g_assert_cmpint (n, ==, 5);
g_assert_cmpstr (array[0], ==, "hello");
g_assert_cmpstr (array[1], ==, "world");
g_assert_cmpstr (array[2], ==, "hello");
g_assert_cmpstr (array[3], ==, NULL);
g_assert_cmpuint (GPOINTER_TO_SIZE (array[4]), ==, 23);
g_assert_cmpstr (array[5], ==, NULL);
free (array);
list = ptr_list_alloc (0);
ptr_list_free (list);
}
static void static void
teardown (Fixture *f, teardown (Fixture *f,
gconstpointer data) gconstpointer data)
...@@ -149,6 +191,7 @@ main (int argc, ...@@ -149,6 +191,7 @@ main (int argc,
g_test_add ("/build-filename", Fixture, NULL, setup, g_test_add ("/build-filename", Fixture, NULL, setup,
test_build_filename, teardown); test_build_filename, teardown);
g_test_add ("/ptr-list", Fixture, NULL, setup, test_ptr_list, teardown);
return g_test_run (); return g_test_run ();
} }
...@@ -462,6 +462,41 @@ ptr_list_alloc(size_t size) ...@@ -462,6 +462,41 @@ ptr_list_alloc(size_t size)
return list; return list;
} }
/*
* ptr_list_free_to_array:
* @list: (transfer full): list to free
* @n: (out) (optional): if not %NULL, used to return the number of
* items that were in @list
*
* Add an extra %NULL entry to @list, then return an array with the
* same contents as @list, freeing @list. If @n is not %NULL, set it
* to the number of elements in the returned array before the %NULL
* added by this function.
*/
void **
ptr_list_free_to_array (ptr_list *list, size_t *n)
{
void *ret;
// Without these assertions, it's unsafe to assign a ptr_item *
// to a void **
static_assert( alignof( void * ) == alignof( ptr_item ),
"union {void *, ElfW(Addr)} assumed to be same size "
"as void *");
static_assert( sizeof( void * ) == sizeof( ptr_item ),
"union {void *, ElfW(Addr)} assumed to be same "
"alignment as void *");
if( n != NULL )
*n = list->next;
ptr_list_push_ptr( list, NULL );
ret = list->loc;
list->loc = NULL;
ptr_list_free (list);
return ret;
}
void void
ptr_list_free (ptr_list *list) ptr_list_free (ptr_list *list)
{ {
......
...@@ -75,6 +75,7 @@ typedef int (*ptrcmp) (const void *a, const void *b); ...@@ -75,6 +75,7 @@ typedef int (*ptrcmp) (const void *a, const void *b);
ptr_list *ptr_list_alloc (size_t size); ptr_list *ptr_list_alloc (size_t size);
void *ptr_list_nth_ptr (ptr_list *list, size_t nth); void *ptr_list_nth_ptr (ptr_list *list, size_t nth);
void ptr_list_free (ptr_list *list); void ptr_list_free (ptr_list *list);
void **ptr_list_free_to_array (ptr_list *list, size_t *n);
void ptr_list_push_ptr (ptr_list *list, void *ptr); void ptr_list_push_ptr (ptr_list *list, void *ptr);
void ptr_list_push_addr (ptr_list *list, ElfW(Addr) addr); void ptr_list_push_addr (ptr_list *list, ElfW(Addr) addr);
int ptr_list_contains (ptr_list *list, ElfW(Addr) addr); int ptr_list_contains (ptr_list *list, ElfW(Addr) addr);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment