gwnavruntime/kernel/SF_File.h Source File

SF_File.h
Go to the documentation of this file.
1 /*
2  * Copyright 2016 Autodesk, Inc. All rights reserved.
3  * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4  * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5  */
6 
7 #pragma once
8 
13 #include <stdio.h>
14 
15 namespace Kaim
16 {
17 
18 // ***** Declared classes
19 class FileConstants;
20 class File;
21 class DelegatedFile;
22 class BufferedFile;
23 
24 // ***** Flags for File & Directory accesses
25 
26 class FileConstants
27 {
28 public:
29  // *** File open flags
30  enum OpenFlags
31  {
32  Open_Read = 1,
33  Open_Write = 2,
34  Open_ReadWrite = 3,
35 
36  // Opens file and truncates it to zero length
37  // - file must have write permission
38  // - when used with Create, it opens an existing
39  // file and empties it or creates a new file
40  Open_Truncate = 4,
41 
42  // Creates and opens new file
43  // - does not erase contents if file already
44  // exists unless combined with Truncate
45  Open_Create = 8,
46 
47  // Returns an error value if the file already exists
48  Open_CreateOnly = 24,
49 
50  // Open file with buffering
51  Open_Buffered = 32
52  };
53 
54  // *** File Mode flags
55  enum Modes
56  {
57  Mode_Read = 0444,
58  Mode_Write = 0222,
59  Mode_Execute = 0111,
60 
61  Mode_ReadWrite = 0666
62  };
63 
64  // *** Seek operations
65  enum SeekOps
66  {
67  Seek_Set = 0,
68  Seek_Cur = 1,
69  Seek_End = 2
70  };
71 
72  // *** Errors
73  enum Errors
74  {
75  Error_FileNotFound = 0x1001,
76  Error_Access = 0x1002,
77  Error_IOError = 0x1003,
78  Error_DiskFull = 0x1004
79  };
80 };
81 
82 // ***** File Class
83 
84 // The pure virtual base random-access file
85 // This is a base class to all files
86 
87 class File : public RefCountBase<File, Stat_Default_Mem>, public FileConstants
88 {
89 public:
90  File() {}
91  // ** Location Information
92 
93  // Returns a file name path relative to the 'reference' directory
94  // This is often a path that was used to create a file
95  // (this is not a global path, global path can be obtained with help of directory)
96  virtual const char* GetFilePath() = 0;
97 
98  // ** File Information
99 
100  // Return 1 if file's usable (open)
101  virtual bool IsValid() = 0;
102  // Return 1 if file's writable, otherwise 0
103  virtual bool IsWritable() = 0;
104 
105  // Return position
106  virtual int Tell() = 0;
107  virtual SInt64 LTell() = 0;
108 
109  // File size
110  virtual int GetLength() = 0;
111  virtual SInt64 LGetLength() = 0;
112 
113  // Return errno-based error code
114  // Useful if any other function failed
115  virtual int GetErrorCode() = 0;
116 
117  // ** Stream implementation & I/O
118 
119  // Blocking write, will write in the given number of bytes to the stream
120  // Returns : -1 for error
121  // Otherwise number of bytes read
122  virtual int Write(const UByte* pbufer, int numBytes) = 0;
123 
124  // Blocking read, will read in the given number of bytes or less from the stream
125  // Returns : -1 for error
126  // Otherwise number of bytes read,
127  // if 0 or < numBytes, no more bytes available; end of file or the other side of stream is closed
128  virtual int Read(UByte* pbufer, int numBytes) = 0;
129 
130  // Skips (ignores) a given # of bytes
131  // Same return values as Read
132  virtual int SkipBytes(int numBytes) = 0;
133 
134  // Returns the number of bytes available to read from a stream without blocking
135  // For a file, this should generally be number of bytes to the end
136  virtual int BytesAvailable() = 0;
137 
138  // Causes any implementation's buffered data to be delivered to destination
139  // Return 0 for error
140  virtual bool Flush() = 0;
141 
142  // Need to provide a more optimized implementation that doe snot necessarily involve a lot of seeking
143  KY_INLINE bool IsEOF() { return !BytesAvailable(); }
144 
145  // Seeking
146  // Returns new position, -1 for error
147  virtual int Seek(int offset, int origin = Seek_Set) = 0;
148  virtual SInt64 LSeek(SInt64 offset, int origin = Seek_Set) = 0;
149 
150  // Seek simplification
151  virtual int SeekToBegin() { return Seek(0); }
152  int SeekToEnd() { return Seek(0, Seek_End); }
153  int Skip(int numBytes) { return Seek(numBytes, Seek_Cur); }
154 
155  // Resizing the file
156  // Return 0 for failure
157  virtual bool ChangeSize(int newSize) = 0;
158 
159  // Appends other file data from a stream
160  // Return -1 for error, else # of bytes written
161  virtual int CopyFromStream(File* pstream, int byteSize) = 0;
162 
163  // Closes the file
164  // After close, file cannot be accessed
165  virtual bool Close() = 0;
166 
167  // ***** Inlines for convenient primitive type serialization
168 
169  // Read/Write helpers
170 private:
171  UInt64 PRead64()
172  {
173  UInt64 v = 0;
174  Read((UByte*)&v, 8);
175  return v;
176  }
177  UInt32 PRead32()
178  {
179  UInt32 v = 0;
180  Read((UByte*)&v, 4);
181  return v;
182  }
183  UInt16 PRead16()
184  {
185  UInt16 v = 0;
186  Read((UByte*)&v, 2);
187  return v;
188  }
189  UInt8 PRead8()
190  {
191  UInt8 v = 0;
192  Read((UByte*)&v, 1);
193  return v;
194  }
195  void PWrite64(UInt64 v) { Write((UByte*)&v, 8); }
196  void PWrite32(UInt32 v) { Write((UByte*)&v, 4); }
197  void PWrite16(UInt16 v) { Write((UByte*)&v, 2); }
198  void PWrite8(UInt8 v) { Write((UByte*)&v, 1); }
199 
200 public:
201  // Writing primitive types - Little Endian
202  inline void WriteUByte(UByte v) { PWrite8((UInt8)Alg::ByteUtil::SystemToLE(v)); }
203  inline void WriteSByte(SByte v) { PWrite8((UInt8)Alg::ByteUtil::SystemToLE(v)); }
204  inline void WriteUInt8(UInt8 v) { PWrite8((UInt8)Alg::ByteUtil::SystemToLE(v)); }
205  inline void WriteSInt8(SInt8 v) { PWrite8((UInt8)Alg::ByteUtil::SystemToLE(v)); }
206  inline void WriteUInt16(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); }
207  inline void WriteSInt16(SInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToLE(v)); }
208  inline void WriteUInt32(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); }
209  inline void WriteSInt32(SInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToLE(v)); }
210  inline void WriteUInt64(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); }
211  inline void WriteSInt64(SInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToLE(v)); }
212  inline void WriteFloat(float v)
213  {
214  v = Alg::ByteUtil::SystemToLE(v);
215  Write((UByte*)&v, 4);
216  }
217  inline void WriteDouble(double v)
218  {
219  v = Alg::ByteUtil::SystemToLE(v);
220  Write((UByte*)&v, 8);
221  }
222  // Writing primitive types - Big Endian
223  inline void WriteUByteBE(UByte v) { PWrite8((UInt8)Alg::ByteUtil::SystemToBE(v)); }
224  inline void WriteSByteBE(SByte v) { PWrite8((UInt8)Alg::ByteUtil::SystemToBE(v)); }
225  inline void WriteUInt8BE(UInt16 v) { PWrite8((UInt8)Alg::ByteUtil::SystemToBE(v)); }
226  inline void WriteSInt8BE(SInt16 v) { PWrite8((UInt8)Alg::ByteUtil::SystemToBE(v)); }
227  inline void WriteUInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); }
228  inline void WriteSInt16BE(UInt16 v) { PWrite16((UInt16)Alg::ByteUtil::SystemToBE(v)); }
229  inline void WriteUInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); }
230  inline void WriteSInt32BE(UInt32 v) { PWrite32((UInt32)Alg::ByteUtil::SystemToBE(v)); }
231  inline void WriteUInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); }
232  inline void WriteSInt64BE(UInt64 v) { PWrite64((UInt64)Alg::ByteUtil::SystemToBE(v)); }
233  inline void WriteFloatBE(float v)
234  {
235  v = Alg::ByteUtil::SystemToBE(v);
236  Write((UByte*)&v, 4);
237  }
238  inline void WriteDoubleBE(double v)
239  {
240  v = Alg::ByteUtil::SystemToBE(v);
241  Write((UByte*)&v, 8);
242  }
243 
244  // Reading primitive types - Little Endian
245  inline UByte ReadUByte() { return (UByte)Alg::ByteUtil::LEToSystem(PRead8()); }
246  inline SByte ReadSByte() { return (SByte)Alg::ByteUtil::LEToSystem(PRead8()); }
247  inline UInt8 ReadUInt8() { return (UInt8)Alg::ByteUtil::LEToSystem(PRead8()); }
248  inline SInt8 ReadSInt8() { return (SInt8)Alg::ByteUtil::LEToSystem(PRead8()); }
249  inline UInt16 ReadUInt16() { return (UInt16)Alg::ByteUtil::LEToSystem(PRead16()); }
250  inline SInt16 ReadSInt16() { return (SInt16)Alg::ByteUtil::LEToSystem(PRead16()); }
251  inline UInt32 ReadUInt32() { return (UInt32)Alg::ByteUtil::LEToSystem(PRead32()); }
252  inline SInt32 ReadSInt32() { return (SInt32)Alg::ByteUtil::LEToSystem(PRead32()); }
253  inline UInt64 ReadUInt64() { return (UInt64)Alg::ByteUtil::LEToSystem(PRead64()); }
254  inline SInt64 ReadSInt64() { return (SInt64)Alg::ByteUtil::LEToSystem(PRead64()); }
255  inline float ReadFloat()
256  {
257  float v = 0.0f;
258  Read((UByte*)&v, 4);
259  return Alg::ByteUtil::LEToSystem(v);
260  }
261  inline double ReadDouble()
262  {
263  double v = 0.0;
264  Read((UByte*)&v, 8);
265  return Alg::ByteUtil::LEToSystem(v);
266  }
267  // Reading primitive types - Big Endian
268  inline UByte ReadUByteBE() { return (UByte)Alg::ByteUtil::BEToSystem(PRead8()); }
269  inline SByte ReadSByteBE() { return (SByte)Alg::ByteUtil::BEToSystem(PRead8()); }
270  inline UInt8 ReadUInt8BE() { return (UInt8)Alg::ByteUtil::BEToSystem(PRead8()); }
271  inline SInt8 ReadSInt8BE() { return (SInt8)Alg::ByteUtil::BEToSystem(PRead8()); }
272  inline UInt16 ReadUInt16BE() { return (UInt16)Alg::ByteUtil::BEToSystem(PRead16()); }
273  inline SInt16 ReadSInt16BE() { return (SInt16)Alg::ByteUtil::BEToSystem(PRead16()); }
274  inline UInt32 ReadUInt32BE() { return (UInt32)Alg::ByteUtil::BEToSystem(PRead32()); }
275  inline SInt32 ReadSInt32BE() { return (SInt32)Alg::ByteUtil::BEToSystem(PRead32()); }
276  inline UInt64 ReadUInt64BE() { return (UInt64)Alg::ByteUtil::BEToSystem(PRead64()); }
277  inline SInt64 ReadSInt64BE() { return (SInt64)Alg::ByteUtil::BEToSystem(PRead64()); }
278  inline float ReadFloatBE()
279  {
280  float v = 0.0f;
281  Read((UByte*)&v, 4);
282  return Alg::ByteUtil::BEToSystem(v);
283  }
284  inline double ReadDoubleBE()
285  {
286  double v = 0.0;
287  Read((UByte*)&v, 8);
288  return Alg::ByteUtil::BEToSystem(v);
289  }
290 };
291 
292 // *** Delegated File
293 
294 class DelegatedFile : public File
295 {
296 protected:
297  // Delegating file pointer
298  Ptr<File> pFile;
299 
300  // Hidden default constructor
301  DelegatedFile() : pFile(0) {}
302  DelegatedFile(const DelegatedFile& source) : File() { KY_UNUSED(source); }
303 
304 public:
305  // Constructors
306  DelegatedFile(File* pfile) : pFile(pfile) {}
307 
308  // ** Location Information
309  virtual const char* GetFilePath() { return pFile->GetFilePath(); }
310 
311  // ** File Information
312  virtual bool IsValid() { return pFile && pFile->IsValid(); }
313  virtual bool IsWritable() { return pFile->IsWritable(); }
314 
315  virtual int Tell() { return pFile->Tell(); }
316  virtual SInt64 LTell() { return pFile->LTell(); }
317 
318  virtual int GetLength() { return pFile->GetLength(); }
319  virtual SInt64 LGetLength() { return pFile->LGetLength(); }
320 
321  virtual int GetErrorCode() { return pFile->GetErrorCode(); }
322 
323  // ** Stream implementation & I/O
324  virtual int Write(const UByte* pbuffer, int numBytes) { return pFile->Write(pbuffer, numBytes); }
325  virtual int Read(UByte* pbuffer, int numBytes) { return pFile->Read(pbuffer, numBytes); }
326 
327  virtual int SkipBytes(int numBytes) { return pFile->SkipBytes(numBytes); }
328 
329  virtual int BytesAvailable() { return pFile->BytesAvailable(); }
330 
331  virtual bool Flush() { return pFile->Flush(); }
332 
333  // Seeking
334  virtual int Seek(int offset, int origin = Seek_Set) { return pFile->Seek(offset, origin); }
335  virtual SInt64 LSeek(SInt64 offset, int origin = Seek_Set) { return pFile->LSeek(offset, origin); }
336 
337  // Resizing the file
338  virtual bool ChangeSize(int newSize) { return pFile->ChangeSize(newSize); }
339  virtual int CopyFromStream(File* pstream, int byteSize) { return pFile->CopyFromStream(pstream, byteSize); }
340 
341  // Closing the file
342  virtual bool Close() { return pFile->Close(); }
343 };
344 
345 // *** Buffered File
346 
347 // This file class adds buffering to an existing file
348 // Buffered file never fails by itself; if there's not
349 // enough memory for buffer, no buffer's used
350 
351 class BufferedFile : public DelegatedFile
352 {
353 protected:
354  enum BufferModeType
355  {
356  NoBuffer,
357  ReadBuffer,
358  WriteBuffer
359  };
360 
361  // Buffer & the mode it's in
362  UByte* pBuffer;
363  BufferModeType BufferMode;
364  unsigned Pos; // Position in buffer
365  unsigned DataSize; // Data in buffer if reading
366  UInt64 FilePos; // Underlying file position
367 
368  // Initializes buffering to a certain mode
369  bool SetBufferMode(BufferModeType mode);
370 
371  // Flushes buffer
372  // WriteBuffer - write data to disk, ReadBuffer - reset buffer & fix file position
373  void FlushBuffer();
374 
375  // Loads data into ReadBuffer
376  // WARNING: Right now LoadBuffer() assumes the buffer's empty
377  void LoadBuffer();
378 
379  // Hidden constructor
380  BufferedFile();
381  inline BufferedFile(const BufferedFile& source) : DelegatedFile() { KY_UNUSED(source); }
382 
383 public:
384  static int FILEBUFFER_SIZE;
385  static int FILEBUFFER_TOLERANCE;
386 
387  // Constructor
388  // - takes another file as source
389  BufferedFile(File* pfile);
390  ~BufferedFile();
391 
392  // ** Overridden functions
393 
394  // We override all the functions that can possibly
395  // require buffer mode switch, flush, or extra calculations
396  virtual int Tell();
397  virtual SInt64 LTell();
398 
399  virtual int GetLength();
400  virtual SInt64 LGetLength();
401 
402  // virtual bool Stat(GFileStats *pfs);
403 
404  virtual int Write(const UByte* pbufer, int numBytes);
405  virtual int Read(UByte* pbufer, int numBytes);
406 
407  virtual int SkipBytes(int numBytes);
408 
409  virtual int BytesAvailable();
410 
411  virtual bool Flush();
412 
413  virtual int Seek(int offset, int origin = Seek_Set);
414  virtual SInt64 LSeek(SInt64 offset, int origin = Seek_Set);
415 
416  virtual bool ChangeSize(int newSize);
417  virtual int CopyFromStream(File* pstream, int byteSize);
418 
419  virtual bool Close();
420 };
421 
422 // *** Memory File
423 
424 class MemoryFile : public File
425 {
426 public:
427  const char* GetFilePath() { return FilePath.ToCStr(); }
428 
429  bool IsValid() { return Valid; }
430  bool IsWritable() { return false; }
431 
432  bool Flush() { return true; }
433  int GetErrorCode() { return 0; }
434 
435  int Tell() { return FileIndex; }
436  SInt64 LTell() { return (SInt64)FileIndex; }
437 
438  int GetLength() { return FileSize; }
439  SInt64 LGetLength() { return (SInt64)FileSize; }
440 
441  bool Close()
442  {
443  Valid = false;
444  return false;
445  }
446 
447  int CopyFromStream(File* pstream, int byteSize)
448  {
449  KY_UNUSED2(pstream, byteSize);
450  return 0;
451  }
452 
453  int Write(const UByte* pbuffer, int numBytes)
454  {
455  KY_UNUSED2(pbuffer, numBytes);
456  return 0;
457  }
458 
459  int Read(UByte* pbufer, int numBytes)
460  {
461  if (FileIndex + numBytes > FileSize)
462  {
463  numBytes = FileSize - FileIndex;
464  }
465 
466  if (numBytes > 0)
467  {
468  ::memcpy(pbufer, &FileData[FileIndex], numBytes);
469 
470  FileIndex += numBytes;
471  }
472 
473  return numBytes;
474  }
475 
476  int SkipBytes(int numBytes)
477  {
478  if (FileIndex + numBytes > FileSize)
479  {
480  numBytes = FileSize - FileIndex;
481  }
482 
483  FileIndex += numBytes;
484 
485  return numBytes;
486  }
487 
488  int BytesAvailable() { return (FileSize - FileIndex); }
489 
490  int Seek(int offset, int origin = Seek_Set)
491  {
492  switch (origin)
493  {
494  case Seek_Set: FileIndex = offset; break;
495  case Seek_Cur: FileIndex += offset; break;
496  case Seek_End: FileIndex = FileSize - offset; break;
497  }
498 
499  return FileIndex;
500  }
501 
502  SInt64 LSeek(SInt64 offset, int origin = Seek_Set) { return (SInt64)Seek((int)offset, origin); }
503 
504  bool ChangeSize(int newSize)
505  {
506  FileSize = newSize;
507  return true;
508  }
509 
510 public:
511  MemoryFile(const String& fileName, const UByte* pBuffer, int buffSize) : FilePath(fileName)
512  {
513  FileData = pBuffer;
514  FileSize = buffSize;
515  FileIndex = 0;
516  Valid = (!fileName.IsEmpty() && pBuffer && buffSize > 0) ? true : false;
517  }
518 
519  // pfileName should be encoded as UTF-8 to support international file names.
520  MemoryFile(const char* pfileName, const UByte* pBuffer, int buffSize) : FilePath(pfileName)
521  {
522  FileData = pBuffer;
523  FileSize = buffSize;
524  FileIndex = 0;
525  Valid = (pfileName && pBuffer && buffSize > 0) ? true : false;
526  }
527 
528 private:
529  String FilePath;
530  const UByte* FileData;
531  int FileSize;
532  int FileIndex;
533  bool Valid;
534 };
535 
536 // ***** Global path helpers
537 
538 // Find trailing short filename in a path.
539 const char* GetShortFilename(const char* purl);
540 }
std::int64_t SInt64
int64_t
Definition: SF_Types.h:132
std::uint16_t UInt16
uint16_t
Definition: SF_Types.h:136
std::uint8_t UByte
uint8_t
Definition: SF_Types.h:134
std::int32_t SInt32
int32_t
Definition: SF_Types.h:131
std::uint32_t UInt32
uint32_t
Definition: SF_Types.h:137
std::int8_t SInt8
int8_t
Definition: SF_Types.h:129
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
std::uint8_t UInt8
uint8_t
Definition: SF_Types.h:135
std::int8_t SByte
uint8_t
Definition: SF_Types.h:128
std::uint64_t UInt64
uint64_t
Definition: SF_Types.h:138
std::int16_t SInt16
int16_t
Definition: SF_Types.h:130