nuclear@3: /************************************************************************************ nuclear@3: nuclear@3: PublicHeader: Kernel nuclear@3: Filename : OVR_File.h nuclear@3: Content : Header for all internal file management - functions and structures nuclear@3: to be inherited by OS specific subclasses. nuclear@3: Created : September 19, 2012 nuclear@3: Notes : nuclear@3: nuclear@3: Notes : errno may not be preserved across use of BaseFile member functions nuclear@3: : Directories cannot be deleted while files opened from them are in use nuclear@3: (For the GetFullName function) nuclear@3: nuclear@3: Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved. nuclear@3: nuclear@3: Use of this software is subject to the terms of the Oculus license nuclear@3: agreement provided at the time of installation or download, or which nuclear@3: otherwise accompanies this software in either electronic or hard copy form. nuclear@3: nuclear@3: ************************************************************************************/ nuclear@3: nuclear@3: #ifndef OVR_File_h nuclear@3: #define OVR_File_h nuclear@3: nuclear@3: #include "OVR_RefCount.h" nuclear@3: #include "OVR_Std.h" nuclear@3: #include "OVR_Alg.h" nuclear@3: nuclear@3: #include nuclear@3: #include "OVR_String.h" nuclear@3: nuclear@3: namespace OVR { nuclear@3: nuclear@3: // ***** Declared classes nuclear@3: class FileConstants; nuclear@3: class File; nuclear@3: class DelegatedFile; nuclear@3: class BufferedFile; nuclear@3: nuclear@3: nuclear@3: // ***** Flags for File & Directory accesses nuclear@3: nuclear@3: class FileConstants nuclear@3: { nuclear@3: public: nuclear@3: nuclear@3: // *** File open flags nuclear@3: enum OpenFlags nuclear@3: { nuclear@3: Open_Read = 1, nuclear@3: Open_Write = 2, nuclear@3: Open_ReadWrite = 3, nuclear@3: nuclear@3: // Opens file and truncates it to zero length nuclear@3: // - file must have write permission nuclear@3: // - when used with Create, it opens an existing nuclear@3: // file and empties it or creates a new file nuclear@3: Open_Truncate = 4, nuclear@3: nuclear@3: // Creates and opens new file nuclear@3: // - does not erase contents if file already nuclear@3: // exists unless combined with Truncate nuclear@3: Open_Create = 8, nuclear@3: nuclear@3: // Returns an error value if the file already exists nuclear@3: Open_CreateOnly = 24, nuclear@3: nuclear@3: // Open file with buffering nuclear@3: Open_Buffered = 32 nuclear@3: }; nuclear@3: nuclear@3: // *** File Mode flags nuclear@3: enum Modes nuclear@3: { nuclear@3: Mode_Read = 0444, nuclear@3: Mode_Write = 0222, nuclear@3: Mode_Execute = 0111, nuclear@3: nuclear@3: Mode_ReadWrite = 0666 nuclear@3: }; nuclear@3: nuclear@3: // *** Seek operations nuclear@3: enum SeekOps nuclear@3: { nuclear@3: Seek_Set = 0, nuclear@3: Seek_Cur = 1, nuclear@3: Seek_End = 2 nuclear@3: }; nuclear@3: nuclear@3: // *** Errors nuclear@3: enum Errors nuclear@3: { nuclear@3: Error_FileNotFound = 0x1001, nuclear@3: Error_Access = 0x1002, nuclear@3: Error_IOError = 0x1003, nuclear@3: Error_DiskFull = 0x1004 nuclear@3: }; nuclear@3: }; nuclear@3: nuclear@3: nuclear@3: //----------------------------------------------------------------------------------- nuclear@3: // ***** File Class nuclear@3: nuclear@3: // The pure virtual base random-access file nuclear@3: // This is a base class to all files nuclear@3: nuclear@3: class File : public RefCountBase, public FileConstants nuclear@3: { nuclear@3: public: nuclear@3: File() { } nuclear@3: // ** Location Information nuclear@3: nuclear@3: // Returns a file name path relative to the 'reference' directory nuclear@3: // This is often a path that was used to create a file nuclear@3: // (this is not a global path, global path can be obtained with help of directory) nuclear@3: virtual const char* GetFilePath() = 0; nuclear@3: nuclear@3: nuclear@3: // ** File Information nuclear@3: nuclear@3: // Return 1 if file's usable (open) nuclear@3: virtual bool IsValid() = 0; nuclear@3: // Return 1 if file's writable, otherwise 0 nuclear@3: virtual bool IsWritable() = 0; nuclear@3: nuclear@3: // Return position nuclear@3: virtual int Tell() = 0; nuclear@3: virtual SInt64 LTell() = 0; nuclear@3: nuclear@3: // File size nuclear@3: virtual int GetLength() = 0; nuclear@3: virtual SInt64 LGetLength() = 0; nuclear@3: nuclear@3: // Returns file stats nuclear@3: // 0 for failure nuclear@3: //virtual bool Stat(FileStats *pfs) = 0; nuclear@3: nuclear@3: // Return errno-based error code nuclear@3: // Useful if any other function failed nuclear@3: virtual int GetErrorCode() = 0; nuclear@3: nuclear@3: nuclear@3: // ** Stream implementation & I/O nuclear@3: nuclear@3: // Blocking write, will write in the given number of bytes to the stream nuclear@3: // Returns : -1 for error nuclear@3: // Otherwise number of bytes read nuclear@3: virtual int Write(const UByte *pbufer, int numBytes) = 0; nuclear@3: // Blocking read, will read in the given number of bytes or less from the stream nuclear@3: // Returns : -1 for error nuclear@3: // Otherwise number of bytes read, nuclear@3: // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed nuclear@3: virtual int Read(UByte *pbufer, int numBytes) = 0; nuclear@3: nuclear@3: // Skips (ignores) a given # of bytes nuclear@3: // Same return values as Read nuclear@3: virtual int SkipBytes(int numBytes) = 0; nuclear@3: nuclear@3: // Returns the number of bytes available to read from a stream without blocking nuclear@3: // For a file, this should generally be number of bytes to the end nuclear@3: virtual int BytesAvailable() = 0; nuclear@3: nuclear@3: // Causes any implementation's buffered data to be delivered to destination nuclear@3: // Return 0 for error nuclear@3: virtual bool Flush() = 0; nuclear@3: nuclear@3: nuclear@3: // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking nuclear@3: inline bool IsEOF() { return !BytesAvailable(); } nuclear@3: nuclear@3: nuclear@3: // Seeking nuclear@3: // Returns new position, -1 for error nuclear@3: virtual int Seek(int offset, int origin=Seek_Set) = 0; nuclear@3: virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0; nuclear@3: // Seek simplification nuclear@3: int SeekToBegin() {return Seek(0); } nuclear@3: int SeekToEnd() {return Seek(0,Seek_End); } nuclear@3: int Skip(int numBytes) {return Seek(numBytes,Seek_Cur); } nuclear@3: nuclear@3: nuclear@3: // Appends other file data from a stream nuclear@3: // Return -1 for error, else # of bytes written nuclear@3: virtual int CopyFromStream(File *pstream, int byteSize) = 0; nuclear@3: nuclear@3: // Closes the file nuclear@3: // After close, file cannot be accessed nuclear@3: virtual bool Close() = 0; nuclear@3: nuclear@3: nuclear@3: // ***** Inlines for convenient primitive type serialization nuclear@3: nuclear@3: // Read/Write helpers nuclear@3: private: nuclear@3: UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; } nuclear@3: UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; } nuclear@3: UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; } nuclear@3: UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; } nuclear@3: void PWrite64(UInt64 v) { Write((UByte*)&v, 8); } nuclear@3: void PWrite32(UInt32 v) { Write((UByte*)&v, 4); } nuclear@3: void PWrite16(UInt16 v) { Write((UByte*)&v, 2); } nuclear@3: void PWrite8(UByte v) { Write((UByte*)&v, 1); } nuclear@3: nuclear@3: public: nuclear@3: nuclear@3: // Writing primitive types - Little Endian nuclear@3: inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); } nuclear@3: inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); } nuclear@3: inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); } nuclear@3: // Writing primitive types - Big Endian nuclear@3: inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); } nuclear@3: inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); } nuclear@3: inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); } nuclear@3: nuclear@3: // Reading primitive types - Little Endian nuclear@3: inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } nuclear@3: inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } nuclear@3: inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); } nuclear@3: inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); } nuclear@3: inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); } nuclear@3: inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); } nuclear@3: inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); } nuclear@3: inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); } nuclear@3: inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); } nuclear@3: inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); } nuclear@3: inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); } nuclear@3: inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); } nuclear@3: // Reading primitive types - Big Endian nuclear@3: inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } nuclear@3: inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } nuclear@3: inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); } nuclear@3: inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); } nuclear@3: inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); } nuclear@3: inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); } nuclear@3: inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); } nuclear@3: inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); } nuclear@3: inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); } nuclear@3: inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); } nuclear@3: inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); } nuclear@3: inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); } nuclear@3: }; nuclear@3: nuclear@3: nuclear@3: // *** Delegated File nuclear@3: nuclear@3: class DelegatedFile : public File nuclear@3: { nuclear@3: protected: nuclear@3: // Delegating file pointer nuclear@3: Ptr pFile; nuclear@3: nuclear@3: // Hidden default constructor nuclear@3: DelegatedFile() : pFile(0) { } nuclear@3: DelegatedFile(const DelegatedFile &source) : File() { OVR_UNUSED(source); } nuclear@3: public: nuclear@3: // Constructors nuclear@3: DelegatedFile(File *pfile) : pFile(pfile) { } nuclear@3: nuclear@3: // ** Location Information nuclear@3: virtual const char* GetFilePath() { return pFile->GetFilePath(); } nuclear@3: nuclear@3: // ** File Information nuclear@3: virtual bool IsValid() { return pFile && pFile->IsValid(); } nuclear@3: virtual bool IsWritable() { return pFile->IsWritable(); } nuclear@3: // virtual bool IsRecoverable() { return pFile->IsRecoverable(); } nuclear@3: nuclear@3: virtual int Tell() { return pFile->Tell(); } nuclear@3: virtual SInt64 LTell() { return pFile->LTell(); } nuclear@3: nuclear@3: virtual int GetLength() { return pFile->GetLength(); } nuclear@3: virtual SInt64 LGetLength() { return pFile->LGetLength(); } nuclear@3: nuclear@3: //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); } nuclear@3: nuclear@3: virtual int GetErrorCode() { return pFile->GetErrorCode(); } nuclear@3: nuclear@3: // ** Stream implementation & I/O nuclear@3: virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); } nuclear@3: virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); } nuclear@3: nuclear@3: virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); } nuclear@3: nuclear@3: virtual int BytesAvailable() { return pFile->BytesAvailable(); } nuclear@3: nuclear@3: virtual bool Flush() { return pFile->Flush(); } nuclear@3: nuclear@3: // Seeking nuclear@3: virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); } nuclear@3: virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); } nuclear@3: nuclear@3: virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); } nuclear@3: nuclear@3: // Closing the file nuclear@3: virtual bool Close() { return pFile->Close(); } nuclear@3: }; nuclear@3: nuclear@3: nuclear@3: //----------------------------------------------------------------------------------- nuclear@3: // ***** Buffered File nuclear@3: nuclear@3: // This file class adds buffering to an existing file nuclear@3: // Buffered file never fails by itself; if there's not nuclear@3: // enough memory for buffer, no buffer's used nuclear@3: nuclear@3: class BufferedFile : public DelegatedFile nuclear@3: { nuclear@3: protected: nuclear@3: enum BufferModeType nuclear@3: { nuclear@3: NoBuffer, nuclear@3: ReadBuffer, nuclear@3: WriteBuffer nuclear@3: }; nuclear@3: nuclear@3: // Buffer & the mode it's in nuclear@3: UByte* pBuffer; nuclear@3: BufferModeType BufferMode; nuclear@3: // Position in buffer nuclear@3: unsigned Pos; nuclear@3: // Data in buffer if reading nuclear@3: unsigned DataSize; nuclear@3: // Underlying file position nuclear@3: UInt64 FilePos; nuclear@3: nuclear@3: // Initializes buffering to a certain mode nuclear@3: bool SetBufferMode(BufferModeType mode); nuclear@3: // Flushes buffer nuclear@3: // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position nuclear@3: void FlushBuffer(); nuclear@3: // Loads data into ReadBuffer nuclear@3: // WARNING: Right now LoadBuffer() assumes the buffer's empty nuclear@3: void LoadBuffer(); nuclear@3: nuclear@3: // Hidden constructor nuclear@3: BufferedFile(); nuclear@3: inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); } nuclear@3: public: nuclear@3: nuclear@3: // Constructor nuclear@3: // - takes another file as source nuclear@3: BufferedFile(File *pfile); nuclear@3: ~BufferedFile(); nuclear@3: nuclear@3: nuclear@3: // ** Overridden functions nuclear@3: nuclear@3: // We override all the functions that can possibly nuclear@3: // require buffer mode switch, flush, or extra calculations nuclear@3: virtual int Tell(); nuclear@3: virtual SInt64 LTell(); nuclear@3: nuclear@3: virtual int GetLength(); nuclear@3: virtual SInt64 LGetLength(); nuclear@3: nuclear@3: // virtual bool Stat(GFileStats *pfs); nuclear@3: nuclear@3: virtual int Write(const UByte *pbufer, int numBytes); nuclear@3: virtual int Read(UByte *pbufer, int numBytes); nuclear@3: nuclear@3: virtual int SkipBytes(int numBytes); nuclear@3: nuclear@3: virtual int BytesAvailable(); nuclear@3: nuclear@3: virtual bool Flush(); nuclear@3: nuclear@3: virtual int Seek(int offset, int origin=Seek_Set); nuclear@3: virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set); nuclear@3: nuclear@3: virtual int CopyFromStream(File *pstream, int byteSize); nuclear@3: nuclear@3: virtual bool Close(); nuclear@3: }; nuclear@3: nuclear@3: nuclear@3: //----------------------------------------------------------------------------------- nuclear@3: // ***** Memory File nuclear@3: nuclear@3: class MemoryFile : public File nuclear@3: { nuclear@3: public: nuclear@3: nuclear@3: const char* GetFilePath() { return FilePath.ToCStr(); } nuclear@3: nuclear@3: bool IsValid() { return Valid; } nuclear@3: bool IsWritable() { return false; } nuclear@3: nuclear@3: bool Flush() { return true; } nuclear@3: int GetErrorCode() { return 0; } nuclear@3: nuclear@3: int Tell() { return FileIndex; } nuclear@3: SInt64 LTell() { return (SInt64) FileIndex; } nuclear@3: nuclear@3: int GetLength() { return FileSize; } nuclear@3: SInt64 LGetLength() { return (SInt64) FileSize; } nuclear@3: nuclear@3: bool Close() nuclear@3: { nuclear@3: Valid = false; nuclear@3: return false; nuclear@3: } nuclear@3: nuclear@3: int CopyFromStream(File *pstream, int byteSize) nuclear@3: { OVR_UNUSED2(pstream, byteSize); nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: int Write(const UByte *pbuffer, int numBytes) nuclear@3: { OVR_UNUSED2(pbuffer, numBytes); nuclear@3: return 0; nuclear@3: } nuclear@3: nuclear@3: int Read(UByte *pbufer, int numBytes) nuclear@3: { nuclear@3: if (FileIndex + numBytes > FileSize) nuclear@3: { nuclear@3: numBytes = FileSize - FileIndex; nuclear@3: } nuclear@3: nuclear@3: if (numBytes > 0) nuclear@3: { nuclear@3: ::memcpy (pbufer, &FileData [FileIndex], numBytes); nuclear@3: nuclear@3: FileIndex += numBytes; nuclear@3: } nuclear@3: nuclear@3: return numBytes; nuclear@3: } nuclear@3: nuclear@3: int SkipBytes(int numBytes) nuclear@3: { nuclear@3: if (FileIndex + numBytes > FileSize) nuclear@3: { nuclear@3: numBytes = FileSize - FileIndex; nuclear@3: } nuclear@3: nuclear@3: FileIndex += numBytes; nuclear@3: nuclear@3: return numBytes; nuclear@3: } nuclear@3: nuclear@3: int BytesAvailable() nuclear@3: { nuclear@3: return (FileSize - FileIndex); nuclear@3: } nuclear@3: nuclear@3: int Seek(int offset, int origin = Seek_Set) nuclear@3: { nuclear@3: switch (origin) nuclear@3: { nuclear@3: case Seek_Set : FileIndex = offset; break; nuclear@3: case Seek_Cur : FileIndex += offset; break; nuclear@3: case Seek_End : FileIndex = FileSize - offset; break; nuclear@3: } nuclear@3: nuclear@3: return FileIndex; nuclear@3: } nuclear@3: nuclear@3: SInt64 LSeek(SInt64 offset, int origin = Seek_Set) nuclear@3: { nuclear@3: return (SInt64) Seek((int) offset, origin); nuclear@3: } nuclear@3: nuclear@3: public: nuclear@3: nuclear@3: MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize) nuclear@3: : FilePath(fileName) nuclear@3: { nuclear@3: FileData = pBuffer; nuclear@3: FileSize = buffSize; nuclear@3: FileIndex = 0; nuclear@3: Valid = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false; nuclear@3: } nuclear@3: nuclear@3: // pfileName should be encoded as UTF-8 to support international file names. nuclear@3: MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize) nuclear@3: : FilePath(pfileName) nuclear@3: { nuclear@3: FileData = pBuffer; nuclear@3: FileSize = buffSize; nuclear@3: FileIndex = 0; nuclear@3: Valid = (pfileName && pBuffer && buffSize > 0) ? true : false; nuclear@3: } nuclear@3: private: nuclear@3: nuclear@3: String FilePath; nuclear@3: const UByte *FileData; nuclear@3: int FileSize; nuclear@3: int FileIndex; nuclear@3: bool Valid; nuclear@3: }; nuclear@3: nuclear@3: nuclear@3: // ***** Global path helpers nuclear@3: nuclear@3: // Find trailing short filename in a path. nuclear@3: const char* OVR_CDECL GetShortFilename(const char* purl); nuclear@3: nuclear@3: } // OVR nuclear@3: nuclear@3: #endif