Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fastfloat: support elided integer or float part #84

Merged
merged 1 commit into from Dec 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 28 additions & 4 deletions fastfloat/parse.go
Expand Up @@ -213,6 +213,10 @@ func ParseBestEffort(s string) float64 {
}
}

// the integer part might be elided to remain compliant
// with https://go.dev/ref/spec#Floating-point_literals
intPartElided := s[i] == '.'

d := uint64(0)
j := i
for i < uint(len(s)) {
Expand All @@ -232,7 +236,7 @@ func ParseBestEffort(s string) float64 {
}
break
}
if i <= j {
if i <= j && !intPartElided {
s = s[i:]
if strings.HasPrefix(s, "+") {
s = s[1:]
Expand Down Expand Up @@ -263,7 +267,12 @@ func ParseBestEffort(s string) float64 {
// Parse fractional part.
i++
if i >= uint(len(s)) {
return 0
if intPartElided {
return 0
}
// the fractional part may be elided to remain compliant
// with https://go.dev/ref/spec#Floating-point_literals
return f
}
k := i
for i < uint(len(s)) {
Expand Down Expand Up @@ -296,6 +305,9 @@ func ParseBestEffort(s string) float64 {
}
}
if s[i] == 'e' || s[i] == 'E' {
if intPartElided {
return 0
}
// Parse exponent part.
i++
if i >= uint(len(s)) {
Expand Down Expand Up @@ -363,6 +375,10 @@ func Parse(s string) (float64, error) {
}
}

// the integer part might be elided to remain compliant
// with https://go.dev/ref/spec#Floating-point_literals
intPartElided := s[i] == '.'

d := uint64(0)
j := i
for i < uint(len(s)) {
Expand All @@ -382,7 +398,7 @@ func Parse(s string) (float64, error) {
}
break
}
if i <= j {
if i <= j && !intPartElided {
ss := s[i:]
if strings.HasPrefix(ss, "+") {
ss = ss[1:]
Expand Down Expand Up @@ -413,7 +429,12 @@ func Parse(s string) (float64, error) {
// Parse fractional part.
i++
if i >= uint(len(s)) {
return 0, fmt.Errorf("cannot parse fractional part in %q", s)
if intPartElided {
return 0, fmt.Errorf("cannot parse integer or fractional part in %q", s)
}
// the fractional part might be elided to remain compliant
// with https://go.dev/ref/spec#Floating-point_literals
return f, nil
}
k := i
for i < uint(len(s)) {
Expand Down Expand Up @@ -446,6 +467,9 @@ func Parse(s string) (float64, error) {
}
}
if s[i] == 'e' || s[i] == 'E' {
if intPartElided {
return 0, fmt.Errorf("cannot parse integer part in %q", s)
}
// Parse exponent part.
i++
if i >= uint(len(s)) {
Expand Down
12 changes: 8 additions & 4 deletions fastfloat/parse_test.go
Expand Up @@ -206,6 +206,7 @@ func TestParseBestEffort(t *testing.T) {
f("-", 0)
f("--", 0)
f("-.", 0)
f(".", 0)
f("-.e", 0)
f("+112", 0)
f("++", 0)
Expand All @@ -214,7 +215,6 @@ func TestParseBestEffort(t *testing.T) {
f("-e12", 0)
f(".", 0)
f("..34", 0)
f("-.32", 0)
f("-.e3", 0)
f(".e+3", 0)

Expand All @@ -224,7 +224,6 @@ func TestParseBestEffort(t *testing.T) {
f("12.34.56", 0)
f("13e34.56", 0)
f("12.34e56e4", 0)
f("12.", 0)
f("123..45", 0)
f("123ee34", 0)
f("123e", 0)
Expand Down Expand Up @@ -262,6 +261,9 @@ func TestParseBestEffort(t *testing.T) {
f("-0.1", -0.1)
f("-0.123", -0.123)
f("1.66", 1.66)
f("12.", 12)
f(".12", 0.12)
f("-.12", -0.12)
f("12345.12345678901", 12345.12345678901)
f("12345.123456789012", 12345.123456789012)
f("12345.1234567890123", 12345.1234567890123)
Expand Down Expand Up @@ -338,6 +340,7 @@ func TestParseFailure(t *testing.T) {
f(" bar ")
f("-")
f("--")
f(".")
f("-.")
f("-.e")
f("+112")
Expand All @@ -347,7 +350,6 @@ func TestParseFailure(t *testing.T) {
f("-e12")
f(".")
f("..34")
f("-.32")
f("-.e3")
f(".e+3")

Expand All @@ -357,7 +359,6 @@ func TestParseFailure(t *testing.T) {
f("12.34.56")
f("13e34.56")
f("12.34e56e4")
f("12.")
f("123..45")
f("123ee34")
f("123e")
Expand Down Expand Up @@ -413,6 +414,9 @@ func TestParseSuccess(t *testing.T) {
f("-0.1", -0.1)
f("-0.123", -0.123)
f("1.66", 1.66)
f("12.", 12)
f(".12", 0.12)
f("-.12", -0.12)
f("12345.12345678901", 12345.12345678901)
f("12345.123456789012", 12345.123456789012)
f("12345.1234567890123", 12345.1234567890123)
Expand Down