diff options
| author | Clement Sibille <clements+git@lisible.xyz> | 2024-03-07 22:15:19 +0900 | 
|---|---|---|
| committer | Clement Sibille <clements+git@lisible.xyz> | 2024-03-07 22:15:19 +0900 | 
| commit | 690193ec7ed4b156bd709528d4b04fd0e22d0571 (patch) | |
| tree | 45b5eb4e6ac5f4dd35a9078ef80299d3d1d4bf7d | |
| parent | 709b05466b3153cc75bba6bc439e80f173c92c98 (diff) | |
Fix bitstream implementation
| -rw-r--r-- | lisiblepng/meson.build | 4 | ||||
| -rw-r--r-- | lisiblepng/src/lisiblepng/bitstream.c | 42 | ||||
| -rw-r--r-- | lisiblepng/src/lisiblepng/bitstream.h | 4 | ||||
| -rw-r--r-- | lisiblepng/src/lisiblepng/deflate.c | 24 | 
4 files changed, 39 insertions, 35 deletions
diff --git a/lisiblepng/meson.build b/lisiblepng/meson.build index 22510fe..ae70175 100644 --- a/lisiblepng/meson.build +++ b/lisiblepng/meson.build @@ -1,6 +1,10 @@  cc = meson.get_compiler('c')  m_dep = cc.find_library('m', required: true) +if get_option('buildtype').startswith('debug') +  add_project_arguments('-DLPNG_DEBUG_LOG', language: ['c']) +endif +  lisiblepng_incdir = include_directories('src/')  lisiblepng_lib = library('lisiblepng', 'src/lisiblepng.c', 'src/lisiblepng/deflate.c', 'src/lisiblepng/bitstream.c', dependencies: [m_dep])  lisiblepng_dep = declare_dependency(include_directories: lisiblepng_incdir, link_with: [lisiblepng_lib], dependencies: [m_dep]) diff --git a/lisiblepng/src/lisiblepng/bitstream.c b/lisiblepng/src/lisiblepng/bitstream.c index e7ddb79..83e70c6 100644 --- a/lisiblepng/src/lisiblepng/bitstream.c +++ b/lisiblepng/src/lisiblepng/bitstream.c @@ -10,44 +10,40 @@ void Bitstream_init(Bitstream *bitstream, const uint8_t *data,    ASSERT(data != NULL);    bitstream->data = data;    bitstream->data_size = data_size; -  bitstream->current_byte_index = 0; -  bitstream->current_bit_offset = 0; +  bitstream->byte_offset = 0; +  bitstream->bit_index = 0;  }  void bitstream_advance(Bitstream *bitstream, size_t bit_count) {    ASSERT(bitstream != NULL); -  uint8_t current_bit = bitstream->current_bit_offset; -  bitstream->current_byte_index = -      bitstream->current_byte_index + (current_bit + bit_count) / 8; -  bitstream->current_bit_offset = (current_bit + bit_count) % 8; +  uint8_t current_bit = bitstream->bit_index; +  bitstream->byte_offset = +      bitstream->byte_offset + (current_bit + bit_count) / 8; +  bitstream->bit_index = (current_bit + bit_count) % 8;  }  void Bitstream_skip(Bitstream *bitstream, size_t bit_count) {    ASSERT(bitstream != NULL);    bitstream_advance(bitstream, bit_count);  } -  uint16_t Bitstream_next_bits(Bitstream *bitstream, int bit_count) {    ASSERT(bitstream != NULL);    ASSERT(bit_count <= 16); -  ASSERT((bitstream->current_bit_offset + (size_t)bit_count) / 8 <= +  ASSERT((bitstream->bit_index + bit_count - 1) / 8 + bitstream->byte_offset <           bitstream->data_size); -  int bit_to_read = bit_count; -  uint16_t val = bitstream->data[bitstream->current_byte_index] >> -                 bitstream->current_bit_offset; - -  size_t bit_read = MIN(bit_count, 8 - bitstream->current_bit_offset); -  bitstream_advance(bitstream, bit_read); -  bit_to_read -= bit_read; -  while (bit_to_read > 0) { -    val |= (bitstream->data[bitstream->current_byte_index] >> -            bitstream->current_bit_offset) -           << bit_read; -    bit_read = MIN(bit_to_read, 8 - bitstream->current_bit_offset); -    bitstream_advance(bitstream, bit_read); -    bit_to_read -= bit_read; +  uint16_t val = 0; +  int bits_collected = 0; +  while (bits_collected < bit_count) { +    int bits_in_current_byte = 8 - bitstream->bit_index; +    int bits_to_extract = MIN(bit_count - bits_collected, bits_in_current_byte); +    uint16_t extracted_bits = +        (bitstream->data[bitstream->byte_offset] >> bitstream->bit_index) & +        ((1 << bits_to_extract) - 1); +    val |= extracted_bits << bits_collected; +    bits_collected += bits_to_extract; +    bitstream_advance(bitstream, bits_to_extract);    } -  return (val & ((1 << bit_count) - 1)); +  return val;  } diff --git a/lisiblepng/src/lisiblepng/bitstream.h b/lisiblepng/src/lisiblepng/bitstream.h index 72d8295..2cb4fdc 100644 --- a/lisiblepng/src/lisiblepng/bitstream.h +++ b/lisiblepng/src/lisiblepng/bitstream.h @@ -8,8 +8,8 @@ typedef struct {    const uint8_t *data;    size_t data_size; -  size_t current_byte_index; -  uint8_t current_bit_offset; +  size_t byte_offset; +  uint8_t bit_index;  } Bitstream;  void Bitstream_init(Bitstream *bitstream, const uint8_t *data, diff --git a/lisiblepng/src/lisiblepng/deflate.c b/lisiblepng/src/lisiblepng/deflate.c index 5b33b1d..36073c6 100644 --- a/lisiblepng/src/lisiblepng/deflate.c +++ b/lisiblepng/src/lisiblepng/deflate.c @@ -71,7 +71,7 @@ void OutputBuffer_expand(OutputBuffer *output_buffer) {    output_buffer->cap = new_cap;  } -void OutputBuffer_push(OutputBuffer *output_buffer, char byte) { +void OutputBuffer_push(OutputBuffer *output_buffer, uint8_t byte) {    ASSERT(output_buffer != NULL);    if (output_buffer->len == output_buffer->cap) {      OutputBuffer_expand(output_buffer); @@ -196,9 +196,13 @@ bool deflate_decompress_(Bitstream *bitstream,        return false;      }      if (symbol < 256) { -      OutputBuffer_push(output, (char)symbol); +      OutputBuffer_push(output, symbol);      } else if (symbol > 256) {        symbol -= 257; +      if (symbol >= 29) { +        return false; +      } +        int length = length_size_base[symbol] +                     Bitstream_next_bits(bitstream, length_extra_bits[symbol]);        symbol = huffman_table_decode(distance_table->symbols, @@ -207,14 +211,13 @@ bool deflate_decompress_(Bitstream *bitstream,          return false;        } -      int distance = -          distance_offset_base[symbol] + +      int distance_increment =            Bitstream_next_bits(bitstream, distance_extra_bits[symbol]); -      while (length > 0) { +      unsigned distance = distance_offset_base[symbol] + distance_increment; +      while (length--) {          size_t output_buffer_length = OutputBuffer_length(output); -        OutputBuffer_push( -            output, (char)output->buffer[output_buffer_length - distance]); -        length--; +        OutputBuffer_push(output, +                          output->buffer[output_buffer_length - distance]);        }      }    } @@ -230,6 +233,7 @@ bool deflate_decompress(Bitstream *bitstream, OutputBuffer *output) {    while (!b_final) {      LPNG_LOG_DBG0("Parse deflate block");      b_final = Bitstream_next_bits(bitstream, BFINAL_LENGTH_BITS); +    LPNG_LOG_DBG("Final block: %d", b_final);      const uint8_t b_type = Bitstream_next_bits(bitstream, BTYPE_LENGTH_BITS);      if (b_type == DeflateBlockType_NoCompression) {        LPNG_LOG_ERR0("Uncompressed deflate blocks aren't supported"); @@ -391,8 +395,8 @@ uint8_t *zlib_decompress(const uint8_t *compressed_data_buffer,      return NULL;    } -  size_t adler32_offset = bitstream.current_byte_index; -  if (bitstream.current_bit_offset % 8 != 0) { +  size_t adler32_offset = bitstream.byte_offset; +  if (bitstream.bit_index % 8 != 0) {      adler32_offset++;    }  | 
