version 1.1.1.1, 2012/02/21 16:23:02
|
version 1.1.1.2, 2013/07/22 10:46:14
|
Line 1
|
Line 1
|
/* deflate.c -- compress data using the deflation algorithm |
/* deflate.c -- compress data using the deflation algorithm |
* Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler | * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler |
* For conditions of distribution and use, see copyright notice in zlib.h |
* For conditions of distribution and use, see copyright notice in zlib.h |
*/ |
*/ |
|
|
Line 37
|
Line 37
|
* REFERENCES |
* REFERENCES |
* |
* |
* Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". |
* Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". |
* Available in http://www.ietf.org/rfc/rfc1951.txt | * Available in http://tools.ietf.org/html/rfc1951 |
* |
* |
* A description of the Rabin and Karp algorithm is given in the book |
* A description of the Rabin and Karp algorithm is given in the book |
* "Algorithms" by R. Sedgewick, Addison-Wesley, p252. |
* "Algorithms" by R. Sedgewick, Addison-Wesley, p252. |
Line 52
|
Line 52
|
#include "deflate.h" |
#include "deflate.h" |
|
|
const char deflate_copyright[] = |
const char deflate_copyright[] = |
" deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; | " deflate 1.2.6 Copyright 1995-2012 Jean-loup Gailly and Mark Adler "; |
/* |
/* |
If you use the zlib library in a product, an acknowledgment is welcome |
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 |
in the documentation of your product. If for some reason you cannot |
Line 155 local const config configuration_table[10] = {
|
Line 155 local const config configuration_table[10] = {
|
struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ |
struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ |
#endif |
#endif |
|
|
|
/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ |
|
#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) |
|
|
/* =========================================================================== |
/* =========================================================================== |
* Update a hash value with the given input byte |
* Update a hash value with the given input byte |
* IN assertion: all calls to to UPDATE_HASH are made with consecutive |
* IN assertion: all calls to to UPDATE_HASH are made with consecutive |
Line 235 int ZEXPORT deflateInit2_(strm, level, method, windowB
|
Line 238 int ZEXPORT deflateInit2_(strm, level, method, windowB
|
|
|
strm->msg = Z_NULL; |
strm->msg = Z_NULL; |
if (strm->zalloc == (alloc_func)0) { |
if (strm->zalloc == (alloc_func)0) { |
|
#ifdef Z_SOLO |
|
return Z_STREAM_ERROR; |
|
#else |
strm->zalloc = zcalloc; |
strm->zalloc = zcalloc; |
strm->opaque = (voidpf)0; |
strm->opaque = (voidpf)0; |
|
#endif |
} |
} |
if (strm->zfree == (free_func)0) strm->zfree = zcfree; | if (strm->zfree == (free_func)0) |
| #ifdef Z_SOLO |
| return Z_STREAM_ERROR; |
| #else |
| strm->zfree = zcfree; |
| #endif |
|
|
#ifdef FASTEST |
#ifdef FASTEST |
if (level != 0) level = 1; |
if (level != 0) level = 1; |
Line 314 int ZEXPORT deflateSetDictionary (strm, dictionary, di
|
Line 326 int ZEXPORT deflateSetDictionary (strm, dictionary, di
|
uInt dictLength; |
uInt dictLength; |
{ |
{ |
deflate_state *s; |
deflate_state *s; |
uInt length = dictLength; | uInt str, n; |
uInt n; | int wrap; |
IPos hash_head = 0; | unsigned avail; |
| unsigned char *next; |
|
|
if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || | if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL) |
strm->state->wrap == 2 || | |
(strm->state->wrap == 1 && strm->state->status != INIT_STATE)) | |
return Z_STREAM_ERROR; |
return Z_STREAM_ERROR; |
|
|
s = strm->state; |
s = strm->state; |
if (s->wrap) | wrap = s->wrap; |
| if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) |
| return Z_STREAM_ERROR; |
| |
| /* when using zlib wrappers, compute Adler-32 for provided dictionary */ |
| if (wrap == 1) |
strm->adler = adler32(strm->adler, dictionary, dictLength); |
strm->adler = adler32(strm->adler, dictionary, dictLength); |
|
s->wrap = 0; /* avoid computing Adler-32 in read_buf */ |
|
|
if (length < MIN_MATCH) return Z_OK; | /* if dictionary would fill window, just replace the history */ |
if (length > s->w_size) { | if (dictLength >= s->w_size) { |
length = s->w_size; | if (wrap == 0) { /* already empty otherwise */ |
dictionary += dictLength - length; /* use the tail of the dictionary */ | CLEAR_HASH(s); |
| s->strstart = 0; |
| s->block_start = 0L; |
| s->insert = 0; |
| } |
| dictionary += dictLength - s->w_size; /* use the tail */ |
| dictLength = s->w_size; |
} |
} |
zmemcpy(s->window, dictionary, length); |
|
s->strstart = length; |
|
s->block_start = (long)length; |
|
|
|
/* Insert all strings in the hash table (except for the last two bytes). | /* insert dictionary into window and hash */ |
* s->lookahead stays null, so s->ins_h will be recomputed at the next | avail = strm->avail_in; |
* call of fill_window. | next = strm->next_in; |
*/ | strm->avail_in = dictLength; |
s->ins_h = s->window[0]; | strm->next_in = (Bytef *)dictionary; |
UPDATE_HASH(s, s->ins_h, s->window[1]); | fill_window(s); |
for (n = 0; n <= length - MIN_MATCH; n++) { | while (s->lookahead >= MIN_MATCH) { |
INSERT_STRING(s, n, hash_head); | str = s->strstart; |
| n = s->lookahead - (MIN_MATCH-1); |
| do { |
| UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); |
| #ifndef FASTEST |
| s->prev[str & s->w_mask] = s->head[s->ins_h]; |
| #endif |
| s->head[s->ins_h] = (Pos)str; |
| str++; |
| } while (--n); |
| s->strstart = str; |
| s->lookahead = MIN_MATCH-1; |
| fill_window(s); |
} |
} |
if (hash_head) hash_head = 0; /* to make compiler happy */ | s->strstart += s->lookahead; |
| s->block_start = (long)s->strstart; |
| s->insert = s->lookahead; |
| s->lookahead = 0; |
| s->match_length = s->prev_length = MIN_MATCH-1; |
| s->match_available = 0; |
| strm->next_in = next; |
| strm->avail_in = avail; |
| s->wrap = wrap; |
return Z_OK; |
return Z_OK; |
} |
} |
|
|
/* ========================================================================= */ |
/* ========================================================================= */ |
int ZEXPORT deflateReset (strm) | int ZEXPORT deflateResetKeep (strm) |
z_streamp strm; |
z_streamp strm; |
{ |
{ |
deflate_state *s; |
deflate_state *s; |
Line 380 int ZEXPORT deflateReset (strm)
|
Line 419 int ZEXPORT deflateReset (strm)
|
s->last_flush = Z_NO_FLUSH; |
s->last_flush = Z_NO_FLUSH; |
|
|
_tr_init(s); |
_tr_init(s); |
lm_init(s); |
|
|
|
return Z_OK; |
return Z_OK; |
} |
} |
|
|
/* ========================================================================= */ |
/* ========================================================================= */ |
|
int ZEXPORT deflateReset (strm) |
|
z_streamp strm; |
|
{ |
|
int ret; |
|
|
|
ret = deflateResetKeep(strm); |
|
if (ret == Z_OK) |
|
lm_init(strm->state); |
|
return ret; |
|
} |
|
|
|
/* ========================================================================= */ |
int ZEXPORT deflateSetHeader (strm, head) |
int ZEXPORT deflateSetHeader (strm, head) |
z_streamp strm; |
z_streamp strm; |
gz_headerp head; |
gz_headerp head; |
Line 397 int ZEXPORT deflateSetHeader (strm, head)
|
Line 447 int ZEXPORT deflateSetHeader (strm, head)
|
} |
} |
|
|
/* ========================================================================= */ |
/* ========================================================================= */ |
|
int ZEXPORT deflatePending (strm, pending, bits) |
|
unsigned *pending; |
|
int *bits; |
|
z_streamp strm; |
|
{ |
|
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
|
if (pending != Z_NULL) |
|
*pending = strm->state->pending; |
|
if (bits != Z_NULL) |
|
*bits = strm->state->bi_valid; |
|
return Z_OK; |
|
} |
|
|
|
/* ========================================================================= */ |
int ZEXPORT deflatePrime (strm, bits, value) |
int ZEXPORT deflatePrime (strm, bits, value) |
z_streamp strm; |
z_streamp strm; |
int bits; |
int bits; |
int value; |
int value; |
{ |
{ |
|
deflate_state *s; |
|
int put; |
|
|
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
strm->state->bi_valid = bits; | s = strm->state; |
strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); | if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) |
| return Z_BUF_ERROR; |
| do { |
| put = Buf_size - s->bi_valid; |
| if (put > bits) |
| put = bits; |
| s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); |
| s->bi_valid += put; |
| _tr_flush_bits(s); |
| value >>= put; |
| bits -= put; |
| } while (bits); |
return Z_OK; |
return Z_OK; |
} |
} |
|
|
Line 562 local void putShortMSB (s, b)
|
Line 640 local void putShortMSB (s, b)
|
local void flush_pending(strm) |
local void flush_pending(strm) |
z_streamp strm; |
z_streamp strm; |
{ |
{ |
unsigned len = strm->state->pending; | unsigned len; |
| deflate_state *s = strm->state; |
|
|
|
_tr_flush_bits(s); |
|
len = s->pending; |
if (len > strm->avail_out) len = strm->avail_out; |
if (len > strm->avail_out) len = strm->avail_out; |
if (len == 0) return; |
if (len == 0) return; |
|
|
zmemcpy(strm->next_out, strm->state->pending_out, len); | zmemcpy(strm->next_out, s->pending_out, len); |
strm->next_out += len; |
strm->next_out += len; |
strm->state->pending_out += len; | s->pending_out += len; |
strm->total_out += len; |
strm->total_out += len; |
strm->avail_out -= len; |
strm->avail_out -= len; |
strm->state->pending -= len; | s->pending -= len; |
if (strm->state->pending == 0) { | if (s->pending == 0) { |
strm->state->pending_out = strm->state->pending_buf; | s->pending_out = s->pending_buf; |
} |
} |
} |
} |
|
|
Line 801 int ZEXPORT deflate (strm, flush)
|
Line 882 int ZEXPORT deflate (strm, flush)
|
* flushes. For repeated and useless calls with Z_FINISH, we keep |
* flushes. For repeated and useless calls with Z_FINISH, we keep |
* returning Z_STREAM_END instead of Z_BUF_ERROR. |
* returning Z_STREAM_END instead of Z_BUF_ERROR. |
*/ |
*/ |
} else if (strm->avail_in == 0 && flush <= old_flush && | } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) && |
flush != Z_FINISH) { |
flush != Z_FINISH) { |
ERR_RETURN(strm, Z_BUF_ERROR); |
ERR_RETURN(strm, Z_BUF_ERROR); |
} |
} |
Line 850 int ZEXPORT deflate (strm, flush)
|
Line 931 int ZEXPORT deflate (strm, flush)
|
if (s->lookahead == 0) { |
if (s->lookahead == 0) { |
s->strstart = 0; |
s->strstart = 0; |
s->block_start = 0L; |
s->block_start = 0L; |
|
s->insert = 0; |
} |
} |
} |
} |
} |
} |
Line 945 int ZEXPORT deflateCopy (dest, source)
|
Line 1027 int ZEXPORT deflateCopy (dest, source)
|
|
|
ss = source->state; |
ss = source->state; |
|
|
zmemcpy(dest, source, sizeof(z_stream)); | zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); |
|
|
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); |
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); |
if (ds == Z_NULL) return Z_MEM_ERROR; |
if (ds == Z_NULL) return Z_MEM_ERROR; |
dest->state = (struct internal_state FAR *) ds; |
dest->state = (struct internal_state FAR *) ds; |
zmemcpy(ds, ss, sizeof(deflate_state)); | zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state)); |
ds->strm = dest; |
ds->strm = dest; |
|
|
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); |
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); |
Line 966 int ZEXPORT deflateCopy (dest, source)
|
Line 1048 int ZEXPORT deflateCopy (dest, source)
|
} |
} |
/* following zmemcpy do not work for 16-bit MSDOS */ |
/* following zmemcpy do not work for 16-bit MSDOS */ |
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); |
zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); |
zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); | zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); |
zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); | zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos)); |
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); |
zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size); |
|
|
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); |
ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); |
Line 1001 local int read_buf(strm, buf, size)
|
Line 1083 local int read_buf(strm, buf, size)
|
|
|
strm->avail_in -= len; |
strm->avail_in -= len; |
|
|
|
zmemcpy(buf, strm->next_in, len); |
if (strm->state->wrap == 1) { |
if (strm->state->wrap == 1) { |
strm->adler = adler32(strm->adler, strm->next_in, len); | strm->adler = adler32(strm->adler, buf, len); |
} |
} |
#ifdef GZIP |
#ifdef GZIP |
else if (strm->state->wrap == 2) { |
else if (strm->state->wrap == 2) { |
strm->adler = crc32(strm->adler, strm->next_in, len); | strm->adler = crc32(strm->adler, buf, len); |
} |
} |
#endif |
#endif |
zmemcpy(buf, strm->next_in, len); |
|
strm->next_in += len; |
strm->next_in += len; |
strm->total_in += len; |
strm->total_in += len; |
|
|
Line 1036 local void lm_init (s)
|
Line 1118 local void lm_init (s)
|
s->strstart = 0; |
s->strstart = 0; |
s->block_start = 0L; |
s->block_start = 0L; |
s->lookahead = 0; |
s->lookahead = 0; |
|
s->insert = 0; |
s->match_length = s->prev_length = MIN_MATCH-1; |
s->match_length = s->prev_length = MIN_MATCH-1; |
s->match_available = 0; |
s->match_available = 0; |
s->ins_h = 0; |
s->ins_h = 0; |
Line 1310 local void fill_window(s)
|
Line 1393 local void fill_window(s)
|
unsigned more; /* Amount of free space at the end of the window. */ |
unsigned more; /* Amount of free space at the end of the window. */ |
uInt wsize = s->w_size; |
uInt wsize = s->w_size; |
|
|
|
Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); |
|
|
do { |
do { |
more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); |
more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); |
|
|
Line 1362 local void fill_window(s)
|
Line 1447 local void fill_window(s)
|
#endif |
#endif |
more += wsize; |
more += wsize; |
} |
} |
if (s->strm->avail_in == 0) return; | if (s->strm->avail_in == 0) break; |
|
|
/* If there was no sliding: |
/* If there was no sliding: |
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && |
* strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && |
Line 1381 local void fill_window(s)
|
Line 1466 local void fill_window(s)
|
s->lookahead += n; |
s->lookahead += n; |
|
|
/* Initialize the hash value now that we have some input: */ |
/* Initialize the hash value now that we have some input: */ |
if (s->lookahead >= MIN_MATCH) { | if (s->lookahead + s->insert >= MIN_MATCH) { |
s->ins_h = s->window[s->strstart]; | uInt str = s->strstart - s->insert; |
UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); | s->ins_h = s->window[str]; |
| UPDATE_HASH(s, s->ins_h, s->window[str + 1]); |
#if MIN_MATCH != 3 |
#if MIN_MATCH != 3 |
Call UPDATE_HASH() MIN_MATCH-3 more times |
Call UPDATE_HASH() MIN_MATCH-3 more times |
#endif |
#endif |
|
while (s->insert) { |
|
UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); |
|
#ifndef FASTEST |
|
s->prev[str & s->w_mask] = s->head[s->ins_h]; |
|
#endif |
|
s->head[s->ins_h] = (Pos)str; |
|
str++; |
|
s->insert--; |
|
if (s->lookahead + s->insert < MIN_MATCH) |
|
break; |
|
} |
} |
} |
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, |
/* If the whole input has less than MIN_MATCH bytes, ins_h is garbage, |
* but this is not important since only literal bytes will be emitted. |
* but this is not important since only literal bytes will be emitted. |
Line 1427 local void fill_window(s)
|
Line 1524 local void fill_window(s)
|
s->high_water += init; |
s->high_water += init; |
} |
} |
} |
} |
|
|
|
Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, |
|
"not enough room for search"); |
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
Line 1506 local block_state deflate_stored(s, flush)
|
Line 1606 local block_state deflate_stored(s, flush)
|
FLUSH_BLOCK(s, 0); |
FLUSH_BLOCK(s, 0); |
} |
} |
} |
} |
FLUSH_BLOCK(s, flush == Z_FINISH); | s->insert = 0; |
return flush == Z_FINISH ? finish_done : block_done; | if (flush == Z_FINISH) { |
| FLUSH_BLOCK(s, 1); |
| return finish_done; |
| } |
| if ((long)s->strstart > s->block_start) |
| FLUSH_BLOCK(s, 0); |
| return block_done; |
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
Line 1603 local block_state deflate_fast(s, flush)
|
Line 1709 local block_state deflate_fast(s, flush)
|
} |
} |
if (bflush) FLUSH_BLOCK(s, 0); |
if (bflush) FLUSH_BLOCK(s, 0); |
} |
} |
FLUSH_BLOCK(s, flush == Z_FINISH); | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; |
return flush == Z_FINISH ? finish_done : block_done; | if (flush == Z_FINISH) { |
| FLUSH_BLOCK(s, 1); |
| return finish_done; |
| } |
| if (s->last_lit) |
| FLUSH_BLOCK(s, 0); |
| return block_done; |
} |
} |
|
|
#ifndef FASTEST |
#ifndef FASTEST |
Line 1728 local block_state deflate_slow(s, flush)
|
Line 1840 local block_state deflate_slow(s, flush)
|
_tr_tally_lit(s, s->window[s->strstart-1], bflush); |
_tr_tally_lit(s, s->window[s->strstart-1], bflush); |
s->match_available = 0; |
s->match_available = 0; |
} |
} |
FLUSH_BLOCK(s, flush == Z_FINISH); | s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; |
return flush == Z_FINISH ? finish_done : block_done; | if (flush == Z_FINISH) { |
| FLUSH_BLOCK(s, 1); |
| return finish_done; |
| } |
| if (s->last_lit) |
| FLUSH_BLOCK(s, 0); |
| return block_done; |
} |
} |
#endif /* FASTEST */ |
#endif /* FASTEST */ |
|
|
Line 1749 local block_state deflate_rle(s, flush)
|
Line 1867 local block_state deflate_rle(s, flush)
|
for (;;) { |
for (;;) { |
/* Make sure that we always have enough lookahead, except |
/* Make sure that we always have enough lookahead, except |
* at the end of the input file. We need MAX_MATCH bytes |
* at the end of the input file. We need MAX_MATCH bytes |
* for the longest encodable run. | * for the longest run, plus one for the unrolled loop. |
*/ |
*/ |
if (s->lookahead < MAX_MATCH) { | if (s->lookahead <= MAX_MATCH) { |
fill_window(s); |
fill_window(s); |
if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { | if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) { |
return need_more; |
return need_more; |
} |
} |
if (s->lookahead == 0) break; /* flush the current block */ |
if (s->lookahead == 0) break; /* flush the current block */ |
Line 1776 local block_state deflate_rle(s, flush)
|
Line 1894 local block_state deflate_rle(s, flush)
|
if (s->match_length > s->lookahead) |
if (s->match_length > s->lookahead) |
s->match_length = s->lookahead; |
s->match_length = s->lookahead; |
} |
} |
|
Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan"); |
} |
} |
|
|
/* Emit match if have run of MIN_MATCH or longer, else emit literal */ |
/* Emit match if have run of MIN_MATCH or longer, else emit literal */ |
Line 1796 local block_state deflate_rle(s, flush)
|
Line 1915 local block_state deflate_rle(s, flush)
|
} |
} |
if (bflush) FLUSH_BLOCK(s, 0); |
if (bflush) FLUSH_BLOCK(s, 0); |
} |
} |
FLUSH_BLOCK(s, flush == Z_FINISH); | s->insert = 0; |
return flush == Z_FINISH ? finish_done : block_done; | if (flush == Z_FINISH) { |
| FLUSH_BLOCK(s, 1); |
| return finish_done; |
| } |
| if (s->last_lit) |
| FLUSH_BLOCK(s, 0); |
| return block_done; |
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
Line 1829 local block_state deflate_huff(s, flush)
|
Line 1954 local block_state deflate_huff(s, flush)
|
s->strstart++; |
s->strstart++; |
if (bflush) FLUSH_BLOCK(s, 0); |
if (bflush) FLUSH_BLOCK(s, 0); |
} |
} |
FLUSH_BLOCK(s, flush == Z_FINISH); | s->insert = 0; |
return flush == Z_FINISH ? finish_done : block_done; | if (flush == Z_FINISH) { |
| FLUSH_BLOCK(s, 1); |
| return finish_done; |
| } |
| if (s->last_lit) |
| FLUSH_BLOCK(s, 0); |
| return block_done; |
} |
} |