]> git.lizzy.rs Git - zlib.git/blobdiff - inffast.c
zlib 1.1.4
[zlib.git] / inffast.c
index 8c3e4ce71c3de41a5ec00b5aaddf295f6addada1..aa7f1d4d2ad9f263b011526c454cdcfcb649fa67 100644 (file)
--- a/inffast.c
+++ b/inffast.c
@@ -1,26 +1,24 @@
 /* inffast.c -- process literals and length/distance pairs fast
- * Copyright (C) 1995 Mark Adler
+ * 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"
 
+struct inflate_codes_state {int dummy;}; /* for buggy compilers */
+
 /* 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;}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
 
 /* Called with number of bytes left to write in window at least 258
    (the maximum string length) and number of input bytes available
 
 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 *tl;
+inflate_huft *td; /* need separate declaration for Borland C++ */
+inflate_blocks_statef *s;
+z_streamp 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 */
+  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 */
+  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 */
+  Bytef *r;             /* copy source pointer */
 
   /* load input, output, bit values */
   LOAD
 
-  /* initialize masks in registers */
+  /* initialize masks */
   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 */
+  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 */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
     {
+      DUMPBITS(t->bits)
+      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
       *q++ = (Byte)t->base;
       m--;
+      continue;
     }
-    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);
+    do {
       DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv((stderr, "inflate:         * length %u\n", c));
 
-      /* 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)
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv((stderr, "inflate:         * distance %u\n", d));
 
-      /* 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);
+            /* do the copy */
+            m -= c;
+            r = q - d;
+            if (r < s->window)                  /* wrap if needed */
+            {
+              do {
+                r += s->end - s->window;        /* force pointer in window */
+              } while (r < s->window);          /* covers invalid distances */
+              e = s->end - r;
+              if (c > e)
+              {
+                c -= e;                         /* wrapped copy */
+                do {
+                    *q++ = *r++;
+                } while (--e);
+                r = s->window;
+                do {
+                    *q++ = *r++;
+                } while (--c);
+              }
+              else                              /* normal copy */
+              {
+                *q++ = *r++;  c--;
+                *q++ = *r++;  c--;
+                do {
+                    *q++ = *r++;
+                } while (--c);
+              }
+            }
+            else                                /* normal copy */
+            {
+              *q++ = *r++;  c--;
+              *q++ = *r++;  c--;
+              do {
+                *q++ = *r++;
+              } while (--c);
+            }
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
       }
-      else                             /* else offset after destination */
+      if ((e & 64) == 0)
       {
-       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);
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
       }
-    }
+      else if (e & 32)
+      {
+        Tracevv((stderr, "inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
   } while (m >= 258 && n >= 10);
 
   /* not enough input or output--restore pointers and return */