Repository navigation
Expand file tree
/
Copy pathsplit.go
More file actions
104 lines (95 loc) · 2.78 KB
/
Copy pathsplit.go
File metadata and controls
104 lines (95 loc) · 2.78 KB
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
93
94
95
96
97
98
99
100
101
102
103
104
package regexp2
import (
"errors"
"math"
"slices"
)
// Split splits the given input string using the pattern and returns
// a slice of the parts. Count limits the number of matches to process.
// If Count is -1, then it will process the input fully.
// If Count is 0, returns nil. If Count is 1, returns the original input.
// The only expected error is a Timeout, if it's set.
//
// If capturing parentheses are used in the Regex expression, any captured
// text is included in the resulting string array
// For example, a pattern of "-" Split("a-b") will return ["a", "b"]
// but a pattern with "(-)" Split ("a-b") will return ["a", "-", "b"]
func (re *Regexp) Split(input string, count int) ([]string, error) {
if count < -1 {
return nil, errors.New("count too small")
}
if count == 0 {
return nil, nil
}
if count == 1 {
return []string{input}, nil
}
if count == -1 {
// no limit
count = math.MaxInt
}
startAt, ok, err := re.findStringMatchStart(input, -1)
if err != nil {
return nil, err
}
if !ok {
return []string{input}, nil
}
d := decodeInput(input, startAt, re.decodeFrom(input, startAt), re.optimizations.MaxCachedRuneBufferLength)
runner := re.getRunner()
defer func() {
re.putRunner(runner)
d.release()
}()
text := runner.stringMatchText(input, d.runes, 0, d.byteOffset)
// Keep captures in the reusable match, but only materialize output strings.
// Passing text also ensures registered engines use their capturing program.
priorIndex := 0
if re.RightToLeft() {
priorIndex = len(input)
}
var retVal []string
matched := false
origin := re.stringSearchOrigin(input, -1, d.runeStart)
m, err := runner.scan(d.runes, text, origin, d.runeStart, -1, scanCaptures, re.MatchTimeout)
for ; m != nil && count > 0; m, err = runner.scan(d.runes, text, m.textpos, m.textpos, m.RuneLength, scanCaptures, re.MatchTimeout) {
if m.balancing {
compactBalancedMatches(m)
}
matched = true
start, end := matchInputSpan(m)
if re.RightToLeft() {
retVal = append(retVal, input[end:priorIndex])
} else {
retVal = append(retVal, input[priorIndex:start])
}
// Preserve group order and empty strings for unmatched groups without
// allocating Group objects or their capture histories.
for group := 1; group < len(m.matchcount); group++ {
value := ""
if m.matchcount[group] > 0 {
capture := newCapture(text, m.matchIndex(group), m.matchLength(group))
value = capture.String()
}
retVal = append(retVal, value)
}
priorIndex = end
if re.RightToLeft() {
priorIndex = start
}
count--
}
if err != nil {
return nil, err
}
if !matched {
return []string{input}, nil
}
if re.RightToLeft() {
retVal = append(retVal, input[:priorIndex])
slices.Reverse(retVal)
} else {
retVal = append(retVal, input[priorIndex:])
}
return retVal, nil
}