split inflate_xx_setup() subroutines from inflate_xx()
This commit is contained in:
parent
cd42cb8df0
commit
d1a19affeb
@ -45,22 +45,25 @@ typedef struct huft_s {
|
||||
} v;
|
||||
} huft_t;
|
||||
|
||||
enum {
|
||||
/* gunzip_window size--must be a power of two, and
|
||||
* at least 32K for zip's deflate method */
|
||||
GUNZIP_WSIZE = 0x8000,
|
||||
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
|
||||
BMAX = 16, /* maximum bit length of any code (16 for explode) */
|
||||
N_MAX = 288, /* maximum number of codes in any set */
|
||||
};
|
||||
|
||||
static off_t gunzip_bytes_out; /* number of output bytes */
|
||||
static uint32_t gunzip_crc;
|
||||
|
||||
static int gunzip_src_fd;
|
||||
static unsigned gunzip_outbuf_count; /* bytes in output buffer */
|
||||
|
||||
/* gunzip_window size--must be a power of two, and
|
||||
* at least 32K for zip's deflate method */
|
||||
enum { gunzip_wsize = 0x8000 };
|
||||
static unsigned char *gunzip_window;
|
||||
|
||||
static uint32_t *gunzip_crc_table;
|
||||
|
||||
/* If BMAX needs to be larger than 16, then h and x[] should be ulg. */
|
||||
#define BMAX 16 /* maximum bit length of any code (16 for explode) */
|
||||
#define N_MAX 288 /* maximum number of codes in any set */
|
||||
|
||||
/* bitbuffer */
|
||||
static unsigned gunzip_bb; /* bit buffer */
|
||||
@ -135,19 +138,16 @@ static unsigned fill_bitbuffer(unsigned bitbuffer, unsigned *current, const unsi
|
||||
* each table.
|
||||
* t: table to free
|
||||
*/
|
||||
static int huft_free(huft_t * t)
|
||||
static void huft_free(huft_t * p)
|
||||
{
|
||||
huft_t *p;
|
||||
huft_t *q;
|
||||
|
||||
/* Go through linked list, freeing from the malloced (t[-1]) address. */
|
||||
p = t;
|
||||
while (p != (huft_t *) NULL) {
|
||||
while (p) {
|
||||
q = (--p)->v.t;
|
||||
free((char *) p);
|
||||
free(p);
|
||||
p = q;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Given a list of code lengths and a maximum table size, make a set of
|
||||
@ -339,6 +339,7 @@ static int huft_build(unsigned *b, const unsigned n,
|
||||
return y != 0 && g != 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* inflate (decompress) the codes in a deflated (compressed) block.
|
||||
* Return an error code or zero if it all goes ok.
|
||||
@ -346,106 +347,116 @@ static int huft_build(unsigned *b, const unsigned n,
|
||||
* tl, td: literal/length and distance decoder tables
|
||||
* bl, bd: number of bits decoded by tl[] and td[]
|
||||
*/
|
||||
/* called with setup==1 once from inflate_block */
|
||||
/* called once with setup==0 from inflate_get_next_window */
|
||||
static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, const unsigned my_bd, int setup)
|
||||
/* called once from inflate_block */
|
||||
#define ml inflate_codes_ml
|
||||
#define md inflate_codes_md
|
||||
#define bb inflate_codes_bb
|
||||
#define k inflate_codes_k
|
||||
#define w inflate_codes_w
|
||||
#define tl inflate_codes_tl
|
||||
#define td inflate_codes_td
|
||||
#define bl inflate_codes_bl
|
||||
#define bd inflate_codes_bd
|
||||
static unsigned ml, md; /* masks for bl and bd bits */
|
||||
static unsigned bb; /* bit buffer */
|
||||
static unsigned k; /* number of bits in bit buffer */
|
||||
static unsigned w; /* current gunzip_window position */
|
||||
static huft_t *tl, *td;
|
||||
static unsigned bl, bd;
|
||||
static int resumeCopy; /* = 0; */
|
||||
static void inflate_codes_setup(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, const unsigned my_bd)
|
||||
{
|
||||
static unsigned e; /* table entry flag/number of extra bits */
|
||||
static unsigned n, d; /* length and index for copy */
|
||||
static unsigned w; /* current gunzip_window position */
|
||||
static huft_t *t; /* pointer to table entry */
|
||||
static unsigned ml, md; /* masks for bl and bd bits */
|
||||
static unsigned b; /* bit buffer */
|
||||
static unsigned k; /* number of bits in bit buffer */
|
||||
static huft_t *tl, *td;
|
||||
static unsigned bl, bd;
|
||||
static int resumeCopy = 0;
|
||||
|
||||
if (setup) { // 1st time we are called, copy in variables
|
||||
tl = my_tl;
|
||||
td = my_td;
|
||||
bl = my_bl;
|
||||
bd = my_bd;
|
||||
/* make local copies of globals */
|
||||
b = gunzip_bb; /* initialize bit buffer */
|
||||
k = gunzip_bk;
|
||||
w = gunzip_outbuf_count; /* initialize gunzip_window position */
|
||||
|
||||
/* inflate the coded data */
|
||||
ml = mask_bits[bl]; /* precompute masks for speed */
|
||||
md = mask_bits[bd];
|
||||
return 0; // Don't actually do anything the first time
|
||||
}
|
||||
tl = my_tl;
|
||||
td = my_td;
|
||||
bl = my_bl;
|
||||
bd = my_bd;
|
||||
/* make local copies of globals */
|
||||
bb = gunzip_bb; /* initialize bit buffer */
|
||||
k = gunzip_bk;
|
||||
w = gunzip_outbuf_count; /* initialize gunzip_window position */
|
||||
/* inflate the coded data */
|
||||
ml = mask_bits[bl]; /* precompute masks for speed */
|
||||
md = mask_bits[bd];
|
||||
}
|
||||
/* called once from inflate_get_next_window */
|
||||
static int inflate_codes(void)
|
||||
{
|
||||
unsigned e; /* table entry flag/number of extra bits */
|
||||
huft_t *t; /* pointer to table entry */
|
||||
|
||||
if (resumeCopy) goto do_copy;
|
||||
|
||||
while (1) { /* do until end of block */
|
||||
b = fill_bitbuffer(b, &k, bl);
|
||||
t = tl + ((unsigned) b & ml);
|
||||
bb = fill_bitbuffer(bb, &k, bl);
|
||||
t = tl + ((unsigned) bb & ml);
|
||||
e = t->e;
|
||||
if (e > 16)
|
||||
do {
|
||||
if (e == 99) {
|
||||
bb_error_msg_and_die("inflate_codes error 1");
|
||||
}
|
||||
b >>= t->b;
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
e -= 16;
|
||||
b = fill_bitbuffer(b, &k, e);
|
||||
t = t->v.t + ((unsigned) b & mask_bits[e]);
|
||||
bb = fill_bitbuffer(bb, &k, e);
|
||||
t = t->v.t + ((unsigned) bb & mask_bits[e]);
|
||||
e = t->e;
|
||||
} while (e > 16);
|
||||
b >>= t->b;
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
if (e == 16) { /* then it's a literal */
|
||||
gunzip_window[w++] = (unsigned char) t->v.n;
|
||||
if (w == gunzip_wsize) {
|
||||
gunzip_outbuf_count = (w);
|
||||
if (w == GUNZIP_WSIZE) {
|
||||
gunzip_outbuf_count = w;
|
||||
//flush_gunzip_window();
|
||||
w = 0;
|
||||
return 1; // We have a block to read
|
||||
}
|
||||
} else { /* it's an EOB or a length */
|
||||
/* length and index for copy */
|
||||
unsigned n = n; /* for gcc */
|
||||
unsigned d = d; /* for gcc */
|
||||
|
||||
/* exit if end of block */
|
||||
if (e == 15) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* get length of block to copy */
|
||||
b = fill_bitbuffer(b, &k, e);
|
||||
n = t->v.n + ((unsigned) b & mask_bits[e]);
|
||||
b >>= e;
|
||||
bb = fill_bitbuffer(bb, &k, e);
|
||||
n = t->v.n + ((unsigned) bb & mask_bits[e]);
|
||||
bb >>= e;
|
||||
k -= e;
|
||||
|
||||
/* decode distance of block to copy */
|
||||
b = fill_bitbuffer(b, &k, bd);
|
||||
t = td + ((unsigned) b & md);
|
||||
bb = fill_bitbuffer(bb, &k, bd);
|
||||
t = td + ((unsigned) bb & md);
|
||||
e = t->e;
|
||||
if (e > 16)
|
||||
do {
|
||||
if (e == 99)
|
||||
bb_error_msg_and_die("inflate_codes error 2");
|
||||
b >>= t->b;
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
e -= 16;
|
||||
b = fill_bitbuffer(b, &k, e);
|
||||
t = t->v.t + ((unsigned) b & mask_bits[e]);
|
||||
bb = fill_bitbuffer(bb, &k, e);
|
||||
t = t->v.t + ((unsigned) bb & mask_bits[e]);
|
||||
e = t->e;
|
||||
} while (e > 16);
|
||||
b >>= t->b;
|
||||
bb >>= t->b;
|
||||
k -= t->b;
|
||||
b = fill_bitbuffer(b, &k, e);
|
||||
d = w - t->v.n - ((unsigned) b & mask_bits[e]);
|
||||
b >>= e;
|
||||
bb = fill_bitbuffer(bb, &k, e);
|
||||
d = w - t->v.n - ((unsigned) bb & mask_bits[e]);
|
||||
bb >>= e;
|
||||
k -= e;
|
||||
|
||||
/* do the copy */
|
||||
do_copy:
|
||||
do {
|
||||
/* Was: n -= (e = (e = gunzip_wsize - ((d &= gunzip_wsize - 1) > w ? d : w)) > n ? n : e); */
|
||||
/* Was: n -= (e = (e = GUNZIP_WSIZE - ((d &= GUNZIP_WSIZE - 1) > w ? d : w)) > n ? n : e); */
|
||||
/* Who wrote THAT?? rewritten as: */
|
||||
d &= gunzip_wsize - 1;
|
||||
e = gunzip_wsize - (d > w ? d : w);
|
||||
d &= GUNZIP_WSIZE - 1;
|
||||
e = GUNZIP_WSIZE - (d > w ? d : w);
|
||||
if (e > n) e = n;
|
||||
n -= e;
|
||||
|
||||
@ -461,8 +472,8 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c
|
||||
gunzip_window[w++] = gunzip_window[d++];
|
||||
} while (--e);
|
||||
}
|
||||
if (w == gunzip_wsize) {
|
||||
gunzip_outbuf_count = (w);
|
||||
if (w == GUNZIP_WSIZE) {
|
||||
gunzip_outbuf_count = w;
|
||||
resumeCopy = (n != 0);
|
||||
//flush_gunzip_window();
|
||||
w = 0;
|
||||
@ -474,8 +485,8 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c
|
||||
}
|
||||
|
||||
/* restore the globals from the locals */
|
||||
gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
|
||||
gunzip_bb = b; /* restore global bit buffer */
|
||||
gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
|
||||
gunzip_bb = bb; /* restore global bit buffer */
|
||||
gunzip_bk = k;
|
||||
|
||||
/* normally just after call to inflate_codes, but save code by putting it here */
|
||||
@ -486,44 +497,54 @@ static int inflate_codes(huft_t * my_tl, huft_t * my_td, const unsigned my_bl, c
|
||||
/* done */
|
||||
return 0;
|
||||
}
|
||||
#undef ml
|
||||
#undef md
|
||||
#undef bb
|
||||
#undef k
|
||||
#undef w
|
||||
#undef tl
|
||||
#undef td
|
||||
#undef bl
|
||||
#undef bd
|
||||
|
||||
/* called once (setup==1) from inflate_block */
|
||||
/* and once (setup==0) from inflate_get_next_window */
|
||||
static int inflate_stored(int my_n, int my_b_stored, int my_k_stored, int setup)
|
||||
|
||||
static unsigned inflate_stored_n, inflate_stored_b, inflate_stored_k, inflate_stored_w;
|
||||
/* called once from inflate_block */
|
||||
static void inflate_stored_setup(int my_n, int my_b, int my_k)
|
||||
{
|
||||
inflate_stored_n = my_n;
|
||||
inflate_stored_b = my_b;
|
||||
inflate_stored_k = my_k;
|
||||
/* initialize gunzip_window position */
|
||||
inflate_stored_w = gunzip_outbuf_count;
|
||||
}
|
||||
/* called once from inflate_get_next_window */
|
||||
static int inflate_stored(void)
|
||||
{
|
||||
static unsigned n, b_stored, k_stored, w;
|
||||
|
||||
if (setup) {
|
||||
n = my_n;
|
||||
b_stored = my_b_stored;
|
||||
k_stored = my_k_stored;
|
||||
w = gunzip_outbuf_count; /* initialize gunzip_window position */
|
||||
return 0; // Don't do anything first time
|
||||
}
|
||||
|
||||
/* read and output the compressed data */
|
||||
while (n--) {
|
||||
b_stored = fill_bitbuffer(b_stored, &k_stored, 8);
|
||||
gunzip_window[w++] = (unsigned char) b_stored;
|
||||
if (w == gunzip_wsize) {
|
||||
gunzip_outbuf_count = (w);
|
||||
while (inflate_stored_n--) {
|
||||
inflate_stored_b = fill_bitbuffer(inflate_stored_b, &inflate_stored_k, 8);
|
||||
gunzip_window[inflate_stored_w++] = (unsigned char) inflate_stored_b;
|
||||
if (inflate_stored_w == GUNZIP_WSIZE) {
|
||||
gunzip_outbuf_count = inflate_stored_w;
|
||||
//flush_gunzip_window();
|
||||
w = 0;
|
||||
b_stored >>= 8;
|
||||
k_stored -= 8;
|
||||
inflate_stored_w = 0;
|
||||
inflate_stored_b >>= 8;
|
||||
inflate_stored_k -= 8;
|
||||
return 1; // We have a block
|
||||
}
|
||||
b_stored >>= 8;
|
||||
k_stored -= 8;
|
||||
inflate_stored_b >>= 8;
|
||||
inflate_stored_k -= 8;
|
||||
}
|
||||
|
||||
/* restore the globals from the locals */
|
||||
gunzip_outbuf_count = w; /* restore global gunzip_window pointer */
|
||||
gunzip_bb = b_stored; /* restore global bit buffer */
|
||||
gunzip_bk = k_stored;
|
||||
gunzip_outbuf_count = inflate_stored_w; /* restore global gunzip_window pointer */
|
||||
gunzip_bb = inflate_stored_b; /* restore global bit buffer */
|
||||
gunzip_bk = inflate_stored_k;
|
||||
return 0; // Finished
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* decompress an inflated block
|
||||
* e: last block flag
|
||||
@ -589,7 +610,8 @@ static int inflate_block(int *e)
|
||||
b_stored >>= 16;
|
||||
k_stored -= 16;
|
||||
|
||||
inflate_stored(n, b_stored, k_stored, 1); // Setup inflate_stored
|
||||
inflate_stored_setup(n, b_stored, k_stored); // Setup inflate_stored
|
||||
|
||||
return -1;
|
||||
}
|
||||
case 1:
|
||||
@ -636,7 +658,7 @@ static int inflate_block(int *e)
|
||||
}
|
||||
|
||||
/* decompress until an end-of-block code */
|
||||
inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
|
||||
inflate_codes_setup(tl, td, bl, bd); // Setup inflate_codes
|
||||
|
||||
/* huft_free code moved into inflate_codes */
|
||||
|
||||
@ -790,7 +812,7 @@ static int inflate_block(int *e)
|
||||
}
|
||||
|
||||
/* decompress until an end-of-block code */
|
||||
inflate_codes(tl, td, bl, bd, 1); // Setup inflate_codes
|
||||
inflate_codes_setup(tl, td, bl, bd); // Setup inflate_codes
|
||||
|
||||
/* huft_free code moved into inflate_codes */
|
||||
|
||||
@ -812,7 +834,7 @@ static void calculate_gunzip_crc(void)
|
||||
gunzip_bytes_out += gunzip_outbuf_count;
|
||||
}
|
||||
|
||||
/* One callsite in inflate_unzip */
|
||||
/* One callsite in inflate_unzip_internal */
|
||||
static int inflate_get_next_window(void)
|
||||
{
|
||||
static int method = -1; // Method == -1 for stored, -2 for codes
|
||||
@ -825,7 +847,7 @@ static int inflate_get_next_window(void)
|
||||
int ret;
|
||||
|
||||
if (needAnotherBlock) {
|
||||
if(e) {
|
||||
if (e) {
|
||||
calculate_gunzip_crc();
|
||||
e = 0;
|
||||
needAnotherBlock = 1;
|
||||
@ -836,32 +858,36 @@ static int inflate_get_next_window(void)
|
||||
}
|
||||
|
||||
switch (method) {
|
||||
case -1: ret = inflate_stored(0,0,0,0);
|
||||
break;
|
||||
case -2: ret = inflate_codes(0,0,0,0,0);
|
||||
break;
|
||||
default: bb_error_msg_and_die("inflate error %d", method);
|
||||
case -1:
|
||||
ret = inflate_stored();
|
||||
break;
|
||||
case -2:
|
||||
ret = inflate_codes();
|
||||
break;
|
||||
default:
|
||||
bb_error_msg_and_die("inflate error %d", method);
|
||||
}
|
||||
|
||||
if (ret == 1) {
|
||||
calculate_gunzip_crc();
|
||||
return 1; // More data left
|
||||
} else needAnotherBlock = 1; // End of that block
|
||||
} else
|
||||
needAnotherBlock = 1; // End of that block
|
||||
}
|
||||
/* Doesnt get here */
|
||||
}
|
||||
|
||||
|
||||
/* Called from inflate_gunzip() and archival/unzip.c */
|
||||
/* Called from inflate_gunzip() and inflate_unzip() */
|
||||
/* NB: bytebuffer is allocated here but freeing it is left to the caller! */
|
||||
static USE_DESKTOP(long long) int
|
||||
inflate_unzip_internal(int in, int out)
|
||||
{
|
||||
USE_DESKTOP(long long total = 0;)
|
||||
USE_DESKTOP(long long) int n = 0;
|
||||
ssize_t nwrote;
|
||||
typedef void (*sig_type) (int);
|
||||
|
||||
/* Allocate all global buffers (for DYN_ALLOC option) */
|
||||
gunzip_window = xmalloc(gunzip_wsize);
|
||||
gunzip_window = xmalloc(GUNZIP_WSIZE);
|
||||
gunzip_outbuf_count = 0;
|
||||
gunzip_bytes_out = 0;
|
||||
gunzip_src_fd = in;
|
||||
@ -878,20 +904,17 @@ inflate_unzip_internal(int in, int out)
|
||||
bytebuffer = xmalloc(bytebuffer_max);
|
||||
|
||||
while (1) {
|
||||
int ret = inflate_get_next_window();
|
||||
int r = inflate_get_next_window();
|
||||
nwrote = full_write(out, gunzip_window, gunzip_outbuf_count);
|
||||
if (nwrote != gunzip_outbuf_count) {
|
||||
bb_perror_msg("write");
|
||||
return -1;
|
||||
n = -1;
|
||||
goto ret;
|
||||
}
|
||||
USE_DESKTOP(total += nwrote;)
|
||||
if (ret == 0) break;
|
||||
USE_DESKTOP(n += nwrote;)
|
||||
if (r == 0) break;
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
free(gunzip_window);
|
||||
free(gunzip_crc_table);
|
||||
|
||||
/* Store unused bytes in a global buffer so calling applets can access it */
|
||||
if (gunzip_bk >= 8) {
|
||||
/* Undo too much lookahead. The next read will be byte aligned
|
||||
@ -901,7 +924,11 @@ inflate_unzip_internal(int in, int out)
|
||||
gunzip_bb >>= 8;
|
||||
gunzip_bk -= 8;
|
||||
}
|
||||
return USE_DESKTOP(total) + 0;
|
||||
ret:
|
||||
/* Cleanup */
|
||||
free(gunzip_window);
|
||||
free(gunzip_crc_table);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user