diff options
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | Makefile.in | 14 | ||||
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | README | 10 | ||||
-rw-r--r-- | arg_parser.cc | 12 | ||||
-rw-r--r-- | arg_parser.h | 22 | ||||
-rwxr-xr-x | configure | 56 | ||||
-rw-r--r-- | decoder.cc | 8 | ||||
-rw-r--r-- | decoder.h | 38 | ||||
-rw-r--r-- | doc/lzip.1 | 2 | ||||
-rw-r--r-- | doc/lzip.info | 24 | ||||
-rw-r--r-- | doc/lzip.texinfo | 18 | ||||
-rw-r--r-- | encoder.cc | 33 | ||||
-rw-r--r-- | encoder.h | 111 | ||||
-rw-r--r-- | fast_encoder.cc | 4 | ||||
-rw-r--r-- | fast_encoder.h | 4 | ||||
-rw-r--r-- | lzip.h | 78 | ||||
-rw-r--r-- | main.cc | 44 | ||||
-rwxr-xr-x | testsuite/check.sh | 9 | ||||
-rw-r--r-- | testsuite/unzcrash.cc | 354 |
20 files changed, 239 insertions, 621 deletions
@@ -1,17 +1,15 @@ -2012-01-05 Antonio Diaz Diaz <ant_diaz@teleline.es> +2012-02-24 Antonio Diaz Diaz <ant_diaz@teleline.es> - * Version 1.13-rc2 released. + * Version 1.13 released. + * Lziprecover has been moved to its own package. + * main.cc (close_and_set_permissions): Inability to change output + file attributes has been downgraded from error to warning. * Compression time of option '-0' has been reduced by 2%. * Reorganization of the compression code. * Small change in '--help' output and man page. * Changed quote characters in messages as advised by GNU Standards. - -2011-11-12 Antonio Diaz Diaz <ant_diaz@teleline.es> - - * Version 1.13-rc1 released. - * Lziprecover has been moved to its own package. - * main.cc (close_and_set_permissions): Inability to change output - file attributes has been downgraded from error to warning. + * configure: 'datadir' renamed to 'datarootdir'. + * 'testsuite/unzcrash.cc' has been moved to package 'lziprecover'. 2011-04-30 Antonio Diaz Diaz <ant_diaz@teleline.es> diff --git a/Makefile.in b/Makefile.in index 83991ef..d64b06c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -7,7 +7,6 @@ INSTALL_DIR = $(INSTALL) -d -m 755 SHELL = /bin/sh objs = arg_parser.o decoder.o encoder.o fast_encoder.o main.o -unzobjs = arg_parser.o unzcrash.o .PHONY : all install install-info install-man install-strip \ @@ -17,20 +16,14 @@ unzobjs = arg_parser.o unzcrash.o all : $(progname) $(progname) : $(objs) - $(CXX) $(LDFLAGS) -o $@ $^ + $(CXX) $(LDFLAGS) -o $@ $(objs) $(progname)_profiled : $(objs) - $(CXX) $(LDFLAGS) -pg -o $@ $^ - -unzcrash : $(unzobjs) - $(CXX) $(LDFLAGS) -o $@ $^ + $(CXX) $(LDFLAGS) -pg -o $@ $(objs) main.o : main.cc $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< -unzcrash.o : testsuite/unzcrash.cc - $(CXX) $(CPPFLAGS) $(CXXFLAGS) -DPROGVERSION=\"$(pkgversion)\" -c -o $@ $< - %.o : %.cc $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c -o $@ $< @@ -40,7 +33,6 @@ decoder.o : lzip.h decoder.h encoder.o : lzip.h encoder.h fast_encoder.o : lzip.h encoder.h fast_encoder.h main.o : arg_parser.h lzip.h decoder.h encoder.h fast_encoder.h -unzcrash.o : arg_parser.h Makefile doc : info man @@ -106,7 +98,6 @@ dist : doc $(DISTNAME)/testsuite/test.txt \ $(DISTNAME)/testsuite/test_sync.lz \ $(DISTNAME)/testsuite/test_v[01].lz \ - $(DISTNAME)/testsuite/unzcrash.cc \ $(DISTNAME)/*.h \ $(DISTNAME)/*.cc rm -f $(DISTNAME) @@ -114,7 +105,6 @@ dist : doc clean : -rm -f $(progname) $(progname)_profiled $(objs) - -rm -f unzcrash unzcrash.o distclean : clean -rm -f Makefile config.status *.tar *.tar.lz @@ -13,3 +13,6 @@ A small change has been made in the "--help" output and man page. Quote characters in messages have been changed as advised by GNU Coding Standards. + +Configure option "--datadir" has been renamed to "--datarootdir" to +follow GNU Standards. @@ -26,11 +26,11 @@ or more compressed files. The result is the concatenation of the corresponding uncompressed files. Integrity testing of concatenated compressed files is also supported. -Lzip can produce multi-member files and safely recover, with lziprecover, -the undamaged members in case of file damage. Lzip can also split the -compressed output in volumes of a given size, even when reading from -standard input. This allows the direct creation of multivolume -compressed tar archives. +Lzip can produce multi-member files and safely recover, with +lziprecover, the undamaged members in case of file damage. Lzip can also +split the compressed output in volumes of a given size, even when +reading from standard input. This allows the direct creation of +multivolume compressed tar archives. Lzip will automatically use the smallest possible dictionary size without exceeding the given limit. Keep in mind that the decompression diff --git a/arg_parser.cc b/arg_parser.cc index 27137a1..b3fd48d 100644 --- a/arg_parser.cc +++ b/arg_parser.cc @@ -56,30 +56,30 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a if( ambig && !exact ) { - error_ = "option `"; error_ += opt; error_ += "' is ambiguous"; + error_ = "option '"; error_ += opt; error_ += "' is ambiguous"; return false; } if( index < 0 ) // nothing found { - error_ = "unrecognized option `"; error_ += opt; error_ += '\''; + error_ = "unrecognized option '"; error_ += opt; error_ += '\''; return false; } ++argind; data.push_back( Record( options[index].code ) ); - if( opt[len+2] ) // `--<long_option>=<argument>' syntax + if( opt[len+2] ) // '--<long_option>=<argument>' syntax { if( options[index].has_arg == no ) { - error_ = "option `--"; error_ += options[index].name; + error_ = "option '--"; error_ += options[index].name; error_ += "' doesn't allow an argument"; return false; } if( options[index].has_arg == yes && !opt[len+3] ) { - error_ = "option `--"; error_ += options[index].name; + error_ = "option '--"; error_ += options[index].name; error_ += "' requires an argument"; return false; } @@ -91,7 +91,7 @@ bool Arg_parser::parse_long_option( const char * const opt, const char * const a { if( !arg || !arg[0] ) { - error_ = "option `--"; error_ += options[index].name; + error_ = "option '--"; error_ += options[index].name; error_ += "' requires an argument"; return false; } diff --git a/arg_parser.h b/arg_parser.h index 5d036ab..4fbd1af 100644 --- a/arg_parser.h +++ b/arg_parser.h @@ -26,12 +26,12 @@ Public License. */ -/* Arg_parser reads the arguments in `argv' and creates a number of +/* Arg_parser reads the arguments in 'argv' and creates a number of option codes, option arguments and non-option arguments. - In case of error, `error' returns a non-empty error message. + In case of error, 'error' returns a non-empty error message. - `options' is an array of `struct Option' terminated by an element + 'options' is an array of 'struct Option' terminated by an element containing a code which is zero. A null name means a short-only option. A code value outside the unsigned char range means a long-only option. @@ -40,13 +40,13 @@ were specified before all the non-option arguments for the purposes of parsing, even if the user of your program intermixed option and non-option arguments. If you want the arguments in the exact order - the user typed them, call `Arg_parser' with `in_order' = true. + the user typed them, call 'Arg_parser' with 'in_order' = true. - The argument `--' terminates all options; any following arguments are + The argument '--' terminates all options; any following arguments are treated as non-option arguments, even if they begin with a hyphen. - The syntax for optional option arguments is `-<short_option><argument>' - (without whitespace), or `--<long_option>=<argument>'. + The syntax for optional option arguments is '-<short_option><argument>' + (without whitespace), or '--<long_option>=<argument>'. */ class Arg_parser @@ -85,20 +85,20 @@ public: Arg_parser( const char * const opt, const char * const arg, const Option options[] ); - const std::string & error() const throw() { return error_; } + const std::string & error() const { return error_; } // The number of arguments parsed (may be different from argc) - int arguments() const throw() { return data.size(); } + int arguments() const { return data.size(); } // If code( i ) is 0, argument( i ) is a non-option. // Else argument( i ) is the option's argument (or empty). - int code( const int i ) const throw() + int code( const int i ) const { if( i >= 0 && i < arguments() ) return data[i].code; else return 0; } - const std::string & argument( const int i ) const throw() + const std::string & argument( const int i ) const { if( i >= 0 && i < arguments() ) return data[i].argument; else return error_; @@ -8,7 +8,7 @@ args= no_create= pkgname=lzip -pkgversion=1.13-rc2 +pkgversion=1.13 progname=lzip srctrigger=lzip.h @@ -19,10 +19,9 @@ srcdir= prefix=/usr/local exec_prefix='$(prefix)' bindir='$(exec_prefix)/bin' -datadir='$(prefix)/share' -infodir='$(datadir)/info' -mandir='$(datadir)/man' -sysconfdir='$(prefix)/etc' +datarootdir='$(prefix)/share' +infodir='$(datarootdir)/info' +mandir='$(datarootdir)/man' CXX= CPPFLAGS= CXXFLAGS='-Wall -W -O2' @@ -40,12 +39,12 @@ while [ -n "$1" ] ; do # Split out the argument for options that take them case ${option} in - *=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,'` ;; + *=*) optarg=`echo ${option} | sed -e 's,^[^=]*=,,;s,/$,,'` ;; esac # Process the options case ${option} in - --help | --he* | -h) + --help | -h) echo "Usage: configure [options]" echo echo "Options: [defaults in brackets]" @@ -55,42 +54,31 @@ while [ -n "$1" ] ; do echo " --prefix=DIR install into DIR [${prefix}]" echo " --exec-prefix=DIR base directory for arch-dependent files [${exec_prefix}]" echo " --bindir=DIR user executables directory [${bindir}]" - echo " --datadir=DIR base directory for doc and data [${datadir}]" + echo " --datarootdir=DIR base directory for doc and data [${datarootdir}]" echo " --infodir=DIR info files directory [${infodir}]" echo " --mandir=DIR man pages directory [${mandir}]" - echo " --sysconfdir=DIR read-only single-machine data directory [${sysconfdir}]" echo " CXX=COMPILER C++ compiler to use [g++]" echo " CPPFLAGS=OPTIONS command line options for the preprocessor [${CPPFLAGS}]" echo " CXXFLAGS=OPTIONS command line options for the C++ compiler [${CXXFLAGS}]" echo " LDFLAGS=OPTIONS command line options for the linker [${LDFLAGS}]" echo exit 0 ;; - --version | --ve* | -V) + --version | -V) echo "Configure script for ${pkgname} version ${pkgversion}" exit 0 ;; - --srcdir* | --sr*) - srcdir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --prefix* | --pr*) - prefix=`echo ${optarg} | sed -e 's,/$,,'` ;; - --exec-prefix* | --ex*) - exec_prefix=`echo ${optarg} | sed -e 's,/$,,'` ;; - --bindir* | --bi*) - bindir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --datadir* | --da*) - datadir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --infodir* | --inf*) - infodir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --mandir* | --ma*) - mandir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --sysconfdir* | --sy*) - sysconfdir=`echo ${optarg} | sed -e 's,/$,,'` ;; - --no-create | --no-c*) - no_create=yes ;; - - CXX=*) CXX=${optarg} ;; + --srcdir=*) srcdir=${optarg} ;; + --prefix=*) prefix=${optarg} ;; + --exec-prefix=*) exec_prefix=${optarg} ;; + --bindir=*) bindir=${optarg} ;; + --datarootdir=*) datarootdir=${optarg} ;; + --infodir=*) infodir=${optarg} ;; + --mandir=*) mandir=${optarg} ;; + --no-create) no_create=yes ;; + + CXX=*) CXX=${optarg} ;; CPPFLAGS=*) CPPFLAGS=${optarg} ;; CXXFLAGS=*) CXXFLAGS=${optarg} ;; - LDFLAGS=*) LDFLAGS=${optarg} ;; + LDFLAGS=*) LDFLAGS=${optarg} ;; --* | *=* | *-*-*) ;; *) @@ -154,10 +142,9 @@ echo "VPATH = ${srcdir}" echo "prefix = ${prefix}" echo "exec_prefix = ${exec_prefix}" echo "bindir = ${bindir}" -echo "datadir = ${datadir}" +echo "datarootdir = ${datarootdir}" echo "infodir = ${infodir}" echo "mandir = ${mandir}" -echo "sysconfdir = ${sysconfdir}" echo "CXX = ${CXX}" echo "CPPFLAGS = ${CPPFLAGS}" echo "CXXFLAGS = ${CXXFLAGS}" @@ -178,10 +165,9 @@ VPATH = ${srcdir} prefix = ${prefix} exec_prefix = ${exec_prefix} bindir = ${bindir} -datadir = ${datadir} +datarootdir = ${datarootdir} infodir = ${infodir} mandir = ${mandir} -sysconfdir = ${sysconfdir} CXX = ${CXX} CPPFLAGS = ${CPPFLAGS} CXXFLAGS = ${CXXFLAGS} @@ -34,7 +34,7 @@ const CRC32 crc32; -void Pretty_print::operator()( const char * const msg ) const throw() +void Pretty_print::operator()( const char * const msg ) const { if( verbosity_ >= 0 ) { @@ -54,7 +54,7 @@ void Pretty_print::operator()( const char * const msg ) const throw() // Returns the number of bytes really read. // If (returned value < size) and (errno == 0), means EOF was reached. // -int readblock( const int fd, uint8_t * const buf, const int size ) throw() +int readblock( const int fd, uint8_t * const buf, const int size ) { int rest = size; errno = 0; @@ -73,7 +73,7 @@ int readblock( const int fd, uint8_t * const buf, const int size ) throw() // Returns the number of bytes really written. // If (returned value < size), it is always an error. // -int writeblock( const int fd, const uint8_t * const buf, const int size ) throw() +int writeblock( const int fd, const uint8_t * const buf, const int size ) { int rest = size; errno = 0; @@ -124,7 +124,7 @@ bool LZ_decoder::verify_trailer( const Pretty_print & pp ) const const long long member_size = range_decoder.member_position() + trailer_size; bool error = false; - const int size = range_decoder.read( trailer.data, trailer_size ); + const int size = range_decoder.read_data( trailer.data, trailer_size ); if( size < trailer_size ) { error = true; @@ -29,8 +29,8 @@ class Range_decoder bool read_block(); - Range_decoder( const Range_decoder & ); - void operator=( const Range_decoder & ); + Range_decoder( const Range_decoder & ); // declared as private + void operator=( const Range_decoder & ); // declared as private public: explicit Range_decoder( const int ifd ) @@ -42,16 +42,15 @@ public: code( 0 ), range( 0xFFFFFFFFU ), infd( ifd ), - at_stream_end( false ) {} + at_stream_end( false ) + {} ~Range_decoder() { delete[] buffer; } - bool code_is_zero() const throw() { return ( code == 0 ); } + bool code_is_zero() const { return ( code == 0 ); } bool finished() { return pos >= stream_pos && !read_block(); } - long long member_position() const throw() - { return partial_member_pos + pos; } - void reset_member_position() throw() - { partial_member_pos = -pos; } + long long member_position() const { return partial_member_pos + pos; } + void reset_member_position() { partial_member_pos = -pos; } uint8_t get_byte() { @@ -59,7 +58,7 @@ public: return buffer[pos++]; } - int read( uint8_t * const outbuf, const int size ) + int read_data( uint8_t * const outbuf, const int size ) { int rest = size; while( rest > 0 && !finished() ) @@ -192,7 +191,7 @@ class Literal_decoder { Bit_model bm_literal[1<<literal_context_bits][0x300]; - int lstate( const int prev_byte ) const throw() + int lstate( const uint8_t prev_byte ) const { return ( prev_byte >> ( 8 - literal_context_bits ) ); } public: @@ -209,6 +208,7 @@ public: class LZ_decoder { long long partial_data_pos; + Range_decoder & range_decoder; const int dictionary_size; const int buffer_size; uint8_t * const buffer; // output buffer @@ -217,18 +217,17 @@ class LZ_decoder uint32_t crc_; const int outfd; // output file descriptor const int member_version; - Range_decoder & range_decoder; void flush_data(); bool verify_trailer( const Pretty_print & pp ) const; - uint8_t get_prev_byte() const throw() + uint8_t get_prev_byte() const { const int i = ( ( pos > 0 ) ? pos : buffer_size ) - 1; return buffer[i]; } - uint8_t get_byte( const int distance ) const throw() + uint8_t get_byte( const int distance ) const { int i = pos - distance - 1; if( i < 0 ) i += buffer_size; @@ -258,13 +257,14 @@ class LZ_decoder } } - LZ_decoder( const LZ_decoder & ); - void operator=( const LZ_decoder & ); + LZ_decoder( const LZ_decoder & ); // declared as private + void operator=( const LZ_decoder & ); // declared as private public: LZ_decoder( const File_header & header, Range_decoder & rdec, const int ofd ) : partial_data_pos( 0 ), + range_decoder( rdec ), dictionary_size( header.dictionary_size() ), buffer_size( std::max( 65536, dictionary_size ) ), buffer( new uint8_t[buffer_size] ), @@ -272,16 +272,14 @@ public: stream_pos( 0 ), crc_( 0xFFFFFFFFU ), outfd( ofd ), - member_version( header.version() ), - range_decoder( rdec ) + member_version( header.version() ) { buffer[buffer_size-1] = 0; } // prev_byte of first_byte ~LZ_decoder() { delete[] buffer; } - uint32_t crc() const throw() { return crc_ ^ 0xFFFFFFFFU; } + uint32_t crc() const { return crc_ ^ 0xFFFFFFFFU; } - long long data_position() const throw() - { return partial_data_pos + pos; } + long long data_position() const { return partial_data_pos + pos; } int decode_member( const Pretty_print & pp ); }; @@ -1,5 +1,5 @@ .\" DO NOT MODIFY THIS FILE! It was generated by help2man 1.37.1. -.TH LZIP "1" "January 2012" "Lzip 1.13-rc2" "User Commands" +.TH LZIP "1" "February 2012" "Lzip 1.13" "User Commands" .SH NAME Lzip \- reduces the size of files .SH SYNOPSIS diff --git a/doc/lzip.info b/doc/lzip.info index 5d2c6ec..9379eb3 100644 --- a/doc/lzip.info +++ b/doc/lzip.info @@ -11,7 +11,7 @@ File: lzip.info, Node: Top, Next: Introduction, Up: (dir) Lzip Manual *********** -This manual is for Lzip (version 1.13-rc2, 5 January 2012). +This manual is for Lzip (version 1.13, 24 February 2012). * Menu: @@ -62,8 +62,8 @@ corresponding uncompressed files. Integrity testing of concatenated compressed files is also supported. Lzip can produce multi-member files and safely recover, with -lziprecover, the undamaged members in case of file damage. Lzip can -also split the compressed output in volumes of a given size, even when +lziprecover, the undamaged members in case of file damage. Lzip can also +split the compressed output in volumes of a given size, even when reading from standard input. This allows the direct creation of multivolume compressed tar archives. @@ -389,7 +389,7 @@ File: lzip.info, Node: Examples, Next: Problems, Prev: File Format, Up: Top WARNING! Even if lzip is bug-free, other causes may result in a corrupt compressed file (bugs in the system libraries, memory errors, etc). -Therefore, if the data you are going to compress is important give the +Therefore, if the data you are going to compress is important, give the `--keep' option to lzip and do not remove the original file until you verify the compressed file with a command like `lzip -cd file.lz | cmp file -'. @@ -484,7 +484,7 @@ Concept Index * file format: File Format. (line 6) * getting help: Problems. (line 6) * introduction: Introduction. (line 6) -* invoking lzip: Invoking Lzip. (line 6) +* invoking: Invoking Lzip. (line 6) * options: Invoking Lzip. (line 6) * usage: Invoking Lzip. (line 6) * version: Invoking Lzip. (line 6) @@ -493,13 +493,13 @@ Concept Index Tag Table: Node: Top224 -Node: Introduction921 -Node: Algorithm4422 -Node: Invoking Lzip6940 -Node: File Format12292 -Node: Examples14285 -Node: Problems16231 -Node: Concept Index16753 +Node: Introduction919 +Node: Algorithm4420 +Node: Invoking Lzip6938 +Node: File Format12290 +Node: Examples14283 +Node: Problems16230 +Node: Concept Index16752 End Tag Table diff --git a/doc/lzip.texinfo b/doc/lzip.texinfo index cf7b21e..0ebc9ca 100644 --- a/doc/lzip.texinfo +++ b/doc/lzip.texinfo @@ -6,8 +6,8 @@ @finalout @c %**end of header -@set UPDATED 5 January 2012 -@set VERSION 1.13-rc2 +@set UPDATED 24 February 2012 +@set VERSION 1.13 @dircategory Data Compression @direntry @@ -81,11 +81,11 @@ or more compressed files. The result is the concatenation of the corresponding uncompressed files. Integrity testing of concatenated compressed files is also supported. -Lzip can produce multi-member files and safely recover, with lziprecover, -the undamaged members in case of file damage. Lzip can also split the -compressed output in volumes of a given size, even when reading from -standard input. This allows the direct creation of multivolume -compressed tar archives. +Lzip can produce multi-member files and safely recover, with +lziprecover, the undamaged members in case of file damage. Lzip can also +split the compressed output in volumes of a given size, even when +reading from standard input. This allows the direct creation of +multivolume compressed tar archives. The amount of memory required for compression is about 5 MiB plus 1 or 2 times the dictionary size limit (1 if input file size is less than @@ -188,7 +188,7 @@ LZMA), and Julian Seward (for bzip2's CLI and the idea of unzcrash). @node Invoking Lzip @chapter Invoking Lzip -@cindex invoking lzip +@cindex invoking @cindex options @cindex usage @cindex version @@ -417,7 +417,7 @@ safe recovery of undamaged members from multi-member files. WARNING! Even if lzip is bug-free, other causes may result in a corrupt compressed file (bugs in the system libraries, memory errors, etc). -Therefore, if the data you are going to compress is important give the +Therefore, if the data you are going to compress is important, give the @samp{--keep} option to lzip and do not remove the original file until you verify the compressed file with a command like @w{@samp{lzip -cd file.lz | cmp file -}}. @@ -84,6 +84,7 @@ Matchfinder_base::Matchfinder_base( const int before, const int dict_size, stream_pos( 0 ), at_stream_end( false ) { + for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; const int buffer_size_limit = ( dict_size * dict_factor ) + before_size + after_size; buffer_size = std::max( 65536, dict_size ); @@ -103,7 +104,6 @@ Matchfinder_base::Matchfinder_base( const int before, const int dict_size, else dictionary_size_ = dict_size; pos_limit = buffer_size; if( !at_stream_end ) pos_limit -= after_size; - for( int i = 0; i < num_prev_positions; ++i ) prev_positions[i] = -1; pos_array_size = pos_array_factor * dictionary_size_; pos_array = new( std::nothrow ) int32_t[pos_array_size]; if( !pos_array ) @@ -124,17 +124,7 @@ void Matchfinder_base::reset() } -bool Matchfinder::dec_pos( const int ahead ) throw() - { - if( ahead < 0 || pos < ahead ) return false; - pos -= ahead; - cyclic_pos -= ahead; - if( cyclic_pos < 0 ) cyclic_pos += dictionary_size_; - return true; - } - - -int Matchfinder::longest_match_len( int * const distances ) throw() +int Matchfinder::longest_match_len( int * const distances ) { int len_limit = match_len_limit_; if( len_limit > available_bytes() ) @@ -264,7 +254,7 @@ void Len_encoder::encode( Range_encoder & range_encoder, int symbol, // End Of Stream mark => (dis == 0xFFFFFFFFU, len == min_match_len) void LZ_encoder_base::full_flush( const long long data_position, - const State & state ) + const State state ) { const int pos_state = data_position & pos_state_mask; range_encoder.encode_bit( bm_match[state()][pos_state], 1 ); @@ -281,7 +271,7 @@ void LZ_encoder_base::full_flush( const long long data_position, } -void LZ_encoder::fill_align_prices() throw() +void LZ_encoder::fill_align_prices() { for( int i = 0; i < dis_align_size; ++i ) align_prices[i] = price_symbol_reversed( bm_align, i, dis_align_bits ); @@ -289,7 +279,7 @@ void LZ_encoder::fill_align_prices() throw() } -void LZ_encoder::fill_distance_prices() throw() +void LZ_encoder::fill_distance_prices() { for( int dis = start_dis_model; dis < modeled_distances; ++dis ) { @@ -327,7 +317,7 @@ void LZ_encoder::fill_distance_prices() throw() // trials[0]..trials[retval-1] contain the steps to encode. // ( trials[0].dis == -1 && trials[0].price == 1 ) means literal. int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], - const State & state ) + const State state ) { int main_len; if( longest_match_found > 0 ) // from previous call @@ -381,7 +371,7 @@ int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], const int rep_match_price = match_price + price1( bm_rep[state()] ); if( match_byte == cur_byte ) - trials[1].update( 0, 0, rep_match_price + price_rep_len1( state, pos_state ) ); + trials[1].update( 0, 0, rep_match_price + price_rep_len1( pos_state, state ) ); if( main_len < min_match_len ) { @@ -411,11 +401,10 @@ int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], for( int rep = 0; rep < num_rep_distances; ++rep ) { - const int price = rep_match_price + - price_rep( rep, state, pos_state ); + const int price = rep_match_price + price_rep( rep, pos_state, state ); for( int len = min_match_len; len <= replens[rep]; ++len ) trials[len].update( rep, 0, price + - rep_match_len_encoder.price( len, pos_state ) ); + rep_match_len_encoder.price( len, pos_state ) ); } } @@ -480,7 +469,7 @@ int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], if( match_byte == cur_byte && next_trial.dis != 0 ) next_trial.update( 0, cur, rep_match_price + - price_rep_len1( cur_trial.state, pos_state ) ); + price_rep_len1( pos_state, cur_trial.state ) ); const int len_limit = std::min( std::min( max_num_trials - 1 - cur, matchfinder.available_bytes() ), matchfinder.match_len_limit() ); @@ -495,7 +484,7 @@ int LZ_encoder::sequence_optimizer( const int reps[num_rep_distances], if( len >= min_match_len ) { const int price = rep_match_price + - price_rep( rep, cur_trial.state, pos_state ); + price_rep( rep, pos_state, cur_trial.state ); while( num_trials < cur + len ) trials[++num_trials].price = infinite_price; for( ; len >= min_match_len; --len ) @@ -23,7 +23,7 @@ class Dis_slots unsigned char data[1<<12]; public: - void init() throw() + void init() { for( int slot = 0; slot < 4; ++slot ) data[slot] = slot; for( int i = 4, size = 2, slot = 4; slot < 24; slot += 2 ) @@ -35,9 +35,9 @@ public: } } - unsigned char table( const int dis ) const throw() { return data[dis]; } + unsigned char table( const int dis ) const { return data[dis]; } - int operator[]( const uint32_t dis ) const throw() + int operator[]( const uint32_t dis ) const { if( dis < (1 << 12) ) return data[dis]; if( dis < (1 << 23) ) return data[dis>>11] + 22; @@ -53,7 +53,7 @@ class Prob_prices int data[bit_model_total >> 2]; public: - void init() throw() + void init() { const int num_bits = ( bit_model_total_bits - 2 ); int j = 1, end = 2; @@ -66,24 +66,24 @@ public: } } - int operator[]( const int probability ) const throw() + int operator[]( const int probability ) const { return data[probability >> 2]; } }; extern Prob_prices prob_prices; -inline int price0( const Bit_model & bm ) throw() +inline int price0( const Bit_model & bm ) { return prob_prices[bm.probability]; } -inline int price1( const Bit_model & bm ) throw() +inline int price1( const Bit_model & bm ) { return prob_prices[bit_model_total-bm.probability]; } -inline int price_bit( const Bit_model & bm, const int bit ) throw() +inline int price_bit( const Bit_model & bm, const int bit ) { if( bit ) return price1( bm ); else return price0( bm ); } -inline int price_symbol( const Bit_model bm[], int symbol, const int num_bits ) throw() +inline int price_symbol( const Bit_model bm[], int symbol, const int num_bits ) { int price = 0; symbol |= ( 1 << num_bits ); @@ -98,7 +98,7 @@ inline int price_symbol( const Bit_model bm[], int symbol, const int num_bits ) inline int price_symbol_reversed( const Bit_model bm[], int symbol, - const int num_bits ) throw() + const int num_bits ) { int price = 0; int model = 1; @@ -114,7 +114,7 @@ inline int price_symbol_reversed( const Bit_model bm[], int symbol, inline int price_matched( const Bit_model bm[], const int symbol, - const int match_byte ) throw() + const int match_byte ) { int price = 0; int model = 1; @@ -142,12 +142,12 @@ inline int price_matched( const Bit_model bm[], const int symbol, class Matchfinder_base { - Matchfinder_base( const Matchfinder_base & ); // declared as private - void operator=( const Matchfinder_base & ); // declared as private - bool read_block(); void normalize_pos(); + Matchfinder_base( const Matchfinder_base & ); // declared as private + void operator=( const Matchfinder_base & ); // declared as private + protected: enum { after_size = max_match_len }; // bytes to keep in buffer after pos @@ -177,15 +177,15 @@ protected: { delete[] pos_array; std::free( buffer ); delete[] prev_positions; } public: - uint8_t operator[]( const int i ) const throw() { return buffer[pos+i]; } - int available_bytes() const throw() { return stream_pos - pos; } - long long data_position() const throw() { return partial_data_pos + pos; } - int dictionary_size() const throw() { return dictionary_size_; } - bool finished() const throw() { return at_stream_end && pos >= stream_pos; } - int match_len_limit() const throw() { return match_len_limit_; } - const uint8_t * ptr_to_current_pos() const throw() { return buffer + pos; } - - int true_match_len( const int index, const int distance, int len_limit ) const throw() + uint8_t operator[]( const int i ) const { return buffer[pos+i]; } + int available_bytes() const { return stream_pos - pos; } + long long data_position() const { return partial_data_pos + pos; } + int dictionary_size() const { return dictionary_size_; } + bool finished() const { return at_stream_end && pos >= stream_pos; } + int match_len_limit() const { return match_len_limit_; } + const uint8_t * ptr_to_current_pos() const { return buffer + pos; } + + int true_match_len( const int index, const int distance, int len_limit ) const { if( index + len_limit > available_bytes() ) len_limit = available_bytes() - index; @@ -225,8 +225,16 @@ public: cycles( ( len_limit < max_match_len ) ? 16 + ( len_limit / 2 ) : 256 ) {} - bool dec_pos( const int ahead ) throw(); - int longest_match_len( int * const distances = 0 ) throw(); + bool dec_pos( const int ahead ) + { + if( ahead < 0 || pos < ahead ) return false; + pos -= ahead; + cyclic_pos -= ahead; + if( cyclic_pos < 0 ) cyclic_pos += dictionary_size_; + return true; + } + + int longest_match_len( int * const distances = 0 ); }; @@ -244,8 +252,8 @@ class Range_encoder void shift_low() { - const uint32_t carry = low >> 32; - if( low < 0xFF000000U || carry == 1 ) + const bool carry = ( low > 0xFFFFFFFFU ); + if( carry || low < 0xFF000000U ) { put_byte( cache + carry ); for( ; ff_count > 0; --ff_count ) put_byte( 0xFF + carry ); @@ -255,8 +263,8 @@ class Range_encoder low = ( low & 0x00FFFFFFU ) << 8; } - Range_encoder( const Range_encoder & ); - void operator=( const Range_encoder & ); + Range_encoder( const Range_encoder & ); // declared as private + void operator=( const Range_encoder & ); // declared as private public: explicit Range_encoder( const int ofd ) @@ -268,11 +276,12 @@ public: range( 0xFFFFFFFFU ), ff_count( 0 ), outfd( ofd ), - cache( 0 ) {} + cache( 0 ) + {} ~Range_encoder() { delete[] buffer; } - long long member_position() const throw() + long long member_position() const { return partial_member_pos + pos + ff_count; } void flush() { for( int i = 0; i < 5; ++i ) shift_low(); } @@ -371,7 +380,7 @@ class Len_encoder const int len_symbols; int counters[pos_states]; - void update_prices( const int pos_state ) throw() + void update_prices( const int pos_state ) { int * const pps = prices[pos_state]; int tmp = price0( choice1 ); @@ -401,7 +410,7 @@ public: void encode( Range_encoder & range_encoder, int symbol, const int pos_state ); - int price( const int symbol, const int pos_state ) const throw() + int price( const int symbol, const int pos_state ) const { return prices[pos_state][symbol - min_match_len]; } }; @@ -410,7 +419,7 @@ class Literal_encoder { Bit_model bm_literal[1<<literal_context_bits][0x300]; - int lstate( const uint8_t prev_byte ) const throw() + int lstate( const uint8_t prev_byte ) const { return ( prev_byte >> ( 8 - literal_context_bits ) ); } public: @@ -423,11 +432,11 @@ public: { range_encoder.encode_matched( bm_literal[lstate(prev_byte)], symbol, match_byte ); } - int price_symbol( uint8_t prev_byte, uint8_t symbol ) const throw() + int price_symbol( uint8_t prev_byte, uint8_t symbol ) const { return ::price_symbol( bm_literal[lstate(prev_byte)], symbol, 8 ); } int price_matched( uint8_t prev_byte, uint8_t symbol, - uint8_t match_byte ) const throw() + uint8_t match_byte ) const { return ::price_matched( bm_literal[lstate(prev_byte)], symbol, match_byte ); } }; @@ -458,7 +467,7 @@ protected: const int num_dis_slots; - uint32_t crc() const throw() { return crc_ ^ 0xFFFFFFFFU; } + uint32_t crc() const { return crc_ ^ 0xFFFFFFFFU; } LZ_encoder_base( const File_header & header, const int dictionary_size, const int match_len_limit, const int outfd ) @@ -474,7 +483,7 @@ protected: } // move-to-front dis in/into reps - void mtf_reps( const int dis, int reps[num_rep_distances] ) throw() + void mtf_reps( const int dis, int reps[num_rep_distances] ) { if( dis >= num_rep_distances ) { @@ -489,7 +498,7 @@ protected: } } - void encode_pair( const uint32_t dis, const int len, const int pos_state ) throw() + void encode_pair( const uint32_t dis, const int len, const int pos_state ) { len_encoder.encode( range_encoder, len, pos_state ); const int dis_slot = dis_slots[dis]; @@ -512,11 +521,10 @@ protected: } } - void full_flush( const long long data_position, const State & state ); + void full_flush( const long long data_position, const State state ); public: - long long member_position() const throw() - { return range_encoder.member_position(); } + long long member_position() const { return range_encoder.member_position(); } }; @@ -531,7 +539,7 @@ class LZ_encoder : public LZ_encoder_base int prev_index; // index of prev trial in trials[] int price; // dual use var; cumulative price, match length int reps[num_rep_distances]; - void update( const int d, const int p_i, const int pr ) throw() + void update( const int d, const int p_i, const int pr ) { if( pr < price ) { dis = d; prev_index = p_i; price = pr; } } }; @@ -545,16 +553,15 @@ class LZ_encoder : public LZ_encoder_base int align_prices[dis_align_size]; int align_price_count; - void fill_align_prices() throw(); - void fill_distance_prices() throw(); + void fill_align_prices(); + void fill_distance_prices(); - int price_rep_len1( const State & state, const int pos_state ) const throw() + int price_rep_len1( const int pos_state, const State state ) const { return price0( bm_rep0[state()] ) + price0( bm_len[state()][pos_state] ); } - int price_rep( const int rep, const State & state, - const int pos_state ) const throw() + int price_rep( const int rep, const int pos_state, const State state ) const { if( rep == 0 ) return price0( bm_rep0[state()] ) + price1( bm_len[state()][pos_state] ); @@ -569,7 +576,7 @@ class LZ_encoder : public LZ_encoder_base return price; } - int price_dis( const int dis, const int dis_state ) const throw() + int price_dis( const int dis, const int dis_state ) const { if( dis < modeled_distances ) return dis_prices[dis_state][dis]; @@ -578,7 +585,7 @@ class LZ_encoder : public LZ_encoder_base align_prices[dis & (dis_align_size - 1)]; } - int price_pair( const int dis, const int len, const int pos_state ) const throw() + int price_pair( const int dis, const int len, const int pos_state ) const { if( len <= min_match_len && dis >= modeled_distances ) return infinite_price; @@ -586,7 +593,7 @@ class LZ_encoder : public LZ_encoder_base price_dis( dis, get_dis_state( len ) ); } - int read_match_distances() throw() + int read_match_distances() { int len = matchfinder.longest_match_len( match_distances ); if( len == matchfinder.match_len_limit() && len < max_match_len ) @@ -619,7 +626,7 @@ class LZ_encoder : public LZ_encoder_base } int sequence_optimizer( const int reps[num_rep_distances], - const State & state ); + const State state ); public: LZ_encoder( Matchfinder & mf, const File_header & header, const int outfd ) diff --git a/fast_encoder.cc b/fast_encoder.cc index 319250a..2d99b04 100644 --- a/fast_encoder.cc +++ b/fast_encoder.cc @@ -30,7 +30,7 @@ #include "fast_encoder.h" -int Fmatchfinder::longest_match_len( int * const distance ) throw() +int Fmatchfinder::longest_match_len( int * const distance ) { int len_limit = match_len_limit_; if( len_limit > available_bytes() ) @@ -80,7 +80,7 @@ int Fmatchfinder::longest_match_len( int * const distance ) throw() } -void Fmatchfinder::longest_match_len() throw() +void Fmatchfinder::longest_match_len() { int len_limit = match_len_limit_; if( len_limit > available_bytes() ) diff --git a/fast_encoder.h b/fast_encoder.h index ce5bae5..05c3ca8 100644 --- a/fast_encoder.h +++ b/fast_encoder.h @@ -35,8 +35,8 @@ public: {} void reset() { Matchfinder_base::reset(); key4 = 0; } - int longest_match_len( int * const distance ) throw(); - void longest_match_len() throw(); + int longest_match_len( int * const distance ); + void longest_match_len(); }; @@ -21,32 +21,32 @@ class State public: enum { states = 12 }; - State() throw() : st( 0 ) {} - unsigned char operator()() const throw() { return st; } - bool is_char() const throw() { return st < 7; } + State() : st( 0 ) {} + unsigned char operator()() const { return st; } + bool is_char() const { return st < 7; } - void set_char() throw() + void set_char() { static const unsigned char next[states] = { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 }; st = next[st]; } - void set_match() throw() + void set_match() { static const unsigned char next[states] = { 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 }; st = next[st]; } - void set_rep() throw() + void set_rep() { static const unsigned char next[states] = { 8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11 }; st = next[st]; } - void set_short_rep() throw() + void set_short_rep() { static const unsigned char next[states] = { 9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11 }; @@ -86,7 +86,7 @@ enum { max_dis_states = 4 }; -inline int get_dis_state( int len ) throw() +inline int get_dis_state( int len ) { len -= min_match_len; if( len >= max_dis_states ) len = max_dis_states - 1; @@ -101,7 +101,7 @@ enum { bit_model_move_bits = 5, struct Bit_model { unsigned int probability; - Bit_model() throw() : probability( bit_model_total / 2 ) {} + Bit_model() : probability( bit_model_total / 2 ) {} }; @@ -135,10 +135,10 @@ public: first_post = true; } - void reset() const throw() { if( name_.size() ) first_post = true; } - const char * name() const throw() { return name_.c_str(); } - int verbosity() const throw() { return verbosity_; } - void operator()( const char * const msg = 0 ) const throw(); + void reset() const { if( name_.size() ) first_post = true; } + const char * name() const { return name_.c_str(); } + int verbosity() const { return verbosity_; } + void operator()( const char * const msg = 0 ) const; }; @@ -158,10 +158,10 @@ public: } } - uint32_t operator[]( const uint8_t byte ) const throw() { return data[byte]; } - void update( uint32_t & crc, const uint8_t byte ) const throw() + uint32_t operator[]( const uint8_t byte ) const { return data[byte]; } + void update( uint32_t & crc, const uint8_t byte ) const { crc = data[(crc^byte)&0xFF] ^ ( crc >> 8 ); } - void update( uint32_t & crc, const uint8_t * const buffer, const int size ) const throw() + void update( uint32_t & crc, const uint8_t * const buffer, const int size ) const { for( int i = 0; i < size; ++i ) crc = data[(crc^buffer[i])&0xFF] ^ ( crc >> 8 ); @@ -171,11 +171,11 @@ public: extern const CRC32 crc32; -inline int real_bits( const int value ) throw() +inline int real_bits( const unsigned int value ) { - int bits = 0; - for( int i = 1, mask = 1; mask > 0; ++i, mask <<= 1 ) - if( value & mask ) bits = i; + int bits = 0, i = 1; + unsigned int mask = 1; + for( ; mask > 0; ++i, mask <<= 1 ) if( value & mask ) bits = i; return bits; } @@ -189,24 +189,22 @@ struct File_header // 5 coded_dict_size enum { size = 6 }; - void set_magic() throw() - { std::memcpy( data, magic_string, 4 ); data[4] = 1; } - - bool verify_magic() const throw() + void set_magic() { std::memcpy( data, magic_string, 4 ); data[4] = 1; } + bool verify_magic() const { return ( std::memcmp( data, magic_string, 4 ) == 0 ); } - uint8_t version() const throw() { return data[4]; } - bool verify_version() const throw() { return ( data[4] <= 1 ); } + uint8_t version() const { return data[4]; } + bool verify_version() const { return ( data[4] <= 1 ); } - int dictionary_size() const throw() + int dictionary_size() const { int sz = ( 1 << ( data[5] & 0x1F ) ); if( sz > min_dictionary_size && sz <= max_dictionary_size ) - sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 0x07 ); + sz -= ( sz / 16 ) * ( ( data[5] >> 5 ) & 7 ); return sz; } - bool dictionary_size( const int sz ) throw() + bool dictionary_size( const int sz ) { if( sz >= min_dictionary_size && sz <= max_dictionary_size ) { @@ -235,36 +233,36 @@ struct File_trailer static int size( const int version = 1 ) { return ( ( version >= 1 ) ? 20 : 12 ); } - uint32_t data_crc() const throw() + uint32_t data_crc() const { uint32_t tmp = 0; for( int i = 3; i >= 0; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } - void data_crc( uint32_t crc ) throw() + void data_crc( uint32_t crc ) { for( int i = 0; i <= 3; ++i ) { data[i] = (uint8_t)crc; crc >>= 8; } } - long long data_size() const throw() + long long data_size() const { long long tmp = 0; for( int i = 11; i >= 4; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } - void data_size( long long sz ) throw() + void data_size( long long sz ) { for( int i = 4; i <= 11; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } - long long member_size() const throw() + long long member_size() const { long long tmp = 0; for( int i = 19; i >= 12; --i ) { tmp <<= 8; tmp += data[i]; } return tmp; } - void member_size( long long sz ) throw() + void member_size( long long sz ) { for( int i = 12; i <= 19; ++i ) { data[i] = (uint8_t)sz; sz >>= 8; } } @@ -274,15 +272,15 @@ struct File_trailer struct Error { const char * const msg; - explicit Error( const char * const s ) throw() : msg( s ) {} + explicit Error( const char * const s ) : msg( s ) {} }; // defined in main.cc void show_error( const char * const msg, const int errcode = 0, - const bool help = false ) throw(); -void internal_error( const char * const msg ) throw(); + const bool help = false ); +void internal_error( const char * const msg ); // defined in decoder.cc -int readblock( const int fd, uint8_t * const buf, const int size ) throw(); -int writeblock( const int fd, const uint8_t * const buf, const int size ) throw(); +int readblock( const int fd, uint8_t * const buf, const int size ); +int writeblock( const int fd, const uint8_t * const buf, const int size ); @@ -108,7 +108,7 @@ mode_t outfd_mode = usr_rw; bool delete_output_on_interrupt = false; -void show_help() throw() +void show_help() { std::printf( "%s - Data compressor based on the LZMA algorithm.\n", Program_name ); std::printf( "\nUsage: %s [options] [files]\n", invocation_name ); @@ -144,7 +144,7 @@ void show_help() throw() } -void show_version() throw() +void show_version() { std::printf( "%s %s\n", Program_name, PROGVERSION ); std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); @@ -154,7 +154,7 @@ void show_version() throw() } -const char * format_num( long long num ) throw() +const char * format_num( long long num ) { const char * const prefix[8] = { "Ki", "Mi", "Gi", "Ti", "Pi", "Ei", "Zi", "Yi" }; @@ -173,7 +173,7 @@ const char * format_num( long long num ) throw() long long getnum( const char * const ptr, const long long llimit = LLONG_MIN + 1, - const long long ulimit = LLONG_MAX ) throw() + const long long ulimit = LLONG_MAX ) { errno = 0; char *tail; @@ -226,7 +226,7 @@ long long getnum( const char * const ptr, } -int get_dict_size( const char * const arg ) throw() +int get_dict_size( const char * const arg ) { char *tail; int bits = std::strtol( arg, &tail, 0 ); @@ -237,7 +237,7 @@ int get_dict_size( const char * const arg ) throw() } -int extension_index( const std::string & name ) throw() +int extension_index( const std::string & name ) { for( int i = 0; known_extensions[i].from; ++i ) { @@ -252,7 +252,7 @@ int extension_index( const std::string & name ) throw() int open_instream( const std::string & name, struct stat * const in_statsp, const Mode program_mode, const int eindex, - const bool recompress, const bool to_stdout ) throw() + const bool recompress, const bool to_stdout ) { int infd = -1; if( program_mode == m_compress && !recompress && eindex >= 0 ) @@ -294,7 +294,7 @@ int open_instream( const std::string & name, struct stat * const in_statsp, } -void set_c_outname( const std::string & name, const bool multifile ) throw() +void set_c_outname( const std::string & name, const bool multifile ) { output_filename = name; if( multifile ) output_filename += "00001"; @@ -302,7 +302,7 @@ void set_c_outname( const std::string & name, const bool multifile ) throw() } -void set_d_outname( const std::string & name, const int i ) throw() +void set_d_outname( const std::string & name, const int i ) { if( i >= 0 ) { @@ -321,7 +321,7 @@ void set_d_outname( const std::string & name, const int i ) throw() } -bool open_outstream( const bool force ) throw() +bool open_outstream( const bool force ) { int flags = O_CREAT | O_WRONLY | o_binary; if( force ) flags |= O_TRUNC; else flags |= O_EXCL; @@ -340,7 +340,7 @@ bool open_outstream( const bool force ) throw() } -bool check_tty( const int infd, const Mode program_mode ) throw() +bool check_tty( const int infd, const Mode program_mode ) { if( program_mode == m_compress && outfd >= 0 && isatty( outfd ) ) { @@ -357,7 +357,7 @@ bool check_tty( const int infd, const Mode program_mode ) throw() } -void cleanup_and_fail( const int retval ) throw() +void cleanup_and_fail( const int retval ) { if( delete_output_on_interrupt ) { @@ -460,7 +460,7 @@ int compress( const long long member_size, const long long volume_size, if( retval == 0 && verbosity >= 1 ) { if( in_size <= 0 || out_size <= 0 ) - std::fprintf( stderr, "No data compressed.\n" ); + std::fprintf( stderr, " no data compressed.\n" ); else std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " "%5.2f%% saved, %lld in, %lld out.\n", @@ -523,7 +523,7 @@ int fcompress( const long long member_size, const long long volume_size, if( retval == 0 && verbosity >= 1 ) { if( in_size <= 0 || out_size <= 0 ) - std::fprintf( stderr, "No data compressed.\n" ); + std::fprintf( stderr, " no data compressed.\n" ); else std::fprintf( stderr, "%6.3f:1, %6.3f bits/byte, " "%5.2f%% saved, %lld in, %lld out.\n", @@ -543,7 +543,7 @@ int fcompress( const long long member_size, const long long volume_size, } -unsigned char xdigit( const int value ) throw() +unsigned char xdigit( const int value ) { if( value >= 0 && value <= 9 ) return '0' + value; if( value >= 10 && value <= 15 ) return 'A' + value - 10; @@ -552,7 +552,7 @@ unsigned char xdigit( const int value ) throw() void show_trailing_garbage( const uint8_t * const data, const int size, - const Pretty_print & pp, const bool all ) throw() + const Pretty_print & pp, const bool all ) { std::string garbage_msg; if( !all ) garbage_msg = "first bytes of "; @@ -566,7 +566,7 @@ void show_trailing_garbage( const uint8_t * const data, const int size, garbage_msg.append( (const char *)data, size ); garbage_msg += '\''; } - else + else { for( int i = 0; i < size; ++i ) { @@ -590,7 +590,7 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) { File_header header; rdec.reset_member_position(); - const int size = rdec.read( header.data, File_header::size ); + const int size = rdec.read_data( header.data, File_header::size ); if( rdec.finished() ) // End Of File { if( first_member ) @@ -663,14 +663,14 @@ int decompress( const int infd, const Pretty_print & pp, const bool testing ) } -extern "C" void signal_handler( int ) throw() +extern "C" void signal_handler( int ) { show_error( "Control-C or similar caught, quitting." ); cleanup_and_fail( 1 ); } -void set_signals() throw() +void set_signals() { std::signal( SIGHUP, signal_handler ); std::signal( SIGINT, signal_handler ); @@ -680,7 +680,7 @@ void set_signals() throw() } // end namespace -void show_error( const char * const msg, const int errcode, const bool help ) throw() +void show_error( const char * const msg, const int errcode, const bool help ) { if( verbosity >= 0 ) { @@ -698,7 +698,7 @@ void show_error( const char * const msg, const int errcode, const bool help ) th } -void internal_error( const char * const msg ) throw() +void internal_error( const char * const msg ) { if( verbosity >= 0 ) std::fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); diff --git a/testsuite/check.sh b/testsuite/check.sh index a82d0de..116345c 100755 --- a/testsuite/check.sh +++ b/testsuite/check.sh @@ -22,24 +22,22 @@ mkdir tmp cd "${objdir}"/tmp cat "${testdir}"/test.txt > in || framework_failure +cat in in > in2 || framework_failure fail=0 printf "testing lzip-%s..." "$2" "${LZIP}" -t "${testdir}"/test_v0.lz || fail=1 -printf . "${LZIP}" -cd "${testdir}"/test_v0.lz > copy || fail=1 cmp in copy || fail=1 printf . "${LZIP}" -t "${testdir}"/test_v1.lz || fail=1 -printf . "${LZIP}" -cd "${testdir}"/test_v1.lz > copy || fail=1 cmp in copy || fail=1 printf . "${LZIP}" -t "${testdir}"/test_sync.lz || fail=1 -printf . "${LZIP}" -cd "${testdir}"/test_sync.lz > copy || fail=1 cmp in copy || fail=1 printf . @@ -82,6 +80,11 @@ for i in s4Ki 0 1 2 3 4 5 6 7 8 9 ; do printf . done +"${LZIP}" < in2 > out2 || fail=1 +"${LZIP}" -d < out2 > copy2 || fail=1 +cmp in2 copy2 || fail=1 +printf . + "${LZIP}" < in > anyothername || fail=1 "${LZIP}" -d anyothername || fail=1 cmp in anyothername.out || fail=1 diff --git a/testsuite/unzcrash.cc b/testsuite/unzcrash.cc deleted file mode 100644 index 65d160d..0000000 --- a/testsuite/unzcrash.cc +++ /dev/null @@ -1,354 +0,0 @@ -/* Unzcrash - A test program written to test robustness to - decompression of corrupted data. - Inspired by unzcrash.c from Julian Seward's bzip2. - Copyright (C) 2008, 2009, 2010, 2011 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 - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include <cerrno> -#include <climits> -#include <csignal> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <string> -#include <vector> -#include <stdint.h> -#include <unistd.h> - -#include "../arg_parser.h" - -#if CHAR_BIT != 8 -#error "Environments where CHAR_BIT != 8 are not supported." -#endif - -#ifndef LLONG_MAX -#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL -#endif -#ifndef LLONG_MIN -#define LLONG_MIN (-LLONG_MAX - 1LL) -#endif -#ifndef ULLONG_MAX -#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL -#endif - - -namespace { - -const char * const Program_name = "Unzcrash"; -const char * const program_name = "unzcrash"; -const char * const program_year = "2011"; -const char * invocation_name = 0; - -int verbosity = 0; - - -void show_help() throw() - { - std::printf( "%s - A test program written to test robustness to\n", Program_name ); - std::printf( "decompression of corrupted data.\n" - "\nUsage: %s [options] \"lzip -tv\" filename.lz\n", invocation_name ); - std::printf( "\nThis program reads the specified file and then repeatedly decompresses\n" - "it, increasing 256 times each byte of the compressed data, so as to test\n" - "all possible one-byte errors. This should not cause any invalid memory\n" - "accesses. If it does, please, report it as a bug.\n" - "\nOptions:\n" - " -h, --help display this help and exit\n" - " -V, --version output version information and exit\n" - " -b, --bits=<n>[,<n>]... test <n>-bit errors instead of full byte\n" - " -p, --position=<bytes> first byte position to test\n" - " -q, --quiet suppress all messages\n" - " -s, --size=<bytes> number of byte positions to test\n" - " -v, --verbose be verbose (a 2nd -v gives more)\n" - "\nReport bugs to lzip-bug@nongnu.org\n" - "Lzip home page: http://www.nongnu.org/lzip/lzip.html\n" ); - } - - -void show_version() throw() - { - std::printf( "%s %s\n", Program_name, PROGVERSION ); - std::printf( "Copyright (C) %s Antonio Diaz Diaz.\n", program_year ); - std::printf( "License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>\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" ); - } - - -void show_error( const char * const msg, const int errcode = 0, - const bool help = false ) throw() - { - if( verbosity >= 0 ) - { - if( msg && msg[0] ) - { - std::fprintf( stderr, "%s: %s", program_name, msg ); - if( errcode > 0 ) - std::fprintf( stderr, ": %s", std::strerror( errcode ) ); - std::fprintf( stderr, "\n" ); - } - if( help && invocation_name && invocation_name[0] ) - std::fprintf( stderr, "Try `%s --help' for more information.\n", - invocation_name ); - } - } - - -void internal_error( const char * const msg ) throw() __attribute__ ((noreturn)); -void internal_error( const char * const msg ) throw() - { - if( verbosity >= 0 ) - std::fprintf( stderr, "%s: internal error: %s.\n", program_name, msg ); - std::exit( 3 ); - } - - -long long getnum( const char * const ptr, - const long long llimit = LLONG_MIN + 1, - const long long ulimit = LLONG_MAX ) throw() - { - errno = 0; - char *tail; - long long result = strtoll( ptr, &tail, 0 ); - if( tail == ptr ) - { - show_error( "Bad or missing numerical argument.", 0, true ); - std::exit( 1 ); - } - - if( !errno && tail[0] ) - { - int factor = ( tail[1] == 'i' ) ? 1024 : 1000; - int exponent = 0; - bool bad_multiplier = false; - switch( tail[0] ) - { - case ' ': break; - case 'Y': exponent = 8; break; - case 'Z': exponent = 7; break; - case 'E': exponent = 6; break; - case 'P': exponent = 5; break; - case 'T': exponent = 4; break; - case 'G': exponent = 3; break; - case 'M': exponent = 2; break; - case 'K': if( factor == 1024 ) exponent = 1; else bad_multiplier = true; - break; - case 'k': if( factor == 1000 ) exponent = 1; else bad_multiplier = true; - break; - default : bad_multiplier = true; - } - if( bad_multiplier ) - { - show_error( "Bad multiplier in numerical argument.", 0, true ); - std::exit( 1 ); - } - for( int i = 0; i < exponent; ++i ) - { - if( LLONG_MAX / factor >= llabs( result ) ) result *= factor; - else { errno = ERANGE; break; } - } - } - if( !errno && ( result < llimit || result > ulimit ) ) errno = ERANGE; - if( errno ) - { - show_error( "Numerical argument out of limits." ); - std::exit( 1 ); - } - return result; - } - - -class Bitset8 // 8 value bitset (1..8) - { - bool data[8]; - static bool valid_digit( const unsigned char ch ) throw() - { return ( ch >= '1' && ch <= '8' ); } - -public: - Bitset8() throw() { for( int i = 0; i < 8; ++i ) data[i] = true; } - - bool includes( const int i ) const throw() - { return ( i >= 1 && i <= 8 && data[i-1] ); } - - // Recognized formats: 1 1,2,3 1-4 1,3-5,8 - bool parse( const char * p ) throw() - { - for( int i = 0; i < 8; ++i ) data[i] = false; - while( true ) - { - const unsigned char ch1 = *p++; - if( !valid_digit( ch1 ) ) break; - if( *p != '-' ) data[ch1-'1'] = true; - else - { - ++p; - if( !valid_digit( *p ) || ch1 > *p ) break; - for( int c = ch1; c <= *p; ++c ) data[c-'1'] = true; - ++p; - } - if( *p == 0 ) return true; - if( *p == ',' ) ++p; else break; - } - show_error( "Invalid value or range." ); - return false; - } - - // number of n-bit errors per byte (n=0..8): 1 8 28 56 70 56 28 8 1 - void print() const throw() - { - std::fflush( stderr ); - int c = 0; - for( int i = 0; i < 8; ++i ) if( data[i] ) ++c; - if( c == 8 ) std::printf( "Testing full byte.\n" ); - else if( c == 0 ) std::printf( "Nothing to test.\n" ); - else - { - std::printf( "Testing " ); - for( int i = 0; i < 8; ++i ) - if( data[i] ) - { - std::printf( "%d", i + 1 ); - if( --c ) std::printf( "," ); - } - std::printf( " bit errors.\n" ); - } - std::fflush( stdout ); - } - }; - - -int differing_bits( const uint8_t byte1, const uint8_t byte2 ) - { - int count = 0; - uint8_t dif = byte1 ^ byte2; - while( dif ) - { count += ( dif & 1 ); dif >>= 1; } - return count; - } - -} // end namespace - - -int main( const int argc, const char * const argv[] ) - { - enum { buffer_size = 3 << 20 }; - Bitset8 bits; // if Bitset8::parse not called test full byte - int pos = 0; - int max_size = buffer_size; - invocation_name = argv[0]; - - const Arg_parser::Option options[] = - { - { 'h', "help", Arg_parser::no }, - { 'b', "bits", Arg_parser::yes }, - { 'p', "position", Arg_parser::yes }, - { 'q', "quiet", Arg_parser::no }, - { 's', "size", Arg_parser::yes }, - { 'v', "verbose", Arg_parser::no }, - { 'V', "version", Arg_parser::no }, - { 0 , 0, Arg_parser::no } }; - - const Arg_parser parser( argc, argv, options ); - if( parser.error().size() ) // bad option - { show_error( parser.error().c_str(), 0, true ); return 1; } - - int argind = 0; - for( ; argind < parser.arguments(); ++argind ) - { - const int code = parser.code( argind ); - if( !code ) break; // no more options - const char * const arg = parser.argument( argind ).c_str(); - switch( code ) - { - case 'h': show_help(); return 0; - case 'b': if( !bits.parse( arg ) ) return 1; break; - case 'p': pos = getnum( arg, 0, buffer_size - 1 ); break; - case 'q': verbosity = -1; break; - case 's': max_size = getnum( arg, 1, buffer_size ); break; - case 'v': if( verbosity < 4 ) ++verbosity; break; - case 'V': show_version(); return 0; - default : internal_error( "uncaught option" ); - } - } // end process options - - if( argind + 2 != parser.arguments() ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "Usage: %s \"lzip -tv\" filename.lz\n", - invocation_name ); - return 1; - } - - FILE *f = std::fopen( parser.argument( argind + 1 ).c_str(), "rb" ); - if( !f ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "Can't open file `%s' for reading\n", - parser.argument( argind + 1 ).c_str() ); - return 1; - } - - uint8_t * const buffer = new uint8_t[buffer_size]; - const int size = std::fread( buffer, 1, buffer_size, f ); - if( size >= buffer_size ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "input file `%s' is too big.\n", - parser.argument( argind + 1 ).c_str() ); - return 1; - } - std::fclose( f ); - - f = popen( parser.argument( argind ).c_str(), "w" ); - if( !f ) - { show_error( "Can't open pipe", errno ); return 1; } - const int wr = std::fwrite( buffer, 1, size, f ); - if( wr != size || pclose( f ) != 0 ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "Could not run `%s' : %s.\n", - parser.argument( argind ).c_str(), std::strerror( errno ) ); - return 1; - } - - std::signal( SIGPIPE, SIG_IGN ); - if( verbosity >= 1 ) bits.print(); - - const int end = ( ( pos + max_size < size ) ? pos + max_size : size ); - for( int i = pos; i < end; ++i ) - { - if( verbosity >= 0 ) - std::fprintf( stderr, "byte %d\n", i ); - const uint8_t byte = buffer[i]; - for( int j = 0; j < 255; ++j ) - { - ++buffer[i]; - if( bits.includes( differing_bits( byte, buffer[i] ) ) ) - { - f = popen( parser.argument( argind ).c_str(), "w" ); - if( !f ) - { show_error( "Can't open pipe", errno ); return 1; } - std::fwrite( buffer, 1, size, f ); - if( pclose( f ) == 0 && verbosity >= 0 ) - std::fprintf( stderr, "0x%02X (0x%02X+0x%02X) passed the test\n", - buffer[i], byte, j + 1 ); - } - } - buffer[i] = byte; - } - - delete[] buffer; - return 0; - } |