quote meta func

This commit is contained in:
gobwas 2016-02-24 23:53:19 +03:00
parent f910d4c1c7
commit 1801ade38c
3 changed files with 55 additions and 2 deletions

19
glob.go
View File

@ -54,3 +54,22 @@ func MustCompile(pattern string, separators ...rune) Glob {
return g return g
} }
// QuoteMeta returns a string that quotes all glob pattern metacharacters
// inside the argument text; For example, QuoteMeta(`{foo*}`) returns `\[foo\*\]`.
func QuoteMeta(s string) string {
b := make([]byte, 2*len(s))
// A byte loop is correct because all metacharacters are ASCII.
j := 0
for i := 0; i < len(s); i++ {
if special(s[i]) {
b[j] = '\\'
j++
}
b[j] = s[i]
j++
}
return string(b[0:j])
}

View File

@ -150,6 +150,22 @@ func TestGlob(t *testing.T) {
} }
} }
func TestQuoteMeta(t *testing.T) {
for id, test := range []struct {
in, out string
}{
{
in: `[foo*]`,
out: `\[foo\*\]`,
},
} {
act := QuoteMeta(test.in)
if act != test.out {
t.Errorf("#%d QuoteMeta(%q) = %q; want %q", id, test.in, act, test.out)
}
}
}
func BenchmarkParseGlob(b *testing.B) { func BenchmarkParseGlob(b *testing.B) {
for i := 0; i < b.N; i++ { for i := 0; i < b.N; i++ {
Compile(pattern_all) Compile(pattern_all)
@ -193,12 +209,12 @@ func BenchmarkAllGlobMismatch(b *testing.B) {
_ = m.Match(fixture_all_mismatch) _ = m.Match(fixture_all_mismatch)
} }
} }
func BenchmarkAllGlobMatchParallel(b *testing.B) { func BenchmarkAllGlobMismatchParallel(b *testing.B) {
m, _ := Compile(pattern_all) m, _ := Compile(pattern_all)
b.RunParallel(func(pb *testing.PB) { b.RunParallel(func(pb *testing.PB) {
for pb.Next() { for pb.Next() {
_ = m.Match(fixture_all_match) _ = m.Match(fixture_all_mismatch)
} }
}) })
} }

View File

@ -1,6 +1,7 @@
package glob package glob
import ( import (
"bytes"
"fmt" "fmt"
"strings" "strings"
"unicode/utf8" "unicode/utf8"
@ -19,6 +20,23 @@ const (
char_range_between = '-' char_range_between = '-'
) )
var specials = []byte{
char_any,
char_separator,
char_single,
char_escape,
char_range_open,
char_range_close,
char_terms_open,
char_terms_close,
char_range_not,
char_range_between,
}
func special(c byte) bool {
return bytes.IndexByte(specials, c) != -1
}
var eof rune = 0 var eof rune = 0
type stateFn func(*lexer) stateFn type stateFn func(*lexer) stateFn