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

1476 lines
40 KiB
C++
Executable File

//
// STORAGE.CPP
//
// Source file for ArchiveLib 2.0
//
// Copyright (c) Greenleaf Software, Inc. 1994-1996
// All Rights Reserved
//
// CONTENTS
//
// ALStorage::operator new()
// ALStorage::ALStorage()
// ALStorage::~ALStorage()
// deleteALStorage()
// ALStorage::Open()
// ALStorageOpen()
// ALStorage::Create()
// ALStorageCreate()
// ALStorage::Close()
// ALStorageClose()
// ALStorage::ReadBuffer()
// ALStorageReadBuffer()
// ALStorageReadBufferVB32()
// ALStorage::WriteBuffer()
// ALStorageWriteBuffer()
// ALStorageWriteBufferVB32()
// ALStorage::WriteString()
// ALStorageWriteString()
// ALStorage::ReadString()
// ALStorage::Tell()
// ALStorageTell()
// ALStorage::WriteStorageObjectData()
// ALStorage::ReadStorageObjectData()
// ALStorage::ReadCopyright()
// ALStorageReadCopyright()
// ALStorageReadCopyrightVB()
//
// DESCRIPTION
//
// This file contains all of the source code for the member functions
// of ALStorage. AlStorage has pure virtual functions, so you can't
// ever instantiate one of these guys.
//
// REVISION HISTORY
//
// May 26, 1994 1.0A : First release
//
// July 7, 1994 1.0B : Minor bug fixes
//
// February 14, 1996 2.0A : New release.
//
#include "arclib.h"
#if !defined( AL_IBM )
#pragma hdrstop
#endif
#include "_vbutil.h"
#include <string.h>
//
// NAME
//
// ALStorage::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 * ALStorage::operator new( size_t size )
//
// C SYNOPSIS
//
// None, internal C++ member function.
//
// VB SYNOPSIS
//
// None, internal C++ member function.
//
// DELPHI SYNOPSIS
//
// None, internal C++ member function.
//
// ARGUMENTS
//
// size : The number of bytes that the compiler has decided will be
// necessary to construct a new ALStorage 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.
//
// Note that this function will probably never be called. You can't
// instantiate an ALStorage object, because it has some pure virtual
// functions. So only derived classes get instantiated, and they
// really ought to have their own new operators.
// RETURNS
//
// A pointer to some memory that should have been pulled out of the
// heap for the DLL.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// May 24, 1994 1.0A : First release
//
// February 14, 1996 2.0A : New release.
//
#if defined( AL_BUILDING_DLL )
void AL_DLL_FAR * AL_PROTO
ALStorage::operator new( size_t size ) /* Tag protected function */
{
return ::new char[ size ];
}
#endif
//
// NAME
//
// ALStorage::ALStorage()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// The ALStorage constructor.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// ALStorage::ALStorage( const char *file_name,
// size_t size,
// const enum ALStorageType object_type,
// ALCase name_case = AL_MIXED );
//
// C SYNOPSIS
//
// None, this function is not available to C programmers.
//
// VB SYNOPSIS
//
// None, this function is not available to VB programmers.
//
// DELPHI SYNOPSIS
//
// None, this function is not available to Delphi programmers.
//
// ARGUMENTS
//
// file_name : The name to assign to the mName data member of the
// newly created storage object.
//
// size : The size of the I/O buffer that is going to be used
// for the storage object. ALFile uses 4096 as a default.
//
// object_type : The type of object, as defined in ALDEFS.H. Good
// values include AL_FILE_OBJECT and AL_MEMORY_OBJECT.
//
// name_case : The case sensitivity of the object name. For objects
// such as ALFile, AL_MIXED is a no-no. Those objects
// need to be forced to convert names to all upper
// or all lower, because the operating system considers
// file names to be case insensitive.
//
// DESCRIPTION
//
// The constructor for ALStorage gets called from the constructor of
// derived classes. It has to initialize all sorts of data members.
// First, in the initializer list, it sets up the mName data member,
// as well as muBufferSize and miStorageObjectType. The latter two
// data members are set to be const so I can make them public, which
// means we have to initialize them in the initializer list.
//
// In the body of the constructor, we initialize a bunch of data members,
// none of which mean anything at this point.
//
// RETURNS
//
// Nothing, it is a constructor.
//
// EXAMPLE
//
// N/A, not part of the public API.
//
// SEE ALSO
//
// ALFile::ALFile(), ALMemory::ALMemory()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
AL_PROTO
ALStorage::ALStorage( const char AL_DLL_FAR *file_name, /* Tag public function */
size_t size,
const enum ALStorageType object_type,
ALCase name_case /* = AL_MIXED */ )
: mName( file_name, name_case ),
miStorageObjectType( object_type ),
muBufferSize( size )
{
mpcBuffer = 0;
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlCrc32 = 0xffffffffL;
mlSize = -1L;
mpMonitor = 0;
miCreated = 0;
if ( mName.GetName() == 0 )
mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in "
"ALStorage constructor" );
}
//
// NAME
//
// ALStorage::~ALStorage()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// The ALStorage destructor.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// ALStorage::~ALStorage();
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// void deleteALStorage( hALStorage this_object );
//
// VB SYNOPSIS
//
// Declare Sub deleteALStorage Lib "AL20LW" (ByVal this_object&)
//
// DELPHI SYNOPSIS
//
// procedure deleteALStorage( this_object : hALStorage );
//
// ARGUMENTS
//
// this_object : A handle for (pointer to) the storage object that
// is going to be destroyed. Note that the C++ version
// of this function doesn't have this argument, since it
// has implicit access to 'this'.
//
// DESCRIPTION
//
// In debug mode, we first check to make sure we are destroying the
// right type of object.
//
// The only thing left to do is free up the I/O buffer if it is still
// allocated. This piece of work probably isn't necessary. Since this
// is a virtual destructor, we will be called after the destructors
// for the derived class. Any derived class that is doing its job
// will make sure that it calls Close() before destroying itself. If
// it doesn't, it will probably be leaving unfinished business behind
// that we aren't going to be able to deal with here. Even so, we will
// be diligent in our attention to detail.
//
//
// RETURNS
//
// Nothing.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
AL_PROTO
ALStorage::~ALStorage() /* Tag public function */
{
AL_ASSERT( GoodTag(), "~ALStorage: attempting to delete invalid object" );
if ( mpcBuffer )
Close();
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE void AL_FUNCTION
deleteALStorage( hALStorage this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALStorage, "deleteALStorage" );
delete (ALStorage *) this_object;
}
#endif
//
// NAME
//
// ALStorage::Open()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Open a storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::Open()
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorageOpen( hALStorage this_object )
//
// VB SYNOPSIS
//
// Declare Function ALStorageOpen Lib "AL20LW"
// (ByVal this_object&) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageOpen( this_object : hALStorage ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to be opened. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// DESCRIPTION
//
// Any derived class needs to have its own Open() function. However,
// the derived class can also call this Open() function in the base
// class to do some odds and ends for it. The most important thing it
// does is allocate the I/O buffer, which is what makes ALStorage a
// relatively fast way to read and write data. Although the buffer
// is in place, there is no data in it, so this guy also sets up the
// indices and pointers to reflect that.
//
// Upon exit, all you need to to is start reading or writing, and the
// whole thing should be ready to go.
//
// RETURNS
//
// AL_SUCCESS, or AL_CANT_OPEN_BUFFER on memory allocation failure.
// If the object was already in an error state, it is very possible to
// get some other error code < 0.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::Create(), ALStorage::Close()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::Open() /* Tag public function */
{
if ( mStatus < AL_SUCCESS )
return mStatus;
if ( muBufferSize != 0 )
mpcBuffer = new unsigned char[ muBufferSize ];
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlCrc32 = 0xffffffffL;
if ( mpcBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in Open()" );
return AL_SUCCESS;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE int AL_FUNCTION
ALStorageOpen( hALStorage this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageOpen" );
return ( (ALStorage *) this_object )->Open();
}
#endif
//
// NAME
//
// ALStorage::Create();
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Create a new storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::Create( long desired_size = - 1 );
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorageCreate( hALStorage this_object, long desired_size );
//
// VB SYNOPSIS
//
// Declare Function ALStorageCreate Lib "AL20LW"
// (ByVal this_object&, ByVal desired_size&) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageCreate( this_object : hALStorage;
// desired_size : Long ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to be created. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// desired_size : If you know in advance how much space a storage object
// is going to occupy, you can pass that number as the
// desired_size argument. Some storage types, such as
// ALMemory, can make good use of this information. Others
// such as ALFile, could care less. In any case, the base
// class, ALStorage, ignores the info. If you don't know
// how many bytes the storage object is going to need,
// pass a -1L as the argument.
//
// DESCRIPTION
//
// This function is nearly identical to ALStorage::Open().
//
// Any derived class needs to have its own Create() function. However,
// the derived class can also call this Create() function in the base
// class to do some odds and ends for it. The most important thing it
// does is allocate the I/O buffer, which is what makes ALStorage a
// relatively fast way to read and write data. Although the buffer
// is in place, there is no data in it, so this guy also sets up the
// indices and pointers to reflect that.
//
// RETURNS
//
// AL_SUCCESS, or AL_CANT_OPEN_BUFFER on memory allocation failure.
// If the object was already in an error state, it is very possible to
// get some other error code < 0.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::Delete(), ALStorage::Open()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::Create( long /* desired_size = - 1 */ ) /* Tag public function */
{
if ( mStatus < AL_SUCCESS )
return mStatus;
mpcBuffer = new unsigned char[ muBufferSize ];
muBufferValidData = 0;
muWriteIndex = 0;
muReadIndex = 0;
mlFilePointer = 0;
miUpdateCrcFlag = 0;
mlSize = 0; //If the file has been opened previously, mlSize might be non-zero
mlCrc32 = 0xffffffffL;
miCreated = 1;
if ( mpcBuffer == 0 )
return mStatus.SetError( AL_CANT_OPEN_BUFFER,
"Allocation of buffer failed in Open()" );
return AL_SUCCESS;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE int AL_FUNCTION
ALStorageCreate( hALStorage this_object, /* Tag public function */
long desired_size )
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageCreate" );
if ( desired_size == AL_DEFAULT )
desired_size = -1;
return ( (ALStorage *) this_object )->Create( desired_size );
}
#endif
//
// NAME
//
// ALStorage::Close()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Close an ALStorage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::Close();
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorageClose( hALStorage this_object );
//
// VB SYNOPSIS
//
// Declare Function ALStorageClose Lib "AL20LW"
// (ByVal this_object&) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageClose( this_object : hALStorage ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to be closed. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// DESCRIPTION
//
// Just like with Open(), most derived classes will have their own
// versions of Close(). They can call this version to delete the I/O
// buffer if they feel like it is too hard to do themselves.
//
// RETURNS
//
// The current integer status of the object. Hopefully this will be
// AL_SUCCESS, but it could well be a value < AL_SUCCESS.
//
// EXAMPLE
//
// SEE ALSO
//
// ALFile::Create(), ALFile::Open()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::Close() /* Tag public function */
{
if ( mpcBuffer ) {
delete[] mpcBuffer;
mpcBuffer = 0;
}
return mStatus;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE int AL_FUNCTION
ALStorageClose( hALStorage this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageClose" );
return ( (ALStorage *) this_object )->Close();
}
#endif
//
// NAME
//
// ALStorage::ReadBuffer()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Read in a buffer full of data.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// size_t ALStorage::ReadBuffer( unsigned char *buf, size_t length );
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// size_t ALStorageReadBuffer( hALStorage this_object,
// unsigned char *buffer,
// size_t length );
//
// VB SYNOPSIS
//
// Declare Function ALStorageReadBuffer Lib "AL20LW"
// (ByVal this_object&, ByVal buffer$, ByVal length%) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageReadBuffer( this_object : hALStorage;
// buffer : PChar;
// length : Integer ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to be read. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// buf : The buffer that is going to receive input characters.
//
// length : The number of bytes you want to read.
//
// DESCRIPTION
//
// We could write a simple version of this function by just calling
// ReadChar() over and over, but it would be nice to do things
// a little more efficiently. Since we have this nice big buffer
// full of data ready to read, it makes sense to copy big chunks of
// it in one fell swoop. That is what this guy does. It sits in a loop
// doing a memcpy() followed by LoadBuffer() until all of the data
// that has been asked for got moved. As data is read in, we have to
// update the data member muReadIndex. Other data members will get
// updated by LoadBuffer().
//
// RETURNS
//
// The number of bytes read in, always. If this function generates an
// error, it will be found in the mStatus member.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::ReadChar(), ALStorage::WriteBuffer()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
size_t AL_PROTO
ALStorage::ReadBuffer( unsigned char AL_DLL_FAR *buf, /* Tag public function */
size_t length )
{
size_t bytes_left_to_read = length;
size_t buffer_bytes_available;
while ( bytes_left_to_read ) {
buffer_bytes_available = muBufferValidData - muReadIndex;
if ( buffer_bytes_available == 0 ) {
if ( LoadBuffer( mlFilePointer ) < 0 )
return length - bytes_left_to_read;
buffer_bytes_available = muBufferValidData;
}
if ( bytes_left_to_read <= buffer_bytes_available ) {
memcpy( buf, mpcBuffer + muReadIndex, bytes_left_to_read );
muReadIndex += bytes_left_to_read;
return length;
} else {
memcpy( buf, mpcBuffer + muReadIndex, buffer_bytes_available );
buf += buffer_bytes_available;
bytes_left_to_read -= buffer_bytes_available;
muReadIndex += buffer_bytes_available;
if ( LoadBuffer( mlFilePointer ) < 0 )
return length - bytes_left_to_read;
}
}
return length;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE size_t AL_FUNCTION
ALStorageReadBuffer( hALStorage this_object, /* Tag public function */
unsigned char AL_DLL_FAR *buffer,
size_t length )
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadBuffer" );
AL_ASSERT( buffer != 0, "Passed a null buffer to ALStorageReadBuffer" );
return ( (ALStorage * ) this_object )->ReadBuffer( buffer, length );
}
#endif
#if defined( AL_VB32 )
extern "C" AL_LINKAGE size_t AL_FUNCTION
ALStorageReadBufferVB32( hALStorage this_object, /* Tag public function */
LPSAFEARRAY *ppsa,
size_t length )
{
unsigned char *p;
size_t result;
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageReadBufferVB32" );
AL_ASSERT( SafeArrayGetDim( *ppsa ) > 0, "Array with < 1 dimensions in ALStorageWriteBufferVB32" );
//
// This doesn't work, don't know why
//
// int j = SafeArrayGetElemsize( *ppsa );
// wsprintf( buffer, "Array dim = %d j = %d length = %d", i, j, length );
// char buffer[ 81 ];
// MessageBox( 0, buffer, buffer, MB_OK );
// AL_ASSERT( j >= (int) length, "Buffer too small in ALStorageReadBufferVB32" );
// int j =
SafeArrayAccessData( *ppsa, (void **) &p );
result = ( (ALStorage * ) this_object )->ReadBuffer( p, length );
SafeArrayUnaccessData( *ppsa );
return result;
}
#endif
//
// NAME
//
// ALStorage::WriteBuffer()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Write a buffer to a storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// size_t ALStorage::WriteBuffer( const unsigned char *buf,
// size_t length );
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// size_t ALStorageWriteBuffer( hALStorage this_object,
// unsigned char *buffer,
// size_t length );
//
// VB SYNOPSIS
//
// Declare Function ALStorageWriteBuffer Lib "AL20LW"
// (ByVal this_object&, ByVal buffer$, ByVal length%) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageWriteBuffer( this_object : hALStorage;
// buffer : PChar;
// length : Integer ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to be written to. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// buf : The buffer that is contains the output data.
//
// length : The number of bytes you want to write.
//
// DESCRIPTION
//
// We could write a simple version of this function by just calling
// WriteChar() over and over, but it would be nice to do things
// a little more efficiently. Since we have this nice big buffer
// just waiting for data, it makes sense to copy big chunks to
// it in one fell swoop. That is what this guy does. It sits in a loop
// doing a memcpy() followed by FlushBuffer() until all of the data
// that was ready to go has been sent. As data is written, we have to
// update the data member muWriteIndex. Other data members will get
// updated by FlushBuffer().
//
// RETURNS
//
// The number of bytes written, always. If this function generates an
// error, it will be found in the mStatus member.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::WriteChar(), ALStorage::ReadBuffer()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
size_t AL_PROTO
ALStorage::WriteBuffer( const unsigned char AL_DLL_FAR *buf, /* Tag public function */
size_t length )
{
size_t buffer_bytes_free;
size_t write_bytes_left = length;
if ( mStatus < 0 )
return 0;
while ( write_bytes_left > 0 ) {
buffer_bytes_free = muBufferSize - muWriteIndex;
if ( buffer_bytes_free == 0 ) {
if ( FlushBuffer() < 0 )
return length - write_bytes_left;
buffer_bytes_free = muBufferSize;
}
if ( write_bytes_left <= buffer_bytes_free ) {
memcpy( mpcBuffer + muWriteIndex, buf, write_bytes_left );
muWriteIndex += write_bytes_left;
return length;
} else {
memcpy( mpcBuffer + muWriteIndex, buf, buffer_bytes_free );
muWriteIndex += buffer_bytes_free;
buf += buffer_bytes_free;
write_bytes_left -= buffer_bytes_free;
if ( FlushBuffer() < 0 )
return length - write_bytes_left;
}
}
return length;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE size_t AL_FUNCTION
ALStorageWriteBuffer( hALStorage this_object, /* Tag public function */
unsigned char AL_DLL_FAR *buffer,
size_t length )
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteBuffer" );
AL_ASSERT( buffer != 0, "Passed a null buffer to ALStorageWriteBuffer" );
return ( (ALStorage * ) this_object )->WriteBuffer( buffer, length );
}
#endif
#if defined( AL_VB32 )
extern "C" AL_LINKAGE size_t AL_FUNCTION
ALStorageWriteBufferVB32( hALStorage this_object, /* Tag public function */
LPSAFEARRAY *ppsa,
size_t length )
{
unsigned char *p;
size_t result;
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteBufferVB32" );
AL_ASSERT( SafeArrayGetDim( *ppsa ) > 0, "Array with < 1 dimensions in ALStorageWriteBufferVB32" );
// i = SafeArrayGetElemsize( *ppsa );
// AL_ASSERT( i >= (int)length, "Buffer too small in ALStorageWriteBufferVB32" );
// int j =
SafeArrayAccessData( *ppsa, (void **) &p );
result = ( (ALStorage * ) this_object )->WriteBuffer( p, length );
SafeArrayUnaccessData( *ppsa );
return result;
}
#endif
//
// NAME
//
// ALStorage::WriteString()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Write a null terminated string to a storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::WriteString( const char AL_DLL_FAR *string_data );
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorageWriteString( hALStorage this_object,
// char *string );
//
// VB SYNOPSIS
//
// Declare Function ALStorageWriteString Lib "AL20LW"
// (ByVal this_object&, ByVal string_data$) As Integer
//
// DELPHI SYNOPSIS
//
// function ALStorageWriteString( this_object : hALStorage;
// string_data : PChar ) : Integer;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to have a string written to it. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// string_data : A C-style null terminated string to be written out in
// our portable format.
//
// DESCRIPTION
//
// We write random length data to archive directories using this special
// format, which is a 16 bit int describing the length of the data,
// followed by the data itself. All of the storage objects and compression
// engines write their own private data out using this format. This
// means that even if another class doesn't understand the content of data
// stored in this format, at least it knows how to read it in so as to
// move past it.
//
// This function won't write just any random data, it is specifically
// oriented towards C strings. This means it is mostly used to write
// file names and comments. Their are a few places where classes
// write private data that isn't kept in C strings, they just manually
// write the length with WriteGlShort(), followed by the data.
//
// RETURNS
//
// AL_SUCCESS if things work, or an error code < AL_SUCCESS if an error
// occurs writing the data out.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::ReadString()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::WriteString( const char AL_DLL_FAR *string_data ) /* Tag public function */
{
short unsigned int len;
if ( string_data != 0 )
len = (short unsigned int) strlen( string_data );
else
len = 0;
WriteGlShort( len );
if ( len )
WriteBuffer( (unsigned char *) string_data, len );
return mStatus;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE int AL_FUNCTION
ALStorageWriteString( hALStorage this_object, /* Tag public function */
char AL_DLL_FAR *string )
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageWriteString" );
AL_ASSERT( string != 0, "Passing null string in ALStorageWriteString()" );
return ( (ALStorage *) this_object )->WriteString( string );
}
#endif
//
// NAME
//
// ALStorage::ReadString()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Read a string from a storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::ReadString( ALName &name,
// short int length = -1 );
//
// C SYNOPSIS
//
// None, we have problems with this in C/VB/Delphi.
//
// VB SYNOPSIS
//
// None, we have problems with this in C/VB/Delphi.
//
// DELPHI SYNOPSIS
//
// None, we have problems with this in C/VB/Delphi.
//
// ARGUMENTS
//
// name : A reference to the storage object that is going to be loaded
// up with a string. Note that using an ALName object is a good
// thing here, because we are going to have to dynamically allocate
// data based on how long the input string is. If we returned a
// char *, we would have problems, because the pointer would be
// allocated inside the DLL, but the user would have to free it
// outside the DLL. With an ALName, the data will be freed inside
// the DLL when the ALName object is destroyed.
//
// We can't pass around this ALName object to C/VB/Delphi, so they
// don't get access to this function. Sorry.
//
// length : Normally, you read the length in from the storage object,
// and then read in the data. But sometimes, you know the
// length in advance, and don't want to read it from the
// storage object. In that case, pass the length in this arg.
// O/w, pass -1.
//
// DESCRIPTION
//
// This function is used internally by ArchiveLib. It is used to read
// random length blocks of data out of archives (or other storage objects).
//
// RETURNS
//
// AL_SUCCESS, or not.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::WriteString()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::ReadString( ALName AL_DLL_FAR &name, /* Tag public function */
short int length /* = -1 */ )
{
if ( length == -1 ) {
if ( ReadGlShort( length ) < 0 )
return mStatus.SetError( AL_READ_ERROR,
"Error reading string length"
"in ReadString() for object %s",
mName.GetSafeName() );
}
char *new_string = new char[ length + 1 ];
if ( new_string ) {
ReadBuffer( (unsigned char *) new_string, length );
new_string[ length ] = '\0';
name = new_string;
delete[] new_string;
return AL_SUCCESS;
}
return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
"Error allocating buffer space in call "
"to ReadString() for object %s",
mName.GetSafeName() );
}
//
// NAME
//
// ALStorage::Tell()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Return the current offset in the storage object.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// long ALStorage::Tell();
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// long ALStorageTell( hALStorage this_object );
//
// VB SYNOPSIS
//
// Declare Function ALStorageTell Lib "AL20LW"
// (ByVal this_object&) As Long
//
// DELPHI SYNOPSIS
//
// function ALStorageTell( this_object : hALStorage ) : LongInt;
//
// ARGUMENTS
//
// this_object : A reference or pointer to the ALStorage object that
// is going to have its offset returned. Note that the C++
// version of this call doesn't have an explicit argument
// here, since it has access to 'this' implicitly.
//
// DESCRIPTION
//
// Because we are using buffered I/O here, figuring out the current
// position of the read write pointer is just a tiny bit more complicated
// than just checking a pointer. We have to find the physical location of
// the file pointer, then add in any offset created by the presence of
// data in the I/O buffer.
//
// RETURNS
//
// A long integer indicating the current position of the read/write
// pointer for the file.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::Seek(), ALStorage::WriteBuffer()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
long AL_PROTO
ALStorage::Tell() /* Tag public function */
{
if ( muWriteIndex )
return mlFilePointer + muWriteIndex;
else
return mlFilePointer - muBufferValidData + muReadIndex;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE long AL_FUNCTION
ALStorageTell( hALStorage this_object ) /* Tag public function */
{
AL_ASSERT_OBJECT( this_object, ALStorage, "ALStorageTell" );
return ( (ALStorage *) this_object )->Tell();
}
#endif
//
// NAME
//
// ALStorage::WriteStorageObjectData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Write out class-specific storage object data.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::WriteStorageObjectData( ALStorage * archive );
//
// C SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// VB SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// ARGUMENTS
//
// archive : A pointer to the storage object where we are going to
// write the private data.
//
// DESCRIPTION
//
// All storage objects have the ability to create a private data block
// that will be stored along with the directory when creating an archive.
// None of the classes predefined in ArchiveLib use this data block, which
// means they use this function instead of providing their own virtual
// substitute. This function writes a private data block of exactly 0
// bytes in length. Our internal storage format means that a block
// of 0 bytes length takes 2 bytes to store.
//
// RETURNS
//
// AL_SUCCESS if things went okay, otherwise an error code < AL_SUCCESS.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::WriteStorageObjectData( ALStorage AL_DLL_FAR * archive ) /* Tag public function */
{
return archive->WriteGlShort( 0 );
}
//
// NAME
//
// ALStorage::ReadStorageObjectData()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++
//
// SHORT DESCRIPTION
//
// Read in class specific data from an archive.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// int ALStorage::ReadStorageObjectData( ALStorage * archive );
//
// C SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// VB SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// DELPHI SYNOPSIS
//
// None, this is an internal callback virtual function.
//
// ARGUMENTS
//
// archive : A pointer to the storage object where we are going to
// read in the private data..
//
// DESCRIPTION
//
// All storage objects have the ability to create a private data block
// that will be stored along with the directory when creating an archive.
// None of the classes predefined in ArchiveLib use this data block, which
// means they use this function instead of providing their own virtual
// substitute. This function reads a private data block of exactly 0
// bytes in length. Our internal storage format means that a block
// of 0 bytes length takes 2 bytes to store.
//
// In debug mode, we get really bent out of shape if this data block
// doesn't look exactly like we expect it to.
//
// RETURNS
//
// AL_SUCCESS if things went okay, otherwise an error code < AL_SUCCESS.
//
// EXAMPLE
//
// SEE ALSO
//
// ALStorage::WriteStorageObjectData()
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
int AL_PROTO
ALStorage::ReadStorageObjectData( ALStorage AL_DLL_FAR * archive ) /* Tag public function */
{
short int temp;
int status = archive->ReadGlShort( temp );
AL_ASSERT( temp == 0, "ReadStorageObjectData: stored data is not null" );
return status;
}
//
// NAME
//
// ALStorage::ReadCopyright()
//
// PLATFORMS/ENVIRONMENTS
//
// Console Windows PM
// C++ C VB Delphi
//
// SHORT DESCRIPTION
//
// Read a copyright string for human display.
//
// C++ SYNOPSIS
//
// #include "arclib.h"
//
// char * ALStorage::ReadCopyright();
//
// C SYNOPSIS
//
// #include "arclib.h"
//
// char * ALReadCopyright( void );
//
// VB SYNOPSIS
//
// Declare Function ALReadCopyright Lib "AL20FW"
// Alias "ALReadCopyrightVB"
// As String
//
// DELPHI SYNOPSIS
//
// function ALReadCopyright : PChar;
//
// ARGUMENTS
//
// None. Note that we don't have the usual this_object argument, because
// this is a static function. It's only in the ALStorage class to avoid
// name space clutter.
//
// DESCRIPTION
//
// It is a good idea for us to have a copyright notice embedded in the
// library. Hopefully, this notice will show up in any executables linked
// using this library, or in the DLL they link to.
//
// RETURNS
//
// A pointer to a copyright notice.
//
// EXAMPLE
//
// SEE ALSO
//
// REVISION HISTORY
//
// February 14, 1996 2.0A : New release.
//
char *_al_copyright = "Copyright (c) 1994-1996 Greenleaf Software, Inc.\n"
"All Rights Reserved.\n";
char AL_DLL_FAR * AL_PROTO
ALStorage::ReadCopyright() /* Tag public function */
{
return _al_copyright;
}
#if !defined( AL_NO_C )
extern "C" AL_LINKAGE char AL_DLL_FAR * AL_FUNCTION
ALReadCopyright( void ) /* Tag public function */
{
return _al_copyright;
}
#if defined( AL_VB )
extern "C" AL_LINKAGE long AL_FUNCTION
ALReadCopyrightVB( void ) /* Tag public function */
{
return ALCreateVBString( _al_copyright,
(unsigned short int) _fstrlen( _al_copyright ) );
}
#elif defined( AL_VB32 )
extern "C" AL_LINKAGE BSTR AL_FUNCTION
ALReadCopyrightVB( void ) /* Tag public function */
{
return SysAllocStringByteLen( _al_copyright, strlen( _al_copyright ) );
}
#endif /* #if defined( AL_VB ) */
#endif /* #if !defined( AL_NO_C ) */