version 1.1, 2012/02/17 15:09:30
|
version 1.1.1.2, 2013/10/14 07:51:14
|
Line 1
|
Line 1
|
/* trees.c -- output deflated data using Huffman coding |
/* trees.c -- output deflated data using Huffman coding |
* Copyright (C) 1995-2005 Jean-loup Gailly | * Copyright (C) 1995-2012 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 |
* For conditions of distribution and use, see copyright notice in zlib.h |
*/ |
*/ |
|
|
Line 73 local const uch bl_order[BL_CODES]
|
Line 74 local const uch bl_order[BL_CODES]
|
* probability, to avoid transmitting the lengths for unused bit length codes. |
* probability, to avoid transmitting the lengths for unused bit length codes. |
*/ |
*/ |
|
|
#define Buf_size (8 * 2*sizeof(char)) |
|
/* Number of bits used within bi_buf. (bi_buf might be implemented on |
|
* more than 16 bits on some systems.) |
|
*/ |
|
|
|
/* =========================================================================== |
/* =========================================================================== |
* Local data. These are initialized only once. |
* Local data. These are initialized only once. |
*/ |
*/ |
Line 150 local void send_tree OF((deflate_state *s, ct_dat
|
Line 146 local void send_tree OF((deflate_state *s, ct_dat
|
local int build_bl_tree OF((deflate_state *s)); |
local int build_bl_tree OF((deflate_state *s)); |
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, |
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, |
int blcodes)); |
int blcodes)); |
local void compress_block OF((deflate_state *s, ct_data *ltree, | local void compress_block OF((deflate_state *s, const ct_data *ltree, |
ct_data *dtree)); | const 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 unsigned bi_reverse OF((unsigned value, int length)); |
local void bi_windup OF((deflate_state *s)); |
local void bi_windup OF((deflate_state *s)); |
local void bi_flush OF((deflate_state *s)); |
local void bi_flush OF((deflate_state *s)); |
Line 203 local void send_bits(s, value, length)
|
Line 199 local void send_bits(s, value, length)
|
* unused bits in value. |
* unused bits in value. |
*/ |
*/ |
if (s->bi_valid > (int)Buf_size - length) { |
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); |
put_short(s, s->bi_buf); |
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); |
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); |
s->bi_valid += length - Buf_size; |
s->bi_valid += length - Buf_size; |
} else { |
} else { |
s->bi_buf |= value << s->bi_valid; | s->bi_buf |= (ush)value << s->bi_valid; |
s->bi_valid += length; |
s->bi_valid += length; |
} |
} |
} |
} |
Line 218 local void send_bits(s, value, length)
|
Line 214 local void send_bits(s, value, length)
|
{ int len = length;\ |
{ int len = length;\ |
if (s->bi_valid > (int)Buf_size - len) {\ |
if (s->bi_valid > (int)Buf_size - len) {\ |
int val = value;\ |
int val = value;\ |
s->bi_buf |= (val << s->bi_valid);\ | s->bi_buf |= (ush)val << s->bi_valid;\ |
put_short(s, s->bi_buf);\ |
put_short(s, s->bi_buf);\ |
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ |
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ |
s->bi_valid += len - Buf_size;\ |
s->bi_valid += len - Buf_size;\ |
} else {\ |
} else {\ |
s->bi_buf |= (value) << s->bi_valid;\ | s->bi_buf |= (ush)(value) << s->bi_valid;\ |
s->bi_valid += len;\ |
s->bi_valid += len;\ |
}\ |
}\ |
} |
} |
Line 250 local void tr_static_init()
|
Line 246 local void tr_static_init()
|
if (static_init_done) return; |
if (static_init_done) return; |
|
|
/* For some embedded targets, global variables are not initialized: */ |
/* For some embedded targets, global variables are not initialized: */ |
|
#ifdef NO_INIT_GLOBAL_POINTERS |
static_l_desc.static_tree = static_ltree; |
static_l_desc.static_tree = static_ltree; |
static_l_desc.extra_bits = extra_lbits; |
static_l_desc.extra_bits = extra_lbits; |
static_d_desc.static_tree = static_dtree; |
static_d_desc.static_tree = static_dtree; |
static_d_desc.extra_bits = extra_dbits; |
static_d_desc.extra_bits = extra_dbits; |
static_bl_desc.extra_bits = extra_blbits; |
static_bl_desc.extra_bits = extra_blbits; |
|
#endif |
|
|
/* Initialize the mapping length (0..255) -> length code (0..28) */ |
/* Initialize the mapping length (0..255) -> length code (0..28) */ |
length = 0; |
length = 0; |
Line 348 void gen_trees_header()
|
Line 346 void gen_trees_header()
|
static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); |
static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); |
} |
} |
|
|
fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); | fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n"); |
for (i = 0; i < DIST_CODE_LEN; i++) { |
for (i = 0; i < DIST_CODE_LEN; i++) { |
fprintf(header, "%2u%s", _dist_code[i], |
fprintf(header, "%2u%s", _dist_code[i], |
SEPARATOR(i, DIST_CODE_LEN-1, 20)); |
SEPARATOR(i, DIST_CODE_LEN-1, 20)); |
} |
} |
|
|
fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); | fprintf(header, |
| "const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); |
for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { |
for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { |
fprintf(header, "%2u%s", _length_code[i], |
fprintf(header, "%2u%s", _length_code[i], |
SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); |
SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); |
Line 379 void gen_trees_header()
|
Line 378 void gen_trees_header()
|
/* =========================================================================== |
/* =========================================================================== |
* Initialize the tree data structures for a new zlib stream. |
* Initialize the tree data structures for a new zlib stream. |
*/ |
*/ |
void _tr_init(s) | void ZLIB_INTERNAL _tr_init(s) |
deflate_state *s; |
deflate_state *s; |
{ |
{ |
tr_static_init(); |
tr_static_init(); |
Line 395 void _tr_init(s)
|
Line 394 void _tr_init(s)
|
|
|
s->bi_buf = 0; |
s->bi_buf = 0; |
s->bi_valid = 0; |
s->bi_valid = 0; |
s->last_eob_len = 8; /* enough lookahead for inflate */ |
|
#ifdef DEBUG |
#ifdef DEBUG |
s->compressed_len = 0L; |
s->compressed_len = 0L; |
s->bits_sent = 0L; |
s->bits_sent = 0L; |
Line 864 local void send_all_trees(s, lcodes, dcodes, blcodes)
|
Line 862 local void send_all_trees(s, lcodes, dcodes, blcodes)
|
/* =========================================================================== |
/* =========================================================================== |
* Send a stored block |
* Send a stored block |
*/ |
*/ |
void _tr_stored_block(s, buf, stored_len, eof) | void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) |
deflate_state *s; |
deflate_state *s; |
charf *buf; /* input block */ |
charf *buf; /* input block */ |
ulg stored_len; /* length of 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 |
#ifdef DEBUG |
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; |
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; |
s->compressed_len += (stored_len + 4) << 3; |
s->compressed_len += (stored_len + 4) << 3; |
Line 879 void _tr_stored_block(s, buf, stored_len, eof)
|
Line 877 void _tr_stored_block(s, buf, stored_len, eof)
|
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
|
* Flush the bits in the bit buffer to pending output (leaves at most 7 bits) |
|
*/ |
|
void ZLIB_INTERNAL _tr_flush_bits(s) |
|
deflate_state *s; |
|
{ |
|
bi_flush(s); |
|
} |
|
|
|
/* =========================================================================== |
* Send one empty static block to give enough lookahead for inflate. |
* Send one empty static block to give enough lookahead for inflate. |
* This takes 10 bits, of which 7 may remain in the bit buffer. |
* This takes 10 bits, of which 7 may remain in the bit buffer. |
* The current inflate code requires 9 bits of lookahead. If the |
|
* last two codes for the previous block (real code plus EOB) were coded |
|
* on 5 bits or less, inflate may have only 5+3 bits of lookahead to decode |
|
* the last real code. In this case we send two empty static blocks instead |
|
* of one. (There are no problems if the previous block is stored or fixed.) |
|
* To simplify the code, we assume the worst case of last real code encoded |
|
* on one bit only. |
|
*/ |
*/ |
void _tr_align(s) | void ZLIB_INTERNAL _tr_align(s) |
deflate_state *s; |
deflate_state *s; |
{ |
{ |
send_bits(s, STATIC_TREES<<1, 3); |
send_bits(s, STATIC_TREES<<1, 3); |
Line 898 void _tr_align(s)
|
Line 898 void _tr_align(s)
|
s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ |
s->compressed_len += 10L; /* 3 for block type, 7 for EOB */ |
#endif |
#endif |
bi_flush(s); |
bi_flush(s); |
/* Of the 10 bits for the empty block, we have already sent |
|
* (10 - bi_valid) bits. The lookahead for the last real code (before |
|
* the EOB of the previous block) was thus at least one plus the length |
|
* of the EOB plus what we have just sent of the empty static block. |
|
*/ |
|
if (1 + s->last_eob_len + 10 - s->bi_valid < 9) { |
|
send_bits(s, STATIC_TREES<<1, 3); |
|
send_code(s, END_BLOCK, static_ltree); |
|
#ifdef DEBUG |
|
s->compressed_len += 10L; |
|
#endif |
|
bi_flush(s); |
|
} |
|
s->last_eob_len = 7; |
|
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
* Determine the best encoding for the current block: dynamic trees, static |
* Determine the best encoding for the current block: dynamic trees, static |
* trees or store, and output the encoded block to the zip file. |
* trees or store, and output the encoded block to the zip file. |
*/ |
*/ |
void _tr_flush_block(s, buf, stored_len, eof) | void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) |
deflate_state *s; |
deflate_state *s; |
charf *buf; /* input block, or NULL if too old */ |
charf *buf; /* input block, or NULL if too old */ |
ulg stored_len; /* length of 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 */ |
{ |
{ |
ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ |
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 */ |
int max_blindex = 0; /* index of last bit length code of non zero freq */ |
Line 931 void _tr_flush_block(s, buf, stored_len, eof)
|
Line 917 void _tr_flush_block(s, buf, stored_len, eof)
|
if (s->level > 0) { |
if (s->level > 0) { |
|
|
/* Check if the file is binary or text */ |
/* Check if the file is binary or text */ |
if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) | if (s->strm->data_type == Z_UNKNOWN) |
set_data_type(s); | s->strm->data_type = detect_data_type(s); |
|
|
/* Construct the literal and distance trees */ |
/* Construct the literal and distance trees */ |
build_tree(s, (tree_desc *)(&(s->l_desc))); |
build_tree(s, (tree_desc *)(&(s->l_desc))); |
Line 978 void _tr_flush_block(s, buf, stored_len, eof)
|
Line 964 void _tr_flush_block(s, buf, stored_len, eof)
|
* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to |
* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to |
* transform a block into a stored block. |
* 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 |
#ifdef FORCE_STATIC |
} else if (static_lenb >= 0) { /* force static trees */ |
} else if (static_lenb >= 0) { /* force static trees */ |
#else |
#else |
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { |
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { |
#endif |
#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); | compress_block(s, (const ct_data *)static_ltree, |
| (const ct_data *)static_dtree); |
#ifdef DEBUG |
#ifdef DEBUG |
s->compressed_len += 3 + s->static_len; |
s->compressed_len += 3 + s->static_len; |
#endif |
#endif |
} else { |
} 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, |
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, |
max_blindex+1); |
max_blindex+1); |
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); | compress_block(s, (const ct_data *)s->dyn_ltree, |
| (const ct_data *)s->dyn_dtree); |
#ifdef DEBUG |
#ifdef DEBUG |
s->compressed_len += 3 + s->opt_len; |
s->compressed_len += 3 + s->opt_len; |
#endif |
#endif |
Line 1005 void _tr_flush_block(s, buf, stored_len, eof)
|
Line 993 void _tr_flush_block(s, buf, stored_len, eof)
|
*/ |
*/ |
init_block(s); |
init_block(s); |
|
|
if (eof) { | if (last) { |
bi_windup(s); |
bi_windup(s); |
#ifdef DEBUG |
#ifdef DEBUG |
s->compressed_len += 7; /* align on byte boundary */ |
s->compressed_len += 7; /* align on byte boundary */ |
#endif |
#endif |
} |
} |
Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, |
Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, |
s->compressed_len-7*eof)); | s->compressed_len-7*last)); |
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
* Save the match info and tally the frequency counts. Return true if |
* Save the match info and tally the frequency counts. Return true if |
* the current block must be flushed. |
* the current block must be flushed. |
*/ |
*/ |
int _tr_tally (s, dist, lc) | int ZLIB_INTERNAL _tr_tally (s, dist, lc) |
deflate_state *s; |
deflate_state *s; |
unsigned dist; /* distance of matched string */ |
unsigned dist; /* distance of matched string */ |
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ |
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ |
Line 1071 int _tr_tally (s, dist, lc)
|
Line 1059 int _tr_tally (s, dist, lc)
|
*/ |
*/ |
local void compress_block(s, ltree, dtree) |
local void compress_block(s, ltree, dtree) |
deflate_state *s; |
deflate_state *s; |
ct_data *ltree; /* literal tree */ | const ct_data *ltree; /* literal tree */ |
ct_data *dtree; /* distance tree */ | const ct_data *dtree; /* distance tree */ |
{ |
{ |
unsigned dist; /* distance of matched string */ |
unsigned dist; /* distance of matched string */ |
int lc; /* match length or unmatched char (if dist == 0) */ |
int lc; /* match length or unmatched char (if dist == 0) */ |
Line 1114 local void compress_block(s, ltree, dtree)
|
Line 1102 local void compress_block(s, ltree, dtree)
|
} while (lx < s->last_lit); |
} while (lx < s->last_lit); |
|
|
send_code(s, END_BLOCK, ltree); |
send_code(s, END_BLOCK, ltree); |
s->last_eob_len = ltree[END_BLOCK].Len; |
|
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
* Set the data type to BINARY or TEXT, using a crude approximation: | * Check if the data type is TEXT or BINARY, using the following algorithm: |
* set it to Z_TEXT if all symbols are either printable characters (33 to 255) | * - TEXT if the two conditions below are satisfied: |
* or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. | * 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. |
* 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; |
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; |
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) |
if (s->dyn_ltree[n].Freq != 0) |
break; | return Z_TEXT; |
if (n == 9) | |
for (n = 14; n < 32; n++) | /* There are no "black-listed" or "white-listed" bytes: |
if (s->dyn_ltree[n].Freq != 0) | * this stream either is empty or has tolerated ("gray-listed") bytes only. |
break; | */ |
s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; | return Z_BINARY; |
} |
} |
|
|
/* =========================================================================== |
/* =========================================================================== |
Line 1201 local void copy_block(s, buf, len, header)
|
Line 1209 local void copy_block(s, buf, len, header)
|
int header; /* true if block header must be written */ |
int header; /* true if block header must be written */ |
{ |
{ |
bi_windup(s); /* align on byte boundary */ |
bi_windup(s); /* align on byte boundary */ |
s->last_eob_len = 8; /* enough lookahead for inflate */ |
|
|
|
if (header) { |
if (header) { |
put_short(s, (ush)len); |
put_short(s, (ush)len); |