mirror of
https://github.com/KranX/Vangers.git
synced 2025-11-30 23:15:27 +07:00
707 lines
16 KiB
C++
707 lines
16 KiB
C++
#include "xzip.h"
|
|
|
|
typedef unsigned char uchar;
|
|
//typedef unsigned short ushort;
|
|
//typedef unsigned long ulong;
|
|
|
|
extern char* IErrMsg;
|
|
|
|
#ifdef _LARGE_MODEL_
|
|
#define WSIZE 0x4000U
|
|
#define OUTBUFSIZ 0x800U
|
|
#else
|
|
#define WSIZE 0x8000U
|
|
#define OUTBUFSIZ 0x1000U
|
|
#endif
|
|
|
|
#define MIN_MATCH 3
|
|
#define MAX_MATCH 258
|
|
|
|
#define DYN_ALLOC
|
|
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
|
|
#define MAX_DIST (WSIZE-MIN_LOOKAHEAD)
|
|
|
|
#define UNKNOWN (-1)
|
|
#define BINARY 0
|
|
#define ASCII 1
|
|
|
|
#define STORE 0
|
|
#define DEFLATE 8
|
|
|
|
#define MAX_BITS 15
|
|
#define MAX_BL_BITS 7
|
|
#define LENGTH_CODES 29
|
|
#define LITERALS 256
|
|
#define END_BLOCK 256
|
|
#define L_CODES (LITERALS+1+LENGTH_CODES)
|
|
#define D_CODES 30
|
|
#define BL_CODES 19
|
|
|
|
#define STORED_BLOCK 0
|
|
#define STATIC_TREES 1
|
|
#define DYN_TREES 2
|
|
|
|
#define LIT_BUFSIZE 0x4000
|
|
|
|
#define DIST_BUFSIZE LIT_BUFSIZE
|
|
|
|
#define REP_3_6 16
|
|
#define REPZ_3_10 17
|
|
#define REPZ_11_138 18
|
|
|
|
typedef struct ct_data {
|
|
union {
|
|
unsigned short freq;
|
|
unsigned short code;
|
|
} fc;
|
|
union {
|
|
unsigned short dad;
|
|
unsigned short len;
|
|
} dl;
|
|
} ct_data;
|
|
|
|
typedef struct tree_desc
|
|
{
|
|
ct_data* dyn_tree;
|
|
ct_data* static_tree;
|
|
int* extra_bits;
|
|
int extra_base;
|
|
int elems;
|
|
int max_length;
|
|
int max_code;
|
|
} tree_desc;
|
|
|
|
#define Freq fc.freq
|
|
#define Code fc.code
|
|
#define Dad dl.dad
|
|
#define Len dl.len
|
|
|
|
#define HEAP_SIZE (2 * L_CODES + 1)
|
|
|
|
// ---------- EXTERN SECTION ----------
|
|
|
|
extern int verbose;
|
|
extern int level;
|
|
|
|
// ---------- PROTOTYPE SECTION ----------
|
|
|
|
void ct_init(unsigned short* attr,int* method);
|
|
unsigned int flush_block(char* buf,unsigned int stored_len,int eof);
|
|
int ct_tally(int dist,int lc);
|
|
|
|
void copy_block(char* buf,unsigned len,int header);
|
|
void bi_windup(void);
|
|
unsigned bi_reverse(unsigned code,int len);
|
|
void send_bits(int value,int length);
|
|
void free_data(void);
|
|
void lm_free(void);
|
|
|
|
static void init_block(void);
|
|
static void pqdownheap(ct_data* tree, int k);
|
|
static void gen_bitlen(tree_desc* desc);
|
|
static void gen_codes(ct_data* tree, int max_code);
|
|
static void build_tree(tree_desc* desc);
|
|
static void scan_tree(ct_data* tree, int max_code);
|
|
static void send_tree(ct_data* tree, int max_code);
|
|
static int build_bl_tree(void);
|
|
static void send_all_trees(int lcodes, int dcodes, int blcodes);
|
|
static void compress_block(ct_data* ltree, ct_data* dtree);
|
|
static void set_file_type(void);
|
|
|
|
// ---------- DEFINITION SECTION ----------
|
|
|
|
static int extra_lbits[LENGTH_CODES]
|
|
= {0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0};
|
|
|
|
static int extra_dbits[D_CODES]
|
|
= {0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13};
|
|
|
|
static int extra_blbits[BL_CODES]
|
|
= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,3,7};
|
|
|
|
static ct_data dyn_ltree[HEAP_SIZE];
|
|
static ct_data dyn_dtree[2*D_CODES+1];
|
|
|
|
static ct_data static_ltree[L_CODES+2];
|
|
static ct_data static_dtree[D_CODES];
|
|
static ct_data bl_tree[2*BL_CODES+1];
|
|
|
|
static tree_desc l_desc =
|
|
{dyn_ltree, static_ltree, extra_lbits, LITERALS + 1, L_CODES, MAX_BITS, 0};
|
|
|
|
static tree_desc d_desc =
|
|
{dyn_dtree, static_dtree, extra_dbits, 0, D_CODES, MAX_BITS, 0};
|
|
|
|
static tree_desc bl_desc =
|
|
{bl_tree, NULL, extra_blbits, 0, BL_CODES, MAX_BL_BITS, 0};
|
|
|
|
static unsigned short bl_count[MAX_BITS + 1];
|
|
|
|
static uchar bl_order[BL_CODES]
|
|
= {16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15};
|
|
|
|
static int heap[2 * L_CODES + 1];
|
|
static int heap_len;
|
|
static int heap_max;
|
|
|
|
static uchar depth[2 * L_CODES + 1];
|
|
static uchar length_code[MAX_MATCH - MIN_MATCH + 1];
|
|
static uchar dist_code[512];
|
|
static int base_length[LENGTH_CODES];
|
|
|
|
static int base_dist[D_CODES];
|
|
|
|
#ifndef DYN_ALLOC
|
|
static uchar l_buf[LIT_BUFSIZE];
|
|
static unsigned short d_buf[DIST_BUFSIZE];
|
|
#else
|
|
static uchar* l_buf;
|
|
static unsigned short* d_buf;
|
|
#endif
|
|
|
|
static uchar flag_buf[(LIT_BUFSIZE/8)];
|
|
|
|
static unsigned last_lit;
|
|
static unsigned last_dist;
|
|
static unsigned last_flags;
|
|
static uchar flags;
|
|
static uchar flag_bit;
|
|
|
|
static unsigned int opt_len;
|
|
static unsigned int static_len;
|
|
|
|
static unsigned int compressed_len;
|
|
|
|
static unsigned int input_len;
|
|
|
|
unsigned short *file_type;
|
|
int *file_method;
|
|
|
|
extern int block_start;
|
|
extern unsigned strstart;
|
|
|
|
# define send_code(c, tree) \
|
|
{ if(verbose>1) fprintf(stderr,"\ncd %3d ",(c)); \
|
|
send_bits(tree[c].Code, tree[c].Len); }
|
|
|
|
#define d_code(dist) \
|
|
((dist) < 256 ? dist_code[dist] : dist_code[256+((dist)>>7)])
|
|
|
|
#define MAX(a,b) (a >= b ? a : b)
|
|
|
|
void ct_init(unsigned short* attr,int* method)
|
|
{
|
|
int n;
|
|
int bits;
|
|
int length;
|
|
int code;
|
|
int dist;
|
|
|
|
file_type = attr;
|
|
file_method = method;
|
|
compressed_len = input_len = 0L;
|
|
|
|
#ifdef DYN_ALLOC
|
|
d_buf = new unsigned short[DIST_BUFSIZE];
|
|
l_buf = new uchar[LIT_BUFSIZE];
|
|
#endif
|
|
length = 0;
|
|
for(code = 0; code < LENGTH_CODES-1; code++){
|
|
base_length[code] = length;
|
|
for(n = 0; n < (1<<extra_lbits[code]); n++){
|
|
length_code[length++] = (uchar)code;
|
|
}
|
|
}
|
|
length_code[length-1] = (uchar)code;
|
|
|
|
dist = 0;
|
|
for(code = 0 ; code < 16; code++){
|
|
base_dist[code] = dist;
|
|
for(n = 0; n < (1<<extra_dbits[code]); n++){
|
|
dist_code[dist++] = (uchar)code;
|
|
}
|
|
}
|
|
dist >>= 7;
|
|
for( ; code < D_CODES; code++){
|
|
base_dist[code] = dist << 7;
|
|
for(n = 0; n < (1<<(extra_dbits[code]-7)); n++){
|
|
dist_code[256 + dist++] = (uchar)code;
|
|
}
|
|
}
|
|
|
|
for(bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
|
|
n = 0;
|
|
while(n <= 143) static_ltree[n++].Len = 8, bl_count[8]++;
|
|
while(n <= 255) static_ltree[n++].Len = 9, bl_count[9]++;
|
|
while(n <= 279) static_ltree[n++].Len = 7, bl_count[7]++;
|
|
while(n <= 287) static_ltree[n++].Len = 8, bl_count[8]++;
|
|
gen_codes((ct_data*)static_ltree, L_CODES+1);
|
|
|
|
for(n = 0; n < D_CODES; n++){
|
|
static_dtree[n].Len = 5;
|
|
static_dtree[n].Code = bi_reverse(n, 5);
|
|
}
|
|
|
|
init_block();
|
|
}
|
|
|
|
static void init_block(void)
|
|
{
|
|
int n;
|
|
|
|
for(n = 0; n < L_CODES; n++) dyn_ltree[n].Freq = 0;
|
|
for(n = 0; n < D_CODES; n++) dyn_dtree[n].Freq = 0;
|
|
for(n = 0; n < BL_CODES; n++) bl_tree[n].Freq = 0;
|
|
|
|
dyn_ltree[END_BLOCK].Freq = 1;
|
|
opt_len = static_len = 0L;
|
|
last_lit = last_dist = last_flags = 0;
|
|
flags = 0; flag_bit = 1;
|
|
}
|
|
|
|
#define SMALLEST 1
|
|
|
|
#define pqremove(tree, top) \
|
|
{\
|
|
top = heap[SMALLEST]; \
|
|
heap[SMALLEST] = heap[heap_len--]; \
|
|
pqdownheap(tree,SMALLEST); \
|
|
}
|
|
|
|
#define smaller(tree, n, m) \
|
|
(tree[n].Freq < tree[m].Freq || \
|
|
(tree[n].Freq == tree[m].Freq && depth[n] <= depth[m]))
|
|
|
|
static void pqdownheap(ct_data* tree,int k)
|
|
{
|
|
int v = heap[k];
|
|
int j = k << 1;
|
|
int htemp;
|
|
|
|
while(j <= heap_len){
|
|
if(j < heap_len && smaller(tree, heap[j+1], heap[j])) j++;
|
|
|
|
htemp = heap[j];
|
|
if(smaller(tree, v, htemp)) break;
|
|
|
|
heap[k] = htemp;
|
|
k = j;
|
|
|
|
j <<= 1;
|
|
}
|
|
heap[k] = v;
|
|
}
|
|
|
|
static void gen_bitlen(tree_desc* desc)
|
|
{
|
|
ct_data* tree = desc->dyn_tree;
|
|
int* extra = desc->extra_bits;
|
|
int base = desc->extra_base;
|
|
int max_code = desc->max_code;
|
|
int max_length = desc->max_length;
|
|
ct_data* stree = desc->static_tree;
|
|
int h;
|
|
int n, m;
|
|
int bits;
|
|
int xbits;
|
|
unsigned short f;
|
|
int overflow = 0;
|
|
|
|
for(bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
|
|
|
|
tree[heap[heap_max]].Len = 0;
|
|
|
|
for(h = heap_max+1; h < HEAP_SIZE; h++){
|
|
n = heap[h];
|
|
bits = tree[tree[n].Dad].Len + 1;
|
|
if(bits > max_length) bits = max_length, overflow++;
|
|
tree[n].Len = bits;
|
|
|
|
if(n > max_code) continue;
|
|
|
|
bl_count[bits]++;
|
|
xbits = 0;
|
|
if(n >= base) xbits = extra[n-base];
|
|
f = tree[n].Freq;
|
|
opt_len += (unsigned int)f * (bits + xbits);
|
|
if(stree) static_len += (unsigned int)f * (stree[n].Len + xbits);
|
|
}
|
|
if(overflow == 0) return;
|
|
|
|
do {
|
|
bits = max_length-1;
|
|
while(bl_count[bits] == 0) bits--;
|
|
bl_count[bits]--;
|
|
bl_count[bits+1] += 2;
|
|
bl_count[max_length]--;
|
|
overflow -= 2;
|
|
} while(overflow > 0);
|
|
|
|
for(bits = max_length; bits != 0; bits--){
|
|
n = bl_count[bits];
|
|
while(n != 0){
|
|
m = heap[--h];
|
|
if(m > max_code) continue;
|
|
if(tree[m].Len != (unsigned) bits){
|
|
opt_len += ((int)bits-(int)tree[m].Len)*(int)tree[m].Freq;
|
|
tree[m].Len = bits;
|
|
}
|
|
n--;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void gen_codes (ct_data* tree,int max_code)
|
|
{
|
|
unsigned short next_code[MAX_BITS+1];
|
|
unsigned short code = 0;
|
|
int bits;
|
|
int n;
|
|
|
|
for(bits = 1; bits <= MAX_BITS; bits++){
|
|
next_code[bits] = code = (code + bl_count[bits-1]) << 1;
|
|
}
|
|
for(n = 0; n <= max_code; n++){
|
|
int len = tree[n].Len;
|
|
if(len == 0) continue;
|
|
tree[n].Code = bi_reverse(next_code[len]++, len);
|
|
}
|
|
}
|
|
|
|
static void build_tree(tree_desc* desc)
|
|
{
|
|
ct_data* tree = desc->dyn_tree;
|
|
ct_data* stree = desc->static_tree;
|
|
int elems = desc->elems;
|
|
int n, m;
|
|
int max_code = -1;
|
|
int node = elems;
|
|
|
|
heap_len = 0, heap_max = HEAP_SIZE;
|
|
|
|
for(n = 0; n < elems; n++){
|
|
if(tree[n].Freq != 0){
|
|
heap[++heap_len] = max_code = n;
|
|
depth[n] = 0;
|
|
}
|
|
else {
|
|
tree[n].Len = 0;
|
|
}
|
|
}
|
|
|
|
while(heap_len < 2){
|
|
int new_ = heap[++heap_len] = (max_code < 2 ? ++max_code : 0);
|
|
tree[new_].Freq = 1;
|
|
depth[new_] = 0;
|
|
opt_len--;
|
|
if(stree)
|
|
static_len -= stree[new_].Len;
|
|
}
|
|
desc->max_code = max_code;
|
|
|
|
for(n = heap_len/2; n >= 1; n--) pqdownheap(tree, n);
|
|
|
|
do {
|
|
pqremove(tree, n);
|
|
m = heap[SMALLEST];
|
|
|
|
heap[--heap_max] = n;
|
|
heap[--heap_max] = m;
|
|
|
|
tree[node].Freq = tree[n].Freq + tree[m].Freq;
|
|
depth[node] = (uchar) (MAX(depth[n], depth[m]) + 1);
|
|
tree[n].Dad = tree[m].Dad = node;
|
|
heap[SMALLEST] = node++;
|
|
pqdownheap(tree, SMALLEST);
|
|
|
|
} while(heap_len >= 2);
|
|
|
|
heap[--heap_max] = heap[SMALLEST];
|
|
gen_bitlen((tree_desc*)desc);
|
|
gen_codes ((ct_data*)tree, max_code);
|
|
}
|
|
|
|
static void scan_tree (ct_data* tree,int max_code)
|
|
{
|
|
int n;
|
|
int prevlen = -1;
|
|
int curlen;
|
|
int nextlen = tree[0].Len;
|
|
int count = 0;
|
|
int max_count = 7;
|
|
int min_count = 4;
|
|
|
|
if(nextlen == 0) max_count = 138, min_count = 3;
|
|
tree[max_code+1].Len = (unsigned short)-1;
|
|
|
|
for(n = 0; n <= max_code; n++){
|
|
curlen = nextlen; nextlen = tree[n+1].Len;
|
|
if(++count < max_count && curlen == nextlen){
|
|
continue;
|
|
}
|
|
else
|
|
if(count < min_count){
|
|
bl_tree[curlen].Freq += count;
|
|
}
|
|
else
|
|
if(curlen != 0){
|
|
if(curlen != prevlen) bl_tree[curlen].Freq++;
|
|
bl_tree[REP_3_6].Freq++;
|
|
}
|
|
else
|
|
if(count <= 10){
|
|
bl_tree[REPZ_3_10].Freq++;
|
|
}
|
|
else {
|
|
bl_tree[REPZ_11_138].Freq++;
|
|
}
|
|
count = 0; prevlen = curlen;
|
|
if(nextlen == 0){
|
|
max_count = 138, min_count = 3;
|
|
} else
|
|
if(curlen == nextlen){
|
|
max_count = 6, min_count = 3;
|
|
}
|
|
else {
|
|
max_count = 7, min_count = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void send_tree (ct_data* tree,int max_code)
|
|
{
|
|
int n;
|
|
int prevlen = -1;
|
|
int curlen;
|
|
int nextlen = tree[0].Len;
|
|
int count = 0;
|
|
int max_count = 7;
|
|
int min_count = 4;
|
|
|
|
if(nextlen == 0) max_count = 138, min_count = 3;
|
|
|
|
for(n = 0; n <= max_code; n++){
|
|
curlen = nextlen; nextlen = tree[n+1].Len;
|
|
if(++count < max_count && curlen == nextlen){
|
|
continue;
|
|
}
|
|
else
|
|
if(count < min_count){
|
|
do { send_code(curlen, bl_tree); } while(--count != 0);
|
|
|
|
}
|
|
else
|
|
if(curlen != 0){
|
|
if(curlen != prevlen){
|
|
send_code(curlen, bl_tree); count--;
|
|
}
|
|
send_code(REP_3_6, bl_tree); send_bits(count-3, 2);
|
|
|
|
}
|
|
else
|
|
if(count <= 10){
|
|
send_code(REPZ_3_10, bl_tree); send_bits(count-3, 3);
|
|
|
|
}
|
|
else {
|
|
send_code(REPZ_11_138, bl_tree); send_bits(count-11, 7);
|
|
}
|
|
count = 0; prevlen = curlen;
|
|
if(nextlen == 0){
|
|
max_count = 138, min_count = 3;
|
|
}
|
|
else
|
|
if(curlen == nextlen){
|
|
max_count = 6, min_count = 3;
|
|
}
|
|
else {
|
|
max_count = 7, min_count = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int build_bl_tree()
|
|
{
|
|
int max_blindex;
|
|
|
|
scan_tree((ct_data*)dyn_ltree, l_desc.max_code);
|
|
scan_tree((ct_data*)dyn_dtree, d_desc.max_code);
|
|
|
|
build_tree((tree_desc*)(&bl_desc));
|
|
for(max_blindex = BL_CODES-1; max_blindex >= 3; max_blindex--){
|
|
if(bl_tree[bl_order[max_blindex]].Len != 0) break;
|
|
}
|
|
opt_len += 3*(max_blindex+1) + 5+5+4;
|
|
|
|
return max_blindex;
|
|
}
|
|
|
|
static void send_all_trees(int lcodes,int dcodes,int blcodes)
|
|
{
|
|
int rank;
|
|
|
|
send_bits(lcodes-257, 5);
|
|
send_bits(dcodes-1, 5);
|
|
send_bits(blcodes-4, 4);
|
|
for(rank = 0; rank < blcodes; rank++){
|
|
send_bits(bl_tree[bl_order[rank]].Len, 3);
|
|
}
|
|
|
|
send_tree((ct_data*)dyn_ltree, lcodes-1);
|
|
send_tree((ct_data*)dyn_dtree, dcodes-1);
|
|
}
|
|
|
|
unsigned int flush_block(char* buf,unsigned int stored_len,int eof)
|
|
{
|
|
unsigned int opt_lenb, static_lenb;
|
|
int max_blindex;
|
|
|
|
flag_buf[last_flags] = flags;
|
|
|
|
if(*file_type == (unsigned short)UNKNOWN) set_file_type();
|
|
|
|
build_tree((tree_desc*)(&l_desc));
|
|
|
|
build_tree((tree_desc*)(&d_desc));
|
|
max_blindex = build_bl_tree();
|
|
|
|
opt_lenb = (opt_len+3+7)>>3;
|
|
static_lenb = (static_len+3+7)>>3;
|
|
input_len += stored_len;
|
|
if(static_lenb <= opt_lenb) opt_lenb = static_lenb;
|
|
|
|
if(stored_len <= opt_lenb && eof && compressed_len == 0L){
|
|
//if(buf == NULL) ErrH.Abort(IErrMsg);
|
|
copy_block(buf,(unsigned)stored_len,0);
|
|
compressed_len = stored_len << 3;
|
|
*file_method = STORE;
|
|
}
|
|
else
|
|
if(stored_len+4 <= opt_lenb && buf != (char*)NULL){
|
|
send_bits((STORED_BLOCK<<1)+eof, 3);
|
|
compressed_len = (compressed_len + 3 + 7) & ~7L;
|
|
compressed_len += (stored_len + 4) << 3;
|
|
|
|
copy_block(buf, (unsigned)stored_len, 1);
|
|
}
|
|
else
|
|
if(static_lenb == opt_lenb){
|
|
send_bits((STATIC_TREES<<1)+eof, 3);
|
|
compress_block((ct_data*)static_ltree, (ct_data*)static_dtree);
|
|
compressed_len += 3 + static_len;
|
|
}
|
|
else {
|
|
send_bits((DYN_TREES<<1)+eof, 3);
|
|
send_all_trees(l_desc.max_code+1, d_desc.max_code+1, max_blindex+1);
|
|
compress_block((ct_data*)dyn_ltree, (ct_data*)dyn_dtree);
|
|
compressed_len += 3 + opt_len;
|
|
}
|
|
init_block();
|
|
if(eof){
|
|
#ifdef DYN_ALLOC
|
|
extern uchar *window;
|
|
#else
|
|
extern uchar window[];
|
|
#endif
|
|
memset(window, 0, (unsigned)(2*WSIZE-1));
|
|
bi_windup();
|
|
compressed_len += 7;
|
|
}
|
|
return compressed_len >> 3;
|
|
}
|
|
|
|
|
|
int ct_tally(int dist,int lc)
|
|
{
|
|
l_buf[last_lit++] = (uchar)lc;
|
|
if(dist == 0){
|
|
dyn_ltree[lc].Freq++;
|
|
}
|
|
else {
|
|
dist--;
|
|
|
|
dyn_ltree[length_code[lc]+LITERALS+1].Freq++;
|
|
dyn_dtree[d_code(dist)].Freq++;
|
|
|
|
d_buf[last_dist++] = dist;
|
|
flags |= flag_bit;
|
|
}
|
|
flag_bit <<= 1;
|
|
|
|
if((last_lit & 7) == 0){
|
|
flag_buf[last_flags++] = flags;
|
|
flags = 0, flag_bit = 1;
|
|
}
|
|
if(level > 2 && (last_lit & 0xfff) == 0){
|
|
unsigned int out_length = (unsigned int)last_lit*8L;
|
|
unsigned int in_length = (unsigned int)strstart-block_start;
|
|
int dcode;
|
|
for(dcode = 0; dcode < D_CODES; dcode++){
|
|
out_length += (unsigned int)dyn_dtree[dcode].Freq*(5L+extra_dbits[dcode]);
|
|
}
|
|
out_length >>= 3;
|
|
if(last_dist < last_lit/2 && out_length < in_length/2) return 1;
|
|
}
|
|
return (last_lit == LIT_BUFSIZE-1 || last_dist == DIST_BUFSIZE);
|
|
}
|
|
|
|
static void compress_block(ct_data* ltree,ct_data* dtree)
|
|
{
|
|
unsigned dist;
|
|
int lc;
|
|
unsigned lx = 0;
|
|
unsigned dx = 0;
|
|
unsigned fx = 0;
|
|
uchar flag = 0;
|
|
unsigned code;
|
|
int extra;
|
|
|
|
if(last_lit != 0) do {
|
|
if((lx & 7) == 0) flag = flag_buf[fx++];
|
|
lc = l_buf[lx++];
|
|
if((flag & 1) == 0){
|
|
send_code(lc, ltree);
|
|
}
|
|
else {
|
|
code = length_code[lc];
|
|
send_code(code+LITERALS+1, ltree);
|
|
extra = extra_lbits[code];
|
|
if(extra != 0){
|
|
lc -= base_length[code];
|
|
send_bits(lc, extra);
|
|
}
|
|
dist = d_buf[dx++];
|
|
code = d_code(dist);
|
|
|
|
send_code(code, dtree);
|
|
extra = extra_dbits[code];
|
|
if(extra != 0){
|
|
dist -= base_dist[code];
|
|
send_bits(dist, extra);
|
|
}
|
|
}
|
|
flag >>= 1;
|
|
} while(lx < last_lit);
|
|
send_code(END_BLOCK, ltree);
|
|
}
|
|
|
|
static void set_file_type()
|
|
{
|
|
int n = 0;
|
|
unsigned ascii_freq = 0;
|
|
unsigned bin_freq = 0;
|
|
while(n < 7) bin_freq += dyn_ltree[n++].Freq;
|
|
while(n < 128) ascii_freq += dyn_ltree[n++].Freq;
|
|
while(n < LITERALS) bin_freq += dyn_ltree[n++].Freq;
|
|
*file_type = bin_freq > (ascii_freq >> 2) ? BINARY : ASCII;
|
|
}
|
|
|
|
void free_data(void)
|
|
{
|
|
#ifdef DYN_ALLOC
|
|
delete l_buf;
|
|
delete d_buf;
|
|
lm_free();
|
|
#endif
|
|
}
|