mirror of
https://github.com/cuberite/libdeflate.git
synced 2025-09-10 04:41:45 -04:00
deflate_compress: introduce the lazy2 compressor
Add deflate_compress_lazy2(), which is a slightly stronger variant of deflate_compress_lazy(). It looks ahead 2 positions instead of 1.
This commit is contained in:
parent
f699b697d6
commit
1b3eaf2f13
@ -2070,15 +2070,11 @@ deflate_compress_greedy(struct libdeflate_compressor * restrict c,
|
|||||||
return deflate_flush_output(&os);
|
return deflate_flush_output(&os);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
static forceinline size_t
|
||||||
* This is the "lazy" DEFLATE compressor. Before choosing a match, it checks to
|
deflate_compress_lazy_generic(struct libdeflate_compressor * restrict c,
|
||||||
* see if there's a better match at the next position. If yes, it outputs a
|
|
||||||
* literal and continues to the next position. If no, it outputs the match.
|
|
||||||
*/
|
|
||||||
static size_t
|
|
||||||
deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|
||||||
const u8 * restrict in, size_t in_nbytes,
|
const u8 * restrict in, size_t in_nbytes,
|
||||||
u8 * restrict out, size_t out_nbytes_avail)
|
u8 * restrict out, size_t out_nbytes_avail,
|
||||||
|
bool lazy2)
|
||||||
{
|
{
|
||||||
const u8 *in_next = in;
|
const u8 *in_next = in;
|
||||||
const u8 *in_end = in_next + in_nbytes;
|
const u8 *in_end = in_next + in_nbytes;
|
||||||
@ -2195,9 +2191,55 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
cur_offset = next_offset;
|
cur_offset = next_offset;
|
||||||
goto have_cur_match;
|
goto have_cur_match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (lazy2) {
|
||||||
|
/* In lazy2 mode, look ahead another position */
|
||||||
|
adjust_max_and_nice_len(&max_len, &nice_len,
|
||||||
|
in_end - in_next);
|
||||||
|
next_len = hc_matchfinder_longest_match(
|
||||||
|
&c->p.g.hc_mf,
|
||||||
|
&in_cur_base,
|
||||||
|
in_next++,
|
||||||
|
cur_len - 1,
|
||||||
|
max_len,
|
||||||
|
nice_len,
|
||||||
|
c->max_search_depth >> 2,
|
||||||
|
next_hashes,
|
||||||
|
&next_offset);
|
||||||
|
if (next_len >= cur_len &&
|
||||||
|
4 * (int)(next_len - cur_len) +
|
||||||
|
((int)bsr32(cur_offset) -
|
||||||
|
(int)bsr32(next_offset)) > 6) {
|
||||||
/*
|
/*
|
||||||
* No better match at the next position. Output the
|
* There's a much better match two
|
||||||
* current match.
|
* positions ahead, so use two literals.
|
||||||
|
*/
|
||||||
|
deflate_choose_literal(
|
||||||
|
c, *(in_next - 3), &litrunlen);
|
||||||
|
deflate_choose_literal(
|
||||||
|
c, *(in_next - 2), &litrunlen);
|
||||||
|
cur_len = next_len;
|
||||||
|
cur_offset = next_offset;
|
||||||
|
goto have_cur_match;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* No better match at either of the next 2
|
||||||
|
* positions. Output the current match.
|
||||||
|
*/
|
||||||
|
deflate_choose_match(c, cur_len, cur_offset,
|
||||||
|
&litrunlen, &next_seq);
|
||||||
|
if (cur_len > 3)
|
||||||
|
in_next = hc_matchfinder_skip_positions(
|
||||||
|
&c->p.g.hc_mf,
|
||||||
|
&in_cur_base,
|
||||||
|
in_next,
|
||||||
|
in_end,
|
||||||
|
cur_len - 3,
|
||||||
|
next_hashes);
|
||||||
|
} else { /* !lazy2 */
|
||||||
|
/*
|
||||||
|
* No better match at the next position. Output
|
||||||
|
* the current match.
|
||||||
*/
|
*/
|
||||||
deflate_choose_match(c, cur_len, cur_offset,
|
deflate_choose_match(c, cur_len, cur_offset,
|
||||||
&litrunlen, &next_seq);
|
&litrunlen, &next_seq);
|
||||||
@ -2208,6 +2250,7 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
in_end,
|
in_end,
|
||||||
cur_len - 2,
|
cur_len - 2,
|
||||||
next_hashes);
|
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,
|
!should_end_block(&c->split_stats,
|
||||||
@ -2222,6 +2265,34 @@ deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
|||||||
return deflate_flush_output(&os);
|
return deflate_flush_output(&os);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is the "lazy" DEFLATE compressor. Before choosing a match, it checks to
|
||||||
|
* see if there's a better match at the next position. If yes, it outputs a
|
||||||
|
* literal and continues to the next position. If no, it outputs the match.
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
deflate_compress_lazy(struct libdeflate_compressor * restrict c,
|
||||||
|
const u8 * restrict in, size_t in_nbytes,
|
||||||
|
u8 * restrict out, size_t out_nbytes_avail)
|
||||||
|
{
|
||||||
|
return deflate_compress_lazy_generic(c, in, in_nbytes, out,
|
||||||
|
out_nbytes_avail, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The lazy2 compressor. This is similar to the regular lazy one, but it looks
|
||||||
|
* for a better match at the next 2 positions rather than the next 1. This
|
||||||
|
* makes it take slightly more time, but compress some inputs slightly more.
|
||||||
|
*/
|
||||||
|
static size_t
|
||||||
|
deflate_compress_lazy2(struct libdeflate_compressor * restrict c,
|
||||||
|
const u8 * restrict in, size_t in_nbytes,
|
||||||
|
u8 * restrict out, size_t out_nbytes_avail)
|
||||||
|
{
|
||||||
|
return deflate_compress_lazy_generic(c, in, in_nbytes, out,
|
||||||
|
out_nbytes_avail, true);
|
||||||
|
}
|
||||||
|
|
||||||
#if SUPPORT_NEAR_OPTIMAL_PARSING
|
#if SUPPORT_NEAR_OPTIMAL_PARSING
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user