diff options
Diffstat (limited to 'LibOVR/Src/Kernel/OVR_File.cpp')
-rw-r--r-- | LibOVR/Src/Kernel/OVR_File.cpp | 1142 |
1 files changed, 571 insertions, 571 deletions
diff --git a/LibOVR/Src/Kernel/OVR_File.cpp b/LibOVR/Src/Kernel/OVR_File.cpp index 7620e37..26e94e8 100644 --- a/LibOVR/Src/Kernel/OVR_File.cpp +++ b/LibOVR/Src/Kernel/OVR_File.cpp @@ -1,571 +1,571 @@ -/**************************************************************************
-
-Filename : OVR_File.cpp
-Content : File wrapper class implementation (Win32)
-
-Created : April 5, 1999
-Authors : Michael Antonov
-
-Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
-
-Use of this software is subject to the terms of the Oculus license
-agreement provided at the time of installation or download, or which
-otherwise accompanies this software in either electronic or hard copy form.
-
-**************************************************************************/
-
-#define GFILE_CXX
-
-// Standard C library (Captain Obvious guarantees!)
-#include <stdio.h>
-
-#include "OVR_File.h"
-
-namespace OVR {
-
-// Buffered file adds buffering to an existing file
-// FILEBUFFER_SIZE defines the size of internal buffer, while
-// FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer
-#define FILEBUFFER_SIZE (8192-8)
-#define FILEBUFFER_TOLERANCE 4096
-
-// ** Constructor/Destructor
-
-// Hidden constructor
-// Not supposed to be used
-BufferedFile::BufferedFile() : DelegatedFile(0)
-{
- pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
- BufferMode = NoBuffer;
- FilePos = 0;
- Pos = 0;
- DataSize = 0;
-}
-
-// Takes another file as source
-BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile)
-{
- pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE);
- BufferMode = NoBuffer;
- FilePos = pfile->LTell();
- Pos = 0;
- DataSize = 0;
-}
-
-
-// Destructor
-BufferedFile::~BufferedFile()
-{
- // Flush in case there's data
- if (pFile)
- FlushBuffer();
- // Get rid of buffer
- if (pBuffer)
- OVR_FREE(pBuffer);
-}
-
-/*
-bool BufferedFile::VCopy(const Object &source)
-{
- if (!DelegatedFile::VCopy(source))
- return 0;
-
- // Data members
- BufferedFile *psource = (BufferedFile*)&source;
-
- // Buffer & the mode it's in
- pBuffer = psource->pBuffer;
- BufferMode = psource->BufferMode;
- Pos = psource->Pos;
- DataSize = psource->DataSize;
- return 1;
-}
-*/
-
-// Initializes buffering to a certain mode
-bool BufferedFile::SetBufferMode(BufferModeType mode)
-{
- if (!pBuffer)
- return false;
- if (mode == BufferMode)
- return true;
-
- FlushBuffer();
-
- // Can't set write mode if we can't write
- if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) )
- return 0;
-
- // And SetMode
- BufferMode = mode;
- Pos = 0;
- DataSize = 0;
- return 1;
-}
-
-// Flushes buffer
-void BufferedFile::FlushBuffer()
-{
- switch(BufferMode)
- {
- case WriteBuffer:
- // Write data in buffer
- FilePos += pFile->Write(pBuffer,Pos);
- Pos = 0;
- break;
-
- case ReadBuffer:
- // Seek back & reset buffer data
- if ((DataSize-Pos)>0)
- FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur);
- DataSize = 0;
- Pos = 0;
- break;
- default:
- // not handled!
- break;
- }
-}
-
-// Reloads data for ReadBuffer
-void BufferedFile::LoadBuffer()
-{
- if (BufferMode == ReadBuffer)
- {
- // We should only reload once all of pre-loaded buffer is consumed.
- OVR_ASSERT(Pos == DataSize);
-
- // WARNING: Right now LoadBuffer() assumes the buffer's empty
- int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE);
- DataSize = sz<0 ? 0 : (unsigned)sz;
- Pos = 0;
- FilePos += DataSize;
- }
-}
-
-
-// ** Overridden functions
-
-// We override all the functions that can possibly
-// require buffer mode switch, flush, or extra calculations
-
-// Tell() requires buffer adjustment
-int BufferedFile::Tell()
-{
- if (BufferMode == ReadBuffer)
- return int (FilePos - DataSize + Pos);
-
- int pos = pFile->Tell();
- // Adjust position based on buffer mode & data
- if (pos!=-1)
- {
- OVR_ASSERT(BufferMode != ReadBuffer);
- if (BufferMode == WriteBuffer)
- pos += Pos;
- }
- return pos;
-}
-
-SInt64 BufferedFile::LTell()
-{
- if (BufferMode == ReadBuffer)
- return FilePos - DataSize + Pos;
-
- SInt64 pos = pFile->LTell();
- if (pos!=-1)
- {
- OVR_ASSERT(BufferMode != ReadBuffer);
- if (BufferMode == WriteBuffer)
- pos += Pos;
- }
- return pos;
-}
-
-int BufferedFile::GetLength()
-{
- int len = pFile->GetLength();
- // If writing through buffer, file length may actually be bigger
- if ((len!=-1) && (BufferMode==WriteBuffer))
- {
- int currPos = pFile->Tell() + Pos;
- if (currPos>len)
- len = currPos;
- }
- return len;
-}
-SInt64 BufferedFile::LGetLength()
-{
- SInt64 len = pFile->LGetLength();
- // If writing through buffer, file length may actually be bigger
- if ((len!=-1) && (BufferMode==WriteBuffer))
- {
- SInt64 currPos = pFile->LTell() + Pos;
- if (currPos>len)
- len = currPos;
- }
- return len;
-}
-
-/*
-bool BufferedFile::Stat(FileStats *pfs)
-{
- // Have to fix up length is stat
- if (pFile->Stat(pfs))
- {
- if (BufferMode==WriteBuffer)
- {
- SInt64 currPos = pFile->LTell() + Pos;
- if (currPos > pfs->Size)
- {
- pfs->Size = currPos;
- // ??
- pfs->Blocks = (pfs->Size+511) >> 9;
- }
- }
- return 1;
- }
- return 0;
-}
-*/
-
-int BufferedFile::Write(const UByte *psourceBuffer, int numBytes)
-{
- if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer))
- {
- // If not data space in buffer, flush
- if ((FILEBUFFER_SIZE-(int)Pos)<numBytes)
- {
- FlushBuffer();
- // If bigger then tolerance, just write directly
- if (numBytes>FILEBUFFER_TOLERANCE)
- {
- int sz = pFile->Write(psourceBuffer,numBytes);
- if (sz > 0)
- FilePos += sz;
- return sz;
- }
- }
-
- // Enough space in buffer.. so copy to it
- memcpy(pBuffer+Pos, psourceBuffer, numBytes);
- Pos += numBytes;
- return numBytes;
- }
- int sz = pFile->Write(psourceBuffer,numBytes);
- if (sz > 0)
- FilePos += sz;
- return sz;
-}
-
-int BufferedFile::Read(UByte *pdestBuffer, int numBytes)
-{
- if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer))
- {
- // Data in buffer... copy it
- if ((int)(DataSize-Pos) >= numBytes)
- {
- memcpy(pdestBuffer, pBuffer+Pos, numBytes);
- Pos += numBytes;
- return numBytes;
- }
-
- // Not enough data in buffer, copy buffer
- int readBytes = DataSize-Pos;
- memcpy(pdestBuffer, pBuffer+Pos, readBytes);
- numBytes -= readBytes;
- pdestBuffer += readBytes;
- Pos = DataSize;
-
- // Don't reload buffer if more then tolerance
- // (No major advantage, and we don't want to write a loop)
- if (numBytes>FILEBUFFER_TOLERANCE)
- {
- numBytes = pFile->Read(pdestBuffer,numBytes);
- if (numBytes > 0)
- {
- FilePos += numBytes;
- Pos = DataSize = 0;
- }
- return readBytes + ((numBytes==-1) ? 0 : numBytes);
- }
-
- // Reload the buffer
- // WARNING: Right now LoadBuffer() assumes the buffer's empty
- LoadBuffer();
- if ((int)(DataSize-Pos) < numBytes)
- numBytes = (int)DataSize-Pos;
-
- memcpy(pdestBuffer, pBuffer+Pos, numBytes);
- Pos += numBytes;
- return numBytes + readBytes;
-
- /*
- // Alternative Read implementation. The one above is probably better
- // due to FILEBUFFER_TOLERANCE.
- int total = 0;
-
- do {
- int bufferBytes = (int)(DataSize-Pos);
- int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes;
-
- memcpy(pdestBuffer, pBuffer+Pos, copyBytes);
- numBytes -= copyBytes;
- pdestBuffer += copyBytes;
- Pos += copyBytes;
- total += copyBytes;
-
- if (numBytes == 0)
- break;
- LoadBuffer();
-
- } while (DataSize > 0);
-
- return total;
- */
- }
- int sz = pFile->Read(pdestBuffer,numBytes);
- if (sz > 0)
- FilePos += sz;
- return sz;
-}
-
-
-int BufferedFile::SkipBytes(int numBytes)
-{
- int skippedBytes = 0;
-
- // Special case for skipping a little data in read buffer
- if (BufferMode==ReadBuffer)
- {
- skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos);
- Pos += skippedBytes;
- numBytes -= skippedBytes;
- }
-
- if (numBytes)
- {
- numBytes = pFile->SkipBytes(numBytes);
- // Make sure we return the actual number skipped, or error
- if (numBytes!=-1)
- {
- skippedBytes += numBytes;
- FilePos += numBytes;
- Pos = DataSize = 0;
- }
- else if (skippedBytes <= 0)
- skippedBytes = -1;
- }
- return skippedBytes;
-}
-
-int BufferedFile::BytesAvailable()
-{
- int available = pFile->BytesAvailable();
- // Adjust available size based on buffers
- switch(BufferMode)
- {
- case ReadBuffer:
- available += DataSize-Pos;
- break;
- case WriteBuffer:
- available -= Pos;
- if (available<0)
- available= 0;
- break;
- default:
- break;
- }
- return available;
-}
-
-bool BufferedFile::Flush()
-{
- FlushBuffer();
- return pFile->Flush();
-}
-
-// Seeking could be optimized better..
-int BufferedFile::Seek(int offset, int origin)
-{
- if (BufferMode == ReadBuffer)
- {
- if (origin == Seek_Cur)
- {
- // Seek can fall either before or after Pos in the buffer,
- // but it must be within bounds.
- if (((unsigned(offset) + Pos)) <= DataSize)
- {
- Pos += offset;
- return int (FilePos - DataSize + Pos);
- }
-
- // Lightweight buffer "Flush". We do this to avoid an extra seek
- // back operation which would take place if we called FlushBuffer directly.
- origin = Seek_Set;
- OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0);
- offset = (int)(FilePos - DataSize + Pos) + offset;
- Pos = DataSize = 0;
- }
- else if (origin == Seek_Set)
- {
- if (((unsigned)offset - (FilePos-DataSize)) <= DataSize)
- {
- OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0);
- Pos = (unsigned)offset - (unsigned)(FilePos-DataSize);
- return offset;
- }
- Pos = DataSize = 0;
- }
- else
- {
- FlushBuffer();
- }
- }
- else
- {
- FlushBuffer();
- }
-
- /*
- // Old Seek Logic
- if (origin == Seek_Cur && offset + Pos < DataSize)
- {
- //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset));
- Pos += offset;
- OVR_ASSERT(int (Pos) >= 0);
- return int (FilePos - DataSize + Pos);
- }
- else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos)
- {
- Pos = unsigned(offset - FilePos + DataSize);
- OVR_ASSERT(int (Pos) >= 0);
- return int (FilePos - DataSize + Pos);
- }
-
- FlushBuffer();
- */
-
-
- FilePos = pFile->Seek(offset,origin);
- return int (FilePos);
-}
-
-SInt64 BufferedFile::LSeek(SInt64 offset, int origin)
-{
- if (BufferMode == ReadBuffer)
- {
- if (origin == Seek_Cur)
- {
- // Seek can fall either before or after Pos in the buffer,
- // but it must be within bounds.
- if (((unsigned(offset) + Pos)) <= DataSize)
- {
- Pos += (unsigned)offset;
- return SInt64(FilePos - DataSize + Pos);
- }
-
- // Lightweight buffer "Flush". We do this to avoid an extra seek
- // back operation which would take place if we called FlushBuffer directly.
- origin = Seek_Set;
- offset = (SInt64)(FilePos - DataSize + Pos) + offset;
- Pos = DataSize = 0;
- }
- else if (origin == Seek_Set)
- {
- if (((UInt64)offset - (FilePos-DataSize)) <= DataSize)
- {
- Pos = (unsigned)((UInt64)offset - (FilePos-DataSize));
- return offset;
- }
- Pos = DataSize = 0;
- }
- else
- {
- FlushBuffer();
- }
- }
- else
- {
- FlushBuffer();
- }
-
-/*
- OVR_ASSERT(BufferMode != NoBuffer);
-
- if (origin == Seek_Cur && offset + Pos < DataSize)
- {
- Pos += int (offset);
- return FilePos - DataSize + Pos;
- }
- else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos))
- {
- Pos = unsigned(offset - FilePos + DataSize);
- return FilePos - DataSize + Pos;
- }
-
- FlushBuffer();
- */
-
- FilePos = pFile->LSeek(offset,origin);
- return FilePos;
-}
-
-int BufferedFile::CopyFromStream(File *pstream, int byteSize)
-{
- // We can't rely on overridden Write()
- // because delegation doesn't override virtual pointers
- // So, just re-implement
- UByte buff[0x4000];
- int count = 0;
- int szRequest, szRead, szWritten;
-
- while(byteSize)
- {
- szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
-
- szRead = pstream->Read(buff,szRequest);
- szWritten = 0;
- if (szRead > 0)
- szWritten = Write(buff,szRead);
-
- count +=szWritten;
- byteSize-=szWritten;
- if (szWritten < szRequest)
- break;
- }
- return count;
-}
-
-// Closing files
-bool BufferedFile::Close()
-{
- switch(BufferMode)
- {
- case WriteBuffer:
- FlushBuffer();
- break;
- case ReadBuffer:
- // No need to seek back on close
- BufferMode = NoBuffer;
- break;
- default:
- break;
- }
- return pFile->Close();
-}
-
-
-// ***** Global path helpers
-
-// Find trailing short filename in a path.
-const char* OVR_CDECL GetShortFilename(const char* purl)
-{
- UPInt len = OVR_strlen(purl);
- for (UPInt i=len; i>0; i--)
- if (purl[i]=='\\' || purl[i]=='/')
- return purl+i+1;
- return purl;
-}
-
-} // OVR
-
+/************************************************************************** + +Filename : OVR_File.cpp +Content : File wrapper class implementation (Win32) + +Created : April 5, 1999 +Authors : Michael Antonov + +Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. + +Use of this software is subject to the terms of the Oculus license +agreement provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +**************************************************************************/ + +#define GFILE_CXX + +// Standard C library (Captain Obvious guarantees!) +#include <stdio.h> + +#include "OVR_File.h" + +namespace OVR { + +// Buffered file adds buffering to an existing file +// FILEBUFFER_SIZE defines the size of internal buffer, while +// FILEBUFFER_TOLERANCE controls the amount of data we'll effectively try to buffer +#define FILEBUFFER_SIZE (8192-8) +#define FILEBUFFER_TOLERANCE 4096 + +// ** Constructor/Destructor + +// Hidden constructor +// Not supposed to be used +BufferedFile::BufferedFile() : DelegatedFile(0) +{ + pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + BufferMode = NoBuffer; + FilePos = 0; + Pos = 0; + DataSize = 0; +} + +// Takes another file as source +BufferedFile::BufferedFile(File *pfile) : DelegatedFile(pfile) +{ + pBuffer = (UByte*)OVR_ALLOC(FILEBUFFER_SIZE); + BufferMode = NoBuffer; + FilePos = pfile->LTell(); + Pos = 0; + DataSize = 0; +} + + +// Destructor +BufferedFile::~BufferedFile() +{ + // Flush in case there's data + if (pFile) + FlushBuffer(); + // Get rid of buffer + if (pBuffer) + OVR_FREE(pBuffer); +} + +/* +bool BufferedFile::VCopy(const Object &source) +{ + if (!DelegatedFile::VCopy(source)) + return 0; + + // Data members + BufferedFile *psource = (BufferedFile*)&source; + + // Buffer & the mode it's in + pBuffer = psource->pBuffer; + BufferMode = psource->BufferMode; + Pos = psource->Pos; + DataSize = psource->DataSize; + return 1; +} +*/ + +// Initializes buffering to a certain mode +bool BufferedFile::SetBufferMode(BufferModeType mode) +{ + if (!pBuffer) + return false; + if (mode == BufferMode) + return true; + + FlushBuffer(); + + // Can't set write mode if we can't write + if ((mode==WriteBuffer) && (!pFile || !pFile->IsWritable()) ) + return 0; + + // And SetMode + BufferMode = mode; + Pos = 0; + DataSize = 0; + return 1; +} + +// Flushes buffer +void BufferedFile::FlushBuffer() +{ + switch(BufferMode) + { + case WriteBuffer: + // Write data in buffer + FilePos += pFile->Write(pBuffer,Pos); + Pos = 0; + break; + + case ReadBuffer: + // Seek back & reset buffer data + if ((DataSize-Pos)>0) + FilePos = pFile->LSeek(-(int)(DataSize-Pos), Seek_Cur); + DataSize = 0; + Pos = 0; + break; + default: + // not handled! + break; + } +} + +// Reloads data for ReadBuffer +void BufferedFile::LoadBuffer() +{ + if (BufferMode == ReadBuffer) + { + // We should only reload once all of pre-loaded buffer is consumed. + OVR_ASSERT(Pos == DataSize); + + // WARNING: Right now LoadBuffer() assumes the buffer's empty + int sz = pFile->Read(pBuffer,FILEBUFFER_SIZE); + DataSize = sz<0 ? 0 : (unsigned)sz; + Pos = 0; + FilePos += DataSize; + } +} + + +// ** Overridden functions + +// We override all the functions that can possibly +// require buffer mode switch, flush, or extra calculations + +// Tell() requires buffer adjustment +int BufferedFile::Tell() +{ + if (BufferMode == ReadBuffer) + return int (FilePos - DataSize + Pos); + + int pos = pFile->Tell(); + // Adjust position based on buffer mode & data + if (pos!=-1) + { + OVR_ASSERT(BufferMode != ReadBuffer); + if (BufferMode == WriteBuffer) + pos += Pos; + } + return pos; +} + +SInt64 BufferedFile::LTell() +{ + if (BufferMode == ReadBuffer) + return FilePos - DataSize + Pos; + + SInt64 pos = pFile->LTell(); + if (pos!=-1) + { + OVR_ASSERT(BufferMode != ReadBuffer); + if (BufferMode == WriteBuffer) + pos += Pos; + } + return pos; +} + +int BufferedFile::GetLength() +{ + int len = pFile->GetLength(); + // If writing through buffer, file length may actually be bigger + if ((len!=-1) && (BufferMode==WriteBuffer)) + { + int currPos = pFile->Tell() + Pos; + if (currPos>len) + len = currPos; + } + return len; +} +SInt64 BufferedFile::LGetLength() +{ + SInt64 len = pFile->LGetLength(); + // If writing through buffer, file length may actually be bigger + if ((len!=-1) && (BufferMode==WriteBuffer)) + { + SInt64 currPos = pFile->LTell() + Pos; + if (currPos>len) + len = currPos; + } + return len; +} + +/* +bool BufferedFile::Stat(FileStats *pfs) +{ + // Have to fix up length is stat + if (pFile->Stat(pfs)) + { + if (BufferMode==WriteBuffer) + { + SInt64 currPos = pFile->LTell() + Pos; + if (currPos > pfs->Size) + { + pfs->Size = currPos; + // ?? + pfs->Blocks = (pfs->Size+511) >> 9; + } + } + return 1; + } + return 0; +} +*/ + +int BufferedFile::Write(const UByte *psourceBuffer, int numBytes) +{ + if ( (BufferMode==WriteBuffer) || SetBufferMode(WriteBuffer)) + { + // If not data space in buffer, flush + if ((FILEBUFFER_SIZE-(int)Pos)<numBytes) + { + FlushBuffer(); + // If bigger then tolerance, just write directly + if (numBytes>FILEBUFFER_TOLERANCE) + { + int sz = pFile->Write(psourceBuffer,numBytes); + if (sz > 0) + FilePos += sz; + return sz; + } + } + + // Enough space in buffer.. so copy to it + memcpy(pBuffer+Pos, psourceBuffer, numBytes); + Pos += numBytes; + return numBytes; + } + int sz = pFile->Write(psourceBuffer,numBytes); + if (sz > 0) + FilePos += sz; + return sz; +} + +int BufferedFile::Read(UByte *pdestBuffer, int numBytes) +{ + if ( (BufferMode==ReadBuffer) || SetBufferMode(ReadBuffer)) + { + // Data in buffer... copy it + if ((int)(DataSize-Pos) >= numBytes) + { + memcpy(pdestBuffer, pBuffer+Pos, numBytes); + Pos += numBytes; + return numBytes; + } + + // Not enough data in buffer, copy buffer + int readBytes = DataSize-Pos; + memcpy(pdestBuffer, pBuffer+Pos, readBytes); + numBytes -= readBytes; + pdestBuffer += readBytes; + Pos = DataSize; + + // Don't reload buffer if more then tolerance + // (No major advantage, and we don't want to write a loop) + if (numBytes>FILEBUFFER_TOLERANCE) + { + numBytes = pFile->Read(pdestBuffer,numBytes); + if (numBytes > 0) + { + FilePos += numBytes; + Pos = DataSize = 0; + } + return readBytes + ((numBytes==-1) ? 0 : numBytes); + } + + // Reload the buffer + // WARNING: Right now LoadBuffer() assumes the buffer's empty + LoadBuffer(); + if ((int)(DataSize-Pos) < numBytes) + numBytes = (int)DataSize-Pos; + + memcpy(pdestBuffer, pBuffer+Pos, numBytes); + Pos += numBytes; + return numBytes + readBytes; + + /* + // Alternative Read implementation. The one above is probably better + // due to FILEBUFFER_TOLERANCE. + int total = 0; + + do { + int bufferBytes = (int)(DataSize-Pos); + int copyBytes = (bufferBytes > numBytes) ? numBytes : bufferBytes; + + memcpy(pdestBuffer, pBuffer+Pos, copyBytes); + numBytes -= copyBytes; + pdestBuffer += copyBytes; + Pos += copyBytes; + total += copyBytes; + + if (numBytes == 0) + break; + LoadBuffer(); + + } while (DataSize > 0); + + return total; + */ + } + int sz = pFile->Read(pdestBuffer,numBytes); + if (sz > 0) + FilePos += sz; + return sz; +} + + +int BufferedFile::SkipBytes(int numBytes) +{ + int skippedBytes = 0; + + // Special case for skipping a little data in read buffer + if (BufferMode==ReadBuffer) + { + skippedBytes = (((int)DataSize-(int)Pos) >= numBytes) ? numBytes : (DataSize-Pos); + Pos += skippedBytes; + numBytes -= skippedBytes; + } + + if (numBytes) + { + numBytes = pFile->SkipBytes(numBytes); + // Make sure we return the actual number skipped, or error + if (numBytes!=-1) + { + skippedBytes += numBytes; + FilePos += numBytes; + Pos = DataSize = 0; + } + else if (skippedBytes <= 0) + skippedBytes = -1; + } + return skippedBytes; +} + +int BufferedFile::BytesAvailable() +{ + int available = pFile->BytesAvailable(); + // Adjust available size based on buffers + switch(BufferMode) + { + case ReadBuffer: + available += DataSize-Pos; + break; + case WriteBuffer: + available -= Pos; + if (available<0) + available= 0; + break; + default: + break; + } + return available; +} + +bool BufferedFile::Flush() +{ + FlushBuffer(); + return pFile->Flush(); +} + +// Seeking could be optimized better.. +int BufferedFile::Seek(int offset, int origin) +{ + if (BufferMode == ReadBuffer) + { + if (origin == Seek_Cur) + { + // Seek can fall either before or after Pos in the buffer, + // but it must be within bounds. + if (((unsigned(offset) + Pos)) <= DataSize) + { + Pos += offset; + return int (FilePos - DataSize + Pos); + } + + // Lightweight buffer "Flush". We do this to avoid an extra seek + // back operation which would take place if we called FlushBuffer directly. + origin = Seek_Set; + OVR_ASSERT(((FilePos - DataSize + Pos) + (UInt64)offset) < ~(UInt64)0); + offset = (int)(FilePos - DataSize + Pos) + offset; + Pos = DataSize = 0; + } + else if (origin == Seek_Set) + { + if (((unsigned)offset - (FilePos-DataSize)) <= DataSize) + { + OVR_ASSERT((FilePos-DataSize) < ~(UInt64)0); + Pos = (unsigned)offset - (unsigned)(FilePos-DataSize); + return offset; + } + Pos = DataSize = 0; + } + else + { + FlushBuffer(); + } + } + else + { + FlushBuffer(); + } + + /* + // Old Seek Logic + if (origin == Seek_Cur && offset + Pos < DataSize) + { + //OVR_ASSERT((FilePos - DataSize) >= (FilePos - DataSize + Pos + offset)); + Pos += offset; + OVR_ASSERT(int (Pos) >= 0); + return int (FilePos - DataSize + Pos); + } + else if (origin == Seek_Set && unsigned(offset) >= FilePos - DataSize && unsigned(offset) < FilePos) + { + Pos = unsigned(offset - FilePos + DataSize); + OVR_ASSERT(int (Pos) >= 0); + return int (FilePos - DataSize + Pos); + } + + FlushBuffer(); + */ + + + FilePos = pFile->Seek(offset,origin); + return int (FilePos); +} + +SInt64 BufferedFile::LSeek(SInt64 offset, int origin) +{ + if (BufferMode == ReadBuffer) + { + if (origin == Seek_Cur) + { + // Seek can fall either before or after Pos in the buffer, + // but it must be within bounds. + if (((unsigned(offset) + Pos)) <= DataSize) + { + Pos += (unsigned)offset; + return SInt64(FilePos - DataSize + Pos); + } + + // Lightweight buffer "Flush". We do this to avoid an extra seek + // back operation which would take place if we called FlushBuffer directly. + origin = Seek_Set; + offset = (SInt64)(FilePos - DataSize + Pos) + offset; + Pos = DataSize = 0; + } + else if (origin == Seek_Set) + { + if (((UInt64)offset - (FilePos-DataSize)) <= DataSize) + { + Pos = (unsigned)((UInt64)offset - (FilePos-DataSize)); + return offset; + } + Pos = DataSize = 0; + } + else + { + FlushBuffer(); + } + } + else + { + FlushBuffer(); + } + +/* + OVR_ASSERT(BufferMode != NoBuffer); + + if (origin == Seek_Cur && offset + Pos < DataSize) + { + Pos += int (offset); + return FilePos - DataSize + Pos; + } + else if (origin == Seek_Set && offset >= SInt64(FilePos - DataSize) && offset < SInt64(FilePos)) + { + Pos = unsigned(offset - FilePos + DataSize); + return FilePos - DataSize + Pos; + } + + FlushBuffer(); + */ + + FilePos = pFile->LSeek(offset,origin); + return FilePos; +} + +int BufferedFile::CopyFromStream(File *pstream, int byteSize) +{ + // We can't rely on overridden Write() + // because delegation doesn't override virtual pointers + // So, just re-implement + UByte buff[0x4000]; + int count = 0; + int szRequest, szRead, szWritten; + + while(byteSize) + { + szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize; + + szRead = pstream->Read(buff,szRequest); + szWritten = 0; + if (szRead > 0) + szWritten = Write(buff,szRead); + + count +=szWritten; + byteSize-=szWritten; + if (szWritten < szRequest) + break; + } + return count; +} + +// Closing files +bool BufferedFile::Close() +{ + switch(BufferMode) + { + case WriteBuffer: + FlushBuffer(); + break; + case ReadBuffer: + // No need to seek back on close + BufferMode = NoBuffer; + break; + default: + break; + } + return pFile->Close(); +} + + +// ***** Global path helpers + +// Find trailing short filename in a path. +const char* OVR_CDECL GetShortFilename(const char* purl) +{ + UPInt len = OVR_strlen(purl); + for (UPInt i=len; i>0; i--) + if (purl[i]=='\\' || purl[i]=='/') + return purl+i+1; + return purl; +} + +} // OVR + |