compare operator support float first

This commit is contained in:
murasame
2025-01-03 17:42:34 +08:00
parent 43a40ec044
commit 0741a6ce53
5 changed files with 57 additions and 0 deletions
+5
View File
@@ -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)
})
}
+6
View File
@@ -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
BIN
View File
Binary file not shown.
+27
View File
@@ -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)
+19
View File
@@ -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) {