00001 
00002 
00003 
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 
00014 #define exop word.what.Exop
00015 #define bits word.what.Bits
00016 
00017 typedef enum {        
00018       START,    
00019       LEN,      
00020       LENEXT,   
00021       DIST,     
00022       DISTEXT,  
00023       COPY,     
00024       LIT,      
00025       WASH,     
00026       END,      
00027       BADCODE}  
00028 inflate_codes_mode;
00029 
00030 
00031 struct inflate_codes_state {
00032 
00033   
00034   inflate_codes_mode mode;      
00035 
00036   
00037   uInt len;
00038   union {
00039     struct {
00040       inflate_huft *tree;       
00041       uInt need;                
00042     } code;             
00043     uInt lit;           
00044     struct {
00045       uInt get;                 
00046       uInt dist;                
00047     } copy;             
00048   } sub;                
00049 
00050   
00051   Byte lbits;           
00052   Byte dbits;           
00053   inflate_huft *ltree;          
00054   inflate_huft *dtree;          
00055 
00056 };
00057 
00058 
00059 inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
00060 uInt bl, bd;
00061 inflate_huft *tl;
00062 inflate_huft *td; 
00063 z_streamp z;
00064 {
00065   inflate_codes_statef *c;
00066 
00067   if ((c = (inflate_codes_statef *)
00068        ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
00069   {
00070     c->mode = START;
00071     c->lbits = (Byte)bl;
00072     c->dbits = (Byte)bd;
00073     c->ltree = tl;
00074     c->dtree = td;
00075     Tracev((stderr, "inflate:       codes new\n"));
00076   }
00077   return c;
00078 }
00079 
00080 
00081 int inflate_codes(s, z, r)
00082 inflate_blocks_statef *s;
00083 z_streamp z;
00084 int r;
00085 {
00086   uInt j;               
00087   inflate_huft *t;      
00088   uInt e;               
00089   uLong b;              
00090   uInt k;               
00091   Bytef *p;             
00092   uInt n;               
00093   Bytef *q;             
00094   uInt m;               
00095   Bytef *f;             
00096   inflate_codes_statef *c = s->sub.decode.codes;  
00097 
00098   
00099   LOAD
00100 
00101   
00102   while (1) switch (c->mode)
00103   {             
00104     case START:         
00105 #ifndef SLOW
00106       if (m >= 258 && n >= 10)
00107       {
00108         UPDATE
00109         r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
00110         LOAD
00111         if (r != Z_OK)
00112         {
00113           c->mode = r == Z_STREAM_END ? WASH : BADCODE;
00114           break;
00115         }
00116       }
00117 #endif 
00118       c->sub.code.need = c->lbits;
00119       c->sub.code.tree = c->ltree;
00120       c->mode = LEN;
00121     case LEN:           
00122       j = c->sub.code.need;
00123       NEEDBITS(j)
00124       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
00125       DUMPBITS(t->bits)
00126       e = (uInt)(t->exop);
00127       if (e == 0)               
00128       {
00129         c->sub.lit = t->base;
00130         Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
00131                  "inflate:         literal '%c'\n" :
00132                  "inflate:         literal 0x%02x\n", t->base));
00133         c->mode = LIT;
00134         break;
00135       }
00136       if (e & 16)               
00137       {
00138         c->sub.copy.get = e & 15;
00139         c->len = t->base;
00140         c->mode = LENEXT;
00141         break;
00142       }
00143       if ((e & 64) == 0)        
00144       {
00145         c->sub.code.need = e;
00146         c->sub.code.tree = t + t->base;
00147         break;
00148       }
00149       if (e & 32)               
00150       {
00151         Tracevv((stderr, "inflate:         end of block\n"));
00152         c->mode = WASH;
00153         break;
00154       }
00155       c->mode = BADCODE;        
00156       z->msg = (char*)"invalid literal/length code";
00157       r = Z_DATA_ERROR;
00158       LEAVE
00159     case LENEXT:        
00160       j = c->sub.copy.get;
00161       NEEDBITS(j)
00162       c->len += (uInt)b & inflate_mask[j];
00163       DUMPBITS(j)
00164       c->sub.code.need = c->dbits;
00165       c->sub.code.tree = c->dtree;
00166       Tracevv((stderr, "inflate:         length %u\n", c->len));
00167       c->mode = DIST;
00168     case DIST:          
00169       j = c->sub.code.need;
00170       NEEDBITS(j)
00171       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
00172       DUMPBITS(t->bits)
00173       e = (uInt)(t->exop);
00174       if (e & 16)               
00175       {
00176         c->sub.copy.get = e & 15;
00177         c->sub.copy.dist = t->base;
00178         c->mode = DISTEXT;
00179         break;
00180       }
00181       if ((e & 64) == 0)        
00182       {
00183         c->sub.code.need = e;
00184         c->sub.code.tree = t + t->base;
00185         break;
00186       }
00187       c->mode = BADCODE;        
00188       z->msg = (char*)"invalid distance code";
00189       r = Z_DATA_ERROR;
00190       LEAVE
00191     case DISTEXT:       
00192       j = c->sub.copy.get;
00193       NEEDBITS(j)
00194       c->sub.copy.dist += (uInt)b & inflate_mask[j];
00195       DUMPBITS(j)
00196       Tracevv((stderr, "inflate:         distance %u\n", c->sub.copy.dist));
00197       c->mode = COPY;
00198     case COPY:          
00199 #ifndef __TURBOC__ 
00200       f = (uInt)(q - s->window) < c->sub.copy.dist ?
00201           s->end - (c->sub.copy.dist - (q - s->window)) :
00202           q - c->sub.copy.dist;
00203 #else
00204       f = q - c->sub.copy.dist;
00205       if ((uInt)(q - s->window) < c->sub.copy.dist)
00206         f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
00207 #endif
00208       while (c->len)
00209       {
00210         NEEDOUT
00211         OUTBYTE(*f++)
00212         if (f == s->end)
00213           f = s->window;
00214         c->len--;
00215       }
00216       c->mode = START;
00217       break;
00218     case LIT:           
00219       NEEDOUT
00220       OUTBYTE(c->sub.lit)
00221       c->mode = START;
00222       break;
00223     case WASH:          
00224       if (k > 7)        
00225       {
00226         Assert(k < 16, "inflate_codes grabbed too many bytes")
00227         k -= 8;
00228         n++;
00229         p--;            
00230       }
00231       FLUSH
00232       if (s->read != s->write)
00233         LEAVE
00234       c->mode = END;
00235     case END:
00236       r = Z_STREAM_END;
00237       LEAVE
00238     case BADCODE:       
00239       r = Z_DATA_ERROR;
00240       LEAVE
00241     default:
00242       r = Z_STREAM_ERROR;
00243       LEAVE
00244   }
00245 #ifdef NEED_DUMMY_RETURN
00246   return Z_STREAM_ERROR;  
00247 #endif
00248 }
00249 
00250 
00251 void inflate_codes_free(c, z)
00252 inflate_codes_statef *c;
00253 z_streamp z;
00254 {
00255   ZFREE(z, c);
00256   Tracev((stderr, "inflate:       codes free\n"));
00257 }