commit
6cc3910a10
@ -133,7 +133,7 @@ public:
|
||||
RAPIDJSON_ASSERT(count_ + offset <= kCapacity);
|
||||
|
||||
if (interShift == 0) {
|
||||
std::memmove(&digits_[count_ - 1 + offset], &digits_[count_ - 1], count_ * sizeof(Type));
|
||||
std::memmove(digits_ + offset, digits_, count_ * sizeof(Type));
|
||||
count_ += offset;
|
||||
}
|
||||
else {
|
||||
|
@ -20,6 +20,7 @@
|
||||
#define RAPIDJSON_DIYFP_H_
|
||||
|
||||
#include "../rapidjson.h"
|
||||
#include <limits>
|
||||
|
||||
#if defined(_MSC_VER) && defined(_M_AMD64) && !defined(__INTEL_COMPILER)
|
||||
#include <intrin.h>
|
||||
@ -141,6 +142,15 @@ struct DiyFp {
|
||||
double d;
|
||||
uint64_t u64;
|
||||
}u;
|
||||
RAPIDJSON_ASSERT(f <= kDpHiddenBit + kDpSignificandMask);
|
||||
if (e < kDpDenormalExponent) {
|
||||
// Underflow.
|
||||
return 0.0;
|
||||
}
|
||||
if (e >= kDpMaxExponent) {
|
||||
// Overflow.
|
||||
return std::numeric_limits<double>::infinity();
|
||||
}
|
||||
const uint64_t be = (e == kDpDenormalExponent && (f & kDpHiddenBit) == 0) ? 0 :
|
||||
static_cast<uint64_t>(e + kDpExponentBias);
|
||||
u.u64 = (f & kDpSignificandMask) | (be << kDpSignificandSize);
|
||||
@ -220,6 +230,7 @@ inline DiyFp GetCachedPowerByIndex(size_t index) {
|
||||
641, 667, 694, 720, 747, 774, 800, 827, 853, 880,
|
||||
907, 933, 960, 986, 1013, 1039, 1066
|
||||
};
|
||||
RAPIDJSON_ASSERT(index < 87);
|
||||
return DiyFp(kCachedPowers_F[index], kCachedPowers_E[index]);
|
||||
}
|
||||
|
||||
@ -238,10 +249,11 @@ inline DiyFp GetCachedPower(int e, int* K) {
|
||||
}
|
||||
|
||||
inline DiyFp GetCachedPower10(int exp, int *outExp) {
|
||||
unsigned index = (static_cast<unsigned>(exp) + 348u) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
RAPIDJSON_ASSERT(exp >= -348);
|
||||
unsigned index = static_cast<unsigned>(exp + 348) / 8u;
|
||||
*outExp = -348 + static_cast<int>(index) * 8;
|
||||
return GetCachedPowerByIndex(index);
|
||||
}
|
||||
|
||||
#ifdef __GNUC__
|
||||
RAPIDJSON_DIAG_POP
|
||||
|
@ -19,6 +19,8 @@
|
||||
#include "biginteger.h"
|
||||
#include "diyfp.h"
|
||||
#include "pow10.h"
|
||||
#include <climits>
|
||||
#include <limits>
|
||||
|
||||
RAPIDJSON_NAMESPACE_BEGIN
|
||||
namespace internal {
|
||||
@ -126,20 +128,20 @@ inline bool StrtodFast(double d, int p, double* result) {
|
||||
}
|
||||
|
||||
// Compute an approximation and see if it is within 1/2 ULP
|
||||
inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosition, int exp, double* result) {
|
||||
inline bool StrtodDiyFp(const char* decimals, int dLen, int dExp, double* result) {
|
||||
uint64_t significand = 0;
|
||||
size_t i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < length; i++) {
|
||||
int i = 0; // 2^64 - 1 = 18446744073709551615, 1844674407370955161 = 0x1999999999999999
|
||||
for (; i < dLen; i++) {
|
||||
if (significand > RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) ||
|
||||
(significand == RAPIDJSON_UINT64_C2(0x19999999, 0x99999999) && decimals[i] > '5'))
|
||||
break;
|
||||
significand = significand * 10u + static_cast<unsigned>(decimals[i] - '0');
|
||||
}
|
||||
|
||||
if (i < length && decimals[i] >= '5') // Rounding
|
||||
if (i < dLen && decimals[i] >= '5') // Rounding
|
||||
significand++;
|
||||
|
||||
size_t remaining = length - i;
|
||||
int remaining = dLen - i;
|
||||
const int kUlpShift = 3;
|
||||
const int kUlp = 1 << kUlpShift;
|
||||
int64_t error = (remaining == 0) ? 0 : kUlp / 2;
|
||||
@ -148,24 +150,24 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
v = v.Normalize();
|
||||
error <<= -v.e;
|
||||
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(i) + exp;
|
||||
dExp += remaining;
|
||||
|
||||
int actualExp;
|
||||
DiyFp cachedPower = GetCachedPower10(dExp, &actualExp);
|
||||
if (actualExp != dExp) {
|
||||
static const DiyFp kPow10[] = {
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 00000000), -60), // 10^1
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 00000000), -57), // 10^2
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 00000000), -54), // 10^3
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 00000000), -50), // 10^4
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 00000000), -47), // 10^5
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 00000000), -44), // 10^6
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 00000000), -40) // 10^7
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xa0000000, 0x00000000), -60), // 10^1
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc8000000, 0x00000000), -57), // 10^2
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xfa000000, 0x00000000), -54), // 10^3
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x9c400000, 0x00000000), -50), // 10^4
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xc3500000, 0x00000000), -47), // 10^5
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0xf4240000, 0x00000000), -44), // 10^6
|
||||
DiyFp(RAPIDJSON_UINT64_C2(0x98968000, 0x00000000), -40) // 10^7
|
||||
};
|
||||
int adjustment = dExp - actualExp - 1;
|
||||
RAPIDJSON_ASSERT(adjustment >= 0 && adjustment < 7);
|
||||
v = v * kPow10[adjustment];
|
||||
if (length + static_cast<unsigned>(adjustment)> 19u) // has more digits than decimal digits in 64-bit
|
||||
int adjustment = dExp - actualExp;
|
||||
RAPIDJSON_ASSERT(adjustment >= 1 && adjustment < 8);
|
||||
v = v * kPow10[adjustment - 1];
|
||||
if (dLen + adjustment > 19) // has more digits than decimal digits in 64-bit
|
||||
error += kUlp / 2;
|
||||
}
|
||||
|
||||
@ -203,9 +205,9 @@ inline bool StrtodDiyFp(const char* decimals, size_t length, size_t decimalPosit
|
||||
return halfWay - static_cast<unsigned>(error) >= precisionBits || precisionBits >= halfWay + static_cast<unsigned>(error);
|
||||
}
|
||||
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, size_t length, size_t decimalPosition, int exp) {
|
||||
const BigInteger dInt(decimals, length);
|
||||
const int dExp = static_cast<int>(decimalPosition) - static_cast<int>(length) + exp;
|
||||
inline double StrtodBigInteger(double approx, const char* decimals, int dLen, int dExp) {
|
||||
RAPIDJSON_ASSERT(dLen >= 0);
|
||||
const BigInteger dInt(decimals, static_cast<unsigned>(dLen));
|
||||
Double a(approx);
|
||||
int cmp = CheckWithinHalfULP(a.Value(), dInt, dExp);
|
||||
if (cmp < 0)
|
||||
@ -225,42 +227,61 @@ inline double StrtodFullPrecision(double d, int p, const char* decimals, size_t
|
||||
RAPIDJSON_ASSERT(d >= 0.0);
|
||||
RAPIDJSON_ASSERT(length >= 1);
|
||||
|
||||
double result;
|
||||
double result = 0.0;
|
||||
if (StrtodFast(d, p, &result))
|
||||
return result;
|
||||
|
||||
RAPIDJSON_ASSERT(length <= INT_MAX);
|
||||
int dLen = static_cast<int>(length);
|
||||
|
||||
RAPIDJSON_ASSERT(length >= decimalPosition);
|
||||
RAPIDJSON_ASSERT(length - decimalPosition <= INT_MAX);
|
||||
int dExpAdjust = static_cast<int>(length - decimalPosition);
|
||||
|
||||
RAPIDJSON_ASSERT(exp >= INT_MIN + dExpAdjust);
|
||||
int dExp = exp - dExpAdjust;
|
||||
|
||||
// Make sure length+dExp does not overflow
|
||||
RAPIDJSON_ASSERT(dExp <= INT_MAX - dLen);
|
||||
|
||||
// Trim leading zeros
|
||||
while (*decimals == '0' && length > 1) {
|
||||
length--;
|
||||
while (dLen > 0 && *decimals == '0') {
|
||||
dLen--;
|
||||
decimals++;
|
||||
decimalPosition--;
|
||||
}
|
||||
|
||||
// Trim trailing zeros
|
||||
while (decimals[length - 1] == '0' && length > 1) {
|
||||
length--;
|
||||
decimalPosition--;
|
||||
exp++;
|
||||
while (dLen > 0 && decimals[dLen - 1] == '0') {
|
||||
dLen--;
|
||||
dExp++;
|
||||
}
|
||||
|
||||
if (dLen == 0) { // Buffer only contains zeros.
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// Trim right-most digits
|
||||
const int kMaxDecimalDigit = 780;
|
||||
if (static_cast<int>(length) > kMaxDecimalDigit) {
|
||||
int delta = (static_cast<int>(length) - kMaxDecimalDigit);
|
||||
exp += delta;
|
||||
decimalPosition -= static_cast<unsigned>(delta);
|
||||
length = kMaxDecimalDigit;
|
||||
const int kMaxDecimalDigit = 767 + 1;
|
||||
if (dLen > kMaxDecimalDigit) {
|
||||
dExp += dLen - kMaxDecimalDigit;
|
||||
dLen = kMaxDecimalDigit;
|
||||
}
|
||||
|
||||
// If too small, underflow to zero
|
||||
if (int(length) + exp < -324)
|
||||
// If too small, underflow to zero.
|
||||
// Any x <= 10^-324 is interpreted as zero.
|
||||
if (dLen + dExp <= -324)
|
||||
return 0.0;
|
||||
|
||||
if (StrtodDiyFp(decimals, length, decimalPosition, exp, &result))
|
||||
// If too large, overflow to infinity.
|
||||
// Any x >= 10^309 is interpreted as +infinity.
|
||||
if (dLen + dExp > 309)
|
||||
return std::numeric_limits<double>::infinity();
|
||||
|
||||
if (StrtodDiyFp(decimals, dLen, dExp, &result))
|
||||
return result;
|
||||
|
||||
// Use approximation from StrtodDiyFp and make adjustment with BigInteger comparison
|
||||
return StrtodBigInteger(result, decimals, length, decimalPosition, exp);
|
||||
return StrtodBigInteger(result, decimals, dLen, dExp);
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
@ -1561,8 +1561,6 @@ private:
|
||||
// Force double for big integer
|
||||
if (useDouble) {
|
||||
while (RAPIDJSON_LIKELY(s.Peek() >= '0' && s.Peek() <= '9')) {
|
||||
if (RAPIDJSON_UNLIKELY(d >= 1.7976931348623157e307)) // DBL_MAX / 10.0
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
|
||||
d = d * 10 + (s.TakePush() - '0');
|
||||
}
|
||||
}
|
||||
@ -1702,6 +1700,13 @@ private:
|
||||
else
|
||||
d = internal::StrtodNormalPrecision(d, p);
|
||||
|
||||
// Use > max, instead of == inf, to fix bogus warning -Wfloat-equal
|
||||
if (d > std::numeric_limits<double>::max()) {
|
||||
// Overflow
|
||||
// TODO: internal::StrtodX should report overflow (or underflow)
|
||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, startOffset);
|
||||
}
|
||||
|
||||
cont = handler.Double(minus ? -d : d);
|
||||
}
|
||||
else if (useNanOrInf) {
|
||||
|
@ -120,6 +120,11 @@ TEST(BigInteger, LeftShift) {
|
||||
EXPECT_TRUE(BIGINTEGER_LITERAL("4537899042132549697536") == a);
|
||||
a <<= 99;
|
||||
EXPECT_TRUE(BIGINTEGER_LITERAL("2876235222267216943024851750785644982682875244576768") == a);
|
||||
|
||||
a = 1;
|
||||
a <<= 64; // a.count_ != 1
|
||||
a <<= 256; // interShift == 0
|
||||
EXPECT_TRUE(BIGINTEGER_LITERAL("2135987035920910082395021706169552114602704522356652769947041607822219725780640550022962086936576") == a);
|
||||
}
|
||||
|
||||
TEST(BigInteger, Compare) {
|
||||
|
@ -377,6 +377,208 @@ static void TestParseDouble() {
|
||||
d = d.Value() * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 1249
|
||||
TEST_DOUBLE(fullPrecision, "0e100", 0.0);
|
||||
|
||||
// Issue 1251
|
||||
TEST_DOUBLE(fullPrecision, "128.74836467836484838364836483643636483648e-336", 0.0);
|
||||
|
||||
// Issue 1256
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"6223372036854775296.1701512723685473547372536854755293372036854685477"
|
||||
"529752233737201701512337200972013723685473123372036872036854236854737"
|
||||
"247372368372367752975258547752975254729752547372368737201701512354737"
|
||||
"83723677529752585477247372368372368547354737253685475529752",
|
||||
6223372036854775808.0);
|
||||
|
||||
#if 0
|
||||
// Test (length + exponent) overflow
|
||||
TEST_DOUBLE(fullPrecision, "0e+2147483647", 0.0);
|
||||
TEST_DOUBLE(fullPrecision, "0e-2147483648", 0.0);
|
||||
TEST_DOUBLE(fullPrecision, "1e-2147483648", 0.0);
|
||||
TEST_DOUBLE(fullPrecision, "0e+9223372036854775807", 0.0);
|
||||
TEST_DOUBLE(fullPrecision, "0e-9223372036854775808", 0.0);
|
||||
#endif
|
||||
|
||||
if (fullPrecision)
|
||||
{
|
||||
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", 5e-324);
|
||||
TEST_DOUBLE(fullPrecision, "2.48e-324",5e-324);
|
||||
TEST_DOUBLE(fullPrecision, "2.5e-324", 5e-324);
|
||||
|
||||
// Slightly above max-normal
|
||||
TEST_DOUBLE(fullPrecision, "1.7976931348623158e+308", 1.7976931348623158e+308);
|
||||
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"17976931348623157081452742373170435679807056752584499659891747680315726"
|
||||
"07800285387605895586327668781715404589535143824642343213268894641827684"
|
||||
"67546703537516986049910576551282076245490090389328944075868508455133942"
|
||||
"30458323690322294816580855933212334827479782620414472316873817718091929"
|
||||
"9881250404026184124858368",
|
||||
std::numeric_limits<double>::max());
|
||||
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"243546080556034731077856379609316893158278902575447060151047"
|
||||
"212703405344938119816206067372775299130836050315842578309818"
|
||||
"316450894337978612745889730079163798234256495613858256849283"
|
||||
"467066859489192118352020514036083287319232435355752493038825"
|
||||
"828481044358810649108367633313557305310641892225870327827273"
|
||||
"41408256.000000",
|
||||
2.4354608055603473e+307);
|
||||
// 9007199254740991 * 2^971 (max normal)
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"1.797693134862315708145274237317043567980705675258449965989174768031572607800285"
|
||||
"38760589558632766878171540458953514382464234321326889464182768467546703537516986"
|
||||
"04991057655128207624549009038932894407586850845513394230458323690322294816580855"
|
||||
"9332123348274797826204144723168738177180919299881250404026184124858368e+308",
|
||||
1.797693134862315708e+308 // 0x1.fffffffffffffp1023
|
||||
);
|
||||
#if 0
|
||||
// TODO:
|
||||
// Should work at least in full-precision mode...
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"0.00000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000024703282292062327208828439643411068618252"
|
||||
"9901307162382212792841250337753635104375932649918180817996189"
|
||||
"8982823477228588654633283551779698981993873980053909390631503"
|
||||
"5659515570226392290858392449105184435931802849936536152500319"
|
||||
"3704576782492193656236698636584807570015857692699037063119282"
|
||||
"7955855133292783433840935197801553124659726357957462276646527"
|
||||
"2827220056374006485499977096599470454020828166226237857393450"
|
||||
"7363390079677619305775067401763246736009689513405355374585166"
|
||||
"6113422376667860416215968046191446729184030053005753084904876"
|
||||
"5391711386591646239524912623653881879636239373280423891018672"
|
||||
"3484976682350898633885879256283027559956575244555072551893136"
|
||||
"9083625477918694866799496832404970582102851318545139621383772"
|
||||
"2826145437693412532098591327667236328125",
|
||||
0.0);
|
||||
#endif
|
||||
// 9007199254740991 * 2^-1074 = (2^53 - 1) * 2^-1074
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014402272114819593418263951869639092703291296046852219449644444042153"
|
||||
"89103305904781627017582829831782607924221374017287738918929105531441481564124348"
|
||||
"67599762821265346585071045737627442980259622449029037796981144446145705102663115"
|
||||
"10031828794952795966823603998647925096578034214163701381261333311989876551545144"
|
||||
"03152612538132666529513060001849177663286607555958373922409899478075565940981010"
|
||||
"21612198814605258742579179000071675999344145086087205681577915435923018910334964"
|
||||
"86942061405218289243144579760516365090360651414037721744226256159024466852576737"
|
||||
"24464300755133324500796506867194913776884780053099639677097589658441378944337966"
|
||||
"21993967316936280457084866613206797017728916080020698679408551343728867675409720"
|
||||
"757232455434770912461317493580281734466552734375e-308",
|
||||
4.450147717014402272e-308 // 0x1.fffffffffffffp-1022
|
||||
);
|
||||
// 9007199254740990 * 2^-1074
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014401778049173752171719775300846224481918930987049605124880018456471"
|
||||
"39035755177760751831052846195619008686241717547743167145836439860405887584484471"
|
||||
"19639655002484083577939142623582164522087943959208000909794783876158397872163051"
|
||||
"22622675229968408654350206725478309956546318828765627255022767720818849892988457"
|
||||
"26333908582101604036318532842699932130356061901518261174396928478121372742040102"
|
||||
"17446565569357687263889031732270082446958029584739170416643195242132750803227473"
|
||||
"16608838720742955671061336566907126801014814608027120593609275183716632624844904"
|
||||
"31985250929886016737037234388448352929102742708402644340627409931664203093081360"
|
||||
"70794835812045179006047003875039546061891526346421705014598610179523165038319441"
|
||||
"51446491086954182492263498716056346893310546875e-308",
|
||||
4.450147717014401778e-308 // 0x1.ffffffffffffep-1022
|
||||
);
|
||||
// half way between the two numbers above.
|
||||
// round to nearest even.
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014402025081996672794991863585242658592605113516950912287262231249312"
|
||||
"64069530541271189424317838013700808305231545782515453032382772695923684574304409"
|
||||
"93619708911874715081505094180604803751173783204118519353387964161152051487413083"
|
||||
"16327252012460602310586905362063117526562176521464664318142050516404363222266800"
|
||||
"64743260560117135282915796422274554896821334728738317548403413978098469341510556"
|
||||
"19529382191981473003234105366170879223151087335413188049110555339027884856781219"
|
||||
"01775450062980622457102958163711745945687733011032421168917765671370549738710820"
|
||||
"78224775842509670618916870627821633352993761380751142008862499795052791018709663"
|
||||
"46394401564490729731565935244123171539810221213221201847003580761626016356864581"
|
||||
"1358486831521563686919762403704226016998291015625e-308",
|
||||
4.450147717014401778e-308 // 0x1.ffffffffffffep-1022
|
||||
);
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014402025081996672794991863585242658592605113516950912287262231249312"
|
||||
"64069530541271189424317838013700808305231545782515453032382772695923684574304409"
|
||||
"93619708911874715081505094180604803751173783204118519353387964161152051487413083"
|
||||
"16327252012460602310586905362063117526562176521464664318142050516404363222266800"
|
||||
"64743260560117135282915796422274554896821334728738317548403413978098469341510556"
|
||||
"19529382191981473003234105366170879223151087335413188049110555339027884856781219"
|
||||
"01775450062980622457102958163711745945687733011032421168917765671370549738710820"
|
||||
"78224775842509670618916870627821633352993761380751142008862499795052791018709663"
|
||||
"46394401564490729731565935244123171539810221213221201847003580761626016356864581"
|
||||
"13584868315215636869197624037042260169982910156250000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000e-308",
|
||||
4.450147717014401778e-308 // 0x1.ffffffffffffep-1022
|
||||
);
|
||||
#if 0
|
||||
// ... round up
|
||||
// TODO:
|
||||
// Should work at least in full-precision mode...
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014402025081996672794991863585242658592605113516950912287262231249312"
|
||||
"64069530541271189424317838013700808305231545782515453032382772695923684574304409"
|
||||
"93619708911874715081505094180604803751173783204118519353387964161152051487413083"
|
||||
"16327252012460602310586905362063117526562176521464664318142050516404363222266800"
|
||||
"64743260560117135282915796422274554896821334728738317548403413978098469341510556"
|
||||
"19529382191981473003234105366170879223151087335413188049110555339027884856781219"
|
||||
"01775450062980622457102958163711745945687733011032421168917765671370549738710820"
|
||||
"78224775842509670618916870627821633352993761380751142008862499795052791018709663"
|
||||
"46394401564490729731565935244123171539810221213221201847003580761626016356864581"
|
||||
"13584868315215636869197624037042260169982910156250000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000001e-308",
|
||||
4.450147717014402272e-308 // 0x1.fffffffffffffp-1022
|
||||
);
|
||||
#endif
|
||||
// ... round down
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"4.450147717014402025081996672794991863585242658592605113516950912287262231249312"
|
||||
"64069530541271189424317838013700808305231545782515453032382772695923684574304409"
|
||||
"93619708911874715081505094180604803751173783204118519353387964161152051487413083"
|
||||
"16327252012460602310586905362063117526562176521464664318142050516404363222266800"
|
||||
"64743260560117135282915796422274554896821334728738317548403413978098469341510556"
|
||||
"19529382191981473003234105366170879223151087335413188049110555339027884856781219"
|
||||
"01775450062980622457102958163711745945687733011032421168917765671370549738710820"
|
||||
"78224775842509670618916870627821633352993761380751142008862499795052791018709663"
|
||||
"46394401564490729731565935244123171539810221213221201847003580761626016356864581"
|
||||
"13584868315215636869197624037042260169982910156249999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999e-308",
|
||||
4.450147717014401778e-308 // 0x1.ffffffffffffep-1022
|
||||
);
|
||||
// Slightly below half way between max-normal and infinity.
|
||||
// Should round down.
|
||||
TEST_DOUBLE(fullPrecision,
|
||||
"1.797693134862315807937289714053034150799341327100378269361737789804449682927647"
|
||||
"50946649017977587207096330286416692887910946555547851940402630657488671505820681"
|
||||
"90890200070838367627385484581771153176447573027006985557136695962284291481986083"
|
||||
"49364752927190741684443655107043427115596995080930428801779041744977919999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999"
|
||||
"99999999999999999999999999999999999999999999999999999999999999999999999999999999e+308",
|
||||
1.797693134862315708e+308 // 0x1.fffffffffffffp1023
|
||||
);
|
||||
}
|
||||
|
||||
#undef TEST_DOUBLE
|
||||
}
|
||||
|
||||
@ -422,15 +624,17 @@ TEST(Reader, ParseNumber_NormalPrecisionError) {
|
||||
printf("ULP Average = %g, Max = %g \n", ulpSum / count, ulpMax);
|
||||
}
|
||||
|
||||
TEST(Reader, ParseNumber_Error) {
|
||||
template<bool fullPrecision>
|
||||
static void TestParseNumberError() {
|
||||
#define TEST_NUMBER_ERROR(errorCode, str, errorOffset, streamPos) \
|
||||
{ \
|
||||
char buffer[1001]; \
|
||||
char buffer[2048]; \
|
||||
ASSERT_LT(std::strlen(str), 2048u); \
|
||||
sprintf(buffer, "%s", str); \
|
||||
InsituStringStream s(buffer); \
|
||||
BaseReaderHandler<> h; \
|
||||
Reader reader; \
|
||||
EXPECT_FALSE(reader.Parse(s, h)); \
|
||||
EXPECT_FALSE(reader.Parse<fullPrecision ? kParseFullPrecisionFlag : 0>(s, h)); \
|
||||
EXPECT_EQ(errorCode, reader.GetParseErrorCode());\
|
||||
EXPECT_EQ(errorOffset, reader.GetErrorOffset());\
|
||||
EXPECT_EQ(streamPos, s.Tell());\
|
||||
@ -443,7 +647,7 @@ TEST(Reader, ParseNumber_Error) {
|
||||
for (int i = 1; i < 310; i++)
|
||||
n1e309[i] = '0';
|
||||
n1e309[310] = '\0';
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, n1e309, 0, 309);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, n1e309, 0, 310);
|
||||
}
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309", 0, 5);
|
||||
|
||||
@ -455,9 +659,97 @@ TEST(Reader, ParseNumber_Error) {
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e", 2, 2);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberMissExponent, "1e_", 2, 2);
|
||||
|
||||
// Issue 849
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.8e308", 0, 7);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "5e308", 0, 5);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e309", 0, 5);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.0e310", 0, 7);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1.00e310", 0, 8);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "-1.8e308", 0, 8);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "-1e309", 0, 6);
|
||||
|
||||
// Issue 1253
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "2e308", 0, 5);
|
||||
|
||||
// Issue 1259
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig,
|
||||
"88474320368547737236837236775298547354737253685475547552933720368546854775297525"
|
||||
"29337203685468547770151233720097201372368547312337203687203685423685123372036872"
|
||||
"03685473724737236837236775297525854775297525472975254737236873720170151235473783"
|
||||
"7236737247372368772473723683723456789012E66", 0, 283);
|
||||
|
||||
#if 0
|
||||
// Test (length + exponent) overflow
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+2147483647", 0, 13);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+9223372036854775807", 0, 22);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+10000", 0, 8);
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig, "1e+50000", 0, 8);
|
||||
#endif
|
||||
|
||||
// 9007199254740992 * 2^971 ("infinity")
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig,
|
||||
"1.797693134862315907729305190789024733617976978942306572734300811577326758055009"
|
||||
"63132708477322407536021120113879871393357658789768814416622492847430639474124377"
|
||||
"76789342486548527630221960124609411945308295208500576883815068234246288147391311"
|
||||
"0540827237163350510684586298239947245938479716304835356329624224137216e+308", 0, 315);
|
||||
|
||||
// TODO:
|
||||
// These tests (currently) fail in normal-precision mode
|
||||
if (fullPrecision)
|
||||
{
|
||||
// Half way between max-normal and infinity
|
||||
// Should round to infinity in nearest-even mode.
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig,
|
||||
"1.797693134862315807937289714053034150799341327100378269361737789804449682927647"
|
||||
"50946649017977587207096330286416692887910946555547851940402630657488671505820681"
|
||||
"90890200070838367627385484581771153176447573027006985557136695962284291481986083"
|
||||
"49364752927190741684443655107043427115596995080930428801779041744977920000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000e+308", 0, 1125);
|
||||
// ...round up
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig,
|
||||
"1.797693134862315807937289714053034150799341327100378269361737789804449682927647"
|
||||
"50946649017977587207096330286416692887910946555547851940402630657488671505820681"
|
||||
"90890200070838367627385484581771153176447573027006985557136695962284291481986083"
|
||||
"49364752927190741684443655107043427115596995080930428801779041744977920000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000001e+308", 0, 1205);
|
||||
}
|
||||
|
||||
TEST_NUMBER_ERROR(kParseErrorNumberTooBig,
|
||||
"10000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"00000000000000000000000000000000000000000000000000000000000000000000000000000000"
|
||||
"0000000000000000000000000000000000000000000000000000000000000000000001", 0, 310);
|
||||
|
||||
#undef TEST_NUMBER_ERROR
|
||||
}
|
||||
|
||||
TEST(Reader, ParseNumberError_NormalPrecisionDouble) {
|
||||
TestParseNumberError<false>();
|
||||
}
|
||||
|
||||
TEST(Reader, ParseNumberError_FullPrecisionDouble) {
|
||||
TestParseNumberError<true>();
|
||||
}
|
||||
|
||||
template <typename Encoding>
|
||||
struct ParseStringHandler : BaseReaderHandler<Encoding, ParseStringHandler<Encoding> > {
|
||||
ParseStringHandler() : str_(0), length_(0), copy_() {}
|
||||
|
Loading…
x
Reference in New Issue
Block a user