Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 5 additions & 18 deletions src/Lua/IO/MemoryStreams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,18 +112,6 @@ public virtual ValueTask<string> ReadAllAsync(CancellationToken cancellationToke
}

var remaining = contents[Position..].Span;
var startPos = Position;

// Use the shared utility to scan for a number
var numberLength = NumberReaderHelper.ScanNumberLength(remaining, true);

if (numberLength == 0)
{
Position = contents.Length;
return new((double?)null);
}

// Find where the actual number starts (after whitespace)
var whitespaceLength = 0;
while (
whitespaceLength < remaining.Length && char.IsWhiteSpace(remaining[whitespaceLength])
Expand All @@ -132,12 +120,10 @@ public virtual ValueTask<string> ReadAllAsync(CancellationToken cancellationToke
whitespaceLength++;
}

var numberSpan = remaining.Slice(whitespaceLength, numberLength);
Position = startPos + whitespaceLength + numberLength;

// Parse using shared utility
var result = NumberReaderHelper.ParseNumber(numberSpan);
return new(result);
remaining = remaining[whitespaceLength..];
var numberLength = NumberReaderHelper.ScanNumberLength(remaining);
Position += whitespaceLength + numberLength;
return new(NumberReaderHelper.ParseNumber(remaining[..numberLength]));
}

public ValueTask WriteAsync(ReadOnlyMemory<char> content, CancellationToken cancellationToken)
Expand Down Expand Up @@ -200,6 +186,7 @@ public override ValueTask<string> ReadAllAsync(CancellationToken cancellationTok
cancellationToken.ThrowIfCancellationRequested();
if (Position == 0)
{
Position = content.Length;
return new(content);
}

Expand Down
15 changes: 2 additions & 13 deletions src/Lua/IO/NumberReaderHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,16 @@ internal static class NumberReaderHelper
/// Returns the length of the number portion, or 0 if no valid number is found.
/// </summary>
/// <param name="span">The span to scan</param>
/// <param name="skipWhitespace">Whether to skip leading whitespace</param>
/// <returns>The length of the valid number portion</returns>
public static int ScanNumberLength(ReadOnlySpan<char> span, bool skipWhitespace = true)
public static int ScanNumberLength(ReadOnlySpan<char> span)
{
var position = 0;

// Skip leading whitespace
if (skipWhitespace)
{
while (position < span.Length && char.IsWhiteSpace(span[position]))
{
position++;
}
}

if (position >= span.Length)
{
return 0;
}

var numberStart = position;
var hasStarted = false;
var isHex = false;
var hasDecimal = false;
Expand Down Expand Up @@ -129,7 +118,7 @@ public static int ScanNumberLength(ReadOnlySpan<char> span, bool skipWhitespace
}

// Return the length of the number portion
return position - numberStart;
return position;
}

public static bool TryParseToDouble(ReadOnlySpan<char> span, out double result)
Expand Down
22 changes: 21 additions & 1 deletion src/Lua/LuaFunctionExecutionContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ public T GetArgument<T>(int index)
return ReadArgument<T>(index, in Arguments[index]);
}

// Lua library strings accept numbers; typed C# arguments remain strict.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal string GetStringArgument(int index)
{
var argument = GetArgument(index);
if (argument.TryReadString(out var text))
return text;
if (argument.Type == LuaValueType.Number)
{
text = argument.ToLuaString(State.Platform.NumberFormat);
State.Stack.Get(FrameBase + index) = text;
return text;
}
ThrowArgumentError<string>(index, argument);
return null!;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal T GetArgumentOrDefault<T>(int index, T defaultValue = default!)
{
Expand Down Expand Up @@ -110,7 +127,10 @@ T ReadArgument<T>(int index, in LuaValue arg)
void ThrowArgumentError<T>(int index, in LuaValue arg)
{
var t = typeof(T);
if ((t == typeof(int) || t == typeof(long)) && arg.TryReadNumber(out _))
if (
(t == typeof(int) || t == typeof(long) || t == typeof(uint) || t == typeof(ulong))
&& arg.TryReadNumber(out _)
)
{
LuaRuntimeException.BadArgumentNumberIsNotInteger(State, index + 1);
}
Expand Down
19 changes: 12 additions & 7 deletions src/Lua/LuaValue.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public bool TryRead<T>(out T result)
}
else if (t == typeof(int))
{
if (!MathEx.IsInteger(value))
if (!MathEx.IsInteger(value) || value < int.MinValue || value > int.MaxValue)
{
break;
}
Expand All @@ -75,7 +75,12 @@ public bool TryRead<T>(out T result)
}
else if (t == typeof(long))
{
if (!MathEx.IsInteger(value))
// The upper bound is exclusive: long.MaxValue rounds to 2^63 as a double.
if (
!MathEx.IsInteger(value)
|| value < long.MinValue
|| value >= 9223372036854775808d
)
{
break;
}
Expand All @@ -86,23 +91,23 @@ public bool TryRead<T>(out T result)
}
else if (t == typeof(uint))
{
if (!MathEx.IsInteger(value))
if (!MathEx.IsInteger(value) || value < 0 || value > uint.MaxValue)
{
break;
}

var v = checked((uint)value);
var v = (uint)value;
result = Unsafe.As<uint, T>(ref v);
return true;
}
else if (t == typeof(ulong))
{
if (!MathEx.IsInteger(value))
if (!MathEx.IsInteger(value) || value < 0 || value >= 18446744073709551616d)
{
break;
}

var v = checked((ulong)value);
var v = (ulong)value;
result = Unsafe.As<ulong, T>(ref v);
return true;
}
Expand All @@ -124,7 +129,7 @@ public bool TryRead<T>(out T result)
}
else if (t == typeof(object))
{
result = (T)(object)value;
result = (T)(object)(value != 0);
return true;
}
else
Expand Down
12 changes: 6 additions & 6 deletions src/Lua/Standard/BasicLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ CancellationToken cancellationToken
{
if (context.HasArgument(0))
{
var option = context.GetArgument<string>(0);
var option = context.GetStringArgument(0);
if (!KnownCollectGarbageOptions.Contains(option))
{
throw new LuaRuntimeException(
Expand All @@ -129,7 +129,7 @@ public async ValueTask<int> DoFile(
CancellationToken cancellationToken
)
{
var arg0 = context.GetArgument<string>(0);
var arg0 = context.GetStringArgument(0);
context.State.Stack.PopUntil(context.ReturnFrameBase);
var closure = await context.State.LoadFileAsync(
context.State.Platform.DecodeText(arg0),
Expand Down Expand Up @@ -217,8 +217,8 @@ public async ValueTask<int> LoadFile(
CancellationToken cancellationToken
)
{
var arg0 = context.GetArgument<string>(0);
var mode = context.HasArgument(1) ? context.GetArgument<string>(1) : "bt";
var arg0 = context.GetStringArgument(0);
var mode = context.HasArgument(1) ? context.GetStringArgument(1) : "bt";
var hasEnvironment = context.ArgumentCount > 2;
var environment = hasEnvironment ? context.GetArgument(2) : LuaValue.Nil;

Expand Down Expand Up @@ -251,9 +251,9 @@ CancellationToken cancellationToken
{
var arg0 = context.GetArgument(0);

var name = context.HasArgument(1) ? context.GetArgument<string>(1) : null;
var name = context.HasArgument(1) ? context.GetStringArgument(1) : null;

var mode = context.HasArgument(2) ? context.GetArgument<string>(2) : "bt";
var mode = context.HasArgument(2) ? context.GetStringArgument(2) : "bt";

var hasEnvironment = context.ArgumentCount > 3;
var environment = hasEnvironment ? context.GetArgument(3) : LuaValue.Nil;
Expand Down
8 changes: 4 additions & 4 deletions src/Lua/Standard/FileHandle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -244,8 +244,8 @@ static async (context, cancellationToken) =>
(context, cancellationToken) =>
{
var file = context.GetArgument<FileHandle>(0);
var whence = context.HasArgument(1) ? context.GetArgument<string>(1) : "cur";
var offset = context.HasArgument(2) ? context.GetArgument<int>(2) : 0;
var whence = context.HasArgument(1) ? context.GetStringArgument(1) : "cur";
var offset = context.HasArgument(2) ? context.GetArgument<long>(2) : 0;

if (whence is not ("set" or "cur" or "end"))
{
Expand All @@ -257,7 +257,7 @@ static async (context, cancellationToken) =>

try
{
return new(context.Return(file.Seek(whence, (long)offset)));
return new(context.Return(file.Seek(whence, offset)));
}
catch (IOException ex)
{
Expand All @@ -277,7 +277,7 @@ static async (context, cancellationToken) =>
(context, cancellationToken) =>
{
var file = context.GetArgument<FileHandle>(0);
var mode = context.GetArgument<string>(1);
var mode = context.GetStringArgument(1);
var size = context.HasArgument(2) ? context.GetArgument<int>(2) : -1;

file.SetVBuf(mode, size);
Expand Down
6 changes: 3 additions & 3 deletions src/Lua/Standard/IOLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ static async (context, cancellationToken) =>
}
else
{
var fileName = context.GetArgument<string>(0);
var fileName = context.GetStringArgument(0);
LuaValue[] formats =
context.ArgumentCount > 1
? context.Arguments[1..context.ArgumentCount].ToArray()
Expand Down Expand Up @@ -207,8 +207,8 @@ public async ValueTask<int> Open(
CancellationToken cancellationToken
)
{
var fileName = context.GetArgument<string>(0);
var mode = context.HasArgument(1) ? context.GetArgument<string>(1) : "r";
var fileName = context.GetStringArgument(0);
var mode = context.HasArgument(1) ? context.GetStringArgument(1) : "r";
context.Return();
try
{
Expand Down
14 changes: 7 additions & 7 deletions src/Lua/Standard/ModuleLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public async ValueTask<int> Require(
CancellationToken cancellationToken
)
{
var arg0 = context.GetArgument<string>(0);
var arg0 = context.GetStringArgument(0);
var loaded = context.GlobalState.LoadedModules;

if (!loaded.TryGetValue(arg0, out var loadedTable))
Expand Down Expand Up @@ -74,10 +74,10 @@ public ValueTask<int> SearchPath(
CancellationToken cancellationToken
)
{
var name = context.GetArgument<string>(0);
var path = context.GetArgument<string>(1);
var separator = context.GetArgument<string>(2);
var dirSeparator = context.GetArgument<string>(3);
var name = context.GetStringArgument(0);
var path = context.GetStringArgument(1);
var separator = context.GetStringArgument(2);
var dirSeparator = context.GetStringArgument(3);
var fileName = SearchPath(context.State, name, path, separator, dirSeparator);
return new(context.Return(fileName ?? LuaValue.Nil));
}
Expand Down Expand Up @@ -170,7 +170,7 @@ public ValueTask<int> SearcherPreload(
CancellationToken cancellationToken
)
{
var name = context.GetArgument<string>(0);
var name = context.GetStringArgument(0);
var preload = context.GlobalState.PreloadModules[name];
if (preload == LuaValue.Nil)
{
Expand All @@ -185,7 +185,7 @@ public async ValueTask<int> SearcherLua(
CancellationToken cancellationToken
)
{
var name = context.GetArgument<string>(0);
var name = context.GetStringArgument(0);
var fileName = await FindFile(
context.State,
name,
Expand Down
2 changes: 1 addition & 1 deletion src/Lua/Standard/OpenLibsExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public static void OpenStringLibrary(this LuaState state)
"index",
(context, cancellationToken) =>
{
context.GetArgument<string>(0);
context.GetStringArgument(0);
var key = context.GetArgument(1);
return new(context.Return(@string[key]));
}
Expand Down
14 changes: 6 additions & 8 deletions src/Lua/Standard/OperatingSystemLibrary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ public ValueTask<int> Date(
CancellationToken cancellationToken
)
{
var format = context.HasArgument(0)
? context.GetArgument<string>(0).AsSpan()
: "%c".AsSpan();
var format = context.HasArgument(0) ? context.GetStringArgument(0).AsSpan() : "%c".AsSpan();
if (format.IsEmpty)
return new(context.Return(""));

Expand Down Expand Up @@ -155,7 +153,7 @@ public ValueTask<int> GetEnv(
CancellationToken cancellationToken
)
{
var variable = context.GetArgument<string>(0);
var variable = context.GetStringArgument(0);
var platform = context.State.Platform;
var value = platform.OsEnvironment.GetEnvironmentVariable(platform.DecodeText(variable));
return new(context.Return(value is null ? LuaValue.Nil : platform.EncodeText(value)));
Expand All @@ -166,7 +164,7 @@ public async ValueTask<int> Remove(
CancellationToken cancellationToken
)
{
var fileName = context.GetArgument<string>(0);
var fileName = context.GetStringArgument(0);
try
{
await context.GlobalState.Platform.FileSystem.Remove(
Expand All @@ -190,8 +188,8 @@ public async ValueTask<int> Rename(
CancellationToken cancellationToken
)
{
var oldName = context.GetArgument<string>(0);
var newName = context.GetArgument<string>(1);
var oldName = context.GetStringArgument(0);
var newName = context.GetStringArgument(1);
try
{
await context.GlobalState.Platform.FileSystem.Rename(
Expand All @@ -218,7 +216,7 @@ CancellationToken cancellationToken
{
// os.setlocale is not supported besides the standard "C" POSIX locale
// Any locale besides "C" will return nil
var locale = context.GetArgument<string>(0);
var locale = context.GetStringArgument(0);
if (locale == "C")
{
return new(context.Return(locale));
Expand Down
Loading
Loading