- unsigned verbatim_bits;
- unsigned aligned_bits;
- int ret;
- int i;
- u8 *match_dest;
- u8 *match_src;
-
- /* The main element is offset by 256 because values under 256 indicate a
- * literal value. */
- main_element -= LZX_NUM_CHARS;
-
- /* The length header consists of the lower 3 bits of the main element.
- * The position slot is the rest of it. */
- length_header = main_element & LZX_NUM_PRIMARY_LENS;
- position_slot = main_element >> 3;
-
- /* If the length_header is less than LZX_NUM_PRIMARY_LENS (= 7), it
- * gives the match length as the offset from LZX_MIN_MATCH. Otherwise,
- * the length is given by an additional symbol encoded using the length
- * tree, offset by 9 (LZX_MIN_MATCH + LZX_NUM_PRIMARY_LENS) */
- match_len = LZX_MIN_MATCH + length_header;
- if (length_header == LZX_NUM_PRIMARY_LENS) {
- ret = read_huffsym_using_lentree(istream, tables,
- &additional_len);
- if (ret != 0)
- return -1;
- match_len += additional_len;
- }
-
-
- /* If the position_slot is 0, 1, or 2, the match offset is retrieved
- * from the LRU queue. Otherwise, the match offset is not in the LRU
- * queue. */
- switch (position_slot) {
- case 0:
- match_offset = queue->R0;
- break;
- case 1:
- match_offset = queue->R1;
- swap(queue->R0, queue->R1);
- break;
- case 2:
- /* The queue doesn't work quite the same as a real LRU queue,
- * since using the R2 offset doesn't bump the R1 offset down to
- * R2. */
- match_offset = queue->R2;
- swap(queue->R0, queue->R2);
- break;
- default:
- /* Otherwise, the offset was not encoded as one the offsets in
- * the queue. Depending on the position slot, there is a
- * certain number of extra bits that need to be read to fully
- * decode the match offset. */
-
- /* Look up the number of extra bits that need to be read. */
- num_extra_bits = lzx_extra_bits[position_slot];
-
- /* For aligned blocks, if there are at least 3 extra bits, the
- * actual number of extra bits is 3 less, and they encode a
- * number of 8-byte words that are added to the offset; there
- * is then an additional symbol read using the aligned tree that
- * specifies the actual byte alignment. */
- if (block_type == LZX_BLOCKTYPE_ALIGNED && num_extra_bits >= 3) {
-
- /* There is an error in the LZX "specification" at this
- * point; it indicates that a Huffman symbol is to be
- * read only if num_extra_bits is greater than 3, but
- * actually it is if num_extra_bits is greater than or
- * equal to 3. (Note that in the case with
- * num_extra_bits == 3, the assignment to verbatim_bits
- * will just set it to 0. ) */
- ret = bitstream_read_bits(istream, num_extra_bits - 3,
- &verbatim_bits);
- if (ret != 0)
- return -1;