in common/src/main/java/com/microsoft/alm/helpers/SimpleJson.java [121:348]
static void parse(final String input, final Map<String, Object> destination) {
final StringBuilder token = new StringBuilder();
final StringBuilder unicodeHex = new StringBuilder();
State state = State.START;
String key = null;
Object value;
for (final char c : input.toCharArray()) {
switch (state) {
case START:
if (isLeftCurlyBracket(c)) {
state = State.PRE_KEY;
}
else if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
case PRE_KEY:
if (isDoubleQuote(c)) {
state = State.KEY;
}
else if (isRightCurlyBracket(c)) {
state = State.END;
}
else if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
case KEY:
if (isDoubleQuote(c)) {
key = token.toString();
token.setLength(0);
state = State.PRE_VALUE;
}
else {
token.append(c);
}
break;
case PRE_VALUE:
if (isColon(c)) {
state = State.VALUE;
}
else if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
case VALUE:
if (isDoubleQuote(c)) {
state = State.STRING_VALUE;
}
else if (isMinus(c) || isDigit(c)) {
token.append(c);
state = State.NUMBER_VALUE;
}
else if (isLiteralStart(c)) {
token.append(c);
state = State.LITERAL_VALUE;
}
else if (isLeftSquareBracket(c)) {
state = State.SQUARE_BRACKET_STRING;
}
else if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
case NUMBER_VALUE:
if (isComma(c) || isInsignificantWhitespace(c) || isRightCurlyBracket(c)) {
final String candidateDouble = token.toString();
token.setLength(0);
value = Double.parseDouble(candidateDouble);
destination.put(key, value);
if (isComma(c)) {
state = State.PRE_KEY;
}
else if (isRightCurlyBracket(c)) {
state = State.END;
}
else {
state = State.POST_VALUE;
}
}
else if (isDigit(c) || isExp(c) || isPeriod(c)) {
token.append(c);
}
else {
error(c, state);
}
break;
case STRING_VALUE:
if (isEscape(c)) {
state = State.STRING_VALUE_ESCAPE;
}
else if (isDoubleQuote(c)) {
value = token.toString();
token.setLength(0);
destination.put(key, value);
state = State.POST_VALUE;
}
else {
token.append(c);
}
break;
case STRING_VALUE_ESCAPE:
switch (c) {
case '"':
case '\\':
case '/':
token.append(c);
state = State.STRING_VALUE;
break;
case 'b':
token.append('\b');
state = State.STRING_VALUE;
break;
case 'f':
token.append('\f');
state = State.STRING_VALUE;
break;
case 'n':
token.append('\n');
state = State.STRING_VALUE;
break;
case 'r':
token.append('\r');
state = State.STRING_VALUE;
break;
case 't':
token.append('\t');
state = State.STRING_VALUE;
break;
case 'u':
state = State.STRING_VALUE_UNICODE;
break;
default:
error(c, state);
}
break;
case STRING_VALUE_UNICODE:
if (isHexDigit(c)) {
unicodeHex.append(c);
if (unicodeHex.length() == 4) {
final String candidateHex = unicodeHex.toString();
unicodeHex.setLength(0);
final int codePoint = Integer.parseInt(candidateHex, 16);
final char[] chars = Character.toChars(codePoint);
token.append(chars);
state = State.STRING_VALUE;
}
}
else {
error(c, state);
}
break;
case SQUARE_BRACKET_STRING:
if (isRightSquareBracket(c)) {
value = token.toString();
token.setLength(0);
destination.put(key, value);
state = State.POST_VALUE;
}
else {
token.append(c);
}
break;
case LITERAL_VALUE:
switch (c) {
case 'a':
case 'e':
case 'l':
case 'r':
case 's':
case 'u':
token.append(c);
break;
case ',':
case '}':
final String candidateLiteral = token.toString();
token.setLength(0);
final Object literal = decodeLiteral(candidateLiteral);
destination.put(key, literal);
if (isComma(c)) {
state = State.POST_VALUE;
}
else {
state = State.END;
}
break;
default:
error(c, state);
}
break;
case POST_VALUE:
if (isComma(c)) {
state = State.PRE_KEY;
}
else if (isRightCurlyBracket(c)) {
state = State.END;
}
else if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
case END:
if (isInsignificantWhitespace(c)) {
continue;
}
else {
error(c, state);
}
break;
}
}
}