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:
Jakob Borg
2016-04-02 21:03:24 +02:00
committed by Audrius Butkevicius
parent 46e913dc23
commit 4c3cd4c9e3
61 changed files with 6121 additions and 203 deletions

45
vendor/github.com/gobwas/glob/match/any.go generated vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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)
}

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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)
}
})
}