252 lines
5.8 KiB
C
252 lines
5.8 KiB
C
|
/*
|
||
|
* dectree.c
|
||
|
*
|
||
|
* Decoding the encoded tree structures
|
||
|
*
|
||
|
* To save much code size, the fillbuf()/getbits() calls have
|
||
|
* been made into functions, rather than being inlined macros.
|
||
|
* The macros actually take up a lot of space. There is no
|
||
|
* performance loss from doing so here.
|
||
|
*/
|
||
|
#include "decoder.h"
|
||
|
|
||
|
/* number of elements in pre-tree */
|
||
|
#define NUM_DECODE_SMALL 20
|
||
|
|
||
|
/* lookup table size */
|
||
|
#define DS_TABLE_BITS 8
|
||
|
|
||
|
/* macro to decode a pre-tree element */
|
||
|
#define DECODE_SMALL(item) \
|
||
|
{ \
|
||
|
item = small_table[context->dec_bitbuf >> (32-DS_TABLE_BITS) ]; \
|
||
|
if (item < 0) \
|
||
|
{ \
|
||
|
mask = (1L << (32-1-DS_TABLE_BITS)); \
|
||
|
do \
|
||
|
{ \
|
||
|
item = -item; \
|
||
|
if (context->dec_bitbuf & mask) \
|
||
|
item = leftright_s[2*item+1]; \
|
||
|
else \
|
||
|
item = leftright_s[2*item]; \
|
||
|
mask >>= 1; \
|
||
|
} while (item < 0); \
|
||
|
} \
|
||
|
fillbuf(context, small_bitlen[item]); \
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Reads a compressed tree structure
|
||
|
*/
|
||
|
static bool NEAR ReadRepTree(
|
||
|
t_decoder_context *context,
|
||
|
int num_elements,
|
||
|
byte *lastlen,
|
||
|
byte *len
|
||
|
)
|
||
|
{
|
||
|
ulong mask;
|
||
|
int i;
|
||
|
int consecutive;
|
||
|
byte small_bitlen[24];
|
||
|
short small_table[1 << DS_TABLE_BITS];
|
||
|
short leftright_s [2*(2 * 24 - 1)];
|
||
|
short Temp;
|
||
|
|
||
|
/* Declare this inline to help compilers see the optimisation */
|
||
|
static const byte Modulo17Lookup[] =
|
||
|
{
|
||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
|
||
|
};
|
||
|
|
||
|
/* read pre-tree */
|
||
|
for (i = 0; i < NUM_DECODE_SMALL; i++)
|
||
|
{
|
||
|
small_bitlen[i] = (byte) getbits(context, 4);
|
||
|
}
|
||
|
|
||
|
/* exceeded input buffer? */
|
||
|
if (context->dec_error_condition)
|
||
|
return false;
|
||
|
|
||
|
/* make a table for this pre-tree */
|
||
|
make_table(
|
||
|
context,
|
||
|
NUM_DECODE_SMALL,
|
||
|
small_bitlen,
|
||
|
DS_TABLE_BITS,
|
||
|
small_table,
|
||
|
leftright_s
|
||
|
);
|
||
|
|
||
|
for (i = 0; i < num_elements; i++)
|
||
|
{
|
||
|
DECODE_SMALL(Temp);
|
||
|
|
||
|
/* exceeded input buffer? */
|
||
|
if (context->dec_error_condition)
|
||
|
return false;
|
||
|
|
||
|
/* Repeat "TREE_ENC_REP_MIN...TREE_ENC_REP_MIN+(1<<TREE_ENC_REPZ_FIRST_EXTRA_BITS)-1" zeroes */
|
||
|
if (Temp == 17)
|
||
|
{
|
||
|
/* code 17 means "a small number of repeated zeroes" */
|
||
|
consecutive = (byte) getbits(context, TREE_ENC_REPZ_FIRST_EXTRA_BITS);
|
||
|
consecutive += TREE_ENC_REP_MIN;
|
||
|
|
||
|
/* boundary check */
|
||
|
if (i + consecutive >= num_elements)
|
||
|
consecutive = num_elements-i;
|
||
|
|
||
|
while (consecutive-- > 0)
|
||
|
len[i++] = 0;
|
||
|
|
||
|
i--;
|
||
|
}
|
||
|
else if (Temp == 18)
|
||
|
{
|
||
|
/* code 18 means "a large number of repeated zeroes" */
|
||
|
|
||
|
/* Repeat "TREE_ENC_REP_MIN+(1<<TREE_ENC_REPZ_FIRST_EXTRA_BITS)-1...<ditto>+(1<<TREE_ENC_REPZ_SECOND_EXTRA_BITS)-1" zeroes */
|
||
|
consecutive = (byte) getbits(context, TREE_ENC_REPZ_SECOND_EXTRA_BITS);
|
||
|
consecutive += (TREE_ENC_REP_MIN+TREE_ENC_REP_ZERO_FIRST);
|
||
|
|
||
|
/* boundary check */
|
||
|
if (i + consecutive >= num_elements)
|
||
|
consecutive = num_elements-i;
|
||
|
|
||
|
while (consecutive-- > 0)
|
||
|
len[i++] = 0;
|
||
|
|
||
|
i--;
|
||
|
}
|
||
|
else if (Temp == 19)
|
||
|
{
|
||
|
byte value;
|
||
|
|
||
|
/* code 19 means "a small number of repeated somethings" */
|
||
|
/* Repeat "TREE_ENC_REP_MIN...TREE_ENC_REP_MIN+(1<<TREE_ENC_REP_SAME_EXTRA_BITS)-1" elements */
|
||
|
consecutive = (byte) getbits(context, TREE_ENC_REP_SAME_EXTRA_BITS);
|
||
|
consecutive += TREE_ENC_REP_MIN;
|
||
|
|
||
|
/* boundary check */
|
||
|
if (i + consecutive >= num_elements)
|
||
|
consecutive = num_elements-i;
|
||
|
|
||
|
/* get the element number to repeat */
|
||
|
DECODE_SMALL(Temp);
|
||
|
value = Modulo17Lookup[(lastlen[i] - Temp)+17];
|
||
|
|
||
|
while (consecutive-- > 0)
|
||
|
len[i++] = value;
|
||
|
|
||
|
i--;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
len[i] = Modulo17Lookup[(lastlen[i] - Temp)+17];
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* exceeded input buffer? */
|
||
|
if (context->dec_error_condition)
|
||
|
return false;
|
||
|
else
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
bool NEAR read_main_and_secondary_trees(t_decoder_context *context)
|
||
|
{
|
||
|
/* read first 256 elements (characters) of the main tree */
|
||
|
if (false == ReadRepTree(
|
||
|
context,
|
||
|
256,
|
||
|
context->dec_main_tree_prev_len,
|
||
|
context->dec_main_tree_len))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* read remaining elements (primary match lengths * positions)
|
||
|
* of the main tree
|
||
|
*/
|
||
|
if (false == ReadRepTree(
|
||
|
context,
|
||
|
context->dec_num_position_slots*NUM_LENGTHS,
|
||
|
&context->dec_main_tree_prev_len[256],
|
||
|
&context->dec_main_tree_len[256]))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* create lookup table for the main tree */
|
||
|
if (false == make_table(
|
||
|
context,
|
||
|
MAIN_TREE_ELEMENTS,
|
||
|
context->dec_main_tree_len,
|
||
|
MAIN_TREE_TABLE_BITS,
|
||
|
context->dec_main_tree_table,
|
||
|
context->dec_main_tree_left_right))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* read secondary length tree */
|
||
|
if (false == ReadRepTree(
|
||
|
context,
|
||
|
NUM_SECONDARY_LENGTHS,
|
||
|
context->dec_secondary_length_tree_prev_len,
|
||
|
context->dec_secondary_length_tree_len))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/* create lookup table for the secondary length tree */
|
||
|
if (false == make_table(
|
||
|
context,
|
||
|
NUM_SECONDARY_LENGTHS,
|
||
|
context->dec_secondary_length_tree_len,
|
||
|
SECONDARY_LEN_TREE_TABLE_BITS,
|
||
|
context->dec_secondary_length_tree_table,
|
||
|
context->dec_secondary_length_tree_left_right))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* read 8 element aligned offset tree */
|
||
|
bool NEAR read_aligned_offset_tree(t_decoder_context *context)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
/* read bit lengths of the 8 codes */
|
||
|
for (i = 0; i < 8; i++)
|
||
|
{
|
||
|
context->dec_aligned_len[i] = (byte) getbits(context, 3);
|
||
|
}
|
||
|
|
||
|
if (context->dec_error_condition)
|
||
|
return false;
|
||
|
|
||
|
/*
|
||
|
* Make table with no left/right, and byte Table[] instead of
|
||
|
* short Table[]
|
||
|
*/
|
||
|
if (false == make_table_8bit(
|
||
|
context,
|
||
|
context->dec_aligned_len,
|
||
|
(byte *) context->dec_aligned_table))
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return true;
|
||
|
}
|