Skip to content

Commit 1d1837f

Browse files
authored
Merge pull request #6 from launchdarkly/eb/ch110425/float-exp-parsing
fix float parsing when there's an exponent but no decimal
2 parents 1c4de4b + b65dcfd commit 1d1837f

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

internal/commontest/test_values.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,14 @@ func makeNumberTestValues(encodingBehavior encodingBehavior) []testValue {
4747
{"int large", 1603312301195, "1603312301195", ""}, // enough magnitude for a millisecond timestamp
4848
{"float", 3.5, "3.5", ""},
4949
{"float negative", -3.5, "-3.5", ""},
50-
{"float with exp", 3500, "3.5e3", "3500"},
51-
{"float with Exp", 3500, "3.5E3", "3500"},
52-
{"float with exp+", 3500, "3.5e+3", "3500"},
53-
{"float with exp-", 0.0035, "3.5e-3", "0.0035"},
50+
{"float with exp and decimal", 3500, "3.5e3", "3500"},
51+
{"float with Exp and decimal", 3500, "3.5E3", "3500"},
52+
{"float with exp+ and decimal", 3500, "3.5e+3", "3500"},
53+
{"float with exp- and decimal", 0.0035, "3.5e-3", "0.0035"},
54+
{"float with exp but no decimal", 5000, "5e3", "5000"},
55+
{"float with Exp but no decimal", 5000, "5E3", "5000"},
56+
{"float with exp+ but no decimal", 5000, "5e+3", "5000"},
57+
{"float with exp- but no decimal", 0.005, "5e-3", "0.005"},
5458
} {
5559
enc := v.encoding
5660
if !encodingBehavior.forParsing && v.simplestEncoding != "" {

jreader/token_reader_default.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -380,21 +380,22 @@ func (r *tokenReader) consumeASCIILowercaseAlphabeticChars() int {
380380

381381
func (r *tokenReader) readNumber(first byte) (float64, bool) {
382382
startPos := r.lastPos
383-
hasDecimal := false
383+
isFloat := false
384384
var ch byte
385385
var ok bool
386386
for {
387387
ch, ok = r.readByte()
388388
if !ok {
389389
break
390390
}
391-
if (ch < '0' || ch > '9') && !(ch == '.' && !hasDecimal) {
391+
if (ch < '0' || ch > '9') && !(ch == '.' && !isFloat) {
392392
break
393393
}
394394
if ch == '.' {
395-
hasDecimal = true
395+
isFloat = true
396396
}
397397
}
398+
hasExponent := false
398399
if ch == 'e' || ch == 'E' {
399400
// exponent must match this regex: [eE][-+]?[0-9]+
400401
ch, ok = r.readByte()
@@ -407,7 +408,6 @@ func (r *tokenReader) readNumber(first byte) (float64, bool) {
407408
} else {
408409
return 0, false
409410
}
410-
haveExpDigits := false
411411
for {
412412
ch, ok = r.readByte()
413413
if !ok {
@@ -417,18 +417,19 @@ func (r *tokenReader) readNumber(first byte) (float64, bool) {
417417
r.unreadByte()
418418
break
419419
}
420-
haveExpDigits = true
420+
hasExponent = true
421421
}
422-
if !haveExpDigits {
422+
if !hasExponent {
423423
return 0, false
424424
}
425+
isFloat = true
425426
} else {
426427
if ok {
427428
r.unreadByte()
428429
}
429430
}
430431
chars := r.data[startPos:r.pos]
431-
if hasDecimal {
432+
if isFloat {
432433
// Unfortunately, strconv.ParseFloat requires a string - there is no []byte equivalent. This means we can't
433434
// avoid a heap allocation here. Easyjson works around this by creating an unsafe string that points directly
434435
// at the existing bytes, but in our default implementation we can't use unsafe.

0 commit comments

Comments
 (0)