Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninfcodes.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 Sun May 27 2012 04:33:51 for ReactOS by
1.7.6.1
|