667 lines
16 KiB
C++
667 lines
16 KiB
C++
|
//
|
||
|
// ARC.CPP
|
||
|
//
|
||
|
// Source file for ArchiveLib 2.0
|
||
|
//
|
||
|
// Copyright (c) Greenleaf Software, Inc. 1994-1996
|
||
|
// All Rights Reserved
|
||
|
//
|
||
|
// CONTENTS
|
||
|
//
|
||
|
// ALArchive::ALArchive( ALStorage * )
|
||
|
// ALArchive::operator new()
|
||
|
// ALArchive::ScanStatus()
|
||
|
// ALArchive::CalculateJobSize()
|
||
|
// ALArchive::CalculateCompressedJobSize()
|
||
|
// ALArchive::WriteArchiveData()
|
||
|
// ALArchive::ReadArchiveData()
|
||
|
// ALArchive::~ALArchive()
|
||
|
// deleteALArchive()
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// This file contains the ALArchive ctor, dtor, and any functions
|
||
|
// that will *always* be linked (mostly because they are virtual.)
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
|
||
|
#include "arclib.h"
|
||
|
#if !defined( AL_IBM )
|
||
|
#pragma hdrstop
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::ALArchive()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Constructor for ALArchive, the base Archive class.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// ALArchive::ALArchive( ALStorage *storage_object,
|
||
|
// short int delete_in_dtor )
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// storage_object : A pointer to the storage object that will contain
|
||
|
// the archive.
|
||
|
//
|
||
|
// delete_in_dtor : When a user creates an archive, it will ordinarily
|
||
|
// be with a storage object that will be managed by
|
||
|
// their code. When that's the case, we will ordinarily
|
||
|
// expect them to be responsible for its destruction.
|
||
|
// However, there are times when a temporary archive
|
||
|
// might be created that isn't under the users control.
|
||
|
// This flag controls whether the Archive destructor
|
||
|
// will destroy the storage object as well.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// The base class ALArchive is very simple. It has a few data members
|
||
|
// to initialize, and not much else. The complexity in Archive classes
|
||
|
// is found in the derived classes ALGlArchive and ALPkArchive. Both
|
||
|
// of them use this base class to initialize their storage object
|
||
|
// and the flag that indicates whether the storage object should be
|
||
|
// destroyed in the ALArchive destructor.
|
||
|
//
|
||
|
// Although this is a public function, it isn't likely that there will
|
||
|
// ever be a good reason for an end user to call it. It really isn't much
|
||
|
// good to anyone but the constructors for the archiving classes.
|
||
|
//
|
||
|
// For this reason, there also isn't any reason to have a C/VB/Delphi
|
||
|
// translation routine. Any attempt to construct an ALArchive by itself
|
||
|
// is doomed to failure anyway, since it has numerous pure virtual
|
||
|
// functions.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// Nothing.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release, added the members to control
|
||
|
// whether or not to strip path information.
|
||
|
//
|
||
|
|
||
|
AL_PROTO
|
||
|
ALArchive::ALArchive( ALStorage AL_DLL_FAR *storage_object, /* Tag public function */
|
||
|
short int delete_in_dtor )
|
||
|
: mfDeleteStorageObject( delete_in_dtor )
|
||
|
{
|
||
|
mfStripPathOnInsert = 0;
|
||
|
mfStripPathOnExtract = 0;
|
||
|
mpArchiveStorageObject = storage_object;
|
||
|
mlDirectoryOffset = -1L;
|
||
|
miVersion = -1;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::operator new()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Memory allocator used when ArchiveLib resides in a 16 bit DLL.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// void * ALArchive::operator new( size_t size )
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// size : The number of bytes that the compiler has decided will be
|
||
|
// necessary to construct a new ALArchive object.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// When using a DLL, it is easy to get into 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.
|
||
|
//
|
||
|
// Incidentally, I suspect that this function never gets called. If an
|
||
|
// object of a derived archive class is being created, it should use
|
||
|
// its own new operator, rendering this one useless.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// A pointer to some memory that should have been pulled out of the
|
||
|
// heap for the DLL.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
#if defined( AL_BUILDING_DLL )
|
||
|
|
||
|
void AL_DLL_FAR * AL_PROTO
|
||
|
ALArchive::operator new( size_t size ) /* Tag internal function */
|
||
|
{
|
||
|
return ::new char[ size ];
|
||
|
}
|
||
|
|
||
|
#endif
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::ScanStatus()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Scan the list of entries for errors after an archiving operation
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// void ALArchive::ScanStatus( ALEntryList &list )
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// list : The list of entries that have just been processed, in one of
|
||
|
// the exciting functions, such as Create(), Delete(), etc.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// After an archive operation, I use this function to update the
|
||
|
// status member of the archive. If the archive doesn't already
|
||
|
// have an error, I check through all the storage objects and
|
||
|
// compression engines to see if any of them hosed up. Any error
|
||
|
// of any sort by any of them is copied into the archive status.
|
||
|
// The whole point of this is to ensure that if
|
||
|
// ALArchive.mStatus == AL_SUCCESS, it means everything worked.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// None. This function sort of has a return, it will update
|
||
|
// the member mStatus with an error code if one is found.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
void AL_PROTO
|
||
|
ALArchive::ScanStatus( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
|
||
|
{
|
||
|
if ( mStatus < AL_SUCCESS )
|
||
|
return;
|
||
|
ALEntry *job = list.GetFirstEntry();
|
||
|
while ( job ) {
|
||
|
if ( job->mpStorageObject->mStatus < AL_SUCCESS ) {
|
||
|
mStatus.SetError( job->mpStorageObject->mStatus,
|
||
|
"%s: %s",
|
||
|
job->mpStorageObject->mName.GetSafeName(),
|
||
|
job->mpStorageObject->mStatus.GetStatusDetail() );
|
||
|
return;
|
||
|
}
|
||
|
job = job->GetNextEntry();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::CalculateJobSize()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Calculate the total number of bytes in a job.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// long ALArchive::CalculateJobSize( ALEntryList &list )
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// list : The list of entries in the job. The calculation function
|
||
|
// will iterator through this list.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// If a monitor is running in AL_MONITOR_JOB mode, we need to add up
|
||
|
// the sizes of all the storage objects we are going to process, so
|
||
|
// that we can accurately track our progress from 0 to 100%. In many
|
||
|
// cases, the sizes of all the files will not yet be known, which means
|
||
|
// this routine will have to open the files up and check the values.
|
||
|
// That is why we only call this routine when we have to.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// This function is used to calculate the total number of bytes that
|
||
|
// are going to have to be moved when performing a Create() or Append()
|
||
|
// operation. We need that info in order to set up a monitor properly
|
||
|
// when its mode is AL_MONITOR_JOB. Naturally, we don't really care
|
||
|
// about the total size when the monitor is in AL_MONITOR_OBJECTS mode.
|
||
|
// Anyway, it returns the total unocmpressed size of all the objects added up.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
long AL_PROTO
|
||
|
ALArchive::CalculateJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
|
||
|
{
|
||
|
long total = 0;
|
||
|
ALEntry *job = list.GetFirstEntry();
|
||
|
while ( job ) {
|
||
|
if ( job->miMark ) {
|
||
|
long obj_size;
|
||
|
if ( ( obj_size = job->mpStorageObject->GetSize() ) == -1 ) {
|
||
|
job->mpStorageObject->Open();
|
||
|
obj_size = job->mpStorageObject->GetSize();
|
||
|
job->mpStorageObject->Close();
|
||
|
if ( obj_size == -1 )
|
||
|
return -1;
|
||
|
}
|
||
|
total += obj_size;
|
||
|
}
|
||
|
job = job->GetNextEntry();
|
||
|
}
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::CalculateCompressedJobSize()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Calculate the total number of bytes in a job.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// long ALArchive::CalculateCompressedJobSize( ALEntryList &list )
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// list : The list of entries in the job. The calculation function
|
||
|
// will iterator through this list.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// When we are monitoring an Extract() command, the monitor object
|
||
|
// gets attached to the Archive, not to the objects that are getting
|
||
|
// sucked out of it. This means that progress is being measured
|
||
|
// against the compressed objects, not the true size objects. So
|
||
|
// before I start the extract, I call this function to see just how
|
||
|
// much compressed space is taken up by the compressed objects in
|
||
|
// the archive.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// The total size of a bunch of compressed objects, not the uncompressed
|
||
|
// size.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
long AL_PROTO
|
||
|
ALArchive::CalculateCompressedJobSize( ALEntryList AL_DLL_FAR &list ) /* Tag protected function */
|
||
|
{
|
||
|
long total = 0;
|
||
|
ALEntry *job = list.GetFirstEntry();
|
||
|
while ( job ) {
|
||
|
if ( job->miMark ) {
|
||
|
if ( job->mlCompressedSize == -1 )
|
||
|
return -1;
|
||
|
else
|
||
|
total += job->mlCompressedSize;
|
||
|
}
|
||
|
job = job->GetNextEntry();
|
||
|
}
|
||
|
return total;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::WriteArchiveData()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Write out any customized archive data.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// int ALArchive::WriteArchiveData()
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// Derived classes can write out customized archive data, for whatever
|
||
|
// reasons they deem necessary. Our base class has nothing that it
|
||
|
// needs to save, so it just writes out a zero length string, which takes
|
||
|
// two bytes to save. Instead of using WriteString like I ought to, for
|
||
|
// some reason I write the 0 out directly.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// AL_SUCCESS if everything writes out okay, or < AL_SUCCESS for trouble.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
int AL_PROTO
|
||
|
ALArchive::WriteArchiveData() /* Tag protected function */
|
||
|
{
|
||
|
return mpArchiveStorageObject->WriteGlShort( 0 );
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::ReadArchiveData()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// Read in any customized archive data.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// int ALArchive::ReadArchiveData()
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// None.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// The base class doesn't store anything in the archive specific
|
||
|
// data area. That means that when I am reading the archive specific
|
||
|
// data in, I should see a zero length string, which is the same thing
|
||
|
// as a single short of value 0. I read it in and verify it here.
|
||
|
//
|
||
|
// Note that derived classes are free to override this function, but
|
||
|
// nothing we ship with ArchiveLib does so.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// AL_SUCCESS if things went well, < AL_SUCCESS it things go sour.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
int AL_PROTO
|
||
|
ALArchive::ReadArchiveData() /* Tag protected function */
|
||
|
{
|
||
|
short temp;
|
||
|
mpArchiveStorageObject->ReadGlShort( temp );
|
||
|
AL_ASSERT( temp == 0, "ReadArchiveData(): archive data != 0" );
|
||
|
return mpArchiveStorageObject->mStatus;
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// NAME
|
||
|
//
|
||
|
// ALArchive::~ALArchive()
|
||
|
//
|
||
|
// PLATFORMS/ENVIRONMENTS
|
||
|
//
|
||
|
// Console Windows PM
|
||
|
// C++ C VB Delphi
|
||
|
//
|
||
|
// SHORT DESCRIPTION
|
||
|
//
|
||
|
// The base class destructor for ALArchive.
|
||
|
//
|
||
|
// C++ SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// ALArchive::~ALArchive()
|
||
|
//
|
||
|
// C SYNOPSIS
|
||
|
//
|
||
|
// #include "arclib.h"
|
||
|
//
|
||
|
// void deleteALArchive( hALArchive this_object );
|
||
|
//
|
||
|
// VB SYNOPSIS
|
||
|
//
|
||
|
// Declare Sub deleteALArchive Lib "AL20LW" (ByVal this_object&)
|
||
|
//
|
||
|
// DELPHI SYNOPSIS
|
||
|
//
|
||
|
// procedure deleteALArchive( this_object : hALArchive );
|
||
|
//
|
||
|
// ARGUMENTS
|
||
|
//
|
||
|
// this_object : A reference or pointer to the ALArchive object that
|
||
|
// is going to be destroyed. The C++ version of this
|
||
|
// function doesn't have an argument, because it knows
|
||
|
// implicitly who to destroy.
|
||
|
//
|
||
|
// DESCRIPTION
|
||
|
//
|
||
|
// The destructor for the base class doesn't have to do too much work.
|
||
|
// All it has to do is destroy the storage object, if that service was
|
||
|
// requested when the object was constructed.
|
||
|
//
|
||
|
// It's a little deceptive to show the C/VB/Delphi translation here
|
||
|
// as well. Since the archive being destroyed will always be in a base
|
||
|
// class, the virtual function call will direct a call to deleteALArchive
|
||
|
// down to the derived class destructor before coming back up here. But
|
||
|
// I don't really have a better place to put it.
|
||
|
//
|
||
|
// RETURNS
|
||
|
//
|
||
|
// Nothing.
|
||
|
//
|
||
|
// EXAMPLE
|
||
|
//
|
||
|
// SEE ALSO
|
||
|
//
|
||
|
// REVISION HISTORY
|
||
|
//
|
||
|
// February 14, 1996 2.0A : New release
|
||
|
//
|
||
|
|
||
|
AL_PROTO
|
||
|
ALArchive::~ALArchive() /* Tag public function */
|
||
|
{
|
||
|
AL_ASSERT( GoodTag(), "~ALArchive(): Attempting to delete invalid ALArchive" );
|
||
|
if ( mpArchiveStorageObject && mfDeleteStorageObject )
|
||
|
delete mpArchiveStorageObject;
|
||
|
AL_ASSERT( GoodTag(), "~ALArchive::Attempting to delete invalid ALArchive" );
|
||
|
}
|
||
|
|
||
|
#if !defined( AL_NO_C )
|
||
|
|
||
|
extern "C" AL_LINKAGE void AL_FUNCTION
|
||
|
deleteALArchive( hALArchive this_object ) /* Tag public function */
|
||
|
{
|
||
|
AL_ASSERT_OBJECT( this_object, ALArchive, "deleteALArchive()" );
|
||
|
delete (ALArchive *) this_object;
|
||
|
}
|
||
|
|
||
|
#endif
|