diff --git a/Capy64/LuaRuntime/Handlers/ReadHandle.cs b/Capy64/LuaRuntime/Handlers/ReadHandle.cs index 6005c58..50e77dd 100644 --- a/Capy64/LuaRuntime/Handlers/ReadHandle.cs +++ b/Capy64/LuaRuntime/Handlers/ReadHandle.cs @@ -9,23 +9,19 @@ using System.Threading.Tasks; namespace Capy64.LuaRuntime.Handlers; -public class ReadHandle : IDisposable +public class ReadHandle { - private readonly MemoryStream _memoryStream; - private readonly StreamReader _stream; - private bool isClosed = false; + public readonly StreamReader Stream; + public bool IsClosed = false; public ReadHandle(Stream stream) { - _memoryStream = new MemoryStream(capacity: (int)stream.Length); - stream.CopyTo(_memoryStream); - _memoryStream.Position = 0; - _stream = new StreamReader(_memoryStream); + Stream = new StreamReader(stream); } - public void Push(Lua L) + public void Push(Lua L, bool newTable = true) { - - L.NewTable(); + if (newTable) + L.NewTable(); L.PushString("readAll"); L.PushCFunction(L_ReadAll); @@ -42,35 +38,49 @@ public class ReadHandle : IDisposable L.PushString("close"); L.PushCFunction(L_Close); L.SetTable(-3); + + L.PushString("_handle"); + L.PushObject(this); + L.SetTable(-3); } - private int L_ReadAll(IntPtr state) + private static int L_ReadAll(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); + + if (h is null || h.IsClosed) L.Error("handle is closed"); - if (_stream.EndOfStream) + if (h.Stream.EndOfStream) { L.PushNil(); return 1; } - var content = _stream.ReadToEnd(); + var content = h.Stream.ReadToEnd(); L.PushString(content); return 1; } - private int L_ReadLine(IntPtr state) + private static int L_ReadLine(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); + + if (h is null || h.IsClosed) L.Error("handle is closed"); - var line = _stream.ReadLine(); + var line = h.Stream.ReadLine(); if (line is null) L.PushNil(); @@ -80,17 +90,24 @@ public class ReadHandle : IDisposable return 1; } - private int L_Read(IntPtr state) + private static int L_Read(IntPtr state) { var L = Lua.FromIntPtr(state); - var count = (int)L.OptNumber(1, 1); - L.ArgumentCheck(count >= 1, 1, "count must be a positive integer"); + L.CheckType(1, LuaType.Table); + var count = (int)L.OptNumber(2, 1); - if (isClosed) + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); + + + L.ArgumentCheck(count >= 1, 2, "count must be a positive integer"); + + if (h is null || h.IsClosed) L.Error("handle is closed"); - if (_stream.EndOfStream) + if (h.Stream.EndOfStream) { L.PushNil(); return 1; @@ -98,29 +115,29 @@ public class ReadHandle : IDisposable var chunk = new char[count]; - _stream.Read(chunk, 0, count); + h.Stream.Read(chunk, 0, count); L.PushString(new string(chunk)); return 1; } - private int L_Close(IntPtr state) + private static int L_Close(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, true); + + if (h is null || h.IsClosed) return 0; - _stream.Close(); + h.Stream.Close(); - isClosed = true; + h.IsClosed = true; return 0; } - - public void Dispose() - { - GC.SuppressFinalize(this); - } } diff --git a/Capy64/LuaRuntime/Handlers/WriteHandle.cs b/Capy64/LuaRuntime/Handlers/WriteHandle.cs index d33d9ae..38eb398 100644 --- a/Capy64/LuaRuntime/Handlers/WriteHandle.cs +++ b/Capy64/LuaRuntime/Handlers/WriteHandle.cs @@ -10,21 +10,22 @@ namespace Capy64.LuaRuntime.Handlers; public class WriteHandle { - private readonly StreamWriter _stream; - private bool isClosed = false; + public readonly StreamWriter Stream; + public bool IsClosed = false; public WriteHandle(Stream stream) { - _stream = new StreamWriter(stream); + Stream = new StreamWriter(stream); } public WriteHandle(StreamWriter stream) { - _stream = stream; + Stream = stream; } - public void Push(Lua L) + public void Push(Lua L, bool newTable = true) { - L.NewTable(); + if (newTable) + L.NewTable(); L.PushString("write"); L.PushCFunction(L_Write); @@ -33,7 +34,7 @@ public class WriteHandle L.PushString("writeLine"); L.PushCFunction(L_WriteLine); L.SetTable(-3); - + L.PushString("flush"); L.PushCFunction(L_Flush); L.SetTable(-3); @@ -41,61 +42,84 @@ public class WriteHandle L.PushString("close"); L.PushCFunction(L_Close); L.SetTable(-3); + + L.PushString("_handle"); + L.PushObject(this); + L.SetTable(-3); } - private int L_Write(IntPtr state) + private static int L_Write(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + var content = L.CheckString(2); + + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); + + if (h is null || h.IsClosed) L.Error("handle is closed"); - var content = L.CheckString(1); - _stream.Write(content); + h.Stream.Write(content); return 0; } - private int L_WriteLine(IntPtr state) + private static int L_WriteLine(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + var content = L.CheckString(2); + + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); + + if (h is null || h.IsClosed) L.Error("handle is closed"); - var content = L.CheckString(1); - _stream.WriteLine(content); + h.Stream.WriteLine(content); return 0; } - private int L_Flush(IntPtr state) + private static int L_Flush(IntPtr state) { var L = Lua.FromIntPtr(state); - var count = (int)L.OptNumber(1, 1); - L.ArgumentCheck(count < 1, 1, "count must be a positive integer"); + L.CheckType(1, LuaType.Table); + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, false); - if (isClosed) + if (h is null || h.IsClosed) L.Error("handle is closed"); - _stream.Flush(); + h.Stream.Flush(); return 0; } - private int L_Close(IntPtr state) + private static int L_Close(IntPtr state) { var L = Lua.FromIntPtr(state); - if (isClosed) + L.CheckType(1, LuaType.Table); + L.PushString("_handle"); + L.GetTable(1); + var h = L.ToObject(-1, true); + + if (h is null || h.IsClosed) return 0; - _stream.Close(); + h.Stream.Close(); - isClosed = true; + h.IsClosed = true; return 0; } diff --git a/Capy64/LuaRuntime/Libraries/FileSystem.cs b/Capy64/LuaRuntime/Libraries/FileSystem.cs index 84adf3c..ca9f8f0 100644 --- a/Capy64/LuaRuntime/Libraries/FileSystem.cs +++ b/Capy64/LuaRuntime/Libraries/FileSystem.cs @@ -1,5 +1,6 @@ using Capy64.API; using Capy64.LuaRuntime.Extensions; +using Capy64.LuaRuntime.Handlers; using KeraLua; using System; using System.Collections.Generic; @@ -512,225 +513,18 @@ public class FileSystem : IPlugin } } - var handle = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite); - bool isClosed = false; + var fileStream = File.Open(path, fileMode, fileAccess, FileShare.ReadWrite); - - var functions = new Dictionary>(); + // todo: add binary mode if (fileAccess == FileAccess.Read) { - var reader = new StreamReader(handle); - functions["read"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - var count = (int)L.OptNumber(1, 1); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (reader.EndOfStream) - { - L.PushNil(); - return 1; - } - - if (binaryMode) - { - var data = new byte[count]; - handle.Read(data, 0, count); - L.PushBuffer(data); - } - else - { - var data = new char[count]; - reader.ReadBlock(data, 0, count); - L.PushString(new string(data)); - } - - return 1; - }; - - functions["readLine"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - var count = (int)L.OptNumber(1, 1); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (reader.EndOfStream) - { - L.PushNil(); - return 1; - } - - if (binaryMode) - { - var line = reader.ReadLine(); - L.PushBuffer(Encoding.UTF8.GetBytes(line)); - } - else - { - var line = reader.ReadLine(); - L.PushString(line); - } - - return 1; - }; - - functions["readAll"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - var count = (int)L.OptNumber(1, 1); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (reader.EndOfStream) - { - L.PushNil(); - return 1; - } - - if (binaryMode) - { - var content = reader.ReadToEnd(); - L.PushBuffer(Encoding.UTF8.GetBytes(content)); - } - else - { - var content = reader.ReadToEnd(); - L.PushString(content); - } - - return 1; - }; - + var handle = new ReadHandle(fileStream); + handle.Push(L); } - else + else if (fileAccess == FileAccess.Write) { - var writer = new StreamWriter(handle); - functions["write"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - L.ArgumentCheck(L.IsStringOrNumber(1), 1, "string or number value expected"); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (L.IsString(1)) - { - if (binaryMode) - { - handle.Write(L.ToBuffer(1)); - } - else - { - writer.Write(L.ToString(1)); - } - } - else - { - handle.WriteByte((byte)L.ToInteger(1)); - } - - return 0; - }; - - functions["writeLine"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - L.ArgumentCheck(L.IsStringOrNumber(1), 1, "string or number value expected"); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (L.IsString(1)) - { - if (binaryMode) - { - handle.Write(L.ToBuffer(1)); - handle.WriteByte((byte)'\n'); - } - else - { - writer.WriteLine(L.ToString(1)); - } - } - else - { - handle.WriteByte((byte)L.ToInteger(1)); - handle.WriteByte((byte)'\n'); - } - - return 0; - }; - - functions["flush"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - handle.Flush(); - - return 0; - }; - } - - - functions["close"] = (IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - if (isClosed) - { - L.Error("file handle is closed"); - return 0; - } - - if (fileAccess != FileAccess.Read) - { - handle.Flush(); - } - handle.Dispose(); - - isClosed = true; - - return 0; - }; - - - L.NewTable(); - foreach (var pair in functions) - { - L.PushString(pair.Key); - L.PushCFunction(new LuaFunction(pair.Value)); - L.SetTable(-3); + var handle = new WriteHandle(fileStream); + handle.Push(L); } return 1; diff --git a/Capy64/LuaRuntime/Libraries/HTTP.cs b/Capy64/LuaRuntime/Libraries/HTTP.cs index cacb779..d92aac6 100644 --- a/Capy64/LuaRuntime/Libraries/HTTP.cs +++ b/Capy64/LuaRuntime/Libraries/HTTP.cs @@ -160,8 +160,8 @@ public class HTTP : IPlugin else content = await response.Content.ReadAsStringAsync();*/ - var _stream = new StreamReader(await response.Content.ReadAsStreamAsync()); - var isClosed = false; + var stream = await response.Content.ReadAsStreamAsync(); + var handler = new ReadHandle(stream); _game.LuaRuntime.PushEvent("http_response", L => { @@ -195,94 +195,7 @@ public class HTTP : IPlugin L.SetTable(-3); - L.PushString("content"); - L.NewTable(); - - L.PushString("readAll"); - L.PushCFunction((IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - if (isClosed) - L.Error("handle is closed"); - - if (_stream.EndOfStream) - { - L.PushNil(); - return 1; - } - - var content = _stream.ReadToEnd(); - L.PushString(content); - - return 1; - }); - L.SetTable(-3); - - L.PushString("readLine"); - L.PushCFunction((IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - if (isClosed) - L.Error("handle is closed"); - - var line = _stream.ReadLine(); - - if (line is null) - L.PushNil(); - else - L.PushString(line); - - return 1; - }); - L.SetTable(-3); - - L.PushString("read"); - L.PushCFunction((IntPtr state) => - { - var L = Lua.FromIntPtr(state); - var count = (int)L.OptNumber(1, 1); - - L.ArgumentCheck(count >= 1, 1, "count must be a positive integer"); - - if (isClosed) - L.Error("handle is closed"); - - if (_stream.EndOfStream) - { - L.PushNil(); - return 1; - } - - var chunk = new char[count]; - - _stream.Read(chunk, 0, count); - - L.PushString(new string(chunk)); - - return 1; - }); - L.SetTable(-3); - - L.PushString("close"); - L.PushCFunction((IntPtr state) => - { - var L = Lua.FromIntPtr(state); - - if (isClosed) - return 0; - - _stream.Close(); - - isClosed = true; - - return 0; - }); - L.SetTable(-3); - - - L.SetTable(-3); + handler.Push(L, false); return 2; });