campo-sirio/al/examples/ex23con.cpp
alex 714dd74636 Archive Library versione 2.00
git-svn-id: svn://10.65.10.50/trunk@5350 c028cbd2-c16b-5b4b-a496-9718f37d4682
1997-10-09 16:09:54 +00:00

294 lines
8.8 KiB
C++
Executable File

//
// EX23CON.CPP
//
// C++/DOS Example program for ArchiveLib 2.0
//
// Copyright (c) Greenleaf Software, Inc. 1994 - 1996
// All Rights Reserved
//
// MEMBERS/FUNCTIONS DEMONSTRATED
//
// ALEngine::Compress()
// ALEngine::Decompress()
//
// DESCRIPTION
//
// This program is used to benchmark the performance of our various
// compression engines. It is called with a single command line argument,
// which is a wildcard specification for a group of files. The program
// expands the wild card specification and individually compresses and
// decompresses each of the files. The temporary files created by this
// process are deleted.
//
// After the whole batch of files is done, a summary of the compression
// time and statistics is displayed.
//
// If the optional -c argument is appended to the command line, the
// program runs in "compress-only" mode. In this case, the decompression
// state is skipped. You can use this to determine the ratio between
// compression and decompresion times.
//
// A program very similar to this is used to compare the speed of the
// PKWare data compression library to our library. It is called
// PKWARE.CPP, and it is distributed with our example program.s
//
// This example program does one funky thing to try to give us real
// fast performance. Instead of using the default buffer size of 4096
// bytes, I jack it up to a hefty 28672 bytes. This gives us a few
// percentage points. Just change the definition of BIG_BUFFER to
// benchmark at the default size.
//
// Note that the default version of this program doesn't use a monitor.
// To test the effects of a monitor on program performance, just define
//
// Note that this is a non-destructive test! None of the input files are
// modified at any time!
//
// MONITOR.
//
// REVISION HISTORY
//
// February 1, 1996 2.0A : Second release.
//
#include <stdio.h>
#include <stdlib.h>
#include <iostream.h>
#include <conio.h>
#include "al.h"
#if !defined( AL_OS2 )
#include <dos.h>
#endif
//
// This program runs under standard MS-DOS and extended DOS. Under
// extended DOS, we use the Windows API to get the time of day. To
// make the source code less messy, the details of the time of day
// are concealed in this class.
//
class TIME {
public :
long milliseconds;
TIME();
TIME( long t ){ milliseconds = t; }
TIME operator-(TIME &);
};
//
// The time constructor does the job of initializing the time of day.
// It has to be done differently under Extended DOS as opposed to
// standard real mode DOS.
//
#if defined( AL_WINDOWS )
inline TIME::TIME( void )
{
milliseconds = GetTickCount();
}
#elif defined( AL_OS2 )
inline TIME::TIME(void )
{
DATETIME t;
DosGetDateTime( &t );
milliseconds = t.hundredths * 10L;
milliseconds += t.seconds * 1000L;
milliseconds += t.minutes * 1000L * 60L;
milliseconds += t.hours * 1000L * 60L * 60L;
}
#else
inline TIME::TIME( void )
{
#if defined( AL_SYMANTEC )
struct dos_time_t t;
#else
struct dostime_t t;
#endif
_dos_gettime( &t );
milliseconds = t.hsecond * 10L;
milliseconds += t.second * 1000L;
milliseconds += t.minute * 1000L * 60L;
milliseconds += t.hour * 1000L * 60L * 60L;
}
#endif
//
// To determine how long an operation took, I need to calculate the
// difference of two times. This is strictly a convenience.
//
TIME TIME::operator-( TIME &rhs )
{
return TIME( milliseconds - rhs.milliseconds );
}
//
// A standard function for calculating the compression ratio of a file,
// give the input and output sizes.
//
inline int ratio( long plain, long compressed )
{
if ( plain == 0 )
return 0;
compressed *= 100;
return (int) ( 100 - ( compressed / plain ) );
}
//
// There are many places in the code where I want to send the time
// to an output stream. This function takes care of that.
//
ostream& operator<<(ostream& s, TIME t )
{
long m = t.milliseconds;
int hours;
int minutes;
int seconds;
int hsecs;
hours = (int) ( m / ( 1000L * 60L * 60L ) );
m -= hours * ( 1000L * 60L * 60L );
minutes = (int) ( m / ( 1000L * 60L ) );
m -= minutes * (1000L * 60L );
seconds = (int) ( m / ( 1000L ) );
m -= seconds * 1000L;
hsecs = (int) ( m / 10L );
(void) s.width( 2 );
char temp = s.fill( '0' );
s << (int) hours << ':';
(void) s.width( 2 );
s << (int) minutes << ':';
(void) s.width( 2 );
s << (int) seconds << '.';
(void) s.width( 2 );
s << (int) hsecs;
s.fill( temp );
return s;
}
//
// main() is kind of long, but it should be pretty straightforward.
// Most of the body of the code is grunt code to either create
// nice looking output or to collect statistics.
//
#if !defined( BIG_BUFFER )
#define BIG_BUFFER 28672
#endif
int main( int argc, char *argv[] )
{
long total_input = 0;
long total_compressed = 0;
int compress_only_flag = 0;
int bad = 0;
cout << "Archive Library 2.0\nEX23CON.CPP\n\n";
cout << "This program runs under standard MS-DOS and extended DOS. Under\n";
cout << "extended DOS, we use the Windows API to get the time of day. To\n";
cout << "make the source code less messy, the details of the time of day\n";
cout << "are concealed in this class.\n";
getch();
if ( argc < 2 ) {
cout << "Usage: EX23CON wild-spec [-c]\n"
<< "\n"
<< "This program is used to run benchmarks on ArchiveLib's\n"
<< "compression size and speed. It compresses a group of\n"
<< "files as specified in the wild-spec, and gives stats on\n"
<< "total compression time and ratio. To do a real test,\n"
<< "you probably ought to also turn off SMARTDRV or any other\n"
<< "disk caching program.\n"
<< "\n"
<< "The optional -c argument lets you specify that you only\n"
<< "want to compress files, so the decompression pass is\n"
<< "skipped.\n"
<< "\n"
<< "Note that this is a non-destructive test! None of the\n"
<< "input files are modified at any time!\n"
<< "\n";
exit( 1 );
}
cout.rdbuf()->setbuf( (char *) 0, 0 ); // Some compilers buffer cout
if ( argc > 2 && strcmp( argv[ 2 ], "-c" ) == 0 ) {
cout << "\nSkipping decompression!\n\n";
compress_only_flag = 1;
}
ALWildCardExpander expander( argv[ 1 ] );
#if defined( ZIP )
ALPkCompressor compressor( 6, 14, 7 );
ALPkDecompressor decompressor;
#else
ALGlCompressor compressor( AL_GREENLEAF_LEVEL_4 );
ALGlDecompressor decompressor( AL_GREENLEAF_LEVEL_4 );
#endif
char *name;
TIME global_start;
ALSpinner monitor( AL_MONITOR_OBJECTS, cout );
//
// This is the big loop where we compress all the files.
//
while ( ( name = expander.GetNextFile() ) != 0 ) {
TIME local_start;
ALFile input( name, BIG_BUFFER );
ALFile compressed( "", BIG_BUFFER );
//
// Print out the name of the file, sans drive and path
//
ALName filename( name );
filename.StripPath();
(void) cout.width( 13 );
cout << filename;
#if defined( MONITOR )
compressed.mpMonitor = &monitor;
monitor.mlObjectStart = 0;
#endif
compressor.Compress( input, compressed );
cout << " ";
(void) cout.width( 9 );
cout << input.GetSize() << " ";
(void) cout.width( 9 );
cout << compressed.GetSize();
ALFile output( "", BIG_BUFFER );
if ( !compress_only_flag )
decompressor.Decompress( compressed, output );
total_input += input.GetSize();
total_compressed += compressed.GetSize();
(void) cout.width( 4 );
cout << " ";
(void) cout.width( 4 );
cout << ratio( input.GetSize(), compressed.GetSize() ) << "%";
TIME local_stop;
cout << " " << ( local_stop - local_start );
if ( !compress_only_flag ) {
int test = output.Compare( input );
if (test < 0 )
bad++;
cout << " compare: " << test;
}
cout << endl;
if ( !compress_only_flag )
output.Delete();
compressed.Delete();
}
TIME global_stop;
cout << "Total input: " << total_input << " bytes.\n";
cout << "Total compressed: " << total_compressed << " bytes.\n";
cout << "Ratio : " << ratio( total_input, total_compressed ) << "%\n";
cout << "Total time: ";
cout << "Total failures: " << bad << endl;
cout << ( global_stop - global_start );;
cout << "\n";
return 0;
}