ea150a8931
git-svn-id: svn://10.65.10.50/trunk@33 c028cbd2-c16b-5b4b-a496-9718f37d4682
434 lines
13 KiB
C++
Executable File
434 lines
13 KiB
C++
Executable File
//
|
|
// ARCHIVE.CPP
|
|
//
|
|
// Source file for ArchiveLib 1.0
|
|
//
|
|
// Copyright (c) Greenleaf Software, Inc. 1994
|
|
// All Rights Reserved
|
|
//
|
|
// CONTENTS
|
|
//
|
|
// ALArchive::operator new()
|
|
// ALArchive::ALArchive()
|
|
// ALArchive::~ALArchive()
|
|
// ALArchive::CreateCompressionEngine()
|
|
// ALArchive::CreateStorageObject()
|
|
// ALArchive::AddWildCardFiles()
|
|
// ALArchive::MakeEntriesFromListBox()
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This file contains all the source code for class ALArchive. ALArchive
|
|
// is a class derived from ALArchiveBase that knows how to create ALFile
|
|
// and ALMemory objects. Remember that ALArchiveBase doesn't know how
|
|
// to create any kind of storage object, so we need derived classes to
|
|
// bind ourselves to certain types of objects.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
//
|
|
#include "arclib.h"
|
|
#pragma hdrstop
|
|
|
|
#include "archive.h"
|
|
#include "grenengn.h"
|
|
#include "copyengn.h"
|
|
#include "filestor.h"
|
|
#include "memstore.h"
|
|
#include "wildcard.h"
|
|
|
|
//
|
|
// void * ALArchive::operator new( size_t size )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// size : The number of bytes needed to create a new ALArchive object.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// A pointer to the newly allocated storage area, or 0 if no storage
|
|
// was available.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// When using a DLL, it is easy to create 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.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
#if defined( AL_BUILDING_DLL )
|
|
void AL_DLL_FAR * AL_PROTO ALArchive::operator new( size_t size )
|
|
{
|
|
return ::new char[ size ];
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// ALArchive::ALArchive( const char *file_name )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// name : The name of the ALFile object that is going to hold the
|
|
// ALArchive.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// Nothing, this is a constructor.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This is one of two constructors for ALArchive. (The other one
|
|
// follows immediately in this source file.) It is used
|
|
// when the archive you are working with or are going to create will
|
|
// reside in an ALFile object, which should be often. It simply
|
|
// calls the constructor for the base class with the appropriately
|
|
// created ALFile object and returns. It doesn't have to initialize
|
|
// any data members of its own, so life is really simple.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
AL_PROTO ALArchive::ALArchive( const char AL_DLL_FAR *file_name )
|
|
: ALArchiveBase( new ALFile( file_name ), 1 )
|
|
{
|
|
}
|
|
|
|
//
|
|
// ALArchive::ALArchive( ALStorage &so )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// so : A storage object that will used as the storage for the archive.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// Nothing, this is a constructor.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This is one of two constructors for ALArchive. (The other one
|
|
// immediately precedes this function in the same source file.) It is used
|
|
// when the archive you are working with or are going to create will
|
|
// reside in an object that you have already constructed.
|
|
// It doesn't have to initialize any data members of its own, so
|
|
// all it does is call the base class constructor from an
|
|
// initializer list, and then return.
|
|
//
|
|
// The storage object used for this archive is your responsibility to delete.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
AL_PROTO ALArchive::ALArchive( ALStorage AL_DLL_FAR &so )
|
|
: ALArchiveBase( &so, 0 )
|
|
{
|
|
}
|
|
|
|
//
|
|
// ALArchive::~ALArchive()
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// None.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// Nothing, destructor.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This destructor has an easy life of it, since it has no data
|
|
// members to clean up after. Instead, it leaves all of the heavy
|
|
// lifting to the base class destructor. In debug mode we at least
|
|
// do *something*, which is just to verify that this is the correct
|
|
// type of object.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
AL_PROTO ALArchive::~ALArchive()
|
|
{
|
|
AL_ASSERT( GoodTag(), "~ALArchive: attempt to delete invalid object" );
|
|
}
|
|
|
|
//
|
|
// ALCompressionEngine *ALArchive::CreateCompressionEngine( int engine_type )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// engine_type : An integer from ALDEFS.H that defines the type of compression
|
|
// to be created.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// A pointer to a newly created compression engine. If things go bad,
|
|
// a value of 0 is possible.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// ALArchiveBase doesn't know how to create compression engines or
|
|
// storage objects. That knowledge is left up to derived classes like
|
|
// this one. When extracting objects from an archive, this class has
|
|
// to be able to create a compression engine with no more information
|
|
// than the integer engine type stored in the archive directory.
|
|
// This is where we do it.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
ALCompressionEngine AL_DLL_FAR *
|
|
AL_PROTO ALArchive::CreateCompressionEngine( int engine_type )
|
|
{
|
|
switch ( engine_type ) {
|
|
case AL_COMPRESSION_COPY :
|
|
return new ALCopyEngine();
|
|
case AL_COMPRESSION_GREENLEAF :
|
|
return new ALGreenleafEngine();
|
|
default :
|
|
mStatus.SetError( AL_UNKNOWN_COMPRESSION_TYPE,
|
|
"Unknown compression type (%d) found in archive",
|
|
engine_type );
|
|
break; //Break instead of return because of bogus warnings
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//
|
|
// ALStorage * ALArchive::CreateStorageObject( const char *name,
|
|
// int object_type )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// name : The name of the storage object to be created.
|
|
//
|
|
// object_type : The object type, from ALStorageType in STORAGE.H.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// A pointer to a newly storage object. If things go bad,
|
|
// a value of 0 is possible.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// ALArchiveBase doesn't know how to create compression engines or
|
|
// storage objects. That knowledge is left up to derived classes like
|
|
// this one. When extracting objects from an archive, this class has
|
|
// to be able to create a storage object with no more information
|
|
// than the integer object type stored in the archive directory.
|
|
// This is where we do it.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
ALStorage AL_DLL_FAR * AL_PROTO
|
|
ALArchive::CreateStorageObject( const char AL_DLL_FAR *name,
|
|
int object_type )
|
|
{
|
|
switch ( object_type ) {
|
|
case AL_MEMORY_OBJECT :
|
|
return new ALMemory( name );
|
|
case AL_FILE_OBJECT :
|
|
return new ALFile( name );
|
|
default :
|
|
mStatus.SetError( AL_UNKNOWN_STORAGE_OBJECT,
|
|
"Unknown storage object type (%d) "
|
|
"found in archive",
|
|
object_type );
|
|
|
|
break;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// STATIC MEMBER FUNCTION
|
|
//
|
|
// int ALArchive::AddWildCardFiles(
|
|
// ALEntryList & list,
|
|
// const char *wild_spec = "*.*",
|
|
// int traverse_flag = 0,
|
|
// short int compression_level = AL_GREENLEAF_LEVEL_2 )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// list : The list that is going to receive the newly created
|
|
// ALEntry objects.
|
|
//
|
|
// wild_spec : The wild card file spec to expand into a list of
|
|
// files. Note that this string can contain multiple
|
|
// file specs, separated by commas or spaces.
|
|
//
|
|
// traverse_flag : A flag to indicate whether wild card expansion
|
|
// should traverse subdirectories.
|
|
//
|
|
// compression_level : The compression level that will be used to create
|
|
// compression engines for the new entries.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// The number of entries created by the wild card expansion.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// It is handy to have a function that will create a bunch of ALEntry
|
|
// objects and add them to a list of your choosing. We can't do this
|
|
// in the base class of ALArchiveBase, because it doesn't know anything
|
|
// about specific storage objects or compression engines. So the
|
|
// logical place to turn is to this derived class, which does know about
|
|
// ALFile and ALMemory.
|
|
//
|
|
// The only bad thing here is that this is a static public functions,
|
|
// so it is kind of confusing. You might think that this ought to be
|
|
// a member function of ALEntryList. The problem is, we don't want
|
|
// ALEntryList to know about specific engines or compression classes,
|
|
// because then they would get linked in to any application created
|
|
// with ArchiveLib.
|
|
//
|
|
// So anyway, this function creates a bunch of new ALEntry objects,
|
|
// with the storage object being an instance of class ALFile, and the
|
|
// compression engine being an object of class ALGreenleafEngine. It
|
|
// then adds the new ALEntry to the specified ALEntryList, so you don't
|
|
// have to do any work at all.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
int AL_PROTO
|
|
ALArchive::AddWildCardFiles( ALEntryList AL_DLL_FAR & list,
|
|
const char AL_DLL_FAR *wild_spec /* = "*.*" */,
|
|
int traverse_flag /* = 0 */,
|
|
short int compression_level /* = AL_GREENLEAF_LEVEL_2 */ )
|
|
{
|
|
AL_ASSERT( wild_spec != 0, "AddWildCardFiles: null parameter for wild_spec" );
|
|
ALWildCardExpander files( wild_spec, traverse_flag );
|
|
int count = 0;
|
|
|
|
char *new_name; ALEntry* dummy;
|
|
while ( ( new_name = files.GetNextFile() ) != 0 ) {
|
|
dummy = new ALEntry( list,
|
|
new ALFile( new_name ),
|
|
new ALGreenleafEngine( compression_level ) );
|
|
count++;
|
|
}
|
|
return count;
|
|
}
|
|
|
|
//
|
|
// int ALArchive::MakeEntriesFromListBox( ALEntryList &list,
|
|
// HWND hDlg,
|
|
// int list_box /* = -1 */ )
|
|
//
|
|
// ARGUMENTS:
|
|
//
|
|
// list : The list that is going to get the new entries.
|
|
//
|
|
// hDlg : The handle of the dialog box that contains the list box
|
|
// control. If you aren't using a dialog box, you can pass
|
|
// the handle of the list box control directly, and set
|
|
// the list_box parameter to -1.
|
|
//
|
|
// list_box : The id of the list box control in the dialog box. If this
|
|
// parameter is set to -1, it means that hDlg doesn't refer
|
|
// to a dialog, it refers to the actual handle of a list box
|
|
// control.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// The number of new entries created from the list box.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This function goes through a list box, and picks out all the
|
|
// highlighted entries. It creates a new ALEntry object for each
|
|
// of the marked entires, using ALFile and ALGreenleafEngine objects.
|
|
// For purposes of orthogonality, I probably should have had a
|
|
// compression_level parameter here, but I neglected to include that.
|
|
// We could do it in the next release using a default parameter and
|
|
// nobody would even notice.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
#if defined( AL_WINDOWS_GUI )
|
|
|
|
int AL_PROTO ALArchive::
|
|
MakeEntriesFromListBox( ALEntryList AL_DLL_FAR &list,
|
|
HWND hDlg,
|
|
int list_box /* = -1 */ )
|
|
{
|
|
HWND window;
|
|
|
|
if ( list_box != -1 )
|
|
window = GetDlgItem( hDlg, (short int) list_box );
|
|
else
|
|
window = hDlg;
|
|
int count = (WORD) SendMessage( window, LB_GETSELCOUNT, 0, 0L );
|
|
if ( count == LB_ERR )
|
|
return AL_GETSEL_ERROR;
|
|
int *items = new int[ count ];
|
|
if ( items == 0 )
|
|
return AL_CANT_ALLOCATE_MEMORY;
|
|
#ifdef AL_FLAT_MODEL
|
|
if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM) items ) ) {
|
|
#else
|
|
if ( count != SendMessage( window, LB_GETSELITEMS, (short int) count, (LPARAM)(int _far *) items ) ) {
|
|
#endif
|
|
delete items;
|
|
return AL_GETSEL_ERROR;
|
|
}
|
|
for ( WORD i = 0 ; i < (WORD) count ; i++ ) {
|
|
WORD length = (WORD) SendMessage( window, LB_GETTEXTLEN, (short int) items[ i ], 0L );
|
|
if ( length > 0 ) {
|
|
char *name = new char[ length + 1 ];
|
|
if ( name ) {
|
|
if ( SendMessage( window, LB_GETTEXT, (short int) items[ i ], (LPARAM)( (LPSTR) name ) ) >= 0 ) {
|
|
new ALEntry( list,
|
|
new ALFile( name ),
|
|
new ALGreenleafEngine() );
|
|
}
|
|
delete name;
|
|
SendMessage( window,
|
|
LB_SETSEL,
|
|
0,
|
|
items[ i ] );
|
|
}
|
|
}
|
|
}
|
|
delete items;
|
|
return count;
|
|
}
|
|
|
|
#endif //#ifdef AL_WINDOWS_GUI
|