forked from mirror/gjson
Better safe integer range for numbers
This commit optimizes the safe float to int conversion function by using the full -9007199254740991 to 9007199254740991 range as suggested at: https://tc39.es/ecma262/#sec-number.min_safe_integer closes #174
This commit is contained in:
parent
2f043b7abd
commit
5100d6926a
50
gjson.go
50
gjson.go
|
@ -125,17 +125,18 @@ func (t Result) Int() int64 {
|
||||||
return n
|
return n
|
||||||
case Number:
|
case Number:
|
||||||
// try to directly convert the float64 to int64
|
// try to directly convert the float64 to int64
|
||||||
n, ok := floatToInt(t.Num)
|
i, ok := safeInt(t.Num)
|
||||||
if !ok {
|
if ok {
|
||||||
|
return i
|
||||||
|
}
|
||||||
// now try to parse the raw string
|
// now try to parse the raw string
|
||||||
n, ok = parseInt(t.Raw)
|
i, ok = parseInt(t.Raw)
|
||||||
if !ok {
|
if ok {
|
||||||
|
return i
|
||||||
|
}
|
||||||
// fallback to a standard conversion
|
// fallback to a standard conversion
|
||||||
return int64(t.Num)
|
return int64(t.Num)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uint returns an unsigned integer representation.
|
// Uint returns an unsigned integer representation.
|
||||||
|
@ -150,17 +151,18 @@ func (t Result) Uint() uint64 {
|
||||||
return n
|
return n
|
||||||
case Number:
|
case Number:
|
||||||
// try to directly convert the float64 to uint64
|
// try to directly convert the float64 to uint64
|
||||||
n, ok := floatToUint(t.Num)
|
i, ok := safeInt(t.Num)
|
||||||
if !ok {
|
if ok && i >= 0 {
|
||||||
|
return uint64(i)
|
||||||
|
}
|
||||||
// now try to parse the raw string
|
// now try to parse the raw string
|
||||||
n, ok = parseUint(t.Raw)
|
u, ok := parseUint(t.Raw)
|
||||||
if !ok {
|
if ok {
|
||||||
|
return u
|
||||||
|
}
|
||||||
// fallback to a standard conversion
|
// fallback to a standard conversion
|
||||||
return uint64(t.Num)
|
return uint64(t.Num)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Float returns an float64 representation.
|
// Float returns an float64 representation.
|
||||||
|
@ -2525,25 +2527,11 @@ func parseInt(s string) (n int64, ok bool) {
|
||||||
return n, true
|
return n, true
|
||||||
}
|
}
|
||||||
|
|
||||||
const minUint53 = 0
|
func safeInt(f float64) (n int64, ok bool) {
|
||||||
const maxUint53 = 4503599627370495
|
if f < -9007199254740991 || f > 9007199254740991 {
|
||||||
const minInt53 = -2251799813685248
|
|
||||||
const maxInt53 = 2251799813685247
|
|
||||||
|
|
||||||
func floatToUint(f float64) (n uint64, ok bool) {
|
|
||||||
n = uint64(f)
|
|
||||||
if float64(n) == f && n >= minUint53 && n <= maxUint53 {
|
|
||||||
return n, true
|
|
||||||
}
|
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
|
||||||
|
|
||||||
func floatToInt(f float64) (n int64, ok bool) {
|
|
||||||
n = int64(f)
|
|
||||||
if float64(n) == f && n >= minInt53 && n <= maxInt53 {
|
|
||||||
return n, true
|
|
||||||
}
|
}
|
||||||
return 0, false
|
return int64(f), true
|
||||||
}
|
}
|
||||||
|
|
||||||
// execModifier parses the path to find a matching modifier function.
|
// execModifier parses the path to find a matching modifier function.
|
||||||
|
|
Loading…
Reference in New Issue