summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cpukit/zlib/deflate.c268
-rw-r--r--cpukit/zlib/deflate.h17
-rw-r--r--cpukit/zlib/trees.c82
3 files changed, 250 insertions, 117 deletions
diff --git a/cpukit/zlib/deflate.c b/cpukit/zlib/deflate.c
index 29ce1f64a5..fcd698cc62 100644
--- a/cpukit/zlib/deflate.c
+++ b/cpukit/zlib/deflate.c
@@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm
- * Copyright (C) 1995-2005 Jean-loup Gailly.
+ * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -52,7 +52,7 @@
#include "deflate.h"
const char deflate_copyright[] =
- " deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly ";
+ " deflate 1.2.4 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
/*
If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot
@@ -79,19 +79,18 @@ local block_state deflate_fast OF((deflate_state *s, int flush));
#ifndef FASTEST
local block_state deflate_slow OF((deflate_state *s, int flush));
#endif
+local block_state deflate_rle OF((deflate_state *s, int flush));
+local block_state deflate_huff OF((deflate_state *s, int flush));
local void lm_init OF((deflate_state *s));
local void putShortMSB OF((deflate_state *s, uInt b));
local void flush_pending OF((z_streamp strm));
local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
-#ifndef FASTEST
#ifdef ASMV
void match_init OF((void)); /* asm code initialization */
uInt longest_match OF((deflate_state *s, IPos cur_match));
#else
local uInt longest_match OF((deflate_state *s, IPos cur_match));
#endif
-#endif
-local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
#ifdef DEBUG
local void check_match OF((deflate_state *s, IPos start, IPos match,
@@ -110,11 +109,6 @@ local void check_match OF((deflate_state *s, IPos start, IPos match,
#endif
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
-#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
-/* Minimum amount of lookahead, except at the end of the input file.
- * See deflate.c for comments about the MIN_MATCH+1.
- */
-
/* Values for max_lazy_match, good_match and max_chain_length, depending on
* the desired pack level (0..9). The values given below have been tuned to
* exclude worst case performance for pathological files. Better values may be
@@ -288,6 +282,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
+ s->high_water = 0; /* nothing written to s->window yet */
+
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
@@ -332,8 +328,8 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
strm->adler = adler32(strm->adler, dictionary, dictLength);
if (length < MIN_MATCH) return Z_OK;
- if (length > MAX_DIST(s)) {
- length = MAX_DIST(s);
+ if (length > s->w_size) {
+ length = s->w_size;
dictionary += dictLength - length; /* use the tail of the dictionary */
}
zmemcpy(s->window, dictionary, length);
@@ -435,9 +431,10 @@ int ZEXPORT deflateParams(strm, level, strategy)
}
func = configuration_table[s->level].func;
- if (func != configuration_table[level].func && strm->total_in != 0) {
+ if ((strategy != s->strategy || func != configuration_table[level].func) &&
+ strm->total_in != 0) {
/* Flush the last buffer: */
- err = deflate(strm, Z_PARTIAL_FLUSH);
+ err = deflate(strm, Z_BLOCK);
}
if (s->level != level) {
s->level = level;
@@ -481,33 +478,66 @@ int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
* resulting from using fixed blocks instead of stored blocks, which deflate
* can emit on compressed data for some combinations of the parameters.
*
- * This function could be more sophisticated to provide closer upper bounds
- * for every combination of windowBits and memLevel, as well as wrap.
- * But even the conservative upper bound of about 14% expansion does not
- * seem onerous for output buffer allocation.
+ * This function could be more sophisticated to provide closer upper bounds for
+ * every combination of windowBits and memLevel. But even the conservative
+ * upper bound of about 14% expansion does not seem onerous for output buffer
+ * allocation.
*/
uLong ZEXPORT deflateBound(strm, sourceLen)
z_streamp strm;
uLong sourceLen;
{
deflate_state *s;
- uLong destLen;
+ uLong complen, wraplen;
+ Bytef *str;
- /* conservative upper bound */
- destLen = sourceLen +
- ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11;
+ /* conservative upper bound for compressed data */
+ complen = sourceLen +
+ ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
- /* if can't get parameters, return conservative bound */
+ /* if can't get parameters, return conservative bound plus zlib wrapper */
if (strm == Z_NULL || strm->state == Z_NULL)
- return destLen;
+ return complen + 6;
- /* if not default parameters, return conservative bound */
+ /* compute wrapper length */
s = strm->state;
+ switch (s->wrap) {
+ case 0: /* raw deflate */
+ wraplen = 0;
+ break;
+ case 1: /* zlib wrapper */
+ wraplen = 6 + (s->strstart ? 4 : 0);
+ break;
+ case 2: /* gzip wrapper */
+ wraplen = 18;
+ if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
+ if (s->gzhead->extra != Z_NULL)
+ wraplen += 2 + s->gzhead->extra_len;
+ str = s->gzhead->name;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ str = s->gzhead->comment;
+ if (str != Z_NULL)
+ do {
+ wraplen++;
+ } while (*str++);
+ if (s->gzhead->hcrc)
+ wraplen += 2;
+ }
+ break;
+ default: /* for compiler happiness */
+ wraplen = 6;
+ }
+
+ /* if not default parameters, return conservative bound */
if (s->w_bits != 15 || s->hash_bits != 8 + 7)
- return destLen;
+ return complen + wraplen;
/* default settings: return tight bound for that case */
- return compressBound(sourceLen);
+ return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
+ (sourceLen >> 25) + 13 - 6 + wraplen;
}
/* =========================================================================
@@ -557,7 +587,7 @@ int ZEXPORT deflate (strm, flush)
deflate_state *s;
if (strm == Z_NULL || strm->state == Z_NULL ||
- flush > Z_FINISH || flush < 0) {
+ flush > Z_BLOCK || flush < 0) {
return Z_STREAM_ERROR;
}
s = strm->state;
@@ -581,7 +611,7 @@ int ZEXPORT deflate (strm, flush)
put_byte(s, 31);
put_byte(s, 139);
put_byte(s, 8);
- if (s->gzhead == NULL) {
+ if (s->gzhead == Z_NULL) {
put_byte(s, 0);
put_byte(s, 0);
put_byte(s, 0);
@@ -608,7 +638,7 @@ int ZEXPORT deflate (strm, flush)
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0));
put_byte(s, s->gzhead->os & 0xff);
- if (s->gzhead->extra != NULL) {
+ if (s->gzhead->extra != Z_NULL) {
put_byte(s, s->gzhead->extra_len & 0xff);
put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
}
@@ -650,7 +680,7 @@ int ZEXPORT deflate (strm, flush)
}
#ifdef GZIP
if (s->status == EXTRA_STATE) {
- if (s->gzhead->extra != NULL) {
+ if (s->gzhead->extra != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
@@ -678,7 +708,7 @@ int ZEXPORT deflate (strm, flush)
s->status = NAME_STATE;
}
if (s->status == NAME_STATE) {
- if (s->gzhead->name != NULL) {
+ if (s->gzhead->name != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
@@ -709,7 +739,7 @@ int ZEXPORT deflate (strm, flush)
s->status = COMMENT_STATE;
}
if (s->status == COMMENT_STATE) {
- if (s->gzhead->comment != NULL) {
+ if (s->gzhead->comment != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */
int val;
@@ -787,7 +817,9 @@ int ZEXPORT deflate (strm, flush)
(flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
block_state bstate;
- bstate = (*(configuration_table[s->level].func))(s, flush);
+ bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
+ (s->strategy == Z_RLE ? deflate_rle(s, flush) :
+ (*(configuration_table[s->level].func))(s, flush));
if (bstate == finish_started || bstate == finish_done) {
s->status = FINISH_STATE;
@@ -808,13 +840,17 @@ int ZEXPORT deflate (strm, flush)
if (bstate == block_done) {
if (flush == Z_PARTIAL_FLUSH) {
_tr_align(s);
- } else { /* FULL_FLUSH or SYNC_FLUSH */
+ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
_tr_stored_block(s, (char*)0, 0L, 0);
/* For a full flush, this empty block will be recognized
* as a special marker by inflate_sync().
*/
if (flush == Z_FULL_FLUSH) {
CLEAR_HASH(s); /* forget history */
+ if (s->lookahead == 0) {
+ s->strstart = 0;
+ s->block_start = 0L;
+ }
}
}
flush_pending(strm);
@@ -1167,12 +1203,13 @@ local uInt longest_match(s, cur_match)
return s->lookahead;
}
#endif /* ASMV */
-#endif /* FASTEST */
+
+#else /* FASTEST */
/* ---------------------------------------------------------------------------
- * Optimized version for level == 1 or strategy == Z_RLE only
+ * Optimized version for FASTEST only
*/
-local uInt longest_match_fast(s, cur_match)
+local uInt longest_match(s, cur_match)
deflate_state *s;
IPos cur_match; /* current match */
{
@@ -1225,6 +1262,8 @@ local uInt longest_match_fast(s, cur_match)
return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
}
+#endif /* FASTEST */
+
#ifdef DEBUG
/* ===========================================================================
* Check that the match at match_start is indeed a match.
@@ -1303,7 +1342,6 @@ local void fill_window(s)
later. (Using level 0 permanently is not an optimal usage of
zlib, so we don't care about this pathological case.)
*/
- /* %%% avoid this when Z_RLE */
n = s->hash_size;
p = &s->head[n];
do {
@@ -1355,27 +1393,61 @@ local void fill_window(s)
*/
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
+
+ /* If the WIN_INIT bytes after the end of the current data have never been
+ * written, then zero those bytes in order to avoid memory check reports of
+ * the use of uninitialized (or uninitialised as Julian writes) bytes by
+ * the longest match routines. Update the high water mark for the next
+ * time through here. WIN_INIT is set to MAX_MATCH since the longest match
+ * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
+ */
+ if (s->high_water < s->window_size) {
+ ulg curr = s->strstart + (ulg)(s->lookahead);
+ ulg init;
+
+ if (s->high_water < curr) {
+ /* Previous high water mark below current data -- zero WIN_INIT
+ * bytes or up to end of window, whichever is less.
+ */
+ init = s->window_size - curr;
+ if (init > WIN_INIT)
+ init = WIN_INIT;
+ zmemzero(s->window + curr, (unsigned)init);
+ s->high_water = curr + init;
+ }
+ else if (s->high_water < (ulg)curr + WIN_INIT) {
+ /* High water mark at or above current data, but below current data
+ * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
+ * to end of window, whichever is less.
+ */
+ init = (ulg)curr + WIN_INIT - s->high_water;
+ if (init > s->window_size - s->high_water)
+ init = s->window_size - s->high_water;
+ zmemzero(s->window + s->high_water, (unsigned)init);
+ s->high_water += init;
+ }
+ }
}
/* ===========================================================================
* Flush the current block, with given end-of-file flag.
* IN assertion: strstart is set to the end of the current match.
*/
-#define FLUSH_BLOCK_ONLY(s, eof) { \
+#define FLUSH_BLOCK_ONLY(s, last) { \
_tr_flush_block(s, (s->block_start >= 0L ? \
(charf *)&s->window[(unsigned)s->block_start] : \
(charf *)Z_NULL), \
(ulg)((long)s->strstart - s->block_start), \
- (eof)); \
+ (last)); \
s->block_start = s->strstart; \
flush_pending(s->strm); \
Tracev((stderr,"[FLUSH]")); \
}
/* Same but force premature exit if necessary. */
-#define FLUSH_BLOCK(s, eof) { \
- FLUSH_BLOCK_ONLY(s, eof); \
- if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \
+#define FLUSH_BLOCK(s, last) { \
+ FLUSH_BLOCK_ONLY(s, last); \
+ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
}
/* ===========================================================================
@@ -1449,7 +1521,7 @@ local block_state deflate_fast(s, flush)
deflate_state *s;
int flush;
{
- IPos hash_head = NIL; /* head of the hash chain */
+ IPos hash_head; /* head of the hash chain */
int bflush; /* set if current block must be flushed */
for (;;) {
@@ -1469,6 +1541,7 @@ local block_state deflate_fast(s, flush)
/* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
+ hash_head = NIL;
if (s->lookahead >= MIN_MATCH) {
INSERT_STRING(s, s->strstart, hash_head);
}
@@ -1481,19 +1554,8 @@ local block_state deflate_fast(s, flush)
* of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file).
*/
-#ifdef FASTEST
- if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
- (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
- s->match_length = longest_match_fast (s, hash_head);
- }
-#else
- if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
- s->match_length = longest_match (s, hash_head);
- } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
- s->match_length = longest_match_fast (s, hash_head);
- }
-#endif
- /* longest_match() or longest_match_fast() sets match_start */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
}
if (s->match_length >= MIN_MATCH) {
check_match(s, s->strstart, s->match_start, s->match_length);
@@ -1555,7 +1617,7 @@ local block_state deflate_slow(s, flush)
deflate_state *s;
int flush;
{
- IPos hash_head = NIL; /* head of hash chain */
+ IPos hash_head; /* head of hash chain */
int bflush; /* set if current block must be flushed */
/* Process the input block. */
@@ -1576,6 +1638,7 @@ local block_state deflate_slow(s, flush)
/* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain:
*/
+ hash_head = NIL;
if (s->lookahead >= MIN_MATCH) {
INSERT_STRING(s, s->strstart, hash_head);
}
@@ -1591,12 +1654,8 @@ local block_state deflate_slow(s, flush)
* of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file).
*/
- if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
- s->match_length = longest_match (s, hash_head);
- } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
- s->match_length = longest_match_fast (s, hash_head);
- }
- /* longest_match() or longest_match_fast() sets match_start */
+ s->match_length = longest_match (s, hash_head);
+ /* longest_match() sets match_start */
if (s->match_length <= 5 && (s->strategy == Z_FILTERED
#if TOO_FAR <= 32767
@@ -1674,7 +1733,6 @@ local block_state deflate_slow(s, flush)
}
#endif /* FASTEST */
-#if 0
/* ===========================================================================
* For Z_RLE, simply look for runs of bytes, generate matches only of distance
* one. Do not maintain a hash table. (It will be regenerated if this run of
@@ -1684,11 +1742,9 @@ local block_state deflate_rle(s, flush)
deflate_state *s;
int flush;
{
- int bflush; /* set if current block must be flushed */
- uInt run; /* length of run */
- uInt max; /* maximum length of run */
- uInt prev; /* byte at distance one to match */
- Bytef *scan; /* scan for end of run */
+ int bflush; /* set if current block must be flushed */
+ uInt prev; /* byte at distance one to match */
+ Bytef *scan, *strend; /* scan goes up to strend for length of run */
for (;;) {
/* Make sure that we always have enough lookahead, except
@@ -1704,23 +1760,33 @@ local block_state deflate_rle(s, flush)
}
/* See how many times the previous byte repeats */
- run = 0;
- if (s->strstart > 0) { /* if there is a previous byte, that is */
- max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
+ s->match_length = 0;
+ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
scan = s->window + s->strstart - 1;
- prev = *scan++;
- do {
- if (*scan++ != prev)
- break;
- } while (++run < max);
+ prev = *scan;
+ if (prev == *++scan && prev == *++scan && prev == *++scan) {
+ strend = s->window + s->strstart + MAX_MATCH;
+ do {
+ } while (prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ prev == *++scan && prev == *++scan &&
+ scan < strend);
+ s->match_length = MAX_MATCH - (int)(strend - scan);
+ if (s->match_length > s->lookahead)
+ s->match_length = s->lookahead;
+ }
}
/* Emit match if have run of MIN_MATCH or longer, else emit literal */
- if (run >= MIN_MATCH) {
- check_match(s, s->strstart, s->strstart - 1, run);
- _tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
- s->lookahead -= run;
- s->strstart += run;
+ if (s->match_length >= MIN_MATCH) {
+ check_match(s, s->strstart, s->strstart - 1, s->match_length);
+
+ _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
+
+ s->lookahead -= s->match_length;
+ s->strstart += s->match_length;
+ s->match_length = 0;
} else {
/* No match, output a literal byte */
Tracevv((stderr,"%c", s->window[s->strstart]));
@@ -1733,4 +1799,36 @@ local block_state deflate_rle(s, flush)
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
}
-#endif
+
+/* ===========================================================================
+ * For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
+ * (It will be regenerated if this run of deflate switches away from Huffman.)
+ */
+local block_state deflate_huff(s, flush)
+ deflate_state *s;
+ int flush;
+{
+ int bflush; /* set if current block must be flushed */
+
+ for (;;) {
+ /* Make sure that we have a literal to write. */
+ if (s->lookahead == 0) {
+ fill_window(s);
+ if (s->lookahead == 0) {
+ if (flush == Z_NO_FLUSH)
+ return need_more;
+ break; /* flush the current block */
+ }
+ }
+
+ /* Output a literal byte */
+ s->match_length = 0;
+ Tracevv((stderr,"%c", s->window[s->strstart]));
+ _tr_tally_lit (s, s->window[s->strstart], bflush);
+ s->lookahead--;
+ s->strstart++;
+ if (bflush) FLUSH_BLOCK(s, 0);
+ }
+ FLUSH_BLOCK(s, flush == Z_FINISH);
+ return flush == Z_FINISH ? finish_done : block_done;
+}
diff --git a/cpukit/zlib/deflate.h b/cpukit/zlib/deflate.h
index 05a5ab3a2c..f53deba852 100644
--- a/cpukit/zlib/deflate.h
+++ b/cpukit/zlib/deflate.h
@@ -1,5 +1,5 @@
/* deflate.h -- internal compression state
- * Copyright (C) 1995-2004 Jean-loup Gailly
+ * Copyright (C) 1995-2009 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -260,6 +260,13 @@ typedef struct internal_state {
* are always zero.
*/
+ ulg high_water;
+ /* High water mark offset in window for initialized bytes -- bytes above
+ * this are set to zero in order to avoid memory check warnings when
+ * longest match routines access bytes past the input. This is then
+ * updated to the new high water mark.
+ */
+
} FAR deflate_state;
/* Output a byte on the stream.
@@ -278,14 +285,18 @@ typedef struct internal_state {
* distances are limited to MAX_DIST instead of WSIZE.
*/
+#define WIN_INIT MAX_MATCH
+/* Number of bytes after end of data in window to initialize in order to avoid
+ memory checker errors from longest match routines */
+
/* in trees.c */
void _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len,
- int eof));
+ int last));
void _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
- int eof));
+ int last));
#define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
diff --git a/cpukit/zlib/trees.c b/cpukit/zlib/trees.c
index 395e4e1681..1a6e997ac0 100644
--- a/cpukit/zlib/trees.c
+++ b/cpukit/zlib/trees.c
@@ -1,5 +1,6 @@
/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1995-2005 Jean-loup Gailly
+ * Copyright (C) 1995-2009 Jean-loup Gailly
+ * detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h
*/
@@ -152,7 +153,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
int blcodes));
local void compress_block OF((deflate_state *s, ct_data *ltree,
ct_data *dtree));
-local void set_data_type OF((deflate_state *s));
+local int detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length));
local void bi_windup OF((deflate_state *s));
local void bi_flush OF((deflate_state *s));
@@ -203,12 +204,12 @@ local void send_bits(s, value, length)
* unused bits in value.
*/
if (s->bi_valid > (int)Buf_size - length) {
- s->bi_buf |= (value << s->bi_valid);
+ s->bi_buf |= (ush)value << s->bi_valid;
put_short(s, s->bi_buf);
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
s->bi_valid += length - Buf_size;
} else {
- s->bi_buf |= value << s->bi_valid;
+ s->bi_buf |= (ush)value << s->bi_valid;
s->bi_valid += length;
}
}
@@ -218,12 +219,12 @@ local void send_bits(s, value, length)
{ int len = length;\
if (s->bi_valid > (int)Buf_size - len) {\
int val = value;\
- s->bi_buf |= (val << s->bi_valid);\
+ s->bi_buf |= (ush)val << s->bi_valid;\
put_short(s, s->bi_buf);\
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
s->bi_valid += len - Buf_size;\
} else {\
- s->bi_buf |= (value) << s->bi_valid;\
+ s->bi_buf |= (ush)(value) << s->bi_valid;\
s->bi_valid += len;\
}\
}
@@ -250,11 +251,13 @@ local void tr_static_init()
if (static_init_done) return;
/* For some embedded targets, global variables are not initialized: */
+#ifdef NO_INIT_GLOBAL_POINTERS
static_l_desc.static_tree = static_ltree;
static_l_desc.extra_bits = extra_lbits;
static_d_desc.static_tree = static_dtree;
static_d_desc.extra_bits = extra_dbits;
static_bl_desc.extra_bits = extra_blbits;
+#endif
/* Initialize the mapping length (0..255) -> length code (0..28) */
length = 0;
@@ -864,13 +867,13 @@ local void send_all_trees(s, lcodes, dcodes, blcodes)
/* ===========================================================================
* Send a stored block
*/
-void _tr_stored_block(s, buf, stored_len, eof)
+void _tr_stored_block(s, buf, stored_len, last)
deflate_state *s;
charf *buf; /* input block */
ulg stored_len; /* length of input block */
- int eof; /* true if this is the last block for a file */
+ int last; /* one if this is the last block for a file */
{
- send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */
+ send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
#ifdef DEBUG
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
s->compressed_len += (stored_len + 4) << 3;
@@ -918,11 +921,11 @@ void _tr_align(s)
* Determine the best encoding for the current block: dynamic trees, static
* trees or store, and output the encoded block to the zip file.
*/
-void _tr_flush_block(s, buf, stored_len, eof)
+void _tr_flush_block(s, buf, stored_len, last)
deflate_state *s;
charf *buf; /* input block, or NULL if too old */
ulg stored_len; /* length of input block */
- int eof; /* true if this is the last block for a file */
+ int last; /* one if this is the last block for a file */
{
ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
int max_blindex = 0; /* index of last bit length code of non zero freq */
@@ -931,8 +934,8 @@ void _tr_flush_block(s, buf, stored_len, eof)
if (s->level > 0) {
/* Check if the file is binary or text */
- if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
- set_data_type(s);
+ if (s->strm->data_type == Z_UNKNOWN)
+ s->strm->data_type = detect_data_type(s);
/* Construct the literal and distance trees */
build_tree(s, (tree_desc *)(&(s->l_desc)));
@@ -978,20 +981,20 @@ void _tr_flush_block(s, buf, stored_len, eof)
* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
* transform a block into a stored block.
*/
- _tr_stored_block(s, buf, stored_len, eof);
+ _tr_stored_block(s, buf, stored_len, last);
#ifdef FORCE_STATIC
} else if (static_lenb >= 0) { /* force static trees */
#else
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
- send_bits(s, (STATIC_TREES<<1)+eof, 3);
+ send_bits(s, (STATIC_TREES<<1)+last, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
#ifdef DEBUG
s->compressed_len += 3 + s->static_len;
#endif
} else {
- send_bits(s, (DYN_TREES<<1)+eof, 3);
+ send_bits(s, (DYN_TREES<<1)+last, 3);
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
max_blindex+1);
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
@@ -1005,14 +1008,14 @@ void _tr_flush_block(s, buf, stored_len, eof)
*/
init_block(s);
- if (eof) {
+ if (last) {
bi_windup(s);
#ifdef DEBUG
s->compressed_len += 7; /* align on byte boundary */
#endif
}
Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
- s->compressed_len-7*eof));
+ s->compressed_len-7*last));
}
/* ===========================================================================
@@ -1118,24 +1121,45 @@ local void compress_block(s, ltree, dtree)
}
/* ===========================================================================
- * Set the data type to BINARY or TEXT, using a crude approximation:
- * set it to Z_TEXT if all symbols are either printable characters (33 to 255)
- * or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise.
+ * Check if the data type is TEXT or BINARY, using the following algorithm:
+ * - TEXT if the two conditions below are satisfied:
+ * a) There are no non-portable control characters belonging to the
+ * "black list" (0..6, 14..25, 28..31).
+ * b) There is at least one printable character belonging to the
+ * "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
+ * - BINARY otherwise.
+ * - The following partially-portable control characters form a
+ * "gray list" that is ignored in this detection algorithm:
+ * (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
* IN assertion: the fields Freq of dyn_ltree are set.
*/
-local void set_data_type(s)
+local int detect_data_type(s)
deflate_state *s;
{
+ /* black_mask is the bit mask of black-listed bytes
+ * set bits 0..6, 14..25, and 28..31
+ * 0xf3ffc07f = binary 11110011111111111100000001111111
+ */
+ unsigned long black_mask = 0xf3ffc07fUL;
int n;
- for (n = 0; n < 9; n++)
+ /* Check for non-textual ("black-listed") bytes. */
+ for (n = 0; n <= 31; n++, black_mask >>= 1)
+ if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
+ return Z_BINARY;
+
+ /* Check for textual ("white-listed") bytes. */
+ if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
+ || s->dyn_ltree[13].Freq != 0)
+ return Z_TEXT;
+ for (n = 32; n < LITERALS; n++)
if (s->dyn_ltree[n].Freq != 0)
- break;
- if (n == 9)
- for (n = 14; n < 32; n++)
- if (s->dyn_ltree[n].Freq != 0)
- break;
- s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY;
+ return Z_TEXT;
+
+ /* There are no "black-listed" or "white-listed" bytes:
+ * this stream either is empty or has tolerated ("gray-listed") bytes only.
+ */
+ return Z_BINARY;
}
/* ===========================================================================