lib/ignore: Replace lib/fnmatch with github.com/gobwas/glob
Because it's literally ten times faster: benchmark old ns/op new ns/op delta BenchmarkMatch-8 13842 1200 -91.33% BenchmarkMatchCached-8 139 147 +5.76% benchmark old allocs new allocs delta BenchmarkMatch-8 0 0 +0.00% BenchmarkMatchCached-8 0 0 +0.00% benchmark old bytes new bytes delta BenchmarkMatch-8 12 0 -100.00% BenchmarkMatchCached-8 0 0 +0.00%
This commit is contained in:
committed by
Audrius Butkevicius
parent
46e913dc23
commit
4c3cd4c9e3
45
vendor/github.com/gobwas/glob/match/any.go
generated
vendored
Normal file
45
vendor/github.com/gobwas/glob/match/any.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gobwas/glob/strings"
|
||||
)
|
||||
|
||||
type Any struct {
|
||||
Separators []rune
|
||||
}
|
||||
|
||||
func NewAny(s []rune) Any {
|
||||
return Any{s}
|
||||
}
|
||||
|
||||
func (self Any) Match(s string) bool {
|
||||
return strings.IndexAnyRunes(s, self.Separators) == -1
|
||||
}
|
||||
|
||||
func (self Any) Index(s string) (int, []int) {
|
||||
found := strings.IndexAnyRunes(s, self.Separators)
|
||||
switch found {
|
||||
case -1:
|
||||
case 0:
|
||||
return 0, segments0
|
||||
default:
|
||||
s = s[:found]
|
||||
}
|
||||
|
||||
segments := acquireSegments(len(s))
|
||||
for i := range s {
|
||||
segments = append(segments, i)
|
||||
}
|
||||
segments = append(segments, len(s))
|
||||
|
||||
return 0, segments
|
||||
}
|
||||
|
||||
func (self Any) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Any) String() string {
|
||||
return fmt.Sprintf("<any:![%s]>", string(self.Separators))
|
||||
}
|
||||
85
vendor/github.com/gobwas/glob/match/any_of.go
generated
vendored
Normal file
85
vendor/github.com/gobwas/glob/match/any_of.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type AnyOf struct {
|
||||
Matchers Matchers
|
||||
}
|
||||
|
||||
func NewAnyOf(m ...Matcher) AnyOf {
|
||||
return AnyOf{Matchers(m)}
|
||||
}
|
||||
|
||||
func (self *AnyOf) Add(m Matcher) error {
|
||||
self.Matchers = append(self.Matchers, m)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self AnyOf) Match(s string) bool {
|
||||
for _, m := range self.Matchers {
|
||||
if m.Match(s) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self AnyOf) Index(s string) (int, []int) {
|
||||
index := -1
|
||||
|
||||
segments := acquireSegments(len(s))
|
||||
for _, m := range self.Matchers {
|
||||
idx, seg := m.Index(s)
|
||||
if idx == -1 {
|
||||
continue
|
||||
}
|
||||
|
||||
if index == -1 || idx < index {
|
||||
index = idx
|
||||
segments = append(segments[:0], seg...)
|
||||
continue
|
||||
}
|
||||
|
||||
if idx > index {
|
||||
continue
|
||||
}
|
||||
|
||||
// here idx == index
|
||||
segments = appendMerge(segments, seg)
|
||||
}
|
||||
|
||||
if index == -1 {
|
||||
releaseSegments(segments)
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
return index, segments
|
||||
}
|
||||
|
||||
func (self AnyOf) Len() (l int) {
|
||||
l = -1
|
||||
for _, m := range self.Matchers {
|
||||
ml := m.Len()
|
||||
if ml == -1 {
|
||||
return -1
|
||||
}
|
||||
|
||||
if l == -1 {
|
||||
l = ml
|
||||
continue
|
||||
}
|
||||
|
||||
if l != ml {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (self AnyOf) String() string {
|
||||
return fmt.Sprintf("<any_of:[%s]>", self.Matchers)
|
||||
}
|
||||
53
vendor/github.com/gobwas/glob/match/any_of_test.go
generated
vendored
Normal file
53
vendor/github.com/gobwas/glob/match/any_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAnyOfIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
matchers Matchers
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
Matchers{
|
||||
NewAny(nil),
|
||||
NewText("b"),
|
||||
NewText("c"),
|
||||
},
|
||||
"abc",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
{
|
||||
Matchers{
|
||||
NewPrefix("b"),
|
||||
NewSuffix("c"),
|
||||
},
|
||||
"abc",
|
||||
0,
|
||||
[]int{3},
|
||||
},
|
||||
{
|
||||
Matchers{
|
||||
NewList([]rune("[def]"), false),
|
||||
NewList([]rune("[abc]"), false),
|
||||
},
|
||||
"abcdef",
|
||||
0,
|
||||
[]int{1},
|
||||
},
|
||||
} {
|
||||
everyOf := NewAnyOf(test.matchers...)
|
||||
index, segments := everyOf.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/any_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/any_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAnyIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
sep []rune
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
[]rune{'.'},
|
||||
"abc",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
{
|
||||
[]rune{'.'},
|
||||
"abc.def",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
} {
|
||||
p := NewAny(test.sep)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexAny(b *testing.B) {
|
||||
m := NewAny(bench_separators)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexAnyParallel(b *testing.B) {
|
||||
m := NewAny(bench_separators)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
146
vendor/github.com/gobwas/glob/match/btree.go
generated
vendored
Normal file
146
vendor/github.com/gobwas/glob/match/btree.go
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type BTree struct {
|
||||
Value Matcher
|
||||
Left Matcher
|
||||
Right Matcher
|
||||
ValueLengthRunes int
|
||||
LeftLengthRunes int
|
||||
RightLengthRunes int
|
||||
LengthRunes int
|
||||
}
|
||||
|
||||
func NewBTree(Value, Left, Right Matcher) (tree BTree) {
|
||||
tree.Value = Value
|
||||
tree.Left = Left
|
||||
tree.Right = Right
|
||||
|
||||
lenOk := true
|
||||
if tree.ValueLengthRunes = Value.Len(); tree.ValueLengthRunes == -1 {
|
||||
lenOk = false
|
||||
}
|
||||
|
||||
if Left != nil {
|
||||
if tree.LeftLengthRunes = Left.Len(); tree.LeftLengthRunes == -1 {
|
||||
lenOk = false
|
||||
}
|
||||
}
|
||||
|
||||
if Right != nil {
|
||||
if tree.RightLengthRunes = Right.Len(); tree.RightLengthRunes == -1 {
|
||||
lenOk = false
|
||||
}
|
||||
}
|
||||
|
||||
if lenOk {
|
||||
tree.LengthRunes = tree.LeftLengthRunes + tree.ValueLengthRunes + tree.RightLengthRunes
|
||||
} else {
|
||||
tree.LengthRunes = -1
|
||||
}
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
func (self BTree) Len() int {
|
||||
return self.LengthRunes
|
||||
}
|
||||
|
||||
// todo?
|
||||
func (self BTree) Index(s string) (int, []int) {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (self BTree) Match(s string) bool {
|
||||
inputLen := len(s)
|
||||
|
||||
// self.Length, self.RLen and self.LLen are values meaning the length of runes for each part
|
||||
// here we manipulating byte length for better optimizations
|
||||
// but these checks still works, cause minLen of 1-rune string is 1 byte.
|
||||
if self.LengthRunes != -1 && self.LengthRunes > inputLen {
|
||||
return false
|
||||
}
|
||||
|
||||
// try to cut unnecessary parts
|
||||
// by knowledge of length of right and left part
|
||||
var offset, limit int
|
||||
if self.LeftLengthRunes >= 0 {
|
||||
offset = self.LeftLengthRunes
|
||||
}
|
||||
if self.RightLengthRunes >= 0 {
|
||||
limit = inputLen - self.RightLengthRunes
|
||||
} else {
|
||||
limit = inputLen
|
||||
}
|
||||
|
||||
for offset < limit {
|
||||
// search for matching part in substring
|
||||
index, segments := self.Value.Index(s[offset:limit])
|
||||
if index == -1 {
|
||||
releaseSegments(segments)
|
||||
return false
|
||||
}
|
||||
|
||||
l := s[:offset+index]
|
||||
var left bool
|
||||
if self.Left != nil {
|
||||
left = self.Left.Match(l)
|
||||
} else {
|
||||
left = l == ""
|
||||
}
|
||||
|
||||
if left {
|
||||
for i := len(segments) - 1; i >= 0; i-- {
|
||||
length := segments[i]
|
||||
|
||||
var right bool
|
||||
var r string
|
||||
// if there is no string for the right branch
|
||||
if inputLen <= offset+index+length {
|
||||
r = ""
|
||||
} else {
|
||||
r = s[offset+index+length:]
|
||||
}
|
||||
|
||||
if self.Right != nil {
|
||||
right = self.Right.Match(r)
|
||||
} else {
|
||||
right = r == ""
|
||||
}
|
||||
|
||||
if right {
|
||||
releaseSegments(segments)
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_, step := utf8.DecodeRuneInString(s[offset+index:])
|
||||
offset += index + step
|
||||
|
||||
releaseSegments(segments)
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self BTree) String() string {
|
||||
const n string = "<nil>"
|
||||
var l, r string
|
||||
if self.Left == nil {
|
||||
l = n
|
||||
} else {
|
||||
l = self.Left.String()
|
||||
}
|
||||
if self.Right == nil {
|
||||
r = n
|
||||
} else {
|
||||
r = self.Right.String()
|
||||
}
|
||||
|
||||
return fmt.Sprintf("<btree:[%s<-%s->%s]>", l, self.Value, r)
|
||||
}
|
||||
90
vendor/github.com/gobwas/glob/match/btree_test.go
generated
vendored
Normal file
90
vendor/github.com/gobwas/glob/match/btree_test.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestBTree(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
tree BTree
|
||||
str string
|
||||
exp bool
|
||||
}{
|
||||
{
|
||||
NewBTree(NewText("abc"), NewSuper(), NewSuper()),
|
||||
"abc",
|
||||
true,
|
||||
},
|
||||
{
|
||||
NewBTree(NewText("a"), NewSingle(nil), NewSingle(nil)),
|
||||
"aaa",
|
||||
true,
|
||||
},
|
||||
{
|
||||
NewBTree(NewText("b"), NewSingle(nil), nil),
|
||||
"bbb",
|
||||
false,
|
||||
},
|
||||
{
|
||||
NewBTree(
|
||||
NewText("c"),
|
||||
NewBTree(
|
||||
NewSingle(nil),
|
||||
NewSuper(),
|
||||
nil,
|
||||
),
|
||||
nil,
|
||||
),
|
||||
"abc",
|
||||
true,
|
||||
},
|
||||
} {
|
||||
act := test.tree.Match(test.str)
|
||||
if act != test.exp {
|
||||
t.Errorf("#%d match %q error: act: %t; exp: %t", id, test.str, act, test.exp)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type fakeMatcher struct {
|
||||
len int
|
||||
name string
|
||||
}
|
||||
|
||||
func (f *fakeMatcher) Match(string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var i = 3
|
||||
|
||||
func (f *fakeMatcher) Index(s string) (int, []int) {
|
||||
seg := make([]int, 0, i)
|
||||
for x := 0; x < i; x++ {
|
||||
seg = append(seg, x)
|
||||
}
|
||||
return 0, seg
|
||||
}
|
||||
func (f *fakeMatcher) Len() int {
|
||||
return f.len
|
||||
}
|
||||
func (f *fakeMatcher) String() string {
|
||||
return f.name
|
||||
}
|
||||
|
||||
func BenchmarkMatchBTree(b *testing.B) {
|
||||
l := &fakeMatcher{4, "left_fake"}
|
||||
r := &fakeMatcher{4, "right_fake"}
|
||||
v := &fakeMatcher{2, "value_fake"}
|
||||
|
||||
// must be <= len(l + r + v)
|
||||
fixture := "abcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghijabcdefghij"
|
||||
|
||||
bt := NewBTree(v, l, r)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
bt.Match(fixture)
|
||||
}
|
||||
})
|
||||
}
|
||||
58
vendor/github.com/gobwas/glob/match/contains.go
generated
vendored
Normal file
58
vendor/github.com/gobwas/glob/match/contains.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Contains struct {
|
||||
Needle string
|
||||
Not bool
|
||||
}
|
||||
|
||||
func NewContains(needle string, not bool) Contains {
|
||||
return Contains{needle, not}
|
||||
}
|
||||
|
||||
func (self Contains) Match(s string) bool {
|
||||
return strings.Contains(s, self.Needle) != self.Not
|
||||
}
|
||||
|
||||
func (self Contains) Index(s string) (int, []int) {
|
||||
var offset int
|
||||
|
||||
idx := strings.Index(s, self.Needle)
|
||||
|
||||
if !self.Not {
|
||||
if idx == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
offset = idx + len(self.Needle)
|
||||
if len(s) <= offset {
|
||||
return 0, []int{offset}
|
||||
}
|
||||
s = s[offset:]
|
||||
} else if idx != -1 {
|
||||
s = s[:idx]
|
||||
}
|
||||
|
||||
segments := acquireSegments(len(s) + 1)
|
||||
for i, _ := range s {
|
||||
segments = append(segments, offset+i)
|
||||
}
|
||||
|
||||
return 0, append(segments, offset+len(s))
|
||||
}
|
||||
|
||||
func (self Contains) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Contains) String() string {
|
||||
var not string
|
||||
if self.Not {
|
||||
not = "!"
|
||||
}
|
||||
return fmt.Sprintf("<contains:%s[%s]>", not, self.Needle)
|
||||
}
|
||||
74
vendor/github.com/gobwas/glob/match/contains_test.go
generated
vendored
Normal file
74
vendor/github.com/gobwas/glob/match/contains_test.go
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestContainsIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
prefix string
|
||||
not bool
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"ab",
|
||||
false,
|
||||
"abc",
|
||||
0,
|
||||
[]int{2, 3},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
false,
|
||||
"fffabfff",
|
||||
0,
|
||||
[]int{5, 6, 7, 8},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
true,
|
||||
"abc",
|
||||
0,
|
||||
[]int{0},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
true,
|
||||
"fffabfff",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
} {
|
||||
p := NewContains(test.prefix, test.not)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexContains(b *testing.B) {
|
||||
m := NewContains(string(bench_separators), true)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexContainsParallel(b *testing.B) {
|
||||
m := NewContains(string(bench_separators), true)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
55
vendor/github.com/gobwas/glob/match/debug/debug.go
generated
vendored
Normal file
55
vendor/github.com/gobwas/glob/match/debug/debug.go
generated
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
package debug
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/gobwas/glob/match"
|
||||
"math/rand"
|
||||
)
|
||||
|
||||
func Graphviz(pattern string, m match.Matcher) string {
|
||||
return fmt.Sprintf(`digraph G {graph[label="%s"];%s}`, pattern, graphviz_internal(m, fmt.Sprintf("%x", rand.Int63())))
|
||||
}
|
||||
|
||||
func graphviz_internal(m match.Matcher, id string) string {
|
||||
buf := &bytes.Buffer{}
|
||||
|
||||
switch matcher := m.(type) {
|
||||
case match.BTree:
|
||||
fmt.Fprintf(buf, `"%s"[label="%s"];`, id, matcher.Value.String())
|
||||
for _, m := range []match.Matcher{matcher.Left, matcher.Right} {
|
||||
switch n := m.(type) {
|
||||
case nil:
|
||||
rnd := rand.Int63()
|
||||
fmt.Fprintf(buf, `"%x"[label="<nil>"];`, rnd)
|
||||
fmt.Fprintf(buf, `"%s"->"%x";`, id, rnd)
|
||||
|
||||
default:
|
||||
sub := fmt.Sprintf("%x", rand.Int63())
|
||||
fmt.Fprintf(buf, `"%s"->"%s";`, id, sub)
|
||||
fmt.Fprintf(buf, graphviz_internal(n, sub))
|
||||
}
|
||||
}
|
||||
|
||||
case match.AnyOf:
|
||||
fmt.Fprintf(buf, `"%s"[label="AnyOf"];`, id)
|
||||
for _, m := range matcher.Matchers {
|
||||
rnd := rand.Int63()
|
||||
fmt.Fprintf(buf, graphviz_internal(m, fmt.Sprintf("%x", rnd)))
|
||||
fmt.Fprintf(buf, `"%s"->"%x";`, id, rnd)
|
||||
}
|
||||
|
||||
case match.EveryOf:
|
||||
fmt.Fprintf(buf, `"%s"[label="EveryOf"];`, id)
|
||||
for _, m := range matcher.Matchers {
|
||||
rnd := rand.Int63()
|
||||
fmt.Fprintf(buf, graphviz_internal(m, fmt.Sprintf("%x", rnd)))
|
||||
fmt.Fprintf(buf, `"%s"->"%x";`, id, rnd)
|
||||
}
|
||||
|
||||
default:
|
||||
fmt.Fprintf(buf, `"%s"[label="%s"];`, id, m.String())
|
||||
}
|
||||
|
||||
return buf.String()
|
||||
}
|
||||
99
vendor/github.com/gobwas/glob/match/every_of.go
generated
vendored
Normal file
99
vendor/github.com/gobwas/glob/match/every_of.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type EveryOf struct {
|
||||
Matchers Matchers
|
||||
}
|
||||
|
||||
func NewEveryOf(m ...Matcher) EveryOf {
|
||||
return EveryOf{Matchers(m)}
|
||||
}
|
||||
|
||||
func (self *EveryOf) Add(m Matcher) error {
|
||||
self.Matchers = append(self.Matchers, m)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self EveryOf) Len() (l int) {
|
||||
for _, m := range self.Matchers {
|
||||
if ml := m.Len(); l > 0 {
|
||||
l += ml
|
||||
} else {
|
||||
return -1
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (self EveryOf) Index(s string) (int, []int) {
|
||||
var index int
|
||||
var offset int
|
||||
|
||||
// make `in` with cap as len(s),
|
||||
// cause it is the maximum size of output segments values
|
||||
next := acquireSegments(len(s))
|
||||
current := acquireSegments(len(s))
|
||||
|
||||
sub := s
|
||||
for i, m := range self.Matchers {
|
||||
idx, seg := m.Index(sub)
|
||||
if idx == -1 {
|
||||
releaseSegments(next)
|
||||
releaseSegments(current)
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
// we use copy here instead of `current = seg`
|
||||
// cause seg is a slice from reusable buffer `in`
|
||||
// and it could be overwritten in next iteration
|
||||
current = append(current, seg...)
|
||||
} else {
|
||||
// clear the next
|
||||
next = next[:0]
|
||||
|
||||
delta := index - (idx + offset)
|
||||
for _, ex := range current {
|
||||
for _, n := range seg {
|
||||
if ex+delta == n {
|
||||
next = append(next, n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(next) == 0 {
|
||||
releaseSegments(next)
|
||||
releaseSegments(current)
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
current = append(current[:0], next...)
|
||||
}
|
||||
|
||||
index = idx + offset
|
||||
sub = s[index:]
|
||||
offset += idx
|
||||
}
|
||||
|
||||
releaseSegments(next)
|
||||
|
||||
return index, current
|
||||
}
|
||||
|
||||
func (self EveryOf) Match(s string) bool {
|
||||
for _, m := range self.Matchers {
|
||||
if !m.Match(s) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (self EveryOf) String() string {
|
||||
return fmt.Sprintf("<every_of:[%s]>", self.Matchers)
|
||||
}
|
||||
45
vendor/github.com/gobwas/glob/match/every_of_test.go
generated
vendored
Normal file
45
vendor/github.com/gobwas/glob/match/every_of_test.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEveryOfIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
matchers Matchers
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
Matchers{
|
||||
NewAny(nil),
|
||||
NewText("b"),
|
||||
NewText("c"),
|
||||
},
|
||||
"dbc",
|
||||
-1,
|
||||
nil,
|
||||
},
|
||||
{
|
||||
Matchers{
|
||||
NewAny(nil),
|
||||
NewPrefix("b"),
|
||||
NewSuffix("c"),
|
||||
},
|
||||
"abc",
|
||||
1,
|
||||
[]int{2},
|
||||
},
|
||||
} {
|
||||
everyOf := NewEveryOf(test.matchers...)
|
||||
index, segments := everyOf.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
49
vendor/github.com/gobwas/glob/match/list.go
generated
vendored
Normal file
49
vendor/github.com/gobwas/glob/match/list.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gobwas/glob/runes"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type List struct {
|
||||
List []rune
|
||||
Not bool
|
||||
}
|
||||
|
||||
func NewList(list []rune, not bool) List {
|
||||
return List{list, not}
|
||||
}
|
||||
|
||||
func (self List) Match(s string) bool {
|
||||
r, w := utf8.DecodeRuneInString(s)
|
||||
if len(s) > w {
|
||||
return false
|
||||
}
|
||||
|
||||
inList := runes.IndexRune(self.List, r) != -1
|
||||
return inList == !self.Not
|
||||
}
|
||||
|
||||
func (self List) Len() int {
|
||||
return lenOne
|
||||
}
|
||||
|
||||
func (self List) Index(s string) (int, []int) {
|
||||
for i, r := range s {
|
||||
if self.Not == (runes.IndexRune(self.List, r) == -1) {
|
||||
return i, segmentsByRuneLength[utf8.RuneLen(r)]
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (self List) String() string {
|
||||
var not string
|
||||
if self.Not {
|
||||
not = "!"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("<list:%s[%s]>", not, string(self.List))
|
||||
}
|
||||
58
vendor/github.com/gobwas/glob/match/list_test.go
generated
vendored
Normal file
58
vendor/github.com/gobwas/glob/match/list_test.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestListIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
list []rune
|
||||
not bool
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
[]rune("ab"),
|
||||
false,
|
||||
"abc",
|
||||
0,
|
||||
[]int{1},
|
||||
},
|
||||
{
|
||||
[]rune("ab"),
|
||||
true,
|
||||
"fffabfff",
|
||||
0,
|
||||
[]int{1},
|
||||
},
|
||||
} {
|
||||
p := NewList(test.list, test.not)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexList(b *testing.B) {
|
||||
m := NewList([]rune("def"), false)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
m.Index(bench_pattern)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexListParallel(b *testing.B) {
|
||||
m := NewList([]rune("def"), false)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
m.Index(bench_pattern)
|
||||
}
|
||||
})
|
||||
}
|
||||
81
vendor/github.com/gobwas/glob/match/match.go
generated
vendored
Normal file
81
vendor/github.com/gobwas/glob/match/match.go
generated
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
package match
|
||||
|
||||
// todo common table of rune's length
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const lenOne = 1
|
||||
const lenZero = 0
|
||||
const lenNo = -1
|
||||
|
||||
type Matcher interface {
|
||||
Match(string) bool
|
||||
Index(string) (int, []int)
|
||||
Len() int
|
||||
String() string
|
||||
}
|
||||
|
||||
type Matchers []Matcher
|
||||
|
||||
func (m Matchers) String() string {
|
||||
var s []string
|
||||
for _, matcher := range m {
|
||||
s = append(s, fmt.Sprint(matcher))
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s", strings.Join(s, ","))
|
||||
}
|
||||
|
||||
// appendMerge merges and sorts given already SORTED and UNIQUE segments.
|
||||
func appendMerge(target, sub []int) []int {
|
||||
lt, ls := len(target), len(sub)
|
||||
out := make([]int, 0, lt+ls)
|
||||
|
||||
for x, y := 0, 0; x < lt || y < ls; {
|
||||
if x >= lt {
|
||||
out = append(out, sub[y:]...)
|
||||
break
|
||||
}
|
||||
|
||||
if y >= ls {
|
||||
out = append(out, target[x:]...)
|
||||
break
|
||||
}
|
||||
|
||||
xValue := target[x]
|
||||
yValue := sub[y]
|
||||
|
||||
switch {
|
||||
|
||||
case xValue == yValue:
|
||||
out = append(out, xValue)
|
||||
x++
|
||||
y++
|
||||
|
||||
case xValue < yValue:
|
||||
out = append(out, xValue)
|
||||
x++
|
||||
|
||||
case yValue < xValue:
|
||||
out = append(out, yValue)
|
||||
y++
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
target = append(target[:0], out...)
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
func reverseSegments(input []int) {
|
||||
l := len(input)
|
||||
m := l / 2
|
||||
|
||||
for i := 0; i < m; i++ {
|
||||
input[i], input[l-i-1] = input[l-i-1], input[i]
|
||||
}
|
||||
}
|
||||
90
vendor/github.com/gobwas/glob/match/match_test.go
generated
vendored
Normal file
90
vendor/github.com/gobwas/glob/match/match_test.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
var bench_separators = []rune{'.'}
|
||||
|
||||
const bench_pattern = "abcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
func TestAppendMerge(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
segments [2][]int
|
||||
exp []int
|
||||
}{
|
||||
{
|
||||
[2][]int{
|
||||
[]int{0, 6, 7},
|
||||
[]int{0, 1, 3},
|
||||
},
|
||||
[]int{0, 1, 3, 6, 7},
|
||||
},
|
||||
{
|
||||
[2][]int{
|
||||
[]int{0, 1, 3, 6, 7},
|
||||
[]int{0, 1, 10},
|
||||
},
|
||||
[]int{0, 1, 3, 6, 7, 10},
|
||||
},
|
||||
} {
|
||||
act := appendMerge(test.segments[0], test.segments[1])
|
||||
if !reflect.DeepEqual(act, test.exp) {
|
||||
t.Errorf("#%d merge sort segments unexpected:\nact: %v\nexp:%v", id, act, test.exp)
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMerge(b *testing.B) {
|
||||
s1 := []int{0, 1, 3, 6, 7}
|
||||
s2 := []int{0, 1, 3}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
appendMerge(s1, s2)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkAppendMergeParallel(b *testing.B) {
|
||||
s1 := []int{0, 1, 3, 6, 7}
|
||||
s2 := []int{0, 1, 3}
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
appendMerge(s1, s2)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkReverse(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
reverseSegments([]int{1, 2, 3, 4})
|
||||
}
|
||||
}
|
||||
|
||||
func getTable() []int {
|
||||
table := make([]int, utf8.MaxRune+1)
|
||||
for i := 0; i <= utf8.MaxRune; i++ {
|
||||
table[i] = utf8.RuneLen(rune(i))
|
||||
}
|
||||
|
||||
return table
|
||||
}
|
||||
|
||||
var table = getTable()
|
||||
|
||||
const runeToLen = 'q'
|
||||
|
||||
func BenchmarkRuneLenFromTable(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = table[runeToLen]
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRuneLenFromUTF8(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_ = utf8.RuneLen(runeToLen)
|
||||
}
|
||||
}
|
||||
49
vendor/github.com/gobwas/glob/match/max.go
generated
vendored
Normal file
49
vendor/github.com/gobwas/glob/match/max.go
generated
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type Max struct {
|
||||
Limit int
|
||||
}
|
||||
|
||||
func NewMax(l int) Max {
|
||||
return Max{l}
|
||||
}
|
||||
|
||||
func (self Max) Match(s string) bool {
|
||||
var l int
|
||||
for range s {
|
||||
l += 1
|
||||
if l > self.Limit {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (self Max) Index(s string) (int, []int) {
|
||||
segments := acquireSegments(self.Limit + 1)
|
||||
segments = append(segments, 0)
|
||||
var count int
|
||||
for i, r := range s {
|
||||
count++
|
||||
if count > self.Limit {
|
||||
break
|
||||
}
|
||||
segments = append(segments, i+utf8.RuneLen(r))
|
||||
}
|
||||
|
||||
return 0, segments
|
||||
}
|
||||
|
||||
func (self Max) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Max) String() string {
|
||||
return fmt.Sprintf("<max:%d>", self.Limit)
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/max_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/max_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMaxIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
limit int
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
3,
|
||||
"abc",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
{
|
||||
3,
|
||||
"abcdef",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
} {
|
||||
p := NewMax(test.limit)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexMax(b *testing.B) {
|
||||
m := NewMax(10)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexMaxParallel(b *testing.B) {
|
||||
m := NewMax(10)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/min.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/min.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type Min struct {
|
||||
Limit int
|
||||
}
|
||||
|
||||
func NewMin(l int) Min {
|
||||
return Min{l}
|
||||
}
|
||||
|
||||
func (self Min) Match(s string) bool {
|
||||
var l int
|
||||
for range s {
|
||||
l += 1
|
||||
if l >= self.Limit {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self Min) Index(s string) (int, []int) {
|
||||
var count int
|
||||
|
||||
c := len(s) - self.Limit + 1
|
||||
if c <= 0 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
segments := acquireSegments(c)
|
||||
for i, r := range s {
|
||||
count++
|
||||
if count >= self.Limit {
|
||||
segments = append(segments, i+utf8.RuneLen(r))
|
||||
}
|
||||
}
|
||||
|
||||
if len(segments) == 0 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
return 0, segments
|
||||
}
|
||||
|
||||
func (self Min) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Min) String() string {
|
||||
return fmt.Sprintf("<min:%d>", self.Limit)
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/min_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/min_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMinIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
limit int
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
1,
|
||||
"abc",
|
||||
0,
|
||||
[]int{1, 2, 3},
|
||||
},
|
||||
{
|
||||
3,
|
||||
"abcd",
|
||||
0,
|
||||
[]int{3, 4},
|
||||
},
|
||||
} {
|
||||
p := NewMin(test.limit)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexMin(b *testing.B) {
|
||||
m := NewMin(10)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexMinParallel(b *testing.B) {
|
||||
m := NewMin(10)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
27
vendor/github.com/gobwas/glob/match/nothing.go
generated
vendored
Normal file
27
vendor/github.com/gobwas/glob/match/nothing.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Nothing struct{}
|
||||
|
||||
func NewNothing() Nothing {
|
||||
return Nothing{}
|
||||
}
|
||||
|
||||
func (self Nothing) Match(s string) bool {
|
||||
return len(s) == 0
|
||||
}
|
||||
|
||||
func (self Nothing) Index(s string) (int, []int) {
|
||||
return 0, segments0
|
||||
}
|
||||
|
||||
func (self Nothing) Len() int {
|
||||
return lenZero
|
||||
}
|
||||
|
||||
func (self Nothing) String() string {
|
||||
return fmt.Sprintf("<nothing>")
|
||||
}
|
||||
54
vendor/github.com/gobwas/glob/match/nothing_test.go
generated
vendored
Normal file
54
vendor/github.com/gobwas/glob/match/nothing_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNothingIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"abc",
|
||||
0,
|
||||
[]int{0},
|
||||
},
|
||||
{
|
||||
"",
|
||||
0,
|
||||
[]int{0},
|
||||
},
|
||||
} {
|
||||
p := NewNothing()
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexNothing(b *testing.B) {
|
||||
m := NewNothing()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexNothingParallel(b *testing.B) {
|
||||
m := NewNothing()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
50
vendor/github.com/gobwas/glob/match/prefix.go
generated
vendored
Normal file
50
vendor/github.com/gobwas/glob/match/prefix.go
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type Prefix struct {
|
||||
Prefix string
|
||||
}
|
||||
|
||||
func NewPrefix(p string) Prefix {
|
||||
return Prefix{p}
|
||||
}
|
||||
|
||||
func (self Prefix) Index(s string) (int, []int) {
|
||||
idx := strings.Index(s, self.Prefix)
|
||||
if idx == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
length := len(self.Prefix)
|
||||
var sub string
|
||||
if len(s) > idx+length {
|
||||
sub = s[idx+length:]
|
||||
} else {
|
||||
sub = ""
|
||||
}
|
||||
|
||||
segments := acquireSegments(len(sub) + 1)
|
||||
segments = append(segments, length)
|
||||
for i, r := range sub {
|
||||
segments = append(segments, length+i+utf8.RuneLen(r))
|
||||
}
|
||||
|
||||
return idx, segments
|
||||
}
|
||||
|
||||
func (self Prefix) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Prefix) Match(s string) bool {
|
||||
return strings.HasPrefix(s, self.Prefix)
|
||||
}
|
||||
|
||||
func (self Prefix) String() string {
|
||||
return fmt.Sprintf("<prefix:%s>", self.Prefix)
|
||||
}
|
||||
62
vendor/github.com/gobwas/glob/match/prefix_suffix.go
generated
vendored
Normal file
62
vendor/github.com/gobwas/glob/match/prefix_suffix.go
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PrefixSuffix struct {
|
||||
Prefix, Suffix string
|
||||
}
|
||||
|
||||
func NewPrefixSuffix(p, s string) PrefixSuffix {
|
||||
return PrefixSuffix{p, s}
|
||||
}
|
||||
|
||||
func (self PrefixSuffix) Index(s string) (int, []int) {
|
||||
prefixIdx := strings.Index(s, self.Prefix)
|
||||
if prefixIdx == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
suffixLen := len(self.Suffix)
|
||||
if suffixLen <= 0 {
|
||||
return prefixIdx, []int{len(s) - prefixIdx}
|
||||
}
|
||||
|
||||
if (len(s) - prefixIdx) <= 0 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
segments := acquireSegments(len(s) - prefixIdx)
|
||||
for sub := s[prefixIdx:]; ; {
|
||||
suffixIdx := strings.LastIndex(sub, self.Suffix)
|
||||
if suffixIdx == -1 {
|
||||
break
|
||||
}
|
||||
|
||||
segments = append(segments, suffixIdx+suffixLen)
|
||||
sub = sub[:suffixIdx]
|
||||
}
|
||||
|
||||
if len(segments) == 0 {
|
||||
releaseSegments(segments)
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
reverseSegments(segments)
|
||||
|
||||
return prefixIdx, segments
|
||||
}
|
||||
|
||||
func (self PrefixSuffix) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self PrefixSuffix) Match(s string) bool {
|
||||
return strings.HasPrefix(s, self.Prefix) && strings.HasSuffix(s, self.Suffix)
|
||||
}
|
||||
|
||||
func (self PrefixSuffix) String() string {
|
||||
return fmt.Sprintf("<prefix_suffix:[%s,%s]>", self.Prefix, self.Suffix)
|
||||
}
|
||||
67
vendor/github.com/gobwas/glob/match/prefix_suffix_test.go
generated
vendored
Normal file
67
vendor/github.com/gobwas/glob/match/prefix_suffix_test.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrefixSuffixIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
prefix string
|
||||
suffix string
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"a",
|
||||
"c",
|
||||
"abc",
|
||||
0,
|
||||
[]int{3},
|
||||
},
|
||||
{
|
||||
"f",
|
||||
"f",
|
||||
"fffabfff",
|
||||
0,
|
||||
[]int{1, 2, 3, 6, 7, 8},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
"bc",
|
||||
"abc",
|
||||
0,
|
||||
[]int{3},
|
||||
},
|
||||
} {
|
||||
p := NewPrefixSuffix(test.prefix, test.suffix)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexPrefixSuffix(b *testing.B) {
|
||||
m := NewPrefixSuffix("qew", "sqw")
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexPrefixSuffixParallel(b *testing.B) {
|
||||
m := NewPrefixSuffix("qew", "sqw")
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/prefix_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/prefix_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPrefixIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
prefix string
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"ab",
|
||||
"abc",
|
||||
0,
|
||||
[]int{2, 3},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
"fffabfff",
|
||||
3,
|
||||
[]int{2, 3, 4, 5},
|
||||
},
|
||||
} {
|
||||
p := NewPrefix(test.prefix)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexPrefix(b *testing.B) {
|
||||
m := NewPrefix("qew")
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexPrefixParallel(b *testing.B) {
|
||||
m := NewPrefix("qew")
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
48
vendor/github.com/gobwas/glob/match/range.go
generated
vendored
Normal file
48
vendor/github.com/gobwas/glob/match/range.go
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type Range struct {
|
||||
Lo, Hi rune
|
||||
Not bool
|
||||
}
|
||||
|
||||
func NewRange(lo, hi rune, not bool) Range {
|
||||
return Range{lo, hi, not}
|
||||
}
|
||||
|
||||
func (self Range) Len() int {
|
||||
return lenOne
|
||||
}
|
||||
|
||||
func (self Range) Match(s string) bool {
|
||||
r, w := utf8.DecodeRuneInString(s)
|
||||
if len(s) > w {
|
||||
return false
|
||||
}
|
||||
|
||||
inRange := r >= self.Lo && r <= self.Hi
|
||||
|
||||
return inRange == !self.Not
|
||||
}
|
||||
|
||||
func (self Range) Index(s string) (int, []int) {
|
||||
for i, r := range s {
|
||||
if self.Not != (r >= self.Lo && r <= self.Hi) {
|
||||
return i, segmentsByRuneLength[utf8.RuneLen(r)]
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (self Range) String() string {
|
||||
var not string
|
||||
if self.Not {
|
||||
not = "!"
|
||||
}
|
||||
return fmt.Sprintf("<range:%s[%s,%s]>", not, string(self.Lo), string(self.Hi))
|
||||
}
|
||||
67
vendor/github.com/gobwas/glob/match/range_test.go
generated
vendored
Normal file
67
vendor/github.com/gobwas/glob/match/range_test.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRangeIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
lo, hi rune
|
||||
not bool
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
'a', 'z',
|
||||
false,
|
||||
"abc",
|
||||
0,
|
||||
[]int{1},
|
||||
},
|
||||
{
|
||||
'a', 'c',
|
||||
false,
|
||||
"abcd",
|
||||
0,
|
||||
[]int{1},
|
||||
},
|
||||
{
|
||||
'a', 'c',
|
||||
true,
|
||||
"abcd",
|
||||
3,
|
||||
[]int{1},
|
||||
},
|
||||
} {
|
||||
m := NewRange(test.lo, test.hi, test.not)
|
||||
index, segments := m.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexRange(b *testing.B) {
|
||||
m := NewRange('0', '9', false)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexRangeParallel(b *testing.B) {
|
||||
m := NewRange('0', '9', false)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
85
vendor/github.com/gobwas/glob/match/row.go
generated
vendored
Normal file
85
vendor/github.com/gobwas/glob/match/row.go
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Row struct {
|
||||
Matchers Matchers
|
||||
RunesLength int
|
||||
Segments []int
|
||||
}
|
||||
|
||||
func NewRow(len int, m ...Matcher) Row {
|
||||
return Row{
|
||||
Matchers: Matchers(m),
|
||||
RunesLength: len,
|
||||
Segments: []int{len},
|
||||
}
|
||||
}
|
||||
|
||||
func (self Row) matchAll(s string) bool {
|
||||
var idx int
|
||||
for _, m := range self.Matchers {
|
||||
length := m.Len()
|
||||
|
||||
var next, i int
|
||||
for next = range s[idx:] {
|
||||
i++
|
||||
if i == length {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if i < length || !m.Match(s[idx:idx+next+1]) {
|
||||
return false
|
||||
}
|
||||
|
||||
idx += next + 1
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (self Row) lenOk(s string) bool {
|
||||
var i int
|
||||
for range s {
|
||||
i++
|
||||
if i >= self.RunesLength {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (self Row) Match(s string) bool {
|
||||
return self.lenOk(s) && self.matchAll(s)
|
||||
}
|
||||
|
||||
func (self Row) Len() (l int) {
|
||||
return self.RunesLength
|
||||
}
|
||||
|
||||
func (self Row) Index(s string) (int, []int) {
|
||||
if !self.lenOk(s) {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
for i := range s {
|
||||
// this is not strict check but useful
|
||||
if len(s[i:]) < self.RunesLength {
|
||||
break
|
||||
}
|
||||
|
||||
if self.matchAll(s[i:]) {
|
||||
return i, self.Segments
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (self Row) String() string {
|
||||
return fmt.Sprintf("<row_%d:[%s]>", self.RunesLength, self.Matchers)
|
||||
}
|
||||
82
vendor/github.com/gobwas/glob/match/row_test.go
generated
vendored
Normal file
82
vendor/github.com/gobwas/glob/match/row_test.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRowIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
matchers Matchers
|
||||
length int
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
Matchers{
|
||||
NewText("abc"),
|
||||
NewText("def"),
|
||||
NewSingle(nil),
|
||||
},
|
||||
7,
|
||||
"qweabcdefghij",
|
||||
3,
|
||||
[]int{7},
|
||||
},
|
||||
{
|
||||
Matchers{
|
||||
NewText("abc"),
|
||||
NewText("def"),
|
||||
NewSingle(nil),
|
||||
},
|
||||
7,
|
||||
"abcd",
|
||||
-1,
|
||||
nil,
|
||||
},
|
||||
} {
|
||||
p := NewRow(test.length, test.matchers...)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkRowIndex(b *testing.B) {
|
||||
m := NewRow(
|
||||
7,
|
||||
Matchers{
|
||||
NewText("abc"),
|
||||
NewText("def"),
|
||||
NewSingle(nil),
|
||||
}...,
|
||||
)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexRowParallel(b *testing.B) {
|
||||
m := NewRow(
|
||||
7,
|
||||
Matchers{
|
||||
NewText("abc"),
|
||||
NewText("def"),
|
||||
NewSingle(nil),
|
||||
}...,
|
||||
)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
91
vendor/github.com/gobwas/glob/match/segments.go
generated
vendored
Normal file
91
vendor/github.com/gobwas/glob/match/segments.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"sync"
|
||||
)
|
||||
|
||||
type SomePool interface {
|
||||
Get() []int
|
||||
Put([]int)
|
||||
}
|
||||
|
||||
var segmentsPools [1024]sync.Pool
|
||||
|
||||
func toPowerOfTwo(v int) int {
|
||||
v--
|
||||
v |= v >> 1
|
||||
v |= v >> 2
|
||||
v |= v >> 4
|
||||
v |= v >> 8
|
||||
v |= v >> 16
|
||||
v++
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
const (
|
||||
cacheFrom = 16
|
||||
cacheToAndHigher = 1024
|
||||
cacheFromIndex = 15
|
||||
cacheToAndHigherIndex = 1023
|
||||
)
|
||||
|
||||
var (
|
||||
segments0 = []int{0}
|
||||
segments1 = []int{1}
|
||||
segments2 = []int{2}
|
||||
segments3 = []int{3}
|
||||
segments4 = []int{4}
|
||||
)
|
||||
|
||||
var segmentsByRuneLength [5][]int = [5][]int{
|
||||
0: segments0,
|
||||
1: segments1,
|
||||
2: segments2,
|
||||
3: segments3,
|
||||
4: segments4,
|
||||
}
|
||||
|
||||
func init() {
|
||||
for i := cacheToAndHigher; i >= cacheFrom; i >>= 1 {
|
||||
func(i int) {
|
||||
segmentsPools[i-1] = sync.Pool{New: func() interface{} {
|
||||
return make([]int, 0, i)
|
||||
}}
|
||||
}(i)
|
||||
}
|
||||
}
|
||||
|
||||
func getTableIndex(c int) int {
|
||||
p := toPowerOfTwo(c)
|
||||
switch {
|
||||
case p >= cacheToAndHigher:
|
||||
return cacheToAndHigherIndex
|
||||
case p <= cacheFrom:
|
||||
return cacheFromIndex
|
||||
default:
|
||||
return p - 1
|
||||
}
|
||||
}
|
||||
|
||||
func acquireSegments(c int) []int {
|
||||
// make []int with less capacity than cacheFrom
|
||||
// is faster than acquiring it from pool
|
||||
if c < cacheFrom {
|
||||
return make([]int, 0, c)
|
||||
}
|
||||
|
||||
return segmentsPools[getTableIndex(c)].Get().([]int)[:0]
|
||||
}
|
||||
|
||||
func releaseSegments(s []int) {
|
||||
c := cap(s)
|
||||
|
||||
// make []int with less capacity than cacheFrom
|
||||
// is faster than acquiring it from pool
|
||||
if c < cacheFrom {
|
||||
return
|
||||
}
|
||||
|
||||
segmentsPools[getTableIndex(c)].Put(s)
|
||||
}
|
||||
83
vendor/github.com/gobwas/glob/match/segments_test.go
generated
vendored
Normal file
83
vendor/github.com/gobwas/glob/match/segments_test.go
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func benchPool(i int, b *testing.B) {
|
||||
pool := sync.Pool{New: func() interface{} {
|
||||
return make([]int, 0, i)
|
||||
}}
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
s := pool.Get().([]int)[:0]
|
||||
pool.Put(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func benchMake(i int, b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_ = make([]int, 0, i)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkSegmentsPool_1(b *testing.B) {
|
||||
benchPool(1, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_2(b *testing.B) {
|
||||
benchPool(2, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_4(b *testing.B) {
|
||||
benchPool(4, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_8(b *testing.B) {
|
||||
benchPool(8, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_16(b *testing.B) {
|
||||
benchPool(16, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_32(b *testing.B) {
|
||||
benchPool(32, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_64(b *testing.B) {
|
||||
benchPool(64, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_128(b *testing.B) {
|
||||
benchPool(128, b)
|
||||
}
|
||||
func BenchmarkSegmentsPool_256(b *testing.B) {
|
||||
benchPool(256, b)
|
||||
}
|
||||
|
||||
func BenchmarkSegmentsMake_1(b *testing.B) {
|
||||
benchMake(1, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_2(b *testing.B) {
|
||||
benchMake(2, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_4(b *testing.B) {
|
||||
benchMake(4, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_8(b *testing.B) {
|
||||
benchMake(8, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_16(b *testing.B) {
|
||||
benchMake(16, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_32(b *testing.B) {
|
||||
benchMake(32, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_64(b *testing.B) {
|
||||
benchMake(64, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_128(b *testing.B) {
|
||||
benchMake(128, b)
|
||||
}
|
||||
func BenchmarkSegmentsMake_256(b *testing.B) {
|
||||
benchMake(256, b)
|
||||
}
|
||||
43
vendor/github.com/gobwas/glob/match/single.go
generated
vendored
Normal file
43
vendor/github.com/gobwas/glob/match/single.go
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/gobwas/glob/runes"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// single represents ?
|
||||
type Single struct {
|
||||
Separators []rune
|
||||
}
|
||||
|
||||
func NewSingle(s []rune) Single {
|
||||
return Single{s}
|
||||
}
|
||||
|
||||
func (self Single) Match(s string) bool {
|
||||
r, w := utf8.DecodeRuneInString(s)
|
||||
if len(s) > w {
|
||||
return false
|
||||
}
|
||||
|
||||
return runes.IndexRune(self.Separators, r) == -1
|
||||
}
|
||||
|
||||
func (self Single) Len() int {
|
||||
return lenOne
|
||||
}
|
||||
|
||||
func (self Single) Index(s string) (int, []int) {
|
||||
for i, r := range s {
|
||||
if runes.IndexRune(self.Separators, r) == -1 {
|
||||
return i, segmentsByRuneLength[utf8.RuneLen(r)]
|
||||
}
|
||||
}
|
||||
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
func (self Single) String() string {
|
||||
return fmt.Sprintf("<single:![%s]>", string(self.Separators))
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/single_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/single_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSingleIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
separators []rune
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
[]rune{'.'},
|
||||
".abc",
|
||||
1,
|
||||
[]int{1},
|
||||
},
|
||||
{
|
||||
[]rune{'.'},
|
||||
".",
|
||||
-1,
|
||||
nil,
|
||||
},
|
||||
} {
|
||||
p := NewSingle(test.separators)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSingle(b *testing.B) {
|
||||
m := NewSingle(bench_separators)
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSingleParallel(b *testing.B) {
|
||||
m := NewSingle(bench_separators)
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
35
vendor/github.com/gobwas/glob/match/suffix.go
generated
vendored
Normal file
35
vendor/github.com/gobwas/glob/match/suffix.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Suffix struct {
|
||||
Suffix string
|
||||
}
|
||||
|
||||
func NewSuffix(s string) Suffix {
|
||||
return Suffix{s}
|
||||
}
|
||||
|
||||
func (self Suffix) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Suffix) Match(s string) bool {
|
||||
return strings.HasSuffix(s, self.Suffix)
|
||||
}
|
||||
|
||||
func (self Suffix) Index(s string) (int, []int) {
|
||||
idx := strings.Index(s, self.Suffix)
|
||||
if idx == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
return 0, []int{idx + len(self.Suffix)}
|
||||
}
|
||||
|
||||
func (self Suffix) String() string {
|
||||
return fmt.Sprintf("<suffix:%s>", self.Suffix)
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/suffix_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/suffix_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSuffixIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
prefix string
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"ab",
|
||||
"abc",
|
||||
0,
|
||||
[]int{2},
|
||||
},
|
||||
{
|
||||
"ab",
|
||||
"fffabfff",
|
||||
0,
|
||||
[]int{5},
|
||||
},
|
||||
} {
|
||||
p := NewSuffix(test.prefix)
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSuffix(b *testing.B) {
|
||||
m := NewSuffix("qwe")
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSuffixParallel(b *testing.B) {
|
||||
m := NewSuffix("qwe")
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
33
vendor/github.com/gobwas/glob/match/super.go
generated
vendored
Normal file
33
vendor/github.com/gobwas/glob/match/super.go
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type Super struct{}
|
||||
|
||||
func NewSuper() Super {
|
||||
return Super{}
|
||||
}
|
||||
|
||||
func (self Super) Match(s string) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (self Super) Len() int {
|
||||
return lenNo
|
||||
}
|
||||
|
||||
func (self Super) Index(s string) (int, []int) {
|
||||
segments := acquireSegments(len(s) + 1)
|
||||
for i := range s {
|
||||
segments = append(segments, i)
|
||||
}
|
||||
segments = append(segments, len(s))
|
||||
|
||||
return 0, segments
|
||||
}
|
||||
|
||||
func (self Super) String() string {
|
||||
return fmt.Sprintf("<super>")
|
||||
}
|
||||
54
vendor/github.com/gobwas/glob/match/super_test.go
generated
vendored
Normal file
54
vendor/github.com/gobwas/glob/match/super_test.go
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSuperIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"abc",
|
||||
0,
|
||||
[]int{0, 1, 2, 3},
|
||||
},
|
||||
{
|
||||
"",
|
||||
0,
|
||||
[]int{0},
|
||||
},
|
||||
} {
|
||||
p := NewSuper()
|
||||
index, segments := p.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSuper(b *testing.B) {
|
||||
m := NewSuper()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexSuperParallel(b *testing.B) {
|
||||
m := NewSuper()
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
45
vendor/github.com/gobwas/glob/match/text.go
generated
vendored
Normal file
45
vendor/github.com/gobwas/glob/match/text.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// raw represents raw string to match
|
||||
type Text struct {
|
||||
Str string
|
||||
RunesLength int
|
||||
BytesLength int
|
||||
Segments []int
|
||||
}
|
||||
|
||||
func NewText(s string) Text {
|
||||
return Text{
|
||||
Str: s,
|
||||
RunesLength: utf8.RuneCountInString(s),
|
||||
BytesLength: len(s),
|
||||
Segments: []int{len(s)},
|
||||
}
|
||||
}
|
||||
|
||||
func (self Text) Match(s string) bool {
|
||||
return self.Str == s
|
||||
}
|
||||
|
||||
func (self Text) Len() int {
|
||||
return self.RunesLength
|
||||
}
|
||||
|
||||
func (self Text) Index(s string) (int, []int) {
|
||||
index := strings.Index(s, self.Str)
|
||||
if index == -1 {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
return index, self.Segments
|
||||
}
|
||||
|
||||
func (self Text) String() string {
|
||||
return fmt.Sprintf("<text:`%v`>", self.Str)
|
||||
}
|
||||
57
vendor/github.com/gobwas/glob/match/text_test.go
generated
vendored
Normal file
57
vendor/github.com/gobwas/glob/match/text_test.go
generated
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
package match
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestTextIndex(t *testing.T) {
|
||||
for id, test := range []struct {
|
||||
text string
|
||||
fixture string
|
||||
index int
|
||||
segments []int
|
||||
}{
|
||||
{
|
||||
"b",
|
||||
"abc",
|
||||
1,
|
||||
[]int{1},
|
||||
},
|
||||
{
|
||||
"f",
|
||||
"abcd",
|
||||
-1,
|
||||
nil,
|
||||
},
|
||||
} {
|
||||
m := NewText(test.text)
|
||||
index, segments := m.Index(test.fixture)
|
||||
if index != test.index {
|
||||
t.Errorf("#%d unexpected index: exp: %d, act: %d", id, test.index, index)
|
||||
}
|
||||
if !reflect.DeepEqual(segments, test.segments) {
|
||||
t.Errorf("#%d unexpected segments: exp: %v, act: %v", id, test.segments, segments)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexText(b *testing.B) {
|
||||
m := NewText("foo")
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIndexTextParallel(b *testing.B) {
|
||||
m := NewText("foo")
|
||||
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
_, s := m.Index(bench_pattern)
|
||||
releaseSegments(s)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user