summaryrefslogtreecommitdiffstats
path: root/contrib/tools/python3/src/Modules/zlibmodule.c
diff options
context:
space:
mode:
authorshadchin <[email protected]>2022-04-18 12:39:32 +0300
committershadchin <[email protected]>2022-04-18 12:39:32 +0300
commitd4be68e361f4258cf0848fc70018dfe37a2acc24 (patch)
tree153e294cd97ac8b5d7a989612704a0c1f58e8ad4 /contrib/tools/python3/src/Modules/zlibmodule.c
parent260c02f5ccf242d9d9b8a873afaf6588c00237d6 (diff)
IGNIETFERRO-1816 Update Python 3 from 3.9.12 to 3.10.4
ref:9f96be6d02ee8044fdd6f124b799b270c20ce641
Diffstat (limited to 'contrib/tools/python3/src/Modules/zlibmodule.c')
-rw-r--r--contrib/tools/python3/src/Modules/zlibmodule.c813
1 files changed, 492 insertions, 321 deletions
diff --git a/contrib/tools/python3/src/Modules/zlibmodule.c b/contrib/tools/python3/src/Modules/zlibmodule.c
index 4dfd4ae6722..a6940f2fd43 100644
--- a/contrib/tools/python3/src/Modules/zlibmodule.c
+++ b/contrib/tools/python3/src/Modules/zlibmodule.c
@@ -9,11 +9,166 @@
#include "structmember.h" // PyMemberDef
#include "zlib.h"
+// Blocks output buffer wrappers
+#include "pycore_blocks_output_buffer.h"
-#define ENTER_ZLIB(obj) \
- Py_BEGIN_ALLOW_THREADS; \
- PyThread_acquire_lock((obj)->lock, 1); \
- Py_END_ALLOW_THREADS;
+#if OUTPUT_BUFFER_MAX_BLOCK_SIZE > UINT32_MAX
+ #error "The maximum block size accepted by zlib is UINT32_MAX."
+#endif
+
+/* On success, return value >= 0
+ On failure, return -1 */
+static inline Py_ssize_t
+OutputBuffer_InitAndGrow(_BlocksOutputBuffer *buffer, Py_ssize_t max_length,
+ Bytef **next_out, uint32_t *avail_out)
+{
+ Py_ssize_t allocated;
+
+ allocated = _BlocksOutputBuffer_InitAndGrow(
+ buffer, max_length, (void**) next_out);
+ *avail_out = (uint32_t) allocated;
+ return allocated;
+}
+
+/* On success, return value >= 0
+ On failure, return -1 */
+static inline Py_ssize_t
+OutputBuffer_Grow(_BlocksOutputBuffer *buffer,
+ Bytef **next_out, uint32_t *avail_out)
+{
+ Py_ssize_t allocated;
+
+ allocated = _BlocksOutputBuffer_Grow(
+ buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+ *avail_out = (uint32_t) allocated;
+ return allocated;
+}
+
+static inline Py_ssize_t
+OutputBuffer_GetDataSize(_BlocksOutputBuffer *buffer, uint32_t avail_out)
+{
+ return _BlocksOutputBuffer_GetDataSize(buffer, (Py_ssize_t) avail_out);
+}
+
+static inline PyObject *
+OutputBuffer_Finish(_BlocksOutputBuffer *buffer, uint32_t avail_out)
+{
+ return _BlocksOutputBuffer_Finish(buffer, (Py_ssize_t) avail_out);
+}
+
+static inline void
+OutputBuffer_OnError(_BlocksOutputBuffer *buffer)
+{
+ _BlocksOutputBuffer_OnError(buffer);
+}
+
+/* The max buffer size accepted by zlib is UINT32_MAX, the initial buffer size
+ `init_size` may > it in 64-bit build. These wrapper functions maintain an
+ UINT32_MAX sliding window for the first block:
+ 1. OutputBuffer_WindowInitWithSize()
+ 2. OutputBuffer_WindowGrow()
+ 3. OutputBuffer_WindowFinish()
+ 4. OutputBuffer_WindowOnError()
+
+ ==== is the sliding window:
+ 1. ====------
+ ^ next_posi, left_bytes is 6
+ 2. ----====--
+ ^ next_posi, left_bytes is 2
+ 3. --------==
+ ^ next_posi, left_bytes is 0 */
+typedef struct {
+ Py_ssize_t left_bytes;
+ Bytef *next_posi;
+} _Uint32Window;
+
+/* Initialize the buffer with an initial buffer size.
+
+ On success, return value >= 0
+ On failure, return value < 0 */
+static inline Py_ssize_t
+OutputBuffer_WindowInitWithSize(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+ Py_ssize_t init_size,
+ Bytef **next_out, uint32_t *avail_out)
+{
+ Py_ssize_t allocated = _BlocksOutputBuffer_InitWithSize(
+ buffer, init_size, (void**) next_out);
+
+ if (allocated >= 0) {
+ // the UINT32_MAX sliding window
+ Py_ssize_t window_size = Py_MIN((size_t)allocated, UINT32_MAX);
+ *avail_out = (uint32_t) window_size;
+
+ window->left_bytes = allocated - window_size;
+ window->next_posi = *next_out + window_size;
+ }
+ return allocated;
+}
+
+/* Grow the buffer.
+
+ On success, return value >= 0
+ On failure, return value < 0 */
+static inline Py_ssize_t
+OutputBuffer_WindowGrow(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+ Bytef **next_out, uint32_t *avail_out)
+{
+ Py_ssize_t allocated;
+
+ /* ensure no gaps in the data.
+ if inlined, this check could be optimized away.*/
+ if (*avail_out != 0) {
+ PyErr_SetString(PyExc_SystemError,
+ "*avail_out != 0 in OutputBuffer_WindowGrow().");
+ return -1;
+ }
+
+ // slide the UINT32_MAX sliding window
+ if (window->left_bytes > 0) {
+ Py_ssize_t window_size = Py_MIN((size_t)window->left_bytes, UINT32_MAX);
+
+ *next_out = window->next_posi;
+ *avail_out = (uint32_t) window_size;
+
+ window->left_bytes -= window_size;
+ window->next_posi += window_size;
+
+ return window_size;
+ }
+ assert(window->left_bytes == 0);
+
+ // only the first block may > UINT32_MAX
+ allocated = _BlocksOutputBuffer_Grow(
+ buffer, (void**) next_out, (Py_ssize_t) *avail_out);
+ *avail_out = (uint32_t) allocated;
+ return allocated;
+}
+
+/* Finish the buffer.
+
+ On success, return a bytes object
+ On failure, return NULL */
+static inline PyObject *
+OutputBuffer_WindowFinish(_BlocksOutputBuffer *buffer, _Uint32Window *window,
+ uint32_t avail_out)
+{
+ Py_ssize_t real_avail_out = (Py_ssize_t) avail_out + window->left_bytes;
+ return _BlocksOutputBuffer_Finish(buffer, real_avail_out);
+}
+
+static inline void
+OutputBuffer_WindowOnError(_BlocksOutputBuffer *buffer, _Uint32Window *window)
+{
+ _BlocksOutputBuffer_OnError(buffer);
+}
+
+
+#define ENTER_ZLIB(obj) do { \
+ if (!PyThread_acquire_lock((obj)->lock, 0)) { \
+ Py_BEGIN_ALLOW_THREADS \
+ PyThread_acquire_lock((obj)->lock, 1); \
+ Py_END_ALLOW_THREADS \
+ } } while (0)
#define LEAVE_ZLIB(obj) PyThread_release_lock((obj)->lock);
#if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221
@@ -37,18 +192,16 @@ typedef struct {
PyTypeObject *Comptype;
PyTypeObject *Decomptype;
PyObject *ZlibError;
-} _zlibstate;
+} zlibstate;
-static inline _zlibstate*
+static inline zlibstate*
get_zlib_state(PyObject *module)
{
void *state = PyModule_GetState(module);
assert(state != NULL);
- return (_zlibstate *)state;
+ return (zlibstate *)state;
}
-#define _zlibstate_global ((_zlibstate *)PyModule_GetState(PyState_FindModule(&zlibmodule)))
-
typedef struct
{
PyObject_HEAD
@@ -62,7 +215,7 @@ typedef struct
} compobject;
static void
-zlib_error(z_stream zst, int err, const char *msg)
+zlib_error(zlibstate *state, z_stream zst, int err, const char *msg)
{
const char *zmsg = Z_NULL;
/* In case of a version mismatch, zst.msg won't be initialized.
@@ -85,9 +238,9 @@ zlib_error(z_stream zst, int err, const char *msg)
}
}
if (zmsg == Z_NULL)
- PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s", err, msg);
+ PyErr_Format(state->ZlibError, "Error %d %s", err, msg);
else
- PyErr_Format(_zlibstate_global->ZlibError, "Error %d %s: %.200s", err, msg, zmsg);
+ PyErr_Format(state->ZlibError, "Error %d %s: %.200s", err, msg, zmsg);
}
/*[clinic input]
@@ -149,56 +302,6 @@ arrange_input_buffer(z_stream *zst, Py_ssize_t *remains)
*remains -= zst->avail_in;
}
-static Py_ssize_t
-arrange_output_buffer_with_maximum(z_stream *zst, PyObject **buffer,
- Py_ssize_t length,
- Py_ssize_t max_length)
-{
- Py_ssize_t occupied;
-
- if (*buffer == NULL) {
- if (!(*buffer = PyBytes_FromStringAndSize(NULL, length)))
- return -1;
- occupied = 0;
- }
- else {
- occupied = zst->next_out - (Byte *)PyBytes_AS_STRING(*buffer);
-
- if (length == occupied) {
- Py_ssize_t new_length;
- assert(length <= max_length);
- /* can not scale the buffer over max_length */
- if (length == max_length)
- return -2;
- if (length <= (max_length >> 1))
- new_length = length << 1;
- else
- new_length = max_length;
- if (_PyBytes_Resize(buffer, new_length) < 0)
- return -1;
- length = new_length;
- }
- }
-
- zst->avail_out = (uInt)Py_MIN((size_t)(length - occupied), UINT_MAX);
- zst->next_out = (Byte *)PyBytes_AS_STRING(*buffer) + occupied;
-
- return length;
-}
-
-static Py_ssize_t
-arrange_output_buffer(z_stream *zst, PyObject **buffer, Py_ssize_t length)
-{
- Py_ssize_t ret;
-
- ret = arrange_output_buffer_with_maximum(zst, buffer, length,
- PY_SSIZE_T_MAX);
- if (ret == -2)
- PyErr_NoMemory();
-
- return ret;
-}
-
/*[clinic input]
zlib.compress
@@ -215,20 +318,25 @@ static PyObject *
zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
/*[clinic end generated code: output=d80906d73f6294c8 input=638d54b6315dbed3]*/
{
- PyObject *RetVal = NULL;
- Byte *ibuf;
- Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE;
- int err, flush;
+ PyObject *RetVal;
+ int flush;
z_stream zst;
+ _BlocksOutputBuffer buffer = {.list = NULL};
- ibuf = data->buf;
- ibuflen = data->len;
+ zlibstate *state = get_zlib_state(module);
+
+ Byte *ibuf = data->buf;
+ Py_ssize_t ibuflen = data->len;
+
+ if (OutputBuffer_InitAndGrow(&buffer, -1, &zst.next_out, &zst.avail_out) < 0) {
+ goto error;
+ }
zst.opaque = NULL;
zst.zalloc = PyZlib_Malloc;
zst.zfree = PyZlib_Free;
zst.next_in = ibuf;
- err = deflateInit(&zst, level);
+ int err = deflateInit(&zst, level);
switch (err) {
case Z_OK:
@@ -238,11 +346,11 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
"Out of memory while compressing data");
goto error;
case Z_STREAM_ERROR:
- PyErr_SetString(_zlibstate_global->ZlibError, "Bad compression level");
+ PyErr_SetString(state->ZlibError, "Bad compression level");
goto error;
default:
deflateEnd(&zst);
- zlib_error(zst, err, "while compressing data");
+ zlib_error(state, zst, err, "while compressing data");
goto error;
}
@@ -251,10 +359,11 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH;
do {
- obuflen = arrange_output_buffer(&zst, &RetVal, obuflen);
- if (obuflen < 0) {
- deflateEnd(&zst);
- goto error;
+ if (zst.avail_out == 0) {
+ if (OutputBuffer_Grow(&buffer, &zst.next_out, &zst.avail_out) < 0) {
+ deflateEnd(&zst);
+ goto error;
+ }
}
Py_BEGIN_ALLOW_THREADS
@@ -263,7 +372,7 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
if (err == Z_STREAM_ERROR) {
deflateEnd(&zst);
- zlib_error(zst, err, "while compressing data");
+ zlib_error(state, zst, err, "while compressing data");
goto error;
}
@@ -275,49 +384,19 @@ zlib_compress_impl(PyObject *module, Py_buffer *data, int level)
err = deflateEnd(&zst);
if (err == Z_OK) {
- if (_PyBytes_Resize(&RetVal, zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) < 0)
+ RetVal = OutputBuffer_Finish(&buffer, zst.avail_out);
+ if (RetVal == NULL) {
goto error;
+ }
return RetVal;
}
else
- zlib_error(zst, err, "while finishing compression");
+ zlib_error(state, zst, err, "while finishing compression");
error:
- Py_XDECREF(RetVal);
+ OutputBuffer_OnError(&buffer);
return NULL;
}
-/*[python input]
-
-class ssize_t_converter(CConverter):
- type = 'Py_ssize_t'
- converter = 'ssize_t_converter'
- c_ignored_default = "0"
-
-[python start generated code]*/
-/*[python end generated code: output=da39a3ee5e6b4b0d input=5f34ba1b394cb8e7]*/
-
-static int
-ssize_t_converter(PyObject *obj, void *ptr)
-{
- PyObject *long_obj;
- Py_ssize_t val;
-
- /* XXX Should be replaced with PyNumber_AsSsize_t after the end of the
- deprecation period. */
- long_obj = _PyLong_FromNbIndexOrNbInt(obj);
- if (long_obj == NULL) {
- return 0;
- }
- val = PyLong_AsSsize_t(long_obj);
- Py_DECREF(long_obj);
- if (val == -1 && PyErr_Occurred()) {
- return 0;
- }
- *(Py_ssize_t *)ptr = val;
- return 1;
-}
-
/*[clinic input]
zlib.decompress
@@ -326,7 +405,7 @@ zlib.decompress
/
wbits: int(c_default="MAX_WBITS") = MAX_WBITS
The window buffer size and container format.
- bufsize: ssize_t(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
+ bufsize: Py_ssize_t(c_default="DEF_BUF_SIZE") = DEF_BUF_SIZE
The initial output buffer size.
Returns a bytes object containing the uncompressed data.
@@ -335,13 +414,17 @@ Returns a bytes object containing the uncompressed data.
static PyObject *
zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
Py_ssize_t bufsize)
-/*[clinic end generated code: output=77c7e35111dc8c42 input=21960936208e9a5b]*/
+/*[clinic end generated code: output=77c7e35111dc8c42 input=a9ac17beff1f893f]*/
{
- PyObject *RetVal = NULL;
+ PyObject *RetVal;
Byte *ibuf;
Py_ssize_t ibuflen;
int err, flush;
z_stream zst;
+ _BlocksOutputBuffer buffer = {.list = NULL};
+ _Uint32Window window; // output buffer's UINT32_MAX sliding window
+
+ zlibstate *state = get_zlib_state(module);
if (bufsize < 0) {
PyErr_SetString(PyExc_ValueError, "bufsize must be non-negative");
@@ -350,6 +433,11 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
bufsize = 1;
}
+ if (OutputBuffer_WindowInitWithSize(&buffer, &window, bufsize,
+ &zst.next_out, &zst.avail_out) < 0) {
+ goto error;
+ }
+
ibuf = data->buf;
ibuflen = data->len;
@@ -369,7 +457,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
goto error;
default:
inflateEnd(&zst);
- zlib_error(zst, err, "while preparing to decompress data");
+ zlib_error(state, zst, err, "while preparing to decompress data");
goto error;
}
@@ -378,10 +466,12 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH;
do {
- bufsize = arrange_output_buffer(&zst, &RetVal, bufsize);
- if (bufsize < 0) {
- inflateEnd(&zst);
- goto error;
+ if (zst.avail_out == 0) {
+ if (OutputBuffer_WindowGrow(&buffer, &window,
+ &zst.next_out, &zst.avail_out) < 0) {
+ inflateEnd(&zst);
+ goto error;
+ }
}
Py_BEGIN_ALLOW_THREADS
@@ -400,7 +490,7 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
goto error;
default:
inflateEnd(&zst);
- zlib_error(zst, err, "while decompressing data");
+ zlib_error(state, zst, err, "while decompressing data");
goto error;
}
@@ -411,24 +501,23 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
if (err != Z_STREAM_END) {
inflateEnd(&zst);
- zlib_error(zst, err, "while decompressing data");
+ zlib_error(state, zst, err, "while decompressing data");
goto error;
}
err = inflateEnd(&zst);
if (err != Z_OK) {
- zlib_error(zst, err, "while finishing decompression");
+ zlib_error(state, zst, err, "while finishing decompression");
goto error;
}
- if (_PyBytes_Resize(&RetVal, zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) < 0)
- goto error;
-
- return RetVal;
+ RetVal = OutputBuffer_WindowFinish(&buffer, &window, zst.avail_out);
+ if (RetVal != NULL) {
+ return RetVal;
+ }
error:
- Py_XDECREF(RetVal);
+ OutputBuffer_WindowOnError(&buffer, &window);
return NULL;
}
@@ -465,16 +554,14 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits,
int memLevel, int strategy, Py_buffer *zdict)
/*[clinic end generated code: output=8b5bed9c8fc3814d input=2fa3d026f90ab8d5]*/
{
- compobject *self = NULL;
- int err;
-
+ zlibstate *state = get_zlib_state(module);
if (zdict->buf != NULL && (size_t)zdict->len > UINT_MAX) {
PyErr_SetString(PyExc_OverflowError,
"zdict length does not fit in an unsigned int");
- goto error;
+ return NULL;
}
- self = newcompobject(_zlibstate_global->Comptype);
+ compobject *self = newcompobject(state->Comptype);
if (self == NULL)
goto error;
self->zst.opaque = NULL;
@@ -482,7 +569,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits,
self->zst.zfree = PyZlib_Free;
self->zst.next_in = NULL;
self->zst.avail_in = 0;
- err = deflateInit2(&self->zst, level, method, wbits, memLevel, strategy);
+ int err = deflateInit2(&self->zst, level, method, wbits, memLevel, strategy);
switch (err) {
case Z_OK:
self->is_initialised = 1;
@@ -510,7 +597,7 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits,
PyErr_SetString(PyExc_ValueError, "Invalid initialization option");
goto error;
default:
- zlib_error(self->zst, err, "while creating compression object");
+ zlib_error(state, self->zst, err, "while creating compression object");
goto error;
}
@@ -521,11 +608,9 @@ zlib_compressobj_impl(PyObject *module, int level, int method, int wbits,
}
static int
-set_inflate_zdict(compobject *self)
+set_inflate_zdict(zlibstate *state, compobject *self)
{
Py_buffer zdict_buf;
- int err;
-
if (PyObject_GetBuffer(self->zdict, &zdict_buf, PyBUF_SIMPLE) == -1) {
return -1;
}
@@ -535,11 +620,12 @@ set_inflate_zdict(compobject *self)
PyBuffer_Release(&zdict_buf);
return -1;
}
+ int err;
err = inflateSetDictionary(&self->zst,
zdict_buf.buf, (unsigned int)zdict_buf.len);
PyBuffer_Release(&zdict_buf);
if (err != Z_OK) {
- zlib_error(self->zst, err, "while setting zdict");
+ zlib_error(state, self->zst, err, "while setting zdict");
return -1;
}
return 0;
@@ -561,8 +647,7 @@ static PyObject *
zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
/*[clinic end generated code: output=3069b99994f36906 input=d3832b8511fc977b]*/
{
- int err;
- compobject *self;
+ zlibstate *state = get_zlib_state(module);
if (zdict != NULL && !PyObject_CheckBuffer(zdict)) {
PyErr_SetString(PyExc_TypeError,
@@ -570,7 +655,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
return NULL;
}
- self = newcompobject(_zlibstate_global->Decomptype);
+ compobject *self = newcompobject(state->Decomptype);
if (self == NULL)
return NULL;
self->zst.opaque = NULL;
@@ -582,18 +667,18 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
Py_INCREF(zdict);
self->zdict = zdict;
}
- err = inflateInit2(&self->zst, wbits);
+ int err = inflateInit2(&self->zst, wbits);
switch (err) {
case Z_OK:
self->is_initialised = 1;
if (self->zdict != NULL && wbits < 0) {
#ifdef AT_LEAST_ZLIB_1_2_2_1
- if (set_inflate_zdict(self) < 0) {
+ if (set_inflate_zdict(state, self) < 0) {
Py_DECREF(self);
return NULL;
}
#else
- PyErr_Format(_zlibstate_global->ZlibError,
+ PyErr_Format(state->ZlibError,
"zlib version %s does not allow raw inflate with dictionary",
ZLIB_VERSION);
Py_DECREF(self);
@@ -611,7 +696,7 @@ zlib_decompressobj_impl(PyObject *module, int wbits, PyObject *zdict)
"Can't allocate memory for decompression object");
return NULL;
default:
- zlib_error(self->zst, err, "while creating decompression object");
+ zlib_error(state, self->zst, err, "while creating decompression object");
Py_DECREF(self);
return NULL;
}
@@ -625,7 +710,7 @@ Dealloc(compobject *self)
Py_XDECREF(self->unused_data);
Py_XDECREF(self->unconsumed_tail);
Py_XDECREF(self->zdict);
- PyObject_Del(self);
+ PyObject_Free(self);
Py_DECREF(type);
}
@@ -648,6 +733,7 @@ Decomp_dealloc(compobject *self)
/*[clinic input]
zlib.Compress.compress
+ cls: defining_class
data: Py_buffer
Binary data to be compressed.
/
@@ -660,32 +746,40 @@ Call the flush() method to clear these buffers.
[clinic start generated code]*/
static PyObject *
-zlib_Compress_compress_impl(compobject *self, Py_buffer *data)
-/*[clinic end generated code: output=5d5cd791cbc6a7f4 input=0d95908d6e64fab8]*/
+zlib_Compress_compress_impl(compobject *self, PyTypeObject *cls,
+ Py_buffer *data)
+/*[clinic end generated code: output=6731b3f0ff357ca6 input=04d00f65ab01d260]*/
{
- PyObject *RetVal = NULL;
- Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE;
+ PyObject *RetVal;
int err;
+ _BlocksOutputBuffer buffer = {.list = NULL};
+ zlibstate *state = PyType_GetModuleState(cls);
ENTER_ZLIB(self);
self->zst.next_in = data->buf;
- ibuflen = data->len;
+ Py_ssize_t ibuflen = data->len;
+
+ if (OutputBuffer_InitAndGrow(&buffer, -1, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto error;
+ }
do {
arrange_input_buffer(&self->zst, &ibuflen);
do {
- obuflen = arrange_output_buffer(&self->zst, &RetVal, obuflen);
- if (obuflen < 0)
- goto error;
+ if (self->zst.avail_out == 0) {
+ if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto error;
+ }
+ }
Py_BEGIN_ALLOW_THREADS
err = deflate(&self->zst, Z_NO_FLUSH);
Py_END_ALLOW_THREADS
if (err == Z_STREAM_ERROR) {
- zlib_error(self->zst, err, "while compressing data");
+ zlib_error(state, self->zst, err, "while compressing data");
goto error;
}
@@ -694,12 +788,14 @@ zlib_Compress_compress_impl(compobject *self, Py_buffer *data)
} while (ibuflen != 0);
- if (_PyBytes_Resize(&RetVal, self->zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) == 0)
+ RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out);
+ if (RetVal != NULL) {
goto success;
+ }
error:
- Py_CLEAR(RetVal);
+ OutputBuffer_OnError(&buffer);
+ RetVal = NULL;
success:
LEAVE_ZLIB(self);
return RetVal;
@@ -753,10 +849,11 @@ save_unconsumed_input(compobject *self, Py_buffer *data, int err)
/*[clinic input]
zlib.Decompress.decompress
+ cls: defining_class
data: Py_buffer
The binary data to decompress.
/
- max_length: ssize_t = 0
+ max_length: Py_ssize_t = 0
The maximum allowable length of the decompressed data.
Unconsumed input data will be stored in
the unconsumed_tail attribute.
@@ -769,45 +866,47 @@ Call the flush() method to clear these buffers.
[clinic start generated code]*/
static PyObject *
-zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
- Py_ssize_t max_length)
-/*[clinic end generated code: output=6e5173c74e710352 input=b85a212a012b770a]*/
+zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls,
+ Py_buffer *data, Py_ssize_t max_length)
+/*[clinic end generated code: output=b024a93c2c922d57 input=bfb37b3864cfb606]*/
{
int err = Z_OK;
- Py_ssize_t ibuflen, obuflen = DEF_BUF_SIZE, hard_limit;
- PyObject *RetVal = NULL;
+ Py_ssize_t ibuflen;
+ PyObject *RetVal;
+ _BlocksOutputBuffer buffer = {.list = NULL};
+
+ PyObject *module = PyType_GetModule(cls);
+ if (module == NULL)
+ return NULL;
+ zlibstate *state = get_zlib_state(module);
if (max_length < 0) {
PyErr_SetString(PyExc_ValueError, "max_length must be non-negative");
return NULL;
- } else if (max_length == 0)
- hard_limit = PY_SSIZE_T_MAX;
- else
- hard_limit = max_length;
+ } else if (max_length == 0) {
+ max_length = -1;
+ }
ENTER_ZLIB(self);
self->zst.next_in = data->buf;
ibuflen = data->len;
- /* limit amount of data allocated to max_length */
- if (max_length && obuflen > max_length)
- obuflen = max_length;
+ if (OutputBuffer_InitAndGrow(&buffer, max_length, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto abort;
+ }
do {
arrange_input_buffer(&self->zst, &ibuflen);
do {
- obuflen = arrange_output_buffer_with_maximum(&self->zst, &RetVal,
- obuflen, hard_limit);
- if (obuflen == -2) {
- if (max_length > 0) {
+ if (self->zst.avail_out == 0) {
+ if (OutputBuffer_GetDataSize(&buffer, self->zst.avail_out) == max_length) {
goto save;
}
- PyErr_NoMemory();
- }
- if (obuflen < 0) {
- goto abort;
+ if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto abort;
+ }
}
Py_BEGIN_ALLOW_THREADS
@@ -821,8 +920,9 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
break;
default:
if (err == Z_NEED_DICT && self->zdict != NULL) {
- if (set_inflate_zdict(self) < 0)
+ if (set_inflate_zdict(state, self) < 0) {
goto abort;
+ }
else
break;
}
@@ -846,16 +946,18 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
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(state, self->zst, err, "while decompressing data");
goto abort;
}
- if (_PyBytes_Resize(&RetVal, self->zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) == 0)
+ RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out);
+ if (RetVal != NULL) {
goto success;
+ }
abort:
- Py_CLEAR(RetVal);
+ OutputBuffer_OnError(&buffer);
+ RetVal = NULL;
success:
LEAVE_ZLIB(self);
return RetVal;
@@ -864,6 +966,7 @@ zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
/*[clinic input]
zlib.Compress.flush
+ cls: defining_class
mode: int(c_default="Z_FINISH") = zlib.Z_FINISH
One of the constants Z_SYNC_FLUSH, Z_FULL_FLUSH, Z_FINISH.
If mode == Z_FINISH, the compressor object can no longer be
@@ -875,13 +978,14 @@ Return a bytes object containing any remaining compressed data.
[clinic start generated code]*/
static PyObject *
-zlib_Compress_flush_impl(compobject *self, int mode)
-/*[clinic end generated code: output=a203f4cefc9de727 input=73ed066794bd15bc]*/
+zlib_Compress_flush_impl(compobject *self, PyTypeObject *cls, int mode)
+/*[clinic end generated code: output=c7efd13efd62add2 input=286146e29442eb6c]*/
{
int err;
- Py_ssize_t length = DEF_BUF_SIZE;
- PyObject *RetVal = NULL;
+ PyObject *RetVal;
+ _BlocksOutputBuffer buffer = {.list = NULL};
+ zlibstate *state = PyType_GetModuleState(cls);
/* 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 (mode == Z_NO_FLUSH) {
@@ -892,11 +996,15 @@ zlib_Compress_flush_impl(compobject *self, int mode)
self->zst.avail_in = 0;
+ if (OutputBuffer_InitAndGrow(&buffer, -1, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto error;
+ }
+
do {
- length = arrange_output_buffer(&self->zst, &RetVal, length);
- if (length < 0) {
- Py_CLEAR(RetVal);
- goto error;
+ if (self->zst.avail_out == 0) {
+ if (OutputBuffer_Grow(&buffer, &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto error;
+ }
}
Py_BEGIN_ALLOW_THREADS
@@ -904,8 +1012,7 @@ zlib_Compress_flush_impl(compobject *self, int mode)
Py_END_ALLOW_THREADS
if (err == Z_STREAM_ERROR) {
- zlib_error(self->zst, err, "while flushing");
- Py_CLEAR(RetVal);
+ zlib_error(state, self->zst, err, "while flushing");
goto error;
}
} while (self->zst.avail_out == 0);
@@ -917,8 +1024,7 @@ zlib_Compress_flush_impl(compobject *self, int mode)
if (err == Z_STREAM_END && mode == Z_FINISH) {
err = deflateEnd(&self->zst);
if (err != Z_OK) {
- zlib_error(self->zst, err, "while finishing compression");
- Py_CLEAR(RetVal);
+ zlib_error(state, self->zst, err, "while finishing compression");
goto error;
}
else
@@ -929,16 +1035,19 @@ zlib_Compress_flush_impl(compobject *self, int mode)
not an error condition.
*/
} else if (err != Z_OK && err != Z_BUF_ERROR) {
- zlib_error(self->zst, err, "while flushing");
- Py_CLEAR(RetVal);
+ zlib_error(state, self->zst, err, "while flushing");
goto error;
}
- if (_PyBytes_Resize(&RetVal, self->zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) < 0)
- Py_CLEAR(RetVal);
+ RetVal = OutputBuffer_Finish(&buffer, self->zst.avail_out);
+ if (RetVal != NULL) {
+ goto success;
+ }
- error:
+error:
+ OutputBuffer_OnError(&buffer);
+ RetVal = NULL;
+success:
LEAVE_ZLIB(self);
return RetVal;
}
@@ -948,24 +1057,25 @@ zlib_Compress_flush_impl(compobject *self, int mode)
/*[clinic input]
zlib.Compress.copy
+ cls: defining_class
+
Return a copy of the compression object.
[clinic start generated code]*/
static PyObject *
-zlib_Compress_copy_impl(compobject *self)
-/*[clinic end generated code: output=5144aa153c21e805 input=c656351f94b82718]*/
+zlib_Compress_copy_impl(compobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=c4d2cfb4b0d7350b input=235497e482d40986]*/
{
- compobject *retval = NULL;
- int err;
+ zlibstate *state = PyType_GetModuleState(cls);
- retval = newcompobject(_zlibstate_global->Comptype);
+ compobject *retval = newcompobject(state->Comptype);
if (!retval) return NULL;
/* Copy the zstream state
* We use ENTER_ZLIB / LEAVE_ZLIB to make this thread-safe
*/
ENTER_ZLIB(self);
- err = deflateCopy(&retval->zst, &self->zst);
+ int err = deflateCopy(&retval->zst, &self->zst);
switch (err) {
case Z_OK:
break;
@@ -977,7 +1087,7 @@ zlib_Compress_copy_impl(compobject *self)
"Can't allocate memory for compression object");
goto error;
default:
- zlib_error(self->zst, err, "while copying compression object");
+ zlib_error(state, self->zst, err, "while copying compression object");
goto error;
}
Py_INCREF(self->unused_data);
@@ -1002,51 +1112,57 @@ error:
/*[clinic input]
zlib.Compress.__copy__
+
+ cls: defining_class
+
[clinic start generated code]*/
static PyObject *
-zlib_Compress___copy___impl(compobject *self)
-/*[clinic end generated code: output=1875e6791975442e input=be97a05a788dfd83]*/
+zlib_Compress___copy___impl(compobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=074613db332cb668 input=5c0188367ab0fe64]*/
{
- return zlib_Compress_copy_impl(self);
+ return zlib_Compress_copy_impl(self, cls);
}
/*[clinic input]
zlib.Compress.__deepcopy__
+ cls: defining_class
memo: object
/
[clinic start generated code]*/
static PyObject *
-zlib_Compress___deepcopy__(compobject *self, PyObject *memo)
-/*[clinic end generated code: output=f47a2213282c9eb0 input=a9a8b0b40d83388e]*/
+zlib_Compress___deepcopy___impl(compobject *self, PyTypeObject *cls,
+ PyObject *memo)
+/*[clinic end generated code: output=24b3aed785f54033 input=c90347319a514430]*/
{
- return zlib_Compress_copy_impl(self);
+ return zlib_Compress_copy_impl(self, cls);
}
/*[clinic input]
zlib.Decompress.copy
+ cls: defining_class
+
Return a copy of the decompression object.
[clinic start generated code]*/
static PyObject *
-zlib_Decompress_copy_impl(compobject *self)
-/*[clinic end generated code: output=02a883a2a510c8cc input=ba6c3e96712a596b]*/
+zlib_Decompress_copy_impl(compobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=a7ddc016e1d0a781 input=20ef3aa208282ff2]*/
{
- compobject *retval = NULL;
- int err;
+ zlibstate *state = PyType_GetModuleState(cls);
- retval = newcompobject(_zlibstate_global->Decomptype);
+ compobject *retval = newcompobject(state->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);
+ int err = inflateCopy(&retval->zst, &self->zst);
switch (err) {
case Z_OK:
break;
@@ -1058,7 +1174,7 @@ zlib_Decompress_copy_impl(compobject *self)
"Can't allocate memory for decompression object");
goto error;
default:
- zlib_error(self->zst, err, "while copying decompression object");
+ zlib_error(state, self->zst, err, "while copying decompression object");
goto error;
}
@@ -1084,28 +1200,33 @@ error:
/*[clinic input]
zlib.Decompress.__copy__
+
+ cls: defining_class
+
[clinic start generated code]*/
static PyObject *
-zlib_Decompress___copy___impl(compobject *self)
-/*[clinic end generated code: output=80bae8bc43498ad4 input=efcb98b5472c13d2]*/
+zlib_Decompress___copy___impl(compobject *self, PyTypeObject *cls)
+/*[clinic end generated code: output=cf1e6473744f53fa input=cc3143067b622bdf]*/
{
- return zlib_Decompress_copy_impl(self);
+ return zlib_Decompress_copy_impl(self, cls);
}
/*[clinic input]
zlib.Decompress.__deepcopy__
+ cls: defining_class
memo: object
/
[clinic start generated code]*/
static PyObject *
-zlib_Decompress___deepcopy__(compobject *self, PyObject *memo)
-/*[clinic end generated code: output=1f77286ab490124b input=6e99bd0ac4b9cd8b]*/
+zlib_Decompress___deepcopy___impl(compobject *self, PyTypeObject *cls,
+ PyObject *memo)
+/*[clinic end generated code: output=34f7b719a0c0d51b input=fc13b9c58622544e]*/
{
- return zlib_Decompress_copy_impl(self);
+ return zlib_Decompress_copy_impl(self, cls);
}
#endif
@@ -1113,7 +1234,8 @@ zlib_Decompress___deepcopy__(compobject *self, PyObject *memo)
/*[clinic input]
zlib.Decompress.flush
- length: ssize_t(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE
+ cls: defining_class
+ length: Py_ssize_t(c_default="DEF_BUF_SIZE") = zlib.DEF_BUF_SIZE
the initial size of the output buffer.
/
@@ -1121,13 +1243,23 @@ Return a bytes object containing any remaining decompressed data.
[clinic start generated code]*/
static PyObject *
-zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length)
-/*[clinic end generated code: output=68c75ea127cbe654 input=aa4ec37f3aef4da0]*/
+zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls,
+ Py_ssize_t length)
+/*[clinic end generated code: output=4532fc280bd0f8f2 input=42f1f4b75230e2cd]*/
{
int err, flush;
Py_buffer data;
- PyObject *RetVal = NULL;
+ PyObject *RetVal;
Py_ssize_t ibuflen;
+ _BlocksOutputBuffer buffer = {.list = NULL};
+ _Uint32Window window; // output buffer's UINT32_MAX sliding window
+
+ PyObject *module = PyType_GetModule(cls);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ zlibstate *state = get_zlib_state(module);
if (length <= 0) {
PyErr_SetString(PyExc_ValueError, "length must be greater than zero");
@@ -1144,14 +1276,22 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length)
self->zst.next_in = data.buf;
ibuflen = data.len;
+ if (OutputBuffer_WindowInitWithSize(&buffer, &window, length,
+ &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto abort;
+ }
+
do {
arrange_input_buffer(&self->zst, &ibuflen);
flush = ibuflen == 0 ? Z_FINISH : Z_NO_FLUSH;
do {
- length = arrange_output_buffer(&self->zst, &RetVal, length);
- if (length < 0)
- goto abort;
+ if (self->zst.avail_out == 0) {
+ if (OutputBuffer_WindowGrow(&buffer, &window,
+ &self->zst.next_out, &self->zst.avail_out) < 0) {
+ goto abort;
+ }
+ }
Py_BEGIN_ALLOW_THREADS
err = inflate(&self->zst, flush);
@@ -1164,8 +1304,9 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length)
break;
default:
if (err == Z_NEED_DICT && self->zdict != NULL) {
- if (set_inflate_zdict(self) < 0)
+ if (set_inflate_zdict(state, self) < 0) {
goto abort;
+ }
else
break;
}
@@ -1177,8 +1318,9 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length)
} while (err != Z_STREAM_END && ibuflen != 0);
save:
- if (save_unconsumed_input(self, &data, err) < 0)
+ if (save_unconsumed_input(self, &data, err) < 0) {
goto abort;
+ }
/* If at end of stream, clean up any memory allocated by zlib. */
if (err == Z_STREAM_END) {
@@ -1186,17 +1328,19 @@ zlib_Decompress_flush_impl(compobject *self, Py_ssize_t length)
self->is_initialised = 0;
err = inflateEnd(&self->zst);
if (err != Z_OK) {
- zlib_error(self->zst, err, "while finishing decompression");
+ zlib_error(state, self->zst, err, "while finishing decompression");
goto abort;
}
}
- if (_PyBytes_Resize(&RetVal, self->zst.next_out -
- (Byte *)PyBytes_AS_STRING(RetVal)) == 0)
+ RetVal = OutputBuffer_WindowFinish(&buffer, &window, self->zst.avail_out);
+ if (RetVal != NULL) {
goto success;
+ }
abort:
- Py_CLEAR(RetVal);
+ OutputBuffer_WindowOnError(&buffer, &window);
+ RetVal = NULL;
success:
PyBuffer_Release(&data);
LEAVE_ZLIB(self);
@@ -1332,11 +1476,10 @@ static PyType_Slot Comptype_slots[] = {
};
static PyType_Spec Comptype_spec = {
- "zlib.Compress",
- sizeof(compobject),
- 0,
- Py_TPFLAGS_DEFAULT,
- Comptype_slots
+ .name = "zlib.Compress",
+ .basicsize = sizeof(compobject),
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
+ .slots= Comptype_slots,
};
static PyType_Slot Decomptype_slots[] = {
@@ -1347,11 +1490,10 @@ static PyType_Slot Decomptype_slots[] = {
};
static PyType_Spec Decomptype_spec = {
- "zlib.Decompress",
- sizeof(compobject),
- 0,
- Py_TPFLAGS_DEFAULT,
- Decomptype_slots
+ .name = "zlib.Decompress",
+ .basicsize = sizeof(compobject),
+ .flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_DISALLOW_INSTANTIATION,
+ .slots = Decomptype_slots,
};
PyDoc_STRVAR(zlib_module_documentation,
@@ -1370,9 +1512,9 @@ PyDoc_STRVAR(zlib_module_documentation,
"objects support decompress() and flush().");
static int
-zlib_clear(PyObject *m)
+zlib_clear(PyObject *mod)
{
- _zlibstate *state = get_zlib_state(m);
+ zlibstate *state = get_zlib_state(mod);
Py_CLEAR(state->Comptype);
Py_CLEAR(state->Decomptype);
Py_CLEAR(state->ZlibError);
@@ -1380,9 +1522,9 @@ zlib_clear(PyObject *m)
}
static int
-zlib_traverse(PyObject *m, visitproc visit, void *arg)
+zlib_traverse(PyObject *mod, visitproc visit, void *arg)
{
- _zlibstate *state = get_zlib_state(m);
+ zlibstate *state = get_zlib_state(mod);
Py_VISIT(state->Comptype);
Py_VISIT(state->Decomptype);
Py_VISIT(state->ZlibError);
@@ -1390,93 +1532,122 @@ zlib_traverse(PyObject *m, visitproc visit, void *arg)
}
static void
-zlib_free(void *m)
+zlib_free(void *mod)
{
- zlib_clear((PyObject *)m);
+ zlib_clear((PyObject *)mod);
}
-static struct PyModuleDef zlibmodule = {
- PyModuleDef_HEAD_INIT,
- "zlib",
- zlib_module_documentation,
- sizeof(_zlibstate),
- zlib_methods,
- NULL,
- zlib_traverse,
- zlib_clear,
- zlib_free,
-};
-
-PyMODINIT_FUNC
-PyInit_zlib(void)
+static int
+zlib_exec(PyObject *mod)
{
- PyObject *m, *ver;
- m = PyState_FindModule(&zlibmodule);
- if (m != NULL) {
- Py_INCREF(m);
- return m;
+ zlibstate *state = get_zlib_state(mod);
+
+ state->Comptype = (PyTypeObject *)PyType_FromModuleAndSpec(
+ mod, &Comptype_spec, NULL);
+ if (state->Comptype == NULL) {
+ return -1;
}
- m = PyModule_Create(&zlibmodule);
- if (m == NULL)
- return NULL;
- PyTypeObject *Comptype = (PyTypeObject *)PyType_FromSpec(&Comptype_spec);
- if (Comptype == NULL)
- return NULL;
- get_zlib_state(m)->Comptype = Comptype;
+ state->Decomptype = (PyTypeObject *)PyType_FromModuleAndSpec(
+ mod, &Decomptype_spec, NULL);
+ if (state->Decomptype == NULL) {
+ return -1;
+ }
- PyTypeObject *Decomptype = (PyTypeObject *)PyType_FromSpec(&Decomptype_spec);
- if (Decomptype == NULL)
- return NULL;
- get_zlib_state(m)->Decomptype = Decomptype;
+ state->ZlibError = PyErr_NewException("zlib.error", NULL, NULL);
+ if (state->ZlibError == NULL) {
+ return -1;
+ }
- PyObject *ZlibError = PyErr_NewException("zlib.error", NULL, NULL);
- if (ZlibError != NULL) {
- Py_INCREF(ZlibError);
- PyModule_AddObject(m, "error", ZlibError);
- get_zlib_state(m)->ZlibError = ZlibError;
+ Py_INCREF(state->ZlibError);
+ if (PyModule_AddObject(mod, "error", state->ZlibError) < 0) {
+ Py_DECREF(state->ZlibError);
+ return -1;
}
- PyModule_AddIntMacro(m, MAX_WBITS);
- PyModule_AddIntMacro(m, DEFLATED);
- PyModule_AddIntMacro(m, DEF_MEM_LEVEL);
- PyModule_AddIntMacro(m, DEF_BUF_SIZE);
+
+#define ZLIB_ADD_INT_MACRO(c) \
+ do { \
+ if ((PyModule_AddIntConstant(mod, #c, c)) < 0) { \
+ return -1; \
+ } \
+ } while(0)
+
+ ZLIB_ADD_INT_MACRO(MAX_WBITS);
+ ZLIB_ADD_INT_MACRO(DEFLATED);
+ ZLIB_ADD_INT_MACRO(DEF_MEM_LEVEL);
+ ZLIB_ADD_INT_MACRO(DEF_BUF_SIZE);
// compression levels
- PyModule_AddIntMacro(m, Z_NO_COMPRESSION);
- PyModule_AddIntMacro(m, Z_BEST_SPEED);
- PyModule_AddIntMacro(m, Z_BEST_COMPRESSION);
- PyModule_AddIntMacro(m, Z_DEFAULT_COMPRESSION);
+ ZLIB_ADD_INT_MACRO(Z_NO_COMPRESSION);
+ ZLIB_ADD_INT_MACRO(Z_BEST_SPEED);
+ ZLIB_ADD_INT_MACRO(Z_BEST_COMPRESSION);
+ ZLIB_ADD_INT_MACRO(Z_DEFAULT_COMPRESSION);
// compression strategies
- PyModule_AddIntMacro(m, Z_FILTERED);
- PyModule_AddIntMacro(m, Z_HUFFMAN_ONLY);
+ ZLIB_ADD_INT_MACRO(Z_FILTERED);
+ ZLIB_ADD_INT_MACRO(Z_HUFFMAN_ONLY);
#ifdef Z_RLE // 1.2.0.1
- PyModule_AddIntMacro(m, Z_RLE);
+ ZLIB_ADD_INT_MACRO(Z_RLE);
#endif
#ifdef Z_FIXED // 1.2.2.2
- PyModule_AddIntMacro(m, Z_FIXED);
+ ZLIB_ADD_INT_MACRO(Z_FIXED);
#endif
- PyModule_AddIntMacro(m, Z_DEFAULT_STRATEGY);
+ ZLIB_ADD_INT_MACRO(Z_DEFAULT_STRATEGY);
// allowed flush values
- PyModule_AddIntMacro(m, Z_NO_FLUSH);
- PyModule_AddIntMacro(m, Z_PARTIAL_FLUSH);
- PyModule_AddIntMacro(m, Z_SYNC_FLUSH);
- PyModule_AddIntMacro(m, Z_FULL_FLUSH);
- PyModule_AddIntMacro(m, Z_FINISH);
+ ZLIB_ADD_INT_MACRO(Z_NO_FLUSH);
+ ZLIB_ADD_INT_MACRO(Z_PARTIAL_FLUSH);
+ ZLIB_ADD_INT_MACRO(Z_SYNC_FLUSH);
+ ZLIB_ADD_INT_MACRO(Z_FULL_FLUSH);
+ ZLIB_ADD_INT_MACRO(Z_FINISH);
#ifdef Z_BLOCK // 1.2.0.5 for inflate, 1.2.3.4 for deflate
- PyModule_AddIntMacro(m, Z_BLOCK);
+ ZLIB_ADD_INT_MACRO(Z_BLOCK);
#endif
#ifdef Z_TREES // 1.2.3.4, only for inflate
- PyModule_AddIntMacro(m, Z_TREES);
+ ZLIB_ADD_INT_MACRO(Z_TREES);
#endif
- ver = PyUnicode_FromString(ZLIB_VERSION);
- if (ver != NULL)
- PyModule_AddObject(m, "ZLIB_VERSION", ver);
+ PyObject *ver = PyUnicode_FromString(ZLIB_VERSION);
+ if (ver == NULL) {
+ return -1;
+ }
+
+ if (PyModule_AddObject(mod, "ZLIB_VERSION", ver) < 0) {
+ Py_DECREF(ver);
+ return -1;
+ }
ver = PyUnicode_FromString(zlibVersion());
- if (ver != NULL)
- PyModule_AddObject(m, "ZLIB_RUNTIME_VERSION", ver);
+ if (ver == NULL) {
+ return -1;
+ }
+
+ if (PyModule_AddObject(mod, "ZLIB_RUNTIME_VERSION", ver) < 0) {
+ Py_DECREF(ver);
+ return -1;
+ }
- PyModule_AddStringConstant(m, "__version__", "1.0");
+ if (PyModule_AddStringConstant(mod, "__version__", "1.0") < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static PyModuleDef_Slot zlib_slots[] = {
+ {Py_mod_exec, zlib_exec},
+ {0, NULL}
+};
- PyState_AddModule(m, &zlibmodule);
- return m;
+static struct PyModuleDef zlibmodule = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "zlib",
+ .m_doc = zlib_module_documentation,
+ .m_size = sizeof(zlibstate),
+ .m_methods = zlib_methods,
+ .m_slots = zlib_slots,
+ .m_traverse = zlib_traverse,
+ .m_clear = zlib_clear,
+ .m_free = zlib_free,
+};
+
+PyMODINIT_FUNC
+PyInit_zlib(void)
+{
+ return PyModuleDef_Init(&zlibmodule);
}