146 lines
4.7 KiB
C
146 lines
4.7 KiB
C
|
// Maximum size of dynamic tree. The maximum found in a long but non-
|
||
|
// exhaustive search was 1004 huft structures (850 for length/literals
|
||
|
// and 154 for distances, the latter actually the result of an
|
||
|
// exhaustive search). The actual maximum is not known, but the
|
||
|
// value below is more than safe.
|
||
|
|
||
|
#define MANY 1440
|
||
|
|
||
|
// maximum bit length of any code (if BMAX needs to be larger than 16, then h and x[] should be ulong.)
|
||
|
#define BMAX 15
|
||
|
|
||
|
typedef ulong (*check_func) (ulong check, const byte *buf, ulong len);
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
TYPE, // get type bits (3, including end bit)
|
||
|
LENS, // get lengths for stored
|
||
|
STORED, // processing stored block
|
||
|
TABLE, // get table lengths
|
||
|
BTREE, // get bit lengths tree for a dynamic block
|
||
|
DTREE, // get length, distance trees for a dynamic block
|
||
|
CODES, // processing fixed or dynamic block
|
||
|
DRY, // output remaining window bytes
|
||
|
DONE, // finished last block, done
|
||
|
BAD // got a data error--stuck here
|
||
|
} inflate_block_mode;
|
||
|
|
||
|
// waiting for "i:"=input, "o:"=output, "x:"=nothing
|
||
|
typedef enum
|
||
|
{
|
||
|
START, // x: set up for LEN
|
||
|
LEN, // i: get length/literal/eob next
|
||
|
LENEXT, // i: getting length extra (have base)
|
||
|
DIST, // i: get distance next
|
||
|
DISTEXT, // i: getting distance extra
|
||
|
COPY, // o: copying bytes in window, waiting for space
|
||
|
LIT, // o: got literal, waiting for output space
|
||
|
WASH, // o: got eob, possibly still output waiting
|
||
|
END, // x: got eob and all data flushed
|
||
|
BADCODE // x: got error
|
||
|
} inflate_codes_mode;
|
||
|
|
||
|
typedef enum
|
||
|
{
|
||
|
imMETHOD, // waiting for method byte
|
||
|
imFLAG, // waiting for flag byte
|
||
|
imBLOCKS, // decompressing blocks
|
||
|
imCHECK4, // four check bytes to go
|
||
|
imCHECK3, // three check bytes to go
|
||
|
imCHECK2, // two check bytes to go
|
||
|
imCHECK1, // one check byte to go
|
||
|
imDONE, // finished check, done
|
||
|
imBAD // got an error--stay here
|
||
|
} inflate_mode;
|
||
|
|
||
|
typedef struct inflate_huft_s
|
||
|
{
|
||
|
byte Exop; // number of extra bits or operation
|
||
|
byte Bits; // number of bits in this code or subcode
|
||
|
ulong base; // literal, length base, distance base, or table offset
|
||
|
} inflate_huft_t;
|
||
|
|
||
|
// inflate codes private state
|
||
|
typedef struct inflate_codes_state_s
|
||
|
{
|
||
|
inflate_codes_mode mode; // current inflate_codes mode
|
||
|
|
||
|
// mode dependent information
|
||
|
ulong len;
|
||
|
union
|
||
|
{
|
||
|
struct
|
||
|
{
|
||
|
inflate_huft_t *tree; // pointer into tree
|
||
|
ulong need; // bits needed
|
||
|
} code; // if LEN or DIST, where in tree
|
||
|
ulong lit; // if LIT, literal
|
||
|
struct
|
||
|
{
|
||
|
ulong get; // bits to get for extra
|
||
|
ulong dist; // distance back to copy from
|
||
|
} copy; // if EXT or COPY, where and how much
|
||
|
}; // submode
|
||
|
|
||
|
// mode independent information
|
||
|
byte lbits; // ltree bits decoded per branch
|
||
|
byte dbits; // dtree bits decoder per branch
|
||
|
inflate_huft_t *ltree; // literal/length/eob tree
|
||
|
inflate_huft_t *dtree; // distance tree
|
||
|
} inflate_codes_state_t;
|
||
|
|
||
|
// inflate blocks semi-private state
|
||
|
typedef struct inflate_blocks_state_s
|
||
|
{
|
||
|
// mode
|
||
|
inflate_block_mode mode; // current inflate_block mode
|
||
|
|
||
|
// mode dependent information
|
||
|
union
|
||
|
{
|
||
|
ulong left; // if STORED, bytes left to copy
|
||
|
struct
|
||
|
{
|
||
|
ulong table; // table lengths (14 bits)
|
||
|
ulong index; // index into blens (or border)
|
||
|
ulong *blens; // bit lengths of codes
|
||
|
ulong bb; // bit length tree depth
|
||
|
inflate_huft_t *tb; // bit length decoding tree
|
||
|
} trees; // if DTREE, decoding info for trees
|
||
|
struct
|
||
|
{
|
||
|
inflate_codes_state_t *codes;
|
||
|
} decode; // if CODES, current state
|
||
|
}; // submode
|
||
|
bool last; // true if this block is the last block
|
||
|
|
||
|
// mode independent information
|
||
|
ulong bitk; // bits in bit buffer
|
||
|
ulong bitb; // bit buffer
|
||
|
inflate_huft_t *hufts; // single malloc for tree space
|
||
|
byte window[WINDOW_SIZE]; // sliding window
|
||
|
byte *end; // one byte after sliding window
|
||
|
byte *read; // window read pointer
|
||
|
byte *write; // window write pointer
|
||
|
ulong check; // check on output
|
||
|
} inflate_blocks_state_t;
|
||
|
|
||
|
// inflate private state
|
||
|
typedef struct inflate_state_s
|
||
|
{
|
||
|
inflate_mode mode; // current inflate mode
|
||
|
|
||
|
ulong method; // if FLAGS, method byte
|
||
|
|
||
|
// mode independent information
|
||
|
int nowrap; // flag for no wrapper
|
||
|
ulong wbits; // log2(window size) (8..15, defaults to 15)
|
||
|
inflate_blocks_state_t *blocks; // current inflate_blocks state
|
||
|
|
||
|
ulong adler;
|
||
|
ulong calcadler;
|
||
|
} inflate_state;
|
||
|
|
||
|
|
||
|
// end
|