commit a110d70fc686bf2213d98657436ae63bb916a8a2
parent b9b0d4d1716630576e74d7083666eee62ae89eae
Author: francoispqt <francois@parquet.ninja>
Date: Mon, 21 May 2018 23:50:08 +0800
add some tests for float exponents
Diffstat:
4 files changed, 220 insertions(+), 16 deletions(-)
diff --git a/decode_number_float.go b/decode_number_float.go
@@ -15,7 +15,7 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
case ' ', '\n', '\t', '\r', ',':
continue
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- val, err := dec.getFloat(c)
+ val, err := dec.getFloat()
if err != nil {
return err
}
@@ -23,7 +23,7 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
return nil
case '-':
dec.cursor = dec.cursor + 1
- val, err := dec.getFloat(c)
+ val, err := dec.getFloatNegative()
if err != nil {
return err
}
@@ -48,7 +48,20 @@ func (dec *Decoder) decodeFloat64(v *float64) error {
return dec.raiseInvalidJSONErr(dec.cursor)
}
-func (dec *Decoder) getFloat(b byte) (float64, error) {
+func (dec *Decoder) getFloatNegative() (float64, error) {
+ // look for following numbers
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch dec.data[dec.cursor] {
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return dec.getFloat()
+ default:
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ }
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+}
+
+func (dec *Decoder) getFloat() (float64, error) {
var end = dec.cursor
var start = dec.cursor
// look for following numbers
@@ -73,9 +86,16 @@ func (dec *Decoder) getFloat(b byte) (float64, error) {
} else if c == 'e' || c == 'E' {
afterDecimal := dec.atoi64(start, end)
dec.cursor = i + 1
- pow := pow10uint64[end-start+2]
+ expI := end - start + 2
+ if expI >= len(pow10uint64) || expI < 0 {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ pow := pow10uint64[expI]
floatVal := float64(beforeDecimal+afterDecimal) / float64(pow)
exp := dec.getExponent()
+ if +exp+1 >= int64(len(pow10uint64)) {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
// if exponent is negative
if exp < 0 {
return float64(floatVal) * (1 / float64(pow10uint64[exp*-1+1])), nil
@@ -88,14 +108,21 @@ func (dec *Decoder) getFloat(b byte) (float64, error) {
// then we add both integers
// then we divide the number by the power found
afterDecimal := dec.atoi64(start, end)
- pow := pow10uint64[end-start+2]
+ expI := end - start + 2
+ if expI >= len(pow10uint64) || expI < 0 {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ pow := pow10uint64[expI]
return float64(beforeDecimal+afterDecimal) / float64(pow), nil
case 'e', 'E':
- dec.cursor = dec.cursor + 2
+ dec.cursor = j + 1
// we get part before decimal as integer
beforeDecimal := uint64(dec.atoi64(start, end))
// get exponent
exp := dec.getExponent()
+ if +exp+1 >= int64(len(pow10uint64)) {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
// if exponent is negative
if exp < 0 {
return float64(beforeDecimal) * (1 / float64(pow10uint64[exp*-1+1])), nil
@@ -126,7 +153,7 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
case ' ', '\n', '\t', '\r', ',':
continue
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9':
- val, err := dec.getFloat32(c)
+ val, err := dec.getFloat32()
if err != nil {
return err
}
@@ -134,7 +161,7 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
return nil
case '-':
dec.cursor = dec.cursor + 1
- val, err := dec.getFloat32(c)
+ val, err := dec.getFloat32Negative()
if err != nil {
return err
}
@@ -159,7 +186,20 @@ func (dec *Decoder) decodeFloat32(v *float32) error {
return dec.raiseInvalidJSONErr(dec.cursor)
}
-func (dec *Decoder) getFloat32(b byte) (float32, error) {
+func (dec *Decoder) getFloat32Negative() (float32, error) {
+ // look for following numbers
+ for ; dec.cursor < dec.length || dec.read(); dec.cursor++ {
+ switch dec.data[dec.cursor] {
+ case '1', '2', '3', '4', '5', '6', '7', '8', '9':
+ return dec.getFloat32()
+ default:
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ }
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+}
+
+func (dec *Decoder) getFloat32() (float32, error) {
var end = dec.cursor
var start = dec.cursor
// look for following numbers
@@ -184,9 +224,16 @@ func (dec *Decoder) getFloat32(b byte) (float32, error) {
} else if c == 'e' || c == 'E' {
afterDecimal := dec.atoi32(start, end)
dec.cursor = i + 1
- pow := pow10uint64[end-start+2]
+ expI := end - start + 2
+ if expI >= len(pow10uint64) || expI < 0 {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ pow := pow10uint64[expI]
floatVal := float32(beforeDecimal+afterDecimal) / float32(pow)
exp := dec.getExponent()
+ if +exp+1 >= int64(len(pow10uint64)) {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
// if exponent is negative
if exp < 0 {
return float32(floatVal) * (1 / float32(pow10uint64[exp*-1+1])), nil
@@ -199,14 +246,21 @@ func (dec *Decoder) getFloat32(b byte) (float32, error) {
// then we add both integers
// then we divide the number by the power found
afterDecimal := dec.atoi32(start, end)
- pow := pow10uint64[end-start+2]
+ expI := end - start + 2
+ if expI >= len(pow10uint64) || expI < 0 {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
+ pow := pow10uint64[expI]
return float32(beforeDecimal+afterDecimal) / float32(pow), nil
case 'e', 'E':
- dec.cursor = dec.cursor + 2
+ dec.cursor = j + 1
// we get part before decimal as integer
beforeDecimal := uint32(dec.atoi32(start, end))
// get exponent
exp := dec.getExponent()
+ if +exp+1 >= int64(len(pow10uint64)) {
+ return 0, dec.raiseInvalidJSONErr(dec.cursor)
+ }
// if exponent is negative
if exp < 0 {
return float32(beforeDecimal) * (1 / float32(pow10uint64[exp*-1+1])), nil
diff --git a/decode_number_float_test.go b/decode_number_float_test.go
@@ -46,6 +46,20 @@ func TestDecoderFloat64(t *testing.T) {
errType: InvalidJSONError(""),
},
{
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
name: "basic-null-err",
json: "trua",
expectedResult: 0,
@@ -133,6 +147,30 @@ func TestDecoderFloat64(t *testing.T) {
expectedResult: -788.76,
},
{
+ name: "basic-exp-too-big",
+ json: "1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.002e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "error",
json: "83zez4",
expectedResult: 0,
@@ -256,6 +294,20 @@ func TestDecoderFloat32(t *testing.T) {
errType: InvalidJSONError(""),
},
{
+ name: "basic-negative-err",
+ json: "-",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
+ name: "basic-negative-err",
+ json: "-q",
+ expectedResult: 0,
+ err: true,
+ errType: InvalidJSONError(""),
+ },
+ {
name: "basic-exponent-positive-positive-exp4",
json: "8e+005",
expectedResult: 800000,
@@ -306,6 +358,36 @@ func TestDecoderFloat32(t *testing.T) {
expectedResult: -0.000082,
},
{
+ name: "basic-exp-too-big",
+ json: "1e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.0023249242000242e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.002e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009",
+ expectedResult: 0,
+ err: true,
+ },
+ {
+ name: "basic-exp-too-big",
+ json: "1.00232492420002423545849009e10000000000 ",
+ expectedResult: 0,
+ err: true,
+ },
+ {
name: "basic-float",
json: "2.4595",
expectedResult: 2.4595,
diff --git a/decode_number_int.go b/decode_number_int.go
@@ -168,7 +168,7 @@ func (dec *Decoder) getInt16() (int16, error) {
floatVal := float64(beforeDecimal+afterDecimal) / float64(pow)
// we have the floating value, now multiply by the exponent
exp := dec.getExponent()
- if exp+1 >= int64(len(pow10uint64)) || exp < 0 {
+ if +exp+1 >= int64(len(pow10uint64)) {
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
val := floatVal * float64(pow10uint64[exp+1])
@@ -347,7 +347,7 @@ func (dec *Decoder) getInt8() (int8, error) {
floatVal := float64(beforeDecimal+afterDecimal) / float64(pow)
// we have the floating value, now multiply by the exponent
exp := dec.getExponent()
- if exp+1 >= int64(len(pow10uint64)) || exp < 0 {
+ if +exp+1 >= int64(len(pow10uint64)) {
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
val := floatVal * float64(pow10uint64[exp+1])
@@ -525,7 +525,7 @@ func (dec *Decoder) getInt32() (int32, error) {
floatVal := float64(beforeDecimal+afterDecimal) / float64(pow)
// we have the floating value, now multiply by the exponent
exp := dec.getExponent()
- if exp+1 >= int64(len(pow10uint64)) || exp < 0 {
+ if +exp+1 >= int64(len(pow10uint64)) {
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
val := floatVal * float64(pow10uint64[exp+1])
@@ -707,7 +707,7 @@ func (dec *Decoder) getInt64() (int64, error) {
floatVal := float64(beforeDecimal+afterDecimal) / float64(pow)
// we have the floating value, now multiply by the exponent
exp := dec.getExponent()
- if exp+1 >= int64(len(pow10uint64)) || exp < 0 {
+ if +exp+1 >= int64(len(pow10uint64)) {
return 0, dec.raiseInvalidJSONErr(dec.cursor)
}
val := floatVal * float64(pow10uint64[exp+1])
diff --git a/decode_object_test.go b/decode_object_test.go
@@ -53,6 +53,74 @@ func TestDecodeObjectBasic(t *testing.T) {
err: false,
},
{
+ name: "basic-with-exponent",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 3e3,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 123.677,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{
+ testStr: "hello world!",
+ testInt: 3000,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 123.677,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
+ {
+ name: "basic-with-exponent3",
+ json: `{
+ "testStr": "hello world!",
+ "testInt": 3e-3,
+ "testBool": true,
+ "testFloat32": 2.345,
+ "testFloat64": 12e-3,
+ "testInt8": 23,
+ "testInt16": 1245,
+ "testInt32": 456778,
+ "testInt64": 1446685358,
+ "testUint8": 255,
+ "testUint16": 3455,
+ "testUint32": 343443,
+ "testUint64": 545665757
+ }`,
+ expectedResult: testObject{
+ testStr: "hello world!",
+ testInt: 0,
+ testBool: true,
+ testFloat32: 2.345,
+ testFloat64: 0.012,
+ testInt8: 23,
+ testInt16: 1245,
+ testInt32: 456778,
+ testInt64: 1446685358,
+ testUint8: 255,
+ testUint16: 3455,
+ testUint32: 343443,
+ testUint64: 545665757,
+ },
+ err: false,
+ },
+ {
name: "basic-err-invalid-type",
json: `1`,
expectedResult: testObject{},