diff --git a/go.mod b/go.mod index 77adead..f364f8f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,3 @@ module github.com/vertoforce/streamregex -go 1.12 +go 1.24 diff --git a/streamregexdoc_test.go b/streamregexdoc_test.go index b09c76e..8caee8a 100644 --- a/streamregexdoc_test.go +++ b/streamregexdoc_test.go @@ -43,5 +43,5 @@ func ExampleFindReaderIndex() { fmt.Println(match, index) } - // Output: stream of + // Output: stream of [20 32] } diff --git a/steamregexindex.go b/streamregexindex.go similarity index 67% rename from steamregexindex.go rename to streamregexindex.go index 7d40df1..8d5cc40 100644 --- a/steamregexindex.go +++ b/streamregexindex.go @@ -36,16 +36,23 @@ func SplitRegexIndex(re *regexp.Regexp, maxMatchLength int, indexChannel chan [] } } -// FindReaderIndex returns a channel of matched []byte from the reader and a channel of the locations at wich the matches where found -// This function will allocate maxMatchLength*2 bytes of memory +// FindReaderIndex returns a channel of matched strings from the reader and a channel of the locations +// ([start, end] byte offsets) at which the matches were found. +// This function will allocate maxMatchLength*2 bytes of memory. +// +// Both channels are closed once scanning finishes. The caller MUST drain both channels +// (read every match and its corresponding index); each match sends its index before the +// match itself, so reading matches without also reading indexes will deadlock the scanner. +// Canceling ctx stops scanning after the current match. func FindReaderIndex(ctx context.Context, r *regexp.Regexp, maxMatchLength int, reader io.Reader) (chan string, chan []int) { allMatches := make(chan string) - allIndexes := make(chan []int, 1) // Avoid deadlock because if location is not read it blocks SplitRegexIndex from returning the match + allIndexes := make(chan []int, 1) // Buffered so SplitRegexIndex can send the index and still return the match before the consumer reads the index buf := make([]byte, maxMatchLength*2) go func() { defer close(allMatches) + defer close(allIndexes) scanner := bufio.NewScanner(reader) scanner.Buffer(buf, maxMatchLength) diff --git a/steamregexindex_test.go b/streamregexindex_test.go similarity index 100% rename from steamregexindex_test.go rename to streamregexindex_test.go