/*
- * This file provides lzx_compress(), a function to compress an in-memory buffer
- * of data using LZX compression, as used in the WIM file format.
+ * This file provides wimlib_lzx_compress(), a function to compress an in-memory
+ * buffer of data using LZX compression, as used in the WIM file format.
*
* Please see the comments in lzx-decompress.c for more information about this
* compression format.
* blocks from one input chunk is not yet implemented.
*/
-#include "lzx.h"
-#include "compress.h"
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "wimlib.h"
+#include "wimlib/compress.h"
+#include "wimlib/error.h"
+#include "wimlib/lzx.h"
+#include "wimlib/util.h"
+
#include <stdlib.h>
#include <string.h>
}
static u32
-lzx_record_literal(u8 literal, void *__main_freq_tab)
+lzx_record_literal(u8 literal, void *_main_freq_tab)
{
- freq_t *main_freq_tab = __main_freq_tab;
+ freq_t *main_freq_tab = _main_freq_tab;
main_freq_tab[literal]++;
return literal;
}
* intermediate representation documented below. */
static u32
lzx_record_match(unsigned match_offset, unsigned match_len,
- void *__freq_tabs, void *__queue)
+ void *_freq_tabs, void *_queue)
{
- struct lzx_freq_tables *freq_tabs = __freq_tabs;
- struct lru_queue *queue = __queue;
+ struct lzx_freq_tables *freq_tabs = _freq_tabs;
+ struct lru_queue *queue = _queue;
unsigned position_slot;
unsigned position_footer = 0;
u32 match;
unsigned i;
unsigned len_in_run;
unsigned additional_bits;
- char delta;
+ signed char delta;
u8 pretree_sym;
ZERO_ARRAY(pretree_freqs);
* */
while (cur_run_len >= 4) {
additional_bits = (cur_run_len > 4);
- delta = -(char)len_in_run;
+ delta = -(signed char)len_in_run;
if (delta < 0)
delta += 17;
pretree_freqs[19]++;
* as a difference from the length of that codeword in the
* previous tree. */
while (cur_run_len--) {
- delta = -(char)len_in_run;
+ delta = -(signed char)len_in_run;
if (delta < 0)
delta += 17;
/* Builds the canonical Huffman code for the main tree, the length tree, and the
* aligned offset tree. */
-static void
+static void
lzx_make_huffman_codes(const struct lzx_freq_tables *freq_tabs,
struct lzx_codes *codes)
{
static void
do_call_insn_translation(u32 *call_insn_target, int input_pos,
- int32_t file_size)
+ s32 file_size)
{
- int32_t abs_offset;
- int32_t rel_offset;
+ s32 abs_offset;
+ s32 rel_offset;
rel_offset = le32_to_cpu(*call_insn_target);
if (rel_offset >= -input_pos && rel_offset < file_size) {
.too_far = 4096,
};
-/*
- * Performs LZX compression on a block of data.
- *
- * @__uncompressed_data: Pointer to the data to be compressed.
- * @uncompressed_len: Length, in bytes, of the data to be compressed.
- * @compressed_data: Pointer to a location at least (@uncompressed_len - 1)
- * bytes long into which the compressed data may be
- * written.
- * @compressed_len_ret: A pointer to an unsigned int into which the length of
- * the compressed data may be returned.
- *
- * Returns zero if compression was successfully performed. In that case
- * @compressed_data and @compressed_len_ret will contain the compressed data and
- * its length. A return value of nonzero means that compressing the data did
- * not reduce its size, and @compressed_data will not contain the full
- * compressed data.
- */
-int
-lzx_compress(const void *__uncompressed_data, unsigned uncompressed_len,
- void *compressed_data, unsigned *compressed_len_ret)
+/* API function documented in wimlib.h */
+WIMLIBAPI unsigned
+wimlib_lzx_compress(const void *_uncompressed_data, unsigned uncompressed_len,
+ void *compressed_data)
{
struct output_bitstream ostream;
u8 uncompressed_data[uncompressed_len + 8];
int ret;
int block_type = LZX_BLOCKTYPE_ALIGNED;
+ wimlib_assert(uncompressed_len <= 32768);
+
if (uncompressed_len < 100)
- return 1;
+ return 0;
memset(&freq_tabs, 0, sizeof(freq_tabs));
queue.R0 = 1;
/* The input data must be preprocessed. To avoid changing the original
* input, copy it to a temporary buffer. */
- memcpy(uncompressed_data, __uncompressed_data, uncompressed_len);
+ memcpy(uncompressed_data, _uncompressed_data, uncompressed_len);
+ memset(uncompressed_data + uncompressed_len, 0, 8);
/* Before doing any actual compression, do the call instruction (0xe8
* byte) translation on the uncompressed data. */
* main tree. */
ret = lzx_write_compressed_tree(&ostream, codes.main_lens,
LZX_NUM_CHARS);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
/* Write the pre-tree and symbols for the rest of the main tree. */
ret = lzx_write_compressed_tree(&ostream, codes.main_lens +
LZX_NUM_CHARS,
LZX_MAINTREE_NUM_SYMBOLS -
LZX_NUM_CHARS);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
/* Write the pre-tree and symbols for the length tree. */
ret = lzx_write_compressed_tree(&ostream, codes.len_lens,
LZX_LENTREE_NUM_SYMBOLS);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
/* Write the compressed literals. */
ret = lzx_write_compressed_literals(&ostream, block_type,
match_tab, num_matches, &codes);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
ret = flush_output_bitstream(&ostream);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
compressed_len = ostream.bit_output - (u8*)compressed_data;
- *compressed_len_ret = compressed_len;
-
#ifdef ENABLE_VERIFY_COMPRESSION
/* Verify that we really get the same thing back when decompressing. */
- u8 buf[uncompressed_len];
- ret = lzx_decompress(compressed_data, compressed_len, buf,
- uncompressed_len);
- if (ret != 0) {
- ERROR("lzx_compress(): Failed to decompress data we compressed");
- abort();
- }
-
- for (i = 0; i < uncompressed_len; i++) {
- if (buf[i] != *((u8*)__uncompressed_data + i)) {
- ERROR("lzx_compress(): Data we compressed didn't "
- "decompress to the original data (difference at "
- "byte %u of %u)", i + 1, uncompressed_len);
+ {
+ u8 buf[uncompressed_len];
+ ret = wimlib_lzx_decompress(compressed_data, compressed_len,
+ buf, uncompressed_len);
+ if (ret != 0) {
+ ERROR("lzx_compress(): Failed to decompress data we compressed");
abort();
}
+
+ for (i = 0; i < uncompressed_len; i++) {
+ if (buf[i] != *((u8*)_uncompressed_data + i)) {
+ ERROR("lzx_compress(): Data we compressed didn't "
+ "decompress to the original data (difference at "
+ "byte %u of %u)", i + 1, uncompressed_len);
+ abort();
+ }
+ }
}
#endif
- return 0;
+ return compressed_len;
}