static PyObject * PyZlib_uncopy(compobject *self) { compobject *retval = NULL; int err; retval = newcompobject(&Decomptype); if (!retval) return NULL; /* Copy the zstream state * We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe */ ENTER_ZLIB(self); err = inflateCopy(&retval->zst, &self->zst); switch(err) { case(Z_OK): break; case(Z_STREAM_ERROR): PyErr_SetString(PyExc_ValueError, "Inconsistent stream state"); goto error; case(Z_MEM_ERROR): PyErr_SetString(PyExc_MemoryError, "Can't allocate memory for decompression object"); goto error; default: zlib_error(self->zst, err, "while copying decompression object"); goto error; } Py_INCREF(self->unused_data); Py_INCREF(self->unconsumed_tail); Py_XDECREF(retval->unused_data); Py_XDECREF(retval->unconsumed_tail); retval->unused_data = self->unused_data; retval->unconsumed_tail = self->unconsumed_tail; retval->eof = self->eof; /* Mark it as being initialized */ retval->is_initialised = 1; LEAVE_ZLIB(self); return (PyObject *)retval; error: LEAVE_ZLIB(self); Py_XDECREF(retval); return NULL; }
static PyObject * PyZlib_unflush(compobject *self, PyObject *args) { int err, length = DEFAULTALLOC; PyObject * retval = NULL; unsigned long start_total_out; if (!PyArg_ParseTuple(args, "|i:flush", &length)) return NULL; if (length <= 0) { PyErr_SetString(PyExc_ValueError, "length must be greater than zero"); return NULL; } if (!(retval = PyBytes_FromStringAndSize(NULL, length))) return NULL; ENTER_ZLIB(self); start_total_out = self->zst.total_out; self->zst.avail_out = length; self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval); Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_FINISH); 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 || err == Z_BUF_ERROR) && self->zst.avail_out == 0) { if (_PyBytes_Resize(&retval, length << 1) < 0) { Py_DECREF(retval); retval = NULL; goto error; } self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval) + length; self->zst.avail_out = length; length = length << 1; Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_FINISH); Py_END_ALLOW_THREADS } /* If at end of stream, clean up any memory allocated by zlib. */ if (err == Z_STREAM_END) { self->eof = 1; self->is_initialised = 0; err = inflateEnd(&(self->zst)); if (err != Z_OK) { zlib_error(self->zst, err, "while finishing decompression"); Py_DECREF(retval); retval = NULL; goto error; } } if (_PyBytes_Resize(&retval, self->zst.total_out - start_total_out) < 0) { Py_DECREF(retval); retval = NULL; } error: LEAVE_ZLIB(self); return retval; }
static PyObject * PyZlib_flush(compobject *self, PyObject *args) { int err, length = DEFAULTALLOC; PyObject *RetVal; int flushmode = Z_FINISH; unsigned long start_total_out; if (!PyArg_ParseTuple(args, "|i:flush", &flushmode)) 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 PyBytes_FromStringAndSize(NULL, 0); } if (!(RetVal = PyBytes_FromStringAndSize(NULL, length))) return NULL; ENTER_ZLIB(self); start_total_out = self->zst.total_out; self->zst.avail_in = 0; self->zst.avail_out = length; self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal); Py_BEGIN_ALLOW_THREADS err = deflate(&(self->zst), flushmode); 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) { if (_PyBytes_Resize(&RetVal, length << 1) < 0) { Py_DECREF(RetVal); RetVal = NULL; goto error; } self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal) + length; self->zst.avail_out = length; length = length << 1; Py_BEGIN_ALLOW_THREADS err = deflate(&(self->zst), flushmode); Py_END_ALLOW_THREADS } /* If flushmode is Z_FINISH, we also have to call deflateEnd() to free various data structures. Note we should only get Z_STREAM_END when flushmode is Z_FINISH, but checking both for safety*/ if (err == Z_STREAM_END && flushmode == Z_FINISH) { err = deflateEnd(&(self->zst)); if (err != Z_OK) { zlib_error(self->zst, err, "while finishing compression"); Py_DECREF(RetVal); RetVal = NULL; goto error; } else self->is_initialised = 0; /* 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. */ } else if (err!=Z_OK && err!=Z_BUF_ERROR) { zlib_error(self->zst, err, "while flushing"); Py_DECREF(RetVal); RetVal = NULL; goto error; } if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) { Py_DECREF(RetVal); RetVal = NULL; } error: LEAVE_ZLIB(self); return RetVal; }
static PyObject * PyZlib_objdecompress(compobject *self, PyObject *args) { int err, max_length = 0; 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) { PyErr_SetString(PyExc_OverflowError, "Size does not fit in an unsigned int"); goto error_outer; } input = pinput.buf; inplen = pinput.len; if (max_length < 0) { PyErr_SetString(PyExc_ValueError, "max_length must be greater than zero"); goto error_outer; } /* 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; ENTER_ZLIB(self); 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); Py_BEGIN_ALLOW_THREADS err = inflate(&(self->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) { /* If max_length set, don't continue decompressing if we've already reached the limit. */ if (max_length && length >= max_length) break; /* otherwise, ... */ old_length = length; length = length << 1; if (max_length && length > max_length) length = max_length; if (_PyBytes_Resize(&RetVal, length) < 0) { Py_DECREF(RetVal); RetVal = NULL; goto error; } self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal) + old_length; self->zst.avail_out = length - old_length; Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_SYNC_FLUSH); Py_END_ALLOW_THREADS } if(max_length) { /* Not all of the compressed data could be accommodated in a buffer of the specified size. Return the unconsumed tail in an attribute. */ Py_DECREF(self->unconsumed_tail); self->unconsumed_tail = PyBytes_FromStringAndSize((char *)self->zst.next_in, self->zst.avail_in); } else if (PyBytes_GET_SIZE(self->unconsumed_tail) > 0) { /* All of the compressed data was consumed. Clear unconsumed_tail. */ Py_DECREF(self->unconsumed_tail); self->unconsumed_tail = PyBytes_FromStringAndSize("", 0); } if (self->unconsumed_tail == NULL) { Py_DECREF(RetVal); RetVal = NULL; goto error; } /* The end of the compressed data has been reached, so set the unused_data attribute to a string containing the remainder of the data in the string. Note that this is also a logical place to call inflateEnd, but the old behaviour of only calling it on flush() is preserved. */ if (err == Z_STREAM_END) { Py_XDECREF(self->unused_data); /* Free original empty string */ self->unused_data = PyBytes_FromStringAndSize( (char *)self->zst.next_in, self->zst.avail_in); if (self->unused_data == NULL) { Py_DECREF(RetVal); goto error; } self->eof = 1; /* 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. */ } else if (err != Z_OK && err != Z_BUF_ERROR) { zlib_error(self->zst, err, "while decompressing data"); Py_DECREF(RetVal); RetVal = NULL; goto error; } if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) { Py_DECREF(RetVal); RetVal = NULL; } error: LEAVE_ZLIB(self); error_outer: PyBuffer_Release(&pinput); return RetVal; }
static PyObject * PyZlib_objcompress(compobject *self, PyObject *args) { int err; unsigned int inplen; Py_ssize_t length = DEFAULTALLOC; PyObject *RetVal = NULL; Py_buffer pinput; Byte *input; unsigned long start_total_out; if (!PyArg_ParseTuple(args, "y*:compress", &pinput)) return NULL; if (pinput.len > UINT_MAX) { PyErr_SetString(PyExc_OverflowError, "Size does not fit in an unsigned int"); goto error_outer; } input = pinput.buf; inplen = pinput.len; if (!(RetVal = PyBytes_FromStringAndSize(NULL, length))) goto error_outer; ENTER_ZLIB(self); 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); Py_BEGIN_ALLOW_THREADS err = deflate(&(self->zst), Z_NO_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) { if (_PyBytes_Resize(&RetVal, length << 1) < 0) { Py_DECREF(RetVal); RetVal = NULL; goto error; } self->zst.next_out = (unsigned char *)PyBytes_AS_STRING(RetVal) + length; self->zst.avail_out = length; length = length << 1; Py_BEGIN_ALLOW_THREADS err = deflate(&(self->zst), Z_NO_FLUSH); Py_END_ALLOW_THREADS } /* 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. */ if (err != Z_OK && err != Z_BUF_ERROR) { zlib_error(self->zst, err, "while compressing data"); Py_DECREF(RetVal); RetVal = NULL; goto error; } if (_PyBytes_Resize(&RetVal, self->zst.total_out - start_total_out) < 0) { Py_DECREF(RetVal); RetVal = NULL; } error: LEAVE_ZLIB(self); error_outer: PyBuffer_Release(&pinput); return RetVal; }
static PyObject * PyZlib_unflush(compobject *self, PyObject *args) { int err, length = DEFAULTALLOC; PyObject * retval = NULL; unsigned long start_total_out; if (!PyArg_ParseTuple(args, "|i:flush", &length)) return NULL; if (length <= 0) { PyErr_SetString(PyExc_ValueError, "length must be greater than zero"); return NULL; } if (!(retval = PyBytes_FromStringAndSize(NULL, length))) return NULL; ENTER_ZLIB(self); start_total_out = self->zst.total_out; self->zst.avail_out = length; self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval); Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_FINISH); 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 || err == Z_BUF_ERROR) && self->zst.avail_out == 0) { if (_PyBytes_Resize(&retval, length << 1) < 0) { Py_DECREF(retval); retval = NULL; goto error; } self->zst.next_out = (Byte *)PyBytes_AS_STRING(retval) + length; self->zst.avail_out = length; length = length << 1; Py_BEGIN_ALLOW_THREADS err = inflate(&(self->zst), Z_FINISH); Py_END_ALLOW_THREADS } /* If flushmode is Z_FINISH, we also have to call deflateEnd() to free various data structures. Note we should only get Z_STREAM_END when flushmode is Z_FINISH */ if (err == Z_STREAM_END) { err = inflateEnd(&(self->zst)); self->is_initialised = 0; if (err != Z_OK) { zlib_error(self->zst, err, "from inflateEnd()"); Py_DECREF(retval); retval = NULL; goto error; } } if (_PyBytes_Resize(&retval, self->zst.total_out - start_total_out) < 0) { Py_DECREF(retval); retval = NULL; } error: LEAVE_ZLIB(self); return retval; }