forked from mirror/glob
Update
This commit is contained in:
parent
d4d579d13e
commit
678ba81174
86
glob.go
86
glob.go
|
@ -13,40 +13,28 @@ const (
|
||||||
|
|
||||||
var Chars = []string{Any, SuperAny, SingleAny}
|
var Chars = []string{Any, SuperAny, SingleAny}
|
||||||
|
|
||||||
type Matcher interface {
|
type Glob interface {
|
||||||
Match(string) bool
|
Match(string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func firstIndexOfChars(p string, any []string) (min int, c string) {
|
func New(pattern string, d ...string) Glob {
|
||||||
l := len(p)
|
chunks := parse(pattern, nil, strings.Join(d, ""))
|
||||||
min = l
|
|
||||||
weight := 0
|
|
||||||
|
|
||||||
for _, s := range any {
|
if len(chunks) == 1 {
|
||||||
w := len(s)
|
return chunks[0]
|
||||||
i := strings.Index(p, s)
|
|
||||||
if i != -1 && i <= min && w > weight {
|
|
||||||
min = i
|
|
||||||
weight = w
|
|
||||||
c = s
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if min == l {
|
return &composite{chunks}
|
||||||
return -1, ""
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
func parse(p string, m []Glob, d string) []Glob {
|
||||||
}
|
|
||||||
|
|
||||||
func parse(p string, m []Matcher, d []string) ([]Matcher, error) {
|
|
||||||
if len(p) == 0 {
|
if len(p) == 0 {
|
||||||
return m, nil
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
i, c := firstIndexOfChars(p, Chars)
|
i, c := firstIndexOfChars(p, Chars)
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
return append(m, raw{p}), nil
|
return append(m, raw{p})
|
||||||
}
|
}
|
||||||
|
|
||||||
if i > 0 {
|
if i > 0 {
|
||||||
|
@ -65,19 +53,6 @@ func parse(p string, m []Matcher, d []string) ([]Matcher, error) {
|
||||||
return parse(p[i+len(c):], m, d)
|
return parse(p[i+len(c):], m, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New(pattern string, d ...string) (Matcher, error) {
|
|
||||||
chunks, err := parse(pattern, nil, d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(chunks) == 1 {
|
|
||||||
return chunks[0], nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return &composite{chunks}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type raw struct {
|
type raw struct {
|
||||||
s string
|
s string
|
||||||
}
|
}
|
||||||
|
@ -89,39 +64,36 @@ func (self raw) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type multiple struct {
|
type multiple struct {
|
||||||
delimiters []string
|
delimiters string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self multiple) Match(s string) bool {
|
func (self multiple) Match(s string) bool {
|
||||||
i, _ := firstIndexOfChars(s, self.delimiters)
|
return strings.IndexAny(s, self.delimiters) == -1
|
||||||
return i == -1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self multiple) String() string {
|
func (self multiple) String() string {
|
||||||
return fmt.Sprintf("[multiple:%s]", self.delimiters)
|
return fmt.Sprintf("[multiple:%s]", self.delimiters)
|
||||||
}
|
}
|
||||||
|
|
||||||
type single struct {
|
type single struct {
|
||||||
delimiters []string
|
delimiters string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self single) Match(s string) bool {
|
func (self single) Match(s string) bool {
|
||||||
if len(s) != 1 {
|
return len(s) == 1 && strings.IndexAny(s, self.delimiters) == -1
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
i, _ := firstIndexOfChars(s, self.delimiters)
|
|
||||||
|
|
||||||
return i == -1
|
|
||||||
}
|
|
||||||
func (self single) String() string {
|
func (self single) String() string {
|
||||||
return fmt.Sprintf("[single:%s]", self.delimiters)
|
return fmt.Sprintf("[single:%s]", self.delimiters)
|
||||||
}
|
}
|
||||||
|
|
||||||
type composite struct {
|
type composite struct {
|
||||||
chunks []Matcher
|
chunks []Glob
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (self composite) Match(m string) bool {
|
func (self composite) Match(m string) bool {
|
||||||
var prev Matcher
|
var prev Glob
|
||||||
|
|
||||||
for _, c := range self.chunks {
|
for _, c := range self.chunks {
|
||||||
if str, ok := c.(raw); ok {
|
if str, ok := c.(raw); ok {
|
||||||
|
@ -153,3 +125,25 @@ func (self composite) Match(m string) bool {
|
||||||
|
|
||||||
return len(m) == 0
|
return len(m) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func firstIndexOfChars(p string, any []string) (min int, c string) {
|
||||||
|
l := len(p)
|
||||||
|
min = l
|
||||||
|
weight := 0
|
||||||
|
|
||||||
|
for _, s := range any {
|
||||||
|
w := len(s)
|
||||||
|
i := strings.Index(p, s)
|
||||||
|
if i != -1 && i <= min && w > weight {
|
||||||
|
min = i
|
||||||
|
weight = w
|
||||||
|
c = s
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if min == l {
|
||||||
|
return -1, ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
18
glob_test.go
18
glob_test.go
|
@ -56,10 +56,12 @@ func TestGlob(t *testing.T) {
|
||||||
glob(true, "a.?.c", "a.b.c", "."),
|
glob(true, "a.?.c", "a.b.c", "."),
|
||||||
glob(true, "a.?.?", "a.b.c", "."),
|
glob(true, "a.?.?", "a.b.c", "."),
|
||||||
glob(true, "?at", "cat"),
|
glob(true, "?at", "cat"),
|
||||||
|
glob(true, "?at", "fat"),
|
||||||
glob(true, "*", "abc"),
|
glob(true, "*", "abc"),
|
||||||
glob(true, "**", "a.b.c", "."),
|
glob(true, "**", "a.b.c", "."),
|
||||||
|
|
||||||
glob(false, "?at", "at"),
|
glob(false, "?at", "at"),
|
||||||
|
glob(false, "?at", "fat", "f"),
|
||||||
glob(false, "a.*", "a.b.c", "."),
|
glob(false, "a.*", "a.b.c", "."),
|
||||||
glob(false, "a.?.c", "a.bb.c", "."),
|
glob(false, "a.?.c", "a.bb.c", "."),
|
||||||
glob(false, "*", "a.b.c", "."),
|
glob(false, "*", "a.b.c", "."),
|
||||||
|
@ -74,11 +76,7 @@ func TestGlob(t *testing.T) {
|
||||||
glob(false, "*is", "this is a test"),
|
glob(false, "*is", "this is a test"),
|
||||||
glob(false, "*no*", "this is a test"),
|
glob(false, "*no*", "this is a test"),
|
||||||
}{
|
}{
|
||||||
g, err := New(test.pattern, test.delimiters...)
|
g := New(test.pattern, test.delimiters...)
|
||||||
if err != nil {
|
|
||||||
t.Error(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result := g.Match(test.match)
|
result := g.Match(test.match)
|
||||||
if result != test.should {
|
if result != test.should {
|
||||||
|
@ -91,14 +89,14 @@ func TestGlob(t *testing.T) {
|
||||||
const Pattern = "*cat*eyes*"
|
const Pattern = "*cat*eyes*"
|
||||||
const ExpPattern = ".*cat.*eyes.*"
|
const ExpPattern = ".*cat.*eyes.*"
|
||||||
const String = "my cat has very bright eyes"
|
const String = "my cat has very bright eyes"
|
||||||
|
//const Pattern = "*.google.com"
|
||||||
|
//const ExpPattern = ".*google\\.com"
|
||||||
|
//const String = "mail.google.com"
|
||||||
|
|
||||||
func BenchmarkGobwas(b *testing.B) {
|
func BenchmarkGobwas(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
m := New(Pattern)
|
||||||
m, err := New(Pattern)
|
|
||||||
if err != nil {
|
|
||||||
b.Fatal(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
_ = m.Match(String)
|
_ = m.Match(String)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
# glob.[go](https://golang.org)
|
||||||
|
|
||||||
|
Simple globbing library.
|
||||||
|
|
||||||
|
## Install
|
||||||
|
|
||||||
|
```shell
|
||||||
|
go get github.com/gobwas/glob
|
||||||
|
```
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```go
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "github.com/gobwas/glob"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
var g glob.Glob
|
||||||
|
|
||||||
|
// create simple glob
|
||||||
|
g = glob.New("*.github.com")
|
||||||
|
g.Match("api.github.com") // true
|
||||||
|
|
||||||
|
// create new glob with set of delimiters as ["."]
|
||||||
|
g = glob.New("api.*.com", ".")
|
||||||
|
g.Match("api.github.com") // true
|
||||||
|
g.Match("api.gi.hub.com") // false
|
||||||
|
|
||||||
|
// create new glob with set of delimiters as ["."]
|
||||||
|
// but now with super wildcard
|
||||||
|
g = glob.New("api.**.com", ".")
|
||||||
|
g.Match("api.github.com") // true
|
||||||
|
g.Match("api.gi.hub.com") // true
|
||||||
|
|
||||||
|
// create glob with single symbol wildcard
|
||||||
|
g = glob.New("?at")
|
||||||
|
g.Match("cat") // true
|
||||||
|
g.Match("fat") // true
|
||||||
|
g.Match("at") // false
|
||||||
|
|
||||||
|
// create glob with single symbol wildcard and delimiters ["f"]
|
||||||
|
g = glob.New("?at", "f")
|
||||||
|
g.Match("cat") // true
|
||||||
|
g.Match("fat") // false
|
||||||
|
g.Match("at") // false
|
||||||
|
}
|
||||||
|
|
||||||
|
```
|
Loading…
Reference in New Issue