From 90184484440afd7bc4b85587f450c1b9ccd6e8de Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Tue, 30 Jun 2020 23:55:41 +0200 Subject: Updated the Python API for bitfields. --- plugins/pychrysalide/common/bits.c | 238 ++++++++++++++++++++++------------- plugins/pychrysalide/common/bits.h | 4 +- plugins/pychrysalide/common/packed.c | 4 +- tests/common/bitfield.py | 60 ++++----- 4 files changed, 180 insertions(+), 126 deletions(-) diff --git a/plugins/pychrysalide/common/bits.c b/plugins/pychrysalide/common/bits.c index 236bcd6..73fd55b 100644 --- a/plugins/pychrysalide/common/bits.c +++ b/plugins/pychrysalide/common/bits.c @@ -47,9 +47,6 @@ static void py_bitfield_dealloc(py_bitfield_t *); /* Initialise un objet Python de type 'bitfield_t'. */ static int py_bitfield_init(py_bitfield_t *, PyObject *, PyObject *); -/* Crée une copie d'un champ de bits classique. */ -static PyObject *py_bitfield_dup(PyObject *, PyObject *); - /* Effectue une opération de type 'and' avec le type 'bitfield'. */ static PyObject *py_bitfield_nb_and(PyObject *, PyObject *); @@ -65,6 +62,9 @@ static PyObject *py_bitfield_sequence_item(PyObject *, Py_ssize_t); /* Effectue une comparaison avec un objet Python 'bitfield'. */ static PyObject *py_bitfield_richcompare(PyObject *, PyObject *, int); +/* Crée une copie d'un champ de bits classique. */ +static PyObject *py_bitfield_dup(PyObject *, PyObject *); + /* Bascule à 0 un champ de bits dans son intégralité. */ static PyObject *py_bitfield_reset_all(PyObject *, PyObject *); @@ -90,7 +90,7 @@ static PyObject *py_bitfield_test_all(PyObject *, PyObject *); static PyObject *py_bitfield_get_size(PyObject *, void *); /* Détermine le nombre de bits à 1 dans un champ. */ -static PyObject *py_bitfield_popcount(PyObject *, void *); +static PyObject *py_bitfield_get_popcount(PyObject *, void *); @@ -136,6 +136,17 @@ static int py_bitfield_init(py_bitfield_t *self, PyObject *args, PyObject *kwds) int state; /* Initialisation par défaut */ int ret; /* Bilan de lecture des args. */ +#define BITFIELD_DOC \ + "The BitField object describes a group of bits and provides" \ + " operations on it.\n" \ + "\n" \ + "Instances can be created using the following constructor:\n" \ + "\n" \ + " BitField(length, state)" \ + "\n" \ + "Where *length* is the size of the bitfield and *state*" \ + " defines the initial state of each bits." \ + result = -1; ret = PyArg_ParseTuple(args, "kp", &length, &state); @@ -154,33 +165,6 @@ static int py_bitfield_init(py_bitfield_t *self, PyObject *args, PyObject *kwds) /****************************************************************************** * * -* Paramètres : self = champ de bits à dupliquer. * -* args = non utilisé ici. * -* * -* Description : Crée une copie d'un champ de bits classique. * -* * -* Retour : Champ de bits mis en place. * -* * -* Remarques : - * -* * -******************************************************************************/ - -static PyObject *py_bitfield_dup(PyObject *self, PyObject *args) -{ - PyObject *result; /* Instance à retourner */ - py_bitfield_t *bf; /* Instance à manipuler */ - - bf = (py_bitfield_t *)self; - - result = build_from_internal_bitfield(bf->native);; - - return result; - -} - - -/****************************************************************************** -* * * Paramètres : o1 = premier élément concerné par l'opération. * * o2 = second élément concerné par l'opération. * * * @@ -378,6 +362,43 @@ static PyObject *py_bitfield_richcompare(PyObject *a, PyObject *b, int op) /****************************************************************************** * * +* Paramètres : self = champ de bits à dupliquer. * +* args = non utilisé ici. * +* * +* Description : Crée une copie d'un champ de bits classique. * +* * +* Retour : Champ de bits mis en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_bitfield_dup(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + py_bitfield_t *bf; /* Instance à manipuler */ + +#define BITFIELD_DUP_METHOD PYTHON_METHOD_DEF \ +( \ + dup, "$self, /", \ + METH_NOARGS, py_bitfield, \ + "Duplicate a bitfield.\n" \ + "\n" \ + "The result is a new pychrysalide.common.BitField with the same" \ + " content." \ +) + + bf = (py_bitfield_t *)self; + + result = build_from_internal_bitfield(bf->native);; + + return result; + +} + + +/****************************************************************************** +* * * Paramètres : self = champ de bits à modifier. * * args = non utilisé ici. * * * @@ -393,6 +414,13 @@ static PyObject *py_bitfield_reset_all(PyObject *self, PyObject *args) { py_bitfield_t *bf; /* Instance à manipuler */ +#define BITFIELD_RESET_ALL_METHOD PYTHON_METHOD_DEF \ +( \ + reset_all, "$self, /", \ + METH_NOARGS, py_bitfield, \ + "Switch to 0 all bits in a bitfield." \ +) + bf = (py_bitfield_t *)self; reset_all_in_bit_field(bf->native); @@ -419,6 +447,13 @@ static PyObject *py_bitfield_set_all(PyObject *self, PyObject *args) { py_bitfield_t *bf; /* Instance à manipuler */ +#define BITFIELD_SET_ALL_METHOD PYTHON_METHOD_DEF \ +( \ + set_all, "$self, /", \ + METH_NOARGS, py_bitfield, \ + "Switch to 1 all bits in a bitfield." \ +) + bf = (py_bitfield_t *)self; set_all_in_bit_field(bf->native); @@ -448,6 +483,16 @@ static PyObject *py_bitfield_reset(PyObject *self, PyObject *args) int ret; /* Bilan de lecture des args. */ py_bitfield_t *bf; /* Instance à manipuler */ +#define BITFIELD_RESET_METHOD PYTHON_METHOD_DEF \ +( \ + reset, "$self, first, count, /", \ + METH_VARARGS, py_bitfield, \ + "Switch to 0 a part of bits in a bitfield.\n" \ + "\n" \ + "The area to process starts at bit *first* and has a" \ + " size of *count* bits." \ +) + ret = PyArg_ParseTuple(args, "kk", &first, &count); if (!ret) return NULL; @@ -480,6 +525,16 @@ static PyObject *py_bitfield_set(PyObject *self, PyObject *args) int ret; /* Bilan de lecture des args. */ py_bitfield_t *bf; /* Instance à manipuler */ +#define BITFIELD_SET_METHOD PYTHON_METHOD_DEF \ +( \ + set, "$self, first, count, /", \ + METH_VARARGS, py_bitfield, \ + "Switch to 1 a part of bits in a bitfield.\n" \ + "\n" \ + "The area to process starts at bit *first* and has a" \ + " size of *count* bits." \ +) + ret = PyArg_ParseTuple(args, "kk", &first, &count); if (!ret) return NULL; @@ -513,6 +568,16 @@ static PyObject *py_bitfield_test(PyObject *self, PyObject *args) py_bitfield_t *bf; /* Instance à manipuler */ bool status; /* Bilan d'analyse */ +#define BITFIELD_TEST_METHOD PYTHON_METHOD_DEF \ +( \ + test, "$self, n, /", \ + METH_VARARGS, py_bitfield, \ + "Test if a given bit is set in a bitfield.\n" \ + "\n" \ + "The result is a boolean value: True if the tested" \ + " *n* bit is set, False otherwise." \ +) + ret = PyArg_ParseTuple(args, "k", &n); if (!ret) return NULL; @@ -521,7 +586,6 @@ static PyObject *py_bitfield_test(PyObject *self, PyObject *args) status = test_in_bit_field(bf->native, n); result = status ? Py_True : Py_False; - Py_INCREF(result); return result; @@ -551,6 +615,19 @@ static PyObject *py_bitfield_test_none(PyObject *self, PyObject *args) py_bitfield_t *bf; /* Instance à manipuler */ bool status; /* Bilan d'analyse */ +#define BITFIELD_TEST_NONE_METHOD PYTHON_METHOD_DEF \ +( \ + test_none, "$self, first, count, /", \ + METH_VARARGS, py_bitfield, \ + "Test a range of bits against 0.\n" \ + "\n" \ + "The area to process starts at bit *first* and has a" \ + " size of *count* bits." \ + "\n" \ + "The result is a boolean value: True if all tested" \ + " bits are unset, False otherwise." \ +) + ret = PyArg_ParseTuple(args, "kk", &first, &count); if (!ret) return NULL; @@ -559,7 +636,6 @@ static PyObject *py_bitfield_test_none(PyObject *self, PyObject *args) status = test_none_in_bit_field(bf->native, first, count); result = status ? Py_True : Py_False; - Py_INCREF(result); return result; @@ -589,6 +665,19 @@ static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args) py_bitfield_t *bf; /* Instance à manipuler */ bool status; /* Bilan d'analyse */ +#define BITFIELD_TEST_ALL_METHOD PYTHON_METHOD_DEF \ +( \ + test_all, "$self, first, count, /", \ + METH_VARARGS, py_bitfield, \ + "Test a range of bits against 1.\n" \ + "\n" \ + "The area to process starts at bit *first* and has a" \ + " size of *count* bits." \ + "\n" \ + "The result is a boolean value: True if all tested" \ + " bits are set, False otherwise." \ +) + ret = PyArg_ParseTuple(args, "kk", &first, &count); if (!ret) return NULL; @@ -597,7 +686,6 @@ static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args) status = test_all_in_bit_field(bf->native, first, count); result = status ? Py_True : Py_False; - Py_INCREF(result); return result; @@ -624,6 +712,12 @@ static PyObject *py_bitfield_get_size(PyObject *self, void *closure) py_bitfield_t *bf; /* Instance à manipuler */ size_t size; /* Taille du champs de bits */ +#define BITFIELD_SIZE_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + size, py_bitfield, \ + "Provide the size of the bitfield." \ +) + bf = (py_bitfield_t *)self; size = get_bit_field_size(bf->native); @@ -648,12 +742,18 @@ static PyObject *py_bitfield_get_size(PyObject *self, void *closure) * * ******************************************************************************/ -static PyObject *py_bitfield_popcount(PyObject *self, void *closure) +static PyObject *py_bitfield_get_popcount(PyObject *self, void *closure) { PyObject *result; /* Conversion à retourner */ py_bitfield_t *bf; /* Instance à manipuler */ size_t count; /* Quantité de bits à 1 */ +#define BITFIELD_POPCOUNT_ATTRIB PYTHON_GET_DEF_FULL \ +( \ + popcount, py_bitfield, \ + "Get the number of bits set to 1 in the bitfield." \ +) + bf = (py_bitfield_t *)self; count = popcount_for_bit_field(bf->native); @@ -680,10 +780,8 @@ static PyObject *py_bitfield_popcount(PyObject *self, void *closure) PyTypeObject *get_python_bitfield_type(void) { static PyNumberMethods py_bitfield_nb_proto = { - .nb_and = py_bitfield_nb_and, .nb_or = py_bitfield_nb_or - }; static PySequenceMethods py_bitfield_sequence_proto = { @@ -692,58 +790,20 @@ PyTypeObject *get_python_bitfield_type(void) }; static PyMethodDef py_bitfield_methods[] = { - { - "dup", py_bitfield_dup, - METH_NOARGS, - "dup(self, /)\n--\n\nDuplicate a bitfield." - }, - { - "reset_all", py_bitfield_reset_all, - METH_NOARGS, - "reset_all(self, /)\n--\n\nSwitch to 0 all bits in a bitfield." - }, - { - "set_all", py_bitfield_set_all, - METH_NOARGS, - "set_all(self, /)\n--\n\nSwitch to 1 all bits in a bitfield." - }, - { - "reset", py_bitfield_reset, - METH_VARARGS, - "reset(self, first, count, /)\n--\n\nSwitch to 0 a part of bits in a bitfield." - }, - { - "set", py_bitfield_set, - METH_VARARGS, - "set(self, first, count, /)\n--\n\nSwitch to 1 a part of bits in a bitfield." - }, - { - "test", py_bitfield_test, - METH_VARARGS, - "test(self, n, /)\n--\n\nTest if a given bit is set in a bitfield." - }, - { - "test_none", py_bitfield_test_none, - METH_VARARGS, - "test_none(self, first, count, /)\n--\n\nTest a range of bits to 0." - }, - { - "test_all", py_bitfield_test_all, - METH_VARARGS, - "test_all(self, first, count, /)\n--\n\nTest a range of bits to 1." - }, + BITFIELD_DUP_METHOD, + BITFIELD_RESET_ALL_METHOD, + BITFIELD_SET_ALL_METHOD, + BITFIELD_RESET_METHOD, + BITFIELD_SET_METHOD, + BITFIELD_TEST_METHOD, + BITFIELD_TEST_NONE_METHOD, + BITFIELD_TEST_ALL_METHOD, { NULL } }; static PyGetSetDef py_bitfield_getseters[] = { - { - "size", py_bitfield_get_size, NULL, - "Provide the size of the bitfield.", NULL - }, - { - "popcount", py_bitfield_popcount, NULL, - "Get the number of bits set to 1 in the bitfield.", NULL - }, + BITFIELD_SIZE_ATTRIB, + BITFIELD_POPCOUNT_ATTRIB, { NULL } }; @@ -751,7 +811,7 @@ PyTypeObject *get_python_bitfield_type(void) PyVarObject_HEAD_INIT(NULL, 0) - .tp_name = "pychrysalide.common.bitfield", + .tp_name = "pychrysalide.common.BitField", .tp_basicsize = sizeof(py_bitfield_t), .tp_dealloc = (destructor)py_bitfield_dealloc, @@ -761,7 +821,7 @@ PyTypeObject *get_python_bitfield_type(void) .tp_flags = Py_TPFLAGS_DEFAULT, - .tp_doc = "Python object for bitfield_t.", + .tp_doc = BITFIELD_DOC, .tp_richcompare = py_bitfield_richcompare, @@ -782,7 +842,7 @@ PyTypeObject *get_python_bitfield_type(void) * * * Paramètres : module = module dont la définition est à compléter. * * * -* Description : Prend en charge l'objet 'pychrysalide.common.bitfield'. * +* Description : Prend en charge l'objet 'pychrysalide.common.BitField'. * * * * Retour : Bilan de l'opération. * * * @@ -818,7 +878,7 @@ bool ensure_python_bitfield_is_registered(void) * * * Paramètres : field = structure interne à copier en objet Python. * * * -* Description : Convertit une structure de type 'bitfield' en objet Python. * +* Description : Convertit une structure de type 'bitfield_t' en objet Python.* * * * Retour : Object Python résultant de la conversion opérée. * * * diff --git a/plugins/pychrysalide/common/bits.h b/plugins/pychrysalide/common/bits.h index 4a3b90b..6ddaaa5 100644 --- a/plugins/pychrysalide/common/bits.h +++ b/plugins/pychrysalide/common/bits.h @@ -37,10 +37,10 @@ /* Fournit un accès à une définition de type à diffuser. */ PyTypeObject *get_python_bitfield_type(void); -/* Prend en charge l'objet 'pychrysalide.common.bitfield'. */ +/* Prend en charge l'objet 'pychrysalide.common.BitField'. */ bool ensure_python_bitfield_is_registered(void); -/* Convertit une structure de type 'bitfield' en objet Python. */ +/* Convertit une structure de type 'bitfield_t' en objet Python. */ PyObject *build_from_internal_bitfield(const bitfield_t *); diff --git a/plugins/pychrysalide/common/packed.c b/plugins/pychrysalide/common/packed.c index c7fa296..405e241 100644 --- a/plugins/pychrysalide/common/packed.c +++ b/plugins/pychrysalide/common/packed.c @@ -112,8 +112,8 @@ static int py_packed_buffer_init(py_packed_buffer_t *self, PyObject *args, PyObj int result; /* Bilan à retourner */ #define PACKED_BUFFER_DOC \ - "The PackedBuffer is mainly used as helper for the storage of GLib" \ - " objects over the network or into files.\n" \ + "The PackedBuffer object is mainly used as helper for the storage" \ + " of GLib objects over the network or into files.\n" \ "\n" \ "The same kind of features as the Python *struct* module are" \ " provided to store and retrieve data.\n" \ diff --git a/tests/common/bitfield.py b/tests/common/bitfield.py index 717181c..e014111 100644 --- a/tests/common/bitfield.py +++ b/tests/common/bitfield.py @@ -1,21 +1,15 @@ -#!/usr/bin/python3-dbg -# -*- coding: utf-8 -*- - - -# Tests pour valider la manipulation des champs de bits. - from chrysacase import ChrysalideTestCase -from pychrysalide.common import bitfield +from pychrysalide.common import BitField -class TestBitfields(ChrysalideTestCase): - """TestCase for common.bitfield*""" +class TestBitFields(ChrysalideTestCase): + """TestCase for common.BitField*""" - def testDuplicateBitfield(self): + def testDuplicateBitField(self): """Check duplicated bitfield value.""" - bf = bitfield(10, 0) + bf = BitField(10, 0) bf2 = bf.dup() @@ -26,40 +20,40 @@ class TestBitfields(ChrysalideTestCase): self.assertEqual(bf.popcount, bf2.popcount) - def testBitfieldValues(self): + def testBitFieldValues(self): """Evaluate bitfields basic values.""" - bf_a = bitfield(75, 1) + bf_a = BitField(75, 1) - bf_b = bitfield(75, 0) + bf_b = BitField(75, 0) self.assertNotEqual(bf_a, bf_b) - bf_a = bitfield(75, 1) + bf_a = BitField(75, 1) - bf_b = bitfield(75, 0) + bf_b = BitField(75, 0) bf_b.set_all() self.assertEqual(bf_a, bf_b) self.assertEqual(bf_a.popcount, bf_b.popcount) - bf_a = bitfield(75, 1) + bf_a = BitField(75, 1) bf_a.reset_all() - bf_b = bitfield(75, 0) + bf_b = BitField(75, 0) self.assertEqual(bf_a, bf_b) self.assertEqual(bf_a.popcount, bf_b.popcount) - def testBitfieldLogicalOperations(self): + def testBitFieldLogicalOperations(self): """Perform logical operations on bitfields.""" - bf_a = bitfield(75, 1) + bf_a = BitField(75, 1) - bf_b = bitfield(75, 0) + bf_b = BitField(75, 0) self.assertEqual(bf_a.size, bf_b.size) @@ -76,14 +70,14 @@ class TestBitfields(ChrysalideTestCase): self.assertEqual(bf_f.popcount, bf_a.popcount) - def testBitfieldSwitch(self): + def testBitFieldSwitch(self): """Switch various bits in bitfields.""" - bf_1 = bitfield(75, 1) + bf_1 = BitField(75, 1) - bf_0 = bitfield(75, 0) + bf_0 = BitField(75, 0) - bf_t = bitfield(75, 0) + bf_t = BitField(75, 0) for i in range(75): bf_t.set(i, 1) @@ -100,10 +94,10 @@ class TestBitfields(ChrysalideTestCase): self.assertEqual(bf_t.popcount, bf_0.popcount) - def testBitfieldBits(self): + def testBitFieldBits(self): """Test bits in bitfields.""" - bf = bitfield(54, 1) + bf = BitField(54, 1) self.assertTrue(bf.test(0)) @@ -113,7 +107,7 @@ class TestBitfields(ChrysalideTestCase): self.assertFalse(bf.test_none(0, 54)) - bf = bitfield(54, 0) + bf = BitField(54, 0) self.assertFalse(bf.test(0)) @@ -124,23 +118,23 @@ class TestBitfields(ChrysalideTestCase): self.assertTrue(bf.test_none(0, 54)) - def testPopCountForBitfield(self): + def testPopCountForBitField(self): """Count bits set to 1 in bitfield.""" - bf = bitfield(65, 1) + bf = BitField(65, 1) self.assertEqual(bf.size, 65) self.assertEqual(bf.popcount, 65) - def testBitfieldComparison(self): + def testBitFieldComparison(self): """Check bitfield comparison.""" - bf_a = bitfield(9, 0) + bf_a = BitField(9, 0) bf_a.set(0, 1) bf_a.set(5, 1) - bf_b = bitfield(9, 1) + bf_b = BitField(9, 1) self.assertNotEqual(bf_a, bf_b) -- cgit v0.11.2-87-g4458