/* Chrysalide - Outil d'analyse de fichiers binaires
* encaps.c - manipulation des types de données encapsulés
*
* 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 Chrysalide. If not, see .
*/
#include "encaps.h"
#include
#include
#include "../type-int.h"
#include "../../common/extstr.h"
/* Description de type encapsulé (instance) */
struct _GEncapsulatedType
{
GDataType parent; /* A laisser en premier */
EncapsulationType type; /* Encapsulation utilisée */
GDataType *child; /* Sous-type encadré */
size_t dimension; /* Dimension quand applicable */
};
/* Description de type encapsulé (classe) */
struct _GEncapsulatedTypeClass
{
GDataTypeClass parent; /* A laisser en premier */
};
/* Initialise la classe des types encapsulés. */
static void g_encapsulated_type_class_init(GEncapsulatedTypeClass *);
/* Initialise l'instance d'un type encapsulé. */
static void g_encapsulated_type_init(GEncapsulatedType *);
/* Supprime toutes les références externes. */
static void g_encapsulated_type_dispose(GEncapsulatedType *);
/* Procède à la libération totale de la mémoire. */
static void g_encapsulated_type_finalize(GEncapsulatedType *);
/* Crée un copie d'un type existant. */
static GDataType *g_encapsulated_type_dup(const GEncapsulatedType *);
/* Décrit le type fourni sous forme de caractères. */
static char *g_encapsulated_type_to_string(const GEncapsulatedType *, bool);
/* Indique si le type est un pointeur. */
static bool g_encapsulated_type_is_pointer(const GEncapsulatedType *);
/* Indique si le type est une référence. */
static bool g_encapsulated_type_is_reference(const GEncapsulatedType *);
/* Indique le type défini pour un type encapsulé. */
G_DEFINE_TYPE(GEncapsulatedType, g_encapsulated_type, G_TYPE_DATA_TYPE);
/******************************************************************************
* *
* Paramètres : klass = classe à initialiser. *
* *
* Description : Initialise la classe des types encapsulés. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_encapsulated_type_class_init(GEncapsulatedTypeClass *klass)
{
GObjectClass *object; /* Autre version de la classe */
GDataTypeClass *type; /* Version parente et basique */
object = G_OBJECT_CLASS(klass);
object->dispose = (GObjectFinalizeFunc/* ! */)g_encapsulated_type_dispose;
object->finalize = (GObjectFinalizeFunc)g_encapsulated_type_finalize;
type = G_DATA_TYPE_CLASS(klass);
type->dup = (type_dup_fc)g_encapsulated_type_dup;
type->to_string = (type_to_string_fc)g_encapsulated_type_to_string;
type->is_pointer = (type_is_pointer_fc)g_encapsulated_type_is_pointer;
type->is_reference = (type_is_reference_fc)g_encapsulated_type_is_reference;
}
/******************************************************************************
* *
* Paramètres : type = instance à initialiser. *
* *
* Description : Initialise l'instance d'un type encapsulé. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_encapsulated_type_init(GEncapsulatedType *type)
{
type->type = ECT_COUNT;
type->child = NULL;
type->dimension = 0;
}
/******************************************************************************
* *
* Paramètres : type = instance d'objet GLib à traiter. *
* *
* Description : Supprime toutes les références externes. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_encapsulated_type_dispose(GEncapsulatedType *type)
{
if (type->child != NULL)
g_object_unref(G_OBJECT(type->child));
G_OBJECT_CLASS(g_encapsulated_type_parent_class)->dispose(G_OBJECT(type));
}
/******************************************************************************
* *
* Paramètres : type = instance d'objet GLib à traiter. *
* *
* Description : Procède à la libération totale de la mémoire. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
static void g_encapsulated_type_finalize(GEncapsulatedType *type)
{
G_OBJECT_CLASS(g_encapsulated_type_parent_class)->finalize(G_OBJECT(type));
}
/******************************************************************************
* *
* Paramètres : type = type d'extension à représenter. *
* child = base dont on doit dériver. *
* *
* Description : Crée une représentation de variable dérivée. *
* *
* Retour : Adresse de la structure mise en place. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *g_encapsulated_type_new(EncapsulationType type, GDataType *child)
{
GEncapsulatedType *result; /* Structure à retourner */
result = g_object_new(G_TYPE_ENCAPSULATED_TYPE, NULL);
result->type = type;
result->child = child;
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_encapsulated_type_dup(const GEncapsulatedType *type)
{
GDataType *result; /* Nouvelle instance à renvoyer*/
GDataType *child; /* Copie du type interne */
child = g_data_type_dup(type->child);
result = g_encapsulated_type_new(type->type, child);
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à convertir. *
* include = doit-on inclure les espaces de noms ? *
* *
* 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_encapsulated_type_to_string(const GEncapsulatedType *type, bool include)
{
char *result; /* Chaîne finale à renvoyer */
size_t i; /* Boucle de parcours */
result = g_data_type_to_string(type->child, include);
if (result == NULL) goto exit;
switch (type->type)
{
case ECT_POINTER:
if (!g_data_type_is_pointer(type->child))
result = stradd(result, " ");
result = stradd(result, "*");
break;
case ECT_ARRAY:
result = stradd(result, " ");
for (i = 0; i < type->dimension; i++)
result = stradd(result, "[]");
break;
case ECT_REFERENCE:
if (!g_data_type_is_reference(type->child))
result = stradd(result, " ");
result = stradd(result, "&");
break;
case ECT_RVALUE_REF:
if (!g_data_type_is_reference(type->child))
result = stradd(result, " ");
result = stradd(result, "&&");
break;
case ECT_COMPLEX:
result = stradd(result, " complex");
break;
case ECT_IMAGINARY:
result = stradd(result, " imaginary");
break;
default:
assert(false);
free(result);
result = NULL;
break;
}
exit:
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Indique si le type est un pointeur. *
* *
* Retour : Bilan de la consultation. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_encapsulated_type_is_pointer(const GEncapsulatedType *type)
{
bool result; /* Bilan à retourner */
result = (type->type == ECT_POINTER);
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Indique si le type est une référence. *
* *
* Retour : Bilan de la consultation. *
* *
* Remarques : - *
* *
******************************************************************************/
static bool g_encapsulated_type_is_reference(const GEncapsulatedType *type)
{
bool result; /* Bilan à retourner */
result = (type->type == ECT_REFERENCE || type->type == ECT_RVALUE_REF);
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Fournit le type d'encapsulation gérée par le type. *
* *
* Retour : Type d'encapsulation gérée. *
* *
* Remarques : - *
* *
******************************************************************************/
EncapsulationType g_encapsulated_type_get_etype(const GEncapsulatedType *type)
{
return type->type;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Fournit le type encapsulée dans le type. *
* *
* Retour : Sous-type encapsulé dans le type. *
* *
* Remarques : - *
* *
******************************************************************************/
GDataType *g_encapsulated_type_get_item(const GEncapsulatedType *type)
{
GDataType *result; /* Type à retourner */
result = type->child;
if (result != NULL)
g_object_ref(G_OBJECT(result));
return result;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* *
* Description : Fournit la dimension éventuellement associée au type. *
* *
* Retour : Dimension positive ou nulle. *
* *
* Remarques : - *
* *
******************************************************************************/
size_t g_encapsulated_type_get_dimension(const GEncapsulatedType *type)
{
return type->dimension;
}
/******************************************************************************
* *
* Paramètres : type = type à consulter. *
* dim = dimension positive ou nulle. *
* *
* Description : Définit la dimension éventuellement associée au type. *
* *
* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
void g_encapsulated_type_set_dimension(GEncapsulatedType *type, size_t dim)
{
type->dimension = dim;
}