/* infcodes.c -- process literals and length/distance pairs
* Copyright (C) 1995-2002 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "inftrees.h"
#include "infblock.h"
#include "infcodes.h"
#include "infutil.h"
#include "inffast.h"
/* simplify the use of the inflate_huft type with some defines */
typedef enum { /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
/* inflate codes private state */
struct inflate_codes_state {
/* mode */
/* mode dependent information */
union {
struct {
struct {
/* mode independent information */
};
z_streamp z;
{
if ((c = (inflate_codes_statef *)
{
}
return c;
}
int inflate_codes(s, z, r)
z_streamp 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 */
Bytef *p; /* input data pointer */
uInt n; /* bytes available there */
Bytef *q; /* output window write pointer */
uInt m; /* bytes to end of window or read pointer */
Bytef *f; /* pointer to copy strings from */
/* 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 */
#ifndef SLOW
if (m >= 258 && n >= 10)
{
if (r != Z_OK)
{
break;
}
}
#endif /* !SLOW */
NEEDBITS(j)
if (e == 0) /* literal */
{
"inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", t->base));
break;
}
if (e & 16) /* length */
{
break;
}
if ((e & 64) == 0) /* next table */
{
break;
}
if (e & 32) /* end of block */
{
break;
}
r = Z_DATA_ERROR;
case LENEXT: /* i: getting length extra (have base) */
NEEDBITS(j)
DUMPBITS(j)
case DIST: /* i: get distance next */
NEEDBITS(j)
if (e & 16) /* distance */
{
break;
}
if ((e & 64) == 0) /* next table */
{
break;
}
z->msg = (char*)"invalid distance code";
r = Z_DATA_ERROR;
case DISTEXT: /* i: getting distance extra */
NEEDBITS(j)
DUMPBITS(j)
case COPY: /* o: copying bytes in window, waiting for space */
while (f < s->window) /* modulo window size-"while" instead */
while (c->len)
{
OUTBYTE(*f++)
if (f == s->end)
f = s->window;
c->len--;
}
break;
case LIT: /* o: got literal, waiting for output space */
break;
case WASH: /* o: got eob, possibly more output */
if (k > 7) /* return unused byte, if any */
{
k -= 8;
n++;
p--; /* can always return one */
}
case END:
r = Z_STREAM_END;
case BADCODE: /* x: got error */
r = Z_DATA_ERROR;
default:
r = Z_STREAM_ERROR;
}
#ifdef NEED_DUMMY_RETURN
return Z_STREAM_ERROR; /* Some dumb compilers complain without this */
#endif
}
void inflate_codes_free(c, z)
z_streamp z;
{
ZFREE(z, c);
}