1007 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1007 lines
		
	
	
		
			25 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// MEMSTORE.CPP
 | 
						|
//
 | 
						|
//  Source file for ArchiveLib 2.0
 | 
						|
//
 | 
						|
//  Copyright (c) Greenleaf Software, Inc. 1996
 | 
						|
//  All Rights Reserved
 | 
						|
//
 | 
						|
// CONTENTS
 | 
						|
//
 | 
						|
//  ALMemoryBase::operator new()
 | 
						|
//  ALMemoryBase::ALMemoryBase()
 | 
						|
//  ALMemoryBase::~ALMemoryBase()
 | 
						|
//  ALMemoryBase::LoadBuffer()
 | 
						|
//  ALMemoryBase::Rename()
 | 
						|
//  ALMemoryBase::RenameToBackup()
 | 
						|
//  ALMemoryBase::UnRename()
 | 
						|
//  ALMemoryBase::Seek()
 | 
						|
//  ALMemoryBase::FlushBuffer()
 | 
						|
//  ALMemoryBase::Close()
 | 
						|
//  ALMemoryBase::Create()
 | 
						|
//  ALMemoryBase::Open()
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This file contains all the C++ member functions to support the
 | 
						|
//  ALMemoryBase class.  ALMemoryBase doesn't do anything on its
 | 
						|
//  own.  It instead provides a framework for the three derived
 | 
						|
//  memory classes: ALWinMemory, ALMemory, and ALHugeMemory.
 | 
						|
//
 | 
						|
//  The only thing those classes do that ALMemory can't do is to
 | 
						|
//  allocate, free, and copy memory.  Since each of three classes
 | 
						|
//  has their own pointer type, that has to be viewed here as an
 | 
						|
//  abstraction.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#if !defined( AL_IBM )
 | 
						|
#pragma hdrstop
 | 
						|
#endif
 | 
						|
 | 
						|
#include "memstore.h"
 | 
						|
 | 
						|
//
 | 
						|
// Need this for malloc()
 | 
						|
//
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::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"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  void * ALMemoryBase::operator new( size_t size )
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal C++ function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  size  :  The number of bytes that the compiler has decided will be
 | 
						|
//           necessary to construct a new ALMemoryBase 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.
 | 
						|
//
 | 
						|
//  Very important:  this new operator is called to allocate the
 | 
						|
//  storage for the ALMemoryBase object itself.  This has nothing to do
 | 
						|
//  with the storage buffer that the memory object will be using
 | 
						|
//  later on.  In other words, this new operator is responsible for
 | 
						|
//  no more than a couple of dozen bytes, not potentially hundreds
 | 
						|
//  of Kbytes.
 | 
						|
//
 | 
						|
// 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
 | 
						|
ALMemoryBase::operator new( size_t size )  /* Tag internal function */
 | 
						|
{
 | 
						|
    return ::new char[ size ];
 | 
						|
}
 | 
						|
 | 
						|
#endif
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::ALMemoryBase()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  The base class constructor for ALMemory objects.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  ALMemoryBase::ALMemoryBase( const char *buffer_name = "",
 | 
						|
//                              ALCase name_case = AL_MIXED );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal class.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal class.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is an internal class.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  buffer_name  : An arbitrary name assigned to the buffer.  Buffer
 | 
						|
//                 names don't have to be unique, because buffers aren't
 | 
						|
//                 named at the operating system level.  But if you are
 | 
						|
//                 going to insert the storage object into an archive, the
 | 
						|
//                 name needs to be unique so that you will be able to
 | 
						|
//                 extract it properly.
 | 
						|
//
 | 
						|
//  name_case    : This decides whether you want the file name to be
 | 
						|
//                 case sensitive when making comparisons.  MS-DOS
 | 
						|
//                 file names are case-insensitive.  You can make memory
 | 
						|
//                 buffers either mixed case, forced upper, or forced
 | 
						|
//                 lower.  The default of mixed case means that comparisons
 | 
						|
//                 will be case sensitive, which is fine.
 | 
						|
//
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  There are three different memory base storage objects in ArchiveLib
 | 
						|
//  2.0: ALMemory, ALWinMemory, and ALHugeMemory.  The only substantial
 | 
						|
//  difference between these three is in the pointer type they use to
 | 
						|
//  point to their memory buffer.  So they can share a lotta code.  That
 | 
						|
//  code is all combined into a single base class, ALMemoryBase.  The
 | 
						|
//  base class code has to rely on a few virtual functions to take over
 | 
						|
//  when pointer manipulation is needed.
 | 
						|
//
 | 
						|
//  This constructor doesn't do anything except pass the appropriate
 | 
						|
//  initialization information on to the base class constructor.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO
 | 
						|
ALMemoryBase::ALMemoryBase(  /* Tag public function */
 | 
						|
    const char AL_DLL_FAR *buffer_name /* = "" */,
 | 
						|
    ALCase name_case /* = AL_MIXED */ )
 | 
						|
        : ALStorage( buffer_name, 4096, AL_MEMORY_OBJECT, name_case )
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::~ALMemoryBase()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  The destructor for the base memory storage class.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  ALMemoryBase::~ALMemoryBase();
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, destroy using base class function deleteALStorage().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, destroy using base class function deleteALStorage().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, destroy using base class function deleteALStorage().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  The most important thing memory objects have to do in their destructor
 | 
						|
//  is free up the big buffer that underlies the object.  This has to be
 | 
						|
//  handled by the derived classes, since only they know how to handle
 | 
						|
//  specific pointer types.  That leaves this destructor with not much
 | 
						|
//  to do!
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Nothing.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
AL_PROTO
 | 
						|
ALMemoryBase::~ALMemoryBase()  /* Tag public function */
 | 
						|
{
 | 
						|
    AL_ASSERT( GoodTag(), "~ALMemoryBase: attempting to delete invalid object" );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::LoadBuffer();
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Load a new batch of data from the big buffer into the I/O buffer.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::LoadBuffer( long address );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is a protected C++ internal function.
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is a protected C++ internal function.
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, this is a protected C++ internal function.
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  address      :  The desired offset in the storage object to load from.
 | 
						|
//                  This is used to calculate a simple offset into the
 | 
						|
//                  big buffer.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is a virtual function the ALStorage functions rely on when reading
 | 
						|
//  data.  Anytime someone tries to do a ReadChar() or ReadBuffer(), and
 | 
						|
//  it turns out that the I/O buffer has been exhausted, this function
 | 
						|
//  is called.
 | 
						|
//
 | 
						|
//  The simple job of this function is to read as many bytes as possible out
 | 
						|
//  of the giant memory block allocated for the derived class object, and stick
 | 
						|
//  it into the I/O buffer, which caches it for calls to ReadChar()
 | 
						|
//  and friends.
 | 
						|
//
 | 
						|
//  This works fine unless you try to go past the end of the buffer,
 | 
						|
//  since there is nothing there we flag that as an error.
 | 
						|
//
 | 
						|
//  This function takes care of lots of member data maintenance, but the
 | 
						|
//  one thing it won't do is actually load the data from the big buffer.
 | 
						|
//  It has to use the virtual function _LoadBuffer() in the derived class
 | 
						|
//  to to actually move data out of the big buffer and into the I/O buffer.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SEEK_ERROR if we try to read past the end of file.  AL_END_OF_FILE
 | 
						|
//  if we just run out of data.  Otherwise an int indicating how many bytes
 | 
						|
//  are now in the buffer.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::LoadBuffer( long address )  /* Tag protected function */
 | 
						|
{
 | 
						|
    if ( mStatus < AL_SUCCESS )
 | 
						|
        return mStatus;
 | 
						|
    if ( mlFilePointer != address ) {
 | 
						|
        if ( mlFilePointer > mlUserBufferSize )
 | 
						|
            return mStatus.SetError( AL_SEEK_ERROR,
 | 
						|
                                     "Attempt to read past end of the "
 | 
						|
                                     "buffer in ALMemoryBase %s",
 | 
						|
                                     mName.GetName() );
 | 
						|
    }
 | 
						|
    long load = mlUserBufferSize - address;
 | 
						|
    if ( load > (long) muBufferSize )
 | 
						|
        muBufferValidData = muBufferSize;
 | 
						|
    else
 | 
						|
        muBufferValidData = (size_t) load;
 | 
						|
    if ( muBufferValidData <= 0 ) {
 | 
						|
        muReadIndex = 0;
 | 
						|
        return AL_END_OF_FILE;
 | 
						|
    }
 | 
						|
    _LoadBuffer( address );
 | 
						|
    if ( miUpdateCrcFlag )
 | 
						|
        UpdateCrc( muBufferValidData );
 | 
						|
    muReadIndex = 0; //Reading can resume at this location
 | 
						|
    mlFilePointer += muBufferValidData;
 | 
						|
    YieldTime();
 | 
						|
    return muBufferValidData;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::Rename()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Rename a memory storage object.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::Rename( const char *new_name = 0,
 | 
						|
//                            int delete_on_clash = 1 );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  Use the base class function ALStorageRename().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  Use the base class function ALStorageRename().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  Use the base class function ALStorageRename().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  new_name        : The new name of the buffer.
 | 
						|
//
 | 
						|
//  delete_on_clash : This argument makes sense with files.  What it says
 | 
						|
//                    is that if you try to rename BOB.DAT to BOB.BAK,
 | 
						|
//                    and it turns out that there is another BOB.BAK, should
 | 
						|
//                    you delete the other one?  With memory buffers,
 | 
						|
//                    there is no clash, cause the OS doesn't care about
 | 
						|
//                    unique names.  So we ignore this parm.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This function is supposed to rename the underlying physical object.
 | 
						|
//  But in the case of memory buffers, the underlying physical object
 | 
						|
//  doesn't actually have a name, so this is really just a local rename.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Always returns AL_SUCCESS.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::Rename( const char AL_DLL_FAR *new_name /* = 0 */,  /* Tag public function */
 | 
						|
                      int /* delete_on_clash = 1 */ )
 | 
						|
{
 | 
						|
    if ( new_name )
 | 
						|
        mName = new_name;
 | 
						|
    return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::RenameToBackup()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Renames the storage object to a backup name.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::RenameToBackup( int delete_on_clash /* = 1 */ )
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  C programs should use the base class function ALStorageRenameToBackup().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  VB programs should use the base class function ALStorageRenameToBackup().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  Delphi programs should use the base class function
 | 
						|
//  ALStorageRenameToBackup().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  delete_on_clash : This argument makes sense with files.  What it says
 | 
						|
//                    is that if you try to rename BOB.DAT to BOB.BAK,
 | 
						|
//                    and it turns out that there is another BOB.BAK, should
 | 
						|
//                    you delete the other one?  With memory buffers,
 | 
						|
//                    there is no clash, cause the OS doesn't care about
 | 
						|
//                    unique names.  So it doesn't matter what value you
 | 
						|
//                    pass to the Rename() function, it is going to be
 | 
						|
//                    ignored.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This function renames an object.  But instead of making you sweat in
 | 
						|
//  order to come up with a new name, it just uses the default name
 | 
						|
//  that we use to assign a backup name.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Always returns AL_SUCCESS.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::RenameToBackup( int delete_on_clash /* = 1 */ )  /* Tag public function */
 | 
						|
{
 | 
						|
    mName.ChangeExtension();
 | 
						|
    return Rename( 0, delete_on_clash );
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::UnRename()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Restore the old name of the object.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::UnRename( int delete_on_clash = 1 );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  C programs use the base class function ALStorageUnRename().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  VB programs use the base class function ALStorageUnRename().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  Delphi programs use the base class function ALStorageUnRename().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  delete_on_clash : This argument makes sense with files.  What it says
 | 
						|
//                    is that if you try to rename BOB.DAT to BOB.BAK,
 | 
						|
//                    and it turns out that there is another BOB.BAK, should
 | 
						|
//                    you delete the other one?  With memory buffers,
 | 
						|
//                    there is no clash, cause the OS doesn't care about
 | 
						|
//                    unique names.  So we just ignore it here.
 | 
						|
//
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  If you decide you didn't really want to rename an object after all, you
 | 
						|
//  can call this function to get the old name back!  It takes advantage of
 | 
						|
//  the fact that ALName objects always remember their old name after getting
 | 
						|
//  a new one.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  Always returns AL_SUCCESS.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::UnRename( int /* delete_on_clash = 1 */)  /* Tag public function */
 | 
						|
{
 | 
						|
    AL_ASSERT( mName.GetName() != 0, "UnRename: trying to rename with a null name" );
 | 
						|
    AL_ASSERT( mName.GetOldName() != 0, "UnRename: trying to rename with a null old name" );
 | 
						|
    AL_ASSERT( strlen( mName ) > 0, "UnRename: trying to rename with a zero length name"  );
 | 
						|
    AL_ASSERT( strlen( mName.GetOldName() ) > 0, "UnRename: trying to rename with a zero length old name" );
 | 
						|
 | 
						|
    ALStorage::mName = mName.GetOldName();
 | 
						|
    return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::Seek()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Seek to a specified offset in the big memory buffer.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::Seek( long address );
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  C programs should use the base class functin ALStorageSeek().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  VB programs should use the base class functin ALStorageSeek().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  Delphi programs should use the base class functin ALStorageSeek().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  address  :  The address in the memory object to go to.  The read and
 | 
						|
//              write pointers will now be repositioned to this point.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This function acts just like the seek() function in the C runtime
 | 
						|
//  library.  It flushes the current I/O buffers, and then moves the file
 | 
						|
//  read and write pointers to a new spot, specified by the address.  if
 | 
						|
//  there is no memory there, you will get an error.  Note that this
 | 
						|
//  makes it not quite like the C run time library, since it the C RTL can
 | 
						|
//  create new storage space with a seek().  But I don't think we need that
 | 
						|
//  capability yet.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SEEK_ERROR if we can't get to that point in the buffer.  Otherwise
 | 
						|
//  AL_SUCCESS.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::Seek( long address )  /* Tag public function */
 | 
						|
{
 | 
						|
    FlushBuffer();
 | 
						|
    if ( mStatus < 0 )
 | 
						|
        return mStatus;
 | 
						|
 | 
						|
    if ( mlFilePointer != address ) {
 | 
						|
        if ( mlFilePointer > mlUserBufferSize )
 | 
						|
            return mStatus.SetError( AL_SEEK_ERROR,
 | 
						|
                                     "Attempt to read past end of the "
 | 
						|
                                     "buffer in ALMemoryBase %s",
 | 
						|
                                     mName.GetName() );
 | 
						|
    }
 | 
						|
    mlFilePointer = address;
 | 
						|
    return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::FlushBuffer()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Flush the I/O buffer of any newly written data.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::FlushBuffer()
 | 
						|
//
 | 
						|
// 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
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This routine is called when the I/O buffer is filled up. It means
 | 
						|
//  you have filled up the cache with what is usually 4K bytes of data.
 | 
						|
//  This routine is also called if you have hot data in the I/O buffer
 | 
						|
//  and you decide to do a seek(), or a read().
 | 
						|
//
 | 
						|
//  All we have to do here is take the hot data in the I/O buffer and
 | 
						|
//  write it out to our big memory object.  Since the base class doesn't
 | 
						|
//  know anything about the pointer types used in derive classes, that
 | 
						|
//  piece of work is done in a virtual function callled _FlushBuffer().
 | 
						|
//
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_CANT_ALLOCATE_MEMORY, if we run out.  Otherwise, AL_SUCCESS.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::FlushBuffer()  /* Tag protected function */
 | 
						|
{
 | 
						|
    if ( mStatus < 0 )
 | 
						|
        return mStatus;
 | 
						|
//
 | 
						|
// If the write index is 0, we can skip all this stuff, because there
 | 
						|
// is nothing in the buffer to flush out.
 | 
						|
//
 | 
						|
    if ( muWriteIndex != 0 ) {
 | 
						|
        if ( miUpdateCrcFlag )
 | 
						|
            UpdateCrc( muWriteIndex );
 | 
						|
        if ( (long) ( muWriteIndex + mlFilePointer ) > mlUserBufferSize )
 | 
						|
            if ( GrowUserBuffer( muWriteIndex + mlFilePointer ) < 0 )
 | 
						|
                return mStatus;
 | 
						|
        _FlushBuffer( mlFilePointer );
 | 
						|
        mlFilePointer += muWriteIndex;
 | 
						|
        muWriteIndex = 0;
 | 
						|
        if ( mlSize < mlFilePointer )
 | 
						|
            mlSize = mlFilePointer;
 | 
						|
    }
 | 
						|
    muReadIndex = 0;
 | 
						|
    muBufferValidData = 0;
 | 
						|
    YieldTime();
 | 
						|
    return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::Close()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Close the memory object.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::Close();
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  C programs must use the base class function, ALStorageClose().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  VB programs must use the base class function, ALStorageClose().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  Delphi programs must use the base class function, ALStorageClose().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  Close() is supposed to do the same thing as fclose() in the run
 | 
						|
//  time library.  The most important thing we are concerned about is
 | 
						|
//  that the I/O buffer gets freed up by the base class, so this suddenly
 | 
						|
//  might not be a giant heavyweight object any more.
 | 
						|
//
 | 
						|
//  Note that the virtual Close() function is called in the base class,
 | 
						|
//  which does significant work in addition to what you see here.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SUCCESS, or various error codes that filter up or down from other
 | 
						|
//  routines.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::Close()  /* Tag public function */
 | 
						|
{
 | 
						|
    if ( mpcBuffer == 0 )
 | 
						|
        return mStatus;
 | 
						|
    FlushBuffer();
 | 
						|
    ALStorage::Close();
 | 
						|
    return mStatus;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::Create()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Create a new memory storage object.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::Create( long size )
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, C programs should use ALStorageCreate().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, VB programs should use ALStorageCreate().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, Delphi programs should use ALStorageCreate().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  size  :  This is the desired size of the memory object.  This parameter
 | 
						|
//           is important to the derived class, which will use this argument
 | 
						|
//           to initialize a buffer.  At this level, we don't care, and
 | 
						|
//           therefore we don't use it.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is like creating a new file.  If there isn't a memory buffer
 | 
						|
//  already assigned to this object, we create one, with an initial
 | 
						|
//  allocation of 16Kbytes.  Note that this class will never be constructed
 | 
						|
//  on its own, it is safe to assume that some additional work is being
 | 
						|
//  passed off to the derived class.
 | 
						|
//
 | 
						|
//  Note that the virtual Create() function is called in the base class,
 | 
						|
//  which does significant work in addition to what you see here.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SUCCESS, AL_CANT_ALLOCATE_MEMORY, or various error codes that
 | 
						|
//  filter on down from other routines.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::Create( long )  /* Tag public function */
 | 
						|
{
 | 
						|
    ALStorage::Create();
 | 
						|
    if ( mStatus < AL_SUCCESS )
 | 
						|
        return mStatus;
 | 
						|
    if ( (char AL_DLL_FAR *) mName == 0 || strlen( mName ) == 0 )
 | 
						|
        mName = "AL.TMP";
 | 
						|
    if ( mfUserOwnsBuffer )
 | 
						|
        return AL_SUCCESS;  //If the user supplied the buffer, we take what's available
 | 
						|
    return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// NAME
 | 
						|
//
 | 
						|
//  ALMemoryBase::Open()
 | 
						|
//
 | 
						|
// PLATFORMS/ENVIRONMENTS
 | 
						|
//
 | 
						|
//  Console  Windows  PM
 | 
						|
//  C++
 | 
						|
//
 | 
						|
// SHORT DESCRIPTION
 | 
						|
//
 | 
						|
//  Open a memory storage object.
 | 
						|
//
 | 
						|
// C++ SYNOPSIS
 | 
						|
//
 | 
						|
//  #include "arclib.h"
 | 
						|
//  #include "memstore.h"
 | 
						|
//
 | 
						|
//  int ALMemoryBase::Open();
 | 
						|
//
 | 
						|
// C SYNOPSIS
 | 
						|
//
 | 
						|
//  None, C programs should use the base class function ALStorageOpen().
 | 
						|
//
 | 
						|
// VB SYNOPSIS
 | 
						|
//
 | 
						|
//  None, VB programs should use the base class function ALStorageOpen().
 | 
						|
//
 | 
						|
// DELPHI SYNOPSIS
 | 
						|
//
 | 
						|
//  None, Delphi programs should use the base class function ALStorageOpen().
 | 
						|
//
 | 
						|
// ARGUMENTS
 | 
						|
//
 | 
						|
//  None.
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is like opening an existing file.  Since there is supposed to be
 | 
						|
//  an existing memory buffer already, we gripe if we can't find one.
 | 
						|
//
 | 
						|
//  Note that the virtual Open() function is called in the base class,
 | 
						|
//  which does significant work in addition to what you see here.
 | 
						|
//
 | 
						|
// RETURNS
 | 
						|
//
 | 
						|
//  AL_SUCCESS, AL_CANT_OPEN_FILE, or various error codes that
 | 
						|
//  filter on down from other routines.
 | 
						|
//
 | 
						|
// EXAMPLE
 | 
						|
//
 | 
						|
// SEE ALSO
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New Release
 | 
						|
//
 | 
						|
 | 
						|
int AL_PROTO
 | 
						|
ALMemoryBase::Open()  /* Tag public function */
 | 
						|
{
 | 
						|
    ALStorage::Open();
 | 
						|
    if ( mStatus < AL_SUCCESS )
 | 
						|
        return mStatus;
 | 
						|
    else
 | 
						|
        return AL_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 |