Adding upstream version 0.7.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
64ab85d0eb
commit
2c6d5ecc7e
8 changed files with 65 additions and 59 deletions
46
lzd.cc
46
lzd.cc
|
@ -1,5 +1,5 @@
|
|||
/* Lzd - Educational decompressor for lzip files
|
||||
Copyright (C) 2013, 2014 Antonio Diaz Diaz.
|
||||
/* Lzd - Educational decompressor for the lzip format
|
||||
Copyright (C) 2013-2015 Antonio Diaz Diaz.
|
||||
|
||||
This program is free software: you have unlimited permission
|
||||
to copy, distribute and modify it.
|
||||
|
@ -241,7 +241,7 @@ class LZ_decoder
|
|||
|
||||
void flush_data();
|
||||
|
||||
uint8_t get_byte( const unsigned distance ) const
|
||||
uint8_t peek( const unsigned distance ) const
|
||||
{
|
||||
unsigned i = pos - distance - 1;
|
||||
if( pos <= distance ) i += dictionary_size;
|
||||
|
@ -255,7 +255,7 @@ class LZ_decoder
|
|||
}
|
||||
|
||||
public:
|
||||
LZ_decoder( const unsigned dict_size )
|
||||
explicit LZ_decoder( const unsigned dict_size )
|
||||
:
|
||||
partial_data_pos( 0 ),
|
||||
dictionary_size( dict_size ),
|
||||
|
@ -282,7 +282,7 @@ void LZ_decoder::flush_data()
|
|||
crc32.update_buf( crc_, buffer + stream_pos, size );
|
||||
errno = 0;
|
||||
if( std::fwrite( buffer + stream_pos, 1, size, stdout ) != size )
|
||||
{ std::fprintf( stderr, "Write error: %s.\n", std::strerror( errno ) );
|
||||
{ std::fprintf( stderr, "Write error: %s\n", std::strerror( errno ) );
|
||||
std::exit( 1 ); }
|
||||
if( pos >= dictionary_size ) { partial_data_pos += pos; pos = 0; }
|
||||
stream_pos = pos;
|
||||
|
@ -315,16 +315,16 @@ bool LZ_decoder::decode_member() // Returns false if error
|
|||
const int pos_state = data_position() & pos_state_mask;
|
||||
if( rdec.decode_bit( bm_match[state()][pos_state] ) == 0 ) // 1st bit
|
||||
{
|
||||
const uint8_t prev_byte = get_byte( 0 );
|
||||
const uint8_t prev_byte = peek( 0 );
|
||||
const int literal_state = prev_byte >> ( 8 - literal_context_bits );
|
||||
Bit_model * const bm = bm_literal[literal_state];
|
||||
if( state.is_char() )
|
||||
put_byte( rdec.decode_tree( bm, 8 ) );
|
||||
else
|
||||
put_byte( rdec.decode_matched( bm, get_byte( rep0 ) ) );
|
||||
put_byte( rdec.decode_matched( bm, peek( rep0 ) ) );
|
||||
state.set_char();
|
||||
}
|
||||
else
|
||||
else // match or repeated match
|
||||
{
|
||||
int len;
|
||||
if( rdec.decode_bit( bm_rep[state()] ) != 0 ) // 2nd bit
|
||||
|
@ -348,12 +348,12 @@ bool LZ_decoder::decode_member() // Returns false if error
|
|||
else
|
||||
{
|
||||
if( rdec.decode_bit( bm_len[state()][pos_state] ) == 0 ) // 4th bit
|
||||
{ state.set_short_rep(); put_byte( get_byte( rep0 ) ); continue; }
|
||||
{ state.set_short_rep(); put_byte( peek( rep0 ) ); continue; }
|
||||
}
|
||||
state.set_rep();
|
||||
len = min_match_len + rdec.decode_len( rep_len_model, pos_state );
|
||||
}
|
||||
else
|
||||
else // match
|
||||
{
|
||||
rep3 = rep2; rep2 = rep1; rep1 = rep0;
|
||||
len = min_match_len + rdec.decode_len( match_len_model, pos_state );
|
||||
|
@ -372,7 +372,7 @@ bool LZ_decoder::decode_member() // Returns false if error
|
|||
{
|
||||
rep0 += rdec.decode( direct_bits - dis_align_bits ) << dis_align_bits;
|
||||
rep0 += rdec.decode_tree_reversed( bm_align, dis_align_bits );
|
||||
if( rep0 == 0xFFFFFFFFU ) // Marker found
|
||||
if( rep0 == 0xFFFFFFFFU ) // marker found
|
||||
{
|
||||
flush_data();
|
||||
return ( len == min_match_len ); // End Of Stream marker
|
||||
|
@ -383,7 +383,7 @@ bool LZ_decoder::decode_member() // Returns false if error
|
|||
if( rep0 >= dictionary_size || rep0 >= data_position() )
|
||||
{ flush_data(); return false; }
|
||||
}
|
||||
for( int i = 0; i < len; ++i ) put_byte( get_byte( rep0 ) );
|
||||
for( int i = 0; i < len; ++i ) put_byte( peek( rep0 ) );
|
||||
}
|
||||
}
|
||||
flush_data();
|
||||
|
@ -395,14 +395,14 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
if( argc > 1 )
|
||||
{
|
||||
std::printf( "Lzd %s - Educational decompressor for lzip files.\n",
|
||||
std::printf( "Lzd %s - Educational decompressor for the lzip format.\n",
|
||||
PROGVERSION );
|
||||
std::printf( "Study the source to learn how a lzip decompressor works.\n"
|
||||
"See the lzip manual for an explanation of the code.\n"
|
||||
"It is not safe to use lzd for any real work.\n"
|
||||
"\nUsage: %s < file.lz > file\n", argv[0] );
|
||||
std::printf( "Lzd decompresses from standard input to standard output.\n"
|
||||
"\nCopyright (C) 2014 Antonio Diaz Diaz.\n"
|
||||
"\nCopyright (C) 2015 Antonio Diaz Diaz.\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"
|
||||
"Report bugs to lzip-bug@nongnu.org\n"
|
||||
|
@ -419,28 +419,22 @@ int main( const int argc, const char * const argv[] )
|
|||
{
|
||||
File_header header;
|
||||
for( int i = 0; i < 6; ++i ) header[i] = std::getc( stdin );
|
||||
if( std::feof( stdin ) || std::memcmp( header, "LZIP", 4 ) != 0 )
|
||||
if( std::feof( stdin ) || std::memcmp( header, "LZIP\x01", 5 ) != 0 )
|
||||
{
|
||||
if( first_member )
|
||||
{ std::fprintf( stderr, "Bad magic number (file not in lzip format)\n" );
|
||||
{ std::fputs( "Bad magic number (file not in lzip format).\n", stderr );
|
||||
return 2; }
|
||||
break;
|
||||
}
|
||||
if( header[4] != 1 )
|
||||
{
|
||||
std::fprintf( stderr, "Version %d member format not supported.\n",
|
||||
header[4] );
|
||||
return 2;
|
||||
}
|
||||
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::fprintf( stderr, "Invalid dictionary size in member header\n" );
|
||||
{ std::fputs( "Invalid dictionary size in member header.\n", stderr );
|
||||
return 2; }
|
||||
|
||||
LZ_decoder decoder( dict_size );
|
||||
if( !decoder.decode_member() )
|
||||
{ std::fprintf( stderr, "Data error\n" ); return 2; }
|
||||
{ std::fputs( "Data error\n", stderr ); return 2; }
|
||||
|
||||
File_trailer trailer;
|
||||
for( int i = 0; i < 20; ++i ) trailer[i] = std::getc( stdin );
|
||||
|
@ -449,11 +443,11 @@ int main( const int argc, const char * const argv[] )
|
|||
unsigned long long data_size = 0;
|
||||
for( int i = 11; i >= 4; --i ) { data_size <<= 8; data_size += trailer[i]; }
|
||||
if( crc != decoder.crc() || data_size != decoder.data_position() )
|
||||
{ std::fprintf( stderr, "CRC error\n" ); return 2; }
|
||||
{ std::fputs( "CRC error\n", stderr ); return 2; }
|
||||
}
|
||||
|
||||
if( std::fclose( stdout ) != 0 )
|
||||
{ std::fprintf( stderr, "Can't close stdout: %s.\n", std::strerror( errno ) );
|
||||
{ std::fprintf( stderr, "Can't close stdout: %s\n", std::strerror( errno ) );
|
||||
return 1; }
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue