From 194f6a447fe7f2f4318be970a11c5fc2fc67b179 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Thu, 20 Jan 2022 23:36:02 -0800 Subject: [PATCH] deflate_compress: factor out deflate_write_match() Reduce code duplication between deflate_write_sequences() and deflate_write_item_list(). --- lib/deflate_compress.c | 134 +++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 84 deletions(-) diff --git a/lib/deflate_compress.c b/lib/deflate_compress.c index 02e79fd..b11fdc1 100644 --- a/lib/deflate_compress.c +++ b/lib/deflate_compress.c @@ -1703,6 +1703,45 @@ deflate_write_literal_run(struct deflate_output_bitstream *os, #endif } +static forceinline void +deflate_write_match(struct deflate_output_bitstream * restrict os, + unsigned length, unsigned length_slot, + unsigned offset, unsigned offset_symbol, + const struct deflate_codes * restrict codes) +{ + unsigned litlen_symbol = DEFLATE_FIRST_LEN_SYM + length_slot; + + /* Litlen symbol */ + deflate_add_bits(os, codes->codewords.litlen[litlen_symbol], + codes->lens.litlen[litlen_symbol]); + + /* Extra length bits */ + STATIC_ASSERT(CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN + + DEFLATE_MAX_EXTRA_LENGTH_BITS)); + deflate_add_bits(os, length - deflate_length_slot_base[length_slot], + deflate_extra_length_bits[length_slot]); + + if (!CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN + + DEFLATE_MAX_EXTRA_LENGTH_BITS + + MAX_OFFSET_CODEWORD_LEN + + DEFLATE_MAX_EXTRA_OFFSET_BITS)) + deflate_flush_bits(os); + + /* Offset symbol */ + deflate_add_bits(os, codes->codewords.offset[offset_symbol], + codes->lens.offset[offset_symbol]); + + if (!CAN_BUFFER(MAX_OFFSET_CODEWORD_LEN + + DEFLATE_MAX_EXTRA_OFFSET_BITS)) + deflate_flush_bits(os); + + /* Extra offset bits */ + deflate_add_bits(os, offset - deflate_offset_slot_base[offset_symbol], + deflate_extra_offset_bits[offset_symbol]); + + deflate_flush_bits(os); +} + static void deflate_write_sequences(struct deflate_output_bitstream * restrict os, const struct deflate_codes * restrict codes, @@ -1714,9 +1753,6 @@ deflate_write_sequences(struct deflate_output_bitstream * restrict os, for (;;) { u32 litrunlen = seq->litrunlen_and_length & SEQ_LITRUNLEN_MASK; unsigned length = seq->litrunlen_and_length >> SEQ_LENGTH_SHIFT; - unsigned length_slot; - unsigned litlen_symbol; - unsigned offset_symbol; if (litrunlen) { deflate_write_literal_run(os, in_next, litrunlen, @@ -1727,44 +1763,10 @@ deflate_write_sequences(struct deflate_output_bitstream * restrict os, if (length == 0) return; + deflate_write_match(os, length, seq->length_slot, + seq->offset, seq->offset_symbol, codes); + in_next += length; - - length_slot = seq->length_slot; - litlen_symbol = DEFLATE_FIRST_LEN_SYM + length_slot; - - /* Litlen symbol */ - deflate_add_bits(os, codes->codewords.litlen[litlen_symbol], - codes->lens.litlen[litlen_symbol]); - - /* Extra length bits */ - STATIC_ASSERT(CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_LENGTH_BITS)); - deflate_add_bits(os, - length - deflate_length_slot_base[length_slot], - deflate_extra_length_bits[length_slot]); - - if (!CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_LENGTH_BITS + - MAX_OFFSET_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_OFFSET_BITS)) - deflate_flush_bits(os); - - /* Offset symbol */ - offset_symbol = seq->offset_symbol; - deflate_add_bits(os, codes->codewords.offset[offset_symbol], - codes->lens.offset[offset_symbol]); - - if (!CAN_BUFFER(MAX_OFFSET_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_OFFSET_BITS)) - deflate_flush_bits(os); - - /* Extra offset bits */ - deflate_add_bits(os, seq->offset - - deflate_offset_slot_base[offset_symbol], - deflate_extra_offset_bits[offset_symbol]); - - deflate_flush_bits(os); - seq++; } } @@ -1774,10 +1776,6 @@ deflate_write_sequences(struct deflate_output_bitstream * restrict os, * Follow the minimum-cost path in the graph of possible match/literal choices * for the current block and write out the matches/literals using the specified * Huffman codes. - * - * Note: this is slightly duplicated with deflate_write_sequences(), the reason - * being that we don't want to waste time translating between intermediate - * match/literal representations. */ static void deflate_write_item_list(struct deflate_output_bitstream *os, @@ -1791,51 +1789,19 @@ deflate_write_item_list(struct deflate_output_bitstream *os, do { unsigned length = cur_node->item & OPTIMUM_LEN_MASK; unsigned offset = cur_node->item >> OPTIMUM_OFFSET_SHIFT; - unsigned litlen_symbol; - unsigned length_slot; - unsigned offset_slot; if (length == 1) { /* Literal */ - litlen_symbol = offset; - deflate_add_bits(os, - codes->codewords.litlen[litlen_symbol], - codes->lens.litlen[litlen_symbol]); + deflate_add_bits(os, codes->codewords.litlen[offset], + codes->lens.litlen[offset]); deflate_flush_bits(os); } else { - /* Match length */ - length_slot = deflate_length_slot[length]; - litlen_symbol = DEFLATE_FIRST_LEN_SYM + length_slot; - deflate_add_bits(os, - codes->codewords.litlen[litlen_symbol], - codes->lens.litlen[litlen_symbol]); - - deflate_add_bits(os, - length - deflate_length_slot_base[length_slot], - deflate_extra_length_bits[length_slot]); - - if (!CAN_BUFFER(MAX_LITLEN_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_LENGTH_BITS + - MAX_OFFSET_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_OFFSET_BITS)) - deflate_flush_bits(os); - - - /* Match offset */ - offset_slot = c->p.n.offset_slot_full[offset]; - deflate_add_bits(os, - codes->codewords.offset[offset_slot], - codes->lens.offset[offset_slot]); - - if (!CAN_BUFFER(MAX_OFFSET_CODEWORD_LEN + - DEFLATE_MAX_EXTRA_OFFSET_BITS)) - deflate_flush_bits(os); - - deflate_add_bits(os, - offset - deflate_offset_slot_base[offset_slot], - deflate_extra_offset_bits[offset_slot]); - - deflate_flush_bits(os); + /* Match */ + deflate_write_match(os, length, + deflate_length_slot[length], + offset, + c->p.n.offset_slot_full[offset], + codes); } cur_node += length; } while (cur_node != end_node);