|
|
|
@ -47,11 +47,11 @@ |
|
|
|
|
* |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
/* $Id: deflate.c,v 1.13 1996/05/22 11:52:21 me Exp $ */ |
|
|
|
|
/* $Id: deflate.c,v 1.15 1996/07/24 13:40:58 me Exp $ */ |
|
|
|
|
|
|
|
|
|
#include "deflate.h" |
|
|
|
|
|
|
|
|
|
char deflate_copyright[] = " deflate 1.0.2 Copyright 1995-1996 Jean-loup Gailly "; |
|
|
|
|
char deflate_copyright[] = " deflate 1.0.4 Copyright 1995-1996 Jean-loup Gailly "; |
|
|
|
|
/*
|
|
|
|
|
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 |
|
|
|
@ -62,15 +62,25 @@ char deflate_copyright[] = " deflate 1.0.2 Copyright 1995-1996 Jean-loup Gailly |
|
|
|
|
/* ===========================================================================
|
|
|
|
|
* Function prototypes. |
|
|
|
|
*/ |
|
|
|
|
typedef enum { |
|
|
|
|
need_more, /* block not completed, need more input or more output */ |
|
|
|
|
block_done, /* block flush performed */ |
|
|
|
|
finish_started, /* finish started, need only more output at next deflate */ |
|
|
|
|
finish_done /* finish done, accept no more input or output */ |
|
|
|
|
} block_state; |
|
|
|
|
|
|
|
|
|
typedef block_state (*compress_func) OF((deflate_state *s, int flush)); |
|
|
|
|
/* Compression function. Returns the block state after the call. */ |
|
|
|
|
|
|
|
|
|
local void fill_window OF((deflate_state *s)); |
|
|
|
|
local int deflate_stored OF((deflate_state *s, int flush)); |
|
|
|
|
local int deflate_fast OF((deflate_state *s, int flush)); |
|
|
|
|
local int deflate_slow OF((deflate_state *s, int flush)); |
|
|
|
|
local block_state deflate_stored OF((deflate_state *s, int flush)); |
|
|
|
|
local block_state deflate_fast OF((deflate_state *s, int flush)); |
|
|
|
|
local block_state deflate_slow OF((deflate_state *s, int flush)); |
|
|
|
|
local void lm_init OF((deflate_state *s)); |
|
|
|
|
local uInt longest_match OF((deflate_state *s, IPos cur_match)); |
|
|
|
|
local void putShortMSB OF((deflate_state *s, uInt b)); |
|
|
|
|
local void flush_pending OF((z_stream *strm)); |
|
|
|
|
local int read_buf OF((z_stream *strm, charf *buf, unsigned size)); |
|
|
|
|
local void flush_pending OF((z_streamp strm)); |
|
|
|
|
local int read_buf OF((z_streamp strm, charf *buf, unsigned size)); |
|
|
|
|
#ifdef ASMV |
|
|
|
|
void match_init OF((void)); /* asm code initialization */ |
|
|
|
|
#endif |
|
|
|
@ -97,9 +107,6 @@ local void check_match OF((deflate_state *s, IPos start, IPos match, |
|
|
|
|
* See deflate.c for comments about the MIN_MATCH+1. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
typedef int (*compress_func) OF((deflate_state *s, int flush)); |
|
|
|
|
/* Compressing function */ |
|
|
|
|
|
|
|
|
|
/* Values for max_lazy_match, good_match and max_chain_length, depending on
|
|
|
|
|
* the desired pack level (0..9). The values given below have been tuned to |
|
|
|
|
* exclude worst case performance for pathological files. Better values may be |
|
|
|
@ -169,7 +176,7 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateInit_(strm, level, version, stream_size) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
int level; |
|
|
|
|
const char *version; |
|
|
|
|
int stream_size; |
|
|
|
@ -182,7 +189,7 @@ int deflateInit_(strm, level, version, stream_size) |
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
|
|
|
|
version, stream_size) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
int level; |
|
|
|
|
int method; |
|
|
|
|
int windowBits; |
|
|
|
@ -249,7 +256,7 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
|
|
|
|
|
|
|
|
|
if (s->window == Z_NULL || s->prev == Z_NULL || s->head == Z_NULL || |
|
|
|
|
s->pending_buf == Z_NULL) { |
|
|
|
|
strm->msg = ERR_MSG(Z_MEM_ERROR); |
|
|
|
|
strm->msg = (char*)ERR_MSG(Z_MEM_ERROR); |
|
|
|
|
deflateEnd (strm); |
|
|
|
|
return Z_MEM_ERROR; |
|
|
|
|
} |
|
|
|
@ -265,7 +272,7 @@ int deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateSetDictionary (strm, dictionary, dictLength) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
const Bytef *dictionary; |
|
|
|
|
uInt dictLength; |
|
|
|
|
{ |
|
|
|
@ -304,7 +311,7 @@ int deflateSetDictionary (strm, dictionary, dictLength) |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateReset (strm) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
{ |
|
|
|
|
deflate_state *s; |
|
|
|
|
|
|
|
|
@ -334,7 +341,7 @@ int deflateReset (strm) |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateParams(strm, level, strategy) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
int level; |
|
|
|
|
int strategy; |
|
|
|
|
{ |
|
|
|
@ -388,7 +395,7 @@ local void putShortMSB (s, b) |
|
|
|
|
* (See also read_buf()). |
|
|
|
|
*/ |
|
|
|
|
local void flush_pending(strm) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
{ |
|
|
|
|
unsigned len = strm->state->pending; |
|
|
|
|
|
|
|
|
@ -408,14 +415,16 @@ local void flush_pending(strm) |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflate (strm, flush) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
int flush; |
|
|
|
|
{ |
|
|
|
|
int old_flush; /* value of flush param for previous deflate call */ |
|
|
|
|
deflate_state *s; |
|
|
|
|
|
|
|
|
|
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
|
|
|
|
|
|
|
|
|
if (strm == Z_NULL || strm->state == Z_NULL || |
|
|
|
|
flush > Z_FINISH || flush < 0) { |
|
|
|
|
return Z_STREAM_ERROR; |
|
|
|
|
} |
|
|
|
|
s = strm->state; |
|
|
|
|
|
|
|
|
|
if (strm->next_out == Z_NULL || |
|
|
|
@ -447,14 +456,23 @@ int deflate (strm, flush) |
|
|
|
|
if (s->strstart != 0) { |
|
|
|
|
putShortMSB(s, (uInt)(strm->adler >> 16)); |
|
|
|
|
putShortMSB(s, (uInt)(strm->adler & 0xffff)); |
|
|
|
|
strm->adler = 1L; |
|
|
|
|
} |
|
|
|
|
strm->adler = 1L; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Flush as much pending output as possible */ |
|
|
|
|
if (s->pending != 0) { |
|
|
|
|
flush_pending(strm); |
|
|
|
|
if (strm->avail_out == 0) return Z_OK; |
|
|
|
|
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 |
|
|
|
@ -474,22 +492,27 @@ int deflate (strm, flush) |
|
|
|
|
*/ |
|
|
|
|
if (strm->avail_in != 0 || s->lookahead != 0 || |
|
|
|
|
(flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
|
|
|
|
int quit; |
|
|
|
|
block_state bstate; |
|
|
|
|
|
|
|
|
|
if (flush == Z_FINISH) { |
|
|
|
|
bstate = (*(configuration_table[s->level].func))(s, flush); |
|
|
|
|
|
|
|
|
|
if (bstate == finish_started || bstate == finish_done) { |
|
|
|
|
s->status = FINISH_STATE; |
|
|
|
|
} |
|
|
|
|
quit = (*(configuration_table[s->level].func))(s, flush); |
|
|
|
|
|
|
|
|
|
if (quit || strm->avail_out == 0) return Z_OK; |
|
|
|
|
/* If flush != Z_NO_FLUSH && avail_out == 0, the next call
|
|
|
|
|
* of deflate should use the same flush parameter to make sure |
|
|
|
|
* that the flush is complete. So we don't have to output an |
|
|
|
|
* empty block here, this will be done at next call. This also |
|
|
|
|
* ensures that for a very small output buffer, we emit at most |
|
|
|
|
* one empty block. |
|
|
|
|
*/ |
|
|
|
|
if (flush != Z_NO_FLUSH && flush != Z_FINISH) { |
|
|
|
|
if (bstate == need_more || bstate == finish_started) { |
|
|
|
|
if (strm->avail_out == 0) { |
|
|
|
|
s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ |
|
|
|
|
} |
|
|
|
|
return Z_OK; |
|
|
|
|
/* If flush != Z_NO_FLUSH && avail_out == 0, the next call
|
|
|
|
|
* of deflate should use the same flush parameter to make sure |
|
|
|
|
* that the flush is complete. So we don't have to output an |
|
|
|
|
* empty block here, this will be done at next call. This also |
|
|
|
|
* ensures that for a very small output buffer, we emit at most |
|
|
|
|
* one empty block. |
|
|
|
|
*/ |
|
|
|
|
} |
|
|
|
|
if (bstate == block_done) { |
|
|
|
|
if (flush == Z_PARTIAL_FLUSH) { |
|
|
|
|
_tr_align(s); |
|
|
|
|
} else { /* FULL_FLUSH or SYNC_FLUSH */ |
|
|
|
@ -502,7 +525,10 @@ int deflate (strm, flush) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
flush_pending(strm); |
|
|
|
|
if (strm->avail_out == 0) return Z_OK; |
|
|
|
|
if (strm->avail_out == 0) { |
|
|
|
|
s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ |
|
|
|
|
return Z_OK; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Assert(strm->avail_out > 0, "bug2"); |
|
|
|
@ -523,7 +549,7 @@ int deflate (strm, flush) |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateEnd (strm) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
{ |
|
|
|
|
int status; |
|
|
|
|
|
|
|
|
@ -544,8 +570,8 @@ int deflateEnd (strm) |
|
|
|
|
|
|
|
|
|
/* ========================================================================= */ |
|
|
|
|
int deflateCopy (dest, source) |
|
|
|
|
z_stream *dest; |
|
|
|
|
z_stream *source; |
|
|
|
|
z_streamp dest; |
|
|
|
|
z_streamp source; |
|
|
|
|
{ |
|
|
|
|
if (source == Z_NULL || dest == Z_NULL || source->state == Z_NULL) { |
|
|
|
|
return Z_STREAM_ERROR; |
|
|
|
@ -570,7 +596,7 @@ int deflateCopy (dest, source) |
|
|
|
|
* (See also flush_pending()). |
|
|
|
|
*/ |
|
|
|
|
local int read_buf(strm, buf, size) |
|
|
|
|
z_stream *strm; |
|
|
|
|
z_streamp strm; |
|
|
|
|
charf *buf; |
|
|
|
|
unsigned size; |
|
|
|
|
{ |
|
|
|
@ -916,18 +942,18 @@ local void fill_window(s) |
|
|
|
|
/* Same but force premature exit if necessary. */ |
|
|
|
|
#define FLUSH_BLOCK(s, eof) { \ |
|
|
|
|
FLUSH_BLOCK_ONLY(s, eof); \
|
|
|
|
|
if (s->strm->avail_out == 0) return 1; \
|
|
|
|
|
if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ===========================================================================
|
|
|
|
|
* Copy without compression as much as possible from the input stream, return |
|
|
|
|
* true if processing was terminated prematurely (no more input or output |
|
|
|
|
* space). This function does not insert new strings in the dictionary |
|
|
|
|
* since uncompressible data is probably not useful. This function is used |
|
|
|
|
* 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. |
|
|
|
|
*/ |
|
|
|
|
local int deflate_stored(s, flush) |
|
|
|
|
local block_state deflate_stored(s, flush) |
|
|
|
|
deflate_state *s; |
|
|
|
|
int flush; |
|
|
|
|
{ |
|
|
|
@ -939,7 +965,7 @@ local int deflate_stored(s, flush) |
|
|
|
|
s->block_start >= (long)s->w_size, "slide too late"); |
|
|
|
|
|
|
|
|
|
fill_window(s); |
|
|
|
|
if (s->lookahead == 0 && flush == Z_NO_FLUSH) return 1; |
|
|
|
|
if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; |
|
|
|
|
|
|
|
|
|
if (s->lookahead == 0) break; /* flush the current block */ |
|
|
|
|
} |
|
|
|
@ -961,17 +987,17 @@ local int deflate_stored(s, flush) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
FLUSH_BLOCK(s, flush == Z_FINISH); |
|
|
|
|
return 0; /* normal exit */ |
|
|
|
|
return flush == Z_FINISH ? finish_done : block_done; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ===========================================================================
|
|
|
|
|
* Compress as much as possible from the input stream, return true if |
|
|
|
|
* processing was terminated prematurely (no more input or output space). |
|
|
|
|
* Compress as much as possible from the input stream, return the current |
|
|
|
|
* block state. |
|
|
|
|
* This function does not perform lazy evaluation of matches and inserts |
|
|
|
|
* new strings in the dictionary only for unmatched strings or for short |
|
|
|
|
* matches. It is used only for the fast compression options. |
|
|
|
|
*/ |
|
|
|
|
local int deflate_fast(s, flush) |
|
|
|
|
local block_state deflate_fast(s, flush) |
|
|
|
|
deflate_state *s; |
|
|
|
|
int flush; |
|
|
|
|
{ |
|
|
|
@ -986,8 +1012,9 @@ local int deflate_fast(s, flush) |
|
|
|
|
*/ |
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD) { |
|
|
|
|
fill_window(s); |
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; |
|
|
|
|
|
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { |
|
|
|
|
return need_more; |
|
|
|
|
} |
|
|
|
|
if (s->lookahead == 0) break; /* flush the current block */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1055,7 +1082,7 @@ local int deflate_fast(s, flush) |
|
|
|
|
if (bflush) FLUSH_BLOCK(s, 0); |
|
|
|
|
} |
|
|
|
|
FLUSH_BLOCK(s, flush == Z_FINISH); |
|
|
|
|
return 0; /* normal exit */ |
|
|
|
|
return flush == Z_FINISH ? finish_done : block_done; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* ===========================================================================
|
|
|
|
@ -1063,7 +1090,7 @@ local int deflate_fast(s, flush) |
|
|
|
|
* evaluation for matches: a match is finally adopted only if there is |
|
|
|
|
* no better match at the next window position. |
|
|
|
|
*/ |
|
|
|
|
local int deflate_slow(s, flush) |
|
|
|
|
local block_state deflate_slow(s, flush) |
|
|
|
|
deflate_state *s; |
|
|
|
|
int flush; |
|
|
|
|
{ |
|
|
|
@ -1079,8 +1106,9 @@ local int deflate_slow(s, flush) |
|
|
|
|
*/ |
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD) { |
|
|
|
|
fill_window(s); |
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) return 1; |
|
|
|
|
|
|
|
|
|
if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { |
|
|
|
|
return need_more; |
|
|
|
|
} |
|
|
|
|
if (s->lookahead == 0) break; /* flush the current block */ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -1158,7 +1186,7 @@ local int deflate_slow(s, flush) |
|
|
|
|
} |
|
|
|
|
s->strstart++; |
|
|
|
|
s->lookahead--; |
|
|
|
|
if (s->strm->avail_out == 0) return 1; |
|
|
|
|
if (s->strm->avail_out == 0) return need_more; |
|
|
|
|
} else { |
|
|
|
|
/* There is no previous match to compare with, wait for
|
|
|
|
|
* the next step to decide. |
|
|
|
@ -1175,6 +1203,5 @@ local int deflate_slow(s, flush) |
|
|
|
|
s->match_available = 0; |
|
|
|
|
} |
|
|
|
|
FLUSH_BLOCK(s, flush == Z_FINISH); |
|
|
|
|
return 0; |
|
|
|
|
return flush == Z_FINISH ? finish_done : block_done; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|