Skip to content

Commit a5a5590

Browse files
Issue python#29300: Use Argument Clinic for getting struct object from the format.
1 parent 8973de5 commit a5a5590

File tree

2 files changed

+103
-83
lines changed

2 files changed

+103
-83
lines changed

Modules/_struct.c

Lines changed: 52 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ typedef struct { char c; long long x; } s_long_long;
8585
#pragma options align=reset
8686
#endif
8787

88+
/*[python input]
89+
class cache_struct_converter(CConverter):
90+
type = 'PyStructObject *'
91+
converter = 'cache_struct_converter'
92+
c_default = "NULL"
93+
94+
def cleanup(self):
95+
return "Py_XDECREF(%s);\n" % self.name
96+
[python start generated code]*/
97+
/*[python end generated code: output=da39a3ee5e6b4b0d input=49957cca130ffb63]*/
98+
99+
static int cache_struct_converter(PyObject *, PyObject **);
100+
88101
#include "clinic/_struct.c.h"
89102

90103
/* Helper for integer format codes: converts an arbitrary Python object to a
@@ -2037,21 +2050,27 @@ PyTypeObject PyStructType = {
20372050
#define MAXCACHE 100
20382051
static PyObject *cache = NULL;
20392052

2040-
static PyStructObject *
2041-
cache_struct(PyObject *fmt)
2053+
static int
2054+
cache_struct_converter(PyObject *fmt, PyObject **ptr)
20422055
{
20432056
PyObject * s_object;
20442057

2058+
if (fmt == NULL) {
2059+
Py_DECREF(*ptr);
2060+
return 1;
2061+
}
2062+
20452063
if (cache == NULL) {
20462064
cache = PyDict_New();
20472065
if (cache == NULL)
2048-
return NULL;
2066+
return 0;
20492067
}
20502068

20512069
s_object = PyDict_GetItem(cache, fmt);
20522070
if (s_object != NULL) {
20532071
Py_INCREF(s_object);
2054-
return (PyStructObject *)s_object;
2072+
*ptr = s_object;
2073+
return Py_CLEANUP_SUPPORTED;
20552074
}
20562075

20572076
s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL);
@@ -2061,8 +2080,10 @@ cache_struct(PyObject *fmt)
20612080
/* Attempt to cache the result */
20622081
if (PyDict_SetItem(cache, fmt, s_object) == -1)
20632082
PyErr_Clear();
2083+
*ptr = s_object;
2084+
return Py_CLEANUP_SUPPORTED;
20642085
}
2065-
return (PyStructObject *)s_object;
2086+
return 0;
20662087
}
20672088

20682089
/*[clinic input]
@@ -2081,25 +2102,19 @@ _clearcache_impl(PyObject *module)
20812102

20822103

20832104
/*[clinic input]
2084-
calcsize
2105+
calcsize -> Py_ssize_t
20852106
2086-
format: object
2107+
format as s_object: cache_struct
20872108
/
20882109
20892110
Return size in bytes of the struct described by the format string.
20902111
[clinic start generated code]*/
20912112

2092-
static PyObject *
2093-
calcsize(PyObject *module, PyObject *format)
2094-
/*[clinic end generated code: output=90fbcf191fe9470a input=55488303a06777fa]*/
2113+
static Py_ssize_t
2114+
calcsize_impl(PyObject *module, PyStructObject *s_object)
2115+
/*[clinic end generated code: output=db7d23d09c6932c4 input=96a6a590c7717ecd]*/
20952116
{
2096-
Py_ssize_t n;
2097-
PyStructObject *s_object = cache_struct(format);
2098-
if (s_object == NULL)
2099-
return NULL;
2100-
n = s_object->s_size;
2101-
Py_DECREF(s_object);
2102-
return PyLong_FromSsize_t(n);
2117+
return s_object->s_size;
21032118
}
21042119

21052120
PyDoc_STRVAR(pack_doc,
@@ -2111,7 +2126,7 @@ to the format string. See help(struct) for more on format strings.");
21112126
static PyObject *
21122127
pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21132128
{
2114-
PyStructObject *s_object;
2129+
PyObject *s_object = NULL;
21152130
PyObject *format, *result;
21162131

21172132
if (nargs == 0) {
@@ -2120,11 +2135,10 @@ pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21202135
}
21212136
format = args[0];
21222137

2123-
s_object = cache_struct(format);
2124-
if (s_object == NULL) {
2138+
if (!cache_struct_converter(format, &s_object)) {
21252139
return NULL;
21262140
}
2127-
result = s_pack((PyObject *)s_object, args + 1, nargs - 1, kwnames);
2141+
result = s_pack(s_object, args + 1, nargs - 1, kwnames);
21282142
Py_DECREF(s_object);
21292143
return result;
21302144
}
@@ -2140,7 +2154,7 @@ on format strings.");
21402154
static PyObject *
21412155
pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21422156
{
2143-
PyStructObject *s_object;
2157+
PyObject *s_object = NULL;
21442158
PyObject *format, *result;
21452159

21462160
if (nargs == 0) {
@@ -2149,19 +2163,18 @@ pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
21492163
}
21502164
format = args[0];
21512165

2152-
s_object = cache_struct(format);
2153-
if (s_object == NULL) {
2166+
if (!cache_struct_converter(format, &s_object)) {
21542167
return NULL;
21552168
}
2156-
result = s_pack_into((PyObject *)s_object, args + 1, nargs - 1, kwnames);
2169+
result = s_pack_into(s_object, args + 1, nargs - 1, kwnames);
21572170
Py_DECREF(s_object);
21582171
return result;
21592172
}
21602173

21612174
/*[clinic input]
21622175
unpack
21632176
2164-
format: object
2177+
format as s_object: cache_struct
21652178
buffer: Py_buffer
21662179
/
21672180
@@ -2173,24 +2186,16 @@ See help(struct) for more on format strings.
21732186
[clinic start generated code]*/
21742187

21752188
static PyObject *
2176-
unpack_impl(PyObject *module, PyObject *format, Py_buffer *buffer)
2177-
/*[clinic end generated code: output=f75ada02aaa33b3b input=654078e6660c2df0]*/
2189+
unpack_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer)
2190+
/*[clinic end generated code: output=48ddd4d88eca8551 input=05fa3b91678da727]*/
21782191
{
2179-
PyStructObject *s_object;
2180-
PyObject *result;
2181-
2182-
s_object = cache_struct(format);
2183-
if (s_object == NULL)
2184-
return NULL;
2185-
result = Struct_unpack_impl(s_object, buffer);
2186-
Py_DECREF(s_object);
2187-
return result;
2192+
return Struct_unpack_impl(s_object, buffer);
21882193
}
21892194

21902195
/*[clinic input]
21912196
unpack_from
21922197
2193-
format: object
2198+
format as s_object: cache_struct
21942199
/
21952200
buffer: Py_buffer
21962201
offset: Py_ssize_t = 0
@@ -2203,27 +2208,17 @@ See help(struct) for more on format strings.
22032208
[clinic start generated code]*/
22042209

22052210
static PyObject *
2206-
unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer,
2207-
Py_ssize_t offset)
2208-
/*[clinic end generated code: output=2492f0c3a0b82577 input=9ead76c6ac7164f7]*/
2211+
unpack_from_impl(PyObject *module, PyStructObject *s_object,
2212+
Py_buffer *buffer, Py_ssize_t offset)
2213+
/*[clinic end generated code: output=1042631674c6e0d3 input=6e80a5398e985025]*/
22092214
{
2210-
PyStructObject *s_object;
2211-
PyObject *result;
2212-
2213-
s_object = cache_struct(format);
2214-
if (s_object == NULL) {
2215-
return NULL;
2216-
}
2217-
result = Struct_unpack_from_impl(s_object, buffer, offset);
2218-
2219-
Py_DECREF(s_object);
2220-
return result;
2215+
return Struct_unpack_from_impl(s_object, buffer, offset);
22212216
}
22222217

22232218
/*[clinic input]
22242219
iter_unpack
22252220
2226-
format: object
2221+
format as s_object: cache_struct
22272222
buffer: object
22282223
/
22292224
@@ -2236,19 +2231,11 @@ Requires that the bytes length be a multiple of the format struct size.
22362231
[clinic start generated code]*/
22372232

22382233
static PyObject *
2239-
iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer)
2240-
/*[clinic end generated code: output=b1291e97a6d4cf3c input=8674dfd2f0dae416]*/
2234+
iter_unpack_impl(PyObject *module, PyStructObject *s_object,
2235+
PyObject *buffer)
2236+
/*[clinic end generated code: output=0ae50e250d20e74d input=b214a58869a3c98d]*/
22412237
{
2242-
PyStructObject *s_object;
2243-
PyObject *result;
2244-
2245-
s_object = cache_struct(format);
2246-
if (s_object == NULL)
2247-
return NULL;
2248-
2249-
result = Struct_iter_unpack(s_object, buffer);
2250-
Py_DECREF(s_object);
2251-
return result;
2238+
return Struct_iter_unpack(s_object, buffer);
22522239
}
22532240

22542241
static struct PyMethodDef module_functions[] = {

Modules/clinic/_struct.c.h

Lines changed: 51 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,32 @@ PyDoc_STRVAR(calcsize__doc__,
155155
#define CALCSIZE_METHODDEF \
156156
{"calcsize", (PyCFunction)calcsize, METH_O, calcsize__doc__},
157157

158+
static Py_ssize_t
159+
calcsize_impl(PyObject *module, PyStructObject *s_object);
160+
161+
static PyObject *
162+
calcsize(PyObject *module, PyObject *arg)
163+
{
164+
PyObject *return_value = NULL;
165+
PyStructObject *s_object = NULL;
166+
Py_ssize_t _return_value;
167+
168+
if (!PyArg_Parse(arg, "O&:calcsize", cache_struct_converter, &s_object)) {
169+
goto exit;
170+
}
171+
_return_value = calcsize_impl(module, s_object);
172+
if ((_return_value == -1) && PyErr_Occurred()) {
173+
goto exit;
174+
}
175+
return_value = PyLong_FromSsize_t(_return_value);
176+
177+
exit:
178+
/* Cleanup for s_object */
179+
Py_XDECREF(s_object);
180+
181+
return return_value;
182+
}
183+
158184
PyDoc_STRVAR(unpack__doc__,
159185
"unpack($module, format, buffer, /)\n"
160186
"--\n"
@@ -169,26 +195,28 @@ PyDoc_STRVAR(unpack__doc__,
169195
{"unpack", (PyCFunction)unpack, METH_FASTCALL, unpack__doc__},
170196

171197
static PyObject *
172-
unpack_impl(PyObject *module, PyObject *format, Py_buffer *buffer);
198+
unpack_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer);
173199

174200
static PyObject *
175201
unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
176202
{
177203
PyObject *return_value = NULL;
178-
PyObject *format;
204+
PyStructObject *s_object = NULL;
179205
Py_buffer buffer = {NULL, NULL};
180206

181-
if (!_PyArg_ParseStack(args, nargs, "Oy*:unpack",
182-
&format, &buffer)) {
207+
if (!_PyArg_ParseStack(args, nargs, "O&y*:unpack",
208+
cache_struct_converter, &s_object, &buffer)) {
183209
goto exit;
184210
}
185211

186212
if (!_PyArg_NoStackKeywords("unpack", kwnames)) {
187213
goto exit;
188214
}
189-
return_value = unpack_impl(module, format, &buffer);
215+
return_value = unpack_impl(module, s_object, &buffer);
190216

191217
exit:
218+
/* Cleanup for s_object */
219+
Py_XDECREF(s_object);
192220
/* Cleanup for buffer */
193221
if (buffer.obj) {
194222
PyBuffer_Release(&buffer);
@@ -211,26 +239,28 @@ PyDoc_STRVAR(unpack_from__doc__,
211239
{"unpack_from", (PyCFunction)unpack_from, METH_FASTCALL, unpack_from__doc__},
212240

213241
static PyObject *
214-
unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer,
215-
Py_ssize_t offset);
242+
unpack_from_impl(PyObject *module, PyStructObject *s_object,
243+
Py_buffer *buffer, Py_ssize_t offset);
216244

217245
static PyObject *
218246
unpack_from(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
219247
{
220248
PyObject *return_value = NULL;
221249
static const char * const _keywords[] = {"", "buffer", "offset", NULL};
222-
static _PyArg_Parser _parser = {"Oy*|n:unpack_from", _keywords, 0};
223-
PyObject *format;
250+
static _PyArg_Parser _parser = {"O&y*|n:unpack_from", _keywords, 0};
251+
PyStructObject *s_object = NULL;
224252
Py_buffer buffer = {NULL, NULL};
225253
Py_ssize_t offset = 0;
226254

227255
if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser,
228-
&format, &buffer, &offset)) {
256+
cache_struct_converter, &s_object, &buffer, &offset)) {
229257
goto exit;
230258
}
231-
return_value = unpack_from_impl(module, format, &buffer, offset);
259+
return_value = unpack_from_impl(module, s_object, &buffer, offset);
232260

233261
exit:
262+
/* Cleanup for s_object */
263+
Py_XDECREF(s_object);
234264
/* Cleanup for buffer */
235265
if (buffer.obj) {
236266
PyBuffer_Release(&buffer);
@@ -254,27 +284,30 @@ PyDoc_STRVAR(iter_unpack__doc__,
254284
{"iter_unpack", (PyCFunction)iter_unpack, METH_FASTCALL, iter_unpack__doc__},
255285

256286
static PyObject *
257-
iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer);
287+
iter_unpack_impl(PyObject *module, PyStructObject *s_object,
288+
PyObject *buffer);
258289

259290
static PyObject *
260291
iter_unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
261292
{
262293
PyObject *return_value = NULL;
263-
PyObject *format;
294+
PyStructObject *s_object = NULL;
264295
PyObject *buffer;
265296

266-
if (!_PyArg_UnpackStack(args, nargs, "iter_unpack",
267-
2, 2,
268-
&format, &buffer)) {
297+
if (!_PyArg_ParseStack(args, nargs, "O&O:iter_unpack",
298+
cache_struct_converter, &s_object, &buffer)) {
269299
goto exit;
270300
}
271301

272302
if (!_PyArg_NoStackKeywords("iter_unpack", kwnames)) {
273303
goto exit;
274304
}
275-
return_value = iter_unpack_impl(module, format, buffer);
305+
return_value = iter_unpack_impl(module, s_object, buffer);
276306

277307
exit:
308+
/* Cleanup for s_object */
309+
Py_XDECREF(s_object);
310+
278311
return return_value;
279312
}
280-
/*[clinic end generated code: output=0714090a5d0ea8ce input=a9049054013a1b77]*/
313+
/*[clinic end generated code: output=03e0d193ab1983f9 input=a9049054013a1b77]*/

0 commit comments

Comments
 (0)