Skip to content

Commit

Permalink
fmt.Scan: accept Inf and NaN
Browse files Browse the repository at this point in the history
Fixes golang#1308.

R=rsc, r2
CC=golang-dev
https://golang.org/cl/3280045
  • Loading branch information
robpike committed Nov 30, 2010
1 parent 448c05d commit 6540c85
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 0 deletions.
8 changes: 8 additions & 0 deletions src/pkg/fmt/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,16 @@ func (s *ss) scanUint(verb int, bitSize int) uint64 {
// we have at least some digits, but Atof will do that.
func (s *ss) floatToken() string {
s.buf.Reset()
// NaN?
if s.accept("nN") && s.accept("aA") && s.accept("nN") {
return s.buf.String()
}
// leading sign?
s.accept(sign)
// Inf?
if s.accept("iI") && s.accept("nN") && s.accept("fF") {
return s.buf.String()
}
// digits?
for s.accept(decimalDigits) {
}
Expand Down
58 changes: 58 additions & 0 deletions src/pkg/fmt/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"bufio"
. "fmt"
"io"
"math"
"os"
"reflect"
"regexp"
Expand Down Expand Up @@ -80,6 +81,12 @@ var (
renamedComplex128Val renamedComplex128
)

type FloatTest struct {
text string
in float64
out float64
}

// Xs accepts any non-empty run of the verb character
type Xs string

Expand Down Expand Up @@ -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
// 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){
Expand Down

0 comments on commit 6540c85

Please sign in to comment.