in Firmware/ExpressivePixelsCore/JsonStreamingParser.cpp [50:211]
void JsonStreamingParser::parse(char c) {
//System.out.print(c);
// valid whitespace characters in JSON (from RFC4627 for JSON) include:
// space, horizontal tab, line feed or new line, and carriage return.
// thanks:
// http://stackoverflow.com/questions/16042274/definition-of-whitespace-in-json
if ((c == ' ' || c == '\t' || c == '\n' || c == '\r')
&& !(state == STATE_IN_STRING || state == STATE_UNICODE || state == STATE_HEXBYTES || state == STATE_START_ESCAPE
|| state == STATE_IN_NUMBER || state == STATE_START_DOCUMENT)) {
return;
}
switch (state) {
case STATE_IN_STRING:
if (c == '"') {
endString();
} else if (c == '\\') {
state = STATE_START_ESCAPE;
} else if ((c < 0x1f) || (c == 0x7f)) {
//throw new RuntimeException("Unescaped control character encountered: " + c + " at position" + characterCounter);
} else {
buffer[bufferPos] = c;
increaseBufferPointer();
}
break;
case STATE_IN_ARRAY:
if (c == ']') {
endArray();
} else {
startValue(c);
}
break;
case STATE_IN_OBJECT:
if (c == '}') {
endObject();
} else if (c == '"') {
startKey();
} else {
//throw new RuntimeException("Start of string expected for object key. Instead got: " + c + " at position" + characterCounter);
}
break;
case STATE_END_KEY:
if (c != ':') {
//throw new RuntimeException("Expected ':' after key. Instead got " + c + " at position" + characterCounter);
}
state = STATE_AFTER_KEY;
break;
case STATE_AFTER_KEY:
startValue(c);
break;
case STATE_START_ESCAPE:
processEscapeCharacters(c);
break;
case STATE_UNICODE:
processUnicodeCharacter(c);
break;
case STATE_HEXBYTES:
processHexByteCharacter(c);
break;
case STATE_UNICODE_SURROGATE:
unicodeEscapeBuffer[unicodeEscapeBufferPos] = c;
unicodeEscapeBufferPos++;
if (unicodeEscapeBufferPos == 2) {
endUnicodeSurrogateInterstitial();
}
break;
case STATE_AFTER_VALUE: {
// not safe for size == 0!!!
int within = stack[stackPos - 1];
if (within == STACK_OBJECT) {
if (c == '}') {
endObject();
} else if (c == ',') {
state = STATE_IN_OBJECT;
} else {
//throw new RuntimeException("Expected ',' or '}' while parsing object. Got: " + c + ". " + characterCounter);
}
} else if (within == STACK_ARRAY) {
if (c == ']') {
endArray();
} else if (c == ',') {
state = STATE_IN_ARRAY;
} else {
//throw new RuntimeException("Expected ',' or ']' while parsing array. Got: " + c + ". " + characterCounter);
}
} else {
//throw new RuntimeException("Finished a literal, but unclear what state to move to. Last state: " + characterCounter);
}
}break;
case STATE_IN_NUMBER:
if (c >= '0' && c <= '9') {
buffer[bufferPos] = c;
increaseBufferPointer();
} else if (c == '.') {
if (doesCharArrayContain(buffer, bufferPos, '.')) {
//throw new RuntimeException("Cannot have multiple decimal points in a number. " + characterCounter);
} else if (doesCharArrayContain(buffer, bufferPos, 'e')) {
//throw new RuntimeException("Cannot have a decimal point in an exponent." + characterCounter);
}
buffer[bufferPos] = c;
increaseBufferPointer();
} else if (c == 'e' || c == 'E') {
if (doesCharArrayContain(buffer, bufferPos, 'e')) {
//throw new RuntimeException("Cannot have multiple exponents in a number. " + characterCounter);
}
buffer[bufferPos] = c;
increaseBufferPointer();
} else if (c == '+' || c == '-') {
char last = buffer[bufferPos - 1];
if (!(last == 'e' || last == 'E')) {
//throw new RuntimeException("Can only have '+' or '-' after the 'e' or 'E' in a number." + characterCounter);
}
buffer[bufferPos] = c;
increaseBufferPointer();
} else {
endNumber();
// we have consumed one beyond the end of the number
parse(c);
}
break;
case STATE_IN_TRUE:
buffer[bufferPos] = c;
increaseBufferPointer();
if (bufferPos == 4) {
endTrue();
}
break;
case STATE_IN_FALSE:
buffer[bufferPos] = c;
increaseBufferPointer();
if (bufferPos == 5) {
endFalse();
}
break;
case STATE_IN_NULL:
buffer[bufferPos] = c;
increaseBufferPointer();
if (bufferPos == 4) {
endNull();
}
break;
case STATE_START_DOCUMENT:
myListener->startDocument();
if (c == '[') {
startArray();
} else if (c == '{') {
startObject();
} else {
// throw new ParsingError($this->_line_number,
// $this->_char_number,
// "Document must start with object or array.");
}
break;
//case STATE_DONE:
// throw new ParsingError($this->_line_number, $this->_char_number,
// "Expected end of document.");
//default:
// throw new ParsingError($this->_line_number, $this->_char_number,
// "Internal error. Reached an unknown state: ".$this->_state);
}
characterCounter++;
}