From a373fd766e6d8053e87b44f35f60c16dbea4e2fa Mon Sep 17 00:00:00 2001 From: Michael Drake Date: Sun, 18 Apr 2021 17:31:36 +0100 Subject: [PATCH] lzw: Always read three bytes on fast path to avoid swtich. --- libvips/foreign/libnsgif/lzw.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/libvips/foreign/libnsgif/lzw.c b/libvips/foreign/libnsgif/lzw.c index a3034f8a..4b521b68 100644 --- a/libvips/foreign/libnsgif/lzw.c +++ b/libvips/foreign/libnsgif/lzw.c @@ -41,7 +41,7 @@ struct lzw_read_ctx { uint32_t data_sb_next; /**< Offset to sub-block size */ const uint8_t *sb_data; /**< Pointer to current sub-block in data */ - uint32_t sb_bit; /**< Current bit offset in sub-block */ + size_t sb_bit; /**< Current bit offset in sub-block */ uint32_t sb_bit_count; /**< Bit count in sub-block */ }; @@ -165,29 +165,25 @@ static lzw_result lzw__block_advance(struct lzw_read_ctx *restrict ctx) */ static inline lzw_result lzw__read_code( struct lzw_read_ctx *restrict ctx, - uint8_t code_size, + uint32_t code_size, uint32_t *restrict code_out) { uint32_t code = 0; - uint8_t current_bit = ctx->sb_bit & 0x7; - uint8_t byte_advance = (current_bit + code_size) >> 3; + uint32_t current_bit = ctx->sb_bit & 0x7; - assert(byte_advance <= 2); - - if (ctx->sb_bit + code_size <= ctx->sb_bit_count) { - /* Fast path: code fully inside this sub-block */ + if (ctx->sb_bit + 24 <= ctx->sb_bit_count) { + /* Fast path: read three bytes from this sub-block */ const uint8_t *data = ctx->sb_data + (ctx->sb_bit >> 3); - switch (byte_advance) { - case 2: code |= data[2] << 16; /* Fall through */ - case 1: code |= data[1] << 8; /* Fall through */ - case 0: code |= data[0] << 0; - } + code |= *data++ << 0; + code |= *data++ << 8; + code |= *data << 16; ctx->sb_bit += code_size; } else { /* Slow path: code spans sub-blocks */ + uint8_t byte_advance = (current_bit + code_size) >> 3; uint8_t byte = 0; - uint8_t bits_remaining_0 = (code_size < (8 - current_bit)) ? - code_size : (8 - current_bit); + uint8_t bits_remaining_0 = (code_size < (8u - current_bit)) ? + code_size : (8u - current_bit); uint8_t bits_remaining_1 = code_size - bits_remaining_0; uint8_t bits_used[3] = { [0] = bits_remaining_0, @@ -195,6 +191,8 @@ static inline lzw_result lzw__read_code( [2] = bits_remaining_1 - 8, }; + assert(byte_advance <= 2); + while (true) { const uint8_t *data = ctx->sb_data; lzw_result res;