oculus1

diff libovr/Src/Kernel/OVR_FileFILE.cpp @ 3:b069a5c27388

added a couple more stuff, fixed all the LibOVR line endings
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 15 Sep 2013 04:10:05 +0300
parents e2f9e4603129
children
line diff
     1.1 --- a/libovr/Src/Kernel/OVR_FileFILE.cpp	Sat Sep 14 17:51:03 2013 +0300
     1.2 +++ b/libovr/Src/Kernel/OVR_FileFILE.cpp	Sun Sep 15 04:10:05 2013 +0300
     1.3 @@ -1,1 +1,583 @@
     1.4 -/**************************************************************************
     1.5 
     1.6 Filename    :   OVR_FileFILE.cpp
     1.7 Content     :   File wrapper class implementation (Win32)
     1.8 
     1.9 Created     :   April 5, 1999
    1.10 Authors     :   Michael Antonov
    1.11 
    1.12 Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
    1.13 
    1.14 Use of this software is subject to the terms of the Oculus license
    1.15 agreement provided at the time of installation or download, or which
    1.16 otherwise accompanies this software in either electronic or hard copy form.
    1.17 
    1.18 **************************************************************************/
    1.19 
    1.20 #define  GFILE_CXX
    1.21 
    1.22 #include "OVR_Types.h"
    1.23 #include "OVR_Log.h"
    1.24 
    1.25 // Standard C library (Captain Obvious guarantees!)
    1.26 #include <stdio.h>
    1.27 #ifndef OVR_OS_WINCE
    1.28 #include <sys/stat.h>
    1.29 #endif
    1.30 
    1.31 #include "OVR_SysFile.h"
    1.32 
    1.33 #ifndef OVR_OS_WINCE
    1.34 #include <errno.h>
    1.35 #endif
    1.36 
    1.37 namespace OVR {
    1.38 
    1.39 // ***** File interface
    1.40 
    1.41 // ***** FILEFile - C streams file
    1.42 
    1.43 static int SFerror ()
    1.44 {
    1.45     if (errno == ENOENT)
    1.46         return FileConstants::Error_FileNotFound;
    1.47     else if (errno == EACCES || errno == EPERM)
    1.48         return FileConstants::Error_Access;
    1.49     else if (errno == ENOSPC)
    1.50         return FileConstants::Error_DiskFull;
    1.51     else
    1.52         return FileConstants::Error_IOError;
    1.53 };
    1.54 
    1.55 #ifdef OVR_OS_WIN32
    1.56 #include "windows.h"
    1.57 // A simple helper class to disable/enable system error mode, if necessary
    1.58 // Disabling happens conditionally only if a drive name is involved
    1.59 class SysErrorModeDisabler
    1.60 {
    1.61     BOOL    Disabled;
    1.62     UINT    OldMode;
    1.63 public:
    1.64     SysErrorModeDisabler(const char* pfileName)
    1.65     {
    1.66         if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
    1.67         {
    1.68             Disabled = 1;
    1.69             OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
    1.70         }
    1.71         else
    1.72             Disabled = 0;
    1.73     }
    1.74 
    1.75     ~SysErrorModeDisabler()
    1.76     {
    1.77         if (Disabled) ::SetErrorMode(OldMode);
    1.78     }
    1.79 };
    1.80 #else
    1.81 class SysErrorModeDisabler
    1.82 {
    1.83 public:
    1.84     SysErrorModeDisabler(const char* pfileName) { }
    1.85 };
    1.86 #endif // OVR_OS_WIN32
    1.87 
    1.88 
    1.89 // This macro enables verification of I/O results after seeks against a pre-loaded
    1.90 // full file buffer copy. This is generally not necessary, but can been used to debug
    1.91 // memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
    1.92 // under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
    1.93 //#define GFILE_VERIFY_SEEK_ERRORS
    1.94 
    1.95 
    1.96 // This is the simplest possible file implementation, it wraps around the descriptor
    1.97 // This file is delegated to by SysFile.
    1.98 
    1.99 class FILEFile : public File
   1.100 {
   1.101 protected:
   1.102 
   1.103     // Allocated filename
   1.104     String      FileName;
   1.105 
   1.106     // File handle & open mode
   1.107     bool        Opened;
   1.108     FILE*       fs;
   1.109     int         OpenFlags;
   1.110     // Error code for last request
   1.111     int         ErrorCode;
   1.112 
   1.113     int         LastOp;
   1.114 
   1.115 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.116     UByte*      pFileTestBuffer;
   1.117     unsigned    FileTestLength;
   1.118     unsigned    TestPos; // File pointer position during tests.
   1.119 #endif
   1.120 
   1.121 public:
   1.122 
   1.123     FILEFile()
   1.124     {
   1.125         Opened = 0; FileName = "";
   1.126 
   1.127 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.128         pFileTestBuffer =0;
   1.129         FileTestLength  =0;
   1.130         TestPos         =0;
   1.131 #endif
   1.132     }
   1.133     // Initialize file by opening it
   1.134     FILEFile(const String& fileName, int flags, int Mode);
   1.135     // The 'pfileName' should be encoded as UTF-8 to support international file names.
   1.136     FILEFile(const char* pfileName, int flags, int Mode);
   1.137 
   1.138     ~FILEFile()
   1.139     {
   1.140         if (Opened)
   1.141             Close();
   1.142     }
   1.143 
   1.144     virtual const char* GetFilePath();
   1.145 
   1.146     // ** File Information
   1.147     virtual bool        IsValid();
   1.148     virtual bool        IsWritable();
   1.149 
   1.150     // Return position / file size
   1.151     virtual int         Tell();
   1.152     virtual SInt64      LTell();
   1.153     virtual int         GetLength();
   1.154     virtual SInt64      LGetLength();
   1.155 
   1.156 //  virtual bool        Stat(FileStats *pfs);
   1.157     virtual int         GetErrorCode();
   1.158 
   1.159     // ** Stream implementation & I/O
   1.160     virtual int         Write(const UByte *pbuffer, int numBytes);
   1.161     virtual int         Read(UByte *pbuffer, int numBytes);
   1.162     virtual int         SkipBytes(int numBytes);
   1.163     virtual int         BytesAvailable();
   1.164     virtual bool        Flush();
   1.165     virtual int         Seek(int offset, int origin);
   1.166     virtual SInt64      LSeek(SInt64 offset, int origin);
   1.167     
   1.168     virtual int         CopyFromStream(File *pStream, int byteSize);
   1.169     virtual bool        Close();    
   1.170 private:
   1.171     void                init();
   1.172 };
   1.173 
   1.174 
   1.175 // Initialize file by opening it
   1.176 FILEFile::FILEFile(const String& fileName, int flags, int mode)
   1.177   : FileName(fileName), OpenFlags(flags)
   1.178 {
   1.179     OVR_UNUSED(mode);
   1.180     init();
   1.181 }
   1.182 
   1.183 // The 'pfileName' should be encoded as UTF-8 to support international file names.
   1.184 FILEFile::FILEFile(const char* pfileName, int flags, int mode)
   1.185   : FileName(pfileName), OpenFlags(flags)
   1.186 {
   1.187     OVR_UNUSED(mode);
   1.188     init();
   1.189 }
   1.190 
   1.191 void FILEFile::init()
   1.192 {
   1.193     // Open mode for file's open
   1.194     const char *omode = "rb";
   1.195 
   1.196     if (OpenFlags & Open_Truncate)
   1.197     {
   1.198         if (OpenFlags & Open_Read)
   1.199             omode = "w+b";
   1.200         else
   1.201             omode = "wb";
   1.202     }
   1.203     else if (OpenFlags & Open_Create)
   1.204     {
   1.205         if (OpenFlags & Open_Read)
   1.206             omode = "a+b";
   1.207         else
   1.208             omode = "ab";
   1.209     }
   1.210     else if (OpenFlags & Open_Write)
   1.211         omode = "r+b";
   1.212 
   1.213 #ifdef OVR_OS_WIN32
   1.214     SysErrorModeDisabler disabler(FileName.ToCStr());
   1.215 #endif
   1.216 
   1.217 #if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   1.218     wchar_t womode[16];
   1.219     wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
   1.220     UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
   1.221     OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
   1.222     UTF8Util::DecodeString(womode, omode);
   1.223     _wfopen_s(&fs, pwFileName, womode);
   1.224     OVR_FREE(pwFileName);
   1.225 #else
   1.226     fs = fopen(FileName.ToCStr(), omode);
   1.227 #endif
   1.228     if (fs)
   1.229         rewind (fs);
   1.230     Opened = (fs != NULL);
   1.231     // Set error code
   1.232     if (!Opened)
   1.233         ErrorCode = SFerror();
   1.234     else
   1.235     {
   1.236         // If we are testing file seek correctness, pre-load the entire file so
   1.237         // that we can do comparison tests later.
   1.238 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS        
   1.239         TestPos         = 0;
   1.240         fseek(fs, 0, SEEK_END);
   1.241         FileTestLength  = ftell(fs);
   1.242         fseek(fs, 0, SEEK_SET);
   1.243         pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength);
   1.244         if (pFileTestBuffer)
   1.245         {
   1.246             OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
   1.247             Seek(0, Seek_Set);
   1.248         }        
   1.249 #endif
   1.250 
   1.251         ErrorCode = 0;
   1.252     }
   1.253     LastOp = 0;
   1.254 }
   1.255 
   1.256 
   1.257 const char* FILEFile::GetFilePath()
   1.258 {
   1.259     return FileName.ToCStr();
   1.260 }
   1.261 
   1.262 
   1.263 // ** File Information
   1.264 bool    FILEFile::IsValid()
   1.265 {
   1.266     return Opened;
   1.267 }
   1.268 bool    FILEFile::IsWritable()
   1.269 {
   1.270     return IsValid() && (OpenFlags&Open_Write);
   1.271 }
   1.272 /*
   1.273 bool    FILEFile::IsRecoverable()
   1.274 {
   1.275     return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
   1.276 }
   1.277 */
   1.278 
   1.279 // Return position / file size
   1.280 int     FILEFile::Tell()
   1.281 {
   1.282     int pos = (int)ftell (fs);
   1.283     if (pos < 0)
   1.284         ErrorCode = SFerror();
   1.285     return pos;
   1.286 }
   1.287 
   1.288 SInt64  FILEFile::LTell()
   1.289 {
   1.290     SInt64 pos = ftell(fs);
   1.291     if (pos < 0)
   1.292         ErrorCode = SFerror();
   1.293     return pos;
   1.294 }
   1.295 
   1.296 int     FILEFile::GetLength()
   1.297 {
   1.298     int pos = Tell();
   1.299     if (pos >= 0)
   1.300     {
   1.301         Seek (0, Seek_End);
   1.302         int size = Tell();
   1.303         Seek (pos, Seek_Set);
   1.304         return size;
   1.305     }
   1.306     return -1;
   1.307 }
   1.308 SInt64  FILEFile::LGetLength()
   1.309 {
   1.310     SInt64 pos = LTell();
   1.311     if (pos >= 0)
   1.312     {
   1.313         LSeek (0, Seek_End);
   1.314         SInt64 size = LTell();
   1.315         LSeek (pos, Seek_Set);
   1.316         return size;
   1.317     }
   1.318     return -1;
   1.319 }
   1.320 
   1.321 int     FILEFile::GetErrorCode()
   1.322 {
   1.323     return ErrorCode;
   1.324 }
   1.325 
   1.326 // ** Stream implementation & I/O
   1.327 int     FILEFile::Write(const UByte *pbuffer, int numBytes)
   1.328 {
   1.329     if (LastOp && LastOp != Open_Write)
   1.330         fflush(fs);
   1.331     LastOp = Open_Write;
   1.332     int written = (int) fwrite(pbuffer, 1, numBytes, fs);
   1.333     if (written < numBytes)
   1.334         ErrorCode = SFerror();
   1.335 
   1.336 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.337     if (written > 0)
   1.338         TestPos += written;
   1.339 #endif
   1.340 
   1.341     return written;
   1.342 }
   1.343 
   1.344 int     FILEFile::Read(UByte *pbuffer, int numBytes)
   1.345 {
   1.346     if (LastOp && LastOp != Open_Read)
   1.347         fflush(fs);
   1.348     LastOp = Open_Read;
   1.349     int read = (int) fread(pbuffer, 1, numBytes, fs);
   1.350     if (read < numBytes)
   1.351         ErrorCode = SFerror();
   1.352 
   1.353 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.354     if (read > 0)
   1.355     {
   1.356         // Read-in data must match our pre-loaded buffer data!
   1.357         UByte* pcompareBuffer = pFileTestBuffer + TestPos;
   1.358         for (int i=0; i< read; i++)
   1.359         {
   1.360             OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
   1.361         }
   1.362 
   1.363         //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
   1.364         TestPos += read;
   1.365         OVR_ASSERT(ftell(fs) == (int)TestPos);
   1.366     }
   1.367 #endif
   1.368 
   1.369     return read;
   1.370 }
   1.371 
   1.372 // Seeks ahead to skip bytes
   1.373 int     FILEFile::SkipBytes(int numBytes)
   1.374 {
   1.375     SInt64 pos    = LTell();
   1.376     SInt64 newPos = LSeek(numBytes, Seek_Cur);
   1.377 
   1.378     // Return -1 for major error
   1.379     if ((pos==-1) || (newPos==-1))
   1.380     {
   1.381         return -1;
   1.382     }
   1.383     //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
   1.384 
   1.385     return int (newPos-(int)pos);
   1.386 }
   1.387 
   1.388 // Return # of bytes till EOF
   1.389 int     FILEFile::BytesAvailable()
   1.390 {
   1.391     SInt64 pos    = LTell();
   1.392     SInt64 endPos = LGetLength();
   1.393 
   1.394     // Return -1 for major error
   1.395     if ((pos==-1) || (endPos==-1))
   1.396     {
   1.397         ErrorCode = SFerror();
   1.398         return 0;
   1.399     }
   1.400     else
   1.401         ErrorCode = 0;
   1.402 
   1.403     return int (endPos-(int)pos);
   1.404 }
   1.405 
   1.406 // Flush file contents
   1.407 bool    FILEFile::Flush()
   1.408 {
   1.409     return !fflush(fs);
   1.410 }
   1.411 
   1.412 int     FILEFile::Seek(int offset, int origin)
   1.413 {
   1.414     int newOrigin = 0;
   1.415     switch(origin)
   1.416     {
   1.417     case Seek_Set: newOrigin = SEEK_SET; break;
   1.418     case Seek_Cur: newOrigin = SEEK_CUR; break;
   1.419     case Seek_End: newOrigin = SEEK_END; break;
   1.420     }
   1.421 
   1.422     if (newOrigin == SEEK_SET && offset == Tell())
   1.423         return Tell();
   1.424 
   1.425     if (fseek (fs, offset, newOrigin))
   1.426     {
   1.427 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.428         OVR_ASSERT(0);
   1.429 #endif
   1.430         return -1;
   1.431     }
   1.432     
   1.433 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.434     // Track file position after seeks for read verification later.
   1.435     switch(origin)
   1.436     {
   1.437     case Seek_Set:  TestPos = offset;       break;
   1.438     case Seek_Cur:  TestPos += offset;      break;    
   1.439     case Seek_End:  TestPos = FileTestLength + offset; break;
   1.440     }
   1.441     OVR_ASSERT((int)TestPos == Tell());
   1.442 #endif
   1.443 
   1.444     return (int)Tell();
   1.445 }
   1.446 
   1.447 SInt64  FILEFile::LSeek(SInt64 offset, int origin)
   1.448 {
   1.449     return Seek((int)offset,origin);
   1.450 }
   1.451 
   1.452 int FILEFile::CopyFromStream(File *pstream, int byteSize)
   1.453 {
   1.454     UByte   buff[0x4000];
   1.455     int     count = 0;
   1.456     int     szRequest, szRead, szWritten;
   1.457 
   1.458     while (byteSize)
   1.459     {
   1.460         szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
   1.461 
   1.462         szRead    = pstream->Read(buff, szRequest);
   1.463         szWritten = 0;
   1.464         if (szRead > 0)
   1.465             szWritten = Write(buff, szRead);
   1.466 
   1.467         count    += szWritten;
   1.468         byteSize -= szWritten;
   1.469         if (szWritten < szRequest)
   1.470             break;
   1.471     }
   1.472     return count;
   1.473 }
   1.474 
   1.475 
   1.476 bool FILEFile::Close()
   1.477 {
   1.478 #ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.479     if (pFileTestBuffer)
   1.480     {
   1.481         OVR_FREE(pFileTestBuffer);
   1.482         pFileTestBuffer = 0;
   1.483         FileTestLength  = 0;
   1.484     }
   1.485 #endif
   1.486 
   1.487     bool closeRet = !fclose(fs);
   1.488 
   1.489     if (!closeRet)
   1.490     {
   1.491         ErrorCode = SFerror();
   1.492         return 0;
   1.493     }
   1.494     else
   1.495     {
   1.496         Opened    = 0;
   1.497         fs        = 0;
   1.498         ErrorCode = 0;
   1.499     }
   1.500 
   1.501     // Handle safe truncate
   1.502     /*
   1.503     if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
   1.504     {
   1.505         // Delete original file (if it existed)
   1.506         DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
   1.507         if (oldAttributes!=0xFFFFFFFF)
   1.508             if (!FileUtilWin32::DeleteFile(FileName))
   1.509             {
   1.510                 // Try to remove the readonly attribute
   1.511                 FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
   1.512                 // And delete the file again
   1.513                 if (!FileUtilWin32::DeleteFile(FileName))
   1.514                     return 0;
   1.515             }
   1.516 
   1.517         // Rename temp file to real filename
   1.518         if (!FileUtilWin32::MoveFile(TempName, FileName))
   1.519         {
   1.520             //ErrorCode = errno;
   1.521             return 0;
   1.522         }
   1.523     }
   1.524     */
   1.525     return 1;
   1.526 }
   1.527 
   1.528 /*
   1.529 bool    FILEFile::CloseCancel()
   1.530 {
   1.531     bool closeRet = (bool)::CloseHandle(fd);
   1.532 
   1.533     if (!closeRet)
   1.534     {
   1.535         //ErrorCode = errno;
   1.536         return 0;
   1.537     }
   1.538     else
   1.539     {
   1.540         Opened    = 0;
   1.541         fd        = INVALID_HANDLE_VALUE;
   1.542         ErrorCode = 0;
   1.543     }
   1.544 
   1.545     // Handle safe truncate (delete tmp file, leave original unchanged)
   1.546     if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
   1.547         if (!FileUtilWin32::DeleteFile(TempName))
   1.548         {
   1.549             //ErrorCode = errno;
   1.550             return 0;
   1.551         }
   1.552     return 1;
   1.553 }
   1.554 */
   1.555 
   1.556 File *FileFILEOpen(const String& path, int flags, int mode)
   1.557 {
   1.558     return new FILEFile(path, flags, mode);
   1.559 }
   1.560 
   1.561 // Helper function: obtain file information time.
   1.562 bool    SysFile::GetFileStat(FileStat* pfileStat, const String& path)
   1.563 {
   1.564 #if defined(OVR_OS_WIN32)
   1.565     // 64-bit implementation on Windows.
   1.566     struct __stat64 fileStat;
   1.567     // Stat returns 0 for success.
   1.568     wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
   1.569     UTF8Util::DecodeString(pwpath, path.ToCStr());
   1.570 
   1.571     int ret = _wstat64(pwpath, &fileStat);
   1.572     OVR_FREE(pwpath);
   1.573     if (ret) return false;
   1.574 #else
   1.575     struct stat fileStat;
   1.576     // Stat returns 0 for success.
   1.577     if (stat(path, &fileStat) != 0)
   1.578         return false;
   1.579 #endif
   1.580     pfileStat->AccessTime = fileStat.st_atime;
   1.581     pfileStat->ModifyTime = fileStat.st_mtime;
   1.582     pfileStat->FileSize   = fileStat.st_size;
   1.583     return true;
   1.584 }
   1.585 
   1.586 } // Scaleform
   1.587 \ No newline at end of file
   1.588 +/**************************************************************************
   1.589 +
   1.590 +Filename    :   OVR_FileFILE.cpp
   1.591 +Content     :   File wrapper class implementation (Win32)
   1.592 +
   1.593 +Created     :   April 5, 1999
   1.594 +Authors     :   Michael Antonov
   1.595 +
   1.596 +Copyright   :   Copyright 2012 Oculus VR, Inc. All Rights reserved.
   1.597 +
   1.598 +Use of this software is subject to the terms of the Oculus license
   1.599 +agreement provided at the time of installation or download, or which
   1.600 +otherwise accompanies this software in either electronic or hard copy form.
   1.601 +
   1.602 +**************************************************************************/
   1.603 +
   1.604 +#define  GFILE_CXX
   1.605 +
   1.606 +#include "OVR_Types.h"
   1.607 +#include "OVR_Log.h"
   1.608 +
   1.609 +// Standard C library (Captain Obvious guarantees!)
   1.610 +#include <stdio.h>
   1.611 +#ifndef OVR_OS_WINCE
   1.612 +#include <sys/stat.h>
   1.613 +#endif
   1.614 +
   1.615 +#include "OVR_SysFile.h"
   1.616 +
   1.617 +#ifndef OVR_OS_WINCE
   1.618 +#include <errno.h>
   1.619 +#endif
   1.620 +
   1.621 +namespace OVR {
   1.622 +
   1.623 +// ***** File interface
   1.624 +
   1.625 +// ***** FILEFile - C streams file
   1.626 +
   1.627 +static int SFerror ()
   1.628 +{
   1.629 +    if (errno == ENOENT)
   1.630 +        return FileConstants::Error_FileNotFound;
   1.631 +    else if (errno == EACCES || errno == EPERM)
   1.632 +        return FileConstants::Error_Access;
   1.633 +    else if (errno == ENOSPC)
   1.634 +        return FileConstants::Error_DiskFull;
   1.635 +    else
   1.636 +        return FileConstants::Error_IOError;
   1.637 +};
   1.638 +
   1.639 +#ifdef OVR_OS_WIN32
   1.640 +#include "windows.h"
   1.641 +// A simple helper class to disable/enable system error mode, if necessary
   1.642 +// Disabling happens conditionally only if a drive name is involved
   1.643 +class SysErrorModeDisabler
   1.644 +{
   1.645 +    BOOL    Disabled;
   1.646 +    UINT    OldMode;
   1.647 +public:
   1.648 +    SysErrorModeDisabler(const char* pfileName)
   1.649 +    {
   1.650 +        if (pfileName && (pfileName[0]!=0) && pfileName[1]==':')
   1.651 +        {
   1.652 +            Disabled = 1;
   1.653 +            OldMode = ::SetErrorMode(SEM_FAILCRITICALERRORS);
   1.654 +        }
   1.655 +        else
   1.656 +            Disabled = 0;
   1.657 +    }
   1.658 +
   1.659 +    ~SysErrorModeDisabler()
   1.660 +    {
   1.661 +        if (Disabled) ::SetErrorMode(OldMode);
   1.662 +    }
   1.663 +};
   1.664 +#else
   1.665 +class SysErrorModeDisabler
   1.666 +{
   1.667 +public:
   1.668 +    SysErrorModeDisabler(const char* pfileName) { }
   1.669 +};
   1.670 +#endif // OVR_OS_WIN32
   1.671 +
   1.672 +
   1.673 +// This macro enables verification of I/O results after seeks against a pre-loaded
   1.674 +// full file buffer copy. This is generally not necessary, but can been used to debug
   1.675 +// memory corruptions; we've seen this fail due to EAX2/DirectSound corrupting memory
   1.676 +// under FMOD with XP64 (32-bit) and Realtek HA Audio driver.
   1.677 +//#define GFILE_VERIFY_SEEK_ERRORS
   1.678 +
   1.679 +
   1.680 +// This is the simplest possible file implementation, it wraps around the descriptor
   1.681 +// This file is delegated to by SysFile.
   1.682 +
   1.683 +class FILEFile : public File
   1.684 +{
   1.685 +protected:
   1.686 +
   1.687 +    // Allocated filename
   1.688 +    String      FileName;
   1.689 +
   1.690 +    // File handle & open mode
   1.691 +    bool        Opened;
   1.692 +    FILE*       fs;
   1.693 +    int         OpenFlags;
   1.694 +    // Error code for last request
   1.695 +    int         ErrorCode;
   1.696 +
   1.697 +    int         LastOp;
   1.698 +
   1.699 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.700 +    UByte*      pFileTestBuffer;
   1.701 +    unsigned    FileTestLength;
   1.702 +    unsigned    TestPos; // File pointer position during tests.
   1.703 +#endif
   1.704 +
   1.705 +public:
   1.706 +
   1.707 +    FILEFile()
   1.708 +    {
   1.709 +        Opened = 0; FileName = "";
   1.710 +
   1.711 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.712 +        pFileTestBuffer =0;
   1.713 +        FileTestLength  =0;
   1.714 +        TestPos         =0;
   1.715 +#endif
   1.716 +    }
   1.717 +    // Initialize file by opening it
   1.718 +    FILEFile(const String& fileName, int flags, int Mode);
   1.719 +    // The 'pfileName' should be encoded as UTF-8 to support international file names.
   1.720 +    FILEFile(const char* pfileName, int flags, int Mode);
   1.721 +
   1.722 +    ~FILEFile()
   1.723 +    {
   1.724 +        if (Opened)
   1.725 +            Close();
   1.726 +    }
   1.727 +
   1.728 +    virtual const char* GetFilePath();
   1.729 +
   1.730 +    // ** File Information
   1.731 +    virtual bool        IsValid();
   1.732 +    virtual bool        IsWritable();
   1.733 +
   1.734 +    // Return position / file size
   1.735 +    virtual int         Tell();
   1.736 +    virtual SInt64      LTell();
   1.737 +    virtual int         GetLength();
   1.738 +    virtual SInt64      LGetLength();
   1.739 +
   1.740 +//  virtual bool        Stat(FileStats *pfs);
   1.741 +    virtual int         GetErrorCode();
   1.742 +
   1.743 +    // ** Stream implementation & I/O
   1.744 +    virtual int         Write(const UByte *pbuffer, int numBytes);
   1.745 +    virtual int         Read(UByte *pbuffer, int numBytes);
   1.746 +    virtual int         SkipBytes(int numBytes);
   1.747 +    virtual int         BytesAvailable();
   1.748 +    virtual bool        Flush();
   1.749 +    virtual int         Seek(int offset, int origin);
   1.750 +    virtual SInt64      LSeek(SInt64 offset, int origin);
   1.751 +    
   1.752 +    virtual int         CopyFromStream(File *pStream, int byteSize);
   1.753 +    virtual bool        Close();    
   1.754 +private:
   1.755 +    void                init();
   1.756 +};
   1.757 +
   1.758 +
   1.759 +// Initialize file by opening it
   1.760 +FILEFile::FILEFile(const String& fileName, int flags, int mode)
   1.761 +  : FileName(fileName), OpenFlags(flags)
   1.762 +{
   1.763 +    OVR_UNUSED(mode);
   1.764 +    init();
   1.765 +}
   1.766 +
   1.767 +// The 'pfileName' should be encoded as UTF-8 to support international file names.
   1.768 +FILEFile::FILEFile(const char* pfileName, int flags, int mode)
   1.769 +  : FileName(pfileName), OpenFlags(flags)
   1.770 +{
   1.771 +    OVR_UNUSED(mode);
   1.772 +    init();
   1.773 +}
   1.774 +
   1.775 +void FILEFile::init()
   1.776 +{
   1.777 +    // Open mode for file's open
   1.778 +    const char *omode = "rb";
   1.779 +
   1.780 +    if (OpenFlags & Open_Truncate)
   1.781 +    {
   1.782 +        if (OpenFlags & Open_Read)
   1.783 +            omode = "w+b";
   1.784 +        else
   1.785 +            omode = "wb";
   1.786 +    }
   1.787 +    else if (OpenFlags & Open_Create)
   1.788 +    {
   1.789 +        if (OpenFlags & Open_Read)
   1.790 +            omode = "a+b";
   1.791 +        else
   1.792 +            omode = "ab";
   1.793 +    }
   1.794 +    else if (OpenFlags & Open_Write)
   1.795 +        omode = "r+b";
   1.796 +
   1.797 +#ifdef OVR_OS_WIN32
   1.798 +    SysErrorModeDisabler disabler(FileName.ToCStr());
   1.799 +#endif
   1.800 +
   1.801 +#if defined(OVR_CC_MSVC) && (OVR_CC_MSVC >= 1400)
   1.802 +    wchar_t womode[16];
   1.803 +    wchar_t *pwFileName = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(FileName.ToCStr())+1) * sizeof(wchar_t));
   1.804 +    UTF8Util::DecodeString(pwFileName, FileName.ToCStr());
   1.805 +    OVR_ASSERT(strlen(omode) < sizeof(womode)/sizeof(womode[0]));
   1.806 +    UTF8Util::DecodeString(womode, omode);
   1.807 +    _wfopen_s(&fs, pwFileName, womode);
   1.808 +    OVR_FREE(pwFileName);
   1.809 +#else
   1.810 +    fs = fopen(FileName.ToCStr(), omode);
   1.811 +#endif
   1.812 +    if (fs)
   1.813 +        rewind (fs);
   1.814 +    Opened = (fs != NULL);
   1.815 +    // Set error code
   1.816 +    if (!Opened)
   1.817 +        ErrorCode = SFerror();
   1.818 +    else
   1.819 +    {
   1.820 +        // If we are testing file seek correctness, pre-load the entire file so
   1.821 +        // that we can do comparison tests later.
   1.822 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS        
   1.823 +        TestPos         = 0;
   1.824 +        fseek(fs, 0, SEEK_END);
   1.825 +        FileTestLength  = ftell(fs);
   1.826 +        fseek(fs, 0, SEEK_SET);
   1.827 +        pFileTestBuffer = (UByte*)OVR_ALLOC(FileTestLength);
   1.828 +        if (pFileTestBuffer)
   1.829 +        {
   1.830 +            OVR_ASSERT(FileTestLength == (unsigned)Read(pFileTestBuffer, FileTestLength));
   1.831 +            Seek(0, Seek_Set);
   1.832 +        }        
   1.833 +#endif
   1.834 +
   1.835 +        ErrorCode = 0;
   1.836 +    }
   1.837 +    LastOp = 0;
   1.838 +}
   1.839 +
   1.840 +
   1.841 +const char* FILEFile::GetFilePath()
   1.842 +{
   1.843 +    return FileName.ToCStr();
   1.844 +}
   1.845 +
   1.846 +
   1.847 +// ** File Information
   1.848 +bool    FILEFile::IsValid()
   1.849 +{
   1.850 +    return Opened;
   1.851 +}
   1.852 +bool    FILEFile::IsWritable()
   1.853 +{
   1.854 +    return IsValid() && (OpenFlags&Open_Write);
   1.855 +}
   1.856 +/*
   1.857 +bool    FILEFile::IsRecoverable()
   1.858 +{
   1.859 +    return IsValid() && ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC);
   1.860 +}
   1.861 +*/
   1.862 +
   1.863 +// Return position / file size
   1.864 +int     FILEFile::Tell()
   1.865 +{
   1.866 +    int pos = (int)ftell (fs);
   1.867 +    if (pos < 0)
   1.868 +        ErrorCode = SFerror();
   1.869 +    return pos;
   1.870 +}
   1.871 +
   1.872 +SInt64  FILEFile::LTell()
   1.873 +{
   1.874 +    SInt64 pos = ftell(fs);
   1.875 +    if (pos < 0)
   1.876 +        ErrorCode = SFerror();
   1.877 +    return pos;
   1.878 +}
   1.879 +
   1.880 +int     FILEFile::GetLength()
   1.881 +{
   1.882 +    int pos = Tell();
   1.883 +    if (pos >= 0)
   1.884 +    {
   1.885 +        Seek (0, Seek_End);
   1.886 +        int size = Tell();
   1.887 +        Seek (pos, Seek_Set);
   1.888 +        return size;
   1.889 +    }
   1.890 +    return -1;
   1.891 +}
   1.892 +SInt64  FILEFile::LGetLength()
   1.893 +{
   1.894 +    SInt64 pos = LTell();
   1.895 +    if (pos >= 0)
   1.896 +    {
   1.897 +        LSeek (0, Seek_End);
   1.898 +        SInt64 size = LTell();
   1.899 +        LSeek (pos, Seek_Set);
   1.900 +        return size;
   1.901 +    }
   1.902 +    return -1;
   1.903 +}
   1.904 +
   1.905 +int     FILEFile::GetErrorCode()
   1.906 +{
   1.907 +    return ErrorCode;
   1.908 +}
   1.909 +
   1.910 +// ** Stream implementation & I/O
   1.911 +int     FILEFile::Write(const UByte *pbuffer, int numBytes)
   1.912 +{
   1.913 +    if (LastOp && LastOp != Open_Write)
   1.914 +        fflush(fs);
   1.915 +    LastOp = Open_Write;
   1.916 +    int written = (int) fwrite(pbuffer, 1, numBytes, fs);
   1.917 +    if (written < numBytes)
   1.918 +        ErrorCode = SFerror();
   1.919 +
   1.920 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.921 +    if (written > 0)
   1.922 +        TestPos += written;
   1.923 +#endif
   1.924 +
   1.925 +    return written;
   1.926 +}
   1.927 +
   1.928 +int     FILEFile::Read(UByte *pbuffer, int numBytes)
   1.929 +{
   1.930 +    if (LastOp && LastOp != Open_Read)
   1.931 +        fflush(fs);
   1.932 +    LastOp = Open_Read;
   1.933 +    int read = (int) fread(pbuffer, 1, numBytes, fs);
   1.934 +    if (read < numBytes)
   1.935 +        ErrorCode = SFerror();
   1.936 +
   1.937 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
   1.938 +    if (read > 0)
   1.939 +    {
   1.940 +        // Read-in data must match our pre-loaded buffer data!
   1.941 +        UByte* pcompareBuffer = pFileTestBuffer + TestPos;
   1.942 +        for (int i=0; i< read; i++)
   1.943 +        {
   1.944 +            OVR_ASSERT(pcompareBuffer[i] == pbuffer[i]);
   1.945 +        }
   1.946 +
   1.947 +        //OVR_ASSERT(!memcmp(pFileTestBuffer + TestPos, pbuffer, read));
   1.948 +        TestPos += read;
   1.949 +        OVR_ASSERT(ftell(fs) == (int)TestPos);
   1.950 +    }
   1.951 +#endif
   1.952 +
   1.953 +    return read;
   1.954 +}
   1.955 +
   1.956 +// Seeks ahead to skip bytes
   1.957 +int     FILEFile::SkipBytes(int numBytes)
   1.958 +{
   1.959 +    SInt64 pos    = LTell();
   1.960 +    SInt64 newPos = LSeek(numBytes, Seek_Cur);
   1.961 +
   1.962 +    // Return -1 for major error
   1.963 +    if ((pos==-1) || (newPos==-1))
   1.964 +    {
   1.965 +        return -1;
   1.966 +    }
   1.967 +    //ErrorCode = ((NewPos-Pos)<numBytes) ? errno : 0;
   1.968 +
   1.969 +    return int (newPos-(int)pos);
   1.970 +}
   1.971 +
   1.972 +// Return # of bytes till EOF
   1.973 +int     FILEFile::BytesAvailable()
   1.974 +{
   1.975 +    SInt64 pos    = LTell();
   1.976 +    SInt64 endPos = LGetLength();
   1.977 +
   1.978 +    // Return -1 for major error
   1.979 +    if ((pos==-1) || (endPos==-1))
   1.980 +    {
   1.981 +        ErrorCode = SFerror();
   1.982 +        return 0;
   1.983 +    }
   1.984 +    else
   1.985 +        ErrorCode = 0;
   1.986 +
   1.987 +    return int (endPos-(int)pos);
   1.988 +}
   1.989 +
   1.990 +// Flush file contents
   1.991 +bool    FILEFile::Flush()
   1.992 +{
   1.993 +    return !fflush(fs);
   1.994 +}
   1.995 +
   1.996 +int     FILEFile::Seek(int offset, int origin)
   1.997 +{
   1.998 +    int newOrigin = 0;
   1.999 +    switch(origin)
  1.1000 +    {
  1.1001 +    case Seek_Set: newOrigin = SEEK_SET; break;
  1.1002 +    case Seek_Cur: newOrigin = SEEK_CUR; break;
  1.1003 +    case Seek_End: newOrigin = SEEK_END; break;
  1.1004 +    }
  1.1005 +
  1.1006 +    if (newOrigin == SEEK_SET && offset == Tell())
  1.1007 +        return Tell();
  1.1008 +
  1.1009 +    if (fseek (fs, offset, newOrigin))
  1.1010 +    {
  1.1011 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  1.1012 +        OVR_ASSERT(0);
  1.1013 +#endif
  1.1014 +        return -1;
  1.1015 +    }
  1.1016 +    
  1.1017 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  1.1018 +    // Track file position after seeks for read verification later.
  1.1019 +    switch(origin)
  1.1020 +    {
  1.1021 +    case Seek_Set:  TestPos = offset;       break;
  1.1022 +    case Seek_Cur:  TestPos += offset;      break;    
  1.1023 +    case Seek_End:  TestPos = FileTestLength + offset; break;
  1.1024 +    }
  1.1025 +    OVR_ASSERT((int)TestPos == Tell());
  1.1026 +#endif
  1.1027 +
  1.1028 +    return (int)Tell();
  1.1029 +}
  1.1030 +
  1.1031 +SInt64  FILEFile::LSeek(SInt64 offset, int origin)
  1.1032 +{
  1.1033 +    return Seek((int)offset,origin);
  1.1034 +}
  1.1035 +
  1.1036 +int FILEFile::CopyFromStream(File *pstream, int byteSize)
  1.1037 +{
  1.1038 +    UByte   buff[0x4000];
  1.1039 +    int     count = 0;
  1.1040 +    int     szRequest, szRead, szWritten;
  1.1041 +
  1.1042 +    while (byteSize)
  1.1043 +    {
  1.1044 +        szRequest = (byteSize > int(sizeof(buff))) ? int(sizeof(buff)) : byteSize;
  1.1045 +
  1.1046 +        szRead    = pstream->Read(buff, szRequest);
  1.1047 +        szWritten = 0;
  1.1048 +        if (szRead > 0)
  1.1049 +            szWritten = Write(buff, szRead);
  1.1050 +
  1.1051 +        count    += szWritten;
  1.1052 +        byteSize -= szWritten;
  1.1053 +        if (szWritten < szRequest)
  1.1054 +            break;
  1.1055 +    }
  1.1056 +    return count;
  1.1057 +}
  1.1058 +
  1.1059 +
  1.1060 +bool FILEFile::Close()
  1.1061 +{
  1.1062 +#ifdef OVR_FILE_VERIFY_SEEK_ERRORS
  1.1063 +    if (pFileTestBuffer)
  1.1064 +    {
  1.1065 +        OVR_FREE(pFileTestBuffer);
  1.1066 +        pFileTestBuffer = 0;
  1.1067 +        FileTestLength  = 0;
  1.1068 +    }
  1.1069 +#endif
  1.1070 +
  1.1071 +    bool closeRet = !fclose(fs);
  1.1072 +
  1.1073 +    if (!closeRet)
  1.1074 +    {
  1.1075 +        ErrorCode = SFerror();
  1.1076 +        return 0;
  1.1077 +    }
  1.1078 +    else
  1.1079 +    {
  1.1080 +        Opened    = 0;
  1.1081 +        fs        = 0;
  1.1082 +        ErrorCode = 0;
  1.1083 +    }
  1.1084 +
  1.1085 +    // Handle safe truncate
  1.1086 +    /*
  1.1087 +    if ((OpenFlags & OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  1.1088 +    {
  1.1089 +        // Delete original file (if it existed)
  1.1090 +        DWORD oldAttributes = FileUtilWin32::GetFileAttributes(FileName);
  1.1091 +        if (oldAttributes!=0xFFFFFFFF)
  1.1092 +            if (!FileUtilWin32::DeleteFile(FileName))
  1.1093 +            {
  1.1094 +                // Try to remove the readonly attribute
  1.1095 +                FileUtilWin32::SetFileAttributes(FileName, oldAttributes & (~FILE_ATTRIBUTE_READONLY) );
  1.1096 +                // And delete the file again
  1.1097 +                if (!FileUtilWin32::DeleteFile(FileName))
  1.1098 +                    return 0;
  1.1099 +            }
  1.1100 +
  1.1101 +        // Rename temp file to real filename
  1.1102 +        if (!FileUtilWin32::MoveFile(TempName, FileName))
  1.1103 +        {
  1.1104 +            //ErrorCode = errno;
  1.1105 +            return 0;
  1.1106 +        }
  1.1107 +    }
  1.1108 +    */
  1.1109 +    return 1;
  1.1110 +}
  1.1111 +
  1.1112 +/*
  1.1113 +bool    FILEFile::CloseCancel()
  1.1114 +{
  1.1115 +    bool closeRet = (bool)::CloseHandle(fd);
  1.1116 +
  1.1117 +    if (!closeRet)
  1.1118 +    {
  1.1119 +        //ErrorCode = errno;
  1.1120 +        return 0;
  1.1121 +    }
  1.1122 +    else
  1.1123 +    {
  1.1124 +        Opened    = 0;
  1.1125 +        fd        = INVALID_HANDLE_VALUE;
  1.1126 +        ErrorCode = 0;
  1.1127 +    }
  1.1128 +
  1.1129 +    // Handle safe truncate (delete tmp file, leave original unchanged)
  1.1130 +    if ((OpenFlags&OVR_FO_SAFETRUNC) == OVR_FO_SAFETRUNC)
  1.1131 +        if (!FileUtilWin32::DeleteFile(TempName))
  1.1132 +        {
  1.1133 +            //ErrorCode = errno;
  1.1134 +            return 0;
  1.1135 +        }
  1.1136 +    return 1;
  1.1137 +}
  1.1138 +*/
  1.1139 +
  1.1140 +File *FileFILEOpen(const String& path, int flags, int mode)
  1.1141 +{
  1.1142 +    return new FILEFile(path, flags, mode);
  1.1143 +}
  1.1144 +
  1.1145 +// Helper function: obtain file information time.
  1.1146 +bool    SysFile::GetFileStat(FileStat* pfileStat, const String& path)
  1.1147 +{
  1.1148 +#if defined(OVR_OS_WIN32)
  1.1149 +    // 64-bit implementation on Windows.
  1.1150 +    struct __stat64 fileStat;
  1.1151 +    // Stat returns 0 for success.
  1.1152 +    wchar_t *pwpath = (wchar_t*)OVR_ALLOC((UTF8Util::GetLength(path.ToCStr())+1)*sizeof(wchar_t));
  1.1153 +    UTF8Util::DecodeString(pwpath, path.ToCStr());
  1.1154 +
  1.1155 +    int ret = _wstat64(pwpath, &fileStat);
  1.1156 +    OVR_FREE(pwpath);
  1.1157 +    if (ret) return false;
  1.1158 +#else
  1.1159 +    struct stat fileStat;
  1.1160 +    // Stat returns 0 for success.
  1.1161 +    if (stat(path, &fileStat) != 0)
  1.1162 +        return false;
  1.1163 +#endif
  1.1164 +    pfileStat->AccessTime = fileStat.st_atime;
  1.1165 +    pfileStat->ModifyTime = fileStat.st_mtime;
  1.1166 +    pfileStat->FileSize   = fileStat.st_size;
  1.1167 +    return true;
  1.1168 +}
  1.1169 +
  1.1170 +} // Scaleform