Commit 4e9b4f6d authored by abolz's avatar abolz

Return 0 if binary exponent is too small

parent f5e5d47f
// Tencent is pleased to support the open source community by making RapidJSON available.
//
//
// Copyright (C) 2015 THL A29 Limited, a Tencent company, and Milo Yip. All rights reserved.
//
// Licensed under the MIT License (the "License"); you may not use this file except
......@@ -7,9 +7,9 @@
//
// http://opensource.org/licenses/MIT
//
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// Unless required by applicable law or agreed to in writing, software distributed
// under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
// This is a C++ header-only implementation of Grisu2 algorithm from the publication:
......@@ -56,7 +56,7 @@ struct DiyFp {
if (biased_e != 0) {
f = significand + kDpHiddenBit;
e = biased_e - kDpExponentBias;
}
}
else {
f = significand;
e = kDpMinExponent + 1;
......@@ -142,9 +142,12 @@ struct DiyFp {
uint64_t u64;
}u;
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
RAPIDJSON_ASSERT(e >= kDpDenormalExponent);
if (e < kDpDenormalExponent) {
// Underflow.
return 0.0;
}
RAPIDJSON_ASSERT(e < kDpMaxExponent);
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
static_cast<uint64_t>(e + kDpExponentBias);
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
return u.d;
......@@ -226,7 +229,7 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
RAPIDJSON_ASSERT(index < 87);
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
}
inline DiyFp GetCachedPower(int e, int* K) {
//int k = static_cast<int>(ceil((-61 - e) * 0.30102999566398114)) + 374;
......
......@@ -392,6 +392,15 @@ static void TestParseDouble() {
"83723677529752585477247372368372368547354737253685475529752",
6223372036854775808.0);
TEST_DOUBLE(fullPrecision, "1e-325", 0.0);
TEST_DOUBLE(fullPrecision, "1e-324", 0.0);
TEST_DOUBLE(fullPrecision, "2e-324", 0.0);
TEST_DOUBLE(fullPrecision, "2.4703282292062327e-324", 0.0);
TEST_DOUBLE(fullPrecision, "2.4703282292062328e-324", 2.4703282292062328e-324);
TEST_DOUBLE(fullPrecision, "2.48e-324", 2.48e-324);
TEST_DOUBLE(fullPrecision, "2.5e-324", 2.5e-324);
#undef TEST_DOUBLE
}
......@@ -1346,20 +1355,20 @@ TEST(Reader, IterativePullParsing_General) {
handler.LOG_DOUBLE,
handler.LOG_ENDARRAY | 7
};
StringStream is("[1, {\"k\": [1, 2]}, null, false, true, \"string\", 1.2]");
Reader reader;
reader.IterativeParseInit();
while (!reader.IterativeParseComplete()) {
size_t oldLogCount = handler.LogCount;
EXPECT_TRUE(oldLogCount < sizeof(e) / sizeof(int)) << "overrun";
EXPECT_TRUE(reader.IterativeParseNext<kParseDefaultFlags>(is, handler)) << "parse fail";
EXPECT_EQ(handler.LogCount, oldLogCount + 1) << "handler should be invoked exactly once each time";
EXPECT_EQ(e[oldLogCount], handler.Logs[oldLogCount]) << "wrong event returned";
}
EXPECT_FALSE(reader.HasParseError());
EXPECT_EQ(sizeof(e) / sizeof(int), handler.LogCount) << "handler invoked wrong number of times";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment