1010 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			1010 lines
		
	
	
		
			26 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
| //
 | |
| // MEMSTD.CPP
 | |
| //
 | |
| //  Source file for ArchiveLib 2.0
 | |
| //
 | |
| //  Copyright (c) Greenleaf Software, Inc. 1994-1996
 | |
| //  All Rights Reserved
 | |
| //
 | |
| // CONTENTS
 | |
| //
 | |
| //  ALMemory::operator new()
 | |
| //  ALMemory::ALMemory()
 | |
| //  newALMemory()
 | |
| //  ALMemory::~ALMemory()
 | |
| //  ALMemory::_LoadBuffer()
 | |
| //  ALMemory::Delete()
 | |
| //  ALMemory::GrowUserBuffer()
 | |
| //  ALMemory::_FlushBuffer()
 | |
| //  ALMemory::Close()
 | |
| //  ALMemory::Create()
 | |
| //  ALMemory::Open()
 | |
| //  ALMemory::Clone()
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This file contains the C++ member functions to support class
 | |
| //  ALMemory.  This class works very closely with the parent class,
 | |
| //  ALMemoryBase, found in MEMSTORE.CPP.
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //  May 22, 1994  1.0A  : First release
 | |
| //
 | |
| //  July 7, 1994  1.0B  : Had to make a lot of changes to support file
 | |
| //                        management under UNIX.
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| #include "arclib.h"
 | |
| #if !defined( AL_IBM )
 | |
| #pragma hdrstop
 | |
| #endif
 | |
| 
 | |
| #include "memstore.h"
 | |
| 
 | |
| #include <stdlib.h>  // might be using malloc()!
 | |
| 
 | |
| const size_t max_alloc = (size_t) ~0;
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::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 * ALMemory::operator new( size_t size )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  size  :  The number of bytes that the compiler has decided will be
 | |
| //           necessary to construct a new ALMemory object.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  When using a DLL, it is easy to get into a dangerous situation when
 | |
| //  creating objects whose ctor and dtor are both in the DLL.  The problem
 | |
| //  arises because when you create an object using new, the memory for
 | |
| //  the object will be allocated from the EXE.  However, when you destroy
 | |
| //  the object using delete, the memory is freed inside the DLL.  Since
 | |
| //  the DLL doesn't really own that memory, bad things can happen.
 | |
| //
 | |
| //  But, you say, won't the space just go back to the Windows heap regardless
 | |
| //  of who tries to free it?  Maybe, but maybe not.  If the DLL is using
 | |
| //  a subsegment allocation scheme, it might do some sort of local free
 | |
| //  before returning the space to the windows heap.  That is the point where
 | |
| //  you could conceivably cook your heap.
 | |
| //
 | |
| //  By providing our own version of operator new inside this class, we
 | |
| //  ensure that all memory allocation for the class will be done from
 | |
| //  inside the DLL, not the EXE calling the DLL.
 | |
| //
 | |
| //  Incidentally, I suspect that this function never gets called.  If an
 | |
| //  object of a derived archive class is being created, it should use
 | |
| //  its own new operator, rendering this one useless.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  A pointer to some memory that should have been pulled out of the
 | |
| //  heap for the DLL.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| 
 | |
| #if defined( AL_BUILDING_DLL )
 | |
| 
 | |
| void AL_DLL_FAR * AL_PROTO
 | |
| ALMemory::operator new( size_t size )  /* Tag internal function */
 | |
| {
 | |
|     return ::new char[ size ];
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::ALMemory()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++  C  VB  Delphi
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Constructs a new ALMemory object.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  ALMemory::ALMemory( const char *buffer_name = "",
 | |
| //                      char *user_buffer = 0 ,
 | |
| //                      size_t user_buffer_size = 0,
 | |
| //                      ALCase name_case = AL_MIXED );
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  hALStorage newALMemory( char *buffer_name,
 | |
| //                          char *user_buffer,
 | |
| //                          int user_buffer_size );
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, VB should use newALWinMemory();
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, Delphi should use newALWinMemory();
 | |
| //
 | |
| // 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.
 | |
| //
 | |
| //  user_buffer  : If you want the ALMemory class to automatically
 | |
| //                 allocate a buffer for you, and grow it as necessary, just
 | |
| //                 leave this pointer set to 0.  If you want to use your own
 | |
| //                 buffer, which won't have the ability to grow, pass a
 | |
| //                 pointer to it in this parameter.
 | |
| //
 | |
| //  user_buffer_size : If you are passing a pointer to your own buffer,
 | |
| //                     you need to indicate how large it is here.  Since
 | |
| //                     we are dealing with standard buffers here, this is of
 | |
| //                     type size_t.
 | |
| //
 | |
| //  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.
 | |
| //
 | |
| //                 Note that I don't even give the option of using name_case
 | |
| //                 to C users.  They are going to get the default
 | |
| //                 value assigned to their OS/environment.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This constructor calls the base class constructor in an initializer
 | |
| //  list, which takes care of most of the dirty work right away.  After that
 | |
| //  is done, all the constructor has to do is initialize a few data members.
 | |
| //  That should be self-explanatory.  Remember that if the user doesn't
 | |
| //  supply a buffer, we are going to allocate it for her, but not until
 | |
| //  there is actually a demand for memory.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  If memory allocation is being done dynamically, this function returns
 | |
| //  a pointer/handle to a new ALMemory object.  If it is called as
 | |
| //  a static or automatic constructor (only possible in C++), it returns
 | |
| //  nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| //  ALMemoryBase::ALMemoryBase(), ALStorage::ALStorage(),
 | |
| //  ALMemory::~ALMemory()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| AL_PROTO
 | |
| ALMemory::ALMemory( const char AL_DLL_FAR *buffer_name /* = "" */,  /* Tag public function */
 | |
|                     char AL_DLL_FAR *user_buffer /* = 0 */ ,
 | |
|                     size_t user_buffer_size /* = 0 */,
 | |
|                     ALCase name_case /* = AL_MIXED */ )
 | |
|     : ALMemoryBase( buffer_name, name_case )
 | |
| {
 | |
|     if ( user_buffer != 0 ) {
 | |
|         mpcUserBuffer = user_buffer;
 | |
|         mfUserOwnsBuffer = 1;
 | |
|         mlUserBufferSize = user_buffer_size;
 | |
|     } else {
 | |
|         mfUserOwnsBuffer = 0;
 | |
|         mpcUserBuffer = 0;
 | |
|         mlUserBufferSize = 0;
 | |
|     }
 | |
| }
 | |
| 
 | |
| #if !defined( AL_NO_C )
 | |
| 
 | |
| extern "C" AL_LINKAGE hALStorage AL_FUNCTION
 | |
| newALMemory( char AL_DLL_FAR *buffer_name,  /* Tag public function */
 | |
|              char AL_DLL_FAR *user_buffer,
 | |
|              size_t user_buffer_size )
 | |
| {
 | |
|     if ( user_buffer_size == 0 )
 | |
|         return (hALStorage) new ALMemory( buffer_name );
 | |
|     else
 | |
|         return (hALStorage) new ALMemory( buffer_name,
 | |
|                                           user_buffer,
 | |
|                                           user_buffer_size );
 | |
| }
 | |
| 
 | |
| #endif
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::~ALMemory()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Destroy an ALMemory object.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  ALMemory::~ALMemory();
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, use the base class destructor: deleteALStorage().
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, use the base class destructor: deleteALStorage().
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, use the base class destructor: deleteALStorage().
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  None, you don't get any for a destructor.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  The destructor has just one thing it has to do before this object
 | |
| //  goes away.  If the buffer that it has been using all along doesn't
 | |
| //  belong to the user, then it is the class's responsibility to get
 | |
| //  rid of it.  We do so here, using the standard version of free.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| //  ALMemory::ALMemory()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| AL_PROTO
 | |
| ALMemory::~ALMemory()  /* Tag public function */
 | |
| {
 | |
|     AL_ASSERT( GoodTag(), "~ALMemory: attempting to delete invalid object" );
 | |
|     if ( !mfUserOwnsBuffer ) {
 | |
|         if ( mpcUserBuffer ) {
 | |
|             free( mpcUserBuffer );
 | |
|             mpcUserBuffer = 0;
 | |
|         }
 | |
|     }
 | |
|     AL_ASSERT( GoodTag(), "~ALMemory: attempting to delete invalid object" );
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::_LoadBuffer()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Read memory from the big buffer into the local I/O buffer.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  void ALMemory::_LoadBuffer( long address );
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, internal protected function.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, internal protected function.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, internal protected functoin.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  address      :  The offset in the memory object that is going to be
 | |
| //                  loaded.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  External users of an ALStorage class perform all of their access via
 | |
| //  a local I/O buffer.  Functions such as ReadChar() and WriteChar() look
 | |
| //  at a thing called mpcBuffer for their data.  When reading from
 | |
| //  mpcBuffer, you are going to run out of data from time to time.  When
 | |
| //  this happens, you will generate a call to the virtual function
 | |
| //  LoadBuffer().
 | |
| //
 | |
| //  As it happens, all of the ALMemory objects share a common version
 | |
| //  of LoadBuffer().  LoadBuffer() still has to call something a little
 | |
| //  more specialized though, and that's where this version of _LoadBuffer()
 | |
| //  comes into play.  It just performs a memcpy() routine to actually move
 | |
| //  data out of the big memory buffer and into the local I/O buffer
 | |
| //  used by ReadChar() et. al.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| void AL_PROTO
 | |
| ALMemory::_LoadBuffer( long address )  /* Tag protected function */
 | |
| {
 | |
|     memcpy( mpcBuffer, mpcUserBuffer + (size_t) address, muBufferValidData );
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::Delete()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Delete the underlying buffer for the memory object.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  int ALMemory::Delete();
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, C programs use the base class function deleteALStorage().
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, VB programs use the base class function deleteALStorage().
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, Delphi programs use the base class function deleteALStorage().
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  This function is analogous to the unlink() RTL function for files.  It
 | |
| //  has to close the file, and get rid of its big buffer.  This is fairly
 | |
| //  easy with memory buffers, we just call the appropriate version of
 | |
| //  free() to delete the buffer.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| //  ALMemory::Create(), ALStorage::Delete()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALMemory::Delete()  /* Tag public function */
 | |
| {
 | |
|     if ( !mfUserOwnsBuffer ) {
 | |
|         free( mpcUserBuffer );
 | |
|         mpcUserBuffer = 0;
 | |
|     }
 | |
|     return AL_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::GrowUserBuffer()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Enlarge the user buffer.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  int ALMemory::GrowUserBuffer( long minimum_new_size );
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, this is an internal protected C++ function.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, this is an internal protected C++ function.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, this is an internal protected C++ function.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  minimum_new_size : This is the size that the caller absolutely must
 | |
| //                     have to successfully perform a write.  Anything
 | |
| //                     less than this won't do.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  Sometimes a write to a memory object goes past the current end of the
 | |
| //  buffer.  When this happens, code in the base class calls this
 | |
| //  function to attempt to enlarge the buffer.
 | |
| //
 | |
| //  Enlarging the buffer is tricky, because you have to allocate new space,
 | |
| //  then copy the old buffer into the new buffer.  This means you
 | |
| //  temporarily need a boot-load of space.  If you are lucky, the realloc()
 | |
| //  function might be able to attempt to avoid this situation.
 | |
| //
 | |
| //  We try to enlarge things by a fixed amount, large enough to prevent
 | |
| //  thrashing.  But if that doesn't fly, we can fall back and try to
 | |
| //  enlarge to the minimum acceptable size.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  AL_SUCCESS if all went well, some error code < AL_SUCCESS if not.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALMemory::GrowUserBuffer( long minimum_new_size )  /* Tag protected function */
 | |
| {
 | |
|     if ( mStatus < AL_SUCCESS )
 | |
|         return mStatus;
 | |
|     if ( mfUserOwnsBuffer )
 | |
|         return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
 | |
|                                  "Attempt to write past the end of a "
 | |
|                                  "user owned buffer for ALMemory "
 | |
|                                  "%s",
 | |
|                                  mName.GetSafeName() );
 | |
|     if ( minimum_new_size >= max_alloc )
 | |
|         return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
 | |
|                                    "Attempt to allocate a buffer "
 | |
|                                    "of %ld bytes for ALMemory "
 | |
|                                    "%s",
 | |
|                                    minimum_new_size,
 | |
|                                    mName.GetSafeName() );
 | |
|     long trial_size = mlUserBufferSize + 16384;
 | |
|     if ( trial_size >= max_alloc )
 | |
|         trial_size = max_alloc - 16;
 | |
|     if ( trial_size >= minimum_new_size ) {
 | |
|         char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) trial_size );
 | |
|         if ( new_buf ) {
 | |
|             mpcUserBuffer = new_buf;
 | |
|             mlUserBufferSize = (size_t) trial_size;
 | |
|             return AL_SUCCESS;
 | |
|         }
 | |
|     }
 | |
|     char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) minimum_new_size );
 | |
|     if ( new_buf ) {
 | |
|         mpcUserBuffer = new_buf;
 | |
|         mlUserBufferSize = (size_t) minimum_new_size;
 | |
|         return AL_SUCCESS;
 | |
|     }
 | |
|     return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
 | |
|                              "Allocation failure when attempting to "
 | |
|                              "allocate a buffer "
 | |
|                              "of %ld bytes for ALMemory "
 | |
|                              "%s",
 | |
|                              minimum_new_size,
 | |
|                              mName.GetSafeName() );
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::_FlushBuffer()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Flush data to the big buffer.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  void ALMemory::_FlushBuffer( long address )
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, internal protected C++ function.
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None, internal protected C++ function.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None, internal protected C++ function.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  address : The address in the big buffer where the flush should write
 | |
| //            to.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  When performing WriteChar() or WriteBuffer() operations, ALStorage
 | |
| //  causes output to be directed to a small I/O buffer.  When this I/O
 | |
| //  buffer gets full, a call to ALFlushBuffer() is generated, which is
 | |
| //  supposed to dump that memory to a physical device.
 | |
| //
 | |
| //  When ALMemoryBase gets a call to FlushBuffer(), it handles almost
 | |
| //  everything on its own.  The one thing it can't handle, however, is
 | |
| //  the routine to copy the I/O buffer out to the big memory object.
 | |
| //  It has to really on this dinky virtual function to do the job.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| void AL_PROTO
 | |
| ALMemory::_FlushBuffer( long address )  /* Tag protected function */
 | |
| {
 | |
|     memcpy( mpcUserBuffer + (size_t) address, mpcBuffer, muWriteIndex );
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::Close()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Close an open memory buffer object
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  int ALMemory::Close()
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  C programs should use the base class function ALStorageClose().
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  VB programs should use the base class function ALStorageClose().
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  Delphi programs should use the base class function ALStorageClose().
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  Close() is supposed to do the same thing to a memory buffer as fclose()
 | |
| //  in the RTL does to a file.  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.
 | |
| //
 | |
| //  After freeing things up in the base class, we check to see if
 | |
| //  we have allocated more space than we really need.  If so, we do
 | |
| //  a realloc() of some sort to give space back to the O/S.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Nothing.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| //  ALMemory::Open(), ALStorage::Close()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALMemory::Close()  /* Tag public function */
 | |
| {
 | |
|     ALMemoryBase::Close();
 | |
|     if ( mStatus < AL_SUCCESS )
 | |
|         return mStatus;
 | |
|     if ( ! mfUserOwnsBuffer ) {
 | |
|         if ( mlSize != 0 ) {
 | |
|             char *new_buf = (char *) realloc( mpcUserBuffer, (size_t) mlSize );
 | |
|             if ( new_buf ) {
 | |
|                 mpcUserBuffer = new_buf;
 | |
|                 mlUserBufferSize = mlSize;
 | |
|             }
 | |
|         } else {
 | |
|             free( mpcUserBuffer );
 | |
|             mpcUserBuffer = 0;
 | |
|         }
 | |
|     }
 | |
|     return AL_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::Create()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Create the memory storage object big buffer.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  int ALMemory::Create( long init_size );
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  C programs should use the base class function ALStorageCreate().
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  VB programs should use the base class function ALStorageCreate().
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  Delphi programs should use the base class function ALStorageCreate().
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  init_size  :  When you create an ALMemory object of any kind, you can
 | |
| //                write out data to it at your own pace, without having any
 | |
| //                idea how much space you will need.  The storage object
 | |
| //                tries to increase its size every time you fill up
 | |
| //                the current huge buffer.  Well, if you know in advance how
 | |
| //                much space you are going to need, you can allocate the
 | |
| //                whole buffer at once, and avoid all that extra work.  So
 | |
| //                some calls to Create() now pass on an initial size using
 | |
| //                this argument.
 | |
| //
 | |
| // 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, or more if requested.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Either AL_SUCCESS, or an unfriendly error code.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // ALStorage::Create(), ALMemory::Open()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALMemory::Create( long init_size )  /* Tag public function */
 | |
| {
 | |
|     ALMemoryBase::Create();
 | |
|     if ( mStatus < AL_SUCCESS )
 | |
|         return mStatus;
 | |
|     if ( mpcUserBuffer )
 | |
|         return AL_SUCCESS; //If a buffer was already created somewhere down the
 | |
|                            //line, we won't do it again.
 | |
|     if ( init_size == -1L )
 | |
|         init_size = 16384;
 | |
|     if ( init_size > max_alloc )
 | |
|         return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
 | |
|                                  "Allocation failure when attempting to "
 | |
|                                  "initialize a buffer "
 | |
|                                  "of %ld bytes for ALMemory "
 | |
|                                  "%s in _Create()",
 | |
|                                  init_size,
 | |
|                                  mName.GetSafeName() );
 | |
|     mpcUserBuffer = (char *) malloc( (size_t) init_size );
 | |
|     mlUserBufferSize = init_size;
 | |
|     if ( mpcUserBuffer == 0 )
 | |
|         return mStatus.SetError( AL_CANT_ALLOCATE_MEMORY,
 | |
|                                  "Allocation failure when attempting to "
 | |
|                                  "create a buffer "
 | |
|                                  "of %ld bytes for ALMemory "
 | |
|                                  "%s in _Create()",
 | |
|                                  mlUserBufferSize,
 | |
|                                  mName.GetSafeName() );
 | |
|     return AL_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::Open()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Open an existing memory storage object.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  int ALMemory::Open();
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  C programs should use the base class function ALStorageOpen().
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  VB programs should use the base class function ALStorageOpen().
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  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.
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Either AL_SUCCESS, or an unfriendly error code.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| //  ALStorage::Open(), ALMemory::Create()
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| int AL_PROTO
 | |
| ALMemory::Open()  /* Tag public function */
 | |
| {
 | |
|     ALMemoryBase::Open();
 | |
|     if ( mStatus < AL_SUCCESS )
 | |
|         return mStatus;
 | |
|     if ( mpcUserBuffer == 0 )
 | |
|         return mStatus.SetError( AL_CANT_OPEN_FILE,
 | |
|                                    "Attempt to open ALMemory %s "
 | |
|                                    "with no buffer allocated",
 | |
|                                    mName.GetSafeName() );
 | |
|     else
 | |
|         mlSize = mlUserBufferSize;
 | |
|     return AL_SUCCESS;
 | |
| }
 | |
| 
 | |
| //
 | |
| // NAME
 | |
| //
 | |
| //  ALMemory::Clone()
 | |
| //
 | |
| // PLATFORMS/ENVIRONMENTS
 | |
| //
 | |
| //  Console  Windows  PM
 | |
| //  C++
 | |
| //
 | |
| // SHORT DESCRIPTION
 | |
| //
 | |
| //  Clone this memory based storage object.
 | |
| //
 | |
| // C++ SYNOPSIS
 | |
| //
 | |
| //  #include "arclib.h"
 | |
| //  #include "memstore.h"
 | |
| //
 | |
| //  ALStorage ALMemory::Clone( const char *name,
 | |
| //                             int object_type ) const;
 | |
| //
 | |
| // C SYNOPSIS
 | |
| //
 | |
| //  None, this is an internal C++ function
 | |
| //
 | |
| // VB SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // DELPHI SYNOPSIS
 | |
| //
 | |
| //  None.
 | |
| //
 | |
| // ARGUMENTS
 | |
| //
 | |
| //  name         :  The desired name of the new object.  Usually this will
 | |
| //                  be a name found in an Archive directory.
 | |
| //
 | |
| //  object_type  :  The type of object we want to create.  Only
 | |
| //                  AL_STORAGE_DEFAULT and AL_MEMORY_OBJECT will cause this
 | |
| //                  function to succeed.
 | |
| //
 | |
| // DESCRIPTION
 | |
| //
 | |
| //  The virtual Clone() function is used by archiving programs to act
 | |
| //  as a virtual constructor.  When preparing to create storage objects
 | |
| //  based on the contents of an Archive directory, the archiving code can
 | |
| //  call Clone() for all the storage objects in its toolkit until it finds
 | |
| //  one that responds to its object type.
 | |
| //
 | |
| //  For example, if an archive contained an AL_MEMORY object, and we were
 | |
| //  extracting, and an ALFile object was in the toolkit, it would call
 | |
| //  ALFile::Clone() from the toolkit object, with an object type of
 | |
| //  AL_MEMORY_OBJECT.  This Clone() function would fail.  Hopefully, there
 | |
| //  would be a memory based storage object in the toolkit that would
 | |
| //  respond properly to the Clone() call.
 | |
| //
 | |
| //  Another object in the same archive might have an AL_FILE_OBJECT type.
 | |
| //  When the archiving code called Clone() again with that object type,
 | |
| //  we would successfully create the new File object in Clone().
 | |
| //
 | |
| // RETURNS
 | |
| //
 | |
| //  Either a pointer to a newly constructed ALHugeMemory object, or a zero
 | |
| //  in case of error.
 | |
| //
 | |
| // EXAMPLE
 | |
| //
 | |
| // SEE ALSO
 | |
| //
 | |
| // REVISION HISTORY
 | |
| //
 | |
| //   February 14, 1996  2.0A : New Release
 | |
| //
 | |
| 
 | |
| ALStorage AL_DLL_FAR *
 | |
| ALMemory::Clone( const char AL_DLL_FAR *name,  /* Tag public function */
 | |
|                  int object_type ) const
 | |
| {
 | |
|     switch ( object_type ) {
 | |
|         case AL_STORAGE_DEFAULT :
 | |
|         case AL_MEMORY_OBJECT :
 | |
|             return new ALMemory( name );
 | |
|     }
 | |
|     return 0;
 | |
| }
 | |
| 
 |