//OS Calls (P/Invoke)\r
\r
\r
- // For StdInputStream\r
- [DllImport("msvcrt.dll")]\r
- private static extern int _read(int handle, out byte buffer, uint count);\r
- //private static extern int _read(int handle, byte[] buffer, uint count);\r
-\r
-\r
- // For StdOutputStream\r
- [DllImport("msvcrt.dll")]\r
- private static extern int _write(int handle, ref byte buffer, uint count);\r
- //private static extern int _write(int handle, byte[] buffer, uint count);\r
- \r
-\r
/*DWORD GetFullPathName(\r
LPCTSTR lpFileName, // file name\r
DWORD nBufferLength, // size of path buffer\r
\r
public int ReadStdInput(byte[] buffer, int offset, int count)\r
{\r
- /*\r
- * Note that a byte is being passed into the native read\r
- * function. But importantly is that a reference, via the out, is being passed,\r
- * so the the native read function pass the value back to this method. Doing it\r
- * this away to avoid GC issues with the VM as value types (byte) do not get\r
- * moved around like objects (byte[]) do. Downside is that the OS is being called\r
- * many times in this loop. Should WE USE Standard C Library getChar()? Optimally, \r
- * probably want to call the read function the second way (commented out) below...\r
- * but maybe not. Doing it this way could be better since we are forced to do some\r
- * checks.\r
- */\r
- byte b;\r
- int nativeReadRetVal;\r
- int charsRead = 0;\r
-\r
- for (int i = 0; i < count; i++)\r
- {\r
- if (isNextCharacterResidualNewline)\r
- {\r
- isNextCharacterResidualNewline = false;\r
- buffer[i+offset] = residualNewlineByte;\r
- charsRead++;\r
- if (count == 1)\r
- {\r
- break;\r
- }\r
- }\r
- else\r
- {\r
- // Returns 0 if at the end of the stream, -1 if an error;\r
- nativeReadRetVal = _read(STDIN, out b, 1);\r
- if (nativeReadRetVal == -1)\r
- {\r
- throw new System.IO.IOException();\r
- }\r
- // The MS implementation needs the end of stream character on a line by\r
- // itself. So if end of stream character (^Z, which is 0x0017) is reached, but\r
- // the previous character was not a newline character (and since we break\r
- // once a newline is hit, the only way this could be true is if we are on\r
- // the first iteration of ths loop), then it is not\r
- // technically the end of the stream. Is this a correct assumption?\r
- if (nativeReadRetVal == 0 && i == 0)\r
- {\r
- // TODO: Windows: Read: What is the better way to do this? Should I do this? MS implementation seems to.\r
- // Flush any characeters following the ^Z\r
- while (!IsPartOfNewlineSequence(b))\r
- {\r
- nativeReadRetVal = _read(STDIN, out b, 1);\r
- if (nativeReadRetVal == -1)\r
- {\r
- throw new System.IO.IOException();\r
- }\r
- }\r
- break;\r
- }\r
- // If the next byte is part of the newline sequence, place all of the characters\r
- // of the newline in the the buffer, then break. The native read function\r
- // combines the newline characters into one (e.g. CR-LF into just LF)\r
- if (IsPartOfNewlineSequence(b))\r
- {\r
- char[] newlineArray = System.Environment.NewLine.ToCharArray();\r
- for (int j = i; j < (i+newlineArray.Length); j++)\r
- {\r
- // If we are at the end of the buffer (i.e. at the limit of number\r
- // of characters to count) set static boolean to say next character\r
- // should be newline character\r
- // The loop is guaranteed to run to the "else" successfully \r
- // once since we could not have gotten to this point if\r
- // we were at count (the main for loop would have ended)\r
- if (j == count)\r
- {\r
- isNextCharacterResidualNewline = true;\r
- residualNewlineByte = (byte) newlineArray[j-i];\r
- }\r
- else\r
- {\r
- buffer[j+offset] = (byte) newlineArray[j-i];\r
- charsRead++; \r
- }\r
- \r
- }\r
- break;\r
- }\r
- charsRead++;\r
- buffer[i+offset] = b;\r
- }\r
- }\r
- \r
- /*\r
- * SECOND POSSIBLE WAY\r
- * \r
- // Not just using 'buffer' parameter because of the offset. Deal with the offset \r
- // below\r
- byte[] ba = new byte[count];\r
- charsRead = _read(STDIN, ba, (uint) count);\r
- if (charsRead == -1)\r
- {\r
- throw new System.IO.IOException();\r
- }\r
- Array.Copy(ba, 0, buffer, offset, charsRead);\r
- */\r
- \r
- return charsRead; \r
+ return ReadFile(new IntPtr(STDIN), buffer, offset, count);\r
}\r
\r
public void FlushStdOutput(byte[] byteBuf)\r
{\r
- byte b;\r
- /*\r
- * Note that a byte is being passed into the native write\r
- * function. Doing it\r
- * this away to avoid GC issues with the VM as value types (byte) do not get\r
- * moved around like objects (byte[]) do. Downside is that the OS is being called\r
- * many times in this loop. Should WE USE Standard C Library putChar()? Optimally, \r
- * probably want to call the write function the first way (commented out) below\r
- */\r
- //if (_write(STDOUT, byteBuf, (uint) byteBuf.Length) == -1)\r
- for (int i = 0; i < byteBuf.Length; i++)\r
- {\r
- b = byteBuf[i];\r
- if (_write(STDOUT, ref b, 1) == -1)\r
- {\r
- throw new System.IO.IOException(); // An I/O Exception occurred");\r
- }\r
- }\r
- // TODO: Windows: Flush: Determine if a call to a native flush should be called in StdOutputStream\r
+ FlushFile (new IntPtr(STDOUT), byteBuf);\r
}\r
\r
- public int ReadFile(IntPtr handle, byte[] buffer, int offset, int count)\r
+ public unsafe int ReadFile(IntPtr handle, byte[] buffer, int offset, int count)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:ReadFile(System.Int32, byte[], System.Int32, System.Int32): Stub Method");\r
- return -1;\r
+ int res;\r
+\r
+ fixed (void *p = &buffer[offset]) {\r
+ res = _read(handle, p, count);\r
+ }\r
+ return res;\r
}\r
\r
- public int WriteFile(IntPtr handle, byte[] buffer, int offset, int count)\r
+ public unsafe int WriteFile(IntPtr handle, byte[] buffer, int offset, int count)\r
{\r
- return -1;\r
+ int res;\r
+\r
+ fixed (void *p = &buffer [offset]) {\r
+ res = _write(handle, p, count);\r
+ }\r
+ return res;\r
}\r
\r
public int SetLengthFile(IntPtr handle, long length)\r
{\r
- return 0; \r
+ return _ftruncate (handle, (int)length);\r
}\r
\r
public void FlushFile(IntPtr handle, byte[] byteBuf)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:FlushFile(System.Int32, byte[]): Stub Method");\r
+ WriteFile (handle, byteBuf, 0, byteBuf.Length);\r
}\r
\r
public IntPtr OpenFile(string path, FileMode mode, FileAccess access, FileShare share)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:OpenFile(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare): Stub Method");\r
- return new IntPtr(-1);\r
+ int flags = _getUnixFlags (mode, access);\r
+\r
+ return _open (path, flags, 0x1a4);\r
}\r
\r
public void CloseFile(IntPtr handle)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:CloseFile(System.Int32): Stub Method");\r
+ _close (handle);\r
}\r
\r
public long SeekFile(IntPtr handle, long offset, SeekOrigin origin)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:SeekFile(System.Int32, System.Int64, System.IO.SeekOrigin): Stub Method");\r
- return -1;\r
+ switch (origin) {\r
+ case SeekOrigin.End:\r
+ return _lseek (handle, (int)offset, SEEK_END);\r
+ case SeekOrigin.Current:\r
+ return _lseek (handle, (int)offset, SEEK_CUR);\r
+ default:\r
+ return _lseek (handle, (int)offset, SEEK_SET);\r
+ }\r
}\r
\r
public IntPtr CreateFile(string path, FileMode mode, FileAccess access, FileShare share)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:CreateFile(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare): Stub Method");\r
- return new IntPtr(-1);\r
+ return OpenFile(path, FileMode.CreateNew, access, share);\r
}\r
\r
public void DeleteFile(string path)\r
{\r
- System.Diagnostics.Debug.WriteLine("Windows:DeleteFile(System.String): Stub Method");\r
+ _unlink(path);\r
}\r
\r
public bool ExistsFile(string path)\r
[ DllImport("msvcrt", EntryPoint="tanh") ]\r
public extern static double Tanh(double d);\r
\r
+ [ DllImport("msvcrt", EntryPoint="_read", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern int _read(IntPtr fd, void *buf, int count);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_write", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern int _write(IntPtr fd, void *buf, int count);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_lseek", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern int _lseek(IntPtr fd, int offset, int whence);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_chsize", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern int _ftruncate (IntPtr fd, int count);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_close", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern void _close(IntPtr fd);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_open", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern IntPtr _open(string path, int flags, int mode);\r
+\r
+ [ DllImport("msvcrt", EntryPoint="_unlink", CharSet=CharSet.Ansi) ]\r
+ private unsafe static extern int _unlink(string path);\r
+\r
+ private const int O_RDONLY = 0x000;\r
+ private const int O_WRONLY = 0x001;\r
+ private const int O_RDWR = 0x002;\r
+ private const int O_CREAT = 0x040;\r
+ private const int O_EXCL = 0x080;\r
+ private const int O_TRUNC = 0x200;\r
+ private const int O_APPEND = 0x400;\r
+\r
+ private const int SEEK_SET = 0;\r
+ private const int SEEK_CUR = 1;\r
+ private const int SEEK_END = 2;\r
+\r
+ private int _getUnixFlags (FileMode mode, FileAccess access)\r
+ {\r
+ int flags = 0;\r
+ switch (access) {\r
+ case FileAccess.Read:\r
+ flags = O_RDONLY;\r
+ break;\r
+ case FileAccess.Write:\r
+ flags = O_WRONLY;\r
+ break;\r
+ case FileAccess.ReadWrite:\r
+ flags = O_RDWR;\r
+ break;\r
+ }\r
+\r
+ switch (mode) {\r
+ case FileMode.Append:\r
+ flags |= O_APPEND;\r
+ break;\r
+ case FileMode.Create:\r
+ flags |= O_CREAT;\r
+ break;\r
+ case FileMode.CreateNew:\r
+ flags |= O_CREAT | O_EXCL;\r
+ break;\r
+ case FileMode.Open:\r
+ break;\r
+ case FileMode.OpenOrCreate:\r
+ flags |= O_CREAT;\r
+ break;\r
+ case FileMode.Truncate:\r
+ flags |= O_TRUNC;\r
+ break;\r
+ }\r
+\r
+ return flags;\r
+ }\r
}\r
}\r