1363 lines
29 KiB
C
1363 lines
29 KiB
C
#include "python_if.h"
|
|
/**@file python_if.c
|
|
* @brief Python RPNIterExpr type definition
|
|
* @ingroup python_ext
|
|
* @ingroup pymod_pyrpn_RPNExprIter
|
|
*/
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter methods definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PyMethodDef RPNIterExpr_methods[] = {
|
|
PYRPN_method("params", rpnif_params,
|
|
METH_VARARGS | METH_KEYWORDS | METH_CLASS,
|
|
/**@todo add default values */
|
|
"cls, pos_flag, res_flag, size_lim, const_values, stack_size",
|
|
"Get a name tuple with parameters given a position \
|
|
flag, a result flag and size limits"),
|
|
PYRPN_method("get_params", rpnif_get_params,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Get a name tuple with parameters"),
|
|
PYRPN_method("set_mmap", rpnif_set_mmap,
|
|
METH_O,
|
|
"self, mmap, /",
|
|
"Set the mmap that stores data"),
|
|
PYRPN_method("shape", rpnif_shape,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Get the shape of the data buffer"),
|
|
PYRPN_method("keys", rpnif_keys,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Return items keys (see dict.keys)"),
|
|
PYRPN_method("values", rpnif_values,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Return items values (see dict.values)"),
|
|
PYRPN_method("items", rpnif_items,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Return items (key, value) list (see dict.items)"),
|
|
PYRPN_method("step", rpnif_step,
|
|
METH_O,
|
|
"self, position, /",
|
|
"Run an IF given a position and return a new position"),
|
|
PYRPN_method("to_pos", rpnif_to_pos,
|
|
METH_FASTCALL,
|
|
"self, *args, /",
|
|
"Return a position (int) from a coordinates given as"
|
|
"argument."),
|
|
PYRPN_method("from_pos", rpnif_from_pos,
|
|
METH_O,
|
|
"self, position, /",
|
|
"Return a coordinates tuple from given position."),
|
|
PYRPN_method("__getstate__", rpnif_getstate,
|
|
METH_NOARGS,
|
|
"self, /",
|
|
"Pickling method (see pickle module).\n"
|
|
"Return a bytes representation of the expression state."),
|
|
PYRPN_method("__setstate__", rpnif_setstate,
|
|
METH_O,
|
|
"self, state, /",
|
|
"Unpickling method (see pickle module)."),
|
|
{NULL} //Sentinel
|
|
};
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter members definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PyMemberDef RPNIterExpr_members[] = {
|
|
{"expressions", T_OBJECT, offsetof(PyRPNIterExpr_t, expr), READONLY,
|
|
"The tuple of expressions"},
|
|
{"mmap", T_OBJECT, offsetof(PyRPNIterExpr_t, mmap), READONLY,
|
|
"The mmap storing data"},
|
|
{NULL}
|
|
};
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter sequence methods definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PySequenceMethods RPNIterExpr_seq_methods = {
|
|
.sq_length = rpnif_len,
|
|
.sq_item = rpnif_expr_item,
|
|
.sq_ass_item = rpnif_expr_ass_item,
|
|
};
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter mapping methods definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PyMappingMethods RPNIterExpr_mapping_methods = {
|
|
.mp_length = rpnif_len,
|
|
.mp_subscript = rpnif_subscript,
|
|
.mp_ass_subscript = rpnif_ass_subscript,
|
|
};
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter attributes definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PyGetSetDef RPNIterExpr_getset[] = {
|
|
{NULL}
|
|
};
|
|
|
|
/**@brief @ref pymod_pyrpn_RPNExprIter buffer methods definition
|
|
* @ingroup pymod_pyrpn_RPNExprIter */
|
|
static PyBufferProcs RPNIterExpr_as_buffer = {
|
|
(getbufferproc)rpnif_getbuffer,
|
|
(releasebufferproc)rpnif_releasebuffer,
|
|
};
|
|
|
|
PyTypeObject RPNIterExprType = {
|
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
.tp_name = "pyrpn.RPNIterExpr",
|
|
.tp_basicsize = sizeof(PyRPNIterExpr_t),
|
|
.tp_itemsize = 0,
|
|
.tp_del = rpnif_del,
|
|
.tp_repr = rpnif_repr,
|
|
.tp_as_sequence = &RPNIterExpr_seq_methods,
|
|
.tp_as_mapping = &RPNIterExpr_mapping_methods,
|
|
.tp_str = rpnif_str,
|
|
.tp_as_buffer = &RPNIterExpr_as_buffer,
|
|
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
|
|
.tp_doc = "RPN expression evaluator",
|
|
.tp_methods = RPNIterExpr_methods,
|
|
.tp_members = RPNIterExpr_members,
|
|
.tp_getset = RPNIterExpr_getset,
|
|
.tp_init = rpnif_init,
|
|
.tp_new = rpnif_new,
|
|
};
|
|
|
|
PyObject* rpnif_params(PyObject *cls, PyObject *args, PyObject *kwds)
|
|
{
|
|
char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", NULL};
|
|
|
|
unsigned short pos_flag, res_flag, stack_size;
|
|
PyObject *lim_obj, *const_values_obj;
|
|
|
|
stack_size = 16;
|
|
const_values_obj = lim_obj = NULL;
|
|
|
|
if(!PyArg_ParseTupleAndKeywords(args, kwds,
|
|
"HHO|OH:RPNIterExppr.get_params", names,
|
|
&pos_flag, &res_flag, &lim_obj, &const_values_obj,
|
|
&stack_size))
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
|
|
lim_obj, const_values_obj, stack_size);
|
|
if(!rif_params)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *res = _rpnif_params_to_tuple(rif_params);
|
|
if(!res)
|
|
{
|
|
goto err;
|
|
}
|
|
free(rif_params);
|
|
return res;
|
|
|
|
err:
|
|
free(rif_params);
|
|
return NULL;
|
|
}
|
|
|
|
PyObject* rpnif_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
|
|
{
|
|
PyObject *ret, *err;
|
|
PyRPNIterExpr_t *expr;
|
|
ret = PyType_GenericNew(subtype, args, kwds);
|
|
if((err = PyErr_Occurred()))
|
|
{
|
|
Py_DECREF(err);
|
|
return ret;
|
|
}
|
|
expr = (PyRPNIterExpr_t*)ret;
|
|
expr->rif = NULL;
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds)
|
|
{
|
|
PyRPNIterExpr_t *expr_self;
|
|
char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", "mmap", NULL};
|
|
unsigned short pos_flag, res_flag, stack_size;
|
|
PyObject *lim_obj, *const_values_obj, *mmap_obj;
|
|
|
|
|
|
expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
stack_size = 16;
|
|
const_values_obj = lim_obj = mmap_obj = NULL;
|
|
expr_self->rif = NULL;
|
|
expr_self->mmap = NULL;
|
|
|
|
if(!PyArg_ParseTupleAndKeywords(args, kwds, "HHO|OHO:RPNIterExpr.__init__", names,
|
|
&pos_flag, &res_flag, &lim_obj, &const_values_obj, &stack_size,
|
|
&mmap_obj))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
rpn_if_param_t *rif_params = _rpnif_get_params(pos_flag, res_flag,
|
|
lim_obj, const_values_obj, stack_size);
|
|
|
|
if(!rif_params)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
expr_self->ndim = ((rpn_if_default_data_t*)(rif_params->data))->ndim;
|
|
|
|
const Py_ssize_t expt_sz = rif_params->mem_sz * rif_params->value_sz;
|
|
if(!mmap_obj)
|
|
{
|
|
PyObject *fileno = PyLong_FromLong(-1);
|
|
PyObject *length = PyLong_FromSize_t(expt_sz);
|
|
mmap_obj = PyObject_CallFunctionObjArgs(mmap_cls, fileno, length, NULL);
|
|
}
|
|
else
|
|
{
|
|
if(!PyObject_TypeCheck(mmap_obj, (PyTypeObject*)mmap_cls))
|
|
{
|
|
PyErr_Format(PyExc_TypeError,
|
|
"The mmap argument MUST be an instance \
|
|
of mmap.mmap");
|
|
return -1;
|
|
}
|
|
/**@todo check if mmap is shared & writable ? */
|
|
if(PyObject_Length(mmap_obj) != (Py_ssize_t) expt_sz)
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Expected mmap length is %ld but mmap with length %ld provided",
|
|
rif_params->mem_sz, PyObject_Length(mmap_obj));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
if(PyObject_GetBuffer(mmap_obj, &expr_self->mm_buff,
|
|
PyBUF_CONTIG) == -1)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
expr_self->mmap = mmap_obj;
|
|
|
|
// Creating rif with a new memory map
|
|
expr_self->rif = rpn_if_new(rif_params, expr_self->mm_buff.buf);
|
|
if(!expr_self->rif)
|
|
{
|
|
PyErr_Format(PyExc_RuntimeError,
|
|
"Error initalizing if : %s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
// Creating the tuple holding RPNExpr instances of expressions
|
|
expr_self->expr = PyTuple_New(expr_self->rif->params->rpn_sz);
|
|
for(size_t i=0; i<expr_self->rif->params->rpn_sz;i++)
|
|
{
|
|
rpn_expr_t *expr = &expr_self->rif->rpn[i];
|
|
PyObject *instance = rpnexpr_init_borrowing(expr);
|
|
if(!instance)
|
|
{
|
|
return -1;
|
|
}
|
|
PyTuple_SET_ITEM(expr_self->expr, i, instance);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/**@brief Returns the parameters in a named tuple */
|
|
PyObject *rpnif_get_params(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
return _rpnif_params_to_tuple(expr_self->rif->params);
|
|
}
|
|
|
|
PyObject *rpnif_set_mmap(PyObject *self, PyObject *mm_obj)
|
|
{
|
|
if(!PyObject_TypeCheck(mm_obj, (PyTypeObject*)mmap_cls))
|
|
{
|
|
PyErr_Format(PyExc_TypeError,
|
|
"Excpected instance of mmap.mmap");
|
|
return NULL;
|
|
}
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
Py_buffer buff;
|
|
|
|
/**@todo check mm size &writable ? */
|
|
if(PyObject_GetBuffer(mm_obj, &buff, PyBUF_CONTIG) == -1)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
// Release old mmap
|
|
PyBuffer_Release(&expr_self->mm_buff);
|
|
Py_DECREF(expr_self->mmap);
|
|
|
|
if(expr_self->rif->self_mem)
|
|
{
|
|
const size_t mm_sz = expr_self->rif->params->mem_sz *\
|
|
expr_self->rif->params->value_sz;
|
|
munmap(expr_self->rif->mem, mm_sz);
|
|
}
|
|
|
|
// Set new mmap in python struct & rif struct
|
|
expr_self->mm_buff = buff;
|
|
expr_self->mmap = mm_obj;
|
|
|
|
expr_self->rif->mem = buff.buf;
|
|
expr_self->rif->self_mem = 0;
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyObject *rpnif_shape(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *params;
|
|
params = (rpn_if_default_data_t*)(expr_self->rif->params->data);
|
|
|
|
size_t res_sz;
|
|
|
|
switch(params->res_flag)
|
|
{
|
|
case RPN_IF_RES_RGB:
|
|
res_sz = 3;
|
|
break;
|
|
case RPN_IF_RES_RGBA:
|
|
res_sz = 4;
|
|
break;
|
|
default:
|
|
res_sz = 1;
|
|
break;
|
|
}
|
|
|
|
const size_t shape_sz = params->ndim + (res_sz > 1 ?1:0);
|
|
|
|
PyObject *ret = PyTuple_New(shape_sz);
|
|
if(!ret)
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
size_t i;
|
|
for(i = 0; i < params->ndim; i++)
|
|
{
|
|
size_t idx = params->pos_flag == RPN_IF_POSITION_XDIM ? i+1:i;
|
|
PyObject *d = PyLong_FromLong(params->size_lim[idx]);
|
|
if(!d)
|
|
{
|
|
goto item_err;
|
|
}
|
|
PyTuple_SET_ITEM(ret, i, d);
|
|
}
|
|
if(res_sz > 1)
|
|
{
|
|
PyObject *d = PyLong_FromLong(res_sz);
|
|
if(!d)
|
|
{
|
|
goto item_err;
|
|
}
|
|
PyTuple_SET_ITEM(ret, i, d);
|
|
}
|
|
return ret;
|
|
|
|
item_err:
|
|
Py_DECREF(ret);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PyObject *rpnif_step(PyObject *self, PyObject* opos)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
/** @todo allow tuple as argument !!!!! */
|
|
if(!PyLong_Check(opos))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError, "Expected position to be an int");
|
|
return NULL;
|
|
}
|
|
size_t pos = PyLong_AsSize_t(opos);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
pos = rpn_if_step(expr_self->rif, pos);
|
|
|
|
return PyLong_FromSize_t(pos);
|
|
}
|
|
|
|
|
|
PyObject *rpnif_to_pos(PyObject *self, PyObject** argv, Py_ssize_t argc)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
|
|
long long value;
|
|
|
|
if((size_t)argc != rif_data->ndim)
|
|
{
|
|
PyErr_Format(PyExc_IndexError,
|
|
"Expression expect %lu dimentions coordinates,"
|
|
" but %ld arguments given.",
|
|
rif_data->ndim, argc);
|
|
return NULL;
|
|
}
|
|
|
|
rpn_value_t result=0;
|
|
size_t cur_dim_sz = 1;
|
|
|
|
for(size_t i=0; i<rif_data->ndim; i++)
|
|
{
|
|
if(!PyLong_Check(argv[i]))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"coordinates must be integers");
|
|
return NULL;
|
|
}
|
|
value = PyLong_AsLongLong(argv[i]);
|
|
if(value < 0)
|
|
{
|
|
value = (-(rpn_value_t)-value)%rif_data->size_lim[i+idx_off];
|
|
}
|
|
if((size_t)value >= rif_data->size_lim[i+idx_off])
|
|
{
|
|
PyErr_Format(PyExc_IndexError,
|
|
"Coordinate %ld overflows : %R/%lu",
|
|
i, argv[i],
|
|
rif_data->size_lim[i+idx_off]);
|
|
return NULL;
|
|
}
|
|
result += value * cur_dim_sz;
|
|
cur_dim_sz *= rif_data->size_lim[i+idx_off];
|
|
}
|
|
|
|
return PyLong_FromUnsignedLongLong(result);
|
|
}
|
|
|
|
|
|
PyObject *rpnif_from_pos(PyObject *self, PyObject* _pos)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
const short idx_off = rif_data->pos_flag == RPN_IF_POSITION_XDIM?1:0;
|
|
|
|
if(!PyLong_Check(_pos))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError,
|
|
"Expected position to be an integer");
|
|
return NULL;
|
|
}
|
|
|
|
size_t pos = PyLong_AsUnsignedLong(_pos);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *res = PyTuple_New(rif_data->ndim);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
for(size_t i=0; i<rif_data->ndim; i++)
|
|
{
|
|
size_t val;
|
|
size_t lim = rif_data->size_lim[i+idx_off];
|
|
|
|
val = pos % lim;
|
|
pos /= lim;
|
|
|
|
PyObject *elt = PyLong_FromUnsignedLong(val);
|
|
if(PyErr_Occurred())
|
|
{
|
|
goto err;
|
|
}
|
|
PyTuple_SET_ITEM(res, i, elt);
|
|
}
|
|
|
|
return res;
|
|
|
|
err:
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
PyObject *rpnif_keys(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
|
|
Py_ssize_t ret_idx = 0;
|
|
char xdim_key[64];
|
|
|
|
PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
#define _ret_append(key) PyTuple_SET_ITEM(ret, ret_idx++, \
|
|
PyUnicode_FromString(key))
|
|
|
|
switch(rif_data->pos_flag)
|
|
{
|
|
case RPN_IF_POSITION_XY:
|
|
_ret_append("X");
|
|
_ret_append("Y");
|
|
break;
|
|
case RPN_IF_POSITION_LINEAR:
|
|
_ret_append("X");
|
|
break;
|
|
case RPN_IF_POSITION_XDIM:
|
|
for(size_t i=0; i<rif_data->size_lim[0];i++)
|
|
{
|
|
snprintf(xdim_key, 64, "D%ld", i);
|
|
_ret_append(xdim_key);
|
|
}
|
|
break;
|
|
default:
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"UNKOWN POS_FLAG3");
|
|
return NULL;
|
|
}
|
|
switch(rif_data->res_flag)
|
|
{
|
|
case RPN_IF_RES_BOOL:
|
|
case RPN_IF_RES_XFUN:
|
|
_ret_append("R");
|
|
break;
|
|
case RPN_IF_RES_RGB:
|
|
_ret_append("R");
|
|
_ret_append("G");
|
|
_ret_append("B");
|
|
break;
|
|
case RPN_IF_RES_RGBA:
|
|
_ret_append("R");
|
|
_ret_append("G");
|
|
_ret_append("B");
|
|
_ret_append("A");
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
return ret;
|
|
|
|
#undef _ret_append
|
|
}
|
|
|
|
|
|
PyObject *rpnif_values(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
Py_INCREF(expr_self->expr);
|
|
return expr_self->expr;
|
|
}
|
|
|
|
|
|
PyObject *rpnif_items(PyObject *self)
|
|
{
|
|
size_t i;
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
PyObject *keys = rpnif_keys(self);
|
|
for(i=0; i<expr_self->rif->params->rpn_sz; i++)
|
|
{
|
|
PyObject *tmp = PyTuple_New(2);
|
|
if(PyErr_Occurred())
|
|
{
|
|
goto err_loop_newtuple;
|
|
}
|
|
PyObject *key = PyTuple_GET_ITEM(keys, i);
|
|
PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
|
|
Py_INCREF(key);
|
|
Py_INCREF(value);
|
|
PyTuple_SET_ITEM(tmp, 0, key);
|
|
PyTuple_SET_ITEM(tmp, 1, value);
|
|
PyTuple_SET_ITEM(ret, i, tmp);
|
|
if(PyErr_Occurred())
|
|
{
|
|
goto err_loop_setitem;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
/** @todo cleanup seems wrong... */
|
|
for(i=i; i>=0; i--)
|
|
{
|
|
err_loop_setitem:
|
|
PyObject *key = PyTuple_GET_ITEM(keys, i);
|
|
PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
|
|
Py_DECREF(key);
|
|
Py_DECREF(value);
|
|
err_loop_newtuple:
|
|
}
|
|
Py_DECREF(ret);
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void rpnif_del(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
if(expr_self->rif)
|
|
{
|
|
rpn_if_free(expr_self->rif);
|
|
expr_self->rif = NULL;
|
|
}
|
|
if(expr_self->mm_buff.buf)
|
|
{
|
|
PyBuffer_Release(&expr_self->mm_buff);
|
|
}
|
|
Py_DECREF(expr_self->mmap);
|
|
}
|
|
|
|
|
|
Py_ssize_t rpnif_len(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
return expr_self->rif->params->rpn_sz;
|
|
}
|
|
|
|
PyObject* rpnif_expr_item(PyObject *self, Py_ssize_t idx)
|
|
{
|
|
Py_ssize_t _idx = idx;
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
if(idx < 0)
|
|
{
|
|
idx = expr_self->rif->params->rpn_sz - 1 + idx;
|
|
}
|
|
if(idx < 0 || (size_t) idx >= expr_self->rif->params->rpn_sz)
|
|
{
|
|
PyErr_Format(PyExc_IndexError,
|
|
"No expression %ld with given options",
|
|
_idx);
|
|
return NULL;
|
|
}
|
|
PyObject *ret = PyTuple_GET_ITEM(expr_self->expr, idx);
|
|
Py_INCREF(ret);
|
|
return ret;
|
|
}
|
|
|
|
|
|
int rpnif_expr_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
if(!PyUnicode_Check(elt))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError, "RPNExpr expected");
|
|
return -1;
|
|
}
|
|
|
|
PyObject *bytes_str = PyUnicode_AsASCIIString(elt);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return -1;
|
|
}
|
|
const char *code = PyBytes_AS_STRING(bytes_str);
|
|
|
|
rpn_expr_t *expr = &(expr_self->rif->rpn[idx]);
|
|
|
|
if(rpn_expr_recompile(expr, code) < 0)
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Error during expression '%s' compilation : %s",
|
|
code, expr->err_reason);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/** Convert key to integer index
|
|
* @param self @ref PyRPNIterExpr_t instance
|
|
* @param _key An expression name (str)
|
|
* @return The expression index or -1 on error (raise python exception)
|
|
*/
|
|
static Py_ssize_t _rpnif_subscript_idx(PyObject *self, PyObject *_key)
|
|
{
|
|
if(!PyUnicode_Check(_key))
|
|
{
|
|
PyErr_SetString(PyExc_TypeError, "Key should be a str");
|
|
return -1;
|
|
}
|
|
PyObject *bytes_str = PyUnicode_AsASCIIString(_key);
|
|
if(PyErr_Occurred())
|
|
{
|
|
return -1;
|
|
}
|
|
const char *key = PyBytes_AS_STRING(bytes_str);
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
|
|
Py_ssize_t idx = -1;
|
|
Py_ssize_t res_idx = -1;
|
|
|
|
switch(rif_data->pos_flag)
|
|
{
|
|
case RPN_IF_POSITION_XY:
|
|
res_idx = 2;
|
|
if(key[1] != '\0') { break; }
|
|
switch(key[0])
|
|
{
|
|
case 'X':
|
|
idx=0;
|
|
break;
|
|
case 'Y':
|
|
idx=1;
|
|
break;
|
|
}
|
|
break;
|
|
case RPN_IF_POSITION_LINEAR:
|
|
res_idx = 1;
|
|
if(!strcmp("X", key))
|
|
{
|
|
idx = 0;
|
|
}
|
|
break;
|
|
case RPN_IF_POSITION_XDIM:
|
|
size_t ndim = rif_data->size_lim[0];
|
|
res_idx = ndim;
|
|
char possible_key[64];
|
|
for(size_t i=0; i<ndim; i++)
|
|
{
|
|
snprintf(possible_key, 64, "D%ld", i);
|
|
if(!strcmp(possible_key, key))
|
|
{
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"UNKOWN POS_FLAG");
|
|
return -1;
|
|
}
|
|
if(idx < 0)
|
|
{
|
|
// not found yet, looking for result key
|
|
switch(rif_data->res_flag)
|
|
{
|
|
case RPN_IF_RES_BOOL:
|
|
case RPN_IF_RES_XFUN:
|
|
if(!strcmp("R", key))
|
|
{
|
|
idx = res_idx;
|
|
}
|
|
break;
|
|
case RPN_IF_RES_RGBA:
|
|
if(!strcmp("A", key))
|
|
{
|
|
idx = res_idx + 3;
|
|
}
|
|
case RPN_IF_RES_RGB:
|
|
if(key[1] != '\0')
|
|
{
|
|
break;
|
|
}
|
|
switch(key[0])
|
|
{
|
|
case 'R':
|
|
idx=res_idx;
|
|
break;
|
|
case 'G':
|
|
idx=res_idx+1;
|
|
break;
|
|
case 'B':
|
|
idx=res_idx+2;
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
// not implemented, not unknown....
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"UNKOWN RES_FLAG");
|
|
return -1;
|
|
}
|
|
}
|
|
return idx;
|
|
}
|
|
|
|
PyObject* rpnif_subscript(PyObject *self, PyObject *key)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
Py_ssize_t idx = _rpnif_subscript_idx(self, key);
|
|
if(idx < 0)
|
|
{
|
|
PyErr_Format(PyExc_IndexError,
|
|
"No expression '%s' with given parameters",
|
|
key);
|
|
return NULL;
|
|
}
|
|
PyObject *expr = PyTuple_GET_ITEM(expr_self->expr, idx);
|
|
Py_INCREF(expr);
|
|
return expr;
|
|
}
|
|
|
|
int rpnif_ass_subscript(PyObject *self, PyObject *key, PyObject *elt)
|
|
{
|
|
Py_ssize_t idx = _rpnif_subscript_idx(self, key);
|
|
if(idx < 0)
|
|
{
|
|
PyErr_Format(PyExc_IndexError,
|
|
"Cannot set expression '%U' that do not exists with this parameters",
|
|
key);
|
|
return -1;
|
|
}
|
|
|
|
return rpnif_expr_ass_item(self, idx, elt);
|
|
}
|
|
|
|
int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags)
|
|
{
|
|
PyRPNIterExpr_t *expr_self;
|
|
expr_self = (PyRPNIterExpr_t*)self;
|
|
|
|
return PyObject_GetBuffer(expr_self->mmap, view, flags);
|
|
|
|
rpn_if_default_data_t *data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
|
|
view->buf = expr_self->rif->mem;
|
|
dprintf(2, "buffer addr %p\n", expr_self->mm_buff.buf);
|
|
view->obj = self;
|
|
view->len = expr_self->rif->params->mem_sz * expr_self->rif->params->value_sz;
|
|
view->readonly = 0;
|
|
//view->itemsize = expr_self->rif->params->value_sz;
|
|
view->itemsize = sizeof(rpn_value_t);
|
|
if(flags & PyBUF_FORMAT)
|
|
{
|
|
view->format = "L";
|
|
}
|
|
else
|
|
{
|
|
view->format = NULL;
|
|
}
|
|
view->ndim = 1;
|
|
view->shape = NULL;
|
|
if(flags & PyBUF_ND)
|
|
{
|
|
view->ndim = expr_self->ndim;
|
|
|
|
// !! Error if value_sz < sizeof(rpn_value_t) !!
|
|
short nval = view->itemsize / sizeof(rpn_value_t);
|
|
if(nval > 1)
|
|
{
|
|
view->ndim++;
|
|
}
|
|
view->shape = malloc(sizeof(Py_ssize_t) * view->ndim);
|
|
if(!view->shape)
|
|
{
|
|
goto buff_error;
|
|
}
|
|
for(size_t i=0; i<expr_self->ndim; i++)
|
|
{
|
|
int idx = i;
|
|
if(data->pos_flag == RPN_IF_POSITION_XDIM)
|
|
{
|
|
idx++;
|
|
}
|
|
view->shape[i] = data->size_lim[idx];
|
|
}
|
|
if(nval>1)
|
|
{
|
|
view->shape[expr_self->ndim] = nval;
|
|
}
|
|
}
|
|
view->strides = NULL;
|
|
view->suboffsets = NULL;
|
|
|
|
Py_INCREF(self);
|
|
return 0;
|
|
|
|
buff_error:
|
|
PyErr_Format(PyExc_BufferError,
|
|
"Unable to provide buffer : %s", strerror(errno));
|
|
view->obj = NULL;
|
|
return -1;
|
|
}
|
|
|
|
void rpnif_releasebuffer(PyObject *self, Py_buffer *view)
|
|
{
|
|
free(view->shape);
|
|
}
|
|
|
|
PyObject* rpnif_str(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = \
|
|
(rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
const size_t rpn_sz = expr_self->rif->params->rpn_sz;
|
|
const char pyfmt[] = "%VA%ld=%U=\"%S\";";
|
|
|
|
size_t i;
|
|
PyObject *buf, *tmp, *items;
|
|
|
|
buf = NULL;
|
|
items = rpnif_items(self);
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
|
|
|
|
for(i=0; i<rpn_sz; i++)
|
|
{
|
|
PyObject *key, *value, *elt;
|
|
elt = PyTuple_GET_ITEM(items, i);
|
|
key = PyTuple_GET_ITEM(elt, 0);
|
|
value = PyTuple_GET_ITEM(elt, 1);
|
|
|
|
tmp = PyUnicode_FromFormat(pyfmt,
|
|
buf, "",
|
|
i, key, value);
|
|
if(buf) { Py_DECREF(buf); }
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
buf = tmp;
|
|
}
|
|
|
|
|
|
switch(rif_data->res_flag)
|
|
{
|
|
case RPN_IF_RES_CONST:
|
|
tmp = PyUnicode_FromFormat("%U A%ld=C(*)=%lld",
|
|
buf, i+1, rif_data->const_val[0]);
|
|
Py_DECREF(buf);
|
|
buf=tmp;
|
|
break;
|
|
case RPN_IF_RES_CONST_RGBA:
|
|
tmp = PyUnicode_FromFormat("%U A%ld=R(*)=%lld A%ld=G(*)=%lld A%ld=B(*)=%lld A%ld=A(*)=%lld",
|
|
buf,
|
|
i+1, rif_data->const_val[0],
|
|
i+2, rif_data->const_val[1],
|
|
i+3, rif_data->const_val[2],
|
|
i+4, rif_data->const_val[3]);
|
|
Py_DECREF(buf);
|
|
buf=tmp;
|
|
break;
|
|
}
|
|
|
|
Py_INCREF(buf);
|
|
return buf;
|
|
}
|
|
|
|
/** Return a string representation of expressions dict
|
|
* @param self @ref PyRPNIterExpr_t instance
|
|
* @return a str instance */
|
|
static PyObject* _rpnif_expr_repr(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = \
|
|
(rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
|
|
PyObject *buf, *tmp, *items, *const_res;
|
|
const char pyfmt[] = "%V\"%U\":\"%S\"%V";
|
|
|
|
buf = const_res = NULL;
|
|
|
|
items = rpnif_items(self);
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
|
|
#define _const_res_key ",\"const_res\":"
|
|
switch(rif_data->res_flag)
|
|
{
|
|
case RPN_IF_RES_CONST:
|
|
const_res = PyUnicode_FromFormat(
|
|
_const_res_key "{\"r\":%llu}}",
|
|
rif_data->const_val[0]);
|
|
break;
|
|
/*
|
|
case RPN_IF_RES_CONST_RGB:
|
|
const_res = PyUnicode_FromFormat(
|
|
"\"const_res\": {\"r\":%llu, \"g\":%llu, \"b\":%llu}}",
|
|
rif_data->const_val[0],
|
|
rif_data->const_val[1],
|
|
rif_data->const_val[2])
|
|
break;
|
|
*/
|
|
case RPN_IF_RES_CONST_RGBA:
|
|
const_res = PyUnicode_FromFormat(
|
|
_const_res_key \
|
|
"{\"r\":%llu,\"g\":%llu,\"b\":%llu,\"a\":%llu}}",
|
|
rif_data->const_val[0],
|
|
rif_data->const_val[1],
|
|
rif_data->const_val[2],
|
|
rif_data->const_val[3]);
|
|
break;
|
|
default:
|
|
const_res = PyUnicode_FromFormat("}");
|
|
break;
|
|
}
|
|
#undef _const_res_key
|
|
|
|
const size_t rpn_sz = expr_self->rif->params->rpn_sz;
|
|
|
|
for(size_t i=0; i<rpn_sz; i++)
|
|
{
|
|
PyObject *key, *value, *elt;
|
|
elt = PyTuple_GET_ITEM(items, i);
|
|
key = PyTuple_GET_ITEM(elt, 0);
|
|
value = PyTuple_GET_ITEM(elt, 1);
|
|
|
|
tmp = PyUnicode_FromFormat(pyfmt,
|
|
buf, "{", key, value,
|
|
i==rpn_sz-1?const_res:NULL, ",");
|
|
if(buf)
|
|
{
|
|
Py_DECREF(buf);
|
|
}
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
buf = tmp;
|
|
}
|
|
|
|
|
|
return buf;
|
|
}
|
|
|
|
PyObject* rpnif_repr(PyObject *self)
|
|
{
|
|
PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
|
|
rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
|
|
|
|
char *str_pos, *str_res;
|
|
char tmp[64];
|
|
|
|
PyObject *expr_repr = _rpnif_expr_repr(self);
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
|
|
switch(rif_data->pos_flag)
|
|
{
|
|
case RPN_IF_POSITION_XY:
|
|
str_pos = "XY";
|
|
break;
|
|
case RPN_IF_POSITION_LINEAR:
|
|
str_pos = "LINEAR";
|
|
break;
|
|
case RPN_IF_POSITION_XDIM:
|
|
snprintf(tmp, 64, "XDIM%ld", rif_data->size_lim[0]);
|
|
str_pos = tmp;
|
|
break;
|
|
default:
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"UNKOWN POS_FLAG2");
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *const_res = NULL;
|
|
|
|
switch(rif_data->res_flag)
|
|
{
|
|
case RPN_IF_RES_BOOL:
|
|
str_res = "BOOL";
|
|
break;
|
|
case RPN_IF_RES_CONST:
|
|
str_res = "CONST";
|
|
const_res = PyTuple_New(1);
|
|
break;
|
|
case RPN_IF_RES_CONST_RGBA:
|
|
str_res = "CONST_RGBA";
|
|
break;
|
|
case RPN_IF_RES_COUNT:
|
|
str_res = "COUNT";
|
|
break;
|
|
case RPN_IF_RES_XFUN:
|
|
str_res = "XFUN";
|
|
break;
|
|
case RPN_IF_RES_RGB:
|
|
str_res = "RGB";
|
|
break;
|
|
case RPN_IF_RES_RGBA:
|
|
str_res = "RGBA";
|
|
break;
|
|
default:
|
|
PyErr_SetString(PyExc_RuntimeError,
|
|
"UNKOWN RES_FLAG2");
|
|
return NULL;
|
|
}
|
|
|
|
PyObject *res;
|
|
|
|
const_res = const_res?const_res:Py_None;
|
|
|
|
res = PyUnicode_FromFormat(
|
|
"<RPNIterExpr pos_flag:%s res_flag:%s expr:'%U' const_res:%S>",
|
|
str_pos, str_res, expr_repr, const_res);
|
|
if(PyErr_Occurred()) { return NULL; }
|
|
return res;
|
|
}
|
|
|
|
PyObject* rpnif_getstate(PyObject *self, PyObject *noargs)
|
|
{
|
|
PyErr_SetString(PyExc_NotImplementedError,
|
|
"getstate Not implemented");
|
|
return NULL;
|
|
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
PyObject* rpnif_setstate(PyObject *self, PyObject *state_bytes)
|
|
{
|
|
PyErr_SetString(PyExc_NotImplementedError,
|
|
"setstate Not implemented");
|
|
return NULL;
|
|
/**@todo TODO write the function */
|
|
Py_RETURN_NONE;
|
|
}
|
|
|
|
rpn_if_param_t *_rpnif_get_params(unsigned short pos_flag, unsigned short res_flag,
|
|
PyObject *lim_obj, PyObject *const_values_obj,
|
|
unsigned short stack_size)
|
|
{
|
|
char err_str[256];
|
|
int ndim;
|
|
|
|
// Args checking
|
|
if(stack_size < 4 || stack_size > 255)
|
|
{
|
|
snprintf(err_str, 128,
|
|
"Stack size should be in [0..255] but %u given",
|
|
stack_size);
|
|
PyErr_SetString(PyExc_ValueError, err_str);
|
|
return NULL;
|
|
}
|
|
|
|
// Checks flags & fetch expected sizes for size_lim & const_values
|
|
short expt_sizes[2];
|
|
if(rpn_if_sizes_from_flag(pos_flag, res_flag, expt_sizes) < 0)
|
|
{
|
|
if(expt_sizes[0] < 0)
|
|
{
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"Invalid position flag given");
|
|
}
|
|
else
|
|
{
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"Invalid result flag given");
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//Check & convert lim
|
|
PyObject *tmp;
|
|
tmp = PySequence_Fast(lim_obj, "Sequence expected for size_lim argument");
|
|
if(PyErr_Occurred())
|
|
{
|
|
return NULL;
|
|
}
|
|
Py_ssize_t lim_obj_sz = PySequence_Fast_GET_SIZE(tmp);
|
|
ndim = lim_obj_sz;
|
|
if(PyErr_Occurred())
|
|
{
|
|
Py_DECREF(tmp);
|
|
return NULL;
|
|
}
|
|
if(lim_obj_sz < 1)
|
|
{
|
|
Py_DECREF(tmp);
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"Size limits cannot be empty");
|
|
return NULL;
|
|
}
|
|
|
|
if(pos_flag == RPN_IF_POSITION_XDIM)
|
|
{
|
|
PyObject *item = PySequence_Fast_GET_ITEM(tmp, 0);
|
|
Py_ssize_t tmp = PyLong_AsSsize_t(item);
|
|
if(PyErr_Occurred())
|
|
{
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"Unable to convert size_lim[0] to int");
|
|
Py_DECREF(tmp);
|
|
return NULL;
|
|
}
|
|
if(lim_obj_sz != tmp + 1)
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Xdim indicate %d size_lim but len(size_lim)=%d",
|
|
tmp+1, lim_obj_sz);
|
|
Py_DECREF(tmp);
|
|
return NULL;
|
|
}
|
|
expt_sizes[0] = ndim = tmp;
|
|
}
|
|
else
|
|
{
|
|
if(lim_obj_sz != expt_sizes[0])
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Expected %d size_lim but len(size_lim)=%d",
|
|
expt_sizes[0], lim_obj_sz);
|
|
Py_DECREF(tmp);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
size_t sz_limits[lim_obj_sz];
|
|
for(Py_ssize_t i = 0; i<lim_obj_sz; i++)
|
|
{
|
|
PyObject *item = PySequence_Fast_GET_ITEM(tmp, i);
|
|
sz_limits[i] = PyLong_AsSize_t(item);
|
|
if(PyErr_Occurred())
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Unable to convert size_lim[%d] to unsigned int",
|
|
i);
|
|
Py_DECREF(tmp);
|
|
return NULL;
|
|
}
|
|
}
|
|
Py_DECREF(tmp);
|
|
tmp = NULL;
|
|
|
|
//Check & convert const values
|
|
Py_ssize_t values_obj_sz = 0;
|
|
if(expt_sizes[1] > 0)
|
|
{
|
|
tmp = const_values_obj;
|
|
if(!PyTuple_Check(tmp))
|
|
{
|
|
PyErr_SetString(PyExc_ValueError,
|
|
"Invalid type for const_values argument");
|
|
return NULL;
|
|
}
|
|
values_obj_sz = PyTuple_Size(tmp);
|
|
if(values_obj_sz != expt_sizes[1])
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Expected %d const_values but len(const_values)=%d",
|
|
expt_sizes[1], values_obj_sz);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
rpn_value_t const_values[values_obj_sz];
|
|
for(Py_ssize_t i = 0; i<values_obj_sz; i++)
|
|
{
|
|
PyObject *item = PyTuple_GET_ITEM(tmp, i);
|
|
const_values[i] = PyLong_AsRpnValue_t(item);
|
|
if(PyErr_Occurred())
|
|
{
|
|
PyErr_Format(PyExc_ValueError,
|
|
"Unable to convert size_lim[%d] to unsigned int",
|
|
i);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
// Creating rif params
|
|
rpn_if_param_t *rif_params;
|
|
|
|
if(!(rif_params = rpn_if_default_params(pos_flag, res_flag,
|
|
sz_limits, const_values, stack_size)))
|
|
{
|
|
PyErr_SetString(PyExc_ValueError, "Unable to create parameters \
|
|
with given arguments");
|
|
return NULL;
|
|
}
|
|
|
|
return rif_params;
|
|
}
|
|
|
|
PyObject *_rpnif_params_to_tuple(const rpn_if_param_t *_params)
|
|
{
|
|
PyObject *res, *val;
|
|
short expt_sizes[2];
|
|
rpn_if_default_data_t *params;
|
|
params = (rpn_if_default_data_t*)(_params->data);
|
|
|
|
if(rpn_if_sizes_from_flag(params->pos_flag, params->res_flag, expt_sizes) < 0)
|
|
{
|
|
PyErr_SetString(PyExc_RuntimeError, "Invalid internal state");
|
|
return NULL;
|
|
}
|
|
|
|
res = PyStructSequence_New(&rpnif_params_SeqDesc);
|
|
if(!res)
|
|
{
|
|
return NULL;
|
|
}
|
|
val = PyLong_FromLong(_params->rpn_argc);
|
|
PyStructSequence_SET_ITEM(res, 0, val);
|
|
|
|
val = PyLong_FromLong(params->pos_flag);
|
|
PyStructSequence_SET_ITEM(res, 1, val);
|
|
|
|
val = PyLong_FromLong(params->res_flag);
|
|
PyStructSequence_SET_ITEM(res, 2, val);
|
|
|
|
if(params->pos_flag == RPN_IF_POSITION_XDIM)
|
|
{
|
|
expt_sizes[0] = params->size_lim[0] + 1;
|
|
}
|
|
|
|
PyObject *lim = PyTuple_New(expt_sizes[0]);
|
|
if(!lim)
|
|
{
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
PyStructSequence_SET_ITEM(res, 3, lim);
|
|
|
|
for(Py_ssize_t i=0; i<expt_sizes[0]; i++)
|
|
{
|
|
val = PyLong_FromSize_t(params->size_lim[i]);
|
|
PyTuple_SET_ITEM(lim, i, val);
|
|
}
|
|
|
|
if(!params->const_val)
|
|
{
|
|
Py_INCREF(Py_None);
|
|
PyTuple_SET_ITEM(res, 4, Py_None);
|
|
}
|
|
else
|
|
{
|
|
PyObject *values = PyTuple_New(expt_sizes[1]);
|
|
if(!values)
|
|
{
|
|
Py_DECREF(res);
|
|
return NULL;
|
|
}
|
|
PyStructSequence_SET_ITEM(res, 4, values);
|
|
for(Py_ssize_t i=0; i<expt_sizes[1]; i++)
|
|
{
|
|
val = PyLong_FromRpnValue_t(params->const_val[i]);
|
|
PyTuple_SET_ITEM(values, i, val);
|
|
}
|
|
}
|
|
val = PyLong_FromUnsignedLong(_params->mem_sz * _params->value_sz);
|
|
PyStructSequence_SET_ITEM(res, 5, val);
|
|
return res;
|
|
}
|
|
|
|
/**@def _ret_append(key)
|
|
* @hiderefs
|
|
* local macro */
|
|
/**@def _const_res_key()
|
|
* @hiderefs
|
|
* local macro*/
|
|
|