ergo/irc/utils/glob.go

67 lines
1.4 KiB
Go
Raw Normal View History

2020-05-05 04:29:10 +02:00
// Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
// released under the MIT license
package utils
import (
"regexp"
"regexp/syntax"
"strings"
2020-05-05 04:29:10 +02:00
)
// yet another glob implementation in Go
func addRegexp(buf *strings.Builder, glob string, submatch bool) (err error) {
for _, r := range glob {
switch r {
case '*':
2020-05-13 09:41:00 +02:00
if submatch {
buf.WriteString("(.*)")
} else {
buf.WriteString(".*")
}
case '?':
2020-05-13 09:41:00 +02:00
if submatch {
buf.WriteString("(.)")
} else {
buf.WriteString(".")
}
case 0xFFFD:
2020-05-13 09:41:00 +02:00
return &syntax.Error{Code: syntax.ErrInvalidUTF8, Expr: glob}
default:
buf.WriteString(regexp.QuoteMeta(string(r)))
2020-05-05 04:29:10 +02:00
}
}
2020-05-13 09:41:00 +02:00
return
}
func CompileGlob(glob string, submatch bool) (result *regexp.Regexp, err error) {
var buf strings.Builder
2020-05-13 09:41:00 +02:00
buf.WriteByte('^')
err = addRegexp(&buf, glob, submatch)
if err != nil {
return
}
2020-05-05 04:29:10 +02:00
buf.WriteByte('$')
return regexp.Compile(buf.String())
}
2020-05-13 09:41:00 +02:00
2020-05-13 16:07:54 +02:00
// Compile a list of globs into a single or-expression that matches any one of them.
// This is used for channel ban/invite/exception lists. It's applicable to k-lines
// but we're not using it there yet.
2020-05-13 09:41:00 +02:00
func CompileMasks(masks []string) (result *regexp.Regexp, err error) {
var buf strings.Builder
2020-05-13 09:41:00 +02:00
buf.WriteString("^(")
for i, mask := range masks {
err = addRegexp(&buf, mask, false)
if err != nil {
return
}
if i != len(masks)-1 {
buf.WriteByte('|')
}
}
buf.WriteString(")$")
return regexp.Compile(buf.String())
}