- Main Page
- Namespaces
- Classes
- Files
- Directories

- File List
- File Members

# inffast.c

    00001 /* inffast.c -- process literals and length/distance pairs fast
    00002  * Copyright (C) 1995-2002 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             r = q - d;
    00097             if (r < s->window)                  /* wrap if needed */
    00098             {
    00099               do {
    00100                 r += s->end - s->window;        /* force pointer in window */
    00101               } while (r < s->window);          /* covers invalid distances */
    00102               e = s->end - r;
    00103               if (c > e)
    00104               {
    00105                 c -= e;                         /* wrapped copy */
    00106                 do {
    00107                     *q++ = *r++;
    00108                 } while (--e);
    00109                 r = s->window;
    00110                 do {
    00111                     *q++ = *r++;
    00112                 } while (--c);
    00113               }
    00114               else                              /* normal copy */
    00115               {
    00116                 *q++ = *r++;  c--;
    00117                 *q++ = *r++;  c--;
    00118                 do {
    00119                     *q++ = *r++;
    00120                 } while (--c);
    00121               }
    00122             }
    00123             else                                /* normal copy */
    00124             {
    00125               *q++ = *r++;  c--;
    00126               *q++ = *r++;  c--;
    00127               do {
    00128                 *q++ = *r++;
    00129               } while (--c);
    00130             }
    00131             break;
    00132           }
    00133           else if ((e & 64) == 0)
    00134           {
    00135             t += t->base;
    00136             e = (t += ((uInt)b & inflate_mask[e]))->exop;
    00137           }
    00138           else
    00139           {
    00140             z->msg = (char*)"invalid distance code";
    00141             UNGRAB
    00142             UPDATE
    00143             return Z_DATA_ERROR;
    00144           }
    00145         } while (1);
    00146         break;
    00147       }
    00148       if ((e & 64) == 0)
    00149       {
    00150         t += t->base;
    00151         if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
    00152         {
    00153           DUMPBITS(t->bits)
    00154           Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
    00155                     "inflate:         * literal '%c'\n" :
    00156                     "inflate:         * literal 0x%02x\n", t->base));
    00157           *q++ = (Byte)t->base;
    00158           m--;
    00159           break;
    00160         }
    00161       }
    00162       else if (e & 32)
    00163       {
    00164         Tracevv((stderr, "inflate:         * end of block\n"));
    00165         UNGRAB
    00166         UPDATE
    00167         return Z_STREAM_END;
    00168       }
    00169       else
    00170       {
    00171         z->msg = (char*)"invalid literal/length code";
    00172         UNGRAB
    00173         UPDATE
    00174         return Z_DATA_ERROR;
    00175       }
    00176     } while (1);
    00177   } while (m >= 258 && n >= 10);
    00178
    00179   /* not enough input or output--restore pointers and return */
    00180   UNGRAB
    00181   UPDATE
    00182   return Z_OK;
    00183 }