| 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;
|
| }
|
|
|