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
// if is decimal, we don't need this
hasScientificNotion := false
hasIChar := false
scIndex := -1
for i, c := range input {
if hasDecimal {
@ -365,6 +366,10 @@ func NewFromString(input string) (Value, error) {
scIndex = i
break
}
if c == 'i' || c == 'I' {
hasIChar = true
break
}
}
if hasDecimal {
after := input[dotIndex+1:]
@ -395,6 +400,16 @@ func NewFromString(input string) (Value, error) {
return 0, err
}
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 {
v, err := strconv.ParseInt(input, 10, 64)
if err != nil {

View File

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

View File

@ -138,6 +138,15 @@ func TestFromString(t *testing.T) {
assert.Equal(t, Zero, f)
f = MustNewFromString("")
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) {
@ -177,6 +186,10 @@ func TestJson(t *testing.T) {
_ = json.Unmarshal([]byte("0.000062"), &q)
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) {
@ -216,6 +229,10 @@ func TestYaml(t *testing.T) {
_ = yaml.Unmarshal([]byte("0.000062"), &q)
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) {