mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Issue #16612: Add "Argument Clinic", a compile-time preprocessor
for C files to generate argument parsing code. (See PEP 436.)
This commit is contained in:
parent
5ceae41083
commit
3182680210
12 changed files with 4016 additions and 276 deletions
|
@ -8,6 +8,7 @@
|
|||
#include "structmember.h"
|
||||
#include "zlib.h"
|
||||
|
||||
|
||||
#ifdef WITH_THREAD
|
||||
#include "pythread.h"
|
||||
#define ENTER_ZLIB(obj) \
|
||||
|
@ -626,87 +627,136 @@ save_unconsumed_input(compobject *self, int err)
|
|||
return 0;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(decomp_decompress__doc__,
|
||||
"decompress(data, max_length) -- Return a string containing the decompressed\n"
|
||||
"version of the data.\n"
|
||||
/*[clinic]
|
||||
|
||||
module zlib
|
||||
|
||||
zlib.decompress
|
||||
|
||||
data: Py_buffer
|
||||
The binary data to decompress.
|
||||
max_length: int = 0
|
||||
The maximum allowable length of the decompressed data.
|
||||
Unconsumed input data will be stored in
|
||||
the unconsumed_tail attribute.
|
||||
/
|
||||
|
||||
Return a string containing the decompressed version of the data.
|
||||
|
||||
After calling this function, some of the input data may still be stored in
|
||||
internal buffers for later processing.
|
||||
Call the flush() method to clear these buffers.
|
||||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(zlib_decompress__doc__,
|
||||
"Return a string containing the decompressed version of the data.\n"
|
||||
"\n"
|
||||
"zlib.decompress(data, max_length=0)\n"
|
||||
" data\n"
|
||||
" The binary data to decompress.\n"
|
||||
" max_length\n"
|
||||
" The maximum allowable length of the decompressed data.\n"
|
||||
" Unconsumed input data will be stored in\n"
|
||||
" the unconsumed_tail attribute.\n"
|
||||
"\n"
|
||||
"After calling this function, some of the input data may still be stored in\n"
|
||||
"internal buffers for later processing.\n"
|
||||
"Call the flush() method to clear these buffers.\n"
|
||||
"If the max_length parameter is specified then the return value will be\n"
|
||||
"no longer than max_length. Unconsumed input data will be stored in\n"
|
||||
"the unconsumed_tail attribute.");
|
||||
"Call the flush() method to clear these buffers.");
|
||||
|
||||
#define ZLIB_DECOMPRESS_METHODDEF \
|
||||
{"decompress", (PyCFunction)zlib_decompress, METH_VARARGS, zlib_decompress__doc__},
|
||||
|
||||
static PyObject *
|
||||
PyZlib_objdecompress(compobject *self, PyObject *args)
|
||||
zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length);
|
||||
|
||||
static PyObject *
|
||||
zlib_decompress(PyObject *self, PyObject *args)
|
||||
{
|
||||
int err, max_length = 0;
|
||||
PyObject *return_value = NULL;
|
||||
Py_buffer data;
|
||||
int max_length = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args,
|
||||
"y*|i:decompress",
|
||||
&data, &max_length))
|
||||
goto exit;
|
||||
return_value = zlib_decompress_impl(self, &data, max_length);
|
||||
|
||||
exit:
|
||||
/* Cleanup for data */
|
||||
PyBuffer_Release(&data);
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
zlib_decompress_impl(PyObject *self, Py_buffer *data, int max_length)
|
||||
/*[clinic checksum: 168d093d400739dde947cca1f4fb0f9d51cdc2c9]*/
|
||||
{
|
||||
compobject *zself = (compobject *)self;
|
||||
int err;
|
||||
unsigned int inplen;
|
||||
Py_ssize_t old_length, length = DEFAULTALLOC;
|
||||
PyObject *RetVal = NULL;
|
||||
Py_buffer pinput;
|
||||
Byte *input;
|
||||
unsigned long start_total_out;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "y*|i:decompress", &pinput,
|
||||
&max_length))
|
||||
return NULL;
|
||||
if (pinput.len > UINT_MAX) {
|
||||
if (data->len > UINT_MAX) {
|
||||
PyErr_SetString(PyExc_OverflowError,
|
||||
"Size does not fit in an unsigned int");
|
||||
goto error_outer;
|
||||
return NULL;
|
||||
}
|
||||
input = pinput.buf;
|
||||
inplen = pinput.len;
|
||||
input = data->buf;
|
||||
inplen = data->len;
|
||||
if (max_length < 0) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"max_length must be greater than zero");
|
||||
goto error_outer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* limit amount of data allocated to max_length */
|
||||
if (max_length && length > max_length)
|
||||
length = max_length;
|
||||
if (!(RetVal = PyBytes_FromStringAndSize(NULL, length)))
|
||||
goto error_outer;
|
||||
return NULL;
|
||||
|
||||
ENTER_ZLIB(self);
|
||||
ENTER_ZLIB(zself);
|
||||
|
||||
start_total_out = self->zst.total_out;
|
||||
self->zst.avail_in = inplen;
|
||||
self->zst.next_in = input;
|
||||
self->zst.avail_out = length;
|
||||
self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
|
||||
start_total_out = zself->zst.total_out;
|
||||
zself->zst.avail_in = inplen;
|
||||
zself->zst.next_in = input;
|
||||
zself->zst.avail_out = length;
|
||||
zself->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal);
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
||||
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||
Py_END_ALLOW_THREADS
|
||||
|
||||
if (err == Z_NEED_DICT && self->zdict != NULL) {
|
||||
if (err == Z_NEED_DICT && zself->zdict != NULL) {
|
||||
Py_buffer zdict_buf;
|
||||
if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
|
||||
if (PyObject_GetBuffer(zself->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
|
||||
Py_DECREF(RetVal);
|
||||
RetVal = NULL;
|
||||
goto error;
|
||||
}
|
||||
err = inflateSetDictionary(&(self->zst), zdict_buf.buf, zdict_buf.len);
|
||||
err = inflateSetDictionary(&(zself->zst), zdict_buf.buf, zdict_buf.len);
|
||||
PyBuffer_Release(&zdict_buf);
|
||||
if (err != Z_OK) {
|
||||
zlib_error(self->zst, err, "while decompressing data");
|
||||
zlib_error(zself->zst, err, "while decompressing data");
|
||||
Py_DECREF(RetVal);
|
||||
RetVal = NULL;
|
||||
goto error;
|
||||
}
|
||||
/* Repeat the call to inflate. */
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
||||
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
|
||||
/* While Z_OK and the output buffer is full, there might be more output.
|
||||
So extend the output buffer and try again.
|
||||
*/
|
||||
while (err == Z_OK && self->zst.avail_out == 0) {
|
||||
while (err == Z_OK && zself->zst.avail_out == 0) {
|
||||
/* If max_length set, don't continue decompressing if we've already
|
||||
reached the limit.
|
||||
*/
|
||||
|
@ -723,16 +773,16 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
|
|||
Py_CLEAR(RetVal);
|
||||
goto error;
|
||||
}
|
||||
self->zst.next_out =
|
||||
zself->zst.next_out =
|
||||
(unsigned char *)PyBytes_AS_STRING(RetVal) + old_length;
|
||||
self->zst.avail_out = length - old_length;
|
||||
zself->zst.avail_out = length - old_length;
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
err = inflate(&(self->zst), Z_SYNC_FLUSH);
|
||||
err = inflate(&(zself->zst), Z_SYNC_FLUSH);
|
||||
Py_END_ALLOW_THREADS
|
||||
}
|
||||
|
||||
if (save_unconsumed_input(self, err) < 0) {
|
||||
if (save_unconsumed_input(zself, err) < 0) {
|
||||
Py_DECREF(RetVal);
|
||||
RetVal = NULL;
|
||||
goto error;
|
||||
|
@ -741,26 +791,24 @@ PyZlib_objdecompress(compobject *self, PyObject *args)
|
|||
if (err == Z_STREAM_END) {
|
||||
/* This is the logical place to call inflateEnd, but the old behaviour
|
||||
of only calling it on flush() is preserved. */
|
||||
self->eof = 1;
|
||||
zself->eof = 1;
|
||||
} else if (err != Z_OK && err != Z_BUF_ERROR) {
|
||||
/* We will only get Z_BUF_ERROR if the output buffer was full
|
||||
but there wasn't more output when we tried again, so it is
|
||||
not an error condition.
|
||||
*/
|
||||
zlib_error(self->zst, err, "while decompressing data");
|
||||
zlib_error(zself->zst, err, "while decompressing data");
|
||||
Py_DECREF(RetVal);
|
||||
RetVal = NULL;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) {
|
||||
if (_PyBytes_Resize(&RetVal, zself->zst.total_out - start_total_out) < 0) {
|
||||
Py_CLEAR(RetVal);
|
||||
}
|
||||
|
||||
error:
|
||||
LEAVE_ZLIB(self);
|
||||
error_outer:
|
||||
PyBuffer_Release(&pinput);
|
||||
LEAVE_ZLIB(zself);
|
||||
return RetVal;
|
||||
}
|
||||
|
||||
|
@ -856,12 +904,27 @@ PyZlib_flush(compobject *self, PyObject *args)
|
|||
}
|
||||
|
||||
#ifdef HAVE_ZLIB_COPY
|
||||
PyDoc_STRVAR(comp_copy__doc__,
|
||||
"copy() -- Return a copy of the compression object.");
|
||||
|
||||
/*[clinic]
|
||||
|
||||
zlib.copy
|
||||
|
||||
Return a copy of the compression object.
|
||||
[clinic]*/
|
||||
|
||||
PyDoc_STRVAR(zlib_copy__doc__,
|
||||
"Return a copy of the compression object.\n"
|
||||
"\n"
|
||||
"zlib.copy()");
|
||||
|
||||
#define ZLIB_COPY_METHODDEF \
|
||||
{"copy", (PyCFunction)zlib_copy, METH_NOARGS, zlib_copy__doc__},
|
||||
|
||||
static PyObject *
|
||||
PyZlib_copy(compobject *self)
|
||||
zlib_copy(PyObject *self)
|
||||
/*[clinic checksum: 7b648de2c1f933ba2b9fa17331ff1a44d9a4a740]*/
|
||||
{
|
||||
compobject *zself = (compobject *)self;
|
||||
compobject *retval = NULL;
|
||||
int err;
|
||||
|
||||
|
@ -871,8 +934,8 @@ PyZlib_copy(compobject *self)
|
|||
/* Copy the zstream state
|
||||
* We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
|
||||
*/
|
||||
ENTER_ZLIB(self);
|
||||
err = deflateCopy(&retval->zst, &self->zst);
|
||||
ENTER_ZLIB(zself);
|
||||
err = deflateCopy(&retval->zst, &zself->zst);
|
||||
switch(err) {
|
||||
case(Z_OK):
|
||||
break;
|
||||
|
@ -884,28 +947,28 @@ PyZlib_copy(compobject *self)
|
|||
"Can't allocate memory for compression object");
|
||||
goto error;
|
||||
default:
|
||||
zlib_error(self->zst, err, "while copying compression object");
|
||||
zlib_error(zself->zst, err, "while copying compression object");
|
||||
goto error;
|
||||
}
|
||||
Py_INCREF(self->unused_data);
|
||||
Py_INCREF(self->unconsumed_tail);
|
||||
Py_XINCREF(self->zdict);
|
||||
Py_INCREF(zself->unused_data);
|
||||
Py_INCREF(zself->unconsumed_tail);
|
||||
Py_XINCREF(zself->zdict);
|
||||
Py_XDECREF(retval->unused_data);
|
||||
Py_XDECREF(retval->unconsumed_tail);
|
||||
Py_XDECREF(retval->zdict);
|
||||
retval->unused_data = self->unused_data;
|
||||
retval->unconsumed_tail = self->unconsumed_tail;
|
||||
retval->zdict = self->zdict;
|
||||
retval->eof = self->eof;
|
||||
retval->unused_data = zself->unused_data;
|
||||
retval->unconsumed_tail = zself->unconsumed_tail;
|
||||
retval->zdict = zself->zdict;
|
||||
retval->eof = zself->eof;
|
||||
|
||||
/* Mark it as being initialized */
|
||||
retval->is_initialised = 1;
|
||||
|
||||
LEAVE_ZLIB(self);
|
||||
LEAVE_ZLIB(zself);
|
||||
return (PyObject *)retval;
|
||||
|
||||
error:
|
||||
LEAVE_ZLIB(self);
|
||||
LEAVE_ZLIB(zself);
|
||||
Py_XDECREF(retval);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1055,16 +1118,14 @@ static PyMethodDef comp_methods[] =
|
|||
{"flush", (binaryfunc)PyZlib_flush, METH_VARARGS,
|
||||
comp_flush__doc__},
|
||||
#ifdef HAVE_ZLIB_COPY
|
||||
{"copy", (PyCFunction)PyZlib_copy, METH_NOARGS,
|
||||
comp_copy__doc__},
|
||||
ZLIB_COPY_METHODDEF
|
||||
#endif
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static PyMethodDef Decomp_methods[] =
|
||||
{
|
||||
{"decompress", (binaryfunc)PyZlib_objdecompress, METH_VARARGS,
|
||||
decomp_decompress__doc__},
|
||||
ZLIB_DECOMPRESS_METHODDEF
|
||||
{"flush", (binaryfunc)PyZlib_unflush, METH_VARARGS,
|
||||
decomp_flush__doc__},
|
||||
#ifdef HAVE_ZLIB_COPY
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue