ircd/irc/utils/glob.go

67 lines
1.5 KiB
Go

// Copyright (c) 2020 Shivaram Lingamneni <slingamn@cs.stanford.edu>
// released under the MIT license
package utils
import (
"regexp"
"regexp/syntax"
"strings"
)
// yet another glob implementation in Go
func addRegexp(buf *strings.Builder, glob string, submatch bool) (err error) {
for _, r := range glob {
switch r {
case '*':
if submatch {
buf.WriteString("(.*)")
} else {
buf.WriteString(".*")
}
case '?':
if submatch {
buf.WriteString("(.)")
} else {
buf.WriteString(".")
}
case 0xFFFD:
return &syntax.Error{Code: syntax.ErrInvalidUTF8, Expr: glob}
default:
buf.WriteString(regexp.QuoteMeta(string(r)))
}
}
return
}
func CompileGlob(glob string, submatch bool) (result *regexp.Regexp, err error) {
var buf strings.Builder
buf.WriteByte('^')
err = addRegexp(&buf, glob, submatch)
if err != nil {
return
}
buf.WriteByte('$')
return regexp.Compile(buf.String())
}
// CompileMasks 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.
func CompileMasks(masks []string) (result *regexp.Regexp, err error) {
var buf strings.Builder
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())
}