diff --git a/Content.Tests/DMProject/Tests/Text/findlasttext.dm b/Content.Tests/DMProject/Tests/Text/findlasttext.dm new file mode 100644 index 0000000000..c8d6eb403b --- /dev/null +++ b/Content.Tests/DMProject/Tests/Text/findlasttext.dm @@ -0,0 +1,20 @@ +/proc/RunTest() + ASSERT(findlasttext("abcdefg", "f", 0, -1) == 0) + ASSERT(findlasttext("abcdefg", "f", 0, -2) == 6) + ASSERT(findlasttext("abcdefg", "f", 6) == 6) + ASSERT(findlasttext("abcdefg", "f", 5) == 0) + ASSERT(findlasttext("abcdefg", "bc", 2) == 2) + ASSERT(findlasttext("abcdefg", "ab", 10) == 1) + ASSERT(findlasttext("abcdefg", "f", 5) == 0) + ASSERT(findlasttext("Banana", "na", -3) == 3) + ASSERT(findlasttext("Banana", "na", -5) == 0) + ASSERT(findlasttext("Banana", "na", 0) == 5) + ASSERT(findlasttext("Banana", "na", 3) == 3) + ASSERT(findlasttext("Banana", "na", 2) == 0) + ASSERT(findlasttext("Banana", "na", 5) == 5) + ASSERT(findlasttext("Banana", "na", 50) == 5) + ASSERT(findlasttext("Banana", "na", -50) == 0) + ASSERT(findlasttext("abcdefg", "f", 6, -50) == 6) + ASSERT(findlasttext("abcdefg", "f", 6, 50) == 0) + + \ No newline at end of file diff --git a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs index b1d4a4caa6..c32d09ac95 100644 --- a/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs +++ b/OpenDreamRuntime/Procs/Native/DreamProcNativeRoot.cs @@ -685,8 +685,8 @@ public static DreamValue NativeProc_findtextEx(NativeProc.Bundle bundle, DreamOb [DreamProc("findlasttext")] [DreamProcParameter("Haystack", Type = DreamValueTypeFlag.String)] [DreamProcParameter("Needle", Type = DreamValueTypeFlag.String)] - [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] - [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] + [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] + [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] public static DreamValue NativeProc_findlasttext(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { // TODO This is for handling nulls, check if it works right for other bad types int failCount = 0; @@ -700,26 +700,33 @@ public static DreamValue NativeProc_findlasttext(NativeProc.Bundle bundle, Dream return new DreamValue(failCount == 2 ? 1 : 0); } - int start = bundle.GetArgument(2, "Start").MustGetValueAsInteger(); //1-indexed - int end = bundle.GetArgument(3, "End").MustGetValueAsInteger(); //1-indexed + int start = bundle.GetArgument(2, "Start").MustGetValueAsInteger(); //chars from the end + int end = bundle.GetArgument(3, "End").MustGetValueAsInteger(); //1-indexed from the beginning + int actualstart; + int actualcount; - if (end == 0) { - end = text.Length + 1; - } + if(start > 0) + actualstart = start-1; + else + actualstart = (text.Length-1) + start; + actualstart += needle.Length-1; + actualstart = Math.Max(Math.Min(text.Length, actualstart),0); - int needleIndex = text.LastIndexOf(needle, end - 1, end - start, StringComparison.OrdinalIgnoreCase); - if (needleIndex != -1) { - return new DreamValue(needleIndex + 1); //1-indexed - } else { - return new DreamValue(0); - } + if(end > 0) + actualcount = actualstart - (end-1); + else + actualcount = actualstart - ((text.Length-1) + (end)); + actualcount += needle.Length-1; + actualcount = Math.Max(Math.Min(actualstart+1, actualcount),0); + int needleIndex = text.LastIndexOf(needle, actualstart, actualcount, StringComparison.OrdinalIgnoreCase); + return new DreamValue(needleIndex + 1); //1-indexed, or 0 if not found (LastIndexOf returns -1 if not found) } [DreamProc("findlasttextEx")] [DreamProcParameter("Haystack", Type = DreamValueTypeFlag.String)] [DreamProcParameter("Needle", Type = DreamValueTypeFlag.String)] - [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] - [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] + [DreamProcParameter("Start", Type = DreamValueTypeFlag.Float, DefaultValue = 0)] + [DreamProcParameter("End", Type = DreamValueTypeFlag.Float, DefaultValue = 1)] public static DreamValue NativeProc_findlasttextEx(NativeProc.Bundle bundle, DreamObject? src, DreamObject? usr) { // TODO This is for handling nulls, check if it works right for other bad types int failCount = 0; @@ -735,17 +742,24 @@ public static DreamValue NativeProc_findlasttextEx(NativeProc.Bundle bundle, Dre int start = bundle.GetArgument(2, "Start").GetValueAsInteger(); //1-indexed int end = bundle.GetArgument(3, "End").GetValueAsInteger(); //1-indexed - - if (end == 0) { - end = text.Length + 1; - } - - int needleIndex = text.LastIndexOf(needle, end - 1, end - start, StringComparison.InvariantCulture); - if (needleIndex != -1) { - return new DreamValue(needleIndex + 1); //1-indexed - } else { - return new DreamValue(0); - } + int actualstart; + int actualcount; + + if(start > 0) + actualstart = start-1; + else + actualstart = (text.Length-1) + start; + actualstart += needle.Length-1; + actualstart = Math.Max(Math.Min(text.Length, actualstart),0); + + if(end > 0) + actualcount = actualstart - (end-1); + else + actualcount = actualstart - ((text.Length-1) + (end)); + actualcount += needle.Length-1; + actualcount = Math.Max(Math.Min(actualstart+1, actualcount),0); + int needleIndex = text.LastIndexOf(needle, actualstart, actualcount, StringComparison.InvariantCulture); + return new DreamValue(needleIndex + 1); //1-indexed, or 0 if not found (LastIndexOf returns -1 if not found) } [DreamProc("flick")]