diff options
-rw-r--r-- | ChangeLog | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-0 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-10 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-12 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-2 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-4 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-6 | 22 | ||||
-rw-r--r-- | ChangeLog.pre-2-8 | 22 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | garray.c | 177 | ||||
-rw-r--r-- | ghash.c | 8 | ||||
-rw-r--r-- | glib.h | 122 | ||||
-rw-r--r-- | glib/Makefile.am | 1 | ||||
-rw-r--r-- | glib/garray.c | 177 | ||||
-rw-r--r-- | glib/ghash.c | 8 | ||||
-rw-r--r-- | glib/glib.h | 122 | ||||
-rw-r--r-- | glib/grel.c | 428 | ||||
-rw-r--r-- | glib/gstring.c | 2 | ||||
-rw-r--r-- | glib/gutils.c | 21 | ||||
-rw-r--r-- | grel.c | 428 | ||||
-rw-r--r-- | gstring.c | 2 | ||||
-rw-r--r-- | gutils.c | 21 | ||||
-rw-r--r-- | testglib.c | 109 | ||||
-rw-r--r-- | tests/testglib.c | 109 |
24 files changed, 1904 insertions, 8 deletions
@@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 8100e464b..6286236f2 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,25 @@ +Fri Jun 12 00:39:28 1998 Josh MacDonald <jmacd@icw.EECS.Berkeley.EDU> + + * glib.h: add new hash and equal functions g_int_*. complement + g_direct_hash with g_direct_equal. + + * grel.c: new file, GRelations implement tuples of N-N mappings. + A comment in glib.h briefly describes the interface. + + * ghash.c: new function, g_hash_table_size + + * glib.h: new typedefs, gsize, gssize, gtime. + + * garray.c: new functions implementing a simplified GArray. This + GPtrArray is an array of gpointers and has functions to add and + remove elements, much like java.lang.Vector. + + * garray.c: new functions for the single-byte special case of + GArray. The functions g_byte_array* operate on arrays of bytes. + Internally, a GArray is used. + + * testglib.c: tests for g_ptr_array, g_byte_array, and g_relation... + 1998-06-11 Federico Mena Quintero <federico@nuclecu.unam.mx> * gdataset.c: #include <string.h> diff --git a/Makefile.am b/Makefile.am index 84f563524..d09d201b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -23,6 +23,7 @@ libglib_1_1_la_SOURCES = \ gslist.c \ gtimer.c \ gtree.c \ + grel.c \ gstring.c \ gscanner.c \ gutils.c @@ -141,3 +141,180 @@ g_array_maybe_expand (GRealArray *array, memset (array->data + old_alloc, 0, array->alloc - old_alloc); } } + +/* Pointer Array + */ + +typedef struct _GRealPtrArray GRealPtrArray; + +struct _GRealPtrArray +{ + gpointer *pdata; + guint len; + guint alloc; +}; + +static void g_ptr_array_maybe_expand (GRealPtrArray *array, + gint len); + + +static GMemChunk *ptr_array_mem_chunk = NULL; + + + +GPtrArray* +g_ptr_array_new () +{ + GRealPtrArray *array; + + if (!ptr_array_mem_chunk) + ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk", + sizeof (GRealPtrArray), + 1024, G_ALLOC_AND_FREE); + + array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk); + + array->pdata = NULL; + array->len = 0; + array->alloc = 0; + + return (GPtrArray*) array; +} + +void +g_ptr_array_free (GPtrArray *array, + gboolean free_segment) +{ + g_return_if_fail (array); + + if (free_segment) + g_free (array->pdata); + + g_mem_chunk_free (ptr_array_mem_chunk, array); +} + +static void +g_ptr_array_maybe_expand (GRealPtrArray *array, + gint len) +{ + guint old_alloc; + + if ((array->len + len) > array->alloc) + { + old_alloc = array->alloc; + + array->alloc = g_nearest_pow (array->len + len); + array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE); + if (array->pdata) + array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc); + else + array->pdata = g_new0 (gpointer, array->alloc); + + memset (array->pdata + old_alloc, 0, array->alloc - old_alloc); + } +} + +void +g_ptr_array_set_size (GPtrArray *farray, + gint length) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + if (length > array->len) + g_ptr_array_maybe_expand (array, (length - array->len)); + + array->len = length; +} + +void +g_ptr_array_remove_index (GPtrArray* farray, + gint index) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + g_return_if_fail (index >= array->len); + + array->pdata[index] = array->pdata[array->len - 1]; + + array->pdata[array->len - 1] = NULL; + + array->len -= 1; +} + +gboolean +g_ptr_array_remove (GPtrArray* farray, + gpointer data) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + int i; + + g_return_val_if_fail (array, FALSE); + + for (i = 0; i < array->len; i += 1) + { + if (array->pdata[i] == data) + { + g_ptr_array_remove_index (farray, i); + return TRUE; + } + } + + return FALSE; +} + +void +g_ptr_array_add (GPtrArray* farray, + gpointer data) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + g_ptr_array_maybe_expand (array, 1); + + array->pdata[array->len++] = data; +} + +/* Byte arrays + */ + +GByteArray* g_byte_array_new (void) +{ + return (GByteArray*) g_array_new (FALSE); +} + +void g_byte_array_free (GByteArray *array, + gint free_segment) +{ + g_array_free ((GArray*) array, free_segment); +} + +GByteArray* g_byte_array_append (GByteArray *array, + const guint8 *data, + guint len) +{ + g_rarray_append ((GArray*) array, (guint8*)data, len); + + return array; +} + +GByteArray* g_byte_array_prepend (GByteArray *array, + const guint8 *data, + guint len) +{ + g_rarray_prepend ((GArray*) array, (guint8*)data, len); + + return array; +} + +GByteArray* g_byte_array_truncate (GByteArray *array, + gint length) +{ + g_rarray_truncate ((GArray*) array, length, 1); + + return array; +} @@ -424,3 +424,11 @@ g_hash_nodes_destroy (GHashNode *hash_node) node_free_list = hash_node; } } + +/* Returns the number of elements contained in the hash table. */ +gint g_hash_table_size (GHashTable *hash_table) +{ + g_return_val_if_fail (hash_table, 0); + + return ((GRealHashTable *) hash_table)->nnodes; +} @@ -433,6 +433,10 @@ typedef unsigned long guint32; /* This should never happen */ #endif +typedef gint32 gssize; +typedef guint32 gsize; +typedef gint32 gtime; + typedef struct _GList GList; typedef struct _GSList GSList; @@ -445,10 +449,14 @@ typedef struct _GListAllocator GListAllocator; typedef struct _GStringChunk GStringChunk; typedef struct _GString GString; typedef struct _GArray GArray; +typedef struct _GPtrArray GPtrArray; +typedef struct _GByteArray GByteArray; typedef struct _GDebugKey GDebugKey; typedef struct _GScannerConfig GScannerConfig; typedef struct _GScanner GScanner; typedef union _GValue GValue; +typedef struct _GRelation GRelation; +typedef struct _GTuples GTuples; typedef void (*GFunc) (gpointer data, @@ -501,6 +509,23 @@ struct _GArray guint len; }; +struct _GByteArray +{ + guint8 *data; + guint len; +}; + +struct _GPtrArray +{ + gpointer *pdata; + guint len; +}; + +struct _GTuples +{ + guint len; +}; + struct _GDebugKey { gchar *key; @@ -635,6 +660,7 @@ void g_hash_table_thaw (GHashTable *hash_table); void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data); +gint g_hash_table_size (GHashTable *hash_table); /* Caches @@ -891,17 +917,63 @@ GArray* g_rarray_truncate (GArray *array, gint length, gint size); +/* Resizable pointer array. This interface is much less complicated + * than the above. Add appends appends a pointer. Remove fills any + * cleared spot and shortens the array. + */ + +#define g_ptr_array_index(array,index) (array->pdata)[index] + +GPtrArray* g_ptr_array_new (void); +void g_ptr_array_free (GPtrArray *array, + gboolean free_seg); +void g_ptr_array_set_size (GPtrArray *array, + gint length); +void g_ptr_array_remove_index (GPtrArray *array, + gint index); +gboolean g_ptr_array_remove (GPtrArray *array, + gpointer data); +void g_ptr_array_add (GPtrArray *array, + gpointer data); + +/* Byte arrays, an array of guint8. Implemented as a GArray, + * but type-safe. + */ + +GByteArray* g_byte_array_new (void); +void g_byte_array_free (GByteArray *array, + gint free_segment); + +GByteArray* g_byte_array_append (GByteArray *array, + const guint8 *data, + guint len); + +GByteArray* g_byte_array_prepend (GByteArray *array, + const guint8 *data, + guint len); + +GByteArray* g_byte_array_truncate (GByteArray *array, + gint length); + + /* Hash Functions */ gint g_str_equal (gconstpointer v, gconstpointer v2); guint g_str_hash (gconstpointer v); +gint g_int_equal (gconstpointer v, + gconstpointer v2); +guint g_int_hash (gconstpointer v); + /* This "hash" function will just return the key's adress as an * unsigned integer. Useful for hashing on plain adresses or * simple integer values. */ -guint g_direct_hash (gconstpointer key); +guint g_direct_hash (gconstpointer v); +gint g_direct_equal (gconstpointer v, + gconstpointer v2); + /* Location Associated Data @@ -1141,6 +1213,54 @@ GList* g_completion_complete (GCompletion* cmp, gchar** new_prefix); void g_completion_free (GCompletion* cmp); +/* GRelation: Indexed Relations. Imagine a really simple table in a + * database. Relations are not ordered. This data type is meant for + * maintaining a N-way mapping. + * + * g_relation_new() creates a relation with FIELDS fields + * + * g_relation_destroy() frees all resources + * g_tuples_destroy() frees the result of g_relation_select() + * + * g_relation_index() indexes relation FIELD with the provided + * equality and hash functions. this must be done before any + * calls to insert are made. + * + * g_relation_insert() inserts a new tuple. you are expected to + * provide the right number of fields. + * + * g_relation_delete() deletes all relations with KEY in FIELD + * g_relation_select() returns ... + * g_relation_count() counts ... + */ + +GRelation* g_relation_new (gint fields); +void g_relation_destroy (GRelation *relation); +void g_relation_index (GRelation *relation, + gint field, + GHashFunc hash_func, + GCompareFunc key_compare_func); +void g_relation_insert (GRelation *relation, + ...); +gint g_relation_delete (GRelation *relation, + gconstpointer key, + gint field); +GTuples* g_relation_select (GRelation *relation, + gconstpointer key, + gint field); +gint g_relation_count (GRelation *relation, + gconstpointer key, + gint field); +gboolean g_relation_exists (GRelation *relation, + ...); +void g_relation_print (GRelation *relation); + +void g_tuples_destroy (GTuples *tuples); +gpointer g_tuples_index (GTuples *tuples, + gint index, + gint field); + + /* Glib version. */ extern const guint glib_major_version; diff --git a/glib/Makefile.am b/glib/Makefile.am index 84f563524..d09d201b7 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -23,6 +23,7 @@ libglib_1_1_la_SOURCES = \ gslist.c \ gtimer.c \ gtree.c \ + grel.c \ gstring.c \ gscanner.c \ gutils.c diff --git a/glib/garray.c b/glib/garray.c index 4d814a44a..16c1063a8 100644 --- a/glib/garray.c +++ b/glib/garray.c @@ -141,3 +141,180 @@ g_array_maybe_expand (GRealArray *array, memset (array->data + old_alloc, 0, array->alloc - old_alloc); } } + +/* Pointer Array + */ + +typedef struct _GRealPtrArray GRealPtrArray; + +struct _GRealPtrArray +{ + gpointer *pdata; + guint len; + guint alloc; +}; + +static void g_ptr_array_maybe_expand (GRealPtrArray *array, + gint len); + + +static GMemChunk *ptr_array_mem_chunk = NULL; + + + +GPtrArray* +g_ptr_array_new () +{ + GRealPtrArray *array; + + if (!ptr_array_mem_chunk) + ptr_array_mem_chunk = g_mem_chunk_new ("array mem chunk", + sizeof (GRealPtrArray), + 1024, G_ALLOC_AND_FREE); + + array = g_chunk_new (GRealPtrArray, ptr_array_mem_chunk); + + array->pdata = NULL; + array->len = 0; + array->alloc = 0; + + return (GPtrArray*) array; +} + +void +g_ptr_array_free (GPtrArray *array, + gboolean free_segment) +{ + g_return_if_fail (array); + + if (free_segment) + g_free (array->pdata); + + g_mem_chunk_free (ptr_array_mem_chunk, array); +} + +static void +g_ptr_array_maybe_expand (GRealPtrArray *array, + gint len) +{ + guint old_alloc; + + if ((array->len + len) > array->alloc) + { + old_alloc = array->alloc; + + array->alloc = g_nearest_pow (array->len + len); + array->alloc = MAX (array->alloc, MIN_ARRAY_SIZE); + if (array->pdata) + array->pdata = g_realloc (array->pdata, sizeof(gpointer) * array->alloc); + else + array->pdata = g_new0 (gpointer, array->alloc); + + memset (array->pdata + old_alloc, 0, array->alloc - old_alloc); + } +} + +void +g_ptr_array_set_size (GPtrArray *farray, + gint length) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + if (length > array->len) + g_ptr_array_maybe_expand (array, (length - array->len)); + + array->len = length; +} + +void +g_ptr_array_remove_index (GPtrArray* farray, + gint index) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + g_return_if_fail (index >= array->len); + + array->pdata[index] = array->pdata[array->len - 1]; + + array->pdata[array->len - 1] = NULL; + + array->len -= 1; +} + +gboolean +g_ptr_array_remove (GPtrArray* farray, + gpointer data) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + int i; + + g_return_val_if_fail (array, FALSE); + + for (i = 0; i < array->len; i += 1) + { + if (array->pdata[i] == data) + { + g_ptr_array_remove_index (farray, i); + return TRUE; + } + } + + return FALSE; +} + +void +g_ptr_array_add (GPtrArray* farray, + gpointer data) +{ + GRealPtrArray* array = (GRealPtrArray*) farray; + + g_return_if_fail (array); + + g_ptr_array_maybe_expand (array, 1); + + array->pdata[array->len++] = data; +} + +/* Byte arrays + */ + +GByteArray* g_byte_array_new (void) +{ + return (GByteArray*) g_array_new (FALSE); +} + +void g_byte_array_free (GByteArray *array, + gint free_segment) +{ + g_array_free ((GArray*) array, free_segment); +} + +GByteArray* g_byte_array_append (GByteArray *array, + const guint8 *data, + guint len) +{ + g_rarray_append ((GArray*) array, (guint8*)data, len); + + return array; +} + +GByteArray* g_byte_array_prepend (GByteArray *array, + const guint8 *data, + guint len) +{ + g_rarray_prepend ((GArray*) array, (guint8*)data, len); + + return array; +} + +GByteArray* g_byte_array_truncate (GByteArray *array, + gint length) +{ + g_rarray_truncate ((GArray*) array, length, 1); + + return array; +} diff --git a/glib/ghash.c b/glib/ghash.c index ceee09843..ee364c9c2 100644 --- a/glib/ghash.c +++ b/glib/ghash.c @@ -424,3 +424,11 @@ g_hash_nodes_destroy (GHashNode *hash_node) node_free_list = hash_node; } } + +/* Returns the number of elements contained in the hash table. */ +gint g_hash_table_size (GHashTable *hash_table) +{ + g_return_val_if_fail (hash_table, 0); + + return ((GRealHashTable *) hash_table)->nnodes; +} diff --git a/glib/glib.h b/glib/glib.h index 37d49e970..c3733d440 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -433,6 +433,10 @@ typedef unsigned long guint32; /* This should never happen */ #endif +typedef gint32 gssize; +typedef guint32 gsize; +typedef gint32 gtime; + typedef struct _GList GList; typedef struct _GSList GSList; @@ -445,10 +449,14 @@ typedef struct _GListAllocator GListAllocator; typedef struct _GStringChunk GStringChunk; typedef struct _GString GString; typedef struct _GArray GArray; +typedef struct _GPtrArray GPtrArray; +typedef struct _GByteArray GByteArray; typedef struct _GDebugKey GDebugKey; typedef struct _GScannerConfig GScannerConfig; typedef struct _GScanner GScanner; typedef union _GValue GValue; +typedef struct _GRelation GRelation; +typedef struct _GTuples GTuples; typedef void (*GFunc) (gpointer data, @@ -501,6 +509,23 @@ struct _GArray guint len; }; +struct _GByteArray +{ + guint8 *data; + guint len; +}; + +struct _GPtrArray +{ + gpointer *pdata; + guint len; +}; + +struct _GTuples +{ + guint len; +}; + struct _GDebugKey { gchar *key; @@ -635,6 +660,7 @@ void g_hash_table_thaw (GHashTable *hash_table); void g_hash_table_foreach (GHashTable *hash_table, GHFunc func, gpointer user_data); +gint g_hash_table_size (GHashTable *hash_table); /* Caches @@ -891,17 +917,63 @@ GArray* g_rarray_truncate (GArray *array, gint length, gint size); +/* Resizable pointer array. This interface is much less complicated + * than the above. Add appends appends a pointer. Remove fills any + * cleared spot and shortens the array. + */ + +#define g_ptr_array_index(array,index) (array->pdata)[index] + +GPtrArray* g_ptr_array_new (void); +void g_ptr_array_free (GPtrArray *array, + gboolean free_seg); +void g_ptr_array_set_size (GPtrArray *array, + gint length); +void g_ptr_array_remove_index (GPtrArray *array, + gint index); +gboolean g_ptr_array_remove (GPtrArray *array, + gpointer data); +void g_ptr_array_add (GPtrArray *array, + gpointer data); + +/* Byte arrays, an array of guint8. Implemented as a GArray, + * but type-safe. + */ + +GByteArray* g_byte_array_new (void); +void g_byte_array_free (GByteArray *array, + gint free_segment); + +GByteArray* g_byte_array_append (GByteArray *array, + const guint8 *data, + guint len); + +GByteArray* g_byte_array_prepend (GByteArray *array, + const guint8 *data, + guint len); + +GByteArray* g_byte_array_truncate (GByteArray *array, + gint length); + + /* Hash Functions */ gint g_str_equal (gconstpointer v, gconstpointer v2); guint g_str_hash (gconstpointer v); +gint g_int_equal (gconstpointer v, + gconstpointer v2); +guint g_int_hash (gconstpointer v); + /* This "hash" function will just return the key's adress as an * unsigned integer. Useful for hashing on plain adresses or * simple integer values. */ -guint g_direct_hash (gconstpointer key); +guint g_direct_hash (gconstpointer v); +gint g_direct_equal (gconstpointer v, + gconstpointer v2); + /* Location Associated Data @@ -1141,6 +1213,54 @@ GList* g_completion_complete (GCompletion* cmp, gchar** new_prefix); void g_completion_free (GCompletion* cmp); +/* GRelation: Indexed Relations. Imagine a really simple table in a + * database. Relations are not ordered. This data type is meant for + * maintaining a N-way mapping. + * + * g_relation_new() creates a relation with FIELDS fields + * + * g_relation_destroy() frees all resources + * g_tuples_destroy() frees the result of g_relation_select() + * + * g_relation_index() indexes relation FIELD with the provided + * equality and hash functions. this must be done before any + * calls to insert are made. + * + * g_relation_insert() inserts a new tuple. you are expected to + * provide the right number of fields. + * + * g_relation_delete() deletes all relations with KEY in FIELD + * g_relation_select() returns ... + * g_relation_count() counts ... + */ + +GRelation* g_relation_new (gint fields); +void g_relation_destroy (GRelation *relation); +void g_relation_index (GRelation *relation, + gint field, + GHashFunc hash_func, + GCompareFunc key_compare_func); +void g_relation_insert (GRelation *relation, + ...); +gint g_relation_delete (GRelation *relation, + gconstpointer key, + gint field); +GTuples* g_relation_select (GRelation *relation, + gconstpointer key, + gint field); +gint g_relation_count (GRelation *relation, + gconstpointer key, + gint field); +gboolean g_relation_exists (GRelation *relation, + ...); +void g_relation_print (GRelation *relation); + +void g_tuples_destroy (GTuples *tuples); +gpointer g_tuples_index (GTuples *tuples, + gint index, + gint field); + + /* Glib version. */ extern const guint glib_major_version; diff --git a/glib/grel.c b/glib/grel.c new file mode 100644 index 000000000..91d2b68e2 --- /dev/null +++ b/glib/grel.c @@ -0,0 +1,428 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "glib.h" +#include <stdarg.h> + +typedef struct _GRealRelation GRealRelation; +typedef struct _GRealTuples GRealTuples; + +struct _GRealRelation +{ + gint fields; + gint current_field; + + GHashTable *all_tuples; + GHashTable **hashed_tuple_tables; + GMemChunk *tuple_chunk; + + gint count; +}; + +struct _GRealTuples +{ + gint len; + gint width; + gpointer *data; +}; + +gboolean +tuple_equal_2 (gconstpointer v_a, gconstpointer v_b) +{ + gpointer* a = (gpointer*) v_a; + gpointer* b = (gpointer*) v_b; + + return a[0] == b[0] && a[1] == b[1]; +} + +guint +tuple_hash_2 (gconstpointer v_a) +{ + gpointer* a = (gpointer*) v_a; + + return (gulong)a[0] ^ (gulong)a[1]; +} + +GHashFunc +tuple_hash (gint fields) +{ + switch (fields) + { + case 2: + return tuple_hash_2; + default: + g_error ("no tuple hash for %d", fields); + } + + return NULL; +} + +GCompareFunc +tuple_equal (gint fields) +{ + switch (fields) + { + case 2: + return tuple_equal_2; + default: + g_error ("no tuple equal for %d", fields); + } + + return NULL; +} + +GRelation* +g_relation_new (gint fields) +{ + GRealRelation* rel = g_new0 (GRealRelation, 1); + + rel->fields = fields; + rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk", + fields * sizeof (gpointer), + fields * sizeof (gpointer) * 128, + G_ALLOC_AND_FREE); + rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields)); + rel->hashed_tuple_tables = g_new0 (GHashTable*, fields); + + return (GRelation*) rel; +} + +static void +g_relation_free_array (gpointer key, gpointer value, gpointer user_data) +{ + g_hash_table_destroy ((GHashTable*) value); +} + +void +g_relation_destroy (GRelation *relation) +{ + GRealRelation *rel = (GRealRelation *) relation; + gint i; + + if (rel) + { + g_hash_table_destroy (rel->all_tuples); + g_mem_chunk_destroy (rel->tuple_chunk); + + for (i = 0; i < rel->fields; i += 1) + { + if (rel->hashed_tuple_tables[i]) + { + g_hash_table_foreach (rel->hashed_tuple_tables[i], g_relation_free_array, NULL); + g_hash_table_destroy (rel->hashed_tuple_tables[i]); + } + } + + g_free (rel->hashed_tuple_tables); + g_free (rel); + } +} + +void +g_relation_index (GRelation *relation, + gint field, + GHashFunc hash_func, + GCompareFunc key_compare_func) +{ + GRealRelation *rel = (GRealRelation *) relation; + + g_assert (rel->count == 0 && rel->hashed_tuple_tables[field] == NULL); + + rel->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_compare_func); +} + +void +g_relation_insert (GRelation *relation, + ...) +{ + GRealRelation *rel = (GRealRelation *) relation; + gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk); + va_list args; + gint i; + + va_start(args, relation); + + for (i = 0; i < rel->fields; i += 1) + tuple[i] = va_arg(args, gpointer); + + va_end(args); + + g_hash_table_insert (rel->all_tuples, tuple, tuple); + + rel->count += 1; + + for (i = 0; i < rel->fields; i += 1) + { + GHashTable *table; + gpointer key; + GHashTable *per_key_table; + + table = rel->hashed_tuple_tables[i]; + + if (table == NULL) + continue; + + key = tuple[i]; + per_key_table = g_hash_table_lookup (table, key); + + if (per_key_table == NULL) + { + per_key_table = g_hash_table_new (tuple_hash (rel->fields), tuple_equal (rel->fields)); + g_hash_table_insert (table, key, per_key_table); + } + + g_hash_table_insert (per_key_table, tuple, tuple); + } +} + +static void +g_relation_delete_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gpointer *tuple = (gpointer*) tuple_value; + GRealRelation *rel = (GRealRelation *) user_data; + gint j; + + g_assert (tuple_key == tuple_value); + + for (j = 0; j < rel->fields; j += 1) + { + GHashTable *one_table = rel->hashed_tuple_tables[j]; + gpointer one_key; + GHashTable *per_key_table; + + if (one_table == NULL) + continue; + + if (j == rel->current_field) + /* can't delete from the table we're foreaching in */ + continue; + + one_key = tuple[j]; + + per_key_table = g_hash_table_lookup (one_table, one_key); + + g_hash_table_remove (per_key_table, tuple); + } + + g_hash_table_remove (rel->all_tuples, tuple); + + rel->count -= 1; +} + +gint +g_relation_delete (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + gint count = rel->count; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return 0; + + rel->current_field = field; + + g_hash_table_foreach (key_table, g_relation_delete_tuple, rel); + + g_hash_table_remove (table, key); + + g_hash_table_destroy (key_table); + + /* @@@ Remove empty hash tables. */ + + return count - rel->count; +} + +static void +g_relation_select_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gpointer *tuple = (gpointer*) tuple_value; + GRealTuples *tuples = (GRealTuples*) user_data; + gint stride = sizeof (gpointer) * tuples->width; + + g_assert (tuple_key == tuple_value); + + memcpy (tuples->data + (tuples->len * tuples->width), + tuple, + stride); + + tuples->len += 1; +} + +GTuples* +g_relation_select (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + GRealTuples *tuples = g_new0 (GRealTuples, 1); + gint count; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return (GTuples*)tuples; + + count = g_relation_count (relation, key, field); + + tuples->data = g_malloc (sizeof (gpointer) * rel->fields * count); + tuples->width = rel->fields; + + g_hash_table_foreach (key_table, g_relation_select_tuple, tuples); + + g_assert (count == tuples->len); + + return (GTuples*)tuples; +} + +gint +g_relation_count (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return 0; + + return g_hash_table_size (key_table); +} + +gboolean +g_relation_exists (GRelation *relation, ...) +{ + GRealRelation *rel = (GRealRelation *) relation; + gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk); + va_list args; + gint i; + gboolean result; + + va_start(args, relation); + + for (i = 0; i < rel->fields; i += 1) + tuple[i] = va_arg(args, gpointer); + + va_end(args); + + result = g_hash_table_lookup (rel->all_tuples, tuple) != NULL; + + g_mem_chunk_free (rel->tuple_chunk, tuple); + + return result; +} + +void +g_tuples_destroy (GTuples *tuples0) +{ + GRealTuples *tuples = (GRealTuples*) tuples0; + + if (tuples) + { + g_free (tuples->data); + g_free (tuples); + } +} + +gpointer +g_tuples_index (GTuples *tuples0, + gint index, + gint field) +{ + GRealTuples *tuples = (GRealTuples*) tuples0; + + g_assert (field < tuples->width); + + return tuples->data[index * tuples->width + field]; +} + +/* Print + */ + +void +g_relation_print_one (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gint i; + GRealRelation* rel = (GRealRelation*) user_data; + gpointer* tuples = (gpointer*) tuple_value; + + g_print ("["); + + for (i = 0; i < rel->fields; i += 1) + { + g_print ("%p", tuples[i]); + + if (i < (rel->fields - 1)) + g_print (","); + } + + g_print ("]\n"); +} + +void +g_relation_print_index (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + GRealRelation* rel = (GRealRelation*) user_data; + GHashTable* table = (GHashTable*) tuple_value; + + g_print ("*** key %p\n", tuple_key); + + g_hash_table_foreach (table, + g_relation_print_one, + rel); +} + +void +g_relation_print (GRelation *relation) +{ + gint i; + GRealRelation* rel = (GRealRelation*) relation; + + g_print ("*** all tuples (%d)\n", rel->count); + + g_hash_table_foreach (rel->all_tuples, + g_relation_print_one, + rel); + + for (i = 0; i < rel->fields; i += 1) + { + if (rel->hashed_tuple_tables[i] == NULL) + continue; + + g_print ("*** index %d\n", i); + + g_hash_table_foreach (rel->hashed_tuple_tables[i], + g_relation_print_index, + rel); + } + +} diff --git a/glib/gstring.c b/glib/gstring.c index 8350552d2..173a0b8c1 100644 --- a/glib/gstring.c +++ b/glib/gstring.c @@ -16,12 +16,12 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ -#include <glib.h> #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> +#include "glib.h" typedef struct _GRealStringChunk GRealStringChunk; diff --git a/glib/gutils.c b/glib/gutils.c index 8528163f4..c33efc4bd 100644 --- a/glib/gutils.c +++ b/glib/gutils.c @@ -851,8 +851,25 @@ g_parse_debug_string (const gchar *string, } guint -g_direct_hash(gconstpointer key) +g_direct_hash(gconstpointer v) { - return GPOINTER_TO_UINT (key); + return GPOINTER_TO_UINT (v); } +gint +g_direct_equal(gconstpointer v, gconstpointer v2) +{ + return GPOINTER_TO_UINT (v) == GPOINTER_TO_UINT (v2); +} + +gint +g_int_equal (gconstpointer v, gconstpointer v2) +{ + return *((const gint*) v) == *((const gint*) v2); +} + +guint +g_int_hash (gconstpointer v) +{ + return *(const gint*) v; +} @@ -0,0 +1,428 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#include "glib.h" +#include <stdarg.h> + +typedef struct _GRealRelation GRealRelation; +typedef struct _GRealTuples GRealTuples; + +struct _GRealRelation +{ + gint fields; + gint current_field; + + GHashTable *all_tuples; + GHashTable **hashed_tuple_tables; + GMemChunk *tuple_chunk; + + gint count; +}; + +struct _GRealTuples +{ + gint len; + gint width; + gpointer *data; +}; + +gboolean +tuple_equal_2 (gconstpointer v_a, gconstpointer v_b) +{ + gpointer* a = (gpointer*) v_a; + gpointer* b = (gpointer*) v_b; + + return a[0] == b[0] && a[1] == b[1]; +} + +guint +tuple_hash_2 (gconstpointer v_a) +{ + gpointer* a = (gpointer*) v_a; + + return (gulong)a[0] ^ (gulong)a[1]; +} + +GHashFunc +tuple_hash (gint fields) +{ + switch (fields) + { + case 2: + return tuple_hash_2; + default: + g_error ("no tuple hash for %d", fields); + } + + return NULL; +} + +GCompareFunc +tuple_equal (gint fields) +{ + switch (fields) + { + case 2: + return tuple_equal_2; + default: + g_error ("no tuple equal for %d", fields); + } + + return NULL; +} + +GRelation* +g_relation_new (gint fields) +{ + GRealRelation* rel = g_new0 (GRealRelation, 1); + + rel->fields = fields; + rel->tuple_chunk = g_mem_chunk_new ("Relation Chunk", + fields * sizeof (gpointer), + fields * sizeof (gpointer) * 128, + G_ALLOC_AND_FREE); + rel->all_tuples = g_hash_table_new (tuple_hash (fields), tuple_equal (fields)); + rel->hashed_tuple_tables = g_new0 (GHashTable*, fields); + + return (GRelation*) rel; +} + +static void +g_relation_free_array (gpointer key, gpointer value, gpointer user_data) +{ + g_hash_table_destroy ((GHashTable*) value); +} + +void +g_relation_destroy (GRelation *relation) +{ + GRealRelation *rel = (GRealRelation *) relation; + gint i; + + if (rel) + { + g_hash_table_destroy (rel->all_tuples); + g_mem_chunk_destroy (rel->tuple_chunk); + + for (i = 0; i < rel->fields; i += 1) + { + if (rel->hashed_tuple_tables[i]) + { + g_hash_table_foreach (rel->hashed_tuple_tables[i], g_relation_free_array, NULL); + g_hash_table_destroy (rel->hashed_tuple_tables[i]); + } + } + + g_free (rel->hashed_tuple_tables); + g_free (rel); + } +} + +void +g_relation_index (GRelation *relation, + gint field, + GHashFunc hash_func, + GCompareFunc key_compare_func) +{ + GRealRelation *rel = (GRealRelation *) relation; + + g_assert (rel->count == 0 && rel->hashed_tuple_tables[field] == NULL); + + rel->hashed_tuple_tables[field] = g_hash_table_new (hash_func, key_compare_func); +} + +void +g_relation_insert (GRelation *relation, + ...) +{ + GRealRelation *rel = (GRealRelation *) relation; + gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk); + va_list args; + gint i; + + va_start(args, relation); + + for (i = 0; i < rel->fields; i += 1) + tuple[i] = va_arg(args, gpointer); + + va_end(args); + + g_hash_table_insert (rel->all_tuples, tuple, tuple); + + rel->count += 1; + + for (i = 0; i < rel->fields; i += 1) + { + GHashTable *table; + gpointer key; + GHashTable *per_key_table; + + table = rel->hashed_tuple_tables[i]; + + if (table == NULL) + continue; + + key = tuple[i]; + per_key_table = g_hash_table_lookup (table, key); + + if (per_key_table == NULL) + { + per_key_table = g_hash_table_new (tuple_hash (rel->fields), tuple_equal (rel->fields)); + g_hash_table_insert (table, key, per_key_table); + } + + g_hash_table_insert (per_key_table, tuple, tuple); + } +} + +static void +g_relation_delete_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gpointer *tuple = (gpointer*) tuple_value; + GRealRelation *rel = (GRealRelation *) user_data; + gint j; + + g_assert (tuple_key == tuple_value); + + for (j = 0; j < rel->fields; j += 1) + { + GHashTable *one_table = rel->hashed_tuple_tables[j]; + gpointer one_key; + GHashTable *per_key_table; + + if (one_table == NULL) + continue; + + if (j == rel->current_field) + /* can't delete from the table we're foreaching in */ + continue; + + one_key = tuple[j]; + + per_key_table = g_hash_table_lookup (one_table, one_key); + + g_hash_table_remove (per_key_table, tuple); + } + + g_hash_table_remove (rel->all_tuples, tuple); + + rel->count -= 1; +} + +gint +g_relation_delete (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + gint count = rel->count; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return 0; + + rel->current_field = field; + + g_hash_table_foreach (key_table, g_relation_delete_tuple, rel); + + g_hash_table_remove (table, key); + + g_hash_table_destroy (key_table); + + /* @@@ Remove empty hash tables. */ + + return count - rel->count; +} + +static void +g_relation_select_tuple (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gpointer *tuple = (gpointer*) tuple_value; + GRealTuples *tuples = (GRealTuples*) user_data; + gint stride = sizeof (gpointer) * tuples->width; + + g_assert (tuple_key == tuple_value); + + memcpy (tuples->data + (tuples->len * tuples->width), + tuple, + stride); + + tuples->len += 1; +} + +GTuples* +g_relation_select (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + GRealTuples *tuples = g_new0 (GRealTuples, 1); + gint count; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return (GTuples*)tuples; + + count = g_relation_count (relation, key, field); + + tuples->data = g_malloc (sizeof (gpointer) * rel->fields * count); + tuples->width = rel->fields; + + g_hash_table_foreach (key_table, g_relation_select_tuple, tuples); + + g_assert (count == tuples->len); + + return (GTuples*)tuples; +} + +gint +g_relation_count (GRelation *relation, + gconstpointer key, + gint field) +{ + GRealRelation *rel = (GRealRelation *) relation; + GHashTable *table = rel->hashed_tuple_tables[field]; + GHashTable *key_table; + + g_assert (table); + + key_table = g_hash_table_lookup (table, key); + + if (!key_table) + return 0; + + return g_hash_table_size (key_table); +} + +gboolean +g_relation_exists (GRelation *relation, ...) +{ + GRealRelation *rel = (GRealRelation *) relation; + gpointer* tuple = g_chunk_new (gpointer, rel->tuple_chunk); + va_list args; + gint i; + gboolean result; + + va_start(args, relation); + + for (i = 0; i < rel->fields; i += 1) + tuple[i] = va_arg(args, gpointer); + + va_end(args); + + result = g_hash_table_lookup (rel->all_tuples, tuple) != NULL; + + g_mem_chunk_free (rel->tuple_chunk, tuple); + + return result; +} + +void +g_tuples_destroy (GTuples *tuples0) +{ + GRealTuples *tuples = (GRealTuples*) tuples0; + + if (tuples) + { + g_free (tuples->data); + g_free (tuples); + } +} + +gpointer +g_tuples_index (GTuples *tuples0, + gint index, + gint field) +{ + GRealTuples *tuples = (GRealTuples*) tuples0; + + g_assert (field < tuples->width); + + return tuples->data[index * tuples->width + field]; +} + +/* Print + */ + +void +g_relation_print_one (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + gint i; + GRealRelation* rel = (GRealRelation*) user_data; + gpointer* tuples = (gpointer*) tuple_value; + + g_print ("["); + + for (i = 0; i < rel->fields; i += 1) + { + g_print ("%p", tuples[i]); + + if (i < (rel->fields - 1)) + g_print (","); + } + + g_print ("]\n"); +} + +void +g_relation_print_index (gpointer tuple_key, gpointer tuple_value, gpointer user_data) +{ + GRealRelation* rel = (GRealRelation*) user_data; + GHashTable* table = (GHashTable*) tuple_value; + + g_print ("*** key %p\n", tuple_key); + + g_hash_table_foreach (table, + g_relation_print_one, + rel); +} + +void +g_relation_print (GRelation *relation) +{ + gint i; + GRealRelation* rel = (GRealRelation*) relation; + + g_print ("*** all tuples (%d)\n", rel->count); + + g_hash_table_foreach (rel->all_tuples, + g_relation_print_one, + rel); + + for (i = 0; i < rel->fields; i += 1) + { + if (rel->hashed_tuple_tables[i] == NULL) + continue; + + g_print ("*** index %d\n", i); + + g_hash_table_foreach (rel->hashed_tuple_tables[i], + g_relation_print_index, + rel); + } + +} @@ -16,12 +16,12 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ -#include <glib.h> #include <stdarg.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <ctype.h> +#include "glib.h" typedef struct _GRealStringChunk GRealStringChunk; @@ -851,8 +851,25 @@ g_parse_debug_string (const gchar *string, } guint -g_direct_hash(gconstpointer key) +g_direct_hash(gconstpointer v) { - return GPOINTER_TO_UINT (key); + return GPOINTER_TO_UINT (v); } +gint +g_direct_equal(gconstpointer v, gconstpointer v2) +{ + return GPOINTER_TO_UINT (v) == GPOINTER_TO_UINT (v2); +} + +gint +g_int_equal (gconstpointer v, gconstpointer v2) +{ + return *((const gint*) v) == *((const gint*) v2); +} + +guint +g_int_hash (gconstpointer v) +{ + return *(const gint*) v; +} diff --git a/testglib.c b/testglib.c index e96dfb570..45d58dc99 100644 --- a/testglib.c +++ b/testglib.c @@ -104,9 +104,14 @@ main (int argc, gchar *mem[10000], *tmp_string, *tmp_string_2; gint i, j; GArray *garray; + GPtrArray *gparray; + GByteArray *gbarray; GString *string1, *string2; GTree *tree; char chars[62]; + GRelation *relation; + GTuples *tuples; + gint data [1024]; g_print ("checking size of gint8...%ld (should be 1)\n", (glong)sizeof (gint8)); g_print ("checking size of gint16...%ld (should be 2)\n", (glong)sizeof (gint16)); @@ -396,6 +401,110 @@ main (int argc, /* g_debug (argv[0]); */ + /* Relation tests */ + + g_print ("checking relations..."); + + relation = g_relation_new (2); + + g_relation_index (relation, 0, g_int_hash, g_int_equal); + g_relation_index (relation, 1, g_int_hash, g_int_equal); + + for (i = 0; i < 1024; i += 1) + data[i] = i; + + for (i = 1; i < 1023; i += 1) + { + g_relation_insert (relation, data + i, data + i + 1); + g_relation_insert (relation, data + i, data + i - 1); + } + + for (i = 2; i < 1022; i += 1) + { + g_assert (! g_relation_exists (relation, data + i, data + i)); + g_assert (! g_relation_exists (relation, data + i, data + i + 2)); + g_assert (! g_relation_exists (relation, data + i, data + i - 2)); + } + + for (i = 1; i < 1023; i += 1) + { + g_assert (g_relation_exists (relation, data + i, data + i + 1)); + g_assert (g_relation_exists (relation, data + i, data + i - 1)); + } + + for (i = 2; i < 1022; i += 1) + { + g_assert (g_relation_count (relation, data + i, 0) == 2); + g_assert (g_relation_count (relation, data + i, 1) == 2); + } + + g_assert (g_relation_count (relation, data, 0) == 0); + + g_assert (g_relation_count (relation, data + 42, 0) == 2); + g_assert (g_relation_count (relation, data + 43, 1) == 2); + g_assert (g_relation_count (relation, data + 41, 1) == 2); + g_relation_delete (relation, data + 42, 0); + g_assert (g_relation_count (relation, data + 42, 0) == 0); + g_assert (g_relation_count (relation, data + 43, 1) == 1); + g_assert (g_relation_count (relation, data + 41, 1) == 1); + + tuples = g_relation_select (relation, data + 200, 0); + + g_assert (tuples->len == 2); + +#if 0 + for (i = 0; i < tuples->len; i += 1) + { + printf ("%d %d\n", + *(gint*) g_tuples_index (tuples, i, 0), + *(gint*) g_tuples_index (tuples, i, 1)); + } +#endif + + g_assert (g_relation_exists (relation, data + 300, data + 301)); + g_relation_delete (relation, data + 300, 0); + g_assert (!g_relation_exists (relation, data + 300, data + 301)); + + g_tuples_destroy (tuples); + + g_relation_destroy (relation); + + relation = NULL; + + g_print ("ok\n"); + + g_print ("checking pointer arrays..."); + + gparray = g_ptr_array_new (); + for (i = 0; i < 10000; i++) + g_ptr_array_add (gparray, (void*)i); + + for (i = 0; i < 10000; i++) + if (g_ptr_array_index (gparray, i) != (void*)i) + g_print ("array fails: %p ( %p )\n", g_ptr_array_index (gparray, i), (void*)i); + + g_ptr_array_free (gparray, TRUE); + + g_print ("ok\n"); + + + g_print ("checking byte arrays..."); + + gbarray = g_byte_array_new (); + for (i = 0; i < 10000; i++) + g_byte_array_append (gbarray, "abcd", 4); + + for (i = 0; i < 10000; i++) + { + g_assert (gbarray->data[4*i] == 'a'); + g_assert (gbarray->data[4*i+1] == 'b'); + g_assert (gbarray->data[4*i+2] == 'c'); + g_assert (gbarray->data[4*i+3] == 'd'); + } + + g_byte_array_free (gbarray, TRUE); + + g_print ("ok\n"); return 0; } diff --git a/tests/testglib.c b/tests/testglib.c index e96dfb570..45d58dc99 100644 --- a/tests/testglib.c +++ b/tests/testglib.c @@ -104,9 +104,14 @@ main (int argc, gchar *mem[10000], *tmp_string, *tmp_string_2; gint i, j; GArray *garray; + GPtrArray *gparray; + GByteArray *gbarray; GString *string1, *string2; GTree *tree; char chars[62]; + GRelation *relation; + GTuples *tuples; + gint data [1024]; g_print ("checking size of gint8...%ld (should be 1)\n", (glong)sizeof (gint8)); g_print ("checking size of gint16...%ld (should be 2)\n", (glong)sizeof (gint16)); @@ -396,6 +401,110 @@ main (int argc, /* g_debug (argv[0]); */ + /* Relation tests */ + + g_print ("checking relations..."); + + relation = g_relation_new (2); + + g_relation_index (relation, 0, g_int_hash, g_int_equal); + g_relation_index (relation, 1, g_int_hash, g_int_equal); + + for (i = 0; i < 1024; i += 1) + data[i] = i; + + for (i = 1; i < 1023; i += 1) + { + g_relation_insert (relation, data + i, data + i + 1); + g_relation_insert (relation, data + i, data + i - 1); + } + + for (i = 2; i < 1022; i += 1) + { + g_assert (! g_relation_exists (relation, data + i, data + i)); + g_assert (! g_relation_exists (relation, data + i, data + i + 2)); + g_assert (! g_relation_exists (relation, data + i, data + i - 2)); + } + + for (i = 1; i < 1023; i += 1) + { + g_assert (g_relation_exists (relation, data + i, data + i + 1)); + g_assert (g_relation_exists (relation, data + i, data + i - 1)); + } + + for (i = 2; i < 1022; i += 1) + { + g_assert (g_relation_count (relation, data + i, 0) == 2); + g_assert (g_relation_count (relation, data + i, 1) == 2); + } + + g_assert (g_relation_count (relation, data, 0) == 0); + + g_assert (g_relation_count (relation, data + 42, 0) == 2); + g_assert (g_relation_count (relation, data + 43, 1) == 2); + g_assert (g_relation_count (relation, data + 41, 1) == 2); + g_relation_delete (relation, data + 42, 0); + g_assert (g_relation_count (relation, data + 42, 0) == 0); + g_assert (g_relation_count (relation, data + 43, 1) == 1); + g_assert (g_relation_count (relation, data + 41, 1) == 1); + + tuples = g_relation_select (relation, data + 200, 0); + + g_assert (tuples->len == 2); + +#if 0 + for (i = 0; i < tuples->len; i += 1) + { + printf ("%d %d\n", + *(gint*) g_tuples_index (tuples, i, 0), + *(gint*) g_tuples_index (tuples, i, 1)); + } +#endif + + g_assert (g_relation_exists (relation, data + 300, data + 301)); + g_relation_delete (relation, data + 300, 0); + g_assert (!g_relation_exists (relation, data + 300, data + 301)); + + g_tuples_destroy (tuples); + + g_relation_destroy (relation); + + relation = NULL; + + g_print ("ok\n"); + + g_print ("checking pointer arrays..."); + + gparray = g_ptr_array_new (); + for (i = 0; i < 10000; i++) + g_ptr_array_add (gparray, (void*)i); + + for (i = 0; i < 10000; i++) + if (g_ptr_array_index (gparray, i) != (void*)i) + g_print ("array fails: %p ( %p )\n", g_ptr_array_index (gparray, i), (void*)i); + + g_ptr_array_free (gparray, TRUE); + + g_print ("ok\n"); + + + g_print ("checking byte arrays..."); + + gbarray = g_byte_array_new (); + for (i = 0; i < 10000; i++) + g_byte_array_append (gbarray, "abcd", 4); + + for (i = 0; i < 10000; i++) + { + g_assert (gbarray->data[4*i] == 'a'); + g_assert (gbarray->data[4*i+1] == 'b'); + g_assert (gbarray->data[4*i+2] == 'c'); + g_assert (gbarray->data[4*i+3] == 'd'); + } + + g_byte_array_free (gbarray, TRUE); + + g_print ("ok\n"); return 0; } |