mirror of https://github.com/madler/zlib.git
parent
bcf78a2097
commit
913afb9174
23 changed files with 559 additions and 140 deletions
@ -0,0 +1,148 @@ |
||||
/* inffast.c -- process literals and length/distance pairs fast
|
||||
* Copyright (C) 1995 Mark Adler |
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/ |
||||
|
||||
#include "zutil.h" |
||||
#include "inftrees.h" |
||||
#include "infutil.h" |
||||
#include "inffast.h" |
||||
|
||||
/* simplify the use of the inflate_huft type with some defines */ |
||||
#define base more.Base |
||||
#define next more.Next |
||||
#define exop word.what.Exop |
||||
#define bits word.what.Bits |
||||
|
||||
/* macros for bit input with no checking and for returning unused bytes */ |
||||
#ifdef DEBUG |
||||
# undef NEXTBYTE |
||||
# define NEXTBYTE (n--?0:fprintf(stderr,"inffast underrun\n"),*p++) |
||||
#endif |
||||
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}} |
||||
#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;} |
||||
|
||||
/* Called with number of bytes left to write in window at least 258
|
||||
(the maximum string length) and number of input bytes available |
||||
at least ten. The ten bytes are six bytes for the longest length/ |
||||
distance pair plus four bytes for overloading the bit buffer. */ |
||||
|
||||
int inflate_fast(bl, bd, tl, td, s, z) |
||||
uInt bl, bd; |
||||
inflate_huft *tl, *td; |
||||
struct inflate_blocks_state *s; |
||||
z_stream *z; |
||||
{ |
||||
inflate_huft *t; /* temporary pointer */ |
||||
int 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 */ |
||||
uInt ml; /* mask for literal/length tree */ |
||||
uInt md; /* mask for distance tree */ |
||||
uInt c; /* bytes to copy */ |
||||
uInt d; /* distance back to copy from */ |
||||
Byte *r; /* copy source pointer */ |
||||
|
||||
/* load input, output, bit values */ |
||||
LOAD |
||||
|
||||
/* initialize masks in registers */ |
||||
ml = inflate_mask[bl]; |
||||
md = inflate_mask[bd]; |
||||
|
||||
/* do until not enough input or output space for fast loop */ |
||||
do { /* assume called with m >= 258 && n >= 10 */ |
||||
/* get literal/length code */ |
||||
GRABBITS(20) /* max bits for literal/length code */ |
||||
if ((e = (t = tl + ((uInt)b & ml))->exop) < 0) |
||||
do { |
||||
if (e == -128) |
||||
{ |
||||
z->msg = "invalid literal/length code"; |
||||
UNGRAB |
||||
UPDATE |
||||
return Z_DATA_ERROR; |
||||
} |
||||
DUMPBITS(t->bits) |
||||
e = -e; |
||||
if (e & 64) /* end of block */ |
||||
{ |
||||
UNGRAB |
||||
UPDATE |
||||
return Z_STREAM_END; |
||||
} |
||||
} while ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) < 0); |
||||
DUMPBITS(t->bits) |
||||
|
||||
/* process literal or length (end of block already trapped) */ |
||||
if (e & 16) /* then it's a literal */ |
||||
{ |
||||
*q++ = (Byte)t->base; |
||||
m--; |
||||
} |
||||
else /* it's a length */ |
||||
{ |
||||
/* get length of block to copy (already have extra bits) */ |
||||
c = t->base + ((uInt)b & inflate_mask[e]); |
||||
DUMPBITS(e); |
||||
|
||||
/* decode distance base of block to copy */ |
||||
GRABBITS(15); /* max bits for distance code */ |
||||
if ((e = (t = td + ((uInt)b & md))->exop) < 0) |
||||
do { |
||||
if (e == -128) |
||||
{ |
||||
z->msg = "invalid distance code"; |
||||
UNGRAB |
||||
UPDATE |
||||
return Z_DATA_ERROR; |
||||
} |
||||
DUMPBITS(t->bits) |
||||
e = -e; |
||||
} while ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) < 0); |
||||
DUMPBITS(t->bits) |
||||
|
||||
/* get extra bits to add to distance base */ |
||||
GRABBITS(e) /* get extra bits (up to 13) */ |
||||
d = t->base + ((uInt)b & inflate_mask[e]); |
||||
DUMPBITS(e) |
||||
|
||||
/* do the copy */ |
||||
m -= c; |
||||
if (q - s->window >= d) /* if offset before destination, */ |
||||
{ /* just copy */ |
||||
r = q - d; |
||||
*q++ = *r++; c--; /* minimum count is three, */ |
||||
*q++ = *r++; c--; /* so unroll loop a little */ |
||||
do { |
||||
*q++ = *r++; |
||||
} while (--c); |
||||
} |
||||
else /* else offset after destination */ |
||||
{ |
||||
e = d - (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); |
||||
} |
||||
} |
||||
} while (m >= 258 && n >= 10); |
||||
|
||||
/* not enough input or output--restore pointers and return */ |
||||
UNGRAB |
||||
UPDATE |
||||
return Z_OK; |
||||
} |
@ -0,0 +1,17 @@ |
||||
/* inffast.h -- header to use inffast.c
|
||||
* Copyright (C) 1995 Mark Adler |
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/ |
||||
|
||||
/* WARNING: this file should *not* be used by applications. It is
|
||||
part of the implementation of the compression library and is |
||||
subject to change. Applications should only use zlib.h. |
||||
*/ |
||||
|
||||
extern int inflate_fast __P(( |
||||
uInt, |
||||
uInt, |
||||
inflate_huft *, |
||||
inflate_huft *, |
||||
struct inflate_blocks_state *, |
||||
z_stream *)); |
@ -0,0 +1,230 @@ |
||||
/* inflate.c -- zlib interface to inflate modules
|
||||
* Copyright (C) 1995 Mark Adler |
||||
* For conditions of distribution and use, see copyright notice in zlib.h
|
||||
*/ |
||||
|
||||
#include "zutil.h" |
||||
#include "infblock.h" |
||||
|
||||
struct inflate_blocks_state {int dummy;}; /* for buggy compilers */ |
||||
|
||||
/* inflate private state */ |
||||
struct internal_state { |
||||
|
||||
/* mode */ |
||||
enum { |
||||
METHOD, /* waiting for method byte */ |
||||
FLAG, /* waiting for flag byte */ |
||||
START, /* make new blocks state */ |
||||
BLOCKS, /* decompressing blocks */ |
||||
CHECK4, /* four check bytes to go */ |
||||
CHECK3, /* three check bytes to go */ |
||||
CHECK2, /* two check bytes to go */ |
||||
CHECK1, /* one check byte to go */ |
||||
DONE, /* finished check, done */ |
||||
ERROR} /* got an error--stay here */ |
||||
mode; /* current inflate mode */ |
||||
|
||||
/* mode dependent information */ |
||||
union { |
||||
uInt method; /* if FLAGS, method byte */ |
||||
struct inflate_blocks_state |
||||
*blocks; /* if BLOCKS, current state */ |
||||
struct { |
||||
uLong was; /* computed check value */ |
||||
uLong need; /* stream check value */ |
||||
} check; /* if CHECK, check values to compare */ |
||||
} sub; /* submode */ |
||||
|
||||
/* mode independent information */ |
||||
int nowrap; /* flag for no wrapper */ |
||||
uInt wbits; /* log2(window size) (8..15, defaults to 15) */ |
||||
|
||||
}; |
||||
|
||||
|
||||
int inflateInit(z) |
||||
z_stream *z; |
||||
{ |
||||
return inflateInit2(z, WBITS); |
||||
} |
||||
|
||||
|
||||
int inflateInit2(z, w) |
||||
z_stream *z; |
||||
int w; |
||||
{ |
||||
/* initialize state */ |
||||
if (z == Z_NULL) |
||||
return Z_STREAM_ERROR; |
||||
if (z->zalloc == Z_NULL) z->zalloc = zcalloc; |
||||
if (z->zfree == Z_NULL) z->zfree = zcfree; |
||||
z->total_in = z->total_out = 0; |
||||
z->msg = Z_NULL; |
||||
if ((z->state = (struct internal_state *) |
||||
ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL) |
||||
return Z_MEM_ERROR; |
||||
z->state->mode = METHOD; |
||||
|
||||
/* handle undocumented nowrap option (no zlib header or check) */ |
||||
z->state->nowrap = 0; |
||||
if (w < 0) |
||||
{ |
||||
w = - w; |
||||
z->state->nowrap = 1; |
||||
z->state->mode = START; |
||||
} |
||||
|
||||
/* set window size */ |
||||
if (w < 8 || w > 15) |
||||
{ |
||||
inflateEnd(z); |
||||
return Z_STREAM_ERROR; |
||||
} |
||||
z->state->wbits = w; |
||||
return Z_OK; |
||||
} |
||||
|
||||
|
||||
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++) |
||||
|
||||
int inflate(z, f) |
||||
z_stream *z; |
||||
int f; |
||||
{ |
||||
int r; |
||||
uInt b; |
||||
uLong c; |
||||
|
||||
if (z == Z_NULL || z->next_in == Z_NULL) |
||||
return Z_STREAM_ERROR; |
||||
r = Z_BUF_ERROR; |
||||
while (1) switch (z->state->mode) |
||||
{ |
||||
case METHOD: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
if (((z->state->sub.method = NEXTBYTE) & 0xf != DEFLATED)) |
||||
{ |
||||
z->state->mode = ERROR; |
||||
z->msg = "unknown compression method"; |
||||
return Z_DATA_ERROR; |
||||
} |
||||
if ((z->state->sub.method >> 4) > z->state->wbits) |
||||
{ |
||||
z->state->mode = ERROR; |
||||
z->msg = "invalid window size"; |
||||
return Z_DATA_ERROR; |
||||
} |
||||
z->state->mode = FLAG; |
||||
case FLAG: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
if ((b = NEXTBYTE) & 0x20) |
||||
{ |
||||
z->state->mode = ERROR; |
||||
z->msg = "invalid reserved bit"; |
||||
return Z_DATA_ERROR; |
||||
} |
||||
if (((z->state->sub.method << 8) + b) % 31) |
||||
{ |
||||
z->state->mode = ERROR; |
||||
z->msg = "incorrect header check"; |
||||
return Z_DATA_ERROR; |
||||
} |
||||
z->state->mode = START; |
||||
case START: |
||||
if ((z->state->sub.blocks = |
||||
inflate_blocks_new(z,1<< z->state->wbits)) == Z_NULL) |
||||
return Z_MEM_ERROR; |
||||
z->state->mode = BLOCKS; |
||||
case BLOCKS: |
||||
if ((r = inflate_blocks(z->state->sub.blocks, z, r)) != Z_STREAM_END) |
||||
return r; |
||||
inflate_blocks_free(z->state->sub.blocks, z, &c, &r); |
||||
if (z->state->nowrap) |
||||
{ |
||||
if (r != -1) |
||||
z->msg = "inflate bug--took one too many bytes"; |
||||
z->state->mode = r == -1 ? DONE : ERROR; |
||||
break; |
||||
} |
||||
z->state->sub.check.was = c; |
||||
if (r != -1) |
||||
{ |
||||
z->state->sub.check.need = (uLong)r << 24; |
||||
z->state->mode = CHECK3; |
||||
r = Z_OK; |
||||
break; |
||||
} |
||||
r = Z_OK; |
||||
z->state->mode = CHECK4; |
||||
case CHECK4: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
z->state->sub.check.need = (uLong)NEXTBYTE << 24; |
||||
z->state->mode = CHECK3; |
||||
case CHECK3: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 16; |
||||
z->state->mode = CHECK2; |
||||
case CHECK2: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
z->state->sub.check.need += (uLong)NEXTBYTE << 8; |
||||
z->state->mode = CHECK1; |
||||
case CHECK1: |
||||
if (z->avail_in == 0) return r; r = Z_OK; |
||||
z->state->sub.check.need += (uLong)NEXTBYTE; |
||||
if (z->state->sub.check.was != z->state->sub.check.need) |
||||
{ |
||||
z->state->mode = ERROR; |
||||
z->msg = "incorrect data check"; |
||||
return Z_DATA_ERROR; |
||||
} |
||||
z->state->mode = DONE; |
||||
case DONE: |
||||
return Z_STREAM_END; |
||||
case ERROR: |
||||
return Z_DATA_ERROR; |
||||
default: |
||||
return Z_STREAM_ERROR; |
||||
} |
||||
} |
||||
|
||||
|
||||
int inflateEnd(z) |
||||
z_stream *z; |
||||
{ |
||||
uLong c; |
||||
int e; |
||||
|
||||
if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL) |
||||
return Z_STREAM_ERROR; |
||||
if (z->state->mode == BLOCKS) |
||||
inflate_blocks_free(z->state->sub.blocks, z, &c, &e); |
||||
ZFREE(z, z->state); |
||||
z->state = Z_NULL; |
||||
return Z_OK; |
||||
} |
||||
|
||||
|
||||
/* inflateSync not implemented yet--this just consumes input */ |
||||
int inflateSync(z) |
||||
z_stream *z; |
||||
{ |
||||
if (z == Z_NULL) return Z_STREAM_ERROR; |
||||
if (z->avail_in == 0) return Z_BUF_ERROR; |
||||
do { |
||||
z->total_in++; |
||||
} while (--z->avail_in); |
||||
return Z_DATA_ERROR; |
||||
} |
||||
|
||||
|
||||
/* inflateReset not fully implemented yet--this frees and reallocates */ |
||||
int inflateReset(z) |
||||
z_stream *z; |
||||
{ |
||||
int r; |
||||
|
||||
if ((r = inflateEnd(z)) != Z_OK) |
||||
return r; |
||||
return inflateInit(z); |
||||
} |
@ -1,22 +0,0 @@ |
||||
/* temporary kludge assuming single pass decompression */ |
||||
|
||||
/* $Id: inflate.h,v 1.2 1995/04/11 14:47:32 jloup Exp $ */ |
||||
|
||||
#include <stdio.h> |
||||
|
||||
#define NEXTBYTE \ |
||||
(istrm->total_in++, istrm->avail_in-- == 0 ? \
|
||||
(z_error("too small"), 0) : *istrm->next_in++) |
||||
|
||||
#define FLUSH(n) { \ |
||||
if (istrm->avail_out < n) z_error("too big"); \
|
||||
istrm->avail_out -= n; \
|
||||
memcpy(istrm->next_out, slide, n); \
|
||||
istrm->next_out += n; \
|
||||
istrm->total_out += n; \
|
||||
} |
||||
#define WSIZE istrm->state->w_size |
||||
#define slide istrm->state->window |
||||
#define memzero(a,s) memset((a),0,(s)) |
||||
#define inflate z_inflate |
||||
#define qflag 1 |
Loading…
Reference in new issue