#include "../game/q_shared.h" #include "../qcommon/qcommon.h" #include "zip.h" #include "inflate.h" #ifdef _TIMING int totalInflateTime; int totalInflateCount; #endif // If you use the zlib library in a product, an acknowledgment is welcome // in the documentation of your product. If for some reason you cannot // include such an acknowledgment, I would appreciate that you keep this // copyright string in the executable of your product. const char inflate_copyright[] = "Inflate 1.1.3 Copyright 1995-1998 Mark Adler "; static const char *inflate_error = "OK"; // int inflate(z_stream *strm); // // inflate decompresses as much data as possible, and stops when the input // buffer becomes empty or the output buffer becomes full. It may some // introduce some output latency (reading input without producing any output) // except when forced to flush. // // The detailed semantics are as follows. inflate performs one or both of the // following actions: // // - Decompress more input starting at next_in and update next_in and avail_in // accordingly. If not all input can be processed (because there is not // enough room in the output buffer), next_in is updated and processing // will resume at this point for the next call of inflate(). // // - Provide more output starting at next_out and update next_out and avail_out // accordingly. inflate() provides as much output as possible, until there // is no more input data or no more space in the output buffer (see below // about the flush parameter). // // Before the call of inflate(), the application should ensure that at least // one of the actions is possible, by providing more input and/or consuming // more output, and updating the next_* and avail_* values accordingly. // The application can consume the uncompressed output when it wants, for // example when the output buffer is full (avail_out == 0), or after each // call of inflate(). If inflate returns Z_OK and with zero avail_out, it // must be called again after making room in the output buffer because there // might be more output pending. // // If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much // output as possible to the output buffer. The flushing behavior of inflate is // not specified for values of the flush parameter other than Z_SYNC_FLUSH // and Z_FINISH, but the current implementation actually flushes as much output // as possible anyway. // // inflate() should normally be called until it returns Z_STREAM_END or an // error. However if all decompression is to be performed in a single step // (a single call of inflate), the parameter flush should be set to // Z_FINISH. In this case all pending input is processed and all pending // output is flushed; avail_out must be large enough to hold all the // uncompressed data. (The size of the uncompressed data may have been saved // by the compressor for this purpose.) The next operation on this stream must // be inflateEnd to deallocate the decompression state. The use of Z_FINISH // is never required, but can be used to inform inflate that a faster routine // may be used for the single inflate() call. // // It sets strm->adler to the adler32 checksum of all output produced // so and returns Z_OK, Z_STREAM_END or // an error code as described below. At the end of the stream, inflate() // checks that its computed adler32 checksum is equal to that saved by the // compressor and returns Z_STREAM_END only if the checksum is correct. // // inflate() returns Z_OK if some progress has been made (more input processed // or more output produced), Z_STREAM_END if the end of the compressed data has // been reached and all uncompressed output has been produced, // Z_DATA_ERROR if the input data was // corrupted (input stream not conforming to the zlib format or incorrect // adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent // (for example if next_in or next_out was NULL), // Z_BUF_ERROR if no progress is possible or if there was not // enough room in the output buffer when Z_FINISH is used. // int inflateEnd (z_stream *strm); // // All dynamically allocated data structures for this stream are freed. // This function discards any unprocessed input and does not flush any // pending output. // // inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state // was inconsistent. In the error case, msg may be set but then points to a // static string (which must not be deallocated). // EStatus inflateInit(z_stream *strm, EFlush flush, int noWrap = 0); // // inflateInit returns Z_OK if success, // Z_STREAM_ERROR if a parameter is invalid. // msg is set to "OK" if there is no error message. inflateInit // does not perform any decompression apart from reading the zlib header if // present: this will be done by inflate(). (So next_in and avail_in may be // modified, but next_out and avail_out are unchanged.) // Notes beyond the 1.93a appnote.txt: // // 1. Distance pointers never point before the beginning of the output // stream. // 2. Distance pointers can point back across blocks, up to 32k away. // 3. There is an implied maximum of 7 bits for the bit length table and // 15 bits for the actual data. // 4. If only one code exists, then it is encoded using one bit. (Zero // would be more efficient, but perhaps a little confusing.) If two // codes exist, they are coded using one bit each (0 and 1). // 5. There is no way of sending zero distance codes--a dummy must be // sent if there are none. (History: a pre 2.0 version of PKZIP would // store blocks with no distance codes, but this was discovered to be // too harsh a criterion.) Valid only for 1.93a. 2.04c does allow // zero distance codes, which is sent as one code of zero bits in // length. // 6. There are up to 286 literal/length codes. Code 256 represents the // end-of-block. Note however that the static length tree defines // 288 codes just to fill out the Huffman codes. Codes 286 and 287 // cannot be used though, since there is no length base or extra bits // defined for them. Similarily, there are up to 30 distance codes. // However, static trees define 32 codes (all 5 bits) to fill out the // Huffman codes, but the last two had better not show up in the data. // 7. Unzip can check dynamic Huffman blocks for complete code sets. // The exception is that a single code would not be complete (see #4). // 8. The five bits following the block type is really the number of // literal codes sent minus 257. // 9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits // (1+6+6). Therefore, to output three times the length, you output // three codes (1+1+1), whereas to output four times the same length, // you only need two codes (1+3). Hmm. // 10. In the tree reconstruction algorithm, Code = Code + Increment // only if BitLength(i) is not zero. (Pretty obvious.) // 11. Correction: 4 Bits: # of Bit Length codes - 4 (4 - 19) // 12. Note: length code 284 can represent 227-258, but length code 285 // really is 258. The last length deserves its own, short code // since it gets used a lot in very redundant files. The length // 258 is special since 258 - 3 (the min match length) is 255. // 13. The literal/length and distance code bit lengths are read as a // single stream of lengths. It is possible (and advantageous) for // a repeat code (16, 17, or 18) to go across the boundary between // the two sets of lengths. // And'ing with mask[n] masks the lower n bits static const ulong inflate_mask[17] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff }; // Order of the bit length code lengths static const ulong border[] = { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 }; // Copy lengths for literal codes 257..285 (see note #13 above about 258) static const ulong cplens[31] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0 }; // Extra bits for literal codes 257..285 (112 == invalid) static const ulong cplext[31] = { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112 }; // Copy offsets for distance codes 0..29 static const ulong cpdist[30] = { 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 8193, 12289, 16385, 24577 }; static ulong fixed_bl = 9; static ulong fixed_bd = 5; static inflate_huft_t fixed_tl[] = { { 96, 7, 256 }, { 0, 8, 80 }, { 0, 8, 16 }, { 84, 8, 115 }, { 82, 7, 31 }, { 0, 8, 112 }, { 0, 8, 48 }, { 0, 9, 192 }, { 80, 7, 10 }, { 0, 8, 96 }, { 0, 8, 32 }, { 0, 9, 160 }, { 0, 8, 0 }, { 0, 8, 128 }, { 0, 8, 64 }, { 0, 9, 224 }, { 80, 7, 6 }, { 0, 8, 88 }, { 0, 8, 24 }, { 0, 9, 144 }, { 83, 7, 59 }, { 0, 8, 120 }, { 0, 8, 56 }, { 0, 9, 208 }, { 81, 7, 17 }, { 0, 8, 104 }, { 0, 8, 40 }, { 0, 9, 176 }, { 0, 8, 8 }, { 0, 8, 136 }, { 0, 8, 72 }, { 0, 9, 240 }, { 80, 7, 4 }, { 0, 8, 84 }, { 0, 8, 20 }, { 85, 8, 227 }, { 83, 7, 43 }, { 0, 8, 116 }, { 0, 8, 52 }, { 0, 9, 200 }, { 81, 7, 13 }, { 0, 8, 100 }, { 0, 8, 36 }, { 0, 9, 168 }, { 0, 8, 4 }, { 0, 8, 132 }, { 0, 8, 68 }, { 0, 9, 232 }, { 80, 7, 8 }, { 0, 8, 92 }, { 0, 8, 28 }, { 0, 9, 152 }, { 84, 7, 83 }, { 0, 8, 124 }, { 0, 8, 60 }, { 0, 9, 216 }, { 82, 7, 23 }, { 0, 8, 108 }, { 0, 8, 44 }, { 0, 9, 184 }, { 0, 8, 12 }, { 0, 8, 140 }, { 0, 8, 76 }, { 0, 9, 248 }, { 80, 7, 3 }, { 0, 8, 82 }, { 0, 8, 18 }, { 85, 8, 163 }, { 83, 7, 35 }, { 0, 8, 114 }, { 0, 8, 50 }, { 0, 9, 196 }, { 81, 7, 11 }, { 0, 8, 98 }, { 0, 8, 34 }, { 0, 9, 164 }, { 0, 8, 2 }, { 0, 8, 130 }, { 0, 8, 66 }, { 0, 9, 228 }, { 80, 7, 7 }, { 0, 8, 90 }, { 0, 8, 26 }, { 0, 9, 148 }, { 84, 7, 67 }, { 0, 8, 122 }, { 0, 8, 58 }, { 0, 9, 212 }, { 82, 7, 19 }, { 0, 8, 106 }, { 0, 8, 42 }, { 0, 9, 180 }, { 0, 8, 10 }, { 0, 8, 138 }, { 0, 8, 74 }, { 0, 9, 244 }, { 80, 7, 5 }, { 0, 8, 86 }, { 0, 8, 22 }, { 192, 8, 0 }, { 83, 7, 51 }, { 0, 8, 118 }, { 0, 8, 54 }, { 0, 9, 204 }, { 81, 7, 15 }, { 0, 8, 102 }, { 0, 8, 38 }, { 0, 9, 172 }, { 0, 8, 6 }, { 0, 8, 134 }, { 0, 8, 70 }, { 0, 9, 236 }, { 80, 7, 9 }, { 0, 8, 94 }, { 0, 8, 30 }, { 0, 9, 156 }, { 84, 7, 99 }, { 0, 8, 126 }, { 0, 8, 62 }, { 0, 9, 220 }, { 82, 7, 27 }, { 0, 8, 110 }, { 0, 8, 46 }, { 0, 9, 188 }, { 0, 8, 14 }, { 0, 8, 142 }, { 0, 8, 78 }, { 0, 9, 252 }, { 96, 7, 256 }, { 0, 8, 81 }, { 0, 8, 17 }, { 85, 8, 131 }, { 82, 7, 31 }, { 0, 8, 113 }, { 0, 8, 49 }, { 0, 9, 194 }, { 80, 7, 10 }, { 0, 8, 97 }, { 0, 8, 33 }, { 0, 9, 162 }, { 0, 8, 1 }, { 0, 8, 129 }, { 0, 8, 65 }, { 0, 9, 226 }, { 80, 7, 6 }, { 0, 8, 89 }, { 0, 8, 25 }, { 0, 9, 146 }, { 83, 7, 59 }, { 0, 8, 121 }, { 0, 8, 57 }, { 0, 9, 210 }, { 81, 7, 17 }, { 0, 8, 105 }, { 0, 8, 41 }, { 0, 9, 178 }, { 0, 8, 9 }, { 0, 8, 137 }, { 0, 8, 73 }, { 0, 9, 242 }, { 80, 7, 4 }, { 0, 8, 85 }, { 0, 8, 21 }, { 80, 8, 258 }, { 83, 7, 43 }, { 0, 8, 117 }, { 0, 8, 53 }, { 0, 9, 202 }, { 81, 7, 13 }, { 0, 8, 101 }, { 0, 8, 37 }, { 0, 9, 170 }, { 0, 8, 5 }, { 0, 8, 133 }, { 0, 8, 69 }, { 0, 9, 234 }, { 80, 7, 8 }, { 0, 8, 93 }, { 0, 8, 29 }, { 0, 9, 154 }, { 84, 7, 83 }, { 0, 8, 125 }, { 0, 8, 61 }, { 0, 9, 218 }, { 82, 7, 23 }, { 0, 8, 109 }, { 0, 8, 45 }, { 0, 9, 186 }, { 0, 8, 13 }, { 0, 8, 141 }, { 0, 8, 77 }, { 0, 9, 250 }, { 80, 7, 3 }, { 0, 8, 83 }, { 0, 8, 19 }, { 85, 8, 195 }, { 83, 7, 35 }, { 0, 8, 115 }, { 0, 8, 51 }, { 0, 9, 198 }, { 81, 7, 11 }, { 0, 8, 99 }, { 0, 8, 35 }, { 0, 9, 166 }, { 0, 8, 3 }, { 0, 8, 131 }, { 0, 8, 67 }, { 0, 9, 230 }, { 80, 7, 7 }, { 0, 8, 91 }, { 0, 8, 27 }, { 0, 9, 150 }, { 84, 7, 67 }, { 0, 8, 123 }, { 0, 8, 59 }, { 0, 9, 214 }, { 82, 7, 19 }, { 0, 8, 107 }, { 0, 8, 43 }, { 0, 9, 182 }, { 0, 8, 11 }, { 0, 8, 139 }, { 0, 8, 75 }, { 0, 9, 246 }, { 80, 7, 5 }, { 0, 8, 87 }, { 0, 8, 23 }, { 192, 8, 0 }, { 83, 7, 51 }, { 0, 8, 119 }, { 0, 8, 55 }, { 0, 9, 206 }, { 81, 7, 15 }, { 0, 8, 103 }, { 0, 8, 39 }, { 0, 9, 174 }, { 0, 8, 7 }, { 0, 8, 135 }, { 0, 8, 71 }, { 0, 9, 238 }, { 80, 7, 9 }, { 0, 8, 95 }, { 0, 8, 31 }, { 0, 9, 158 }, { 84, 7, 99 }, { 0, 8, 127 }, { 0, 8, 63 }, { 0, 9, 222 }, { 82, 7, 27 }, { 0, 8, 111 }, { 0, 8, 47 }, { 0, 9, 190 }, { 0, 8, 15 }, { 0, 8, 143 }, { 0, 8, 79 }, { 0, 9, 254 }, { 96, 7, 256 }, { 0, 8, 80 }, { 0, 8, 16 }, { 84, 8, 115 }, { 82, 7, 31 }, { 0, 8, 112 }, { 0, 8, 48 }, { 0, 9, 193 }, { 80, 7, 10 }, { 0, 8, 96 }, { 0, 8, 32 }, { 0, 9, 161 }, { 0, 8, 0 }, { 0, 8, 128 }, { 0, 8, 64 }, { 0, 9, 225 }, { 80, 7, 6 }, { 0, 8, 88 }, { 0, 8, 24 }, { 0, 9, 145 }, { 83, 7, 59 }, { 0, 8, 120 }, { 0, 8, 56 }, { 0, 9, 209 }, { 81, 7, 17 }, { 0, 8, 104 }, { 0, 8, 40 }, { 0, 9, 177 }, { 0, 8, 8 }, { 0, 8, 136 }, { 0, 8, 72 }, { 0, 9, 241 }, { 80, 7, 4 }, { 0, 8, 84 }, { 0, 8, 20 }, { 85, 8, 227 }, { 83, 7, 43 }, { 0, 8, 116 }, { 0, 8, 52 }, { 0, 9, 201 }, { 81, 7, 13 }, { 0, 8, 100 }, { 0, 8, 36 }, { 0, 9, 169 }, { 0, 8, 4 }, { 0, 8, 132 }, { 0, 8, 68 }, { 0, 9, 233 }, { 80, 7, 8 }, { 0, 8, 92 }, { 0, 8, 28 }, { 0, 9, 153 }, { 84, 7, 83 }, { 0, 8, 124 }, { 0, 8, 60 }, { 0, 9, 217 }, { 82, 7, 23 }, { 0, 8, 108 }, { 0, 8, 44 }, { 0, 9, 185 }, { 0, 8, 12 }, { 0, 8, 140 }, { 0, 8, 76 }, { 0, 9, 249 }, { 80, 7, 3 }, { 0, 8, 82 }, { 0, 8, 18 }, { 85, 8, 163 }, { 83, 7, 35 }, { 0, 8, 114 }, { 0, 8, 50 }, { 0, 9, 197 }, { 81, 7, 11 }, { 0, 8, 98 }, { 0, 8, 34 }, { 0, 9, 165 }, { 0, 8, 2 }, { 0, 8, 130 }, { 0, 8, 66 }, { 0, 9, 229 }, { 80, 7, 7 }, { 0, 8, 90 }, { 0, 8, 26 }, { 0, 9, 149 }, { 84, 7, 67 }, { 0, 8, 122 }, { 0, 8, 58 }, { 0, 9, 213 }, { 82, 7, 19 }, { 0, 8, 106 }, { 0, 8, 42 }, { 0, 9, 181 }, { 0, 8, 10 }, { 0, 8, 138 }, { 0, 8, 74 }, { 0, 9, 245 }, { 80, 7, 5 }, { 0, 8, 86 }, { 0, 8, 22 }, { 192, 8, 0 }, { 83, 7, 51 }, { 0, 8, 118 }, { 0, 8, 54 }, { 0, 9, 205 }, { 81, 7, 15 }, { 0, 8, 102 }, { 0, 8, 38 }, { 0, 9, 173 }, { 0, 8, 6 }, { 0, 8, 134 }, { 0, 8, 70 }, { 0, 9, 237 }, { 80, 7, 9 }, { 0, 8, 94 }, { 0, 8, 30 }, { 0, 9, 157 }, { 84, 7, 99 }, { 0, 8, 126 }, { 0, 8, 62 }, { 0, 9, 221 }, { 82, 7, 27 }, { 0, 8, 110 }, { 0, 8, 46 }, { 0, 9, 189 }, { 0, 8, 14 }, { 0, 8, 142 }, { 0, 8, 78 }, { 0, 9, 253 }, { 96, 7, 256 }, { 0, 8, 81 }, { 0, 8, 17 }, { 85, 8, 131 }, { 82, 7, 31 }, { 0, 8, 113 }, { 0, 8, 49 }, { 0, 9, 195 }, { 80, 7, 10 }, { 0, 8, 97 }, { 0, 8, 33 }, { 0, 9, 163 }, { 0, 8, 1 }, { 0, 8, 129 }, { 0, 8, 65 }, { 0, 9, 227 }, { 80, 7, 6 }, { 0, 8, 89 }, { 0, 8, 25 }, { 0, 9, 147 }, { 83, 7, 59 }, { 0, 8, 121 }, { 0, 8, 57 }, { 0, 9, 211 }, { 81, 7, 17 }, { 0, 8, 105 }, { 0, 8, 41 }, { 0, 9, 179 }, { 0, 8, 9 }, { 0, 8, 137 }, { 0, 8, 73 }, { 0, 9, 243 }, { 80, 7, 4 }, { 0, 8, 85 }, { 0, 8, 21 }, { 80, 8, 258 }, { 83, 7, 43 }, { 0, 8, 117 }, { 0, 8, 53 }, { 0, 9, 203 }, { 81, 7, 13 }, { 0, 8, 101 }, { 0, 8, 37 }, { 0, 9, 171 }, { 0, 8, 5 }, { 0, 8, 133 }, { 0, 8, 69 }, { 0, 9, 235 }, { 80, 7, 8 }, { 0, 8, 93 }, { 0, 8, 29 }, { 0, 9, 155 }, { 84, 7, 83 }, { 0, 8, 125 }, { 0, 8, 61 }, { 0, 9, 219 }, { 82, 7, 23 }, { 0, 8, 109 }, { 0, 8, 45 }, { 0, 9, 187 }, { 0, 8, 13 }, { 0, 8, 141 }, { 0, 8, 77 }, { 0, 9, 251 }, { 80, 7, 3 }, { 0, 8, 83 }, { 0, 8, 19 }, { 85, 8, 195 }, { 83, 7, 35 }, { 0, 8, 115 }, { 0, 8, 51 }, { 0, 9, 199 }, { 81, 7, 11 }, { 0, 8, 99 }, { 0, 8, 35 }, { 0, 9, 167 }, { 0, 8, 3 }, { 0, 8, 131 }, { 0, 8, 67 }, { 0, 9, 231 }, { 80, 7, 7 }, { 0, 8, 91 }, { 0, 8, 27 }, { 0, 9, 151 }, { 84, 7, 67 }, { 0, 8, 123 }, { 0, 8, 59 }, { 0, 9, 215 }, { 82, 7, 19 }, { 0, 8, 107 }, { 0, 8, 43 }, { 0, 9, 183 }, { 0, 8, 11 }, { 0, 8, 139 }, { 0, 8, 75 }, { 0, 9, 247 }, { 80, 7, 5 }, { 0, 8, 87 }, { 0, 8, 23 }, { 192, 8, 0 }, { 83, 7, 51 }, { 0, 8, 119 }, { 0, 8, 55 }, { 0, 9, 207 }, { 81, 7, 15 }, { 0, 8, 103 }, { 0, 8, 39 }, { 0, 9, 175 }, { 0, 8, 7 }, { 0, 8, 135 }, { 0, 8, 71 }, { 0, 9, 239 }, { 80, 7, 9 }, { 0, 8, 95 }, { 0, 8, 31 }, { 0, 9, 159 }, { 84, 7, 99 }, { 0, 8, 127 }, { 0, 8, 63 }, { 0, 9, 223 }, { 82, 7, 27 }, { 0, 8, 111 }, { 0, 8, 47 }, { 0, 9, 191 }, { 0, 8, 15 }, { 0, 8, 143 }, { 0, 8, 79 }, { 0, 9, 255 } }; static inflate_huft_t fixed_td[] = { { 80, 5, 1 }, { 87, 5, 257 }, { 83, 5, 17 }, { 91, 5, 4097 }, { 81, 5, 5 }, { 89, 5, 1025 }, { 85, 5, 65 }, { 93, 5, 16385 }, { 80, 5, 3 }, { 88, 5, 513 }, { 84, 5, 33 }, { 92, 5, 8193 }, { 82, 5, 9 }, { 90, 5, 2049 }, { 86, 5, 129 }, { 192, 5, 24577 }, { 80, 5, 2 }, { 87, 5, 385 }, { 83, 5, 25 }, { 91, 5, 6145 }, { 81, 5, 7 }, { 89, 5, 1537 }, { 85, 5, 97 }, { 93, 5, 24577 }, { 80, 5, 4 }, { 88, 5, 769 }, { 84, 5, 49 }, { 92, 5, 12289 }, { 82, 5, 13 }, { 90, 5, 3073 }, { 86, 5, 193 }, { 192, 5, 24577 } }; // =============================================================================== // =============================================================================== static void inflate_blocks_reset(z_stream *z, inflate_blocks_state_t *s) { if((s->mode == BTREE) || (s->mode == DTREE)) { Z_Free(s->trees.blens); } if(s->mode == CODES) { Z_Free(s->decode.codes); } s->mode = TYPE; s->bitk = 0; s->bitb = 0; s->write = s->window; s->read = s->window; z->istate->adler = 1; } // =============================================================================== // =============================================================================== static int inflate_blocks_free(z_stream *z, inflate_blocks_state_t *s) { inflate_blocks_reset(z, s); Z_Free(s->hufts); s->hufts = NULL; Z_Free(s); return(Z_OK); } // =============================================================================== // =============================================================================== static inflate_blocks_state_t *inflate_blocks_new(z_stream *z, check_func check) { inflate_blocks_state_t *s; s = (inflate_blocks_state_t *)Z_Malloc(sizeof(inflate_blocks_state_t), TAG_INFLATE, qtrue); s->hufts = (inflate_huft_t *)Z_Malloc(sizeof(inflate_huft_t) * MANY, TAG_INFLATE, qtrue); s->end = s->window + WINDOW_SIZE; s->mode = TYPE; inflate_blocks_reset(z, s); return(s); } // =============================================================================== // copy as much as possible from the sliding window to the output area // =============================================================================== static void inflate_flush_copy(z_stream *z, inflate_blocks_state_t *s, ulong count) { if(count > z->avail_out) { count = z->avail_out; } if(count && (z->error == Z_BUF_ERROR)) { z->error = Z_OK; } // Calculate the checksum if required if(!z->istate->nowrap) { z->istate->adler = adler32(z->istate->adler, s->read, count); } // copy as as end of window memcpy(z->next_out, s->read, count); // update counters z->avail_out -= count; z->total_out += count; z->next_out += count; s->read += count; } // =============================================================================== // =============================================================================== static void inflate_flush(z_stream *z, inflate_blocks_state_t *s) { ulong count; // compute number of bytes to copy as as end of window count = (s->read <= s->write ? s->write : s->end) - s->read; inflate_flush_copy(z, s, count); // see if more to copy at beginning of window if(s->read == s->end) { // wrap pointers s->read = s->window; if(s->write == s->end) { s->write = s->window; } // compute bytes to copy count = s->write - s->read; inflate_flush_copy(z, s, count); } } // =============================================================================== // get bytes and bits // =============================================================================== static bool getbits(z_stream *z, inflate_blocks_state_t *s, ulong bits) { while(s->bitk < bits) { if(z->avail_in) { z->error = Z_OK; } else { inflate_flush(z, s); return(false); } z->avail_in--; z->total_in++; s->bitb |= *z->next_in++ << s->bitk; s->bitk += 8; } return(true); } // =============================================================================== // output bytes // =============================================================================== static ulong needout(z_stream *z, inflate_blocks_state_t *s, ulong bytesToEnd) { if(!bytesToEnd) { if((s->write == s->end) && (s->read != s->window)) { s->write = s->window; bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; } if(!bytesToEnd) { inflate_flush(z, s); bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; if((s->write == s->end) && (s->read != s->window)) { s->write = s->window; bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; } if(!bytesToEnd) { inflate_flush(z, s); return(bytesToEnd); } } } z->error = Z_OK; return(bytesToEnd); } // =============================================================================== // Called with number of bytes left to write in window at least 258 // (the maximum string length) and number of input bytes available // at least ten. The ten bytes are six bytes for the longest length/ // distance pair plus four bytes for overloading the bit buffer. // =============================================================================== inline byte *qcopy(byte *dst, byte *src, int count) { byte *retval; _asm { push ecx push esi push edi mov edi, [dst] mov esi, [src] mov ecx, [count] rep movsb mov [retval], edi pop edi pop esi pop ecx } return(retval); } inline ulong get_remaining(inflate_blocks_state_t *s) { if(s->write < s->read) { return(s->read - s->write - 1); } return(s->end - s->write); } static EStatus inflate_fast(ulong lengthMask, ulong distMask, inflate_huft_t *lengthTree, inflate_huft_t *distTree, inflate_blocks_state_t *s, z_stream *z) { inflate_huft_t *huft; // temporary pointer byte *data; byte *src; // copy source pointer byte *dst; ulong extraBits; // extra bits or operation ulong bytesToEnd; // bytes to end of window or read pointer ulong count; // bytes to copy ulong dist; // distance back to copy from ulong bitb; ulong bitk; ulong availin; ulong morebits; ulong copymore; // load input, output, bit values data = z->next_in; dst = s->write; availin = z->avail_in; bitb = s->bitb; bitk = s->bitk; bytesToEnd = get_remaining(s); // do until not enough input or output space for fast loop // assume called with bytesToEnd >= 258 && availIn >= 10 while((bytesToEnd >= 258) && (availin >= 10)) { // get literal/length code while(bitk < 20) { bitb |= *data++ << bitk; bitk += 8; availin--; } huft = lengthTree + (bitb & lengthMask); if(!huft->Exop) { bitb >>= huft->Bits; bitk -= huft->Bits; *dst++ = (byte)huft->base; bytesToEnd--; } else { extraBits = huft->Exop; morebits = 1; do { bitb >>= huft->Bits; bitk -= huft->Bits; if(extraBits & 16) { // get extra bits for length extraBits &= 15; count = huft->base + (bitb & inflate_mask[extraBits]); bitb >>= extraBits; bitk -= extraBits; // decode distance base of block to copy while(bitk < 15) { bitb |= *data++ << bitk; bitk += 8; availin--; } huft = distTree + (bitb & distMask); extraBits = huft->Exop; copymore = 1; do { bitb >>= huft->Bits; bitk -= huft->Bits; if(extraBits & 16) { // get extra bits to add to distance base extraBits &= 15; while(bitk < extraBits) { bitb |= *data++ << bitk; bitk += 8; availin--; } dist = huft->base + (bitb & inflate_mask[extraBits]); bitb >>= extraBits; bitk -= extraBits; // do the copy bytesToEnd -= count; // offset before dest if((dst - s->window) >= dist) { // just copy src = dst - dist; } // else offset after destination else { // bytes from offset to end extraBits = dist - (dst - s->window); // pointer to offset src = s->end - extraBits; // if source crosses, if(count > extraBits) { // copy to end of window dst = qcopy(dst, src, extraBits); // copy rest from start of window count -= extraBits; src = s->window; } } // copy all or what's left dst = qcopy(dst, src, count); copymore = 0; } else { if(!(extraBits & 64)) { huft += huft->base + (bitb & inflate_mask[extraBits]); extraBits = huft->Exop; } else { inflate_error = "Inflate data: Invalid distance code"; return(Z_DATA_ERROR); } } } while(copymore); morebits = 0; } else { if(!(extraBits & 64)) { huft += huft->base + (bitb & inflate_mask[extraBits]); extraBits = huft->Exop; if(!extraBits) { bitb >>= huft->Bits; bitk -= huft->Bits; *dst++ = (byte)huft->base; bytesToEnd--; morebits = 0; } } else if(extraBits & 32) { count = data - z->next_in; z->avail_in = availin; z->total_in += count; z->next_in = data; s->write = dst; count = (bitk >> 3) < count ? bitk >> 3 : count; s->bitb = bitb; s->bitk = bitk - (count << 3); z->avail_in += count; z->total_in -= count; z->next_in -= count ; return(Z_STREAM_END); } else { inflate_error = "Inflate data: Invalid literal/length code"; return(Z_DATA_ERROR); } } } while(morebits); } } // not enough input or output--restore pointers and return count = data - z->next_in; z->avail_in = availin; z->total_in += count; z->next_in = data; s->write = dst; count = (bitk >> 3) < count ? bitk >> 3 : count; s->bitb = bitb; s->bitk = bitk - (count << 3); z->avail_in += count; z->total_in -= count; z->next_in -= count; return(Z_OK); } // =============================================================================== // =============================================================================== static void inflate_codes(z_stream *z, inflate_blocks_state_t *s) { inflate_huft_t *huft; // temporary pointer ulong extraBits; // extra bits or operation ulong bytesToEnd; // bytes to end of window or read pointer byte *src; // pointer to copy strings from inflate_codes_state_t *infCodes; // codes state infCodes = s->decode.codes; // copy input/output information to locals bytesToEnd = get_remaining(s); // process input and output based on current state while(true) { // waiting for "i:"=input, "o:"=output, "x:"=nothing switch (infCodes->mode) { // x: set up for LEN case START: if((bytesToEnd >= 258) && (z->avail_in >= 10)) { z->error = inflate_fast(inflate_mask[infCodes->lbits], inflate_mask[infCodes->dbits], infCodes->ltree, infCodes->dtree, s, z); bytesToEnd = get_remaining(s); if(z->error != Z_OK) { infCodes->mode = (z->error == Z_STREAM_END) ? WASH : BADCODE; break; } } infCodes->code.need = infCodes->lbits; infCodes->code.tree = infCodes->ltree; infCodes->mode = LEN; // i: get length/literal/eob next case LEN: if(!getbits(z, s, infCodes->code.need)) { // We could get here because we have run out of input data *or* the stream has ended if(z->status == Z_BUF_ERROR) { z->error = Z_STREAM_END; } return; } huft = infCodes->code.tree + (s->bitb & inflate_mask[infCodes->code.need]); s->bitb >>= huft->Bits; s->bitk -= huft->Bits; extraBits = huft->Exop; // literal if(!extraBits) { infCodes->lit = huft->base; infCodes->mode = LIT; break; } // length if(extraBits & 16) { infCodes->copy.get = extraBits & 15; infCodes->len = huft->base; infCodes->mode = LENEXT; break; } // next table if(!(extraBits & 64)) { infCodes->code.need = extraBits; infCodes->code.tree = huft + huft->base; break; } // end of block if(extraBits & 32) { infCodes->mode = WASH; break; } // invalid code infCodes->mode = BADCODE; inflate_error = "Inflate data: Invalid literal/length code"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; // i: getting length extra (have base) case LENEXT: if(!getbits(z, s, infCodes->copy.get)) { return; } infCodes->len += s->bitb & inflate_mask[infCodes->copy.get]; s->bitb >>= infCodes->copy.get; s->bitk -= infCodes->copy.get; infCodes->code.need = infCodes->dbits; infCodes->code.tree = infCodes->dtree; infCodes->mode = DIST; // i: get distance next case DIST: if(!getbits(z, s, infCodes->code.need)) { return; } huft = infCodes->code.tree + (s->bitb & inflate_mask[infCodes->code.need]); s->bitb >>= huft->Bits; s->bitk -= huft->Bits; extraBits = huft->Exop; // distance if(extraBits & 16) { infCodes->copy.get = extraBits & 15; infCodes->copy.dist = huft->base; infCodes->mode = DISTEXT; break; } // next table if(!(extraBits & 64)) { infCodes->code.need = extraBits; infCodes->code.tree = huft + huft->base; break; } // invalid code infCodes->mode = BADCODE; inflate_error = "Inflate data: Invalid distance code"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; // i: getting distance extra case DISTEXT: if(!getbits(z, s, infCodes->copy.get)) { return; } infCodes->copy.dist += s->bitb & inflate_mask[infCodes->copy.get]; s->bitb >>= infCodes->copy.get; s->bitk -= infCodes->copy.get; infCodes->mode = COPY; // o: copying bytes in window, waiting for space case COPY: if(s->write - s->window < infCodes->copy.dist) { src = s->end - (infCodes->copy.dist - (s->write - s->window)); } else { src = s->write - infCodes->copy.dist; } while(infCodes->len) { bytesToEnd = needout(z, s, bytesToEnd); if(!bytesToEnd) { return; } *s->write++ = (byte)(*src++); bytesToEnd--; if(src == s->end) { src = s->window; } infCodes->len--; } infCodes->mode = START; break; // o: got literal, waiting for output space case LIT: bytesToEnd = needout(z, s, bytesToEnd); if(!bytesToEnd) { return; } *s->write++ = (byte)infCodes->lit; bytesToEnd--; infCodes->mode = START; break; // o: got eob, possibly more output case WASH: // return unused byte, if any if(s->bitk > 7) { s->bitk -= 8; z->avail_in++; z->total_in--; // can always return one z->next_in--; } inflate_flush(z, s); bytesToEnd = get_remaining(s); if(s->read != s->write) { inflate_error = "Inflate data: read != write while in WASH"; inflate_flush(z, s); return; } infCodes->mode = END; case END: z->error = Z_STREAM_END; inflate_flush(z, s); return; // x: got error case BADCODE: z->error = Z_DATA_ERROR; inflate_flush(z, s); return; default: z->error = Z_STREAM_ERROR; inflate_flush(z, s); return; } } } // =============================================================================== // =============================================================================== static inflate_codes_state_t *inflate_codes_new(z_stream *z, ulong bl, ulong bd, inflate_huft_t *lengthTree, inflate_huft_t *distTree) { inflate_codes_state_t *c; c = (inflate_codes_state_t *)Z_Malloc(sizeof(inflate_codes_state_t), TAG_INFLATE, qtrue); c->mode = START; c->lbits = (byte)bl; c->dbits = (byte)bd; c->ltree = lengthTree; c->dtree = distTree; return(c); } // =============================================================================== // Generate Huffman trees for efficient decoding // ulong b // code lengths in bits (all assumed <= BMAX) // ulong n // number of codes (assumed <= 288) // ulong s // number of simple-valued codes (0..s-1) // const ulong *d // list of base values for non-simple codes // const ulong *e // list of extra bits for non-simple codes // inflate_huft ** t // result: starting table // ulong *m // maximum lookup bits, returns actual // inflate_huft *hp // space for trees // ulong *hn // hufts used in space // ulong *workspace // working area: values in order of bit length // // Given a list of code lengths and a maximum table size, make a set of // tables to decode that set of codes. Return Z_OK on success, Z_BUF_ERROR // if the given code set is incomplete (the tables are still built in this // case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of // lengths). // // Huffman code decoding is performed using a multi-level table lookup. // The fastest way to decode is to simply build a lookup table whose // size is determined by the longest code. However, the time it takes // to build this table can also be a factor if the data being decoded // is not very long. The most common codes are necessarily the // shortest codes, so those codes dominate the decoding time, and hence // the speed. The idea is you can have a shorter table that decodes the // shorter, more probable codes, and then point to subsidiary tables for // the longer codes. The time it costs to decode the longer codes is // then traded against the time it takes to make longer tables. // // This results of this trade are in the variables lbits and dbits // below. lbits is the number of bits the first level table for literal/ // length codes can decode in one step, and dbits is the same thing for // the distance codes. Subsequent tables are also less than or equal to // those sizes. These values may be adjusted either when all of the // codes are shorter than that, in which case the longest code length in // bits is used, or when the shortest code is *longer* than the requested // table size, in which case the length of the shortest code in bits is // used. // // There are two different values for the two tables, since they code a // different number of possibilities each. The literal/length table // codes 286 possible values, or in a flat code, a little over eight // bits. The distance table codes 30 possible values, or a little less // than five bits, flat. The optimum values for speed end up being // about one bit more than those, so lbits is 8+1 and dbits is 5+1. // The optimum values may differ though from machine to machine, and // possibly even between compilers. Your mileage may vary. // =============================================================================== static EStatus huft_build(ulong *b, ulong numCodes, ulong s, const ulong *d, const ulong *e, inflate_huft_t **t, ulong *m, inflate_huft_t *hp, ulong *hn, ulong *workspace) { ulong codeCounter; // counter for codes of length bitsPerCode ulong bitLengths[BMAX + 1] = { 0 }; // bit length count table ulong bitOffsets[BMAX + 1]; // bit offsets, then code stack ulong f; // i repeats in table every f entries int maxCodeLen; // maximum code length int tableLevel; // table level ulong i; // counter, current code ulong j; // counter int bitsPerCode; // number of bits in current code ulong bitsPerTable; // bits per table (returned in m) int bitsBeforeTable; // bits before this table == (bitsPerTable * tableLevel) ulong *p; // pointer into bitLengths[], b[], or workspace[] inflate_huft_t *q; // points to current table inflate_huft_t r; // table entry for structure assignment inflate_huft_t *tableStack[BMAX]; // table stack ulong *xp; // pointer into bitOffsets int dummyCodes; // number of dummy codes added ulong entryCount; // number of entries in current table // Generate counts for each bit length // assume all entries <= BMAX p = b; i = numCodes; do { bitLengths[*p++]++; } while(--i); // null input--all zero length codes if(bitLengths[0] == numCodes) { *t = NULL; *m = 0; return(Z_OK); } // Find minimum and maximum length, bound *m by those bitsPerTable = *m; for(j = 1; j <= BMAX; j++) { if(bitLengths[j]) { break; } } // minimum code length bitsPerCode = j; if(bitsPerTable < j) { bitsPerTable = j; } for(i = BMAX; i; i--) { if(bitLengths[i]) { break; } } // maximum code length maxCodeLen = i; if(bitsPerTable > i) { bitsPerTable = i; } *m = bitsPerTable; // Adjust last length count to fill out codes, if needed for(dummyCodes = 1 << j; j < i; j++, dummyCodes <<= 1) { dummyCodes -= bitLengths[j]; if(dummyCodes < 0) { return(Z_DATA_ERROR); } } dummyCodes -= bitLengths[i]; if(dummyCodes < 0) { return(Z_DATA_ERROR); } bitLengths[i] += dummyCodes; // Generate starting offsets into the value table for each length bitOffsets[1] = 0; j = 0; p = bitLengths + 1; xp = bitOffsets + 2; // note that i == maxCodeLen from above while(--i) { j += *p++; *xp++ = j; } // Make a table of values in order of bit lengths p = b; i = 0; do { j = *p++; if(j) { workspace[bitOffsets[j]++] = i; } } while(++i < numCodes); // set numCodes to length of workspace numCodes = bitOffsets[maxCodeLen]; // Generate the Huffman codes and for each, make the table entries bitOffsets[0] = 0; // first Huffman code is zero i = 0; p = workspace; // grab values in bit order tableLevel = -1; // no tables yet--level -1 bitsBeforeTable = bitsPerTable; // bits decoded == (bitsPerTable * tableLevel) bitsBeforeTable = -bitsBeforeTable; tableStack[0] = NULL; // just to keep compilers happy q = NULL; // ditto entryCount = 0; // ditto // go through the bit lengths (bitsPerCode already is bits in shortest code) for(; bitsPerCode <= maxCodeLen; bitsPerCode++) { codeCounter = bitLengths[bitsPerCode]; while(codeCounter--) { // here i is the Huffman code of length bitsPerCode bits for value *p // make tables up to required level while(bitsPerCode > bitsBeforeTable + bitsPerTable) { tableLevel++; bitsBeforeTable += bitsPerTable; // previous table always bitsPerTable bits // compute minimum size table less than or equal to bitsPerTable bits entryCount = maxCodeLen - bitsBeforeTable; entryCount = entryCount > bitsPerTable ? bitsPerTable : entryCount; // table size upper limit j = bitsPerCode - bitsBeforeTable; f = 1 << j; if(f > codeCounter + 1) // try a bitsPerCode-bitsBeforeTable bit table { // too few codes for bitsPerCode-bitsBeforeTable bit table f -= codeCounter + 1; // deduct codes from patterns left xp = bitLengths + bitsPerCode; if(j < entryCount) { while(++j < entryCount) // try smaller tables up to entryCount bits { f <<= 1; if(f <= *++xp) { break; // enough codes to use up j bits } f -= *xp; // else deduct codes from patterns } } } entryCount = 1 << j; // table entries for j-bit table // allocate new table if(*hn + entryCount > MANY) // (note: doesn't matter for fixed) { return(Z_DATA_ERROR); // not enough memory } q = hp + *hn; tableStack[tableLevel] = q; *hn += entryCount; // connect to last table, if there is one if(tableLevel) { bitOffsets[tableLevel] = i; // save pattern for backing up r.Bits = (byte)bitsPerTable; // bits to dump before this table r.Exop = (byte)j; // bits in this table j = i >> (bitsBeforeTable - bitsPerTable); r.base = q - tableStack[tableLevel - 1] - j; // offset to this table tableStack[tableLevel - 1][j] = r; // connect to last table } else { *t = q; // first table is returned result } } // set up table entry in r r.Bits = (byte)(bitsPerCode - bitsBeforeTable); if(p >= workspace + numCodes) { r.Exop = 128 + 64; // out of values--invalid code } else if(*p < s) { r.Exop = (byte)(*p < 256 ? 0 : 32 + 64); // 256 is end-of-block r.base = *p++; // simple code is just the value } else { r.Exop = (byte)(e[*p - s] + 16 + 64); // non-simple--look up in lists r.base = d[*p++ - s]; } // fill code-like entries with r f = 1 << (bitsPerCode - bitsBeforeTable); for(j = i >> bitsBeforeTable; j < entryCount; j += f) { q[j] = r; } // backwards increment the bitsPerCode-bit code i for(j = 1 << (bitsPerCode - 1); i & j; j >>= 1) { i ^= j; } i ^= j; // backup over finished tables while((i & ((1 << bitsBeforeTable) - 1)) != bitOffsets[tableLevel]) { tableLevel--; // don't need to update q bitsBeforeTable -= bitsPerTable; } } } // Return Z_BUF_ERROR if we were given an incomplete table if(dummyCodes && (maxCodeLen != 1)) { return(Z_BUF_ERROR); } return(Z_OK); } // =============================================================================== // ulong *c 19 code lengths // ulong *bb bits tree desired/actual depth // inflate_huft **tb bits tree result // inflate_huft *hp space for trees // =============================================================================== static void inflate_trees_bits(z_stream *z, ulong *c, ulong *bb, inflate_huft_t **tb, inflate_huft_t *hp) { ulong hn = 0; // hufts used in space ulong workspace[19]; // work area for huft_build z->error = huft_build(c, 19, 19, NULL, NULL, tb, bb, hp, &hn, workspace); if(z->error == Z_DATA_ERROR) { inflate_error = "Inflate data: Oversubscribed dynamic bit lengths tree"; } else if((z->error == Z_BUF_ERROR) || !*bb) { inflate_error = "Inflate data: Incomplete dynamic bit lengths tree"; z->error = Z_DATA_ERROR; } } // =============================================================================== // ulong *c // that many (total) code lengths // ulong *bl // literal desired/actual bit depth // ulong *bd // distance desired/actual bit depth // inflate_huft **tl // literal/length tree result // inflate_huft **td // distance tree result // inflate_huft *hp // space for trees // =============================================================================== static void inflate_trees_dynamic(z_stream *z, ulong numLiteral, ulong numDist, ulong *c, ulong *bl, ulong *bd, inflate_huft_t **tl, inflate_huft_t **td, inflate_huft_t *hp) { ulong hn = 0; // hufts used in space ulong workspace[288]; // work area for huft_build // build literal/length tree z->error = huft_build(c, numLiteral, 257, cplens, cplext, tl, bl, hp, &hn, workspace); if(z->error != Z_OK || !*bl) { inflate_error = "Inflate data: Erroneous literal/length tree"; z->error = Z_DATA_ERROR; return; } // build distance tree z->error = huft_build(c + numLiteral, numDist, 0, cpdist, extra_dbits, td, bd, hp, &hn, workspace); if((z->error != Z_OK) || (!*bd && numLiteral > 257)) { inflate_error = "Inflate data: Erroneous distance tree"; z->error = Z_DATA_ERROR; return; } } // =============================================================================== // ulong *bl // literal desired/actual bit depth // ulong *bd // distance desired/actual bit depth // inflate_huft **tl // literal/length tree result // inflate_huft **td // distance tree result // =============================================================================== // Fixme: Calculate dynamically static void inflate_trees_fixed(z_stream *z, ulong *bl, ulong *bd, inflate_huft_t **tl, inflate_huft_t **td) { *bl = fixed_bl; *bd = fixed_bd; *tl = fixed_tl; *td = fixed_td; z->error = Z_OK; } // =============================================================================== // =============================================================================== static void inflate_blocks(inflate_blocks_state_t *s, z_stream *z) { ulong t; // temporary storage ulong bytesToEnd; // bytes to end of window or read pointer ulong bl, bd; inflate_huft_t *lengthTree = NULL; inflate_huft_t *distTree = NULL; inflate_codes_state_t *c; // copy input/output information to locals (UPDATE macro restores) bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; // process input based on current state while(true) { switch (s->mode) { case TYPE: if(!getbits(z, s, 3)) { return; } t = s->bitb & 7; s->last = !!(t & 1); switch (t >> 1) { case STORED_BLOCK: s->bitb >>= 3; s->bitk -= 3; t = s->bitk & 7; // go to byte boundary s->bitb >>= t; s->bitk -= t; s->mode = LENS; // get length of stored block break; case STATIC_TREES: inflate_trees_fixed(z, &bl, &bd, &lengthTree, &distTree); s->decode.codes = inflate_codes_new(z, bl, bd, lengthTree, distTree); s->bitb >>= 3; s->bitk -= 3; s->mode = CODES; break; case DYN_TREES: s->bitb >>= 3; s->bitk -= 3; s->mode = TABLE; break; case MODE_ILLEGAL: s->bitb >>= 3; s->bitk -= 3; s->mode = BAD; inflate_error = "Inflate data: Invalid block type"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; } break; case LENS: if(!getbits(z, s, 32)) { return; } if(((~s->bitb) >> 16) != (s->bitb & 0xffff)) { s->mode = BAD; inflate_error = "Inflate data: Invalid stored block lengths"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; } s->left = s->bitb & 0xffff; s->bitb = 0; s->bitk = 0; // dump bits s->mode = s->left ? STORED : (s->last ? DRY : TYPE); break; case STORED: if(!z->avail_in) { inflate_flush(z, s); return; } bytesToEnd = needout(z, s, bytesToEnd); if(!bytesToEnd) { return; } t = s->left; if(t > z->avail_in) { t = z->avail_in; } if(t > bytesToEnd) { t = bytesToEnd; } memcpy(s->write, z->next_in, t); z->next_in += t; z->avail_in -= t; z->total_in += t; s->write += t; bytesToEnd -= t; s->left -= t; if(s->left) { break; } s->mode = s->last ? DRY : TYPE; break; case TABLE: if(!getbits(z, s, 14)) { return; } t = s->bitb & 0x3fff; s->trees.table = t; if((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { s->mode = BAD; inflate_error = "Inflate data: Too many length or distance symbols"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; } t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); s->trees.blens = (ulong *)Z_Malloc(t * sizeof(ulong), TAG_INFLATE, qfalse); s->bitb >>= 14; s->bitk -= 14; s->trees.index = 0; s->mode = BTREE; case BTREE: while(s->trees.index < 4 + (s->trees.table >> 10)) { if(!getbits(z, s, 3)) { return; } s->trees.blens[border[s->trees.index++]] = s->bitb & 7; s->bitb >>= 3; s->bitk -= 3; } while(s->trees.index < 19) { s->trees.blens[border[s->trees.index++]] = 0; } s->trees.bb = 7; inflate_trees_bits(z, s->trees.blens, &s->trees.bb, &s->trees.tb, s->hufts); if(z->error != Z_OK) { Z_Free(s->trees.blens); s->mode = BAD; inflate_flush(z, s); return; } s->trees.index = 0; s->mode = DTREE; case DTREE: while(t = s->trees.table, s->trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)) { inflate_huft_t *h; ulong i, j, c; t = s->trees.bb; if(!getbits(z, s, t)) { return; } h = s->trees.tb + (s->bitb & inflate_mask[t]); t = h->Bits; c = h->base; if(c < 16) { s->bitb >>= t; s->bitk -= t; s->trees.blens[s->trees.index++] = c; } else // c == 16..18 { i = (c == 18) ? 7 : c - 14; j = (c == 18) ? 11 : 3; if(!getbits(z, s, t + i)) { return; } s->bitb >>= t; s->bitk -= t; j += s->bitb & inflate_mask[i]; s->bitb >>= i; s->bitk -= i; i = s->trees.index; t = s->trees.table; if(i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)) { Z_Free(s->trees.blens); s->mode = BAD; inflate_error = "Inflate data: Invalid bit length repeat"; z->error = Z_DATA_ERROR; inflate_flush(z, s); return; } c = (c == 16) ? s->trees.blens[i - 1] : 0; do { s->trees.blens[i++] = c; } while(--j); s->trees.index = i; } } s->trees.tb = NULL; bl = 9; // must be <= 9 for lookahead assumptions bd = 6; // must be <= 9 for lookahead assumptions t = s->trees.table; inflate_trees_dynamic(z, 257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), s->trees.blens, &bl, &bd, &lengthTree, &distTree, s->hufts); Z_Free(s->trees.blens); if(z->error != Z_OK) { s->mode = BAD; inflate_flush(z, s); return; } c = inflate_codes_new(z, bl, bd, lengthTree, distTree); s->decode.codes = c; s->mode = CODES; case CODES: inflate_codes(z, s); if(z->error != Z_STREAM_END) { inflate_flush(z, s); return; } z->error = Z_OK; Z_Free(s->decode.codes); bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; if(!s->last) { s->mode = TYPE; break; } s->mode = DRY; case DRY: inflate_flush(z, s); bytesToEnd = s->write < s->read ? s->read - s->write - 1 : s->end - s->write; if(s->read != s->write) { inflate_error = "Inflate data: read != write in DRY"; inflate_flush(z, s); return; } s->mode = DONE; case DONE: z->error = Z_STREAM_END; inflate_flush(z, s); return; case BAD: default: z->error = Z_DATA_ERROR; inflate_flush(z, s); return; } } } // ------------------------------------------------------------------------------------------------- // Controlling routines // ------------------------------------------------------------------------------------------------- EStatus inflateEnd(z_stream *z) { assert(z); if(z->istate->blocks) { inflate_blocks_free(z, z->istate->blocks); z->istate->blocks = NULL; } if(z->istate) { Z_Free(z->istate); z->istate = NULL; } return(Z_OK); } // =============================================================================== // =============================================================================== EStatus inflateInit(z_stream *z, EFlush flush, int noWrap) { // initialize state assert(z); inflate_error = "OK"; z->istate = (inflate_state *)Z_Malloc(sizeof(inflate_state), TAG_INFLATE, qtrue); z->istate->blocks = NULL; // handle nowrap option (no zlib header or check) z->istate->nowrap = noWrap; z->istate->wbits = MAX_WBITS; // create inflate_blocks state z->istate->blocks = inflate_blocks_new(z, NULL); z->status = Z_OK; if(flush == Z_FINISH) { z->status = Z_BUF_ERROR; } // reset state z->istate->mode = imMETHOD; if(z->istate->nowrap) { z->istate->mode = imBLOCKS; } inflate_blocks_reset(z, z->istate->blocks); return(Z_OK); } // =============================================================================== // =============================================================================== EStatus inflate(z_stream *z) { ulong b; // Sanity check data assert(z); assert(z->istate); while(true) { switch (z->istate->mode) { case imMETHOD: if(!z->avail_in) { return(z->status); } z->istate->method = *z->next_in++; z->avail_in--; z->total_in++; if((z->istate->method & 0xf) != ZF_DEFLATED) { z->istate->mode = imBAD; inflate_error = "Inflate data: Unknown compression method"; return(Z_DATA_ERROR); } if((z->istate->method >> 4) + 8 > z->istate->wbits) { z->istate->mode = imBAD; inflate_error = "Inflate data: Invalid window size"; return(Z_DATA_ERROR); } z->istate->mode = imFLAG; break; case imFLAG: if(!z->avail_in) { return(z->status); } b = *z->next_in++; z->avail_in--; z->total_in++; if(((z->istate->method << 8) + b) % 31) { z->istate->mode = imBAD; inflate_error = "Inflate data: Incorrect header check"; return(Z_DATA_ERROR); } z->istate->mode = imBLOCKS; break; case imBLOCKS: inflate_blocks(z->istate->blocks, z); // Make sure everything processed ok if(z->error == Z_DATA_ERROR) { z->istate->mode = imBAD; return(Z_DATA_ERROR); } if(z->error != Z_STREAM_END) { return(z->status); } z->istate->calcadler = z->istate->adler; inflate_blocks_reset(z, z->istate->blocks); if(z->istate->nowrap) { z->istate->mode = imDONE; break; } z->istate->mode = imCHECK4; break; case imCHECK4: if(!z->avail_in) { return(z->status); } z->istate->adler = *z->next_in++ << 24; z->avail_in--; z->total_in++; z->istate->mode = imCHECK3; break; case imCHECK3: if(!z->avail_in) { return(z->status); } z->istate->adler += *z->next_in++ << 16; z->avail_in--; z->total_in++; z->istate->mode = imCHECK2; break; case imCHECK2: if(!z->avail_in) { return(z->status); } z->istate->adler += *z->next_in++ << 8; z->avail_in--; z->total_in++; z->istate->mode = imCHECK1; break; case imCHECK1: if(!z->avail_in) { return(z->status); } z->istate->adler += *z->next_in++; z->avail_in--; z->total_in++; if(z->istate->calcadler != z->istate->adler) { inflate_error = "Inflate data: Failed Adler checksum"; z->istate->mode = imBAD; break; } z->istate->mode = imDONE; break; case imDONE: return(Z_STREAM_END); case imBAD: return(Z_DATA_ERROR); default: return(Z_STREAM_ERROR); } } assert(0); return(Z_OK); } // =============================================================================== // =============================================================================== const char *inflateError(void) { return(inflate_error); } // =============================================================================== // External calls // =============================================================================== bool InflateFile(byte *src, ulong compressedSize, byte *dst, ulong uncompressedSize, int noWrap) { z_stream z = { 0 }; inflateInit(&z, Z_FINISH, noWrap); z.next_in = src; z.avail_in = compressedSize; z.next_out = dst; z.avail_out = uncompressedSize; #ifdef _TIMING int temp = timeGetTime(); #endif if(inflate(&z) != Z_STREAM_END) { inflate_error = "Inflate data: Stream did not end"; inflateEnd(&z); return(false); } #ifdef _TIMING totalInflateTime += timeGetTime() - temp; totalInflateCount++; #endif if(z.avail_in) { inflate_error = "Inflate data: Remaining input data at stream end"; inflateEnd(&z); return(false); } if(z.avail_out) { inflate_error = "Inflate data: Remaining output space at stream end"; inflateEnd(&z); return(false); } if(z.total_in != compressedSize) { inflate_error = "Inflate data: Number of processed bytes != compressed size"; inflateEnd(&z); return(false); } if(z.total_out != uncompressedSize) { inflate_error = "Inflate data: Number of bytes output != uncompressed size"; inflateEnd(&z); return(false); } inflateEnd(&z); return(true); } // end