windows-nt/Source/XPSP1/NT/enduser/stuff/itss/lzx/decoder/d16verb.c

125 lines
3.2 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* d16verb.c
*
* Decoding verbatim-bit blocks
*/
#include "decoder.h"
int NEAR decode_verbatim_block(
t_decoder_context * context,
long BufPos,
int amount_to_decode /* yes, it will equal 32768 */
)
{
ulong match_pos;
ulong dec_bitbuf;
byte *dec_input_curpos;
byte *dec_end_input_pos;
int match_length;
int c;
char dec_bitcount;
char m;
MATCH match_info;
/*
* Store commonly used variables locally
*/
dec_bitcount = context->dec_bitcount;
dec_bitbuf = context->dec_bitbuf;
dec_input_curpos = context->dec_input_curpos;
dec_end_input_pos = context->dec_end_input_pos;
/*
* amount_to_decode must never be > 32768
*
* As it stands, we do the (amount_to_decode >= 0) check
* at the bottom of the DO loop, rather than at the top of
* a WHILE loop, so that we can used a signed int; this way,
* we decrement it by at least 1 by the time we check against
* zero.
*/
do
{
/* decode an item from the main tree */
DECODE_MAIN_TREE(c);
if ((c -= NUM_CHARS) < 0)
{
/* it's a character */
/* note: c - 256 == c if c is a byte */
context->DComp_Token_Literal(context, (int) ((byte) c));
amount_to_decode--;
}
else
{
/* get match length header */
if ((match_length = c & NUM_PRIMARY_LENGTHS) == NUM_PRIMARY_LENGTHS)
{
/* get match length footer if necessary */
DECODE_LEN_TREE_NOEOFCHECK(match_length);
}
/* get match position slot */
m = c >> NL_SHIFT;
/* read any extra bits for the match position */
if (m > 2)
{
if (m > 3) /* dec_extra_bits[m] != 0 */
{
GET_BITS17_NOEOFCHECK(dec_extra_bits[ m ], match_pos);
match_pos += MP_POS_minus2[m];
}
else
{
match_pos = MP_POS_minus2[3];
}
/*
* Add match base to "extra bits". Our match base
* table has 2 subtracted from all the elements.
*
* This is because encoded positions 0,1,2 denote
* repeated offsets. Encoded position 3 denotes
* a match 1 character away, 4 encodes 2 away, etc.
* Hence the subtraction of 2, which has been
* incorporated into the table.
*/
/* update LRU repeated offset list */
context->dec_last_matchpos_offset[2] = context->dec_last_matchpos_offset[1];
context->dec_last_matchpos_offset[1] = context->dec_last_matchpos_offset[0];
context->dec_last_matchpos_offset[0] = match_pos;
}
else
{
/* positions 0, 1, 2 denote repeated offsets */
match_pos = context->dec_last_matchpos_offset[m];
if (m)
{
context->dec_last_matchpos_offset[m] = context->dec_last_matchpos_offset[0];
context->dec_last_matchpos_offset[0] = match_pos;
}
}
/* match lengths range from 2...257 */
match_length += MIN_MATCH;
match_info.Len = match_length;
match_info.Dist = match_pos;
context->DComp_Token_Match(context, match_info);
amount_to_decode -= match_length;
}
} while (amount_to_decode > 0);
context->dec_bitcount = dec_bitcount;
context->dec_bitbuf = dec_bitbuf;
context->dec_input_curpos = dec_input_curpos;
return 0;
}