Commit 6540c85c authored by Rob Pike's avatar Rob Pike

fmt.Scan: accept Inf and NaN

Fixes #1308.

R=rsc, r2
CC=golang-dev
https://golang.org/cl/3280045
parent 448c05d7
...@@ -546,8 +546,16 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 { ...@@ -546,8 +546,16 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
// we have at least some digits, but Atof will do that. // we have at least some digits, but Atof will do that.
func (s *ss) floatToken() string { func (s *ss) floatToken() string {
s.buf.Reset() s.buf.Reset()
// NaN?
if s.accept("nN") && s.accept("aA") && s.accept("nN") {
return s.buf.String()
}
// leading sign? // leading sign?
s.accept(sign) s.accept(sign)
// Inf?
if s.accept("iI") && s.accept("nN") && s.accept("fF") {
return s.buf.String()
}
// digits? // digits?
for s.accept(decimalDigits) { for s.accept(decimalDigits) {
} }
......
...@@ -8,6 +8,7 @@ import ( ...@@ -8,6 +8,7 @@ import (
"bufio" "bufio"
. "fmt" . "fmt"
"io" "io"
"math"
"os" "os"
"reflect" "reflect"
"regexp" "regexp"
...@@ -80,6 +81,12 @@ var ( ...@@ -80,6 +81,12 @@ var (
renamedComplex128Val renamedComplex128 renamedComplex128Val renamedComplex128
) )
type FloatTest struct {
text string
in float64
out float64
}
// Xs accepts any non-empty run of the verb character // Xs accepts any non-empty run of the verb character
type Xs string type Xs string
...@@ -399,6 +406,57 @@ func TestScanOverflow(t *testing.T) { ...@@ -399,6 +406,57 @@ func TestScanOverflow(t *testing.T) {
} }
} }
func verifyNaN(str string, t *testing.T) {
var f float
var f32 float32
var f64 float64
text := str + " " + str + " " + str
n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
if err != nil {
t.Errorf("got error scanning %q: %s", text, err)
}
if n != 3 {
t.Errorf("count error scanning %q: got %d", text, n)
}
if !math.IsNaN(float64(f)) || !math.IsNaN(float64(f32)) || !math.IsNaN(f64) {
t.Errorf("didn't get NaNs scanning %q: got %g %g %g", text, f, f32, f64)
}
}
func TestNaN(t *testing.T) {
for _, s := range []string{"nan", "NAN", "NaN"} {
verifyNaN(s, t)
}
}
func verifyInf(str string, t *testing.T) {
var f float
var f32 float32
var f64 float64
text := str + " " + str + " " + str
n, err := Fscan(strings.NewReader(text), &f, &f32, &f64)
if err != nil {
t.Errorf("got error scanning %q: %s", text, err)
}
if n != 3 {
t.Errorf("count error scanning %q: got %d", text, n)
}
sign := 1
if str[0] == '-' {
sign = -1
}
if !math.IsInf(float64(f), sign) || !math.IsInf(float64(f32), sign) || !math.IsInf(f64, sign) {
t.Errorf("didn't get right Infs scanning %q: got %g %g %g", text, f, f32, f64)
}
}
func TestInf(t *testing.T) {
for _, s := range []string{"inf", "+inf", "-inf", "INF", "-INF", "+INF", "Inf", "-Inf", "+Inf"} {
verifyInf(s, t)
}
}
// TODO: there's no conversion from []T to ...T, but we can fake it. These // TODO: there's no conversion from []T to ...T, but we can fake it. These
// functions do the faking. We index the table by the length of the param list. // functions do the faking. We index the table by the length of the param list.
var fscanf = []func(io.Reader, string, []interface{}) (int, os.Error){ var fscanf = []func(io.Reader, string, []interface{}) (int, os.Error){
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment