oculus1

view libovr/Src/Kernel/OVR_File.h @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
parents e2f9e4603129
children
line source
1 /************************************************************************************
3 PublicHeader: Kernel
4 Filename : OVR_File.h
5 Content : Header for all internal file management - functions and structures
6 to be inherited by OS specific subclasses.
7 Created : September 19, 2012
8 Notes :
10 Notes : errno may not be preserved across use of BaseFile member functions
11 : Directories cannot be deleted while files opened from them are in use
12 (For the GetFullName function)
14 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
16 Use of this software is subject to the terms of the Oculus license
17 agreement provided at the time of installation or download, or which
18 otherwise accompanies this software in either electronic or hard copy form.
20 ************************************************************************************/
22 #ifndef OVR_File_h
23 #define OVR_File_h
25 #include "OVR_RefCount.h"
26 #include "OVR_Std.h"
27 #include "OVR_Alg.h"
29 #include <stdio.h>
30 #include "OVR_String.h"
32 namespace OVR {
34 // ***** Declared classes
35 class FileConstants;
36 class File;
37 class DelegatedFile;
38 class BufferedFile;
41 // ***** Flags for File & Directory accesses
43 class FileConstants
44 {
45 public:
47 // *** File open flags
48 enum OpenFlags
49 {
50 Open_Read = 1,
51 Open_Write = 2,
52 Open_ReadWrite = 3,
54 // Opens file and truncates it to zero length
55 // - file must have write permission
56 // - when used with Create, it opens an existing
57 // file and empties it or creates a new file
58 Open_Truncate = 4,
60 // Creates and opens new file
61 // - does not erase contents if file already
62 // exists unless combined with Truncate
63 Open_Create = 8,
65 // Returns an error value if the file already exists
66 Open_CreateOnly = 24,
68 // Open file with buffering
69 Open_Buffered = 32
70 };
72 // *** File Mode flags
73 enum Modes
74 {
75 Mode_Read = 0444,
76 Mode_Write = 0222,
77 Mode_Execute = 0111,
79 Mode_ReadWrite = 0666
80 };
82 // *** Seek operations
83 enum SeekOps
84 {
85 Seek_Set = 0,
86 Seek_Cur = 1,
87 Seek_End = 2
88 };
90 // *** Errors
91 enum Errors
92 {
93 Error_FileNotFound = 0x1001,
94 Error_Access = 0x1002,
95 Error_IOError = 0x1003,
96 Error_DiskFull = 0x1004
97 };
98 };
101 //-----------------------------------------------------------------------------------
102 // ***** File Class
104 // The pure virtual base random-access file
105 // This is a base class to all files
107 class File : public RefCountBase<File>, public FileConstants
108 {
109 public:
110 File() { }
111 // ** Location Information
113 // Returns a file name path relative to the 'reference' directory
114 // This is often a path that was used to create a file
115 // (this is not a global path, global path can be obtained with help of directory)
116 virtual const char* GetFilePath() = 0;
119 // ** File Information
121 // Return 1 if file's usable (open)
122 virtual bool IsValid() = 0;
123 // Return 1 if file's writable, otherwise 0
124 virtual bool IsWritable() = 0;
126 // Return position
127 virtual int Tell() = 0;
128 virtual SInt64 LTell() = 0;
130 // File size
131 virtual int GetLength() = 0;
132 virtual SInt64 LGetLength() = 0;
134 // Returns file stats
135 // 0 for failure
136 //virtual bool Stat(FileStats *pfs) = 0;
138 // Return errno-based error code
139 // Useful if any other function failed
140 virtual int GetErrorCode() = 0;
143 // ** Stream implementation & I/O
145 // Blocking write, will write in the given number of bytes to the stream
146 // Returns : -1 for error
147 // Otherwise number of bytes read
148 virtual int Write(const UByte *pbufer, int numBytes) = 0;
149 // Blocking read, will read in the given number of bytes or less from the stream
150 // Returns : -1 for error
151 // Otherwise number of bytes read,
152 // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed
153 virtual int Read(UByte *pbufer, int numBytes) = 0;
155 // Skips (ignores) a given # of bytes
156 // Same return values as Read
157 virtual int SkipBytes(int numBytes) = 0;
159 // Returns the number of bytes available to read from a stream without blocking
160 // For a file, this should generally be number of bytes to the end
161 virtual int BytesAvailable() = 0;
163 // Causes any implementation's buffered data to be delivered to destination
164 // Return 0 for error
165 virtual bool Flush() = 0;
168 // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking
169 inline bool IsEOF() { return !BytesAvailable(); }
172 // Seeking
173 // Returns new position, -1 for error
174 virtual int Seek(int offset, int origin=Seek_Set) = 0;
175 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) = 0;
176 // Seek simplification
177 int SeekToBegin() {return Seek(0); }
178 int SeekToEnd() {return Seek(0,Seek_End); }
179 int Skip(int numBytes) {return Seek(numBytes,Seek_Cur); }
182 // Appends other file data from a stream
183 // Return -1 for error, else # of bytes written
184 virtual int CopyFromStream(File *pstream, int byteSize) = 0;
186 // Closes the file
187 // After close, file cannot be accessed
188 virtual bool Close() = 0;
191 // ***** Inlines for convenient primitive type serialization
193 // Read/Write helpers
194 private:
195 UInt64 PRead64() { UInt64 v = 0; Read((UByte*)&v, 8); return v; }
196 UInt32 PRead32() { UInt32 v = 0; Read((UByte*)&v, 4); return v; }
197 UInt16 PRead16() { UInt16 v = 0; Read((UByte*)&v, 2); return v; }
198 UByte PRead8() { UByte v = 0; Read((UByte*)&v, 1); return v; }
199 void PWrite64(UInt64 v) { Write((UByte*)&v, 8); }
200 void PWrite32(UInt32 v) { Write((UByte*)&v, 4); }
201 void PWrite16(UInt16 v) { Write((UByte*)&v, 2); }
202 void PWrite8(UByte v) { Write((UByte*)&v, 1); }
204 public:
206 // Writing primitive types - Little Endian
207 inline void WriteUByte(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); }
208 inline void WriteSByte(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); }
209 inline void WriteUInt8(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); }
210 inline void WriteSInt8(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToLE(v)); }
211 inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); }
212 inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); }
213 inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); }
214 inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); }
215 inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); }
216 inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); }
217 inline void WriteFloat(float v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 4); }
218 inline void WriteDouble(double v) { v = Alg::ByteUtil::SystemToLE(v); Write((UByte*)&v, 8); }
219 // Writing primitive types - Big Endian
220 inline void WriteUByteBE(UByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); }
221 inline void WriteSByteBE(SByte v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); }
222 inline void WriteUInt8BE(UInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); }
223 inline void WriteSInt8BE(SInt16 v) { PWrite8((UByte)Alg::ByteUtil::SystemToBE(v)); }
224 inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); }
225 inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); }
226 inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); }
227 inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); }
228 inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); }
229 inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); }
230 inline void WriteFloatBE(float v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 4); }
231 inline void WriteDoubleBE(double v) { v = Alg::ByteUtil::SystemToBE(v); Write((UByte*)&v, 8); }
233 // Reading primitive types - Little Endian
234 inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); }
235 inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); }
236 inline UByte ReadUInt8() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); }
237 inline SByte ReadSInt8() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); }
238 inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); }
239 inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); }
240 inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); }
241 inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); }
242 inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); }
243 inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); }
244 inline float ReadFloat() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::LEToSystem(v); }
245 inline double ReadDouble() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::LEToSystem(v); }
246 // Reading primitive types - Big Endian
247 inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); }
248 inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); }
249 inline UByte ReadUInt8BE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); }
250 inline SByte ReadSInt8BE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); }
251 inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); }
252 inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); }
253 inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); }
254 inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); }
255 inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); }
256 inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); }
257 inline float ReadFloatBE() { float v = 0.0f; Read((UByte*)&v, 4); return Alg::ByteUtil::BEToSystem(v); }
258 inline double ReadDoubleBE() { double v = 0.0; Read((UByte*)&v, 8); return Alg::ByteUtil::BEToSystem(v); }
259 };
262 // *** Delegated File
264 class DelegatedFile : public File
265 {
266 protected:
267 // Delegating file pointer
268 Ptr<File> pFile;
270 // Hidden default constructor
271 DelegatedFile() : pFile(0) { }
272 DelegatedFile(const DelegatedFile &source) : File() { OVR_UNUSED(source); }
273 public:
274 // Constructors
275 DelegatedFile(File *pfile) : pFile(pfile) { }
277 // ** Location Information
278 virtual const char* GetFilePath() { return pFile->GetFilePath(); }
280 // ** File Information
281 virtual bool IsValid() { return pFile && pFile->IsValid(); }
282 virtual bool IsWritable() { return pFile->IsWritable(); }
283 // virtual bool IsRecoverable() { return pFile->IsRecoverable(); }
285 virtual int Tell() { return pFile->Tell(); }
286 virtual SInt64 LTell() { return pFile->LTell(); }
288 virtual int GetLength() { return pFile->GetLength(); }
289 virtual SInt64 LGetLength() { return pFile->LGetLength(); }
291 //virtual bool Stat(FileStats *pfs) { return pFile->Stat(pfs); }
293 virtual int GetErrorCode() { return pFile->GetErrorCode(); }
295 // ** Stream implementation & I/O
296 virtual int Write(const UByte *pbuffer, int numBytes) { return pFile->Write(pbuffer,numBytes); }
297 virtual int Read(UByte *pbuffer, int numBytes) { return pFile->Read(pbuffer,numBytes); }
299 virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); }
301 virtual int BytesAvailable() { return pFile->BytesAvailable(); }
303 virtual bool Flush() { return pFile->Flush(); }
305 // Seeking
306 virtual int Seek(int offset, int origin=Seek_Set) { return pFile->Seek(offset,origin); }
307 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set) { return pFile->LSeek(offset,origin); }
309 virtual int CopyFromStream(File *pstream, int byteSize) { return pFile->CopyFromStream(pstream,byteSize); }
311 // Closing the file
312 virtual bool Close() { return pFile->Close(); }
313 };
316 //-----------------------------------------------------------------------------------
317 // ***** Buffered File
319 // This file class adds buffering to an existing file
320 // Buffered file never fails by itself; if there's not
321 // enough memory for buffer, no buffer's used
323 class BufferedFile : public DelegatedFile
324 {
325 protected:
326 enum BufferModeType
327 {
328 NoBuffer,
329 ReadBuffer,
330 WriteBuffer
331 };
333 // Buffer & the mode it's in
334 UByte* pBuffer;
335 BufferModeType BufferMode;
336 // Position in buffer
337 unsigned Pos;
338 // Data in buffer if reading
339 unsigned DataSize;
340 // Underlying file position
341 UInt64 FilePos;
343 // Initializes buffering to a certain mode
344 bool SetBufferMode(BufferModeType mode);
345 // Flushes buffer
346 // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position
347 void FlushBuffer();
348 // Loads data into ReadBuffer
349 // WARNING: Right now LoadBuffer() assumes the buffer's empty
350 void LoadBuffer();
352 // Hidden constructor
353 BufferedFile();
354 inline BufferedFile(const BufferedFile &source) : DelegatedFile() { OVR_UNUSED(source); }
355 public:
357 // Constructor
358 // - takes another file as source
359 BufferedFile(File *pfile);
360 ~BufferedFile();
363 // ** Overridden functions
365 // We override all the functions that can possibly
366 // require buffer mode switch, flush, or extra calculations
367 virtual int Tell();
368 virtual SInt64 LTell();
370 virtual int GetLength();
371 virtual SInt64 LGetLength();
373 // virtual bool Stat(GFileStats *pfs);
375 virtual int Write(const UByte *pbufer, int numBytes);
376 virtual int Read(UByte *pbufer, int numBytes);
378 virtual int SkipBytes(int numBytes);
380 virtual int BytesAvailable();
382 virtual bool Flush();
384 virtual int Seek(int offset, int origin=Seek_Set);
385 virtual SInt64 LSeek(SInt64 offset, int origin=Seek_Set);
387 virtual int CopyFromStream(File *pstream, int byteSize);
389 virtual bool Close();
390 };
393 //-----------------------------------------------------------------------------------
394 // ***** Memory File
396 class MemoryFile : public File
397 {
398 public:
400 const char* GetFilePath() { return FilePath.ToCStr(); }
402 bool IsValid() { return Valid; }
403 bool IsWritable() { return false; }
405 bool Flush() { return true; }
406 int GetErrorCode() { return 0; }
408 int Tell() { return FileIndex; }
409 SInt64 LTell() { return (SInt64) FileIndex; }
411 int GetLength() { return FileSize; }
412 SInt64 LGetLength() { return (SInt64) FileSize; }
414 bool Close()
415 {
416 Valid = false;
417 return false;
418 }
420 int CopyFromStream(File *pstream, int byteSize)
421 { OVR_UNUSED2(pstream, byteSize);
422 return 0;
423 }
425 int Write(const UByte *pbuffer, int numBytes)
426 { OVR_UNUSED2(pbuffer, numBytes);
427 return 0;
428 }
430 int Read(UByte *pbufer, int numBytes)
431 {
432 if (FileIndex + numBytes > FileSize)
433 {
434 numBytes = FileSize - FileIndex;
435 }
437 if (numBytes > 0)
438 {
439 ::memcpy (pbufer, &FileData [FileIndex], numBytes);
441 FileIndex += numBytes;
442 }
444 return numBytes;
445 }
447 int SkipBytes(int numBytes)
448 {
449 if (FileIndex + numBytes > FileSize)
450 {
451 numBytes = FileSize - FileIndex;
452 }
454 FileIndex += numBytes;
456 return numBytes;
457 }
459 int BytesAvailable()
460 {
461 return (FileSize - FileIndex);
462 }
464 int Seek(int offset, int origin = Seek_Set)
465 {
466 switch (origin)
467 {
468 case Seek_Set : FileIndex = offset; break;
469 case Seek_Cur : FileIndex += offset; break;
470 case Seek_End : FileIndex = FileSize - offset; break;
471 }
473 return FileIndex;
474 }
476 SInt64 LSeek(SInt64 offset, int origin = Seek_Set)
477 {
478 return (SInt64) Seek((int) offset, origin);
479 }
481 public:
483 MemoryFile (const String& fileName, const UByte *pBuffer, int buffSize)
484 : FilePath(fileName)
485 {
486 FileData = pBuffer;
487 FileSize = buffSize;
488 FileIndex = 0;
489 Valid = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false;
490 }
492 // pfileName should be encoded as UTF-8 to support international file names.
493 MemoryFile (const char* pfileName, const UByte *pBuffer, int buffSize)
494 : FilePath(pfileName)
495 {
496 FileData = pBuffer;
497 FileSize = buffSize;
498 FileIndex = 0;
499 Valid = (pfileName && pBuffer && buffSize > 0) ? true : false;
500 }
501 private:
503 String FilePath;
504 const UByte *FileData;
505 int FileSize;
506 int FileIndex;
507 bool Valid;
508 };
511 // ***** Global path helpers
513 // Find trailing short filename in a path.
514 const char* OVR_CDECL GetShortFilename(const char* purl);
516 } // OVR
518 #endif