66 lines
1.3 KiB
Go
66 lines
1.3 KiB
Go
package miniredis
|
|
|
|
// Translate the 'KEYS' argument ('foo*', 'f??', &c.) into a regexp.
|
|
|
|
import (
|
|
"bytes"
|
|
"regexp"
|
|
)
|
|
|
|
// patternRE compiles a KEYS argument to a regexp. Returns nil if the given
|
|
// pattern will never match anything.
|
|
// The general strategy is to sandwich all non-meta characters between \Q...\E.
|
|
func patternRE(k string) *regexp.Regexp {
|
|
re := bytes.Buffer{}
|
|
re.WriteString(`^\Q`)
|
|
for i := 0; i < len(k); i++ {
|
|
p := k[i]
|
|
switch p {
|
|
case '*':
|
|
re.WriteString(`\E.*\Q`)
|
|
case '?':
|
|
re.WriteString(`\E.\Q`)
|
|
case '[':
|
|
charClass := bytes.Buffer{}
|
|
i++
|
|
for ; i < len(k); i++ {
|
|
if k[i] == ']' {
|
|
break
|
|
}
|
|
if k[i] == '\\' {
|
|
if i == len(k)-1 {
|
|
// Ends with a '\'. U-huh.
|
|
return nil
|
|
}
|
|
charClass.WriteByte(k[i])
|
|
i++
|
|
charClass.WriteByte(k[i])
|
|
continue
|
|
}
|
|
charClass.WriteByte(k[i])
|
|
}
|
|
if charClass.Len() == 0 {
|
|
// '[]' is valid in Redis, but matches nothing.
|
|
return nil
|
|
}
|
|
re.WriteString(`\E[`)
|
|
re.Write(charClass.Bytes())
|
|
re.WriteString(`]\Q`)
|
|
|
|
case '\\':
|
|
if i == len(k)-1 {
|
|
// Ends with a '\'. U-huh.
|
|
return nil
|
|
}
|
|
// Forget the \, keep the next char.
|
|
i++
|
|
re.WriteByte(k[i])
|
|
continue
|
|
default:
|
|
re.WriteByte(p)
|
|
}
|
|
}
|
|
re.WriteString(`\E$`)
|
|
return regexp.MustCompile(re.String())
|
|
}
|