infcodes.c

Go to the documentation of this file.
00001 /* infcodes.c -- process literals and length/distance pairs
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 
00012 /* simplify the use of the inflate_huft type with some defines */
00013 #define exop word.what.Exop
00014 #define bits word.what.Bits
00015 
00016 typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
00017       START,    /* x: set up for LEN */
00018       LEN,      /* i: get length/literal/eob next */
00019       LENEXT,   /* i: getting length extra (have base) */
00020       DIST,     /* i: get distance next */
00021       DISTEXT,  /* i: getting distance extra */
00022       COPY,     /* o: copying bytes in window, waiting for space */
00023       LIT,      /* o: got literal, waiting for output space */
00024       WASH,     /* o: got eob, possibly still output waiting */
00025       END,      /* x: got eob and all data flushed */
00026       BADCODE}  /* x: got error */
00027 inflate_codes_mode;
00028 
00029 /* inflate codes private state */
00030 struct inflate_codes_state {
00031 
00032   /* mode */
00033   inflate_codes_mode mode;      /* current inflate_codes mode */
00034 
00035   /* mode dependent information */
00036   uInt len;
00037   union {
00038     struct {
00039       inflate_huft *tree;       /* pointer into tree */
00040       uInt need;                /* bits needed */
00041     } code;             /* if LEN or DIST, where in tree */
00042     uInt lit;           /* if LIT, literal */
00043     struct {
00044       uInt get;                 /* bits to get for extra */
00045       uInt dist;                /* distance back to copy from */
00046     } copy;             /* if EXT or COPY, where and how much */
00047   } sub;                /* submode */
00048 
00049   /* mode independent information */
00050   Byte lbits;           /* ltree bits decoded per branch */
00051   Byte dbits;           /* dtree bits decoder per branch */
00052   inflate_huft *ltree;          /* literal/length/eob tree */
00053   inflate_huft *dtree;          /* distance tree */
00054 
00055 };
00056 
00057 
00058 local inflate_codes_statef *inflate_codes_new( /* bl, bd, tl, td, z) */
00059 uInt bl, uInt bd,
00060 inflate_huft *tl,
00061 inflate_huft *td, /* need separate declaration for Borland C++ */
00062 z_streamp z )
00063 {
00064   inflate_codes_statef *c;
00065 
00066   if ((c = (inflate_codes_statef *)
00067        ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
00068   {
00069     c->mode = START;
00070     c->lbits = (Byte)bl;
00071     c->dbits = (Byte)bd;
00072     c->ltree = tl;
00073     c->dtree = td;
00074     Tracev((stderr, "inflate:       codes new\n"));
00075   }
00076   return c;
00077 }
00078 
00079 
00080 local int inflate_codes( /* s, z, r) */
00081 inflate_blocks_statef *s,
00082 z_streamp z,
00083 int r )
00084 {
00085   uInt j;               /* temporary storage */
00086   inflate_huft *t;      /* temporary pointer */
00087   uInt e;               /* extra bits or operation */
00088   uLong b;              /* bit buffer */
00089   uInt k;               /* bits in bit buffer */
00090   Bytef *p;             /* input data pointer */
00091   uInt n;               /* bytes available there */
00092   Bytef *q;             /* output window write pointer */
00093   uInt m;               /* bytes to end of window or read pointer */
00094   Bytef *f;             /* pointer to copy strings from */
00095   inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
00096 
00097   /* copy input/output information to locals (UPDATE macro restores) */
00098   LOAD
00099 
00100   /* process input and output based on current state */
00101   while (1) switch (c->mode)
00102   {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
00103     case START:         /* x: set up for LEN */
00104 #ifndef SLOW
00105       if (m >= 258 && n >= 10)
00106       {
00107         UPDATE
00108         r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
00109         LOAD
00110         if (r != Z_OK)
00111         {
00112           c->mode = r == Z_STREAM_END ? WASH : BADCODE;
00113           break;
00114         }
00115       }
00116 #endif /* !SLOW */
00117       c->sub.code.need = c->lbits;
00118       c->sub.code.tree = c->ltree;
00119       c->mode = LEN;
00120     case LEN:           /* i: get length/literal/eob next */
00121       j = c->sub.code.need;
00122       NEEDBITS(j)
00123       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
00124       DUMPBITS(t->bits)
00125       e = (uInt)(t->exop);
00126       if (e == 0)               /* literal */
00127       {
00128         c->sub.lit = t->base;
00129         Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
00130                  "inflate:         literal '%c'\n" :
00131                  "inflate:         literal 0x%02x\n", t->base));
00132         c->mode = LIT;
00133         break;
00134       }
00135       if (e & 16)               /* length */
00136       {
00137         c->sub.copy.get = e & 15;
00138         c->len = t->base;
00139         c->mode = LENEXT;
00140         break;
00141       }
00142       if ((e & 64) == 0)        /* next table */
00143       {
00144         c->sub.code.need = e;
00145         c->sub.code.tree = t + t->base;
00146         break;
00147       }
00148       if (e & 32)               /* end of block */
00149       {
00150         Tracevv((stderr, "inflate:         end of block\n"));
00151         c->mode = WASH;
00152         break;
00153       }
00154       c->mode = BADCODE;        /* invalid code */
00155       z->msg = (char*)"invalid literal/length code";
00156       r = Z_DATA_ERROR;
00157       LEAVE
00158     case LENEXT:        /* i: getting length extra (have base) */
00159       j = c->sub.copy.get;
00160       NEEDBITS(j)
00161       c->len += (uInt)b & inflate_mask[j];
00162       DUMPBITS(j)
00163       c->sub.code.need = c->dbits;
00164       c->sub.code.tree = c->dtree;
00165       Tracevv((stderr, "inflate:         length %u\n", c->len));
00166       c->mode = DIST;
00167     case DIST:          /* i: get distance next */
00168       j = c->sub.code.need;
00169       NEEDBITS(j)
00170       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
00171       DUMPBITS(t->bits)
00172       e = (uInt)(t->exop);
00173       if (e & 16)               /* distance */
00174       {
00175         c->sub.copy.get = e & 15;
00176         c->sub.copy.dist = t->base;
00177         c->mode = DISTEXT;
00178         break;
00179       }
00180       if ((e & 64) == 0)        /* next table */
00181       {
00182         c->sub.code.need = e;
00183         c->sub.code.tree = t + t->base;
00184         break;
00185       }
00186       c->mode = BADCODE;        /* invalid code */
00187       z->msg = (char*)"invalid distance code";
00188       r = Z_DATA_ERROR;
00189       LEAVE
00190     case DISTEXT:       /* i: getting distance extra */
00191       j = c->sub.copy.get;
00192       NEEDBITS(j)
00193       c->sub.copy.dist += (uInt)b & inflate_mask[j];
00194       DUMPBITS(j)
00195       Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
00196       c->mode = COPY;
00197     case COPY:          /* o: copying bytes in window, waiting for space */
00198       f = q - c->sub.copy.dist;
00199       while (f < s->window)             /* modulo window size-"while" instead */
00200         f += s->end - s->window;        /* of "if" handles invalid distances */
00201       while (c->len)
00202       {
00203         NEEDOUT
00204         OUTBYTE(*f++)
00205         if (f == s->end)
00206           f = s->window;
00207         c->len--;
00208       }
00209       c->mode = START;
00210       break;
00211     case LIT:           /* o: got literal, waiting for output space */
00212       NEEDOUT
00213       OUTBYTE(c->sub.lit)
00214       c->mode = START;
00215       break;
00216     case WASH:          /* o: got eob, possibly more output */
00217       if (k > 7)        /* return unused byte, if any */
00218       {
00219         Assert(k < 16, "inflate_codes grabbed too many bytes")
00220         k -= 8;
00221         n++;
00222         p--;            /* can always return one */
00223       }
00224       FLUSH
00225       if (s->read != s->write)
00226         LEAVE
00227       c->mode = END;
00228     case END:
00229       r = Z_STREAM_END;
00230       LEAVE
00231     case BADCODE:       /* x: got error */
00232       r = Z_DATA_ERROR;
00233       LEAVE
00234     default:
00235       r = Z_STREAM_ERROR;
00236       LEAVE
00237   }
00238 #ifdef NEED_DUMMY_RETURN
00239   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
00240 #endif
00241 }
00242 
00243 
00244 local void inflate_codes_free( /* c, z) */
00245 inflate_codes_statef *c,
00246 z_streamp z )
00247 {
00248   ZFREE(z, c);
00249   Tracev((stderr, "inflate:       codes free\n"));
00250 }

Generated on Tue Jul 5 14:13:47 2011 for ROOT_528-00b_version by  doxygen 1.5.1