summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-12-07 23:57:37 -0800
committerMark Adler <madler@alumni.caltech.edu>2011-12-08 00:13:52 -0800
commitafe7cf78d51b819dcdc5b0f4cb85a25a52a9fcd0 (patch)
tree24c9db96071504cd7beb1d1800dbb265c736070f
parentfbac04f666339eef3678e4eb81b25ae69bfcbd81 (diff)
downloadzlib-afe7cf78d51b819dcdc5b0f4cb85a25a52a9fcd0.tar.gz
zlib-afe7cf78d51b819dcdc5b0f4cb85a25a52a9fcd0.tar.bz2
zlib-afe7cf78d51b819dcdc5b0f4cb85a25a52a9fcd0.zip
Enable dictionary setting in middle of stream, and keeping the dictionary.
This patch adds the deflateResetKeep() function to retain the sliding window for the next deflate operation, and fixes an inflateResetKeep() problem that came from inflate() not updating the window when the stream completed. This enables constructing and decompressing a series of concatenated deflate streams where each can depend on the history of uncompressed data that precedes it. This generalizes deflateSetDictionary() and inflateSetDictionary() to permit setting the dictionary in the middle of a stream for raw deflate and inflate. This in combination with the Keep functions enables a scheme for updating files block by block with the transmission of compressed data, where blocks are sent with deflateResetKeep() to retain history for better compression, and deflateSetDictionary() is used for blocks already present at the receiver to skip compression but insert that data in the history, again for better compression. The corresponding inflate calls are done on the receiver side.
-rw-r--r--as400/bndsrc1
-rw-r--r--as400/zlib.inc4
-rw-r--r--contrib/vstudio/vc10/zlibvc.def1
-rw-r--r--contrib/vstudio/vc9/zlibvc.def1
-rw-r--r--deflate.c90
-rw-r--r--inflate.c27
-rw-r--r--win32/zlib.def1
-rw-r--r--zconf.h1
-rw-r--r--zconf.h.cmakein1
-rw-r--r--zconf.h.in1
-rw-r--r--zlib.h27
-rw-r--r--zlib.map4
12 files changed, 109 insertions, 50 deletions
diff --git a/as400/bndsrc b/as400/bndsrc
index 036cd63..3e26283 100644
--- a/as400/bndsrc
+++ b/as400/bndsrc
@@ -33,6 +33,7 @@ STRPGMEXP PGMLVL(*CURRENT) SIGNATURE('ZLIB')
33 EXPORT SYMBOL("deflateSetDictionary") 33 EXPORT SYMBOL("deflateSetDictionary")
34 EXPORT SYMBOL("deflateCopy") 34 EXPORT SYMBOL("deflateCopy")
35 EXPORT SYMBOL("deflateReset") 35 EXPORT SYMBOL("deflateReset")
36 EXPORT SYMBOL("deflateResetKeep")
36 EXPORT SYMBOL("deflateParams") 37 EXPORT SYMBOL("deflateParams")
37 EXPORT SYMBOL("deflatePending") 38 EXPORT SYMBOL("deflatePending")
38 EXPORT SYMBOL("deflatePrime") 39 EXPORT SYMBOL("deflatePrime")
diff --git a/as400/zlib.inc b/as400/zlib.inc
index 976dca2..f0915c8 100644
--- a/as400/zlib.inc
+++ b/as400/zlib.inc
@@ -435,6 +435,10 @@
435 D PR 10I 0 extproc('inflateResetKeep') End and init. stream 435 D PR 10I 0 extproc('inflateResetKeep') End and init. stream
436 D strm like(z_stream) Expansion stream 436 D strm like(z_stream) Expansion stream
437 * 437 *
438 D deflateResetKeep...
439 D PR 10I 0 extproc('deflateResetKeep') End and init. stream
440 D strm like(z_stream) Expansion stream
441 *
438 D gzflags PR 10U 0 extproc('gzflags') 442 D gzflags PR 10U 0 extproc('gzflags')
439 * 443 *
440 /endif 444 /endif
diff --git a/contrib/vstudio/vc10/zlibvc.def b/contrib/vstudio/vc10/zlibvc.def
index d6ab1c1..5521885 100644
--- a/contrib/vstudio/vc10/zlibvc.def
+++ b/contrib/vstudio/vc10/zlibvc.def
@@ -133,3 +133,4 @@ EXPORTS
133 gzgetc_ @30 133 gzgetc_ @30
134 gzflags @162 134 gzflags @162
135 inflateResetKeep @163 135 inflateResetKeep @163
136 deflateResetKeep @164
diff --git a/contrib/vstudio/vc9/zlibvc.def b/contrib/vstudio/vc9/zlibvc.def
index d6ab1c1..5521885 100644
--- a/contrib/vstudio/vc9/zlibvc.def
+++ b/contrib/vstudio/vc9/zlibvc.def
@@ -133,3 +133,4 @@ EXPORTS
133 gzgetc_ @30 133 gzgetc_ @30
134 gzflags @162 134 gzflags @162
135 inflateResetKeep @163 135 inflateResetKeep @163
136 deflateResetKeep @164
diff --git a/deflate.c b/deflate.c
index 4b8e91b..096207d 100644
--- a/deflate.c
+++ b/deflate.c
@@ -323,43 +323,68 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
323 uInt dictLength; 323 uInt dictLength;
324{ 324{
325 deflate_state *s; 325 deflate_state *s;
326 uInt length = dictLength; 326 uInt str, n;
327 uInt n; 327 int wrap;
328 IPos hash_head = 0; 328 unsigned avail;
329 unsigned char *next;
329 330
330 if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || 331 if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)
331 strm->state->wrap == 2 ||
332 (strm->state->wrap == 1 && strm->state->status != INIT_STATE))
333 return Z_STREAM_ERROR; 332 return Z_STREAM_ERROR;
334
335 s = strm->state; 333 s = strm->state;
336 if (s->wrap) 334 wrap = s->wrap;
337 strm->adler = adler32(strm->adler, dictionary, dictLength); 335 if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead)
336 return Z_STREAM_ERROR;
338 337
339 if (length < MIN_MATCH) return Z_OK; 338 /* when using zlib wrappers, compute Adler-32 for provided dictionary */
340 if (length > s->w_size) { 339 if (wrap == 1)
341 length = s->w_size; 340 strm->adler = adler32(strm->adler, dictionary, dictLength);
342 dictionary += dictLength - length; /* use the tail of the dictionary */ 341 s->wrap = 0; /* avoid computing Adler-32 in read_buf */
342
343 /* if dictionary would fill window, just replace the history */
344 if (dictLength >= s->w_size) {
345 if (wrap == 0) { /* already empty otherwise */
346 CLEAR_HASH(s);
347 s->strstart = 0;
348 s->block_start = 0L;
349 }
350 dictionary += dictLength - s->w_size; /* use the tail */
351 dictLength = s->w_size;
343 } 352 }
344 zmemcpy(s->window, dictionary, length);
345 s->strstart = length;
346 s->block_start = (long)length;
347 353
348 /* Insert all strings in the hash table (except for the last two bytes). 354 /* insert dictionary into window and hash */
349 * s->lookahead stays null, so s->ins_h will be recomputed at the next 355 avail = strm->avail_in;
350 * call of fill_window. 356 next = strm->next_in;
351 */ 357 strm->avail_in = dictLength;
352 s->ins_h = s->window[0]; 358 strm->next_in = (Bytef *)dictionary;
353 UPDATE_HASH(s, s->ins_h, s->window[1]); 359 fill_window(s);
354 for (n = 0; n <= length - MIN_MATCH; n++) { 360 while (s->lookahead >= MIN_MATCH) {
355 INSERT_STRING(s, n, hash_head); 361 str = s->strstart;
362 n = s->lookahead - (MIN_MATCH-1);
363 do {
364 UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]);
365#ifndef FASTEST
366 s->prev[str & s->w_mask] = s->head[s->ins_h];
367#endif
368 s->head[s->ins_h] = (Pos)str;
369 str++;
370 } while (--n);
371 s->strstart = str;
372 s->lookahead = MIN_MATCH-1;
373 fill_window(s);
356 } 374 }
357 if (hash_head) hash_head = 0; /* to make compiler happy */ 375 s->strstart += s->lookahead;
376 s->block_start = (long)s->strstart;
377 s->lookahead = 0;
378 s->match_length = s->prev_length = MIN_MATCH-1;
379 s->match_available = 0;
380 strm->next_in = next;
381 strm->avail_in = avail;
382 s->wrap = wrap;
358 return Z_OK; 383 return Z_OK;
359} 384}
360 385
361/* ========================================================================= */ 386/* ========================================================================= */
362int ZEXPORT deflateReset (strm) 387int ZEXPORT deflateResetKeep (strm)
363 z_streamp strm; 388 z_streamp strm;
364{ 389{
365 deflate_state *s; 390 deflate_state *s;
@@ -389,12 +414,23 @@ int ZEXPORT deflateReset (strm)
389 s->last_flush = Z_NO_FLUSH; 414 s->last_flush = Z_NO_FLUSH;
390 415
391 _tr_init(s); 416 _tr_init(s);
392 lm_init(s);
393 417
394 return Z_OK; 418 return Z_OK;
395} 419}
396 420
397/* ========================================================================= */ 421/* ========================================================================= */
422int ZEXPORT deflateReset (strm)
423 z_streamp strm;
424{
425 int ret;
426
427 ret = deflateResetKeep(strm);
428 if (ret == Z_OK)
429 lm_init(strm->state);
430 return ret;
431}
432
433/* ========================================================================= */
398int ZEXPORT deflateSetHeader (strm, head) 434int ZEXPORT deflateSetHeader (strm, head)
399 z_streamp strm; 435 z_streamp strm;
400 gz_headerp head; 436 gz_headerp head;
diff --git a/inflate.c b/inflate.c
index 6b0ebbf..6832b8b 100644
--- a/inflate.c
+++ b/inflate.c
@@ -1232,7 +1232,7 @@ int flush;
1232 */ 1232 */
1233 inf_leave: 1233 inf_leave:
1234 RESTORE(); 1234 RESTORE();
1235 if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) 1235 if (state->wsize || (state->mode < BAD && out != strm->avail_out))
1236 if (updatewindow(strm, out)) { 1236 if (updatewindow(strm, out)) {
1237 state->mode = MEM; 1237 state->mode = MEM;
1238 return Z_MEM_ERROR; 1238 return Z_MEM_ERROR;
@@ -1274,6 +1274,9 @@ uInt dictLength;
1274{ 1274{
1275 struct inflate_state FAR *state; 1275 struct inflate_state FAR *state;
1276 unsigned long id; 1276 unsigned long id;
1277 unsigned char *next;
1278 unsigned avail;
1279 int ret;
1277 1280
1278 /* check state */ 1281 /* check state */
1279 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; 1282 if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
@@ -1289,21 +1292,19 @@ uInt dictLength;
1289 return Z_DATA_ERROR; 1292 return Z_DATA_ERROR;
1290 } 1293 }
1291 1294
1292 /* copy dictionary to window */ 1295 /* copy dictionary to window using updatewindow(), which will amend the
1293 if (updatewindow(strm, strm->avail_out)) { 1296 existing dictionary if appropriate */
1297 next = strm->next_out;
1298 avail = strm->avail_out;
1299 strm->next_out = (Bytef *)dictionary + dictLength;
1300 strm->avail_out = 0;
1301 ret = updatewindow(strm, dictLength);
1302 strm->avail_out = avail;
1303 strm->next_out = next;
1304 if (ret) {
1294 state->mode = MEM; 1305 state->mode = MEM;
1295 return Z_MEM_ERROR; 1306 return Z_MEM_ERROR;
1296 } 1307 }
1297 if (dictLength > state->wsize) {
1298 zmemcpy(state->window, dictionary + dictLength - state->wsize,
1299 state->wsize);
1300 state->whave = state->wsize;
1301 }
1302 else {
1303 zmemcpy(state->window + state->wsize - dictLength, dictionary,
1304 dictLength);
1305 state->whave = dictLength;
1306 }
1307 state->havedict = 1; 1308 state->havedict = 1;
1308 Tracev((stderr, "inflate: dictionary set\n")); 1309 Tracev((stderr, "inflate: dictionary set\n"));
1309 return Z_OK; 1310 return Z_OK;
diff --git a/win32/zlib.def b/win32/zlib.def
index c420d8b..21bff1f 100644
--- a/win32/zlib.def
+++ b/win32/zlib.def
@@ -78,5 +78,6 @@ EXPORTS
78 get_crc_table 78 get_crc_table
79 inflateUndermine 79 inflateUndermine
80 inflateResetKeep 80 inflateResetKeep
81 deflateResetKeep
81 gzgetc_ 82 gzgetc_
82 gzflags 83 gzflags
diff --git a/zconf.h b/zconf.h
index 84ffb32..51c80ac 100644
--- a/zconf.h
+++ b/zconf.h
@@ -46,6 +46,7 @@
46# define deflatePending z_deflatePending 46# define deflatePending z_deflatePending
47# define deflatePrime z_deflatePrime 47# define deflatePrime z_deflatePrime
48# define deflateReset z_deflateReset 48# define deflateReset z_deflateReset
49# define deflateResetKeep z_deflateResetKeep
49# define deflateSetDictionary z_deflateSetDictionary 50# define deflateSetDictionary z_deflateSetDictionary
50# define deflateSetHeader z_deflateSetHeader 51# define deflateSetHeader z_deflateSetHeader
51# define deflateTune z_deflateTune 52# define deflateTune z_deflateTune
diff --git a/zconf.h.cmakein b/zconf.h.cmakein
index b2d78b3..3ea5531 100644
--- a/zconf.h.cmakein
+++ b/zconf.h.cmakein
@@ -48,6 +48,7 @@
48# define deflatePending z_deflatePending 48# define deflatePending z_deflatePending
49# define deflatePrime z_deflatePrime 49# define deflatePrime z_deflatePrime
50# define deflateReset z_deflateReset 50# define deflateReset z_deflateReset
51# define deflateResetKeep z_deflateResetKeep
51# define deflateSetDictionary z_deflateSetDictionary 52# define deflateSetDictionary z_deflateSetDictionary
52# define deflateSetHeader z_deflateSetHeader 53# define deflateSetHeader z_deflateSetHeader
53# define deflateTune z_deflateTune 54# define deflateTune z_deflateTune
diff --git a/zconf.h.in b/zconf.h.in
index 84ffb32..51c80ac 100644
--- a/zconf.h.in
+++ b/zconf.h.in
@@ -46,6 +46,7 @@
46# define deflatePending z_deflatePending 46# define deflatePending z_deflatePending
47# define deflatePrime z_deflatePrime 47# define deflatePrime z_deflatePrime
48# define deflateReset z_deflateReset 48# define deflateReset z_deflateReset
49# define deflateResetKeep z_deflateResetKeep
49# define deflateSetDictionary z_deflateSetDictionary 50# define deflateSetDictionary z_deflateSetDictionary
50# define deflateSetHeader z_deflateSetHeader 51# define deflateSetHeader z_deflateSetHeader
51# define deflateTune z_deflateTune 52# define deflateTune z_deflateTune
diff --git a/zlib.h b/zlib.h
index 3121b0a..3669f2e 100644
--- a/zlib.h
+++ b/zlib.h
@@ -581,10 +581,15 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
581 uInt dictLength)); 581 uInt dictLength));
582/* 582/*
583 Initializes the compression dictionary from the given byte sequence 583 Initializes the compression dictionary from the given byte sequence
584 without producing any compressed output. This function must be called 584 without producing any compressed output. When using the zlib format, this
585 immediately after deflateInit, deflateInit2 or deflateReset, before any call 585 function must be called immediately after deflateInit, deflateInit2 or
586 of deflate. The compressor and decompressor must use exactly the same 586 deflateReset, and before any call of deflate. When doing raw deflate, this
587 dictionary (see inflateSetDictionary). 587 function must be called either before any call of deflate, or immediately
588 after the completion of a deflate block, i.e. after all input has been
589 consumed and all output has been delivered when using any of the flush
590 options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The
591 compressor and decompressor must use exactly the same dictionary (see
592 inflateSetDictionary).
588 593
589 The dictionary should consist of strings (byte sequences) that are likely 594 The dictionary should consist of strings (byte sequences) that are likely
590 to be encountered later in the data to be compressed, with the most commonly 595 to be encountered later in the data to be compressed, with the most commonly
@@ -611,8 +616,8 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
611 deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a 616 deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
612 parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is 617 parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
613 inconsistent (for example if deflate has already been called for this stream 618 inconsistent (for example if deflate has already been called for this stream
614 or if the compression method is bsort). deflateSetDictionary does not 619 or if not at a block boundary for raw deflate). deflateSetDictionary does
615 perform any compression: this will be done by deflate(). 620 not perform any compression: this will be done by deflate().
616*/ 621*/
617 622
618ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, 623ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest,
@@ -810,10 +815,11 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm,
810 if that call returned Z_NEED_DICT. The dictionary chosen by the compressor 815 if that call returned Z_NEED_DICT. The dictionary chosen by the compressor
811 can be determined from the adler32 value returned by that call of inflate. 816 can be determined from the adler32 value returned by that call of inflate.
812 The compressor and decompressor must use exactly the same dictionary (see 817 The compressor and decompressor must use exactly the same dictionary (see
813 deflateSetDictionary). For raw inflate, this function can be called 818 deflateSetDictionary). For raw inflate, this function can be called at any
814 immediately after inflateInit2() or inflateReset() and before any call of 819 time to set the dictionary. If the provided dictionary is smaller than the
815 inflate() to set the dictionary. The application must insure that the 820 window and there is already data in the window, then the provided dictionary
816 dictionary that was used for compression is provided. 821 will amend what's there. The application must insure that the dictionary
822 that was used for compression is provided.
817 823
818 inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a 824 inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
819 parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is 825 parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is
@@ -1694,6 +1700,7 @@ ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp));
1694ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void)); 1700ZEXTERN const uLongf * ZEXPORT get_crc_table OF((void));
1695ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); 1701ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int));
1696ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); 1702ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp));
1703ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp));
1697#ifndef Z_SOLO 1704#ifndef Z_SOLO
1698 ZEXTERN unsigned long ZEXPORT gzflags OF((void)); 1705 ZEXTERN unsigned long ZEXPORT gzflags OF((void));
1699#endif 1706#endif
diff --git a/zlib.map b/zlib.map
index dd27591..80c4774 100644
--- a/zlib.map
+++ b/zlib.map
@@ -76,3 +76,7 @@ ZLIB_1.2.5.2 {
76 gzgetc_; 76 gzgetc_;
77 inflateResetKeep; 77 inflateResetKeep;
78} ZLIB_1.2.5.1; 78} ZLIB_1.2.5.1;
79
80ZLIB_1.2.5.3 {
81 deflateResetKeep;
82} ZLIB_1.2.5.2;