arraylist: add g_array_list_move()

This function will do a more optimzed move of an item within the list
than its equivelent, g_array_list_remove() and g_array_list_prepend().
This commit is contained in:
Christian Hergert 2015-09-13 04:58:09 -07:00
parent dad8c25e9d
commit 4232c04655
3 changed files with 64 additions and 1 deletions

View File

@ -644,3 +644,51 @@ g_array_list_copy_reversed (GArrayList *self,
return ret;
}
/**
* g_array_list_move:
* @self: A #GListArray
* @src: the index of the item to move
* @dest: the new index to place the item.
*
* This function is analagous to calling g_array_list_remove_index() followed
* by g_array_list_insert() but allows for avoiding the need to copy the item
* as well as re-build the linked list twice.
*/
void
g_array_list_move (GArrayList *self,
gsize src,
gsize dest)
{
GArrayListAny *any = (GArrayListAny *)self;
GArrayListEmbed *embed = (GArrayListEmbed *)self;
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
GList *items;
gpointer src_data;
gsize i;
g_return_if_fail (self != NULL);
g_return_if_fail (src < any->len);
g_return_if_fail (dest < any->len);
if (src == dest)
return;
items = (any->mode == MODE_EMBED) ? embed->items : alloc->items;
src_data = items [src].data;
if (dest < src)
{
for (i = src; i > dest; i--)
items [i].data = items [i - 1].data;
}
else
{
for (i = src; i < dest; i++)
items [i].data = items [i + 1].data;
}
items [dest].data = src_data;
_g_array_list_update_pointers (items, any->len);
}

View File

@ -95,6 +95,11 @@ gpointer *g_array_list_copy_reversed(GArrayList *list,
GCopyFunc copy_func,
gpointer copy_data);
GLIB_AVAILABLE_IN_2_46
void g_array_list_move (GArrayList *list,
gsize src,
gsize dest);
#define g_array_list_empty(list) ((list)->len == 0)
#define g_array_list_first(list) (((list)->len == 0) ? NULL : g_array_list_index((list),0))
#define g_array_list_last(list) (((list)->len == 0) ? NULL : g_array_list_index((list),(list)->len-1))

View File

@ -76,13 +76,23 @@ test_basic (GArrayList *al)
g_assert_cmpint (al->len, ==, 500);
g_assert_cmpint (test_basic_counter, ==, 500);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_last (al)), ==, 1000);
g_array_list_prepend (al, GSIZE_TO_POINTER (191919));
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_index (al, 0)), ==, 191919);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_last (al)), ==, 1000);
g_array_list_move (al, 0, al->len - 1);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_index (al, 0)), ==, 501);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_last (al)), ==, 191919);
g_array_list_move (al, al->len - 1, 0);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_index (al, 0)), ==, 191919);
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_last (al)), ==, 1000);
g_array_list_clear (al);
g_assert_cmpint (al->len, ==, 0);
g_assert_cmpint (test_basic_counter, ==, 1000);
g_assert_cmpint (test_basic_counter, ==, 1001);
g_array_list_destroy (al);