Index: third_party/zlib/deflate.c |
=================================================================== |
--- third_party/zlib/deflate.c (revision 112951) |
+++ third_party/zlib/deflate.c (working copy) |
@@ -1,5 +1,5 @@ |
/* deflate.c -- compress data using the deflation algorithm |
- * Copyright (C) 1995-2005 Jean-loup Gailly. |
+ * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler |
* For conditions of distribution and use, see copyright notice in zlib.h |
*/ |
@@ -47,12 +47,12 @@ |
* |
*/ |
-/* @(#) $Id: deflate.c,v 3.6 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ |
+/* @(#) $Id$ */ |
#include "deflate.h" |
const char deflate_copyright[] = |
- " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; |
+ " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; |
/* |
If you use the zlib library in a product, an acknowledgment is welcome |
in the documentation of your product. If for some reason you cannot |
@@ -79,19 +79,18 @@ |
#ifndef FASTEST |
local block_state deflate_slow OF((deflate_state *s, int flush)); |
#endif |
+local block_state deflate_rle OF((deflate_state *s, int flush)); |
+local block_state deflate_huff OF((deflate_state *s, int flush)); |
local void lm_init OF((deflate_state *s)); |
local void putShortMSB OF((deflate_state *s, uInt b)); |
local void flush_pending OF((z_streamp strm)); |
local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
-#ifndef FASTEST |
#ifdef ASMV |
void match_init OF((void)); /* asm code initialization */ |
uInt longest_match OF((deflate_state *s, IPos cur_match)); |
#else |
local uInt longest_match OF((deflate_state *s, IPos cur_match)); |
#endif |
-#endif |
-local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); |
#ifdef DEBUG |
local void check_match OF((deflate_state *s, IPos start, IPos match, |
@@ -110,11 +109,6 @@ |
#endif |
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ |
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) |
-/* Minimum amount of lookahead, except at the end of the input file. |
- * See deflate.c for comments about the MIN_MATCH+1. |
- */ |
- |
/* Values for max_lazy_match, good_match and max_chain_length, depending on |
* the desired pack level (0..9). The values given below have been tuned to |
* exclude worst case performance for pathological files. Better values may be |
@@ -288,6 +282,8 @@ |
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); |
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); |
+ s->high_water = 0; /* nothing written to s->window yet */ |
+ |
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ |
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); |
@@ -332,8 +328,8 @@ |
strm->adler = adler32(strm->adler, dictionary, dictLength); |
if (length < MIN_MATCH) return Z_OK; |
- if (length > MAX_DIST(s)) { |
- length = MAX_DIST(s); |
+ if (length > s->w_size) { |
+ length = s->w_size; |
dictionary += dictLength - length; /* use the tail of the dictionary */ |
} |
zmemcpy(s->window, dictionary, length); |
@@ -435,9 +431,10 @@ |
} |
func = configuration_table[s->level].func; |
- if (func != configuration_table[level].func && strm->total_in != 0) { |
+ if ((strategy != s->strategy || func != configuration_table[level].func) && |
+ strm->total_in != 0) { |
/* Flush the last buffer: */ |
- err = deflate(strm, Z_PARTIAL_FLUSH); |
+ err = deflate(strm, Z_BLOCK); |
} |
if (s->level != level) { |
s->level = level; |
@@ -481,33 +478,66 @@ |
* resulting from using fixed blocks instead of stored blocks, which deflate |
* can emit on compressed data for some combinations of the parameters. |
* |
- * This function could be more sophisticated to provide closer upper bounds |
- * for every combination of windowBits and memLevel, as well as wrap. |
- * But even the conservative upper bound of about 14% expansion does not |
- * seem onerous for output buffer allocation. |
+ * This function could be more sophisticated to provide closer upper bounds for |
+ * every combination of windowBits and memLevel. But even the conservative |
+ * upper bound of about 14% expansion does not seem onerous for output buffer |
+ * allocation. |
*/ |
uLong ZEXPORT deflateBound(strm, sourceLen) |
z_streamp strm; |
uLong sourceLen; |
{ |
deflate_state *s; |
- uLong destLen; |
+ uLong complen, wraplen; |
+ Bytef *str; |
- /* conservative upper bound */ |
- destLen = sourceLen + |
- ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; |
+ /* conservative upper bound for compressed data */ |
+ complen = sourceLen + |
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; |
- /* if can't get parameters, return conservative bound */ |
+ /* if can't get parameters, return conservative bound plus zlib wrapper */ |
if (strm == Z_NULL || strm->state == Z_NULL) |
- return destLen; |
+ return complen + 6; |
+ /* compute wrapper length */ |
+ s = strm->state; |
+ switch (s->wrap) { |
+ case 0: /* raw deflate */ |
+ wraplen = 0; |
+ break; |
+ case 1: /* zlib wrapper */ |
+ wraplen = 6 + (s->strstart ? 4 : 0); |
+ break; |
+ case 2: /* gzip wrapper */ |
+ wraplen = 18; |
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ |
+ if (s->gzhead->extra != Z_NULL) |
+ wraplen += 2 + s->gzhead->extra_len; |
+ str = s->gzhead->name; |
+ if (str != Z_NULL) |
+ do { |
+ wraplen++; |
+ } while (*str++); |
+ str = s->gzhead->comment; |
+ if (str != Z_NULL) |
+ do { |
+ wraplen++; |
+ } while (*str++); |
+ if (s->gzhead->hcrc) |
+ wraplen += 2; |
+ } |
+ break; |
+ default: /* for compiler happiness */ |
+ wraplen = 6; |
+ } |
+ |
/* if not default parameters, return conservative bound */ |
- s = strm->state; |
if (s->w_bits != 15 || s->hash_bits != 8 + 7) |
- return destLen; |
+ return complen + wraplen; |
/* default settings: return tight bound for that case */ |
- return compressBound(sourceLen); |
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + |
+ (sourceLen >> 25) + 13 - 6 + wraplen; |
} |
/* ========================================================================= |
@@ -557,7 +587,7 @@ |
deflate_state *s; |
if (strm == Z_NULL || strm->state == Z_NULL || |
- flush > Z_FINISH || flush < 0) { |
+ flush > Z_BLOCK || flush < 0) { |
return Z_STREAM_ERROR; |
} |
s = strm->state; |
@@ -581,7 +611,7 @@ |
put_byte(s, 31); |
put_byte(s, 139); |
put_byte(s, 8); |
- if (s->gzhead == NULL) { |
+ if (s->gzhead == Z_NULL) { |
put_byte(s, 0); |
put_byte(s, 0); |
put_byte(s, 0); |
@@ -608,7 +638,7 @@ |
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
4 : 0)); |
put_byte(s, s->gzhead->os & 0xff); |
- if (s->gzhead->extra != NULL) { |
+ if (s->gzhead->extra != Z_NULL) { |
put_byte(s, s->gzhead->extra_len & 0xff); |
put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); |
} |
@@ -650,7 +680,7 @@ |
} |
#ifdef GZIP |
if (s->status == EXTRA_STATE) { |
- if (s->gzhead->extra != NULL) { |
+ if (s->gzhead->extra != Z_NULL) { |
uInt beg = s->pending; /* start of bytes to update crc */ |
while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { |
@@ -678,7 +708,7 @@ |
s->status = NAME_STATE; |
} |
if (s->status == NAME_STATE) { |
- if (s->gzhead->name != NULL) { |
+ if (s->gzhead->name != Z_NULL) { |
uInt beg = s->pending; /* start of bytes to update crc */ |
int val; |
@@ -709,7 +739,7 @@ |
s->status = COMMENT_STATE; |
} |
if (s->status == COMMENT_STATE) { |
- if (s->gzhead->comment != NULL) { |
+ if (s->gzhead->comment != Z_NULL) { |
uInt beg = s->pending; /* start of bytes to update crc */ |
int val; |
@@ -787,7 +817,9 @@ |
(flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
block_state bstate; |
- bstate = (*(configuration_table[s->level].func))(s, flush); |
+ bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) : |
+ (s->strategy == Z_RLE ? deflate_rle(s, flush) : |
+ (*(configuration_table[s->level].func))(s, flush)); |
if (bstate == finish_started || bstate == finish_done) { |
s->status = FINISH_STATE; |
@@ -808,13 +840,17 @@ |
if (bstate == block_done) { |
if (flush == Z_PARTIAL_FLUSH) { |
_tr_align(s); |
- } else { /* FULL_FLUSH or SYNC_FLUSH */ |
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ |
_tr_stored_block(s, (char*)0, 0L, 0); |
/* For a full flush, this empty block will be recognized |
* as a special marker by inflate_sync(). |
*/ |
if (flush == Z_FULL_FLUSH) { |
CLEAR_HASH(s); /* forget history */ |
+ if (s->lookahead == 0) { |
+ s->strstart = 0; |
+ s->block_start = 0L; |
+ } |
} |
} |
flush_pending(strm); |
@@ -1167,12 +1203,13 @@ |
return s->lookahead; |
} |
#endif /* ASMV */ |
-#endif /* FASTEST */ |
+#else /* FASTEST */ |
+ |
/* --------------------------------------------------------------------------- |
- * Optimized version for level == 1 or strategy == Z_RLE only |
+ * Optimized version for FASTEST only |
*/ |
-local uInt longest_match_fast(s, cur_match) |
+local uInt longest_match(s, cur_match) |
deflate_state *s; |
IPos cur_match; /* current match */ |
{ |
@@ -1225,6 +1262,8 @@ |
return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; |
} |
+#endif /* FASTEST */ |
+ |
#ifdef DEBUG |
/* =========================================================================== |
* Check that the match at match_start is indeed a match. |
@@ -1303,7 +1342,6 @@ |
later. (Using level 0 permanently is not an optimal usage of |
zlib, so we don't care about this pathological case.) |
*/ |
- /* %%% avoid this when Z_RLE */ |
n = s->hash_size; |
p = &s->head[n]; |
do { |
@@ -1355,27 +1393,61 @@ |
*/ |
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); |
+ |
+ /* If the WIN_INIT bytes after the end of the current data have never been |
+ * written, then zero those bytes in order to avoid memory check reports of |
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by |
+ * the longest match routines. Update the high water mark for the next |
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match |
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. |
+ */ |
+ if (s->high_water < s->window_size) { |
+ ulg curr = s->strstart + (ulg)(s->lookahead); |
+ ulg init; |
+ |
+ if (s->high_water < curr) { |
+ /* Previous high water mark below current data -- zero WIN_INIT |
+ * bytes or up to end of window, whichever is less. |
+ */ |
+ init = s->window_size - curr; |
+ if (init > WIN_INIT) |
+ init = WIN_INIT; |
+ zmemzero(s->window + curr, (unsigned)init); |
+ s->high_water = curr + init; |
+ } |
+ else if (s->high_water < (ulg)curr + WIN_INIT) { |
+ /* High water mark at or above current data, but below current data |
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up |
+ * to end of window, whichever is less. |
+ */ |
+ init = (ulg)curr + WIN_INIT - s->high_water; |
+ if (init > s->window_size - s->high_water) |
+ init = s->window_size - s->high_water; |
+ zmemzero(s->window + s->high_water, (unsigned)init); |
+ s->high_water += init; |
+ } |
+ } |
} |
/* =========================================================================== |
* Flush the current block, with given end-of-file flag. |
* IN assertion: strstart is set to the end of the current match. |
*/ |
-#define FLUSH_BLOCK_ONLY(s, eof) { \ |
+#define FLUSH_BLOCK_ONLY(s, last) { \ |
_tr_flush_block(s, (s->block_start >= 0L ? \ |
(charf *)&s->window[(unsigned)s->block_start] : \ |
(charf *)Z_NULL), \ |
(ulg)((long)s->strstart - s->block_start), \ |
- (eof)); \ |
+ (last)); \ |
s->block_start = s->strstart; \ |
flush_pending(s->strm); \ |
Tracev((stderr,"[FLUSH]")); \ |
} |
/* Same but force premature exit if necessary. */ |
-#define FLUSH_BLOCK(s, eof) { \ |
- FLUSH_BLOCK_ONLY(s, eof); \ |
- if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ |
+#define FLUSH_BLOCK(s, last) { \ |
+ FLUSH_BLOCK_ONLY(s, last); \ |
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ |
} |
/* =========================================================================== |
@@ -1449,7 +1521,7 @@ |
deflate_state *s; |
int flush; |
{ |
- IPos hash_head = NIL; /* head of the hash chain */ |
+ IPos hash_head; /* head of the hash chain */ |
int bflush; /* set if current block must be flushed */ |
for (;;) { |
@@ -1469,6 +1541,7 @@ |
/* Insert the string window[strstart .. strstart+2] in the |
* dictionary, and set hash_head to the head of the hash chain: |
*/ |
+ hash_head = NIL; |
if (s->lookahead >= MIN_MATCH) { |
INSERT_STRING(s, s->strstart, hash_head); |
} |
@@ -1481,19 +1554,8 @@ |
* of window index 0 (in particular we have to avoid a match |
* of the string with itself at the start of the input file). |
*/ |
-#ifdef FASTEST |
- if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) || |
- (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { |
- s->match_length = longest_match_fast (s, hash_head); |
- } |
-#else |
- if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { |
- s->match_length = longest_match (s, hash_head); |
- } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { |
- s->match_length = longest_match_fast (s, hash_head); |
- } |
-#endif |
- /* longest_match() or longest_match_fast() sets match_start */ |
+ s->match_length = longest_match (s, hash_head); |
+ /* longest_match() sets match_start */ |
} |
if (s->match_length >= MIN_MATCH) { |
check_match(s, s->strstart, s->match_start, s->match_length); |
@@ -1555,7 +1617,7 @@ |
deflate_state *s; |
int flush; |
{ |
- IPos hash_head = NIL; /* head of hash chain */ |
+ IPos hash_head; /* head of hash chain */ |
int bflush; /* set if current block must be flushed */ |
/* Process the input block. */ |
@@ -1576,6 +1638,7 @@ |
/* Insert the string window[strstart .. strstart+2] in the |
* dictionary, and set hash_head to the head of the hash chain: |
*/ |
+ hash_head = NIL; |
if (s->lookahead >= MIN_MATCH) { |
INSERT_STRING(s, s->strstart, hash_head); |
} |
@@ -1591,12 +1654,8 @@ |
* of window index 0 (in particular we have to avoid a match |
* of the string with itself at the start of the input file). |
*/ |
- if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) { |
- s->match_length = longest_match (s, hash_head); |
- } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { |
- s->match_length = longest_match_fast (s, hash_head); |
- } |
- /* longest_match() or longest_match_fast() sets match_start */ |
+ s->match_length = longest_match (s, hash_head); |
+ /* longest_match() sets match_start */ |
if (s->match_length <= 5 && (s->strategy == Z_FILTERED |
#if TOO_FAR <= 32767 |
@@ -1674,7 +1733,6 @@ |
} |
#endif /* FASTEST */ |
-#if 0 |
/* =========================================================================== |
* For Z_RLE, simply look for runs of bytes, generate matches only of distance |
* one. Do not maintain a hash table. (It will be regenerated if this run of |
@@ -1684,11 +1742,9 @@ |
deflate_state *s; |
int flush; |
{ |
- int bflush; /* set if current block must be flushed */ |
- uInt run; /* length of run */ |
- uInt max; /* maximum length of run */ |
- uInt prev; /* byte at distance one to match */ |
- Bytef *scan; /* scan for end of run */ |
+ int bflush; /* set if current block must be flushed */ |
+ uInt prev; /* byte at distance one to match */ |
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */ |
for (;;) { |
/* Make sure that we always have enough lookahead, except |
@@ -1704,23 +1760,33 @@ |
} |
/* See how many times the previous byte repeats */ |
- run = 0; |
- if (s->strstart > 0) { /* if there is a previous byte, that is */ |
- max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH; |
+ s->match_length = 0; |
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) { |
scan = s->window + s->strstart - 1; |
- prev = *scan++; |
- do { |
- if (*scan++ != prev) |
- break; |
- } while (++run < max); |
+ prev = *scan; |
+ if (prev == *++scan && prev == *++scan && prev == *++scan) { |
+ strend = s->window + s->strstart + MAX_MATCH; |
+ do { |
+ } while (prev == *++scan && prev == *++scan && |
+ prev == *++scan && prev == *++scan && |
+ prev == *++scan && prev == *++scan && |
+ prev == *++scan && prev == *++scan && |
+ scan < strend); |
+ s->match_length = MAX_MATCH - (int)(strend - scan); |
+ if (s->match_length > s->lookahead) |
+ s->match_length = s->lookahead; |
+ } |
} |
/* Emit match if have run of MIN_MATCH or longer, else emit literal */ |
- if (run >= MIN_MATCH) { |
- check_match(s, s->strstart, s->strstart - 1, run); |
- _tr_tally_dist(s, 1, run - MIN_MATCH, bflush); |
- s->lookahead -= run; |
- s->strstart += run; |
+ if (s->match_length >= MIN_MATCH) { |
+ check_match(s, s->strstart, s->strstart - 1, s->match_length); |
+ |
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush); |
+ |
+ s->lookahead -= s->match_length; |
+ s->strstart += s->match_length; |
+ s->match_length = 0; |
} else { |
/* No match, output a literal byte */ |
Tracevv((stderr,"%c", s->window[s->strstart])); |
@@ -1733,4 +1799,36 @@ |
FLUSH_BLOCK(s, flush == Z_FINISH); |
return flush == Z_FINISH ? finish_done : block_done; |
} |
-#endif |
+ |
+/* =========================================================================== |
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table. |
+ * (It will be regenerated if this run of deflate switches away from Huffman.) |
+ */ |
+local block_state deflate_huff(s, flush) |
+ deflate_state *s; |
+ int flush; |
+{ |
+ int bflush; /* set if current block must be flushed */ |
+ |
+ for (;;) { |
+ /* Make sure that we have a literal to write. */ |
+ if (s->lookahead == 0) { |
+ fill_window(s); |
+ if (s->lookahead == 0) { |
+ if (flush == Z_NO_FLUSH) |
+ return need_more; |
+ break; /* flush the current block */ |
+ } |
+ } |
+ |
+ /* Output a literal byte */ |
+ s->match_length = 0; |
+ Tracevv((stderr,"%c", s->window[s->strstart])); |
+ _tr_tally_lit (s, s->window[s->strstart], bflush); |
+ s->lookahead--; |
+ s->strstart++; |
+ if (bflush) FLUSH_BLOCK(s, 0); |
+ } |
+ FLUSH_BLOCK(s, flush == Z_FINISH); |
+ return flush == Z_FINISH ? finish_done : block_done; |
+} |