aboutsummaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorskytrias <skytrias@protonmail.com>2022-12-01 21:54:30 +0100
committerskytrias <skytrias@protonmail.com>2022-12-18 23:11:23 +0100
commit967afd8bbb3be3bed7caab2fd7bab09d8dfaf0cd (patch)
tree6c26fc9fdb3769f1646db622c23cb43ff9e3cf59 /core
parent0ae1812f90eac575b07fc3cfdfdcaf9c48119cd6 (diff)
try helper procedures / structs
Diffstat (limited to 'core')
-rw-r--r--core/text/lua/strlib.odin134
1 files changed, 133 insertions, 1 deletions
diff --git a/core/text/lua/strlib.odin b/core/text/lua/strlib.odin
index 05495afe4..52b669f6e 100644
--- a/core/text/lua/strlib.odin
+++ b/core/text/lua/strlib.odin
@@ -1,5 +1,6 @@
package strlib
+import "core:runtime"
import "core:unicode"
import "core:unicode/utf8"
import "core:strings"
@@ -898,4 +899,135 @@ pattern_case_insensitive_allocator :: proc(
return pattern_case_insensitive_builder(&builder, pattern)
}
-pattern_case_insensitive :: proc { pattern_case_insensitive_builder, pattern_case_insensitive_allocator } \ No newline at end of file
+pattern_case_insensitive :: proc { pattern_case_insensitive_builder, pattern_case_insensitive_allocator }
+
+find_test :: proc(
+ haystack: string,
+ pattern: string,
+ offset: int = 0,
+ captures: ..^Match,
+) -> (start, end: int, ok: bool) #no_bounds_check {
+ matches: [MAXCAPTURES]Match
+ length, err := find_aux(haystack, pattern, offset, true, &matches)
+
+ ok = length > 0 && err == .OK
+ match := matches[0]
+ start = match.byte_start
+ end = match.byte_end
+
+ for arg, i in captures {
+ arg^ = matches[i + 1]
+ }
+
+ return
+}
+
+match_test :: proc(
+ haystack: string,
+ pattern: string,
+ offset: int = 0,
+ captures: ..^Match,
+) -> (word: string, ok: bool) #no_bounds_check {
+ matches: [MAXCAPTURES]Match
+ length, err := find_aux(haystack, pattern, offset, true, &matches)
+
+ ok = length > 0 && err == .OK
+ match := matches[0]
+ word = haystack[match.byte_start:match.byte_end]
+
+ for arg, i in captures {
+ arg^ = matches[i + 1]
+ }
+
+ return
+}
+
+Matcher :: struct {
+ haystack: string,
+ pattern: string,
+ captures: [MAXCAPTURES]Match,
+ captures_length: int,
+ offset: int,
+ err: Error,
+
+ // changing content for iterators
+ iter: string,
+}
+
+// matcher
+matcher_init :: proc(haystack, pattern: string, offset: int = 0) -> (res: Matcher) {
+ res.haystack = haystack
+ res.pattern = pattern
+ res.offset = offset
+ res.iter = haystack
+ return
+}
+
+matcher_find :: proc(matcher: ^Matcher) -> (start, end: int, ok: bool) #no_bounds_check {
+ matcher.captures_length, matcher.err = find_aux(
+ matcher.haystack,
+ matcher.pattern,
+ matcher.offset,
+ true,
+ &matcher.captures,
+ )
+ ok = matcher.captures_length > 0 && matcher.err == .OK
+ match := matcher.captures[0]
+ start = match.byte_start
+ end = match.byte_end
+ return
+}
+
+matcher_match :: proc(matcher: ^Matcher) -> (word: string, ok: bool) #no_bounds_check {
+ matcher.captures_length, matcher.err = find_aux(
+ matcher.haystack,
+ matcher.pattern,
+ matcher.offset,
+ false,
+ &matcher.captures,
+ )
+ ok = matcher.captures_length > 0 && matcher.err == .OK
+ match := matcher.captures[0]
+ word = matcher.haystack[match.byte_start:match.byte_end]
+ return
+}
+
+// get the capture at the correct spot
+matcher_capture :: proc(matcher: ^Matcher, index: int, loc := #caller_location) -> string #no_bounds_check {
+ runtime.bounds_check_error_loc(loc, index + 1, MAXCAPTURES - 1)
+ cap := matcher.captures[index + 1]
+ return matcher.haystack[cap.byte_start:cap.byte_end]
+}
+
+matcher_capture_raw :: proc(matcher: ^Matcher, index: int, loc := #caller_location) -> Match #no_bounds_check {
+ runtime.bounds_check_error_loc(loc, index + 1, MAXCAPTURES - 1)
+ return matcher.captures[index + 1]
+}
+
+matcher_gmatch :: matcher_match_iter
+
+matcher_match_iter :: proc(matcher: ^Matcher) -> (res: string, ok: bool) {
+ if len(matcher.iter) > 0 {
+ matcher.captures_length, matcher.err = find_aux(
+ matcher.iter,
+ matcher.pattern,
+ matcher.offset,
+ false,
+ &matcher.captures,
+ )
+
+ if matcher.captures_length != 0 && matcher.err == .OK {
+ ok = true
+ first := matcher.captures_length > 1 ? 1 : 0
+ match := matcher.captures[first]
+ res = matcher.iter[match.byte_start:match.byte_end]
+ matcher.iter = matcher.iter[match.byte_end:]
+ }
+ }
+
+ return
+}
+
+matcher_captures_slice :: proc(matcher: ^Matcher) -> []Match {
+ return matcher.captures[1:matcher.captures_length]
+}