zlib 的 inflate/deflate 对 avail_in 和 avail_out 有什么保证?
What guarantees does zlib's inflate/deflate make about avail_in and avail_out?
在调用 inflate
之后,zlib
对 avail_in
和 avail_out
的状态提供什么保证?我看到 miniz
的特殊行为,我想确定这不是对 zlib
API 的误解。实际上,在调用 inflate
之后,我有 avail_in
non-zero,avail_out
也有 non-zero,所以有些输入看起来没有得到处理。下面有更多详细信息。
我一直在使用miniz to inflate/deflate a file I stream to/from disk. My inflate/deflate loop is identical to the zlib sample in zpipe.c,包括使用MZ_NO_FLUSH
。
这个循环几乎总是有效,但今天我给早些时候放气的流充气,并始终如一地得到 MZ_DATA_ERROR
。不过,在添加适当的 header 之后,gzip
能够很好地对其进行充气并且我的数据完好无损。
我的问题归结为最后一次调用 mz_inflate
。我在这里包括了典型的膨胀循环:
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
重复内部 do
循环,直到处理完所有当前块并且 avail_out
有额外空间。然而,在这个特定流的最后一块,inflate
没有 return 错误,而是会将 avail_in
减少到某个 non-zero 数字,并且会减少 avail_out
也到一些(其他)non-zero号码。所以内部 do
循环退出,因为 avail_out
是 non-zero,我们尝试将更多数据放入 next_in
和 avail_in
,即使不是全部avail_in
已被处理,因为 avail_in
是 non-zero。这破坏了 next_in
和 avail_in
中的任何内容,并且 inflate
在下一次调用时失败。
我的解决方法是将内部循环的终止条件从
strm.avail_out == 0
至
strm.avail_out == 0 || strm.avail_in > 0
但我不知道这是否正确。我觉得这可能是 miniz
中的错误,但我不确定。我会想,如果avail_in
表示还有数据要处理,那avail_out
一定是零。
以防相关:我使用的输入缓冲区大小为 512KB,输出缓冲区为 2MB。
如果 inflate()
returns Z_OK
或 Z_BUF_ERROR
,并且 avail_out
不是 零,则 avail_in
是零。
能否提供相关的压缩数据?
在调用 inflate
之后,zlib
对 avail_in
和 avail_out
的状态提供什么保证?我看到 miniz
的特殊行为,我想确定这不是对 zlib
API 的误解。实际上,在调用 inflate
之后,我有 avail_in
non-zero,avail_out
也有 non-zero,所以有些输入看起来没有得到处理。下面有更多详细信息。
我一直在使用miniz to inflate/deflate a file I stream to/from disk. My inflate/deflate loop is identical to the zlib sample in zpipe.c,包括使用MZ_NO_FLUSH
。
这个循环几乎总是有效,但今天我给早些时候放气的流充气,并始终如一地得到 MZ_DATA_ERROR
。不过,在添加适当的 header 之后,gzip
能够很好地对其进行充气并且我的数据完好无损。
我的问题归结为最后一次调用 mz_inflate
。我在这里包括了典型的膨胀循环:
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
重复内部 do
循环,直到处理完所有当前块并且 avail_out
有额外空间。然而,在这个特定流的最后一块,inflate
没有 return 错误,而是会将 avail_in
减少到某个 non-zero 数字,并且会减少 avail_out
也到一些(其他)non-zero号码。所以内部 do
循环退出,因为 avail_out
是 non-zero,我们尝试将更多数据放入 next_in
和 avail_in
,即使不是全部avail_in
已被处理,因为 avail_in
是 non-zero。这破坏了 next_in
和 avail_in
中的任何内容,并且 inflate
在下一次调用时失败。
我的解决方法是将内部循环的终止条件从
strm.avail_out == 0
至
strm.avail_out == 0 || strm.avail_in > 0
但我不知道这是否正确。我觉得这可能是 miniz
中的错误,但我不确定。我会想,如果avail_in
表示还有数据要处理,那avail_out
一定是零。
以防相关:我使用的输入缓冲区大小为 512KB,输出缓冲区为 2MB。
如果 inflate()
returns Z_OK
或 Z_BUF_ERROR
,并且 avail_out
不是 零,则 avail_in
是零。
能否提供相关的压缩数据?