]> wimlib.net Git - wimlib/blobdiff - src/lzx_decompress.c
Make read_huffsym() return unsigned int
[wimlib] / src / lzx_decompress.c
index 57b32890b7813bc57aa7faa3f8d7cae9fd95e4ab..86c0839038ac0d396acf65ff88c3e62e7e828e69 100644 (file)
@@ -5,7 +5,7 @@
  */
 
 /*
- * Copyright (C) 2012, 2013, 2014 Eric Biggers
+ * Copyright (C) 2012, 2013, 2014, 2015 Eric Biggers
  *
  * This file is free software; you can redistribute it and/or modify it under
  * the terms of the GNU Lesser General Public License as published by the Free
 #  include "config.h"
 #endif
 
+#include <string.h>
+
 #include "wimlib/decompressor_ops.h"
 #include "wimlib/decompress_common.h"
 #include "wimlib/error.h"
 #include "wimlib/lzx_common.h"
 #include "wimlib/util.h"
 
-#include <string.h>
-
 /* These values are chosen for fast decompression.  */
 #define LZX_MAINCODE_TABLEBITS         11
 #define LZX_LENCODE_TABLEBITS          10
@@ -91,6 +91,18 @@ struct lzx_tables {
        u8 alignedcode_lens[LZX_ALIGNEDCODE_NUM_SYMBOLS];
 } _aligned_attribute(DECODE_TABLE_ALIGNMENT);
 
+/* Least-recently used queue for match offsets.  */
+struct lzx_lru_queue {
+       u32 R[LZX_NUM_RECENT_OFFSETS];
+};
+
+static inline void
+lzx_lru_queue_init(struct lzx_lru_queue *queue)
+{
+       for (unsigned i = 0; i < LZX_NUM_RECENT_OFFSETS; i++)
+               queue->R[i] = 1;
+}
+
 /* The main LZX decompressor structure.
  *
  * Note: we keep track of most of the decompression state outside this
@@ -104,7 +116,7 @@ struct lzx_decompressor {
 };
 
 /* Read a Huffman-encoded symbol using the precode.  */
-static inline u16
+static inline unsigned
 read_huffsym_using_precode(struct input_bitstream *istream,
                           const u16 precode_decode_table[])
 {
@@ -113,7 +125,7 @@ read_huffsym_using_precode(struct input_bitstream *istream,
 }
 
 /* Read a Huffman-encoded symbol using the main code.  */
-static inline u16
+static inline unsigned
 read_huffsym_using_maincode(struct input_bitstream *istream,
                            const struct lzx_tables *tables)
 {
@@ -122,7 +134,7 @@ read_huffsym_using_maincode(struct input_bitstream *istream,
 }
 
 /* Read a Huffman-encoded symbol using the length code.  */
-static inline u16
+static inline unsigned
 read_huffsym_using_lencode(struct input_bitstream *istream,
                           const struct lzx_tables *tables)
 {
@@ -131,7 +143,7 @@ read_huffsym_using_lencode(struct input_bitstream *istream,
 }
 
 /* Read a Huffman-encoded symbol using the aligned offset code.  */
-static inline u16
+static inline unsigned
 read_huffsym_using_alignedcode(struct input_bitstream *istream,
                               const struct lzx_tables *tables)
 {
@@ -216,6 +228,8 @@ lzx_read_codeword_lens(struct input_bitstream *istream, u8 *lens, unsigned num_l
                                run_len = 4 + bitstream_read_bits(istream, 1);
                                presym = read_huffsym_using_precode(istream,
                                                                    precode_decode_table);
+                               if (unlikely(presym > 17))
+                                       return -1;
                                len = *len_ptr - presym;
                                if ((s8)len < 0)
                                        len += 17;
@@ -443,15 +457,15 @@ lzx_decompress_block(int block_type, u32 block_size,
 
                /* Decode the length header and offset slot.  */
                mainsym -= LZX_NUM_CHARS;
-               match_len = mainsym & 0x7;
-               offset_slot = mainsym >> 3;
+               match_len = mainsym % LZX_NUM_LEN_HEADERS;
+               offset_slot = mainsym / LZX_NUM_LEN_HEADERS;
 
                /* If needed, read a length symbol to decode the full length. */
-               if (match_len == 0x7)
+               if (match_len == LZX_NUM_PRIMARY_LENS)
                        match_len += read_huffsym_using_lencode(istream, tables);
                match_len += LZX_MIN_MATCH_LEN;
 
-               if (offset_slot <= 2) {
+               if (offset_slot < LZX_NUM_RECENT_OFFSETS) {
                        /* Repeat offset  */
 
                        /* Note: This isn't a real LRU queue, since using the R2
@@ -475,18 +489,22 @@ lzx_decompress_block(int block_type, u32 block_size,
                         * each offset are encoded using the aligned offset
                         * code.  Otherwise, all the extra bits are literal.  */
 
-                       /*if (block_type == LZX_BLOCKTYPE_ALIGNED && num_extra_bits >= 3) {*/
-                       if ((num_extra_bits & ones_if_aligned) >= 3) {
-                               match_offset += bitstream_read_bits(istream, num_extra_bits - 3) << 3;
+                       if ((num_extra_bits & ones_if_aligned) >= LZX_NUM_ALIGNED_OFFSET_BITS) {
+                               match_offset +=
+                                       bitstream_read_bits(istream,
+                                                           num_extra_bits -
+                                                               LZX_NUM_ALIGNED_OFFSET_BITS)
+                                                       << LZX_NUM_ALIGNED_OFFSET_BITS;
                                match_offset += read_huffsym_using_alignedcode(istream, tables);
                        } else {
                                match_offset += bitstream_read_bits(istream, num_extra_bits);
                        }
 
                        /* Adjust the offset.  */
-                       match_offset -= LZX_OFFSET_OFFSET;
+                       match_offset -= LZX_OFFSET_ADJUSTMENT;
 
                        /* Update the match offset LRU queue.  */
+                       BUILD_BUG_ON(LZX_NUM_RECENT_OFFSETS != 3);
                        queue->R[2] = queue->R[1];
                        queue->R[1] = queue->R[0];
                        queue->R[0] = match_offset;