/* Chrysalide - Outil d'analyse de fichiers binaires * type.h - prototypes pour la manipulation des types en tout genre * * Copyright (C) 2010-2018 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 "type.h" #include #include #include "type-int.h" #include "../common/extstr.h" /* Initialise la classe des types quelconques. */ static void g_data_type_class_init(GDataTypeClass *); /* Initialise l'instance d'un type quelconque. */ static void g_data_type_init(GDataType *); /* Supprime toutes les références externes. */ static void g_data_type_dispose(GDataType *); /* Procède à la libération totale de la mémoire. */ static void g_data_type_finalize(GDataType *); /* Indique le type défini pour un type quelconque. */ G_DEFINE_TYPE(GDataType, g_data_type, G_TYPE_OBJECT); /****************************************************************************** * * * Paramètres : klass = classe à initialiser. * * * * Description : Initialise la classe des types quelconques. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_data_type_class_init(GDataTypeClass *klass) { GObjectClass *object; /* Autre version de la classe */ object = G_OBJECT_CLASS(klass); object->dispose = (GObjectFinalizeFunc/* ! */)g_data_type_dispose; object->finalize = (GObjectFinalizeFunc)g_data_type_finalize; } /****************************************************************************** * * * Paramètres : type = instance à initialiser. * * * * Description : Initialise l'instance d'un type quelconque. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_data_type_init(GDataType *type) { } /****************************************************************************** * * * Paramètres : type = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ static void g_data_type_dispose(GDataType *type) { g_clear_object(&type->namespace); G_OBJECT_CLASS(g_data_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_data_type_finalize(GDataType *type) { if (type->ns_sep != NULL) free(type->ns_sep); G_OBJECT_CLASS(g_data_type_parent_class)->finalize(G_OBJECT(type)); } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Calcule une empreinte pour un type de données. * * * * Retour : Valeur arbitraire sur 32 bits, idéalement unique par type. * * * * Remarques : - * * * ******************************************************************************/ guint g_data_type_hash(const GDataType *type) { guint result; /* Empreinte à renvoyer */ GDataTypeClass *class; /* Classe du type */ class = G_DATA_TYPE_GET_CLASS(type); result = class->hash(type); result ^= g_int_hash((gint []){ g_data_type_get_qualifiers(type) }); if (type->namespace != NULL) result ^= g_data_type_hash(type->namespace); return result; } /****************************************************************************** * * * Paramètres : type = type à dupliquer. * * * * Description : Crée un copie d'un type existant. * * * * Retour : Nouvelle instance de type identique à celle fournie. * * * * Remarques : - * * * ******************************************************************************/ GDataType *g_data_type_dup(const GDataType *type) { GDataType *result; /* Copie à retourner */ GDataTypeClass *class; /* Classe du type */ GDataType *ns; /* Eventuel espace de noms */ char *ns_sep; /* Séparation des espaces */ class = G_DATA_TYPE_GET_CLASS(type); result = class->dup(type); if (type->namespace != NULL) { ns = g_data_type_dup(type->namespace); ns_sep = type->ns_sep != NULL ? strdup(type->ns_sep) : NULL; g_data_type_set_namespace(result, ns, ns_sep); } result->qualifiers = type->qualifiers; 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 : - * * * ******************************************************************************/ char *g_data_type_to_string(const GDataType *type, bool include) { char *result; /* Chaîne à retourner */ GDataTypeClass *class; /* Classe du type */ char *namespace; /* Groupe d'appartenance */ class = G_DATA_TYPE_GET_CLASS(type); result = class->to_string(type, include); if (result == NULL) result = strdup(""); if (include && type->namespace != NULL && g_data_type_handle_namespaces(type)) { namespace = g_data_type_to_string(type->namespace, true); result = strprep(result, type->ns_sep); result = strprep(result, namespace); free(namespace); } if (type->qualifiers & TQF_RESTRICT) result = strprep(result, "restrict "); if (type->qualifiers & TQF_VOLATILE) result = strprep(result, "volatile "); if (type->qualifiers & TQF_CONST) result = strprep(result, "const "); return result; } /****************************************************************************** * * * Paramètres : type = type à mettre à jour. * * namespace = instance d'appartenance. * * sep = séparateur à utiliser entre les éléments. * * * * Description : Définit le groupe d'appartenance d'un type donné. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_data_type_set_namespace(GDataType *type, GDataType *namespace, char *sep) { if (type->namespace != NULL) g_object_unref(G_OBJECT(type->namespace)); if (type->ns_sep != NULL) free(type->ns_sep); type->namespace = namespace; type->ns_sep = sep; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Fournit le groupe d'appartenance d'un type donné. * * * * Retour : Eventuelle instance d'appartenance ou NULL. * * * * Remarques : - * * * ******************************************************************************/ GDataType *g_data_type_get_namespace(const GDataType *type) { GDataType *result; /* Espace à renvoyer */ result = type->namespace; if (result != NULL) g_object_ref(G_OBJECT(result)); return result; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Fournit la chaîne de séparation entre deux entités. * * * * Retour : Eventuelle chaîne de séparation ou NULL. * * * * Remarques : - * * * ******************************************************************************/ const char *g_data_type_get_namespace_separator(const GDataType *type) { char *result; /* Séparateur à retourner */ result = type->ns_sep; return result; } /****************************************************************************** * * * Paramètres : type = instance à mettre à jour. * * qualifiers = nouveaux qualificatifs pour la variable. * * * * Description : Définit l'ensemble des qualificatifs d'une instance de type. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_data_type_set_qualifiers(GDataType *type, TypeQualifier qualifiers) { type->qualifiers = qualifiers; } /****************************************************************************** * * * Paramètres : type = instance à mettre à jour. * * qualifier = nouveau qualificatif pour la variable. * * * * Description : Ajoute un qualificatif à une instance de type. * * * * Retour : - * * * * Remarques : - * * * ******************************************************************************/ void g_data_type_add_qualifier(GDataType *type, TypeQualifier qualifier) { type->qualifiers |= qualifier; } /****************************************************************************** * * * Paramètres : type = instance à consulter. * * * * Description : Fournit les qualificatifs associés à une instance de type. * * * * Retour : Qualificatifs éventuels. * * * * Remarques : - * * * ******************************************************************************/ TypeQualifier g_data_type_get_qualifiers(const GDataType *type) { TypeQualifier result; /* Qualificatifs à renvoyer */ result = type->qualifiers; return result; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Indique si le type assure une gestion des espaces de noms. * * * * Retour : Bilan de la consultation. * * * * Remarques : - * * * ******************************************************************************/ bool g_data_type_handle_namespaces(const GDataType *type) { bool result; /* Bilan à retourner */ GDataTypeClass *class; /* Classe du type */ class = G_DATA_TYPE_GET_CLASS(type); if (class->handle_ns != NULL) result = class->handle_ns(type); else result = true; return result; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Indique si le type est un pointeur. * * * * Retour : Bilan de la consultation. * * * * Remarques : - * * * ******************************************************************************/ bool g_data_type_is_pointer(const GDataType *type) { bool result; /* Bilan à retourner */ GDataTypeClass *class; /* Classe du type */ class = G_DATA_TYPE_GET_CLASS(type); if (class->is_pointer != NULL) result = class->is_pointer(type); else result = false; return result; } /****************************************************************************** * * * Paramètres : type = type à consulter. * * * * Description : Indique si le type est une référence. * * * * Retour : Bilan de la consultation. * * * * Remarques : - * * * ******************************************************************************/ bool g_data_type_is_reference(const GDataType *type) { bool result; /* Bilan à retourner */ GDataTypeClass *class; /* Classe du type */ class = G_DATA_TYPE_GET_CLASS(type); if (class->is_reference != NULL) result = class->is_reference(type); else result = false; return result; }