summaryrefslogtreecommitdiffstats
path: root/decoder.h
diff options
context:
space:
mode:
Diffstat (limited to 'decoder.h')
-rw-r--r--decoder.h98
1 files changed, 40 insertions, 58 deletions
diff --git a/decoder.h b/decoder.h
index 212c62f..36090c5 100644
--- a/decoder.h
+++ b/decoder.h
@@ -15,74 +15,57 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-class Input_buffer
+class Range_decoder
{
- enum { buffer_size = 65536 };
- uint8_t * const buffer;
+ enum { buffer_size = 16384 };
+ long long partial_member_pos;
+ uint8_t * const buffer; // input buffer
int pos;
int stream_pos; // when reached, a new block must be read
- const int ides_; // input file descriptor
+ uint32_t code;
+ uint32_t range;
+ const int infd_; // input file descriptor
bool at_stream_end;
bool read_block();
public:
- Input_buffer( const int ides )
+ Range_decoder( const int infd )
:
+ partial_member_pos( 0 ),
buffer( new uint8_t[buffer_size] ),
pos( 0 ),
stream_pos( 0 ),
- ides_( ides ),
+ code( 0 ),
+ range( 0xFFFFFFFFU ),
+ infd_( infd ),
at_stream_end( false ) {}
- ~Input_buffer() { delete[] buffer; }
+ ~Range_decoder() { delete[] buffer; }
+ bool code_is_zero() const throw() { return ( code == 0 ); }
bool finished() const throw() { return at_stream_end && pos >= stream_pos; }
+ long long member_position() const throw()
+ { return partial_member_pos + pos; }
+ void reset_member_position() throw()
+ { partial_member_pos = -pos; }
uint8_t get_byte()
{
if( pos >= stream_pos && !read_block() ) return 0;
return buffer[pos++];
}
- };
-
-
-class Range_decoder
- {
- mutable long long member_pos;
- uint32_t code;
- uint32_t range;
- Input_buffer & ibuf;
-
-public:
- Range_decoder( const int header_size, Input_buffer & buf )
- :
- member_pos( header_size ),
- code( 0 ),
- range( 0xFFFFFFFF ),
- ibuf( buf )
- { for( int i = 0; i < 5; ++i ) code = (code << 8) | get_byte(); }
-
- bool code_is_zero() const throw() { return ( code == 0 ); }
- bool finished() const throw() { return ibuf.finished(); }
- long long member_position() const throw() { return member_pos; }
-
- uint8_t get_byte() const
- {
- ++member_pos;
- return ibuf.get_byte();
- }
- void reload() throw()
+ void load() throw()
{
code = 0;
- range = 0xFFFFFFFF;
+ range = 0xFFFFFFFFU;
for( int i = 0; i < 5; ++i ) code = (code << 8) | get_byte();
}
void normalize()
{
- if( range <= 0x00FFFFFF )
+ if( range <= 0x00FFFFFFU )
{ range <<= 8; code = (code << 8) | get_byte(); }
}
@@ -92,7 +75,7 @@ public:
for( int i = num_bits; i > 0; --i )
{
symbol <<= 1;
- if( range <= 0x00FFFFFF )
+ if( range <= 0x00FFFFFFU )
{
range <<= 7; code = (code << 8) | get_byte();
if( code >= range ) { code -= range; symbol |= 1; }
@@ -148,16 +131,16 @@ public:
int decode_matched( Bit_model bm[], const int match_byte )
{
- Bit_model *bm1 = bm + 0x100;
+ Bit_model * const bm1 = bm + 0x100;
int symbol = 1;
- for( int i = 1; i <= 8; ++i )
+ for( int i = 7; i >= 0; --i )
{
- const int match_bit = ( match_byte << i ) & 0x100;
- const int bit = decode_bit( bm1[match_bit+symbol] );
+ const int match_bit = ( match_byte >> i ) & 1;
+ const int bit = decode_bit( bm1[(match_bit<<8)+symbol] );
symbol = ( symbol << 1 ) | bit;
- if( ( match_bit && !bit ) || ( !match_bit && bit ) )
+ if( match_bit != bit )
{
- while( ++i <= 8 )
+ while( --i >= 0 )
symbol = ( symbol << 1 ) | decode_bit( bm[symbol] );
break;
}
@@ -193,30 +176,30 @@ class Literal_decoder
{
Bit_model bm_literal[1<<literal_context_bits][0x300];
- int state( const int prev_byte ) const throw()
+ int lstate( const int prev_byte ) const throw()
{ return ( prev_byte >> ( 8 - literal_context_bits ) ); }
public:
uint8_t decode( Range_decoder & range_decoder, const uint8_t prev_byte )
- { return range_decoder.decode_tree( bm_literal[state(prev_byte)], 8 ); }
+ { return range_decoder.decode_tree( bm_literal[lstate(prev_byte)], 8 ); }
uint8_t decode_matched( Range_decoder & range_decoder,
const uint8_t prev_byte, const uint8_t match_byte )
- { return range_decoder.decode_matched( bm_literal[state(prev_byte)], match_byte ); }
+ { return range_decoder.decode_matched( bm_literal[lstate(prev_byte)], match_byte ); }
};
class LZ_decoder
{
long long partial_data_pos;
- const int format_version;
+ const int member_version;
const int dictionary_size;
const int buffer_size;
uint8_t * const buffer;
int pos;
int stream_pos; // first byte not yet written to file
uint32_t crc_;
- const int odes_; // output file descriptor
+ const int outfd_; // output file descriptor
Bit_model bm_match[State::states][pos_states];
Bit_model bm_rep[State::states];
@@ -228,7 +211,7 @@ class LZ_decoder
Bit_model bm_dis[modeled_distances-end_dis_model];
Bit_model bm_align[dis_align_size];
- Range_decoder range_decoder;
+ Range_decoder & range_decoder;
Len_decoder len_decoder;
Len_decoder rep_match_len_decoder;
Literal_decoder literal_decoder;
@@ -267,24 +250,23 @@ class LZ_decoder
bool verify_trailer( const Pretty_print & pp ) const;
public:
- LZ_decoder( const File_header & header, Input_buffer & ibuf, const int odes )
+ LZ_decoder( const File_header & header, Range_decoder & rdec, const int outfd )
:
partial_data_pos( 0 ),
- format_version( header.version ),
+ member_version( header.version() ),
dictionary_size( header.dictionary_size() ),
buffer_size( std::max( 65536, dictionary_size ) ),
buffer( new uint8_t[buffer_size] ),
pos( 0 ),
stream_pos( 0 ),
- crc_( 0xFFFFFFFF ),
- odes_( odes ),
- range_decoder( sizeof header, ibuf ),
- literal_decoder()
+ crc_( 0xFFFFFFFFU ),
+ outfd_( outfd ),
+ range_decoder( rdec )
{ buffer[buffer_size-1] = 0; } // prev_byte of first_byte
~LZ_decoder() { delete[] buffer; }
- uint32_t crc() const throw() { return crc_ ^ 0xFFFFFFFF; }
+ uint32_t crc() const throw() { return crc_ ^ 0xFFFFFFFFU; }
int decode_member( const Pretty_print & pp );
long long member_position() const throw()