summaryrefslogtreecommitdiff
path: root/inffast.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-09-09 22:52:17 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-09-09 22:52:17 -0700
commit913afb9174bb474104049906c1382dec81826424 (patch)
tree46bb8ca746088f81382b4f33970b9d43c33d9ba3 /inffast.c
parentbcf78a20978d76f64b7cd46d1a4d7a79a578c77b (diff)
downloadzlib-913afb9174bb474104049906c1382dec81826424.tar.gz
zlib 0.79v0.79
Diffstat (limited to 'inffast.c')
-rw-r--r--inffast.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/inffast.c b/inffast.c
new file mode 100644
index 0000000..8c3e4ce
--- /dev/null
+++ b/inffast.c
@@ -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;
+}