campo-sirio/al/cpp_all/arcentry.cpp
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

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