714dd74636
git-svn-id: svn://10.65.10.50/trunk@5350 c028cbd2-c16b-5b4b-a496-9718f37d4682
581 lines
17 KiB
C++
Executable File
581 lines
17 KiB
C++
Executable File
//
|
|
// ARCENTRY.CPP
|
|
//
|
|
// Source file for ArchiveLib 2.0
|
|
//
|
|
// Copyright (c) Greenleaf Software, Inc. 1994-1996
|
|
// All Rights Reserved
|
|
//
|
|
// CONTENTS
|
|
//
|
|
// ALEntry::operator new()
|
|
// ALEntry::ALEntry()
|
|
// newALEntry()
|
|
// ALEntry::~ALEntry()
|
|
// deleteALEntry()
|
|
// ALEntry::InsertBefore()
|
|
// ALEntry::GetNextEntry()
|
|
// ALEntryGetNextEntry()
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// Class ALEntry describes the state of an object that is in an archive.
|
|
// It contains a pointer to a storage object and two engines,
|
|
// which define what goes in the archive and how it is put there. It
|
|
// also defines how to extract it. The ALEntry object also contains
|
|
// miscellaneous items that go with the object in the archive, such
|
|
// as its time/date stamp, its CRC, and its comment.
|
|
//
|
|
// You have to create an ALEntry *before* you put an object into an
|
|
// archive. The archiving class member function figure out what you want
|
|
// to do by looking at objects of the ALEntry. You also have to read
|
|
// the contents of the archive into a list of ALEntry objects before you
|
|
// can extract anything.
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
// February 14, 1996 2.0A : New release. The big change in 2.0 is
|
|
// that the entry now contains a pointer to
|
|
// a compressor and a decompressor, instead
|
|
// of a single pointer to an engine.
|
|
//
|
|
|
|
#include "arclib.h"
|
|
#if !defined( AL_IBM )
|
|
#pragma hdrstop
|
|
#endif
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALEntry::operator new()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Windows
|
|
// C++
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// Memory allocation operator needed with DLL.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// void * ALEntry::operator new( size_t size )
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// size : The number of bytes needed to create a new ALEntry object.
|
|
//
|
|
// 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.
|
|
//
|
|
//
|
|
// RETURNS
|
|
//
|
|
// A pointer to the newly allocated storage area, or 0 if no storage
|
|
// was available.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// None.
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
|
|
#if defined( AL_BUILDING_DLL )
|
|
void AL_DLL_FAR * AL_PROTO
|
|
ALEntry::operator new( size_t size ) /* Tag internal function */
|
|
{
|
|
return ::new char[ size ];
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALEntry::ALEntry()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Console Windows PM
|
|
// C++ C VB Delphi
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// The constructor for ALEntry objects.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// ALEntry::ALEntry( ALEntryList &list,
|
|
// ALStorage *object,
|
|
// ALCompressor *compressor,
|
|
// ALDecompressor *decompressor );
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// hALEntry AL_FUNCTION newALEntry( hALEntryList list,
|
|
// hALStorage storage,
|
|
// hALCompressor compressor,
|
|
// hALDecompressor decompressor );
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// Declare Function newALEntry Lib "AL20LW"
|
|
// (ByVal list&,
|
|
// ByVal storage&,
|
|
// ByVal compressor&,
|
|
// ByVal decompressor&) As Long
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// function newALEntry( list : hALEntryList;
|
|
// storage : hALStorage;
|
|
// compressor : hALCompressor;
|
|
// decompressor : hALDecompressor ) : hALEntry;
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// list : A reference to the list the ALEntry object is going to
|
|
// be linked into. ALEntry objects aren't allowed to exist
|
|
// without being in a list.
|
|
//
|
|
// object : A pointer to the storage object that is attached to this
|
|
// entry. Remember, this is an unopened storage object,
|
|
// so it is not consuming very much space. It is okay
|
|
// to have a zillion or so of these just lying around.
|
|
// Don't forget that the ALEntry dtor is going to destroy
|
|
// this guy for you, don't you dare try it!.
|
|
//
|
|
// compressor : A pointer to the compression engine that is going to
|
|
// be used to create/insert the storage object into
|
|
// the archive. Just like with the storage object
|
|
// it is a low cost object, and you can keep lots
|
|
// of them on hand. This engine will be destroyed in the
|
|
// ALEntry dtor, so be sure to give up any claim you might
|
|
// have on this guy. If you aren't going to be compressing
|
|
// the object, a value of 0 is perfectly acceptable here.
|
|
//
|
|
// decompressor: A pointer to the decompression engine that is going to
|
|
// be used to extractt the storage object from the archive.
|
|
// Just like with the compression engine, it is a low cost
|
|
// object, and you can keep lots of them on hand. This
|
|
// engine will be destroyed in the ALEntry dtor, so be sure
|
|
// to give up any claim you might have on this guy. If you
|
|
// aren't going to be decompressing the object, a value of 0
|
|
// is perfectly acceptable here.
|
|
//
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This ctor creates a new ALEntry object. You can do this by hand, but
|
|
// frequently you will ask ArchiveLib to create ALEntry objects for you,
|
|
// maybe by pulling them out of a list box, or reading them in from and
|
|
// archive. Note that ALEntry objects aren't allowed to ever exist
|
|
// outside a list, each entry absolutely has to appear in a list.
|
|
//
|
|
// dtor issues relating to the ALEntry object are very important. Since
|
|
// ALEntry objects always are part of a list, it made sense for the
|
|
// ALEntryList destructor to clean up all the entries in its list. So
|
|
// even though you might have created this ALEntry object, you don't get to
|
|
// delete it, that will be done for you.
|
|
//
|
|
// Also, the storage object and compression engine in the ALEntry object
|
|
// are going to be automatically destroyed by the ALEntry dtor. Don't
|
|
// even think about trying it yourself!
|
|
//
|
|
// You can think of an ALEntryList as a directory of an archive, and each
|
|
// ALEntry object in the list is a single entry in that directory.
|
|
//
|
|
//
|
|
// RETURNS
|
|
//
|
|
// The C++ constructor doesn't return anything. The C/VB/Delphi versions
|
|
// of the constructor point to a newly created object, or perhaps to
|
|
// 0 if the constructor failed.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
|
|
AL_PROTO
|
|
ALEntry::ALEntry( ALEntryList &list, /* Tag public function */
|
|
ALStorage *object,
|
|
ALCompressor *compressor,
|
|
ALDecompressor *decompressor )
|
|
: mrList( list ) // Initialize our own pointer to the list we will
|
|
// be a member of.
|
|
{
|
|
mpNextItem = this;
|
|
mpPreviousItem = this;
|
|
mpStorageObject = object;
|
|
mpCompressor = compressor;
|
|
mpDecompressor = decompressor;
|
|
mlCompressedSize = -1;
|
|
mlCompressedObjectPosition = -1;
|
|
miMark = 1; //Always construct with the mark turned on
|
|
mszComment = 0;
|
|
//
|
|
// I check for the object member to be non-zero because of a clunky design
|
|
// choice I made a while back. Each ALEntryList has an ALEntry member that
|
|
// points to the first and last members of the list. I could have (and
|
|
// probably should have) made the root of the list just be a pair of pointers,
|
|
// instead of a dummy ALEntry. Anyway, I can tell that dummy entry apart
|
|
// from the valid entries by virtue of the fact that it has a null
|
|
// pointer in its object pointer.
|
|
//
|
|
// So anyway, when I create this dummy object, I don't want to try to add
|
|
// it to the list, because by definition it is already in the list. So
|
|
// I do a check before adding any ALEntry to the list.
|
|
//
|
|
if ( object )
|
|
InsertBefore( *list.mpListHead );
|
|
}
|
|
|
|
|
|
#if !defined( AL_NO_C )
|
|
|
|
extern "C" AL_LINKAGE
|
|
hALEntry AL_FUNCTION newALEntry( hALEntryList list, /* Tag public function */
|
|
hALStorage storage,
|
|
hALCompressor compressor,
|
|
hALDecompressor decompressor )
|
|
{
|
|
AL_ASSERT_OBJECT( list, ALEntryList, "newALEntry" );
|
|
AL_ASSERT_OBJECT( storage, ALStorage, "newALEntry" );
|
|
if ( compressor )
|
|
AL_ASSERT_OBJECT( compressor, ALCompressor, "newALEntry" );
|
|
if ( decompressor )
|
|
AL_ASSERT_OBJECT( decompressor, ALDecompressor, "newALEntry" );
|
|
return (hALEntry) new ALEntry( *( (ALEntryList *) list ),
|
|
(ALStorage * ) storage,
|
|
(ALCompressor *) compressor,
|
|
(ALDecompressor *) decompressor );
|
|
}
|
|
|
|
#endif
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALEntry::~ALEntry()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Console Windows PM
|
|
// C++ C VB Delphi
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// Destructor for ALEntry objects.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// ALEntry::~ALEntry()
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// void deleteALEntry( hALEntry this_object );
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// Declare Sub deleteALEntry Lib "AL20LW" (ByVal this_object&)
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// procedure deleteALEntry( this_object : hALEntry );
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// this_object : A reference or pointer to the ALEntry object that
|
|
// is going to be deleted. Note that the C++
|
|
// version of this call doesn't have an explicit argument
|
|
// here, since it has access to 'this' implicitly.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This destructor should normally be called by the ALEntryList dtor. The
|
|
// list that owns an entry will always try to delete it when the list
|
|
// is deleted.
|
|
//
|
|
// The ALEntry object tries to delete four dynamically allocated objects
|
|
// that it has control over: the storage object, the compression engines,
|
|
// and the comment. In each case it won't do it if the object pointer
|
|
// is 0. This provides a convenient mechanism for you to steal a storage
|
|
// object from an ALEntry. All you have to do is take the pointer, and
|
|
// then sen ALEntry::mpStorageObject to 0. This is an especially useful
|
|
// thing to do for ALMemory objects.
|
|
//
|
|
//
|
|
// RETURNS
|
|
//
|
|
// Nothing.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// None, we don't want you to call this on your own.
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
|
|
AL_PROTO
|
|
ALEntry::~ALEntry() /* Tag public function */
|
|
{
|
|
AL_ASSERT( GoodTag(), "~ALEntry: Attempting to delete invalid object" );
|
|
if ( mszComment )
|
|
delete[] mszComment;
|
|
if ( mpStorageObject != 0 )
|
|
delete mpStorageObject;
|
|
if ( mpCompressor != 0 )
|
|
delete mpCompressor;
|
|
if ( mpDecompressor !=0 )
|
|
delete mpDecompressor;
|
|
AL_ASSERT( mpNextItem != 0 ,"~ALEntry: next item is null" );
|
|
AL_ASSERT( mpPreviousItem != 0, "~ALEntry: previous item is null" );
|
|
|
|
ALEntry *next_job = mpNextItem;
|
|
ALEntry *previous_job = mpPreviousItem;
|
|
|
|
if ( next_job != this ) {
|
|
next_job->mpPreviousItem = previous_job;
|
|
previous_job->mpNextItem = next_job;
|
|
}
|
|
//
|
|
// Note that I check the object twice, one at the start of the dtor, and
|
|
// once again at the end. With all the linked list and dynamic deletion
|
|
// being done here, it seems like it would be really easy to hose things
|
|
// up if any mistakes were made.
|
|
//
|
|
AL_ASSERT( GoodTag(), "~ALEntry: Attempting to delete invalid object" );
|
|
}
|
|
|
|
#if !defined( AL_NO_C )
|
|
extern "C" AL_LINKAGE void AL_FUNCTION
|
|
deleteALEntry( hALEntry this_object ) /* Tag public function */
|
|
{
|
|
AL_ASSERT_OBJECT( this_object, ALEntry, "deleteALEntry" );
|
|
delete (ALEntry *) this_object;
|
|
}
|
|
#endif
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALEntry::InsertBefore()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Console Windows PM
|
|
// C++ C VB Delphi
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// Insert an ALEntry into the list before another job.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// void ALEntry::InsertBefore( ALEntry &job )
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// None.
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// job : A reference to another job in the target list.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This function is used inside the ALEntry class to add a new ALEntry
|
|
// object to an ALEntryList. Since the list is a doubly linked list, the
|
|
// code to do the job is pretty simple. It would have been a little more
|
|
// complicated if I used a pair of pointers in the ALEntryList to start
|
|
// the list, instead of a dummy ALEntry object.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// Nothing.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
// February 14, 1996 2.0A : New release
|
|
|
|
void AL_PROTO
|
|
ALEntry::InsertBefore( ALEntry &job ) /* Tag protected function */
|
|
{
|
|
mpNextItem = &job;
|
|
mpPreviousItem = job.mpPreviousItem;
|
|
(job.mpPreviousItem)->mpNextItem = this;
|
|
job.mpPreviousItem = this;
|
|
}
|
|
|
|
//
|
|
// NAME
|
|
//
|
|
// ALEntry::GetNextEntry()
|
|
//
|
|
// PLATFORMS/ENVIRONMENTS
|
|
//
|
|
// Console Windows PM
|
|
// C++ C VB Delphi
|
|
//
|
|
// SHORT DESCRIPTION
|
|
//
|
|
// Get the next entry in the list.
|
|
//
|
|
// C++ SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// ALEntry * ALEntry::GetNextEntry()
|
|
//
|
|
// C SYNOPSIS
|
|
//
|
|
// #include <arclib.h>
|
|
//
|
|
// hALEntry ALEntryGetNextEntry( hALEntry this_object );
|
|
//
|
|
// VB SYNOPSIS
|
|
//
|
|
// Declare Function ALEntryGetNextEntry Lib "AL20LW"
|
|
// (ByVal this_object&) As Long
|
|
//
|
|
// DELPHI SYNOPSIS
|
|
//
|
|
// function ALEntryGetNextEntry( this_object : hALEntry ) : hALEntry;
|
|
//
|
|
// ARGUMENTS
|
|
//
|
|
// this_object : A reference or pointer to the ALEntry object being used.
|
|
// Note that the C++ version of this call doesn't have an
|
|
// explicit argument for this_object, since it has access to
|
|
// 'this' implicitly.
|
|
//
|
|
// DESCRIPTION
|
|
//
|
|
// This function is used to iterate through an ALEntryList. Each entry has
|
|
// a pointer to the next and previous entries, so this function is really
|
|
// simple. The only complication comes from trying to detect the end of
|
|
// the list, which is denoted by the list head instance of ALEntry. We
|
|
// can tell it apart from all the legitimate entries by the fact that
|
|
// its storage object is 0.
|
|
//
|
|
// RETURNS
|
|
//
|
|
// A pointer to the next entry in the list. If the next entry is the
|
|
// list head, it means we have reached the end of the list, and a value
|
|
// of 0 is returned.
|
|
//
|
|
// EXAMPLE
|
|
//
|
|
// SEE ALSO
|
|
//
|
|
// REVISION HISTORY
|
|
//
|
|
// May 23, 1994 1.0A : First release
|
|
//
|
|
|
|
ALEntry AL_DLL_FAR * AL_PROTO
|
|
ALEntry::GetNextEntry() /* Tag public function */
|
|
{
|
|
ALEntry *next_entry = this->mpNextItem;
|
|
//
|
|
// The list head has the special case where both the compression engine
|
|
// and storage object pointers are 0, and that makes the end of the list.
|
|
//
|
|
// if ( mpNextItem->mpStorageObject == 0 )
|
|
//
|
|
// Try a new technique. I need to, because lately I've been making
|
|
// a lot of entries with zeros in one or more of the entries.
|
|
//
|
|
if ( next_entry == mrList.mpListHead )
|
|
return 0;
|
|
else
|
|
return next_entry;
|
|
}
|
|
|
|
#if !defined( AL_NO_C )
|
|
|
|
extern "C" AL_LINKAGE hALEntry AL_FUNCTION
|
|
ALEntryGetNextEntry( hALEntry this_object ) /* Tag public function */
|
|
{
|
|
AL_ASSERT_OBJECT( this_object, ALEntry, "ALEntryGetNextEntry" );
|
|
return (hALEntry) ( ((ALEntry *) this_object )->GetNextEntry() );
|
|
}
|
|
|
|
#endif
|
|
|
|
|