mirror of https://github.com/tidwall/gjson.git
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
60
gjson.go
60
gjson.go
|
@ -125,16 +125,17 @@ func (t Result) Int() int64 {
|
|||
return n
|
||||
case Number:
|
||||
// try to directly convert the float64 to int64
|
||||
n, ok := floatToInt(t.Num)
|
||||
if !ok {
|
||||
// now try to parse the raw string
|
||||
n, ok = parseInt(t.Raw)
|
||||
if !ok {
|
||||
// fallback to a standard conversion
|
||||
return int64(t.Num)
|
||||
}
|
||||
i, ok := safeInt(t.Num)
|
||||
if ok {
|
||||
return i
|
||||
}
|
||||
return n
|
||||
// now try to parse the raw string
|
||||
i, ok = parseInt(t.Raw)
|
||||
if ok {
|
||||
return i
|
||||
}
|
||||
// fallback to a standard conversion
|
||||
return int64(t.Num)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,16 +151,17 @@ func (t Result) Uint() uint64 {
|
|||
return n
|
||||
case Number:
|
||||
// try to directly convert the float64 to uint64
|
||||
n, ok := floatToUint(t.Num)
|
||||
if !ok {
|
||||
// now try to parse the raw string
|
||||
n, ok = parseUint(t.Raw)
|
||||
if !ok {
|
||||
// fallback to a standard conversion
|
||||
return uint64(t.Num)
|
||||
}
|
||||
i, ok := safeInt(t.Num)
|
||||
if ok && i >= 0 {
|
||||
return uint64(i)
|
||||
}
|
||||
return n
|
||||
// now try to parse the raw string
|
||||
u, ok := parseUint(t.Raw)
|
||||
if ok {
|
||||
return u
|
||||
}
|
||||
// fallback to a standard conversion
|
||||
return uint64(t.Num)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2525,25 +2527,11 @@ func parseInt(s string) (n int64, ok bool) {
|
|||
return n, true
|
||||
}
|
||||
|
||||
const minUint53 = 0
|
||||
const maxUint53 = 4503599627370495
|
||||
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
|
||||
func safeInt(f float64) (n int64, ok bool) {
|
||||
if f < -9007199254740991 || f > 9007199254740991 {
|
||||
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.
|
||||
|
|
Loading…
Reference in New Issue