LILAC
Language to language Interop LAyer Compiler
Loading...
Searching...
No Matches
FileEmitter.cs
Go to the documentation of this file.
1using System.Runtime.CompilerServices;
2using System.Runtime.InteropServices;
3using System.Text;
4
5namespace Lilac.Generator;
6
7public static partial class FileEmitter
8{
9 [Flags]
10 private enum FileFlags
11 {
12 ReadOnly = 0,
13 WriteOnly = 1,
14 ReadWrite = 2,
15 Create = 64
16 }
17
18 [LibraryImport("c", EntryPoint = "open", SetLastError = true, StringMarshalling = StringMarshalling.Utf8)]
19 [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
20 private static unsafe partial int Open([MarshalAs(UnmanagedType.LPUTF8Str)] string path, FileFlags flags);
21
22 [LibraryImport("c", EntryPoint = "write", SetLastError = true)]
23 [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
24 private static unsafe partial int Write(int fd, void* buffer, nuint size);
25
26 [LibraryImport("c", EntryPoint = "close", SetLastError = true)]
27 [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
28 private static unsafe partial int Close(int fd);
29
30 [LibraryImport("kernel32", EntryPoint = "WriteFileA", SetLastError = true)]
31 private static unsafe partial int WriteFile(
32 void* handle,
33 void* buffer,
34 int numBytesToWrite,
35 int* numBytesWritten,
36 NativeOverlapped* lpOverlapped);
37
38 [LibraryImport(
39 "kernel32",
40 EntryPoint = "CreateFileW",
41 SetLastError = true,
42 StringMarshalling = StringMarshalling.Utf16)]
43 private static partial IntPtr CreateFileW(
44 [MarshalAs(UnmanagedType.LPWStr)] string filename,
45 FileAccess access,
46 FileShare share,
47 IntPtr securityAttributes,
48 FileMode creationDisposition,
49 FileAttributes flagsAndAttributes,
50 IntPtr templateFile);
51
52 [LibraryImport("kernel32", EntryPoint = "CloseHandleA", SetLastError = true)]
53 [return: MarshalAs(UnmanagedType.Bool)]
54 private static unsafe partial bool CloseHandle(IntPtr handle);
55
56 [LibraryImport("c", EntryPoint = "getcwd", SetLastError = true)]
57 private static unsafe partial byte* GetCurrentDirectory(byte* buf, nuint size);
58
59 [LibraryImport("kernel32", EntryPoint = "GetCurrentDirectoryW", SetLastError = true)]
60 private static unsafe partial uint GetCurrentDirectory(uint nBufferLength, byte* lpBuffer);
61
62 public static string GetCurrentDirectory()
63 {
64 var buffer = new byte[65535];
65 unsafe
66 {
67 fixed (byte* p = buffer)
68 {
69 if (OperatingSystem.IsWindows())
70 GetCurrentDirectory((uint)buffer.Length, p);
71 else
72 GetCurrentDirectory(p, (nuint)buffer.Length);
73
74 return Marshal.PtrToStringUTF8((IntPtr)p, buffer.Length);
75 }
76 }
77 }
78
79 public static void Write(string path, string text)
80 {
81 var windows = OperatingSystem.IsWindows();
82
83 var handle = windows
84 ? CreateFileW(
85 path,
86 FileAccess.Write,
87 FileShare.None,
88 0,
89 FileMode.OpenOrCreate,
90 FileAttributes.None,
91 0)
92 : Open(path, FileFlags.WriteOnly | FileFlags.Create);
93 if (handle < 0)
94 Console.WriteLine($"Failed to open file: {Marshal.GetLastWin32Error()}");
95
96 unsafe
97 {
98 var buffer = Encoding.UTF8.GetBytes(text);
99 var len = buffer.Length;
100 fixed (byte* p = buffer)
101 {
102 if (windows)
103 WriteFile((void*)handle, p, len, &len, null);
104 else
105 Write((int)handle, p, (UIntPtr)len);
106 }
107 }
108
109 if (windows)
110 CloseHandle(handle);
111 else
112 Close((int)handle);
113 }
114}