Skip to content

Commit 1b19926

Browse files
committed
Cleanup jsonwire.ParseFloat to simply wrap strconv
Calling strconv.ParseFloat() does not allocate now, so the necessity of fast path is reduced. This fast path actually slows down the process when it fails. If overflows, return infinity as all other libs, don't give surprise to user. Since we now always treat overflow as error, this may not be very important, but still a breaking change.
1 parent 0640c11 commit 1b19926

File tree

4 files changed

+7
-36
lines changed

4 files changed

+7
-36
lines changed

arshal_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5434,7 +5434,7 @@ func TestUnmarshal(t *testing.T) {
54345434
name: jsontest.Name("Floats/Float32/Overflow"),
54355435
inBuf: `-1e1000`,
54365436
inVal: addr(float32(32.32)),
5437-
want: addr(float32(-math.MaxFloat32)),
5437+
want: addr(float32(math.Inf(-1))),
54385438
wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float32]()),
54395439
}, {
54405440
name: jsontest.Name("Floats/Float64/Pi"),
@@ -5450,13 +5450,13 @@ func TestUnmarshal(t *testing.T) {
54505450
name: jsontest.Name("Floats/Float64/Overflow"),
54515451
inBuf: `-1e1000`,
54525452
inVal: addr(float64(64.64)),
5453-
want: addr(float64(-math.MaxFloat64)),
5453+
want: addr(float64(math.Inf(-1))),
54545454
wantErr: EU(strconv.ErrRange).withVal(`-1e1000`).withType('0', T[float64]()),
54555455
}, {
54565456
name: jsontest.Name("Floats/Any/Overflow"),
54575457
inBuf: `1e1000`,
54585458
inVal: new(any),
5459-
want: addr(any(float64(math.MaxFloat64))),
5459+
want: addr(any(math.Inf(+1))),
54605460
wantErr: EU(strconv.ErrRange).withVal(`1e1000`).withType('0', T[float64]()),
54615461
}, {
54625462
name: jsontest.Name("Floats/Named"),

internal/jsonwire/decode.go

Lines changed: 0 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -605,36 +605,7 @@ func ParseUint(b []byte) (v uint64, ok bool) {
605605

606606
// ParseFloat parses a floating point number according to the Go float grammar.
607607
// Note that the JSON number grammar is a strict subset.
608-
//
609-
// If the number overflows the finite representation of a float,
610-
// then we return MaxFloat since any finite value will always be infinitely
611-
// more accurate at representing another finite value than an infinite value.
612608
func ParseFloat(b []byte, bits int) (v float64, ok bool) {
613-
// Fast path for exact integer numbers which fit in the
614-
// 24-bit or 53-bit significand of a float32 or float64.
615-
var negLen int // either 0 or 1
616-
if len(b) > 0 && b[0] == '-' {
617-
negLen = 1
618-
}
619-
u, ok := ParseUint(b[negLen:])
620-
if ok && ((bits == 32 && u <= 1<<24) || (bits == 64 && u <= 1<<53)) {
621-
return math.Copysign(float64(u), float64(-1*negLen)), true
622-
}
623-
624-
// Note that the []byte->string conversion unfortunately allocates.
625-
// See https://go.dev/issue/42429 for more information.
626609
fv, err := strconv.ParseFloat(string(b), bits)
627-
if math.IsInf(fv, 0) {
628-
switch {
629-
case bits == 32 && math.IsInf(fv, +1):
630-
fv = +math.MaxFloat32
631-
case bits == 64 && math.IsInf(fv, +1):
632-
fv = +math.MaxFloat64
633-
case bits == 32 && math.IsInf(fv, -1):
634-
fv = -math.MaxFloat32
635-
case bits == 64 && math.IsInf(fv, -1):
636-
fv = -math.MaxFloat64
637-
}
638-
}
639610
return fv, err == nil
640611
}

internal/jsonwire/decode_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,8 +421,8 @@ func TestParseFloat(t *testing.T) {
421421
{"-9007199254740993", -9007199254740992, -9007199254740992, true}, // -(1<<53 + 1)
422422
{"9007199254740993", 9007199254740992, 9007199254740992, true}, // +(1<<53 + 1)
423423

424-
{"-1e1000", -math.MaxFloat32, -math.MaxFloat64, false},
425-
{"1e1000", +math.MaxFloat32, +math.MaxFloat64, false},
424+
{"-1e1000", math.Inf(-1), math.Inf(-1), false},
425+
{"1e1000", math.Inf(+1), math.Inf(+1), false},
426426
}
427427

428428
for _, tt := range tests {

jsontext/token_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ func TestTokenAccessors(t *testing.T) {
7373
{Uint(maxUint64 - 1), token{String: "18446744073709551614", Float: maxUint64 - 1, Int: maxInt64, Uint: maxUint64 - 1, Kind: '0'}},
7474
{Uint(maxUint64), token{String: "18446744073709551615", Float: maxUint64, Int: maxInt64, Uint: maxUint64, Kind: '0'}},
7575
{rawToken(`-0`), token{String: "-0", Float: math.Copysign(0, -1), Int: 0, Uint: 0, Kind: '0'}},
76-
{rawToken(`1e1000`), token{String: "1e1000", Float: math.MaxFloat64, Int: maxInt64, Uint: maxUint64, Kind: '0'}},
77-
{rawToken(`-1e1000`), token{String: "-1e1000", Float: -math.MaxFloat64, Int: minInt64, Uint: minUint64, Kind: '0'}},
76+
{rawToken(`1e1000`), token{String: "1e1000", Float: math.Inf(+1), Int: maxInt64, Uint: maxUint64, Kind: '0'}},
77+
{rawToken(`-1e1000`), token{String: "-1e1000", Float: math.Inf(-1), Int: minInt64, Uint: minUint64, Kind: '0'}},
7878
{rawToken(`0.1`), token{String: "0.1", Float: 0.1, Int: 0, Uint: 0, Kind: '0'}},
7979
{rawToken(`0.5`), token{String: "0.5", Float: 0.5, Int: 0, Uint: 0, Kind: '0'}},
8080
{rawToken(`0.9`), token{String: "0.9", Float: 0.9, Int: 0, Uint: 0, Kind: '0'}},

0 commit comments

Comments
 (0)