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

667 lines
16 KiB
C++
Executable File

//
// ARC.CPP
//
// Source file for ArchiveLib 2.0
//
// Copyright (c) Greenleaf Software, Inc. 1994-1996
// All Rights Reserved
//
// CONTENTS
//
// ALArchive::ALArchive( ALStorage * )
// ALArchive::operator new()
// ALArchive::ScanStatus()
// ALArchive::CalculateJobSize()
// ALArchive::CalculateCompressedJobSize()
// ALArchive::WriteArchiveData()
// ALArchive::ReadArchiveData()
// ALArchive::~ALArchive()
// deleteALArchive()
//
// DESCRIPTION
//
// This file contains the ALArchive ctor, dtor, and any functions
// that will *always* be linked (mostly because they are virtual.)
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
#include "arclib.h"
#if !defined( AL_IBM )
#pragma hdrstop
#endif
//
// NAME
//
// ALArchive::ALArchive()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Constructor for ALArchive, the base Archive class.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// ALArchive::ALArchive( ALStorage *storage_object,
// short int delete_in_dtor )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// storage_object : A pointer to the storage object that will contain
// the archive.
//
// delete_in_dtor : When a user creates an archive, it will ordinarily
// be with a storage object that will be managed by
// their code. When that's the case, we will ordinarily
// expect them to be responsible for its destruction.
// However, there are times when a temporary archive
// might be created that isn't under the users control.
// This flag controls whether the Archive destructor
// will destroy the storage object as well.
//
// DESCRIPTION
//
// The base class ALArchive is very simple. It has a few data members
// to initialize, and not much else. The complexity in Archive classes
// is found in the derived classes ALGlArchive and ALPkArchive. Both
// of them use this base class to initialize their storage object
// and the flag that indicates whether the storage object should be
// destroyed in the ALArchive destructor.
//
// Although this is a public function, it isn't likely that there will
// ever be a good reason for an end user to call it. It really isn't much
// good to anyone but the constructors for the archiving classes.
//
// For this reason, there also isn't any reason to have a C/VB/Delphi
// translation routine. Any attempt to construct an ALArchive by itself
// is doomed to failure anyway, since it has numerous pure virtual
// functions.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release, added the members to control
// whether or not to strip path information.
//
AL_PROTO
ALArchive::ALArchive( ALStorage AL_DLL_FAR *storage_object, /* Tag public function */
short int delete_in_dtor )
: mfDeleteStorageObject( delete_in_dtor )
{
mfStripPathOnInsert = 0;
mfStripPathOnExtract = 0;
mpArchiveStorageObject = storage_object;
mlDirectoryOffset = -1L;
miVersion = -1;
}
//
// NAME
//
// ALArchive::operator new()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Memory allocator used when ArchiveLib resides in a 16 bit DLL.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// void * ALArchive::operator new( size_t size )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// size : The number of bytes that the compiler has decided will be
// necessary to construct a new ALArchive object.
//
// DESCRIPTION
//
// When using a DLL, it is easy to get into a dangerous situation when
// creating objects whose ctor and dtor are both in the DLL. The problem
// arises because when you create an object using new, the memory for
// the object will be allocated from the EXE. However, when you destroy
// the object using delete, the memory is freed inside the DLL. Since
// the DLL doesn't really own that memory, bad things can happen.
//
// But, you say, won't the space just go back to the Windows heap regardless
// of who tries to free it? Maybe, but maybe not. If the DLL is using
// a subsegment allocation scheme, it might do some sort of local free
// before returning the space to the windows heap. That is the point where
// you could conceivably cook your heap.
//
// By providing our own version of operator new inside this class, we
// ensure that all memory allocation for the class will be done from
// inside the DLL, not the EXE calling the DLL.
//
// Incidentally, I suspect that this function never gets called. If an
// object of a derived archive class is being created, it should use
// its own new operator, rendering this one useless.
//
// RETURNS
//
// A pointer to some memory that should have been pulled out of the
// heap for the DLL.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO
ALArchive::operator new( size_t size ) /* Tag internal function */
{
return ::new char[ size ];
}
#endif
//
// NAME
//
// ALArchive::ScanStatus()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Scan the list of entries for errors after an archiving operation
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// void ALArchive::ScanStatus( ALEntryList &list )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// list : The list of entries that have just been processed, in one of
// the exciting functions, such as Create(), Delete(), etc.
//
// DESCRIPTION
//
// After an archive operation, I use this function to update the
// status member of the archive. If the archive doesn't already
// have an error, I check through all the storage objects and
// compression engines to see if any of them hosed up. Any error
// of any sort by any of them is copied into the archive status.
// The whole point of this is to ensure that if
// ALArchive.mStatus == AL_SUCCESS, it means everything worked.
//
// RETURNS
//
// None. This function sort of has a return, it will update
// the member mStatus with an error code if one is found.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
void AL_PROTO
ALArchive::ScanStatus( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
{
if ( mStatus < AL_SUCCESS )
return;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->mpStorageObject->mStatus < AL_SUCCESS ) {
mStatus.SetError( job->mpStorageObject->mStatus,
"%s: %s",
job->mpStorageObject->mName.GetSafeName(),
job->mpStorageObject->mStatus.GetStatusDetail() );
return;
}
job = job->GetNextEntry();
}
}
//
// NAME
//
// ALArchive::CalculateJobSize()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Calculate the total number of bytes in a job.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// long ALArchive::CalculateJobSize( ALEntryList &list )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// list : The list of entries in the job. The calculation function
// will iterator through this list.
//
// DESCRIPTION
//
// If a monitor is running in AL_MONITOR_JOB mode, we need to add up
// the sizes of all the storage objects we are going to process, so
// that we can accurately track our progress from 0 to 100%. In many
// cases, the sizes of all the files will not yet be known, which means
// this routine will have to open the files up and check the values.
// That is why we only call this routine when we have to.
//
// RETURNS
//
// This function is used to calculate the total number of bytes that
// are going to have to be moved when performing a Create() or Append()
// operation. We need that info in order to set up a monitor properly
// when its mode is AL_MONITOR_JOB. Naturally, we don't really care
// about the total size when the monitor is in AL_MONITOR_OBJECTS mode.
// Anyway, it returns the total unocmpressed size of all the objects added up.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
long AL_PROTO
ALArchive::CalculateJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
{
long total = 0;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
long obj_size;
if ( ( obj_size = job->mpStorageObject->GetSize() ) == -1 ) {
job->mpStorageObject->Open();
obj_size = job->mpStorageObject->GetSize();
job->mpStorageObject->Close();
if ( obj_size == -1 )
return -1;
}
total += obj_size;
}
job = job->GetNextEntry();
}
return total;
}
//
// NAME
//
// ALArchive::CalculateCompressedJobSize()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Calculate the total number of bytes in a job.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// long ALArchive::CalculateCompressedJobSize( ALEntryList &list )
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// list : The list of entries in the job. The calculation function
// will iterator through this list.
//
// DESCRIPTION
//
// When we are monitoring an Extract() command, the monitor object
// gets attached to the Archive, not to the objects that are getting
// sucked out of it. This means that progress is being measured
// against the compressed objects, not the true size objects. So
// before I start the extract, I call this function to see just how
// much compressed space is taken up by the compressed objects in
// the archive.
//
// RETURNS
//
// The total size of a bunch of compressed objects, not the uncompressed
// size.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
long AL_PROTO
ALArchive::CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
{
long total = 0;
ALEntry *job = list.GetFirstEntry();
while ( job ) {
if ( job->miMark ) {
if ( job->mlCompressedSize == -1 )
return -1;
else
total += job->mlCompressedSize;
}
job = job->GetNextEntry();
}
return total;
}
//
// NAME
//
// ALArchive::WriteArchiveData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Write out any customized archive data.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALArchive::WriteArchiveData()
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// Derived classes can write out customized archive data, for whatever
// reasons they deem necessary. Our base class has nothing that it
// needs to save, so it just writes out a zero length string, which takes
// two bytes to save. Instead of using WriteString like I ought to, for
// some reason I write the 0 out directly.
//
// RETURNS
//
// AL_SUCCESS if everything writes out okay, or < AL_SUCCESS for trouble.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
int AL_PROTO
ALArchive::WriteArchiveData() /* Tag protected function */
{
return mpArchiveStorageObject->WriteGlShort( 0 );
}
//
// NAME
//
// ALArchive::ReadArchiveData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Read in any customized archive data.
//
// C++ SYNOPSIS
//
// int ALArchive::ReadArchiveData()
//
// C SYNOPSIS
//
// None.
//
// VB SYNOPSIS
//
// None.
//
// DELPHI SYNOPSIS
//
// None.
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// The base class doesn't store anything in the archive specific
// data area. That means that when I am reading the archive specific
// data in, I should see a zero length string, which is the same thing
// as a single short of value 0. I read it in and verify it here.
//
// Note that derived classes are free to override this function, but
// nothing we ship with ArchiveLib does so.
//
// RETURNS
//
// AL_SUCCESS if things went well, < AL_SUCCESS it things go sour.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
int AL_PROTO
ALArchive::ReadArchiveData() /* Tag protected function */
{
short temp;
mpArchiveStorageObject->ReadGlShort( temp );
AL_ASSERT( temp == 0, "ReadArchiveData(): archive data != 0" );
return mpArchiveStorageObject->mStatus;
}
//
// NAME
//
// ALArchive::~ALArchive()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// The base class destructor for ALArchive.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// ALArchive::~ALArchive()
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// void deleteALArchive( hALArchive this_object );
//
// VB SYNOPSIS
//
// Declare Sub deleteALArchive Lib "AL20LW" (ByVal this_object&)
//
// DELPHI SYNOPSIS
//
// procedure deleteALArchive( this_object : hALArchive );
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALArchive object that
// is going to be destroyed. The C++ version of this
// function doesn't have an argument, because it knows
// implicitly who to destroy.
//
// DESCRIPTION
//
// The destructor for the base class doesn't have to do too much work.
// All it has to do is destroy the storage object, if that service was
// requested when the object was constructed.
//
// It's a little deceptive to show the C/VB/Delphi translation here
// as well. Since the archive being destroyed will always be in a base
// class, the virtual function call will direct a call to deleteALArchive
// down to the derived class destructor before coming back up here. But
// I don't really have a better place to put it.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release
//
AL_PROTO
ALArchive::~ALArchive() /* Tag public function */
{
AL_ASSERT( GoodTag(), "~ALArchive(): Attempting to delete invalid ALArchive" );
if ( mpArchiveStorageObject && mfDeleteStorageObject )
delete mpArchiveStorageObject;
AL_ASSERT( GoodTag(), "~ALArchive::Attempting to delete invalid ALArchive" );
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE void AL_FUNCTION
deleteALArchive( hALArchive this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALArchive, "deleteALArchive()" );
delete (ALArchive *) this_object;
}
#endif