From 48adba2805713cf91696c33069c8db58170621fe Mon Sep 17 00:00:00 2001 From: Tim Janik Date: Wed, 30 Sep 1998 08:56:00 +0000 Subject: [PATCH] added ghook.c. Wed Sep 30 10:53:03 1998 Tim Janik * Makefile.am: added ghook.c. * glib.h: * ghook.c: generic callback maintenance functions. * glib.h: define G_GNUC_UNUSED. --- ChangeLog | 9 + ChangeLog.pre-2-0 | 9 + ChangeLog.pre-2-10 | 9 + ChangeLog.pre-2-12 | 9 + ChangeLog.pre-2-2 | 9 + ChangeLog.pre-2-4 | 9 + ChangeLog.pre-2-6 | 9 + ChangeLog.pre-2-8 | 9 + Makefile.am | 1 + ghook.c | 566 +++++++++++++++++++++++++++++++++++++++++++++ glib.h | 241 ++++++++++++++----- glib/Makefile.am | 1 + glib/ghook.c | 566 +++++++++++++++++++++++++++++++++++++++++++++ glib/glib.h | 241 ++++++++++++++----- 14 files changed, 1566 insertions(+), 122 deletions(-) create mode 100644 ghook.c create mode 100644 glib/ghook.c diff --git a/ChangeLog b/ChangeLog index 9804496a..f33a3713 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 9804496a..f33a3713 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,12 @@ +Wed Sep 30 10:53:03 1998 Tim Janik + + * Makefile.am: added ghook.c. + + * glib.h: + * ghook.c: generic callback maintenance functions. + + * glib.h: define G_GNUC_UNUSED. + Fri Sep 25 00:04:37 1998 Tim Janik * configure.in: version bump to 1.1.4, binary age 0, interface age 0. diff --git a/Makefile.am b/Makefile.am index 4c79cecc..25b3fa8b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -26,6 +26,7 @@ libglib_la_SOURCES = \ gdataset.c \ gerror.c \ ghash.c \ + ghook.c \ glist.c \ gmem.c \ gmessages.c \ diff --git a/ghook.c b/ghook.c new file mode 100644 index 00000000..2ac65751 --- /dev/null +++ b/ghook.c @@ -0,0 +1,566 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * GHook: Callback maintenance functions + * Copyright (C) 1998 Tim Janik + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "glib.h" + + +/* --- defines --- */ +#define G_HOOKS_PREALLOC (16) + + +/* --- functions --- */ +void +g_hook_list_init (GHookList *hook_list, + guint hook_size) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_size >= sizeof (GHook)); + + hook_list->seq_id = 1; + hook_list->hook_size = hook_size; + hook_list->is_setup = TRUE; + hook_list->hooks = NULL; + hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk", + hook_size, + hook_size * G_HOOKS_PREALLOC, + G_ALLOC_AND_FREE); +} + +void +g_hook_list_clear (GHookList *hook_list) +{ + g_return_if_fail (hook_list != NULL); + + if (hook_list->is_setup) + { + GHook *hook; + + hook_list->is_setup = FALSE; + + hook = hook_list->hooks; + if (!hook) + { + g_mem_chunk_destroy (hook_list->hook_memchunk); + hook_list->hook_memchunk = NULL; + } + else + do + { + register GHook *tmp; + + g_hook_ref (hook_list, hook); + g_hook_destroy_link (hook_list, hook); + tmp = hook->next; + g_hook_unref (hook_list, hook); + hook = tmp; + } + while (hook); + } +} + +GHook* +g_hook_alloc (GHookList *hook_list) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (hook_list->is_setup, NULL); + + hook = g_chunk_new0 (GHook, hook_list->hook_memchunk); + hook->data = NULL; + hook->next = NULL; + hook->prev = NULL; + hook->flags = G_HOOK_ACTIVE; + hook->ref_count = 0; + hook->id = 0; + hook->func = NULL; + hook->destroy = NULL; + + return hook; +} + +void +g_hook_free (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + + g_chunk_free (hook, hook_list->hook_memchunk); +} + +void +g_hook_destroy_link (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + + if (hook->id) + { + hook->id = 0; + hook->flags &= ~G_HOOK_ACTIVE; + if (hook->destroy) + { + register GDestroyNotify destroy; + + destroy = hook->destroy; + hook->destroy = NULL; + destroy (hook->data); + } + g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */ + } +} + +gboolean +g_hook_destroy (GHookList *hook_list, + guint id) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, FALSE); + g_return_val_if_fail (id > 0, FALSE); + + hook = g_hook_get (hook_list, id); + if (hook) + { + g_hook_destroy_link (hook_list, hook); + return TRUE; + } + + return FALSE; +} + +void +g_hook_unref (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + g_return_if_fail (hook->ref_count > 0); + + hook->ref_count--; + if (!hook->ref_count) + { + g_return_if_fail (hook->id == 0); + g_return_if_fail (!G_HOOK_IS_IN_CALL (hook)); + + if (hook->prev) + hook->prev->next = hook->next; + else + hook_list->hooks = hook->next; + if (hook->next) + { + hook->next->prev = hook->prev; + hook->next = NULL; + } + hook->prev = NULL; + + g_chunk_free (hook, hook_list->hook_memchunk); + + if (!hook_list->hooks && + !hook_list->is_setup) + { + g_mem_chunk_destroy (hook_list->hook_memchunk); + hook_list->hook_memchunk = NULL; + } + } +} + +void +g_hook_ref (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + g_return_if_fail (hook->ref_count > 0); + + hook->ref_count++; +} + +void +g_hook_prepend (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + + g_hook_insert_before (hook_list, hook_list->hooks, hook); +} + +void +g_hook_insert_before (GHookList *hook_list, + GHook *sibling, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + g_return_if_fail (hook->func != NULL); + + hook->id = hook_list->seq_id++; + hook->ref_count = 1; /* counterpart to g_hook_destroy_link */ + + if (sibling) + { + if (sibling->prev) + { + hook->prev = sibling->prev; + hook->prev->next = hook; + hook->next = sibling; + sibling->prev = hook; + } + else + { + hook_list->hooks = hook; + hook->next = sibling; + sibling->prev = hook; + } + } + else + { + if (hook_list->hooks) + { + sibling = hook_list->hooks; + while (sibling->next) + sibling = sibling->next; + hook->prev = sibling; + sibling->next = hook; + } + else + hook_list->hooks = hook; + } +} + +void +g_hook_list_invoke (GHookList *hook_list, + gboolean may_recurse) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + register GHookFunc func; + gboolean was_in_call; + + g_hook_ref (hook_list, hook); + func = hook->func; + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + func (hook->data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +void +g_hook_list_invoke_check (GHookList *hook_list, + gboolean may_recurse) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + register GHookCheckFunc func; + gboolean was_in_call; + register gboolean need_destroy; + + g_hook_ref (hook_list, hook); + func = hook->func; + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + need_destroy = !func (hook->data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + if (need_destroy) + g_hook_destroy_link (hook_list, hook); + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +void +g_hook_list_marshall (GHookList *hook_list, + gboolean may_recurse, + GHookMarshaller marshaller, + gpointer data) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (marshaller != NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + gboolean was_in_call; + + g_hook_ref (hook_list, hook); + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + marshaller (hook, data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +GHook* +g_hook_first_valid (GHookList *hook_list) +{ + g_return_val_if_fail (hook_list != NULL, NULL); + + if (hook_list->is_setup) + { + GHook *hook; + + hook = hook_list->hooks; + if (hook) + { + if (G_HOOK_IS_VALID (hook)) + return hook; + else + return g_hook_next_valid (hook); + } + } + + return NULL; +} + +GHook* +g_hook_next_valid (GHook *hook) +{ + if (!hook) + return NULL; + + hook = hook->next; + while (hook) + { + if (G_HOOK_IS_VALID (hook)) + return hook; + hook = hook->next; + } + + return NULL; +} + +GHook* +g_hook_get (GHookList *hook_list, + guint id) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (id > 0, NULL); + + hook = hook_list->hooks; + while (hook) + { + if (hook->id == id) + return hook; + hook = hook->next; + } + + return NULL; +} + +GHook* +g_hook_find (GHookList *hook_list, + gboolean need_valids, + GHookFindFunc func, + gpointer data) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + + g_hook_ref (hook_list, hook); + + if (func (hook, data) && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + { + g_hook_unref (hook_list, hook); + + return hook; + } + tmp = g_hook_next_valid (hook); + g_hook_unref (hook_list, hook); + hook = tmp; + } + + return NULL; +} + +GHook* +g_hook_find_data (GHookList *hook_list, + gboolean need_valids, + gpointer data) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->data == data && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +GHook* +g_hook_find_func (GHookList *hook_list, + gboolean need_valids, + gpointer func) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->func == func && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +GHook* +g_hook_find_func_data (GHookList *hook_list, + gboolean need_valids, + gpointer func, + gpointer data) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->data == data && hook->func == func && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +void +g_hook_insert_sorted (GHookList *hook_list, + GHook *hook, + GHookCompareFunc func) +{ + GHook *sibling; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + g_return_if_fail (hook->func != NULL); + g_return_if_fail (func != NULL); + + sibling = g_hook_first_valid (hook_list); + + while (sibling) + { + register GHook *tmp; + + g_hook_ref (hook_list, sibling); + if (func (hook, sibling) <= 0 && sibling->id) + { + g_hook_unref (hook_list, sibling); + break; + } + tmp = g_hook_next_valid (sibling); + g_hook_unref (hook_list, sibling); + sibling = tmp; + } + + g_hook_insert_before (hook_list, sibling, hook); +} + +gint +g_hook_compare_ids (GHook *new_hook, + GHook *sibling) +{ + return ((glong) new_hook->id) - ((glong) sibling->id); +} diff --git a/glib.h b/glib.h index 9724acbf..2e19a3c9 100644 --- a/glib.h +++ b/glib.h @@ -131,11 +131,11 @@ extern "C" { */ #if !defined (G_VA_COPY) # if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)) -# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) +# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) # elif defined (G_VA_COPY_AS_ARRAY) -# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) +# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) # else /* va_list is a pointer */ -# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) +# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) # endif /* va_list is a pointer */ #endif /* !G_VA_COPY */ @@ -184,7 +184,7 @@ extern "C" { # else /* !inline && !__inline__ && !__inline */ # define inline /* don't inline, then */ # ifndef G_INLINE_FUNC -# undef G_CAN_INLINE +# undef G_CAN_INLINE # endif # endif # endif @@ -245,12 +245,15 @@ extern "C" { __attribute__((noreturn)) #define G_GNUC_CONST \ __attribute__((const)) +#define G_GNUC_UNUSED \ + __attribute__((unused)) #else /* !__GNUC__ */ #define G_GNUC_PRINTF( format_idx, arg_idx ) #define G_GNUC_SCANF( format_idx, arg_idx ) #define G_GNUC_FORMAT( arg_idx ) #define G_GNUC_NORETURN #define G_GNUC_CONST +#define G_GNUC_UNUSED #endif /* !__GNUC__ */ @@ -303,8 +306,8 @@ extern "C" { */ #ifdef __DMALLOC_H__ -# define g_new(type, count) (ALLOC (type, count)) -# define g_new0(type, count) (CALLOC (type, count)) +# define g_new(type, count) (ALLOC (type, count)) +# define g_new0(type, count) (CALLOC (type, count)) # define g_renew(type, mem, count) (REALLOC (mem, type, count)) #else /* __DMALLOC_H__ */ # define g_new(type, count) \ @@ -572,6 +575,8 @@ typedef struct _GCompletion GCompletion; typedef struct _GData GData; typedef struct _GDebugKey GDebugKey; typedef struct _GHashTable GHashTable; +typedef struct _GHook GHook; +typedef struct _GHookList GHookList; typedef struct _GList GList; typedef struct _GListAllocator GListAllocator; typedef struct _GMemChunk GMemChunk; @@ -617,7 +622,7 @@ typedef enum /* log flags */ G_LOG_FLAG_RECURSION = 1 << 0, G_LOG_FLAG_FATAL = 1 << 1, - + /* GLib log levels */ G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */ G_LOG_LEVEL_CRITICAL = 1 << 3, @@ -625,7 +630,7 @@ typedef enum G_LOG_LEVEL_MESSAGE = 1 << 5, G_LOG_LEVEL_INFO = 1 << 6, G_LOG_LEVEL_DEBUG = 1 << 7, - + G_LOG_LEVEL_MASK = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL) } GLogLevelFlags; @@ -652,6 +657,14 @@ typedef void (*GHFunc) (gpointer key, typedef gboolean (*GHRFunc) (gpointer key, gpointer value, gpointer user_data); +typedef gint (*GHookCompareFunc) (GHook *new_hook, + GHook *sibling); +typedef gboolean (*GHookFindFunc) (GHook *hook, + gpointer data); +typedef void (*GHookMarshaller) (GHook *hook, + gpointer data); +typedef void (*GHookFunc) (gpointer data); +typedef gboolean (*GHookCheckFunc) (gpointer data); typedef void (*GLogFunc) (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, @@ -992,6 +1005,112 @@ GNode* g_node_last_sibling (GNode *node); ((GNode*) (node))->children : NULL) +/* Callback maintenance functions + */ +#define G_HOOK_FLAG_USER_SHIFT (4) +typedef enum +{ + G_HOOK_ACTIVE = 1 << 0, + G_HOOK_IN_CALL = 1 << 1, + G_HOOK_FLAG_MASK = 0x0f +} GHookFlagMask; + +struct _GHookList +{ + guint seq_id; + guint hook_size; + guint is_setup : 1; + GHook *hooks; + GMemChunk *hook_memchunk; +}; + +struct _GHook +{ + gpointer data; + GHook *next; + GHook *prev; + guint ref_count; + guint id; + guint flags; + gpointer func; + GDestroyNotify destroy; +}; + +#define G_HOOK_IS_ACTIVE(hook) ((((GHook*) hook)->flags & \ + G_HOOK_ACTIVE) != 0) +#define G_HOOK_IS_IN_CALL(hook) ((((GHook*) hook)->flags & \ + G_HOOK_IN_CALL) != 0) +#define G_HOOK_IS_VALID(hook) (((GHook*) hook)->id != 0 && \ + G_HOOK_IS_ACTIVE (hook)) +#define G_HOOK_IS_UNLINKED(hook) (((GHook*) hook)->next == NULL && \ + ((GHook*) hook)->prev == NULL && \ + ((GHook*) hook)->id == 0 && \ + ((GHook*) hook)->ref_count == 0) + +void g_hook_list_init (GHookList *hook_list, + guint hook_size); +void g_hook_list_clear (GHookList *hook_list); +GHook* g_hook_alloc (GHookList *hook_list); +void g_hook_free (GHookList *hook_list, + GHook *hook); +void g_hook_ref (GHookList *hook_list, + GHook *hook); +void g_hook_unref (GHookList *hook_list, + GHook *hook); +gboolean g_hook_destroy (GHookList *hook_list, + guint id); +void g_hook_destroy_link (GHookList *hook_list, + GHook *hook); +void g_hook_prepend (GHookList *hook_list, + GHook *hook); +void g_hook_insert_before (GHookList *hook_list, + GHook *sibling, + GHook *hook); +void g_hook_insert_sorted (GHookList *hook_list, + GHook *hook, + GHookCompareFunc func); +GHook* g_hook_get (GHookList *hook_list, + guint id); +GHook* g_hook_find (GHookList *hook_list, + gboolean need_valids, + GHookFindFunc func, + gpointer data); +GHook* g_hook_find_data (GHookList *hook_list, + gboolean need_valids, + gpointer data); +GHook* g_hook_find_func (GHookList *hook_list, + gboolean need_valids, + gpointer func); +GHook* g_hook_find_func_data (GHookList *hook_list, + gboolean need_valids, + gpointer func, + gpointer data); +GHook* g_hook_first_valid (GHookList *hook_list); +GHook* g_hook_next_valid (GHook *hook); +gint g_hook_compare_ids (GHook *new_hook, + GHook *sibling); + +/* convenience macros */ +#define g_hook_append( hook_list, hook ) \ + g_hook_insert_before ((hook_list), NULL, (hook)) + +/* invoke all valid hooks with the (*GHookFunc) signature. + */ +void g_hook_list_invoke (GHookList *hook_list, + gboolean may_recurse); +/* invoke all valid hooks with the (*GHookCheckFunc) signature, + * and destroy the hook if FALSE is returned. + */ +void g_hook_list_invoke_check (GHookList *hook_list, + gboolean may_recurse); +/* invoke a marshaller on all valid hooks. + */ +void g_hook_list_marshall (GHookList *hook_list, + gboolean may_recurse, + GHookMarshaller marshaller, + gpointer data); + + /* Fatal error handlers. * g_on_error_query() will prompt the user to either * [E]xit, [H]alt, [P]roceed or show [S]tack trace. @@ -1171,7 +1290,7 @@ gdouble g_timer_elapsed (GTimer *timer, /* String utility functions */ -#define G_STR_DELIMITERS "_-|> <." +#define G_STR_DELIMITERS "_-|> <." void g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter); @@ -1181,12 +1300,12 @@ gchar* g_strdup_printf (const gchar *format, gchar* g_strdup_vprintf (const gchar *format, va_list args); gchar* g_strndup (const gchar *str, - guint n); -gchar* g_strnfill (guint length, + guint n); +gchar* g_strnfill (guint length, gchar fill_char); gchar* g_strconcat (const gchar *string1, ...); /* NULL terminated */ -gdouble g_strtod (const gchar *nptr, +gdouble g_strtod (const gchar *nptr, gchar **endptr); gchar* g_strerror (gint errnum); gchar* g_strsignal (gint signum); @@ -1196,12 +1315,12 @@ void g_strdown (gchar *string); void g_strup (gchar *string); void g_strreverse (gchar *string); gpointer g_memdup (gconstpointer mem, - guint byte_size); + guint byte_size); /* calculate a string size, guarranteed to fit format + args. */ guint g_printf_string_upper_bound (const gchar* format, - va_list args); + va_list args); /* Retrive static string info @@ -1294,7 +1413,7 @@ g_bit_nth_msf (guint32 mask, while (nth_bit > 0); return -1; } -#endif /* G_CAN_INLINE */ +#endif /* G_CAN_INLINE */ G_INLINE_FUNC guint g_bit_storage (guint number); #ifdef G_CAN_INLINE @@ -1302,7 +1421,7 @@ G_INLINE_FUNC guint g_bit_storage (guint number) { register guint n_bits = 0; - + do { n_bits++; @@ -1311,7 +1430,7 @@ g_bit_storage (guint number) while (number); return n_bits; } -#endif /* G_CAN_INLINE */ +#endif /* G_CAN_INLINE */ /* String Chunks @@ -1368,18 +1487,18 @@ void g_string_sprintfa (GString *string, #define g_array_prepend_val(a,v) g_array_prepend_vals(a,&v,1) #define g_array_index(a,t,i) (((t*)a->data)[i]) -GArray* g_array_new (gboolean zero_terminated, - gboolean clear, - guint element_size); -void g_array_free (GArray *array, - gboolean free_segment); -GArray* g_array_append_vals (GArray *array, +GArray* g_array_new (gboolean zero_terminated, + gboolean clear, + guint element_size); +void g_array_free (GArray *array, + gboolean free_segment); +GArray* g_array_append_vals (GArray *array, gconstpointer data, - guint len); -GArray* g_array_prepend_vals (GArray *array, + guint len); +GArray* g_array_prepend_vals (GArray *array, gconstpointer data, - guint len); -GArray* g_array_set_size (GArray *array, + guint len); +GArray* g_array_set_size (GArray *array, guint length); /* Resizable pointer array. This interface is much less complicated @@ -1392,28 +1511,28 @@ void g_ptr_array_free (GPtrArray *array, gboolean free_seg); void g_ptr_array_set_size (GPtrArray *array, gint length); -gpointer 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); +gpointer 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, - gboolean free_segment); -GByteArray* g_byte_array_append (GByteArray *array, +GByteArray* g_byte_array_new (void); +void g_byte_array_free (GByteArray *array, + gboolean free_segment); +GByteArray* g_byte_array_append (GByteArray *array, const guint8 *data, - guint len); -GByteArray* g_byte_array_prepend (GByteArray *array, + guint len); +GByteArray* g_byte_array_prepend (GByteArray *array, const guint8 *data, - guint len); -GByteArray* g_byte_array_set_size (GByteArray *array, - guint length); + guint len); +GByteArray* g_byte_array_set_size (GByteArray *array, + guint length); /* Hash Functions @@ -1538,7 +1657,7 @@ typedef enum typedef enum { G_TOKEN_EOF = 0, - + G_TOKEN_LEFT_PAREN = '(', G_TOKEN_RIGHT_PAREN = ')', G_TOKEN_LEFT_CURLY = '{', @@ -1547,11 +1666,11 @@ typedef enum G_TOKEN_RIGHT_BRACE = ']', G_TOKEN_EQUAL_SIGN = '=', G_TOKEN_COMMA = ',', - + G_TOKEN_NONE = 256, - + G_TOKEN_ERROR, - + G_TOKEN_CHAR, G_TOKEN_BINARY, G_TOKEN_OCTAL, @@ -1559,11 +1678,11 @@ typedef enum G_TOKEN_HEX, G_TOKEN_FLOAT, G_TOKEN_STRING, - + G_TOKEN_SYMBOL, G_TOKEN_IDENTIFIER, G_TOKEN_IDENTIFIER_NULL, - + G_TOKEN_COMMENT_SINGLE, G_TOKEN_COMMENT_MULTI, G_TOKEN_LAST @@ -1592,11 +1711,11 @@ struct _GScannerConfig gchar *cset_identifier_first; gchar *cset_identifier_nth; gchar *cpair_comment_single; /* default: "#\n" */ - + /* Should symbol lookup work case sensitive? */ guint case_sensitive : 1; - + /* Boolean values to be adjusted "on the fly" * to configure scanning behaviour. */ @@ -1627,31 +1746,31 @@ struct _GScanner /* unused fields */ gpointer user_data; guint max_parse_errors; - + /* g_scanner_error() increments this field */ guint parse_errors; - + /* name of input stream, featured by the default message handler */ const gchar *input_name; - + /* data pointer for derived structures */ gpointer derived_data; - + /* link into the scanner configuration */ GScannerConfig *config; - + /* fields filled in after g_scanner_get_next_token() */ GTokenType token; GTokenValue value; guint line; guint position; - + /* fields filled in after g_scanner_peek_next_token() */ GTokenType next_token; GTokenValue next_value; guint next_line; guint next_position; - + /* to be considered private */ GHashTable *symbol_table; gint input_fd; @@ -1659,7 +1778,7 @@ struct _GScanner const gchar *text_end; gchar *buffer; guint scope_id; - + /* handler function for _warn and _error */ GScannerMsgFunc msg_handler; }; @@ -1730,7 +1849,7 @@ struct _GCompletion { GList* items; GCompletionFunc func; - + gchar* prefix; GList* cache; }; @@ -1800,12 +1919,12 @@ gpointer g_tuples_index (GTuples *tuples, /* This function returns prime numbers spaced by approximately 1.5-2.0 * and is for use in resizing data structures which prefer - * prime-valued sizes. The closest spaced prime function returns the + * prime-valued sizes. The closest spaced prime function returns the * next largest prime, or the highest it knows about which is about * MAXINT/4. */ -guint g_spaced_primes_closest (guint num); +guint g_spaced_primes_closest (guint num); /* Glib version. */ diff --git a/glib/Makefile.am b/glib/Makefile.am index 4c79cecc..25b3fa8b 100644 --- a/glib/Makefile.am +++ b/glib/Makefile.am @@ -26,6 +26,7 @@ libglib_la_SOURCES = \ gdataset.c \ gerror.c \ ghash.c \ + ghook.c \ glist.c \ gmem.c \ gmessages.c \ diff --git a/glib/ghook.c b/glib/ghook.c new file mode 100644 index 00000000..2ac65751 --- /dev/null +++ b/glib/ghook.c @@ -0,0 +1,566 @@ +/* GLIB - Library of useful routines for C programming + * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald + * + * GHook: Callback maintenance functions + * Copyright (C) 1998 Tim Janik + * + * 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., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#include "glib.h" + + +/* --- defines --- */ +#define G_HOOKS_PREALLOC (16) + + +/* --- functions --- */ +void +g_hook_list_init (GHookList *hook_list, + guint hook_size) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_size >= sizeof (GHook)); + + hook_list->seq_id = 1; + hook_list->hook_size = hook_size; + hook_list->is_setup = TRUE; + hook_list->hooks = NULL; + hook_list->hook_memchunk = g_mem_chunk_new ("GHook Memchunk", + hook_size, + hook_size * G_HOOKS_PREALLOC, + G_ALLOC_AND_FREE); +} + +void +g_hook_list_clear (GHookList *hook_list) +{ + g_return_if_fail (hook_list != NULL); + + if (hook_list->is_setup) + { + GHook *hook; + + hook_list->is_setup = FALSE; + + hook = hook_list->hooks; + if (!hook) + { + g_mem_chunk_destroy (hook_list->hook_memchunk); + hook_list->hook_memchunk = NULL; + } + else + do + { + register GHook *tmp; + + g_hook_ref (hook_list, hook); + g_hook_destroy_link (hook_list, hook); + tmp = hook->next; + g_hook_unref (hook_list, hook); + hook = tmp; + } + while (hook); + } +} + +GHook* +g_hook_alloc (GHookList *hook_list) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (hook_list->is_setup, NULL); + + hook = g_chunk_new0 (GHook, hook_list->hook_memchunk); + hook->data = NULL; + hook->next = NULL; + hook->prev = NULL; + hook->flags = G_HOOK_ACTIVE; + hook->ref_count = 0; + hook->id = 0; + hook->func = NULL; + hook->destroy = NULL; + + return hook; +} + +void +g_hook_free (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + + g_chunk_free (hook, hook_list->hook_memchunk); +} + +void +g_hook_destroy_link (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + + if (hook->id) + { + hook->id = 0; + hook->flags &= ~G_HOOK_ACTIVE; + if (hook->destroy) + { + register GDestroyNotify destroy; + + destroy = hook->destroy; + hook->destroy = NULL; + destroy (hook->data); + } + g_hook_unref (hook_list, hook); /* counterpart to g_hook_insert_before */ + } +} + +gboolean +g_hook_destroy (GHookList *hook_list, + guint id) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, FALSE); + g_return_val_if_fail (id > 0, FALSE); + + hook = g_hook_get (hook_list, id); + if (hook) + { + g_hook_destroy_link (hook_list, hook); + return TRUE; + } + + return FALSE; +} + +void +g_hook_unref (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + g_return_if_fail (hook->ref_count > 0); + + hook->ref_count--; + if (!hook->ref_count) + { + g_return_if_fail (hook->id == 0); + g_return_if_fail (!G_HOOK_IS_IN_CALL (hook)); + + if (hook->prev) + hook->prev->next = hook->next; + else + hook_list->hooks = hook->next; + if (hook->next) + { + hook->next->prev = hook->prev; + hook->next = NULL; + } + hook->prev = NULL; + + g_chunk_free (hook, hook_list->hook_memchunk); + + if (!hook_list->hooks && + !hook_list->is_setup) + { + g_mem_chunk_destroy (hook_list->hook_memchunk); + hook_list->hook_memchunk = NULL; + } + } +} + +void +g_hook_ref (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook != NULL); + g_return_if_fail (hook->ref_count > 0); + + hook->ref_count++; +} + +void +g_hook_prepend (GHookList *hook_list, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + + g_hook_insert_before (hook_list, hook_list->hooks, hook); +} + +void +g_hook_insert_before (GHookList *hook_list, + GHook *sibling, + GHook *hook) +{ + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + g_return_if_fail (hook->func != NULL); + + hook->id = hook_list->seq_id++; + hook->ref_count = 1; /* counterpart to g_hook_destroy_link */ + + if (sibling) + { + if (sibling->prev) + { + hook->prev = sibling->prev; + hook->prev->next = hook; + hook->next = sibling; + sibling->prev = hook; + } + else + { + hook_list->hooks = hook; + hook->next = sibling; + sibling->prev = hook; + } + } + else + { + if (hook_list->hooks) + { + sibling = hook_list->hooks; + while (sibling->next) + sibling = sibling->next; + hook->prev = sibling; + sibling->next = hook; + } + else + hook_list->hooks = hook; + } +} + +void +g_hook_list_invoke (GHookList *hook_list, + gboolean may_recurse) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + register GHookFunc func; + gboolean was_in_call; + + g_hook_ref (hook_list, hook); + func = hook->func; + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + func (hook->data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +void +g_hook_list_invoke_check (GHookList *hook_list, + gboolean may_recurse) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + register GHookCheckFunc func; + gboolean was_in_call; + register gboolean need_destroy; + + g_hook_ref (hook_list, hook); + func = hook->func; + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + need_destroy = !func (hook->data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + if (need_destroy) + g_hook_destroy_link (hook_list, hook); + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +void +g_hook_list_marshall (GHookList *hook_list, + gboolean may_recurse, + GHookMarshaller marshaller, + gpointer data) +{ + GHook *hook; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (marshaller != NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + gboolean was_in_call; + + g_hook_ref (hook_list, hook); + + was_in_call = G_HOOK_IS_IN_CALL (hook); + hook->flags |= G_HOOK_IN_CALL; + marshaller (hook, data); + if (!was_in_call) + hook->flags &= ~G_HOOK_IN_CALL; + + if (may_recurse) + tmp = g_hook_next_valid (hook); + else + do + tmp = g_hook_next_valid (hook); + while (tmp && G_HOOK_IS_IN_CALL (tmp)); + + g_hook_unref (hook_list, hook); + hook = tmp; + } +} + +GHook* +g_hook_first_valid (GHookList *hook_list) +{ + g_return_val_if_fail (hook_list != NULL, NULL); + + if (hook_list->is_setup) + { + GHook *hook; + + hook = hook_list->hooks; + if (hook) + { + if (G_HOOK_IS_VALID (hook)) + return hook; + else + return g_hook_next_valid (hook); + } + } + + return NULL; +} + +GHook* +g_hook_next_valid (GHook *hook) +{ + if (!hook) + return NULL; + + hook = hook->next; + while (hook) + { + if (G_HOOK_IS_VALID (hook)) + return hook; + hook = hook->next; + } + + return NULL; +} + +GHook* +g_hook_get (GHookList *hook_list, + guint id) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (id > 0, NULL); + + hook = hook_list->hooks; + while (hook) + { + if (hook->id == id) + return hook; + hook = hook->next; + } + + return NULL; +} + +GHook* +g_hook_find (GHookList *hook_list, + gboolean need_valids, + GHookFindFunc func, + gpointer data) +{ + GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + register GHook *tmp; + + g_hook_ref (hook_list, hook); + + if (func (hook, data) && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + { + g_hook_unref (hook_list, hook); + + return hook; + } + tmp = g_hook_next_valid (hook); + g_hook_unref (hook_list, hook); + hook = tmp; + } + + return NULL; +} + +GHook* +g_hook_find_data (GHookList *hook_list, + gboolean need_valids, + gpointer data) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->data == data && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +GHook* +g_hook_find_func (GHookList *hook_list, + gboolean need_valids, + gpointer func) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->func == func && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +GHook* +g_hook_find_func_data (GHookList *hook_list, + gboolean need_valids, + gpointer func, + gpointer data) +{ + register GHook *hook; + + g_return_val_if_fail (hook_list != NULL, NULL); + g_return_val_if_fail (func != NULL, NULL); + + hook = g_hook_first_valid (hook_list); + while (hook) + { + if (hook->data == data && hook->func == func && hook->id && (!need_valids || G_HOOK_IS_ACTIVE (hook))) + return hook; + + hook = g_hook_next_valid (hook); + } + + return NULL; +} + +void +g_hook_insert_sorted (GHookList *hook_list, + GHook *hook, + GHookCompareFunc func) +{ + GHook *sibling; + + g_return_if_fail (hook_list != NULL); + g_return_if_fail (hook_list->is_setup); + g_return_if_fail (hook != NULL); + g_return_if_fail (G_HOOK_IS_UNLINKED (hook)); + g_return_if_fail (hook->func != NULL); + g_return_if_fail (func != NULL); + + sibling = g_hook_first_valid (hook_list); + + while (sibling) + { + register GHook *tmp; + + g_hook_ref (hook_list, sibling); + if (func (hook, sibling) <= 0 && sibling->id) + { + g_hook_unref (hook_list, sibling); + break; + } + tmp = g_hook_next_valid (sibling); + g_hook_unref (hook_list, sibling); + sibling = tmp; + } + + g_hook_insert_before (hook_list, sibling, hook); +} + +gint +g_hook_compare_ids (GHook *new_hook, + GHook *sibling) +{ + return ((glong) new_hook->id) - ((glong) sibling->id); +} diff --git a/glib/glib.h b/glib/glib.h index 9724acbf..2e19a3c9 100644 --- a/glib/glib.h +++ b/glib/glib.h @@ -131,11 +131,11 @@ extern "C" { */ #if !defined (G_VA_COPY) # if defined (__GNUC__) && defined (__PPC__) && (defined (_CALL_SYSV) || defined (_WIN32)) -# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) +# define G_VA_COPY(ap1, ap2) (*(ap1) = *(ap2)) # elif defined (G_VA_COPY_AS_ARRAY) -# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) +# define G_VA_COPY(ap1, ap2) g_memmove ((ap1), (ap2), sizeof (va_list)) # else /* va_list is a pointer */ -# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) +# define G_VA_COPY(ap1, ap2) ((ap1) = (ap2)) # endif /* va_list is a pointer */ #endif /* !G_VA_COPY */ @@ -184,7 +184,7 @@ extern "C" { # else /* !inline && !__inline__ && !__inline */ # define inline /* don't inline, then */ # ifndef G_INLINE_FUNC -# undef G_CAN_INLINE +# undef G_CAN_INLINE # endif # endif # endif @@ -245,12 +245,15 @@ extern "C" { __attribute__((noreturn)) #define G_GNUC_CONST \ __attribute__((const)) +#define G_GNUC_UNUSED \ + __attribute__((unused)) #else /* !__GNUC__ */ #define G_GNUC_PRINTF( format_idx, arg_idx ) #define G_GNUC_SCANF( format_idx, arg_idx ) #define G_GNUC_FORMAT( arg_idx ) #define G_GNUC_NORETURN #define G_GNUC_CONST +#define G_GNUC_UNUSED #endif /* !__GNUC__ */ @@ -303,8 +306,8 @@ extern "C" { */ #ifdef __DMALLOC_H__ -# define g_new(type, count) (ALLOC (type, count)) -# define g_new0(type, count) (CALLOC (type, count)) +# define g_new(type, count) (ALLOC (type, count)) +# define g_new0(type, count) (CALLOC (type, count)) # define g_renew(type, mem, count) (REALLOC (mem, type, count)) #else /* __DMALLOC_H__ */ # define g_new(type, count) \ @@ -572,6 +575,8 @@ typedef struct _GCompletion GCompletion; typedef struct _GData GData; typedef struct _GDebugKey GDebugKey; typedef struct _GHashTable GHashTable; +typedef struct _GHook GHook; +typedef struct _GHookList GHookList; typedef struct _GList GList; typedef struct _GListAllocator GListAllocator; typedef struct _GMemChunk GMemChunk; @@ -617,7 +622,7 @@ typedef enum /* log flags */ G_LOG_FLAG_RECURSION = 1 << 0, G_LOG_FLAG_FATAL = 1 << 1, - + /* GLib log levels */ G_LOG_LEVEL_ERROR = 1 << 2, /* always fatal */ G_LOG_LEVEL_CRITICAL = 1 << 3, @@ -625,7 +630,7 @@ typedef enum G_LOG_LEVEL_MESSAGE = 1 << 5, G_LOG_LEVEL_INFO = 1 << 6, G_LOG_LEVEL_DEBUG = 1 << 7, - + G_LOG_LEVEL_MASK = ~(G_LOG_FLAG_RECURSION | G_LOG_FLAG_FATAL) } GLogLevelFlags; @@ -652,6 +657,14 @@ typedef void (*GHFunc) (gpointer key, typedef gboolean (*GHRFunc) (gpointer key, gpointer value, gpointer user_data); +typedef gint (*GHookCompareFunc) (GHook *new_hook, + GHook *sibling); +typedef gboolean (*GHookFindFunc) (GHook *hook, + gpointer data); +typedef void (*GHookMarshaller) (GHook *hook, + gpointer data); +typedef void (*GHookFunc) (gpointer data); +typedef gboolean (*GHookCheckFunc) (gpointer data); typedef void (*GLogFunc) (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, @@ -992,6 +1005,112 @@ GNode* g_node_last_sibling (GNode *node); ((GNode*) (node))->children : NULL) +/* Callback maintenance functions + */ +#define G_HOOK_FLAG_USER_SHIFT (4) +typedef enum +{ + G_HOOK_ACTIVE = 1 << 0, + G_HOOK_IN_CALL = 1 << 1, + G_HOOK_FLAG_MASK = 0x0f +} GHookFlagMask; + +struct _GHookList +{ + guint seq_id; + guint hook_size; + guint is_setup : 1; + GHook *hooks; + GMemChunk *hook_memchunk; +}; + +struct _GHook +{ + gpointer data; + GHook *next; + GHook *prev; + guint ref_count; + guint id; + guint flags; + gpointer func; + GDestroyNotify destroy; +}; + +#define G_HOOK_IS_ACTIVE(hook) ((((GHook*) hook)->flags & \ + G_HOOK_ACTIVE) != 0) +#define G_HOOK_IS_IN_CALL(hook) ((((GHook*) hook)->flags & \ + G_HOOK_IN_CALL) != 0) +#define G_HOOK_IS_VALID(hook) (((GHook*) hook)->id != 0 && \ + G_HOOK_IS_ACTIVE (hook)) +#define G_HOOK_IS_UNLINKED(hook) (((GHook*) hook)->next == NULL && \ + ((GHook*) hook)->prev == NULL && \ + ((GHook*) hook)->id == 0 && \ + ((GHook*) hook)->ref_count == 0) + +void g_hook_list_init (GHookList *hook_list, + guint hook_size); +void g_hook_list_clear (GHookList *hook_list); +GHook* g_hook_alloc (GHookList *hook_list); +void g_hook_free (GHookList *hook_list, + GHook *hook); +void g_hook_ref (GHookList *hook_list, + GHook *hook); +void g_hook_unref (GHookList *hook_list, + GHook *hook); +gboolean g_hook_destroy (GHookList *hook_list, + guint id); +void g_hook_destroy_link (GHookList *hook_list, + GHook *hook); +void g_hook_prepend (GHookList *hook_list, + GHook *hook); +void g_hook_insert_before (GHookList *hook_list, + GHook *sibling, + GHook *hook); +void g_hook_insert_sorted (GHookList *hook_list, + GHook *hook, + GHookCompareFunc func); +GHook* g_hook_get (GHookList *hook_list, + guint id); +GHook* g_hook_find (GHookList *hook_list, + gboolean need_valids, + GHookFindFunc func, + gpointer data); +GHook* g_hook_find_data (GHookList *hook_list, + gboolean need_valids, + gpointer data); +GHook* g_hook_find_func (GHookList *hook_list, + gboolean need_valids, + gpointer func); +GHook* g_hook_find_func_data (GHookList *hook_list, + gboolean need_valids, + gpointer func, + gpointer data); +GHook* g_hook_first_valid (GHookList *hook_list); +GHook* g_hook_next_valid (GHook *hook); +gint g_hook_compare_ids (GHook *new_hook, + GHook *sibling); + +/* convenience macros */ +#define g_hook_append( hook_list, hook ) \ + g_hook_insert_before ((hook_list), NULL, (hook)) + +/* invoke all valid hooks with the (*GHookFunc) signature. + */ +void g_hook_list_invoke (GHookList *hook_list, + gboolean may_recurse); +/* invoke all valid hooks with the (*GHookCheckFunc) signature, + * and destroy the hook if FALSE is returned. + */ +void g_hook_list_invoke_check (GHookList *hook_list, + gboolean may_recurse); +/* invoke a marshaller on all valid hooks. + */ +void g_hook_list_marshall (GHookList *hook_list, + gboolean may_recurse, + GHookMarshaller marshaller, + gpointer data); + + /* Fatal error handlers. * g_on_error_query() will prompt the user to either * [E]xit, [H]alt, [P]roceed or show [S]tack trace. @@ -1171,7 +1290,7 @@ gdouble g_timer_elapsed (GTimer *timer, /* String utility functions */ -#define G_STR_DELIMITERS "_-|> <." +#define G_STR_DELIMITERS "_-|> <." void g_strdelimit (gchar *string, const gchar *delimiters, gchar new_delimiter); @@ -1181,12 +1300,12 @@ gchar* g_strdup_printf (const gchar *format, gchar* g_strdup_vprintf (const gchar *format, va_list args); gchar* g_strndup (const gchar *str, - guint n); -gchar* g_strnfill (guint length, + guint n); +gchar* g_strnfill (guint length, gchar fill_char); gchar* g_strconcat (const gchar *string1, ...); /* NULL terminated */ -gdouble g_strtod (const gchar *nptr, +gdouble g_strtod (const gchar *nptr, gchar **endptr); gchar* g_strerror (gint errnum); gchar* g_strsignal (gint signum); @@ -1196,12 +1315,12 @@ void g_strdown (gchar *string); void g_strup (gchar *string); void g_strreverse (gchar *string); gpointer g_memdup (gconstpointer mem, - guint byte_size); + guint byte_size); /* calculate a string size, guarranteed to fit format + args. */ guint g_printf_string_upper_bound (const gchar* format, - va_list args); + va_list args); /* Retrive static string info @@ -1294,7 +1413,7 @@ g_bit_nth_msf (guint32 mask, while (nth_bit > 0); return -1; } -#endif /* G_CAN_INLINE */ +#endif /* G_CAN_INLINE */ G_INLINE_FUNC guint g_bit_storage (guint number); #ifdef G_CAN_INLINE @@ -1302,7 +1421,7 @@ G_INLINE_FUNC guint g_bit_storage (guint number) { register guint n_bits = 0; - + do { n_bits++; @@ -1311,7 +1430,7 @@ g_bit_storage (guint number) while (number); return n_bits; } -#endif /* G_CAN_INLINE */ +#endif /* G_CAN_INLINE */ /* String Chunks @@ -1368,18 +1487,18 @@ void g_string_sprintfa (GString *string, #define g_array_prepend_val(a,v) g_array_prepend_vals(a,&v,1) #define g_array_index(a,t,i) (((t*)a->data)[i]) -GArray* g_array_new (gboolean zero_terminated, - gboolean clear, - guint element_size); -void g_array_free (GArray *array, - gboolean free_segment); -GArray* g_array_append_vals (GArray *array, +GArray* g_array_new (gboolean zero_terminated, + gboolean clear, + guint element_size); +void g_array_free (GArray *array, + gboolean free_segment); +GArray* g_array_append_vals (GArray *array, gconstpointer data, - guint len); -GArray* g_array_prepend_vals (GArray *array, + guint len); +GArray* g_array_prepend_vals (GArray *array, gconstpointer data, - guint len); -GArray* g_array_set_size (GArray *array, + guint len); +GArray* g_array_set_size (GArray *array, guint length); /* Resizable pointer array. This interface is much less complicated @@ -1392,28 +1511,28 @@ void g_ptr_array_free (GPtrArray *array, gboolean free_seg); void g_ptr_array_set_size (GPtrArray *array, gint length); -gpointer 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); +gpointer 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, - gboolean free_segment); -GByteArray* g_byte_array_append (GByteArray *array, +GByteArray* g_byte_array_new (void); +void g_byte_array_free (GByteArray *array, + gboolean free_segment); +GByteArray* g_byte_array_append (GByteArray *array, const guint8 *data, - guint len); -GByteArray* g_byte_array_prepend (GByteArray *array, + guint len); +GByteArray* g_byte_array_prepend (GByteArray *array, const guint8 *data, - guint len); -GByteArray* g_byte_array_set_size (GByteArray *array, - guint length); + guint len); +GByteArray* g_byte_array_set_size (GByteArray *array, + guint length); /* Hash Functions @@ -1538,7 +1657,7 @@ typedef enum typedef enum { G_TOKEN_EOF = 0, - + G_TOKEN_LEFT_PAREN = '(', G_TOKEN_RIGHT_PAREN = ')', G_TOKEN_LEFT_CURLY = '{', @@ -1547,11 +1666,11 @@ typedef enum G_TOKEN_RIGHT_BRACE = ']', G_TOKEN_EQUAL_SIGN = '=', G_TOKEN_COMMA = ',', - + G_TOKEN_NONE = 256, - + G_TOKEN_ERROR, - + G_TOKEN_CHAR, G_TOKEN_BINARY, G_TOKEN_OCTAL, @@ -1559,11 +1678,11 @@ typedef enum G_TOKEN_HEX, G_TOKEN_FLOAT, G_TOKEN_STRING, - + G_TOKEN_SYMBOL, G_TOKEN_IDENTIFIER, G_TOKEN_IDENTIFIER_NULL, - + G_TOKEN_COMMENT_SINGLE, G_TOKEN_COMMENT_MULTI, G_TOKEN_LAST @@ -1592,11 +1711,11 @@ struct _GScannerConfig gchar *cset_identifier_first; gchar *cset_identifier_nth; gchar *cpair_comment_single; /* default: "#\n" */ - + /* Should symbol lookup work case sensitive? */ guint case_sensitive : 1; - + /* Boolean values to be adjusted "on the fly" * to configure scanning behaviour. */ @@ -1627,31 +1746,31 @@ struct _GScanner /* unused fields */ gpointer user_data; guint max_parse_errors; - + /* g_scanner_error() increments this field */ guint parse_errors; - + /* name of input stream, featured by the default message handler */ const gchar *input_name; - + /* data pointer for derived structures */ gpointer derived_data; - + /* link into the scanner configuration */ GScannerConfig *config; - + /* fields filled in after g_scanner_get_next_token() */ GTokenType token; GTokenValue value; guint line; guint position; - + /* fields filled in after g_scanner_peek_next_token() */ GTokenType next_token; GTokenValue next_value; guint next_line; guint next_position; - + /* to be considered private */ GHashTable *symbol_table; gint input_fd; @@ -1659,7 +1778,7 @@ struct _GScanner const gchar *text_end; gchar *buffer; guint scope_id; - + /* handler function for _warn and _error */ GScannerMsgFunc msg_handler; }; @@ -1730,7 +1849,7 @@ struct _GCompletion { GList* items; GCompletionFunc func; - + gchar* prefix; GList* cache; }; @@ -1800,12 +1919,12 @@ gpointer g_tuples_index (GTuples *tuples, /* This function returns prime numbers spaced by approximately 1.5-2.0 * and is for use in resizing data structures which prefer - * prime-valued sizes. The closest spaced prime function returns the + * prime-valued sizes. The closest spaced prime function returns the * next largest prime, or the highest it knows about which is about * MAXINT/4. */ -guint g_spaced_primes_closest (guint num); +guint g_spaced_primes_closest (guint num); /* Glib version. */ -- 2.34.1