ToNumberFunction.cs 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. using System.Globalization;
  2. namespace Lua.Standard.Basic;
  3. public sealed class ToNumberFunction : LuaFunction
  4. {
  5. public override string Name => "tonumber";
  6. public static readonly ToNumberFunction Instance = new();
  7. protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  8. {
  9. var arg0 = context.ReadArgument(0);
  10. var arg1 = context.ArgumentCount >= 2
  11. ? (int)context.ReadArgument<double>(1)
  12. : 10;
  13. if (arg1 < 2 || arg1 > 36)
  14. {
  15. throw new LuaRuntimeException(context.State.GetTracebacks(), "bad argument #2 to 'tonumber' (base out of range)");
  16. }
  17. if (arg0.Type is LuaValueType.Number)
  18. {
  19. buffer.Span[0] = arg0;
  20. }
  21. else if (arg0.TryRead<string>(out var str))
  22. {
  23. if ((arg1 == 10 || arg1 == 16) && str.Length >= 3 && str[0] == '0' && str[1] == 'x')
  24. {
  25. if (int.TryParse(str.AsSpan(2), NumberStyles.HexNumber, CultureInfo.InvariantCulture, out var result))
  26. {
  27. buffer.Span[0] = result;
  28. }
  29. else
  30. {
  31. buffer.Span[0] = LuaValue.Nil;
  32. }
  33. }
  34. else if (arg0 == 10)
  35. {
  36. if (double.TryParse(str, NumberStyles.Float, CultureInfo.InvariantCulture, out double result))
  37. {
  38. buffer.Span[0] = result;
  39. }
  40. else
  41. {
  42. buffer.Span[0] = LuaValue.Nil;
  43. }
  44. }
  45. else
  46. {
  47. try
  48. {
  49. buffer.Span[0] = Convert.ToInt64(str, arg1);
  50. }
  51. catch (FormatException)
  52. {
  53. buffer.Span[0] = LuaValue.Nil;
  54. }
  55. }
  56. }
  57. else
  58. {
  59. buffer.Span[0] = LuaValue.Nil;
  60. }
  61. return new(1);
  62. }
  63. }