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