Commit 79058b6d authored by Simon McVittie's avatar Simon McVittie

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: Simon McVittie's avatarSimon McVittie <smcv@collabora.com>
parent a48eafa7
......@@ -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
teardown (Fixture *f,
gconstpointer data)
......@@ -149,6 +191,7 @@ main (int argc,
g_test_add ("/build-filename", Fixture, NULL, setup,
test_build_filename, teardown);
g_test_add ("/ptr-list", Fixture, NULL, setup, test_ptr_list, teardown);
return g_test_run ();
}
......@@ -462,6 +462,41 @@ ptr_list_alloc(size_t size)
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
ptr_list_free (ptr_list *list)
{
......
......@@ -75,6 +75,7 @@ typedef int (*ptrcmp) (const void *a, const void *b);
ptr_list *ptr_list_alloc (size_t size);
void *ptr_list_nth_ptr (ptr_list *list, size_t nth);
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_addr (ptr_list *list, ElfW(Addr) addr);
int ptr_list_contains (ptr_list *list, ElfW(Addr) addr);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment