Skip to main content

Modules/zlibmodule.c

Source:

cpython 3.14 @ ab2d84fe1023/Modules/zlibmodule.c

zlib wraps the zlib C library for deflate compression. It provides one-shot functions and stream objects for incremental compression.

Map

LinesSymbolRole
1-100ConstantsDEFLATED, Z_BEST_SPEED, Z_BEST_COMPRESSION, Z_DEFAULT_COMPRESSION
101-300zlib_compressOne-shot compress: zlib.compress(data, level)
301-500zlib_decompressOne-shot decompress with wbits and buffer size
501-700Compress typeStreaming compressobj — deflate incrementally
701-900Decompress typeStreaming decompressobj — inflate incrementally
901-1100compress_compress, compress_flushFeed data, flush remaining
1101-1300decompress_decompress, decompress_flushFeed compressed data
1301-1400zlib_crc32, zlib_adler32Checksums

Reading

One-shot compress

// CPython: Modules/zlibmodule.c:140 zlib_compress_impl
static PyObject *
zlib_compress_impl(PyObject *module, Py_buffer *data, int level, int wbits)
{
z_stream zst;
zst.zalloc = Z_NULL;
zst.zfree = Z_NULL;
zst.opaque = Z_NULL;
deflateInit2(&zst, level, Z_DEFLATED, wbits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
zst.avail_in = data->len;
zst.next_in = data->buf;
/* Allocate output buffer: worst-case bound from deflateBound() */
Py_ssize_t obuflen = deflateBound(&zst, data->len);
...
deflate(&zst, Z_FINISH);
deflateEnd(&zst);
return PyBytes_FromStringAndSize(obuf, zst.total_out);
}

Stream compression

// CPython: Modules/zlibmodule.c:620 zlib_Compress_compress_impl
static PyObject *
zlib_Compress_compress_impl(compobject *self, Py_buffer *data)
{
self->zst.avail_in = data->len;
self->zst.next_in = data->buf;
do {
/* Grow output buffer as needed */
arrange_input_buffer(&self->zst, &ibuflen);
err = deflate(&self->zst, Z_NO_FLUSH);
...
} while (self->zst.avail_in != 0);
return PyBytes_FromStringAndSize(retbuf, output_len);
}

// CPython: Modules/zlibmodule.c:680 zlib_Compress_flush_impl
static PyObject *
zlib_Compress_flush_impl(compobject *self, int mode)
{
do {
err = deflate(&self->zst, mode); /* Z_FINISH or Z_SYNC_FLUSH */
...
} while (err != Z_STREAM_END);
deflateEnd(&self->zst);
return PyBytes_FromStringAndSize(retbuf, output_len);
}

Decompress with unconsumed tail

// CPython: Modules/zlibmodule.c:820 zlib_Decompress_decompress_impl
static PyObject *
zlib_Decompress_decompress_impl(compobject *self, Py_buffer *data,
Py_ssize_t max_length)
{
self->zst.avail_in = data->len;
self->zst.next_in = data->buf;
do {
err = inflate(&self->zst, Z_SYNC_FLUSH);
if (err == Z_STREAM_END) {
/* Store remaining unconsumed bytes */
self->unconsumed_tail = PyBytes_FromStringAndSize(
(char *)self->zst.next_in, self->zst.avail_in);
break;
}
...
} while (self->zst.avail_out == 0);
return retval;
}

decompressobj.unconsumed_tail holds bytes after Z_STREAM_END — useful when a zlib stream is embedded in a larger byte sequence.

crc32

// CPython: Modules/zlibmodule.c:1320 zlib_crc32_impl
static PyObject *
zlib_crc32_impl(PyObject *module, Py_buffer *data, unsigned int value)
{
unsigned long crc = crc32(value, data->buf, data->len);
return PyLong_FromUnsignedLong(crc & 0xffffffff);
}

Always returns an unsigned 32-bit value. zlib.crc32(b'') is 0.

gopy notes

zlib is in module/zlib/ and uses Go's compress/zlib and compress/flate packages. The stream objects wrap flate.Writer/flate.Reader. crc32 and adler32 use hash/crc32 and hash/adler32. The wbits parameter controls format: positive = zlib wrapper, negative = raw deflate, 16+ = gzip wrapper (mapped to Go's compress/gzip).