diff options
| author | stainer_t <thomas.stainer@oecd-nea.org> | 2025-09-08 13:48:49 +0200 |
|---|---|---|
| committer | stainer_t <thomas.stainer@oecd-nea.org> | 2025-09-08 13:48:49 +0200 |
| commit | 7dfcc480ba1e19bd3232349fc733caef94034292 (patch) | |
| tree | 03ee104eb8846d5cc1a981d267687a729185d3f3 /PyGan/src/lifomodule.c | |
Initial commit from Polytechnique Montreal
Diffstat (limited to 'PyGan/src/lifomodule.c')
| -rw-r--r-- | PyGan/src/lifomodule.c | 528 |
1 files changed, 528 insertions, 0 deletions
diff --git a/PyGan/src/lifomodule.c b/PyGan/src/lifomodule.c new file mode 100644 index 0000000..a71f949 --- /dev/null +++ b/PyGan/src/lifomodule.c @@ -0,0 +1,528 @@ + +/*--------------------------------*/ +/* Python3-Lifo bindings */ +/* author: A. Hebert (03/07/2020) */ +/*--------------------------------*/ + +/* +Copyright (C) 2020 Ecole Polytechnique de Montreal + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. +*/ +#include <Python.h> +#include <structmember.h> +#include "pylcm.h" + +static char AbortString[132]; +static PyObject *PyLifoError = NULL; +static PyTypeObject LifoType; /* shared type-descriptor */ + +static PyObject *lifo_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { + int_32 impx = 0; + + /* Parse arguments */ + static char *kwlist[] = {"impx", NULL}; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|l", kwlist, &impx)) { + return NULL; + } + + lifoobject *self = (lifoobject*)PyObject_New(lifoobject, type); + self->impx_lifo = impx; + cleopn(&(self->stack)); + return (PyObject *)self; +} + +static void lifo_dealloc(lifoobject *self) +{ + char *nomsub="lifo_dealloc"; + if (self->impx_lifo > 0) printf("%s: deallocate a lifo object\n",nomsub); + PyObject_DEL(self); +} + +static PyObject *lifo_lib(lifoobject *self) { + fflush(stdout); + clelib(&(self->stack)); + fflush(stdout); + return Py_BuildValue("O",Py_None); +} + +static PyObject *lifo_push(lifoobject *self, PyObject *args) { + char *nomsub="lifo_push"; + PyObject *item=NULL; + lifo_node *my_node; + + /* Parse arguments */ + if(!PyArg_ParseTuple(args, "O", &item)) { + return NULL; + } + + PyObject *module = PyImport_ImportModule("lcm"); + if (module == NULL) { + sprintf(AbortString,"%s: module lcm should be installed first",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + PyObject *moduleDict = PyModule_GetDict(module); + PyObject *protocolClass = PyDict_GetItemString(moduleDict, "new"); + if (protocolClass == NULL) { + sprintf(AbortString,"%s: unable to find class new in module lcm",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + + lifo *my_lifo = self->stack; + int ipos = my_lifo->nup; + my_node = (lifo_node *) malloc(sizeof(lifo_node)); + sprintf(my_node->name,"inpu_val%04d", ipos+1); + if (PyObject_IsInstance(item, (PyObject *)&PyLong_Type)) { + long my_int = (long)PyLong_AsLong(item); + if (self->impx_lifo > 1) printf("item %d is an integer --> %ld\n", ipos, my_int); + my_node->type = 11; my_node->value.ival = my_int; + } else if (PyObject_IsInstance(item, (PyObject *)&PyFloat_Type)) { + double my_double = (double)PyFloat_AsDouble(item); + if (self->impx_lifo > 1) printf("item %d is a double floating point number --> %e\n", ipos, my_double); + my_node->type = 14; my_node->value.dval = my_double; + } else if (PyObject_IsInstance(item, (PyObject *)&PyBool_Type)) { + long my_int = 1; + if (item == Py_False) my_int = -1; + if (self->impx_lifo > 0) printf("%s: unique item is a boolean number --> %ld\n", nomsub, my_int); + my_node->type = 15; my_node->value.ival = my_int; + } else if (PyObject_IsInstance(item, (PyObject *)&PyUnicode_Type)) { + int len = PyUnicode_GET_LENGTH(item); + if (len > 72) { + sprintf(AbortString,"%s: character data overflow",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + int kind = PyUnicode_KIND(item); + void *data = PyUnicode_DATA(item); + char* my_string; + my_string = (char *)malloc(len+1); + int n; + for (n=0; n<len; n++) { + my_string[n] = (Py_UCS4)PyUnicode_READ(kind, data, n); + } + my_string[len] = '\0'; + if (self->impx_lifo > 1) printf("item %d is a string --> %s\n", ipos, my_string); + my_node->type = 13; + strcpy(my_node->value.hval, my_string); + free(my_string); + } else if (PyObject_IsInstance(item, protocolClass)) { + pylcmobject *lcm_object = (pylcmobject *)item; + char *pytype = lcm_object->type_lcm; + if (strcmp(pytype,"LCM") == 0) { + my_node->type = 3; + } else if (strcmp(pytype,"XSM") == 0) { + my_node->type = 4; + } else if (strcmp(pytype,"BINARY") == 0) { + my_node->type = 5; + } else if (strcmp(pytype,"ASCII") == 0) { + my_node->type = 6; + } else if (strcmp(pytype,"DA")== 0) { + my_node->type = 7; + my_node->lparam = lcm_object->lrda_lcm; + } else if (strcmp(pytype,"HDF5") == 0) { + my_node->type = 8; + } else { + sprintf(AbortString,"%s: invalid type=%s",nomsub,pytype); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + if (self->impx_lifo > 1) printf("item %d is a lcm object named %s (type=%d)\n", ipos, lcm_object->name_lcm, my_node->type); + strcpy(my_node->OSname, lcm_object->name_lcm); + my_node->access = lcm_object->iact_lcm; + my_node->value.mylcm = lcm_object->iplist; + } else { + /* Create an empty slot in the lifo */ + sprintf(my_node->name,"outp_val%04d", ipos+1); + PyObject* objectsRepresentation = PyObject_Repr(item); + int len = PyUnicode_GET_LENGTH(objectsRepresentation); + int kind = PyUnicode_KIND(objectsRepresentation); + void *data = PyUnicode_DATA(objectsRepresentation); + char* my_string; + my_string = (char *)malloc(len+1); + int n; + for (n=0; n<len; n++) { + my_string[n] = (Py_UCS4)PyUnicode_READ(kind, data, n); + } + my_string[len] = '\0'; + if (self->impx_lifo > 1) printf("item %d is a %s\n", ipos, my_string); + if (strcmp(my_string, "<class 'int'>") == 0) { + my_node->type = -11; + } else if (strcmp(my_string, "<class 'str'>") == 0) { + my_node->type = -13; + } else if (strcmp(my_string, "<class 'float'>") == 0) { + my_node->type = -14; + } else if (strcmp(my_string, "<class 'bool'>") == 0) { + my_node->type = -15; + } + free(my_string); + } + clepush(&my_lifo, my_node); + return Py_BuildValue("O",Py_None); +} + +static PyObject *lifo_pushEmpty(lifoobject *self, PyObject *args) { + char *nomsub="lifo_pushEmpty"; + lifo_node *my_node; + char *OSname = NULL; + char *htype = NULL; + + /* Parse arguments */ + if(!PyArg_ParseTuple(args, "s|s", &OSname, &htype)) { + return NULL; + } + + lifo *my_lifo = self->stack; + int ipos = my_lifo->nup; + my_node = (lifo_node *) malloc(sizeof(lifo_node)); + if (self->impx_lifo > 1) printf("item %d is an empty %s object\n", ipos, htype); + if (strlen(OSname) > 72) { + sprintf(AbortString,"%s: character OSname overflow",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + strcpy(my_node->OSname, OSname); + sprintf(my_node->name,"outp_val%04d", ipos+1); + my_node->access = 0; + if (htype == NULL) { + my_node->type = -3; + } else { + if (strcmp(htype,"LCM") == 0) { + my_node->type = -3; + } else if (strcmp(htype,"XSM") == 0) { + my_node->type = -4; + } else if (strcmp(htype,"BINARY") == 0) { + my_node->type = -5; + } else if (strcmp(htype,"ASCII") == 0) { + my_node->type = -6; + } else if (strcmp(htype,"DA")== 0) { + my_node->type = -7; + } else if (strcmp(htype,"HDF5")== 0) { + my_node->type = -8; + } else if (strcmp(htype,"I")== 0) { + my_node->type = -11; + } else if (strcmp(htype,"S")== 0) { + my_node->type = -13; + } else if (strcmp(htype,"D")== 0) { + my_node->type = -14; + } else if (strcmp(htype,"B")== 0) { + my_node->type = -15; + } else { + sprintf(AbortString,"%s: invalid type=%s",nomsub,htype); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + } + clepush(&my_lifo, my_node); + return Py_BuildValue("O",Py_None); +} + +static PyObject *lifo_pop(lifoobject *self) { + char *nomsub="lifo_pop"; + PyObject *item=NULL; + pylcmobject *rv = NULL; + char lcm_type[8]; + lifo *my_lifo = self->stack; + + PyObject *module = PyImport_ImportModule("lcm"); + if (module == NULL) { + sprintf(AbortString,"%s: module lcm should be installed first",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + PyObject *moduleDict = PyModule_GetDict(module); + PyTypeObject *protocolClass = (PyTypeObject *)PyDict_GetItemString(moduleDict, "new"); + if (protocolClass == NULL) { + sprintf(AbortString,"%s: unable to find class new in module lcm",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + + lifo_node *my_node = clepop(&my_lifo); + if(!my_node) { + sprintf(AbortString,"%s: empty stack",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + if(my_node->type < 0) { + free(my_node); + return Py_BuildValue("O",Py_None); + } + switch (my_node->type) { + case 3 : + strcpy(lcm_type, "LCM"); + goto c37; + case 4 : + strcpy(lcm_type, "XSM"); + goto c37; + case 5 : + strcpy(lcm_type, "BINARY"); + goto c37; + case 6 : + strcpy(lcm_type, "ASCII"); + goto c37; + case 7 : + strcpy(lcm_type, "DA"); + goto c37; + case 8 : + strcpy(lcm_type, "HDF5"); + c37: + rv = (pylcmobject*)PyObject_New(pylcmobject, protocolClass); + rv->iplist = my_node->value.mylcm; + rv->impx_lcm = self->impx_lifo; + strcpy(rv->type_lcm, lcm_type); + strcpy(rv->name_lcm, my_node->OSname); + rv->iact_lcm = my_node->access; + rv->lrda_lcm = my_node->lparam; + item = (PyObject *) rv; + Py_INCREF(item); + break; + case 11 : + item = Py_BuildValue("i", my_node->value.ival); + break; + case 13 : + item = Py_BuildValue("s", my_node->value.hval); + break; + case 14 : + item = Py_BuildValue("d", my_node->value.dval); + break; + case 15 : + if (my_node->value.ival == -1) { + item = Py_False; + } else { + item = Py_True; + } + break; + default : + sprintf(AbortString,"%s: undefined node (%d) - use node method",nomsub,my_node->type); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + free(my_node); + return item; +} + +static PyObject *lifo_pos(lifoobject *self, PyObject *args) { + char *nomsub="lifo_pos"; + PyObject *item=NULL; + pylcmobject *rv = NULL; + long ipos = 0; + char lcm_type[8]; + /* Parse arguments */ + if(!PyArg_ParseTuple(args, "O", &item)) { + return NULL; + } + lifo *my_lifo = self->stack; + if (PyObject_IsInstance(item, (PyObject *)&PyLong_Type)) { + ipos = (long)PyLong_AsLong(item); + if (self->impx_lifo > 0) printf("%s: recover node at position %ld\n", nomsub, ipos); + } else if (PyObject_IsInstance(item, (PyObject *)&PyUnicode_Type)) { + int len = PyUnicode_GET_LENGTH(item); + if (len > 72) { + sprintf(AbortString,"%s: CHARACTER DATA OVERFLOW.",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + int kind = PyUnicode_KIND(item); + void *data = PyUnicode_DATA(item); + char* my_string; + my_string = (char *)malloc(len+1); + int n; + for (n=0; n<len; n++) { + my_string[n] = (Py_UCS4)PyUnicode_READ(kind, data, n); + } + my_string[len] = '\0'; + for (n=0; n<my_lifo->nup; n++) { + lifo_node *my_node = clepos(&my_lifo, n); + if (strcmp(my_string, my_node->OSname) == 0) { + ipos = n; + goto findit; + } + } + sprintf(AbortString,"%s: unable to find a node with OSname=%s",nomsub, my_string); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + + findit: + if (self->impx_lifo > 0) printf("%s: recover node %s at position %ld\n", nomsub, my_string, ipos); + free(my_string); + } + if (ipos+1 > my_lifo->nup) { + sprintf(AbortString,"%s: node index %ld overflow the stack length=%d",nomsub, ipos, my_lifo->nup); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + + PyObject *module = PyImport_ImportModule("lcm"); + if (module == NULL) { + sprintf(AbortString,"%s: module lcm should be installed first",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + PyObject *moduleDict = PyModule_GetDict(module); + PyTypeObject *protocolClass = (PyTypeObject *)PyDict_GetItemString(moduleDict, "new"); + if (protocolClass == NULL) { + sprintf(AbortString,"%s: unable to find class new in module lcm",nomsub); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + + lifo_node *my_node = clepos(&my_lifo, ipos); + switch (my_node->type) { + case 3 : + strcpy(lcm_type, "LCM"); + goto c37; + case 4 : + strcpy(lcm_type, "XSM"); + goto c37; + case 5 : + strcpy(lcm_type, "BINARY"); + goto c37; + case 6 : + strcpy(lcm_type, "ASCII"); + goto c37; + case 7 : + strcpy(lcm_type, "DA"); + goto c37; + case 8 : + strcpy(lcm_type, "HDF5"); + c37: + rv = (pylcmobject*)PyObject_New(pylcmobject, protocolClass); + rv->iplist = my_node->value.mylcm; + rv->impx_lcm = self->impx_lifo; + strcpy(rv->type_lcm, lcm_type); + strcpy(rv->name_lcm, my_node->OSname); + rv->iact_lcm = my_node->access; + rv->lrda_lcm = my_node->lparam; + item = (PyObject *) rv; + Py_INCREF(item); + break; + case 11 : + item = Py_BuildValue("i", my_node->value.ival); + break; + case 13 : + item = Py_BuildValue("s", my_node->value.hval); + break; + case 14 : + item = Py_BuildValue("d", my_node->value.dval); + break; + case 15 : + if (my_node->value.ival == -1) { + item = Py_False; + } else { + item = Py_True; + } + break; + default : + sprintf(AbortString,"%s: node %ld is undefined",nomsub, ipos); + PyErr_SetString(PyLifoError, AbortString); + return NULL; + } + return item; +} + +static PyObject *lifo_len(lifoobject *self) { + lifo *my_lifo = self->stack; + return Py_BuildValue("i", my_lifo->nup); +} + +static PyObject *lifo_osname(lifoobject *self, PyObject *args) { + char *nomsub="lifo_osname"; + long ipos = 0; + /* Parse arguments */ + if(!PyArg_ParseTuple(args, "l", &ipos)) { + return NULL; + } + if (self->impx_lifo > 0) printf("%s: recover node OSname at position %ld\n", nomsub, ipos); + + lifo *my_lifo = self->stack; + lifo_node *my_node = clepos(&my_lifo, ipos); + return Py_BuildValue("s", my_node->OSname); +} + +static PyMethodDef lifo_methods[] = { + {"lib", (PyCFunction)lifo_lib, METH_NOARGS, "Print the table-of-content of the stack"}, + {"push", (PyCFunction)lifo_push, METH_VARARGS, "Push an entry in the stack"}, + {"pushEmpty", (PyCFunction)lifo_pushEmpty, METH_VARARGS, "Push an empty Lcm object in the stack"}, + {"pop", (PyCFunction)lifo_pop, METH_NOARGS, "Pop an entry from the stack"}, + {"node", (PyCFunction)lifo_pos, METH_VARARGS, "Recover an entry from the stack"}, + {"getMax", (PyCFunction)lifo_len, METH_NOARGS, "Return the length of the stack"}, + {"OSName", (PyCFunction)lifo_osname, METH_VARARGS, "Return the OSname of a node"}, + {NULL} /* Sentinel */ +}; + +static PyMemberDef lifo_members[] = { + {"_impx", T_INT, offsetof(lifoobject, impx_lifo), 0, "print index"}, + {NULL} /* Sentinel */ +}; + +static PyTypeObject LifoType = { + PyVarObject_HEAD_INIT(NULL, 0) + "lifo.new", /*tp_name*/ + sizeof(lifoobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + (destructor)lifo_dealloc, /*tp_dealloc*/ + (printfunc) lifo_lib, /*tp_print*/ + 0, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash */ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /*tp_getattro*/ + 0, /*tp_setattro*/ + 0, /*tp_as_buffer*/ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/ + "Custom objects", /*tp_doc*/ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + lifo_methods, /* tp_methods */ + lifo_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + lifo_new, /* tp_new */ +}; + +static PyModuleDef lifomodule = { + PyModuleDef_HEAD_INIT, + "lifo", + "A Python module for accessing the lifo stack from C code.", + -1, + NULL, NULL, NULL, NULL, NULL +}; +PyMODINIT_FUNC PyInit_lifo(void) { + PyObject* m; + + Py_Initialize(); + if (PyType_Ready(&LifoType) < 0) return NULL; + + m = PyModule_Create(&lifomodule); + if (m == NULL) return NULL; + + PyModule_AddObject(m, "new", (PyObject *)&LifoType); + + /* Initialize new exception object */ + PyLifoError = PyErr_NewException("lifo.PyLifoError", NULL, NULL); + + /* Add exception object to your module */ + PyModule_AddObject(m, "PyLifoError", PyLifoError); + return m; +} |
