Commit 30ea2a32 authored by miloyip's avatar miloyip

Prepare custom strtod data. (cannot pass unit test) [ci skip]

parent 774a4aa2
......@@ -731,6 +731,7 @@ private:
~NumberStream() {}
RAPIDJSON_FORCEINLINE Ch Peek() const { return is.Peek(); }
RAPIDJSON_FORCEINLINE Ch TakePush() { return is.Take(); }
RAPIDJSON_FORCEINLINE Ch Take() { return is.Take(); }
size_t Tell() { return is.Tell(); }
const char* Pop() { return 0; }
......@@ -748,7 +749,7 @@ private:
NumberStream(GenericReader& reader, InputStream& is) : NumberStream<InputStream, false>(reader, is), stackStream(reader.stack_) {}
~NumberStream() {}
RAPIDJSON_FORCEINLINE Ch Take() {
RAPIDJSON_FORCEINLINE Ch TakePush() {
stackStream.Put((char)Base::is.Peek());
return Base::is.Take();
}
......@@ -762,7 +763,7 @@ private:
StackStream<char> stackStream;
};
double StrtodFastPath(double significand, int exp) {
static double StrtodFastPath(double significand, int exp) {
if (exp < -308)
return 0.0;
else if (exp >= 0)
......@@ -771,6 +772,17 @@ private:
return significand / internal::Pow10(-exp);
}
static double NormalPrecision(double d, int p, int exp, int expFrac) {
if (p < -308) {
// Prevent expSum < -308, making Pow10(p) = 0
d = StrtodFastPath(d, exp);
d = StrtodFastPath(d, expFrac);
}
else
d = StrtodFastPath(d, p);
return d;
}
template<unsigned parseFlags, typename InputStream, typename Handler>
void ParseNumber(InputStream& is, Handler& handler) {
internal::StreamLocalCopy<InputStream> copy(is);
......@@ -789,10 +801,10 @@ private:
bool use64bit = false;
if (s.Peek() == '0') {
i = 0;
s.Take();
s.TakePush();
}
else if (s.Peek() >= '1' && s.Peek() <= '9') {
i = static_cast<unsigned>(s.Take() - '0');
i = static_cast<unsigned>(s.TakePush() - '0');
if (minus)
while (s.Peek() >= '0' && s.Peek() <= '9') {
......@@ -803,7 +815,7 @@ private:
break;
}
}
i = i * 10 + static_cast<unsigned>(s.Take() - '0');
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
}
else
while (s.Peek() >= '0' && s.Peek() <= '9') {
......@@ -814,7 +826,7 @@ private:
break;
}
}
i = i * 10 + static_cast<unsigned>(s.Take() - '0');
i = i * 10 + static_cast<unsigned>(s.TakePush() - '0');
}
}
else
......@@ -833,7 +845,7 @@ private:
useDouble = true;
break;
}
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
}
else
while (s.Peek() >= '0' && s.Peek() <= '9') {
......@@ -843,23 +855,19 @@ private:
useDouble = true;
break;
}
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
i64 = i64 * 10 + static_cast<unsigned>(s.TakePush() - '0');
}
}
// Force double for big integer
if (useDouble) {
if (parseFlags & kParseFullPrecisionFlag) {
while (s.Peek() >= '0' && s.Peek() <= '9')
s.Take();
if (parseFlags & kParseFullPrecisionFlag)
useStrtod = true;
}
else {
while (s.Peek() >= '0' && s.Peek() <= '9') {
if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
d = d * 10 + (s.Take() - '0');
}
while (s.Peek() >= '0' && s.Peek() <= '9') {
if (d >= 1.7976931348623157e307) // DBL_MAX / 10.0
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
d = d * 10 + (s.TakePush() - '0');
}
}
......@@ -877,15 +885,16 @@ private:
while (s.Peek() >= '0' && s.Peek() <= '9') {
if (i64 > RAPIDJSON_UINT64_C2(0x1FFFFF, 0xFFFFFFFF)) { // 2^53 - 1 for fast path
if (parseFlags & kParseFullPrecisionFlag) {
while (s.Peek() >= '0' && s.Peek() <= '9')
s.Take();
while (s.Peek() >= '0' && s.Peek() <= '9') {
s.TakeAndPush();
--expFrac;
}
useStrtod = true;
--expFrac;
}
break;
}
else {
i64 = i64 * 10 + static_cast<unsigned>(s.Take() - '0');
i64 = i64 * 10 + static_cast<unsigned>(s.TakeAndPush() - '0');
--expFrac;
}
}
......@@ -901,14 +910,15 @@ private:
if ((parseFlags & kParseFullPrecisionFlag) == 0 || !useStrtod) {
while (s.Peek() >= '0' && s.Peek() <= '9') {
d = d * 10.0 + (s.Take() - '0');
d = d * 10.0 + (s.TakePush() - '0');
--expFrac;
}
}
else {
while (s.Peek() >= '0' && s.Peek() <= '9')
s.Take();
--expFrac;
while (s.Peek() >= '0' && s.Peek() <= '9') {
s.TakePush();
--expFrac;
}
}
if (expFrac == 0)
......@@ -966,33 +976,18 @@ private:
useStrtod = true;
}
if (!useStrtod && p >= -22 && d <= 9007199254740991.0) { // 2^53 - 1
if (!useStrtod && p >= -22 && d <= 9007199254740991.0) // 2^53 - 1
d = StrtodFastPath(d, p);
if (minus)
d = -d;
}
else {
char* end = 0;
d = strtod(str, &end);
RAPIDJSON_ASSERT(*end == '\0'); // Should have consumed the whole string.
if (d == HUGE_VAL || d == -HUGE_VAL)
RAPIDJSON_PARSE_ERROR(kParseErrorNumberTooBig, s.Tell());
printf("s=%s p=%d\n", str, p);
double guess = NormalPrecision(d, p, exp, expFrac);
d = guess;
}
}
else {
if (p < -308) {
// Prevent expSum < -308, making Pow10(p) = 0
d = StrtodFastPath(d, exp);
d = StrtodFastPath(d, expFrac);
}
else
d = StrtodFastPath(d, p);
if (minus)
d = -d;
d = NormalPrecision(d, p, exp, expFrac);
}
cont = handler.Double(d);
cont = handler.Double(minus ? -d : d);
}
else {
if (use64bit) {
......
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