summaryrefslogtreecommitdiff
path: root/plugins/yaml/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/yaml/tree.c')
-rw-r--r--plugins/yaml/tree.c383
1 files changed, 383 insertions, 0 deletions
diff --git a/plugins/yaml/tree.c b/plugins/yaml/tree.c
new file mode 100644
index 0000000..98ee30c
--- /dev/null
+++ b/plugins/yaml/tree.c
@@ -0,0 +1,383 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * tree.c - ligne de contenu Yaml
+ *
+ * Copyright (C) 2019 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 "tree.h"
+
+
+#include <malloc.h>
+#include <string.h>
+
+
+
+/* Arborescence de lignes au format Yaml (instance) */
+struct _GYamlTree
+{
+ GObject parent; /* A laisser en premier */
+
+ size_t indent; /* Niveau d'indentation */
+
+ GYamlNode **nodes; /* Liste de noeuds à la racine */
+ size_t count; /* Quantité de ces noeuds */
+
+};
+
+/* Arborescence de lignes au format Yaml (classe) */
+struct _GYamlTreeClass
+{
+ GObjectClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des arborescence de lignes Yaml. */
+static void g_yaml_tree_class_init(GYamlTreeClass *);
+
+/* Initialise une instance d'arborescence de lignes Yaml. */
+static void g_yaml_tree_init(GYamlTree *);
+
+/* Supprime toutes les références externes. */
+static void g_yaml_tree_dispose(GYamlTree *);
+
+/* Procède à la libération totale de la mémoire. */
+static void g_yaml_tree_finalize(GYamlTree *);
+
+/* Construit un nouveau noeud dans une arborescence Yaml. */
+static GYamlNode *g_yaml_tree_build_node(GYamlLine **, size_t, size_t *);
+
+
+
+/* Indique le type défini pour une arborescence de lignes au format Yaml. */
+G_DEFINE_TYPE(GYamlTree, g_yaml_tree, G_TYPE_OBJECT);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des arborescence de lignes Yaml. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_yaml_tree_class_init(GYamlTreeClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)g_yaml_tree_dispose;
+ object->finalize = (GObjectFinalizeFunc)g_yaml_tree_finalize;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = instance à initialiser. *
+* *
+* Description : Initialise une instance d'arborescence de lignes Yaml. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_yaml_tree_init(GYamlTree *tree)
+{
+ tree->indent = 0;
+
+ tree->nodes = NULL;
+ tree->count = 0;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_yaml_tree_dispose(GYamlTree *tree)
+{
+ size_t i; /* Boucle de parcours */
+
+ for (i = 0; i < tree->count; i++)
+ g_clear_object(&tree->nodes[i]);
+
+ G_OBJECT_CLASS(g_yaml_tree_parent_class)->dispose(G_OBJECT(tree));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void g_yaml_tree_finalize(GYamlTree *tree)
+{
+ if (tree->nodes != NULL)
+ free(tree->nodes);
+
+ G_OBJECT_CLASS(g_yaml_tree_parent_class)->finalize(G_OBJECT(tree));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : indent = indentation nominale pour les lignes à traiter. *
+* lines = ensemble de lignes à constituer en arborescence. *
+* count = taille de cet ensemble de lignes. *
+* *
+* Description : Construit une arborescence à partir de lignes Yaml. *
+* *
+* Retour : Instance mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlTree *g_yaml_tree_new(size_t indent, GYamlLine **lines, size_t count)
+{
+ GYamlTree *result; /* Structure à retourner */
+ size_t cur; /* Boucle de parcours */
+ GYamlNode *node; /* Nouveau noeud à intéger */
+
+ result = g_object_new(G_TYPE_YAML_TREE, NULL);
+
+ result->indent = indent;
+
+ for (cur = 0; cur < count; )
+ {
+ node = g_yaml_tree_build_node(lines, count, &cur);
+
+ if (node == NULL)
+ break;
+
+ result->nodes = realloc(result->nodes, ++result->count * sizeof(GYamlNode *));
+
+ g_object_ref_sink(G_OBJECT(node));
+ result->nodes[result->count - 1] = node;
+
+ }
+
+ if (cur < count)
+ {
+ g_object_unref(G_OBJECT(result));
+ result = NULL;
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : lines = ensemble de lignes à constituer en arborescence. *
+* count = taille de cet ensemble de lignes. *
+* cur = position courante dans les lignes. [OUT] *
+* *
+* Description : Construit un nouveau noeud dans une arborescence Yaml. *
+* *
+* Retour : Noeud mis en place ou NULL en cas d'erreur. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlNode *g_yaml_tree_build_node(GYamlLine **lines, size_t count, size_t *cur)
+{
+ GYamlNode *result; /* Structure à retourner */
+ GYamlLine *line; /* Ligne de parcours courante */
+ size_t cur_indent; /* Indentation courante */
+ bool same_indent; /* Comparaison pour les enfants*/
+ size_t next_indent; /* Indentation de la ligne */
+ GYamlNode *child; /* Sous-noeud mis en place */
+
+ line = lines[(*cur)++];
+
+ result = g_yaml_node_new(line);
+
+ /* Détermination de l'indentation associée */
+
+ cur_indent = g_yaml_line_count_indent(line);
+
+ same_indent = g_yaml_line_is_list_item(line);
+
+ /* Parcours du reste des lignes */
+
+ for (; *cur < count; )
+ {
+ line = lines[*cur];
+
+ next_indent = g_yaml_line_count_indent(line);
+
+ if ((same_indent && next_indent > cur_indent)
+ || (!same_indent && next_indent <= cur_indent))
+ break;
+
+ child = g_yaml_tree_build_node(lines, count, cur);
+
+ if (child == NULL)
+ goto build_error;
+
+ g_yaml_node_add_child(result, child);
+
+ }
+
+ return result;
+
+ build_error:
+
+ g_object_unref(G_OBJECT(result));
+
+ return NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = ligne au format Yaml à consulter. *
+* *
+* Description : Fournit la taille de l'indentation nomilae d'un arbre Yaml. *
+* *
+* Retour : Taille de l'indentation associée. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+size_t g_yaml_tree_get_indent(const GYamlTree *tree)
+{
+ size_t result; /* Quantité à retourner */
+
+ result = tree->indent;
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = ligne au format Yaml à consulter. *
+* count = taille de la liste constituée. [OUT] *
+* *
+* Description : Fournit la liste des premiers noeuds de l'arborescence Yaml. *
+* *
+* Retour : Noeuds constituant les racines de l'arborescence. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode **g_yaml_tree_get_root_nodes(const GYamlTree *tree, size_t *count)
+{
+ GYamlNode **result; /* Liste à retourner */
+ size_t i; /* Boucle de parcours */
+
+ *count = tree->count;
+
+ result = malloc(*count * sizeof(GYamlNode *));
+
+ for (i = 0; i < *count; i++)
+ {
+ result[i] = tree->nodes[i];
+ g_object_ref(G_OBJECT(result[i]));
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : tree = ligne au format Yaml à consulter. *
+* path = chemin d'accès à parcourir. *
+* *
+* Description : Recherche le noeud correspondant à un chemin. *
+* *
+* Retour : Eventuel noeud trouvé ou NULL si aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode *g_yaml_tree_find_node_by_path(const GYamlTree *tree, const char *path)
+{
+ GYamlNode *result; /* Trouvaille à retourner */
+ char *next; /* Prochaine partie du chemin */
+ size_t cmplen; /* Etendue de la comparaison */
+ size_t i; /* Boucle de parcours */
+ GYamlLine *line; /* Ligne Yaml d'un enfant */
+ const char *key; /* Clef d'un noeud */
+ int ret; /* Bilan d'une comparaison */
+
+ result = NULL;
+
+ if (path[0] == '/' && path[0] != '\0')
+ {
+ next = strchr(path + 1, '/');
+
+ cmplen = (next == NULL ? strlen(path + 1) : next - path - 1);
+
+ for (i = 0; i < tree->count && result == NULL; i++)
+ {
+ line = g_yaml_node_get_yaml_line(tree->nodes[i]);
+
+ key = g_yaml_line_get_key(line);
+
+ ret = strncmp(path + 1, key, cmplen);
+
+ if (ret == 0)
+ result = g_yaml_node_find_node_by_path(tree->nodes[i], next);
+
+ }
+
+ }
+
+ return result;
+
+}