arraylist: add g_array_list_prepend()

Not the most optimized way to do this, but we need it to make incremental
porting easier. We can also look at changing directions based on the
common access pattern (since we have O(1) access to head and tail).
This commit is contained in:
Christian Hergert 2015-09-13 03:52:59 -07:00
parent 2b1e7de628
commit 87dee43c42
3 changed files with 74 additions and 13 deletions

View File

@ -183,12 +183,31 @@ g_array_list_index (GArrayList *self,
return items [index].data; return items [index].data;
} }
static inline void
_g_array_list_update_pointers (GList *array,
gsize array_len)
{
gsize i;
if (array_len > 0)
array [0].next = &array [1];
for (i = 1; i < (array_len - 1); i++)
{
array [i].prev = &array [i - 1];
array [i].next = &array [i + 1];
}
if (array_len > 1)
array [array_len- 1].prev = &array [array_len - 1 - 1];
}
static void static void
_g_array_list_grow (GArrayList *self) _g_array_list_grow (GArrayList *self,
gboolean update_pointers)
{ {
GArrayListAlloc *alloc = (GArrayListAlloc *)self; GArrayListAlloc *alloc = (GArrayListAlloc *)self;
gpointer old_items; gpointer old_items;
gsize i;
DEBUG_ASSERT (self != NULL); DEBUG_ASSERT (self != NULL);
DEBUG_ASSERT (alloc->mode == MODE_ALLOC); DEBUG_ASSERT (alloc->mode == MODE_ALLOC);
@ -203,17 +222,10 @@ _g_array_list_grow (GArrayList *self)
if (G_LIKELY (old_items == alloc->items)) if (G_LIKELY (old_items == alloc->items))
return; return;
if (alloc->len > 0) if (!update_pointers)
alloc->items [0].next = &alloc->items [1]; return;
for (i = 1; i < (alloc->len - 1); i++) _g_array_list_update_pointers (alloc->items, alloc->len);
{
alloc->items [i].prev = &alloc->items [i-1];
alloc->items [i].next = &alloc->items [i+1];
}
if (alloc->len > 1)
alloc->items [alloc->len - 1].prev = &alloc->items [alloc->len - 1 - 1];
} }
static void static void
@ -301,7 +313,7 @@ g_array_list_add (GArrayList *self,
DEBUG_ASSERT (any->mode == MODE_ALLOC); DEBUG_ASSERT (any->mode == MODE_ALLOC);
if (G_UNLIKELY (alloc->len == alloc->items_len)) if (G_UNLIKELY (alloc->len == alloc->items_len))
_g_array_list_grow (self); _g_array_list_grow (self, TRUE);
item = &alloc->items [alloc->len]; item = &alloc->items [alloc->len];
prev = (alloc->len > 0) ? &alloc->items [alloc->len - 1] : NULL; prev = (alloc->len > 0) ? &alloc->items [alloc->len - 1] : NULL;
@ -320,6 +332,47 @@ g_array_list_add (GArrayList *self,
DEBUG_ASSERT (alloc->items [alloc->len - 1].data == data); DEBUG_ASSERT (alloc->items [alloc->len - 1].data == data);
} }
void
g_array_list_prepend (GArrayList *self,
gpointer data)
{
GArrayListAny *any = (GArrayListAny *)self;
GArrayListEmbed *embed = (GArrayListEmbed *)self;
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
g_return_if_fail (self != NULL);
if (G_LIKELY (any->mode == MODE_EMBED))
{
if (G_LIKELY (embed->len < G_N_ELEMENTS (embed->items)))
{
memmove (&embed->items [1], &embed->items [0], sizeof (GList) * embed->len);
embed->items [0].prev = NULL;
embed->items [0].next = &embed->items [1];
embed->items [0].data = data;
embed->len++;
return;
}
_g_array_list_transition (self);
}
DEBUG_ASSERT (any->mode == MODE_ALLOC);
if (G_UNLIKELY (alloc->len == alloc->items_len))
_g_array_list_grow (self, FALSE);
memmove (&alloc->items [1], &alloc->items [0], sizeof (GList) * alloc->len);
alloc->items [0].data = data;
_g_array_list_update_pointers (alloc->items, alloc->len);
DEBUG_ASSERT (alloc->len <= alloc->items_len);
DEBUG_ASSERT (alloc->len > 0);
DEBUG_ASSERT (alloc->items [0].data == data);
}
void void
g_array_list_remove_index (GArrayList *self, g_array_list_remove_index (GArrayList *self,
guint index) guint index)

View File

@ -74,6 +74,10 @@ void g_array_list_destroy (GArrayList *list);
GLIB_AVAILABLE_IN_2_46 GLIB_AVAILABLE_IN_2_46
const GList *g_array_list_last_link (GArrayList *list); const GList *g_array_list_last_link (GArrayList *list);
GLIB_AVAILABLE_IN_2_46
void g_array_list_prepend (GArrayList *list,
gpointer data);
#define g_array_list_first(list) (((list)->len == 0) ? NULL : g_array_list_index((list),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)) #define g_array_list_last(list) (((list)->len == 0) ? NULL : g_array_list_index((list),(list)->len-1))

View File

@ -73,6 +73,10 @@ test_basic (GArrayList *al)
g_assert_cmpint (al->len, ==, 500); g_assert_cmpint (al->len, ==, 500);
g_assert_cmpint (test_basic_counter, ==, 500); g_assert_cmpint (test_basic_counter, ==, 500);
g_array_list_prepend (al, GSIZE_TO_POINTER (191919));
g_assert_cmpint (GPOINTER_TO_SIZE (g_array_list_index (al, 0)), ==, 191919);
g_array_list_destroy (al); g_array_list_destroy (al);
g_assert_cmpint (test_basic_counter, ==, 1000); g_assert_cmpint (test_basic_counter, ==, 1000);