Index: third_party/zlib/deflate.c |
diff --git a/third_party/zlib/deflate.c b/third_party/zlib/deflate.c |
index 02fa2f64f83edb150c409e6216f84eb94efd0de5..aa0c9c67a6dc07e8bfaa05bce6260f1e88265314 100644 |
--- a/third_party/zlib/deflate.c |
+++ b/third_party/zlib/deflate.c |
@@ -1,5 +1,5 @@ |
/* deflate.c -- compress data using the deflation algorithm |
- * Copyright (C) 1995-2013 Jean-loup Gailly and Mark Adler |
+ * Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler |
* For conditions of distribution and use, see copyright notice in zlib.h |
*/ |
@@ -53,7 +53,7 @@ |
#include "x86.h" |
const char deflate_copyright[] = |
- " deflate 1.2.8 Copyright 1995-2013 Jean-loup Gailly and Mark Adler "; |
+ " deflate 1.2.11 Copyright 1995-2017 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 |
@@ -74,6 +74,8 @@ typedef enum { |
typedef block_state (*compress_func) OF((deflate_state *s, int flush)); |
/* Compression function. Returns the block state after the call. */ |
+local int deflateStateCheck OF((z_streamp strm)); |
+local void slide_hash OF((deflate_state *s)); |
local void fill_window OF((deflate_state *s)); |
local block_state deflate_stored OF((deflate_state *s, int flush)); |
local block_state deflate_fast OF((deflate_state *s, int flush)); |
@@ -85,22 +87,20 @@ 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)); |
- |
+unsigned ZLIB_INTERNAL read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
#ifdef ASMV |
+# pragma message("Assembler code may have bugs -- use at your own risk") |
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 |
-#ifdef DEBUG |
+#ifdef ZLIB_DEBUG |
local void check_match OF((deflate_state *s, IPos start, IPos match, |
int length)); |
#endif |
-/* For fill_window_sse.c to use */ |
-ZLIB_INTERNAL int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
- |
/* From crc32.c */ |
extern void ZLIB_INTERNAL crc_reset(deflate_state *const s); |
extern void ZLIB_INTERNAL crc_finalize(deflate_state *const s); |
@@ -166,21 +166,14 @@ local const config configuration_table[10] = { |
* meaning. |
*/ |
-#define EQUAL 0 |
-/* result of memcmp for equal strings */ |
- |
-#ifndef NO_DUMMY_DECL |
-struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ |
-#endif |
- |
/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ |
-#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) |
+#define RANK(f) (((f) * 2) - ((f) > 4 ? 9 : 0)) |
/* =========================================================================== |
* Update a hash value with the given input byte |
- * IN assertion: all calls to to UPDATE_HASH are made with consecutive |
- * input characters, so that a running hash key can be computed from the |
- * previous key instead of complete recalculation each time. |
+ * IN assertion: all calls to UPDATE_HASH are made with consecutive input |
+ * characters, so that a running hash key can be computed from the previous |
+ * key instead of complete recalculation each time. |
*/ |
#define UPDATE_HASH(s,h,c) (h = (((h)<<s->hash_shift) ^ (c)) & s->hash_mask) |
@@ -190,9 +183,9 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ |
* the previous length of the hash chain. |
* If this file is compiled with -DFASTEST, the compression level is forced |
* to 1, and no hash chains are maintained. |
- * IN assertion: all calls to to INSERT_STRING are made with consecutive |
- * input characters and the first MIN_MATCH bytes of str are valid |
- * (except for the last MIN_MATCH-1 bytes of the input file). |
+ * IN assertion: all calls to INSERT_STRING are made with consecutive input |
+ * characters and the first MIN_MATCH bytes of str are valid (except for |
+ * the last MIN_MATCH-1 bytes of the input file). |
*/ |
local INLINE Pos insert_string_c(deflate_state *const s, const Pos str) |
{ |
@@ -225,6 +218,37 @@ local INLINE Pos insert_string(deflate_state *const s, const Pos str) |
s->head[s->hash_size-1] = NIL; \ |
zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); |
+/* =========================================================================== |
+ * Slide the hash table when sliding the window down (could be avoided with 32 |
+ * bit values at the expense of memory usage). We slide even when level == 0 to |
+ * keep the hash table consistent if we switch back to level > 0 later. |
+ */ |
+local void slide_hash(s) |
+ deflate_state *s; |
+{ |
+ unsigned n, m; |
+ Posf *p; |
+ uInt wsize = s->w_size; |
+ |
+ n = s->hash_size; |
+ p = &s->head[n]; |
+ do { |
+ m = *--p; |
+ *p = (Pos)(m >= wsize ? m - wsize : NIL); |
+ } while (--n); |
+ n = wsize; |
+#ifndef FASTEST |
+ p = &s->prev[n]; |
+ do { |
+ m = *--p; |
+ *p = (Pos)(m >= wsize ? m - wsize : NIL); |
+ /* If n is not on any hash chain, prev[n] is garbage but |
+ * its value will never be used. |
+ */ |
+ } while (--n); |
+#endif |
+} |
+ |
/* ========================================================================= */ |
int ZEXPORT deflateInit_(strm, level, version, stream_size) |
z_streamp strm; |
@@ -301,7 +325,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
#endif |
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || |
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || |
- strategy < 0 || strategy > Z_FIXED) { |
+ strategy < 0 || strategy > Z_FIXED || (windowBits == 8 && wrap != 1)) { |
return Z_STREAM_ERROR; |
} |
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ |
@@ -309,10 +333,11 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
if (s == Z_NULL) return Z_MEM_ERROR; |
strm->state = (struct internal_state FAR *)s; |
s->strm = strm; |
+ s->status = INIT_STATE; /* to pass state test in deflateReset() */ |
s->wrap = wrap; |
s->gzhead = Z_NULL; |
- s->w_bits = windowBits; |
+ s->w_bits = (uInt)windowBits; |
s->w_size = 1 << s->w_bits; |
s->w_mask = s->w_size - 1; |
@@ -326,7 +351,9 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
s->hash_mask = s->hash_size - 1; |
s->hash_shift = ((s->hash_bits+MIN_MATCH-1)/MIN_MATCH); |
- s->window = (Bytef *) ZALLOC(strm, s->w_size + window_padding, 2*sizeof(Byte)); |
+ s->window = (Bytef *) ZALLOC(strm, |
+ s->w_size + window_padding, |
+ 2*sizeof(Byte)); |
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); |
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); |
@@ -355,6 +382,31 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
return deflateReset(strm); |
} |
+/* ========================================================================= |
+ * Check for a valid deflate stream state. Return 0 if ok, 1 if not. |
+ */ |
+local int deflateStateCheck (strm) |
+ z_streamp strm; |
+{ |
+ deflate_state *s; |
+ if (strm == Z_NULL || |
+ strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) |
+ return 1; |
+ s = strm->state; |
+ if (s == Z_NULL || s->strm != strm || (s->status != INIT_STATE && |
+#ifdef GZIP |
+ s->status != GZIP_STATE && |
+#endif |
+ s->status != EXTRA_STATE && |
+ s->status != NAME_STATE && |
+ s->status != COMMENT_STATE && |
+ s->status != HCRC_STATE && |
+ s->status != BUSY_STATE && |
+ s->status != FINISH_STATE)) |
+ return 1; |
+ return 0; |
+} |
+ |
/* ========================================================================= */ |
int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) |
z_streamp strm; |
@@ -367,7 +419,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) |
unsigned avail; |
z_const unsigned char *next; |
- if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) |
+ if (deflateStateCheck(strm) || dictionary == Z_NULL) |
return Z_STREAM_ERROR; |
s = strm->state; |
wrap = s->wrap; |
@@ -421,13 +473,34 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) |
} |
/* ========================================================================= */ |
+int ZEXPORT deflateGetDictionary (strm, dictionary, dictLength) |
+ z_streamp strm; |
+ Bytef *dictionary; |
+ uInt *dictLength; |
+{ |
+ deflate_state *s; |
+ uInt len; |
+ |
+ if (deflateStateCheck(strm)) |
+ return Z_STREAM_ERROR; |
+ s = strm->state; |
+ len = s->strstart + s->lookahead; |
+ if (len > s->w_size) |
+ len = s->w_size; |
+ if (dictionary != Z_NULL && len) |
+ zmemcpy(dictionary, s->window + s->strstart + s->lookahead - len, len); |
+ if (dictLength != Z_NULL) |
+ *dictLength = len; |
+ return Z_OK; |
+} |
+ |
+/* ========================================================================= */ |
int ZEXPORT deflateResetKeep (strm) |
z_streamp strm; |
{ |
deflate_state *s; |
- if (strm == Z_NULL || strm->state == Z_NULL || |
- strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) { |
+ if (deflateStateCheck(strm)) { |
return Z_STREAM_ERROR; |
} |
@@ -442,7 +515,11 @@ int ZEXPORT deflateResetKeep (strm) |
if (s->wrap < 0) { |
s->wrap = -s->wrap; /* was made negative by deflate(..., Z_FINISH); */ |
} |
- s->status = s->wrap ? INIT_STATE : BUSY_STATE; |
+ s->status = |
+#ifdef GZIP |
+ s->wrap == 2 ? GZIP_STATE : |
+#endif |
+ s->wrap ? INIT_STATE : BUSY_STATE; |
strm->adler = |
#ifdef GZIP |
s->wrap == 2 ? crc32(0L, Z_NULL, 0) : |
@@ -472,8 +549,8 @@ int ZEXPORT deflateSetHeader (strm, head) |
z_streamp strm; |
gz_headerp head; |
{ |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
- if (strm->state->wrap != 2) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm) || strm->state->wrap != 2) |
+ return Z_STREAM_ERROR; |
strm->state->gzhead = head; |
return Z_OK; |
} |
@@ -484,7 +561,7 @@ int ZEXPORT deflatePending (strm, pending, bits) |
int *bits; |
z_streamp strm; |
{ |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR; |
if (pending != Z_NULL) |
*pending = strm->state->pending; |
if (bits != Z_NULL) |
@@ -501,7 +578,7 @@ int ZEXPORT deflatePrime (strm, bits, value) |
deflate_state *s; |
int put; |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR; |
s = strm->state; |
if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) |
return Z_BUF_ERROR; |
@@ -526,9 +603,8 @@ int ZEXPORT deflateParams(strm, level, strategy) |
{ |
deflate_state *s; |
compress_func func; |
- int err = Z_OK; |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR; |
s = strm->state; |
#ifdef FASTEST |
@@ -542,13 +618,22 @@ int ZEXPORT deflateParams(strm, level, strategy) |
func = configuration_table[s->level].func; |
if ((strategy != s->strategy || func != configuration_table[level].func) && |
- strm->total_in != 0) { |
+ s->high_water) { |
/* Flush the last buffer: */ |
- err = deflate(strm, Z_BLOCK); |
- if (err == Z_BUF_ERROR && s->pending == 0) |
- err = Z_OK; |
+ int err = deflate(strm, Z_BLOCK); |
+ if (err == Z_STREAM_ERROR) |
+ return err; |
+ if (strm->avail_out == 0) |
+ return Z_BUF_ERROR; |
} |
if (s->level != level) { |
+ if (s->level == 0 && s->matches != 0) { |
+ if (s->matches == 1) |
+ slide_hash(s); |
+ else |
+ CLEAR_HASH(s); |
+ s->matches = 0; |
+ } |
s->level = level; |
s->max_lazy_match = configuration_table[level].max_lazy; |
s->good_match = configuration_table[level].good_length; |
@@ -556,7 +641,7 @@ int ZEXPORT deflateParams(strm, level, strategy) |
s->max_chain_length = configuration_table[level].max_chain; |
} |
s->strategy = strategy; |
- return err; |
+ return Z_OK; |
} |
/* ========================================================================= */ |
@@ -569,12 +654,12 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain) |
{ |
deflate_state *s; |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR; |
s = strm->state; |
- s->good_match = good_length; |
- s->max_lazy_match = max_lazy; |
+ s->good_match = (uInt)good_length; |
+ s->max_lazy_match = (uInt)max_lazy; |
s->nice_match = nice_length; |
- s->max_chain_length = max_chain; |
+ s->max_chain_length = (uInt)max_chain; |
return Z_OK; |
} |
@@ -601,14 +686,13 @@ uLong ZEXPORT deflateBound(strm, sourceLen) |
{ |
deflate_state *s; |
uLong complen, wraplen; |
- Bytef *str; |
/* conservative upper bound for compressed data */ |
complen = sourceLen + |
((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5; |
/* if can't get parameters, return conservative bound plus zlib wrapper */ |
- if (strm == Z_NULL || strm->state == Z_NULL) |
+ if (deflateStateCheck(strm)) |
return complen + 6; |
/* compute wrapper length */ |
@@ -620,9 +704,11 @@ uLong ZEXPORT deflateBound(strm, sourceLen) |
case 1: /* zlib wrapper */ |
wraplen = 6 + (s->strstart ? 4 : 0); |
break; |
+#ifdef GZIP |
case 2: /* gzip wrapper */ |
wraplen = 18; |
if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ |
+ Bytef *str; |
if (s->gzhead->extra != Z_NULL) |
wraplen += 2 + s->gzhead->extra_len; |
str = s->gzhead->name; |
@@ -639,6 +725,7 @@ uLong ZEXPORT deflateBound(strm, sourceLen) |
wraplen += 2; |
} |
break; |
+#endif |
default: /* for compiler happiness */ |
wraplen = 6; |
} |
@@ -666,10 +753,10 @@ local void putShortMSB (s, b) |
} |
/* ========================================================================= |
- * Flush as much pending output as possible. All deflate() output goes |
- * through this function so some applications may wish to modify it |
- * to avoid allocating a large strm->next_out buffer and copying into it. |
- * (See also read_buf()). |
+ * Flush as much pending output as possible. All deflate() output, except for |
+ * some deflate_stored() output, goes through this function so some |
+ * applications may wish to modify it to avoid allocating a large |
+ * strm->next_out buffer and copying into it. (See also read_buf()). |
*/ |
local void flush_pending(strm) |
z_streamp strm; |
@@ -686,13 +773,23 @@ local void flush_pending(strm) |
strm->next_out += len; |
s->pending_out += len; |
strm->total_out += len; |
- strm->avail_out -= len; |
- s->pending -= len; |
+ strm->avail_out -= len; |
+ s->pending -= len; |
if (s->pending == 0) { |
s->pending_out = s->pending_buf; |
} |
} |
+/* =========================================================================== |
+ * Update the header CRC with the bytes s->pending_buf[beg..s->pending - 1]. |
+ */ |
+#define HCRC_UPDATE(beg) \ |
+ do { \ |
+ if (s->gzhead->hcrc && s->pending > (beg)) \ |
+ strm->adler = crc32(strm->adler, s->pending_buf + (beg), \ |
+ s->pending - (beg)); \ |
+ } while (0) |
+ |
/* ========================================================================= */ |
int ZEXPORT deflate (strm, flush) |
z_streamp strm; |
@@ -701,230 +798,229 @@ int ZEXPORT deflate (strm, flush) |
int old_flush; /* value of flush param for previous deflate call */ |
deflate_state *s; |
- if (strm == Z_NULL || strm->state == Z_NULL || |
- flush > Z_BLOCK || flush < 0) { |
+ if (deflateStateCheck(strm) || flush > Z_BLOCK || flush < 0) { |
return Z_STREAM_ERROR; |
} |
s = strm->state; |
if (strm->next_out == Z_NULL || |
- (strm->next_in == Z_NULL && strm->avail_in != 0) || |
+ (strm->avail_in != 0 && strm->next_in == Z_NULL) || |
(s->status == FINISH_STATE && flush != Z_FINISH)) { |
ERR_RETURN(strm, Z_STREAM_ERROR); |
} |
if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); |
- s->strm = strm; /* just in case */ |
old_flush = s->last_flush; |
s->last_flush = flush; |
+ /* Flush as much pending output as possible */ |
+ if (s->pending != 0) { |
+ flush_pending(strm); |
+ if (strm->avail_out == 0) { |
+ /* Since avail_out is 0, deflate will be called again with |
+ * more output space, but possibly with both pending and |
+ * avail_in equal to zero. There won't be anything to do, |
+ * but this is not an error situation so make sure we |
+ * return OK instead of BUF_ERROR at next call of deflate: |
+ */ |
+ s->last_flush = -1; |
+ return Z_OK; |
+ } |
+ |
+ /* Make sure there is something to do and avoid duplicate consecutive |
+ * flushes. For repeated and useless calls with Z_FINISH, we keep |
+ * returning Z_STREAM_END instead of Z_BUF_ERROR. |
+ */ |
+ } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && |
+ flush != Z_FINISH) { |
+ ERR_RETURN(strm, Z_BUF_ERROR); |
+ } |
+ |
+ /* User must not provide more input after the first FINISH: */ |
+ if (s->status == FINISH_STATE && strm->avail_in != 0) { |
+ ERR_RETURN(strm, Z_BUF_ERROR); |
+ } |
+ |
/* Write the header */ |
if (s->status == INIT_STATE) { |
-#ifdef GZIP |
- if (s->wrap == 2) { |
- crc_reset(s); |
- put_byte(s, 31); |
- put_byte(s, 139); |
- put_byte(s, 8); |
- if (s->gzhead == Z_NULL) { |
- put_byte(s, 0); |
- put_byte(s, 0); |
- put_byte(s, 0); |
- put_byte(s, 0); |
- put_byte(s, 0); |
- put_byte(s, s->level == 9 ? 2 : |
- (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
- 4 : 0)); |
- put_byte(s, OS_CODE); |
- s->status = BUSY_STATE; |
- } |
- else { |
- put_byte(s, (s->gzhead->text ? 1 : 0) + |
- (s->gzhead->hcrc ? 2 : 0) + |
- (s->gzhead->extra == Z_NULL ? 0 : 4) + |
- (s->gzhead->name == Z_NULL ? 0 : 8) + |
- (s->gzhead->comment == Z_NULL ? 0 : 16) |
- ); |
- put_byte(s, (Byte)(s->gzhead->time & 0xff)); |
- put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); |
- put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); |
- put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); |
- put_byte(s, s->level == 9 ? 2 : |
- (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
- 4 : 0)); |
- put_byte(s, s->gzhead->os & 0xff); |
- if (s->gzhead->extra != Z_NULL) { |
- put_byte(s, s->gzhead->extra_len & 0xff); |
- put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); |
- } |
- if (s->gzhead->hcrc) |
- strm->adler = crc32(strm->adler, s->pending_buf, |
- s->pending); |
- s->gzindex = 0; |
- s->status = EXTRA_STATE; |
- } |
- } |
+ /* zlib header */ |
+ uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; |
+ uInt level_flags; |
+ |
+ if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) |
+ level_flags = 0; |
+ else if (s->level < 6) |
+ level_flags = 1; |
+ else if (s->level == 6) |
+ level_flags = 2; |
else |
-#endif |
- { |
- uInt header = (Z_DEFLATED + ((s->w_bits-8)<<4)) << 8; |
- uInt level_flags; |
- |
- if (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2) |
- level_flags = 0; |
- else if (s->level < 6) |
- level_flags = 1; |
- else if (s->level == 6) |
- level_flags = 2; |
- else |
- level_flags = 3; |
- header |= (level_flags << 6); |
- if (s->strstart != 0) header |= PRESET_DICT; |
- header += 31 - (header % 31); |
+ level_flags = 3; |
+ header |= (level_flags << 6); |
+ if (s->strstart != 0) header |= PRESET_DICT; |
+ header += 31 - (header % 31); |
+ |
+ putShortMSB(s, header); |
+ |
+ /* Save the adler32 of the preset dictionary: */ |
+ if (s->strstart != 0) { |
+ putShortMSB(s, (uInt)(strm->adler >> 16)); |
+ putShortMSB(s, (uInt)(strm->adler & 0xffff)); |
+ } |
+ strm->adler = adler32(0L, Z_NULL, 0); |
+ s->status = BUSY_STATE; |
+ /* Compression must start with an empty pending buffer */ |
+ flush_pending(strm); |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
+ } |
+ } |
+#ifdef GZIP |
+ if (s->status == GZIP_STATE) { |
+ /* gzip header */ |
+ crc_reset(s); |
+ put_byte(s, 31); |
+ put_byte(s, 139); |
+ put_byte(s, 8); |
+ if (s->gzhead == Z_NULL) { |
+ put_byte(s, 0); |
+ put_byte(s, 0); |
+ put_byte(s, 0); |
+ put_byte(s, 0); |
+ put_byte(s, 0); |
+ put_byte(s, s->level == 9 ? 2 : |
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
+ 4 : 0)); |
+ put_byte(s, OS_CODE); |
s->status = BUSY_STATE; |
- putShortMSB(s, header); |
- /* Save the adler32 of the preset dictionary: */ |
- if (s->strstart != 0) { |
- putShortMSB(s, (uInt)(strm->adler >> 16)); |
- putShortMSB(s, (uInt)(strm->adler & 0xffff)); |
+ /* Compression must start with an empty pending buffer */ |
+ flush_pending(strm); |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
+ } |
+ } |
+ else { |
+ put_byte(s, (s->gzhead->text ? 1 : 0) + |
+ (s->gzhead->hcrc ? 2 : 0) + |
+ (s->gzhead->extra == Z_NULL ? 0 : 4) + |
+ (s->gzhead->name == Z_NULL ? 0 : 8) + |
+ (s->gzhead->comment == Z_NULL ? 0 : 16) |
+ ); |
+ put_byte(s, (Byte)(s->gzhead->time & 0xff)); |
+ put_byte(s, (Byte)((s->gzhead->time >> 8) & 0xff)); |
+ put_byte(s, (Byte)((s->gzhead->time >> 16) & 0xff)); |
+ put_byte(s, (Byte)((s->gzhead->time >> 24) & 0xff)); |
+ put_byte(s, s->level == 9 ? 2 : |
+ (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
+ 4 : 0)); |
+ put_byte(s, s->gzhead->os & 0xff); |
+ if (s->gzhead->extra != Z_NULL) { |
+ put_byte(s, s->gzhead->extra_len & 0xff); |
+ put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); |
} |
- strm->adler = adler32(0L, Z_NULL, 0); |
+ if (s->gzhead->hcrc) |
+ strm->adler = crc32(strm->adler, s->pending_buf, |
+ s->pending); |
+ s->gzindex = 0; |
+ s->status = EXTRA_STATE; |
} |
} |
-#ifdef GZIP |
if (s->status == EXTRA_STATE) { |
if (s->gzhead->extra != Z_NULL) { |
- uInt beg = s->pending; /* start of bytes to update crc */ |
- |
- while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { |
- if (s->pending == s->pending_buf_size) { |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
- flush_pending(strm); |
- beg = s->pending; |
- if (s->pending == s->pending_buf_size) |
- break; |
+ ulg beg = s->pending; /* start of bytes to update crc */ |
+ uInt left = (s->gzhead->extra_len & 0xffff) - s->gzindex; |
+ while (s->pending + left > s->pending_buf_size) { |
+ uInt copy = s->pending_buf_size - s->pending; |
+ zmemcpy(s->pending_buf + s->pending, |
+ s->gzhead->extra + s->gzindex, copy); |
+ s->pending = s->pending_buf_size; |
+ HCRC_UPDATE(beg); |
+ s->gzindex += copy; |
+ flush_pending(strm); |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
} |
- put_byte(s, s->gzhead->extra[s->gzindex]); |
- s->gzindex++; |
- } |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
- if (s->gzindex == s->gzhead->extra_len) { |
- s->gzindex = 0; |
- s->status = NAME_STATE; |
+ beg = 0; |
+ left -= copy; |
} |
+ zmemcpy(s->pending_buf + s->pending, |
+ s->gzhead->extra + s->gzindex, left); |
+ s->pending += left; |
+ HCRC_UPDATE(beg); |
+ s->gzindex = 0; |
} |
- else |
- s->status = NAME_STATE; |
+ s->status = NAME_STATE; |
} |
if (s->status == NAME_STATE) { |
if (s->gzhead->name != Z_NULL) { |
- uInt beg = s->pending; /* start of bytes to update crc */ |
+ ulg beg = s->pending; /* start of bytes to update crc */ |
int val; |
- |
do { |
if (s->pending == s->pending_buf_size) { |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
+ HCRC_UPDATE(beg); |
flush_pending(strm); |
- beg = s->pending; |
- if (s->pending == s->pending_buf_size) { |
- val = 1; |
- break; |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
} |
+ beg = 0; |
} |
val = s->gzhead->name[s->gzindex++]; |
put_byte(s, val); |
} while (val != 0); |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
- if (val == 0) { |
- s->gzindex = 0; |
- s->status = COMMENT_STATE; |
- } |
+ HCRC_UPDATE(beg); |
+ s->gzindex = 0; |
} |
- else |
- s->status = COMMENT_STATE; |
+ s->status = COMMENT_STATE; |
} |
if (s->status == COMMENT_STATE) { |
if (s->gzhead->comment != Z_NULL) { |
- uInt beg = s->pending; /* start of bytes to update crc */ |
+ ulg beg = s->pending; /* start of bytes to update crc */ |
int val; |
- |
do { |
if (s->pending == s->pending_buf_size) { |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
+ HCRC_UPDATE(beg); |
flush_pending(strm); |
- beg = s->pending; |
- if (s->pending == s->pending_buf_size) { |
- val = 1; |
- break; |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
} |
+ beg = 0; |
} |
val = s->gzhead->comment[s->gzindex++]; |
put_byte(s, val); |
} while (val != 0); |
- if (s->gzhead->hcrc && s->pending > beg) |
- strm->adler = crc32(strm->adler, s->pending_buf + beg, |
- s->pending - beg); |
- if (val == 0) |
- s->status = HCRC_STATE; |
+ HCRC_UPDATE(beg); |
} |
- else |
- s->status = HCRC_STATE; |
+ s->status = HCRC_STATE; |
} |
if (s->status == HCRC_STATE) { |
if (s->gzhead->hcrc) { |
- if (s->pending + 2 > s->pending_buf_size) |
+ if (s->pending + 2 > s->pending_buf_size) { |
flush_pending(strm); |
- if (s->pending + 2 <= s->pending_buf_size) { |
- put_byte(s, (Byte)(strm->adler & 0xff)); |
- put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); |
- strm->adler = crc32(0L, Z_NULL, 0); |
- s->status = BUSY_STATE; |
+ if (s->pending != 0) { |
+ s->last_flush = -1; |
+ return Z_OK; |
+ } |
} |
+ put_byte(s, (Byte)(strm->adler & 0xff)); |
+ put_byte(s, (Byte)((strm->adler >> 8) & 0xff)); |
+ strm->adler = crc32(0L, Z_NULL, 0); |
} |
- else |
- s->status = BUSY_STATE; |
- } |
-#endif |
+ s->status = BUSY_STATE; |
- /* Flush as much pending output as possible */ |
- if (s->pending != 0) { |
+ /* Compression must start with an empty pending buffer */ |
flush_pending(strm); |
- if (strm->avail_out == 0) { |
- /* Since avail_out is 0, deflate will be called again with |
- * more output space, but possibly with both pending and |
- * avail_in equal to zero. There won't be anything to do, |
- * but this is not an error situation so make sure we |
- * return OK instead of BUF_ERROR at next call of deflate: |
- */ |
+ if (s->pending != 0) { |
s->last_flush = -1; |
return Z_OK; |
} |
- |
- /* Make sure there is something to do and avoid duplicate consecutive |
- * flushes. For repeated and useless calls with Z_FINISH, we keep |
- * returning Z_STREAM_END instead of Z_BUF_ERROR. |
- */ |
- } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && |
- flush != Z_FINISH) { |
- ERR_RETURN(strm, Z_BUF_ERROR); |
- } |
- |
- /* User must not provide more input after the first FINISH: */ |
- if (s->status == FINISH_STATE && strm->avail_in != 0) { |
- ERR_RETURN(strm, Z_BUF_ERROR); |
} |
+#endif |
/* Start a new block or continue the current one. |
*/ |
@@ -932,9 +1028,10 @@ int ZEXPORT deflate (strm, flush) |
(flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
block_state bstate; |
- 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)); |
+ bstate = s->level == 0 ? deflate_stored(s, flush) : |
+ 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; |
@@ -976,7 +1073,6 @@ int ZEXPORT deflate (strm, flush) |
} |
} |
} |
- Assert(strm->avail_out > 0, "bug2"); |
if (flush != Z_FINISH) return Z_OK; |
if (s->wrap <= 0) return Z_STREAM_END; |
@@ -1014,18 +1110,9 @@ int ZEXPORT deflateEnd (strm) |
{ |
int status; |
- if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
+ if (deflateStateCheck(strm)) return Z_STREAM_ERROR; |
status = strm->state->status; |
- if (status != INIT_STATE && |
- status != EXTRA_STATE && |
- status != NAME_STATE && |
- status != COMMENT_STATE && |
- status != HCRC_STATE && |
- status != BUSY_STATE && |
- status != FINISH_STATE) { |
- return Z_STREAM_ERROR; |
- } |
/* Deallocate in reverse order of allocations: */ |
TRY_FREE(strm, strm->state->pending_buf); |
@@ -1056,7 +1143,7 @@ int ZEXPORT deflateCopy (dest, source) |
ushf *overlay; |
- if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { |
+ if (deflateStateCheck(source) || dest == Z_NULL) { |
return Z_STREAM_ERROR; |
} |
@@ -1106,7 +1193,7 @@ int ZEXPORT deflateCopy (dest, source) |
* allocating a large strm->next_in buffer and copying from it. |
* (See also flush_pending()). |
*/ |
-ZLIB_INTERNAL int read_buf(strm, buf, size) |
+ZLIB_INTERNAL unsigned read_buf(strm, buf, size) |
z_streamp strm; |
Bytef *buf; |
unsigned size; |
@@ -1131,7 +1218,7 @@ ZLIB_INTERNAL int read_buf(strm, buf, size) |
strm->next_in += len; |
strm->total_in += len; |
- return (int)len; |
+ return len; |
} |
/* =========================================================================== |
@@ -1185,9 +1272,9 @@ local uInt longest_match(s, cur_match) |
{ |
unsigned chain_length = s->max_chain_length;/* max hash chain length */ |
register Bytef *scan = s->window + s->strstart; /* current string */ |
- register Bytef *match; /* matched string */ |
+ register Bytef *match; /* matched string */ |
register int len; /* length of current match */ |
- int best_len = s->prev_length; /* best match length so far */ |
+ int best_len = (int)s->prev_length; /* best match length so far */ |
int nice_match = s->nice_match; /* stop if match long enough */ |
IPos limit = s->strstart > (IPos)MAX_DIST(s) ? |
s->strstart - (IPos)MAX_DIST(s) : NIL; |
@@ -1222,7 +1309,7 @@ local uInt longest_match(s, cur_match) |
/* Do not look for matches beyond the end of the input. This is necessary |
* to make deflate deterministic. |
*/ |
- if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; |
+ if ((uInt)nice_match > s->lookahead) nice_match = (int)s->lookahead; |
Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); |
@@ -1383,7 +1470,11 @@ local uInt longest_match(s, cur_match) |
#endif /* FASTEST */ |
-#ifdef DEBUG |
+#ifdef ZLIB_DEBUG |
+ |
+#define EQUAL 0 |
+/* result of memcmp for equal strings */ |
+ |
/* =========================================================================== |
* Check that the match at match_start is indeed a match. |
*/ |
@@ -1409,7 +1500,7 @@ local void check_match(s, start, match, length) |
} |
#else |
# define check_match(s, start, match, length) |
-#endif /* DEBUG */ |
+#endif /* ZLIB_DEBUG */ |
/* =========================================================================== |
* Fill the window when the lookahead becomes insufficient. |
@@ -1436,8 +1527,7 @@ local void fill_window(deflate_state *s) |
local void fill_window_c(s) |
deflate_state *s; |
{ |
- register unsigned n, m; |
- register Posf *p; |
+ unsigned n; |
unsigned more; /* Amount of free space at the end of the window. */ |
uInt wsize = s->w_size; |
@@ -1464,35 +1554,11 @@ local void fill_window_c(s) |
*/ |
if (s->strstart >= wsize+MAX_DIST(s)) { |
- zmemcpy(s->window, s->window+wsize, (unsigned)wsize); |
+ zmemcpy(s->window, s->window+wsize, (unsigned)wsize - more); |
s->match_start -= wsize; |
s->strstart -= wsize; /* we now have strstart >= MAX_DIST */ |
s->block_start -= (long) wsize; |
- |
- /* Slide the hash table (could be avoided with 32 bit values |
- at the expense of memory usage). We slide even when level == 0 |
- to keep the hash table consistent if we switch back to level > 0 |
- later. (Using level 0 permanently is not an optimal usage of |
- zlib, so we don't care about this pathological case.) |
- */ |
- n = s->hash_size; |
- p = &s->head[n]; |
- do { |
- m = *--p; |
- *p = (Pos)(m >= wsize ? m-wsize : NIL); |
- } while (--n); |
- |
- n = wsize; |
-#ifndef FASTEST |
- p = &s->prev[n]; |
- do { |
- m = *--p; |
- *p = (Pos)(m >= wsize ? m-wsize : NIL); |
- /* If n is not on any hash chain, prev[n] is garbage but |
- * its value will never be used. |
- */ |
- } while (--n); |
-#endif |
+ slide_hash(s); |
more += wsize; |
} |
if (s->strm->avail_in == 0) break; |
@@ -1598,70 +1664,199 @@ local void fill_window_c(s) |
if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \ |
} |
+/* Maximum stored block length in deflate format (not including header). */ |
+#define MAX_STORED 65535 |
+ |
+/* Minimum of a and b. */ |
+#define MIN(a, b) ((a) > (b) ? (b) : (a)) |
+ |
/* =========================================================================== |
* Copy without compression as much as possible from the input stream, return |
* the current block state. |
- * This function does not insert new strings in the dictionary since |
- * uncompressible data is probably not useful. This function is used |
- * only for the level=0 compression option. |
- * NOTE: this function should be optimized to avoid extra copying from |
- * window to pending_buf. |
+ * |
+ * In case deflateParams() is used to later switch to a non-zero compression |
+ * level, s->matches (otherwise unused when storing) keeps track of the number |
+ * of hash table slides to perform. If s->matches is 1, then one hash table |
+ * slide will be done when switching. If s->matches is 2, the maximum value |
+ * allowed here, then the hash table will be cleared, since two or more slides |
+ * is the same as a clear. |
+ * |
+ * deflate_stored() is written to minimize the number of times an input byte is |
+ * copied. It is most efficient with large input and output buffers, which |
+ * maximizes the opportunites to have a single copy from next_in to next_out. |
*/ |
local block_state deflate_stored(s, flush) |
deflate_state *s; |
int flush; |
{ |
- /* Stored blocks are limited to 0xffff bytes, pending_buf is limited |
- * to pending_buf_size, and each stored block has a 5 byte header: |
+ /* Smallest worthy block size when not flushing or finishing. By default |
+ * this is 32K. This can be as small as 507 bytes for memLevel == 1. For |
+ * large input and output buffers, the stored block size will be larger. |
*/ |
- ulg max_block_size = 0xffff; |
- ulg max_start; |
- |
- if (max_block_size > s->pending_buf_size - 5) { |
- max_block_size = s->pending_buf_size - 5; |
- } |
+ unsigned min_block = MIN(s->pending_buf_size - 5, s->w_size); |
- /* Copy as much as possible from input to output: */ |
- for (;;) { |
- /* Fill the window as much as possible: */ |
- if (s->lookahead <= 1) { |
- |
- Assert(s->strstart < s->w_size+MAX_DIST(s) || |
- s->block_start >= (long)s->w_size, "slide too late"); |
+ /* Copy as many min_block or larger stored blocks directly to next_out as |
+ * possible. If flushing, copy the remaining available input to next_out as |
+ * stored blocks, if there is enough space. |
+ */ |
+ unsigned len, left, have, last = 0; |
+ unsigned used = s->strm->avail_in; |
+ do { |
+ /* Set len to the maximum size block that we can copy directly with the |
+ * available input data and output space. Set left to how much of that |
+ * would be copied from what's left in the window. |
+ */ |
+ len = MAX_STORED; /* maximum deflate stored block length */ |
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ |
+ if (s->strm->avail_out < have) /* need room for header */ |
+ break; |
+ /* maximum stored block length that will fit in avail_out: */ |
+ have = s->strm->avail_out - have; |
+ left = s->strstart - s->block_start; /* bytes left in window */ |
+ if (len > (ulg)left + s->strm->avail_in) |
+ len = left + s->strm->avail_in; /* limit len to the input */ |
+ if (len > have) |
+ len = have; /* limit len to the output */ |
+ |
+ /* If the stored block would be less than min_block in length, or if |
+ * unable to copy all of the available input when flushing, then try |
+ * copying to the window and the pending buffer instead. Also don't |
+ * write an empty block when flushing -- deflate() does that. |
+ */ |
+ if (len < min_block && ((len == 0 && flush != Z_FINISH) || |
+ flush == Z_NO_FLUSH || |
+ len != left + s->strm->avail_in)) |
+ break; |
- fill_window(s); |
- if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; |
+ /* Make a dummy stored block in pending to get the header bytes, |
+ * including any pending bits. This also updates the debugging counts. |
+ */ |
+ last = flush == Z_FINISH && len == left + s->strm->avail_in ? 1 : 0; |
+ _tr_stored_block(s, (char *)0, 0L, last); |
+ |
+ /* Replace the lengths in the dummy stored block with len. */ |
+ s->pending_buf[s->pending - 4] = len; |
+ s->pending_buf[s->pending - 3] = len >> 8; |
+ s->pending_buf[s->pending - 2] = ~len; |
+ s->pending_buf[s->pending - 1] = ~len >> 8; |
+ |
+ /* Write the stored block header bytes. */ |
+ flush_pending(s->strm); |
+ |
+#ifdef ZLIB_DEBUG |
+ /* Update debugging counts for the data about to be copied. */ |
+ s->compressed_len += len << 3; |
+ s->bits_sent += len << 3; |
+#endif |
- if (s->lookahead == 0) break; /* flush the current block */ |
+ /* Copy uncompressed bytes from the window to next_out. */ |
+ if (left) { |
+ if (left > len) |
+ left = len; |
+ zmemcpy(s->strm->next_out, s->window + s->block_start, left); |
+ s->strm->next_out += left; |
+ s->strm->avail_out -= left; |
+ s->strm->total_out += left; |
+ s->block_start += left; |
+ len -= left; |
} |
- Assert(s->block_start >= 0L, "block gone"); |
- |
- s->strstart += s->lookahead; |
- s->lookahead = 0; |
- |
- /* Emit a stored block if pending_buf will be full: */ |
- max_start = s->block_start + max_block_size; |
- if (s->strstart == 0 || (ulg)s->strstart >= max_start) { |
- /* strstart == 0 is possible when wraparound on 16-bit machine */ |
- s->lookahead = (uInt)(s->strstart - max_start); |
- s->strstart = (uInt)max_start; |
- FLUSH_BLOCK(s, 0); |
+ |
+ /* Copy uncompressed bytes directly from next_in to next_out, updating |
+ * the check value. |
+ */ |
+ if (len) { |
+ read_buf(s->strm, s->strm->next_out, len); |
+ s->strm->next_out += len; |
+ s->strm->avail_out -= len; |
+ s->strm->total_out += len; |
} |
- /* Flush if we may have to slide, otherwise block_start may become |
- * negative and the data will be gone: |
+ } while (last == 0); |
+ |
+ /* Update the sliding window with the last s->w_size bytes of the copied |
+ * data, or append all of the copied data to the existing window if less |
+ * than s->w_size bytes were copied. Also update the number of bytes to |
+ * insert in the hash tables, in the event that deflateParams() switches to |
+ * a non-zero compression level. |
+ */ |
+ used -= s->strm->avail_in; /* number of input bytes directly copied */ |
+ if (used) { |
+ /* If any input was used, then no unused input remains in the window, |
+ * therefore s->block_start == s->strstart. |
*/ |
- if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { |
- FLUSH_BLOCK(s, 0); |
+ if (used >= s->w_size) { /* supplant the previous history */ |
+ s->matches = 2; /* clear hash */ |
+ zmemcpy(s->window, s->strm->next_in - s->w_size, s->w_size); |
+ s->strstart = s->w_size; |
} |
+ else { |
+ if (s->window_size - s->strstart <= used) { |
+ /* Slide the window down. */ |
+ s->strstart -= s->w_size; |
+ zmemcpy(s->window, s->window + s->w_size, s->strstart); |
+ if (s->matches < 2) |
+ s->matches++; /* add a pending slide_hash() */ |
+ } |
+ zmemcpy(s->window + s->strstart, s->strm->next_in - used, used); |
+ s->strstart += used; |
+ } |
+ s->block_start = s->strstart; |
+ s->insert += MIN(used, s->w_size - s->insert); |
} |
- s->insert = 0; |
- if (flush == Z_FINISH) { |
- FLUSH_BLOCK(s, 1); |
+ if (s->high_water < s->strstart) |
+ s->high_water = s->strstart; |
+ |
+ /* If the last block was written to next_out, then done. */ |
+ if (last) |
return finish_done; |
+ |
+ /* If flushing and all input has been consumed, then done. */ |
+ if (flush != Z_NO_FLUSH && flush != Z_FINISH && |
+ s->strm->avail_in == 0 && (long)s->strstart == s->block_start) |
+ return block_done; |
+ |
+ /* Fill the window with any remaining input. */ |
+ have = s->window_size - s->strstart - 1; |
+ if (s->strm->avail_in > have && s->block_start >= (long)s->w_size) { |
+ /* Slide the window down. */ |
+ s->block_start -= s->w_size; |
+ s->strstart -= s->w_size; |
+ zmemcpy(s->window, s->window + s->w_size, s->strstart); |
+ if (s->matches < 2) |
+ s->matches++; /* add a pending slide_hash() */ |
+ have += s->w_size; /* more space now */ |
} |
- if ((long)s->strstart > s->block_start) |
- FLUSH_BLOCK(s, 0); |
- return block_done; |
+ if (have > s->strm->avail_in) |
+ have = s->strm->avail_in; |
+ if (have) { |
+ read_buf(s->strm, s->window + s->strstart, have); |
+ s->strstart += have; |
+ } |
+ if (s->high_water < s->strstart) |
+ s->high_water = s->strstart; |
+ |
+ /* There was not enough avail_out to write a complete worthy or flushed |
+ * stored block to next_out. Write a stored block to pending instead, if we |
+ * have enough input for a worthy block, or if flushing and there is enough |
+ * room for the remaining input as a stored block in the pending buffer. |
+ */ |
+ have = (s->bi_valid + 42) >> 3; /* number of header bytes */ |
+ /* maximum stored block length that will fit in pending: */ |
+ have = MIN(s->pending_buf_size - have, MAX_STORED); |
+ min_block = MIN(have, s->w_size); |
+ left = s->strstart - s->block_start; |
+ if (left >= min_block || |
+ ((left || flush == Z_FINISH) && flush != Z_NO_FLUSH && |
+ s->strm->avail_in == 0 && left <= have)) { |
+ len = MIN(left, have); |
+ last = flush == Z_FINISH && s->strm->avail_in == 0 && |
+ len == left ? 1 : 0; |
+ _tr_stored_block(s, (charf *)s->window + s->block_start, len, last); |
+ s->block_start += len; |
+ flush_pending(s->strm); |
+ } |
+ |
+ /* We've done all we can with the available input and output. */ |
+ return last ? finish_started : need_more; |
} |
/* =========================================================================== |
@@ -1938,7 +2133,7 @@ local block_state deflate_rle(s, flush) |
prev == *++scan && prev == *++scan && |
prev == *++scan && prev == *++scan && |
scan < strend); |
- s->match_length = MAX_MATCH - (int)(strend - scan); |
+ s->match_length = MAX_MATCH - (uInt)(strend - scan); |
if (s->match_length > s->lookahead) |
s->match_length = s->lookahead; |
} |