Prepare custom strtod data. (cannot pass unit test) [ci skip]
This commit is contained in:
parent
774a4aa2b2
commit
30ea2a32d1
@ -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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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.Take() - '0');
|
d = d * 10 + (s.TakePush() - '0');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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();
|
||||||
useStrtod = true;
|
|
||||||
--expFrac;
|
--expFrac;
|
||||||
}
|
}
|
||||||
|
useStrtod = true;
|
||||||
|
}
|
||||||
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,15 +910,16 @@ 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)
|
||||||
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
|
RAPIDJSON_PARSE_ERROR(kParseErrorNumberMissFraction, s.Tell());
|
||||||
@ -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
|
cont = handler.Double(minus ? -d : d);
|
||||||
d = StrtodFastPath(d, p);
|
|
||||||
|
|
||||||
if (minus)
|
|
||||||
d = -d;
|
|
||||||
}
|
|
||||||
cont = handler.Double(d);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (use64bit) {
|
if (use64bit) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user