mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-15 07:18:29 -04:00
deflate_compress: clean up deflate_compress_{greedy,lazy,near_optimal}()
Various minor cleanups, such as adjusting the coding style and refactoring some logic into a helper function. No "real" changes.
This commit is contained in:
parent
12e72cf936
commit
dd5b9693cb
@ -1957,6 +1957,19 @@ should_end_block(struct block_split_stats *stats,
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decrease the maximum and nice match lengths if we're approaching the end of
|
||||||
|
* the input buffer.
|
||||||
|
*/
|
||||||
|
static forceinline void
|
||||||
|
adjust_max_and_nice_len(unsigned *max_len, unsigned *nice_len, size_t remaining)
|
||||||
|
{
|
||||||
|
if (unlikely(remaining < DEFLATE_MAX_MATCH_LEN)) {
|
||||||
|
*max_len = remaining;
|
||||||
|
*nice_len = MIN(*nice_len, *max_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This is the level 0 "compressor". It always outputs uncompressed blocks.
|
* This is the level 0 "compressor". It always outputs uncompressed blocks.
|
||||||
*/
|
*/
|
||||||
@ -1994,7 +2007,7 @@ deflate_compress_greedy(struct libdeflate_compressor * restrict c,
|
|||||||
hc_matchfinder_init(&c->p.g.hc_mf);
|
hc_matchfinder_init(&c->p.g.hc_mf);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Starting a new DEFLATE block. */
|
/* Starting a new DEFLATE block. */
|
||||||
|
|
||||||
const u8 * const in_block_begin = in_next;
|
const u8 * const in_block_begin = in_next;
|
||||||
const u8 * const in_max_block_end =
|
const u8 * const in_max_block_end =
|
||||||
@ -2009,44 +2022,42 @@ deflate_compress_greedy(struct libdeflate_compressor * restrict c,
|
|||||||
u32 length;
|
u32 length;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
|
|
||||||
/* Decrease the maximum and nice match lengths if we're
|
adjust_max_and_nice_len(&max_len, &nice_len,
|
||||||
* approaching the end of the input buffer. */
|
in_end - in_next);
|
||||||
if (unlikely(max_len > in_end - in_next)) {
|
length = hc_matchfinder_longest_match(
|
||||||
max_len = in_end - in_next;
|
&c->p.g.hc_mf,
|
||||||
nice_len = MIN(nice_len, max_len);
|
&in_cur_base,
|
||||||
}
|
in_next,
|
||||||
|
DEFLATE_MIN_MATCH_LEN - 1,
|
||||||
length = hc_matchfinder_longest_match(&c->p.g.hc_mf,
|
max_len,
|
||||||
&in_cur_base,
|
nice_len,
|
||||||
in_next,
|
c->max_search_depth,
|
||||||
DEFLATE_MIN_MATCH_LEN - 1,
|
next_hashes,
|
||||||
max_len,
|
&offset);
|
||||||
nice_len,
|
|
||||||
c->max_search_depth,
|
|
||||||
next_hashes,
|
|
||||||
&offset);
|
|
||||||
|
|
||||||
if (length >= DEFLATE_MIN_MATCH_LEN) {
|
if (length >= DEFLATE_MIN_MATCH_LEN) {
|
||||||
/* Match found. */
|
/* Match found. */
|
||||||
deflate_choose_match(c, length, offset,
|
deflate_choose_match(c, length, offset,
|
||||||
&litrunlen, &next_seq);
|
&litrunlen, &next_seq);
|
||||||
observe_match(&c->split_stats, length);
|
observe_match(&c->split_stats, length);
|
||||||
in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
|
in_next = hc_matchfinder_skip_positions(
|
||||||
&in_cur_base,
|
&c->p.g.hc_mf,
|
||||||
in_next + 1,
|
&in_cur_base,
|
||||||
in_end,
|
in_next + 1,
|
||||||
length - 1,
|
in_end,
|
||||||
next_hashes);
|
length - 1,
|
||||||
|
next_hashes);
|
||||||
} else {
|
} else {
|
||||||
/* No match found. */
|
/* No match found. */
|
||||||
deflate_choose_literal(c, *in_next, &litrunlen);
|
deflate_choose_literal(c, *in_next, &litrunlen);
|
||||||
observe_literal(&c->split_stats, *in_next);
|
observe_literal(&c->split_stats, *in_next);
|
||||||
in_next++;
|
in_next++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if it's time to output another block. */
|
/* Check if it's time to output another block. */
|
||||||
} while (in_next < in_max_block_end &&
|
} while (in_next < in_max_block_end &&
|
||||||
!should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
|
!should_end_block(&c->split_stats,
|
||||||
|
in_block_begin, in_next, in_end));
|
||||||
|
|
||||||
deflate_finish_sequence(next_seq, litrunlen);
|
deflate_finish_sequence(next_seq, litrunlen);
|
||||||
deflate_flush_block(c, &os, in_block_begin,
|
deflate_flush_block(c, &os, in_block_begin,
|
||||||
@ -2079,7 +2090,7 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
hc_matchfinder_init(&c->p.g.hc_mf);
|
hc_matchfinder_init(&c->p.g.hc_mf);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Starting a new DEFLATE block. */
|
/* Starting a new DEFLATE block. */
|
||||||
|
|
||||||
const u8 * const in_block_begin = in_next;
|
const u8 * const in_block_begin = in_next;
|
||||||
const u8 * const in_max_block_end =
|
const u8 * const in_max_block_end =
|
||||||
@ -2096,51 +2107,49 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
unsigned next_len;
|
unsigned next_len;
|
||||||
unsigned next_offset;
|
unsigned next_offset;
|
||||||
|
|
||||||
if (unlikely(in_end - in_next < DEFLATE_MAX_MATCH_LEN)) {
|
/* Find the longest match at the current position. */
|
||||||
max_len = in_end - in_next;
|
adjust_max_and_nice_len(&max_len, &nice_len,
|
||||||
nice_len = MIN(nice_len, max_len);
|
in_end - in_next);
|
||||||
}
|
cur_len = hc_matchfinder_longest_match(
|
||||||
|
&c->p.g.hc_mf,
|
||||||
/* Find the longest match at the current position. */
|
&in_cur_base,
|
||||||
cur_len = hc_matchfinder_longest_match(&c->p.g.hc_mf,
|
in_next,
|
||||||
&in_cur_base,
|
DEFLATE_MIN_MATCH_LEN - 1,
|
||||||
in_next,
|
max_len,
|
||||||
DEFLATE_MIN_MATCH_LEN - 1,
|
nice_len,
|
||||||
max_len,
|
c->max_search_depth,
|
||||||
nice_len,
|
next_hashes,
|
||||||
c->max_search_depth,
|
&cur_offset);
|
||||||
next_hashes,
|
|
||||||
&cur_offset);
|
|
||||||
in_next += 1;
|
|
||||||
|
|
||||||
if (cur_len < DEFLATE_MIN_MATCH_LEN) {
|
if (cur_len < DEFLATE_MIN_MATCH_LEN) {
|
||||||
/* No match found. Choose a literal. */
|
/* No match found. Choose a literal. */
|
||||||
deflate_choose_literal(c, *(in_next - 1), &litrunlen);
|
deflate_choose_literal(c, *in_next, &litrunlen);
|
||||||
observe_literal(&c->split_stats, *(in_next - 1));
|
observe_literal(&c->split_stats, *in_next);
|
||||||
|
in_next++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
in_next++;
|
||||||
|
|
||||||
have_cur_match:
|
have_cur_match:
|
||||||
observe_match(&c->split_stats, cur_len);
|
observe_match(&c->split_stats, cur_len);
|
||||||
|
/*
|
||||||
/* We have a match at the current position. */
|
* We have a match at the current position.
|
||||||
|
* If it's very long, choose it immediately.
|
||||||
/* If the current match is very long, choose it
|
*/
|
||||||
* immediately. */
|
|
||||||
if (cur_len >= nice_len) {
|
if (cur_len >= nice_len) {
|
||||||
deflate_choose_match(c, cur_len, cur_offset,
|
deflate_choose_match(c, cur_len, cur_offset,
|
||||||
&litrunlen, &next_seq);
|
&litrunlen, &next_seq);
|
||||||
in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
|
in_next = hc_matchfinder_skip_positions(
|
||||||
&in_cur_base,
|
&c->p.g.hc_mf,
|
||||||
in_next,
|
&in_cur_base,
|
||||||
in_end,
|
in_next,
|
||||||
cur_len - 1,
|
in_end,
|
||||||
next_hashes);
|
cur_len - 1,
|
||||||
|
next_hashes);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find a match at the next position.
|
* Try to find a longer match at the next position.
|
||||||
*
|
*
|
||||||
* Note: since we already have a match at the *current*
|
* Note: since we already have a match at the *current*
|
||||||
* position, we use only half the 'max_search_depth'
|
* position, we use only half the 'max_search_depth'
|
||||||
@ -2155,45 +2164,47 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
* have two call sites, with longest_match() inlined at
|
* have two call sites, with longest_match() inlined at
|
||||||
* each.
|
* each.
|
||||||
*/
|
*/
|
||||||
if (unlikely(in_end - in_next < DEFLATE_MAX_MATCH_LEN)) {
|
adjust_max_and_nice_len(&max_len, &nice_len,
|
||||||
max_len = in_end - in_next;
|
in_end - in_next);
|
||||||
nice_len = MIN(nice_len, max_len);
|
next_len = hc_matchfinder_longest_match(
|
||||||
}
|
&c->p.g.hc_mf,
|
||||||
next_len = hc_matchfinder_longest_match(&c->p.g.hc_mf,
|
&in_cur_base,
|
||||||
&in_cur_base,
|
in_next++,
|
||||||
in_next,
|
cur_len,
|
||||||
cur_len,
|
max_len,
|
||||||
max_len,
|
nice_len,
|
||||||
nice_len,
|
c->max_search_depth >> 1,
|
||||||
c->max_search_depth / 2,
|
next_hashes,
|
||||||
next_hashes,
|
&next_offset);
|
||||||
&next_offset);
|
|
||||||
in_next += 1;
|
|
||||||
|
|
||||||
if (next_len > cur_len) {
|
if (next_len > cur_len) {
|
||||||
/* Found a longer match at the next position.
|
/*
|
||||||
|
* Found a longer match at the next position.
|
||||||
* Output a literal. Then the next match
|
* Output a literal. Then the next match
|
||||||
* becomes the current match. */
|
* becomes the current match.
|
||||||
deflate_choose_literal(c, *(in_next - 2), &litrunlen);
|
*/
|
||||||
|
deflate_choose_literal(c, *(in_next - 2),
|
||||||
|
&litrunlen);
|
||||||
cur_len = next_len;
|
cur_len = next_len;
|
||||||
cur_offset = next_offset;
|
cur_offset = next_offset;
|
||||||
goto have_cur_match;
|
goto have_cur_match;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
/* No longer match at the next position.
|
* No longer match at the next position. Output the
|
||||||
* Output the current match. */
|
* current match.
|
||||||
|
*/
|
||||||
deflate_choose_match(c, cur_len, cur_offset,
|
deflate_choose_match(c, cur_len, cur_offset,
|
||||||
&litrunlen, &next_seq);
|
&litrunlen, &next_seq);
|
||||||
in_next = hc_matchfinder_skip_positions(&c->p.g.hc_mf,
|
in_next = hc_matchfinder_skip_positions(
|
||||||
&in_cur_base,
|
&c->p.g.hc_mf,
|
||||||
in_next,
|
&in_cur_base,
|
||||||
in_end,
|
in_next,
|
||||||
cur_len - 2,
|
in_end,
|
||||||
next_hashes);
|
cur_len - 2,
|
||||||
|
next_hashes);
|
||||||
/* Check if it's time to output another block. */
|
/* Check if it's time to output another block. */
|
||||||
} while (in_next < in_max_block_end &&
|
} while (in_next < in_max_block_end &&
|
||||||
!should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
|
!should_end_block(&c->split_stats,
|
||||||
|
in_block_begin, in_next, in_end));
|
||||||
|
|
||||||
deflate_finish_sequence(next_seq, litrunlen);
|
deflate_finish_sequence(next_seq, litrunlen);
|
||||||
deflate_flush_block(c, &os, in_block_begin,
|
deflate_flush_block(c, &os, in_block_begin,
|
||||||
@ -2501,7 +2512,8 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
const u8 *in_end = in_next + in_nbytes;
|
const u8 *in_end = in_next + in_nbytes;
|
||||||
struct deflate_output_bitstream os;
|
struct deflate_output_bitstream os;
|
||||||
const u8 *in_cur_base = in_next;
|
const u8 *in_cur_base = in_next;
|
||||||
const u8 *in_next_slide = in_next + MIN(in_end - in_next, MATCHFINDER_WINDOW_SIZE);
|
const u8 *in_next_slide =
|
||||||
|
in_next + MIN(in_end - in_next, MATCHFINDER_WINDOW_SIZE);
|
||||||
unsigned max_len = DEFLATE_MAX_MATCH_LEN;
|
unsigned max_len = DEFLATE_MAX_MATCH_LEN;
|
||||||
unsigned nice_len = MIN(c->nice_match_length, max_len);
|
unsigned nice_len = MIN(c->nice_match_length, max_len);
|
||||||
u32 next_hashes[2] = {0, 0};
|
u32 next_hashes[2] = {0, 0};
|
||||||
@ -2510,7 +2522,7 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
bt_matchfinder_init(&c->p.n.bt_mf);
|
bt_matchfinder_init(&c->p.n.bt_mf);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Starting a new DEFLATE block. */
|
/* Starting a new DEFLATE block. */
|
||||||
|
|
||||||
struct lz_match *cache_ptr = c->p.n.match_cache;
|
struct lz_match *cache_ptr = c->p.n.match_cache;
|
||||||
const u8 * const in_block_begin = in_next;
|
const u8 * const in_block_begin = in_next;
|
||||||
@ -2531,20 +2543,14 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
do {
|
do {
|
||||||
struct lz_match *matches;
|
struct lz_match *matches;
|
||||||
unsigned best_len;
|
unsigned best_len;
|
||||||
|
size_t remaining = in_end - in_next;
|
||||||
|
|
||||||
/* Slide the window forward if needed. */
|
/* Slide the window forward if needed. */
|
||||||
if (in_next == in_next_slide) {
|
if (in_next == in_next_slide) {
|
||||||
bt_matchfinder_slide_window(&c->p.n.bt_mf);
|
bt_matchfinder_slide_window(&c->p.n.bt_mf);
|
||||||
in_cur_base = in_next;
|
in_cur_base = in_next;
|
||||||
in_next_slide = in_next + MIN(in_end - in_next,
|
in_next_slide = in_next +
|
||||||
MATCHFINDER_WINDOW_SIZE);
|
MIN(remaining, MATCHFINDER_WINDOW_SIZE);
|
||||||
}
|
|
||||||
|
|
||||||
/* Decrease the maximum and nice match lengths if we're
|
|
||||||
* approaching the end of the input buffer. */
|
|
||||||
if (unlikely(max_len > in_end - in_next)) {
|
|
||||||
max_len = in_end - in_next;
|
|
||||||
nice_len = MIN(nice_len, max_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2566,24 +2572,28 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
*/
|
*/
|
||||||
matches = cache_ptr;
|
matches = cache_ptr;
|
||||||
best_len = 0;
|
best_len = 0;
|
||||||
|
adjust_max_and_nice_len(&max_len, &nice_len, remaining);
|
||||||
if (likely(max_len >= BT_MATCHFINDER_REQUIRED_NBYTES)) {
|
if (likely(max_len >= BT_MATCHFINDER_REQUIRED_NBYTES)) {
|
||||||
cache_ptr = bt_matchfinder_get_matches(&c->p.n.bt_mf,
|
cache_ptr = bt_matchfinder_get_matches(
|
||||||
in_cur_base,
|
&c->p.n.bt_mf,
|
||||||
in_next - in_cur_base,
|
in_cur_base,
|
||||||
max_len,
|
in_next - in_cur_base,
|
||||||
nice_len,
|
max_len,
|
||||||
c->max_search_depth,
|
nice_len,
|
||||||
next_hashes,
|
c->max_search_depth,
|
||||||
&best_len,
|
next_hashes,
|
||||||
matches);
|
&best_len,
|
||||||
|
matches);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_next >= next_observation) {
|
if (in_next >= next_observation) {
|
||||||
if (best_len >= 4) {
|
if (best_len >= 4) {
|
||||||
observe_match(&c->split_stats, best_len);
|
observe_match(&c->split_stats,
|
||||||
|
best_len);
|
||||||
next_observation = in_next + best_len;
|
next_observation = in_next + best_len;
|
||||||
} else {
|
} else {
|
||||||
observe_literal(&c->split_stats, *in_next);
|
observe_literal(&c->split_stats,
|
||||||
|
*in_next);
|
||||||
next_observation = in_next + 1;
|
next_observation = in_next + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2605,26 +2615,31 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
* data must be highly compressible, so it doesn't
|
* data must be highly compressible, so it doesn't
|
||||||
* matter much what we do.
|
* matter much what we do.
|
||||||
*/
|
*/
|
||||||
if (best_len >= DEFLATE_MIN_MATCH_LEN && best_len >= nice_len) {
|
if (best_len >= DEFLATE_MIN_MATCH_LEN &&
|
||||||
|
best_len >= nice_len) {
|
||||||
--best_len;
|
--best_len;
|
||||||
do {
|
do {
|
||||||
|
remaining = in_end - in_next;
|
||||||
if (in_next == in_next_slide) {
|
if (in_next == in_next_slide) {
|
||||||
bt_matchfinder_slide_window(&c->p.n.bt_mf);
|
bt_matchfinder_slide_window(
|
||||||
|
&c->p.n.bt_mf);
|
||||||
in_cur_base = in_next;
|
in_cur_base = in_next;
|
||||||
in_next_slide = in_next + MIN(in_end - in_next,
|
in_next_slide = in_next +
|
||||||
MATCHFINDER_WINDOW_SIZE);
|
MIN(remaining,
|
||||||
|
MATCHFINDER_WINDOW_SIZE);
|
||||||
}
|
}
|
||||||
if (unlikely(max_len > in_end - in_next)) {
|
adjust_max_and_nice_len(&max_len,
|
||||||
max_len = in_end - in_next;
|
&nice_len,
|
||||||
nice_len = MIN(nice_len, max_len);
|
remaining);
|
||||||
}
|
if (max_len >=
|
||||||
if (max_len >= BT_MATCHFINDER_REQUIRED_NBYTES) {
|
BT_MATCHFINDER_REQUIRED_NBYTES) {
|
||||||
bt_matchfinder_skip_position(&c->p.n.bt_mf,
|
bt_matchfinder_skip_position(
|
||||||
in_cur_base,
|
&c->p.n.bt_mf,
|
||||||
in_next - in_cur_base,
|
in_cur_base,
|
||||||
nice_len,
|
in_next - in_cur_base,
|
||||||
c->max_search_depth,
|
nice_len,
|
||||||
next_hashes);
|
c->max_search_depth,
|
||||||
|
next_hashes);
|
||||||
}
|
}
|
||||||
cache_ptr->length = 0;
|
cache_ptr->length = 0;
|
||||||
cache_ptr->offset = *in_next;
|
cache_ptr->offset = *in_next;
|
||||||
@ -2634,13 +2649,16 @@ deflate_compress_near_optimal(struct libdeflate_compressor * restrict c,
|
|||||||
}
|
}
|
||||||
} while (in_next < in_max_block_end &&
|
} while (in_next < in_max_block_end &&
|
||||||
cache_ptr < &c->p.n.match_cache[CACHE_LENGTH] &&
|
cache_ptr < &c->p.n.match_cache[CACHE_LENGTH] &&
|
||||||
!should_end_block(&c->split_stats, in_block_begin, in_next, in_end));
|
!should_end_block(&c->split_stats,
|
||||||
|
in_block_begin, in_next, in_end));
|
||||||
/* All the matches for this block have been cached. Now choose
|
/*
|
||||||
* the sequence of items to output and flush the block. */
|
* All the matches for this block have been cached. Now choose
|
||||||
|
* the sequence of items to output and flush the block.
|
||||||
|
*/
|
||||||
deflate_optimize_block(c, in_next - in_block_begin, cache_ptr,
|
deflate_optimize_block(c, in_next - in_block_begin, cache_ptr,
|
||||||
in_block_begin == in);
|
in_block_begin == in);
|
||||||
deflate_flush_block(c, &os, in_block_begin, in_next - in_block_begin,
|
deflate_flush_block(c, &os, in_block_begin,
|
||||||
|
in_next - in_block_begin,
|
||||||
in_next == in_end, true);
|
in_next == in_end, true);
|
||||||
} while (in_next != in_end);
|
} while (in_next != in_end);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user