FindFunction.cs 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. using System.Text.RegularExpressions;
  2. using Lua.Internal;
  3. namespace Lua.Standard.Text;
  4. public sealed class FindFunction : LuaFunction
  5. {
  6. public override string Name => "find";
  7. public static readonly FindFunction Instance = new();
  8. protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
  9. {
  10. var s = context.GetArgument<string>(0);
  11. var pattern = context.GetArgument<string>(1);
  12. var init = context.HasArgument(2)
  13. ? context.GetArgument<double>(2)
  14. : 1;
  15. var plain = context.HasArgument(3)
  16. ? context.GetArgument<bool>(3)
  17. : false;
  18. LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, this, 3, init);
  19. // init can be negative value
  20. if (init < 0)
  21. {
  22. init = s.Length + init + 1;
  23. }
  24. var source = s.AsSpan()[(int)(init - 1)..];
  25. if (plain)
  26. {
  27. var start = source.IndexOf(pattern);
  28. if (start == -1)
  29. {
  30. buffer.Span[0] = LuaValue.Nil;
  31. return new(1);
  32. }
  33. // 1-based
  34. buffer.Span[0] = start + 1;
  35. buffer.Span[1] = start + pattern.Length;
  36. return new(2);
  37. }
  38. else
  39. {
  40. var regex = StringHelper.ToRegex(pattern);
  41. var match = regex.Match(source.ToString());
  42. if (match.Success)
  43. {
  44. // 1-based
  45. buffer.Span[0] = match.Index + 1;
  46. buffer.Span[1] = match.Index + match.Length;
  47. return new(2);
  48. }
  49. else
  50. {
  51. buffer.Span[0] = LuaValue.Nil;
  52. return new(1);
  53. }
  54. }
  55. }
  56. }