/* Chrysalide - Outil d'analyse de fichiers binaires
* template.c - manipulation des types reposant sur des gabarits
*
* Copyright (C) 2012-2017 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 .
*/
#include "template.h"
#include
#include
#include "cse-int.h"
#include "../type-int.h"
#include "../../common/extstr.h"
/* Description de type reposant sur des gabarits (instance) */
struct _GTemplateType
{
GClassEnumType parent; /* A laisser en premier */
GDataType **models; /* Sous-types associés */
size_t models_count; /* Quantité de ces modèles */
};
/* Description de type reposant sur des gabarits (classe) */
struct _GTemplateTypeClass
{
GClassEnumTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types reposant sur des gabarits. */
static void g_template_type_class_init(GTemplateTypeClass *);
/* Initialise l'instance d'un type reposant sur des gabarits. */
static void g_template_type_init(GTemplateType *);
/* Crée un copie d'un type existant. */
static GDataType *g_template_type_dup(const GTemplateType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_template_type_to_string(const GTemplateType *);
/* Procède à l'impression de la description d'un type. */
//static void g_template_type_output(const GTemplateType *, GLangOutput *, GBufferLine *, bool, bool);
/* Indique le type défini pour un type reposant sur des gabarits. */
G_DEFINE_TYPE(GTemplateType, g_template_type, G_TYPE_CLASS_ENUM_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types reposant sur des gabarits. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_template_type_class_init(GTemplateTypeClass *klass)
{
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type reposant sur des gabarits. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_template_type_init(GTemplateType *type)
{
GDataType *data_type; /* Version basique */
GClassEnumType *ce_type; /* Version basique #2 */
data_type = G_DATA_TYPE(type);
data_type->dup = (type_dup_fc)g_template_type_dup;
data_type->to_string = (type_to_string_fc)g_template_type_to_string;
//data_type->output = (output_type_fc)g_template_type_output;
ce_type = G_CLASS_ENUM_TYPE(type);
ce_type->type = CET_CLASS;
}
/******************************************************************************
* *
* Paramètres : name = désignation humaine du type. *
* list = élements du modèle sur lequel doit reposer le type. *
* *
* Description : Crée une représentation de type reposant sur des gabarits. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *g_template_type_new(const char *name, GSList *list)
{
GTemplateType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_TEMPLATE_TYPE, NULL);
G_CLASS_ENUM_TYPE(result)->name = strdup(name);
g_template_type_add_params(result, list);
return G_DATA_TYPE(result);
}
/******************************************************************************
* *
* Paramètres : type = type à dupliquer. *
* *
* Description : Crée un copie d'un type existant. *
* *
* Retour : Nouvelle instance de type identique à celle fournie. *
* *
* Remarques : - *
* *
******************************************************************************/
static GDataType *g_template_type_dup(const GTemplateType *type)
{
GDataType *result; /* Copie à retourner */
GSList *list; /* Format de liste à fournir */
size_t i; /* Boucle de parcours */
list = NULL;
for (i = 0; i < type->models_count; i++)
list = g_slist_prepend(list, type->models[i]);
result = g_template_type_new(G_CLASS_ENUM_TYPE(type)->name, list);
return G_DATA_TYPE(result);
}
/******************************************************************************
* *
* Paramètres : type = type à convertir. *
* *
* Description : Décrit le type fourni sous forme de caractères. *
* *
* Retour : Chaîne à libérer de la mémoire après usage. *
* *
* Remarques : - *
* *
******************************************************************************/
static char *g_template_type_to_string(const GTemplateType *type)
{
char *result; /* Valeur à renvoyer */
size_t i; /* Boucle de parcours */
char *sub; /* Sous-type à décrire */
result = g_class_enum_type_to_string(G_CLASS_ENUM_TYPE(type));
result = stradd(result, "<");
for (i = 0; i < type->models_count; i++)
{
if (i > 0) result = stradd(result, ", ");
sub = g_data_type_to_string(type->models[i]);
result = stradd(result, sub);
free(sub);
}
result = stradd(result, ">");
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à afficher. *
* lang = langage à utiliser pour la sortie humaine. *
* buffer = tampon mis à disposition pour la sortie. *
* info = nature du cadre de destination. *
* full = besoin de descriptions étendues ? *
* *
* Description : Procède à l'impression de la description d'un type. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
#if 0
static void g_template_type_output(const GTemplateType *type, GLangOutput *lang, GBufferLine *line, bool info, bool full)
{
size_t i; /* Boucle de parcours */
g_class_enum_type_output(G_CLASS_ENUM_TYPE(type), lang, line, info, full);
g_buffer_line_append_text(line, BLC_LAST_USED, "<", 1, info ? RTT_COMMENT : RTT_LTGT, NULL);
for (i = 0; i < type->models_count; i++)
{
if (i > 0)
g_buffer_line_append_text(line, BLC_LAST_USED, ", ", 2, info ? RTT_COMMENT : RTT_SIGNS, NULL);
g_data_type_output(type->models[i], lang, line, info, full);
}
g_buffer_line_append_text(line, BLC_LAST_USED, ">", 1, info ? RTT_COMMENT : RTT_LTGT, NULL);
}
#endif
/******************************************************************************
* *
* Paramètres : type = type à mettre à jour. *
* list = élements du modèle sur lequel doit reposer le type. *
* *
* Description : Ajoute une série de paramètres à un gabarit. *
* *
* Retour : - *
* *
* Remarques : La liste doit contenir des éléments dans l'ordre inverse *
* d'apparition. De plus, elle est libérée dans cette fonction. *
* *
******************************************************************************/
void g_template_type_add_params(GTemplateType *type, GSList *list)
{
GSList *iter; /* Boucle de parcours */
list = g_slist_reverse(list);
for (iter = list; iter != NULL; iter = g_slist_next(iter))
{
type->models = (GDataType **)realloc(type->models,
++type->models_count * sizeof(GDataType *));
type->models[type->models_count - 1] = G_DATA_TYPE(iter->data);
}
g_slist_free(list);
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Indique le nombre de paramètres associés du gabarit. *
* *
* Retour : Nombre de paramètres inclus dans le gabarit. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_template_type_count_param(const GTemplateType *type)
{
return type->models_count;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* index = indice du paramètre à retourner. *
* *
* Description : Fournit un paramètre donné du gabarit. *
* *
* Retour : Type inclus dans le modèle ou NULL si mauvais indice. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *g_template_type_get_param(const GTemplateType *type, size_t index)
{
return (index < type->models_count ? type->models[index] : NULL);
}