summaryrefslogtreecommitdiff
path: root/src/glibext
diff options
context:
space:
mode:
Diffstat (limited to 'src/glibext')
-rw-r--r--src/glibext/Makefile.am12
-rw-r--r--src/glibext/bufferline.c334
-rw-r--r--src/glibext/bufferline.h14
-rw-r--r--src/glibext/comparable.c18
-rw-r--r--src/glibext/helpers.h28
-rw-r--r--src/glibext/log-int.h58
-rw-r--r--src/glibext/log.c306
-rw-r--r--src/glibext/log.h43
-rw-r--r--src/glibext/objhole-int.h33
-rw-r--r--src/glibext/objhole.c85
-rw-r--r--src/glibext/objhole.h16
-rw-r--r--src/glibext/options/Makefile.am3
-rw-r--r--src/glibext/options/asm.h65
-rw-r--r--src/glibext/secstorage.c4
-rw-r--r--src/glibext/serialize-int.h54
-rw-r--r--src/glibext/serialize.c113
-rw-r--r--src/glibext/serialize.h52
-rw-r--r--src/glibext/sigredir.c (renamed from src/glibext/signal.c)159
-rw-r--r--src/glibext/sigredir.h (renamed from src/glibext/_signal.h)21
-rw-r--r--src/glibext/singleton.c6
-rw-r--r--src/glibext/storage-int.h75
-rw-r--r--src/glibext/storage.c1147
-rw-r--r--src/glibext/storage.h81
-rw-r--r--src/glibext/tpmem-int.h78
-rw-r--r--src/glibext/tpmem.c363
-rw-r--r--src/glibext/tpmem.h57
-rw-r--r--src/glibext/widthtracker.c8
27 files changed, 2971 insertions, 262 deletions
diff --git a/src/glibext/Makefile.am b/src/glibext/Makefile.am
index 81d13d2..b0a7c31 100644
--- a/src/glibext/Makefile.am
+++ b/src/glibext/Makefile.am
@@ -14,7 +14,6 @@ noinst_LTLIBRARIES = libglibext.la libglibextui.la
# \
# proto.h \
# seq.h seq.c \
-# _signal.h signal.c \
# singleton.h singleton.c \
# linetoken.h linetoken.c \
# umemslice-int.h \
@@ -43,16 +42,25 @@ libglibext_la_SOURCES = \
hashable-int.h \
hashable.h hashable.c \
helpers.h \
+ log-int.h \
+ log.h log.c \
objhole-int.h \
objhole.h objhole.c \
portion-int.h \
portion.h portion.c \
secstorage-int.h \
secstorage.h secstorage.c \
+ serialize-int.h \
+ serialize.h serialize.c \
+ sigredir.h sigredir.c \
singleton-int.h \
singleton.h singleton.c \
+ storage-int.h \
+ storage.h storage.c \
strbuilder-int.h \
strbuilder.h strbuilder.c \
+ tpmem-int.h \
+ tpmem.h tpmem.c \
work-int.h \
work.h work.c \
workgroup-int.h \
@@ -60,7 +68,7 @@ libglibext_la_SOURCES = \
workqueue-int.h \
workqueue.h workqueue.c
-libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS)
+libglibext_la_CFLAGS = $(TOOLKIT_CFLAGS) $(LIBZIP_CFLAGS)
RES_FILES = \
diff --git a/src/glibext/bufferline.c b/src/glibext/bufferline.c
index 4862e9f..e3fb27b 100644
--- a/src/glibext/bufferline.c
+++ b/src/glibext/bufferline.c
@@ -24,14 +24,16 @@
#include "bufferline.h"
+#include <assert.h>
+#include <malloc.h>
+
+
#include "bufferline-int.h"
#if 0
-#include <assert.h>
-#include <malloc.h>
#include <string.h>
@@ -273,158 +275,12 @@ bool g_buffer_line_create(GBufferLine *line, size_t col_count)
}
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne à venir compléter. *
-* column = colonne de la ligne visée par l'insertion. *
-* tag = type de décorateur à utiliser. *
-* text = texte à insérer dans l'existant. *
-* length = taille du texte à traiter. *
-* style = gestionnaire de paramètres de rendu à consulter. *
-* creator = instance GLib quelconque à associer. *
-* *
-* Description : Ajoute du texte à formater dans une ligne donnée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator)
-{
- size_t index; /* Indice d'insertion */
- //content_origin *origin; /* Définition d'une origine */
-
- assert(column < line->col_count);
- assert(length > 0);
-
- index = append_text_to_line_column(&line->columns[column], tag, text, length, style);
-
- /*
- if (creator != NULL)
- {
- line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
-
- origin = &line->origins[line->ocount - 1];
-
- origin->coord.column = column;
- origin->coord.index = index;
-
- origin->creator = creator;
- g_object_ref(G_OBJECT(creator));
-
- }
- */
-
-}
-
-
-
-
-
-
-
-
-
-
-
-/******************************************************************************
-* *
-* Paramètres : line = ligne de texte à manipuler. *
-* cr = contexte graphique dédié à la procédure. *
-* column = (première) colonne à traiter. *
-* y = ordonnée du point d'impression. *
-* style = style de rendu pour les bribes de texte. *
-* *
-* Description : Imprime la ligne de texte représentée. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style)
-{
-#if 0
- GBufferLineClass *class; /* Stockage de briques de base */
- bool has_src_surface; /* Note une présence définie */
-#endif
- size_t max_column; /* Borne de fin des colonnes */
- int x; /* Point de départ d'impression*/
- size_t i; /* Boucle de parcours */
-
- /*
- if (line->flags != BLF_NONE)
- {
- class = G_BUFFER_LINE_GET_CLASS(line);
-
- if (line->flags & BLF_ENTRYPOINT)
- {
- cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
- has_src_surface = true;
- }
- else if (line->flags & BLF_BOOKMARK)
- {
- cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
- has_src_surface = true;
- }
- else
- has_src_surface = false;
-
- if (has_src_surface)
- cairo_paint(cairo);
-
- }
- */
-
-
- /* Détermination de l'éventail des colonnes à traiter */
-
- if (column == line->merge_start)
- max_column = line->col_count;
-
- else if (column > line->merge_start)
- max_column = 0;
-
- else
- max_column = column + 1;
-
- /* Dessin du contenu de ces colonnes */
-
- x = 0;
-
- for (i = column; i < max_column; i++)
- draw_line_column(&line->columns[i], cr, &x, y, style);
-
-}
-
-
-
-
-
-
-
-
-
-
-#if 0
-
-
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation physique à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation physique à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -434,7 +290,7 @@ void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int
* *
******************************************************************************/
-void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_physical(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -448,20 +304,22 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
if (i == len)
i = len - 1;
+ assert(column < line->col_count);
+
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_PHYS_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_PHYS_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_PHYS_ADDR, &position[i], len - i, NULL, NULL);
}
/******************************************************************************
* *
-* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
-* size = taille souhaitée de l'impression des positions. *
-* addr = localisation virtuelle à venir représenter. *
+* Paramètres : line = ligne à venir compléter. *
+* column = indice de la colonne visée par l'insertion. *
+* size = taille souhaitée de l'impression des positions. *
+* addr = localisation virtuelle à venir représenter. *
* *
* Description : Construit le tronc commun d'une ligne autour de sa position. *
* *
@@ -471,7 +329,7 @@ void g_buffer_line_fill_phys(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size, const vmpa2t *addr)
+void g_buffer_line_fill_virtual(GBufferLine *line, size_t column, MemoryDataSize size, const vmpa2t *addr)
{
VMPA_BUFFER(position); /* Emplacement au format texte */
size_t len; /* Taille de l'élément inséré */
@@ -479,6 +337,8 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
vmpa2_virt_to_string(addr, size, position, &len);
+ assert(column < line->col_count);
+
if (has_virt_addr(addr))
{
for (i = 2; i < len; i++)
@@ -488,14 +348,14 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
i = len - 1;
if (i > 0)
- g_buffer_line_append_text(line, col, position, i, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, i, NULL, NULL);
- g_buffer_line_append_text(line, col, &position[i], len - i, RTT_VIRT_ADDR, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR, &position[i], len - i, NULL, NULL);
}
else
- g_buffer_line_append_text(line, col, position, len, RTT_VIRT_ADDR_PAD, NULL);
+ g_buffer_line_append_text(line, column, TRT_VIRT_ADDR_PAD, position, len, NULL, NULL);
}
@@ -503,7 +363,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
/******************************************************************************
* *
* Paramètres : line = ligne à venir compléter. *
-* col = indice de la colonne à constituer. *
+* column = indice de la colonne visée par l'insertion. *
* content = contenu binaire global à venir lire. *
* range = localisation des données à venir lire et présenter.*
* max = taille maximale de la portion binaire en octets. *
@@ -516,7 +376,7 @@ void g_buffer_line_fill_virt(GBufferLine *line, size_t col, MemoryDataSize size,
* *
******************************************************************************/
-void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent *content, const mrange_t *range, phys_t max)
+void g_buffer_line_fill_content(GBufferLine *line, size_t column, const GBinContent *content, const mrange_t *range, phys_t max)
{
phys_t length; /* Taille de la couverture */
bool truncated; /* Indique si le code est coupé*/
@@ -548,7 +408,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
if (required <= sizeof(static_buffer))
bin_code = static_buffer;
else
- bin_code = (char *)calloc(required, sizeof(char));
+ bin_code = calloc(required, sizeof(char));
/* Code brut */
@@ -589,7 +449,7 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/* Conclusion */
- g_buffer_line_append_text(line, col, bin_code, iter - bin_code, RTT_RAW_CODE, NULL);
+ g_buffer_line_append_text(line, column, TRT_RAW_CODE, bin_code, iter - bin_code, NULL, NULL);
if (bin_code != static_buffer)
free(bin_code);
@@ -599,6 +459,146 @@ void g_buffer_line_fill_content(GBufferLine *line, size_t col, const GBinContent
/******************************************************************************
* *
+* Paramètres : line = ligne à venir compléter. *
+* column = colonne de la ligne visée par l'insertion. *
+* tag = type de décorateur à utiliser. *
+* text = texte à insérer dans l'existant. *
+* length = taille du texte à traiter. *
+* style = gestionnaire de paramètres de rendu à consulter. *
+* creator = instance GLib quelconque à associer. *
+* *
+* Description : Ajoute du texte à formater dans une ligne donnée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_line_append_text(GBufferLine *line, size_t column, TokenRenderingTag tag, const char *text, size_t length, const GTokenStyle *style, GObject *creator)
+{
+ size_t index; /* Indice d'insertion */
+ //content_origin *origin; /* Définition d'une origine */
+
+ assert(column < line->col_count);
+ assert(length > 0);
+
+ index = append_text_to_line_column(&line->columns[column], tag, text, length, style);
+
+ /*
+ if (creator != NULL)
+ {
+ line->origins = realloc(line->origins, ++line->ocount * sizeof(content_origin));
+
+ origin = &line->origins[line->ocount - 1];
+
+ origin->coord.column = column;
+ origin->coord.index = index;
+
+ origin->creator = creator;
+ g_object_ref(G_OBJECT(creator));
+
+ }
+ */
+
+}
+
+
+
+
+
+
+
+
+
+
+
+/******************************************************************************
+* *
+* Paramètres : line = ligne de texte à manipuler. *
+* cr = contexte graphique dédié à la procédure. *
+* column = (première) colonne à traiter. *
+* y = ordonnée du point d'impression. *
+* style = style de rendu pour les bribes de texte. *
+* *
+* Description : Imprime la ligne de texte représentée. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_buffer_line_draw(const GBufferLine *line, cairo_t *cr, size_t column, int y, const GTokenStyle *style)
+{
+#if 0
+ GBufferLineClass *class; /* Stockage de briques de base */
+ bool has_src_surface; /* Note une présence définie */
+#endif
+ size_t max_column; /* Borne de fin des colonnes */
+ int x; /* Point de départ d'impression*/
+ size_t i; /* Boucle de parcours */
+
+ /*
+ if (line->flags != BLF_NONE)
+ {
+ class = G_BUFFER_LINE_GET_CLASS(line);
+
+ if (line->flags & BLF_ENTRYPOINT)
+ {
+ cairo_set_source_surface(cairo, class->entrypoint_img, 5, y);
+ has_src_surface = true;
+ }
+ else if (line->flags & BLF_BOOKMARK)
+ {
+ cairo_set_source_surface(cairo, class->bookmark_img, 5, y);
+ has_src_surface = true;
+ }
+ else
+ has_src_surface = false;
+
+ if (has_src_surface)
+ cairo_paint(cairo);
+
+ }
+ */
+
+
+ /* Détermination de l'éventail des colonnes à traiter */
+
+ if (column == line->merge_start)
+ max_column = line->col_count;
+
+ else if (column > line->merge_start)
+ max_column = 0;
+
+ else
+ max_column = column + 1;
+
+ /* Dessin du contenu de ces colonnes */
+
+ x = 0;
+
+ for (i = column; i < max_column; i++)
+ draw_line_column(&line->columns[i], cr, &x, y, style);
+
+}
+
+
+
+
+
+
+
+
+
+
+#if 0
+
+
+
+/******************************************************************************
+* *
* Paramètres : line = ligne à venir consulter. *
* column = indice de la colonne visée par les recherches. *
* *
diff --git a/src/glibext/bufferline.h b/src/glibext/bufferline.h
index d6a2e2d..e95ee2b 100644
--- a/src/glibext/bufferline.h
+++ b/src/glibext/bufferline.h
@@ -30,6 +30,8 @@
#include "helpers.h"
#include "tokenstyle.h"
+#include "../arch/vmpa.h"
+#include "../analysis/content.h"
@@ -45,8 +47,6 @@
#ifdef INCLUDE_GTK_SUPPORT
# include "widthtracker.h"
#endif
-#include "../analysis/content.h"
-#include "../arch/vmpa.h"
@@ -75,6 +75,9 @@ typedef struct _GBufferLineClass GBufferLineClass;
+
+
+
#define G_TYPE_BUFFER_LINE (g_buffer_line_get_type())
DECLARE_GTYPE(GBufferLine, g_buffer_line, G, BUFFER_LINE);
@@ -98,7 +101,14 @@ typedef enum _BufferLineFlags
/* Crée une nouvelle représentation de fragments de texte. */
GBufferLine *g_buffer_line_new(size_t);
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_physical(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+
+/* Construit le tronc commun d'une ligne autour de sa position. */
+void g_buffer_line_fill_virtual(GBufferLine *, size_t, MemoryDataSize, const vmpa2t *);
+/* Construit le tronc commun d'une ligne autour de son contenu. */
+void g_buffer_line_fill_content(GBufferLine *, size_t, const GBinContent *, const mrange_t *, phys_t);
/* Ajoute du texte à formater dans une ligne donnée. */
void g_buffer_line_append_text(GBufferLine *, size_t, TokenRenderingTag, const char *, size_t, const GTokenStyle *, GObject *);
diff --git a/src/glibext/comparable.c b/src/glibext/comparable.c
index 95e7de7..40fd110 100644
--- a/src/glibext/comparable.c
+++ b/src/glibext/comparable.c
@@ -25,6 +25,7 @@
#include "comparable-int.h"
+#include "../common/sort.h"
@@ -72,11 +73,24 @@ static void g_comparable_object_default_init(GComparableObjectInterface *iface)
int g_comparable_object_compare(const GComparableObject *object, const GComparableObject *other)
{
int result; /* Bilan à retourner */
+ GType type_a; /* Type de l'object A */
+ GType type_b; /* Type de l'object B */
GComparableObjectInterface *iface; /* Interface utilisée */
- iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
+ type_a = G_OBJECT_TYPE(G_OBJECT(object));
+ type_b = G_OBJECT_TYPE(G_OBJECT(other));
- result = iface->compare(object, other);
+ assert(sizeof(GType) <= sizeof(unsigned long));
+
+ result = sort_unsigned_long(type_a, type_b);
+
+ if (result == 0)
+ {
+ iface = G_COMPARABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->compare(object, other);
+
+ }
return result;
diff --git a/src/glibext/helpers.h b/src/glibext/helpers.h
index cfcc85b..6176245 100644
--- a/src/glibext/helpers.h
+++ b/src/glibext/helpers.h
@@ -29,6 +29,9 @@
#include <glib-object.h>
+#include "../common/compiler.h"
+
+
/**
* Les définitions issues de <glib-2.80>/gobject/gtype.h fournissent des macros
@@ -118,6 +121,31 @@
}
+/**
+ * Définition sous condition d'une inclusion d'interface. Cette inclusion se réalise
+ * lorsque la fonction d'initialisation renseignée est définie.
+ *
+ * Cette version étendue de la macro G_IMPLEMENT_INTERFACE d'origine est principalement
+ * pour les raffinements d'objets en forme graphique.
+ */
+
+#define G_IMPLEMENT_INTERFACE_IF_SYM(iface_tp_getter, iface_init) \
+ do \
+ { \
+ extern GType iface_tp_getter(void) __weak; \
+ extern void iface_init(GTypeInterface *, gpointer) __weak; \
+ if (&iface_tp_getter != NULL && &iface_init != NULL) \
+ { \
+ GType iface_type = iface_tp_getter(); \
+ const GInterfaceInfo implementation_info = { \
+ (GInterfaceInitFunc)(void (*)(void))iface_init, NULL, NULL \
+ }; \
+ g_type_add_interface_static(g_define_type_id, iface_type, &implementation_info);\
+ } \
+ } \
+ while (0);
+
+
/**
* Les principales fonctions incrémentant ou réduisant le nombre de références
diff --git a/src/glibext/log-int.h b/src/glibext/log-int.h
new file mode 100644
index 0000000..3b3208a
--- /dev/null
+++ b/src/glibext/log-int.h
@@ -0,0 +1,58 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log-int.h - prototypes internes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_INT_H
+#define _GLIBEXT_LOG_INT_H
+
+
+#include <stdbool.h>
+
+
+#include "log.h"
+
+
+
+/* Définition d'une conservation d'objets construits (instance) */
+struct _GLogEntry
+{
+ GObject parent; /* A laisser en premier */
+
+ LogMessageType type; /* Type de message porté */
+ char *msg; /* Contenu du message diffusé */
+
+};
+
+/* Définition d'une conservation d'objets construits (classe) */
+struct _GLogEntryClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place une conservation pour élément de journalisation. */
+bool g_log_entry_create(GLogEntry *, LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_INT_H */
diff --git a/src/glibext/log.c b/src/glibext/log.c
new file mode 100644
index 0000000..039172c
--- /dev/null
+++ b/src/glibext/log.c
@@ -0,0 +1,306 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.c - conservation hors mémoire d'objets choisis
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "log.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+#include "log-int.h"
+
+
+
+/* ---------------------------- ENTREE DE JOURNALISATION ---------------------------- */
+
+
+/* Liste des propriétés */
+
+typedef enum _LogEntryProperty {
+
+ PROP_0, /* Réservé */
+
+ PROP_ICON_NAME, /* Nom d'image de représentat° */
+ PROP_MESSAGE, /* Contenu du message diffusé */
+
+ N_PROPERTIES
+
+} LogEntryProperty;
+
+static GParamSpec *_log_entry_properties[N_PROPERTIES] = { NULL, };
+
+
+/* Initialise la classe des conservations d'objets en place. */
+static void g_log_entry_class_init(GLogEntryClass *);
+
+/* Initialise une instance de conservation d'objets en place. */
+static void g_log_entry_init(GLogEntry *);
+
+/* Supprime toutes les références externes. */
+static void g_log_entry_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_log_entry_finalize(GObject *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Fournit la valeur d'une propriété d'instance GObject. */
+static void gtk_log_entry_get_property(GObject *, guint, GValue *, GParamSpec *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* ENTREE DE JOURNALISATION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une conservation d'objets construits. */
+G_DEFINE_TYPE(GLogEntry, g_log_entry, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des conservations d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_class_init(GLogEntryClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_log_entry_dispose;
+ object->finalize = g_log_entry_finalize;
+ object->get_property = gtk_log_entry_get_property;
+
+ _log_entry_properties[PROP_ICON_NAME] =
+ g_param_spec_string("icon-name", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ _log_entry_properties[PROP_MESSAGE] =
+ g_param_spec_string("message", NULL, NULL,
+ NULL,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(object, N_PROPERTIES, _log_entry_properties);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance à initialiser. *
+* *
+* Description : Initialise une instance de conservation d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_init(GLogEntry *entry)
+{
+ entry->type = LMT_COUNT;
+ entry->msg = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_dispose(GObject *object)
+{
+ G_OBJECT_CLASS(g_log_entry_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_log_entry_finalize(GObject *object)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ if (entry->msg != NULL)
+ free(entry->msg);
+
+ G_OBJECT_CLASS(g_log_entry_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Crée une conservation pour un élément de journalisation. *
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GLogEntry *g_log_entry_new(LogMessageType type, const char *msg)
+{
+ GLogEntry *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_LOG_ENTRY, NULL);
+
+ if (!g_log_entry_create(result, type, msg))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : entry = instance de conservation à initialiser pleinement. *
+* type = espèce du message à représenter. *
+* msg = message à faire apparaître à l'écran. *
+* *
+* Description : Met en place une conservation pour élément de journalisation.*
+* *
+* Retour : Conservation mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_log_entry_create(GLogEntry *entry, LogMessageType type, const char *msg)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ entry->type = type;
+ entry->msg = strdup(msg);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à mamnipuler. *
+* prop_id = identifiant de la propriété visée. *
+* value = valeur à transmettre. [OUT] *
+* pspec = définition de la propriété. *
+* *
+* Description : Fournit la valeur d'une propriété d'instance GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_log_entry_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+ GLogEntry *entry; /* Version spécialisée */
+
+ entry = G_LOG_ENTRY(object);
+
+ switch (prop_id)
+ {
+ case PROP_ICON_NAME:
+ switch (entry->type)
+ {
+ case LMT_INFO:
+ g_value_set_string(value, "dialog-information-symbolic");
+ break;
+
+ case LMT_PROCESS:
+ g_value_set_string(value, "system-run-symbolic");
+ break;
+
+ case LMT_WARNING:
+ case LMT_BAD_BINARY:
+ g_value_set_string(value, "dialog-warning-symbolic");
+ break;
+
+ case LMT_ERROR:
+ case LMT_EXT_ERROR:
+ g_value_set_string(value, "computer-fail-symbolic");
+ break;
+
+
+ case LMT_COUNT:
+ g_value_set_string(value, "dialog-question-symbolic");
+ break;
+
+ }
+ break;
+
+ case PROP_MESSAGE:
+ g_value_set_string(value, entry->msg);
+ break;
+
+ }
+
+}
diff --git a/src/glibext/log.h b/src/glibext/log.h
new file mode 100644
index 0000000..472773c
--- /dev/null
+++ b/src/glibext/log.h
@@ -0,0 +1,43 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * log.h - prototypes pour la conservation à destination graphique des éléments de journalisation
+ *
+ * Copyright (C) 2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_LOG_H
+#define _GLIBEXT_LOG_H
+
+
+#include "helpers.h"
+#include "../core/logs.h"
+
+
+
+#define G_TYPE_LOG_ENTRY (g_log_entry_get_type())
+
+DECLARE_GTYPE(GLogEntry, g_log_entry, G, LOG_ENTRY);
+
+
+/* Crée une conservation pour un élément de journalisation. */
+GLogEntry *g_log_entry_new(LogMessageType, const char *);
+
+
+
+#endif /* _GLIBEXT_LOG_H */
diff --git a/src/glibext/objhole-int.h b/src/glibext/objhole-int.h
index b4abf6f..dbfb412 100644
--- a/src/glibext/objhole-int.h
+++ b/src/glibext/objhole-int.h
@@ -105,6 +105,9 @@
#endif
+#define GOBJECT_LOCK_BIT 3
+
+
/* Nouvelle version dense des objets (instance) */
typedef struct _GThickObject
{
@@ -142,23 +145,23 @@ struct _GThickObjectClass
/* GLib 2.83.0 - cfa36f5e9 */
#define GOBJECT_RESERVED_EXTRA_BITS 5
-#define GET_GOBJECT_EXTRA(obj, tp) \
- ({ \
- BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
- tp *___result; \
- guint __val; \
- __val = g_thick_object_get_extra(obj); \
- ___result = (tp *)(guint []){ __val }; \
- ___result; \
+#define GET_GOBJECT_EXTRA(obj, tp) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ tp ___result; \
+ guint __val; \
+ __val = g_thick_object_get_extra(G_THICK_OBJECT(obj)); \
+ ___result = *(tp *)(guint []){ __val }; \
+ ___result; \
})
-#define SET_GOBJECT_EXTRA(obj, tp, data) \
- ({ \
- BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
- BUILD_BUG_ON(sizeof(data) > sizeof(guint *)); \
- guint __val; \
- __val = *(guint *)data; \
- g_thick_object_set_extra(obj, __val); \
+#define SET_GOBJECT_EXTRA(obj, tp, data) \
+ ({ \
+ BUILD_BUG_ON(sizeof(tp) > sizeof(guint)); \
+ BUILD_BUG_ON(sizeof(data) > sizeof(guint *)); \
+ guint __val; \
+ __val = *(guint *)data; \
+ g_thick_object_set_extra(G_THICK_OBJECT(obj), __val); \
})
diff --git a/src/glibext/objhole.c b/src/glibext/objhole.c
index 20bb2a8..fd6fbc9 100644
--- a/src/glibext/objhole.c
+++ b/src/glibext/objhole.c
@@ -38,10 +38,10 @@ static void g_thick_object_class_init(GThickObjectClass *);
static void g_thick_object_init(GThickObject *);
/* Supprime toutes les références externes. */
-static void g_thick_object_dispose(GThickObject *);
+static void g_thick_object_dispose(GObject *);
/* Procède à la libération totale de la mémoire. */
-static void g_thick_object_finalize(GThickObject *);
+static void g_thick_object_finalize(GObject *);
@@ -66,8 +66,8 @@ static void g_thick_object_class_init(GThickObjectClass *klass)
object = G_OBJECT_CLASS(klass);
- object->dispose = (GObjectFinalizeFunc/* ! */)g_thick_object_dispose;
- object->finalize = (GObjectFinalizeFunc)g_thick_object_finalize;
+ object->dispose = g_thick_object_dispose;
+ object->finalize = g_thick_object_finalize;
}
@@ -93,7 +93,7 @@ static void g_thick_object_init(GThickObject *obj)
/******************************************************************************
* *
-* Paramètres : obj = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
@@ -103,16 +103,16 @@ static void g_thick_object_init(GThickObject *obj)
* *
******************************************************************************/
-static void g_thick_object_dispose(GThickObject *obj)
+static void g_thick_object_dispose(GObject *object)
{
- G_OBJECT_CLASS(g_thick_object_parent_class)->dispose(G_OBJECT(obj));
+ G_OBJECT_CLASS(g_thick_object_parent_class)->dispose(object);
}
/******************************************************************************
* *
-* Paramètres : obj = instance d'objet GLib à traiter. *
+* Paramètres : object = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
@@ -122,15 +122,80 @@ static void g_thick_object_dispose(GThickObject *obj)
* *
******************************************************************************/
-static void g_thick_object_finalize(GThickObject *obj)
+static void g_thick_object_finalize(GObject *object)
{
- G_OBJECT_CLASS(g_thick_object_parent_class)->finalize(G_OBJECT(obj));
+ G_OBJECT_CLASS(g_thick_object_parent_class)->finalize(object);
}
/******************************************************************************
* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Pose un verrou à l'aide du bit dédié de GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_lock(GThickObject *obj)
+{
+ g_bit_lock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Retire un verrou via le bit dédié de GObject. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_thick_object_unlock(GThickObject *obj)
+{
+ g_bit_unlock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : obj = instance d'objet GLib à manipuler. *
+* *
+* Description : Vérifie qu'un verrou est appliqué à l'aide du bit de GObject.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+#ifndef NDEBUG
+bool g_thick_object_check_lock(GThickObject *obj)
+{
+ bool result; /* Bilan à retourner */
+ gboolean status; /* Bilan d'une tentative */
+
+ status = g_bit_trylock((gint *)&obj->extra, GOBJECT_LOCK_BIT);
+
+ result = (status == FALSE);
+
+ return result;
+
+}
+#endif
+
+
+/******************************************************************************
+* *
* Paramètres : obj = instance d'objet GLib à consulter. *
* *
* Description : Fournit la valeur courante de la zone de stockage d'un objet.*
diff --git a/src/glibext/objhole.h b/src/glibext/objhole.h
index c1e8cf1..461c37a 100644
--- a/src/glibext/objhole.h
+++ b/src/glibext/objhole.h
@@ -25,6 +25,11 @@
#define _GLIBEXT_OBJHOLE_H
+#ifndef NDEBUG
+# include <stdbool.h>
+#endif
+
+
#include "../glibext/helpers.h"
@@ -34,6 +39,17 @@
DECLARE_GTYPE(GThickObject, g_thick_object, G, THICK_OBJECT);
+/* Pose un verrou à l'aide du bit dédié de GObject. */
+void g_thick_object_lock(GThickObject *);
+
+/* Retire un verrou via le bit dédié de GObject. */
+void g_thick_object_unlock(GThickObject *);
+
+/* Vérifie qu'un verrou est appliqué à l'aide du bit de GObject. */
+#ifndef NDEBUG
+bool g_thick_object_check_lock(GThickObject *obj);
+#endif
+
/* Fournit la valeur courante de la zone de stockage d'un objet. */
guint g_thick_object_get_extra(const GThickObject *);
diff --git a/src/glibext/options/Makefile.am b/src/glibext/options/Makefile.am
index 448de7b..3f400c6 100644
--- a/src/glibext/options/Makefile.am
+++ b/src/glibext/options/Makefile.am
@@ -2,7 +2,8 @@
noinst_LTLIBRARIES = libglibextoptions.la
-libglibextoptions_la_SOURCES = \
+libglibextoptions_la_SOURCES = \
+ asm.h \
hex.h hex.c
libglibextoptions_la_CFLAGS = $(TOOLKIT_CFLAGS)
diff --git a/src/glibext/options/asm.h b/src/glibext/options/asm.h
new file mode 100644
index 0000000..d7a2c86
--- /dev/null
+++ b/src/glibext/options/asm.h
@@ -0,0 +1,65 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * asm.h - prototypes pour les options de rendus de code désassemblé
+ *
+ * Copyright (C) 2025 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_OPTIONS_ASM_H
+#define _GLIBEXT_OPTIONS_ASM_H
+
+
+#include "../helpers.h"
+
+
+
+/* Liste des colonnes en options */
+typedef enum _DisassColumnOptions
+{
+ ACO_PHYSICAL, /* Position physique */
+ ACO_VIRTUAL, /* Adresse virtuelle */
+ ACO_BINARY, /* Contenu sous forme binaire */
+
+ ACO_COUNT
+
+} DisassColumnOptions;
+
+
+#define ACO_ASSEMBLY_LABEL (ACO_COUNT + 0) /* Etiquette dans les données */
+#define ACO_ASSEMBLY_HEAD (ACO_COUNT + 1) /* Instruction pour assembleur */
+#define ACO_ASSEMBLY (ACO_COUNT + 2) /* Code pour assembleur */
+#define ACO_COMMENTS (ACO_COUNT + 3) /* Commentaires éventuels */
+
+
+
+
+
+
+#if 0
+#define G_TYPE_HEX_OPTIONS (g_hex_options_get_type())
+
+DECLARE_GTYPE(GHexOptions, g_hex_options, G, HEX_OPTIONS);
+
+
+/* Crée un groupe d'options pour le rendu d'hexadécimal. */
+GHexOptions *g_hex_options_new(void);
+#endif
+
+
+#endif /* _GLIBEXT_OPTIONS_HEX_H */
diff --git a/src/glibext/secstorage.c b/src/glibext/secstorage.c
index b118aa6..161214c 100644
--- a/src/glibext/secstorage.c
+++ b/src/glibext/secstorage.c
@@ -160,7 +160,7 @@ static void g_secret_storage_init(GSecretStorage *storage)
static void g_secret_storage_dispose(GObject *object)
{
- GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+ GSecretStorage *storage; /* Version spécialisée */
storage = G_SECRET_STORAGE(object);
@@ -185,7 +185,7 @@ static void g_secret_storage_dispose(GObject *object)
static void g_secret_storage_finalize(GObject *object)
{
- GSecretStorage *storage; /* Gestion de stockage sécurisé*/
+ GSecretStorage *storage; /* Version spécialisée */
storage = G_SECRET_STORAGE(object);
diff --git a/src/glibext/serialize-int.h b/src/glibext/serialize-int.h
new file mode 100644
index 0000000..df9c597
--- /dev/null
+++ b/src/glibext/serialize-int.h
@@ -0,0 +1,54 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * serialize-int.h - définitions internes propres aux objets entreposables dans un cache
+ *
+ * Copyright (C) 2020-2025 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_SERIALIZE_INT_H
+#define _GLIBEXT_SERIALIZE_INT_H
+
+
+#include "serialize.h"
+
+
+#include "storage.h"
+
+
+
+/* Charge un objet depuis une mémoire tampon. */
+typedef bool (* load_serializable_object_cb) (GSerializableObject *, GObjectStorage *, int);
+
+/* Sauvegarde un objet dans une mémoire tampon. */
+typedef bool (* store_serializable_object_cb) (const GSerializableObject *, GObjectStorage *, int);
+
+
+/* Intermédiaire pour la mise en cache d'objet (interface) */
+struct _GSerializableObjectInterface
+{
+ GTypeInterface base_iface; /* A laisser en premier */
+
+ load_serializable_object_cb load; /* Chargement */
+ store_serializable_object_cb store; /* Enregistrement */
+
+};
+
+
+
+#endif /* _GLIBEXT_SERIALIZE_INT_H */
diff --git a/src/glibext/serialize.c b/src/glibext/serialize.c
new file mode 100644
index 0000000..b43f0c2
--- /dev/null
+++ b/src/glibext/serialize.c
@@ -0,0 +1,113 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * serialize.h - objets entreposables dans un cache
+ *
+ * Copyright (C) 2020-2025 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/>.
+ */
+
+
+#include "serialize.h"
+
+
+#include "serialize-int.h"
+
+
+
+/* Procède à l'initialisation de l'interface de mise en cache. */
+static void g_serializable_object_default_init(GSerializableObjectInterface *);
+
+
+
+/* Détermine le type d'une interface pour la mise en cache d'objet. */
+G_DEFINE_INTERFACE(GSerializableObject, g_serializable_object, G_TYPE_OBJECT)
+
+
+/******************************************************************************
+* *
+* Paramètres : iface = interface GLib à initialiser. *
+* *
+* Description : Procède à l'initialisation de l'interface de mise en cache. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_serializable_object_default_init(GSerializableObjectInterface *iface)
+{
+ iface->load = NULL;
+ iface->store = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = élément GLib à constuire. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en lecture. *
+* *
+* Description : Charge un objet depuis un flux de données. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_serializable_object_load(GSerializableObject *object, GObjectStorage *storage, int fd)
+{
+ bool result; /* Bilan à retourner */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->load(object, storage, fd);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = élément GLib à consulter. *
+* storage = conservateur de données à manipuler. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Sauvegarde un objet dans un flux de données. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_serializable_object_store(const GSerializableObject *object, GObjectStorage *storage, int fd)
+{
+ bool result; /* Bilan à retourner */
+ GSerializableObjectInterface *iface; /* Interface utilisée */
+
+ iface = G_SERIALIZABLE_OBJECT_GET_IFACE(object);
+
+ result = iface->store(object, storage, fd);
+
+ return result;
+
+}
diff --git a/src/glibext/serialize.h b/src/glibext/serialize.h
new file mode 100644
index 0000000..c95ac30
--- /dev/null
+++ b/src/glibext/serialize.h
@@ -0,0 +1,52 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * serialize.h - prototypes pour les objets entreposables dans un cache
+ *
+ * Copyright (C) 2020-2025 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_SERIALIZE_H
+#define _GLIBEXT_SERIALIZE_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_SERIALIZABLE_OBJECT (g_serializable_object_get_type())
+
+DECLARE_INTERFACE(GSerializableObject, g_serializable_object, G, SERIALIZABLE_OBJECT);
+
+
+/* storage.h : définition d'une conservation d'objets construits */
+typedef struct _GObjectStorage GObjectStorage;
+
+
+/* Charge un objet depuis un flux de données. */
+bool g_serializable_object_load(GSerializableObject *, GObjectStorage *, int);
+
+/* Sauvegarde un objet dans un flux de données. */
+bool g_serializable_object_store(const GSerializableObject *, GObjectStorage *, int);
+
+
+
+#endif /* _GLIBEXT_SERIALIZE_H */
diff --git a/src/glibext/signal.c b/src/glibext/sigredir.c
index 33290fb..67e8563 100644
--- a/src/glibext/signal.c
+++ b/src/glibext/sigredir.c
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.c - encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,49 +21,55 @@
*/
-#include "signal.h"
+#include "sigredir.h"
#include <assert.h>
#include <malloc.h>
#include <stdarg.h>
#include <stdbool.h>
+#include <gobject/gclosure.h>
#include <gobject/gvaluecollector.h>
-/* Prototype pour le transfert d'exécution. */
-typedef void (* GSignalCallback) (gpointer, ...);
+/* Informations utiles à l'appel final */
+typedef struct _gsignal_wrapper_params_t
+{
+ GClosure *closure; /* Glue pour les appels */
+
+ guint n_params; /* Nombre de paramètres */
+ GValue instance_and_params[0]; /* Instance & paramètres */
+
+} gsignal_wrapper_params_t;
+
+/* Transmet un signal dans le contexte principal. */
+static gboolean to_main_wrapper(gpointer);
+/* Supprime de la mémoire le transporteur d'informations. */
+static void destroy_wrapper_params(gpointer);
/* Informations concernant une diffusion de signal */
-typedef struct _gsignal_wrapper_info
+typedef struct _gsignal_wrapper_info_t
{
gpointer instance; /* Instance GLib initiatrice */
+ gulong id; /* Identifiant de connexion */
GClosure *closure; /* Glue pour les appels */
- GType return_type; /* Type de la valeur retournée */
guint n_params; /* Nombre de paramètres */
- const GType *param_types; /* Type des paramètres associés*/
+ GType param_types[0]; /* Type des paramètres associés*/
- GValue return_value; /* Valeur de retour */
- GValue instance_and_params[0]; /* Instance & paramètres */
-
-} gsignal_wrapper_info;
-
-
-/* Transmet un signal dans le contexte principal. */
-static gboolean to_main_wrapper(gsignal_wrapper_info *);
+} gsignal_wrapper_info_t;
/* Réceptionne un signal et redirige son exécution. */
-static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *, ...);
/******************************************************************************
* *
-* Paramètres : info = collecteur d'informations sur la diffusion. *
+* Paramètres : data = collecteur d'informations sur la diffusion. *
* *
* Description : Transmet un signal dans le contexte principal. *
* *
@@ -73,11 +79,17 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *, ...);
* *
******************************************************************************/
-static gboolean to_main_wrapper(gsignal_wrapper_info *info)
+static gboolean to_main_wrapper(gpointer data)
{
- g_closure_invoke(info->closure, NULL/*&info->return_value*/,
- info->n_params + 1, info->instance_and_params,
- NULL);
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_invoke(params->closure,
+ NULL /* return_value */,
+ params->n_params + 1,
+ params->instance_and_params,
+ NULL /* invocation_hint */);
return G_SOURCE_REMOVE;
@@ -86,6 +98,35 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
/******************************************************************************
* *
+* Paramètres : data = collecteur d'informations à supprimer. *
+* *
+* Description : Supprime de la mémoire le transporteur d'informations. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void destroy_wrapper_params(gpointer data)
+{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
+ guint i; /* Boucle de parcours */
+
+ params = (gsignal_wrapper_params_t *)data;
+
+ g_closure_unref(params->closure);
+
+ for (i = 0; i < (params->n_params + 1); i++)
+ g_value_unset(params->instance_and_params + i);
+
+ free(params);
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : info = collecteur d'informations sur la diffusion. *
* ... = arguments poussés par la GLib sur la pile. *
* *
@@ -97,23 +138,26 @@ static gboolean to_main_wrapper(gsignal_wrapper_info *info)
* *
******************************************************************************/
-static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
+static void carry_signal_to_main_thread(gsignal_wrapper_info_t *info, ...)
{
+ gsignal_wrapper_params_t *params; /* Informations d'appel */
GValue *param_values; /* Paramètres d'appel */
va_list ap; /* Liste d'arguments sur pile */
guint i; /* Boucle de parcours */
bool static_scope; /* Portée des arguments */
gchar *error; /* Eventuelle erreur inattendue*/
- //g_value_init(&info->return_value, info->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE);
+ params = calloc(1, sizeof(gsignal_wrapper_params_t) + sizeof(GValue) * (info->n_params + 1));
+
+ params->closure = info->closure;
+ g_closure_ref(info->closure);
- if (G_IS_VALUE(info->instance_and_params))
- g_value_unset(info->instance_and_params);
+ params->n_params = info->n_params;
- g_value_init(info->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
- g_value_set_instance(info->instance_and_params, info->instance);
+ g_value_init(params->instance_and_params, G_TYPE_FROM_INSTANCE(info->instance));
+ g_value_set_instance(params->instance_and_params, info->instance);
- param_values = info->instance_and_params + 1;
+ param_values = params->instance_and_params + 1;
va_start(ap, info);
@@ -121,9 +165,6 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
for (i = 0; i < info->n_params; i++)
{
- if (G_IS_VALUE(param_values + i))
- g_value_unset(param_values + i);
-
static_scope = info->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
G_VALUE_COLLECT_INIT(param_values + i,
@@ -143,7 +184,28 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
va_end(ap);
if (error == NULL)
- g_idle_add_full(G_PRIORITY_HIGH_IDLE, (GSourceFunc)to_main_wrapper, info, NULL);
+ g_idle_add_full(G_PRIORITY_HIGH_IDLE, to_main_wrapper, params, destroy_wrapper_params);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : info = collecteur d'informations à supprimer. *
+* *
+* Description : Déconnecte un signal redirigé vers le contexte principal. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *info)
+{
+ g_signal_handler_disconnect(info->instance, info->id);
+
+ free(info);
}
@@ -165,41 +227,44 @@ static void carry_signal_to_main_thread(gsignal_wrapper_info *info, ...)
* *
******************************************************************************/
-gulong _g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer instance, const gchar *signal, GCallback handler, gpointer data, GClosureMarshal marshal, GConnectFlags flags)
{
+ gsignal_wrapper_info_t *result; /* Structure à renvoyer */
guint signal_id; /* Identifiant du signal visé */
GSignalQuery query; /* Information sur le signal */
- gsignal_wrapper_info *info; /* Encapsulation des données */
/* Collection d'informations */
signal_id = g_signal_lookup(signal, G_TYPE_FROM_INSTANCE(instance));
g_signal_query(signal_id, &query);
+
assert(query.signal_id != 0);
+ assert(query.return_type == G_TYPE_NONE);
/* Allocation adaptée */
- info = calloc(1, sizeof(gsignal_wrapper_info) + sizeof(GValue) * (query.n_params + 1));
+ result = malloc(sizeof(gsignal_wrapper_info_t) + sizeof(GType) * query.n_params);
- info->instance = instance;
+ result->instance = instance;
if (flags & G_CONNECT_SWAPPED)
- info->closure = g_cclosure_new_swap(handler, data, NULL);
+ result->closure = g_cclosure_new_swap(handler, data, NULL);
else
- info->closure = g_cclosure_new(handler, data, NULL);
+ result->closure = g_cclosure_new(handler, data, NULL);
- g_closure_ref(info->closure);
- g_closure_sink(info->closure);
+ g_closure_ref(result->closure);
+ g_closure_sink(result->closure);
- g_closure_set_marshal(info->closure, marshal);
+ g_closure_set_marshal(result->closure, marshal);
- info->return_type = query.return_type;
- info->n_params = query.n_params;
- info->param_types = query.param_types;
+ result->n_params = query.n_params;
+ memcpy(result->param_types, query.param_types, sizeof(GType) * query.n_params);
- assert(query.return_type == G_TYPE_NONE);
+ /* Connexion au signal */
+
+ result->id = g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), result);
- return g_signal_connect_swapped(instance, signal, G_CALLBACK(carry_signal_to_main_thread), info);
+ return result;
}
diff --git a/src/glibext/_signal.h b/src/glibext/sigredir.h
index 4f0ab4b..f394d77 100644
--- a/src/glibext/_signal.h
+++ b/src/glibext/sigredir.h
@@ -1,8 +1,8 @@
/* Chrysalide - Outil d'analyse de fichiers binaires
- * signal.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
+ * sigredir.h - prototypes pour un encadrement des signaux supplémentaire par rapport à celui de la GLib
*
- * Copyright (C) 2014-2018 Cyrille Bagard
+ * Copyright (C) 2014-2025 Cyrille Bagard
*
* This file is part of Chrysalide.
*
@@ -21,20 +21,23 @@
*/
-#ifndef _GLIBEXT_SIGNAL_H
-#define _GLIBEXT_SIGNAL_H
+#ifndef _GLIBEXT_SIGREDIR_H
+#define _GLIBEXT_SIGREDIR_H
#include <glib-object.h>
-#include <gobject/gclosure.h>
-#include <glib/gdataset.h>
-#include <glib/glist.h>
#include <gobject/gsignal.h>
+/* Informations concernant une diffusion de signal */
+typedef struct _gsignal_wrapper_info_t gsignal_wrapper_info_t;
+
/* Reproduit le comportement de la fonction g_signal_connect(). */
-gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+gsignal_wrapper_info_t *_g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, GClosureMarshal, GConnectFlags);
+
+/* Déconnecte un signal redirigé vers le contexte principal. */
+void g_signal_disconnect_from_main(gsignal_wrapper_info_t *);
#define g_signal_connect_to_main(instance, signal, handler, data, marshal) \
@@ -45,4 +48,4 @@ gulong _g_signal_connect_to_main(gpointer, const gchar *, GCallback, gpointer, G
-#endif /* _GLIBEXT_SIGNAL_H */
+#endif /* _GLIBEXT_SIGREDIR_H */
diff --git a/src/glibext/singleton.c b/src/glibext/singleton.c
index 0a50d19..ed49934 100644
--- a/src/glibext/singleton.c
+++ b/src/glibext/singleton.c
@@ -74,9 +74,9 @@ static void g_singleton_factory_finalize(GSingletonFactory *);
/* Détermine le type d'une interface pour la constitution d'objets uniques. */
-G_DEFINE_INTERFACE_WITH_CODE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT,
- g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_HASHABLE_OBJECT);
- g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_COMPARABLE_OBJECT))
+G_DEFINE_INTERFACE_WITH_CODE(GSingletonCandidate, g_singleton_candidate, G_TYPE_OBJECT,;
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_COMPARABLE_OBJECT);
+ g_type_interface_add_prerequisite(g_define_type_id, G_TYPE_HASHABLE_OBJECT))
/******************************************************************************
diff --git a/src/glibext/storage-int.h b/src/glibext/storage-int.h
new file mode 100644
index 0000000..d89e1c8
--- /dev/null
+++ b/src/glibext/storage-int.h
@@ -0,0 +1,75 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * storage-int.h - prototypes internes pour la conservation sur disque d'objets construits
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_STORAGE_INT_H
+#define _GLIBEXT_STORAGE_INT_H
+
+
+#include "storage.h"
+#include "tpmem.h"
+#include "../common/szbin.h"
+
+
+
+/* Gestion d'enregistrements spécifiques */
+typedef struct _storage_backend_t
+{
+ char *name; /* Désignation du groupe */
+
+ char *filename; /* Nom du fichier associé */
+ int fd; /* Flux d'accès correspondant */
+
+} storage_backend_t;
+
+/* Définition d'une conservation d'objets construits (instance) */
+struct _GObjectStorage
+{
+ GObject parent; /* A laisser en premier */
+
+ sized_binary_t type; /* Type de conservation */
+ uint8_t version; /* Version correspondante */
+
+ sized_binary_t uid; /* Identifiant de distinction */
+
+ GTypeMemory *tpmem; /* Mémorisation de types */
+
+ storage_backend_t *backends; /* Gestionnaires existants */
+ size_t count; /* Quantité de gestionnaires */
+ GMutex mutex; /* Contrôle d'accès à la liste */
+
+};
+
+/* Définition d'une conservation d'objets construits (classe) */
+struct _GObjectStorageClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Met en place un support d'une conservation d'objets en place. */
+bool g_object_storage_create(GObjectStorage *, const char *, uint8_t, const char *);
+
+
+
+#endif /* _GLIBEXT_STORAGE_INT_H */
diff --git a/src/glibext/storage.c b/src/glibext/storage.c
new file mode 100644
index 0000000..0a3c4e7
--- /dev/null
+++ b/src/glibext/storage.c
@@ -0,0 +1,1147 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * storage.c - conservation hors mémoire d'objets choisis
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "storage.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <string.h>
+#include <unistd.h>
+#include <zip.h>
+
+
+#include "storage-int.h"
+#include "../common/cpp.h"
+#include "../common/pathname.h"
+#include "../core/logs.h"
+
+
+/**
+ * Historique du format :
+ *
+ * - 09/03/25 : 1.0 (version initiale)
+ *
+ */
+#define STORAGE_MAGIC "COBSTR"
+#define STORAGE_NUMBER "\x01\x00"
+
+
+/* Initialise la classe des conservations d'objets en place. */
+static void g_object_storage_class_init(GObjectStorageClass *);
+
+/* Initialise une instance de conservation d'objets en place. */
+static void g_object_storage_init(GObjectStorage *);
+
+/* Supprime toutes les références externes. */
+static void g_object_storage_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_object_storage_finalize(GObject *);
+
+/* Assure l'inexistence d'un groupe avec un nom donné. */
+static bool g_object_storage_has_no_backend_named(GObjectStorage *, const char *);
+
+/* Retrouve l'encadrement pour un nouveau groupe d'objets. */
+static storage_backend_t *g_object_storage_find_backend(GObjectStorage *, const char *);
+
+/* Ajoute le support d'un nouveau groupe d'objets construits. */
+static bool g_object_storage_add_backend(GObjectStorage *, const char *, storage_backend_t **);
+
+/* Charge un objet à partir de données rassemblées. */
+static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *, const char *, off64_t);
+
+
+
+/* Indique le type défini pour une conservation d'objets construits. */
+G_DEFINE_TYPE(GObjectStorage, g_object_storage, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des conservations d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_storage_class_init(GObjectStorageClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_object_storage_dispose;
+ object->finalize = g_object_storage_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = instance à initialiser. *
+* *
+* Description : Initialise une instance de conservation d'objets en place. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_storage_init(GObjectStorage *storage)
+{
+ init_sized_binary(&storage->type);
+ storage->version = 0;
+
+ init_sized_binary(&storage->uid);
+
+ storage->tpmem = g_type_memory_new();
+
+ storage->backends = NULL;
+ storage->count = 0;
+ g_mutex_init(&storage->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_storage_dispose(GObject *object)
+{
+ GObjectStorage *storage; /* Version spécialisée */
+
+ storage = G_OBJECT_STORAGE(object);
+
+ g_clear_object(&storage->tpmem);
+
+ G_OBJECT_CLASS(g_object_storage_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_object_storage_finalize(GObject *object)
+{
+ GObjectStorage *storage; /* Version spécialisée */
+ size_t i; /* Boucle de parcours */
+ storage_backend_t *backend; /* Gestionnaire à manipuler */
+ int ret; /* Bilan d'un appel */
+
+ storage = G_OBJECT_STORAGE(object);
+
+ g_mutex_lock(&storage->mutex);
+
+ for (i = 0; i < storage->count; i++)
+ {
+ backend = &storage->backends[i];
+
+ /**
+ * Chargement incomplet depuis g_object_storage_load().
+ */
+ if (backend->name == NULL)
+ break;
+
+ if (backend->fd != -1)
+ close(backend->fd);
+ else
+ assert(false);
+
+ ret = access(backend->filename, W_OK);
+ if (ret == 0)
+ {
+ ret = unlink(backend->filename);
+ if (ret != 0) LOG_ERROR_N("unlink");
+ }
+
+ free(backend->name);
+
+ free(backend->filename);
+
+ }
+
+ if (storage->backends != NULL)
+ free(storage->backends);
+
+ g_mutex_unlock(&storage->mutex);
+
+ g_mutex_clear(&storage->mutex);
+
+ exit_sized_binary(&storage->type);
+
+ exit_sized_binary(&storage->uid);
+
+ G_OBJECT_CLASS(g_object_storage_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type global à indiquer dans une conservation. *
+* version = numéro de version associé. *
+* uid = identifiant arbitraire mais unique pour distinguer.*
+* *
+* Description : Crée le support d'une conservation d'objets en place. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObjectStorage *g_object_storage_new(const char *type, uint8_t version, const char *uid)
+{
+ GObjectStorage *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_OBJECT_STORAGE, NULL);
+
+ if (!g_object_storage_create(result, type, version, uid))
+ g_clear_object(&result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = stockage d'objets à initialiser. *
+* type = type global à indiquer dans une conservation. *
+* version = numéro de version associé. *
+* uid = identifiant arbitraire mais unique pour distinguer.*
+* *
+* Description : Met en place un support d'une conservation d'objets en place.*
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_storage_create(GObjectStorage *storage, const char *type, uint8_t version, const char *uid)
+{
+ bool result; /* Bilan à retourner */
+
+ result = true;
+
+ dup_into_sized_binary(&storage->type, type, strlen(type));
+
+ storage->version = version;
+
+ dup_into_sized_binary(&storage->uid, uid, strlen(uid) + 1);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = fichier de source à traiter. *
+* *
+* Description : Charge le support d'une conservation d'objets en place. *
+* *
+* Retour : Gestionnaire de conservations construit ou NULL si erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObjectStorage *g_object_storage_load(const char *filename)
+{
+ GObjectStorage *result; /* Structure à retourner */
+ GObjectStorage *storage; /* Structure en construction */
+ int err; /* Eventuel code d'erreur */
+ zip_t *archive; /* Archive ZIP à manipuler */
+ zip_error_t error; /* Suivi des erreurs obtenues */
+ char *tpmem_filename; /* Chemin d'accès pour types */
+ zip_int64_t entries_count; /* Nombre d'éléments ZIP */
+ void *data; /* Données (décompressées) */
+ zip_stat_t stats; /* Information sur les données */
+ zip_file_t *file; /* Echantillon à extraire */
+ zip_int64_t got; /* Nombre d'octets lus */
+ int ret; /* Bilan d'un appel */
+ const void *pos; /* Tête de lecture */
+ const void *max; /* Fin des données lisibles */
+ bool status; /* Bilan d'une extraction */
+ char *prefix; /* Début de nom de fichier */
+ int fd; /* Descripteur de flux ouvert */
+ off_t moved; /* Nouvelle position établie */
+ zip_int64_t i; /* Boucle de parcours */
+ storage_backend_t *backend; /* Informations à intégrer */
+ const char *slash; /* Pointeur vers un caractère /*/
+
+ result = NULL;
+
+ storage = g_object_new(G_TYPE_OBJECT_STORAGE, NULL);
+
+ archive = zip_open(filename, ZIP_RDONLY, &err);
+ if (archive == NULL)
+ {
+ zip_error_init_with_code(&error, err);
+ LOG_ERROR_ZIP("zip_open", &error);
+ goto exit;
+ }
+
+ zip_error_init(&error);
+
+ tpmem_filename = NULL;
+
+ /* Validation du nombre d'entrées */
+
+ entries_count = zip_get_num_entries(archive, ZIP_FL_UNCHANGED);
+
+ if (entries_count < 2)
+ goto exit_with_archive;
+
+ data = NULL;
+
+ /* Extraction de la partie de contrôle */
+
+ ret = zip_stat_index(archive, 0, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
+ {
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
+
+ if (strcmp(stats.name, "control") != 0)
+ goto exit_with_archive;
+
+ if (stats.size < (6 + 2 + 1 + 1 + 1))
+ goto exit_with_archive;
+
+ file = zip_fopen_index(archive, 0, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ data = malloc(stats.size);
+
+ got = zip_fread(file, data, stats.size);
+
+ ret = zip_fclose(file);
+ if (ret != 0)
+ {
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
+ }
+
+ if (got != stats.size)
+ goto exit_with_data;
+
+ if (memcmp(data, STORAGE_MAGIC, 6) != 0)
+ goto exit_with_data;
+
+ if (memcmp(((uint8_t *)data) + 6, STORAGE_NUMBER, 2) != 0)
+ goto exit_with_data;
+
+ pos = (uint8_t *)data + 8;
+ max = (uint8_t *)data + got;
+
+ status = unpack_sized_binary(&storage->type, &pos, max);
+ if (!status) goto exit_with_data;
+
+ if (pos >= max)
+ goto exit_with_data;
+
+ storage->version = *(uint8_t *)pos;
+ pos = (uint8_t *)pos + 1;
+
+ unpack_sized_binary_as_string(&storage->uid, &pos, max);
+ if (!status) goto exit_with_data;
+
+ if (pos != max)
+ goto exit_with_data;
+
+ free(data);
+ data = NULL;
+
+ /* Extraction de la conservation des types */
+
+ ret = zip_stat_index(archive, 1, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
+ {
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
+
+ if (strcmp(stats.name, "types") != 0)
+ goto exit_with_archive;
+
+ file = zip_fopen_index(archive, 1, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ data = malloc(stats.size);
+
+ got = zip_fread(file, data, stats.size);
+
+ ret = zip_fclose(file);
+ if (ret != 0)
+ {
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
+ }
+
+ asprintf(&prefix, "%s-types", storage->uid.static_data);
+
+ fd = make_tmp_file(prefix, "cache", &tpmem_filename);
+
+ free(prefix);
+
+ if (fd == -1)
+ goto exit_with_data;
+
+ status = safe_write(fd, data, stats.size);
+ if (!status)
+ {
+ close(fd);
+ goto exit_with_data;
+ }
+
+ moved = lseek(fd, 0, SEEK_SET);
+ if (moved == ((off_t)-1))
+ {
+ LOG_ERROR_N("lseek");
+ close(fd);
+ goto exit_with_data;
+ }
+
+ status = g_type_memory_load(storage->tpmem, fd);
+
+ close(fd);
+
+ if (!status)
+ goto exit_with_data;
+
+ free(data);
+ data = NULL;
+
+ /* Extraction des différents objects restants */
+
+ if (entries_count > 2)
+ {
+ storage->count = entries_count - 2;
+ storage->backends = calloc(storage->count, sizeof(storage_backend_t));
+
+ for (i = 2; i < entries_count; i++)
+ {
+ backend = &storage->backends[i - 2];
+
+ ret = zip_stat_index(archive, i, ZIP_FL_UNCHANGED, &stats);
+ if (ret != 0)
+ {
+ LOG_ERROR_ZIP("zip_stat_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ if ((stats.valid & (ZIP_STAT_NAME | ZIP_STAT_SIZE)) != (ZIP_STAT_NAME | ZIP_STAT_SIZE))
+ goto exit_with_archive;
+
+ if (strncmp(stats.name, SL("backends/")) != 0)
+ goto exit_with_archive;
+
+ slash = strchr(stats.name, '/');
+
+ if (slash == NULL)
+ goto exit_with_archive;
+
+ if (strchr(slash + 1, '/') != NULL)
+ goto exit_with_archive;
+
+ if (!g_object_storage_has_no_backend_named(storage, slash + 1))
+ goto exit_with_archive;
+
+ file = zip_fopen_index(archive, i, ZIP_FL_UNCHANGED);
+ if (file == NULL)
+ {
+ LOG_ERROR_ZIP("zip_fopen_index", zip_get_error(archive));
+ goto exit_with_archive;
+ }
+
+ data = malloc(stats.size);
+
+ got = zip_fread(file, data, stats.size);
+
+ ret = zip_fclose(file);
+ if (ret != 0)
+ {
+ zip_error_set(&error, ret, 0);
+ LOG_ERROR_ZIP("zip_fclose", &error);
+ goto exit_with_data;
+ }
+
+ backend->name = strdup(slash + 1);
+
+ asprintf(&prefix, "%s-%s", storage->uid.static_data, backend->name);
+
+ backend->fd = make_tmp_file(prefix, "cache", &backend->filename);
+
+ free(prefix);
+
+ if (backend->fd == -1)
+ goto exit_with_data;
+
+ status = safe_write(backend->fd, data, stats.size);
+ if (!status) goto exit_with_data;
+
+ moved = lseek(backend->fd, 0, SEEK_SET);
+ if (moved == ((off_t)-1))
+ {
+ LOG_ERROR_N("lseek");
+ goto exit_with_data;
+ }
+
+ free(data);
+ data = NULL;
+
+ }
+
+ }
+
+ /* Clôture des opérations */
+
+ result = storage;
+ ref_object(storage);
+
+ exit_with_data:
+
+ if (data != NULL)
+ free(data);
+
+ exit_with_archive:
+
+ ret = zip_close(archive);
+
+ if (ret != 0)
+ LOG_ERROR_ZIP("zip_close", zip_get_error(archive));
+
+ if (tpmem_filename != NULL)
+ unlink(tpmem_filename);
+
+ zip_error_fini(&error);
+
+ exit:
+
+ unref_object(storage);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire de conservations à manipuler. *
+* filename = fichier de destination à constituer. *
+* *
+* Description : Sauvegarde le support d'une conservation d'objets en place. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_storage_store(GObjectStorage *storage, const char *filename)
+{
+ bool result; /* Bilan à retourner */
+ int err; /* Eventuel code d'erreur */
+ zip_t *archive; /* Archive ZIP à manipuler */
+ zip_error_t error; /* Suivi des erreurs obtenues */
+ char *tpmem_filename; /* Chemin d'accès pour types */
+ void *type_buf; /* Données pour le type */
+ size_t type_buflen; /* Quantité de ces données */
+ void *uid_buf; /* Données pour l'identifiant */
+ size_t uid_buflen; /* Quantité de ces données */
+ size_t control_len; /* Taille des premières données*/
+ uint8_t *control; /* Premières données du fichier*/
+ zip_source_t *zip_data; /* Données ZIP à intégrer */
+ zip_int64_t index; /* Nouvel index du contenu */
+ int ret; /* Bilan d'un appel */
+ char *prefix; /* Début de nom de fichier */
+ int fd; /* Descripteur de flux ouvert */
+ bool status; /* Bilan d'une écriture */
+ size_t i; /* Boucle de parcours */
+ char *zip_name; /* Destination pour l'archive */
+
+ result = false;
+
+ archive = zip_open(filename, ZIP_CREATE | ZIP_TRUNCATE, &err);
+ if (archive == NULL)
+ {
+ zip_error_init_with_code(&error, err);
+ LOG_ERROR_ZIP("zip_open", &error);
+ goto exit;
+ }
+
+ zip_error_init(&error);
+
+ tpmem_filename = NULL;
+
+ /* Fichier de contrôle */
+
+ type_buf = pack_sized_binary(&storage->type, &type_buflen);
+
+ uid_buf = pack_sized_binary_as_string(&storage->uid, &uid_buflen);
+
+ assert((sizeof(STORAGE_MAGIC) - 1 + sizeof(STORAGE_NUMBER) - 1) == 8);
+
+ control_len = 8 + type_buflen + 1 + uid_buflen;
+ control = malloc(control_len * sizeof(uint8_t));
+
+ memcpy(control, STORAGE_MAGIC, 6);
+ memcpy(control + 6, STORAGE_NUMBER, 2);
+
+ memcpy(control + 8, type_buf, type_buflen);
+
+ control[8 + type_buflen] = storage->version;
+
+ memcpy(control + 8 + type_buflen + 1, uid_buf, uid_buflen);
+
+ zip_data = zip_source_buffer_create(control, control_len, 0, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_buffer_create", &error);
+ goto exit_with_control;
+ }
+
+ index = zip_file_add(archive, "control", zip_data, ZIP_FL_ENC_UTF_8);
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_control;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_STORE, 0 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_control;
+ }
+
+ /* Composants de la conservation */
+
+ g_mutex_lock(&storage->mutex);
+
+ /* Conservation des types */
+
+ asprintf(&prefix, "%s-types", storage->uid.static_data);
+
+ fd = make_tmp_file(prefix, "cache", &tpmem_filename);
+
+ free(prefix);
+
+ if (fd == -1)
+ goto exit_with_lock;
+
+ status = g_type_memory_store(storage->tpmem, fd);
+
+ close(fd);
+
+ if (!status)
+ goto exit_with_lock;
+
+ zip_data = zip_source_file_create(tpmem_filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_file_create", &error);
+ goto exit_with_lock;
+ }
+
+ index = zip_file_add(archive, "types", zip_data, ZIP_FL_ENC_UTF_8);
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ /* Conservation des objets */
+
+ for (i = 0; i < storage->count; i++)
+ {
+ zip_data = zip_source_file_create(storage->backends[i].filename, 0, -1 /* ZIP_LENGTH_TO_END */, &error);
+ if (zip_data == NULL)
+ {
+ LOG_ERROR_ZIP("zip_source_file_create", &error);
+ goto exit_with_lock;
+ }
+
+ /**
+ * Pas besoin de distinguer les chemins UNIX et Windows ici.
+ *
+ * Cf. https://pkware.cachefly.net/webdocs/casestudies/APPNOTE.TXT :
+ *
+ * 4.4.17 file name: (Variable)
+ *
+ * The path stored MUST NOT contain a drive or
+ * device letter, or a leading slash. All slashes
+ * MUST be forward slashes '/' as opposed to
+ * backwards slashes '\' for compatibility with Amiga
+ * and UNIX file systems etc. If input came from standard
+ * input, there is no file name field.
+ *
+ */
+
+ asprintf(&zip_name, "backends/%s", storage->backends[i].name);
+
+ index = zip_file_add(archive, zip_name, zip_data, ZIP_FL_ENC_UTF_8);
+
+ free(zip_name);
+
+ if (index == -1)
+ {
+ zip_source_free(zip_data);
+ LOG_ERROR_ZIP("zip_file_add", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ ret = zip_set_file_compression(archive, index, ZIP_CM_DEFLATE, 9 /* comp_flags */);
+ if (ret == -1)
+ {
+ LOG_ERROR_ZIP("zip_set_file_compression", zip_get_error(archive));
+ goto exit_with_lock;
+ }
+
+ }
+
+ result = true;
+
+ /* Clôture des opérations */
+
+ exit_with_lock:
+
+ g_mutex_unlock(&storage->mutex);
+
+ exit_with_control:
+
+ ret = zip_close(archive);
+
+ if (ret != 0)
+ LOG_ERROR_ZIP("zip_close", zip_get_error(archive));
+
+ free(control);
+
+ if (tpmem_filename != NULL)
+ unlink(tpmem_filename);
+
+ zip_error_fini(&error);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire de conservations à consulter. *
+* name = désignation d'un nouveau groupe d'objets. *
+* *
+* Description : Assure l'inexistence d'un groupe avec un nom donné. *
+* *
+* Retour : Bilan des recherches. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_object_storage_has_no_backend_named(GObjectStorage *storage, const char *name)
+{
+ bool result; /* Bilan à retourner */
+ size_t i; /* Boucle de parcours */
+
+ result = true;
+
+ for (i = 0; i < storage->count && result; i++)
+ {
+ if (storage->backends[i].name == NULL)
+ break;
+
+ if (strcmp(storage->backends[i].name, name) == 0)
+ result = false;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire de conservations à compléter. *
+* name = désignation d'un nouveau groupe d'objets. *
+* *
+* Description : Retrouve l'encadrement pour un nouveau groupe d'objets. *
+* *
+* Retour : Informations liées à un groupe ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static storage_backend_t *g_object_storage_find_backend(GObjectStorage *storage, const char *name)
+{
+ storage_backend_t *result; /* Encadrement à retourner */
+ size_t i; /* Boucle de parcours */
+
+ assert(!g_mutex_trylock(&storage->mutex));
+
+ for (i = 0; i < storage->count; i++)
+ if (strcmp(storage->backends[i].name, name) == 0)
+ break;
+
+ if (i == storage->count)
+ result = NULL;
+ else
+ result = &storage->backends[i];
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire de conservations à compléter. *
+* name = désignation d'un nouveau groupe d'objets. *
+* backend = support mis en place pour les enregistrements. *
+* *
+* Description : Ajoute le support d'un nouveau groupe d'objets construits. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static bool g_object_storage_add_backend(GObjectStorage *storage, const char *name, storage_backend_t **backend)
+{
+ bool result; /* Bilan à retourner */
+ char *prefix; /* Début de nom de fichier */
+ char *filename; /* Chemin d'accès aux données */
+ int fd; /* Descripteur de flux ouvert */
+
+ result = false;
+
+ *backend = NULL;
+
+ assert(!g_mutex_trylock(&storage->mutex));
+
+ if (g_object_storage_find_backend(storage, name) != NULL)
+ goto exit;
+
+ /* Préparatifs */
+
+ asprintf(&prefix, "%s-%s", storage->uid.static_data, name);
+
+ fd = make_tmp_file(prefix, "cache", &filename);
+
+ free(prefix);
+
+ if (fd == -1)
+ goto exit;
+
+ /* Inscription en bonne et due forme */
+
+ storage->backends = realloc(storage->backends, ++storage->count * sizeof(storage_backend_t));
+
+ *backend = &storage->backends[storage->count - 1];
+
+ (*backend)->name = strdup(name);
+
+ (*backend)->filename = filename;
+ (*backend)->fd = fd;
+
+ result = true;
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire à manipuler. *
+* name = désignation d'un groupe d'objets à consulter. *
+* pos = tête de lecture avant écriture. *
+* *
+* Description : Charge un objet à partir de données rassemblées. *
+* *
+* Retour : Objet restauré en mémoire ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GSerializableObject *g_object_storage_load_object_unlocked(GObjectStorage *storage, const char *name, off64_t pos)
+{
+ GSerializableObject *result; /* Instance à retourner */
+ storage_backend_t *backend; /* Informations à consulter */
+ off64_t new; /* Nouvelle position de lecture*/
+ bool status; /* Bilan d'une opération */
+
+ result = NULL;
+
+ assert(!g_mutex_trylock(&storage->mutex));
+
+ /* Chargement */
+
+ backend = g_object_storage_find_backend(storage, name);
+ if (backend == NULL) goto exit;
+
+ new = lseek64(backend->fd, pos, SEEK_SET);
+ if (new == (off_t)-1)
+ {
+ LOG_ERROR_N("lseek64");
+ goto exit;
+ }
+
+ assert (new == pos);
+
+ /* Phase de conversion */
+
+ result = G_SERIALIZABLE_OBJECT(g_type_memory_create_object_from_gtype(storage->tpmem, backend->fd));
+
+ if (result)
+ {
+ status = g_serializable_object_load(result, storage, backend->fd);
+
+ if (!status)
+ g_clear_object(&result);
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire à manipuler. *
+* name = désignation d'un groupe d'objets à consulter. *
+* pos = tête de lecture avant écriture. *
+* *
+* Description : Charge un objet à partir de données rassemblées. *
+* *
+* Retour : Objet restauré en mémoire ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSerializableObject *g_object_storage_load_object(GObjectStorage *storage, const char *name, off64_t pos)
+{
+ GSerializableObject *result; /* Instance à retourner */
+
+ g_mutex_lock(&storage->mutex);
+
+ result = g_object_storage_load_object_unlocked(storage, name, pos);
+
+ g_mutex_unlock(&storage->mutex);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire à manipuler. *
+* fd = flux de données de l'objet courant. *
+* name = désignation du groupe de l'objets à extraire. *
+* *
+* Description : Charge un objet interne à partir d'une référence embarquée. *
+* *
+* Retour : Objet restauré en mémoire ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GSerializableObject *g_object_storage_unpack_object(GObjectStorage *storage, int fd, const char *name)
+{
+ GSerializableObject *result; /* Instance à retourner */
+ storage_backend_t *backend; /* Informations à consulter */
+ uleb128_t pos; /* Localisation des données */
+ bool status; /* Bilan d'une opération */
+ off64_t saved; /* Sauvegarde de position */
+ off64_t new; /* Nouvelle position de lecture*/
+
+ result = NULL;
+
+ g_mutex_lock(&storage->mutex);
+
+ /* Récupération de la position */
+
+ backend = g_object_storage_find_backend(storage, name);
+ if (backend == NULL) goto exit;
+
+ status = load_uleb128(&pos, backend->fd);
+ if (!status) goto exit;
+
+ saved = lseek64(backend->fd, 0, SEEK_CUR);
+ if (saved == (off_t)-1)
+ {
+ LOG_ERROR_N("lseek64");
+ goto exit;
+ }
+
+ /* Chargement */
+
+ result = g_object_storage_load_object_unlocked(storage, name, pos);
+
+ if (result == NULL) goto exit;
+
+ /* Restauration de la position courante */
+
+ new = lseek64(backend->fd, saved, SEEK_SET);
+ if (new == (off_t)-1)
+ {
+ LOG_ERROR_N("lseek64");
+
+ g_clear_object(&result);
+ goto exit;
+
+ }
+
+ assert (new == saved);
+
+ exit:
+
+ g_mutex_unlock(&storage->mutex);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : storage = gestionnaire à manipuler. *
+* name = désignation d'un groupe d'objets, nouveau ou non. *
+* object = objet sérialisable à traiter. *
+* pos = tête de lecture avant écriture. [OUT] *
+* *
+* Description : Sauvegarde un object sous forme de données rassemblées. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_object_storage_store_object(GObjectStorage *storage, const char *name, const GSerializableObject *object, off64_t *pos)
+{
+ bool result; /* Bilan à retourner */
+ storage_backend_t *backend; /* Informations à consulter */
+ off64_t tmp; /* Conservation éphémère */
+
+ result = false;
+
+ g_mutex_lock(&storage->mutex);
+
+ backend = g_object_storage_find_backend(storage, name);
+
+ if (backend == NULL)
+ g_object_storage_add_backend(storage, name, &backend);
+
+ if (backend != NULL)
+ {
+ if (pos == NULL)
+ pos = &tmp;
+
+ *pos = lseek64(backend->fd, 0, SEEK_CUR);
+
+ if (*pos != (off64_t)-1)
+ {
+ result = g_type_memory_store_object_gtype(storage->tpmem, G_OBJECT(object), backend->fd);
+
+ if (result)
+ result = g_serializable_object_store(object, storage, backend->fd);
+
+ }
+
+ }
+
+ g_mutex_unlock(&storage->mutex);
+
+ return result;
+
+}
diff --git a/src/glibext/storage.h b/src/glibext/storage.h
new file mode 100644
index 0000000..ea06ed4
--- /dev/null
+++ b/src/glibext/storage.h
@@ -0,0 +1,81 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * storage.h - prototypes pour la conservation sur disque d'objets construits
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_STORAGE_H
+#define _GLIBEXT_STORAGE_H
+
+
+#include <stdint.h>
+
+
+#include "helpers.h"
+#include "serialize.h"
+
+
+
+#define G_TYPE_OBJECT_STORAGE (g_object_storage_get_type())
+
+DECLARE_GTYPE(GObjectStorage, g_object_storage, G, OBJECT_STORAGE);
+
+
+/* Crée le support d'une conservation d'objets en place. */
+GObjectStorage *g_object_storage_new(const char *, uint8_t, const char *);
+
+/* Charge le support d'une conservation d'objets en place. */
+GObjectStorage *g_object_storage_load(const char *);
+
+/* Sauvegarde le support d'une conservation d'objets en place. */
+bool g_object_storage_store(GObjectStorage *, const char *);
+
+/* Charge un objet à partir de données rassemblées. */
+GSerializableObject *g_object_storage_load_object(GObjectStorage *, const char *, off64_t);
+
+/* Charge un objet interne à partir d'une référence embarquée. */
+GSerializableObject *g_object_storage_unpack_object(GObjectStorage *, int, const char *);
+
+/* Sauvegarde un object sous forme de données rassemblées. */
+bool g_object_storage_store_object(GObjectStorage *, const char *, const GSerializableObject *, off64_t *);
+
+
+
+
+#if 0
+
+/**
+ * TODO : REMME ?
+ */
+
+#define get_storage_linked_format(s) \
+ ({ \
+ void*__result; \
+ __result = g_object_get_data(G_OBJECT(s), "format"); \
+ g_object_ref(G_OBJECT(__result)); \
+ __result; \
+ })
+
+#endif
+
+
+
+
+#endif /* _GLIBEXT_STORAGE_H */
diff --git a/src/glibext/tpmem-int.h b/src/glibext/tpmem-int.h
new file mode 100644
index 0000000..b1b7eec
--- /dev/null
+++ b/src/glibext/tpmem-int.h
@@ -0,0 +1,78 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tpmem-int.h - définitions internes propres à la mémorisation des types d'objets mis en cache
+ *
+ * Copyright (C) 2020-2025 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_TPMEM_INT_H
+#define _GLIBEXT_TPMEM_INT_H
+
+
+#include "tpmem.h"
+
+
+/* Conservation d'une référence sur un type */
+typedef struct _gtype_ref_info_t
+{
+ GType gtype; /* Type pour la GLib */
+ gpointer gclass; /* Lien vers sa classe */
+
+ /**
+ * La GLib n'est pas très claire sur la taille de GType comme le montre le
+ * code issu de <sources>/gobject/gtype.h :
+ *
+ * #if GLIB_SIZEOF_SIZE_T != GLIB_SIZEOF_LONG || !defined __cplusplus
+ * typedef gsize GType;
+ * #else // for historic reasons, C++ links against gulong GTypes
+ * typedef gulong GType;
+ * #endif
+ *
+ * Et :
+ *
+ * typedef unsigned $glib_size_type_define gsize;
+ *
+ * On prend donc le parti de conserver ces types sous forme de valeurs 64 bits
+ * lors des enregistrements.
+ */
+
+} gtype_ref_info_t;
+
+
+/* Définition d'une mémoire de types d'objets (instance) */
+struct _GTypeMemory
+{
+ GObject parent; /* A laisser en premier */
+
+ gtype_ref_info_t *gtypes; /* Types des objets reconnus */
+ size_t count; /* Quantité de ces objets */
+ GMutex mutex; /* Contrôle d'accès à la liste */
+
+};
+
+/* Définition d'une mémoire de types d'objets (classe) */
+struct _GTypeMemoryClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+
+#endif /* _GLIBEXT_TPMEM_INT_H */
diff --git a/src/glibext/tpmem.c b/src/glibext/tpmem.c
new file mode 100644
index 0000000..14b5e33
--- /dev/null
+++ b/src/glibext/tpmem.c
@@ -0,0 +1,363 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tpmem.c - mémorisation des types d'objets mis en cache
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#include "tpmem.h"
+
+
+#include <assert.h>
+
+
+#include "tpmem-int.h"
+#include "../common/szbin.h"
+#include "../core/logs.h"
+
+
+
+/* Initialise la classe des mémoires de types d'objets. */
+static void g_type_memory_class_init(GTypeMemoryClass *);
+
+/* Initialise une instance de mémoire de types d'objets. */
+static void g_type_memory_init(GTypeMemory *);
+
+/* Supprime toutes les références externes. */
+static void g_type_memory_dispose(GObject *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_type_memory_finalize(GObject *);
+
+
+
+/* Indique le type défini pour une mémoire de types d'objets. */
+G_DEFINE_TYPE(GTypeMemory, g_type_memory, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des mémoires de types d'objets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_type_memory_class_init(GTypeMemoryClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = g_type_memory_dispose;
+ object->finalize = g_type_memory_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tpmem = instance à initialiser. *
+* *
+* Description : Initialise une instance de mémoire de types d'objets. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_type_memory_init(GTypeMemory *tpmem)
+{
+ tpmem->gtypes = NULL;
+ tpmem->count = 0;
+ g_mutex_init(&tpmem->mutex);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_type_memory_dispose(GObject *object)
+{
+ GTypeMemory *tpmem; /* Version spécialisée */
+ uint64_t i; /* Boucle de parcours */
+
+ tpmem = G_TYPE_MEMORY(object);
+
+ g_mutex_lock(&tpmem->mutex);
+
+ for (i = 0; i < tpmem->count; i++)
+ if (tpmem->gtypes[i].gclass != NULL)
+ g_type_class_unref(tpmem->gtypes[i].gclass);
+
+ g_mutex_unlock(&tpmem->mutex);
+
+ g_mutex_clear(&tpmem->mutex);
+
+ G_OBJECT_CLASS(g_type_memory_parent_class)->dispose(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : object = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_type_memory_finalize(GObject *object)
+{
+ GTypeMemory *tpmem; /* Version spécialisée */
+
+ tpmem = G_TYPE_MEMORY(object);
+
+ if (tpmem->gtypes != NULL)
+ free(tpmem->gtypes);
+
+ G_OBJECT_CLASS(g_type_memory_parent_class)->finalize(object);
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une mémoire pour types d'objets. *
+* *
+* Retour : Instance mise en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GTypeMemory *g_type_memory_new(void)
+{
+ GTypeMemory *result; /* Structure à retourner */
+
+ result = g_object_new(G_TYPE_TYPE_MEMORY, NULL);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tpmem = mémoire à compléter. *
+* fd = flux ouvert en lecture. *
+* *
+* Description : Apprend tous les types mémorisés dans un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_type_memory_load(GTypeMemory *tpmem, int fd)
+{
+ bool result; /* Bilan à enregistrer */
+ uleb128_t count; /* Nombre d'éléments détectés */
+ uleb128_t i; /* Boucle de parcours */
+ sized_binary_t str; /* Chaîne à charger */
+
+ result = load_uleb128(&count, fd);
+
+ if (result)
+ {
+ g_mutex_lock(&tpmem->mutex);
+
+ tpmem->count = count;
+
+ assert(tpmem->gtypes == NULL);
+ tpmem->gtypes = calloc(count, sizeof(gtype_ref_info_t));
+
+ for (i = 0; i < tpmem->count && result; i++)
+ {
+ result = load_sized_binary_as_string(&str, fd);
+ if (!result) break;
+
+ tpmem->gtypes[i].gtype = g_type_from_name(str.data);
+ result = (tpmem->gtypes[i].gtype != 0);
+
+ if (!result)
+ log_variadic_message(LMT_ERROR, "Unknown type: '%s'", str.data);
+
+ else
+ tpmem->gtypes[i].gclass = g_type_class_ref(tpmem->gtypes[i].gtype);
+
+ exit_sized_binary(&str);
+
+ }
+
+ g_mutex_unlock(&tpmem->mutex);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tpmem = mémoire à consulter. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Enregistre tous les types mémorisés dans un tampon. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_type_memory_store(GTypeMemory *tpmem, int fd)
+{
+ bool result; /* Bilan à enregistrer */
+ uint64_t i; /* Boucle de parcours */
+ const gchar *name; /* Désignation d'un type */
+ sized_binary_t str; /* Chaîne à conserver */
+
+ g_mutex_lock(&tpmem->mutex);
+
+ result = store_uleb128((uleb128_t []){ tpmem->count }, fd);
+
+ for (i = 0; i < tpmem->count && result; i++)
+ {
+ name = g_type_name(tpmem->gtypes[i].gtype);
+
+ setup_sized_binary_from_static_string(&str, name);
+
+ store_sized_binary_as_string(&str, fd);
+
+ }
+
+ g_mutex_unlock(&tpmem->mutex);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tpmem = mémoire à manipuler. *
+* fd = flux ouvert en lecture. *
+* *
+* Description : Crée une nouvelle instance d'objet à partir de son type. *
+* *
+* Retour : Instance issue de l'opération ou NULL. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GObject *g_type_memory_create_object_from_gtype(GTypeMemory *tpmem, int fd)
+{
+ GObject *result; /* Nouvelle instance à renvoyer*/
+ uleb128_t index; /* Indice du point d'insertion */
+ bool status; /* Bilan d'une récupération */
+
+ result = NULL;
+
+ status = load_uleb128(&index, fd);
+
+ if (status)
+ {
+ g_mutex_lock(&tpmem->mutex);
+
+ if (index < tpmem->count)
+ result = g_object_new(tpmem->gtypes[index].gtype, NULL);
+
+ g_mutex_unlock(&tpmem->mutex);
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tpmem = mémoire à manipuler. *
+* obj = instance dont le type est à mémoriser. *
+* fd = flux ouvert en écriture. *
+* *
+* Description : Sauvegarde le type d'un objet instancié. *
+* *
+* Retour : Bilan de l'opération. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+bool g_type_memory_store_object_gtype(GTypeMemory *tpmem, GObject *obj, int fd)
+{
+ bool result; /* Bilan à retourner */
+ GType gtype; /* Type à enregistrer */
+ size_t index; /* Indice du point d'insertion */
+
+ gtype = G_TYPE_FROM_INSTANCE(obj);
+
+ g_mutex_lock(&tpmem->mutex);
+
+ for (index = 0; index < tpmem->count; index++)
+ if (tpmem->gtypes[index].gtype == gtype)
+ break;
+
+ if (index == tpmem->count)
+ {
+ tpmem->gtypes = realloc(tpmem->gtypes, ++tpmem->count * sizeof(gtype_ref_info_t));
+
+ tpmem->gtypes[index].gtype = gtype;
+ tpmem->gtypes[index].gclass = g_type_class_ref(gtype);
+
+ }
+
+ g_mutex_unlock(&tpmem->mutex);
+
+ result = store_uleb128((uleb128_t []){ index }, fd);
+
+ return result;
+
+}
diff --git a/src/glibext/tpmem.h b/src/glibext/tpmem.h
new file mode 100644
index 0000000..ccb8323
--- /dev/null
+++ b/src/glibext/tpmem.h
@@ -0,0 +1,57 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tpmem.h - prototypes pour la mémorisation des types d'objets mis en cache
+ *
+ * Copyright (C) 2020-2025 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 Foobar. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef _GLIBEXT_TPMEM_H
+#define _GLIBEXT_TPMEM_H
+
+
+#include <stdbool.h>
+
+
+#include "helpers.h"
+
+
+
+#define G_TYPE_TYPE_MEMORY (g_type_memory_get_type())
+
+DECLARE_GTYPE(GTypeMemory, g_type_memory, G, TYPE_MEMORY);
+
+
+/* Crée une mémoire pour types d'objets. */
+GTypeMemory *g_type_memory_new(void);
+
+/* Apprend tous les types mémorisés dans un tampon. */
+bool g_type_memory_load(GTypeMemory *, int);
+
+/* Enregistre tous les types mémorisés dans un tampon. */
+bool g_type_memory_store(GTypeMemory *, int);
+
+/* Crée une nouvelle instance d'objet à partir de son type. */
+GObject *g_type_memory_create_object_from_gtype(GTypeMemory *, int);
+
+/* Sauvegarde le type d'un objet instancié. */
+bool g_type_memory_store_object_gtype(GTypeMemory *, GObject *, int);
+
+
+
+#endif /* _GLIBEXT_TPMEM_H */
diff --git a/src/glibext/widthtracker.c b/src/glibext/widthtracker.c
index 7e06578..0a3dbe6 100644
--- a/src/glibext/widthtracker.c
+++ b/src/glibext/widthtracker.c
@@ -330,13 +330,17 @@ void g_width_tracker_set_column_min_width(GWidthTracker *tracker, size_t col, in
void g_width_tracker_compute_width(const GWidthTracker *tracker, int *width)
{
+ size_t col_count; /* Nombre maximum de colonnes */
size_t i; /* Boucle de parcours */
*width = 0;
- // FIX access to col_count
- for (i = 0; i < tracker->col_count; i++)
+
+ col_count = tracker->opt_count + tracker->reg_count;
+
+
+ for (i = 0; i < col_count; i++)
*width += tracker->min_widths[i];
}