From b8a99266e691ec5a2a13f10d6c775f4bdc0dbbc2 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 18 Dec 2018 23:54:36 +0100 Subject: Made Python constant values storable using Pickle. --- plugins/pychrysalide/constval.c | 73 ++++++++++++++++++++++++++++++++++++----- tests/constval.py | 30 ++++++++++++++--- 2 files changed, 90 insertions(+), 13 deletions(-) diff --git a/plugins/pychrysalide/constval.c b/plugins/pychrysalide/constval.c index b6d20aa..7067770 100644 --- a/plugins/pychrysalide/constval.c +++ b/plugins/pychrysalide/constval.c @@ -26,6 +26,7 @@ #include +#include #include @@ -46,7 +47,7 @@ typedef struct _PyConstvalObject * de l'objet PyLongObject, dont la taille est dynamique. */ - /*const char *name;*/ /* Désignation de la valeur */ + /*char *name;*/ /* Désignation de la valeur */ } PyConstvalObject; @@ -56,11 +57,14 @@ typedef struct _PyConstvalObject static PyObject *py_constval_new(PyTypeObject *, PyObject *, PyObject *); /* Calcule l'emplacement reservé pour une désignation de valeur. */ -static const char **py_constval_compute_name_ptr(PyConstvalObject *); +static char **py_constval_compute_name_ptr(PyConstvalObject *); /* Construit une représentation textuelle de l'objet. */ static PyObject *py_constval_str(PyObject *); +/* Fournit une réduction de l'objet en vue d'une sérialisation. */ +static PyObject *py_constval_reduce(PyObject *, PyObject *); + /****************************************************************************** @@ -79,9 +83,17 @@ static PyObject *py_constval_str(PyObject *); static PyObject *py_constval_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { - PyErr_Format(PyExc_RuntimeError, _("%s is meant to be only used from C code"), type->tp_name); + PyObject *result; /* Instance à retourner */ + unsigned long value; /* Valeur entière */ + const char *name; /* Désignation humaine */ + int ret; /* Bilan de lecture des args. */ + + ret = PyArg_ParseTuple(args, "ks", &value, &name); + if (!ret) return NULL; + + result = build_constval_from_c_code(name, value); - return NULL; + return result; } @@ -98,7 +110,7 @@ static PyObject *py_constval_new(PyTypeObject *type, PyObject *args, PyObject *k * * ******************************************************************************/ -static const char **py_constval_compute_name_ptr(PyConstvalObject *self) +static char **py_constval_compute_name_ptr(PyConstvalObject *self) { digit *result; /* Adresse mémoire à retourner */ Py_ssize_t size; /* Taille supplémentaire */ @@ -110,7 +122,7 @@ static const char **py_constval_compute_name_ptr(PyConstvalObject *self) result = &self->base.ob_digit[size]; - return (const char **)result; + return (char **)result; } @@ -131,7 +143,7 @@ static PyObject *py_constval_str(PyObject *self) { PyObject *result; /* Elément à retourner */ PyConstvalObject *constval; /* Autre version de l'objet */ - const char **ptr; /* Désignation à convertir */ + char **ptr; /* Désignation à convertir */ constval = (PyConstvalObject *)self; @@ -146,6 +158,44 @@ static PyObject *py_constval_str(PyObject *self) /****************************************************************************** * * +* Paramètres : self = architecture concernée par la procédure. * +* args = instruction représentant le point de départ. * +* * +* Description : Fournit une réduction de l'objet en vue d'une sérialisation. * +* * +* Retour : Données utiles à une reconstruction. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_constval_reduce(PyObject *self, PyObject *args) +{ + PyObject *result; /* Données à retourner */ + unsigned long value; /* Valeur entière */ + PyConstvalObject *constval; /* Autre version de l'objet */ + char **ptr; /* Désignation à convertir */ + PyObject *params; /* Paramètres de construction */ + + value = PyLong_AsUnsignedLong(self); + + constval = (PyConstvalObject *)self; + + ptr = py_constval_compute_name_ptr(constval); + + params = Py_BuildValue("(ks)", value, *ptr); + + result = Py_BuildValue("(OO)", Py_TYPE(self), params); + + Py_DECREF(params); + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : - * * * * Description : Fournit un accès à une définition de type à diffuser. * @@ -159,6 +209,11 @@ static PyObject *py_constval_str(PyObject *self) PyTypeObject *get_python_py_constval_type(void) { static PyMethodDef py_constval_methods[] = { + { + "__reduce__", py_constval_reduce, + METH_NOARGS, + "__reduce__($self, /)\n--\n\nProvide information to rebuild the object." + }, { NULL } }; @@ -249,7 +304,7 @@ PyObject *build_constval_from_c_code(const char *name, unsigned long value) Py_ssize_t size; /* Taille supplémentaire */ PyTypeObject *type; /* Type Python 'PyConstval...' */ PyConstvalObject *constval; /* Autre version de l'objet */ - const char **ptr; /* Désignation à convertir */ + char **ptr; /* Désignation à convertir */ /* Création d'une base de travail */ @@ -293,7 +348,7 @@ PyObject *build_constval_from_c_code(const char *name, unsigned long value) ptr = py_constval_compute_name_ptr(constval); - *ptr = name; + *ptr = strdup(name); return result; diff --git a/tests/constval.py b/tests/constval.py index 4863d39..eafb8d3 100644 --- a/tests/constval.py +++ b/tests/constval.py @@ -5,18 +5,40 @@ from chrysacase import ChrysalideTestCase from pychrysalide import PyConstvalObject from pychrysalide.arch import ArchInstruction +import pickle class TestConstVal(ChrysalideTestCase): """TestCase for PyConstvalObject.""" - def testGI(self): - """Validate the PyConstvalObject implementation.""" + def testCreation(self): + """Validate PyConstvalObject creation from Python.""" + + cst = PyConstvalObject(123, 'XXX') + + self.assertEqual(cst, 123) + + self.assertEqual(str(cst), 'XXX') - with self.assertRaises(RuntimeError): - cv = PyConstvalObject() + + def testString(self): + """Validate the PyConstvalObject implementation.""" self.assertEqual(ArchInstruction.ILT_JUMP, 1) self.assertEqual(str(ArchInstruction.ILT_JUMP), 'ILT_JUMP') + + + def testStorage(self): + """Ensure PyConstvalObject instances are storable.""" + + cst = ArchInstruction.ILT_JUMP + + data = pickle.dumps(cst) + + cst = pickle.loads(data) + + self.assertEqual(cst, ArchInstruction.ILT_JUMP) + + self.assertEqual(str(cst), 'ILT_JUMP') -- cgit v0.11.2-87-g4458