syncthing/lib/fnmatch/fnmatch.go

80 lines
2.0 KiB
Go
Raw Normal View History

2014-11-16 20:13:20 +00:00
// Copyright (C) 2014 The Syncthing Authors.
2014-09-29 19:43:32 +00:00
//
2015-03-07 20:36:35 +00:00
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.
package fnmatch
import (
"path/filepath"
"regexp"
"runtime"
"strings"
)
const (
2015-04-04 20:03:03 +00:00
NoEscape = (1 << iota)
PathName
CaseFold
)
func Convert(pattern string, flags int) (*regexp.Regexp, error) {
2014-08-26 11:07:59 +00:00
any := "."
switch runtime.GOOS {
case "windows":
2015-04-04 20:03:03 +00:00
flags |= NoEscape | CaseFold
pattern = filepath.FromSlash(pattern)
2015-04-04 20:03:03 +00:00
if flags&PathName != 0 {
any = `[^\\]`
2014-08-26 11:07:59 +00:00
}
case "darwin":
2015-04-04 20:03:03 +00:00
flags |= CaseFold
fallthrough
default:
2015-04-04 20:03:03 +00:00
if flags&PathName != 0 {
any = `[^/]`
}
}
2015-04-04 20:03:03 +00:00
if flags&NoEscape != 0 {
pattern = strings.Replace(pattern, `\`, `\\`, -1)
} else {
pattern = strings.Replace(pattern, `\*`, "[:escapedstar:]", -1)
pattern = strings.Replace(pattern, `\?`, "[:escapedques:]", -1)
pattern = strings.Replace(pattern, `\.`, "[:escapeddot:]", -1)
}
// Characters that are special in regexps but not in glob, must be
// escaped.
for _, char := range []string{`.`, `+`, `$`, `^`, `(`, `)`, `|`} {
pattern = strings.Replace(pattern, char, `\`+char, -1)
}
pattern = strings.Replace(pattern, `**`, `[:doublestar:]`, -1)
pattern = strings.Replace(pattern, `*`, any+`*`, -1)
pattern = strings.Replace(pattern, `[:doublestar:]`, `.*`, -1)
pattern = strings.Replace(pattern, `?`, any, -1)
pattern = strings.Replace(pattern, `[:escapedstar:]`, `\*`, -1)
pattern = strings.Replace(pattern, `[:escapedques:]`, `\?`, -1)
pattern = strings.Replace(pattern, `[:escapeddot:]`, `\.`, -1)
pattern = `^` + pattern + `$`
2015-04-04 20:03:03 +00:00
if flags&CaseFold != 0 {
pattern = `(?i)` + pattern
}
return regexp.Compile(pattern)
}
2015-04-28 20:32:10 +00:00
// Match matches the pattern against the string, with the given flags, and
// returns true if the match is successful.
func Match(pattern, s string, flags int) (bool, error) {
exp, err := Convert(pattern, flags)
if err != nil {
return false, err
}
return exp.MatchString(s), nil
}