From f06602ac36b4ad7974d836aad76ed236a7a0c942 Mon Sep 17 00:00:00 2001 From: Cyrille Bagard Date: Fri, 21 Apr 2023 06:28:03 +0200 Subject: Implement the itoa() non-standard function. --- plugins/pychrysalide/common/Makefile.am | 1 + plugins/pychrysalide/common/itoa.c | 124 +++++++++++++++++++++++++++++ plugins/pychrysalide/common/itoa.h | 39 +++++++++ plugins/pychrysalide/common/module.c | 2 + src/common/Makefile.am | 1 + src/common/itoa.c | 135 ++++++++++++++++++++++++++++++++ src/common/itoa.h | 34 ++++++++ tests/common/itoa.py | 28 +++++++ 8 files changed, 364 insertions(+) create mode 100644 plugins/pychrysalide/common/itoa.c create mode 100644 plugins/pychrysalide/common/itoa.h create mode 100644 src/common/itoa.c create mode 100644 src/common/itoa.h create mode 100644 tests/common/itoa.py diff --git a/plugins/pychrysalide/common/Makefile.am b/plugins/pychrysalide/common/Makefile.am index 7e1ba9e..b5249b9 100644 --- a/plugins/pychrysalide/common/Makefile.am +++ b/plugins/pychrysalide/common/Makefile.am @@ -5,6 +5,7 @@ libpychrysacommon_la_SOURCES = \ bits.h bits.c \ fnv1a.h fnv1a.c \ hex.h hex.c \ + itoa.h itoa.c \ leb128.h leb128.c \ module.h module.c \ packed.h packed.c \ diff --git a/plugins/pychrysalide/common/itoa.c b/plugins/pychrysalide/common/itoa.c new file mode 100644 index 0000000..107b047 --- /dev/null +++ b/plugins/pychrysalide/common/itoa.c @@ -0,0 +1,124 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * itoa.c - équivalent Python du fichier "common/itoa.c" + * + * Copyright (C) 2023 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 "itoa.h" + + +#include + + +#include "../access.h" +#include "../helpers.h" + + + +/* Détermine l'empreinte Itoa d'une chaîne de caractères. */ +static PyObject *py_itoa(PyObject *, PyObject *); + + + +/****************************************************************************** +* * +* Paramètres : self = NULL car méthode statique. * +* args = arguments fournis lors de l'appel à la fonction. * +* * +* Description : Convertit une valeur en une forme textuelle. * +* * +* Retour : Chaîne de caractères mises en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +static PyObject *py_itoa(PyObject *self, PyObject *args) +{ + PyObject *result; /* Instance à retourner */ + long long n; /* Valeur à transformer */ + unsigned char base; /* Base de travail */ + int ret; /* Bilan de lecture des args. */ + char *strval; /* Valeur sous forme de chaîne */ + +#define ITOA_METHOD PYTHON_METHOD_DEF \ +( \ + itoa, "n, /, base=10", \ + METH_VARARGS, py, \ + "Construct a string representation of an integer *n* according" \ + " to a given *base*.\n" \ + "\n" \ + "Both arguments are expected to be integer values; the result" \ + " is a string or None in case of failure." \ +) + + base = 10; + + ret = PyArg_ParseTuple(args, "L|b", &n, &base); + if (!ret) return NULL; + + strval = itoa(n, base); + + if (strval != NULL) + { + result = PyUnicode_FromString(strval); + free(strval); + } + else + { + result = Py_None; + Py_INCREF(result); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : - * +* * +* Description : Définit une extension du module 'common' à compléter. * +* * +* Retour : Bilan de l'opération. * +* * +* Remarques : - * +* * +******************************************************************************/ + +bool populate_common_module_with_itoa(void) +{ + bool result; /* Bilan à retourner */ + PyObject *module; /* Module à recompléter */ + + static PyMethodDef py_itoa_methods[] = { + ITOA_METHOD, + { NULL } + }; + + module = get_access_to_python_module("pychrysalide.common"); + + result = register_python_module_methods(module, py_itoa_methods); + + return result; + +} diff --git a/plugins/pychrysalide/common/itoa.h b/plugins/pychrysalide/common/itoa.h new file mode 100644 index 0000000..a66e767 --- /dev/null +++ b/plugins/pychrysalide/common/itoa.h @@ -0,0 +1,39 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * itoa.h - prototypes pour l'équivalent Python du fichier "common/itoa.c" + * + * Copyright (C) 2023 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_PYCHRYSALIDE_COMMON_ITOA_H +#define _PLUGINS_PYCHRYSALIDE_COMMON_ITOA_H + + +#include +#include + + + +/* Définit une extension du module 'common' à compléter. */ +bool populate_common_module_with_itoa(void); + + + +#endif /* _PLUGINS_PYCHRYSALIDE_COMMON_ITOA_H */ diff --git a/plugins/pychrysalide/common/module.c b/plugins/pychrysalide/common/module.c index 6ced1b7..a0042ee 100644 --- a/plugins/pychrysalide/common/module.c +++ b/plugins/pychrysalide/common/module.c @@ -28,6 +28,7 @@ #include "bits.h" #include "fnv1a.h" #include "hex.h" +#include "itoa.h" #include "leb128.h" #include "packed.h" #include "pathname.h" @@ -99,6 +100,7 @@ bool populate_common_module(void) if (result) result = populate_common_module_with_fnv1a(); if (result) result = populate_common_module_with_hex(); + if (result) result = populate_common_module_with_itoa(); if (result) result = populate_common_module_with_leb128(); if (result) result = populate_common_module_with_pathname(); if (result) result = populate_common_module_with_pearson(); diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 2f6fd6d..4da8170 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -17,6 +17,7 @@ libcommon_la_SOURCES = \ hex.h hex.c \ ibuf.h ibuf.c \ io.h io.c \ + itoa.h itoa.c \ fnv1a.h fnv1a.c \ leb128.h leb128.c \ macros.h \ diff --git a/src/common/itoa.c b/src/common/itoa.c new file mode 100644 index 0000000..56fc638 --- /dev/null +++ b/src/common/itoa.c @@ -0,0 +1,135 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * itoa.c - conversion d'un nombre en chaîne de caractères + * + * Copyright (C) 2023 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 Chrysalide. If not, see . + */ + + +#include "itoa.h" + + +#include +#include +#include + + + +/****************************************************************************** +* * +* Paramètres : n = nombre à transformer. * +* base = base à considérer pour la sortie. * +* * +* Description : Convertit une valeur en une forme textuelle. * +* * +* Retour : Chaîne de caractères mises en place. * +* * +* Remarques : - * +* * +******************************************************************************/ + +char *itoa(long long n, unsigned char base) +{ + char *result; /* Texte à retourner */ + size_t size; /* Taille de chaîne en sortie */ + char *iter; /* Tête d'écriture */ +#ifndef NDEBUG + size_t counter; /* Décompte des impressions */ +#endif + long long rem; /* Unité à transposer */ + + /** + * Préparation du stockage de la chaîne finale. + */ + + if (n == 0) + size = 1; + + else if (n < 0) + { + size = (size_t)(log(-n) / log(base) + 1); + size++; + } + else + size = (size_t)(log(n) / log(base) + 1); + + /* '\0' final */ + size++; + + result = malloc(size); + if (result == NULL) goto exit; + + /** + * Remplissage avec la valeur textuelle correspondant à la valeur fournie. + */ + +#ifndef NDEBUG + counter = 0; +#endif + + if (n < 0) + { + result[0] = '-'; +#ifndef NDEBUG + counter++; +#endif + + n *= -1; + + } + + iter = result + size - 1; + + *iter-- = '\0'; +#ifndef NDEBUG + counter++; +#endif + + if (n == 0) + { + *iter-- = '0'; +#ifndef NDEBUG + counter++; +#endif + } + + else + while (n > 0) + { + rem = n % base; + + if (rem >= 10) + *iter-- = 'a' + (rem - 10); + else + *iter-- = '0' + rem; + +#ifndef NDEBUG + counter++; +#endif + + n = n / base; + + } + + assert(counter < size); + + exit: + + return result; + +} diff --git a/src/common/itoa.h b/src/common/itoa.h new file mode 100644 index 0000000..4608a50 --- /dev/null +++ b/src/common/itoa.h @@ -0,0 +1,34 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * itoa.h - prototypes pour la conversion d'un nombre en chaîne de caractères + * + * Copyright (C) 2023 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 Chrysalide. If not, see . + */ + + +#ifndef _COMMON_ITOA_H +#define _COMMON_ITOA_H + + + +/* Convertit une valeur en une forme textuelle. */ +char *itoa(long long, unsigned char); + + + +#endif /* _COMMON_ITOA_H */ diff --git a/tests/common/itoa.py b/tests/common/itoa.py new file mode 100644 index 0000000..a004cbd --- /dev/null +++ b/tests/common/itoa.py @@ -0,0 +1,28 @@ + +from chrysacase import ChrysalideTestCase +from pychrysalide.common import itoa + + +class TestItoa(ChrysalideTestCase): + """TestCase for calls to the itoa() implementation.""" + + def testItoaCallss(self): + """Convert some integer values into strings.""" + + val = itoa(123, 10) + self.assertEqual(val, '123') + + val = itoa(-123, 10) + self.assertEqual(val, '-123') + + val = itoa(0, 10) + self.assertEqual(val, '0') + + val = itoa(0, 2) + self.assertEqual(val, '0') + + val = itoa(127, 2) + self.assertEqual(val, '1111111') + + val = itoa(101, 2) + self.assertEqual(val, '1100101') -- cgit v0.11.2-87-g4458