* fail during decompression if the Huffman symbol 256 is not found after
* the actual data."
*
- * This is the case for the implementation in WIMGAPI. However, wimlib's
- * decompressor in this file currently does not care if this extra symbol is
- * there or not.
+ * This is the case with Microsoft's implementation in WIMGAPI, for example. So
+ * although our implementation doesn't currently check for this extra symbol,
+ * compressors would be wise to add it.
*/
#ifdef HAVE_CONFIG_H
#include "wimlib/decompressor_ops.h"
#include "wimlib/decompress_common.h"
#include "wimlib/error.h"
+#include "wimlib/util.h"
#include "wimlib/xpress_constants.h"
/* This value is chosen for fast decompression. */
#define XPRESS_TABLEBITS 11
+struct xpress_decompressor {
+ union {
+ DECODE_TABLE(decode_table, XPRESS_NUM_SYMBOLS,
+ XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
+ u8 lens[XPRESS_NUM_SYMBOLS];
+ };
+ DECODE_TABLE_WORKING_SPACE(working_space, XPRESS_NUM_SYMBOLS,
+ XPRESS_MAX_CODEWORD_LEN);
+} _aligned_attribute(DECODE_TABLE_ALIGNMENT);
+
static int
xpress_decompress(const void *restrict compressed_data, size_t compressed_size,
void *restrict uncompressed_data, size_t uncompressed_size,
- void *restrict _ctx)
+ void *restrict _d)
{
+ struct xpress_decompressor *d = _d;
const u8 * const in_begin = compressed_data;
u8 * const out_begin = uncompressed_data;
u8 *out_next = out_begin;
u8 * const out_end = out_begin + uncompressed_size;
- union {
- DECODE_TABLE(decode_table, XPRESS_NUM_SYMBOLS,
- XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
- u8 lens[XPRESS_NUM_SYMBOLS];
- } u;
struct input_bitstream is;
/* Read the Huffman codeword lengths. */
if (compressed_size < XPRESS_NUM_SYMBOLS / 2)
return -1;
for (int i = 0; i < XPRESS_NUM_SYMBOLS / 2; i++) {
- u.lens[2 * i + 0] = in_begin[i] & 0xf;
- u.lens[2 * i + 1] = in_begin[i] >> 4;
+ d->lens[2 * i + 0] = in_begin[i] & 0xf;
+ d->lens[2 * i + 1] = in_begin[i] >> 4;
}
/* Build a decoding table for the Huffman code. */
- if (make_huffman_decode_table(u.decode_table, XPRESS_NUM_SYMBOLS,
- XPRESS_TABLEBITS, u.lens,
- XPRESS_MAX_CODEWORD_LEN))
+ if (make_huffman_decode_table(d->decode_table, XPRESS_NUM_SYMBOLS,
+ XPRESS_TABLEBITS, d->lens,
+ XPRESS_MAX_CODEWORD_LEN,
+ d->working_space))
return -1;
/* Decode the matches and literals. */
u32 length;
u32 offset;
- sym = read_huffsym(&is, u.decode_table,
+ sym = read_huffsym(&is, d->decode_table,
XPRESS_TABLEBITS, XPRESS_MAX_CODEWORD_LEN);
if (sym < XPRESS_NUM_CHARS) {
/* Literal */
}
length += XPRESS_MIN_MATCH_LEN;
- if (unlikely(offset > out_next - out_begin))
+ if (unlikely(lz_copy(length, offset,
+ out_begin, out_next, out_end,
+ XPRESS_MIN_MATCH_LEN)))
return -1;
- if (unlikely(length > out_end - out_next))
- return -1;
-
- lz_copy(out_next, length, offset, out_end,
- XPRESS_MIN_MATCH_LEN);
-
out_next += length;
}
}
}
static int
-xpress_create_decompressor(size_t max_block_size, void **dec_ret)
+xpress_create_decompressor(size_t max_block_size, void **d_ret)
{
+ struct xpress_decompressor *d;
+
if (max_block_size > XPRESS_MAX_OFFSET + 1)
return WIMLIB_ERR_INVALID_PARAM;
+ d = ALIGNED_MALLOC(sizeof(*d), DECODE_TABLE_ALIGNMENT);
+ if (!d)
+ return WIMLIB_ERR_NOMEM;
+
+ *d_ret = d;
return 0;
}
+static void
+xpress_free_decompressor(void *_d)
+{
+ ALIGNED_FREE(_d);
+}
+
const struct decompressor_ops xpress_decompressor_ops = {
.create_decompressor = xpress_create_decompressor,
.decompress = xpress_decompress,
+ .free_decompressor = xpress_free_decompressor,
};