mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-23 18:52:09 +01:00
arraylist: add GArrayList
GArrayList is a datastructure that allows you to store data internally as an array for fast index based access. However, it maintains that array as an array of GList so that you can also use the data in compatability APIs as a GList. This has some additional costs in keeping the array based GList pointers in sync, but overhead is mitigated in the common cases of small lists. You can also embed the structure removing malloc overhead for small cases such as [0..2].
This commit is contained in:
parent
a51a877d27
commit
094785b790
@ -2524,6 +2524,20 @@ g_ptr_array_foreach
|
||||
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>List Arrays</TITLE>
|
||||
<FILE>arraylist</FILE>
|
||||
GArrayList
|
||||
g_array_list_new
|
||||
g_array_list_init
|
||||
g_array_list_peek
|
||||
g_array_list_index
|
||||
g_array_list_add
|
||||
g_array_list_remove
|
||||
g_array_list_remove_index
|
||||
g_array_list_destroy
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>Byte Arrays</TITLE>
|
||||
<FILE>arrays_byte</FILE>
|
||||
|
@ -103,6 +103,7 @@ libglib_2_0_la_SOURCES = \
|
||||
$(deprecated_sources) \
|
||||
glib_probes.d \
|
||||
garray.c \
|
||||
garraylist.c \
|
||||
gasyncqueue.c \
|
||||
gasyncqueueprivate.h \
|
||||
gatomic.c \
|
||||
@ -245,6 +246,7 @@ glibsubinclude_HEADERS = \
|
||||
glib-autocleanups.h \
|
||||
galloca.h \
|
||||
garray.h \
|
||||
garraylist.h \
|
||||
gasyncqueue.h \
|
||||
gatomic.h \
|
||||
gbacktrace.h \
|
||||
|
428
glib/garraylist.c
Normal file
428
glib/garraylist.c
Normal file
@ -0,0 +1,428 @@
|
||||
/* garraylist.c
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "garraylist.h"
|
||||
#include "gmessages.h"
|
||||
#include "gslice.h"
|
||||
|
||||
/**
|
||||
* SECTION:garraylist
|
||||
* @title: GArrayList
|
||||
* @short_description: Linked lists implemented as arrays.
|
||||
*
|
||||
* Sometimes, when building APIs we make mistakes about the undelrying
|
||||
* data structure that should have been used. GArrayList is a data structure
|
||||
* that allows read-only compatability with #GList but is implemented as an
|
||||
* array underneath. This means fast forward and backward iteration using
|
||||
* typical array style index access, while providing read-only #GList access
|
||||
* for compatability APIs.
|
||||
*
|
||||
* There is a cost associated with doing this, but the trade-off can be worth
|
||||
* it under certain scenarios.
|
||||
*
|
||||
* Mutating the array list is potentially more expensive than a #GList.
|
||||
* However, given no array growth is required, appending to the array list
|
||||
* can be performed in O(1).
|
||||
*
|
||||
* The ideal use case for this data structure is a read-heavy data set
|
||||
* where reverse iteration may be necessary and compatability with #GList
|
||||
* must be maintained.
|
||||
*
|
||||
* It is unlikely that you should be writing new APIs that use this
|
||||
* data structure.
|
||||
*
|
||||
* Since: 2.48
|
||||
*/
|
||||
|
||||
#if 0
|
||||
# define DEBUG_ASSERT(x) g_assert(x)
|
||||
#else
|
||||
# define DEBUG_ASSERT(x)
|
||||
#endif
|
||||
|
||||
#define G_ARRAY_LIST_DEFAULT_ALLOC 8
|
||||
|
||||
/*
|
||||
* The following structures give us a data-structure that can be dynamic,
|
||||
* by changing it's implementation based on the number of items in the
|
||||
* #GArrayList. When we have 2 or fewer items, we simply embed the #GList
|
||||
* items in the toplevel structure.
|
||||
*
|
||||
* When this grows, we allocate an array to contain the #GList items and
|
||||
* update prev/next pionters as necessary.
|
||||
*
|
||||
* This structure allows for fast iteration forwards and backwards from any
|
||||
* arbitrary point in the structure, just like an array. It also allows for
|
||||
* returning a read-only #GList for when API compatability is needed.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint len;
|
||||
guint flags;
|
||||
GDestroyNotify destroy;
|
||||
GList items[2];
|
||||
} GArrayListEmbed;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint len;
|
||||
guint flags;
|
||||
GDestroyNotify destroy;
|
||||
|
||||
/*
|
||||
* This is an array of GList items, which we keep in sync by updating
|
||||
* the next/prev pointers when necessary.
|
||||
*/
|
||||
GList *items;
|
||||
gsize items_len;
|
||||
|
||||
gpointer padding[4];
|
||||
} GArrayListAlloc;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint len;
|
||||
guint on_heap : 1;
|
||||
guint mode : 31;
|
||||
GDestroyNotify destroy;
|
||||
gpointer padding[6];
|
||||
} GArrayListAny;
|
||||
|
||||
G_STATIC_ASSERT (sizeof (GArrayListAny) == sizeof (GArrayList));
|
||||
G_STATIC_ASSERT (sizeof (GArrayListAny) == sizeof (GArrayListAlloc));
|
||||
G_STATIC_ASSERT (sizeof (GArrayListAny) == sizeof (GArrayListEmbed));
|
||||
|
||||
enum {
|
||||
MODE_EMBED,
|
||||
MODE_ALLOC,
|
||||
};
|
||||
|
||||
GArrayList *
|
||||
g_array_list_new (GDestroyNotify destroy)
|
||||
{
|
||||
GArrayListAny *any;
|
||||
|
||||
any = g_slice_new0 (GArrayListAny);
|
||||
|
||||
any->mode = MODE_EMBED;
|
||||
any->len = 0;
|
||||
any->destroy = destroy;
|
||||
any->on_heap = TRUE;
|
||||
|
||||
return (GArrayList *)any;
|
||||
}
|
||||
|
||||
void
|
||||
g_array_list_init (GArrayList *self,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
memset (any, 0, sizeof *any);
|
||||
|
||||
any->mode = MODE_EMBED;
|
||||
any->len = 0;
|
||||
any->destroy = destroy;
|
||||
any->on_heap = FALSE;
|
||||
}
|
||||
|
||||
const GList *
|
||||
g_array_list_peek (GArrayList *self)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
|
||||
g_return_val_if_fail (self != NULL, NULL);
|
||||
|
||||
if (self->len == 0)
|
||||
return NULL;
|
||||
|
||||
return (any->mode == MODE_EMBED) ? embed->items : (GList *)alloc->items;
|
||||
}
|
||||
|
||||
gpointer
|
||||
g_array_list_index (GArrayList *self,
|
||||
guint index)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *items;
|
||||
|
||||
g_return_val_if_fail (self != NULL, NULL);
|
||||
g_return_val_if_fail (index < self->len, NULL);
|
||||
|
||||
DEBUG_ASSERT ((any->len < G_N_ELEMENTS (embed->items)) ||
|
||||
(any->mode == MODE_ALLOC));
|
||||
|
||||
items = (any->mode == MODE_EMBED) ? embed->items : (GList *)alloc->items;
|
||||
|
||||
return items [index].data;
|
||||
}
|
||||
|
||||
static void
|
||||
_g_array_list_grow (GArrayList *self)
|
||||
{
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
gpointer old_items;
|
||||
gsize i;
|
||||
|
||||
DEBUG_ASSERT (self != NULL);
|
||||
DEBUG_ASSERT (alloc->mode == MODE_ALLOC);
|
||||
DEBUG_ASSERT (alloc->len < G_MAXINT);
|
||||
DEBUG_ASSERT (alloc->len > 0);
|
||||
|
||||
old_items = alloc->items;
|
||||
|
||||
alloc->items_len <<= 1;
|
||||
alloc->items = g_realloc_n (alloc->items, alloc->items_len, sizeof (GList));
|
||||
|
||||
if (G_LIKELY (old_items == alloc->items))
|
||||
return;
|
||||
|
||||
if (alloc->len > 0)
|
||||
alloc->items [0].next = &alloc->items [1];
|
||||
|
||||
for (i = 1; i < (alloc->len - 1); i++)
|
||||
{
|
||||
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
|
||||
_g_array_list_transition (GArrayList *self)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *items;
|
||||
gsize i;
|
||||
|
||||
DEBUG_ASSERT (self != NULL);
|
||||
DEBUG_ASSERT (embed->mode == MODE_EMBED);
|
||||
DEBUG_ASSERT (embed->len == G_N_ELEMENTS (embed->items));
|
||||
|
||||
items = g_malloc_n (G_ARRAY_LIST_DEFAULT_ALLOC, sizeof (GList));
|
||||
|
||||
items [0].prev = NULL;
|
||||
items [0].data = embed->items [0].data;
|
||||
items [0].next = &items [1];
|
||||
|
||||
for (i = 1; i < (G_N_ELEMENTS (embed->items) - 1); i++)
|
||||
{
|
||||
items [i].prev = &items [i - 1];
|
||||
items [i].next = &items [i + 1];
|
||||
items [i].data = &embed->items [i].data;
|
||||
}
|
||||
|
||||
items [G_N_ELEMENTS (embed->items) - 1].prev = &items [G_N_ELEMENTS (embed->items) - 1 - 1];
|
||||
items [G_N_ELEMENTS (embed->items) - 1].next = NULL;
|
||||
items [G_N_ELEMENTS (embed->items) - 1].data = embed->items [G_N_ELEMENTS (embed->items) - 1].data;
|
||||
|
||||
any->mode = MODE_ALLOC;
|
||||
|
||||
alloc->items_len = G_ARRAY_LIST_DEFAULT_ALLOC;
|
||||
alloc->items = items;
|
||||
}
|
||||
|
||||
void
|
||||
g_array_list_add (GArrayList *self,
|
||||
gpointer data)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *item;
|
||||
GList *prev;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
if (G_LIKELY (any->mode == MODE_EMBED))
|
||||
{
|
||||
if (G_LIKELY (embed->len < G_N_ELEMENTS (embed->items)))
|
||||
{
|
||||
if (G_LIKELY (embed->len == 0))
|
||||
{
|
||||
embed->items [0].prev = NULL;
|
||||
embed->items [0].next = NULL;
|
||||
embed->items [0].data = data;
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = &embed->items [embed->len - 1];
|
||||
item = &embed->items [embed->len];
|
||||
|
||||
item->prev = prev;
|
||||
item->next = NULL;
|
||||
item->data = data;
|
||||
|
||||
prev->next = item;
|
||||
}
|
||||
|
||||
embed->len++;
|
||||
|
||||
DEBUG_ASSERT (embed->len <= G_N_ELEMENTS (embed->items));
|
||||
DEBUG_ASSERT (embed->len > 0);
|
||||
DEBUG_ASSERT (embed->items [embed->len - 1].data == data);
|
||||
|
||||
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);
|
||||
|
||||
item = &alloc->items [alloc->len];
|
||||
prev = (alloc->len > 0) ? &alloc->items [alloc->len - 1] : NULL;
|
||||
|
||||
item->data = data;
|
||||
item->prev = NULL;
|
||||
item->next = NULL;
|
||||
|
||||
if (prev)
|
||||
prev->next = item;
|
||||
|
||||
alloc->len++;
|
||||
|
||||
DEBUG_ASSERT (alloc->len <= alloc->items_len);
|
||||
DEBUG_ASSERT (alloc->len > 0);
|
||||
DEBUG_ASSERT (alloc->items [alloc->len - 1].data == data);
|
||||
}
|
||||
|
||||
void
|
||||
g_array_list_remove_index (GArrayList *self,
|
||||
guint index)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *items;
|
||||
gpointer data = NULL;
|
||||
gsize i;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
g_return_if_fail (index < self->len);
|
||||
|
||||
if (G_LIKELY (any->mode == MODE_EMBED))
|
||||
{
|
||||
DEBUG_ASSERT (index < G_N_ELEMENTS (embed->items));
|
||||
|
||||
data = embed->items [index].data;
|
||||
embed->len--;
|
||||
items = embed->items;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_ASSERT (any->mode == MODE_ALLOC);
|
||||
DEBUG_ASSERT (index < alloc->items_len);
|
||||
|
||||
data = alloc->items [index].data;
|
||||
alloc->len--;
|
||||
items = alloc->items;
|
||||
}
|
||||
|
||||
if (index != alloc->len)
|
||||
memmove (&items [index],
|
||||
&items [index + 1],
|
||||
sizeof (GList) * (any->len - index));
|
||||
|
||||
for (i = index; i < any->len; i++)
|
||||
{
|
||||
if (i > 0)
|
||||
items [i].prev = &items [i - 1];
|
||||
else
|
||||
items [i].prev = NULL;
|
||||
|
||||
if (i < (any->len - 1))
|
||||
items [i].next = &items [i + 1];
|
||||
else
|
||||
items [i].next = NULL;
|
||||
}
|
||||
|
||||
if (any->destroy)
|
||||
any->destroy (data);
|
||||
}
|
||||
|
||||
void
|
||||
g_array_list_remove (GArrayList *self,
|
||||
gpointer data)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *items;
|
||||
gsize i;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
items = (any->mode == MODE_EMBED) ? embed->items : alloc->items;
|
||||
|
||||
for (i = 0; i < any->len; i++)
|
||||
{
|
||||
if (items [i].data == data)
|
||||
{
|
||||
g_array_list_remove_index (self, i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
g_warning ("Failed to locate %p in GArrayList", data);
|
||||
}
|
||||
|
||||
void
|
||||
g_array_list_destroy (GArrayList *self)
|
||||
{
|
||||
GArrayListAny *any = (GArrayListAny *)self;
|
||||
GArrayListEmbed *embed = (GArrayListEmbed *)self;
|
||||
GArrayListAlloc *alloc = (GArrayListAlloc *)self;
|
||||
GList *items;
|
||||
gsize i;
|
||||
|
||||
g_return_if_fail (self != NULL);
|
||||
|
||||
if (any->mode == MODE_EMBED)
|
||||
items = embed->items;
|
||||
else
|
||||
items = alloc->items;
|
||||
|
||||
if (any->destroy)
|
||||
for (i = 0; i < any->len; i++)
|
||||
any->destroy (items [i].data);
|
||||
|
||||
if (any->mode == MODE_ALLOC)
|
||||
g_free (alloc->items);
|
||||
|
||||
if (any->on_heap)
|
||||
g_slice_free (GArrayListAny, any);
|
||||
}
|
76
glib/garraylist.h
Normal file
76
glib/garraylist.h
Normal file
@ -0,0 +1,76 @@
|
||||
/* garraylist.h
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This file is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __G_ARRAY_LIST_H__
|
||||
#define __G_ARRAY_LIST_H__
|
||||
|
||||
#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
|
||||
#error "Only <glib.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <glib/gtypes.h>
|
||||
#include <glib/glist.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint len;
|
||||
|
||||
guint padding;
|
||||
gpointer padding1;
|
||||
gpointer padding2;
|
||||
gpointer padding3;
|
||||
gpointer padding4;
|
||||
gpointer padding5;
|
||||
gpointer padding6;
|
||||
gpointer padding7;
|
||||
} GArrayList;
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
GArrayList *g_array_list_new (GDestroyNotify notify);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_array_list_init (GArrayList *list,
|
||||
GDestroyNotify notify);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
const GList *g_array_list_peek (GArrayList *list);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
gpointer g_array_list_index (GArrayList *list,
|
||||
guint index);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_array_list_add (GArrayList *list,
|
||||
gpointer data);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_array_list_remove (GArrayList *list,
|
||||
gpointer data);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_array_list_remove_index (GArrayList *list,
|
||||
guint index);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_46
|
||||
void g_array_list_destroy (GArrayList *list);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __G_ARRAY_LIST_H__ */
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <glib/galloca.h>
|
||||
#include <glib/garray.h>
|
||||
#include <glib/garraylist.h>
|
||||
#include <glib/gasyncqueue.h>
|
||||
#include <glib/gatomic.h>
|
||||
#include <glib/gbacktrace.h>
|
||||
|
1
glib/tests/.gitignore
vendored
1
glib/tests/.gitignore
vendored
@ -3,6 +3,7 @@
|
||||
642026
|
||||
642026-ec
|
||||
array-test
|
||||
arraylist
|
||||
asyncqueue
|
||||
atomic
|
||||
autoptr
|
||||
|
@ -31,6 +31,7 @@ test_extra_programs = \
|
||||
|
||||
test_programs = \
|
||||
array-test \
|
||||
arraylist \
|
||||
asyncqueue \
|
||||
base64 \
|
||||
bitlock \
|
||||
|
100
glib/tests/arraylist.c
Normal file
100
glib/tests/arraylist.c
Normal file
@ -0,0 +1,100 @@
|
||||
/* arraylist.c
|
||||
*
|
||||
* Copyright (C) 2015 Christian Hergert <christian@hergert.me>
|
||||
*
|
||||
* This is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
static int test_basic_counter;
|
||||
|
||||
static void
|
||||
test_basic_destroy (gpointer data)
|
||||
{
|
||||
test_basic_counter++;
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic (GArrayList *al)
|
||||
{
|
||||
const GList *iter, *list;
|
||||
gsize i;
|
||||
gsize counter = 0;
|
||||
|
||||
g_assert (al != NULL);
|
||||
g_assert_cmpint (al->len, ==, 0);
|
||||
|
||||
for (i = 1; i <= 1000; i++)
|
||||
{
|
||||
g_array_list_add (al, GSIZE_TO_POINTER (i));
|
||||
g_assert_cmpint (al->len, ==, i);
|
||||
}
|
||||
|
||||
list = g_array_list_peek (al);
|
||||
|
||||
for (iter = list; iter; iter = iter->next)
|
||||
{
|
||||
counter++;
|
||||
g_assert_cmpint (counter, ==, GPOINTER_TO_SIZE (iter->data));
|
||||
}
|
||||
|
||||
g_assert_cmpint (counter, ==, 1000);
|
||||
|
||||
for (i = 1; i <= 500; i++)
|
||||
{
|
||||
gpointer item = GSIZE_TO_POINTER (i);
|
||||
gpointer val = g_array_list_index (al, 0);
|
||||
g_assert_cmpint (GPOINTER_TO_SIZE (val), ==, i);
|
||||
g_array_list_remove (al, item);
|
||||
}
|
||||
|
||||
g_assert_cmpint (al->len, ==, 500);
|
||||
g_assert_cmpint (test_basic_counter, ==, 500);
|
||||
g_array_list_destroy (al);
|
||||
g_assert_cmpint (test_basic_counter, ==, 1000);
|
||||
|
||||
test_basic_counter = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic_alloc (void)
|
||||
{
|
||||
test_basic (g_array_list_new (test_basic_destroy));
|
||||
}
|
||||
|
||||
static void
|
||||
test_basic_stack (void)
|
||||
{
|
||||
GArrayList al;
|
||||
|
||||
g_array_list_init (&al, test_basic_destroy);
|
||||
test_basic (&al);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
g_test_bug_base ("http://bugzilla.gnome.org/");
|
||||
|
||||
g_test_add_func ("/GArrayList/heap", test_basic_alloc);
|
||||
g_test_add_func ("/GArrayList/stack", test_basic_stack);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user