diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 075e1802bebc3e..b25414bea659b7 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -6266,6 +6266,10 @@ def test_stat_module_has_signatures(self): import stat self._test_module_has_signatures(stat) + def test_struct_module_has_signatures(self): + import struct + self._test_module_has_signatures(struct) + def test_string_module_has_signatures(self): import string self._test_module_has_signatures(string) diff --git a/Modules/_struct.c b/Modules/_struct.c index a8e9021f0a303a..34e931790ebb39 100644 --- a/Modules/_struct.c +++ b/Modules/_struct.c @@ -1784,15 +1784,13 @@ Struct.__init__ 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. +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 Struct___init___impl(PyStructObject *self, PyObject *format) -/*[clinic end generated code: output=b8e80862444e92d0 input=192a4575a3dde802]*/ +/*[clinic end generated code: output=b8e80862444e92d0 input=1af78a5f57d82cec]*/ { int ret = 0; @@ -1914,15 +1912,14 @@ Struct.unpack 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. +Unpack according to the struct format string. The buffer's +size in bytes must be the struct size. See help(struct) for more on +format strings. [clinic start generated code]*/ static PyObject * Struct_unpack_impl(PyStructObject *self, Py_buffer *buffer) -/*[clinic end generated code: output=873a24faf02e848a input=3113f8e7038b2f6c]*/ +/*[clinic end generated code: output=873a24faf02e848a input=488843a57c47065a]*/ { _structmodulestate *state = get_struct_state_structinst(self); ENSURE_STRUCT_IS_READY(self); @@ -1943,18 +1940,16 @@ Struct.unpack_from Return a tuple containing unpacked values. -Values are unpacked according to the format string Struct.format. - -The buffer's size in bytes, starting at position offset, must be -at least Struct.size. - -See help(struct) for more on format strings. +Values are unpacked according to the struct format string. The +buffer's size in bytes, starting at position offset, must be at +least the 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=cafd4851d473c894]*/ +/*[clinic end generated code: output=57fac875e0977316 input=57cfcf84c088faa4]*/ { _structmodulestate *state = get_struct_state_structinst(self); ENSURE_STRUCT_IS_READY(self); @@ -2098,14 +2093,13 @@ Struct.iter_unpack 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. +invocation of unpack_from(). Requires that the bytes length be +a multiple of the struct size. [clinic start generated code]*/ static PyObject * Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer) -/*[clinic end generated code: output=818f89ad4afa8d64 input=6d65b3f3107dbc99]*/ +/*[clinic end generated code: output=818f89ad4afa8d64 input=9555d2d29d1d9cd2]*/ { _structmodulestate *state = get_struct_state_structinst(self); unpackiterobject *iter; @@ -2150,7 +2144,7 @@ Struct_iter_unpack_impl(PyStructObject *self, PyObject *buffer) * */ static int -s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, +s_pack_internal(PyStructObject *soself, PyObject *const *args, char* buf, _structmodulestate *state) { formatcode *code; @@ -2159,7 +2153,7 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, Py_ssize_t i; memset(buf, '\0', soself->s_size); - i = offset; + i = 0; for (code = soself->s_codes; code->fmtdef != NULL; code++) { const formatdef *e = code->fmtdef; char *res = buf + code->offset; @@ -2234,145 +2228,132 @@ s_pack_internal(PyStructObject *soself, PyObject *const *args, int offset, } -PyDoc_STRVAR(s_pack__doc__, -"S.pack(v1, v2, ...) -> bytes\n\ -\n\ -Return a bytes object containing values v1, v2, ... packed according\n\ -to the format string S.format. See help(struct) for more on format\n\ -strings."); +/*[clinic input] +Struct.pack + + *values: array + +Pack values and return the packed bytes. + +Return a bytes object containing the provided values packed +according to the struct format string. See help(struct) for more on +format strings. +[clinic start generated code]*/ static PyObject * -s_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +Struct_pack_impl(PyStructObject *self, PyObject * const *values, + Py_ssize_t values_length) +/*[clinic end generated code: output=5766e18f596cae9e input=295f4b1a97747458]*/ { - PyStructObject *soself; _structmodulestate *state = get_struct_state_structinst(self); /* Validate arguments. */ - soself = PyStructObject_CAST(self); - ENSURE_STRUCT_IS_READY(soself); - assert(PyStruct_Check(self, state)); - if (nargs != soself->s_len) - { + ENSURE_STRUCT_IS_READY(self); + if (values_length != self->s_len) { PyErr_Format(state->StructError, - "pack expected %zd items for packing (got %zd)", soself->s_len, nargs); + "pack expected %zd items for packing (got %zd)", + self->s_len, values_length); return NULL; } - /* Allocate a new string */ - PyBytesWriter *writer = PyBytesWriter_Create(soself->s_size); + PyBytesWriter *writer = PyBytesWriter_Create(self->s_size); if (writer == NULL) { return NULL; } char *buf = PyBytesWriter_GetData(writer); /* Call the guts */ - if ( s_pack_internal(soself, args, 0, buf, state) != 0 ) { + if (s_pack_internal(self, values, buf, state) != 0) { PyBytesWriter_Discard(writer); return NULL; } - return PyBytesWriter_FinishWithSize(writer, soself->s_size); + return PyBytesWriter_FinishWithSize(writer, self->s_size); } -PyDoc_STRVAR(s_pack_into__doc__, -"S.pack_into(buffer, offset, v1, v2, ...)\n\ -\n\ -Pack the values v1, v2, ... according to the format string S.format\n\ -and write the packed bytes into the writable buffer buf starting at\n\ -offset. Note that the offset is a required argument. See\n\ -help(struct) for more on format strings."); +/*[clinic input] +Struct.pack_into + + buffer: Py_buffer(accept={rwbuffer}) + offset as offset_obj: object + / + *values: array + +Pack values and write the packed bytes into the buffer. + +Pack the provided values according to the struct format string +and write the packed bytes into the writable buffer starting at +offset. Note that the offset is a required argument. See +help(struct) for more on format strings. +[clinic start generated code]*/ static PyObject * -s_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, + PyObject *offset_obj, PyObject * const *values, + Py_ssize_t values_length) +/*[clinic end generated code: output=b0c2ef496135dad3 input=d0de9b9f138c782d]*/ { - PyStructObject *soself; - Py_buffer buffer; Py_ssize_t offset; _structmodulestate *state = get_struct_state_structinst(self); - /* Validate arguments. +1 is for the first arg as buffer. */ - soself = PyStructObject_CAST(self); - ENSURE_STRUCT_IS_READY(soself); - assert(PyStruct_Check(self, state)); - if (nargs != (soself->s_len + 2)) - { - if (nargs == 0) { - PyErr_Format(state->StructError, - "pack_into expected buffer argument"); - } - else if (nargs == 1) { - PyErr_Format(state->StructError, - "pack_into expected offset argument"); - } - else { - PyErr_Format(state->StructError, - "pack_into expected %zd items for packing (got %zd)", - soself->s_len, (nargs - 2)); - } + ENSURE_STRUCT_IS_READY(self); + if (values_length != self->s_len) { + PyErr_Format(state->StructError, + "pack_into expected %zd items for packing (got %zd)", + self->s_len, values_length); return NULL; } - /* Extract a writable memory buffer from the first argument */ - if (!PyArg_Parse(args[0], "w*", &buffer)) - return NULL; - assert(buffer.len >= 0); - /* Extract the offset from the first argument */ - offset = PyNumber_AsSsize_t(args[1], PyExc_IndexError); + offset = PyNumber_AsSsize_t(offset_obj, PyExc_IndexError); if (offset == -1 && PyErr_Occurred()) { - PyBuffer_Release(&buffer); return NULL; } /* Support negative offsets. */ if (offset < 0) { /* Check that negative offset is low enough to fit data */ - if (offset + soself->s_size > 0) { + if (offset + self->s_size > 0) { PyErr_Format(state->StructError, "no space to pack %zd bytes at offset %zd", - soself->s_size, + self->s_size, offset); - PyBuffer_Release(&buffer); return NULL; } /* Check that negative offset is not crossing buffer boundary */ - if (offset + buffer.len < 0) { + if (offset + buffer->len < 0) { PyErr_Format(state->StructError, "offset %zd out of range for %zd-byte buffer", offset, - buffer.len); - PyBuffer_Release(&buffer); + buffer->len); return NULL; } - offset += buffer.len; + offset += buffer->len; } /* Check boundaries */ - if ((buffer.len - offset) < soself->s_size) { + if ((buffer->len - offset) < self->s_size) { assert(offset >= 0); - assert(soself->s_size >= 0); + assert(self->s_size >= 0); PyErr_Format(state->StructError, "pack_into requires a buffer of at least %zu bytes for " "packing %zd bytes at offset %zd " "(actual buffer size is %zd)", - (size_t)soself->s_size + (size_t)offset, - soself->s_size, + (size_t)self->s_size + (size_t)offset, + self->s_size, offset, - buffer.len); - PyBuffer_Release(&buffer); + buffer->len); return NULL; } /* Call the guts */ - if (s_pack_internal(soself, args, 2, (char*)buffer.buf + offset, state) != 0) { - PyBuffer_Release(&buffer); + if (s_pack_internal(self, values, (char*)buffer->buf + offset, state) != 0) { return NULL; } - PyBuffer_Release(&buffer); Py_RETURN_NONE; } @@ -2392,13 +2373,14 @@ s_get_size(PyObject *op, void *Py_UNUSED(closure)) return PyLong_FromSsize_t(self->s_size); } -PyDoc_STRVAR(s_sizeof__doc__, -"S.__sizeof__() -> size of S in memory, in bytes"); +/*[clinic input] +Struct.__sizeof__ +[clinic start generated code]*/ static PyObject * -s_sizeof(PyObject *op, PyObject *Py_UNUSED(dummy)) +Struct___sizeof___impl(PyStructObject *self) +/*[clinic end generated code: output=2d0d78900b4cdb4e input=faca5925c1f1ffd0]*/ { - PyStructObject *self = PyStructObject_CAST(op); size_t size = _PyObject_SIZE(Py_TYPE(self)) + sizeof(formatcode); for (formatcode *code = self->s_codes; code->fmtdef != NULL; code++) { size += sizeof(formatcode); @@ -2424,11 +2406,11 @@ s_repr(PyObject *op) static struct PyMethodDef s_methods[] = { STRUCT_ITER_UNPACK_METHODDEF - {"pack", _PyCFunction_CAST(s_pack), METH_FASTCALL, s_pack__doc__}, - {"pack_into", _PyCFunction_CAST(s_pack_into), METH_FASTCALL, s_pack_into__doc__}, + STRUCT_PACK_METHODDEF + STRUCT_PACK_INTO_METHODDEF STRUCT_UNPACK_METHODDEF STRUCT_UNPACK_FROM_METHODDEF - {"__sizeof__", s_sizeof, METH_NOARGS, s_sizeof__doc__}, + STRUCT___SIZEOF___METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2443,17 +2425,12 @@ static PyGetSetDef s_getsetlist[] = { {NULL} /* sentinel */ }; -PyDoc_STRVAR(s__doc__, -"Struct(fmt) --> compiled struct object\n" -"\n" -); - static PyType_Slot PyStructType_slots[] = { {Py_tp_dealloc, s_dealloc}, {Py_tp_getattro, PyObject_GenericGetAttr}, {Py_tp_setattro, PyObject_GenericSetAttr}, {Py_tp_repr, s_repr}, - {Py_tp_doc, (void*)s__doc__}, + {Py_tp_doc, (void*)Struct___init____doc__}, {Py_tp_traverse, s_traverse}, {Py_tp_clear, s_clear}, {Py_tp_methods, s_methods}, @@ -2543,58 +2520,52 @@ calcsize_impl(PyObject *module, PyStructObject *s_object) return s_object->s_size; } -PyDoc_STRVAR(pack_doc, -"pack(format, v1, v2, ...) -> bytes\n\ -\n\ -Return a bytes object containing the values v1, v2, ... packed according\n\ -to the format string. See help(struct) for more on format strings."); +/*[clinic input] +pack + + format as s_object: cache_struct + / + *values: array + +Pack values and return the packed bytes. + +Return a bytes object containing the provided values packed according +to the format string. See help(struct) for more on format strings. +[clinic start generated code]*/ static PyObject * -pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +pack_impl(PyObject *module, PyStructObject *s_object, + PyObject * const *values, Py_ssize_t values_length) +/*[clinic end generated code: output=2f874191ddecdec0 input=8144972342391de1]*/ { - PyObject *s_object = NULL; - PyObject *format, *result; + return Struct_pack_impl(s_object, values, values_length); +} - if (nargs == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - format = args[0]; +/*[clinic input] +pack_into - if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { - return NULL; - } - result = s_pack(s_object, args + 1, nargs - 1); - Py_DECREF(s_object); - return result; -} + format as s_object: cache_struct + buffer: Py_buffer(accept={rwbuffer}) + offset as offset_obj: object + / + *values: array -PyDoc_STRVAR(pack_into_doc, -"pack_into(format, buffer, offset, v1, v2, ...)\n\ -\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."); +Pack values and write the packed bytes into the buffer. + +Pack the provided values according to the format string and write the +packed bytes into the writable buffer starting at offset. Note that the +offset is a required argument. See help(struct) for more on format +strings. +[clinic start generated code]*/ static PyObject * -pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, + PyObject *offset_obj, PyObject * const *values, + Py_ssize_t values_length) +/*[clinic end generated code: output=148ef659a490eec3 input=3c5fe5bd3b6fd396]*/ { - PyObject *s_object = NULL; - PyObject *format, *result; - - if (nargs == 0) { - PyErr_SetString(PyExc_TypeError, "missing format argument"); - return NULL; - } - format = args[0]; - - if (!cache_struct_converter(module, format, (PyStructObject **)&s_object)) { - return NULL; - } - result = s_pack_into(s_object, args + 1, nargs - 1); - Py_DECREF(s_object); - return result; + return Struct_pack_into_impl(s_object, buffer, offset_obj, + values, values_length); } /*[clinic input] @@ -2606,14 +2577,13 @@ unpack 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. +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_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer) -/*[clinic end generated code: output=48ddd4d88eca8551 input=05fa3b91678da727]*/ +/*[clinic end generated code: output=48ddd4d88eca8551 input=7df28c5d0b5b6f4e]*/ { return Struct_unpack_impl(s_object, buffer); } @@ -2628,15 +2598,14 @@ unpack_from 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. +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_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, Py_ssize_t offset) -/*[clinic end generated code: output=1042631674c6e0d3 input=6e80a5398e985025]*/ +/*[clinic end generated code: output=1042631674c6e0d3 input=599262b23559f6c5]*/ { return Struct_unpack_from_impl(s_object, buffer, offset); } @@ -2650,26 +2619,25 @@ iter_unpack 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. +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 calcsize(format). [clinic start generated code]*/ static PyObject * iter_unpack_impl(PyObject *module, PyStructObject *s_object, PyObject *buffer) -/*[clinic end generated code: output=0ae50e250d20e74d input=b214a58869a3c98d]*/ +/*[clinic end generated code: output=0ae50e250d20e74d input=ac5086c5c4ed68bb]*/ { - return Struct_iter_unpack((PyObject*)s_object, buffer); + return Struct_iter_unpack_impl(s_object, buffer); } static struct PyMethodDef module_functions[] = { _CLEARCACHE_METHODDEF CALCSIZE_METHODDEF ITER_UNPACK_METHODDEF - {"pack", _PyCFunction_CAST(pack), METH_FASTCALL, pack_doc}, - {"pack_into", _PyCFunction_CAST(pack_into), METH_FASTCALL, pack_into_doc}, + PACK_METHODDEF + PACK_INTO_METHODDEF UNPACK_METHODDEF UNPACK_FROM_METHODDEF {NULL, NULL} /* sentinel */ diff --git a/Modules/clinic/_struct.c.h b/Modules/clinic/_struct.c.h index e4eaadb91eb231..11cd26174a3418 100644 --- a/Modules/clinic/_struct.c.h +++ b/Modules/clinic/_struct.c.h @@ -15,10 +15,8 @@ PyDoc_STRVAR(Struct___init____doc__, "\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."); +"Return a new Struct object which writes and reads binary data according\n" +"to the format string. See help(struct) for more on format strings."); static int Struct___init___impl(PyStructObject *self, PyObject *format); @@ -77,10 +75,9 @@ PyDoc_STRVAR(Struct_unpack__doc__, "\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."); +"Unpack according to the struct format string. The buffer\'s\n" +"size in bytes must be the struct size. See help(struct) for more on\n" +"format strings."); #define STRUCT_UNPACK_METHODDEF \ {"unpack", (PyCFunction)Struct_unpack, METH_O, Struct_unpack__doc__}, @@ -114,12 +111,10 @@ PyDoc_STRVAR(Struct_unpack_from__doc__, "\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, starting at position offset, must be\n" -"at least Struct.size.\n" -"\n" -"See help(struct) for more on format strings."); +"Values are unpacked according to the struct format string. The\n" +"buffer\'s size in bytes, starting at position offset, must be at\n" +"least the struct size. See help(struct) for more on format\n" +"strings."); #define STRUCT_UNPACK_FROM_METHODDEF \ {"unpack_from", _PyCFunction_CAST(Struct_unpack_from), METH_FASTCALL|METH_KEYWORDS, Struct_unpack_from__doc__}, @@ -206,9 +201,8 @@ PyDoc_STRVAR(Struct_iter_unpack__doc__, "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."); +"invocation of unpack_from(). Requires that the bytes length be\n" +"a multiple of the struct size."); #define STRUCT_ITER_UNPACK_METHODDEF \ {"iter_unpack", (PyCFunction)Struct_iter_unpack, METH_O, Struct_iter_unpack__doc__}, @@ -226,6 +220,103 @@ Struct_iter_unpack(PyObject *self, PyObject *buffer) return return_value; } +PyDoc_STRVAR(Struct_pack__doc__, +"pack($self, /, *values)\n" +"--\n" +"\n" +"Pack values and return the packed bytes.\n" +"\n" +"Return a bytes object containing the provided values packed\n" +"according to the struct format string. See help(struct) for more on\n" +"format strings."); + +#define STRUCT_PACK_METHODDEF \ + {"pack", _PyCFunction_CAST(Struct_pack), METH_FASTCALL, Struct_pack__doc__}, + +static PyObject * +Struct_pack_impl(PyStructObject *self, PyObject * const *values, + Py_ssize_t values_length); + +static PyObject * +Struct_pack(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyObject * const *values; + Py_ssize_t values_length; + + values = args; + values_length = nargs; + return_value = Struct_pack_impl((PyStructObject *)self, values, values_length); + + return return_value; +} + +PyDoc_STRVAR(Struct_pack_into__doc__, +"pack_into($self, buffer, offset, /, *values)\n" +"--\n" +"\n" +"Pack values and write the packed bytes into the buffer.\n" +"\n" +"Pack the provided values according to the struct format string\n" +"and write the packed bytes into the writable buffer starting at\n" +"offset. Note that the offset is a required argument. See\n" +"help(struct) for more on format strings."); + +#define STRUCT_PACK_INTO_METHODDEF \ + {"pack_into", _PyCFunction_CAST(Struct_pack_into), METH_FASTCALL, Struct_pack_into__doc__}, + +static PyObject * +Struct_pack_into_impl(PyStructObject *self, Py_buffer *buffer, + PyObject *offset_obj, PyObject * const *values, + Py_ssize_t values_length); + +static PyObject * +Struct_pack_into(PyObject *self, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + Py_buffer buffer = {NULL, NULL}; + PyObject *offset_obj; + PyObject * const *values; + Py_ssize_t values_length; + + if (!_PyArg_CheckPositional("pack_into", nargs, 2, PY_SSIZE_T_MAX)) { + goto exit; + } + if (PyObject_GetBuffer(args[0], &buffer, PyBUF_WRITABLE) < 0) { + _PyArg_BadArgument("pack_into", "argument 1", "read-write bytes-like object", args[0]); + goto exit; + } + offset_obj = args[1]; + values = args + 2; + values_length = nargs - 2; + return_value = Struct_pack_into_impl((PyStructObject *)self, &buffer, offset_obj, values, values_length); + +exit: + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + +PyDoc_STRVAR(Struct___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n"); + +#define STRUCT___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)Struct___sizeof__, METH_NOARGS, Struct___sizeof____doc__}, + +static PyObject * +Struct___sizeof___impl(PyStructObject *self); + +static PyObject * +Struct___sizeof__(PyObject *self, PyObject *Py_UNUSED(ignored)) +{ + return Struct___sizeof___impl((PyStructObject *)self); +} + PyDoc_STRVAR(_clearcache__doc__, "_clearcache($module, /)\n" "--\n" @@ -279,15 +370,110 @@ calcsize(PyObject *module, PyObject *arg) return return_value; } +PyDoc_STRVAR(pack__doc__, +"pack($module, format, /, *values)\n" +"--\n" +"\n" +"Pack values and return the packed bytes.\n" +"\n" +"Return a bytes object containing the provided values packed according\n" +"to the format string. See help(struct) for more on format strings."); + +#define PACK_METHODDEF \ + {"pack", _PyCFunction_CAST(pack), METH_FASTCALL, pack__doc__}, + +static PyObject * +pack_impl(PyObject *module, PyStructObject *s_object, + PyObject * const *values, Py_ssize_t values_length); + +static PyObject * +pack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyStructObject *s_object = NULL; + PyObject * const *values; + Py_ssize_t values_length; + + if (!_PyArg_CheckPositional("pack", nargs, 1, PY_SSIZE_T_MAX)) { + goto exit; + } + if (!cache_struct_converter(module, args[0], &s_object)) { + goto exit; + } + values = args + 1; + values_length = nargs - 1; + return_value = pack_impl(module, s_object, values, values_length); + +exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); + + return return_value; +} + +PyDoc_STRVAR(pack_into__doc__, +"pack_into($module, format, buffer, offset, /, *values)\n" +"--\n" +"\n" +"Pack values and write the packed bytes into the buffer.\n" +"\n" +"Pack the provided values according to the format string and write the\n" +"packed bytes into the writable buffer starting at offset. Note that the\n" +"offset is a required argument. See help(struct) for more on format\n" +"strings."); + +#define PACK_INTO_METHODDEF \ + {"pack_into", _PyCFunction_CAST(pack_into), METH_FASTCALL, pack_into__doc__}, + +static PyObject * +pack_into_impl(PyObject *module, PyStructObject *s_object, Py_buffer *buffer, + PyObject *offset_obj, PyObject * const *values, + Py_ssize_t values_length); + +static PyObject * +pack_into(PyObject *module, PyObject *const *args, Py_ssize_t nargs) +{ + PyObject *return_value = NULL; + PyStructObject *s_object = NULL; + Py_buffer buffer = {NULL, NULL}; + PyObject *offset_obj; + PyObject * const *values; + Py_ssize_t values_length; + + if (!_PyArg_CheckPositional("pack_into", nargs, 3, PY_SSIZE_T_MAX)) { + goto exit; + } + if (!cache_struct_converter(module, args[0], &s_object)) { + goto exit; + } + if (PyObject_GetBuffer(args[1], &buffer, PyBUF_WRITABLE) < 0) { + _PyArg_BadArgument("pack_into", "argument 2", "read-write bytes-like object", args[1]); + goto exit; + } + offset_obj = args[2]; + values = args + 3; + values_length = nargs - 3; + return_value = pack_into_impl(module, s_object, &buffer, offset_obj, values, values_length); + +exit: + /* Cleanup for s_object */ + Py_XDECREF(s_object); + /* Cleanup for buffer */ + if (buffer.obj) { + PyBuffer_Release(&buffer); + } + + return return_value; +} + PyDoc_STRVAR(unpack__doc__, "unpack($module, format, buffer, /)\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."); +"The buffer\'s size in bytes must be calcsize(format). See help(struct)\n" +"for more on format strings."); #define UNPACK_METHODDEF \ {"unpack", _PyCFunction_CAST(unpack), METH_FASTCALL, unpack__doc__}, @@ -330,9 +516,8 @@ PyDoc_STRVAR(unpack_from__doc__, "\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."); +"The buffer\'s size, minus offset, must be at least calcsize(format). See\n" +"help(struct) for more on format strings."); #define UNPACK_FROM_METHODDEF \ {"unpack_from", _PyCFunction_CAST(unpack_from), METH_FASTCALL|METH_KEYWORDS, unpack_from__doc__}, @@ -424,10 +609,9 @@ PyDoc_STRVAR(iter_unpack__doc__, "\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."); +"The bytes are unpacked according to the format string, like a repeated\n" +"invocation of unpack_from(). Requires that the bytes length be\n" +"a multiple of calcsize(format)."); #define ITER_UNPACK_METHODDEF \ {"iter_unpack", _PyCFunction_CAST(iter_unpack), METH_FASTCALL, iter_unpack__doc__}, @@ -458,4 +642,4 @@ iter_unpack(PyObject *module, PyObject *const *args, Py_ssize_t nargs) return return_value; } -/*[clinic end generated code: output=caa7f36443e91cb9 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=dc4f86c77ab3b1c9 input=a9049054013a1b77]*/