From: Aaron Bockover Date: Thu, 17 Aug 2006 21:49:00 +0000 (-0000) Subject: 2006-08-17 Aaron Bockover X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=4793cf9e5ffbe5cf97a547f9681ef66146c47498;p=mono.git 2006-08-17 Aaron Bockover * src/gptrarray.c: Added beginnings of GPtrArray (alloc, free, add, iterate) * src/glib.h: Added GPtrArray signatures * src/Makefile.am: Added gptrarray.c to build * test/ptrarray.c: * test/tests.h: * test/driver.c: * test/Makefile.am: Add ptrarray tests for available functionality svn path=/trunk/mono/; revision=63947 --- diff --git a/eglib/ChangeLog b/eglib/ChangeLog index d9dff20e706..5414e3390f9 100644 --- a/eglib/ChangeLog +++ b/eglib/ChangeLog @@ -1,3 +1,16 @@ +2006-08-17 Aaron Bockover + + * src/gptrarray.c: Added beginnings of GPtrArray (alloc, free, add, iterate) + + * src/glib.h: Added GPtrArray signatures + + * src/Makefile.am: Added gptrarray.c to build + + * test/ptrarray.c: + * test/tests.h: + * test/driver.c: + * test/Makefile.am: Add ptrarray tests for available functionality + 2006-08-17 Aaron Bockover * test/test.h: diff --git a/eglib/src/Makefile.am b/eglib/src/Makefile.am index f5604c9ec4c..4d084d09a66 100644 --- a/eglib/src/Makefile.am +++ b/eglib/src/Makefile.am @@ -1,13 +1,14 @@ noinst_LTLIBRARIES = libeglib.la libeglib_la_SOURCES = \ - ghashtable.c \ - gmem.c \ - gmodule.c \ - goutput.c \ - gstr.c \ - gslist.c \ - gstring.c + ghashtable.c \ + gmem.c \ + gmodule.c \ + goutput.c \ + gstr.c \ + gslist.c \ + gstring.c \ + gptrarray.c libeglib_la_CFLAGS = -Wall -Werror -D_FORTIFY_SOURCE=2 diff --git a/eglib/src/glib.h b/eglib/src/glib.h index 1261fc59936..bad2f0bc3a2 100644 --- a/eglib/src/glib.h +++ b/eglib/src/glib.h @@ -4,6 +4,7 @@ #include #include #include +#include /* * Basic data types @@ -74,6 +75,7 @@ gpointer g_memdup (gconstpointer mem, guint byte_size); typedef struct _GHashTable GHashTable; typedef void (*GFunc) (gpointer data, gpointer user_data); typedef gint (*GCompareFunc) (gconstpointer a, gconstpointer b); +typedef gint (*GCompareDataFunc) (gconstpointer a, gconstpointer b, gpointer user_data); typedef void (*GHFunc) (gpointer key, gpointer value, gpointer user_data); typedef gboolean (*GHRFunc) (gpointer key, gpointer value, gpointer user_data); typedef void (*GDestroyNotify) (gpointer data); @@ -168,6 +170,31 @@ GSList *g_slist_insert_sorted (GSList *list, gpointer data, GCompareFunc func); guint g_slist_length (GSList *list); #define g_slist_next (slist) ((slist) ? (((GSList *) slist)->next) : NULL) +/* + * Pointer Array + */ + +typedef struct _GPtrArray GPtrArray; +struct _GPtrArray { + gpointer *pdata; + guint len; +}; + +GPtrArray *g_ptr_array_new (); +GPtrArray *g_ptr_array_sized_new (guint reserved_size); +void g_ptr_array_add (GPtrArray *array, gpointer data); +gboolean g_ptr_array_remove (GPtrArray *array, gpointer data); +gpointer g_ptr_array_remove_index (GPtrArray *array, guint index); +gboolean g_ptr_array_remove_fast (GPtrArray *array, gpointer data); +gpointer g_ptr_array_remove_index_fast (GPtrArray *array, gpointer data); +void g_ptr_array_sort (GPtrArray *array, GCompareFunc compare_func); +void g_ptr_array_sort_with_data (GPtrArray *array, GCompareDataFunc compare_func, gpointer user_data); +void g_ptr_array_set_size (GPtrArray *array, gint length); +gpointer *g_ptr_array_free (GPtrArray *array, gboolean free_seg); +void g_ptr_array_foreach (GPtrArray *array, GFunc func, gpointer user_data); +#define g_ptr_array_index(array,index) array->pdata[index] + + /* * Modules */ diff --git a/eglib/src/gptrarray.c b/eglib/src/gptrarray.c new file mode 100644 index 00000000000..4d9b96f7c50 --- /dev/null +++ b/eglib/src/gptrarray.c @@ -0,0 +1,119 @@ +/* + * Pointer Array + * + * Author: + * Aaron Bockover (abockover@novell.com) + * + * (C) 2006 Novell, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#define _GNU_SOURCE +#include +#include + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) + +typedef struct _GPtrArrayPriv { + gpointer *pdata; + guint len; + guint size; +} GPtrArrayPriv; + +static void +g_ptr_array_grow(GPtrArrayPriv *array, guint length) +{ + gint new_length = array->len + length; + + g_return_if_fail(array != NULL); + + if(new_length <= array->size) { + return; + } + + array->size = 1; + + while(array->size < new_length) { + array->size <<= 1; + } + + array->size = MAX(array->size, 16); + array->pdata = g_realloc(array->pdata, array->size * sizeof(gpointer)); +} + +GPtrArray * +g_ptr_array_new() +{ + return g_ptr_array_sized_new(0); +} + +GPtrArray * +g_ptr_array_sized_new(guint reserved_size) +{ + GPtrArrayPriv *array = g_new0(GPtrArrayPriv, 1); + + array->pdata = NULL; + array->len = 0; + array->size = 0; + + if(reserved_size > 0) { + g_ptr_array_grow(array, reserved_size); + } + + return (GPtrArray *)array; +} + +gpointer * +g_ptr_array_free(GPtrArray *array, gboolean free_seg) +{ + gpointer *data = NULL; + + g_return_val_if_fail(array != NULL, NULL); + + if(free_seg) { + g_free(array->pdata); + } else { + data = array->pdata; + } + + g_free(array); + + return data; +} + +void +g_ptr_array_add(GPtrArray *array, gpointer data) +{ + g_return_if_fail(array != NULL); + g_ptr_array_grow((GPtrArrayPriv *)array, 1); + array->pdata[array->len++] = data; +} + +void +g_ptr_array_foreach(GPtrArray *array, GFunc func, gpointer user_data) +{ + gint i; + + for(i = 0; i < array->len; i++) { + func(g_ptr_array_index(array, i), user_data); + } +} + diff --git a/eglib/test/Makefile.am b/eglib/test/Makefile.am index 0820e9392ec..36df80a4007 100644 --- a/eglib/test/Makefile.am +++ b/eglib/test/Makefile.am @@ -8,7 +8,8 @@ test_SOURCES = \ hashtable.c \ string-util.c \ string.c \ - slist.c + slist.c \ + ptrarray.c test_CFLAGS = -Wall -Werror -D_FORTIFY_SOURCE=2 INCLUDES = -I../src diff --git a/eglib/test/driver.c b/eglib/test/driver.c index 99b6dd178a9..d3fc878fed8 100644 --- a/eglib/test/driver.c +++ b/eglib/test/driver.c @@ -9,6 +9,7 @@ int main() "string", strutil_tests_init, "hashtable", hashtable_tests_init, "slist", slist_tests_init, + "ptrarray", ptrarray_tests_init, "gstring", string_tests_init, NULL ); diff --git a/eglib/test/ptrarray.c b/eglib/test/ptrarray.c new file mode 100644 index 00000000000..420cd325317 --- /dev/null +++ b/eglib/test/ptrarray.c @@ -0,0 +1,128 @@ +#include +#include +#include "test.h" + +/* Redefine the private structure only to verify proper allocations */ +typedef struct _GPtrArrayPriv { + gpointer *pdata; + guint len; + guint size; +} GPtrArrayPriv; + +/* Don't add more than 32 items to this please */ +static const char *items [] = { + "Apples", "Oranges", "Plumbs", "Goats", "Snorps", "Grapes", + "Tickle", "Place", "Coffee", "Cookies", "Cake", "Cheese", + "Tseng", "Holiday", "Avenue", "Smashing", "Water", "Toilet", + NULL +}; + +static GPtrArray *ptrarray_alloc_and_fill(gint *item_count) +{ + GPtrArray *array = g_ptr_array_new(); + gint i; + + for(i = 0; items[i] != NULL; i++) { + g_ptr_array_add(array, (gpointer)items[i]); + } + + if(item_count != NULL) { + *item_count = i; + } + + return array; +} + +static gint guess_size(gint length) +{ + gint size = 1; + + while(size < length) { + size <<= 1; + } + + return size; +} + +char *ptrarray_alloc() +{ + GPtrArrayPriv *array; + gint i; + + array = (GPtrArrayPriv *)ptrarray_alloc_and_fill(&i); + + if(array->size != guess_size(array->len)) { + return g_strdup_printf("Size should be %d, but it is %d", + guess_size(array->len), array->size); + } + + if(array->len != i) { + return g_strdup_printf("Expected %d node(s) in the array", i); + } + + g_ptr_array_free((GPtrArray *)array, TRUE); + + return NULL; +} + +char *ptrarray_for_iterate() +{ + GPtrArray *array = ptrarray_alloc_and_fill(NULL); + gint i; + + for(i = 0; i < array->len; i++) { + char *item = (char *)g_ptr_array_index(array, i); + if(item != items[i]) { + return g_strdup_printf( + "Expected item at %d to be %s, but it was %s", + i, items[i], item); + } + } + + g_ptr_array_free(array, TRUE); + + return NULL; +} + +static gint foreach_iterate_index = 0; +static char *foreach_iterate_error = NULL; + +void foreach_callback(gpointer data, gpointer user_data) +{ + char *item = (char *)data; + const char *item_cmp = items[foreach_iterate_index++]; + + if(foreach_iterate_error != NULL) { + return; + } + + if(item != item_cmp) { + foreach_iterate_error = g_strdup_printf( + "Expected item at %d to be %s, but it was %s", + foreach_iterate_index - 1, item_cmp, item); + } +} + +char *ptrarray_foreach_iterate() +{ + GPtrArray *array = ptrarray_alloc_and_fill(NULL); + + foreach_iterate_index = 0; + foreach_iterate_error = NULL; + + g_ptr_array_foreach(array, foreach_callback, array); + + g_ptr_array_free(array, TRUE); + + return foreach_iterate_error; +} + +static Test ptrarray_tests [] = { + {"ptrarray_alloc", ptrarray_alloc}, + {"ptrarray_for_iterate", ptrarray_for_iterate}, + {"ptrarray_foreach_iterate", ptrarray_foreach_iterate}, + {NULL, NULL} +}; + +DEFINE_TEST_GROUP_INIT(ptrarray_tests_init, ptrarray_tests) + diff --git a/eglib/test/tests.h b/eglib/test/tests.h index 7d9f72c6a87..775a054525b 100644 --- a/eglib/test/tests.h +++ b/eglib/test/tests.h @@ -3,3 +3,5 @@ DEFINE_TEST_GROUP_INIT_H(string_tests_init); DEFINE_TEST_GROUP_INIT_H(strutil_tests_init); DEFINE_TEST_GROUP_INIT_H(slist_tests_init); DEFINE_TEST_GROUP_INIT_H(hashtable_tests_init); +DEFINE_TEST_GROUP_INIT_H(ptrarray_tests_init); +