diff options
Diffstat (limited to 'plugins/yaml/python')
| -rw-r--r-- | plugins/yaml/python/Makefile.am | 1 | ||||
| -rw-r--r-- | plugins/yaml/python/collection.c | 370 | ||||
| -rw-r--r-- | plugins/yaml/python/collection.h | 45 | ||||
| -rw-r--r-- | plugins/yaml/python/module.c | 2 | ||||
| -rw-r--r-- | plugins/yaml/python/node.c | 168 | ||||
| -rw-r--r-- | plugins/yaml/python/reader.c | 16 | ||||
| -rw-r--r-- | plugins/yaml/python/tree.c | 99 | 
7 files changed, 586 insertions, 115 deletions
| diff --git a/plugins/yaml/python/Makefile.am b/plugins/yaml/python/Makefile.am index 8a8d960..a750343 100644 --- a/plugins/yaml/python/Makefile.am +++ b/plugins/yaml/python/Makefile.am @@ -2,6 +2,7 @@  noinst_LTLIBRARIES = libyamlpython.la  libyamlpython_la_SOURCES =					\ +	collection.h collection.c				\  	line.h line.c							\  	module.h module.c						\  	node.h node.c							\ diff --git a/plugins/yaml/python/collection.c b/plugins/yaml/python/collection.c new file mode 100644 index 0000000..7166784 --- /dev/null +++ b/plugins/yaml/python/collection.c @@ -0,0 +1,370 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * collection.c - équivalent Python du fichier "plugins/yaml/collection.c" + * + * 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#include "collection.h" + + +#include <pygobject.h> + + +#include <plugins/pychrysalide/helpers.h> + + +#include "../collection.h" + + + +/* Crée un nouvel objet Python de type 'YamlCollection'. */ +static PyObject *py_yaml_collection_new(PyTypeObject *, PyObject *, PyObject *); + +/* Recherche les noeuds correspondant à un chemin. */ +static PyObject *py_yaml_collection_find_by_path(PyObject *, PyObject *); + +/* Indique la nature d'une collection Yaml. */ +static PyObject *py_yaml_collection_is_sequence(PyObject *, void *); + +/* Fournit la liste des noeuds intégrés dans une collection. */ +static PyObject *py_yaml_collection_get_nodes(PyObject *, void *); + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : type = type de l'objet à instancier.                         * +*                args = arguments fournis à l'appel.                          * +*                kwds = arguments de type key=val fournis.                    * +*                                                                             * +*  Description : Crée un nouvel objet Python de type 'YamlCollection'.        * +*                                                                             * +*  Retour      : Instance Python mise en place.                               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_yaml_collection_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ +    PyObject *result;                       /* Instance à retourner        */ +    int seq;                                /* Indicateur de type          */ +    int ret;                                /* Bilan de lecture des args.  */ +    GYamlCollection *collec;                /* Création GLib à transmettre */ + +#define YAML_COLLECTION_DOC                                                         \ +    "YamlCollection handle a collection of Yaml nodes.\n"                           \ +    "\n"                                                                            \ +    "Instances can be created using the following constructor:\n"                   \ +    "\n"                                                                            \ +    "    YamlCollection(seq=False)\n"                                               \ +    "\n"                                                                            \ +    "Where seq defines if the collection will be a sequence or a mapping of nodes." + +    ret = PyArg_ParseTuple(args, "p", &seq); +    if (!ret) return NULL; + +    collec = g_yaml_collection_new(seq); + +    g_object_ref_sink(G_OBJECT(collec)); +    result = pygobject_new(G_OBJECT(collec)); +    g_object_unref(collec); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self = variable non utilisée ici.                            * +*                args = arguments fournis à l'appel.                          * +*                                                                             * +*  Description : Recherche les noeuds correspondant à un chemin.              * +*                                                                             * +*  Retour      : Liste de noeuds trouvés, éventuellement vide.                * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_yaml_collection_find_by_path(PyObject *self, PyObject *args) +{ +    PyObject *result;                       /* Instance à retourner        */ +    const char *path;                       /* Chemin d'accès à traiter    */ +    int ret;                                /* Bilan de lecture des args.  */ +    GYamlCollection *collec;                /* Version GLib du type        */ +    GYamlNode **found;                      /* Créations GLib à transmettre*/ +    size_t count;                           /* Quantité de trouvailles     */ +    size_t i;                               /* Boucle de parcours          */ + +#define YAML_COLLECTION_FIND_BY_PATH PYTHON_METHOD_DEF                      \ +(                                                                           \ +    find_by_path, "path",                                                   \ +    METH_VARARGS, py_yaml_collection,                                       \ +    "Find nodes from a Yaml node using a path.\n"                           \ +    "\n"                                                                    \ +    "Paths are node keys separated by '/', such as '/my/path/to/node'."     \ +) + +    ret = PyArg_ParseTuple(args, "s", &path); +    if (!ret) return NULL; + +    collec = G_YAML_COLLEC(pygobject_get(self)); + +    g_yaml_collection_find_by_path(collec, path, &found, &count); + +    result = PyTuple_New(count); + +    for (i = 0; i < count; i++) +    { +#ifndef NDEBUG +        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +        assert(ret == 0); +#else +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +#endif + +        g_object_unref(G_OBJECT(found[i])); + +    } + +    if (found != NULL) +        free(found); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Fournit la liste des noeuds intégrés dans une collection.    * +*                                                                             * +*  Retour      : Enfants d'un noeud issu d'une collection Yaml.               * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_yaml_collection_get_nodes(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Résultat à retourner        */ +    GYamlCollection *collec;                /* Version GLib du type        */ +    size_t count;                           /* Quantité de noeuds à traiter*/ +    GYamlNode **nodes;                      /* Liste des noeuds à la racine*/ +    size_t i;                               /* Boucle de parcours          */ +#ifndef NDEBUG +    int ret;                                /* Bilan d'une insertion       */ +#endif + +#define YAML_COLLECTION_NODES_ATTRIB PYTHON_GET_DEF_FULL    \ +(                                                           \ +    nodes, py_yaml_collection,                              \ +    "List of nodes contained in the current collection."    \ +) + +    collec = G_YAML_COLLEC(pygobject_get(self)); + +    nodes = g_yaml_collection_get_nodes(collec, &count); + +    result = PyTuple_New(count); + +    for (i = 0; i < count; i++) +    { +#ifndef NDEBUG +        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); +        assert(ret == 0); +#else +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); +#endif + +        g_object_unref(G_OBJECT(nodes[i])); + +    } + +    free(nodes); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = objet Python concerné par l'appel.                 * +*                closure = non utilisé ici.                                   * +*                                                                             * +*  Description : Indique la nature d'une collection Yaml.                     * +*                                                                             * +*  Retour      : Nature de la collection.                                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static PyObject *py_yaml_collection_is_sequence(PyObject *self, void *closure) +{ +    PyObject *result;                       /* Résultat à retourner        */ +    GYamlCollection *collec;                /* Version GLib du type        */ +    bool status;                            /* Bilan de consultation       */ + +#define YAML_COLLECTION_IS_SEQUENCE_ATTRIB PYTHON_IS_DEF_FULL           \ +(                                                                       \ +    sequence, py_yaml_collection,                                       \ +    "Nature of the collection: True is the collection is a sequence,"   \ +    " False if it is a mapping of \"key: value\" nodes."                \ +) + +    collec = G_YAML_COLLEC(pygobject_get(self)); + +    status = g_yaml_collection_is_sequence(collec); + +    result = status ? Py_True : Py_False; +    Py_INCREF(result); + +    return result; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : -                                                            * +*                                                                             * +*  Description : Fournit un accès à une définition de type à diffuser.        * +*                                                                             * +*  Retour      : Définition d'objet pour Python.                              * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +PyTypeObject *get_python_yaml_collection_type(void) +{ +    static PyMethodDef py_yaml_collection_methods[] = { +        YAML_COLLECTION_FIND_BY_PATH, +        { NULL } +    }; + +    static PyGetSetDef py_yaml_collection_getseters[] = { +        YAML_COLLECTION_IS_SEQUENCE_ATTRIB, +        YAML_COLLECTION_NODES_ATTRIB, +        { NULL } +    }; + +    static PyTypeObject py_yaml_collection_type = { + +        PyVarObject_HEAD_INIT(NULL, 0) + +        .tp_name        = "pychrysalide.plugins.yaml.YamlCollection", +        .tp_basicsize   = sizeof(PyGObject), + +        .tp_flags       = Py_TPFLAGS_DEFAULT, + +        .tp_doc         = YAML_COLLECTION_DOC, + +        .tp_methods     = py_yaml_collection_methods, +        .tp_getset      = py_yaml_collection_getseters, +        .tp_new         = py_yaml_collection_new + +    }; + +    return &py_yaml_collection_type; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : module = module dont la définition est à compléter.          * +*                                                                             * +*  Description : Prend en charge l'objet 'pychrysalide.....YamlCollection.    * +*                                                                             * +*  Retour      : Bilan de l'opération.                                        * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +bool register_python_yaml_collection(PyObject *module) +{ +    PyTypeObject *type;                     /* Type Python 'YamlCollection'*/ +    PyObject *dict;                         /* Dictionnaire du module      */ + +    type = get_python_yaml_collection_type(); + +    dict = PyModule_GetDict(module); + +    if (!register_class_for_pygobject(dict, G_TYPE_YAML_COLLEC, type, &PyGObject_Type)) +        return false; + +    return true; + +} + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : arg = argument quelconque à tenter de convertir.             * +*                dst = destination des valeurs récupérées en cas de succès.   * +*                                                                             * +*  Description : Tente de convertir en collection de noeuds de format Yaml.   * +*                                                                             * +*  Retour      : Bilan de l'opération, voire indications supplémentaires.     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +int convert_to_yaml_collection(PyObject *arg, void *dst) +{ +    int result;                             /* Bilan à retourner           */ + +    result = PyObject_IsInstance(arg, (PyObject *)get_python_yaml_collection_type()); + +    switch (result) +    { +        case -1: +            /* L'exception est déjà fixée par Python */ +            result = 0; +            break; + +        case 0: +            PyErr_SetString(PyExc_TypeError, "unable to convert the provided argument to Yaml collection"); +            break; + +        case 1: +            *((GYamlCollection **)dst) = G_YAML_COLLEC(pygobject_get(arg)); +            break; + +        default: +            assert(false); +            break; + +    } + +    return result; + +} diff --git a/plugins/yaml/python/collection.h b/plugins/yaml/python/collection.h new file mode 100644 index 0000000..ab2caba --- /dev/null +++ b/plugins/yaml/python/collection.h @@ -0,0 +1,45 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * collection.h - prototypes pour l'équivalent Python du fichier "plugins/yaml/collection.h" + * + * 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 this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + */ + + +#ifndef _PLUGINS_YAML_PYTHON_COLLECTION_H +#define _PLUGINS_YAML_PYTHON_COLLECTION_H + + +#include <Python.h> +#include <stdbool.h> + + + +/* Fournit un accès à une définition de type à diffuser. */ +PyTypeObject *get_python_yaml_collection_type(void); + +/* Prend en charge l'objet 'pychrysalide.plugins.yaml.YamlCollection'. */ +bool register_python_yaml_collection(PyObject *); + +/* Tente de convertir en collection de noeuds de format Yaml. */ +int convert_to_yaml_collection(PyObject *, void *); + + + +#endif  /* _PLUGINS_YAML_PYTHON_COLLECTION_H */ diff --git a/plugins/yaml/python/module.c b/plugins/yaml/python/module.c index 542a551..2a4401e 100644 --- a/plugins/yaml/python/module.c +++ b/plugins/yaml/python/module.c @@ -33,6 +33,7 @@  #include <plugins/pychrysalide/helpers.h> +#include "collection.h"  #include "line.h"  #include "node.h"  #include "reader.h" @@ -108,6 +109,7 @@ bool populate_yaml_module(void)      module = get_access_to_python_module("pychrysalide.plugins.yaml"); +    if (result) result = register_python_yaml_collection(module);      if (result) result = register_python_yaml_line(module);      if (result) result = register_python_yaml_node(module);      if (result) result = register_python_yaml_reader(module); diff --git a/plugins/yaml/python/node.c b/plugins/yaml/python/node.c index d1aabee..f2984d1 100644 --- a/plugins/yaml/python/node.c +++ b/plugins/yaml/python/node.c @@ -31,6 +31,7 @@  #include <plugins/pychrysalide/helpers.h> +#include "collection.h"  #include "line.h"  #include "../node.h" @@ -39,14 +40,17 @@  /* Crée un nouvel objet Python de type 'YamlNode'. */  static PyObject *py_yaml_node_new(PyTypeObject *, PyObject *, PyObject *); -/* Recherche le noeud correspondant à un chemin. */ -static PyObject *py_yaml_node_find_node_by_path(PyObject *, PyObject *); +/* Recherche les noeuds correspondant à un chemin. */ +static PyObject *py_yaml_node_find_by_path(PyObject *, PyObject *);  /* Fournit la ligne principale associée à un noeud. */  static PyObject *py_yaml_node_get_yaml_line(PyObject *, void *); -/* Fournit la liste des noeuds intégrés dans un noeud Yaml. */ -static PyObject *py_yaml_node_get_children(PyObject *, void *); +/* Attache une collection de noeuds Yaml à un noeud. */ +static int py_yaml_node_set_collection(PyObject *, PyObject *, void *); + +/* Fournit une éventuelle collection rattachée à un noeud. */ +static PyObject *py_yaml_node_get_collection(PyObject *, void *); @@ -99,27 +103,29 @@ static PyObject *py_yaml_node_new(PyTypeObject *type, PyObject *args, PyObject *  *  Paramètres  : self = variable non utilisée ici.                            *  *                args = arguments fournis à l'appel.                          *  *                                                                             * -*  Description : Recherche le noeud correspondant à un chemin.                * +*  Description : Recherche les noeuds correspondant à un chemin.              *  *                                                                             * -*  Retour      : Eventuel noeud trouvé ou NULL si aucun.                      * +*  Retour      : Liste de noeuds trouvés, éventuellement vide.                *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_yaml_node_find_node_by_path(PyObject *self, PyObject *args) +static PyObject *py_yaml_node_find_by_path(PyObject *self, PyObject *args)  {      PyObject *result;                       /* Instance à retourner        */      const char *path;                       /* Chemin d'accès à traiter    */      int ret;                                /* Bilan de lecture des args.  */ -    GYamlNode *node;                        /* Version GLib du type        */ -    GYamlNode *found;                       /* Création GLib à transmettre */ +    GYamlNode *node;                        /* Version GLib du noeud       */ +    GYamlNode **found;                      /* Créations GLib à transmettre*/ +    size_t count;                           /* Quantité de trouvailles     */ +    size_t i;                               /* Boucle de parcours          */  #define YAML_NODE_FIND_BY_PATH PYTHON_METHOD_DEF                            \  (                                                                           \ -    find_node_by_path, "path",                                              \ +    find_by_path, "path",                                                   \      METH_VARARGS, py_yaml_node,                                             \ -    "Find a child node in a Yaml node by its path.\n"                       \ +    "Find nodes from a Yaml node using a path.\n"                           \      "\n"                                                                    \      "Paths are node keys separated by '/', such as '/my/path/to/node'."     \  ) @@ -129,20 +135,26 @@ static PyObject *py_yaml_node_find_node_by_path(PyObject *self, PyObject *args)      node = G_YAML_NODE(pygobject_get(self)); -    found = g_yaml_node_find_node_by_path(node, path); +    g_yaml_node_find_by_path(node, path, &found, &count); -    if (found == NULL) -    { -        result = Py_None; -        Py_INCREF(result); -    } +    result = PyTuple_New(count); -    else +    for (i = 0; i < count; i++)      { -        result = pygobject_new(G_OBJECT(found)); -        g_object_unref(found); +#ifndef NDEBUG +        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +        assert(ret == 0); +#else +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +#endif + +        g_object_unref(G_OBJECT(found[i])); +      } +    if (found != NULL) +        free(found); +      return result;  } @@ -164,7 +176,7 @@ static PyObject *py_yaml_node_find_node_by_path(PyObject *self, PyObject *args)  static PyObject *py_yaml_node_get_yaml_line(PyObject *self, void *closure)  {      PyObject *result;                       /* Résultat à retourner        */ -    GYamlNode *node;                        /* Version GLib du type        */ +    GYamlNode *node;                        /* Version GLib du noeud       */      GYamlLine *line;                        /* Line Yaml associée          */  #define YAML_NODE_YAML_LINE_ATTRIB PYTHON_GET_DEF_FULL      \ @@ -177,9 +189,65 @@ static PyObject *py_yaml_node_get_yaml_line(PyObject *self, void *closure)      line = g_yaml_node_get_yaml_line(node); -    result = pygobject_new(G_OBJECT(line)); +    if (line == NULL) +    { +        result = Py_None; +        Py_INCREF(result); +    } +    else +    { +        result = pygobject_new(G_OBJECT(line)); +        g_object_unref(G_OBJECT(line)); +    } + +    return result; + +} + + + + + +/****************************************************************************** +*                                                                             * +*  Paramètres  : self    = contenu binaire à manipuler.                       * +*                value   = collection de noeuds Yaml.                         * +*                closure = adresse non utilisée ici.                          * +*                                                                             * +*  Description : Attache une collection de noeuds Yaml à un noeud.            * +*                                                                             * +*  Retour      : Jeu d'attributs liés au contenu courant.                     * +*                                                                             * +*  Remarques   : -                                                            * +*                                                                             * +******************************************************************************/ + +static int py_yaml_node_set_collection(PyObject *self, PyObject *value, void *closure) +{ +    int result;                             /* Bilan à renvoyer            */ +    GYamlNode *node;                        /* Version GLib du noeud       */ +    GYamlCollection *collec;                /* Version GLib de la valeur   */ + +    node = G_YAML_NODE(pygobject_get(self)); -    g_object_unref(G_OBJECT(line)); +    if (value == Py_None) +    { +        g_yaml_node_set_collection(node, NULL); +        result = 0; +    } + +    else +    { +        if (!convert_to_yaml_collection(value, &collec)) +            result = -1; + +        else +        { +            g_yaml_node_set_collection(node, collec); +            result = 0; +        } + +    }      return result; @@ -188,54 +256,44 @@ static PyObject *py_yaml_node_get_yaml_line(PyObject *self, void *closure)  /******************************************************************************  *                                                                             * -*  Paramètres  : self    = objet Python concerné par l'appel.                 * -*                closure = non utilisé ici.                                   * +*  Paramètres  : self    = contenu binaire à manipuler.                       * +*                closure = adresse non utilisée ici.                          *  *                                                                             * -*  Description : Fournit la liste des noeuds intégrés dans un noeud Yaml.     * +*  Description : Fournit une éventuelle collection rattachée à un noeud.      *  *                                                                             * -*  Retour      : Enfants d'un noeud issu d'une arborescence Yaml.             * +*  Retour      : Collection de noeuds Yaml ou None.                           *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_yaml_node_get_children(PyObject *self, void *closure) +static PyObject *py_yaml_node_get_collection(PyObject *self, void *closure)  { -    PyObject *result;                       /* Résultat à retourner        */ -    GYamlNode *node;                        /* Version GLib du type        */ -    size_t count;                           /* Quantité de noeuds à traiter*/ -    GYamlNode **nodes;                      /* Liste des noeuds à la racine*/ -    size_t i;                               /* Boucle de parcours          */ -#ifndef NDEBUG -    int ret;                                /* Bilan d'une insertion       */ -#endif +    PyObject *result;                       /* Instance à retourner        */ +    GYamlNode *node;                        /* Version GLib du noeud       */ +    GYamlCollection *collec;                /* Collection à transmettre    */ -#define YAML_NODE_CHILDREN_ATTRIB PYTHON_GET_DEF_FULL           \ -(                                                               \ -    children, py_yaml_node,                                     \ -    "List of nodes which are children of the current node."     \ +#define YAML_NODE_COLLECTION_ATTRIB PYTHON_GETSET_DEF_FULL                      \ +(                                                                               \ +    collection, py_yaml_node,                                                   \ +    "Provide or define the collection of nodes attached to another Yaml node."  \  )      node = G_YAML_NODE(pygobject_get(self)); -    nodes = g_yaml_node_get_children(node, &count); +    collec = g_yaml_node_get_collection(node); -    result = PyTuple_New(count); - -    for (i = 0; i < count; i++) +    if (collec == NULL)      { -#ifndef NDEBUG -        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); -        assert(ret == 0); -#else -        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); -#endif - -        g_object_unref(G_OBJECT(nodes[i])); - +        result = Py_None; +        Py_INCREF(result);      } -    free(nodes); +    else +    { +        result = pygobject_new(G_OBJECT(collec)); +        g_object_unref(collec); +    }      return result; @@ -263,7 +321,7 @@ PyTypeObject *get_python_yaml_node_type(void)      static PyGetSetDef py_yaml_node_getseters[] = {          YAML_NODE_YAML_LINE_ATTRIB, -        YAML_NODE_CHILDREN_ATTRIB, +        YAML_NODE_COLLECTION_ATTRIB,          { NULL }      }; diff --git a/plugins/yaml/python/reader.c b/plugins/yaml/python/reader.c index 43db6bb..809ece2 100644 --- a/plugins/yaml/python/reader.c +++ b/plugins/yaml/python/reader.c @@ -208,7 +208,8 @@ static PyObject *py_yaml_reader_get_lines(PyObject *self, void *closure)      } -    free(lines); +    if (lines != NULL) +        free(lines);      return result; @@ -244,9 +245,16 @@ static PyObject *py_yaml_reader_get_tree(PyObject *self, void *closure)      tree = g_yaml_reader_get_tree(reader); -    result = pygobject_new(G_OBJECT(tree)); - -    g_object_unref(G_OBJECT(tree)); +    if (tree == NULL) +    { +        result = Py_None; +        Py_INCREF(result); +    } +    else +    { +        result = pygobject_new(G_OBJECT(tree)); +        g_object_unref(G_OBJECT(tree)); +    }      return result; diff --git a/plugins/yaml/python/tree.c b/plugins/yaml/python/tree.c index 9e1a2a3..eeab3de 100644 --- a/plugins/yaml/python/tree.c +++ b/plugins/yaml/python/tree.c @@ -40,11 +40,11 @@  /* Crée un nouvel objet Python de type 'YamlTree'. */  static PyObject *py_yaml_tree_new(PyTypeObject *, PyObject *, PyObject *); -/* Recherche le noeud correspondant à un chemin. */ -static PyObject *py_yaml_tree_find_node_by_path(PyObject *, PyObject *); +/* Recherche les noeuds correspondant à un chemin. */ +static PyObject *py_yaml_tree_find_by_path(PyObject *, PyObject *); -/* Fournit la liste des premiers noeuds de l'arborescence Yaml. */ -static PyObject *py_yaml_tree_get_root_nodes(PyObject *, void *); +/* Fournit le noeud constituant la racine d'arborescence Yaml. */ +static PyObject *py_yaml_tree_get_root(PyObject *, void *); @@ -65,7 +65,6 @@ static PyObject *py_yaml_tree_get_root_nodes(PyObject *, void *);  static PyObject *py_yaml_tree_new(PyTypeObject *type, PyObject *args, PyObject *kwds)  {      PyObject *result;                       /* Instance à retourner        */ -    Py_ssize_t indent;                      /* Indice de ligne associée    */      PyObject *tuple;                        /* Liste de lignes Yaml        */      int ret;                                /* Bilan de lecture des args.  */      size_t count;                           /* Nombre d'éléments présents  */ @@ -80,12 +79,11 @@ static PyObject *py_yaml_tree_new(PyTypeObject *type, PyObject *args, PyObject *      "\n"                                                                    \      "Instances can be created using the following constructor:\n"           \      "\n"                                                                    \ -    "    YamlTree(indent, lines)"                                           \ +    "    YamlTree(lines)"                                                   \      "\n"                                                                    \ -    "Where indent provides the length of a single level of indentation"     \ -    " and lines are a tuple of Yaml lines used to built the tree." +    "Where lines are a tuple of Yaml lines used to built the tree." -    ret = PyArg_ParseTuple(args, "nO!", &indent, &PyTuple_Type, &tuple); +    ret = PyArg_ParseTuple(args, "O!", &PyTuple_Type, &tuple);      if (!ret) return NULL;      count = PyTuple_Size(tuple); @@ -106,7 +104,7 @@ static PyObject *py_yaml_tree_new(PyTypeObject *type, PyObject *args, PyObject *      } -    tree = g_yaml_tree_new(indent, lines, count); +    tree = g_yaml_tree_new(lines, count);   arg_error: @@ -141,27 +139,29 @@ static PyObject *py_yaml_tree_new(PyTypeObject *type, PyObject *args, PyObject *  *  Paramètres  : self = variable non utilisée ici.                            *  *                args = arguments fournis à l'appel.                          *  *                                                                             * -*  Description : Recherche le noeud correspondant à un chemin.                * +*  Description : Recherche les noeuds correspondant à un chemin.              *  *                                                                             * -*  Retour      : Eventuel noeud trouvé ou NULL si aucun.                      * +*  Retour      : Liste de noeuds trouvés, éventuellement vide.                *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_yaml_tree_find_node_by_path(PyObject *self, PyObject *args) +static PyObject *py_yaml_tree_find_by_path(PyObject *self, PyObject *args)  {      PyObject *result;                       /* Instance à retourner        */      const char *path;                       /* Chemin d'accès à traiter    */      int ret;                                /* Bilan de lecture des args.  */      GYamlTree *tree;                        /* Version GLib du type        */ -    GYamlNode *found;                       /* Création GLib à transmettre */ +    GYamlNode **found;                      /* Créations GLib à transmettre*/ +    size_t count;                           /* Quantité de trouvailles     */ +    size_t i;                               /* Boucle de parcours          */  #define YAML_TREE_FIND_BY_PATH PYTHON_METHOD_DEF                            \  (                                                                           \ -    find_node_by_path, "path",                                              \ +    find_by_path, "path",                                                   \      METH_VARARGS, py_yaml_tree,                                             \ -    "Find a node in a Yaml tree by its path.\n"                             \ +    "Find nodes in a Yaml tree using a path.\n"                             \      "\n"                                                                    \      "Paths are node keys separated by '/', such as '/my/path/to/node'."     \  ) @@ -171,20 +171,26 @@ static PyObject *py_yaml_tree_find_node_by_path(PyObject *self, PyObject *args)      tree = G_YAML_TREE(pygobject_get(self)); -    found = g_yaml_tree_find_node_by_path(tree, path); +    g_yaml_tree_find_by_path(tree, path, &found, &count); -    if (found == NULL) -    { -        result = Py_None; -        Py_INCREF(result); -    } +    result = PyTuple_New(count); -    else +    for (i = 0; i < count; i++)      { -        result = pygobject_new(G_OBJECT(found)); -        g_object_unref(found); +#ifndef NDEBUG +        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +        assert(ret == 0); +#else +        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(found[i]))); +#endif + +        g_object_unref(G_OBJECT(found[i])); +      } +    if (found != NULL) +        free(found); +      return result;  } @@ -195,51 +201,32 @@ static PyObject *py_yaml_tree_find_node_by_path(PyObject *self, PyObject *args)  *  Paramètres  : self    = objet Python concerné par l'appel.                 *  *                closure = non utilisé ici.                                   *  *                                                                             * -*  Description : Fournit la liste des premiers noeuds de l'arborescence Yaml. * +*  Description : Fournit le noeud constituant la racine d'arborescence Yaml.  *  *                                                                             * -*  Retour      : Noeuds constituant les racines de l'arborescence.            * +*  Retour      : Noeud constituant la racine de l'arborescence.               *  *                                                                             *  *  Remarques   : -                                                            *  *                                                                             *  ******************************************************************************/ -static PyObject *py_yaml_tree_get_root_nodes(PyObject *self, void *closure) +static PyObject *py_yaml_tree_get_root(PyObject *self, void *closure)  {      PyObject *result;                       /* Résultat à retourner        */      GYamlTree *tree;                        /* Version GLib du type        */ -    size_t count;                           /* Quantité de noeuds à traiter*/ -    GYamlNode **nodes;                      /* Liste des noeuds à la racine*/ -    size_t i;                               /* Boucle de parcours          */ -#ifndef NDEBUG -    int ret;                                /* Bilan d'une insertion       */ -#endif +    GYamlNode *root;                        /* Noeud racine d'arborescence */ -#define YAML_TREE_ROOT_NODES_ATTRIB PYTHON_GET_DEF_FULL             \ -(                                                                   \ -    root_nodes, py_yaml_tree,                                       \ -    "List of Yaml nodes which are the roots of all tree nodes."     \ +#define YAML_TREE_ROOT_ATTRIB PYTHON_GET_DEF_FULL           \ +(                                                           \ +    root, py_yaml_tree,                                     \ +    "Yaml node which is the root of the whole tree nodes."  \  )      tree = G_YAML_TREE(pygobject_get(self)); -    nodes = g_yaml_tree_get_root_nodes(tree, &count); - -    result = PyTuple_New(count); - -    for (i = 0; i < count; i++) -    { -#ifndef NDEBUG -        ret = PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); -        assert(ret == 0); -#else -        PyTuple_SetItem(result, i, pygobject_new(G_OBJECT(nodes[i]))); -#endif - -        g_object_unref(G_OBJECT(nodes[i])); - -    } +    root = g_yaml_tree_get_root(tree); -    free(nodes); +    result = pygobject_new(G_OBJECT(root)); +    g_object_unref(G_OBJECT(root));      return result; @@ -266,7 +253,7 @@ PyTypeObject *get_python_yaml_tree_type(void)      };      static PyGetSetDef py_yaml_tree_getseters[] = { -        YAML_TREE_ROOT_NODES_ATTRIB, +        YAML_TREE_ROOT_ATTRIB,          { NULL }      }; | 
