PhysFSFileStream.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* PhysFSFileStream.cs - (c)2003 Gregory S. Read */
  2. using System;
  3. using System.Collections;
  4. using System.IO;
  5. namespace PhysFS_NET
  6. {
  7. public enum PhysFSFileMode {Read, Write, Append};
  8. // Our exception class we'll use for throwing all PhysFS API related exception
  9. public class PhysFSException : IOException
  10. {
  11. public PhysFSException(string Message) : base(Message) {}
  12. public PhysFSException() : base(PhysFS_DLL.PHYSFS_getLastError()) {}
  13. }
  14. public unsafe class PhysFSFileStream : Stream
  15. {
  16. // ***Public properties***
  17. public override bool CanRead
  18. {
  19. get
  20. {
  21. // Reading is supported
  22. return true;
  23. }
  24. }
  25. public override bool CanSeek
  26. {
  27. get
  28. {
  29. // Seek is supported
  30. return true;
  31. }
  32. }
  33. public override bool CanWrite
  34. {
  35. get
  36. {
  37. // Writing is supported
  38. return true;
  39. }
  40. }
  41. public override long Length
  42. {
  43. get
  44. {
  45. long TempLength;
  46. TempLength = PhysFS_DLL.PHYSFS_fileLength(pHandle);
  47. // If call returned an error, throw an exception
  48. if(TempLength == -1)
  49. throw new PhysFSException();
  50. return TempLength;
  51. }
  52. }
  53. public override long Position
  54. {
  55. get
  56. {
  57. long TempPosition;
  58. TempPosition = PhysFS_DLL.PHYSFS_tell(pHandle);
  59. // If call returned an error, throw an exception
  60. if(TempPosition == -1)
  61. throw new PhysFSException();
  62. return TempPosition;
  63. }
  64. set
  65. {
  66. // Seek from beginning of file using the position value
  67. Seek(value, SeekOrigin.Begin);
  68. }
  69. }
  70. // ***Public methods***
  71. public PhysFSFileStream(string FileName, PhysFSFileMode FileMode, ulong BufferSize)
  72. {
  73. // Open the specified file with the appropriate file access
  74. switch(FileMode)
  75. {
  76. case PhysFSFileMode.Read:
  77. pHandle = PhysFS_DLL.PHYSFS_openRead(FileName);
  78. break;
  79. case PhysFSFileMode.Write:
  80. pHandle = PhysFS_DLL.PHYSFS_openWrite(FileName);
  81. break;
  82. case PhysFSFileMode.Append:
  83. pHandle = PhysFS_DLL.PHYSFS_openAppend(FileName);
  84. break;
  85. default:
  86. throw new PhysFSException("Invalid FileMode specified");
  87. }
  88. // If handle is null, an error occured, so raise an exception
  89. //!!! Does object get created if exception is thrown?
  90. if(pHandle == null)
  91. throw new PhysFSException();
  92. // Set buffer size, raise an exception if an error occured
  93. if(PhysFS_DLL.PHYSFS_setBuffer(pHandle, BufferSize) == 0)
  94. throw new PhysFSException();
  95. }
  96. // This constructor sets the buffer size to 0 if not specified
  97. public PhysFSFileStream(string FileName, PhysFSFileMode FileMode) : this(FileName, FileMode, 0) {}
  98. ~PhysFSFileStream()
  99. {
  100. // Don't close the handle if they've specifically closed it already
  101. if(!Closed)
  102. Close();
  103. }
  104. public override void Flush()
  105. {
  106. if(PhysFS_DLL.PHYSFS_flush(pHandle) == 0)
  107. throw new PhysFSException();
  108. }
  109. public override int Read(byte[] buffer, int offset, int count)
  110. {
  111. long RetValue;
  112. fixed(byte *pbytes = &buffer[offset])
  113. {
  114. // Read into our allocated pointer
  115. RetValue = PhysFS_DLL.PHYSFS_read(pHandle, pbytes, sizeof(byte), (uint)count);
  116. }
  117. if(RetValue == -1)
  118. throw new PhysFSException();
  119. // Return number of bytes read
  120. // Note: This cast should be safe since we are only reading 'count' items, which
  121. // is of type 'int'.
  122. return (int)RetValue;
  123. }
  124. public override void Write(byte[] buffer, int offset, int count)
  125. {
  126. long RetValue;
  127. fixed(byte* pbytes = &buffer[offset])
  128. {
  129. // Write buffer
  130. RetValue = PhysFS_DLL.PHYSFS_write(pHandle, pbytes, sizeof(byte), (uint)count);
  131. }
  132. if(RetValue == -1)
  133. throw new PhysFSException();
  134. }
  135. public override long Seek(long offset, SeekOrigin origin)
  136. {
  137. // Only seeking from beginning is supported by PhysFS API
  138. if(origin != SeekOrigin.Begin)
  139. throw new PhysFSException("Only seek origin of \"Begin\" is supported");
  140. // Seek to specified offset, raise an exception if error occured
  141. if(PhysFS_DLL.PHYSFS_seek(pHandle, (ulong)offset) == 0)
  142. throw new PhysFSException();
  143. // Since we always seek from beginning, the offset is always
  144. // the absolute position.
  145. return offset;
  146. }
  147. public override void SetLength(long value)
  148. {
  149. throw new NotSupportedException("SetLength method not supported in PhysFSFileStream objects.");
  150. }
  151. public override void Close()
  152. {
  153. // Close the handle
  154. if(PhysFS_DLL.PHYSFS_close(pHandle) == 0)
  155. throw new PhysFSException();
  156. // File has been closed. Rock.
  157. Closed = true;
  158. }
  159. // ***Private variables***
  160. private void *pHandle;
  161. private bool Closed = false;
  162. }
  163. }