summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/glibext/buffercache.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-05-11 21:33:36 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-05-11 21:33:36 (GMT)
commitd2861533cc53fbcc217048bafebf34b1f70ba3aa (patch)
tree28c847a8093761fcaa0916be54445328d843096d /plugins/pychrysalide/glibext/buffercache.c
parent6c9e1b5f7ee0915036d47b83f1e34b87b44b1723 (diff)
Updated the API for buffer caches.
Diffstat (limited to 'plugins/pychrysalide/glibext/buffercache.c')
-rw-r--r--plugins/pychrysalide/glibext/buffercache.c947
1 files changed, 918 insertions, 29 deletions
diff --git a/plugins/pychrysalide/glibext/buffercache.c b/plugins/pychrysalide/glibext/buffercache.c
index 9ce06c1..fec5844 100644
--- a/plugins/pychrysalide/glibext/buffercache.c
+++ b/plugins/pychrysalide/glibext/buffercache.c
@@ -28,63 +28,897 @@
#include <pygobject.h>
-#include <glibext/gbuffercache.h>
+#include <glibext/gbuffercache-int.h>
+#include <plugins/dt.h>
+#include "constants.h"
+#include "bufferline.h"
+#include "linegen.h"
#include "../access.h"
#include "../helpers.h"
-#include "../arch/vmpa.h"
+#include "../analysis/content.h"
-#if 0
-/* Retrouve une ligne au sein d'un tampon avec une adresse. */
-static PyObject *py_code_buffer_find_line_by_addr(PyObject *, PyObject *);
+/* ------------------------ GLUE POUR CREATION DEPUIS PYTHON ------------------------ */
+/* Accompagne la création d'une instance dérivée en Python. */
+static PyObject *py_buffer_cache_new(PyTypeObject *, PyObject *, PyObject *);
+
+/* Initialise une instance sur la base du dérivé de GObject. */
+static int py_buffer_cache_init(PyObject *, PyObject *, PyObject *);
+
+
+
+/* -------------------------- TAMPON POUR CODE DESASSEMBLE -------------------------- */
+
+
+/* Insère un générateur dans des lignes à une position donnée. */
+static PyObject *py_buffer_cache_insert_at(PyObject *, PyObject *);
+
+/* Retire une ligne du tampon. */
+static PyObject *py_buffer_cache_delete_at(PyObject *, PyObject *);
+
+/* Retire un type de générateur de lignes. */
+static PyObject *py_buffer_cache_delete_type_at(PyObject *, PyObject *);
+
+/* Ajoute en fin de tampon un générateur de lignes. */
+static PyObject *py_buffer_cache_append(PyObject *, PyObject *);
+
+/* Etend un tampon avec un générateur de lignes unique. */
+static PyObject *py_buffer_cache_extend_with(PyObject *, PyObject *);
+
+/* Réduit le tampon à une quantité de lignes précise. */
+static PyObject *py_buffer_cache_truncate(PyObject *, PyObject *);
+
+/* Détermine l'ensemble des propriétés attachées à une ligne. */
+static PyObject *py_buffer_cache_get_line_flags(PyObject *, PyObject *);
+
+/* Retrouve une ligne au sein d'un tampon avec un indice. */
+static PyObject *py_buffer_cache_find_line_by_index(PyObject *, PyObject *);
+
+/* Avance autant que possible vers une ligne idéale. */
+static PyObject *py_buffer_cache_look_for_flag(PyObject *, PyObject *);
+
+/* Indique l'éventuel contenu binaire associé au cache. */
+static PyObject *py_buffer_cache_get_content(PyObject *, void *);
+
+/* Fournit la hauteur d'impression d'une ligne visualisée. */
+static PyObject *py_buffer_cache_get_line_height(PyObject *, void *);
+
+/* Fournit la taille réservée pour la marge gauche. */
+static PyObject *py_buffer_cache_get_left_margin(PyObject *, void *);
+
+/* Fournit la position de départ pour l'impression de texte. */
+static PyObject *py_buffer_cache_get_text_position(PyObject *, void *);
+
+/* Compte le nombre de lignes rassemblées dans un tampon. */
+static PyObject *py_buffer_cache_get_lines_count(PyObject *, void *);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* GLUE POUR CREATION DEPUIS PYTHON */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : type = type du nouvel objet à mettre en place. *
+* args = éventuelle liste d'arguments. *
+* kwds = éventuel dictionnaire de valeurs mises à disposition. *
+* *
+* Description : Accompagne la création d'une instance dérivée en Python. *
+* *
+* Retour : Nouvel objet Python mis en place ou NULL en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyObject *result; /* Objet à retourner */
+ PyTypeObject *base; /* Type de base à dériver */
+ bool first_time; /* Evite les multiples passages*/
+ GType gtype; /* Nouveau type de processeur */
+ bool status; /* Bilan d'un enregistrement */
+
+ /* Validations diverses */
+
+ base = get_python_buffer_cache_type();
+
+ if (type == base)
+ goto simple_way;
+
+ /* Mise en place d'un type dédié */
+
+ first_time = (g_type_from_name(type->tp_name) == 0);
+
+ gtype = build_dynamic_type(G_TYPE_BUFFER_CACHE, type->tp_name, NULL, NULL, NULL);
+
+ if (first_time)
+ {
+ status = register_class_for_dynamic_pygobject(gtype, type, base);
+
+ if (!status)
+ {
+ result = NULL;
+ goto exit;
+ }
+
+ }
+
+ /* On crée, et on laisse ensuite la main à PyGObject_Type.tp_init() */
+
+ simple_way:
+
+ result = PyType_GenericNew(type, args, kwds);
+
+ exit:
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet à initialiser (théoriquement). *
+* args = arguments fournis à l'appel. *
+* kwds = arguments de type key=val fournis. *
+* *
+* Description : Initialise une instance sur la base du dérivé de GObject. *
+* *
+* Retour : 0. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static int py_buffer_cache_init(PyObject *self, PyObject *args, PyObject *kwds)
+{
+ GBinContent *content; /* Instance GLib du contenu */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Version GLib du tampon */
+
+#define BUFFER_CACHE_DOC \
+ "The BufferCache object manages a group of lines intended to get" \
+ " printed onto the screen or into a file.\n" \
+ "\n" \
+ "These lines are cached and rebuilt when needed.\n" \
+ "\n" \
+ "Instances can be created using the following constructor:\n" \
+ "\n" \
+ " BufferCache(content=None)" \
+ "\n" \
+ "Where content is a pychrysalide.analysis.BinContent instance, if" \
+ " defined. This content is provided to lines as argument when the" \
+ " lines get printed, so it may not be always useful and thus can be" \
+ " discarded when creating a new buffer cache." \
+
+ /* Récupération des paramètres */
+
+ content = NULL;
+
+ ret = PyArg_ParseTuple(args, "|O&", convert_to_binary_content_or_none, &content);
+ if (!ret) return -1;
+
+ /* Initialisation d'un objet GLib */
+
+ ret = forward_pygobjet_init(self);
+ if (ret == -1) return -1;
+
+ /* Eléments de base */
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ if (content != NULL)
+ {
+ cache->content = content;
+ g_object_ref(G_OBJECT(content));
+ }
+
+ return 0;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* TAMPON POUR CODE DESASSEMBLE */
+/* ---------------------------------------------------------------------------------- */
+
/******************************************************************************
* *
* Paramètres : self = classe représentant un tampon de code. *
* args = arguments fournis à l'appel. *
* *
-* Description : Retrouve une ligne au sein d'un tampon avec une adresse. *
+* Description : Insère un générateur dans des lignes à une position donnée. *
* *
-* Retour : Instance de la ligne trouvée. *
+* Retour : - *
* *
* Remarques : - *
* *
******************************************************************************/
-static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args)
+static PyObject *py_buffer_cache_insert_at(PyObject *self, PyObject *args)
{
PyObject *result; /* Trouvailles à retourner */
- PyObject *py_vmpa; /* Localisation version Python */
+ size_t index; /* Indice de ligne à supprimer */
+ GLineGenerator *generator; /* Générateur à associer */
+ BufferLineFlags flags; /* Particularités nominales */
+ int before; /* Insertion avant ? */
+ int after; /* Insertion après ? */
int ret; /* Bilan de lecture des args. */
- vmpa2t *addr; /* Adresse visée par l'opérat° */
- GBuffercache *buffer; /* Version native */
- GBufferLine *line; /* Ligne trouvée */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_INSERT_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ insert_at, "$self, index, generator, /, flags=" \
+ "pychrysalide.glibext.BufferLine.BufferLineFlags.NONE," \
+ " before=False, after=False", \
+ METH_VARARGS, py_buffer_cache, \
+ "Add an extra content generator to a given line.\n" \
+ "\n" \
+ "The new content generator for the line at, before or after" \
+ " the provided index is a pychrysalide.glibext.LineGenerator" \
+ " instance. Nominal properties can be set for this line as" \
+ " extra pychrysalide.glibext.BufferLine.BufferLineFlags" \
+ " values.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
- ret = PyArg_ParseTuple(args, "O", &py_vmpa);
+ flags = BLF_NONE;
+ before = 0;
+ after = 0;
+
+ ret = PyArg_ParseTuple(args, "nO&|O&pp", &index, convert_to_line_generator, &generator,
+ convert_to_buffer_line_flags, &flags, &before, &after);
if (!ret) return NULL;
- ret = PyObject_IsInstance(py_vmpa, (PyObject *)get_python_vmpa_type());
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_insert_at(cache, index, generator, flags, before, after);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Retire une ligne du tampon. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_delete_at(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de ligne à supprimer */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_DELETE_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ delete_at, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Delete the line at the *index* position from a buffer cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
if (!ret) return NULL;
- addr = get_internal_vmpa(py_vmpa);
- if (addr == NULL) return NULL;
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_delete_at(cache, index);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Retire un type de générateur de lignes. *
+* *
+* Retour : Générateur éventuellement trouvé ou NULL si aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_delete_type_at(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de ligne à supprimer */
+ PyObject *py_gtype; /* Version Python d'un GType */
+ int before; /* Insertion avant ? */
+ int after; /* Insertion après ? */
+ int ret; /* Bilan de lecture des args. */
+ GType gtype; /* Type de générateur visé */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GLineGenerator *generator; /* Générateur retiré ou NULL */
+
+#define BUFFER_CACHE_DELETE_TYPE_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ delete_type_at, "$self, index, gtype, /, before=False, after=False", \
+ METH_VARARGS, py_buffer_cache, \
+ "Delete the first generator of a given type found inside a line of a" \
+ " buffer cache.\n" \
+ "\n" \
+ "The target type has to be a gobject.GType, usually provided by the" \
+ " *__gtype__* attribute of a generator interface. The generator is" \
+ " deleted from the line at, before or after the provided index.\n" \
+ "\n" \
+ "The function returns the deleted generator as a" \
+ " pychrysalide.glibext.LineGenerator instance, or None if none found.\n"\
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ before = 0;
+ after = 0;
+
+ ret = PyArg_ParseTuple(args, "nO|pp", &index, &py_gtype, &before, &after);
+ if (!ret) return NULL;
- buffer = G_CODE_BUFFER(pygobject_get(self));
+ gtype = pyg_type_from_object(py_gtype);
+ if (gtype == 0) return NULL;
- line = g_code_buffer_find_line_by_addr(buffer, addr, 0, NULL);
- if (line == NULL) Py_RETURN_NONE;
+ cache = G_BUFFER_CACHE(pygobject_get(self));
- result = pygobject_new(G_OBJECT(line));
+ generator = g_buffer_cache_delete_type_at(cache, index, gtype, before, after);
+
+ if (generator != NULL)
+ {
+ result = pygobject_new(G_OBJECT(generator));
+ g_object_unref(G_OBJECT(generator));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Ajoute en fin de tampon un générateur de lignes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_append(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ GLineGenerator *generator; /* Générateur à associer */
+ BufferLineFlags flags; /* Particularités nominales */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_APPEND_METHOD PYTHON_METHOD_DEF \
+( \
+ append, "$self, generator, /, flags=" \
+ "pychrysalide.glibext.BufferLine.BufferLineFlags.NONE", \
+ METH_VARARGS, py_buffer_cache, \
+ "Append a new line at the end of a buffer cache.\n" \
+ "\n" \
+ "The content generator for this new line is a" \
+ " pychrysalide.glibext.LineGenerator instance. Nominal" \
+ " properties can be set for the line as extra" \
+ " pychrysalide.glibext.BufferLine.BufferLineFlags values.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ flags = BLF_NONE;
+
+ ret = PyArg_ParseTuple(args, "O&|O&", convert_to_line_generator, &generator,
+ convert_to_buffer_line_flags, &flags);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_append(cache, generator, flags);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Etend un tampon avec un générateur de lignes unique. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_extend_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t count; /* Quantité de lignes à créer */
+ GLineGenerator *generator; /* Générateur à associer */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_EXTEND_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ extend_with, "$self, count, generator, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Extend the buffer cache so it will contain *count* lines.\n" \
+ "\n" \
+ "The *count* number should be greater than the current line" \
+ " quantity, otherwise the call makes no sense. The generator" \
+ " is a pychrysalide.glibext.LineGenerator instance used to" \
+ " produce the extra new lines on demand." \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "nO&", &count, convert_to_line_generator, &generator);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_extend_with(cache, count, generator);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Réduit le tampon à une quantité de lignes précise. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_truncate(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t max; /* Nombre de lignes au maximum */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+
+#define BUFFER_CACHE_TRUNCATE_METHOD PYTHON_METHOD_DEF \
+( \
+ truncate, "$self, max, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Shrink the buffer cache so it will contain at most *max* lines.\n" \
+ "\n" \
+ "The *max* number should be lesser than the current line quantity," \
+ " otherwise no effect will happen." \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &max);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ g_buffer_cache_truncate(cache, max);
+
+ result = Py_None;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Détermine l'ensemble des propriétés attachées à une ligne. *
+* *
+* Retour : Somme de toutes les propriétés enregistrées. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_line_flags(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ BufferLineFlags flags; /* Fanions conservés */
+
+#define BUFFER_CACHE_GET_LINE_FLAGS_METHOD PYTHON_METHOD_DEF \
+( \
+ get_line_flags, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Provide the optional flags assigned to a given buffer line. The" \
+ " line is located using the *index* argument.\n" \
+ "\n" \
+ "The result is a pychrysalide.glibext.BufferLine.BufferLineFlags" \
+ " value.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ flags = g_buffer_cache_get_line_flags(cache, index);
+
+ result = cast_with_constants_group_from_type(get_python_buffer_line_type(), "BufferLineFlags", flags);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Retrouve une ligne au sein d'un tampon avec un indice. *
+* *
+* Retour : Line retrouvée ou None en cas d'échec. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_find_line_by_index(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GBufferLine *line; /* Ligne trouvée ? */
+
+#define BUFFER_CACHE_FIND_LINE_BY_INDEX_METHOD PYTHON_METHOD_DEF \
+( \
+ find_line_by_index, "$self, index, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Retrieve the line contained in a buffer cache at a given index.\n" \
+ "\n" \
+ "The result is a pychrysalide.glibext.BufferLine instance or" \
+ " None.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "n", &index);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ line = g_buffer_cache_find_line_by_index(cache, index);
+
+ if (line != NULL)
+ {
+ result = pygobject_new(G_OBJECT(line));
+ g_object_unref(G_OBJECT(line));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = classe représentant un tampon de code. *
+* args = arguments fournis à l'appel. *
+* *
+* Description : Avance autant que possible vers une ligne idéale. *
+* *
+* Retour : Indice de la ligne recherchée, si elle existe. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_look_for_flag(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Trouvailles à retourner */
+ size_t index; /* Indice de la ligne visée */
+ BufferLineFlags flag; /* Particularité à retrouver */
+ int ret; /* Bilan de lecture des args. */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ size_t found; /* Indice de la ligne trouvée */
+
+#define BUFFER_CACHE_LOOK_FOR_FLAG_METHOD PYTHON_METHOD_DEF \
+( \
+ look_for_flag, "$self, index, flag, /", \
+ METH_VARARGS, py_buffer_cache, \
+ "Iterate the buffer cache lines from a starting index until a" \
+ " line with flags matching the provided flag is met.\n" \
+ "\n" \
+ "The *flag* argument has to be a" \
+ " pychrysalide.glibext.BufferLine.BufferLineFlags value.\n" \
+ "\n" \
+ "The result is an index equal or greater than the starting index" \
+ " or, if no match is found, the number of lines in the buffer" \
+ " cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ ret = PyArg_ParseTuple(args, "nO&", &index, convert_to_buffer_line_flags, &flag);
+ if (!ret) return NULL;
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ found = g_buffer_cache_look_for_flag(cache, index, flag);
+
+ result = PyLong_FromSize_t(found);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Indique l'éventuel contenu binaire associé au cache. *
+* *
+* Retour : Eventuel contenu renseigné ou None. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_content(PyObject *self, void *closure)
+{
+ PyObject *result; /* Contenu binaire à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ GBinContent *content; /* Contenu éventuel à renvoyer */
+
+#define BUFFER_CACHE_CONTENT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ content, py_buffer_cache, \
+ "Binary content linked to the buffer cache, as a" \
+ " pychrysalide.analysis.BinContent instance, or None." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ content = g_buffer_cache_get_content(cache);
+
+ if (content != NULL)
+ {
+ result = pygobject_new(G_OBJECT(content));
+ g_object_unref(G_OBJECT(content));
+ }
+
+ else
+ {
+ result = Py_None;
+ Py_INCREF(result);
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la hauteur d'impression d'une ligne visualisée. *
+* *
+* Retour : Hauteur de ligne en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_line_height(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint height; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_LINE_HEIGHT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ line_height, py_buffer_cache, \
+ "Height of a line printed from the buffer cache." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ height = g_buffer_cache_get_line_height(cache);
+
+ result = PyLong_FromLong(height);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la taille réservée pour la marge gauche. *
+* *
+* Retour : Largeur en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_left_margin(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint width; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_LEFT_MARGIN_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ left_margin, py_buffer_cache, \
+ "Width of the left margin inside of a buffer cache output." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ width = g_buffer_cache_get_left_margin(cache);
+
+ result = PyLong_FromLong(width);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Fournit la position de départ pour l'impression de texte. *
+* *
+* Retour : Position en pixels. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_text_position(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ gint pos; /* Valeur obtenue du cache */
+
+#define BUFFER_CACHE_TEXT_POSITION_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ text_position, py_buffer_cache, \
+ "Starting position of the text on the left of a buffer cache output." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ pos = g_buffer_cache_get_text_position(cache);
+
+ result = PyLong_FromLong(pos);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = objet Python concerné par l'appel. *
+* closure = non utilisé ici. *
+* *
+* Description : Compte le nombre de lignes rassemblées dans un tampon. *
+* *
+* Retour : Nombre de lignes constituant le tampon. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_buffer_cache_get_lines_count(PyObject *self, void *closure)
+{
+ PyObject *result; /* Valeur à retourner */
+ GBufferCache *cache; /* Tampon natif à consulter */
+ size_t count; /* Décompte de première main */
+
+#define BUFFER_CACHE_LINES_COUNT_ATTRIB PYTHON_GET_DEF_FULL \
+( \
+ lines_count, py_buffer_cache, \
+ "Count the number of lines contained in a buffer cache.\n" \
+ "\n" \
+ "An access lock has to be held for the cache; see the" \
+ " pychrysalide.glibext.BufferCache.lock() function." \
+)
+
+ cache = G_BUFFER_CACHE(pygobject_get(self));
+
+ count = g_buffer_cache_count_lines(cache);
+
+ result = PyLong_FromSize_t(count);
return result;
}
-#endif
/******************************************************************************
@@ -102,17 +936,24 @@ static PyObject *py_code_buffer_find_line_by_addr(PyObject *self, PyObject *args
PyTypeObject *get_python_buffer_cache_type(void)
{
static PyMethodDef py_buffer_cache_methods[] = {
-#if 0
- {
- "find_line_by_addr", py_buffer_cache_find_line_by_addr,
- METH_VARARGS,
- "find_line_by_addr($self, addr, /)\n--\n\nFind a buffer line with a given address."
- },
-#endif
+ BUFFER_CACHE_INSERT_AT_METHOD,
+ BUFFER_CACHE_DELETE_AT_METHOD,
+ BUFFER_CACHE_DELETE_TYPE_AT_METHOD,
+ BUFFER_CACHE_APPEND_METHOD,
+ BUFFER_CACHE_EXTEND_WITH_METHOD,
+ BUFFER_CACHE_TRUNCATE_METHOD,
+ BUFFER_CACHE_GET_LINE_FLAGS_METHOD,
+ BUFFER_CACHE_FIND_LINE_BY_INDEX_METHOD,
+ BUFFER_CACHE_LOOK_FOR_FLAG_METHOD,
{ NULL }
};
static PyGetSetDef py_buffer_cache_getseters[] = {
+ BUFFER_CACHE_CONTENT_ATTRIB,
+ BUFFER_CACHE_LINE_HEIGHT_ATTRIB,
+ BUFFER_CACHE_LEFT_MARGIN_ATTRIB,
+ BUFFER_CACHE_TEXT_POSITION_ATTRIB,
+ BUFFER_CACHE_LINES_COUNT_ATTRIB,
{ NULL }
};
@@ -125,11 +966,14 @@ PyTypeObject *get_python_buffer_cache_type(void)
.tp_flags = Py_TPFLAGS_DEFAULT,
- .tp_doc = "PyChrysalide code buffer",
+ .tp_doc = BUFFER_CACHE_DOC,
.tp_methods = py_buffer_cache_methods,
.tp_getset = py_buffer_cache_getseters,
+ .tp_init = py_buffer_cache_init,
+ .tp_new = py_buffer_cache_new
+
};
return &py_buffer_cache_type;
@@ -171,3 +1015,48 @@ bool ensure_python_buffer_cache_is_registered(void)
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 tampon de lignes. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_buffer_cache(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_buffer_cache_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 buffer cache");
+ break;
+
+ case 1:
+ *((GBufferCache **)dst) = G_BUFFER_CACHE(pygobject_get(arg));
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}