mirror of https://github.com/python/cpython
patches from Andrew
NOTE: There is still a bug of some sort in the behavior of zlib. In at least one case, inflate returns Z_OK (which is typically interpreted to mean that more output space is needed) when it has finished inflating a buffer. This has been reported as a bug to the zlib maintainers; we may need to change the Python interface.
This commit is contained in:
parent
1924a0677d
commit
a37e244536
|
@ -80,7 +80,7 @@ PyZlib_compress(self, args)
|
||||||
"Can't allocate memory to compress data");
|
"Can't allocate memory to compress data");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
zst.zalloc=(alloc_func)NULL;
|
|
||||||
zst.zfree=(free_func)Z_NULL;
|
zst.zfree=(free_func)Z_NULL;
|
||||||
zst.next_out=(Byte *)output;
|
zst.next_out=(Byte *)output;
|
||||||
zst.next_in =(Byte *)input;
|
zst.next_in =(Byte *)input;
|
||||||
|
@ -172,7 +172,7 @@ PyZlib_decompress(self, args)
|
||||||
|
|
||||||
if (r_strlen <= 0)
|
if (r_strlen <= 0)
|
||||||
r_strlen = 1;
|
r_strlen = 1;
|
||||||
|
|
||||||
zst.avail_in=length;
|
zst.avail_in=length;
|
||||||
zst.avail_out=r_strlen;
|
zst.avail_out=r_strlen;
|
||||||
if (!(result_str = PyString_FromStringAndSize(NULL, r_strlen)))
|
if (!(result_str = PyString_FromStringAndSize(NULL, r_strlen)))
|
||||||
|
@ -212,6 +212,8 @@ PyZlib_decompress(self, args)
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
err=inflate(&zst, Z_FINISH);
|
err=inflate(&zst, Z_FINISH);
|
||||||
|
fprintf(stderr, "err=%d avail_in=%d avail_out=%d\n",
|
||||||
|
err, zst.avail_in, zst.avail_out);
|
||||||
switch(err)
|
switch(err)
|
||||||
{
|
{
|
||||||
case(Z_STREAM_END):
|
case(Z_STREAM_END):
|
||||||
|
@ -488,8 +490,11 @@ PyZlib_objdecompress(self, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
static char comp_flush__doc__[] =
|
static char comp_flush__doc__[] =
|
||||||
"flush() -- Return a string containing any remaining compressed data. "
|
"flush( [mode] ) -- Return a string containing any remaining compressed data.\n"
|
||||||
"The compressor object can no longer be used after this call."
|
"mode can be one of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH; the \n"
|
||||||
|
"default value used when mode is not specified is Z_FINISH.\n"
|
||||||
|
"If mode == Z_FINISH, the compressor object can no longer be used after\n"
|
||||||
|
"calling the flush() method. Otherwise, more data can still be compressed.\n"
|
||||||
;
|
;
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
|
@ -499,9 +504,19 @@ PyZlib_flush(self, args)
|
||||||
{
|
{
|
||||||
int length=DEFAULTALLOC, err = Z_OK;
|
int length=DEFAULTALLOC, err = Z_OK;
|
||||||
PyObject *RetVal;
|
PyObject *RetVal;
|
||||||
|
int flushmode = Z_FINISH;
|
||||||
if (!PyArg_NoArgs(args))
|
unsigned long start_total_out;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "|i", &flushmode))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* Flushing with Z_NO_FLUSH is a no-op, so there's no point in
|
||||||
|
doing any work at all; just return an empty string. */
|
||||||
|
if (flushmode == Z_NO_FLUSH)
|
||||||
|
{
|
||||||
|
return PyString_FromStringAndSize(NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
self->zst.avail_in = 0;
|
self->zst.avail_in = 0;
|
||||||
self->zst.next_in = Z_NULL;
|
self->zst.next_in = Z_NULL;
|
||||||
if (!(RetVal = PyString_FromStringAndSize(NULL, length))) {
|
if (!(RetVal = PyString_FromStringAndSize(NULL, length))) {
|
||||||
|
@ -509,10 +524,14 @@ PyZlib_flush(self, args)
|
||||||
"Can't allocate memory to compress data");
|
"Can't allocate memory to compress data");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
start_total_out = self->zst.total_out;
|
||||||
self->zst.next_out = (unsigned char *)PyString_AsString(RetVal);
|
self->zst.next_out = (unsigned char *)PyString_AsString(RetVal);
|
||||||
self->zst.avail_out = length;
|
self->zst.avail_out = length;
|
||||||
while (err == Z_OK)
|
|
||||||
{
|
/* When flushing the zstream, there's no input data.
|
||||||
|
If zst.avail_out == 0, that means that more output space is
|
||||||
|
needed to complete the flush operation. */
|
||||||
|
do {
|
||||||
err = deflate(&(self->zst), Z_FINISH);
|
err = deflate(&(self->zst), Z_FINISH);
|
||||||
if (self->zst.avail_out <= 0) {
|
if (self->zst.avail_out <= 0) {
|
||||||
if (_PyString_Resize(&RetVal, length << 1) == -1) {
|
if (_PyString_Resize(&RetVal, length << 1) == -1) {
|
||||||
|
@ -524,31 +543,34 @@ PyZlib_flush(self, args)
|
||||||
self->zst.avail_out = length;
|
self->zst.avail_out = length;
|
||||||
length = length << 1;
|
length = length << 1;
|
||||||
}
|
}
|
||||||
}
|
} while (self->zst.avail_out == 0);
|
||||||
if (err!=Z_STREAM_END) {
|
|
||||||
|
if (err!=Z_OK && err != Z_STREAM_END)
|
||||||
|
{
|
||||||
if (self->zst.msg == Z_NULL)
|
if (self->zst.msg == Z_NULL)
|
||||||
PyErr_Format(ZlibError, "Error %i while compressing",
|
PyErr_Format(ZlibError, "Error %i while flushing",
|
||||||
err);
|
err);
|
||||||
else
|
else
|
||||||
PyErr_Format(ZlibError, "Error %i while compressing: %.200s",
|
PyErr_Format(ZlibError, "Error %i while flushing: %.200s",
|
||||||
err, self->zst.msg);
|
err, self->zst.msg);
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
err=deflateEnd(&(self->zst));
|
if (flushmode == Z_FINISH) {
|
||||||
if (err!=Z_OK) {
|
err=deflateEnd(&(self->zst));
|
||||||
|
if (err!=Z_OK) {
|
||||||
if (self->zst.msg == Z_NULL)
|
if (self->zst.msg == Z_NULL)
|
||||||
PyErr_Format(ZlibError, "Error %i while flushing compression object",
|
PyErr_Format(ZlibError, "Error %i from deflateEnd()",
|
||||||
err);
|
err);
|
||||||
else
|
else
|
||||||
PyErr_Format(ZlibError,
|
PyErr_Format(ZlibError,
|
||||||
"Error %i while flushing compression object: %.200s",
|
"Error %i from deflateEnd(): %.200s",
|
||||||
err, self->zst.msg);
|
err, self->zst.msg);
|
||||||
Py_DECREF(RetVal);
|
Py_DECREF(RetVal);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
_PyString_Resize(&RetVal,
|
_PyString_Resize(&RetVal, self->zst.total_out - start_total_out);
|
||||||
(char *)self->zst.next_out - PyString_AsString(RetVal));
|
|
||||||
return RetVal;
|
return RetVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -627,7 +649,7 @@ PyZlib_unflush(self, args)
|
||||||
static PyMethodDef comp_methods[] =
|
static PyMethodDef comp_methods[] =
|
||||||
{
|
{
|
||||||
{"compress", (binaryfunc)PyZlib_objcompress, 1, comp_compress__doc__},
|
{"compress", (binaryfunc)PyZlib_objcompress, 1, comp_compress__doc__},
|
||||||
{"flush", (binaryfunc)PyZlib_flush, 0, comp_flush__doc__},
|
{"flush", (binaryfunc)PyZlib_flush, 1, comp_flush__doc__},
|
||||||
{NULL, NULL}
|
{NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -805,6 +827,12 @@ PyInit_zlib()
|
||||||
insint(d, "Z_FILTERED", Z_FILTERED);
|
insint(d, "Z_FILTERED", Z_FILTERED);
|
||||||
insint(d, "Z_HUFFMAN_ONLY", Z_HUFFMAN_ONLY);
|
insint(d, "Z_HUFFMAN_ONLY", Z_HUFFMAN_ONLY);
|
||||||
insint(d, "Z_DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
|
insint(d, "Z_DEFAULT_STRATEGY", Z_DEFAULT_STRATEGY);
|
||||||
|
|
||||||
|
insint(d, "Z_FINISH", Z_FINISH);
|
||||||
|
insint(d, "Z_NO_FLUSH", Z_NO_FLUSH);
|
||||||
|
insint(d, "Z_SYNC_FLUSH", Z_SYNC_FLUSH);
|
||||||
|
insint(d, "Z_FULL_FLUSH", Z_FULL_FLUSH);
|
||||||
|
|
||||||
ver = PyString_FromString(ZLIB_VERSION);
|
ver = PyString_FromString(ZLIB_VERSION);
|
||||||
PyDict_SetItemString(d, "ZLIB_VERSION", ver);
|
PyDict_SetItemString(d, "ZLIB_VERSION", ver);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue