

##############################################################
# Paolo Ferragina @ August 2008
#
# This perl script decompresses a large file 
# which is partitioned into blocks stored in "_compr-file_.out"
# and whose sizes are stored in "_compr-sizes.out".
# 
# It writes the decompressed file in "_decompressed_.out"
##############################################################

use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
  

######################################################
# Opening the useful files containing input data
######################################################
open(COMPR,"<_compr-file_.out")
	|| die "Fail to open _compr-file_.out\n";


open(SIZES,"<_compr-sizes_.out")
	|| die "Fail to open _compr-sizes_.out\n";

$comprType = <SIZES>; # first row of this file

if (($comprType < 0) || ($comprType > 20)) {
    printf("comprType %d must be in [0-20]!\n\n",$comprType);
    exit;
}


if(scalar(@ARGV) < 1) { 
    print "We need the verbosity level (0 or 1)\n"; 
    exit;
}

$verbosity = shift @ARGV;

$totTimeSpent = 0.0;
$totSize = 0;

print "\n\nProcess started.....\n\n\n";
`rm -f _decompressed_.out _aa_ _block_.*`;
$initTotTime = Time::HiRes::time(); # from the epoch

$numBlocks = 0;

while (	$CBlockSize = <SIZES> ) {

	`rm -f _block_*`; 

	# timings Reading the block
	printf("Reads block \# %d..... ",$numBlocks+1);
	$prevTime = Time::HiRes::time(); # from the epoch

	$read = sysread(COMPR, $block, $CBlockSize);
	warn "only read $read bytes, not $CBlockSize" if $CBlockSize != $read;

	open(BLOCK,">_block_.out");
	$written = syswrite(BLOCK, $block);
		die "syswrite failed: $!\n" unless $written == length($block);
	close(BLOCK);

	$currTime = Time::HiRes::time(); # from the epoch
	printf(" done! (%.6f secs)\n", $currTime - $prevTime);


	# timings Decompressing the block
	printf("Decompresses the block \# %d..... ",$numBlocks+1);
	$prevTime = Time::HiRes::time(); # from the epoch

	# Perl does not support natively the SWITCH....	
	if($comprType == 0)
	    { `gunzip -c _block_.out > _block_.txt;` } 
	elsif($comprType == 1) 
	    { `bunzip2 -c _block_.out > _block_.txt;` }
	elsif($comprType == 2)
	    { `./ppmdi d _block_.out;` }
	elsif(($comprType >= 3) && ($comprType < 6))
	    { `./unbst _block_.out -o _block_.txt;` }
	elsif($comprType == 8)
	    { `./ppmdi d _block_.out;`; }
	elsif($comprType == 9)
	    { `gunzip -c _block_.out > _block_.vc; vcdiff decode --target_matches --dictionary _dict_.txt < _block_.vc > _block_.txt;`; }
	elsif($comprType == 10)
	    { `./unbst _block_.out -o _block_.vc; vcdiff decode --target_matches -dictionary _dict_.txt < _block_.vc > _block_.txt;`; }
	elsif($comprType == 11)
	    { `./7za e _block_.out; mv _aa_ _block_.vc; vcdiff decode --target_matches -dictionary _dict_.txt < _block_.vc > _block_.txt;`; }
	elsif($comprType == 13)
	    { `gunzip -c _block_.out > _block_.vc; vcdiff decode --target_matches --dictionary _dict_.txt < _block_.vc > _block_.txt;`; }
	elsif($comprType == 14)
	    { `./bwtp -d -r 10 _block_.out; mv _block_.out.y _block_.txt;`; }
	elsif($comprType == 15)
	{ `./7za e _block_.out; `; }
	elsif($comprType == 16)
	{ `gunzip -c _block_.out | ./BMIdecompress > _block_.txt`; }
	elsif($comprType == 17)
	{ ` ./rzip -d _block_.out -o _block_.txt`; }
	elsif($comprType == 18)
	{ `./7za e _block_.out; ./BMIdecompress <_block_.tmp > _block_.txt`; }
	elsif($comprType == 19)
	{ `./unbst _block_.out -o _aa_; ./BMIdecompress <_aa_ > _block_.txt`; }
	elsif($comprType == 20)
	{ `./7za e _block_.out; ./vczip -udelta,huffgroup <_block_.tmp > _block_.txt`; }
	else { print "The compressor type must be in [0-20]!"; exit; }


	$currTime = Time::HiRes::time(); # from the epoch
	printf(" done! (%.6f secs)\n", ($currTime - $prevTime));
	$totTimeSpent += ($currTime -$prevTime);
	$sizeTmp = -s "_block_.txt";
	$totSize += $sizeTmp;

	if($verbosity)
	{`cat _block_.txt >> _decompressed_.out`;}

	`rm -f _block_* _aa_`; 
	$numBlocks++;
        }
	    
# Overall timings 
$currTotTime = Time::HiRes::time(); # in secs from the epoch
printf("\n\nTotal decompression took %.1f secs", $currTotTime - $initTotTime);
printf("\nDecompression took %.3f secs", $totTimeSpent);
printf("\nDecompression speed %.2f MB/sec \n", ($totSize / 1000000.0) / $totTimeSpent);


