diff options
Diffstat (limited to 'plugins/yaml/pair.c')
-rw-r--r-- | plugins/yaml/pair.c | 427 |
1 files changed, 291 insertions, 136 deletions
diff --git a/plugins/yaml/pair.c b/plugins/yaml/pair.c index 0e96937..4faba88 100644 --- a/plugins/yaml/pair.c +++ b/plugins/yaml/pair.c @@ -1,8 +1,8 @@ /* Chrysalide - Outil d'analyse de fichiers binaires - * pair.c - noeud Yaml de paire clef/valeur + * pair.c - noeud YAML de paire clef/valeur * - * Copyright (C) 2020 Cyrille Bagard + * Copyright (C) 2020-2023 Cyrille Bagard * * This file is part of Chrysalide. * @@ -24,38 +24,25 @@ #include "pair.h" +#include <assert.h> #include <malloc.h> #include <string.h> -#include "node-int.h" +#include <common/extstr.h> +#include "pair-int.h" -/* Noeud d'une arborescence au format Yaml (instance) */ -struct _GYamlPair -{ - GYamlNode parent; /* A laisser en premier */ - - char *key; /* Clef présente dans le noeud */ - char *value; /* Valeur associée */ - - GYamlCollection *collection; /* Collection de noeuds */ -}; - -/* Noeud d'une arborescence au format Yaml (classe) */ -struct _GYamlPairClass -{ - GYamlNodeClass parent; /* A laisser en premier */ -}; +/* -------------------- DEFINITIONS PROPRES POUR LE SUPPORT YAML -------------------- */ -/* Initialise la classe des noeuds d'arborescence Yaml. */ +/* Initialise la classe des noeuds d'arborescence YAML. */ static void g_yaml_pair_class_init(GYamlPairClass *); -/* Initialise une instance de noeud d'arborescence Yaml. */ +/* Initialise une instance de noeud d'arborescence YAML. */ static void g_yaml_pair_init(GYamlPair *); /* Supprime toutes les références externes. */ @@ -64,12 +51,22 @@ static void g_yaml_pair_dispose(GYamlPair *); /* Procède à la libération totale de la mémoire. */ static void g_yaml_pair_finalize(GYamlPair *); -/* Recherche les noeuds correspondant à un chemin. */ -static void g_yaml_pair_find_by_path(const GYamlPair *, const char *, bool, GYamlNode ***, size_t *); +/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */ + + +/* Recherche le premier noeud correspondant à un chemin. */ +static GYamlNode *g_yaml_pair_find_first_by_path(GYamlPair *, const char *); + + + +/* ---------------------------------------------------------------------------------- */ +/* DEFINITIONS PROPRES POUR LE SUPPORT YAML */ +/* ---------------------------------------------------------------------------------- */ -/* Indique le type défini pour un noeud d'arborescence Yaml. */ + +/* Indique le type défini pour un noeud d'arborescence YAML. */ G_DEFINE_TYPE(GYamlPair, g_yaml_pair, G_TYPE_YAML_NODE); @@ -77,7 +74,7 @@ G_DEFINE_TYPE(GYamlPair, g_yaml_pair, G_TYPE_YAML_NODE); * * * Paramètres : klass = classe à initialiser. * * * -* Description : Initialise la classe des noeuds d'arborescence Yaml. * +* Description : Initialise la classe des noeuds d'arborescence YAML. * * * * Retour : - * * * @@ -97,16 +94,16 @@ static void g_yaml_pair_class_init(GYamlPairClass *klass) node = G_YAML_NODE_CLASS(klass); - node->find = (find_yaml_node_fc)g_yaml_pair_find_by_path; + node->find = (find_first_yaml_node_fc)g_yaml_pair_find_first_by_path; } /****************************************************************************** * * -* Paramètres : node = instance à initialiser. * +* Paramètres : pair = instance à initialiser. * * * -* Description : Initialise une instance de noeud d'arborescence Yaml. * +* Description : Initialise une instance de noeud d'arborescence YAML. * * * * Retour : - * * * @@ -114,19 +111,22 @@ static void g_yaml_pair_class_init(GYamlPairClass *klass) * * ******************************************************************************/ -static void g_yaml_pair_init(GYamlPair *node) +static void g_yaml_pair_init(GYamlPair *pair) { - node->key = NULL; - node->value = NULL; + pair->key = NULL; + pair->key_style = YOS_PLAIN; + + pair->value = NULL; + pair->value_style = YOS_PLAIN; - node->collection = NULL; + pair->children = NULL; } /****************************************************************************** * * -* Paramètres : node = instance d'objet GLib à traiter. * +* Paramètres : pair = instance d'objet GLib à traiter. * * * * Description : Supprime toutes les références externes. * * * @@ -136,18 +136,18 @@ static void g_yaml_pair_init(GYamlPair *node) * * ******************************************************************************/ -static void g_yaml_pair_dispose(GYamlPair *node) +static void g_yaml_pair_dispose(GYamlPair *pair) { - g_clear_object(&node->collection); + g_clear_object(&pair->children); - G_OBJECT_CLASS(g_yaml_pair_parent_class)->dispose(G_OBJECT(node)); + G_OBJECT_CLASS(g_yaml_pair_parent_class)->dispose(G_OBJECT(pair)); } /****************************************************************************** * * -* Paramètres : node = instance d'objet GLib à traiter. * +* Paramètres : pair = instance d'objet GLib à traiter. * * * * Description : Procède à la libération totale de la mémoire. * * * @@ -157,24 +157,27 @@ static void g_yaml_pair_dispose(GYamlPair *node) * * ******************************************************************************/ -static void g_yaml_pair_finalize(GYamlPair *node) +static void g_yaml_pair_finalize(GYamlPair *pair) { - if (node->key != NULL) - free(node->key); + if (pair->key != NULL) + free(pair->key); - if (node->value != NULL) - free(node->value); + if (pair->value != NULL) + free(pair->value); - G_OBJECT_CLASS(g_yaml_pair_parent_class)->finalize(G_OBJECT(node)); + G_OBJECT_CLASS(g_yaml_pair_parent_class)->finalize(G_OBJECT(pair)); } /****************************************************************************** * * -* Paramètres : line = ligne Yaml à l'origine du futur noeud. * +* Paramètres : key = désignation pour le noeud YAML. * +* kstyle = format d'origine de la clef. * +* value = éventuelle valeur directe portée par le noeud. * +* vstyle = éventuel format d'origine de l'éventuelle valeur. * * * -* Description : Construit un noeud d'arborescence Yaml. * +* Description : Construit un noeud d'arborescence YAML. * * * * Retour : Instance mise en place ou NULL en cas d'échec. * * * @@ -182,33 +185,14 @@ static void g_yaml_pair_finalize(GYamlPair *node) * * ******************************************************************************/ -GYamlPair *g_yaml_pair_new(GYamlLine *line) +GYamlPair *g_yaml_pair_new(const char *key, YamlOriginalStyle kstyle, const char *value, YamlOriginalStyle vstyle) { GYamlPair *result; /* Structure à retourner */ - const char *key; /* Clef associée au noeud */ - const char *value; /* Eventuelle valeur associée */ - - key = g_yaml_line_get_key(line); - value = g_yaml_line_get_value(line); - - if (key == NULL) - result = NULL; - else - { - result = g_object_new(G_TYPE_YAML_PAIR, NULL); - - G_YAML_NODE(result)->line = line; - g_object_ref(G_OBJECT(line)); + result = g_object_new(G_TYPE_YAML_PAIR, NULL); - result->key = strdup(key); - - if (value == NULL) - result->value = NULL; - else - result->value = strdup(value); - - } + if (!g_yaml_pair_create(result, key, kstyle, value, vstyle)) + g_clear_object(&result); return result; @@ -217,105 +201,126 @@ GYamlPair *g_yaml_pair_new(GYamlLine *line) /****************************************************************************** * * -* Paramètres : node = noeud d'arborescence Yaml à consulter. * -* path = chemin d'accès à parcourir. * -* prepare = indication sur une préparation d'un prochain appel.* -* nodes = liste de noeuds avec correspondance établie. [OUT] * -* count = quantité de ces noeuds. [OUT] * +* Paramètres : pair = paire YAML à initialiser pleinement. * +* key = désignation pour le noeud YAML. * +* kstyle = format d'origine de la clef. * +* value = éventuelle valeur directe portée par le noeud. * +* vstyle = éventuel format d'origine de l'éventuelle valeur. * * * -* Description : Recherche les noeuds correspondant à un chemin. * +* Description : Met en place une pair clef/valeur YAML. * * * -* Retour : - * +* Retour : Bilan de l'opération. * * * * Remarques : - * * * ******************************************************************************/ -static void g_yaml_pair_find_by_path(const GYamlPair *node, const char *path, bool prepare, GYamlNode ***nodes, size_t *count) +bool g_yaml_pair_create(GYamlPair *pair, const char *key, YamlOriginalStyle kstyle, const char *value, YamlOriginalStyle vstyle) { - char *next; /* Prochaine partie du chemin */ - size_t cmplen; /* Etendue de la comparaison */ - int ret; /* Bilan d'une comparaison */ + bool result; /* Bilan à retourner */ - if (path[0] == '\0') - goto exit; + result = true; - /* Correspondance au niveau du noeud ? */ + pair->key = strdup(key); + pair->key_style = kstyle; - if (path[0] == '/') + if (value != NULL) { - path++; + pair->value = strdup(value); + pair->value_style = vstyle; + } - if (path[0] == '\0') - goto matched; + return result; - } +} - next = strchr(path, '/'); - if (next == NULL) - ret = strcmp(path, node->key); +/****************************************************************************** +* * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * +* * +* Description : Fournit la clef représentée dans une paire en YAML. * +* * +* Retour : Clef sous forme de chaîne de caractères. * +* * +* Remarques : - * +* * +******************************************************************************/ - else - { - cmplen = next - path; +const char *g_yaml_pair_get_key(const GYamlPair *pair) +{ + char *result; /* Valeur à retourner */ - if (cmplen == 0) - goto cont; + result = pair->key; - ret = strncmp(path, node->key, cmplen); + return result; - } +} - if (ret != 0) - goto done; - else if (next != NULL) - { - path += cmplen; - goto cont; - } +/****************************************************************************** +* * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * +* * +* Description : Indique le format d'origine YAML associé à la clef. * +* * +* Retour : Valeur renseignée lors du chargement du noeud. * +* * +* Remarques : - * +* * +******************************************************************************/ - matched: +YamlOriginalStyle g_yaml_pair_get_key_style(const GYamlPair *pair) +{ + YamlOriginalStyle result; /* Indication à retourner */ - *nodes = realloc(*nodes, ++(*count) * sizeof(GYamlNode **)); + result = pair->key_style; - g_object_ref(G_OBJECT(node)); - (*nodes)[*count - 1] = G_YAML_NODE(node); + return result; - goto done; +} - cont: - if (node->collection != NULL) - _g_yaml_node_find_by_path(G_YAML_NODE(node->collection), path, prepare, nodes, count); +/****************************************************************************** +* * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * +* * +* Description : Fournit l'éventuelle valeur d'une paire en YAML. * +* * +* Retour : Valeur sous forme de chaîne de caractères ou NULL. * +* * +* Remarques : - * +* * +******************************************************************************/ - done: +const char *g_yaml_pair_get_value(const GYamlPair *pair) +{ + char *result; /* Valeur à retourner */ - exit: + result = pair->value; - ; + return result; } /****************************************************************************** * * -* Paramètres : node = noeud d'arborescence Yaml à consulter. * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * * * -* Description : Fournit la clef représentée dans une paire en Yaml. * +* Description : Indique le format d'origine YAML associé à la valeur. * * * -* Retour : Clef sous forme de chaîne de caractères. * +* Retour : Valeur renseignée lors du chargement du noeud. * * * * Remarques : - * * * ******************************************************************************/ -const char *g_yaml_pair_get_key(const GYamlPair *node) +YamlOriginalStyle g_yaml_pair_get_value_style(const GYamlPair *pair) { - char *result; /* Valeur à retourner */ + YamlOriginalStyle result; /* Indication à retourner */ - result = node->key; + result = pair->value_style; return result; @@ -324,9 +329,9 @@ const char *g_yaml_pair_get_key(const GYamlPair *node) /****************************************************************************** * * -* Paramètres : node = noeud d'arborescence Yaml à consulter. * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * * * -* Description : Fournit l'éventuelle valeur d'une paire en Yaml. * +* Description : Rassemble une éventuelle séquence de valeurs attachées. * * * * Retour : Valeur sous forme de chaîne de caractères ou NULL. * * * @@ -334,11 +339,88 @@ const char *g_yaml_pair_get_key(const GYamlPair *node) * * ******************************************************************************/ -const char *g_yaml_pair_get_value(const GYamlPair *node) +char *g_yaml_pair_aggregate_value(const GYamlPair *pair) { char *result; /* Valeur à retourner */ + GYamlNode **nodes; /* Eventuels noeuds trouvés */ + size_t count; /* Quantité de ces noeuds */ + size_t i; /* Boucle de parcours */ + GYamlPair *child; /* Couple clef/valeur enfant */ + bool failed; /* Détection d'un échec */ + + result = NULL; + + if (pair->value != NULL) + result = strdup(pair->value); + + else if (pair->children != NULL) + { + if (!g_yaml_collection_is_sequence(pair->children)) + goto exit; + + nodes = g_yaml_collection_get_nodes(pair->children, &count); + + if (count == 0) + result = strdup("[ ]"); + + else + { + result = strdup("[ "); + + for (i = 0; i < count; i++) + { + if (!G_IS_YAML_PAIR(nodes[i])) + break; + + child = G_YAML_PAIR(nodes[i]); + + if (child->value != NULL) + break; + + if (i > 0) + result = stradd(result, ", "); + + switch (child->key_style) + { + case YOS_PLAIN: + result = stradd(result, child->key); + break; + + case YOS_SINGLE_QUOTED: + result = straddfmt(result, "'%s'", child->key); + break; + + case YOS_DOUBLE_QUOTED: + result = straddfmt(result, "\"%s\"", child->key); + break; + + } + + g_object_unref(G_OBJECT(nodes[i])); + + } - result = node->value; + failed = (i < count); + + for (; i < count; i++) + g_object_unref(G_OBJECT(nodes[i])); + + free(nodes); + + if (failed) + { + free(result); + result = NULL; + } + + else + result = stradd(result, " ]"); + + } + + } + + exit: return result; @@ -347,10 +429,10 @@ const char *g_yaml_pair_get_value(const GYamlPair *node) /****************************************************************************** * * -* Paramètres : node = noeud d'arborescence Yaml à compléter. * -* collec = collection de noeuds Yaml. * +* Paramètres : pair = noeud d'arborescence YAML à compléter. * +* children = collection de noeuds YAML. * * * -* Description : Attache une collection de noeuds Yaml à un noeud. * +* Description : Attache une collection de noeuds YAML à un noeud. * * * * Retour : - * * * @@ -358,33 +440,33 @@ const char *g_yaml_pair_get_value(const GYamlPair *node) * * ******************************************************************************/ -void g_yaml_pair_set_collection(GYamlPair *node, GYamlCollection *collec) +void g_yaml_pair_set_children(GYamlPair *pair, GYamlCollection *children) { - g_clear_object(&node->collection); + g_clear_object(&pair->children); - g_object_ref_sink(G_OBJECT(collec)); - node->collection = collec; + g_object_ref_sink(G_OBJECT(children)); + pair->children = children; } /****************************************************************************** * * -* Paramètres : node = noeud d'arborescence Yaml à consulter. * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * * * * Description : Fournit une éventuelle collection rattachée à un noeud. * * * -* Retour : Collection de noeuds Yaml ou NULL. * +* Retour : Collection de noeuds YAML ou NULL. * * * * Remarques : - * * * ******************************************************************************/ -GYamlCollection *g_yaml_pair_get_collection(const GYamlPair *node) +GYamlCollection *g_yaml_pair_get_children(const GYamlPair *pair) { GYamlCollection *result; /* Collection à renvoyer */ - result = node->collection; + result = pair->children; if (result != NULL) g_object_ref(G_OBJECT(result)); @@ -392,3 +474,76 @@ GYamlCollection *g_yaml_pair_get_collection(const GYamlPair *node) return result; } + + + +/* ---------------------------------------------------------------------------------- */ +/* IMPLEMENTATION DES FONCTIONS DE CLASSE */ +/* ---------------------------------------------------------------------------------- */ + + +/****************************************************************************** +* * +* Paramètres : pair = noeud d'arborescence YAML à consulter. * +* path = chemin d'accès à parcourir. * +* * +* Description : Recherche le premier noeud correspondant à un chemin. * +* * +* Retour : Noeud avec la correspondance établie ou NULL si non trouvé. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static GYamlNode *g_yaml_pair_find_first_by_path(GYamlPair *pair, const char *path) +{ + GYamlNode *result; /* Trouvaille à retourner */ + char *next; /* Prochaine partie du chemin */ + size_t cmplen; /* Etendue de la comparaison */ + int ret; /* Bilan d'une comparaison */ + + assert(path[0] != '/' && path[0] != '\0'); + + /* Correspondance au niveau du noeud ? */ + + next = strchr(path, '/'); + + if (next == NULL) + ret = strcmp(path, pair->key); + + else + { + cmplen = next - path; + assert(cmplen > 0); + + ret = strncmp(path, pair->key, cmplen); + + } + + /* Si correspondance il y a... */ + + if (ret == 0) + { + /* ... et que la recherche se trouve en bout de parcours */ + if (next == NULL) + { + result = G_YAML_NODE(pair); + g_object_ref(G_OBJECT(result)); + } + + /* Recherche supplémentaire dans les sous-noeuds ? */ + + else if (pair->children != NULL) + result = g_yaml_node_find_first_by_path(G_YAML_NODE(pair->children), path + cmplen); + + else + result = NULL; + + } + + else + result = NULL; + + return result; + +} |