diff options
author | Victor Stinner <victor.stinner@gmail.com> | 2017-02-02 11:09:30 (GMT) |
---|---|---|
committer | Victor Stinner <victor.stinner@gmail.com> | 2017-02-02 11:09:30 (GMT) |
commit | 3f2d10132d9835b1ebda3283643fbbfdb0851b91 (patch) | |
tree | c510112913f972aac1520a60a487445895fe158f /Modules/_struct.c | |
parent | fd6d0d2a18bb487ec06dbbeb1a53d0ac13384cfe (diff) | |
download | cpython-3f2d10132d9835b1ebda3283643fbbfdb0851b91.zip cpython-3f2d10132d9835b1ebda3283643fbbfdb0851b91.tar.gz cpython-3f2d10132d9835b1ebda3283643fbbfdb0851b91.tar.bz2 |
Issue #29300: Convert _struct module to Argument Clinic
* The struct module now requires contiguous buffers.
* Convert most functions and methods of the _struct module to Argument Clinic
* Use "Py_buffer" type for the "buffer" argument. Argument Clinic is
responsible to create and release the Py_buffer object.
* Use "PyStructObject *" type for self to avoid explicit conversions.
* Add an unit test on the _struct.Struct.unpack_from() method to test passing
arguments as keywords.
* Rephrase docstrings.
* Rename "fmt" argument to "format" in docstrings and the documentation.
As a side effect, functions and methods which used METH_VARARGS calling
convention like struct.pack() now use the METH_FASTCALL calling convention
which avoids the creation of temporary tuple to pass positional arguments and
so is faster. For example, struct.pack("i", 1) becomes 1.56x faster (-36%)::
$ ./python -m perf timeit \
-s 'import struct; pack=struct.pack' 'pack("i", 1)' \
--compare-to=../default-ref/python
Median +- std dev: 119 ns +- 1 ns -> 76.8 ns +- 0.4 ns: 1.56x faster (-36%)
Significant (t=295.91)
Patch co-written with Serhiy Storchaka.
Diffstat (limited to 'Modules/_struct.c')
-rw-r--r-- | Modules/_struct.c | 472 |
1 files changed, 246 insertions, 226 deletions
diff --git a/Modules/_struct.c b/Modules/_struct.c index d621789..3626bad 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -9,6 +9,11 @@ #include "structmember.h" #include <ctype.h> +/*[clinic input] +class Struct "PyStructObject *" "&PyStructType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=9b032058a83ed7c3]*/ + static PyTypeObject PyStructType; /* The translation function for each format character is table driven */ @@ -80,6 +85,8 @@ typedef struct { char c; long long x; } s_long_long; #pragma options align=reset #endif +#include "clinic/_struct.c.h" + /* Helper for integer format codes: converts an arbitrary Python object to a PyLongObject if possible, otherwise fails. Caller should decref. */ @@ -1429,41 +1436,46 @@ s_new(PyTypeObject *type, PyObject *args, PyObject *kwds) return self; } +/*[clinic input] +Struct.__init__ + + format: object + +Create a compiled struct object. + +Return a new Struct object which writes and reads binary data according to +the format string. + +See help(struct) for more on format strings. +[clinic start generated code]*/ + static int -s_init(PyObject *self, PyObject *args, PyObject *kwds) +Struct___init___impl(PyStructObject *self, PyObject *format) +/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/ { - PyStructObject *soself = (PyStructObject *)self; - PyObject *o_format = NULL; int ret = 0; - static char *kwlist[] = {"format", 0}; - - assert(PyStruct_Check(self)); - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:Struct", kwlist, - &o_format)) - return -1; - if (PyUnicode_Check(o_format)) { - o_format = PyUnicode_AsASCIIString(o_format); - if (o_format == NULL) + if (PyUnicode_Check(format)) { + format = PyUnicode_AsASCIIString(format); + if (format == NULL) return -1; } /* XXX support buffer interface, too */ else { - Py_INCREF(o_format); + Py_INCREF(format); } - if (!PyBytes_Check(o_format)) { - Py_DECREF(o_format); + if (!PyBytes_Check(format)) { + Py_DECREF(format); PyErr_Format(PyExc_TypeError, "Struct() argument 1 must be a bytes object, not %.200s", - Py_TYPE(o_format)->tp_name); + Py_TYPE(format)->tp_name); return -1; } - Py_XSETREF(soself->s_format, o_format); + Py_XSETREF(self->s_format, format); - ret = prepare_s(soself); + ret = prepare_s(self); return ret; } @@ -1517,78 +1529,69 @@ fail: } -PyDoc_STRVAR(s_unpack__doc__, -"S.unpack(buffer) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format\n\ -string S.format. The buffer's size in bytes must be S.size. See\n\ -help(struct) for more on format strings."); +/*[clinic input] +Struct.unpack + + buffer: Py_buffer + / + +Return a tuple containing unpacked values. + +Unpack according to the format string Struct.format. The buffer's size +in bytes must be Struct.size. + +See help(struct) for more on format strings. +[clinic start generated code]*/ static PyObject * -s_unpack(PyObject *self, PyObject *input) +Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer) +/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/ { - Py_buffer vbuf; - PyObject *result; - PyStructObject *soself = (PyStructObject *)self; - - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); - if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0) - return NULL; - if (vbuf.len != soself->s_size) { + assert(self->s_codes != NULL); + if (buffer->len != self->s_size) { PyErr_Format(StructError, "unpack requires a bytes object of length %zd", - soself->s_size); - PyBuffer_Release(&vbuf); + self->s_size); return NULL; } - result = s_unpack_internal(soself, vbuf.buf); - PyBuffer_Release(&vbuf); - return result; + return s_unpack_internal(self, buffer->buf); } -PyDoc_STRVAR(s_unpack_from__doc__, -"S.unpack_from(buffer, offset=0) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format\n\ -string S.format. The buffer's size in bytes, minus offset, must be at\n\ -least S.size. See help(struct) for more on format strings."); +/*[clinic input] +Struct.unpack_from -static PyObject * -s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"buffer", "offset", 0}; + buffer: Py_buffer + offset: Py_ssize_t = 0 - PyObject *input; - Py_ssize_t offset = 0; - Py_buffer vbuf; - PyObject *result; - PyStructObject *soself = (PyStructObject *)self; +Return a tuple containing unpacked values. - assert(PyStruct_Check(self)); - assert(soself->s_codes != NULL); +Values are unpacked according to the format string Struct.format. + +The buffer's size in bytes, minus offset, must be at least Struct.size. + +See help(struct) for more on format strings. +[clinic start generated code]*/ + +static PyObject * +Struct_unpack_from_impl(PyStructObject *self, Py_buffer *buffer, + Py_ssize_t offset) +/*[clinic end generated code: output=57fac875e0977316 input=97ade52422f8962f]*/ +{ + assert(self->s_codes != NULL); - if (!PyArg_ParseTupleAndKeywords(args, kwds, - "O|n:unpack_from", kwlist, - &input, &offset)) - return NULL; - if (PyObject_GetBuffer(input, &vbuf, PyBUF_SIMPLE) < 0) - return NULL; if (offset < 0) - offset += vbuf.len; - if (offset < 0 || vbuf.len - offset < soself->s_size) { + offset += buffer->len; + if (offset < 0 || buffer->len - offset < self->s_size) { PyErr_Format(StructError, "unpack_from requires a buffer of at least %zd bytes", - soself->s_size); - PyBuffer_Release(&vbuf); + self->s_size); return NULL; } - result = s_unpack_internal(soself, (char*)vbuf.buf + offset); - PyBuffer_Release(&vbuf); - return result; + return s_unpack_internal(self, (char*)buffer->buf + offset); } + /* Unpack iterator type */ typedef struct { @@ -1680,48 +1683,54 @@ static PyTypeObject unpackiter_type = { unpackiter_methods /* tp_methods */ }; -PyDoc_STRVAR(s_iter_unpack__doc__, -"S.iter_unpack(buffer) -> iterator(v1, v2, ...)\n\ -\n\ -Return an iterator yielding tuples unpacked from the given bytes\n\ -source, like a repeated invocation of unpack_from(). Requires\n\ -that the bytes length be a multiple of the struct size."); +/*[clinic input] +Struct.iter_unpack + + buffer: object + / + +Return an iterator yielding tuples. + +Tuples are unpacked from the given bytes source, like a repeated +invocation of unpack_from(). + +Requires that the bytes length be a multiple of the struct size. +[clinic start generated code]*/ static PyObject * -s_iter_unpack(PyObject *_so, PyObject *input) +Struct_iter_unpack(PyStructObject *self, PyObject *buffer) +/*[clinic end generated code: output=172d83d0cd15dbab input=6d65b3f3107dbc99]*/ { - PyStructObject *so = (PyStructObject *) _so; - unpackiterobject *self; + unpackiterobject *iter; - assert(PyStruct_Check(_so)); - assert(so->s_codes != NULL); + assert(self->s_codes != NULL); - if (so->s_size == 0) { + if (self->s_size == 0) { PyErr_Format(StructError, "cannot iteratively unpack with a struct of length 0"); return NULL; } - self = (unpackiterobject *) PyType_GenericAlloc(&unpackiter_type, 0); - if (self == NULL) + iter = (unpackiterobject *) PyType_GenericAlloc(&unpackiter_type, 0); + if (iter == NULL) return NULL; - if (PyObject_GetBuffer(input, &self->buf, PyBUF_SIMPLE) < 0) { - Py_DECREF(self); + if (PyObject_GetBuffer(buffer, &iter->buf, PyBUF_SIMPLE) < 0) { + Py_DECREF(iter); return NULL; } - if (self->buf.len % so->s_size != 0) { + if (iter->buf.len % self->s_size != 0) { PyErr_Format(StructError, "iterative unpacking requires a bytes length " "multiple of %zd", - so->s_size); - Py_DECREF(self); + self->s_size); + Py_DECREF(iter); return NULL; } - Py_INCREF(so); - self->so = so; - self->index = 0; - return (PyObject *) self; + Py_INCREF(self); + iter->so = self; + iter->index = 0; + return (PyObject *)iter; } @@ -1736,7 +1745,7 @@ s_iter_unpack(PyObject *_so, PyObject *input) * */ static int -s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf) +s_pack_internal(PyStructObject *soself, PyObject **args, int offset, char* buf) { formatcode *code; /* XXX(nnorwitz): why does i need to be a local? can we use @@ -1750,7 +1759,7 @@ s_pack_internal(PyStructObject *soself, PyObject *args, int offset, char* buf) char *res = buf + code->offset; Py_ssize_t j = code->repeat; while (j--) { - PyObject *v = PyTuple_GET_ITEM(args, i++); + PyObject *v = args[i++]; if (e->format == 's') { Py_ssize_t n; int isstring; @@ -1823,7 +1832,7 @@ to the format string S.format. See help(struct) for more on format\n\ strings."); static PyObject * -s_pack(PyObject *self, PyObject *args) +s_pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { PyStructObject *soself; PyObject *result; @@ -1832,10 +1841,13 @@ s_pack(PyObject *self, PyObject *args) soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != soself->s_len) + if (nargs != soself->s_len) { PyErr_Format(StructError, - "pack expected %zd items for packing (got %zd)", soself->s_len, PyTuple_GET_SIZE(args)); + "pack expected %zd items for packing (got %zd)", soself->s_len, nargs); + return NULL; + } + if (!_PyArg_NoStackKeywords("pack", kwnames)) { return NULL; } @@ -1862,7 +1874,7 @@ offset. Note that the offset is a required argument. See\n\ help(struct) for more on format strings."); static PyObject * -s_pack_into(PyObject *self, PyObject *args) +s_pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { PyStructObject *soself; Py_buffer buffer; @@ -1872,31 +1884,34 @@ s_pack_into(PyObject *self, PyObject *args) soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->s_codes != NULL); - if (PyTuple_GET_SIZE(args) != (soself->s_len + 2)) + if (nargs != (soself->s_len + 2)) { - if (PyTuple_GET_SIZE(args) == 0) { + if (nargs == 0) { PyErr_Format(StructError, "pack_into expected buffer argument"); } - else if (PyTuple_GET_SIZE(args) == 1) { + else if (nargs == 1) { PyErr_Format(StructError, "pack_into expected offset argument"); } else { PyErr_Format(StructError, "pack_into expected %zd items for packing (got %zd)", - soself->s_len, (PyTuple_GET_SIZE(args) - 2)); + soself->s_len, (nargs - 2)); } return NULL; } + if (!_PyArg_NoStackKeywords("pack_into", kwnames)) { + return NULL; + } /* Extract a writable memory buffer from the first argument */ - if (!PyArg_Parse(PyTuple_GET_ITEM(args, 0), "w*", &buffer)) + if (!PyArg_Parse(args[0], "w*", &buffer)) return NULL; assert(buffer.len >= 0); /* Extract the offset from the first argument */ - offset = PyNumber_AsSsize_t(PyTuple_GET_ITEM(args, 1), PyExc_IndexError); + offset = PyNumber_AsSsize_t(args[1], PyExc_IndexError); if (offset == -1 && PyErr_Occurred()) { PyBuffer_Release(&buffer); return NULL; @@ -1956,22 +1971,15 @@ s_sizeof(PyStructObject *self, void *unused) /* List of functions */ static struct PyMethodDef s_methods[] = { - {"iter_unpack", s_iter_unpack, METH_O, s_iter_unpack__doc__}, - {"pack", s_pack, METH_VARARGS, s_pack__doc__}, - {"pack_into", s_pack_into, METH_VARARGS, s_pack_into__doc__}, - {"unpack", s_unpack, METH_O, s_unpack__doc__}, - {"unpack_from", (PyCFunction)s_unpack_from, METH_VARARGS|METH_KEYWORDS, - s_unpack_from__doc__}, + STRUCT_ITER_UNPACK_METHODDEF + {"pack", (PyCFunction)s_pack, METH_FASTCALL, s_pack__doc__}, + {"pack_into", (PyCFunction)s_pack_into, METH_FASTCALL, s_pack_into__doc__}, + STRUCT_UNPACK_METHODDEF + STRUCT_UNPACK_FROM_METHODDEF {"__sizeof__", (PyCFunction)s_sizeof, METH_NOARGS, s_sizeof__doc__}, {NULL, NULL} /* sentinel */ }; -PyDoc_STRVAR(s__doc__, -"Struct(fmt) --> compiled struct object\n" -"\n" -"Return a new Struct object which writes and reads binary data according to\n" -"the format string fmt. See help(struct) for more on format strings."); - #define OFF(x) offsetof(PyStructObject, x) static PyGetSetDef s_getsetlist[] = { @@ -1998,29 +2006,29 @@ PyTypeObject PyStructType = { 0, /* tp_hash */ 0, /* tp_call */ 0, /* tp_str */ - PyObject_GenericGetAttr, /* tp_getattro */ - PyObject_GenericSetAttr, /* tp_setattro */ + PyObject_GenericGetAttr, /* tp_getattro */ + PyObject_GenericSetAttr, /* tp_setattro */ 0, /* tp_as_buffer */ - Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ - s__doc__, /* tp_doc */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + Struct___init____doc__, /* tp_doc */ 0, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ offsetof(PyStructObject, weakreflist), /* tp_weaklistoffset */ 0, /* tp_iter */ 0, /* tp_iternext */ - s_methods, /* tp_methods */ - NULL, /* tp_members */ - s_getsetlist, /* tp_getset */ + s_methods, /* tp_methods */ + NULL, /* tp_members */ + s_getsetlist, /* tp_getset */ 0, /* tp_base */ 0, /* tp_dict */ 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - s_init, /* tp_init */ - PyType_GenericAlloc,/* tp_alloc */ - s_new, /* tp_new */ - PyObject_Del, /* tp_free */ + Struct___init__, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + s_new, /* tp_new */ + PyObject_Del, /* tp_free */ }; @@ -2029,7 +2037,7 @@ PyTypeObject PyStructType = { #define MAXCACHE 100 static PyObject *cache = NULL; -static PyObject * +static PyStructObject * cache_struct(PyObject *fmt) { PyObject * s_object; @@ -2043,7 +2051,7 @@ cache_struct(PyObject *fmt) s_object = PyDict_GetItem(cache, fmt); if (s_object != NULL) { Py_INCREF(s_object); - return s_object; + return (PyStructObject *)s_object; } s_object = PyObject_CallFunctionObjArgs((PyObject *)(&PyStructType), fmt, NULL); @@ -2054,191 +2062,203 @@ cache_struct(PyObject *fmt) if (PyDict_SetItem(cache, fmt, s_object) == -1) PyErr_Clear(); } - return s_object; + return (PyStructObject *)s_object; } -PyDoc_STRVAR(clearcache_doc, -"Clear the internal cache."); +/*[clinic input] +_clearcache + +Clear the internal cache. +[clinic start generated code]*/ static PyObject * -clearcache(PyObject *self) +_clearcache_impl(PyObject *module) +/*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/ { Py_CLEAR(cache); Py_RETURN_NONE; } -PyDoc_STRVAR(calcsize_doc, -"calcsize(fmt) -> integer\n\ -\n\ -Return size in bytes of the struct described by the format string fmt."); + +/*[clinic input] +calcsize + + format: object + / + +Return size in bytes of the struct described by the format string. +[clinic start generated code]*/ static PyObject * -calcsize(PyObject *self, PyObject *fmt) +calcsize(PyObject *module, PyObject *format) +/*[clinic end generated code: output=90fbcf191fe9470a input=55488303a06777fa]*/ { Py_ssize_t n; - PyObject *s_object = cache_struct(fmt); + PyStructObject *s_object = cache_struct(format); if (s_object == NULL) return NULL; - n = ((PyStructObject *)s_object)->s_size; + n = s_object->s_size; Py_DECREF(s_object); return PyLong_FromSsize_t(n); } PyDoc_STRVAR(pack_doc, -"pack(fmt, v1, v2, ...) -> bytes\n\ +"pack(format, v1, v2, ...) -> bytes\n\ \n\ Return a bytes object containing the values v1, v2, ... packed according\n\ -to the format string fmt. See help(struct) for more on format strings."); +to the format string. See help(struct) for more on format strings."); static PyObject * -pack(PyObject *self, PyObject *args) +pack(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); + PyStructObject *s_object; + PyObject *format, *result; - if (n == 0) { + if (nargs == 0) { PyErr_SetString(PyExc_TypeError, "missing format argument"); return NULL; } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; + format = args[0]; - s_object = cache_struct(fmt); + s_object = cache_struct(format); if (s_object == NULL) { - Py_DECREF(newargs); return NULL; } - result = s_pack(s_object, newargs); - Py_DECREF(newargs); + result = s_pack((PyObject *)s_object, args + 1, nargs - 1, kwnames); Py_DECREF(s_object); return result; } PyDoc_STRVAR(pack_into_doc, -"pack_into(fmt, buffer, offset, v1, v2, ...)\n\ +"pack_into(format, buffer, offset, v1, v2, ...)\n\ \n\ -Pack the values v1, v2, ... according to the format string fmt and write\n\ +Pack the values v1, v2, ... according to the format string and write\n\ the packed bytes into the writable buffer buf starting at offset. Note\n\ that the offset is a required argument. See help(struct) for more\n\ on format strings."); static PyObject * -pack_into(PyObject *self, PyObject *args) +pack_into(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) { - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); + PyStructObject *s_object; + PyObject *format, *result; - if (n == 0) { + if (nargs == 0) { PyErr_SetString(PyExc_TypeError, "missing format argument"); return NULL; } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; + format = args[0]; - s_object = cache_struct(fmt); + s_object = cache_struct(format); if (s_object == NULL) { - Py_DECREF(newargs); return NULL; } - result = s_pack_into(s_object, newargs); - Py_DECREF(newargs); + result = s_pack_into((PyObject *)s_object, args + 1, nargs - 1, kwnames); Py_DECREF(s_object); return result; } -PyDoc_STRVAR(unpack_doc, -"unpack(fmt, buffer) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format string\n\ -fmt. The buffer's size in bytes must be calcsize(fmt). See help(struct)\n\ -for more on format strings."); +/*[clinic input] +unpack + + format: object + inputstr: object + / + +Return a tuple containing values unpacked according to the format string. + +The buffer's size in bytes must be calcsize(format). + +See help(struct) for more on format strings. +[clinic start generated code]*/ static PyObject * -unpack(PyObject *self, PyObject *args) +unpack_impl(PyObject *module, PyObject *format, PyObject *inputstr) +/*[clinic end generated code: output=06951d66eae6d63b input=4b81d54988890f5e]*/ { - PyObject *s_object, *fmt, *inputstr, *result; - - if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) - return NULL; + PyStructObject *s_object; + PyObject *result; - s_object = cache_struct(fmt); + s_object = cache_struct(format); if (s_object == NULL) return NULL; - result = s_unpack(s_object, inputstr); + result = Struct_unpack(s_object, inputstr); Py_DECREF(s_object); return result; } -PyDoc_STRVAR(unpack_from_doc, -"unpack_from(fmt, buffer, offset=0) -> (v1, v2, ...)\n\ -\n\ -Return a tuple containing values unpacked according to the format string\n\ -fmt. The buffer's size, minus offset, must be at least calcsize(fmt).\n\ -See help(struct) for more on format strings."); +/*[clinic input] +unpack_from + + format: object + / + buffer: Py_buffer + offset: Py_ssize_t = 0 + +Return a tuple containing values unpacked according to the format string. + +The buffer's size, minus offset, must be at least calcsize(format). + +See help(struct) for more on format strings. +[clinic start generated code]*/ static PyObject * -unpack_from(PyObject *self, PyObject *args, PyObject *kwds) +unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer, + Py_ssize_t offset) +/*[clinic end generated code: output=2492f0c3a0b82577 input=9ead76c6ac7164f7]*/ { - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); - - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; + PyStructObject *s_object; + PyObject *result; - s_object = cache_struct(fmt); + s_object = cache_struct(format); if (s_object == NULL) { - Py_DECREF(newargs); return NULL; } - result = s_unpack_from(s_object, newargs, kwds); - Py_DECREF(newargs); + result = Struct_unpack_from_impl(s_object, buffer, offset); + Py_DECREF(s_object); return result; } -PyDoc_STRVAR(iter_unpack_doc, -"iter_unpack(fmt, buffer) -> iterator(v1, v2, ...)\n\ -\n\ -Return an iterator yielding tuples unpacked from the given bytes\n\ -source according to the format string, like a repeated invocation of\n\ -unpack_from(). Requires that the bytes length be a multiple of the\n\ -format struct size."); +/*[clinic input] +iter_unpack + + format: object + buffer: object + / + +Return an iterator yielding tuples unpacked from the given bytes. + +The bytes are unpacked according to the format string, like +a repeated invocation of unpack_from(). + +Requires that the bytes length be a multiple of the format struct size. +[clinic start generated code]*/ static PyObject * -iter_unpack(PyObject *self, PyObject *args) +iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer) +/*[clinic end generated code: output=b1291e97a6d4cf3c input=8674dfd2f0dae416]*/ { - PyObject *s_object, *fmt, *input, *result; - - if (!PyArg_ParseTuple(args, "OO:iter_unpack", &fmt, &input)) - return NULL; + PyStructObject *s_object; + PyObject *result; - s_object = cache_struct(fmt); + s_object = cache_struct(format); if (s_object == NULL) return NULL; - result = s_iter_unpack(s_object, input); + + result = Struct_iter_unpack(s_object, buffer); Py_DECREF(s_object); return result; } static struct PyMethodDef module_functions[] = { - {"_clearcache", (PyCFunction)clearcache, METH_NOARGS, clearcache_doc}, - {"calcsize", calcsize, METH_O, calcsize_doc}, - {"iter_unpack", iter_unpack, METH_VARARGS, iter_unpack_doc}, - {"pack", pack, METH_VARARGS, pack_doc}, - {"pack_into", pack_into, METH_VARARGS, pack_into_doc}, - {"unpack", unpack, METH_VARARGS, unpack_doc}, - {"unpack_from", (PyCFunction)unpack_from, - METH_VARARGS|METH_KEYWORDS, unpack_from_doc}, + _CLEARCACHE_METHODDEF + CALCSIZE_METHODDEF + ITER_UNPACK_METHODDEF + {"pack", (PyCFunction)pack, METH_FASTCALL, pack_doc}, + {"pack_into", (PyCFunction)pack_into, METH_FASTCALL, pack_into_doc}, + UNPACK_METHODDEF + UNPACK_FROM_METHODDEF {NULL, NULL} /* sentinel */ }; |