Skip to content

Commit 009b562

Browse files
committed
Expand number parsing, add test
Signed-off-by: Jonathan Rudenberg <[email protected]>
1 parent c7156f9 commit 009b562

File tree

2 files changed

+68
-7
lines changed

2 files changed

+68
-7
lines changed

decode.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,25 @@ func (n Number) String() string { return string(n) }
178178

179179
// Float64 returns the number as a float64.
180180
func (n Number) Float64() (float64, error) {
181+
if h, ok := hexString(string(n)); ok {
182+
n, err := strconv.ParseInt(h, 16, 64)
183+
if err != nil {
184+
return 0, err
185+
}
186+
f := float64(n)
187+
if h[0] == '-' && n == 0 {
188+
f = -f
189+
}
190+
return f, nil
191+
}
181192
return strconv.ParseFloat(string(n), 64)
182193
}
183194

184195
// Int64 returns the number as an int64.
185196
func (n Number) Int64() (int64, error) {
197+
if h, ok := hexString(string(n)); ok {
198+
return strconv.ParseInt(h, 16, 64)
199+
}
186200
return strconv.ParseInt(string(n), 10, 64)
187201
}
188202

@@ -1127,7 +1141,7 @@ func (d *decodeState) literalInterface() interface{} {
11271141
return math.Inf(0)
11281142

11291143
case 'N': // NaN
1130-
return math.NaN
1144+
return math.NaN()
11311145

11321146
case '"', '\'': // string
11331147
s, ok := unquote(item)

number_test.go

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package json5
66

77
import (
8-
"regexp"
8+
"math"
99
"testing"
1010
)
1111

@@ -182,10 +182,57 @@ func BenchmarkNumberIsValid(b *testing.B) {
182182
}
183183
}
184184

185-
func BenchmarkNumberIsValidRegexp(b *testing.B) {
186-
var jsonNumberRegexp = regexp.MustCompile(`^-?(?:0|[1-9]\d*)(?:\.\d+)?(?:[eE][+-]?\d+)?$`)
187-
s := "-61657.61667E+61673"
188-
for i := 0; i < b.N; i++ {
189-
jsonNumberRegexp.MatchString(s)
185+
func TestNumberFloat64(t *testing.T) {
186+
tests := map[string]float64{
187+
"0xDeADb": 0xdeadb,
188+
"+0xDeADb": 0xdeadb,
189+
"-0xDeADb": -0xdeadb,
190+
"-0XDeADb": -0xdeadb,
191+
"-0x0": math.Copysign(0, -1),
192+
".5": 0.5,
193+
"-.5": -0.5,
194+
"+1.e1": 1.e1,
195+
"-1.e1": -1.e1,
196+
"-0": math.Copysign(0, -1),
197+
"-Infinity": math.Inf(-1),
198+
"Infinity": math.Inf(0),
199+
"+Infinity": math.Inf(1),
200+
"NaN": math.NaN(),
201+
}
202+
203+
for s, f := range tests {
204+
res, err := Number(s).Float64()
205+
if err != nil {
206+
t.Errorf("failed to parse %s: %s", s, err)
207+
}
208+
if s == "NaN" {
209+
if !math.IsNaN(res) {
210+
t.Errorf("expected NaN")
211+
}
212+
} else {
213+
if res != f {
214+
t.Errorf("wanted %v, got %v", f, res)
215+
}
216+
}
217+
}
218+
}
219+
220+
func TestNumberInt64(t *testing.T) {
221+
tests := map[string]int64{
222+
"0xDeADb": 0xdeadb,
223+
"+0xDeADb": 0xdeadb,
224+
"-0xDeADb": -0xdeadb,
225+
"-0XDeADb": -0xdeadb,
226+
"0x0": 0,
227+
}
228+
229+
for s, i := range tests {
230+
res, err := Number(s).Int64()
231+
if err != nil {
232+
t.Errorf("failed to parse %s: %s", s, err)
233+
}
234+
if res != i {
235+
t.Errorf("wanted %v, got %v", i, res)
236+
}
190237
}
191238
}

0 commit comments

Comments
 (0)