Browse Source

Add: string.find

AnnulusGames 1 year ago
parent
commit
e2dd96e114
2 changed files with 67 additions and 0 deletions
  1. 1 0
      src/Lua/Standard/OpenLibExtensions.cs
  2. 66 0
      src/Lua/Standard/Text/FindFunction.cs

+ 1 - 0
src/Lua/Standard/OpenLibExtensions.cs

@@ -80,6 +80,7 @@ public static class OpenLibExtensions
         ByteFunction.Instance,
         ByteFunction.Instance,
         CharFunction.Instance,
         CharFunction.Instance,
         DumpFunction.Instance,
         DumpFunction.Instance,
+        FindFunction.Instance,
         FormatFunction.Instance,
         FormatFunction.Instance,
         LenFunction.Instance,
         LenFunction.Instance,
         LowerFunction.Instance,
         LowerFunction.Instance,

+ 66 - 0
src/Lua/Standard/Text/FindFunction.cs

@@ -0,0 +1,66 @@
+
+using System.Text.RegularExpressions;
+using Lua.Internal;
+
+namespace Lua.Standard.Text;
+
+public sealed class FindFunction : LuaFunction
+{
+    public override string Name => "find";
+    public static readonly FindFunction Instance = new();
+
+    protected override ValueTask<int> InvokeAsyncCore(LuaFunctionExecutionContext context, Memory<LuaValue> buffer, CancellationToken cancellationToken)
+    {
+        var s = context.GetArgument<string>(0);
+        var pattern = context.GetArgument<string>(1);
+        var init = context.HasArgument(2)
+            ? context.GetArgument<double>(2)
+            : 1;
+        var plain = context.HasArgument(3)
+            ? context.GetArgument<bool>(3)
+            : false;
+
+        LuaRuntimeException.ThrowBadArgumentIfNumberIsNotInteger(context.State, this, 3, init);
+
+        // init can be negative value
+        if (init < 0)
+        {
+            init = s.Length + init + 1;
+        }
+
+        var source = s.AsSpan()[(int)(init - 1)..];
+        
+        if (plain)
+        {
+            var start = source.IndexOf(pattern);
+            if (start == -1)
+            {
+                buffer.Span[0] = LuaValue.Nil;
+                return new(1);
+            }
+
+            // 1-based
+            buffer.Span[0] = start + 1;
+            buffer.Span[1] = start + pattern.Length;
+            return new(2);
+        }
+        else
+        {
+            var regex = StringHelper.ToRegex(pattern);
+            var match = regex.Match(s);
+
+            if (match.Success)
+            {
+                // 1-based
+                buffer.Span[0] = match.Index + 1;
+                buffer.Span[1] = match.Index + match.Length;
+                return new(2);
+            }
+            else
+            {
+                buffer.Span[0] = LuaValue.Nil;
+                return new(1);
+            }
+        }
+    }
+}