Capy64/Capy64/Runtime/Objects/Handlers/BinaryReadHandle.cs
Alessandro Proto d1d7bc1463 Completely rewritten the Lua runtime.
Somehow fixed annoying bug in coroutine
2023-01-25 23:06:37 +01:00

371 lines
8.1 KiB
C#

using KeraLua;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace Capy64.Runtime.Objects.Handlers;
public class BinaryReadHandle : IHandle
{
private readonly BinaryReader Stream;
private bool IsClosed = false;
private bool EndOfStream => Stream.BaseStream.Position == Stream.BaseStream.Length;
public BinaryReadHandle(Stream stream)
{
Stream = new BinaryReader(stream, Encoding.ASCII);
}
private static readonly Dictionary<string, LuaFunction> functions = new()
{
["nextByte"] = L_NextByte,
["nextShort"] = L_NextShort,
["nextInt"] = L_NextInt,
["nextLong"] = L_NextLong,
["nextSByte"] = L_NextSByte,
["nextUShort"] = L_NextUShort,
["nextUInt"] = L_NextUInt,
["nextULong"] = L_NextULong,
["nextHalf"] = L_NextHalf,
["nextFloat"] = L_NextFloat,
["nextDouble"] = L_NextDouble,
["nextChar"] = L_NextChar,
["nextString"] = L_NextString,
["nextBoolean"] = L_NextBoolean,
["close"] = L_Close,
};
public void Push(Lua L, bool newTable = true)
{
if (newTable)
L.NewTable();
// metatable
L.NewTable();
L.PushString("__close");
L.PushCFunction(L_Close);
L.SetTable(-3);
L.PushString("__gc");
L.PushCFunction(L_Close);
L.SetTable(-3);
L.SetMetaTable(-2);
foreach (var pair in functions)
{
L.PushString(pair.Key);
L.PushCFunction(pair.Value);
L.SetTable(-3);
}
L.PushString("_handle");
L.PushObject(this);
L.SetTable(-3);
}
private static BinaryReadHandle GetHandle(Lua L, bool gc = true)
{
L.CheckType(1, LuaType.Table);
L.PushString("_handle");
L.GetTable(1);
return L.ToObject<BinaryReadHandle>(-1, gc);
}
private static int L_NextByte(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var count = (int)L.OptNumber(2, 1);
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
if (count == 1)
{
var b = h.Stream.ReadByte();
L.PushInteger(b);
return 1;
}
else
{
var bs = h.Stream.ReadBytes(count);
foreach (var b in bs)
{
L.PushInteger(b);
}
return bs.Length;
}
}
private static int L_NextShort(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadInt16();
L.PushInteger(b);
return 1;
}
private static int L_NextInt(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadInt32();
L.PushInteger(b);
return 1;
}
private static int L_NextLong(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadInt64();
L.PushInteger(b);
return 1;
}
private static int L_NextSByte(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadSByte();
L.PushInteger(b);
return 1;
}
private static int L_NextUShort(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadUInt16();
L.PushInteger(b);
return 1;
}
private static int L_NextUInt(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadUInt32();
L.PushInteger(b);
return 1;
}
private static int L_NextULong(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadUInt64();
L.PushInteger((long)b);
return 1;
}
private static int L_NextHalf(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadHalf();
L.PushNumber((double)b);
return 1;
}
private static int L_NextFloat(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadSingle();
L.PushNumber((double)b);
return 1;
}
private static int L_NextDouble(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadDouble();
L.PushNumber((double)b);
return 1;
}
private static int L_NextChar(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var count = (int)L.OptNumber(2, 1);
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
if (count == 1)
{
var b = h.Stream.ReadChar();
L.PushString(b.ToString());
return 1;
}
else
{
var bs = h.Stream.ReadChars(count);
foreach (var b in bs)
{
L.PushString(b.ToString());
}
return bs.Length;
}
}
private static int L_NextString(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var count = (int)L.OptNumber(2, 1);
L.ArgumentCheck(count >= 1, 2, "count must be a positive integer");
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
if (count == 1)
{
var b = h.Stream.ReadChar();
L.PushString(b.ToString());
return 1;
}
else
{
var bs = h.Stream.ReadBytes(count);
L.PushBuffer(bs);
return 1;
}
}
private static int L_NextBoolean(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, false);
if (h is null || h.IsClosed)
L.Error("handle is closed");
if (h.EndOfStream)
return 0;
var b = h.Stream.ReadBoolean();
L.PushBoolean(b);
return 1;
}
private static int L_Close(IntPtr state)
{
var L = Lua.FromIntPtr(state);
var h = GetHandle(L, true);
if (h is null || h.IsClosed)
return 0;
h.Stream.Close();
h.IsClosed = true;
return 0;
}
}