diff options
Diffstat (limited to 'src/glibext')
-rw-r--r-- | src/glibext/Makefile.am | 8 | ||||
-rw-r--r-- | src/glibext/helpers.h | 166 |
2 files changed, 173 insertions, 1 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am index 986bbd1..58ddb93 100644 --- a/src/glibext/Makefile.am +++ b/src/glibext/Makefile.am @@ -1,7 +1,7 @@ BUILT_SOURCES = chrysamarshal.h chrysamarshal.c -noinst_LTLIBRARIES = libglibext.la +noinst_LTLIBRARIES = libglibext4.la # libglibext.la libglibext_la_SOURCES = \ buffercache-int.h \ @@ -52,6 +52,12 @@ libglibext_la_LIBADD = \ generators/libglibextgenerators.la +libglibext4_la_SOURCES = \ + helpers.h + +libglibext4_la_CFLAGS = $(TOOLKIT_CFLAGS) + + devdir = $(includedir)/chrysalide/$(subdir:src/%=core/%) dev_HEADERS = $(libglibext_la_SOURCES:%c=) diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h new file mode 100644 index 0000000..752eb07 --- /dev/null +++ b/src/glibext/helpers.h @@ -0,0 +1,166 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * helpers.h - prototypes pour la simplification des interactions de base avec GLib + * + * Copyright (C) 2024 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * Chrysalide is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * Chrysalide 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Chrysalide. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef _GLIBEXT_HELPERS_H +#define _GLIBEXT_HELPERS_H + + +#include <assert.h> +#include <glib-object.h> + + + +/** + * Les définitions issues de <glib-2.80>/gobject/gtype.h fournissent des macros + * facilitant la déclaration de types pour entêtes. Cependant : + * + * - G_DECLARE_FINAL_TYPE impose une structure de classe fixe ; + * - G_DECLARE_DERIVABLE_TYPE impose une structure d'objet fixe. + * + * Ces deux macros ne peuvent donc pas être employées en l'état dans Chrysalide. + * + * Par ailleurs, la fonctionnalité g_autoptr() n'offre pas une séduction totale : + * elle conduit à un code inconsistant, avec parfois des libérations explicites, + * parfois des libérations invisible gérées par le compilateur. Cet aspect + * fonctionnel offert par les macros GLib est donc inutile pour Chrysalide. + * + * Une nouvelle macro de déclaration est ainsi constituée ici. + * + * De fait de l'absence d'argument, l'inclusion de la définition suivante n'est + * pas possible : + * + * MOD##_TYPE_##NAME t_n##_get_type() + * + * La macro traditionnelle doit ainsi être fournie en parallèle à la déclaration + * condensée ici. Elle y est d'ailleurs référencée, forçant une déclaration + * préalable de manière globale et cohérente dans l'ensemble du code d'emploi. + */ + +#define DECLARE_GTYPE(TN, t_n, MOD, NAME) \ + \ + GType t_n##_get_type(void); \ + \ + typedef struct _##TN TN; \ + typedef struct _##TN##Class TN##Class; \ + \ + G_GNUC_UNUSED static inline TN *MOD##_##NAME(gpointer obj) \ + { \ + return G_TYPE_CHECK_INSTANCE_CAST(obj, MOD##_TYPE_##NAME, TN); \ + } \ + \ + G_GNUC_UNUSED static inline TN##Class *MOD##_##NAME##_CLASS(gpointer klass) \ + { \ + return G_TYPE_CHECK_CLASS_CAST(klass, MOD##_TYPE_##NAME, TN##Class); \ + } \ + \ + G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME(gpointer obj) \ + { \ + return G_TYPE_CHECK_INSTANCE_TYPE(obj, MOD##_TYPE_##NAME); \ + } \ + \ + G_GNUC_UNUSED static inline gboolean MOD##_IS_##NAME##_CLASS(gpointer klass) \ + { \ + return G_TYPE_CHECK_CLASS_TYPE(klass, MOD##_TYPE_##NAME); \ + } \ + \ + G_GNUC_UNUSED static inline TN##Class *MOD##_##NAME##_GET_CLASS(gpointer obj) \ + { \ + return G_TYPE_INSTANCE_GET_CLASS(obj, MOD##_TYPE_##NAME, TN##Class); \ + } + + +/** + * Les principales fonctions incrémentant ou réduisant le nombre de références + * attachées à un objet acceptent de simples pointeurs génériques (cf. définitions + * du fichier <glib-2.80>/gobject/gobject.h : + * + * [...] + * void g_object_notify_by_pspec (GObject *object, + * GParamSpec *pspec); + * void g_object_thaw_notify (GObject *object); + * gboolean g_object_is_floating (gpointer object); + * gpointer g_object_ref_sink (gpointer object); + * gpointer g_object_take_ref (gpointer object); + * gpointer g_object_ref (gpointer object); + * void g_object_unref (gpointer object); + * void g_object_weak_ref (GObject *object, + * GWeakNotify notify, + * gpointer data); + * [...] + * + * La fonction g_object_unref() débute bien par exemple par une validation + * de l'instance, avec un appel à : g_return_if_fail (G_IS_OBJECT (object)). + * + * Cependant, cette vérification est désactivée en cas de compilation de GLib + * avec G_DISABLE_CHECKS. + * + * Une conversion vers un type donné (par exemple avec G_OBJECT()) est par + * ailleurs dépendante d'autres paramètres de compilation, comme le révèle + * le fichier <glib-2.80>/gobject/gtype.h : + * + * #if defined(G_DISABLE_CAST_CHECKS) || defined(__OPTIMIZE__) + * # define _G_TYPE_CIC(ip, gt, ct) ((ct*) (void *) ip) + * # define _G_TYPE_CCC(cp, gt, ct) ((ct*) (void *) cp) + * #else + * # define _G_TYPE_CIC(ip, gt, ct) \ + * ((ct*) (void *) g_type_check_instance_cast ((GTypeInstance*) ip, gt)) + * # define _G_TYPE_CCC(cp, gt, ct) \ + * ((ct*) (void *) g_type_check_class_cast ((GTypeClass*) cp, gt)) + * #endif + * + * Afin d'assurer des conditions de débogage/fuzzing optimales dans tous les + * cas de figure, les fonctions de manipulation des références font l'objet + * ici d'une couche intermédiaire pour les appels. + */ + +#ifndef NDEBUG + +# define ref_object(ip) \ + do \ + { \ + GTypeInstance *__inst; \ + __inst = g_type_check_instance_cast((GTypeInstance *)ip, G_TYPE_OBJECT); \ + assert(__inst != NULL); \ + g_object_ref(ip); \ + } \ + while (0); + +# define unref_object(ip) \ + do \ + { \ + GTypeInstance *__inst; \ + __inst = g_type_check_instance_cast((GTypeInstance *)ip, G_TYPE_OBJECT); \ + assert(__inst != NULL); \ + g_object_unref(ip); \ + } \ + while (0); + +#else + +# define ref_object(p) g_object_ref(p) +# define unref_object(p) g_object_unref(p) + +#endif + + +#endif /* _GLIBEXT_HELPERS_H */ |