Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hex and octal integer parsing #73

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
15 changes: 10 additions & 5 deletions JSONKit.m
Expand Up @@ -1632,12 +1632,11 @@ static int jk_parse_number(JKParseState *parseState) {
const unsigned char *numberStart = JK_AT_STRING_PTR(parseState);
const unsigned char *endOfBuffer = JK_END_STRING_PTR(parseState);
const unsigned char *atNumberCharacter = NULL;
int numberState = JSONNumberStateWholeNumberStart, isFloatingPoint = 0, isNegative = 0, backup = 0;
int numberState = JSONNumberStateWholeNumberStart, isFloatingPoint = 0, isNegative = 0, backup = 0, isHex = 0, isOctal = 0;
size_t startingIndex = parseState->atIndex;

for(atNumberCharacter = numberStart; (JK_EXPECT_T(atNumberCharacter < endOfBuffer)) && (JK_EXPECT_T(!(JK_EXPECT_F(numberState == JSONNumberStateFinished) || JK_EXPECT_F(numberState == JSONNumberStateError)))); atNumberCharacter++) {
unsigned long currentChar = (unsigned long)(*atNumberCharacter), lowerCaseCC = currentChar | 0x20UL;

switch(numberState) {
case JSONNumberStateWholeNumberStart: if (currentChar == '-') { numberState = JSONNumberStateWholeNumberMinus; isNegative = 1; break; }
case JSONNumberStateWholeNumberMinus: if (currentChar == '0') { numberState = JSONNumberStateWholeNumberZero; break; }
Expand All @@ -1648,10 +1647,16 @@ static int jk_parse_number(JKParseState *parseState) {
case JSONNumberStateExponentPlusMinus:if(!((currentChar >= '0') && (currentChar <= '9'))) { /* XXX Add error message */ numberState = JSONNumberStateError; break; }
else { if(numberState == JSONNumberStateFractionalNumberStart) { numberState = JSONNumberStateFractionalNumber; }
else { numberState = JSONNumberStateExponent; } break; }
case JSONNumberStateWholeNumberZero:
case JSONNumberStateWholeNumberZero: if ((currentChar >= '0') && (currentChar <= '7')) { numberState = JSONNumberStateWholeNumber; isOctal = 1; }
else if (lowerCaseCC == 'x') { numberState = JSONNumberStateWholeNumber; isHex = 1; break; }

case JSONNumberStateWholeNumber: if (currentChar == '.') { numberState = JSONNumberStateFractionalNumberStart; isFloatingPoint = 1; break; }
case JSONNumberStateFractionalNumber: if (lowerCaseCC == 'e') { numberState = JSONNumberStateExponentStart; isFloatingPoint = 1; break; }
case JSONNumberStateExponent: if(!((currentChar >= '0') && (currentChar <= '9')) || (numberState == JSONNumberStateWholeNumberZero)) { numberState = JSONNumberStateFinished; backup = 1; break; }
case JSONNumberStateExponent: if(
!(
((currentChar >= '0') && (currentChar <= '9') && !(isOctal && (currentChar >= '8'))) || (isHex && (lowerCaseCC >= 'a' && lowerCaseCC <='f'))
) || (numberState == JSONNumberStateWholeNumberZero)
) { numberState = JSONNumberStateFinished; backup = 1; break; }
break;
default: /* XXX Add error message */ numberState = JSONNumberStateError; break;
}
Expand Down Expand Up @@ -1687,7 +1692,7 @@ static int jk_parse_number(JKParseState *parseState) {
parseState->token.value.ptrRange.length = sizeof(long long);
parseState->token.value.hash = (JK_HASH_INIT + parseState->token.value.type) + (JKHash)parseState->token.value.number.longLongValue;
} else {
parseState->token.value.number.unsignedLongLongValue = strtoull((const char *)numberTempBuf, (char **)&endOfNumber, 10);
parseState->token.value.number.unsignedLongLongValue = strtoull((const char *)numberTempBuf, (char **)&endOfNumber, 0);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by passing 0 as base, strtoull will decide which base to use based on the prefix (hex if prefix is 0x and octal if prefix is 0)

parseState->token.value.type = JKValueTypeUnsignedLongLong;
parseState->token.value.ptrRange.ptr = (const unsigned char *)&parseState->token.value.number.unsignedLongLongValue;
parseState->token.value.ptrRange.length = sizeof(unsigned long long);
Expand Down