diff -r 94d630a02a81 Doc/library/struct.rst --- a/Doc/library/struct.rst Thu Feb 02 11:12:47 2017 +0200 +++ b/Doc/library/struct.rst Thu Feb 02 11:32:57 2017 +0200 @@ -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 94d630a02a81 Lib/test/test_struct.py --- a/Lib/test/test_struct.py Thu Feb 02 11:12:47 2017 +0200 +++ b/Lib/test/test_struct.py Thu Feb 02 11:32:57 2017 +0200 @@ -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 94d630a02a81 Modules/_struct.c --- a/Modules/_struct.c Thu Feb 02 11:12:47 2017 +0200 +++ b/Modules/_struct.c Thu Feb 02 11:32:57 2017 +0200 @@ -9,6 +9,11 @@ #include "structmember.h" #include +/*[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; } #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 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 + + 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(PyStructObject *self, Py_buffer *buffer, + Py_ssize_t offset) +/*[clinic end generated code: output=57fac875e0977316 input=97ade52422f8962f]*/ { - static char *kwlist[] = {"buffer", "offset", 0}; + assert(self->s_codes != NULL); - 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 < 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 *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 +1759,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 +1832,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 +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 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 +1884,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 +1971,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 +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; + PyStructObject *s_object; + PyObject *result; - if (!PyArg_UnpackTuple(args, "unpack", 2, 2, &fmt, &inputstr)) - return NULL; - - 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); + PyStructObject *s_object; + PyObject *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; + result = Struct_unpack_from_impl(s_object, buffer, offset); - 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); 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; + PyStructObject *s_object; + PyObject *result; - if (!PyArg_ParseTuple(args, "OO:iter_unpack", &fmt, &input)) + 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 94d630a02a81 Modules/clinic/_struct.c.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Modules/clinic/_struct.c.h Thu Feb 02 11:32:57 2017 +0200 @@ -0,0 +1,276 @@ +/*[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(PyStructObject *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; + + if (!_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &_parser, + &format)) { + goto exit; + } + return_value = Struct___init___impl((PyStructObject *)self, format); + +exit: + 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(PyStructObject *self, Py_buffer *buffer); + +static PyObject * +Struct_unpack(PyStructObject *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(PyStructObject *self, Py_buffer *buffer, + Py_ssize_t offset); + +static PyObject * +Struct_unpack_from(PyStructObject *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__}, + +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; + PyObject *inputstr; + + if (!_PyArg_UnpackStack(args, nargs, "unpack", + 2, 2, + &format, &inputstr)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("unpack", kwnames)) { + goto exit; + } + return_value = unpack_impl(module, format, inputstr); + +exit: + 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; + static const char * const _keywords[] = {"", "buffer", "offset", NULL}; + static _PyArg_Parser _parser = {"Oy*|n:unpack_from", _keywords, 0}; + PyObject *format; + Py_buffer buffer = {NULL, NULL}; + Py_ssize_t offset = 0; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &format, &buffer, &offset)) { + goto exit; + } + return_value = unpack_from_impl(module, format, &buffer, offset); + +exit: + /* 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; + PyObject *buffer; + + if (!_PyArg_UnpackStack(args, nargs, "iter_unpack", + 2, 2, + &format, &buffer)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("iter_unpack", kwnames)) { + goto exit; + } + return_value = iter_unpack_impl(module, format, buffer); + +exit: + return return_value; +} +/*[clinic end generated code: output=db8152ad222fa3d0 input=a9049054013a1b77]*/