Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

inffast.c

Go to the documentation of this file.
00001 /* inffast.c -- process literals and length/distance pairs fast
00002  * Copyright (C) 1995-1998 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h 
00004  */
00005 
00006 #include "zutil.h"
00007 #include "inftrees.h"
00008 #include "infblock.h"
00009 #include "infcodes.h"
00010 #include "infutil.h"
00011 #include "inffast.h"
00012 
00013 struct inflate_codes_state {int dummy;}; /* for buggy compilers */
00014 
00015 /* simplify the use of the inflate_huft type with some defines */
00016 #define exop word.what.Exop
00017 #define bits word.what.Bits
00018 
00019 /* macros for bit input with no checking and for returning unused bytes */
00020 #define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
00021 #define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
00022 
00023 /* Called with number of bytes left to write in window at least 258
00024    (the maximum string length) and number of input bytes available
00025    at least ten.  The ten bytes are six bytes for the longest length/
00026    distance pair plus four bytes for overloading the bit buffer. */
00027 
00028 int inflate_fast(bl, bd, tl, td, s, z)
00029 uInt bl, bd;
00030 inflate_huft *tl;
00031 inflate_huft *td; /* need separate declaration for Borland C++ */
00032 inflate_blocks_statef *s;
00033 z_streamp z;
00034 {
00035   inflate_huft *t;      /* temporary pointer */
00036   uInt e;               /* extra bits or operation */
00037   uLong b;              /* bit buffer */
00038   uInt k;               /* bits in bit buffer */
00039   Bytef *p;             /* input data pointer */
00040   uInt n;               /* bytes available there */
00041   Bytef *q;             /* output window write pointer */
00042   uInt m;               /* bytes to end of window or read pointer */
00043   uInt ml;              /* mask for literal/length tree */
00044   uInt md;              /* mask for distance tree */
00045   uInt c;               /* bytes to copy */
00046   uInt d;               /* distance back to copy from */
00047   Bytef *r;             /* copy source pointer */
00048 
00049   /* load input, output, bit values */
00050   LOAD
00051 
00052   /* initialize masks */
00053   ml = inflate_mask[bl];
00054   md = inflate_mask[bd];
00055 
00056   /* do until not enough input or output space for fast loop */
00057   do {                          /* assume called with m >= 258 && n >= 10 */
00058     /* get literal/length code */
00059     GRABBITS(20)                /* max bits for literal/length code */
00060     if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
00061     {
00062       DUMPBITS(t->bits)
00063       Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
00064                 "inflate:         * literal '%c'\n" :
00065                 "inflate:         * literal 0x%02x\n", t->base));
00066       *q++ = (Byte)t->base;
00067       m--;
00068       continue;
00069     }
00070     do {
00071       DUMPBITS(t->bits)
00072       if (e & 16)
00073       {
00074         /* get extra bits for length */
00075         e &= 15;
00076         c = t->base + ((uInt)b & inflate_mask[e]);
00077         DUMPBITS(e)
00078         Tracevv((stderr, "inflate:         * length %u\n", c));
00079 
00080         /* decode distance base of block to copy */
00081         GRABBITS(15);           /* max bits for distance code */
00082         e = (t = td + ((uInt)b & md))->exop;
00083         do {
00084           DUMPBITS(t->bits)
00085           if (e & 16)
00086           {
00087             /* get extra bits to add to distance base */
00088             e &= 15;
00089             GRABBITS(e)         /* get extra bits (up to 13) */
00090             d = t->base + ((uInt)b & inflate_mask[e]);
00091             DUMPBITS(e)
00092             Tracevv((stderr, "inflate:         * distance %u\n", d));
00093 
00094             /* do the copy */
00095             m -= c;
00096             if ((uInt)(q - s->window) >= d)     /* offset before dest */
00097             {                                   /*  just copy */
00098               r = q - d;
00099               *q++ = *r++;  c--;        /* minimum count is three, */
00100               *q++ = *r++;  c--;        /*  so unroll loop a little */
00101             }
00102             else                        /* else offset after destination */
00103             {
00104               e = d - (uInt)(q - s->window); /* bytes from offset to end */
00105               r = s->end - e;           /* pointer to offset */
00106               if (c > e)                /* if source crosses, */
00107               {
00108                 c -= e;                 /* copy to end of window */
00109                 do {
00110                   *q++ = *r++;
00111                 } while (--e);
00112                 r = s->window;          /* copy rest from start of window */
00113               }
00114             }
00115             do {                        /* copy all or what's left */
00116               *q++ = *r++;
00117             } while (--c);
00118             break;
00119           }
00120           else if ((e & 64) == 0)
00121           {
00122             t += t->base;
00123             e = (t += ((uInt)b & inflate_mask[e]))->exop;
00124           }
00125           else
00126           {
00127             z->msg = (char*)"invalid distance code";
00128             UNGRAB
00129             UPDATE
00130             return Z_DATA_ERROR;
00131           }
00132         } while (1);
00133         break;
00134       }
00135       if ((e & 64) == 0)
00136       {
00137         t += t->base;
00138         if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
00139         {
00140           DUMPBITS(t->bits)
00141           Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
00142                     "inflate:         * literal '%c'\n" :
00143                     "inflate:         * literal 0x%02x\n", t->base));
00144           *q++ = (Byte)t->base;
00145           m--;
00146           break;
00147         }
00148       }
00149       else if (e & 32)
00150       {
00151         Tracevv((stderr, "inflate:         * end of block\n"));
00152         UNGRAB
00153         UPDATE
00154         return Z_STREAM_END;
00155       }
00156       else
00157       {
00158         z->msg = (char*)"invalid literal/length code";
00159         UNGRAB
00160         UPDATE
00161         return Z_DATA_ERROR;
00162       }
00163     } while (1);
00164   } while (m >= 258 && n >= 10);
00165 
00166   /* not enough input or output--restore pointers and return */
00167   UNGRAB
00168   UPDATE
00169   return Z_OK;
00170 }

Generated on Sat Oct 13 16:08:38 2001 for XMILL by doxygen1.2.11.1 written by Dimitri van Heesch, © 1997-2001