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

643 lines
17 KiB
C++
Executable File

//
// GLENGND.CPP
//
// Source file for ArchiveLib 2.0
//
// Copyright (c) Greenleaf Software, Inc. 1994-1996
// All Rights Reserved
//
// CONTENTS
//
// ALGlDecompressor::operator new()
// ALGlDecompressor::ALGlDecompressor()
// newALGlDecompressor()
// ALGlDecompressor::~ALGlDecompressor()
// ALGlDecompressor::Decompress()
// ALGlDecompressor::WriteEngineData()
// ALGlDecompressor::ReadEngineData()
// ALGlDecompressor::Clone()
//
// DESCRIPTION
//
// This file contains the front end to the Greenleaf decompression engine.
// This contains everything but the actual low level decompression
// code, which can be found in _RE.CPP . That source files is shrouded
// though, so you won't get a tremendous amount of detail!
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
#include "arclib.h"
#if !defined( AL_IBM )
#pragma hdrstop
#endif
#include "glengn.h"
#include "_openf.h"
#include "_r.h"
//
// NAME
//
// ALGlDecompressor::operator new()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// The memory allocator used with DLL versions of ArchiveLib.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// void * ALGlDecompressor::operator new( size_t size )
//
// C SYNOPSIS
//
// None, this is an internal C++ function.
//
// VB SYNOPSIS
//
// None, this is an internal C++ function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal C++ function.
//
// ARGUMENTS
//
// size : The amount of storage that needs to be allocated for
// this object.
//
// DESCRIPTION
//
// When using the DLL version of ArchiveLib, it is a good idea to
// allocate the storage for objects from inside the DLL, since they
// will be freed inside the DLL. If we don't have the new operator
// for a class, its storage will be allocated from the EXE before
// the constructor code is called. Then, when it is time to free
// the storage, the delete operator will be called inside the DLL.
// Not good, right?
//
// 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 storage.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO
ALGlDecompressor::operator new( size_t size ) /* Tag internal function */
{
return ::new char[ size ];
}
#endif
//
// NAME
//
// ALGlDecompressor::ALGlDecompressor()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Constructor for the Greenleaf decompressor engine.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// ALGlDecompressor::ALGlDecompressor(
// short int compression_level = AL_GREENLEAF_LEVEL_2 /* or 4 */ );
//
// C SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// hALDecompressor newALGlDecompressor( short int compression_level );
//
// VB SYNOPSIS
//
// Declare Function newALGlDecompressor Lib "AL20LW"
// (ByVal compression_level% ) As Long
//
// DELPHI SYNOPSIS
//
// function newALGlDecompressor( compression_level : Integer ) : hALCompressor;
//
// ARGUMENTS
//
// compression_level : This is one of the enumerated types found in ALDEFS.H,
// namely AL_GREENLEAF_LEVEL_0 through
// AL_GREENLEAF_LEVEL_4. Level 4 gives the most
// compression, but takes up the most memory as well.
// Note that 16 bit programs default to level 2,
// 32 bit programs default to level 4.
//
// DESCRIPTION
//
// The Greenleaf Decompressor has a very simple constructor. All it has
// to do is initialize a data member, then pass some additional
// data up to the base class ctor. Note that when it isn't actually
// decompressing, this object is pretty teeny.
//
// Note that under Visual Basic or C, it is up to the user to destroy
// this engine by calling deleteDecompressor(). C++ users only need to
// call the destructor explicitly when they have created the object
// dynamically using the new operator.
//
// RETURNS
//
// The C++ function returns nothing. The C and VB functions return the
// handle of the newly created decompressor. A value of 0 for this handle
// means the object could not be properly created.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
// February 14, 1996 2.0A : New Release
//
AL_PROTO
ALGlDecompressor::ALGlDecompressor( /* Tag public function */
short int compression_level /* = AL_GREENLEAF_LEVEL_2 */ )
: ALDecompressor( AL_COMPRESSION_GREENLEAF, "Greenleaf" )
{
miCompressionLevel = compression_level;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE hALDecompressor AL_FUNCTION
newALGlDecompressor( short int compression_level ) /* Tag public function */
{
if ( compression_level == AL_DEFAULT )
#if defined( AL_FLAT_MODEL )
compression_level = AL_GREENLEAF_LEVEL_4;
#else
compression_level = AL_GREENLEAF_LEVEL_2;
#endif
return (hALDecompressor)
new ALGlDecompressor( compression_level );
}
#endif
//
// NAME
//
// ALGlDecompressor::~ALGlDecompressor()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// The Greenleaf Decompressor destructor.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// ALGlDecompressor::~ALGlDecompressor()
//
// C SYNOPSIS
//
// None. C programmers need to call deleteALDecompressor().
//
// VB SYNOPSIS
//
// None. VB programmers need to call deleteALDecompressor().
//
// DELPHI SYNOPSIS
//
// None. Delphi programmers need to call deleteALDecompressor().
//
// ARGUMENTS
//
// None.
//
// DESCRIPTION
//
// The destructor for objects of this class doesn't have to do
// anything. In debug mode, we at least check for the validity
// of the object.
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
AL_PROTO
ALGlDecompressor::~ALGlDecompressor() /* Tag public function */
{
AL_ASSERT( GoodTag(), "~ALGlDecompressor: attempt to delete invalid object" );
}
//
// NAME
//
// ALGlDecompressor::Decompress()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Decompress using Greeenleaf's algorithms.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// int ALGlDecompressor::Decompress( ALStorage &input,
// ALStorage &output,
// long compressed_length );
//
// C SYNOPSIS
//
// None, see the base class function ALDecompress().
//
// VB SYNOPSIS
//
// None, see the base class function ALDecompress().
//
// DELPHI SYNOPSIS
//
// None, see the base class function ALDecompress().
//
// ARGUMENTS
//
// input : A reference to the input storage object.
//
// output : A reference to the output storage object.
//
// compressed_length : A long value indicating how long the compressed
// object is. This helps to tell the decompressor
// when to quit.
// DESCRIPTION
//
// This is the virtual function that is called to expand a compressed
// object. This section of code is really just a front end to the real
// engine, which is found in _RE.CPP. The first thing we do here
// is create an RExpand object, which allocates all of the
// storage we need to perform the decompression. In a tight memory
// situation, that may well fail, so we check its status before moving
// on. If it succeeded, we can call the low level expansion function
// to do the real work.
//
// After the expand function returns, we have to check for errors on
// any of the other objects involved in the expansion, and return the
// cumulative result.
//
// This function now properly supports the incompressible option. When
// the type of compression is selectec, via a compression level of
// AL_GREENLEAF_COPY, we just do a straight binary copy here, instead
// of calling the actual compressor.
//
// This function will almost always be called indirectly, by means of
// a virtual function call off the base class. That's why you won't
// see any C, VB, or Delphi functions here. Those languages will only
// be able to call the Compress() routine by way of the base class.
//
// RETURNS
//
// AL_SUCCESS in the event of a success, an error code < AL_SUCCESS
// if a failure occurred.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
int AL_PROTO
ALGlDecompressor::Decompress( ALStorage AL_DLL_FAR &input, /* Tag public function */
ALStorage AL_DLL_FAR &output,
long compressed_length )
{
ALOpenFiles files( input, output );
if ( input.mStatus < 0 )
return mStatus = input.mStatus;
else if ( output.mStatus < 0 )
return mStatus = output.mStatus;
output.InitCrc32();
if ( miCompressionLevel == AL_GREENLEAF_COPY ) {
int c;
for ( ; compressed_length ; compressed_length-- ) {
c = input.ReadChar();
if ( c < 0 )
break;
output.WriteChar( c );
}
} else {
RExpand re( input, output, compressed_length, miCompressionLevel + 10 );
if ( re.mStatus < 0 )
return mStatus = re.mStatus;
else
re.Expand();
if ( re.mStatus < 0 )
return mStatus = re.mStatus;
}
if ( input.mStatus < 0 )
return mStatus = input.mStatus;
else if ( output.mStatus < 0 )
return mStatus = output.mStatus;
return mStatus;
}
//
// NAME
//
// ALGlDecompressor::WriteEngineData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Write the Greenleaf specific engine data to a file.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// int ALGlDecompressor::WriteEngineData( ALStorage *archive );
//
// C SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// VB SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// ARGUMENTS
//
// archive : A pointer to the storage object where the data is to
// be written. Under normal circumstances, this will always
// be either the storage object that holds the archive, or
// the storage object that holds an ALComprepssedObject.
//
// DESCRIPTION
//
// Every decompression engine used in ArchiveLib gets the opportunity
// to store data it needs to save in order to characterize its decompression
// process. The Greenleaf decompression engine only needs to save a single
// integer, which contains the compression level used. This is the
// function that does so.
//
// Data like this is stored in string format, which consists of a single
// short integer describing the number of bytes in the string, followed
// by the string. We store in this portable format so that even a program
// that doesn't know about compression engines would be able to read in
// archive directory data.
//
// RETURNS
//
// AL_SUCCESS if the data was written properly, else an error code
// less than AL_SUCCESS.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
int AL_PROTO
ALGlDecompressor::WriteEngineData( ALStorage AL_DLL_FAR * archive ) /* Tag protected function */
{
archive->WriteGlShort( 2 );
return archive->WriteGlShort( miCompressionLevel );
}
//
// NAME
//
// ALGlDecompressor::ReadEngineData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Read the Greenleaf specific engine data from a file.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// int ALGlCompressor::ReadEngineData( ALStorage *archive );
//
// C SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// VB SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal C++ protected function.
//
// ARGUMENTS
//
// archive : A pointer to the storage object where the data is to
// be read. Under normal circumstances, this will always
// be either the storage object that holds the archive, or
// the storage object that holds an ALCompressedObject.
//
// DESCRIPTION
//
// Every decompression engine used in ArchiveLib gets the opportunity
// to store data it needs to save in order to characterize its decompression
// process. The Greenleaf decompression engine only needs to save a single
// integer, which contains the compression level used.
//
// During the creation of the decompression engine, this function gets called
// in order to load the engine's private data. All we do is read in
// the compression level, along with a little error checking.
//
// Data like this is stored in string format, which consists of a single
// short integer describing the number of bytes in the string, followed
// by the string. We store in this portable format so that even a program
// that doesn't know about decompression engines would be able to read in
// archive directory data.
//
// RETURNS
//
// AL_SUCCESS if the data was read in properly, else an error code
// less than AL_SUCCESS.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
int AL_PROTO
ALGlDecompressor::ReadEngineData( ALStorage AL_DLL_FAR * archive ) /* Tag protected function */
{
short temp;
archive->ReadGlShort( temp );
AL_ASSERT( temp == 2, "ReadEngineData: engine data size is not 2, it should be" );
return archive->ReadGlShort( miCompressionLevel );
}
//
// NAME
//
// ALGlDecompressor::Clone()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Create a copy of an existing Decompressor
//
// C++ SYNOPSIS
//
// #include "arclib.h"
// #include "glengn.h"
//
// ALGlDecompressor::Clone( int engine_type );
//
// C SYNOPSIS
//
// No C equivalent.
//
// VB SYNOPSIS
//
// No VB equivalent.
//
// DELPHI SYNOPSIS
//
// No Delphi equivalent.
//
// ARGUMENTS
//
// engine_type : This argument indicates what sort of engine the
// caller wants to create. A value of either
// AL_COMPRESSION_DEFAULT or AL_COMPRESSION_GREENLEAF
// will cause this function to create a clone. Any other
// value (for example, AL_DEFLATE), will return a 0,
// indicating that this object doesn't know how to
// perform that sort of decompression.
//
// DESCRIPTION
//
// Although this is a public function, it isn't really of any use
// to end users. Clone() is a virtual function for the base class
// ALDecompressor, and can be called to create a duplicate of an
// existing decompression engine.
//
// Why is this useful? It is useful because it allows us to use
// what is the equivalent of a virtual constructor. We can pass a
// pointer to a Greenleaf engine to the archiving code, and it can then in
// turn stuff copies of that engine into an ALEntryList without
// having any idea what sort of compression engine it is actually creating.
//
// RETURNS
//
// A copy of a newly created compression engine. When this routine is
// called, it will usually be called via a virtual function from a pointer
// to a base class object, which means the resulting pointer will be
// treated as an ALDecompressor * by the code.
//
// If this routine doesn't know how to create an engine of the correct type,
// it returns a 0. When performing compression into an archive, the
// Clone() functions will usually be called with the AL_DEFAULT_COMPRESSION
// engine type, meaning they are happy to take a copy of whatever engine
// happens to show up first in the toolkit.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New Release
//
ALDecompressor AL_DLL_FAR * AL_PROTO
ALGlDecompressor::Clone( int engine_type ) const /* Tag public function */
{
switch ( engine_type ) {
case AL_COMPRESSION_DEFAULT :
case AL_COMPRESSION_GREENLEAF :
return new ALGlDecompressor( miCompressionLevel );
}
return 0;
}