From 9a2b6c01aa2853a87ac5cff2f9981ffce39a2293 Mon Sep 17 00:00:00 2001 From: Jeroen van Rijn Date: Sun, 6 Apr 2025 21:45:37 +0200 Subject: [PATCH] Return loop index in regex iterator. --- core/text/regex/regex.odin | 14 ++++++++++++-- tests/core/text/regex/test_core_text_regex.odin | 7 +++---- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/core/text/regex/regex.odin b/core/text/regex/regex.odin index 1ad582a4f..a887d5967 100644 --- a/core/text/regex/regex.odin +++ b/core/text/regex/regex.odin @@ -73,6 +73,7 @@ Match_Iterator :: struct { offset: int, regex: Regular_Expression, capture: Capture, + idx: int, temp: runtime.Allocator, } @@ -442,7 +443,7 @@ Returns: - result: `Capture` for this iteration. - ok: A bool indicating if there was a match, stopping the iteration on `false`. */ -match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, ok: bool) { +match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, index: int, ok: bool) { runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD() num_groups: int num_groups, ok = match_with_preallocated_capture( @@ -452,6 +453,10 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, ok: bool) { it.temp, ) + defer if ok { + it.idx += 1 + } + if num_groups > 0 { for i in 0.. (result: Capture, ok: bool) { it.offset = it.capture.pos[0][1] result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]} } - return + return result, it.idx, ok } match :: proc { @@ -468,6 +473,11 @@ match :: proc { match_iterator, } +reset :: proc(it: ^Match_Iterator) { + it.offset = 0 + it.idx = 0 +} + /* Allocate a `Capture` in advance for use with `match`. This can save some time if you plan on performing several matches at once and only need the results diff --git a/tests/core/text/regex/test_core_text_regex.odin b/tests/core/text/regex/test_core_text_regex.odin index 7874d76aa..4a34ced68 100644 --- a/tests/core/text/regex/test_core_text_regex.odin +++ b/tests/core/text/regex/test_core_text_regex.odin @@ -1127,13 +1127,12 @@ test_match_iterator :: proc(t: ^testing.T) { (err == nil) or_continue count: int - for capture in regex.match(&it) { + for capture, idx in regex.match(&it) { if count > len(test.expected) { break } - check_capture(t, capture, test.expected[count]) - count += 1 + check_capture(t, capture, test.expected[idx]) } - testing.expect_value(t, count, len(test.expected)) + testing.expect_value(t, it.idx, len(test.expected)) } } \ No newline at end of file