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