diff options
Diffstat (limited to 'deflate.c')
-rw-r--r-- | deflate.c | 139 |
1 files changed, 85 insertions, 54 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* deflate.c -- compress data using the deflation algorithm | 1 | /* deflate.c -- compress data using the deflation algorithm |
2 | * Copyright (C) 1995-2009 Jean-loup Gailly. | 2 | * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -52,7 +52,7 @@ | |||
52 | #include "deflate.h" | 52 | #include "deflate.h" |
53 | 53 | ||
54 | const char deflate_copyright[] = | 54 | const char deflate_copyright[] = |
55 | " deflate 1.2.3.4 Copyright 1995-2009 Jean-loup Gailly "; | 55 | " deflate 1.2.3.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; |
56 | /* | 56 | /* |
57 | If you use the zlib library in a product, an acknowledgment is welcome | 57 | If you use the zlib library in a product, an acknowledgment is welcome |
58 | in the documentation of your product. If for some reason you cannot | 58 | in the documentation of your product. If for some reason you cannot |
@@ -79,19 +79,18 @@ local block_state deflate_fast OF((deflate_state *s, int flush)); | |||
79 | #ifndef FASTEST | 79 | #ifndef FASTEST |
80 | local block_state deflate_slow OF((deflate_state *s, int flush)); | 80 | local block_state deflate_slow OF((deflate_state *s, int flush)); |
81 | #endif | 81 | #endif |
82 | local block_state deflate_rle OF((deflate_state *s, int flush)); | ||
83 | local block_state deflate_huff OF((deflate_state *s, int flush)); | ||
82 | local void lm_init OF((deflate_state *s)); | 84 | local void lm_init OF((deflate_state *s)); |
83 | local void putShortMSB OF((deflate_state *s, uInt b)); | 85 | local void putShortMSB OF((deflate_state *s, uInt b)); |
84 | local void flush_pending OF((z_streamp strm)); | 86 | local void flush_pending OF((z_streamp strm)); |
85 | local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); | 87 | local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
86 | #ifndef FASTEST | ||
87 | #ifdef ASMV | 88 | #ifdef ASMV |
88 | void match_init OF((void)); /* asm code initialization */ | 89 | void match_init OF((void)); /* asm code initialization */ |
89 | uInt longest_match OF((deflate_state *s, IPos cur_match)); | 90 | uInt longest_match OF((deflate_state *s, IPos cur_match)); |
90 | #else | 91 | #else |
91 | local uInt longest_match OF((deflate_state *s, IPos cur_match)); | 92 | local uInt longest_match OF((deflate_state *s, IPos cur_match)); |
92 | #endif | 93 | #endif |
93 | #endif | ||
94 | local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); | ||
95 | 94 | ||
96 | #ifdef DEBUG | 95 | #ifdef DEBUG |
97 | local void check_match OF((deflate_state *s, IPos start, IPos match, | 96 | local void check_match OF((deflate_state *s, IPos start, IPos match, |
@@ -432,9 +431,10 @@ int ZEXPORT deflateParams(strm, level, strategy) | |||
432 | } | 431 | } |
433 | func = configuration_table[s->level].func; | 432 | func = configuration_table[s->level].func; |
434 | 433 | ||
435 | if (func != configuration_table[level].func && strm->total_in != 0) { | 434 | if ((strategy != s->strategy || func != configuration_table[level].func) && |
435 | strm->total_in != 0) { | ||
436 | /* Flush the last buffer: */ | 436 | /* Flush the last buffer: */ |
437 | err = deflate(strm, Z_PARTIAL_FLUSH); | 437 | err = deflate(strm, Z_BLOCK); |
438 | } | 438 | } |
439 | if (s->level != level) { | 439 | if (s->level != level) { |
440 | s->level = level; | 440 | s->level = level; |
@@ -536,7 +536,8 @@ uLong ZEXPORT deflateBound(strm, sourceLen) | |||
536 | return complen + wraplen; | 536 | return complen + wraplen; |
537 | 537 | ||
538 | /* default settings: return tight bound for that case */ | 538 | /* default settings: return tight bound for that case */ |
539 | return compressBound(sourceLen) - 6 + wraplen; | 539 | return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + |
540 | (sourceLen >> 25) + 13 - 6 + wraplen; | ||
540 | } | 541 | } |
541 | 542 | ||
542 | /* ========================================================================= | 543 | /* ========================================================================= |
@@ -816,7 +817,9 @@ int ZEXPORT deflate (strm, flush) | |||
816 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | 817 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
817 | block_state bstate; | 818 | block_state bstate; |
818 | 819 | ||
819 | bstate = (*(configuration_table[s->level].func))(s, flush); | 820 | bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : |
821 | (s->strategy == Z_RLE ? deflate_rle(s, flush) : | ||
822 | (*(configuration_table[s->level].func))(s, flush)); | ||
820 | 823 | ||
821 | if (bstate == finish_started || bstate == finish_done) { | 824 | if (bstate == finish_started || bstate == finish_done) { |
822 | s->status = FINISH_STATE; | 825 | s->status = FINISH_STATE; |
@@ -1200,12 +1203,13 @@ local uInt longest_match(s, cur_match) | |||
1200 | return s->lookahead; | 1203 | return s->lookahead; |
1201 | } | 1204 | } |
1202 | #endif /* ASMV */ | 1205 | #endif /* ASMV */ |
1203 | #endif /* FASTEST */ | 1206 | |
1207 | #else /* FASTEST */ | ||
1204 | 1208 | ||
1205 | /* --------------------------------------------------------------------------- | 1209 | /* --------------------------------------------------------------------------- |
1206 | * Optimized version for level == 1 or strategy == Z_RLE only | 1210 | * Optimized version for FASTEST only |
1207 | */ | 1211 | */ |
1208 | local uInt longest_match_fast(s, cur_match) | 1212 | local uInt longest_match(s, cur_match) |
1209 | deflate_state *s; | 1213 | deflate_state *s; |
1210 | IPos cur_match; /* current match */ | 1214 | IPos cur_match; /* current match */ |
1211 | { | 1215 | { |
@@ -1258,6 +1262,8 @@ local uInt longest_match_fast(s, cur_match) | |||
1258 | return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; | 1262 | return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; |
1259 | } | 1263 | } |
1260 | 1264 | ||
1265 | #endif /* FASTEST */ | ||
1266 | |||
1261 | #ifdef DEBUG | 1267 | #ifdef DEBUG |
1262 | /* =========================================================================== | 1268 | /* =========================================================================== |
1263 | * Check that the match at match_start is indeed a match. | 1269 | * Check that the match at match_start is indeed a match. |
@@ -1336,7 +1342,6 @@ local void fill_window(s) | |||
1336 | later. (Using level 0 permanently is not an optimal usage of | 1342 | later. (Using level 0 permanently is not an optimal usage of |
1337 | zlib, so we don't care about this pathological case.) | 1343 | zlib, so we don't care about this pathological case.) |
1338 | */ | 1344 | */ |
1339 | /* %%% avoid this when Z_RLE */ | ||
1340 | n = s->hash_size; | 1345 | n = s->hash_size; |
1341 | p = &s->head[n]; | 1346 | p = &s->head[n]; |
1342 | do { | 1347 | do { |
@@ -1516,7 +1521,7 @@ local block_state deflate_fast(s, flush) | |||
1516 | deflate_state *s; | 1521 | deflate_state *s; |
1517 | int flush; | 1522 | int flush; |
1518 | { | 1523 | { |
1519 | IPos hash_head = NIL; /* head of the hash chain */ | 1524 | IPos hash_head; /* head of the hash chain */ |
1520 | int bflush; /* set if current block must be flushed */ | 1525 | int bflush; /* set if current block must be flushed */ |
1521 | 1526 | ||
1522 | for (;;) { | 1527 | for (;;) { |
@@ -1536,6 +1541,7 @@ local block_state deflate_fast(s, flush) | |||
1536 | /* Insert the string window[strstart .. strstart+2] in the | 1541 | /* Insert the string window[strstart .. strstart+2] in the |
1537 | * dictionary, and set hash_head to the head of the hash chain: | 1542 | * dictionary, and set hash_head to the head of the hash chain: |
1538 | */ | 1543 | */ |
1544 | hash_head = NIL; | ||
1539 | if (s->lookahead >= MIN_MATCH) { | 1545 | if (s->lookahead >= MIN_MATCH) { |
1540 | INSERT_STRING(s, s->strstart, hash_head); | 1546 | INSERT_STRING(s, s->strstart, hash_head); |
1541 | } | 1547 | } |
@@ -1548,19 +1554,8 @@ local block_state deflate_fast(s, flush) | |||
1548 | * of window index 0 (in particular we have to avoid a match | 1554 | * of window index 0 (in particular we have to avoid a match |
1549 | * of the string with itself at the start of the input file). | 1555 | * of the string with itself at the start of the input file). |
1550 | */ | 1556 | */ |
1551 | #ifdef FASTEST | 1557 | s->match_length = longest_match (s, hash_head); |
1552 | if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || | 1558 | /* longest_match() sets match_start */ |
1553 | (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { | ||
1554 | s->match_length = longest_match_fast (s, hash_head); | ||
1555 | } | ||
1556 | #else | ||
1557 | if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { | ||
1558 | s->match_length = longest_match (s, hash_head); | ||
1559 | } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { | ||
1560 | s->match_length = longest_match_fast (s, hash_head); | ||
1561 | } | ||
1562 | #endif | ||
1563 | /* longest_match() or longest_match_fast() sets match_start */ | ||
1564 | } | 1559 | } |
1565 | if (s->match_length >= MIN_MATCH) { | 1560 | if (s->match_length >= MIN_MATCH) { |
1566 | check_match(s, s->strstart, s->match_start, s->match_length); | 1561 | check_match(s, s->strstart, s->match_start, s->match_length); |
@@ -1622,7 +1617,7 @@ local block_state deflate_slow(s, flush) | |||
1622 | deflate_state *s; | 1617 | deflate_state *s; |
1623 | int flush; | 1618 | int flush; |
1624 | { | 1619 | { |
1625 | IPos hash_head = NIL; /* head of hash chain */ | 1620 | IPos hash_head; /* head of hash chain */ |
1626 | int bflush; /* set if current block must be flushed */ | 1621 | int bflush; /* set if current block must be flushed */ |
1627 | 1622 | ||
1628 | /* Process the input block. */ | 1623 | /* Process the input block. */ |
@@ -1643,6 +1638,7 @@ local block_state deflate_slow(s, flush) | |||
1643 | /* Insert the string window[strstart .. strstart+2] in the | 1638 | /* Insert the string window[strstart .. strstart+2] in the |
1644 | * dictionary, and set hash_head to the head of the hash chain: | 1639 | * dictionary, and set hash_head to the head of the hash chain: |
1645 | */ | 1640 | */ |
1641 | hash_head = NIL; | ||
1646 | if (s->lookahead >= MIN_MATCH) { | 1642 | if (s->lookahead >= MIN_MATCH) { |
1647 | INSERT_STRING(s, s->strstart, hash_head); | 1643 | INSERT_STRING(s, s->strstart, hash_head); |
1648 | } | 1644 | } |
@@ -1658,12 +1654,8 @@ local block_state deflate_slow(s, flush) | |||
1658 | * of window index 0 (in particular we have to avoid a match | 1654 | * of window index 0 (in particular we have to avoid a match |
1659 | * of the string with itself at the start of the input file). | 1655 | * of the string with itself at the start of the input file). |
1660 | */ | 1656 | */ |
1661 | if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { | 1657 | s->match_length = longest_match (s, hash_head); |
1662 | s->match_length = longest_match (s, hash_head); | 1658 | /* longest_match() sets match_start */ |
1663 | } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { | ||
1664 | s->match_length = longest_match_fast (s, hash_head); | ||
1665 | } | ||
1666 | /* longest_match() or longest_match_fast() sets match_start */ | ||
1667 | 1659 | ||
1668 | if (s->match_length <= 5 && (s->strategy == Z_FILTERED | 1660 | if (s->match_length <= 5 && (s->strategy == Z_FILTERED |
1669 | #if TOO_FAR <= 32767 | 1661 | #if TOO_FAR <= 32767 |
@@ -1741,7 +1733,6 @@ local block_state deflate_slow(s, flush) | |||
1741 | } | 1733 | } |
1742 | #endif /* FASTEST */ | 1734 | #endif /* FASTEST */ |
1743 | 1735 | ||
1744 | #if 0 | ||
1745 | /* =========================================================================== | 1736 | /* =========================================================================== |
1746 | * For Z_RLE, simply look for runs of bytes, generate matches only of distance | 1737 | * For Z_RLE, simply look for runs of bytes, generate matches only of distance |
1747 | * one. Do not maintain a hash table. (It will be regenerated if this run of | 1738 | * one. Do not maintain a hash table. (It will be regenerated if this run of |
@@ -1751,11 +1742,9 @@ local block_state deflate_rle(s, flush) | |||
1751 | deflate_state *s; | 1742 | deflate_state *s; |
1752 | int flush; | 1743 | int flush; |
1753 | { | 1744 | { |
1754 | int bflush; /* set if current block must be flushed */ | 1745 | int bflush; /* set if current block must be flushed */ |
1755 | uInt run; /* length of run */ | 1746 | uInt prev; /* byte at distance one to match */ |
1756 | uInt max; /* maximum length of run */ | 1747 | Bytef *scan, *strend; /* scan goes up to strend for length of run */ |
1757 | uInt prev; /* byte at distance one to match */ | ||
1758 | Bytef *scan; /* scan for end of run */ | ||
1759 | 1748 | ||
1760 | for (;;) { | 1749 | for (;;) { |
1761 | /* Make sure that we always have enough lookahead, except | 1750 | /* Make sure that we always have enough lookahead, except |
@@ -1771,23 +1760,33 @@ local block_state deflate_rle(s, flush) | |||
1771 | } | 1760 | } |
1772 | 1761 | ||
1773 | /* See how many times the previous byte repeats */ | 1762 | /* See how many times the previous byte repeats */ |
1774 | run = 0; | 1763 | s->match_length = 0; |
1775 | if (s->strstart > 0) { /* if there is a previous byte, that is */ | 1764 | if (s->lookahead >= MIN_MATCH && s->strstart > 0) { |
1776 | max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; | ||
1777 | scan = s->window + s->strstart - 1; | 1765 | scan = s->window + s->strstart - 1; |
1778 | prev = *scan++; | 1766 | prev = *scan; |
1779 | do { | 1767 | if (prev == *++scan && prev == *++scan && prev == *++scan) { |
1780 | if (*scan++ != prev) | 1768 | strend = s->window + s->strstart + MAX_MATCH; |
1781 | break; | 1769 | do { |
1782 | } while (++run < max); | 1770 | } while (prev == *++scan && prev == *++scan && |
1771 | prev == *++scan && prev == *++scan && | ||
1772 | prev == *++scan && prev == *++scan && | ||
1773 | prev == *++scan && prev == *++scan && | ||
1774 | scan < strend); | ||
1775 | s->match_length = MAX_MATCH - (int)(strend - scan); | ||
1776 | if (s->match_length > s->lookahead) | ||
1777 | s->match_length = s->lookahead; | ||
1778 | } | ||
1783 | } | 1779 | } |
1784 | 1780 | ||
1785 | /* Emit match if have run of MIN_MATCH or longer, else emit literal */ | 1781 | /* Emit match if have run of MIN_MATCH or longer, else emit literal */ |
1786 | if (run >= MIN_MATCH) { | 1782 | if (s->match_length >= MIN_MATCH) { |
1787 | check_match(s, s->strstart, s->strstart - 1, run); | 1783 | check_match(s, s->strstart, s->strstart - 1, s->match_length); |
1788 | _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); | 1784 | |
1789 | s->lookahead -= run; | 1785 | _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); |
1790 | s->strstart += run; | 1786 | |
1787 | s->lookahead -= s->match_length; | ||
1788 | s->strstart += s->match_length; | ||
1789 | s->match_length = 0; | ||
1791 | } else { | 1790 | } else { |
1792 | /* No match, output a literal byte */ | 1791 | /* No match, output a literal byte */ |
1793 | Tracevv((stderr,"%c", s->window[s->strstart])); | 1792 | Tracevv((stderr,"%c", s->window[s->strstart])); |
@@ -1800,4 +1799,36 @@ local block_state deflate_rle(s, flush) | |||
1800 | FLUSH_BLOCK(s, flush == Z_FINISH); | 1799 | FLUSH_BLOCK(s, flush == Z_FINISH); |
1801 | return flush == Z_FINISH ? finish_done : block_done; | 1800 | return flush == Z_FINISH ? finish_done : block_done; |
1802 | } | 1801 | } |
1803 | #endif | 1802 | |
1803 | /* =========================================================================== | ||
1804 | * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. | ||
1805 | * (It will be regenerated if this run of deflate switches away from Huffman.) | ||
1806 | */ | ||
1807 | local block_state deflate_huff(s, flush) | ||
1808 | deflate_state *s; | ||
1809 | int flush; | ||
1810 | { | ||
1811 | int bflush; /* set if current block must be flushed */ | ||
1812 | |||
1813 | for (;;) { | ||
1814 | /* Make sure that we have a literal to write. */ | ||
1815 | if (s->lookahead == 0) { | ||
1816 | fill_window(s); | ||
1817 | if (s->lookahead == 0) { | ||
1818 | if (flush == Z_NO_FLUSH) | ||
1819 | return need_more; | ||
1820 | break; /* flush the current block */ | ||
1821 | } | ||
1822 | } | ||
1823 | |||
1824 | /* Output a literal byte */ | ||
1825 | s->match_length = 0; | ||
1826 | Tracevv((stderr,"%c", s->window[s->strstart])); | ||
1827 | _tr_tally_lit (s, s->window[s->strstart], bflush); | ||
1828 | s->lookahead--; | ||
1829 | s->strstart++; | ||
1830 | if (bflush) FLUSH_BLOCK(s, 0); | ||
1831 | } | ||
1832 | FLUSH_BLOCK(s, flush == Z_FINISH); | ||
1833 | return flush == Z_FINISH ? finish_done : block_done; | ||
1834 | } | ||