Merge pull request #913 from COLDTURNIP/fix/fixedpoint_support_inf_string_unmarshal

fix: fixedpoint UnarshalJson on inf
This commit is contained in:
Yo-An Lin 2022-09-02 15:14:34 +08:00 committed by GitHub
commit 55474b4bf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 8 deletions

View File

@ -347,6 +347,7 @@ func NewFromString(input string) (Value, error) {
decimalCount := 0 decimalCount := 0
// if is decimal, we don't need this // if is decimal, we don't need this
hasScientificNotion := false hasScientificNotion := false
hasIChar := false
scIndex := -1 scIndex := -1
for i, c := range input { for i, c := range input {
if hasDecimal { if hasDecimal {
@ -365,6 +366,10 @@ func NewFromString(input string) (Value, error) {
scIndex = i scIndex = i
break break
} }
if c == 'i' || c == 'I' {
hasIChar = true
break
}
} }
if hasDecimal { if hasDecimal {
after := input[dotIndex+1:] after := input[dotIndex+1:]
@ -395,6 +400,16 @@ func NewFromString(input string) (Value, error) {
return 0, err return 0, err
} }
return Value(int64(math.Trunc(v))), nil return Value(int64(math.Trunc(v))), nil
} else if hasIChar {
if floatV, err := strconv.ParseFloat(input, 64); nil != err {
return 0, err
} else if math.IsInf(floatV, 1) {
return PosInf, nil
} else if math.IsInf(floatV, -1) {
return NegInf, nil
} else {
return 0, fmt.Errorf("fixedpoint.Value parse error, invalid input string %s", input)
}
} else { } else {
v, err := strconv.ParseInt(input, 10, 64) v, err := strconv.ParseInt(input, 10, 64)
if err != nil { if err != nil {

View File

@ -500,7 +500,7 @@ func NewFromString(s string) (Value, error) {
} }
r := &reader{s, 0} r := &reader{s, 0}
sign := r.getSign() sign := r.getSign()
if r.matchStr("inf") { if r.matchStrIgnoreCase("inf") {
return Inf(sign), nil return Inf(sign), nil
} }
coef, exp := r.getCoef() coef, exp := r.getCoef()
@ -550,7 +550,7 @@ func NewFromBytes(s []byte) (Value, error) {
} }
r := &readerBytes{s, 0} r := &readerBytes{s, 0}
sign := r.getSign() sign := r.getSign()
if r.matchStr("inf") { if r.matchStrIgnoreCase("inf") {
return Inf(sign), nil return Inf(sign), nil
} }
coef, exp := r.getCoef() coef, exp := r.getCoef()
@ -631,13 +631,18 @@ func (r *readerBytes) matchDigit() bool {
return false return false
} }
func (r *readerBytes) matchStr(pre string) bool { func (r *readerBytes) matchStrIgnoreCase(pre string) bool {
for i, c := range r.s[r.i:] { pre = strings.ToLower(pre)
boundary := r.i + len(pre)
if boundary > len(r.s) {
return false
}
for i, c := range bytes.ToLower(r.s[r.i:boundary]) {
if pre[i] != c { if pre[i] != c {
return false return false
} }
} }
r.i += len(pre) r.i = boundary
return true return true
} }
@ -745,9 +750,15 @@ func (r *reader) matchDigit() bool {
return false return false
} }
func (r *reader) matchStr(pre string) bool { func (r *reader) matchStrIgnoreCase(pre string) bool {
if strings.HasPrefix(r.s[r.i:], pre) { boundary := r.i + len(pre)
r.i += len(pre) if boundary > len(r.s) {
return false
}
data := strings.ToLower(r.s[r.i:boundary])
pre = strings.ToLower(pre)
if data == pre {
r.i = boundary
return true return true
} }
return false return false

View File

@ -138,6 +138,15 @@ func TestFromString(t *testing.T) {
assert.Equal(t, Zero, f) assert.Equal(t, Zero, f)
f = MustNewFromString("") f = MustNewFromString("")
assert.Equal(t, Zero, f) assert.Equal(t, Zero, f)
for _, s := range []string{"inf", "Inf", "INF", "iNF"} {
f = MustNewFromString(s)
assert.Equal(t, PosInf, f)
f = MustNewFromString("+" + s)
assert.Equal(t, PosInf, f)
f = MustNewFromString("-" + s)
assert.Equal(t, NegInf, f)
}
} }
func TestJson(t *testing.T) { func TestJson(t *testing.T) {
@ -177,6 +186,10 @@ func TestJson(t *testing.T) {
_ = json.Unmarshal([]byte("0.000062"), &q) _ = json.Unmarshal([]byte("0.000062"), &q)
assert.Equal(t, "0.00006194", q.Sub(p).String()) assert.Equal(t, "0.00006194", q.Sub(p).String())
assert.NoError(t, json.Unmarshal([]byte(`"inf"`), &p))
assert.NoError(t, json.Unmarshal([]byte(`"+Inf"`), &q))
assert.Equal(t, PosInf, p)
assert.Equal(t, p, q)
} }
func TestYaml(t *testing.T) { func TestYaml(t *testing.T) {
@ -216,6 +229,10 @@ func TestYaml(t *testing.T) {
_ = yaml.Unmarshal([]byte("0.000062"), &q) _ = yaml.Unmarshal([]byte("0.000062"), &q)
assert.Equal(t, "0.00006194", q.Sub(p).String()) assert.Equal(t, "0.00006194", q.Sub(p).String())
assert.NoError(t, json.Unmarshal([]byte(`"inf"`), &p))
assert.NoError(t, json.Unmarshal([]byte(`"+Inf"`), &q))
assert.Equal(t, PosInf, p)
assert.Equal(t, p, q)
} }
func TestNumFractionalDigits(t *testing.T) { func TestNumFractionalDigits(t *testing.T) {