Browse Source

Add expression accessor for RPNIterExpr

Yann Weber 1 year ago
parent
commit
3097c98237
4 changed files with 68 additions and 10 deletions
  1. 15
    0
      python_if.c
  2. 9
    1
      python_if.h
  3. 34
    9
      python_rpnexpr.c
  4. 10
    0
      python_rpnexpr.h

+ 15
- 0
python_if.c View File

@@ -40,6 +40,8 @@ and the stack state."},
40 40
 };
41 41
 
42 42
 PyMemberDef RPNIterExpr_members[] = {
43
+	{"expressions", T_OBJECT, offsetof(PyRPNIterExpr_t, expr), READONLY,
44
+		"The tuple of expressions"},
43 45
 	{NULL}
44 46
 };
45 47
 
@@ -279,6 +281,19 @@ with given arguments");
279 281
 	// Creating rif with a new memory map
280 282
 	expr_self->rif = rpn_if_new(rif_params, NULL);
281 283
 
284
+	// Creating the tuple holding RPNExpr instances of expressions
285
+	expr_self->expr = PyTuple_New(expr_self->rif->params->rpn_sz);
286
+	for(size_t i=0; i<expr_self->rif->params->rpn_sz;i++)
287
+	{
288
+		rpn_expr_t *expr = &expr_self->rif->rpn[i];
289
+		PyObject *instance = rpnexpr_init_borrowing(expr);
290
+		if(!instance)
291
+		{
292
+			return -1;
293
+		}
294
+		PyTuple_SET_ITEM(expr_self->expr, i, instance);
295
+	}
296
+
282 297
 	return 0;
283 298
 }
284 299
 

+ 9
- 1
python_if.h View File

@@ -75,6 +75,9 @@ typedef struct
75 75
 	/**@brief Pointer on @ref rpn_if_s */
76 76
 	rpn_if_t *rif;
77 77
 
78
+	/**@brief Python tuple with instances of RPNExpr */
79
+	PyObject *expr;
80
+
78 81
 } PyRPNIterExpr_t;
79 82
 
80 83
 /**@brief RpnIterExpr __new__ method
@@ -100,12 +103,17 @@ int rpnif_init(PyObject *self, PyObject *args, PyObject *kwds);
100 103
  */
101 104
 void rpnif_del(PyObject *self);
102 105
 
103
-
106
+/**@brief Buffer protocol request handler method */
104 107
 int rpnif_getbuffer(PyObject *self, Py_buffer *view, int flags);
108
+/**@brief Buffer protocol request release method */
105 109
 void rpnif_releasebuffer(PyObject *self, Py_buffer *view);
106 110
 
111
+/**@brief Return a named tuple of custom rif data */
107 112
 PyObject *rpnif_get_params(PyObject *self);
108 113
 
114
+/**@brief Return the list of expressions */
115
+PyObject *rpnif_get_expr(PyObject *self);
116
+
109 117
 /**@brief RPNIterExpr __getstate__ method for pickling
110 118
  * @param cls RPNIterExpr type object
111 119
  * @param noargs Not an argument...

+ 34
- 9
python_rpnexpr.c View File

@@ -93,6 +93,7 @@ PyObject* rpnexpr_new(PyTypeObject *subtype, PyObject *args, PyObject* kwds)
93 93
 	expr = (PyRPNExpr_t*)ret;
94 94
 	expr->rpn = NULL;
95 95
 	expr->args = NULL;
96
+	expr->borrowed_expr = 0;
96 97
 	return ret;
97 98
 }
98 99
 
@@ -115,13 +116,6 @@ int rpnexpr_init(PyObject *self, PyObject *args, PyObject *kwds)
115 116
 		return -1;
116 117
 	}
117 118
 
118
-	if(strlen(expr) == 0)
119
-	{
120
-		PyErr_SetString(PyExc_ValueError,
121
-			"RpnExpr.__init__() expect expression argument to be not empty");
122
-		return -1;
123
-	}
124
-
125 119
 	if(args_count < 0 || args_count > 255)
126 120
 	{
127 121
 		snprintf(err_str, 128,
@@ -176,12 +170,44 @@ int rpnexpr_init(PyObject *self, PyObject *args, PyObject *kwds)
176 170
 	return 0;
177 171
 }
178 172
 
173
+PyObject* rpnexpr_init_borrowing(rpn_expr_t *borrowed)
174
+{
175
+	PyObject *args, *ret;
176
+	PyRPNExpr_t *instance;
177
+
178
+	args  = Py_BuildValue("sLL", "", borrowed->args_count,
179
+			borrowed->stack_sz);
180
+	if(!args || PyErr_Occurred())
181
+	{
182
+		return NULL;
183
+	}
184
+
185
+	ret = PyObject_CallObject(&RPNExprType, args);
186
+	if(!ret || PyErr_Occurred())
187
+	{
188
+		Py_DECREF(args);
189
+		return NULL;
190
+	}
191
+
192
+	Py_DECREF(args);
193
+
194
+	instance = (PyRPNExpr_t*)ret;
195
+
196
+	rpn_expr_close(instance->rpn);
197
+	free(instance->rpn);
198
+
199
+	instance->borrowed_expr = 1;
200
+	instance->rpn = borrowed;
201
+	
202
+	return ret;
203
+}
204
+
179 205
 void rpnexpr_del(PyObject *self)
180 206
 {
181 207
 	PyRPNExpr_t *expr_self;
182 208
 
183 209
 	expr_self = (PyRPNExpr_t*)self;
184
-	if(expr_self->rpn)
210
+	if(expr_self->rpn && !expr_self->borrowed_expr)
185 211
 	{
186 212
 		rpn_expr_close(expr_self->rpn);
187 213
 		free(expr_self->rpn);
@@ -506,7 +532,6 @@ PyObject* rpnexpr_eval(PyObject* self, PyObject** argv, Py_ssize_t argc)
506 532
 	}
507 533
 
508 534
 	res = rpn_expr_eval(expr_self->rpn, expr_self->args);
509
-//dprintf(2, "[RES=%lu]\n", res);
510 535
 
511 536
 	return PyLong_FromUnsignedLong(res);
512 537
 }

+ 10
- 0
python_rpnexpr.h View File

@@ -63,6 +63,10 @@ typedef struct
63 63
 	/**@brief Array storing expression argument
64 64
 	 * @note As attribute of rpn_expr allowing malloc & free only once */
65 65
 	rpn_value_t *args;
66
+
67
+	/**@brief If true, someone else will take care of freeing the
68
+	 * rpn expression at deletion */
69
+	short borrowed_expr;
66 70
 } PyRPNExpr_t;
67 71
 
68 72
 /**@brief Organize PyRPNExpr_t state data
@@ -76,6 +80,12 @@ typedef struct
76 80
 	size_t token_sz;
77 81
 } PyRPNExpr_state_t;
78 82
 
83
+/**@brief Return a new instance of RPNExpr with a borrowed expression
84
+ * @note Borrowed expression means that the rpn_expr_t is handled by someone
85
+ *       else and should not be freed when the instance is deleted
86
+ */
87
+PyObject* rpnexpr_init_borrowing(rpn_expr_t *borrowed);
88
+
79 89
 /**@brief RpnExpr __new__ method
80 90
  * @param subtype Type of object being created (pyrpn.RPNExpr)
81 91
  * @param args positional arguments for subtype

Loading…
Cancel
Save