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 /deflate.c | |
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.
Diffstat (limited to 'deflate.c')
-rw-r--r-- | deflate.c | 24 |
1 files changed, 21 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; |