NSIS/Source/zlib/INFBLOCK.C
2002-10-02 18:22:11 +00:00

258 lines
No EOL
7 KiB
C

#include "../exehead/config.h"
#ifdef NSIS_COMPRESS_USE_ZLIB
/* infblock.c -- interpret and process block types to last block
* Copyright (C) 1995-1998 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "zutil.h"
#include "infblock.h"
#include "inftrees.h"
#include "infcodes.h"
#include "infutil.h"
/* simplify the use of the inflate_huft type with some defines */
#define exop word.what.Exop
#define bits word.what.Bits
local const char border[] = { /* Order of the bit length code lengths */
16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
void inflateReset(z_streamp z)
{
inflate_blocks_statef *s=&z->blocks;
s->mode = TYPE;
s->bitk = s->bitb = 0;
s->read = s->write = s->window;
s->end = s->window + (1 << DEF_WBITS);
}
int inflate(z_streamp z)
{
inflate_blocks_statef *s=&z->blocks;
// lousy two bytes saved by doing this
struct
{
uInt t; /* temporary storage */
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 */
} _state;
int r=Z_OK;
#define t _state.t
#define b _state.b
#define k _state.k
#define p _state.p
#define n _state.n
#define q _state.q
#define m _state.m
/* copy input/output information to locals (UPDATE macro restores) */
LOAD
/* process input based on current state */
for (;;) switch (s->mode)
{
case TYPE:
NEEDBITS(3)
t = (uInt)b & 7;
DUMPBITS(3)
s->last = t & 1;
switch (t >> 1)
{
case 0: /* stored */
Tracev((stderr, "inflate: stored block%s\n",
s->last ? " (last)" : ""));
DUMPBITS(k&7)
s->mode = LENS; /* get length of stored block */
break;
case 1: /* fixed */
Tracev((stderr, "inflate: fixed codes block%s\n",
s->last ? " (last)" : ""));
{
uInt bl, bd;
inflate_huft *tl, *td;
inflate_trees_fixed(&bl, &bd, &tl, &td);
inflate_codes_new(&s->sub.decode.t_codes,bl, bd, tl, td);
}
s->mode = CODES;
break;
case 2: /* dynamic */
Tracev((stderr, "inflate: dynamic codes block%s\n",
s->last ? " (last)" : ""));
s->mode = TABLE;
break;
default: /* illegal */
s->mode = BAD;
// z->msg = (char*)"err";//invalid block type";
r = Z_DATA_ERROR;
LEAVE
}
break;
case LENS:
NEEDBITS(16)
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)
LEAVE
NEEDOUT
t = s->sub.left;
if (t > n) t = n;
if (t > m) t = m;
zmemcpy(q, p, t);
p += t; n -= t;
q += t; m -= t;
if (!(s->sub.left -= t))
s->mode = s->last ? DRY : TYPE;
break;
case TABLE:
NEEDBITS(14)
s->sub.trees.table = t = (uInt)b & 0x3fff;
if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
{
s->mode = BAD;
r = Z_DATA_ERROR;
LEAVE
}
// t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
DUMPBITS(14)
s->sub.trees.index = 0;
Tracev((stderr, "inflate: table sizes ok\n"));
s->mode = BTREE;
case BTREE:
while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
{
NEEDBITS(3)
s->sub.trees.t_blens[border[s->sub.trees.index++]] = (uInt)b & 7;
DUMPBITS(3)
}
while (s->sub.trees.index < 19)
s->sub.trees.t_blens[border[s->sub.trees.index++]] = 0;
s->sub.trees.bb = 7;
t = inflate_trees_bits(s->sub.trees.t_blens, &s->sub.trees.bb,
&s->sub.trees.tb, s->hufts);
if (t != Z_OK)
{
r = t;
if (r == Z_DATA_ERROR)
s->mode = BAD;
LEAVE
}
s->sub.trees.index = 0;
Tracev((stderr, "inflate: bits tree ok\n"));
s->mode = DTREE;
case DTREE:
while (t = s->sub.trees.table,
s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
{
inflate_huft *h;
uInt i, j, c;
t = s->sub.trees.bb;
NEEDBITS(t)
h = s->sub.trees.tb + ((uInt)b & (uInt)inflate_mask[t]);
t = h->bits;
c = h->base;
DUMPBITS(t)
if (c < 16)
{
s->sub.trees.t_blens[s->sub.trees.index++] = c;
}
else /* c == 16..18 */
{
if (c == 18)
{
i=7;
j=11;
}
else
{
i=c-14;
j=3;
}
NEEDBITS(i)
j += (uInt)b & (uInt)inflate_mask[i];
DUMPBITS(i)
i = s->sub.trees.index;
t = s->sub.trees.table;
if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
(c == 16 && i < 1))
{
s->mode = BAD;
r = Z_DATA_ERROR;
LEAVE
}
c = c == 16 ? s->sub.trees.t_blens[i - 1] : 0;
do {
s->sub.trees.t_blens[i++] = c;
} while (--j);
s->sub.trees.index = i;
}
}
s->sub.trees.tb = Z_NULL;
{
uInt bl, bd;
inflate_huft *tl, *td;
bl = 9; /* must be <= 9 for lookahead assumptions */
bd = 6; /* must be <= 9 for lookahead assumptions */
t = s->sub.trees.table;
t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
s->sub.trees.t_blens, &bl, &bd, &tl, &td,
s->hufts);
if (t != Z_OK)
{
if (t == (uInt)Z_DATA_ERROR)
s->mode = BAD;
r = t;
LEAVE
}
Tracev((stderr, "inflate: trees ok\n"));
inflate_codes_new(&s->sub.decode.t_codes,bl, bd, tl, td);
}
s->mode = CODES;
case CODES:
UPDATE
if ((r = inflate_codes(z, r)) != Z_STREAM_END)
return inflate_flush(z, r);
r = Z_OK;
LOAD
Tracev((stderr, "inflate: codes end, %lu total out\n",
z->total_out + (q >= s->read ? q - s->read :
(s->end - s->read) + (q - s->window))));
if (!s->last)
{
s->mode = TYPE;
break;
}
s->mode = DRY;
case DRY:
FLUSH
if (s->read != s->write)
LEAVE
s->mode = DONE;
case DONE:
r = Z_STREAM_END;
LEAVE
// case BAD:
// r = Z_DATA_ERROR;
// LEAVE
default: // we'll call Z_STREAM_ERROR if BAD anyway
r = Z_STREAM_ERROR;
LEAVE
}
}
#endif