mirror of
https://github.com/ioquake/jedi-academy.git
synced 2024-11-14 00:40:32 +00:00
1839 lines
56 KiB
C++
1839 lines
56 KiB
C++
#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
|