diff options
Diffstat (limited to 'decoder.h')
-rw-r--r-- | decoder.h | 48 |
1 files changed, 27 insertions, 21 deletions
@@ -1,5 +1,5 @@ /* Clzip - LZMA lossless data compressor - Copyright (C) 2010-2015 Antonio Diaz Diaz. + Copyright (C) 2010-2016 Antonio Diaz Diaz. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -60,7 +60,8 @@ static inline void Rd_reset_member_position( struct Range_decoder * const rdec ) static inline uint8_t Rd_get_byte( struct Range_decoder * const rdec ) { - if( Rd_finished( rdec ) ) return 0xAA; /* make code != 0 */ + /* 0xFF avoids decoder error if member is truncated at EOS marker */ + if( Rd_finished( rdec ) ) return 0xFF; return rdec->buffer[rdec->pos++]; } @@ -232,12 +233,12 @@ struct LZ_decoder unsigned long long partial_data_pos; struct Range_decoder * rdec; unsigned dictionary_size; - int buffer_size; uint8_t * buffer; /* output buffer */ - int pos; /* current pos in buffer */ - int stream_pos; /* first byte not yet written to file */ + unsigned pos; /* current pos in buffer */ + unsigned stream_pos; /* first byte not yet written to file */ uint32_t crc; int outfd; /* output file descriptor */ + bool pos_wrapped; Bit_model bm_literal[1<<literal_context_bits][0x300]; Bit_model bm_match[states][pos_states]; @@ -258,56 +259,61 @@ void LZd_flush_data( struct LZ_decoder * const d ); static inline uint8_t LZd_peek_prev( const struct LZ_decoder * const d ) { - const int i = ( ( d->pos > 0 ) ? d->pos : d->buffer_size ) - 1; + const unsigned i = ( ( d->pos > 0 ) ? d->pos : d->dictionary_size ) - 1; return d->buffer[i]; } static inline uint8_t LZd_peek( const struct LZ_decoder * const d, - const int distance ) + const unsigned distance ) { - int i = d->pos - distance - 1; - if( i < 0 ) i += d->buffer_size; + unsigned i = d->pos - distance - 1; + if( d->pos <= distance ) i += d->dictionary_size; return d->buffer[i]; } static inline void LZd_put_byte( struct LZ_decoder * const d, const uint8_t b ) { d->buffer[d->pos] = b; - if( ++d->pos >= d->buffer_size ) LZd_flush_data( d ); + if( ++d->pos >= d->dictionary_size ) LZd_flush_data( d ); } static inline void LZd_copy_block( struct LZ_decoder * const d, - const int distance, int len ) + const unsigned distance, unsigned len ) { - int i = d->pos - distance - 1; - if( i < 0 ) i += d->buffer_size; - if( len < d->buffer_size - max( d->pos, i ) && len <= abs( d->pos - i ) ) + unsigned i = d->pos - distance - 1; + bool fast; + if( d->pos <= distance ) + { i += d->dictionary_size; + fast = ( len <= d->dictionary_size - i && len <= i - d->pos ); } + else + fast = ( len < d->dictionary_size - d->pos && len <= d->pos - i ); + if( fast ) /* no wrap, no overlap */ { - memcpy( d->buffer + d->pos, d->buffer + i, len ); /* no wrap, no overlap */ + memcpy( d->buffer + d->pos, d->buffer + i, len ); d->pos += len; } else for( ; len > 0; --len ) { d->buffer[d->pos] = d->buffer[i]; - if( ++d->pos >= d->buffer_size ) LZd_flush_data( d ); - if( ++i >= d->buffer_size ) i = 0; + if( ++d->pos >= d->dictionary_size ) LZd_flush_data( d ); + if( ++i >= d->dictionary_size ) i = 0; } } static inline bool LZd_init( struct LZ_decoder * const d, struct Range_decoder * const rde, - const int dict_size, const int ofd ) + const unsigned dict_size, const int ofd ) { d->partial_data_pos = 0; d->rdec = rde; d->dictionary_size = dict_size; - d->buffer_size = max( 65536U, d->dictionary_size ); - d->buffer = (uint8_t *)malloc( d->buffer_size ); + d->buffer = (uint8_t *)malloc( d->dictionary_size ); if( !d->buffer ) return false; d->pos = 0; d->stream_pos = 0; d->crc = 0xFFFFFFFFU; d->outfd = ofd; + d->pos_wrapped = false; Bm_array_init( d->bm_literal[0], (1 << literal_context_bits) * 0x300 ); Bm_array_init( d->bm_match[0], states * pos_states ); @@ -321,7 +327,7 @@ static inline bool LZd_init( struct LZ_decoder * const d, Bm_array_init( d->bm_align, dis_align_size ); Lm_init( &d->match_len_model ); Lm_init( &d->rep_len_model ); - d->buffer[d->buffer_size-1] = 0; /* prev_byte of first byte */ + d->buffer[d->dictionary_size-1] = 0; /* prev_byte of first byte */ return true; } |