X-Git-Url: https://wimlib.net/git/?a=blobdiff_plain;f=src%2Flzx_compress.c;h=28a2656fb45852006f529d3df2f686c67fd6bbd2;hb=f1c9d53eb97205b17092ba6de50f0967932861ed;hp=075a65a1e5064541646f1c263c70de10d0d70e39;hpb=814c6f33ee61315286430e5f0044a40061e94b82;p=wimlib diff --git a/src/lzx_compress.c b/src/lzx_compress.c index 075a65a1..28a2656f 100644 --- a/src/lzx_compress.c +++ b/src/lzx_compress.c @@ -105,7 +105,7 @@ /* * LZX_BIT_COST is a scaling factor that represents the cost to output one bit. - * THis makes it possible to consider fractional bit costs. + * This makes it possible to consider fractional bit costs. * * Note: this is only useful as a statistical trick for when the true costs are * unknown. In reality, each token in LZX requires a whole number of bits to @@ -128,7 +128,7 @@ /* * LZX_HASH2_ORDER is the log base 2 of the number of entries in the hash table * for finding length 2 matches. This can be as high as 16 (in which case the - * hash function is trivial), but using a smaller hash table actually speeds up + * hash function is trivial), but using a smaller hash table speeds up * compression due to reduced cache pressure. */ #define LZX_HASH2_ORDER 12 @@ -368,6 +368,10 @@ struct lzx_compressor { /* Pointer to the compress() implementation chosen at allocation time */ void (*impl)(struct lzx_compressor *, struct lzx_output_bitstream *); + /* If true, the compressor need not preserve the input buffer if it + * compresses the data successfully. */ + bool destructive; + /* The Huffman symbol frequency counters for the current block. */ struct lzx_freqs freqs; @@ -1620,13 +1624,11 @@ lzx_compress_near_optimal(struct lzx_compressor *c, max_len = in_end - in_next; nice_len = min(max_len, nice_len); - /* This extra check is needed to ensure that - * reading the next 3 bytes when looking for a - * length 2 match is valid. In addition, we - * cannot allow ourselves to find a length 2 - * match of the very last two bytes with the - * very first two bytes, since such a match has - * an offset too large to be represented. */ + /* This extra check is needed to ensure that we + * never output a length 2 match of the very + * last two bytes with the very first two bytes, + * since such a match has an offset too large to + * be represented. */ if (unlikely(max_len < 3)) { in_next++; cache_ptr->length = 0; @@ -2010,7 +2012,8 @@ lzx_get_compressor_size(size_t max_bufsize, unsigned compression_level) } static u64 -lzx_get_needed_memory(size_t max_bufsize, unsigned compression_level) +lzx_get_needed_memory(size_t max_bufsize, unsigned compression_level, + bool destructive) { u64 size = 0; @@ -2018,13 +2021,14 @@ lzx_get_needed_memory(size_t max_bufsize, unsigned compression_level) return 0; size += lzx_get_compressor_size(max_bufsize, compression_level); - size += max_bufsize; /* in_buffer */ + if (!destructive) + size += max_bufsize; /* in_buffer */ return size; } static int lzx_create_compressor(size_t max_bufsize, unsigned compression_level, - void **c_ret) + bool destructive, void **c_ret) { unsigned window_order; struct lzx_compressor *c; @@ -2039,12 +2043,16 @@ lzx_create_compressor(size_t max_bufsize, unsigned compression_level, if (!c) goto oom0; + c->destructive = destructive; + c->num_main_syms = lzx_get_num_main_syms(window_order); c->window_order = window_order; - c->in_buffer = MALLOC(max_bufsize); - if (!c->in_buffer) - goto oom1; + if (!c->destructive) { + c->in_buffer = MALLOC(max_bufsize); + if (!c->in_buffer) + goto oom1; + } if (compression_level <= LZX_MAX_FAST_LEVEL) { @@ -2117,13 +2125,17 @@ lzx_compress(const void *in, size_t in_nbytes, { struct lzx_compressor *c = _c; struct lzx_output_bitstream os; + size_t result; /* Don't bother trying to compress very small inputs. */ if (in_nbytes < 100) return 0; /* Copy the input data into the internal buffer and preprocess it. */ - memcpy(c->in_buffer, in, in_nbytes); + if (c->destructive) + c->in_buffer = (void *)in; + else + memcpy(c->in_buffer, in, in_nbytes); c->in_nbytes = in_nbytes; lzx_do_e8_preprocessing(c->in_buffer, in_nbytes); @@ -2138,7 +2150,10 @@ lzx_compress(const void *in, size_t in_nbytes, (*c->impl)(c, &os); /* Flush the output bitstream and return the compressed size or 0. */ - return lzx_flush_output(&os); + result = lzx_flush_output(&os); + if (!result && c->destructive) + lzx_undo_e8_preprocessing(c->in_buffer, c->in_nbytes); + return result; } static void @@ -2146,7 +2161,8 @@ lzx_free_compressor(void *_c) { struct lzx_compressor *c = _c; - FREE(c->in_buffer); + if (!c->destructive) + FREE(c->in_buffer); ALIGNED_FREE(c); }