Initial Source Code commit
Initial commit of original Tiberian Dawn and Red Alert source code converted to build as DLLs, and compatible with the release version of Command & Conquer Remastered.
This commit is contained in:
parent
ea8ecc76fa
commit
03416d24e1
1038 changed files with 629779 additions and 0 deletions
984
REDALERT/BFIOFILE.CPP
Normal file
984
REDALERT/BFIOFILE.CPP
Normal file
|
@ -0,0 +1,984 @@
|
|||
//
|
||||
// Copyright 2020 Electronic Arts Inc.
|
||||
//
|
||||
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is free
|
||||
// software: you can redistribute it and/or modify it under the terms of
|
||||
// the GNU General Public License as published by the Free Software Foundation,
|
||||
// either version 3 of the License, or (at your option) any later version.
|
||||
|
||||
// TiberianDawn.DLL and RedAlert.dll and corresponding source code is distributed
|
||||
// in the hope that it will be useful, but with permitted additional restrictions
|
||||
// under Section 7 of the GPL. See the GNU General Public License in LICENSE.TXT
|
||||
// distributed with this program. You should have received a copy of the
|
||||
// GNU General Public License along with permitted additional restrictions
|
||||
// with this program. If not, see https://github.com/electronicarts/CnC_Remastered_Collection
|
||||
|
||||
/* $Header: /CounterStrike/BFIOFILE.CPP 1 3/03/97 10:24a Joe_bostic $ */
|
||||
/***********************************************************************************************
|
||||
*** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
|
||||
***********************************************************************************************
|
||||
* *
|
||||
* Project Name : Westwood Library *
|
||||
* *
|
||||
* File Name : RAMFILE.CPP *
|
||||
* *
|
||||
* Programmer : David R. Dettmer *
|
||||
* *
|
||||
* Start Date : November 10, 1995 *
|
||||
* *
|
||||
* Last Update : November 10, 1995 [DRD] *
|
||||
* *
|
||||
*---------------------------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. *
|
||||
* BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. *
|
||||
* BufferIOFileClass::Cache -- Load part or all of a file data into RAM. *
|
||||
* BufferIOFileClass::Close -- Perform a closure of the file. *
|
||||
* BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. *
|
||||
* BufferIOFileClass::Free -- Frees the allocated buffer. *
|
||||
* BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. *
|
||||
* BufferIOFileClass::Is_Open -- Determines if the file is open. *
|
||||
* BufferIOFileClass::Open -- Assigns name and opens file in one operation. *
|
||||
* BufferIOFileClass::Open -- Opens the file object with the rights specified. *
|
||||
* BufferIOFileClass::Read -- Reads data from the file cache. *
|
||||
* BufferIOFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. *
|
||||
* BufferIOFileClass::Size -- Determines size of file (in bytes). *
|
||||
* BufferIOFileClass::Write -- Writes data to the file cache. *
|
||||
* BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
|
||||
|
||||
#include "bfiofile.h"
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::BufferIOFileClass -- Filename based constructor for a file object. *
|
||||
* *
|
||||
* This constructor is called when a file object is created with a supplied filename, but *
|
||||
* not opened at the same time. In this case, an assumption is made that the supplied *
|
||||
* filename is a constant string. A duplicate of the filename string is not created since *
|
||||
* it would be wasteful in that case. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::BufferIOFileClass(char const * filename) :
|
||||
IsAllocated(false),
|
||||
IsOpen(false),
|
||||
IsDiskOpen(false),
|
||||
IsCached(false),
|
||||
IsChanged(false),
|
||||
UseBuffer(false),
|
||||
BufferRights(0),
|
||||
Buffer(0),
|
||||
BufferSize(0),
|
||||
BufferPos(0),
|
||||
BufferFilePos(0),
|
||||
BufferChangeBeg(-1),
|
||||
BufferChangeEnd(-1),
|
||||
FileSize(0),
|
||||
FilePos(0),
|
||||
TrueFileStart(0)
|
||||
{
|
||||
BufferIOFileClass::Set_Name(filename);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::BufferIOFileClass -- default constructor for a file object. *
|
||||
* *
|
||||
* This is the default constructor for a file object. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::BufferIOFileClass(void) :
|
||||
IsAllocated(false),
|
||||
IsOpen(false),
|
||||
IsDiskOpen(false),
|
||||
IsCached(false),
|
||||
IsChanged(false),
|
||||
UseBuffer(false),
|
||||
BufferRights(0),
|
||||
Buffer(0),
|
||||
BufferSize(0),
|
||||
BufferPos(0),
|
||||
BufferFilePos(0),
|
||||
BufferChangeBeg(-1),
|
||||
BufferChangeEnd(-1),
|
||||
FileSize(0),
|
||||
FilePos(0),
|
||||
TrueFileStart(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::~BufferIOFileClass -- Destructor for the file object. *
|
||||
* *
|
||||
* This destructor will free all memory allocated thru using Cache routines. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
BufferIOFileClass::~BufferIOFileClass(void)
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Cache -- Load part or all of a file data into RAM. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file load successful? It could fail if there wasn't enough room *
|
||||
* to allocate the raw data block. *
|
||||
* *
|
||||
* WARNINGS: This routine goes to disk for a potentially very long time. *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BufferIOFileClass::Cache( long size, void * ptr )
|
||||
{
|
||||
if (Buffer) {
|
||||
//
|
||||
// if trying to cache again with size or ptr fail
|
||||
//
|
||||
if (size || ptr) {
|
||||
return( false );
|
||||
} else {
|
||||
return( true );
|
||||
}
|
||||
}
|
||||
|
||||
if ( Is_Available() ) {
|
||||
FileSize = Size();
|
||||
} else {
|
||||
FileSize = 0;
|
||||
}
|
||||
|
||||
if (size) {
|
||||
//
|
||||
// minimum buffer size for performance
|
||||
//
|
||||
if (size < MINIMUM_BUFFER_SIZE) {
|
||||
size = MINIMUM_BUFFER_SIZE;
|
||||
|
||||
/*
|
||||
** Specifying a size smaller than the minimum is an error
|
||||
** IF a buffer pointer was also specified. In such a case the
|
||||
** system cannot use the buffer.
|
||||
*/
|
||||
if (ptr) {
|
||||
Error(EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
BufferSize = size;
|
||||
} else {
|
||||
BufferSize = FileSize;
|
||||
}
|
||||
|
||||
//
|
||||
// if size == 0 and a ptr to a buffer is specified then that is invalid.
|
||||
// if the BufferSize is 0 then this must be a new file and no size was
|
||||
// specified so exit.
|
||||
//
|
||||
if ( (size == 0 && ptr) || !BufferSize) {
|
||||
return( false );
|
||||
}
|
||||
|
||||
if (ptr) {
|
||||
Buffer = ptr;
|
||||
} else {
|
||||
Buffer = new char [BufferSize];
|
||||
}
|
||||
|
||||
if (Buffer) {
|
||||
IsAllocated = true;
|
||||
IsDiskOpen = false;
|
||||
BufferPos = 0;
|
||||
BufferFilePos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
FilePos = 0;
|
||||
TrueFileStart = 0;
|
||||
|
||||
//
|
||||
// the file was checked for availability then set the FileSize
|
||||
//
|
||||
if (FileSize) {
|
||||
long readsize;
|
||||
int opened = false;
|
||||
long prevpos = 0;
|
||||
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
readsize = FileSize;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
}
|
||||
|
||||
if ( Is_Open() ) {
|
||||
//
|
||||
// get previous file position
|
||||
//
|
||||
prevpos = Seek(0);
|
||||
|
||||
//
|
||||
// get true file position
|
||||
//
|
||||
if ( RawFileClass::Is_Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
} else {
|
||||
TrueFileStart = prevpos;
|
||||
}
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
//
|
||||
// if previous position is non-zero seek to the beginning
|
||||
//
|
||||
if (prevpos) {
|
||||
Seek(0, SEEK_SET);
|
||||
}
|
||||
|
||||
//
|
||||
// set the buffer position for future reads/writes
|
||||
//
|
||||
BufferPos = prevpos;
|
||||
} else {
|
||||
BufferFilePos = prevpos;
|
||||
}
|
||||
|
||||
FilePos = prevpos;
|
||||
} else {
|
||||
if ( Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
long actual = Read(Buffer, readsize);
|
||||
|
||||
if (actual != readsize) {
|
||||
Error(EIO);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
} else {
|
||||
//
|
||||
// seek to the previous position in the file
|
||||
//
|
||||
Seek(prevpos, SEEK_SET);
|
||||
}
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
|
||||
UseBuffer = true;
|
||||
return(true);
|
||||
}
|
||||
|
||||
Error(ENOMEM);
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Free -- Frees the allocated buffer. *
|
||||
* *
|
||||
* This routine will free the buffer. By using this in conjunction with the *
|
||||
* Cache() function, one can maintain tight control of memory usage. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/10/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
void BufferIOFileClass::Free(void)
|
||||
{
|
||||
if (Buffer) {
|
||||
if (IsAllocated) {
|
||||
delete [] Buffer;
|
||||
IsAllocated = false;
|
||||
}
|
||||
|
||||
Buffer = 0;
|
||||
}
|
||||
|
||||
BufferSize = 0;
|
||||
IsOpen = false;
|
||||
IsCached = false;
|
||||
IsChanged = false;
|
||||
UseBuffer = false;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Commit -- Writes the cache to the file if it has changed. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: false, did not need to write the buffer. *
|
||||
* true, wrote the buffer. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
bool BufferIOFileClass::Commit( void )
|
||||
{
|
||||
long size;
|
||||
|
||||
|
||||
if (UseBuffer) {
|
||||
if (IsChanged) {
|
||||
size = BufferChangeEnd - BufferChangeBeg;
|
||||
|
||||
if (IsDiskOpen) {
|
||||
RawFileClass::Seek( TrueFileStart + BufferFilePos +
|
||||
BufferChangeBeg, SEEK_SET );
|
||||
RawFileClass::Write( Buffer, size );
|
||||
RawFileClass::Seek( TrueFileStart + FilePos, SEEK_SET );
|
||||
} else {
|
||||
RawFileClass::Open();
|
||||
RawFileClass::Seek( TrueFileStart + BufferFilePos +
|
||||
BufferChangeBeg, SEEK_SET );
|
||||
RawFileClass::Write( Buffer, size );
|
||||
RawFileClass::Close();
|
||||
}
|
||||
|
||||
IsChanged = false;
|
||||
return( true );
|
||||
} else {
|
||||
return( false );
|
||||
}
|
||||
} else {
|
||||
return( false );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Set_Name -- Checks for name changed for a cached file. *
|
||||
* *
|
||||
* Checks for a previous filename and that it is cached. If so, then check the *
|
||||
* new filename against the old. If they are the same then return that filename. *
|
||||
* Otherwise, the file object's name is set with just the raw filename as passed *
|
||||
* to this routine. *
|
||||
* *
|
||||
* INPUT: filename -- Pointer to the filename to set as the name of this file object. *
|
||||
* *
|
||||
* OUTPUT: Returns a pointer to the final and complete filename of this file object. This *
|
||||
* may have a path attached to the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
char const * BufferIOFileClass::Set_Name(char const * filename)
|
||||
{
|
||||
if ( File_Name() && UseBuffer) {
|
||||
if ( strcmp(filename, File_Name() ) == 0) {
|
||||
return( File_Name() );
|
||||
} else {
|
||||
Commit();
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
RawFileClass::Set_Name(filename);
|
||||
return( File_Name() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Is_Available -- Checks for existence of file cached or on disk. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file available for opening? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/16/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Is_Available(int )
|
||||
{
|
||||
if (UseBuffer) {
|
||||
return(true);
|
||||
}
|
||||
|
||||
return( RawFileClass::Is_Available() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Is_Open -- Determines if the file is open. *
|
||||
* *
|
||||
* If part or all of the file is cached, then return that it is opened. A closed file *
|
||||
* doesn't have a valid pointer. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: bool; Is the file open? *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Is_Open(void) const
|
||||
{
|
||||
if (IsOpen && UseBuffer) {
|
||||
return( true );
|
||||
}
|
||||
|
||||
return( RawFileClass::Is_Open() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Open -- Assigns name and opens file in one operation. *
|
||||
* *
|
||||
* This routine will assign the specified filename to the file object and open it at the *
|
||||
* same time. If the file object was already open, then it will be closed first. If the *
|
||||
* file object was previously assigned a filename, then it will be replaced with the new *
|
||||
* name. Typically, this routine is used when an anonymous file object has been crated and *
|
||||
* now it needs to be assigned a name and opened. *
|
||||
* *
|
||||
* INPUT: filename -- The filename to assign to this file object. *
|
||||
* *
|
||||
* rights -- The open file access rights to use. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened? The return value of this is moot, since the open file *
|
||||
* is designed to never return unless it succeeded. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Open(char const * filename, int rights)
|
||||
{
|
||||
Set_Name(filename);
|
||||
return( BufferIOFileClass::Open( rights ) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Open -- Opens the file object with the rights specified. *
|
||||
* *
|
||||
* This routine is used to open the specified file object with the access rights indicated. *
|
||||
* This only works if the file has already been assigned a filename. It is guaranteed, by *
|
||||
* the error handler, that this routine will always return with success. *
|
||||
* *
|
||||
* INPUT: rights -- The file access rights to use when opening this file. This is a *
|
||||
* combination of READ and/or WRITE bit flags. *
|
||||
* *
|
||||
* OUTPUT: bool; Was the file opened successfully? This will always return true by reason of *
|
||||
* the error handler. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
int BufferIOFileClass::Open(int rights)
|
||||
{
|
||||
BufferIOFileClass::Close();
|
||||
|
||||
if (UseBuffer) {
|
||||
|
||||
BufferRights = rights; // save rights requested for checks later
|
||||
|
||||
if (rights != READ ||
|
||||
(rights == READ && FileSize > BufferSize) ) {
|
||||
|
||||
if (rights == WRITE) {
|
||||
RawFileClass::Open( rights );
|
||||
RawFileClass::Close();
|
||||
rights = READ | WRITE;
|
||||
TrueFileStart = 0; // now writing to single file
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Open( rights );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Open( rights );
|
||||
}
|
||||
|
||||
IsDiskOpen = true;
|
||||
|
||||
if (BufferRights == WRITE) {
|
||||
FileSize = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
IsDiskOpen = false;
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
FilePos = 0;
|
||||
IsOpen = true;
|
||||
} else {
|
||||
RawFileClass::Open( rights );
|
||||
}
|
||||
|
||||
return( true );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Write -- Writes data to the file cache. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer that holds the data to be written. *
|
||||
* *
|
||||
* size -- The number of bytes to write. *
|
||||
* *
|
||||
* OUTPUT: Returns the number of bytes actually written. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Write(void const * buffer, long size)
|
||||
{
|
||||
int opened = false;
|
||||
|
||||
if ( !Is_Open() ) {
|
||||
if (!Open(WRITE)) {
|
||||
return(0);
|
||||
}
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
|
||||
if (UseBuffer) {
|
||||
long sizewritten = 0;
|
||||
|
||||
if (BufferRights != READ) {
|
||||
while (size) {
|
||||
long sizetowrite;
|
||||
|
||||
if (size >= (BufferSize - BufferPos) ) {
|
||||
sizetowrite = (BufferSize - BufferPos);
|
||||
} else {
|
||||
sizetowrite = size;
|
||||
}
|
||||
|
||||
if (sizetowrite != BufferSize) {
|
||||
|
||||
if ( !IsCached ) {
|
||||
long readsize;
|
||||
|
||||
if (FileSize < BufferSize) {
|
||||
readsize = FileSize;
|
||||
BufferFilePos = 0;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
BufferFilePos = FilePos;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( BufferFilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, readsize );
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
}
|
||||
|
||||
memmove((char *)Buffer + BufferPos, (char *)buffer + sizewritten, sizetowrite);
|
||||
|
||||
IsChanged = true;
|
||||
sizewritten += sizetowrite;
|
||||
size -= sizetowrite;
|
||||
|
||||
if (BufferChangeBeg == -1) {
|
||||
BufferChangeBeg = BufferPos;
|
||||
BufferChangeEnd = BufferPos;
|
||||
} else {
|
||||
if (BufferChangeBeg > BufferPos) {
|
||||
BufferChangeBeg = BufferPos;
|
||||
}
|
||||
}
|
||||
|
||||
BufferPos += sizetowrite;
|
||||
|
||||
if (BufferChangeEnd < BufferPos) {
|
||||
BufferChangeEnd = BufferPos;
|
||||
}
|
||||
|
||||
FilePos = BufferFilePos + BufferPos;
|
||||
|
||||
if (FileSize < FilePos) {
|
||||
FileSize = FilePos;
|
||||
}
|
||||
|
||||
//
|
||||
// end of buffer reached?
|
||||
//
|
||||
if (BufferPos == BufferSize) {
|
||||
Commit();
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = FilePos;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
if (size && FileSize > FilePos) {
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( FilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, BufferSize );
|
||||
}
|
||||
} else {
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Error(EACCES);
|
||||
}
|
||||
|
||||
size = sizewritten;
|
||||
} else {
|
||||
size = RawFileClass::Write(buffer, size);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
}
|
||||
|
||||
return( size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Read -- Reads data from the file cache. *
|
||||
* *
|
||||
* *
|
||||
* INPUT: buffer -- Pointer to the buffer to place the read data. *
|
||||
* *
|
||||
* size -- The number of bytes to read. *
|
||||
* *
|
||||
* OUTPUT: Returns the actual number of bytes read (this could be less than requested). *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Read(void * buffer, long size)
|
||||
{
|
||||
int opened = false;
|
||||
|
||||
if ( !Is_Open() ) {
|
||||
if ( Open() ) {
|
||||
TrueFileStart = RawFileClass::Seek(0);
|
||||
opened = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (UseBuffer) {
|
||||
long sizeread = 0;
|
||||
|
||||
if (BufferRights != WRITE) {
|
||||
while (size) {
|
||||
long sizetoread;
|
||||
|
||||
if (size >= (BufferSize - BufferPos) ) {
|
||||
sizetoread = (BufferSize - BufferPos);
|
||||
} else {
|
||||
sizetoread = size;
|
||||
}
|
||||
|
||||
if ( !IsCached ) {
|
||||
long readsize;
|
||||
|
||||
if (FileSize < BufferSize) {
|
||||
readsize = FileSize;
|
||||
BufferFilePos = 0;
|
||||
} else {
|
||||
readsize = BufferSize;
|
||||
BufferFilePos = FilePos;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( BufferFilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, readsize );
|
||||
}
|
||||
|
||||
BufferPos = 0;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
IsCached = true;
|
||||
}
|
||||
|
||||
memmove((char *)buffer + sizeread, (char *)Buffer + BufferPos, sizetoread);
|
||||
|
||||
sizeread += sizetoread;
|
||||
size -= sizetoread;
|
||||
BufferPos += sizetoread;
|
||||
FilePos = BufferFilePos + BufferPos;
|
||||
|
||||
//
|
||||
// end of buffer reached?
|
||||
//
|
||||
if (BufferPos == BufferSize) {
|
||||
Commit();
|
||||
|
||||
BufferPos = 0;
|
||||
BufferFilePos = FilePos;
|
||||
BufferChangeBeg = -1;
|
||||
BufferChangeEnd = -1;
|
||||
|
||||
if (size && FileSize > FilePos) {
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek( FilePos, SEEK_SET );
|
||||
Read( Buffer, BufferSize );
|
||||
Seek( FilePos, SEEK_SET );
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek( FilePos, SEEK_SET );
|
||||
RawFileClass::Read( Buffer, BufferSize );
|
||||
}
|
||||
} else {
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Error(EACCES);
|
||||
}
|
||||
|
||||
size = sizeread;
|
||||
} else {
|
||||
size = RawFileClass::Read(buffer, size);
|
||||
}
|
||||
|
||||
if (opened) {
|
||||
Close();
|
||||
}
|
||||
|
||||
return( size );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Seek -- Moves the current file pointer in the file. *
|
||||
* *
|
||||
* This routine will change the current file pointer to the position specified. It follows *
|
||||
* the same rules the a normal Seek() does, but if the file is part of the mixfile system, *
|
||||
* then only the position value needs to be updated. *
|
||||
* *
|
||||
* INPUT: pos -- The position to move the file to relative to the position indicated *
|
||||
* by the "dir" parameter. *
|
||||
* *
|
||||
* dir -- The direction to affect the position change against. This can be *
|
||||
* either SEEK_CUR, SEEK_END, or SEEK_SET. *
|
||||
* *
|
||||
* OUTPUT: Returns with the position of the new location. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/15/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Seek(long pos, int dir)
|
||||
{
|
||||
if (UseBuffer) {
|
||||
bool adjusted = false;
|
||||
|
||||
switch (dir) {
|
||||
case SEEK_END:
|
||||
FilePos = FileSize;
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
FilePos = 0;
|
||||
break;
|
||||
|
||||
case SEEK_CUR:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (TrueFileStart) {
|
||||
if (pos >= TrueFileStart) {
|
||||
pos -= TrueFileStart;
|
||||
adjusted = true;
|
||||
}
|
||||
}
|
||||
|
||||
FilePos += pos;
|
||||
|
||||
if (FilePos < 0) {
|
||||
FilePos = 0;
|
||||
}
|
||||
|
||||
if (FilePos > FileSize ) {
|
||||
FilePos = FileSize;
|
||||
}
|
||||
|
||||
if (FileSize <= BufferSize) {
|
||||
BufferPos = FilePos;
|
||||
} else {
|
||||
if (FilePos >= BufferFilePos &&
|
||||
FilePos < (BufferFilePos + BufferSize) ) {
|
||||
BufferPos = FilePos - BufferFilePos;
|
||||
} else {
|
||||
Commit();
|
||||
// check!!
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Seek(FilePos, SEEK_SET);
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Seek(FilePos, SEEK_SET);
|
||||
}
|
||||
|
||||
IsCached = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (TrueFileStart && adjusted) {
|
||||
return( FilePos + TrueFileStart );
|
||||
}
|
||||
|
||||
return( FilePos );
|
||||
}
|
||||
|
||||
return( RawFileClass::Seek(pos, dir) );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Size -- Determines size of file (in bytes). *
|
||||
* *
|
||||
* If part or all of the file is cached, then the size of the file is already *
|
||||
* determined and available. Otherwise, go to the low level system to find the file *
|
||||
* size. *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: Returns with the number of bytes in the file. *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
long BufferIOFileClass::Size(void)
|
||||
{
|
||||
if (IsOpen && UseBuffer) {
|
||||
return( FileSize );
|
||||
}
|
||||
|
||||
return( RawFileClass::Size() );
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************************************
|
||||
* BufferIOFileClass::Close -- Perform a closure of the file. *
|
||||
* *
|
||||
* Call Commit() to write the buffer if the file is cached and the buffer has changed, *
|
||||
* then call lower level Close(). *
|
||||
* *
|
||||
* INPUT: none *
|
||||
* *
|
||||
* OUTPUT: none *
|
||||
* *
|
||||
* WARNINGS: none *
|
||||
* *
|
||||
* HISTORY: *
|
||||
* 11/14/1995 DRD : Created. *
|
||||
*=============================================================================================*/
|
||||
void BufferIOFileClass::Close(void)
|
||||
{
|
||||
if (UseBuffer) {
|
||||
Commit();
|
||||
|
||||
if (IsDiskOpen) {
|
||||
|
||||
if (TrueFileStart) {
|
||||
UseBuffer = false;
|
||||
Close();
|
||||
UseBuffer = true;
|
||||
} else {
|
||||
RawFileClass::Close();
|
||||
}
|
||||
|
||||
IsDiskOpen = false;
|
||||
}
|
||||
|
||||
IsOpen = false;
|
||||
} else {
|
||||
RawFileClass::Close();
|
||||
}
|
||||
}
|
||||
|
Reference in a new issue