A massively spiffy yet delicately unobtrusive compression library. (grpc依赖)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

157 lines
5.2 KiB

13 years ago
/* 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"
13 years ago
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
13 years ago
/* 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;
{
13 years ago
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 */
13 years ago
/* 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 */
13 years ago
do { /* assume called with m >= 258 && n >= 10 */
13 years ago
/* get literal/length code */
13 years ago
GRABBITS(20) /* max bits for literal/length code */
13 years ago
if ((e = (t = tl + ((uInt)b & ml))->exop) < 0)
do {
13 years ago
if (e == -128)
{
z->msg = "invalid literal/length code";
13 years ago
UNGRAB
13 years ago
UPDATE
return Z_DATA_ERROR;
}
DUMPBITS(t->bits)
e = -e;
if (e & 64) /* end of block */
{
Tracevv((stderr, "inflate: * end of block\n"));
13 years ago
UNGRAB
13 years ago
UPDATE
return Z_STREAM_END;
}
13 years ago
} while ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) < 0);
DUMPBITS(t->bits)
/* process literal or length (end of block already trapped) */
13 years ago
if (e & 16) /* then it's a literal */
13 years ago
{
13 years ago
Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
13 years ago
"inflate: * literal '%c'\n" :
"inflate: * literal 0x%02x\n", t->base));
13 years ago
*q++ = (Byte)t->base;
m--;
}
13 years ago
else /* it's a length */
13 years ago
{
/* get length of block to copy (already have extra bits) */
c = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e);
13 years ago
Tracevv((stderr, "inflate: * length %u\n", c));
13 years ago
/* decode distance base of block to copy */
13 years ago
GRABBITS(15); /* max bits for distance code */
13 years ago
if ((e = (t = td + ((uInt)b & md))->exop) < 0)
13 years ago
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);
13 years ago
DUMPBITS(t->bits)
/* get extra bits to add to distance base */
13 years ago
GRABBITS((uInt)e) /* get extra bits (up to 13) */
13 years ago
d = t->base + ((uInt)b & inflate_mask[e]);
DUMPBITS(e)
13 years ago
Tracevv((stderr, "inflate: * distance %u\n", d));
13 years ago
/* do the copy */
m -= c;
13 years ago
if ((uInt)(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);
13 years ago
}
13 years ago
else /* else offset after destination */
13 years ago
{
13 years ago
e = d - (q - s->window); /* bytes from offset to end */
r = s->end - e; /* pointer to offset */
if (c > (uInt)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);
13 years ago
}
}
} while (m >= 258 && n >= 10);
/* not enough input or output--restore pointers and return */
UNGRAB
UPDATE
return Z_OK;
}