]> git.lizzy.rs Git - zlib.git/blobdiff - inffast.c
zlib 1.1.4
[zlib.git] / inffast.c
index 49ed1df8ec2da9d30b7ec48d2d44f84488fe2756..aa7f1d4d2ad9f263b011526c454cdcfcb649fa67 100644 (file)
--- a/inffast.c
+++ b/inffast.c
@@ -1,24 +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 */
 #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
@@ -27,23 +27,24 @@ struct inflate_codes_state {int dummy;}; /* for buggy compilers */
 
 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 */
   uInt e;               /* extra bits or operation */
   uLong b;              /* bit buffer */
   uInt k;               /* bits in bit buffer */
-  Byte *p;              /* input data pointer */
+  Bytef *p;             /* input data pointer */
   uInt n;               /* bytes available there */
-  Byte *q;              /* output window write pointer */
+  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 */
-  Byte *r;              /* copy source pointer */
+  Bytef *r;             /* copy source pointer */
 
   /* load input, output, bit values */
   LOAD
@@ -92,35 +93,51 @@ z_stream *z;
 
             /* do the copy */
             m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
+            r = q - d;
+            if (r < s->window)                  /* wrap if needed */
             {
-              e = d - (q - s->window);  /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
+              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;                 /* copy to end of window */
+                c -= e;                         /* wrapped copy */
                 do {
-                  *q++ = *r++;
+                    *q++ = *r++;
                 } while (--e);
-                r = s->window;          /* copy rest from start of window */
+                r = s->window;
+                do {
+                    *q++ = *r++;
+                } while (--c);
+              }
+              else                              /* normal copy */
+              {
+                *q++ = *r++;  c--;
+                *q++ = *r++;  c--;
+                do {
+                    *q++ = *r++;
+                } while (--c);
               }
             }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
+            else                                /* normal copy */
+            {
+              *q++ = *r++;  c--;
+              *q++ = *r++;  c--;
+              do {
+                *q++ = *r++;
+              } while (--c);
+            }
             break;
           }
           else if ((e & 64) == 0)
-            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
           else
           {
-            z->msg = "invalid distance code";
+            z->msg = (char*)"invalid distance code";
             UNGRAB
             UPDATE
             return Z_DATA_ERROR;
@@ -130,7 +147,8 @@ z_stream *z;
       }
       if ((e & 64) == 0)
       {
-        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
         {
           DUMPBITS(t->bits)
           Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
@@ -150,7 +168,7 @@ z_stream *z;
       }
       else
       {
-        z->msg = "invalid literal/length code";
+        z->msg = (char*)"invalid literal/length code";
         UNGRAB
         UPDATE
         return Z_DATA_ERROR;