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