-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbytes.go
92 lines (82 loc) · 1.65 KB
/
bytes.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package regexer
import (
"iter"
"regexp"
)
type (
BMatch = Match[[]byte]
BSub = Sub[[]byte]
BSubs = Subs[[]byte]
)
type Bytes struct {
rex *regexp.Regexp
src []byte
}
func (b Bytes) Find() iter.Seq[BMatch] {
return func(yield func(BMatch) bool) {
shift := 0
for {
subSrc := b.src[shift:]
spans := b.rex.FindSubmatchIndex(subSrc)
if spans == nil {
return
}
spanStart := spans[0]
spanEnd := spans[1]
match := BMatch{
Content: subSrc[spanStart:spanEnd],
Span: Span{
Start: shift + spanStart,
End: shift + spanEnd,
},
Subs: BSubs{
shift: shift,
content: subSrc,
rawSpans: spans,
},
}
more := yield(match)
if !more {
return
}
shift += spanEnd
}
}
}
func (b Bytes) Replace(res *[]byte) iter.Seq[BReplacement] {
return func(yield func(BReplacement) bool) {
prevEnd := 0
for match := range b.Find() {
*res = append(*res, b.src[prevEnd:match.Span.Start]...)
ok := yield(BReplacement{
Match: match,
rex: b.rex,
src: b.src[prevEnd:],
result: res,
})
if !ok {
return
}
prevEnd = match.Span.End
}
*res = append(*res, b.src[prevEnd:]...)
}
}
func (b Bytes) Contains() bool {
return b.rex.Match(b.src)
}
type BReplacement struct {
Match[[]byte]
rex *regexp.Regexp
src []byte
result *[]byte
}
func (r BReplacement) ReplaceLiteral(val []byte) {
*r.result = append(*r.result, val...)
}
func (r BReplacement) ReplaceTemplate(val []byte) {
*r.result = r.rex.Expand(*r.result, val, r.src, r.Subs.rawSpans)
}
func (r BReplacement) ReplaceFunc(f func([]byte) []byte) {
*r.result = append(*r.result, f(r.Match.Content)...)
}