151 lines
3.9 KiB
Go
151 lines
3.9 KiB
Go
package evaluate
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/kashav/fsql/tokenizer"
|
|
"github.com/kashav/fsql/transform"
|
|
)
|
|
|
|
// cmpAlpha performs alphabetic comparison on a and b.
|
|
func cmpAlpha(o *Opts, a, b interface{}) (result bool, err error) {
|
|
switch o.Operator {
|
|
case tokenizer.Equals:
|
|
result = a.(string) == b.(string)
|
|
case tokenizer.NotEquals:
|
|
result = a.(string) != b.(string)
|
|
case tokenizer.Like:
|
|
aStr, bStr := a.(string), b.(string)
|
|
if strings.HasPrefix(bStr, "%") && strings.HasSuffix(bStr, "%") {
|
|
result = strings.Contains(aStr, bStr[1:len(bStr)-1])
|
|
} else if strings.HasPrefix(bStr, "%") {
|
|
result = strings.HasSuffix(aStr, bStr[1:])
|
|
} else if strings.HasSuffix(bStr, "%") {
|
|
result = strings.HasPrefix(aStr, bStr[:len(bStr)-1])
|
|
} else {
|
|
result = strings.Contains(aStr, bStr)
|
|
}
|
|
case tokenizer.RLike:
|
|
result = regexp.MustCompile(b.(string)).MatchString(a.(string))
|
|
case tokenizer.In:
|
|
switch t := b.(type) {
|
|
case map[interface{}]bool:
|
|
if _, ok := t[a.(string)]; ok {
|
|
result = true
|
|
}
|
|
case []string:
|
|
for _, el := range t {
|
|
if a.(string) == el {
|
|
result = true
|
|
}
|
|
}
|
|
case string:
|
|
for _, el := range strings.Split(t, ",") {
|
|
if a.(string) == el {
|
|
result = true
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
err = &ErrUnsupportedOperator{o.Attribute, o.Operator}
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
// cmpNumeric performs numeric comparison on a and b.
|
|
func cmpNumeric(o *Opts, a, b interface{}) (result bool, err error) {
|
|
switch o.Operator {
|
|
case tokenizer.Equals:
|
|
result = a.(int64) == b.(int64)
|
|
case tokenizer.NotEquals:
|
|
result = a.(int64) != b.(int64)
|
|
case tokenizer.GreaterThanEquals:
|
|
result = a.(int64) >= b.(int64)
|
|
case tokenizer.GreaterThan:
|
|
result = a.(int64) > b.(int64)
|
|
case tokenizer.LessThanEquals:
|
|
result = a.(int64) <= b.(int64)
|
|
case tokenizer.LessThan:
|
|
result = a.(int64) < b.(int64)
|
|
case tokenizer.In:
|
|
if _, ok := b.(map[interface{}]bool)[a.(int64)]; ok {
|
|
result = true
|
|
}
|
|
default:
|
|
err = &ErrUnsupportedOperator{o.Attribute, o.Operator}
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
// cmpTime performs time comparison on a and b.
|
|
func cmpTime(o *Opts, a, b interface{}) (result bool, err error) {
|
|
switch o.Operator {
|
|
case tokenizer.Equals:
|
|
result = a.(time.Time).Equal(b.(time.Time))
|
|
case tokenizer.NotEquals:
|
|
result = !a.(time.Time).Equal(b.(time.Time))
|
|
case tokenizer.GreaterThanEquals:
|
|
result = a.(time.Time).After(b.(time.Time)) || a.(time.Time).Equal(b.(time.Time))
|
|
case tokenizer.GreaterThan:
|
|
result = a.(time.Time).After(b.(time.Time))
|
|
case tokenizer.LessThanEquals:
|
|
result = a.(time.Time).Before(b.(time.Time)) || a.(time.Time).Equal(b.(time.Time))
|
|
case tokenizer.LessThan:
|
|
result = a.(time.Time).Before(b.(time.Time))
|
|
case tokenizer.In:
|
|
if _, ok := b.(map[interface{}]bool)[a.(time.Time)]; ok {
|
|
result = true
|
|
}
|
|
default:
|
|
err = &ErrUnsupportedOperator{o.Attribute, o.Operator}
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
// cmpMode performs mode comparison with info and typ.
|
|
func cmpMode(o *Opts) (result bool, err error) {
|
|
if o.Operator != tokenizer.Is {
|
|
return false, &ErrUnsupportedOperator{o.Attribute, o.Operator}
|
|
}
|
|
switch strings.ToUpper(o.Value.(string)) {
|
|
case "DIR":
|
|
result = o.File.Mode().IsDir()
|
|
case "REG":
|
|
result = o.File.Mode().IsRegular()
|
|
default:
|
|
result = false
|
|
}
|
|
return result, err
|
|
}
|
|
|
|
// cmpHash computes the hash of the current file and compares it with the
|
|
// provided value.
|
|
func cmpHash(o *Opts) (result bool, err error) {
|
|
hashType := "SHA1"
|
|
if len(o.Modifiers) > 0 {
|
|
hashType = o.Modifiers[0].Name
|
|
}
|
|
|
|
hashFunc := transform.FindHash(hashType)
|
|
if hashFunc == nil {
|
|
return false, fmt.Errorf("unexpected hash algorithm %s", hashType)
|
|
}
|
|
h, err := transform.ComputeHash(o.File, o.Path, hashFunc())
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
switch o.Operator {
|
|
case tokenizer.Equals:
|
|
result = h == o.Value
|
|
case tokenizer.NotEquals:
|
|
result = h != o.Value
|
|
default:
|
|
err = &ErrUnsupportedOperator{o.Attribute, o.Operator}
|
|
}
|
|
return result, err
|
|
}
|