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
00012
00013 #define exop word.what.Exop
00014 #define bits word.what.Bits
00015
00016 typedef enum {
00017 START,
00018 LEN,
00019 LENEXT,
00020 DIST,
00021 DISTEXT,
00022 COPY,
00023 LIT,
00024 WASH,
00025 END,
00026 BADCODE}
00027 inflate_codes_mode;
00028
00029
00030 struct inflate_codes_state {
00031
00032
00033 inflate_codes_mode mode;
00034
00035
00036 uInt len;
00037 union {
00038 struct {
00039 inflate_huft *tree;
00040 uInt need;
00041 } code;
00042 uInt lit;
00043 struct {
00044 uInt get;
00045 uInt dist;
00046 } copy;
00047 } sub;
00048
00049
00050 Byte lbits;
00051 Byte dbits;
00052 inflate_huft *ltree;
00053 inflate_huft *dtree;
00054
00055 };
00056
00057
00058 local inflate_codes_statef *inflate_codes_new(
00059 uInt bl, uInt bd,
00060 inflate_huft *tl,
00061 inflate_huft *td,
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(
00081 inflate_blocks_statef *s,
00082 z_streamp z,
00083 int r )
00084 {
00085 uInt j;
00086 inflate_huft *t;
00087 uInt e;
00088 uLong b;
00089 uInt k;
00090 Bytef *p;
00091 uInt n;
00092 Bytef *q;
00093 uInt m;
00094 Bytef *f;
00095 inflate_codes_statef *c = s->sub.decode.codes;
00096
00097
00098 LOAD
00099
00100
00101 while (1) switch (c->mode)
00102 {
00103 case START:
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
00117 c->sub.code.need = c->lbits;
00118 c->sub.code.tree = c->ltree;
00119 c->mode = LEN;
00120 case LEN:
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)
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)
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)
00143 {
00144 c->sub.code.need = e;
00145 c->sub.code.tree = t + t->base;
00146 break;
00147 }
00148 if (e & 32)
00149 {
00150 Tracevv((stderr, "inflate: end of block\n"));
00151 c->mode = WASH;
00152 break;
00153 }
00154 c->mode = BADCODE;
00155 z->msg = (char*)"invalid literal/length code";
00156 r = Z_DATA_ERROR;
00157 LEAVE
00158 case LENEXT:
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:
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)
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)
00181 {
00182 c->sub.code.need = e;
00183 c->sub.code.tree = t + t->base;
00184 break;
00185 }
00186 c->mode = BADCODE;
00187 z->msg = (char*)"invalid distance code";
00188 r = Z_DATA_ERROR;
00189 LEAVE
00190 case DISTEXT:
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:
00198 f = q - c->sub.copy.dist;
00199 while (f < s->window)
00200 f += s->end - s->window;
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:
00212 NEEDOUT
00213 OUTBYTE(c->sub.lit)
00214 c->mode = START;
00215 break;
00216 case WASH:
00217 if (k > 7)
00218 {
00219 Assert(k < 16, "inflate_codes grabbed too many bytes")
00220 k -= 8;
00221 n++;
00222 p--;
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:
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;
00240 #endif
00241 }
00242
00243
00244 local void inflate_codes_free(
00245 inflate_codes_statef *c,
00246 z_streamp z )
00247 {
00248 ZFREE(z, c);
00249 Tracev((stderr, "inflate: codes free\n"));
00250 }