in runtime/under-json-module.cpp [564:676]
static int scan(Thread* thread, JSONParser* env, const DataArray& data, byte b,
Object* value_out) {
for (;;) {
word next = env->next;
word length = env->length;
switch (b) {
case '"': {
*value_out = scanString(thread, env, data);
if (value_out->isErrorException()) return -1;
return 0;
}
case '{':
return '{';
case '[':
return '[';
case '-': // `-Infinity` or number
if (next <= length - 8 && data.byteAt(next) == 'I' &&
data.byteAt(next + 1) == 'n' && data.byteAt(next + 2) == 'f' &&
data.byteAt(next + 3) == 'i' && data.byteAt(next + 4) == 'n' &&
data.byteAt(next + 5) == 'i' && data.byteAt(next + 6) == 't' &&
data.byteAt(next + 7) == 'y') {
env->next = next + 8;
if (env->has_parse_constant) {
return callParseConstant(thread, env, data, 9, value_out);
}
*value_out = thread->runtime()->newFloat(-kDoubleInfinity);
return 0;
}
FALLTHROUGH;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9': {
RawObject value = scanNumber(thread, env, data, b);
*value_out = value;
if (value.isErrorException()) return -1;
return 0;
}
case 'n': // `null`
if (next <= length - 3 && data.byteAt(next) == 'u' &&
data.byteAt(next + 1) == 'l' && data.byteAt(next + 2) == 'l') {
env->next = next + 3;
*value_out = NoneType::object();
return 0;
}
break;
case 't': // `true`
if (next <= length - 3 && data.byteAt(next) == 'r' &&
data.byteAt(next + 1) == 'u' && data.byteAt(next + 2) == 'e') {
env->next = next + 3;
*value_out = Bool::trueObj();
return 0;
}
break;
case 'f': // `false`
if (next <= length - 4 && data.byteAt(next) == 'a' &&
data.byteAt(next + 1) == 'l' && data.byteAt(next + 2) == 's' &&
data.byteAt(next + 3) == 'e') {
env->next = next + 4;
*value_out = Bool::falseObj();
return 0;
}
break;
case 'N': // `NaN`
if (next <= length - 2 && data.byteAt(next) == 'a' &&
data.byteAt(next + 1) == 'N') {
env->next = next + 2;
if (env->has_parse_constant) {
return callParseConstant(thread, env, data, 3, value_out);
}
*value_out = thread->runtime()->newFloat(kDoubleNaN);
return 0;
}
break;
case 'I': // `Infinity`
if (next <= length - 7 && data.byteAt(next) == 'n' &&
data.byteAt(next + 1) == 'f' && data.byteAt(next + 2) == 'i' &&
data.byteAt(next + 3) == 'n' && data.byteAt(next + 4) == 'i' &&
data.byteAt(next + 5) == 't' && data.byteAt(next + 6) == 'y') {
env->next = next + 7;
if (env->has_parse_constant) {
return callParseConstant(thread, env, data, 8, value_out);
}
*value_out = thread->runtime()->newFloat(kDoubleInfinity);
return 0;
}
break;
default:
break;
}
DCHECK(b != ' ' && b != '\t' && b != '\r' && b != '\n',
"whitespace not skipped");
if (next == 1 && b == UTF8::kBOM[0] && length >= 3 &&
data.byteAt(1) == UTF8::kBOM[1] && data.byteAt(2) == UTF8::kBOM[2]) {
*value_out =
raiseJSONDecodeError(thread, env, data, next,
"Unexpected UTF-8 BOM (decode using utf-8-sig)");
return -1;
}
*value_out =
raiseJSONDecodeError(thread, env, data, next - 1, "Expecting value");
return -1;
}
}