mirror of
https://github.com/bytedance/arishem.git
synced 2026-04-22 23:07:13 +08:00
compare operator support float first
This commit is contained in:
@@ -19,6 +19,7 @@ package arishem
|
||||
import (
|
||||
"github.com/antlr/antlr4/runtime/Go/antlr/v4"
|
||||
"github.com/bytedance/arishem/internal/core"
|
||||
"github.com/bytedance/arishem/internal/operator"
|
||||
"github.com/bytedance/arishem/typedef"
|
||||
"sync"
|
||||
)
|
||||
@@ -63,6 +64,9 @@ type Configuration struct {
|
||||
|
||||
// sub condition configuration
|
||||
SubCond SubConditionManage
|
||||
|
||||
// when float first set to true, compare operator will judge any of float number between left and right, and use float64 to compare
|
||||
FloatFirst bool
|
||||
}
|
||||
|
||||
func (c *Configuration) getConditionFinder() func(string) (antlr.ParseTree, error) {
|
||||
@@ -119,6 +123,7 @@ func Initialize(cfg *Configuration, opts ...Option) {
|
||||
ApplyOptions(arishemConfiguration, opts...)
|
||||
core.SetFeaturePreParseCache(arishemConfiguration.FeatVisitCache)
|
||||
core.SetFeatureFetchPool(arishemConfiguration.FeatureFetchPool)
|
||||
operator.SetFloatFirst(arishemConfiguration.FloatFirst)
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -120,6 +120,12 @@ func WithCustomSubConditionConfig(sc SubConditionManage) Option {
|
||||
}
|
||||
}
|
||||
|
||||
func WithFloatFirstNumberCompare(ff bool) Option {
|
||||
return func(cfg *Configuration) {
|
||||
cfg.FloatFirst = ff
|
||||
}
|
||||
}
|
||||
|
||||
type defaultSubConditionManage struct {
|
||||
lock sync.RWMutex
|
||||
ExprDict map[string]string
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -22,8 +22,20 @@ import (
|
||||
"github.com/bytedance/arishem/tools"
|
||||
"math/big"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
floatFirst = false
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func SetFloatFirst(ff bool) {
|
||||
once.Do(func() {
|
||||
floatFirst = ff
|
||||
})
|
||||
}
|
||||
|
||||
// CompareOperator will invoke func(cmp int) bool
|
||||
type CompareOperator struct {
|
||||
opr func(cmp int) bool
|
||||
@@ -53,6 +65,15 @@ func LessOrEqualOperate(cmp int) bool {
|
||||
return cmp <= 0
|
||||
}
|
||||
|
||||
func (c *CompareOperator) floatFirstCompare(left interface{}, right interface{}) (bool, error) {
|
||||
lv, _ := tools.ConvToFloat64(left)
|
||||
rv, err := tools.ConvToFloat64(right)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("[use float-first] right type to float error, right(%T,%v)", right, right)
|
||||
}
|
||||
return c.opr(big.NewFloat(lv).Cmp(big.NewFloat(rv))), nil
|
||||
}
|
||||
|
||||
// Operate the left and value whether valid by opr, will convert left to right type implicit.
|
||||
func (c *CompareOperator) Operate(left, right interface{}) (bool, error) {
|
||||
if c.opr == nil {
|
||||
@@ -61,6 +82,9 @@ func (c *CompareOperator) Operate(left, right interface{}) (bool, error) {
|
||||
// convert to left type to right type
|
||||
switch right.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
if floatFirst && tools.IsFloatNumber(left) {
|
||||
return c.floatFirstCompare(left, right)
|
||||
}
|
||||
lv, err := tools.ConvToInt64(left)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("left to right type(int) error, left(%T,%v)", left, left)
|
||||
@@ -74,6 +98,9 @@ func (c *CompareOperator) Operate(left, right interface{}) (bool, error) {
|
||||
return c.opr(+1), nil
|
||||
}
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
if floatFirst && tools.IsFloatNumber(left) {
|
||||
return c.floatFirstCompare(left, right)
|
||||
}
|
||||
lv, err := tools.ConvToUint64(left)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("left to right type(uint) error, left(%T,%v)", left, left)
|
||||
|
||||
@@ -37,6 +37,25 @@ func IsNumber(target interface{}) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func IsFloatNumber(target interface{}) bool {
|
||||
if target == nil {
|
||||
return false
|
||||
}
|
||||
switch t := target.(type) {
|
||||
case float32, float64:
|
||||
return true
|
||||
case string:
|
||||
// a string first has '.' or 'eE' before it can be a float number
|
||||
if strings.Contains(t, ".") || strings.ContainsAny(t, "eE") {
|
||||
_, err := strconv.ParseFloat(t, 64)
|
||||
return err == nil
|
||||
}
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// StringToNumber convert string to number type, float format will be converted to float64 which support scientific format,
|
||||
// and a signed number will be converted to int64, unsigned number will be converted to uint64.
|
||||
func StringToNumber(numStr string) (num interface{}, err error) {
|
||||
|
||||
Reference in New Issue
Block a user