I've got a problem with my usage of the ZLib API. My data is correctly compressed and decompressed again, but the ::inflate()
(decompression) side is never returning with Z_STREAM_END
, only Z_OK
(which is not how it should be, according to the docs and the ZLib source code).
Here's what I'm doing to compress:
// (set up a `z_stream` with `data_type` as `Z_BINARY`)
call `::deflate(..., Z_NO_FLUSH)` to compress chunks until no more input left
call `::deflate(..., Z_FINISH)` until it returns `Z_STREAM_END` (it does!)
Later, I'm doing the same with ::inflate()
:
// (set up a `z_stream` with `data_type` as `Z_BINARY`)
call `::inflate(..., Z_NO_FLUSH)` to decompress chunks until no more input left
call `::inflate(..., Z_FINISH)` until it returns `Z_STREAM_END` (never happens).
What happens is that ::inflate(..., Z_NO_FLUSH)
consumes all input and produces the full decompressed stream(!), while still only returning Z_OK
.
At this point, z_stream::state
is still CHECK
(inflate.c, line #1198 - wants to read 32 bits for adler32 checksum), then z_stream::state
should be set to LENGTH
(inflate.c, line #1221 - want to read another 32 bits for stream length) and finally z_stream::state
should be set to DONE
which gives the expected Z_STREAM_END
return value (inflate.c, line #1235).
However, the 32 bits for the adler32 checksum and the 32 bits for the stream length are never appended by ::deflate()
. Am I missing something or using ZLib wrongly?
UPDATE: as requested, the compression code in detail
// Initialization
this->stream.msg = nullptr;
this->stream.state = nullptr;
this->stream.zalloc = &allocate; // delegates to malloc() (Z_SOLO)
this->stream.zfree = &free; // delegates to free() (Z_SOLO)
this->stream.data_type = Z_BINARY;
int result = ::deflateInit(&this->stream, Z_DEFAULT_COMPRESSION);
// error handling performed here
// ...
while(input_data_available) {
this->stream.next_in = uncompressedBuffer;
this->stream.avail_in = static_cast<uInt>(uncompressedByteCount);
this->stream.next_out = outputBuffer;
this->stream.avail_out = static_cast<uInt>(outputByteCount);
int result = ::deflate(&this->stream, Z_NO_FLUSH);
// error handling performed here
}
do {
this->stream.next_in = nullptr;
this->stream.avail_in = 0;
this->stream.next_out = outputBuffer;
this->stream.avail_out = static_cast<uInt>(outputByteCount);
int result = ::deflate(&this->stream, Z_FINISH);
// error handling performed here
} while(this->stream.avail_out == 0);
assert(result == Z_STREAM_END);
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…