| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 |
- using System.Text;
- using Lua.Internal;
- namespace Lua.Standard.Internal;
- internal static class IOHelper
- {
- public static int Open(LuaState state, string fileName, string mode, Memory<LuaValue> buffer, bool throwError)
- {
- var fileMode = mode switch
- {
- "r" or "rb" or "r+" or "r+b" => FileMode.Open,
- "w" or "wb" or "w+" or "w+b" => FileMode.Create,
- "a" or "ab" or "a+" or "a+b" => FileMode.Append,
- _ => throw new LuaRuntimeException(state.GetTraceback(), "bad argument #2 to 'open' (invalid mode)"),
- };
- var fileAccess = mode switch
- {
- "r" or "rb" => FileAccess.Read,
- "w" or "wb" or "a" or "ab" => FileAccess.Write,
- _ => FileAccess.ReadWrite,
- };
- try
- {
- var stream = File.Open(fileName, fileMode, fileAccess);
- buffer.Span[0] = new LuaValue(new FileHandle(stream));
- return 1;
- }
- catch (IOException ex)
- {
- if (throwError)
- {
- throw;
- }
- buffer.Span[0] = LuaValue.Nil;
- buffer.Span[1] = ex.Message;
- buffer.Span[2] = ex.HResult;
- return 3;
- }
- }
- // TODO: optimize (use IBuffertWrite<byte>, async)
- public static int Write(FileHandle file, string name, LuaFunctionExecutionContext context, Memory<LuaValue> buffer)
- {
- try
- {
- for (int i = 1; i < context.ArgumentCount; i++)
- {
- var arg = context.Arguments[i];
- if (arg.TryRead<string>(out var str))
- {
- file.Write(str);
- }
- else if (arg.TryRead<double>(out var d))
- {
- using var fileBuffer = new PooledArray<char>(64);
- var span = fileBuffer.AsSpan();
- d.TryFormat(span, out var charsWritten);
- file.Write(span[..charsWritten]);
- }
- else
- {
- LuaRuntimeException.BadArgument(context.State.GetTraceback(), i + 1, name);
- }
- }
- }
- catch (IOException ex)
- {
- buffer.Span[0] = LuaValue.Nil;
- buffer.Span[1] = ex.Message;
- buffer.Span[2] = ex.HResult;
- return 3;
- }
- buffer.Span[0] = new(file);
- return 1;
- }
- static readonly LuaValue[] defaultReadFormat = ["*l"];
- public static int Read(LuaState state, FileHandle file, string name, int startArgumentIndex, ReadOnlySpan<LuaValue> formats, Memory<LuaValue> buffer, bool throwError)
- {
- if (formats.Length == 0)
- {
- formats = defaultReadFormat;
- }
- try
- {
- for (int i = 0; i < formats.Length; i++)
- {
- var format = formats[i];
- if (format.TryRead<string>(out var str))
- {
- switch (str)
- {
- case "*n":
- case "*number":
- // TODO: support number format
- throw new NotImplementedException();
- case "*a":
- case "*all":
- buffer.Span[i] = file.ReadToEnd();
- break;
- case "*l":
- case "*line":
- buffer.Span[i] = file.ReadLine() ?? LuaValue.Nil;
- break;
- case "L":
- case "*L":
- var text = file.ReadLine();
- buffer.Span[i] = text == null ? LuaValue.Nil : text + Environment.NewLine;
- break;
- }
- }
- else if (format.TryRead<int>(out var count))
- {
- using var byteBuffer = new PooledArray<byte>(count);
- for (int j = 0; j < count; j++)
- {
- var b = file.ReadByte();
- if (b == -1)
- {
- buffer.Span[0] = LuaValue.Nil;
- return 1;
- }
- byteBuffer[j] = (byte)b;
- }
- buffer.Span[i] = Encoding.UTF8.GetString(byteBuffer.AsSpan());
- }
- else
- {
- LuaRuntimeException.BadArgument(state.GetTraceback(), i + 1, name);
- }
- }
- return formats.Length;
- }
- catch (IOException ex)
- {
- if (throwError)
- {
- throw;
- }
- buffer.Span[0] = LuaValue.Nil;
- buffer.Span[1] = ex.Message;
- buffer.Span[2] = ex.HResult;
- return 3;
- }
- }
- }
|