summaryrefslogtreecommitdiff
path: root/deflate.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2012-01-13 23:54:40 -0600
committerMark Adler <madler@alumni.caltech.edu>2012-01-13 23:54:40 -0600
commit4f5779a8e78e0b1c8b1ecdea88d8456dada17823 (patch)
tree267f14f252dbc3f23e8c7f34a7ddce633491754e /deflate.c
parent0b828b4aa6c962ab46eae624578d77b35395b2c1 (diff)
downloadzlib-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.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/deflate.c b/deflate.c
index 3c04f5d..0ba984d 100644
--- a/deflate.c
+++ b/deflate.c
@@ -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;