/* * 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<= 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<+(1<= 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<= 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; }