static int scan()

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;
  }
}