Fast IFS using RPN notation
python
c
x86-64
nasm
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

python_if.c 22KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018
  1. #include "python_if.h"
  2. /**@file python_if.c
  3. * @brief Python RPNIterExpr type definition
  4. * @ingroup python_ext
  5. * @ingroup pymod_pyrpn_RPNExprIter
  6. */
  7. /**@brief @ref pymod_pyrpn_RPNExprIter methods definition
  8. * @ingroup pymod_pyrpn_RPNExprIter */
  9. static PyMethodDef RPNIterExpr_methods[] = {
  10. PYRPN_method("get_params", rpnif_get_params,
  11. METH_NOARGS,
  12. "self, /",
  13. "Get a name tuple with parameters"),
  14. PYRPN_method("keys", rpnif_keys,
  15. METH_NOARGS,
  16. "self, /",
  17. "Return items keys (see dict.keys)"),
  18. PYRPN_method("values", rpnif_values,
  19. METH_NOARGS,
  20. "self, /",
  21. "Return items values (see dict.values)"),
  22. PYRPN_method("items", rpnif_items,
  23. METH_NOARGS,
  24. "self, /",
  25. "Return items (key, value) list (see dict.items)"),
  26. PYRPN_method("step", rpnif_step,
  27. METH_O,
  28. "self, position, /",
  29. "Run an IF given a position and return a new position"),
  30. PYRPN_method("__getstate__", rpnif_getstate,
  31. METH_NOARGS,
  32. "self, /",
  33. "Pickling method (see pickle module).\n"
  34. "Return a bytes representation of the expression state."),
  35. PYRPN_method("__setstate__", rpnif_setstate,
  36. METH_O,
  37. "self, state, /",
  38. "Unpickling method (see pickle module)."),
  39. {NULL} //Sentinel
  40. };
  41. /**@brief @ref pymod_pyrpn_RPNExprIter members definition
  42. * @ingroup pymod_pyrpn_RPNExprIter */
  43. static PyMemberDef RPNIterExpr_members[] = {
  44. {"expressions", T_OBJECT, offsetof(PyRPNIterExpr_t, expr), READONLY,
  45. "The tuple of expressions"},
  46. {NULL}
  47. };
  48. /**@brief @ref pymod_pyrpn_RPNExprIter sequence methods definition
  49. * @ingroup pymod_pyrpn_RPNExprIter */
  50. static PySequenceMethods RPNIterExpr_seq_methods = {
  51. .sq_length = rpnif_len,
  52. .sq_item = rpnif_expr_item,
  53. .sq_ass_item = rpnif_expr_ass_item,
  54. };
  55. /**@brief @ref pymod_pyrpn_RPNExprIter mapping methods definition
  56. * @ingroup pymod_pyrpn_RPNExprIter */
  57. static PyMappingMethods RPNIterExpr_mapping_methods = {
  58. .mp_length = rpnif_len,
  59. .mp_subscript = rpnif_subscript,
  60. .mp_ass_subscript = rpnif_ass_subscript,
  61. };
  62. /**@brief @ref pymod_pyrpn_RPNExprIter attributes definition
  63. * @ingroup pymod_pyrpn_RPNExprIter */
  64. static PyGetSetDef RPNIterExpr_getset[] = {
  65. {NULL}
  66. };
  67. /**@brief @ref pymod_pyrpn_RPNExprIter buffer methods definition
  68. * @ingroup pymod_pyrpn_RPNExprIter */
  69. static PyBufferProcs RPNIterExpr_as_buffer = {
  70. (getbufferproc)rpnif_getbuffer,
  71. (releasebufferproc)rpnif_releasebuffer,
  72. };
  73. PyTypeObject RPNIterExprType = {
  74. PyVarObject_HEAD_INIT(NULL, 0)
  75. .tp_name = "pyrpn.RPNIterExpr",
  76. .tp_basicsize = sizeof(PyRPNIterExpr_t),
  77. .tp_itemsize = 0,
  78. .tp_del = rpnif_del,
  79. .tp_repr = rpnif_repr,
  80. .tp_as_sequence = &RPNIterExpr_seq_methods,
  81. .tp_as_mapping = &RPNIterExpr_mapping_methods,
  82. .tp_str = rpnif_str,
  83. .tp_as_buffer = &RPNIterExpr_as_buffer,
  84. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
  85. .tp_doc = "RPN expression evaluator",
  86. .tp_methods = RPNIterExpr_methods,
  87. .tp_members = RPNIterExpr_members,
  88. .tp_getset = RPNIterExpr_getset,
  89. .tp_init = rpnif_init,
  90. .tp_new = rpnif_new,
  91. };
  92. PyObject* rpnif_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
  93. {
  94. PyObject *ret, *err;
  95. PyRPNIterExpr_t *expr;
  96. ret = PyType_GenericNew(subtype, args, kwds);
  97. if((err = PyErr_Occurred()))
  98. {
  99. Py_DECREF(err);
  100. return ret;
  101. }
  102. expr = (PyRPNIterExpr_t*)ret;
  103. expr->rif = NULL;
  104. return ret;
  105. }
  106. int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds)
  107. {
  108. PyRPNIterExpr_t *expr_self;
  109. char *names[] = {"pos_flag", "res_flag", "size_lim", "const_values", "stack_size", NULL};
  110. unsigned short pos_flag, res_flag, stack_size;
  111. PyObject *lim_obj, *const_values_obj;
  112. int ndim;
  113. char err_str[256];
  114. expr_self = (PyRPNIterExpr_t*)self;
  115. stack_size = 16;
  116. const_values_obj = lim_obj = NULL;
  117. expr_self->rif = NULL;
  118. if(!PyArg_ParseTupleAndKeywords(args, kwds, "HHO|OH:RPNIterExpr.__init__", names,
  119. &pos_flag, &res_flag, &lim_obj, &const_values_obj, &stack_size))
  120. {
  121. return -1;
  122. }
  123. // Args checking
  124. if(stack_size < 4 || stack_size > 255)
  125. {
  126. snprintf(err_str, 128,
  127. "Stack size should be in [0..255] but %u given",
  128. stack_size);
  129. PyErr_SetString(PyExc_ValueError, err_str);
  130. return -1;
  131. }
  132. // Checks flags & fetch expected sizes for size_lim & const_values
  133. short expt_sizes[2];
  134. if(rpn_if_sizes_from_flag(pos_flag, res_flag, expt_sizes) < 0)
  135. {
  136. if(expt_sizes[0] < 0)
  137. {
  138. PyErr_SetString(PyExc_ValueError,
  139. "Invalid position flag given");
  140. }
  141. else
  142. {
  143. PyErr_SetString(PyExc_ValueError,
  144. "Invalid result flag given");
  145. }
  146. return -1;
  147. }
  148. //Check & convert lim
  149. PyObject *tmp;
  150. tmp = lim_obj;
  151. if(!PyTuple_Check(tmp))
  152. {
  153. PyErr_SetString(PyExc_ValueError,
  154. "Invalid type for size_lim argument");
  155. return -1;
  156. }
  157. Py_ssize_t lim_obj_sz = PyTuple_Size(tmp);
  158. ndim = lim_obj_sz;
  159. if(PyErr_Occurred())
  160. {
  161. return -1;
  162. }
  163. if(lim_obj_sz < 1)
  164. {
  165. PyErr_SetString(PyExc_ValueError,
  166. "Size limits cannot be empty");
  167. }
  168. if(pos_flag == RPN_IF_POSITION_XDIM)
  169. {
  170. PyObject *item = PyTuple_GET_ITEM(tmp, 0);
  171. Py_ssize_t tmp = PyLong_AsSsize_t(item);
  172. if(PyErr_Occurred())
  173. {
  174. PyErr_SetString(PyExc_ValueError,
  175. "Unable to convert size_lim[0] to int");
  176. return -1;
  177. }
  178. if(lim_obj_sz != tmp + 1)
  179. {
  180. PyErr_Format(PyExc_ValueError,
  181. "Xdim indicate %d size_lim but len(size_lim)=%d",
  182. tmp+1, lim_obj_sz);
  183. return -1;
  184. }
  185. expt_sizes[0] = ndim = tmp;
  186. }
  187. else
  188. {
  189. if(lim_obj_sz != expt_sizes[0])
  190. {
  191. PyErr_Format(PyExc_ValueError,
  192. "Expected %d size_lim but len(size_lim)=%d",
  193. expt_sizes[0], lim_obj_sz);
  194. return -1;
  195. }
  196. }
  197. size_t sz_limits[lim_obj_sz];
  198. for(Py_ssize_t i = 0; i<lim_obj_sz; i++)
  199. {
  200. PyObject *item = PyTuple_GET_ITEM(tmp, i);
  201. sz_limits[i] = PyLong_AsSize_t(item);
  202. if(PyErr_Occurred())
  203. {
  204. PyErr_Format(PyExc_ValueError,
  205. "Unable to convert size_lim[%d] to unsigned int",
  206. i);
  207. return -1;
  208. }
  209. }
  210. expr_self->ndim = ndim;
  211. //Check & convert const values
  212. Py_ssize_t values_obj_sz = 0;
  213. tmp = NULL;
  214. if(expt_sizes[1] > 0)
  215. {
  216. tmp = const_values_obj;
  217. if(!PyTuple_Check(tmp))
  218. {
  219. PyErr_SetString(PyExc_ValueError,
  220. "Invalid type for const_values argument");
  221. return -1;
  222. }
  223. values_obj_sz = PyTuple_Size(tmp);
  224. if(values_obj_sz != expt_sizes[1])
  225. {
  226. PyErr_Format(PyExc_ValueError,
  227. "Expected %d const_values but len(const_values)=%d",
  228. expt_sizes[1], values_obj_sz);
  229. return -1;
  230. }
  231. }
  232. rpn_value_t const_values[values_obj_sz];
  233. for(Py_ssize_t i = 0; i<values_obj_sz; i++)
  234. {
  235. PyObject *item = PyTuple_GET_ITEM(tmp, i);
  236. const_values[i] = PyLong_AsRpnValue_t(item);
  237. if(PyErr_Occurred())
  238. {
  239. PyErr_Format(PyExc_ValueError,
  240. "Unable to convert size_lim[%d] to unsigned int",
  241. i);
  242. return -1;
  243. }
  244. }
  245. // Creating rif params
  246. rpn_if_param_t *rif_params;
  247. if(!(rif_params = rpn_if_default_params(pos_flag, res_flag,
  248. sz_limits, const_values, stack_size)))
  249. {
  250. PyErr_SetString(PyExc_ValueError, "Unable to create parameters \
  251. with given arguments");
  252. return -1;
  253. }
  254. // Creating rif with a new memory map
  255. expr_self->rif = rpn_if_new(rif_params, NULL);
  256. // Creating the tuple holding RPNExpr instances of expressions
  257. expr_self->expr = PyTuple_New(expr_self->rif->params->rpn_sz);
  258. for(size_t i=0; i<expr_self->rif->params->rpn_sz;i++)
  259. {
  260. rpn_expr_t *expr = &expr_self->rif->rpn[i];
  261. PyObject *instance = rpnexpr_init_borrowing(expr);
  262. if(!instance)
  263. {
  264. return -1;
  265. }
  266. PyTuple_SET_ITEM(expr_self->expr, i, instance);
  267. }
  268. return 0;
  269. }
  270. /**@brief Returns the parameters in a named tuple */
  271. PyObject *rpnif_get_params(PyObject *self)
  272. {
  273. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  274. PyObject *res, *val;
  275. rpn_if_default_data_t *params;
  276. params = (rpn_if_default_data_t*)(expr_self->rif->params->data);
  277. short expt_sizes[2];
  278. if(rpn_if_sizes_from_flag(params->pos_flag, params->res_flag, expt_sizes) < 0)
  279. {
  280. PyErr_SetString(PyExc_RuntimeError, "Invalid internal state");
  281. return NULL;
  282. }
  283. res = PyStructSequence_New(&rpnif_params_SeqDesc);
  284. if(!res)
  285. {
  286. return NULL;
  287. }
  288. val = PyLong_FromLong(expr_self->rif->params->rpn_argc);
  289. PyStructSequence_SET_ITEM(res, 0, val);
  290. val = PyLong_FromLong(params->pos_flag);
  291. PyStructSequence_SET_ITEM(res, 1, val);
  292. val = PyLong_FromLong(params->res_flag);
  293. PyStructSequence_SET_ITEM(res, 2, val);
  294. if(params->pos_flag == RPN_IF_POSITION_XDIM)
  295. {
  296. expt_sizes[0] = params->size_lim[0] + 1;
  297. }
  298. PyObject *lim = PyTuple_New(expt_sizes[0]);
  299. if(!lim)
  300. {
  301. Py_DECREF(res);
  302. return NULL;
  303. }
  304. PyStructSequence_SET_ITEM(res, 3, lim);
  305. for(Py_ssize_t i=0; i<expt_sizes[0]; i++)
  306. {
  307. val = PyLong_FromSize_t(params->size_lim[i]);
  308. PyTuple_SET_ITEM(lim, i, val);
  309. }
  310. if(!params->const_val)
  311. {
  312. Py_INCREF(Py_None);
  313. PyTuple_SET_ITEM(res, 4, Py_None);
  314. }
  315. else
  316. {
  317. PyObject *values = PyTuple_New(expt_sizes[1]);
  318. if(!values)
  319. {
  320. Py_DECREF(res);
  321. return NULL;
  322. }
  323. PyStructSequence_SET_ITEM(res, 4, values);
  324. for(Py_ssize_t i=0; i<expt_sizes[1]; i++)
  325. {
  326. val = PyLong_FromRpnValue_t(params->const_val[i]);
  327. PyTuple_SET_ITEM(values, i, val);
  328. }
  329. }
  330. return res;
  331. }
  332. PyObject *rpnif_step(PyObject *self, PyObject* opos)
  333. {
  334. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  335. if(!PyLong_Check(opos))
  336. {
  337. PyErr_SetString(PyExc_TypeError, "Expected position to be an int");
  338. return NULL;
  339. }
  340. size_t pos = PyLong_AsSize_t(opos);
  341. if(PyErr_Occurred())
  342. {
  343. return NULL;
  344. }
  345. pos = rpn_if_step(expr_self->rif, pos);
  346. return PyLong_FromSize_t(pos);
  347. }
  348. PyObject *rpnif_keys(PyObject *self)
  349. {
  350. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  351. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  352. Py_ssize_t ret_idx = 0;
  353. char xdim_key[64];
  354. PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
  355. if(PyErr_Occurred())
  356. {
  357. return NULL;
  358. }
  359. #define _ret_append(key) PyTuple_SET_ITEM(ret, ret_idx++, \
  360. PyUnicode_FromString(key))
  361. switch(rif_data->pos_flag)
  362. {
  363. case RPN_IF_POSITION_XY:
  364. _ret_append("X");
  365. _ret_append("Y");
  366. break;
  367. case RPN_IF_POSITION_LINEAR:
  368. _ret_append("X");
  369. break;
  370. case RPN_IF_POSITION_XDIM:
  371. for(size_t i=0; i<rif_data->size_lim[0];i++)
  372. {
  373. snprintf(xdim_key, 64, "D%ld", i);
  374. _ret_append(xdim_key);
  375. }
  376. break;
  377. default:
  378. PyErr_SetString(PyExc_RuntimeError,
  379. "UNKOWN POS_FLAG3");
  380. return NULL;
  381. }
  382. switch(rif_data->res_flag)
  383. {
  384. case RPN_IF_RES_BOOL:
  385. case RPN_IF_RES_XFUN:
  386. _ret_append("R");
  387. break;
  388. case RPN_IF_RES_RGB:
  389. _ret_append("R");
  390. _ret_append("G");
  391. _ret_append("B");
  392. break;
  393. case RPN_IF_RES_RGBA:
  394. _ret_append("R");
  395. _ret_append("G");
  396. _ret_append("B");
  397. _ret_append("A");
  398. break;
  399. default:
  400. break;
  401. }
  402. if(PyErr_Occurred())
  403. {
  404. return NULL;
  405. }
  406. return ret;
  407. #undef _ret_append
  408. }
  409. PyObject *rpnif_values(PyObject *self)
  410. {
  411. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  412. Py_INCREF(expr_self->expr);
  413. return expr_self->expr;
  414. }
  415. PyObject *rpnif_items(PyObject *self)
  416. {
  417. size_t i;
  418. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  419. PyObject *ret = PyTuple_New(expr_self->rif->params->rpn_sz);
  420. if(PyErr_Occurred())
  421. {
  422. return NULL;
  423. }
  424. PyObject *keys = rpnif_keys(self);
  425. for(i=0; i<expr_self->rif->params->rpn_sz; i++)
  426. {
  427. PyObject *tmp = PyTuple_New(2);
  428. if(PyErr_Occurred())
  429. {
  430. goto err_loop_newtuple;
  431. }
  432. PyObject *key = PyTuple_GET_ITEM(keys, i);
  433. PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
  434. Py_INCREF(key);
  435. Py_INCREF(value);
  436. PyTuple_SET_ITEM(tmp, 0, key);
  437. PyTuple_SET_ITEM(tmp, 1, value);
  438. PyTuple_SET_ITEM(ret, i, tmp);
  439. if(PyErr_Occurred())
  440. {
  441. goto err_loop_setitem;
  442. }
  443. }
  444. return ret;
  445. /** @todo cleanup seems wrong... */
  446. for(i=i; i>=0; i--)
  447. {
  448. err_loop_setitem:
  449. PyObject *key = PyTuple_GET_ITEM(keys, i);
  450. PyObject *value = PyTuple_GET_ITEM(expr_self->expr, i);
  451. Py_DECREF(key);
  452. Py_DECREF(value);
  453. err_loop_newtuple:
  454. }
  455. Py_DECREF(ret);
  456. return NULL;
  457. }
  458. void rpnif_del(PyObject *self)
  459. {
  460. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  461. if(expr_self->rif)
  462. {
  463. rpn_if_free(expr_self->rif);
  464. expr_self->rif = NULL;
  465. }
  466. }
  467. Py_ssize_t rpnif_len(PyObject *self)
  468. {
  469. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  470. return expr_self->rif->params->rpn_sz;
  471. }
  472. PyObject* rpnif_expr_item(PyObject *self, Py_ssize_t idx)
  473. {
  474. Py_ssize_t _idx = idx;
  475. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  476. if(idx < 0)
  477. {
  478. idx = expr_self->rif->params->rpn_sz - 1 + idx;
  479. }
  480. if(idx < 0 || (size_t) idx >= expr_self->rif->params->rpn_sz)
  481. {
  482. PyErr_Format(PyExc_IndexError,
  483. "No expression %ld with given options",
  484. _idx);
  485. return NULL;
  486. }
  487. PyObject *ret = PyTuple_GET_ITEM(expr_self->expr, idx);
  488. Py_INCREF(ret);
  489. return ret;
  490. }
  491. int rpnif_expr_ass_item(PyObject *self, Py_ssize_t idx, PyObject* elt)
  492. {
  493. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  494. if(!PyUnicode_Check(elt))
  495. {
  496. PyErr_SetString(PyExc_TypeError, "RPNExpr expected");
  497. return -1;
  498. }
  499. PyObject *bytes_str = PyUnicode_AsASCIIString(elt);
  500. if(PyErr_Occurred())
  501. {
  502. return -1;
  503. }
  504. const char *code = PyBytes_AS_STRING(bytes_str);
  505. rpn_expr_t *expr = &(expr_self->rif->rpn[idx]);
  506. if(rpn_expr_recompile(expr, code) < 0)
  507. {
  508. PyErr_Format(PyExc_ValueError,
  509. "Error during expression '%s' compilation : %s",
  510. code, expr->err_reason);
  511. return -1;
  512. }
  513. return 0;
  514. }
  515. /** Convert key to integer index
  516. * @param self @ref PyRPNIterExpr_t instance
  517. * @param _key An expression name (str)
  518. * @return The expression index or -1 on error (raise python exception)
  519. */
  520. static Py_ssize_t _rpnif_subscript_idx(PyObject *self, PyObject *_key)
  521. {
  522. if(!PyUnicode_Check(_key))
  523. {
  524. PyErr_SetString(PyExc_TypeError, "Key should be a str");
  525. return -1;
  526. }
  527. PyObject *bytes_str = PyUnicode_AsASCIIString(_key);
  528. if(PyErr_Occurred())
  529. {
  530. return -1;
  531. }
  532. const char *key = PyBytes_AS_STRING(bytes_str);
  533. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  534. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  535. Py_ssize_t idx = -1;
  536. Py_ssize_t res_idx = -1;
  537. switch(rif_data->pos_flag)
  538. {
  539. case RPN_IF_POSITION_XY:
  540. res_idx = 2;
  541. if(key[1] != '\0') { break; }
  542. switch(key[0])
  543. {
  544. case 'X':
  545. idx=0;
  546. break;
  547. case 'Y':
  548. idx=1;
  549. break;
  550. }
  551. break;
  552. case RPN_IF_POSITION_LINEAR:
  553. res_idx = 1;
  554. if(!strcmp("X", key))
  555. {
  556. idx = 0;
  557. }
  558. break;
  559. case RPN_IF_POSITION_XDIM:
  560. size_t ndim = rif_data->size_lim[0];
  561. res_idx = ndim;
  562. char possible_key[64];
  563. for(size_t i=0; i<ndim; i++)
  564. {
  565. snprintf(possible_key, 64, "D%ld", i);
  566. if(!strcmp(possible_key, key))
  567. {
  568. idx = i;
  569. break;
  570. }
  571. }
  572. break;
  573. default:
  574. PyErr_SetString(PyExc_RuntimeError,
  575. "UNKOWN POS_FLAG");
  576. return -1;
  577. }
  578. if(idx < 0)
  579. {
  580. // not found yet, looking for result key
  581. switch(rif_data->res_flag)
  582. {
  583. case RPN_IF_RES_BOOL:
  584. case RPN_IF_RES_XFUN:
  585. if(!strcmp("R", key))
  586. {
  587. idx = res_idx;
  588. }
  589. break;
  590. case RPN_IF_RES_RGBA:
  591. if(!strcmp("A", key))
  592. {
  593. idx = res_idx + 3;
  594. }
  595. case RPN_IF_RES_RGB:
  596. if(key[1] != '\0')
  597. {
  598. break;
  599. }
  600. switch(key[0])
  601. {
  602. case 'R':
  603. idx=res_idx;
  604. break;
  605. case 'G':
  606. idx=res_idx+1;
  607. break;
  608. case 'B':
  609. idx=res_idx+2;
  610. break;
  611. }
  612. break;
  613. default:
  614. // not implemented, not unknown....
  615. PyErr_SetString(PyExc_RuntimeError,
  616. "UNKOWN RES_FLAG");
  617. return -1;
  618. }
  619. }
  620. return idx;
  621. }
  622. PyObject* rpnif_subscript(PyObject *self, PyObject *key)
  623. {
  624. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  625. Py_ssize_t idx = _rpnif_subscript_idx(self, key);
  626. if(idx < 0)
  627. {
  628. PyErr_Format(PyExc_IndexError,
  629. "No expression '%s' with given parameters",
  630. key);
  631. return NULL;
  632. }
  633. PyObject *expr = PyTuple_GET_ITEM(expr_self->expr, idx);
  634. Py_INCREF(expr);
  635. return expr;
  636. }
  637. int rpnif_ass_subscript(PyObject *self, PyObject *key, PyObject *elt)
  638. {
  639. Py_ssize_t idx = _rpnif_subscript_idx(self, key);
  640. if(idx < 0)
  641. {
  642. PyErr_Format(PyExc_IndexError,
  643. "Cannot set expression '%s' that do not exists with this parameters",
  644. key);
  645. return -1;
  646. }
  647. return rpnif_expr_ass_item(self, idx, elt);
  648. }
  649. int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags)
  650. {
  651. PyRPNIterExpr_t *expr_self;
  652. expr_self = (PyRPNIterExpr_t*)self;
  653. rpn_if_default_data_t *data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  654. view->buf = expr_self->rif->mem;
  655. view->obj = self;
  656. view->len = expr_self->rif->params->mem_sz * expr_self->rif->params->value_sz;
  657. view->readonly = 0;
  658. //view->itemsize = expr_self->rif->params->value_sz;
  659. view->itemsize = sizeof(rpn_value_t);
  660. if(flags & PyBUF_FORMAT)
  661. {
  662. view->format = "L";
  663. }
  664. else
  665. {
  666. view->format = NULL;
  667. }
  668. view->ndim = 1;
  669. view->shape = NULL;
  670. if(flags & PyBUF_ND)
  671. {
  672. view->ndim = expr_self->ndim;
  673. // !! Error if value_sz < sizeof(rpn_value_t) !!
  674. short nval = view->itemsize / sizeof(rpn_value_t);
  675. if(nval > 1)
  676. {
  677. view->ndim++;
  678. }
  679. view->shape = malloc(sizeof(Py_ssize_t) * view->ndim); /**@todo check error*/
  680. for(size_t i=0; i<expr_self->ndim; i++)
  681. {
  682. int idx = i;
  683. if(data->pos_flag == RPN_IF_POSITION_XDIM)
  684. {
  685. idx++;
  686. }
  687. view->shape[i] = data->size_lim[idx];
  688. }
  689. if(nval>1)
  690. {
  691. view->shape[expr_self->ndim] = nval;
  692. }
  693. }
  694. view->strides = NULL;
  695. view->suboffsets = NULL;
  696. Py_INCREF(self);
  697. return 0;
  698. }
  699. void rpnif_releasebuffer(PyObject *self, Py_buffer *view)
  700. {
  701. free(view->shape);
  702. }
  703. PyObject* rpnif_str(PyObject *self)
  704. {
  705. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  706. rpn_if_default_data_t *rif_data = \
  707. (rpn_if_default_data_t*)expr_self->rif->params->data;
  708. const size_t rpn_sz = expr_self->rif->params->rpn_sz;
  709. const char pyfmt[] = "%VA%ld=%U=\"%S\";";
  710. size_t i;
  711. PyObject *buf, *tmp, *items;
  712. buf = NULL;
  713. items = rpnif_items(self);
  714. if(PyErr_Occurred()) { return NULL; }
  715. for(i=0; i<rpn_sz; i++)
  716. {
  717. PyObject *key, *value, *elt;
  718. elt = PyTuple_GET_ITEM(items, i);
  719. key = PyTuple_GET_ITEM(elt, 0);
  720. value = PyTuple_GET_ITEM(elt, 1);
  721. tmp = PyUnicode_FromFormat(pyfmt,
  722. buf, "",
  723. i, key, value);
  724. if(buf) { Py_DECREF(buf); }
  725. if(PyErr_Occurred()) { return NULL; }
  726. buf = tmp;
  727. }
  728. switch(rif_data->res_flag)
  729. {
  730. case RPN_IF_RES_CONST:
  731. tmp = PyUnicode_FromFormat("%U A%ld=C(*)=%lld",
  732. buf, i+1, rif_data->const_val[0]);
  733. Py_DECREF(buf);
  734. buf=tmp;
  735. break;
  736. case RPN_IF_RES_CONST_RGBA:
  737. tmp = PyUnicode_FromFormat("%U A%ld=R(*)=%lld A%ld=G(*)=%lld A%ld=B(*)=%lld A%ld=A(*)=%lld",
  738. buf,
  739. i+1, rif_data->const_val[0],
  740. i+2, rif_data->const_val[1],
  741. i+3, rif_data->const_val[2],
  742. i+4, rif_data->const_val[3]);
  743. Py_DECREF(buf);
  744. buf=tmp;
  745. break;
  746. }
  747. Py_INCREF(buf);
  748. return buf;
  749. }
  750. /** Return a string representation of expressions dict
  751. * @param self @ref PyRPNIterExpr_t instance
  752. * @return a str instance */
  753. static PyObject* _rpnif_expr_repr(PyObject *self)
  754. {
  755. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  756. rpn_if_default_data_t *rif_data = \
  757. (rpn_if_default_data_t*)expr_self->rif->params->data;
  758. PyObject *buf, *tmp, *items, *const_res;
  759. const char pyfmt[] = "%V\"%U\":\"%S\"%V";
  760. buf = const_res = NULL;
  761. items = rpnif_items(self);
  762. if(PyErr_Occurred()) { return NULL; }
  763. #define _const_res_key ",\"const_res\":"
  764. switch(rif_data->res_flag)
  765. {
  766. case RPN_IF_RES_CONST:
  767. const_res = PyUnicode_FromFormat(
  768. _const_res_key "{\"r\":%llu}}",
  769. rif_data->const_val[0]);
  770. break;
  771. /*
  772. case RPN_IF_RES_CONST_RGB:
  773. const_res = PyUnicode_FromFormat(
  774. "\"const_res\": {\"r\":%llu, \"g\":%llu, \"b\":%llu}}",
  775. rif_data->const_val[0],
  776. rif_data->const_val[1],
  777. rif_data->const_val[2])
  778. break;
  779. */
  780. case RPN_IF_RES_CONST_RGBA:
  781. const_res = PyUnicode_FromFormat(
  782. _const_res_key \
  783. "{\"r\":%llu,\"g\":%llu,\"b\":%llu,\"a\":%llu}}",
  784. rif_data->const_val[0],
  785. rif_data->const_val[1],
  786. rif_data->const_val[2],
  787. rif_data->const_val[3]);
  788. break;
  789. default:
  790. const_res = PyUnicode_FromFormat("}");
  791. break;
  792. }
  793. #undef _const_res_key
  794. const size_t rpn_sz = expr_self->rif->params->rpn_sz;
  795. for(size_t i=0; i<rpn_sz; i++)
  796. {
  797. PyObject *key, *value, *elt;
  798. elt = PyTuple_GET_ITEM(items, i);
  799. key = PyTuple_GET_ITEM(elt, 0);
  800. value = PyTuple_GET_ITEM(elt, 1);
  801. tmp = PyUnicode_FromFormat(pyfmt,
  802. buf, "{", key, value,
  803. i==rpn_sz-1?const_res:NULL, ",");
  804. if(buf)
  805. {
  806. Py_DECREF(buf);
  807. }
  808. if(PyErr_Occurred())
  809. {
  810. return NULL;
  811. }
  812. buf = tmp;
  813. }
  814. return buf;
  815. }
  816. PyObject* rpnif_repr(PyObject *self)
  817. {
  818. PyRPNIterExpr_t *expr_self = (PyRPNIterExpr_t*)self;
  819. rpn_if_default_data_t *rif_data = (rpn_if_default_data_t*)expr_self->rif->params->data;
  820. char *str_pos, *str_res;
  821. char tmp[64];
  822. PyObject *expr_repr = _rpnif_expr_repr(self);
  823. if(PyErr_Occurred()) { return NULL; }
  824. switch(rif_data->pos_flag)
  825. {
  826. case RPN_IF_POSITION_XY:
  827. str_pos = "XY";
  828. break;
  829. case RPN_IF_POSITION_LINEAR:
  830. str_pos = "LINEAR";
  831. break;
  832. case RPN_IF_POSITION_XDIM:
  833. snprintf(tmp, 64, "XDIM%ld", rif_data->size_lim[0]);
  834. str_pos = tmp;
  835. break;
  836. default:
  837. PyErr_SetString(PyExc_RuntimeError,
  838. "UNKOWN POS_FLAG2");
  839. return NULL;
  840. }
  841. PyObject *const_res = NULL;
  842. switch(rif_data->res_flag)
  843. {
  844. case RPN_IF_RES_BOOL:
  845. str_res = "BOOL";
  846. break;
  847. case RPN_IF_RES_CONST:
  848. str_res = "CONST";
  849. const_res = PyTuple_New(1);
  850. break;
  851. case RPN_IF_RES_CONST_RGBA:
  852. str_res = "CONST_RGBA";
  853. break;
  854. case RPN_IF_RES_COUNT:
  855. str_res = "COUNT";
  856. break;
  857. case RPN_IF_RES_XFUN:
  858. str_res = "XFUN";
  859. break;
  860. case RPN_IF_RES_RGB:
  861. str_res = "RGB";
  862. break;
  863. case RPN_IF_RES_RGBA:
  864. str_res = "RGBA";
  865. break;
  866. default:
  867. PyErr_SetString(PyExc_RuntimeError,
  868. "UNKOWN RES_FLAG2");
  869. return NULL;
  870. }
  871. PyObject *res;
  872. const_res = const_res?const_res:Py_None;
  873. res = PyUnicode_FromFormat(
  874. "<RPNIterExpr pos_flag:%s res_flag:%s expr:'%U' const_res:%S>",
  875. str_pos, str_res, expr_repr, const_res);
  876. if(PyErr_Occurred()) { return NULL; }
  877. return res;
  878. }
  879. PyObject* rpnif_getstate(PyObject *self, PyObject *noargs)
  880. {
  881. PyErr_SetString(PyExc_NotImplementedError,
  882. "getstate Not implemented");
  883. return NULL;
  884. /**@todo TODO write the function */
  885. Py_RETURN_NONE;
  886. }
  887. PyObject* rpnif_setstate(PyObject *self, PyObject *state_bytes)
  888. {
  889. PyErr_SetString(PyExc_NotImplementedError,
  890. "setstate Not implemented");
  891. return NULL;
  892. /**@todo TODO write the function */
  893. Py_RETURN_NONE;
  894. }
  895. /**@def _ret_append(key)
  896. * @hiderefs
  897. * local macro */
  898. /**@def _const_res_key()
  899. * @hiderefs
  900. * local macro*/