Go to the documentation of this file.00001
00002
00003
00004
00005
00006 #include "zutil.h"
00007 #include "inftrees.h"
00008 #include "inflate.h"
00009 #include "inffast.h"
00010
00011 #ifndef ASMINF
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifdef POSTINC
00025 # define OFF 0
00026 # define PUP(a) *(a)++
00027 #else
00028 # define OFF 1
00029 # define PUP(a) *++(a)
00030 #endif
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 void inflate_fast(strm, start)
00068 z_streamp strm;
00069 unsigned start;
00070 {
00071 struct inflate_state FAR *state;
00072 unsigned char FAR *in;
00073 unsigned char FAR *last;
00074 unsigned char FAR *out;
00075 unsigned char FAR *beg;
00076 unsigned char FAR *end;
00077 #ifdef INFLATE_STRICT
00078 unsigned dmax;
00079 #endif
00080 unsigned wsize;
00081 unsigned whave;
00082 unsigned write;
00083 unsigned char FAR *window;
00084 unsigned long hold;
00085 unsigned bits;
00086 code const FAR *lcode;
00087 code const FAR *dcode;
00088 unsigned lmask;
00089 unsigned dmask;
00090 code this;
00091 unsigned op;
00092
00093 unsigned len;
00094 unsigned dist;
00095 unsigned char FAR *from;
00096
00097
00098 state = (struct inflate_state FAR *)strm->state;
00099 in = strm->next_in - OFF;
00100 last = in + (strm->avail_in - 5);
00101 out = strm->next_out - OFF;
00102 beg = out - (start - strm->avail_out);
00103 end = out + (strm->avail_out - 257);
00104 #ifdef INFLATE_STRICT
00105 dmax = state->dmax;
00106 #endif
00107 wsize = state->wsize;
00108 whave = state->whave;
00109 write = state->write;
00110 window = state->window;
00111 hold = state->hold;
00112 bits = state->bits;
00113 lcode = state->lencode;
00114 dcode = state->distcode;
00115 lmask = (1U << state->lenbits) - 1;
00116 dmask = (1U << state->distbits) - 1;
00117
00118
00119
00120 do {
00121 if (bits < 15) {
00122 hold += (unsigned long)(PUP(in)) << bits;
00123 bits += 8;
00124 hold += (unsigned long)(PUP(in)) << bits;
00125 bits += 8;
00126 }
00127 this = lcode[hold & lmask];
00128 dolen:
00129 op = (unsigned)(this.bits);
00130 hold >>= op;
00131 bits -= op;
00132 op = (unsigned)(this.op);
00133 if (op == 0) {
00134 Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
00135 "inflate: literal '%c'\n" :
00136 "inflate: literal 0x%02x\n", this.val));
00137 PUP(out) = (unsigned char)(this.val);
00138 }
00139 else if (op & 16) {
00140 len = (unsigned)(this.val);
00141 op &= 15;
00142 if (op) {
00143 if (bits < op) {
00144 hold += (unsigned long)(PUP(in)) << bits;
00145 bits += 8;
00146 }
00147 len += (unsigned)hold & ((1U << op) - 1);
00148 hold >>= op;
00149 bits -= op;
00150 }
00151 Tracevv((stderr, "inflate: length %u\n", len));
00152 if (bits < 15) {
00153 hold += (unsigned long)(PUP(in)) << bits;
00154 bits += 8;
00155 hold += (unsigned long)(PUP(in)) << bits;
00156 bits += 8;
00157 }
00158 this = dcode[hold & dmask];
00159 dodist:
00160 op = (unsigned)(this.bits);
00161 hold >>= op;
00162 bits -= op;
00163 op = (unsigned)(this.op);
00164 if (op & 16) {
00165 dist = (unsigned)(this.val);
00166 op &= 15;
00167 if (bits < op) {
00168 hold += (unsigned long)(PUP(in)) << bits;
00169 bits += 8;
00170 if (bits < op) {
00171 hold += (unsigned long)(PUP(in)) << bits;
00172 bits += 8;
00173 }
00174 }
00175 dist += (unsigned)hold & ((1U << op) - 1);
00176 #ifdef INFLATE_STRICT
00177 if (dist > dmax) {
00178 strm->msg = (char *)"invalid distance too far back";
00179 state->mode = BAD;
00180 break;
00181 }
00182 #endif
00183 hold >>= op;
00184 bits -= op;
00185 Tracevv((stderr, "inflate: distance %u\n", dist));
00186 op = (unsigned)(out - beg);
00187 if (dist > op) {
00188 op = dist - op;
00189 if (op > whave) {
00190 strm->msg = (char *)"invalid distance too far back";
00191 state->mode = BAD;
00192 break;
00193 }
00194 from = window - OFF;
00195 if (write == 0) {
00196 from += wsize - op;
00197 if (op < len) {
00198 len -= op;
00199 do {
00200 PUP(out) = PUP(from);
00201 } while (--op);
00202 from = out - dist;
00203 }
00204 }
00205 else if (write < op) {
00206 from += wsize + write - op;
00207 op -= write;
00208 if (op < len) {
00209 len -= op;
00210 do {
00211 PUP(out) = PUP(from);
00212 } while (--op);
00213 from = window - OFF;
00214 if (write < len) {
00215 op = write;
00216 len -= op;
00217 do {
00218 PUP(out) = PUP(from);
00219 } while (--op);
00220 from = out - dist;
00221 }
00222 }
00223 }
00224 else {
00225 from += write - op;
00226 if (op < len) {
00227 len -= op;
00228 do {
00229 PUP(out) = PUP(from);
00230 } while (--op);
00231 from = out - dist;
00232 }
00233 }
00234 while (len > 2) {
00235 PUP(out) = PUP(from);
00236 PUP(out) = PUP(from);
00237 PUP(out) = PUP(from);
00238 len -= 3;
00239 }
00240 if (len) {
00241 PUP(out) = PUP(from);
00242 if (len > 1)
00243 PUP(out) = PUP(from);
00244 }
00245 }
00246 else {
00247 from = out - dist;
00248 do {
00249 PUP(out) = PUP(from);
00250 PUP(out) = PUP(from);
00251 PUP(out) = PUP(from);
00252 len -= 3;
00253 } while (len > 2);
00254 if (len) {
00255 PUP(out) = PUP(from);
00256 if (len > 1)
00257 PUP(out) = PUP(from);
00258 }
00259 }
00260 }
00261 else if ((op & 64) == 0) {
00262 this = dcode[this.val + (hold & ((1U << op) - 1))];
00263 goto dodist;
00264 }
00265 else {
00266 strm->msg = (char *)"invalid distance code";
00267 state->mode = BAD;
00268 break;
00269 }
00270 }
00271 else if ((op & 64) == 0) {
00272 this = lcode[this.val + (hold & ((1U << op) - 1))];
00273 goto dolen;
00274 }
00275 else if (op & 32) {
00276 Tracevv((stderr, "inflate: end of block\n"));
00277 state->mode = TYPE;
00278 break;
00279 }
00280 else {
00281 strm->msg = (char *)"invalid literal/length code";
00282 state->mode = BAD;
00283 break;
00284 }
00285 } while (in < last && out < end);
00286
00287
00288 len = bits >> 3;
00289 in -= len;
00290 bits -= len << 3;
00291 hold &= (1U << bits) - 1;
00292
00293
00294 strm->next_in = in + OFF;
00295 strm->next_out = out + OFF;
00296 strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last));
00297 strm->avail_out = (unsigned)(out < end ?
00298 257 + (end - out) : 257 - (out - end));
00299 state->hold = hold;
00300 state->bits = bits;
00301 return;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 #endif