From 4232c04655d3eb5b2c2430e5ed6f16fcff2d7e43 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 13 Sep 2015 04:58:09 -0700 Subject: [PATCH] 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(). --- glib/garraylist.c | 48 ++++++++++++++++++++++++++++++++++++++++++ glib/garraylist.h | 5 +++++ glib/tests/arraylist.c | 12 ++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/glib/garraylist.c b/glib/garraylist.c index 177883732..9c00e3030 100644 --- a/glib/garraylist.c +++ b/glib/garraylist.c @@ -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); +} diff --git a/glib/garraylist.h b/glib/garraylist.h index d41aac63d..c078c3e34 100644 --- a/glib/garraylist.h +++ b/glib/garraylist.h @@ -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)) diff --git a/glib/tests/arraylist.c b/glib/tests/arraylist.c index 43fe8ffbd..6b51aa74a 100644 --- a/glib/tests/arraylist.c +++ b/glib/tests/arraylist.c @@ -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);