int main(int argc, char ** argv) { if (argc != 2) { return 1; } #if defined(_MSC_VER) && defined(_WIN32) if (_setmode(_fileno(stdin), _O_BINARY) == -1) { return 1; } #elif defined(__CYGWIN__) if (setmode(fileno(stdin), O_BINARY) == -1) { return 1; } #endif OpenArray(argv[1]); size_t n; while ((n = fread(buf, 1, sizeof(buf), stdin)) > 0) { for (size_t i = 0; i < n; ++i) { AddByte(buf[i]); } } CloseArray(); return 0; }
JSBool js_ConsumeJSONText(JSContext *cx, JSONParser *jp, const jschar *data, uint32 len) { uint32 i; if (*jp->statep == JSON_PARSE_STATE_INIT) { PushState(jp, JSON_PARSE_STATE_OBJECT_VALUE); } for (i = 0; i < len; i++) { jschar c = data[i]; switch (*jp->statep) { case JSON_PARSE_STATE_VALUE : if (c == ']') { // empty array if (!PopState(jp)) return JS_FALSE; if (*jp->statep != JSON_PARSE_STATE_ARRAY) return JS_FALSE; // unexpected char if (!CloseArray(cx, jp) || !PopState(jp)) return JS_FALSE; break; } if (c == '}') { // we should only find these in OBJECT_KEY state return JS_FALSE; // unexpected failure } if (c == '"') { *jp->statep = JSON_PARSE_STATE_STRING; break; } if (IsNumChar(c)) { *jp->statep = JSON_PARSE_STATE_NUMBER; js_AppendChar(jp->buffer, c); break; } if (JS7_ISLET(c)) { *jp->statep = JSON_PARSE_STATE_KEYWORD; js_AppendChar(jp->buffer, c); break; } // fall through in case the value is an object or array case JSON_PARSE_STATE_OBJECT_VALUE : if (c == '{') { *jp->statep = JSON_PARSE_STATE_OBJECT; if (!OpenObject(cx, jp) || !PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR)) return JS_FALSE; } else if (c == '[') { *jp->statep = JSON_PARSE_STATE_ARRAY; if (!OpenArray(cx, jp) || !PushState(jp, JSON_PARSE_STATE_VALUE)) return JS_FALSE; } else if (!JS_ISXMLSPACE(c)) { return JS_FALSE; // unexpected } break; case JSON_PARSE_STATE_OBJECT : if (c == '}') { if (!CloseObject(cx, jp) || !PopState(jp)) return JS_FALSE; } else if (c == ',') { if (!PushState(jp, JSON_PARSE_STATE_OBJECT_PAIR)) return JS_FALSE; } else if (c == ']' || !JS_ISXMLSPACE(c)) { return JS_FALSE; // unexpected } break; case JSON_PARSE_STATE_ARRAY : if (c == ']') { if (!CloseArray(cx, jp) || !PopState(jp)) return JS_FALSE; } else if (c == ',') { if (!PushState(jp, JSON_PARSE_STATE_VALUE)) return JS_FALSE; } else if (!JS_ISXMLSPACE(c)) { return JS_FALSE; // unexpected } break; case JSON_PARSE_STATE_OBJECT_PAIR : if (c == '"') { // we want to be waiting for a : when the string has been read *jp->statep = JSON_PARSE_STATE_OBJECT_IN_PAIR; if (!PushState(jp, JSON_PARSE_STATE_STRING)) return JS_FALSE; } else if (c == '}') { // pop off the object pair state and the object state if (!CloseObject(cx, jp) || !PopState(jp) || !PopState(jp)) return JS_FALSE; } else if (c == ']' || !JS_ISXMLSPACE(c)) { return JS_FALSE; // unexpected } break; case JSON_PARSE_STATE_OBJECT_IN_PAIR: if (c == ':') { *jp->statep = JSON_PARSE_STATE_VALUE; } else if (!JS_ISXMLSPACE(c)) { return JS_FALSE; // unexpected } break; case JSON_PARSE_STATE_STRING: if (c == '"') { if (!PopState(jp)) return JS_FALSE; JSONDataType jdt; if (*jp->statep == JSON_PARSE_STATE_OBJECT_IN_PAIR) { jdt = JSON_DATA_KEYSTRING; } else { jdt = JSON_DATA_STRING; } if (!HandleData(cx, jp, jdt, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer))) return JS_FALSE; } else if (c == '\\') { *jp->statep = JSON_PARSE_STATE_STRING_ESCAPE; } else { js_AppendChar(jp->buffer, c); } break; case JSON_PARSE_STATE_STRING_ESCAPE: switch(c) { case '"': case '\\': case '/': break; case 'b' : c = '\b'; break; case 'f' : c = '\f'; break; case 'n' : c = '\n'; break; case 'r' : c = '\r'; break; case 't' : c = '\t'; break; default : if (c == 'u') { jp->numHex = 0; jp->hexChar = 0; *jp->statep = JSON_PARSE_STATE_STRING_HEX; continue; } else { return JS_FALSE; // unexpected } } js_AppendChar(jp->buffer, c); *jp->statep = JSON_PARSE_STATE_STRING; break; case JSON_PARSE_STATE_STRING_HEX: if (('0' <= c) && (c <= '9')) jp->hexChar = (jp->hexChar << 4) | (c - '0'); else if (('a' <= c) && (c <= 'f')) jp->hexChar = (jp->hexChar << 4) | (c - 'a' + 0x0a); else if (('A' <= c) && (c <= 'F')) jp->hexChar = (jp->hexChar << 4) | (c - 'A' + 0x0a); else return JS_FALSE; // unexpected if (++(jp->numHex) == 4) { js_AppendChar(jp->buffer, jp->hexChar); jp->hexChar = 0; jp->numHex = 0; *jp->statep = JSON_PARSE_STATE_STRING; } break; case JSON_PARSE_STATE_KEYWORD: if (JS7_ISLET(c)) { js_AppendChar(jp->buffer, c); } else { // this character isn't part of the keyword, process it again i--; if(!PopState(jp)) return JS_FALSE; if (!HandleData(cx, jp, JSON_DATA_KEYWORD, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer))) return JS_FALSE; } break; case JSON_PARSE_STATE_NUMBER: if (IsNumChar(c)) { js_AppendChar(jp->buffer, c); } else { // this character isn't part of the number, process it again i--; if(!PopState(jp)) return JS_FALSE; if (!HandleData(cx, jp, JSON_DATA_NUMBER, jp->buffer->base, STRING_BUFFER_OFFSET(jp->buffer))) return JS_FALSE; } break; case JSON_PARSE_STATE_FINISHED: if (!JS_ISXMLSPACE(c)) return JS_FALSE; // extra input break; default: JS_NOT_REACHED("Invalid JSON parser state"); } } return JS_TRUE; }