Fixed a parsing bug in decodeNumber, updating the failing test cases to be
correct in the process. (The test cases incorrectly used exact integers instead
of scientific notation.)
diff --git a/src/lib_json/json_reader.cpp b/src/lib_json/json_reader.cpp
index 603fd76..238a3c5 100644
--- a/src/lib_json/json_reader.cpp
+++ b/src/lib_json/json_reader.cpp
@@ -573,8 +573,6 @@
Value::LargestUInt maxIntegerValue = isNegative ? Value::LargestUInt(-Value::minLargestInt)
: Value::maxLargestUInt;
Value::LargestUInt threshold = maxIntegerValue / 10;
- Value::UInt lastDigitThreshold = Value::UInt( maxIntegerValue % 10 );
- assert( lastDigitThreshold >=0 && lastDigitThreshold <= 9 );
Value::LargestUInt value = 0;
while ( current < token.end_ )
{
@@ -584,10 +582,13 @@
Value::UInt digit(c - '0');
if ( value >= threshold )
{
- // If the current digit is not the last one, or if it is
- // greater than the last digit of the maximum integer value,
- // the parse the number as a double.
- if ( current != token.end_ || digit > lastDigitThreshold )
+ // We've hit or exceeded the max value divided by 10 (rounded down). If
+ // a) we've only just touched the limit, b) this is the last digit, and
+ // c) it's small enough to fit in that rounding delta, we're okay.
+ // Otherwise treat this number as a double to avoid overflow.
+ if (value > threshold ||
+ current != token.end_ ||
+ digit > maxIntegerValue % 10)
{
return decodeDouble( token );
}
diff --git a/test/data/test_real_09.expected b/test/data/test_real_09.expected
index ee2e5ef..6da815e 100644
--- a/test/data/test_real_09.expected
+++ b/test/data/test_real_09.expected
@@ -1 +1 @@
-.=19000000000000000001
+.=1.9e+19
diff --git a/test/data/test_real_11.expected b/test/data/test_real_11.expected
index 83d3cc3..17f4187 100644
--- a/test/data/test_real_11.expected
+++ b/test/data/test_real_11.expected
@@ -1 +1 @@
-.=-9300000000000000001
+.=-9.3e+18
diff --git a/test/data/test_real_12.expected b/test/data/test_real_12.expected
new file mode 100644
index 0000000..a000319
--- /dev/null
+++ b/test/data/test_real_12.expected
@@ -0,0 +1 @@
+.=1.844674407370955e+19
diff --git a/test/data/test_real_12.json b/test/data/test_real_12.json
new file mode 100644
index 0000000..0a13eed
--- /dev/null
+++ b/test/data/test_real_12.json
@@ -0,0 +1,2 @@
+// 2^64 -> switch to double.
+18446744073709551616