#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
struct inflate_codes_state {int dummy;};
#define exop word.what.Exop
#define bits word.what.Bits
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
int inflate_fast(bl, bd, tl, td, s, z)
uInt bl, bd;
inflate_huft *tl;
inflate_huft *td;
inflate_blocks_statef *s;
z_streamp z;
{
inflate_huft *t;
uInt e;
uLong b;
uInt k;
Bytef *p;
uInt n;
Bytef *q;
uInt m;
uInt ml;
uInt md;
uInt c;
uInt d;
Bytef *r;
LOAD
ml = inflate_mask[bl];
md = inflate_mask[bd];
do {
GRABBITS(20)
if ((e = (t = tl + ((uInt)b & ml))->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--;
continue;
}
do {
DUMPBITS(t->bits)
if (e & 16)
{
e &= 15;
c = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * length %u\n", c));
GRABBITS(15);
e = (t = td + ((uInt)b & md))->exop;
do {
DUMPBITS(t->bits)
if (e & 16)
{
e &= 15;
GRABBITS(e)
d = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
Tracevv((stderr, "inflate: * distance %u\n", d));
m -= c;
r = q - d;
if (r < s->window)
{
do {
r += s->end - s->window;
} while (r < s->window);
e = s->end - r;
if (c > e)
{
c -= e;
do {
*q++ = *r++;
} while (--e);
r = s->window;
do {
*q++ = *r++;
} while (--c);
}
else
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
}
else
{
*q++ = *r++; c--;
*q++ = *r++; c--;
do {
*q++ = *r++;
} while (--c);
}
break;
}
else if ((e & 64) == 0)
{
t += t->base;
e = (t += ((uInt)b & inflate_mask[e]))->exop;
}
else
{
z->msg = (char*)"invalid distance code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
break;
}
if ((e & 64) == 0)
{
t += t->base;
if ((e = (t += ((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
UPDATE
return Z_STREAM_END;
}
else
{
z->msg = (char*)"invalid literal/length code";
UNGRAB
UPDATE
return Z_DATA_ERROR;
}
} while (1);
} while (m >= 258 && n >= 10);
UNGRAB
UPDATE
return Z_OK;
}