in Include/cpprestinclude/cpprest/details/json_parsing.hpp [425:580]
bool JSON_Parser<CharType>::CompleteNumberLiteral(CharType first, Token &token)
{
bool minus_sign;
if (first == '-')
{
minus_sign = true;
// Safe to cast because the check after this if/else statement will cover EOF.
first = static_cast<CharType>(NextCharacter());
}
else
{
minus_sign = false;
}
if (first < '0' || first > '9')
return false;
auto ch = PeekCharacter();
//Check for two (or more) zeros at the beginning
if (first == '0' && ch == '0')
return false;
// Parse the number assuming its integer
uint64_t val64;
bool complete = ParseInt64(first, val64);
ch = PeekCharacter();
if (complete && ch!='.' && ch!='E' && ch!='e')
{
if (minus_sign)
{
if (val64 > static_cast<uint64_t>(1) << 63 )
{
// It is negative and cannot be represented in int64, so we resort to double
token.double_val = 0 - static_cast<double>(val64);
token.signed_number = true;
token.kind = JSON_Parser<CharType>::Token::TKN_NumberLiteral;
return true;
}
// It is negative, but fits into int64
token.int64_val = 0 - static_cast<int64_t>(val64);
token.kind = JSON_Parser<CharType>::Token::TKN_IntegerLiteral;
token.signed_number = true;
return true;
}
// It is positive so we use unsigned int64
token.uint64_val = val64;
token.kind = JSON_Parser<CharType>::Token::TKN_IntegerLiteral;
token.signed_number = false;
return true;
}
// Magic number 5 leaves room for decimal point, null terminator, etc (in most cases)
::std::vector<CharType> buf(::std::numeric_limits<uint64_t>::digits10 + 5);
int count = print_llu(buf.data(), buf.size(), val64);
_ASSERTE(count >= 0);
_ASSERTE((size_t)count < buf.size());
// Resize to cut off the null terminator
buf.resize(count);
bool decimal = false;
while (ch != eof<CharType>())
{
// Digit encountered?
if (ch >= '0' && ch <= '9')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
// Decimal dot?
else if (ch == '.')
{
if (decimal)
return false;
decimal = true;
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
// Check that the following char is a digit
if (ch < '0' || ch > '9')
return false;
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
// Exponent?
else if (ch == 'E' || ch == 'e')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
// Check for the exponent sign
if (ch == '+')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
else if (ch == '-')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
// First number of the exponent
if (ch >= '0' && ch <= '9')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
else return false;
// The rest of the exponent
while (ch >= '0' && ch <= '9')
{
buf.push_back(static_cast<CharType>(ch));
NextCharacter();
ch = PeekCharacter();
}
// The peeked character is not a number, so we can break from the loop and construct the number
break;
}
else
{
// Not expected number character?
break;
}
};
buf.push_back('\0');
token.double_val = anystod(buf.data());
if (minus_sign)
{
token.double_val = -token.double_val;
}
token.kind = (JSON_Parser<CharType>::Token::TKN_NumberLiteral);
return true;
}