campo-sirio/arch/archive.cpp
villa ea150a8931 Prime modifiche per compatibilita' UNIX
git-svn-id: svn://10.65.10.50/trunk@33 c028cbd2-c16b-5b4b-a496-9718f37d4682
1994-08-18 10:40:18 +00:00

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