*/
#include "xpress.h"
+#include "wimlib.h"
#include "compress.h"
+
#include <stdlib.h>
#include <string.h>
*
* @codewords and @lens provide the Huffman code that is being used.
*/
-static int xpress_write_match(struct output_bitstream *ostream, u32 match,
- const u16 codewords[], const u8 lens[])
+static int
+xpress_write_match(struct output_bitstream *ostream, u32 match,
+ const u16 codewords[], const u8 lens[])
{
u32 adjusted_match_len = match & 0xffff;
u32 match_offset = match >> 16;
match_offset ^ (1 << offset_bsr), offset_bsr);
}
-static int xpress_write_compressed_literals(struct output_bitstream *ostream,
- const u32 match_tab[],
- unsigned num_matches,
- const u16 codewords[],
- const u8 lens[])
+static int
+xpress_write_compressed_literals(struct output_bitstream *ostream,
+ const u32 match_tab[],
+ unsigned num_matches,
+ const u16 codewords[],
+ const u8 lens[])
{
for (unsigned i = 0; i < num_matches; i++) {
int ret;
lens[XPRESS_END_OF_DATA]);
}
-static u32 xpress_record_literal(u8 literal, void *__freq_tab)
+static u32
+xpress_record_literal(u8 literal, void *__freq_tab)
{
freq_t *freq_tab = __freq_tab;
freq_tab[literal]++;
return literal;
}
-static u32 xpress_record_match(unsigned match_offset, unsigned match_len,
- void *freq_tab, void *ignore)
+static u32
+xpress_record_match(unsigned match_offset, unsigned match_len,
+ void *freq_tab, void *ignore)
{
wimlib_assert(match_len >= XPRESS_MIN_MATCH &&
match_len <= XPRESS_MAX_MATCH);
.too_far = 4096,
};
-/*
- * Performs XPRESS 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 xpress_compress(const void *__uncompressed_data, unsigned uncompressed_len,
- void *__compressed_data, unsigned *compressed_len_ret)
+/* Documented in wimlib.h */
+WIMLIBAPI unsigned
+wimlib_xpress_compress(const void *__uncompressed_data,
+ unsigned uncompressed_len, void *__compressed_data)
{
- const u8 *uncompressed_data = __uncompressed_data;
u8 *compressed_data = __compressed_data;
struct output_bitstream ostream;
u32 match_tab[uncompressed_len];
unsigned compressed_len;
unsigned i;
int ret;
+ u8 uncompressed_data[uncompressed_len + 8];
+
+ memcpy(uncompressed_data, __uncompressed_data, uncompressed_len);
+ memset(uncompressed_data + uncompressed_len, 0, 8);
+
+ wimlib_assert(uncompressed_len <= 32768);
/* XPRESS requires 256 bytes of overhead for the Huffman tables, so it's
* impossible cannot compress 256 bytes or less of data to less than the
* +4 to take into account that init_output_bitstream() requires at
* least 4 bytes of data. */
if (uncompressed_len < XPRESS_NUM_SYMBOLS / 2 + 1 + 4)
- return 1;
+ return 0;
ZERO_ARRAY(freq_tab);
num_matches = lz_analyze_block(uncompressed_data, uncompressed_len,
ret = xpress_write_compressed_literals(&ostream, match_tab,
num_matches, codewords, lens);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
/* Flush any bits that are buffered. */
ret = flush_output_bitstream(&ostream);
- if (ret != 0)
- return ret;
+ if (ret)
+ return 0;
/* Assert that there are no output bytes between the ostream.output
* pointer and the ostream.next_bit_output pointer. This can only
* they may precede a number of bytes embedded into the bitstream.) */
if (ostream.bit_output >
(const u8*)__compressed_data + uncompressed_len - 3)
- return 1;
+ return 0;
*(u16*)ostream.bit_output = cpu_to_le16(0);
compressed_len = ostream.next_bit_output - (const u8*)__compressed_data;
wimlib_assert(compressed_len <= uncompressed_len - 1);
- *compressed_len_ret = compressed_len;
-
-#ifdef ENABLE_VERIFY_COMPRESSION
+#if defined(ENABLE_VERIFY_COMPRESSION)
/* Verify that we really get the same thing back when decompressing. */
- u8 buf[uncompressed_len];
- ret = xpress_decompress(__compressed_data, compressed_len, buf,
- uncompressed_len);
- if (ret != 0) {
- ERROR("xpress_compress(): Failed to decompress data we "
- "compressed");
- abort();
- }
- for (i = 0; i < uncompressed_len; i++) {
- if (buf[i] != uncompressed_data[i]) {
- ERROR("xpress_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_xpress_decompress(__compressed_data, compressed_len,
+ buf, uncompressed_len);
+ if (ret) {
+ ERROR("xpress_compress(): Failed to decompress data we "
+ "compressed");
abort();
}
+ for (i = 0; i < uncompressed_len; i++) {
+ if (buf[i] != uncompressed_data[i]) {
+ ERROR("xpress_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;
}