File.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System;
  2. using System.IO;
  3. using System.Runtime.InteropServices;
  4. namespace AtomicEngine
  5. {
  6. public partial class File : AObject, AbstractFile
  7. {
  8. private class Stream : System.IO.Stream
  9. {
  10. private File file;
  11. public override bool CanRead
  12. {
  13. get
  14. {
  15. return file.Mode == FileMode.FILE_READ || file.Mode == FileMode.FILE_READWRITE;
  16. }
  17. }
  18. public override bool CanSeek
  19. {
  20. get
  21. {
  22. return true;
  23. }
  24. }
  25. public override bool CanWrite
  26. {
  27. get
  28. {
  29. return file.Mode == FileMode.FILE_WRITE ||
  30. file.Mode == FileMode.FILE_READWRITE ||
  31. file.Mode == FileMode.FILE_APPEND;
  32. }
  33. }
  34. public override long Length
  35. {
  36. get
  37. {
  38. return file.GetSize();
  39. }
  40. }
  41. public override long Position
  42. {
  43. get
  44. {
  45. return file.GetPosition();
  46. }
  47. set
  48. {
  49. file.Seek((uint)value);
  50. }
  51. }
  52. public Stream(File file)
  53. {
  54. if (file == null)
  55. throw new ArgumentNullException(nameof(file));
  56. this.file = file;
  57. }
  58. public override void Flush()
  59. {
  60. file.Flush();
  61. }
  62. public override int Read(byte[] buffer, int offset, int count)
  63. {
  64. if (buffer == null)
  65. throw new ArgumentNullException(nameof(buffer));
  66. if (offset + count > buffer.Length)
  67. throw new IndexOutOfRangeException("buffer.Length");
  68. byte[] readData = file.Read(count);
  69. int limit = Math.Min(count, readData.Length);
  70. Array.Copy(readData, 0, buffer, offset, limit);
  71. return limit;
  72. }
  73. public override long Seek(long offset, SeekOrigin origin)
  74. {
  75. if (origin == SeekOrigin.Current)
  76. {
  77. offset += Position;
  78. }
  79. else if (origin == SeekOrigin.End)
  80. {
  81. offset += Length;
  82. }
  83. return file.Seek((uint)offset);
  84. }
  85. public override void SetLength(long value)
  86. {
  87. throw new InvalidOperationException();
  88. }
  89. public override void Write(byte[] buffer, int offset, int count)
  90. {
  91. if (buffer == null)
  92. throw new ArgumentNullException(nameof(buffer));
  93. if (offset + count >= buffer.Length)
  94. throw new IndexOutOfRangeException("buffer.Length");
  95. file.Write(buffer, offset, count);
  96. }
  97. protected override void Dispose(bool disposing)
  98. {
  99. if (file != null)
  100. {
  101. file.Close();
  102. file = null;
  103. }
  104. base.Dispose(disposing);
  105. }
  106. }
  107. public System.IO.Stream ToStream()
  108. {
  109. return new Stream(this);
  110. }
  111. /// <summary>
  112. /// Read bytes from the file. Return array of bytes of the length actually read (can be 0 length)
  113. /// </summary>
  114. unsafe public byte[] Read(int size)
  115. {
  116. byte[] bytes = null;
  117. byte[] buffer = new byte[size];
  118. int sizeRead = 0;
  119. fixed (byte* p = buffer)
  120. {
  121. IntPtr ptr = (IntPtr)p;
  122. sizeRead = (int)csi_Atomic_File_Read(nativeInstance, ptr, (uint)size);
  123. bytes = new byte[sizeRead];
  124. if (sizeRead > 0)
  125. {
  126. Marshal.Copy(ptr, bytes, 0, (int)sizeRead);
  127. }
  128. }
  129. return bytes;
  130. }
  131. [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
  132. internal static extern uint csi_Atomic_File_Read(IntPtr self, IntPtr dest, uint size);
  133. /// <summary>
  134. /// Write bytes to the file, with optional offset into array and count of bytes to write.
  135. /// Return number of bytes actually written.
  136. /// </summary>
  137. unsafe public int Write(byte[] bytes, int offset = 0, int count = 0)
  138. {
  139. if (bytes == null || bytes.Length == 0)
  140. return 0;
  141. if (count == 0)
  142. count = bytes.Length;
  143. if (offset >= bytes.Length)
  144. return 0;
  145. // should this truncate?
  146. if ((offset + count) > bytes.Length)
  147. return 0;
  148. int bytesWritten = 0;
  149. fixed (byte* p = bytes)
  150. {
  151. IntPtr ptr = (IntPtr)p;
  152. bytesWritten = (int)csi_Atomic_File_Write(nativeInstance, ptr, (uint) offset, (uint)count);
  153. }
  154. return bytesWritten;
  155. }
  156. [DllImport(Constants.LIBNAME, CallingConvention = CallingConvention.Cdecl)]
  157. internal static extern uint csi_Atomic_File_Write(IntPtr self, IntPtr data, uint offset, uint size);
  158. };
  159. }