summaryrefslogtreecommitdiff
path: root/plugins/yaml/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/yaml/parser.c')
-rw-r--r--plugins/yaml/parser.c299
1 files changed, 299 insertions, 0 deletions
diff --git a/plugins/yaml/parser.c b/plugins/yaml/parser.c
new file mode 100644
index 0000000..8c06723
--- /dev/null
+++ b/plugins/yaml/parser.c
@@ -0,0 +1,299 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * parser.c - lecteur de contenu Yaml
+ *
+ * Copyright (C) 2019-2023 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 "parser.h"
+
+
+#include <assert.h>
+#include <malloc.h>
+#include <yaml.h>
+#include <gio/gio.h>
+
+
+#include <analysis/contents/file.h>
+
+
+#include "collection.h"
+#include "pair.h"
+
+
+#define SCALAR_STYLE_TO_ORIGINAL_STYLE(v) \
+ ({ \
+ YamlOriginalStyle __result; \
+ if (v == YAML_SINGLE_QUOTED_SCALAR_STYLE) \
+ __result = YOS_SINGLE_QUOTED; \
+ else if (v == YAML_DOUBLE_QUOTED_SCALAR_STYLE) \
+ __result = YOS_DOUBLE_QUOTED; \
+ else \
+ __result = YOS_PLAIN; \
+ __result; \
+ })
+
+
+/* Construit la version GLib d'un noeud YAML brut. */
+static GYamlPair *build_pair_from_yaml(yaml_document_t *, int, int);
+
+/* Transforme un noeud YAML brut en sa version Glib. */
+static GYamlNode *translate_yaml_node(yaml_document_t *, yaml_node_t *);
+
+
+
+/******************************************************************************
+* *
+* Paramètres : document = gestionnaire de l'ensemble des noeuds bruts. *
+* key = indice de la clef du noeud à convertir. *
+* value = indice de la valeur du noeud à convertir. *
+* *
+* Description : Construit la version GLib d'un noeud YAML brut. *
+* *
+* Retour : Noeud GLib obtenu ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlPair *build_pair_from_yaml(yaml_document_t *document, int key, int value)
+{
+ GYamlPair *result; /* Racine à retourner */
+ yaml_node_t *key_node; /* Noeud brut de la clef */
+ yaml_node_t *value_node; /* Noeud brut de la valeur */
+ GYamlNode *children; /* Collection de noeuds YAML */
+
+ result = NULL;
+
+ key_node = yaml_document_get_node(document, key);
+ assert(key_node != NULL);
+
+ if (key_node->type != YAML_SCALAR_NODE)
+ goto exit;
+
+ value_node = yaml_document_get_node(document, value);
+ assert(value_node != NULL);
+
+ if (value_node->type == YAML_SCALAR_NODE)
+ result = g_yaml_pair_new((char *)key_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(key_node->data.scalar.style),
+ (char *)value_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(value_node->data.scalar.style));
+
+ else
+ {
+ children = translate_yaml_node(document, value_node);
+
+ if (children != NULL)
+ {
+ result = g_yaml_pair_new((char *)key_node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(key_node->data.scalar.style),
+ NULL, YOS_PLAIN);
+
+ g_yaml_pair_set_children(result, G_YAML_COLLEC(children));
+
+ }
+
+ }
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : document = gestionnaire de l'ensemble des noeuds bruts. *
+* node = point de départ des transformations. *
+* *
+* Description : Transforme un noeud YAML brut en sa version Glib. *
+* *
+* Retour : Noeud GLib obtenu ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static GYamlNode *translate_yaml_node(yaml_document_t *document, yaml_node_t *node)
+{
+ GYamlNode *result; /* Racine à retourner */
+ yaml_node_item_t *index; /* Elément d'une série */
+ yaml_node_t *item; /* Elément d'une série */
+ GYamlNode *child; /* Version GLib de l'élément */
+ yaml_node_pair_t *pair; /* Combinaison clef/valeur */
+ GYamlPair *sub; /* Sous-noeud à intégrer */
+
+ switch (node->type)
+ {
+ case YAML_SCALAR_NODE:
+ result = G_YAML_NODE(g_yaml_pair_new((char *)node->data.scalar.value,
+ SCALAR_STYLE_TO_ORIGINAL_STYLE(node->data.scalar.style),
+ NULL, YOS_PLAIN));
+ break;
+
+ case YAML_SEQUENCE_NODE:
+
+ result = G_YAML_NODE(g_yaml_collection_new(true));
+
+ for (index = node->data.sequence.items.start; index < node->data.sequence.items.top; index++)
+ {
+ item = yaml_document_get_node(document, *index);
+ assert(item != NULL);
+
+ child = translate_yaml_node(document, item);
+
+ if (child == NULL)
+ {
+ g_clear_object(&result);
+ break;
+ }
+
+ g_yaml_collection_add_node(G_YAML_COLLEC(result), child);
+
+ }
+
+ break;
+
+ case YAML_MAPPING_NODE:
+
+ result = G_YAML_NODE(g_yaml_collection_new(false));
+
+ for (pair = node->data.mapping.pairs.start; pair < node->data.mapping.pairs.top; pair++)
+ {
+ sub = build_pair_from_yaml(document, pair->key, pair->value);
+
+ if (sub == NULL)
+ {
+ g_clear_object(&result);
+ break;
+ }
+
+ g_yaml_collection_add_node(G_YAML_COLLEC(result), G_YAML_NODE(sub));
+
+ }
+
+ break;
+
+ default:
+ assert(false);
+ result = NULL;
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : text = définitions textuelles d'un contenu brut. *
+* len = taille de ces définitions. *
+* *
+* Description : Crée une arborescence YAML pour contenu au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode *parse_yaml_from_text(const char *text, size_t len)
+{
+ GYamlNode *result; /* Racine à retourner */
+ yaml_parser_t parser; /* Lecteur du contenu fourni */
+ yaml_document_t document; /* Document YAML constitué */
+ int ret; /* Bilan de la constitution */
+ yaml_node_t *root; /* Elément racine brut */
+
+ result = NULL;
+
+ yaml_parser_initialize(&parser);
+
+ yaml_parser_set_input_string(&parser, (const unsigned char *)text, len);
+
+ ret = yaml_parser_load(&parser, &document);
+ if (ret != 1) goto bad_loading;
+
+ root = yaml_document_get_root_node(&document);
+
+ if (root != NULL)
+ result = translate_yaml_node(&document, root);
+
+ yaml_document_delete(&document);
+
+ bad_loading:
+
+ yaml_parser_delete(&parser);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : filename = chemin vers des définitions de règles. *
+* *
+* Description : Crée une arborescence YAML pour fichier au format adapté. *
+* *
+* Retour : Arborescence YAML mise en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GYamlNode *parse_yaml_from_file(const char *filename)
+{
+ GYamlNode *result; /* Racine à retourner */
+ GBinContent *content; /* Fichier à parcourir */
+ phys_t size; /* Taille du contenu associé */
+ vmpa2t start; /* Tête de lecture */
+ const bin_t *data; /* Données à consulter */
+ char *dumped; /* Contenu manipulable */
+
+ result = NULL;
+
+ content = g_file_content_new(filename);
+ if (content == NULL) goto no_content;
+
+ size = g_binary_content_compute_size(content);
+
+ g_binary_content_compute_start_pos(content, &start);
+ data = g_binary_content_get_raw_access(content, &start, size);
+
+ dumped = malloc((size + 1) * sizeof(char));
+
+ memcpy(dumped, data, size);
+ dumped[size] = '\0';
+
+ result = parse_yaml_from_text(dumped, size);
+
+ free(dumped);
+
+ g_object_unref(G_OBJECT(content));
+
+ no_content:
+
+ return result;
+
+}