diff options
Diffstat (limited to 'lzd.cc')
-rw-r--r-- | lzd.cc | 55 |
1 files changed, 29 insertions, 26 deletions
@@ -1,5 +1,5 @@ /* Lzd - Educational decompressor for the lzip format - Copyright (C) 2013-2022 Antonio Diaz Diaz. + Copyright (C) 2013-2024 Antonio Diaz Diaz. This program is free software. Redistribution and use in source and binary forms, with or without modification, are permitted provided @@ -18,7 +18,7 @@ */ /* Exit status: 0 for a normal exit, 1 for environmental problems - (file not found, invalid command line options, I/O errors, etc), 2 to + (file not found, invalid command-line options, I/O errors, etc), 2 to indicate a corrupt or invalid input file. */ @@ -130,10 +130,11 @@ public: const CRC32 crc32; -typedef uint8_t Lzip_header[6]; // 0-3 magic bytes - // 4 version - // 5 coded dictionary size -typedef uint8_t Lzip_trailer[20]; +enum { header_size = 6, trailer_size = 20 }; +typedef uint8_t Lzip_header[header_size]; // 0-3 magic bytes + // 4 version + // 5 coded dictionary size +typedef uint8_t Lzip_trailer[trailer_size]; // 0-3 CRC32 of the uncompressed data // 4-11 size of the uncompressed data // 12-19 member size including header and trailer @@ -145,7 +146,8 @@ class Range_decoder uint32_t range; public: - Range_decoder() : member_pos( 6 ), code( 0 ), range( 0xFFFFFFFFU ) + Range_decoder() + : member_pos( header_size ), code( 0 ), range( 0xFFFFFFFFU ) { get_byte(); // discard first byte of the LZMA stream for( int i = 0; i < 4; ++i ) code = ( code << 8 ) | get_byte(); @@ -168,9 +170,9 @@ public: return symbol; } - unsigned decode_bit( Bit_model & bm ) + bool decode_bit( Bit_model & bm ) { - unsigned symbol; + bool symbol; const uint32_t bound = ( range >> bit_model_total_bits ) * bm.probability; if( code < bound ) { @@ -216,8 +218,8 @@ public: unsigned symbol = 1; for( int i = 7; i >= 0; --i ) { - const unsigned match_bit = ( match_byte >> i ) & 1; - const unsigned bit = decode_bit( bm[symbol+(match_bit<<8)+0x100] ); + const bool match_bit = ( match_byte >> i ) & 1; + const bool bit = decode_bit( bm[symbol+(match_bit<<8)+0x100] ); symbol = ( symbol << 1 ) | bit; if( match_bit != bit ) { @@ -232,11 +234,12 @@ public: unsigned decode_len( Len_model & lm, const int pos_state ) { if( decode_bit( lm.choice1 ) == 0 ) - return decode_tree( lm.bm_low[pos_state], len_low_bits ); + return min_match_len + + decode_tree( lm.bm_low[pos_state], len_low_bits ); if( decode_bit( lm.choice2 ) == 0 ) - return len_low_symbols + + return min_match_len + len_low_symbols + decode_tree( lm.bm_mid[pos_state], len_mid_bits ); - return len_low_symbols + len_mid_symbols + + return min_match_len + len_low_symbols + len_mid_symbols + decode_tree( lm.bm_high, len_high_bits ); } }; @@ -371,12 +374,12 @@ bool LZ_decoder::decode_member() // Return false if error rep0 = distance; } state.set_rep(); - len = min_match_len + rdec.decode_len( rep_len_model, pos_state ); + len = rdec.decode_len( rep_len_model, pos_state ); } else // match { rep3 = rep2; rep2 = rep1; rep1 = rep0; - len = min_match_len + rdec.decode_len( match_len_model, pos_state ); + len = rdec.decode_len( match_len_model, pos_state ); const int len_state = std::min( len - min_match_len, len_states - 1 ); rep0 = rdec.decode_tree( bm_dis_slot[len_state], dis_slot_bits ); if( rep0 >= start_dis_model ) @@ -395,7 +398,7 @@ bool LZ_decoder::decode_member() // Return false if error if( rep0 == 0xFFFFFFFFU ) // marker found { flush_data(); - return ( len == min_match_len ); // End Of Stream marker + return len == min_match_len; // End Of Stream marker } } } @@ -420,10 +423,10 @@ int main( const int argc, const char * const argv[] ) "See the lzip manual for an explanation of the code.\n" "\nUsage: %s [-d] < file.lz > file\n" "Lzd decompresses from standard input to standard output.\n" - "\nCopyright (C) 2022 Antonio Diaz Diaz.\n" + "\nCopyright (C) 2024 Antonio Diaz Diaz.\n" "License 2-clause BSD.\n" - "This is free software: you are free to change and redistribute it.\n" - "There is NO WARRANTY, to the extent permitted by law.\n" + "This is free software: you are free to change and redistribute " + "it.\nThere is NO WARRANTY, to the extent permitted by law.\n" "Report bugs to lzip-bug@nongnu.org\n" "Lzd home page: http://www.nongnu.org/lzip/lzd.html\n", PROGVERSION, argv[0] ); @@ -437,8 +440,8 @@ int main( const int argc, const char * const argv[] ) for( bool first_member = true; ; first_member = false ) { - Lzip_header header; // verify header - for( int i = 0; i < 6; ++i ) header[i] = std::getc( stdin ); + Lzip_header header; // check header + for( int i = 0; i < header_size; ++i ) header[i] = std::getc( stdin ); if( std::feof( stdin ) || std::memcmp( header, "LZIP\x01", 5 ) != 0 ) { if( first_member ) @@ -449,15 +452,15 @@ int main( const int argc, const char * const argv[] ) unsigned dict_size = 1 << ( header[5] & 0x1F ); dict_size -= ( dict_size / 16 ) * ( ( header[5] >> 5 ) & 7 ); if( dict_size < min_dictionary_size || dict_size > max_dictionary_size ) - { std::fputs( "Invalid dictionary size in member header.\n", stderr ); - return 2; } + { std::fputs( "Invalid dictionary size in member header.\n", + stderr ); return 2; } LZ_decoder decoder( dict_size ); // decode LZMA stream if( !decoder.decode_member() ) { std::fputs( "Data error\n", stderr ); return 2; } - Lzip_trailer trailer; // verify trailer - for( int i = 0; i < 20; ++i ) trailer[i] = decoder.get_byte(); + Lzip_trailer trailer; // check trailer + for( int i = 0; i < trailer_size; ++i ) trailer[i] = decoder.get_byte(); int retval = 0; unsigned crc = 0; for( int i = 3; i >= 0; --i ) crc = ( crc << 8 ) + trailer[i]; |