-
Notifications
You must be signed in to change notification settings - Fork 1
/
op_compare.go
157 lines (141 loc) · 3.56 KB
/
op_compare.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package cond
import (
"reflect"
"github.com/shopspring/decimal"
)
const (
opEQ Operator = "$eq"
opGT = "$gt"
opGTE = "$gte"
opLT = "$lt"
opLTE = "$lte"
opNE = "$ne"
)
var compareOperators []Operator = []Operator{opEQ, opGT, opGTE, opLT, opLTE, opNE}
func isCompareOperator(op Operator) bool {
for _, v := range compareOperators {
if op == v {
return true
}
}
return false
}
func opCompareFunc(s *State, l string, op Operator, r interface{}, reg map[string]interface{}) bool {
if !isCompareOperator(op) {
panic("not a compare operator :" + string(op))
}
lval := s.loadValFromSession(l, reg)
if lval == nil {
return false
}
switch reflect.TypeOf(lval).Kind() {
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Bool, reflect.String:
return compareValue(s, op, lval, r, reg)
default:
panic("not comparable type : " + reflect.TypeOf(lval).Kind().String())
}
}
type valueType int
const (
valueTypeBool valueType = iota
valueTypeDecimal
valueTypeString
valueTypeOther
)
func getValType(kind reflect.Kind) valueType {
switch kind {
case reflect.Float32, reflect.Float64, reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return valueTypeDecimal
case reflect.Bool:
return valueTypeBool
case reflect.String:
return valueTypeString
default:
return valueTypeOther
}
}
func getDecimalValue(i interface{}) decimal.Decimal {
switch v := i.(type) {
case int:
return decimal.New(int64(v), 0)
case int8:
return decimal.New(int64(v), 0)
case int16:
return decimal.New(int64(v), 0)
case int32:
return decimal.New(int64(v), 0)
case int64:
return decimal.New(int64(v), 0)
case uint:
return decimal.New(int64(v), 0)
case uint8:
return decimal.New(int64(v), 0)
case uint16:
return decimal.New(int64(v), 0)
case uint32:
return decimal.New(int64(v), 0)
case uint64:
return decimal.New(int64(v), 0)
case float32:
return decimal.NewFromFloat32(v)
case float64:
return decimal.NewFromFloat(v)
}
return decimal.New(0, 0)
}
func compareValue(s *State, op Operator, i1 interface{}, ir interface{}, reg map[string]interface{}) bool {
i2 := s.loadVarible(ir, reg)
if getValType(reflect.TypeOf(i1).Kind()) != getValType(reflect.TypeOf(i2).Kind()) {
return false
}
type1 := getValType(reflect.TypeOf(i1).Kind())
switch type1 {
case valueTypeBool:
val1, val2 := i1.(bool), i2.(bool)
if op == opEQ {
return val1 == val2
} else if op == opNE {
return val1 != val2
} else {
return false
}
case valueTypeDecimal:
val1, val2 := getDecimalValue(i1), getDecimalValue(i2)
if op == opEQ {
return val1.Equal(val2)
} else if op == opNE {
return !val1.Equal(val2)
} else if op == opGT {
return val1.GreaterThan(val2)
} else if op == opGTE {
return val1.GreaterThanOrEqual(val2)
} else if op == opLT {
return val1.LessThan(val2)
} else if op == opLTE {
return val1.LessThanOrEqual(val2)
} else {
return false
}
case valueTypeString:
val1, val2 := i1.(string), i2.(string)
if op == opEQ {
return val1 == val2
} else if op == opNE {
return val1 != val2
} else if op == opGT {
return val1 > val2
} else if op == opGTE {
return val1 >= val2
} else if op == opLT {
return val1 < val2
} else if op == opLTE {
return val1 <= val2
} else {
return false
}
default:
return false
}
}