/* Number of literal byte values */ #define LZX_NUM_CHARS 256
/* The smallest and largest allowed match lengths */ #define LZX_MIN_MATCH_LEN 2 #define LZX_MAX_MATCH_LEN 257
/* Number of distinct match lengths that can be represented */ #define LZX_NUM_LENS (LZX_MAX_MATCH_LEN - LZX_MIN_MATCH_LEN + 1)
/* Number of match lengths for which no length symbol is required */ #define LZX_NUM_PRIMARY_LENS 7 #define LZX_NUM_LEN_HEADERS (LZX_NUM_PRIMARY_LENS + 1)
/* Valid values of the 3-bit block type field */ #define LZX_BLOCKTYPE_VERBATIM 1 #define LZX_BLOCKTYPE_ALIGNED 2 #define LZX_BLOCKTYPE_UNCOMPRESSED 3
/* Number of offset slots for a window size of 32768 */ #define LZX_NUM_OFFSET_SLOTS 30
/* Number of symbols in the main code for a window size of 32768 */ #define LZX_MAINCODE_NUM_SYMBOLS \
(LZX_NUM_CHARS + (LZX_NUM_OFFSET_SLOTS * LZX_NUM_LEN_HEADERS))
/* Number of symbols in the length code */ #define LZX_LENCODE_NUM_SYMBOLS (LZX_NUM_LENS - LZX_NUM_PRIMARY_LENS)
/* Number of symbols in the precode */ #define LZX_PRECODE_NUM_SYMBOLS 20
/* Number of bits in which each precode codeword length is represented */ #define LZX_PRECODE_ELEMENT_SIZE 4
/* Number of low-order bits of each match offset that are entropy-encoded in *alignedoffsetblocks
*/ #define LZX_NUM_ALIGNED_OFFSET_BITS 3
/* Number of symbols in the aligned offset code */ #define LZX_ALIGNEDCODE_NUM_SYMBOLS (1 << LZX_NUM_ALIGNED_OFFSET_BITS)
/* Mask for the match offset bits that are entropy-encoded in aligned offset *blocks
*/ #define LZX_ALIGNED_OFFSET_BITMASK ((1 << LZX_NUM_ALIGNED_OFFSET_BITS) - 1)
/* Number of bits in which each aligned offset codeword length is represented */ #define LZX_ALIGNEDCODE_ELEMENT_SIZE 3
/* Maximum lengths (in bits) of the codewords in each Huffman code */ #define LZX_MAX_MAIN_CODEWORD_LEN 16 #define LZX_MAX_LEN_CODEWORD_LEN 16 #define LZX_MAX_PRE_CODEWORD_LEN ((1 << LZX_PRECODE_ELEMENT_SIZE) - 1) #define LZX_MAX_ALIGNED_CODEWORD_LEN ((1 << LZX_ALIGNEDCODE_ELEMENT_SIZE) - 1)
/* The default "filesize" value used in pre/post-processing. In the LZX format *usedincabinetfilesthisvaluemustbegiventothedecompressor,whereas *intheLZXformatusedinWIMfilesandsystem-compressedfilesthisvalueis *fixedat12000000.
*/ #define LZX_DEFAULT_FILESIZE 12000000
/* Assumed block size when the encoded block size begins with a 0 bit. */ #define LZX_DEFAULT_BLOCK_SIZE 32768
/* Number of offsets in the recent (or "repeat") offsets queue. */ #define LZX_NUM_RECENT_OFFSETS 3
/* These values are chosen for fast decompression. */ #define LZX_MAINCODE_TABLEBITS 11 #define LZX_LENCODE_TABLEBITS 10 #define LZX_PRECODE_TABLEBITS 6 #define LZX_ALIGNEDCODE_TABLEBITS 7
/* Read the lengths of the precode codewords. These are given *explicitly.
*/ for (i = 0; i < LZX_PRECODE_NUM_SYMBOLS; i++) {
d->precode_lens[i] =
bitstream_read_bits(is, LZX_PRECODE_ELEMENT_SIZE);
}
/* Make the decoding table for the precode. */ if (make_huffman_decode_table(d->precode_decode_table,
LZX_PRECODE_NUM_SYMBOLS,
LZX_PRECODE_TABLEBITS,
d->precode_lens,
LZX_MAX_PRE_CODEWORD_LEN,
d->working_space)) return -1;
/* Decode the codeword lengths. */ do {
u32 presym;
u8 len;
/* Read the next precode symbol. */
presym = read_presym(d, is); if (presym < 17) { /* Difference from old length */
len = *len_ptr - presym; if ((s8)len < 0)
len += 17;
*len_ptr++ = len;
} else { /* Special RLE values */
u32 run_len;
if (presym == 17) { /* Run of 0's */
run_len = 4 + bitstream_read_bits(is, 4);
len = 0;
} elseif (presym == 18) { /* Longer run of 0's */
run_len = 20 + bitstream_read_bits(is, 5);
len = 0;
} else { /* Run of identical lengths */
run_len = 4 + bitstream_read_bits(is, 1);
presym = read_presym(d, is); if (presym > 17) return -1;
len = *len_ptr - presym; if ((s8)len < 0)
len += 17;
}
do {
*len_ptr++ = len;
} while (--run_len); /* Worst case overrun is when presym == 18, *run_len==20+31,andonly1lengthwasremaining. *SoLZX_READ_LENS_MAX_OVERRUN==50. * *Overrunwhilereadingthefirsthalfofmaincode_lens *cancorruptthepreviousvaluesinthesecondhalf. *Thisdoesn'treallymatterbecausetheresulting *lengthswillstillbeinrange,anddatathat *generatesoverrunsisinvalidanyway.
*/
}
} while (len_ptr < lens_end);
return0;
}
/* *ReadtheheaderofanLZXblockandsavetheblocktypeand(uncompressed) *sizein*block_type_retand*block_size_ret,respectively. * *Iftheblockiscompressed,alsoupdatetheHuffmandecode@tableswiththe *newHuffmancodes.Iftheblockisuncompressed,alsoupdatethematch *offset@queuewiththenewmatchoffsets. * *Return0onsuccess,or-1ifthedatawasinvalid.
*/ staticint lzx_read_block_header(struct lzx_decompressor *d, struct input_bitstream *is, int *block_type_ret,
u32 *block_size_ret,
u32 recent_offsets[])
{ int block_type;
u32 block_size; int i;
bitstream_ensure_bits(is, 4);
/* The first three bits tell us what kind of block it is, and should be *oneoftheLZX_BLOCKTYPE_*values.
*/
block_type = bitstream_pop_bits(is, 3);
/* Read the aligned offset code and prepare its decode table.
*/
for (i = 0; i < LZX_ALIGNEDCODE_NUM_SYMBOLS; i++) {
d->alignedcode_lens[i] =
bitstream_read_bits(is,
LZX_ALIGNEDCODE_ELEMENT_SIZE);
}
if (make_huffman_decode_table(d->alignedcode_decode_table,
LZX_ALIGNEDCODE_NUM_SYMBOLS,
LZX_ALIGNEDCODE_TABLEBITS,
d->alignedcode_lens,
LZX_MAX_ALIGNED_CODEWORD_LEN,
d->working_space)) return -1;
/* Fall though, since the rest of the header for aligned offset *blocksisthesameasthatforverbatimblocks.
*/
fallthrough;
case LZX_BLOCKTYPE_VERBATIM:
/* Read the main code and prepare its decode table. * *Notethatthecodewordlengthsinthemaincodeareencoded *intwoparts:onepartforliteralsymbols,andonepartfor *matchsymbols.
*/
if (lzx_read_codeword_lens(d, is, d->maincode_lens,
LZX_NUM_CHARS)) return -1;
if (lzx_read_codeword_lens(d, is,
d->maincode_lens + LZX_NUM_CHARS,
LZX_MAINCODE_NUM_SYMBOLS - LZX_NUM_CHARS)) return -1;
if (make_huffman_decode_table(d->maincode_decode_table,
LZX_MAINCODE_NUM_SYMBOLS,
LZX_MAINCODE_TABLEBITS,
d->maincode_lens,
LZX_MAX_MAIN_CODEWORD_LEN,
d->working_space)) return -1;
/* Read the length code and prepare its decode table. */
if (lzx_read_codeword_lens(d, is, d->lencode_lens,
LZX_LENCODE_NUM_SYMBOLS)) return -1;
if (make_huffman_decode_table(d->lencode_decode_table,
LZX_LENCODE_NUM_SYMBOLS,
LZX_LENCODE_TABLEBITS,
d->lencode_lens,
LZX_MAX_LEN_CODEWORD_LEN,
d->working_space)) return -1;
break;
case LZX_BLOCKTYPE_UNCOMPRESSED:
/* Before reading the three recent offsets from the uncompressed *blockheader,thestreammustbealignedona16-bit *boundary.Butifthestreamis*already*aligned,thenthe *next16bitsmustbediscarded.
*/
bitstream_ensure_bits(is, 1);
bitstream_align(is);
/* If needed, read a length symbol to decode the full length. */ if (match_len == LZX_NUM_PRIMARY_LENS)
match_len += read_lensym(d, is);
match_len += LZX_MIN_MATCH_LEN;
if (offset_slot < LZX_NUM_RECENT_OFFSETS) { /* Repeat offset */
/* Note: This isn't a real LRU queue, since using the R2 *offsetdoesn'tbumptheR1offsetdowntoR2.This *quirkallowsall3recentoffsetstobehandledby *thesamecode.(ForR0,theswapisano-op.)
*/
match_offset = recent_offsets[offset_slot];
swap(recent_offsets[offset_slot], recent_offsets[0]);
} else { /* Explicit offset */
/* Look up the number of extra bits that need to be read *todecodeoffsetswiththisoffsetslot.
*/
num_extra_bits = lzx_extra_offset_bits[offset_slot];
/* Start with the offset slot base value. */
match_offset = lzx_offset_slot_base[offset_slot];
/* In aligned offset blocks, the low-order 3 bits of *eachoffsetareencodedusingthealignedoffset *code.Otherwise,alltheextrabitsareliteral.
*/
/* Codeword lengths begin as all 0's for delta encoding purposes. */
memset(d->maincode_lens, 0, LZX_MAINCODE_NUM_SYMBOLS);
memset(d->lencode_lens, 0, LZX_LENCODE_NUM_SYMBOLS);
/* Decompress blocks until we have all the uncompressed data. */
while (out_next != out_end) { int block_type;
u32 block_size;
if (lzx_read_block_header(d, &is, &block_type, &block_size,
recent_offsets)) goto invalid;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.