123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283 |
- /*
- * Copyright (C) 2020 Weber Yann
- *
- * This file is part of pyrpn.
- *
- * pyrpn 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
- * any later version.
- *
- * pyrpn 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 pyrpn. If not, see <http://www.gnu.org/licenses/>.
- */
- #include "python_rpnexpr.h"
-
- PyMethodDef RPNExpr_methods[] = {
- {"eval", (PyCFunction)rpnexpr_eval, METH_FASTCALL, "Evaluate an expression"},
- {"reset_stack", (PyCFunction)rpnexpr_reset_stack, METH_NOARGS,
- "Reset stack memory storage (set all items to 0)"},
- {NULL} //Sentinel
- };
-
- PyMemberDef RPNExpr_members[] = {
- {NULL}
- };
-
- PyTypeObject RPNExprType = {
- PyVarObject_HEAD_INIT(NULL, 0)
- "rpn.RPNExpr", /* tp_name */
- sizeof(PyRPNExpr_t), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)rpnexpr_del, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- rpnexpr_repr, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- rpnexpr_str, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT |
- Py_TPFLAGS_BASETYPE, /* tp_flags */
- "RPN expression evaluator", /* tp_doc */
- 0, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- 0, /* tp_iter */
- 0, /* tp_iternext */
- RPNExpr_methods, /* tp_methods */
- RPNExpr_members, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- rpnexpr_init, /* tp_init */
- 0, /* tp_alloc */
- rpnexpr_new, /* tp_new */
- };
-
- PyObject* rpnexpr_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
- {
- PyObject *ret, *err;
- PyRPNExpr_t *expr;
- ret = PyType_GenericNew(subtype, args, kwds);
- if((err = PyErr_Occurred()))
- {
- Py_DECREF(err);
- return ret;
- }
- expr = (PyRPNExpr_t*)ret;
- expr->rpn = NULL;
- expr->args = NULL;
- return ret;
- }
-
- int rpnexpr_init(PyObject *self, PyObject *args, PyObject *kwds)
- {
- PyRPNExpr_t *expr_self;
- char *names[] = {"expression", "args_count", "stack_size", NULL};
- char err_str[256];
- const char *expr;
- long long int args_count, stack_size;
-
- expr_self = (PyRPNExpr_t*)self;
-
- stack_size = 16;
- expr_self->rpn = NULL;
-
- if(!PyArg_ParseTupleAndKeywords(args, kwds, "sL|L:RPNExpr.__init__", names, &expr,
- &args_count, &stack_size))
- {
- return -1;
- }
-
- if(strlen(expr) == 0)
- {
- PyErr_SetString(PyExc_ValueError,
- "RpnExpr.__init__() expect expression argument to be not empty");
- return -1;
- }
-
- if(args_count < 0 || args_count > 255)
- {
- snprintf(err_str, 128,
- "Argument count should be in [4..255] but %lld given",
- args_count);
- PyErr_SetString(PyExc_ValueError, err_str);
- return -1;
- }
-
- if(stack_size < 4 || stack_size > 255)
- {
- snprintf(err_str, 128,
- "Stack size should be in [0..255] but %lld given",
- stack_size);
- PyErr_SetString(PyExc_ValueError, err_str);
- return -1;
- }
-
- expr_self->rpn = malloc(sizeof(rpn_expr_t));
- if(!expr_self->rpn)
- {
- snprintf(err_str, 256,
- "Expression memory allocation error : %s",
- strerror(errno));
- }
- bzero(expr_self->rpn, sizeof(rpn_expr_t));
-
- if(rpn_expr_init(expr_self->rpn, stack_size, args_count) < 0)
- {
- snprintf(err_str, 256,
- "Expression init error : %s",
- expr_self->rpn->err_reason);
- PyErr_SetString(PyExc_ValueError, err_str);
- return -1;
- }
-
- if(!stack_size)
- {
- expr_self->args = NULL;
- return 0;
- }
-
- expr_self->args = malloc(sizeof(unsigned long) * args_count);
- if(!expr_self->args)
- {
- snprintf(err_str, 256,
- "Error allocating arguments memory : %s",
- strerror(errno));
- return -1;
- }
-
- if(rpn_expr_compile(expr_self->rpn, expr))
- {
- PyErr_SetString(PyExc_ValueError, expr_self->rpn->err_reason);
- return -1;
- }
-
- return 0;
- }
-
- void rpnexpr_del(PyObject *self)
- {
- PyRPNExpr_t *expr_self;
-
- expr_self = (PyRPNExpr_t*)self;
- if(expr_self->rpn)
- {
- rpn_expr_close(expr_self->rpn);
- free(expr_self->rpn);
- expr_self->rpn = NULL;
- }
- if(expr_self->args)
- {
- free(expr_self->args);
- expr_self->args = NULL;
- }
- }
-
- PyObject* rpnexpr_eval(PyObject* self, PyObject** argv, Py_ssize_t argc)
- {
- PyRPNExpr_t *expr_self;
- unsigned long res;
- char err_str[128];
- Py_ssize_t i;
- PyObject *cur, *ret;
-
-
- expr_self = (PyRPNExpr_t*)self;
-
- if((unsigned long)argc != expr_self->rpn->args_count)
- {
- snprintf(err_str, 128,
- "RPNExpr expected %ld arguments but %ld given",
- expr_self->rpn->args_count,
- argc);
- PyErr_SetString(PyExc_ValueError, err_str);
- return NULL;
- }
-
- for(i=0; i<argc; i++)
- {
- cur = argv[i];
- if(!PyLong_Check(cur))
- {
- snprintf(err_str, 128,
- "RpnExpr.__call__ expect int as arguments but argument %ld is not",
- i+1);
- PyErr_SetString(PyExc_ValueError, err_str);
- return NULL;
- }
- expr_self->args[i] = PyLong_AsUnsignedLong(argv[i]);
- if((ret = PyErr_Occurred()))
- {
- Py_DECREF(ret);
- return NULL;
- }
- }
-
- res = rpn_expr_eval(expr_self->rpn, expr_self->args);
- //dprintf(2, "[RES=%lu]\n", res);
-
- return PyLong_FromUnsignedLong(res);
- }
-
- PyObject* rpnexpr_reset_stack(PyObject *self, PyObject *noargs)
- {
- rpn_expr_reset_stack(((PyRPNExpr_t*)self)->rpn);
- Py_RETURN_NONE;
- }
-
- PyObject* rpnexpr_str(PyObject *self)
- {
- PyRPNExpr_t *expr_self;
- PyObject *res;
-
- expr_self = (PyRPNExpr_t*)self;
- res = Py_BuildValue("s", expr_self->rpn->expr);
- return res;
- }
-
- PyObject* rpnexpr_repr(PyObject *self)
- {
- PyRPNExpr_t *expr_self;
- PyObject *res;
- size_t sz;
- char *buff, err_str[128];
-
- expr_self = (PyRPNExpr_t*)self;
- sz = snprintf(NULL, 0, "<RPNExpr argc:%ld stck_sz:%d '%s'>",
- expr_self->rpn->args_count, expr_self->rpn->stack_sz,
- expr_self->rpn->expr);
- buff = malloc(sizeof(char) * (sz + 1));
- if(!buff)
- {
- snprintf(err_str, 128,
- "Error allocating repr : %s",
- strerror(errno));
- PyErr_SetString(PyExc_RuntimeError, err_str);
- return NULL;
- }
- snprintf(buff, sz+1, "<RPNExpr argc:%ld stck_sz:%d '%s'>",
- expr_self->rpn->args_count, expr_self->rpn->stack_sz,
- expr_self->rpn->expr);
- res = Py_BuildValue("s", buff);
- free(buff);
- return res;
- }
|