summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/common/bits.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/pychrysalide/common/bits.c')
-rw-r--r--plugins/pychrysalide/common/bits.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/plugins/pychrysalide/common/bits.c b/plugins/pychrysalide/common/bits.c
index 73fd55b..a127251 100644
--- a/plugins/pychrysalide/common/bits.c
+++ b/plugins/pychrysalide/common/bits.c
@@ -65,6 +65,9 @@ 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 *);
+/* Redimensionne un champ de bits. */
+static PyObject *py_bitfield_resize(PyObject *, PyObject *);
+
/* Bascule à 0 un champ de bits dans son intégralité. */
static PyObject *py_bitfield_reset_all(PyObject *, PyObject *);
@@ -77,6 +80,9 @@ static PyObject *py_bitfield_reset(PyObject *, PyObject *);
/* Bascule à 1 une partie d'un champ de bits. */
static PyObject *py_bitfield_set(PyObject *, PyObject *);
+/* Réalise une opération OU logique entre deux champs de bits. */
+static PyObject *py_bitfield_or_at(PyObject *, PyObject *);
+
/* Détermine si un bit est à 1 dans un champ de bits. */
static PyObject *py_bitfield_test(PyObject *, PyObject *);
@@ -86,6 +92,15 @@ static PyObject *py_bitfield_test_none(PyObject *, PyObject *);
/* Détermine si un ensemble de bits est à 1 dans un champ. */
static PyObject *py_bitfield_test_all(PyObject *, PyObject *);
+/* Teste l'état à 0 de bits selon un masque de bits. */
+static PyObject *py_bitfield_test_zeros_with(PyObject *, PyObject *);
+
+/* Teste l'état à 1 de bits selon un masque de bits. */
+static PyObject *py_bitfield_test_ones_with(PyObject *, PyObject *);
+
+/* Recherche un prochain bit défini dans un champ de bits. */
+static PyObject *py_bitfield_find_next_set(PyObject *, PyObject *);
+
/* Indique la taille d'un champ de bits donné. */
static PyObject *py_bitfield_get_size(PyObject *, void *);
@@ -399,6 +414,47 @@ static PyObject *py_bitfield_dup(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = champ de bits à dupliquer. *
+* args = non utilisé ici. *
+* *
+* Description : Redimensionne un champ de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_resize(PyObject *self, PyObject *args)
+{
+ unsigned long length; /* Nouvelle taille à respecter */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+#define BITFIELD_RESIZE_METHOD PYTHON_METHOD_DEF \
+( \
+ resize, "$self, length, /", \
+ METH_VARARGS, py_bitfield, \
+ "Resize a bitfield and fix its new size to *length*.\n" \
+ "\n" \
+ "The new bits get initialized to the same state used at the" \
+ " bitfield creation." \
+)
+
+ ret = PyArg_ParseTuple(args, "k", &length);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ resize_bit_field(&bf->native, length);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = champ de bits à modifier. *
* args = non utilisé ici. *
* *
@@ -552,6 +608,49 @@ static PyObject *py_bitfield_set(PyObject *self, PyObject *args)
* Paramètres : self = champ de bits à consulter. *
* args = arguments fournis pour la conduite de l'opération. *
* *
+* Description : Réalise une opération OU logique entre deux champs de bits. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_or_at(PyObject *self, PyObject *args)
+{
+ bitfield_t *src; /* Seconde champ de bits */
+ unsigned long first; /* Indice du premier bit testé */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+
+#define BITFIELD_OR_AT_METHOD PYTHON_METHOD_DEF \
+( \
+ or_at, "$self, src, first, /", \
+ METH_VARARGS, py_bitfield, \
+ "Perform an OR operation with another bitfield.\n" \
+ "\n" \
+ "The *src* argument is expected to be another" \
+ " pychrysalide.common.BitField instance. The area to" \
+ " process starts at bit *first* from *src*." \
+)
+
+ ret = PyArg_ParseTuple(args, "O&k", convert_to_bitfield, &src, &first);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ or_bit_field_at(bf->native, src, first);
+
+ Py_RETURN_NONE;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
* Description : Détermine si un bit est à 1 dans un champ de bits. *
* *
* Retour : true si le bit correspondant est à l'état haut. *
@@ -695,6 +794,158 @@ static PyObject *py_bitfield_test_all(PyObject *self, PyObject *args)
/******************************************************************************
* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Teste l'état à 0 de bits selon un masque de bits. *
+* *
+* Retour : true si les bits visés sont à l'état bas. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_zeros_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ bitfield_t *mask; /* Champ de bits natif */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+#define BITFIELD_TEST_ZEROS_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ test_zeros_with, "$self, first, mask, /", \
+ METH_VARARGS, py_bitfield, \
+ "Test a range of bits against another bit field.\n" \
+ "\n" \
+ "The area to process starts at bit *first* and the" \
+ " test relies on bits set within the *mask* object.\n" \
+ "\n" \
+ "The result is a boolean value: True if all tested" \
+ " bits are unset, False otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "kO&", &first, convert_to_bitfield, &mask);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_zeros_within_bit_field(bf->native, first, mask);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Teste l'état à 1 de bits selon un masque de bits. *
+* *
+* Retour : true si les bits visés sont à l'état haut. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_test_ones_with(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long first; /* Indice du premier bit testé */
+ bitfield_t *mask; /* Champ de bits natif */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ bool status; /* Bilan d'analyse */
+
+#define BITFIELD_TEST_ONES_WITH_METHOD PYTHON_METHOD_DEF \
+( \
+ test_ones_with, "$self, first, mask, /", \
+ METH_VARARGS, py_bitfield, \
+ "Test a range of bits against another bit field.\n" \
+ "\n" \
+ "The area to process starts at bit *first* and the" \
+ " test relies on bits set within the *mask* object.\n" \
+ "\n" \
+ "The result is a boolean value: True if all tested" \
+ " bits are set, False otherwise." \
+)
+
+ ret = PyArg_ParseTuple(args, "kO&", &first, convert_to_bitfield, &mask);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ status = test_ones_within_bit_field(bf->native, first, mask);
+
+ result = status ? Py_True : Py_False;
+ Py_INCREF(result);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : self = champ de bits à consulter. *
+* args = arguments fournis pour la conduite de l'opération. *
+* *
+* Description : Recherche un prochain bit défini dans un champ de bits. *
+* *
+* Retour : Position d'un bit à 1 ou taille du champ si plus aucun. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static PyObject *py_bitfield_find_next_set(PyObject *self, PyObject *args)
+{
+ PyObject *result; /* Bilan à faire remonter */
+ unsigned long prev; /* Indice d'un bit à écarter */
+ int ret; /* Bilan de lecture des args. */
+ py_bitfield_t *bf; /* Instance à manipuler */
+ size_t found; /* Indice de bit trouvé */
+
+#define BITFIELD_FIND_NEXT_SET_METHOD PYTHON_METHOD_DEF \
+( \
+ find_next_set, "$self, /, prev=None", \
+ METH_VARARGS, py_bitfield, \
+ "Find the index of the next set bit in the bit field.\n"\
+ "\n" \
+ "If provided, the *prev* argument is the position of" \
+ " a previously found bit, which gets discarded for the" \
+ " current call.\n" \
+ "\n" \
+ "The result is a integer value: a valid index inside" \
+ " the bit field, or the bit field size if no set bit" \
+ " is found." \
+)
+
+ prev = (unsigned long)-1;
+
+ ret = PyArg_ParseTuple(args, "|k", &prev);
+ if (!ret) return NULL;
+
+ bf = (py_bitfield_t *)self;
+
+ found = find_next_set_in_bit_field(bf->native, prev == (unsigned long)-1 ? NULL : (size_t []) { prev });
+
+ result = PyLong_FromSize_t(found);
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : self = classe représentant une instruction. *
* closure = adresse non utilisée ici. *
* *
@@ -791,13 +1042,18 @@ PyTypeObject *get_python_bitfield_type(void)
static PyMethodDef py_bitfield_methods[] = {
BITFIELD_DUP_METHOD,
+ BITFIELD_RESIZE_METHOD,
BITFIELD_RESET_ALL_METHOD,
BITFIELD_SET_ALL_METHOD,
BITFIELD_RESET_METHOD,
BITFIELD_SET_METHOD,
+ BITFIELD_OR_AT_METHOD,
BITFIELD_TEST_METHOD,
BITFIELD_TEST_NONE_METHOD,
BITFIELD_TEST_ALL_METHOD,
+ BITFIELD_TEST_ZEROS_WITH_METHOD,
+ BITFIELD_TEST_ONES_WITH_METHOD,
+ BITFIELD_FIND_NEXT_SET_METHOD,
{ NULL }
};
@@ -876,6 +1132,51 @@ bool ensure_python_bitfield_is_registered(void)
/******************************************************************************
* *
+* 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 champ de bits. *
+* *
+* Retour : Bilan de l'opération, voire indications supplémentaires. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int convert_to_bitfield(PyObject *arg, void *dst)
+{
+ int result; /* Bilan à retourner */
+
+ result = PyObject_IsInstance(arg, (PyObject *)get_python_bitfield_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 bit field");
+ break;
+
+ case 1:
+ *((bitfield_t **)dst) = ((py_bitfield_t *)arg)->native;
+ break;
+
+ default:
+ assert(false);
+ break;
+
+ }
+
+ return result;
+
+}
+
+
+/******************************************************************************
+* *
* Paramètres : field = structure interne à copier en objet Python. *
* *
* Description : Convertit une structure de type 'bitfield_t' en objet Python.*