// Package glob implements the tiny wildcard language used by rules.toml. // // Only '*' (any run of characters, including none) and '?' (exactly one // character) are special; everything else matches literally. Unlike path.Match // there is no separator handling, because we match statement descriptions, not // paths. Matching is case-insensitive. package glob import "strings" // Match reports whether s matches pattern. func Match(pattern, s string) bool { return match([]rune(strings.ToUpper(pattern)), []rune(strings.ToUpper(s))) } // match is the classic two-pointer wildcard algorithm: linear time, no // backtracking blowup on patterns like "*a*a*a*". func match(p, s []rune) bool { var ( pi, si int star = -1 // index in p of the last '*' seen starMatch int // index in s that '*' was assumed to match up to hasStar bool ) for si < len(s) { switch { case pi < len(p) && (p[pi] == '?' || p[pi] == s[si]): pi++ si++ case pi < len(p) && p[pi] == '*': star, hasStar = pi, true starMatch = si pi++ case hasStar: // Backtrack: let the last '*' swallow one more character. starMatch++ pi, si = star+1, starMatch default: return false } } for pi < len(p) && p[pi] == '*' { pi++ } return pi == len(p) }