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