📄 inflate.c
字号:
/* do the copy */
m -= c;
if ((UINT)(q - s->window) >= d) /* offset before dest */
{ /* just copy */
r = q - d;
*q++ = *r++; c--; /* minimum count is three, */
*q++ = *r++; c--; /* so unroll loop a little */
}
else /* else offset after destination */
{
e = d - (UINT)(q - s->window); /* bytes from offset to end */
r = s->end - e; /* pointer to offset */
if (c > e) /* if source crosses, */
{
c -= e; /* copy to end of window */
do {
*q++ = *r++;
} while (--e);
r = s->window; /* copy rest from start of window */
}
}
do { /* copy all or what's left */
*q++ = *r++;
} while (--c);
break;
}
else if ((e & 64) == 0)
e = (t = t->next + ((UINT)b & inflate_mask[e]))->exop;
else
{
z->msg = (char*)"invalid distance code";
UNGRAB
ZUPDATE
return Z_DATA_ERROR;
}
} while (1);
break;
}
if ((e & 64) == 0)
{
if ((e = (t = t->next + ((UINT)b & inflate_mask[e]))->exop) == 0)
{
DUMPBITS(t->bits)
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
*q++ = (BYTE)t->base;
m--;
break;
}
}
else if (e & 32)
{
Tracevv((stderr, "inflate: * end of block\n"));
UNGRAB
ZUPDATE
return Z_STREAM_END;
}
else
{
z->msg = (char*)"invalid literal/length code";
UNGRAB
ZUPDATE
return Z_DATA_ERROR;
}
} while (1);
} while (m >= 258 && n >= 10);
/* not enough input or output--restore pointers and return */
UNGRAB
ZUPDATE
return Z_OK;
}
/******************************************************************************
*
* inflate_codes_new -
*/
static inflate_codes_statef *inflate_codes_new(
UINT bl, UINT bd,
inflate_huft *tl,
inflate_huft *td, /* need separate declaration for Borland C++ */
ZAR_STREAM* z )
{
inflate_codes_statef *c;
if ((c = (inflate_codes_statef *)
ZALLOC(z,1,sizeof(struct inflate_codes_state))) != NULL)
{
c->mode = START;
c->lbits = (BYTE)bl;
c->dbits = (BYTE)bd;
c->ltree = tl;
c->dtree = td;
Tracev((stderr, "inflate: codes new\n"));
}
return c;
}
/******************************************************************************
*
* inflate_codes -
*/
static int inflate_codes( inflate_blocks_statef *s,
ZAR_STREAM* z,
int r)
{
UINT j; /* temporary storage */
inflate_huft *t; /* temporary pointer */
UINT e; /* extra bits or operation */
ULONG b; /* bit buffer */
UINT k; /* bits in bit buffer */
BYTE *p; /* input data pointer */
UINT n; /* bytes available there */
BYTE *q; /* output window write pointer */
UINT m; /* bytes to end of window or read pointer */
BYTE *f; /* pointer to copy strings from */
inflate_codes_statef *c = s->sub.decode.codes; /* codes state */
/* copy input/output information to locals (ZUPDATE macro restores) */
LOAD
/* process input and output based on current state */
while (1) switch (c->mode)
{ /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
case START: /* x: set up for LEN */
if (m >= 258 && n >= 10)
{
ZUPDATE
r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
LOAD
if (r != Z_OK)
{
c->mode = r == Z_STREAM_END ? WASH : BADCODE;
break;
}
}
c->sub.code.need = c->lbits;
c->sub.code.tree = c->ltree;
c->mode = LEN;
case LEN: /* i: get length/literal/eob next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((UINT)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (UINT)(t->exop);
if (e == 0) /* literal */
{
c->sub.lit = t->base;
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
c->mode = LIT;
break;
}
if (e & 16) /* length */
{
c->sub.copy.get = e & 15;
c->len = t->base;
c->mode = LENEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t->next;
break;
}
if (e & 32) /* end of block */
{
Tracevv((stderr, "inflate: end of block\n"));
c->mode = WASH;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid literal/length code";
r = Z_DATA_ERROR;
ZLEAVE
case LENEXT: /* i: getting length extra (have base) */
j = c->sub.copy.get;
NEEDBITS(j)
c->len += (UINT)b & inflate_mask[j];
DUMPBITS(j)
c->sub.code.need = c->dbits;
c->sub.code.tree = c->dtree;
Tracevv((stderr, "inflate: length %u\n", c->len));
c->mode = DIST;
case DIST: /* i: get distance next */
j = c->sub.code.need;
NEEDBITS(j)
t = c->sub.code.tree + ((UINT)b & inflate_mask[j]);
DUMPBITS(t->bits)
e = (UINT)(t->exop);
if (e & 16) /* distance */
{
c->sub.copy.get = e & 15;
c->sub.copy.dist = t->base;
c->mode = DISTEXT;
break;
}
if ((e & 64) == 0) /* next table */
{
c->sub.code.need = e;
c->sub.code.tree = t->next;
break;
}
c->mode = BADCODE; /* invalid code */
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
ZLEAVE
case DISTEXT: /* i: getting distance extra */
j = c->sub.copy.get;
NEEDBITS(j)
c->sub.copy.dist += (UINT)b & inflate_mask[j];
DUMPBITS(j)
Tracevv((stderr, "inflate: distance %u\n", c->sub.copy.dist));
c->mode = COPY;
case COPY: /* o: copying bytes in window, waiting for space */
#ifndef __TURBOC__ /* Turbo C bug for following expression */
f = (UINT)(q - s->window) < c->sub.copy.dist ?
s->end - (c->sub.copy.dist - (q - s->window)) :
q - c->sub.copy.dist;
#else
f = q - c->sub.copy.dist;
if ((UINT)(q - s->window) < c->sub.copy.dist)
f = s->end - (c->sub.copy.dist - (UINT)(q - s->window));
#endif
while (c->len)
{
NEEDOUT
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
c->mode = START;
break;
case LIT: /* o: got literal, waiting for output space */
NEEDOUT
OUTBYTE(c->sub.lit)
c->mode = START;
break;
case WASH: /* o: got eob, possibly more output */
FLUSH
if (s->read != s->write)
ZLEAVE
c->mode = END;
case END:
r = Z_STREAM_END;
ZLEAVE
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
ZLEAVE
default:
r = Z_STREAM_ERROR;
ZLEAVE
}
}
/******************************************************************************
*
* inflate_codes_free -
*/
static void inflate_codes_free
(
inflate_codes_statef *c,
ZAR_STREAM* z
)
{
ZFREE(z, c);
}
/******************************************************************************
*
* inflate_blocks_reset -
*/
static void inflate_blocks_reset( inflate_blocks_statef *s,
ZAR_STREAM* z,
ULONG *c )
{
if (s->checkfn != NULL)
*c = s->check;
if (s->mode == BTREE || s->mode == DTREE)
ZFREE(z, s->sub.trees.blens);
if (s->mode == CODES)
{
inflate_codes_free(s->sub.decode.codes, z);
inflate_trees_free(s->sub.decode.td, z);
inflate_trees_free(s->sub.decode.tl, z);
}
s->mode = TYPE;
s->bitk = 0;
s->bitb = 0;
s->read = s->write = s->window;
if (s->checkfn != NULL)
z->adler = s->check = (*s->checkfn)(0L, NULL, 0);
Trace((stderr, "inflate: blocks reset\n"));
}
/******************************************************************************
*
* inflate_blocks_new -
*/
static inflate_blocks_statef *inflate_blocks_new(
ZAR_STREAM* z,
check_func c,
UINT w )
{
inflate_blocks_statef *s;
if ((s = (inflate_blocks_statef *)ZALLOC
(z,1,sizeof(struct inflate_blocks_state))) == NULL)
return s;
if ((s->window = (BYTE *)ZALLOC(z, 1, w)) == NULL)
{
ZFREE(z, s);
return NULL;
}
s->end = s->window + w;
s->checkfn = c;
s->mode = TYPE;
Trace((stderr, "inflate: blocks allocated\n"));
inflate_blocks_reset(s, z, &s->check);
return s;
}
/******************************************************************************
*
* inflate_block -
*/
static int inflate_blocks(
inflate_blocks_statef *s,
ZAR_STREAM* z,
int r)
{
UINT t; /* temporary storage */
ULONG b; /* bit buffer */
UINT k; /* bits in bit buffer */
BYTE *p; /* input data pointer */
UINT n; /* bytes available there */
BYTE *q; /* output window write pointer */
UINT m; /* bytes to end of window or read pointer */
/* copy input/output information to locals (ZUPDATE macro restores) */
LOAD
/* process input based on current state */
while (1) switch (s->mode)
{
case TYPE:
NEEDBITS(3)
t = (UINT)b & 7;
s->last = t & 1;
switch (t >> 1)
{
case 0: /* stored */
Trace((stderr, "inflate: stored block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
t = k & 7; /* go to byte boundary */
DUMPBITS(t)
s->mode = LENS; /* get length of stored block */
break;
case 1: /* fixed */
Trace((stderr, "inflate: fixed codes block%s\n",
s->last ? " (last)" : ""));
{
UINT bl, bd;
inflate_huft *tl, *td;
inflate_trees_fixed(z,&bl, &bd, &tl, &td);
s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
if (s->sub.decode.codes == NULL)
{
r = Z_MEM_ERROR;
ZLEAVE
}
s->sub.decode.tl = NULL; /* don't try to free these */
s->sub.decode.td = NULL;
}
DUMPBITS(3)
s->mode = CODES;
break;
case 2: /* dynamic */
Trace((stderr, "inflate: dynamic codes block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(3)
s->mode = TABLE;
break;
case 3: /* illegal */
DUMPBITS(3)
s->mode = BAD;
z->msg = (char*)"invalid block type";
r = Z_DATA_ERROR;
ZLEAVE
}
break;
case LENS:
NEEDBITS(32)
if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
{
s->mode = BAD;
z->msg = (char*)"invalid stored block lengths";
r = Z_DATA_ERROR;
ZLEAVE
}
s->sub.left = (UINT)b & 0xffff;
b = k = 0; /* dump bits */
Tracev((stderr, "inflate: stored length %u\n", s->sub.left));
s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
break;
case STORED:
if (n == 0)
ZLEAVE
NEEDOUT
t = s->sub.left;
if (t > n) t = n;
if (t > m) t = m;
memcpy(q, p, t);
p += t; n -= t;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -