Browse Source

improve `strings.index_multi`

There's no point searching for substrings after lowest_index,
so let's not.

This significantly improves performance on long strings.
Adam Zadrożny 8 months ago
parent
commit
5dfc24882f
2 changed files with 21 additions and 1 deletions
  1. 2 1
      core/strings/strings.odin
  2. 19 0
      tests/core/strings/test_core_strings.odin

+ 2 - 1
core/strings/strings.odin

@@ -1872,7 +1872,8 @@ index_multi :: proc(s: string, substrs: []string) -> (idx: int, width: int) {
 	lowest_index := len(s)
 	lowest_index := len(s)
 	found := false
 	found := false
 	for substr in substrs {
 	for substr in substrs {
-		if i := index(s, substr); i >= 0 {
+		haystack := s[:min(len(s), lowest_index + len(substr))]
+		if i := index(haystack, substr); i >= 0 {
 			if i < lowest_index {
 			if i < lowest_index {
 				lowest_index = i
 				lowest_index = i
 				width = len(substr)
 				width = len(substr)

+ 19 - 0
tests/core/strings/test_core_strings.odin

@@ -40,6 +40,25 @@ test_last_index_any_small_string_not_found :: proc(t: ^testing.T) {
 	testing.expect(t, index == -1, "last_index_any should be -1")
 	testing.expect(t, index == -1, "last_index_any should be -1")
 }
 }
 
 
+@test
+test_index_multi_overlapping_substrs :: proc(t: ^testing.T) {
+	index, width := strings.index_multi("some example text", {"ample", "exam"})
+	testing.expect_value(t, index, 5)
+	testing.expect_value(t, width, 4)
+}
+
+@test
+test_index_multi_not_found :: proc(t: ^testing.T) {
+	index, width := strings.index_multi("some example text", {"ey", "tey"})
+	testing.expect_value(t, index, -1)
+}
+
+@test
+test_index_multi_with_empty_string :: proc(t: ^testing.T) {
+	index, width := strings.index_multi("some example text", {"ex", ""})
+	testing.expect_value(t, index, -1)
+}
+
 Cut_Test :: struct {
 Cut_Test :: struct {
 	input:  string,
 	input:  string,
 	offset: int,
 	offset: int,