173 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			6.8 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// EX18CON.CPP
 | 
						|
//
 | 
						|
//  C++/DOS Example program for ArchiveLib 2.0
 | 
						|
//
 | 
						|
//  Copyright (c) Greenleaf Software, Inc. 1994 - 1996
 | 
						|
//  All Rights Reserved
 | 
						|
//
 | 
						|
// MEMBERS/FUNCTIONS DEMONSTRATED
 | 
						|
//
 | 
						|
//  ALCompressedObject::ALCompressedObject()
 | 
						|
//  ALCompressedObject::~ALCompressedObject()
 | 
						|
//  ALCompressedObject::Extract()
 | 
						|
//  ALCompressedObject::Insert()
 | 
						|
//  ALStatus::GetStatusCode()
 | 
						|
//  ALStatus::GetStatusString()
 | 
						|
//  ALStatus::GetStatusDetail()
 | 
						|
//  ALStatus::SetError();
 | 
						|
//  ALFileAttributes::PackedAttributes()
 | 
						|
//  ALFileAttributes::SetFromDosAttributes()
 | 
						|
//  ALFileAttributes::SetFromPackedAttributes()
 | 
						|
//  ALStorage::SetTimeDate()
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is another one of those example programs that ties together
 | 
						|
//  a bunch of marginally related functions.  It starts off by creating
 | 
						|
//  a data file on disk, and writing some fixed patterns out to it.  Next,
 | 
						|
//  the data file gets inserted into a compressed object, also on disk.
 | 
						|
//  Then the weird part:  If a random number hits, I randomly change a
 | 
						|
//  byte in the compressed object.  Finally, I extract the original data
 | 
						|
//  file from the compressed object, for better or worse.
 | 
						|
//
 | 
						|
//  After this is all done, I have three TMP files on the disk.  In an
 | 
						|
//  imitation of what you might do in a real debugging situation, I check
 | 
						|
//  to see if the input and output match.  If they do match, I just go
 | 
						|
//  ahead and delete them, all is well.  If they don't match, I want to
 | 
						|
//  hang on to the files.  Not only do I hang on to the files, I give
 | 
						|
//  them a funny time date stamp, and set them to be read-only.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//  February 1, 1996  2.0A  : Second release
 | 
						|
//
 | 
						|
//
 | 
						|
 | 
						|
#include <time.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <conio.h>
 | 
						|
 | 
						|
#include "al.h"
 | 
						|
 | 
						|
main()
 | 
						|
{
 | 
						|
    ALFile DataFile;
 | 
						|
    ALFile CompressedFile;
 | 
						|
    ALFile OutputFile;
 | 
						|
 | 
						|
    cout << "Archive Library 2.0\nEX18CON.CPP\n\n";
 | 
						|
    cout << "This is another one of those example programs that ties together\n";
 | 
						|
    cout << "a bunch of marginally related functions.  It starts off by creating\n";
 | 
						|
    cout << "a data file on disk, and writing some fixed patterns out to it.  Next,\n";
 | 
						|
    cout << "the data file gets inserted into a compressed object, also on disk.\n";
 | 
						|
    cout << "Then the weird part:  If a random number hits, I randomly change a\n";
 | 
						|
    cout << "byte in the compressed object.  Finally, I extract the original data\n";
 | 
						|
    cout << "file from the compressed object, for better or worse.\n\n";
 | 
						|
    getch();
 | 
						|
 | 
						|
#if defined( AL_ZIP )
 | 
						|
    ALPkCompressor Compressor( 3 );
 | 
						|
    ALPkDecompressor Decompressor;
 | 
						|
#else
 | 
						|
    ALGlCompressor Compressor( AL_GREENLEAF_LEVEL_4 );
 | 
						|
    ALGlDecompressor Decompressor;
 | 
						|
#endif
 | 
						|
    ALCompressedObject *CompressedObject;
 | 
						|
 | 
						|
//
 | 
						|
// Here is where I create the input data file and the compressed object.
 | 
						|
// This is all fairly realistic, you could write code that looks a lot
 | 
						|
// like this.
 | 
						|
//
 | 
						|
    CompressedObject = new ALCompressedObject( CompressedFile, &Compressor, &Decompressor );
 | 
						|
    DataFile.Create(); // Temporary file
 | 
						|
    for ( int i = 0 ; i < 64 ; i++ )
 | 
						|
        for ( int j = i; j < 64 ; j++ )
 | 
						|
            DataFile.WriteChar( j );
 | 
						|
    DataFile.Close();
 | 
						|
    CompressedObject->Insert( DataFile );
 | 
						|
//
 | 
						|
// If the one in four chance hits, I change a single byte in the compressed
 | 
						|
// file.  This will almost always cause an expansion error, although it
 | 
						|
// is possible to create a benign change (like the 1/256 chance that you
 | 
						|
// write over the old byte with a new byte that is the same!)
 | 
						|
//
 | 
						|
    srand( (unsigned) time( NULL ) );
 | 
						|
    if ( (rand() & 3) == 0 ) {
 | 
						|
        cout << "Mangling the compressed file!\n";
 | 
						|
        CompressedFile.Open();
 | 
						|
        CompressedFile.Seek( 32 + ( rand() & 31 ));
 | 
						|
        CompressedFile.WriteChar( rand() & 0xff );
 | 
						|
        CompressedFile.Close();
 | 
						|
    }
 | 
						|
//
 | 
						|
// Now I try to extract the output file.  Once I have done that, I perform
 | 
						|
// a compare to the original to see how things went.  Note that there is
 | 
						|
// a tricky bit here.  The only time ALFile objects will get new time/date
 | 
						|
// and attribute stamps is if they are closed immediately after having been
 | 
						|
// created.  The CompressedObject->Extract() call will create the file,
 | 
						|
// then close it.  Once it is closed, the flag indicating that it was just
 | 
						|
// created will be cleared, so I won't be able to set the time stamp.  But,
 | 
						|
// if *I* create it here, the Extract() function will leave it open after
 | 
						|
// performing its magic.  After it returns, I have to close the file,
 | 
						|
// but I can mung the time/date stamp first.
 | 
						|
//
 | 
						|
    OutputFile.Create(); //I need to do this in order to set the time and atts
 | 
						|
    CompressedObject->Extract( OutputFile );
 | 
						|
    OutputFile.Seek( 0L );
 | 
						|
    int status = DataFile.Compare( OutputFile );
 | 
						|
    cout << "Compare returned : " << status << "\n";
 | 
						|
//
 | 
						|
// If the comparison passed, I just delete all of the TMP files created
 | 
						|
// here.  (Note that they all have TMP names because I didn't give them
 | 
						|
// any names in their constructors.)
 | 
						|
//
 | 
						|
    if ( status >= 0 ) {
 | 
						|
        DataFile.Delete();
 | 
						|
        CompressedFile.Delete();
 | 
						|
        OutputFile.Close();
 | 
						|
        OutputFile.Delete();
 | 
						|
    } else {
 | 
						|
//
 | 
						|
// If the comparison failed, I am going to set their time/date stamps and
 | 
						|
// their attributes, using one of two methods.  Note that the Close()
 | 
						|
// routine will only set their attributes if the files have a valid
 | 
						|
// time/date stamp.  Since they are newly created, they don't have one
 | 
						|
// yet.  So I have to cook one up here.
 | 
						|
//
 | 
						|
        cout << "Object "
 | 
						|
             << ( OutputFile.mTimeDate.Valid() ? "has" : "does not have" )
 | 
						|
             << " a valid time stamp\n";
 | 
						|
        struct tm* tblock;
 | 
						|
        time_t t;
 | 
						|
        t = time( 0 );
 | 
						|
        tblock = localtime( &t );
 | 
						|
        if ( tblock->tm_sec > 30 ) {
 | 
						|
            tblock->tm_year--;
 | 
						|
            OutputFile.mTimeDate.SetTimeDate( tblock );
 | 
						|
            cout << "Setting time stamp using tblock\n";
 | 
						|
        } else {
 | 
						|
            cout << "Setting time stamp using a long\n";
 | 
						|
            OutputFile.mTimeDate.SetTimeDate( 20L*365L*24L*60L*60L + 5L*24L*60L*60L + 12L*60L*60L ); // Might be 1/1/1990
 | 
						|
        }
 | 
						|
        short unsigned int atts = OutputFile.mAttributes.PackedAttributes();
 | 
						|
        atts = (short unsigned int)( atts | 1 );
 | 
						|
        OutputFile.mAttributes.SetFromPackedAttributes( atts ); //Make it Read Only
 | 
						|
        OutputFile.Close();
 | 
						|
        CompressedObject->mStatus.SetError( status,
 | 
						|
                                            DataFile.mStatus.GetStatusDetail() );
 | 
						|
    }
 | 
						|
    cout << "Compressed object status code:    "
 | 
						|
         << CompressedObject->mStatus.GetStatusCode()
 | 
						|
         << "\n";
 | 
						|
    cout << "Compressed object status string:  "
 | 
						|
         << CompressedObject->mStatus.GetStatusString()
 | 
						|
         << "\n";
 | 
						|
    cout << "Compressed object status detail:  "
 | 
						|
         << CompressedObject->mStatus.GetStatusDetail()
 | 
						|
         << "\n";
 | 
						|
    delete CompressedObject;
 | 
						|
    return status;
 | 
						|
}
 |