diff -r 8feb6a5ce4c6 Doc/library/struct.rst --- a/Doc/library/struct.rst Wed Jan 25 23:33:27 2017 +0100 +++ b/Doc/library/struct.rst Fri Jan 27 15:38:59 2017 +0100 @@ -48,40 +48,40 @@ The module defines the following excepti is wrong. -.. function:: pack(fmt, v1, v2, ...) +.. function:: pack(format, v1, v2, ...) Return a bytes object containing the values *v1*, *v2*, ... packed according - to the format string *fmt*. The arguments must match the values required by + to the format string *format*. The arguments must match the values required by the format exactly. -.. function:: pack_into(fmt, buffer, offset, v1, v2, ...) +.. function:: pack_into(format, buffer, offset, v1, v2, ...) - Pack the values *v1*, *v2*, ... according to the format string *fmt* and + Pack the values *v1*, *v2*, ... according to the format string *format* and write the packed bytes into the writable buffer *buffer* starting at position *offset*. Note that *offset* is a required argument. -.. function:: unpack(fmt, buffer) +.. function:: unpack(format, buffer) - Unpack from the buffer *buffer* (presumably packed by ``pack(fmt, ...)``) - according to the format string *fmt*. The result is a tuple even if it + Unpack from the buffer *buffer* (presumably packed by ``pack(format, ...)``) + according to the format string *format*. The result is a tuple even if it contains exactly one item. The buffer's size in bytes must match the size required by the format, as reflected by :func:`calcsize`. -.. function:: unpack_from(fmt, buffer, offset=0) +.. function:: unpack_from(format, buffer, offset=0) Unpack from *buffer* starting at position *offset*, according to the format - string *fmt*. The result is a tuple even if it contains exactly one + string *format*. The result is a tuple even if it contains exactly one item. The buffer's size in bytes, minus *offset*, must be at least the size required by the format, as reflected by :func:`calcsize`. -.. function:: iter_unpack(fmt, buffer) +.. function:: iter_unpack(format, buffer) Iteratively unpack from the buffer *buffer* according to the format - string *fmt*. This function returns an iterator which will read + string *format*. This function returns an iterator which will read equally-sized chunks from the buffer until all its contents have been consumed. The buffer's size in bytes must be a multiple of the size required by the format, as reflected by :func:`calcsize`. @@ -91,10 +91,11 @@ The module defines the following excepti .. versionadded:: 3.4 -.. function:: calcsize(fmt) +.. function:: calcsize(format) Return the size of the struct (and hence of the bytes object produced by - ``pack(fmt, ...)``) corresponding to the format string *fmt*. + ``pack(format, ...)``) corresponding to the format string *format*. + .. _struct-format-strings: diff -r 8feb6a5ce4c6 Lib/test/test_struct.py --- a/Lib/test/test_struct.py Wed Jan 25 23:33:27 2017 +0100 +++ b/Lib/test/test_struct.py Fri Jan 27 15:38:59 2017 +0100 @@ -412,6 +412,10 @@ class StructTest(unittest.TestCase): for i in range(6, len(test_string) + 1): self.assertRaises(struct.error, struct.unpack_from, fmt, data, i) + # keyword arguments + self.assertEqual(s.unpack_from(buffer=test_string, offset=2), + (b'cd01',)) + def test_pack_into(self): test_string = b'Reykjavik rocks, eow!' writable_buf = array.array('b', b' '*100) diff -r 8feb6a5ce4c6 Modules/_struct.c --- a/Modules/_struct.c Wed Jan 25 23:33:27 2017 +0100 +++ b/Modules/_struct.c Fri Jan 27 15:38:59 2017 +0100 @@ -9,6 +9,11 @@ #include "structmember.h" #include +/*[clinic input] +class Struct "PyObject *" "&PyStructType" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=25178b51ecd4493b]*/ + static PyTypeObject PyStructType; /* The translation function for each format character is table driven */ @@ -80,6 +85,53 @@ typedef struct { char c; long long x; } #pragma options align=reset #endif +/*[python input] + +class struct_format_converter(CConverter): + type = 'PyObject *' + converter = 'struct_format_converter' + c_default = "NULL" + + def cleanup(self): + return "Py_XDECREF(%s);" % self.name + +[python start generated code]*/ +/*[python end generated code: output=da39a3ee5e6b4b0d input=b5584b69b7f82e0b]*/ + +static int +struct_format_converter(PyObject *format, PyObject **p_format) +{ + if (format == NULL) { + Py_DECREF(*p_format); + return 1; + } + + if (PyUnicode_Check(format)) { + format = PyUnicode_AsASCIIString(format); + if (format == NULL) { + return 0; + } + + assert(PyBytes_Check(format)); + } + /* XXX support buffer interface, too */ + else { + if (!PyBytes_Check(format)) { + PyErr_Format(PyExc_TypeError, + "format argument must be a str or bytes object, not %.200s", + Py_TYPE(format)->tp_name); + return 0; + } + + Py_INCREF(format); + } + + *p_format = format; + return Py_CLEANUP_SUPPORTED; +} + +#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,39 +1481,31 @@ s_new(PyTypeObject *type, PyObject *args return self; } +/*[clinic input] +Struct.__init__ + + format: struct_format + +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(PyObject *self, PyObject *format) +/*[clinic end generated code: output=cbf2eef8f24746f1 input=0ce61cfd6e9d9d58]*/ { 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; + assert(PyBytes_Check(format)); - if (PyUnicode_Check(o_format)) { - o_format = PyUnicode_AsASCIIString(o_format); - if (o_format == NULL) - return -1; - } - /* XXX support buffer interface, too */ - else { - Py_INCREF(o_format); - } - - if (!PyBytes_Check(o_format)) { - Py_DECREF(o_format); - PyErr_Format(PyExc_TypeError, - "Struct() argument 1 must be a bytes object, not %.200s", - Py_TYPE(o_format)->tp_name); - return -1; - } - - Py_XSETREF(soself->s_format, o_format); + Py_INCREF(format); + Py_XSETREF(soself->s_format, format); ret = prepare_s(soself); return ret; @@ -1517,78 +1561,74 @@ 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(PyObject *self, Py_buffer *buffer) +/*[clinic end generated code: output=82c4b44e56b2e639 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) { + if (buffer->len != soself->s_size) { PyErr_Format(StructError, "unpack requires a bytes object of length %zd", soself->s_size); - PyBuffer_Release(&vbuf); return NULL; } - result = s_unpack_internal(soself, vbuf.buf); - PyBuffer_Release(&vbuf); - return result; + return s_unpack_internal(soself, 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 + + buffer: Py_buffer + offset: Py_ssize_t = 0 + +Return a tuple containing unpacked values. + +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 * -s_unpack_from(PyObject *self, PyObject *args, PyObject *kwds) +Struct_unpack_from_impl(PyObject *self, Py_buffer *buffer, Py_ssize_t offset) +/*[clinic end generated code: output=b554a8172ceed903 input=97ade52422f8962f]*/ { - static char *kwlist[] = {"buffer", "offset", 0}; - - PyObject *input; - Py_ssize_t offset = 0; - Py_buffer vbuf; - PyObject *result; PyStructObject *soself = (PyStructObject *)self; assert(PyStruct_Check(self)); assert(soself->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 < soself->s_size) { PyErr_Format(StructError, "unpack_from requires a buffer of at least %zd bytes", soself->s_size); - PyBuffer_Release(&vbuf); return NULL; } - result = s_unpack_internal(soself, (char*)vbuf.buf + offset); - PyBuffer_Release(&vbuf); - return result; + return s_unpack_internal(soself, (char*)buffer->buf + offset); } + /* Unpack iterator type */ typedef struct { @@ -1680,20 +1720,30 @@ 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(PyObject *self, PyObject *buffer) +/*[clinic end generated code: output=b5dd190c2e65b9ce input=6d65b3f3107dbc99]*/ { - PyStructObject *so = (PyStructObject *) _so; - unpackiterobject *self; + PyStructObject *so; + unpackiterobject *obj; - assert(PyStruct_Check(_so)); + assert(PyStruct_Check(self)); + so = (PyStructObject *) self; + assert(so->s_codes != NULL); if (so->s_size == 0) { @@ -1702,26 +1752,26 @@ s_iter_unpack(PyObject *_so, PyObject *i return NULL; } - self = (unpackiterobject *) PyType_GenericAlloc(&unpackiter_type, 0); - if (self == NULL) + obj = (unpackiterobject *) PyType_GenericAlloc(&unpackiter_type, 0); + if (obj == NULL) return NULL; - if (PyObject_GetBuffer(input, &self->buf, PyBUF_SIMPLE) < 0) { - Py_DECREF(self); + if (PyObject_GetBuffer(buffer, &obj->buf, PyBUF_SIMPLE) < 0) { + Py_DECREF(obj); return NULL; } - if (self->buf.len % so->s_size != 0) { + if (obj->buf.len % so->s_size != 0) { PyErr_Format(StructError, "iterative unpacking requires a bytes length " "multiple of %zd", so->s_size); - Py_DECREF(self); + Py_DECREF(obj); return NULL; } Py_INCREF(so); - self->so = so; - self->index = 0; - return (PyObject *) self; + obj->so = so; + obj->index = 0; + return (PyObject *)obj; } @@ -1736,7 +1786,7 @@ s_iter_unpack(PyObject *_so, PyObject *i * */ 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 +1800,7 @@ s_pack_internal(PyStructObject *soself, 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 +1873,7 @@ to the format string S.format. See help 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 +1882,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 +1915,7 @@ offset. Note that the offset is a requi 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 +1925,34 @@ s_pack_into(PyObject *self, PyObject *ar 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 +2012,15 @@ s_sizeof(PyStructObject *self, void *unu /* 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 +2047,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 */ }; @@ -2057,26 +2106,36 @@ cache_struct(PyObject *fmt) return 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: struct_format + / + +Return size in bytes of the struct described by the format string. +[clinic start generated code]*/ static PyObject * -calcsize(PyObject *self, PyObject *fmt) +calcsize_impl(PyObject *module, PyObject *format) +/*[clinic end generated code: output=16c71a42d93255f6 input=06fe4a867e5e7e02]*/ { Py_ssize_t n; - PyObject *s_object = cache_struct(fmt); + PyObject *s_object = cache_struct(format); if (s_object == NULL) return NULL; n = ((PyStructObject *)s_object)->s_size; @@ -2085,160 +2144,157 @@ calcsize(PyObject *self, PyObject *fmt) } 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); + PyObject *s_object, *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(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); + PyObject *s_object, *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); - 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."); - -static PyObject * -unpack(PyObject *self, PyObject *args) -{ - PyObject *s_object, *fmt, *inputstr, *result; - - if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) - return NULL; - result = s_unpack(s_object, inputstr); + result = s_pack_into(s_object, args + 1, nargs - 1, kwnames); 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 + + format: struct_format + 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_from(PyObject *self, PyObject *args, PyObject *kwds) +unpack_impl(PyObject *module, PyObject *format, PyObject *inputstr) +/*[clinic end generated code: output=06951d66eae6d63b input=a101e14b6ef2884c]*/ { - PyObject *s_object, *fmt, *newargs, *result; - Py_ssize_t n = PyTuple_GET_SIZE(args); + PyObject *s_object, *result; - if (n == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); + s_object = cache_struct(format); + if (s_object == NULL) return NULL; - } - fmt = PyTuple_GET_ITEM(args, 0); - newargs = PyTuple_GetSlice(args, 1, n); - if (newargs == NULL) - return NULL; - - s_object = cache_struct(fmt); - if (s_object == NULL) { - Py_DECREF(newargs); - return NULL; - } - result = s_unpack_from(s_object, newargs, kwds); - Py_DECREF(newargs); + result = Struct_unpack(s_object, inputstr); 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] +unpack_from + + format: struct_format + 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 * -iter_unpack(PyObject *self, PyObject *args) +unpack_from_impl(PyObject *module, PyObject *format, Py_buffer *buffer, + Py_ssize_t offset) +/*[clinic end generated code: output=2492f0c3a0b82577 input=10d5813109f1cce1]*/ { - PyObject *s_object, *fmt, *input, *result; + PyObject *s_object, *result; - if (!PyArg_ParseTuple(args, "OO:iter_unpack", &fmt, &input)) + 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; +} + +/*[clinic input] +iter_unpack + + format: struct_format + 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_impl(PyObject *module, PyObject *format, PyObject *buffer) +/*[clinic end generated code: output=b1291e97a6d4cf3c input=1a2935bfd79fc8fc]*/ +{ + PyObject *s_object, *result; + + s_object = cache_struct(format); + if (s_object == NULL) return NULL; - s_object = cache_struct(fmt); - 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 */ }; diff -r 8feb6a5ce4c6 Modules/clinic/_struct.c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/clinic/_struct.c.h Fri Jan 27 15:38:59 2017 +0100 @@ -0,0 +1,307 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(Struct___init____doc__, +"Struct(format)\n" +"--\n" +"\n" +"Create a compiled struct object.\n" +"\n" +"Return a new Struct object which writes and reads binary data according to\n" +"the format string.\n" +"\n" +"See help(struct) for more on format strings."); + +static int +Struct___init___impl(PyObject *self, PyObject *format); + +static int +Struct___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + static const char * const _keywords[] = {"format", NULL}; + static _PyArg_Parser _parser = {"O&:Struct", _keywords, 0}; + PyObject *format = NULL; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + struct_format_converter, &format)) { + goto exit; + } + return_value = Struct___init___impl(self, format); + +exit: + /* Cleanup for format */ + Py_XDECREF(format); + + return return_value; +} + +PyDoc_STRVAR(Struct_unpack__doc__, +"unpack($self, buffer, /)\n" +"--\n" +"\n" +"Return a tuple containing unpacked values.\n" +"\n" +"Unpack according to the format string Struct.format. The buffer\'s size\n" +"in bytes must be Struct.size.\n" +"\n" +"See help(struct) for more on format strings."); + +#define STRUCT_UNPACK_METHODDEF \ + {"unpack", (PyCFunction)Struct_unpack, METH_O, Struct_unpack__doc__}, + +static PyObject * +Struct_unpack_impl(PyObject *self, Py_buffer *buffer); + +static PyObject * +Struct_unpack(PyObject *self, PyObject *arg) +{ + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + + if (!PyArg_Parse(arg, "y*:unpack", &buffer)) { + goto exit; + } + return_value = Struct_unpack_impl(self, &buffer); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +PyDoc_STRVAR(Struct_unpack_from__doc__, +"unpack_from($self, /, buffer, offset=0)\n" +"--\n" +"\n" +"Return a tuple containing unpacked values.\n" +"\n" +"Values are unpacked according to the format string Struct.format.\n" +"\n" +"The buffer\'s size in bytes, minus offset, must be at least Struct.size.\n" +"\n" +"See help(struct) for more on format strings."); + +#define STRUCT_UNPACK_FROM_METHODDEF \ + {"unpack_from", (PyCFunction)Struct_unpack_from, METH_FASTCALL, Struct_unpack_from__doc__}, + +static PyObject * +Struct_unpack_from_impl(PyObject *self, Py_buffer *buffer, Py_ssize_t offset); + +static PyObject * +Struct_unpack_from(PyObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"buffer", "offset", NULL}; + static _PyArg_Parser _parser = {"y*|n:unpack_from", _keywords, 0}; + Py_buffer buffer = {NULL, NULL}; + Py_ssize_t offset = 0; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &buffer, &offset)) { + goto exit; + } + return_value = Struct_unpack_from_impl(self, &buffer, offset); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +PyDoc_STRVAR(Struct_iter_unpack__doc__, +"iter_unpack($self, buffer, /)\n" +"--\n" +"\n" +"Return an iterator yielding tuples.\n" +"\n" +"Tuples are unpacked from the given bytes source, like a repeated\n" +"invocation of unpack_from().\n" +"\n" +"Requires that the bytes length be a multiple of the struct size."); + +#define STRUCT_ITER_UNPACK_METHODDEF \ + {"iter_unpack", (PyCFunction)Struct_iter_unpack, METH_O, Struct_iter_unpack__doc__}, + +PyDoc_STRVAR(_clearcache__doc__, +"_clearcache($module, /)\n" +"--\n" +"\n" +"Clear the internal cache."); + +#define _CLEARCACHE_METHODDEF \ + {"_clearcache", (PyCFunction)_clearcache, METH_NOARGS, _clearcache__doc__}, + +static PyObject * +_clearcache_impl(PyObject *module); + +static PyObject * +_clearcache(PyObject *module, PyObject *Py_UNUSED(ignored)) +{ + return _clearcache_impl(module); +} + +PyDoc_STRVAR(calcsize__doc__, +"calcsize($module, format, /)\n" +"--\n" +"\n" +"Return size in bytes of the struct described by the format string."); + +#define CALCSIZE_METHODDEF \ + {"calcsize", (PyCFunction)calcsize, METH_O, calcsize__doc__}, + +static PyObject * +calcsize_impl(PyObject *module, PyObject *format); + +static PyObject * +calcsize(PyObject *module, PyObject *arg) +{ + PyObject *return_value = NULL; + PyObject *format = NULL; + + if (!PyArg_Parse(arg, "O&:calcsize", struct_format_converter, &format)) { + goto exit; + } + return_value = calcsize_impl(module, format); + +exit: + /* Cleanup for format */ + Py_XDECREF(format); + + return return_value; +} + +PyDoc_STRVAR(unpack__doc__, +"unpack($module, format, inputstr, /)\n" +"--\n" +"\n" +"Return a tuple containing values unpacked according to the format string.\n" +"\n" +"The buffer\'s size in bytes must be calcsize(format).\n" +"\n" +"See help(struct) for more on format strings."); + +#define UNPACK_METHODDEF \ + {"unpack", (PyCFunction)unpack, METH_FASTCALL, unpack__doc__}, + +static PyObject * +unpack_impl(PyObject *module, PyObject *format, PyObject *inputstr); + +static PyObject * +unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + PyObject *format = NULL; + PyObject *inputstr; + + if (!_PyArg_ParseStack(args, nargs, "O&O:unpack", + struct_format_converter, &format, &inputstr)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("unpack", kwnames)) { + goto exit; + } + return_value = unpack_impl(module, format, inputstr); + +exit: + /* Cleanup for format */ + Py_XDECREF(format); + + return return_value; +} + +PyDoc_STRVAR(unpack_from__doc__, +"unpack_from($module, format, buffer, offset=0, /)\n" +"--\n" +"\n" +"Return a tuple containing values unpacked according to the format string.\n" +"\n" +"The buffer\'s size, minus offset, must be at least calcsize(format).\n" +"\n" +"See help(struct) for more on format strings."); + +#define UNPACK_FROM_METHODDEF \ + {"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); + +static PyObject * +unpack_from(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + PyObject *format = NULL; + Py_buffer buffer = {NULL, NULL}; + Py_ssize_t offset = 0; + + if (!_PyArg_ParseStack(args, nargs, "O&y*|n:unpack_from", + struct_format_converter, &format, &buffer, &offset)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("unpack_from", kwnames)) { + goto exit; + } + return_value = unpack_from_impl(module, format, &buffer, offset); + +exit: + /* Cleanup for format */ + Py_XDECREF(format); + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +PyDoc_STRVAR(iter_unpack__doc__, +"iter_unpack($module, format, buffer, /)\n" +"--\n" +"\n" +"Return an iterator yielding tuples unpacked from the given bytes.\n" +"\n" +"The bytes are unpacked according to the format string, like\n" +"a repeated invocation of unpack_from().\n" +"\n" +"Requires that the bytes length be a multiple of the format struct size."); + +#define ITER_UNPACK_METHODDEF \ + {"iter_unpack", (PyCFunction)iter_unpack, METH_FASTCALL, iter_unpack__doc__}, + +static PyObject * +iter_unpack_impl(PyObject *module, PyObject *format, PyObject *buffer); + +static PyObject * +iter_unpack(PyObject *module, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + PyObject *format = NULL; + PyObject *buffer; + + if (!_PyArg_ParseStack(args, nargs, "O&O:iter_unpack", + struct_format_converter, &format, &buffer)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("iter_unpack", kwnames)) { + goto exit; + } + return_value = iter_unpack_impl(module, format, buffer); + +exit: + /* Cleanup for format */ + Py_XDECREF(format); + + return return_value; +} +/*[clinic end generated code: output=9e29daff0960bea7 input=a9049054013a1b77]*/