diff -r f3ff4a3ce77c Modules/_struct.c --- a/Modules/_struct.c Thu Feb 02 12:09:30 2017 +0100 +++ b/Modules/_struct.c Thu Feb 02 14:19:12 2017 +0200 @@ -85,6 +85,18 @@ typedef struct { char c; long long x; } #pragma options align=reset #endif +/*[python input] +class cache_struct_converter(CConverter): + type = 'PyStructObject *' + converter = 'cache_struct_converter' + + def cleanup(self): + return "Py_XDECREF(%s);\n" % self.name +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=0ff09c2ebda48215]*/ + +static int cache_struct_converter(PyObject *, PyObject **); + #include "clinic/_struct.c.h" /* Helper for integer format codes: converts an arbitrary Python object to a @@ -2037,21 +2049,28 @@ PyTypeObject PyStructType = { #define MAXCACHE 100 static PyObject *cache = NULL; -static PyStructObject * -cache_struct(PyObject *fmt) +static int +cache_struct_converter(PyObject *fmt, PyObject **ptr) { PyObject * s_object; + if (fmt == NULL) { + Py_DECREF(*ptr); + return 1; + } + + *ptr = NULL; if (cache == NULL) { cache = PyDict_New(); if (cache == NULL) - return NULL; + return 0; } s_object = PyDict_GetItem(cache, fmt); if (s_object != NULL) { Py_INCREF(s_object); - return (PyStructObject *)s_object; + *ptr = s_object; + return Py_CLEANUP_SUPPORTED; } s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL); @@ -2061,8 +2080,10 @@ cache_struct(PyObject *fmt) /* Attempt to cache the result */ if (PyDict_SetItem(cache, fmt, s_object) == -1) PyErr_Clear(); + *ptr = s_object; + return Py_CLEANUP_SUPPORTED; } - return (PyStructObject *)s_object; + return 0; } /*[clinic input] @@ -2081,25 +2102,19 @@ static PyObject * /*[clinic input] -calcsize +calcsize -> Py_ssize_t - format: object + format as s_object: cache_struct / Return size in bytes of the struct described by the format string. [clinic start generated code]*/ -static PyObject * -calcsize(PyObject *module, PyObject *format) -/*[clinic end generated code: output=90fbcf191fe9470a input=55488303a06777fa]*/ +static Py_ssize_t +calcsize_impl(PyObject *module, PyStructObject *s_object) +/*[clinic end generated code: output=db7d23d09c6932c4 input=96a6a590c7717ecd]*/ { - Py_ssize_t n; - PyStructObject *s_object = cache_struct(format); - if (s_object == NULL) - return NULL; - n = s_object->s_size; - Py_DECREF(s_object); - return PyLong_FromSsize_t(n); + return s_object->s_size; } PyDoc_STRVAR(pack_doc, @@ -2111,7 +2126,7 @@ to the format string. See help(struct) static PyObject * pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { - PyStructObject *s_object; + PyObject *s_object; PyObject *format, *result; if (nargs == 0) { @@ -2120,11 +2135,10 @@ pack(PyObject *self, PyObject **args, Py } format = args[0]; - s_object = cache_struct(format); - if (s_object == NULL) { + if (!cache_struct_converter(format, &s_object)) { return NULL; } - result = s_pack((PyObject *)s_object, args + 1, nargs - 1, kwnames); + result = s_pack(s_object, args + 1, nargs - 1, kwnames); Py_DECREF(s_object); return result; } @@ -2140,7 +2154,7 @@ on format strings."); static PyObject * pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { - PyStructObject *s_object; + PyObject *s_object; PyObject *format, *result; if (nargs == 0) { @@ -2149,11 +2163,10 @@ pack_into(PyObject *self, PyObject **arg } format = args[0]; - s_object = cache_struct(format); - if (s_object == NULL) { + if (!cache_struct_converter(format, &s_object)) { return NULL; } - result = s_pack_into((PyObject *)s_object, args + 1, nargs - 1, kwnames); + result = s_pack_into(s_object, args + 1, nargs - 1, kwnames); Py_DECREF(s_object); return result; } @@ -2161,7 +2174,7 @@ pack_into(PyObject *self, PyObject **arg /*[clinic input] unpack - format: object + format as s_object: cache_struct inputstr: object / @@ -2173,24 +2186,16 @@ See help(struct) for more on format stri [clinic start generated code]*/ static PyObject * -unpack_impl(PyObject *module, PyObject *format, PyObject *inputstr) -/*[clinic end generated code: output=06951d66eae6d63b input=4b81d54988890f5e]*/ +unpack_impl(PyObject *module, PyStructObject *s_object, PyObject *inputstr) +/*[clinic end generated code: output=e7eaa80096f6ec18 input=ac79a656b66a9b67]*/ { - PyStructObject *s_object; - PyObject *result; - - s_object = cache_struct(format); - if (s_object == NULL) - return NULL; - result = Struct_unpack(s_object, inputstr); - Py_DECREF(s_object); - return result; + return Struct_unpack(s_object, inputstr); } /*[clinic input] unpack_from - format: object + format as s_object: cache_struct / buffer: Py_buffer offset: Py_ssize_t = 0 @@ -2203,27 +2208,17 @@ See help(struct) for more on format stri [clinic start generated code]*/ static PyObject * -unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer, - Py_ssize_t offset) -/*[clinic end generated code: output=2492f0c3a0b82577 input=9ead76c6ac7164f7]*/ +unpack_from_impl(PyObject *module, PyStructObject *s_object, + Py_buffer *buffer, Py_ssize_t offset) +/*[clinic end generated code: output=1042631674c6e0d3 input=6e80a5398e985025]*/ { - PyStructObject *s_object; - PyObject *result; - - s_object = cache_struct(format); - if (s_object == NULL) { - return NULL; - } - result = Struct_unpack_from_impl(s_object, buffer, offset); - - Py_DECREF(s_object); - return result; + return Struct_unpack_from_impl(s_object, buffer, offset); } /*[clinic input] iter_unpack - format: object + format as s_object: cache_struct buffer: object / @@ -2236,19 +2231,11 @@ Requires that the bytes length be a mult [clinic start generated code]*/ static PyObject * -iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer) -/*[clinic end generated code: output=b1291e97a6d4cf3c input=8674dfd2f0dae416]*/ +iter_unpack_impl(PyObject *module, PyStructObject *s_object, + PyObject *buffer) +/*[clinic end generated code: output=0ae50e250d20e74d input=b214a58869a3c98d]*/ { - PyStructObject *s_object; - PyObject *result; - - s_object = cache_struct(format); - if (s_object == NULL) - return NULL; - - result = Struct_iter_unpack(s_object, buffer); - Py_DECREF(s_object); - return result; + return Struct_iter_unpack(s_object, buffer); } static struct PyMethodDef module_functions[] = { diff -r f3ff4a3ce77c Modules/clinic/_struct.c.h --- a/Modules/clinic/_struct.c.h Thu Feb 02 12:09:30 2017 +0100 +++ b/Modules/clinic/_struct.c.h Thu Feb 02 14:19:12 2017 +0200 @@ -155,6 +155,32 @@ PyDoc_STRVAR(calcsize__doc__, #define CALCSIZE_METHODDEF \ {"calcsize", (PyCFunction)calcsize, METH_O, calcsize__doc__}, +static Py_ssize_t +calcsize_impl(PyObject *module, PyStructObject *s_object); + +static PyObject * +calcsize(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyStructObject *s_object; + Py_ssize_t _return_value; + + if (!PyArg_Parse(arg, "O&:calcsize", cache_struct_converter, &s_object)) { + goto exit; + } + _return_value = calcsize_impl(module, s_object); + if ((_return_value == -1) && PyErr_Occurred()) { + goto exit; + } + return_value = PyLong_FromSsize_t(_return_value); + +exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); + + return return_value; +} + PyDoc_STRVAR(unpack__doc__, "unpack($module, format, inputstr, /)\n" "--\n" @@ -169,27 +195,29 @@ PyDoc_STRVAR(unpack__doc__, {"unpack", (PyCFunction)unpack, METH_FASTCALL, unpack__doc__}, static PyObject * -unpack_impl(PyObject *module, PyObject *format, PyObject *inputstr); +unpack_impl(PyObject *module, PyStructObject *s_object, PyObject *inputstr); static PyObject * unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - PyObject *format; + PyStructObject *s_object; PyObject *inputstr; - if (!_PyArg_UnpackStack(args, nargs, "unpack", - 2, 2, - &format, &inputstr)) { + if (!_PyArg_ParseStack(args, nargs, "O&O:unpack", + cache_struct_converter, &s_object, &inputstr)) { goto exit; } if (!_PyArg_NoStackKeywords("unpack", kwnames)) { goto exit; } - return_value = unpack_impl(module, format, inputstr); + return_value = unpack_impl(module, s_object, inputstr); exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); + return return_value; } @@ -207,26 +235,28 @@ PyDoc_STRVAR(unpack_from__doc__, {"unpack_from", (PyCFunction)unpack_from, METH_FASTCALL, unpack_from__doc__}, static PyObject * -unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer, - Py_ssize_t offset); +unpack_from_impl(PyObject *module, PyStructObject *s_object, + Py_buffer *buffer, Py_ssize_t offset); static PyObject * unpack_from(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; static const char * const _keywords[] = {"", "buffer", "offset", NULL}; - static _PyArg_Parser _parser = {"Oy*|n:unpack_from", _keywords, 0}; - PyObject *format; + static _PyArg_Parser _parser = {"O&y*|n:unpack_from", _keywords, 0}; + PyStructObject *s_object; Py_buffer buffer = {NULL, NULL}; Py_ssize_t offset = 0; if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, - &format, &buffer, &offset)) { + cache_struct_converter, &s_object, &buffer, &offset)) { goto exit; } - return_value = unpack_from_impl(module, format, &buffer, offset); + return_value = unpack_from_impl(module, s_object, &buffer, offset); exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); /* Cleanup for buffer */ if (buffer.obj) { PyBuffer_Release(&buffer); @@ -250,27 +280,30 @@ PyDoc_STRVAR(iter_unpack__doc__, {"iter_unpack", (PyCFunction)iter_unpack, METH_FASTCALL, iter_unpack__doc__}, static PyObject * -iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer); +iter_unpack_impl(PyObject *module, PyStructObject *s_object, + PyObject *buffer); static PyObject * iter_unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { PyObject *return_value = NULL; - PyObject *format; + PyStructObject *s_object; PyObject *buffer; - if (!_PyArg_UnpackStack(args, nargs, "iter_unpack", - 2, 2, - &format, &buffer)) { + if (!_PyArg_ParseStack(args, nargs, "O&O:iter_unpack", + cache_struct_converter, &s_object, &buffer)) { goto exit; } if (!_PyArg_NoStackKeywords("iter_unpack", kwnames)) { goto exit; } - return_value = iter_unpack_impl(module, format, buffer); + return_value = iter_unpack_impl(module, s_object, buffer); exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); + return return_value; } -/*[clinic end generated code: output=db8152ad222fa3d0 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=49b92fdead2e89cb input=a9049054013a1b77]*/