Add support for special float values (inf and nan) (#210)
This commit is contained in:
committed by
Thomas Pelletier
parent
a1e8a8d702
commit
778c285afa
@@ -204,6 +204,14 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn {
|
||||
return l.lexFalse
|
||||
}
|
||||
|
||||
if l.follow("inf") {
|
||||
return l.lexInf
|
||||
}
|
||||
|
||||
if l.follow("nan") {
|
||||
return l.lexNan
|
||||
}
|
||||
|
||||
if isSpace(next) {
|
||||
l.skip()
|
||||
continue
|
||||
@@ -265,6 +273,18 @@ func (l *tomlLexer) lexFalse() tomlLexStateFn {
|
||||
return l.lexRvalue
|
||||
}
|
||||
|
||||
func (l *tomlLexer) lexInf() tomlLexStateFn {
|
||||
l.fastForward(3)
|
||||
l.emit(tokenInf)
|
||||
return l.lexRvalue
|
||||
}
|
||||
|
||||
func (l *tomlLexer) lexNan() tomlLexStateFn {
|
||||
l.fastForward(3)
|
||||
l.emit(tokenNan)
|
||||
return l.lexRvalue
|
||||
}
|
||||
|
||||
func (l *tomlLexer) lexEqual() tomlLexStateFn {
|
||||
l.next()
|
||||
l.emit(tokenEqual)
|
||||
@@ -651,7 +671,14 @@ func (l *tomlLexer) lexNumber() tomlLexStateFn {
|
||||
|
||||
if r == '+' || r == '-' {
|
||||
l.next()
|
||||
if l.follow("inf") {
|
||||
return l.lexInf
|
||||
}
|
||||
if l.follow("nan") {
|
||||
return l.lexNan
|
||||
}
|
||||
}
|
||||
|
||||
pointSeen := false
|
||||
expSeen := false
|
||||
digitSeen := false
|
||||
|
||||
@@ -5,6 +5,7 @@ package toml
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
@@ -243,6 +244,13 @@ func (p *tomlParser) parseRvalue() interface{} {
|
||||
return true
|
||||
case tokenFalse:
|
||||
return false
|
||||
case tokenInf:
|
||||
if tok.val[0] == '-' {
|
||||
return math.Inf(-1)
|
||||
}
|
||||
return math.Inf(1)
|
||||
case tokenNan:
|
||||
return math.NaN()
|
||||
case tokenInteger:
|
||||
cleanedVal := cleanupNumberToken(tok.val)
|
||||
var err error
|
||||
|
||||
@@ -2,6 +2,7 @@ package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -93,6 +94,25 @@ func TestSimpleNumbers(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestSpecialFloats(t *testing.T) {
|
||||
tree, err := Load(`
|
||||
normalinf = inf
|
||||
plusinf = +inf
|
||||
minusinf = -inf
|
||||
normalnan = nan
|
||||
plusnan = +nan
|
||||
minusnan = -nan
|
||||
`)
|
||||
assertTree(t, tree, err, map[string]interface{}{
|
||||
"normalinf": math.Inf(1),
|
||||
"plusinf": math.Inf(1),
|
||||
"minusinf": math.Inf(-1),
|
||||
"normalnan": math.NaN(),
|
||||
"plusnan": math.NaN(),
|
||||
"minusnan": math.NaN(),
|
||||
})
|
||||
}
|
||||
|
||||
func TestHexIntegers(t *testing.T) {
|
||||
tree, err := Load(`a = 0xDEADBEEF`)
|
||||
assertTree(t, tree, err, map[string]interface{}{"a": int64(3735928559)})
|
||||
|
||||
@@ -23,6 +23,8 @@ const (
|
||||
tokenTrue
|
||||
tokenFalse
|
||||
tokenFloat
|
||||
tokenInf
|
||||
tokenNan
|
||||
tokenEqual
|
||||
tokenLeftBracket
|
||||
tokenRightBracket
|
||||
@@ -55,6 +57,8 @@ var tokenTypeNames = []string{
|
||||
"True",
|
||||
"False",
|
||||
"Float",
|
||||
"Inf",
|
||||
"NaN",
|
||||
"=",
|
||||
"[",
|
||||
"]",
|
||||
|
||||
+2
-2
@@ -54,9 +54,9 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen
|
||||
// Ensure a round float does contain a decimal point. Otherwise feeding
|
||||
// the output back to the parser would convert to an integer.
|
||||
if math.Trunc(value) == value {
|
||||
return strconv.FormatFloat(value, 'f', 1, 32), nil
|
||||
return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil
|
||||
}
|
||||
return strconv.FormatFloat(value, 'f', -1, 32), nil
|
||||
return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil
|
||||
case string:
|
||||
return "\"" + encodeTomlString(value) + "\"", nil
|
||||
case []byte:
|
||||
|
||||
@@ -309,6 +309,24 @@ func TestTreeWriteToFloat(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestTreeWriteToSpecialFloat(t *testing.T) {
|
||||
expected := `a = +inf
|
||||
b = -inf
|
||||
c = nan`
|
||||
|
||||
tree, err := Load(expected)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
str, err := tree.ToTomlString()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.TrimSpace(str) != strings.TrimSpace(expected) {
|
||||
t.Fatalf("Expected:\n%s\nGot:\n%s", expected, str)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTreeToTomlString(b *testing.B) {
|
||||
toml, err := Load(sampleHard)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user