/*
*
- * Copyright (C) 2012, 2013, 2015 Eric Biggers
+ * Copyright (C) 2012-2016 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
* 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 12
+#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 *compressed_data, size_t compressed_size,
- void *uncompressed_data, size_t uncompressed_size, void *_ctx)
+xpress_decompress(const void *restrict compressed_data, size_t compressed_size,
+ void *restrict uncompressed_data, size_t uncompressed_size,
+ 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 {
- u16 decode_table[(1 << XPRESS_TABLEBITS) + 2 * XPRESS_NUM_SYMBOLS]
- _aligned_attribute(DECODE_TABLE_ALIGNMENT);
- 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))
- return -1;
-
- if (unlikely(length > out_end - out_next))
+ if (unlikely(lz_copy(length, offset,
+ out_begin, out_next, out_end,
+ XPRESS_MIN_MATCH_LEN)))
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,
};