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
 | 
						|
 | 
						|
 |