Return loop index in regex iterator.

This commit is contained in:
Jeroen van Rijn
2025-04-06 21:45:37 +02:00
parent 66077add33
commit 9a2b6c01aa
2 changed files with 15 additions and 6 deletions
+12 -2
View File
@@ -73,6 +73,7 @@ Match_Iterator :: struct {
offset: int, offset: int,
regex: Regular_Expression, regex: Regular_Expression,
capture: Capture, capture: Capture,
idx: int,
temp: runtime.Allocator, temp: runtime.Allocator,
} }
@@ -442,7 +443,7 @@ Returns:
- result: `Capture` for this iteration. - result: `Capture` for this iteration.
- ok: A bool indicating if there was a match, stopping the iteration on `false`. - 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() runtime.DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD()
num_groups: int num_groups: int
num_groups, ok = match_with_preallocated_capture( num_groups, ok = match_with_preallocated_capture(
@@ -452,6 +453,10 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, ok: bool) {
it.temp, it.temp,
) )
defer if ok {
it.idx += 1
}
if num_groups > 0 { if num_groups > 0 {
for i in 0..<num_groups { for i in 0..<num_groups {
it.capture.pos[i] += it.offset it.capture.pos[i] += it.offset
@@ -459,7 +464,7 @@ match_iterator :: proc(it: ^Match_Iterator) -> (result: Capture, ok: bool) {
it.offset = it.capture.pos[0][1] it.offset = it.capture.pos[0][1]
result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]} result = {it.capture.pos[:num_groups], it.capture.groups[:num_groups]}
} }
return return result, it.idx, ok
} }
match :: proc { match :: proc {
@@ -468,6 +473,11 @@ match :: proc {
match_iterator, 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 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 if you plan on performing several matches at once and only need the results
@@ -1127,13 +1127,12 @@ test_match_iterator :: proc(t: ^testing.T) {
(err == nil) or_continue (err == nil) or_continue
count: int count: int
for capture in regex.match(&it) { for capture, idx in regex.match(&it) {
if count > len(test.expected) { if count > len(test.expected) {
break break
} }
check_capture(t, capture, test.expected[count]) check_capture(t, capture, test.expected[idx])
count += 1
} }
testing.expect_value(t, count, len(test.expected)) testing.expect_value(t, it.idx, len(test.expected))
} }
} }