summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans Kristian Rosbach <hk-git@circlestorm.org>2021-12-13 22:30:58 +0100
committerHans Kristian Rosbach <hk-github@circlestorm.org>2021-12-24 12:52:14 +0100
commit8a378ba9b85e23a6e2e67b01a1b3d738e86faefe (patch)
treee9e0dc35c97219e5b7276f5c026f28ab6e9f02dd
parent2faaf5bbc993c09f7344353b824e1c1ad585627f (diff)
Fix deflateBound and compressBound returning very small size estimates.
Remove workaround in switchlevels.c, so we do actual testing of this. Use named defines instead of magic numbers where we can.
-rw-r--r--compress.c11
-rw-r--r--deflate.c16
-rw-r--r--test/switchlevels.c2
-rw-r--r--zutil.h14
4 files changed, 32 insertions, 11 deletions
diff --git a/compress.c b/compress.c
index d537959..46e8f8e 100644
--- a/compress.c
+++ b/compress.c
@@ -3,8 +3,8 @@
* For conditions of distribution and use, see copyright notice in zlib.h
*/
-#define ZLIB_INTERNAL
#include "zbuild.h"
+#include "zutil.h"
#if defined(ZLIB_COMPAT)
# include "zlib.h"
#else
@@ -74,10 +74,11 @@ int Z_EXPORT PREFIX(compress)(unsigned char *dest, z_size_t *destLen, const unsi
*/
z_size_t Z_EXPORT PREFIX(compressBound)(z_size_t sourceLen) {
#ifndef NO_QUICK_STRATEGY
- /* Quick deflate strategy worse case is 9 bits per literal, rounded to nearest byte,
- plus the size of block & gzip headers and footers */
- return sourceLen + ((sourceLen + 13 + 7) >> 3) + 18;
+ return sourceLen /* The source size itself */
+ + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */
+ + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */
+ + ZLIB_WRAPLEN; /* zlib wrapper */
#else
- return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13;
+ return sourceLen + (sourceLen >> 4) + 7 + ZLIB_WRAPLEN;
#endif
}
diff --git a/deflate.c b/deflate.c
index ca9dafa..031a1bb 100644
--- a/deflate.c
+++ b/deflate.c
@@ -685,11 +685,11 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
wraplen = 0;
break;
case 1: /* zlib wrapper */
- wraplen = 6 + (s->strstart ? 4 : 0);
+ wraplen = ZLIB_WRAPLEN + (s->strstart ? 4 : 0);
break;
#ifdef GZIP
case 2: /* gzip wrapper */
- wraplen = 18;
+ wraplen = GZIP_WRAPLEN;
if (s->gzhead != NULL) { /* user-supplied gzip header */
unsigned char *str;
if (s->gzhead->extra != NULL) {
@@ -713,7 +713,7 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
break;
#endif
default: /* for compiler happiness */
- wraplen = 6;
+ wraplen = ZLIB_WRAPLEN;
}
/* if not default parameters, return conservative bound */
@@ -721,8 +721,14 @@ unsigned long Z_EXPORT PREFIX(deflateBound)(PREFIX3(stream) *strm, unsigned long
s->w_bits != 15 || HASH_BITS < 15)
return complen + wraplen;
- /* default settings: return tight bound for that case */
- return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + (sourceLen >> 25) + 13 - 6 + wraplen;
+#ifndef NO_QUICK_STRATEGY
+ return sourceLen /* The source size itself */
+ + DEFLATE_QUICK_OVERHEAD(sourceLen) /* Source encoding overhead, padded to next full byte */
+ + DEFLATE_BLOCK_OVERHEAD /* Deflate block overhead bytes */
+ + wraplen; /* none, zlib or gzip wrapper */
+#else
+ return sourceLen + (sourceLen >> 4) + 7 + wraplen;
+#endif
}
/* =========================================================================
diff --git a/test/switchlevels.c b/test/switchlevels.c
index a4ec4b7..1e1fb00 100644
--- a/test/switchlevels.c
+++ b/test/switchlevels.c
@@ -68,7 +68,7 @@ static int compress_chunk(PREFIX3(stream) *strm, int level, int size, int last)
goto done;
}
- compsize = 100 + 2 * PREFIX(deflateBound)(strm, size);
+ compsize = PREFIX(deflateBound)(strm, size);
buf = malloc(size + compsize);
if (buf == NULL) {
fprintf(stderr, "Out of memory\n");
diff --git a/zutil.h b/zutil.h
index c9e769c..015219a 100644
--- a/zutil.h
+++ b/zutil.h
@@ -78,6 +78,20 @@ extern z_const char * const PREFIX(z_errmsg)[10]; /* indexed by 2-zlib_error */
#define ADLER32_INITIAL_VALUE 1 /* initial adler-32 hash value */
+#define ZLIB_WRAPLEN 6 /* zlib format overhead */
+#define GZIP_WRAPLEN 18 /* gzip format overhead */
+
+#define DEFLATE_HEADER_BITS 3
+#define DEFLATE_EOBS_BITS 15
+#define DEFLATE_PAD_BITS 6
+#define DEFLATE_BLOCK_OVERHEAD ((DEFLATE_HEADER_BITS + DEFLATE_EOBS_BITS + DEFLATE_PAD_BITS) >> 3)
+/* deflate block overhead: 3 bits for block start + 15 bits for block end + padding to nearest byte */
+
+#define DEFLATE_QUICK_LIT_MAX_BITS 9
+#define DEFLATE_QUICK_OVERHEAD(x) ((x * (DEFLATE_QUICK_LIT_MAX_BITS - 8) + 7) >> 3)
+/* deflate_quick worst-case overhead: 9 bits per literal, round up to next byte (+7) */
+
+
/* target dependencies */
#ifdef AMIGA