diff options
| author | Mark Adler <madler@alumni.caltech.edu> | 2012-01-13 23:54:40 -0600 |
|---|---|---|
| committer | Mark Adler <madler@alumni.caltech.edu> | 2012-01-13 23:54:40 -0600 |
| commit | 4f5779a8e78e0b1c8b1ecdea88d8456dada17823 (patch) | |
| tree | 267f14f252dbc3f23e8c7f34a7ddce633491754e | |
| parent | 0b828b4aa6c962ab46eae624578d77b35395b2c1 (diff) | |
| download | zlib-4f5779a8e78e0b1c8b1ecdea88d8456dada17823.tar.gz zlib-4f5779a8e78e0b1c8b1ecdea88d8456dada17823.tar.bz2 zlib-4f5779a8e78e0b1c8b1ecdea88d8456dada17823.zip | |
Insert the first two strings in the hash table after a flush.
This allows deflate to generate the same output when continuing after
a Z_SYNC_FLUSH vs. using deflateSetDictionary() after a Z_FULL_FLUSH
or a deflateReset(). It also slightly improves compression when
flushing by providing two more strings to possibly match at the start
of the new block.
| -rw-r--r-- | deflate.c | 24 | ||||
| -rw-r--r-- | deflate.h | 1 |
2 files changed, 22 insertions, 3 deletions
| @@ -349,6 +349,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) | |||
| 349 | CLEAR_HASH(s); | 349 | CLEAR_HASH(s); |
| 350 | s->strstart = 0; | 350 | s->strstart = 0; |
| 351 | s->block_start = 0L; | 351 | s->block_start = 0L; |
| 352 | s->insert = 0; | ||
| 352 | } | 353 | } |
| 353 | dictionary += dictLength - s->w_size; /* use the tail */ | 354 | dictionary += dictLength - s->w_size; /* use the tail */ |
| 354 | dictLength = s->w_size; | 355 | dictLength = s->w_size; |
| @@ -377,6 +378,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) | |||
| 377 | } | 378 | } |
| 378 | s->strstart += s->lookahead; | 379 | s->strstart += s->lookahead; |
| 379 | s->block_start = (long)s->strstart; | 380 | s->block_start = (long)s->strstart; |
| 381 | s->insert = s->lookahead; | ||
| 380 | s->lookahead = 0; | 382 | s->lookahead = 0; |
| 381 | s->match_length = s->prev_length = MIN_MATCH-1; | 383 | s->match_length = s->prev_length = MIN_MATCH-1; |
| 382 | s->match_available = 0; | 384 | s->match_available = 0; |
| @@ -929,6 +931,7 @@ int ZEXPORT deflate (strm, flush) | |||
| 929 | if (s->lookahead == 0) { | 931 | if (s->lookahead == 0) { |
| 930 | s->strstart = 0; | 932 | s->strstart = 0; |
| 931 | s->block_start = 0L; | 933 | s->block_start = 0L; |
| 934 | s->insert = 0; | ||
| 932 | } | 935 | } |
| 933 | } | 936 | } |
| 934 | } | 937 | } |
| @@ -1115,6 +1118,7 @@ local void lm_init (s) | |||
| 1115 | s->strstart = 0; | 1118 | s->strstart = 0; |
| 1116 | s->block_start = 0L; | 1119 | s->block_start = 0L; |
| 1117 | s->lookahead = 0; | 1120 | s->lookahead = 0; |
| 1121 | s->insert = 0; | ||
| 1118 | s->match_length = s->prev_length = MIN_MATCH-1; | 1122 | s->match_length = s->prev_length = MIN_MATCH-1; |
| 1119 | s->match_available = 0; | 1123 | s->match_available = 0; |
| 1120 | s->ins_h = 0; | 1124 | s->ins_h = 0; |
| @@ -1462,12 +1466,24 @@ local void fill_window(s) | |||
| 1462 | s->lookahead += n; | 1466 | s->lookahead += n; |
| 1463 | 1467 | ||
| 1464 | /* Initialize the hash value now that we have some input: */ | 1468 | /* Initialize the hash value now that we have some input: */ |
| 1465 | if (s->lookahead >= MIN_MATCH) { | 1469 | if (s->lookahead + s->insert >= MIN_MATCH) { |
| 1466 | s->ins_h = s->window[s->strstart]; | 1470 | uInt str = s->strstart - s->insert; |
| 1467 | UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); | 1471 | s->ins_h = s->window[str]; |
| 1472 | UPDATE_HASH(s, s->ins_h, s->window[str + 1]); | ||
| 1468 | #if MIN_MATCH != 3 | 1473 | #if MIN_MATCH != 3 |
| 1469 | Call UPDATE_HASH() MIN_MATCH-3 more times | 1474 | Call UPDATE_HASH() MIN_MATCH-3 more times |
| 1470 | #endif | 1475 | #endif |
| 1476 | while (s->insert) { | ||
| 1477 | UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); | ||
| 1478 | #ifndef FASTEST | ||
| 1479 | s->prev[str & s->w_mask] = s->head[s->ins_h]; | ||
| 1480 | #endif | ||
| 1481 | s->head[s->ins_h] = (Pos)str; | ||
| 1482 | str++; | ||
| 1483 | s->insert--; | ||
| 1484 | if (s->lookahead + s->insert < MIN_MATCH) | ||
| 1485 | break; | ||
| 1486 | } | ||
| 1471 | } | 1487 | } |
| 1472 | /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, | 1488 | /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, |
| 1473 | * but this is not important since only literal bytes will be emitted. | 1489 | * but this is not important since only literal bytes will be emitted. |
| @@ -1692,6 +1708,7 @@ local block_state deflate_fast(s, flush) | |||
| 1692 | } | 1708 | } |
| 1693 | if (bflush) FLUSH_BLOCK(s, 0); | 1709 | if (bflush) FLUSH_BLOCK(s, 0); |
| 1694 | } | 1710 | } |
| 1711 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | ||
| 1695 | if (flush == Z_FINISH) { | 1712 | if (flush == Z_FINISH) { |
| 1696 | FLUSH_BLOCK(s, 1); | 1713 | FLUSH_BLOCK(s, 1); |
| 1697 | return finish_done; | 1714 | return finish_done; |
| @@ -1822,6 +1839,7 @@ local block_state deflate_slow(s, flush) | |||
| 1822 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | 1839 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); |
| 1823 | s->match_available = 0; | 1840 | s->match_available = 0; |
| 1824 | } | 1841 | } |
| 1842 | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; | ||
| 1825 | if (flush == Z_FINISH) { | 1843 | if (flush == Z_FINISH) { |
| 1826 | FLUSH_BLOCK(s, 1); | 1844 | FLUSH_BLOCK(s, 1); |
| 1827 | return finish_done; | 1845 | return finish_done; |
| @@ -247,6 +247,7 @@ typedef struct internal_state { | |||
| 247 | ulg opt_len; /* bit length of current block with optimal trees */ | 247 | ulg opt_len; /* bit length of current block with optimal trees */ |
| 248 | ulg static_len; /* bit length of current block with static trees */ | 248 | ulg static_len; /* bit length of current block with static trees */ |
| 249 | uInt matches; /* number of string matches in current block */ | 249 | uInt matches; /* number of string matches in current block */ |
| 250 | uInt insert; /* bytes at end of window left to insert */ | ||
| 250 | 251 | ||
| 251 | #ifdef DEBUG | 252 | #ifdef DEBUG |
| 252 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ | 253 | ulg compressed_len; /* total bit length of compressed file mod 2^32 */ |
