1*635a8641SAndroid Build Coastguard Worker // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2*635a8641SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*635a8641SAndroid Build Coastguard Worker // found in the LICENSE file. 4*635a8641SAndroid Build Coastguard Worker // 5*635a8641SAndroid Build Coastguard Worker // A JSON parser. Converts strings of JSON into a Value object (see 6*635a8641SAndroid Build Coastguard Worker // base/values.h). 7*635a8641SAndroid Build Coastguard Worker // http://www.ietf.org/rfc/rfc4627.txt?number=4627 8*635a8641SAndroid Build Coastguard Worker // 9*635a8641SAndroid Build Coastguard Worker // Known limitations/deviations from the RFC: 10*635a8641SAndroid Build Coastguard Worker // - Only knows how to parse ints within the range of a signed 32 bit int and 11*635a8641SAndroid Build Coastguard Worker // decimal numbers within a double. 12*635a8641SAndroid Build Coastguard Worker // - Assumes input is encoded as UTF8. The spec says we should allow UTF-16 13*635a8641SAndroid Build Coastguard Worker // (BE or LE) and UTF-32 (BE or LE) as well. 14*635a8641SAndroid Build Coastguard Worker // - We limit nesting to 100 levels to prevent stack overflow (this is allowed 15*635a8641SAndroid Build Coastguard Worker // by the RFC). 16*635a8641SAndroid Build Coastguard Worker // - A Unicode FAQ ("http://unicode.org/faq/utf_bom.html") writes a data 17*635a8641SAndroid Build Coastguard Worker // stream may start with a Unicode Byte-Order-Mark (U+FEFF), i.e. the input 18*635a8641SAndroid Build Coastguard Worker // UTF-8 string for the JSONReader::JsonToValue() function may start with a 19*635a8641SAndroid Build Coastguard Worker // UTF-8 BOM (0xEF, 0xBB, 0xBF). 20*635a8641SAndroid Build Coastguard Worker // To avoid the function from mis-treating a UTF-8 BOM as an invalid 21*635a8641SAndroid Build Coastguard Worker // character, the function skips a Unicode BOM at the beginning of the 22*635a8641SAndroid Build Coastguard Worker // Unicode string (converted from the input UTF-8 string) before parsing it. 23*635a8641SAndroid Build Coastguard Worker // 24*635a8641SAndroid Build Coastguard Worker // TODO(tc): Add a parsing option to to relax object keys being wrapped in 25*635a8641SAndroid Build Coastguard Worker // double quotes 26*635a8641SAndroid Build Coastguard Worker // TODO(tc): Add an option to disable comment stripping 27*635a8641SAndroid Build Coastguard Worker 28*635a8641SAndroid Build Coastguard Worker #ifndef BASE_JSON_JSON_READER_H_ 29*635a8641SAndroid Build Coastguard Worker #define BASE_JSON_JSON_READER_H_ 30*635a8641SAndroid Build Coastguard Worker 31*635a8641SAndroid Build Coastguard Worker #include <memory> 32*635a8641SAndroid Build Coastguard Worker #include <string> 33*635a8641SAndroid Build Coastguard Worker 34*635a8641SAndroid Build Coastguard Worker #include "base/base_export.h" 35*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_piece.h" 36*635a8641SAndroid Build Coastguard Worker 37*635a8641SAndroid Build Coastguard Worker namespace base { 38*635a8641SAndroid Build Coastguard Worker 39*635a8641SAndroid Build Coastguard Worker class Value; 40*635a8641SAndroid Build Coastguard Worker 41*635a8641SAndroid Build Coastguard Worker namespace internal { 42*635a8641SAndroid Build Coastguard Worker class JSONParser; 43*635a8641SAndroid Build Coastguard Worker } 44*635a8641SAndroid Build Coastguard Worker 45*635a8641SAndroid Build Coastguard Worker enum JSONParserOptions { 46*635a8641SAndroid Build Coastguard Worker // Parses the input strictly according to RFC 4627, except for where noted 47*635a8641SAndroid Build Coastguard Worker // above. 48*635a8641SAndroid Build Coastguard Worker JSON_PARSE_RFC = 0, 49*635a8641SAndroid Build Coastguard Worker 50*635a8641SAndroid Build Coastguard Worker // Allows commas to exist after the last element in structures. 51*635a8641SAndroid Build Coastguard Worker JSON_ALLOW_TRAILING_COMMAS = 1 << 0, 52*635a8641SAndroid Build Coastguard Worker 53*635a8641SAndroid Build Coastguard Worker // If set the parser replaces invalid characters with the Unicode replacement 54*635a8641SAndroid Build Coastguard Worker // character (U+FFFD). If not set, invalid characters trigger a hard error and 55*635a8641SAndroid Build Coastguard Worker // parsing fails. 56*635a8641SAndroid Build Coastguard Worker JSON_REPLACE_INVALID_CHARACTERS = 1 << 1, 57*635a8641SAndroid Build Coastguard Worker }; 58*635a8641SAndroid Build Coastguard Worker 59*635a8641SAndroid Build Coastguard Worker class BASE_EXPORT JSONReader { 60*635a8641SAndroid Build Coastguard Worker public: 61*635a8641SAndroid Build Coastguard Worker static const int kStackMaxDepth; 62*635a8641SAndroid Build Coastguard Worker 63*635a8641SAndroid Build Coastguard Worker // Error codes during parsing. 64*635a8641SAndroid Build Coastguard Worker enum JsonParseError { 65*635a8641SAndroid Build Coastguard Worker JSON_NO_ERROR = 0, 66*635a8641SAndroid Build Coastguard Worker JSON_INVALID_ESCAPE, 67*635a8641SAndroid Build Coastguard Worker JSON_SYNTAX_ERROR, 68*635a8641SAndroid Build Coastguard Worker JSON_UNEXPECTED_TOKEN, 69*635a8641SAndroid Build Coastguard Worker JSON_TRAILING_COMMA, 70*635a8641SAndroid Build Coastguard Worker JSON_TOO_MUCH_NESTING, 71*635a8641SAndroid Build Coastguard Worker JSON_UNEXPECTED_DATA_AFTER_ROOT, 72*635a8641SAndroid Build Coastguard Worker JSON_UNSUPPORTED_ENCODING, 73*635a8641SAndroid Build Coastguard Worker JSON_UNQUOTED_DICTIONARY_KEY, 74*635a8641SAndroid Build Coastguard Worker JSON_TOO_LARGE, 75*635a8641SAndroid Build Coastguard Worker JSON_PARSE_ERROR_COUNT 76*635a8641SAndroid Build Coastguard Worker }; 77*635a8641SAndroid Build Coastguard Worker 78*635a8641SAndroid Build Coastguard Worker // String versions of parse error codes. 79*635a8641SAndroid Build Coastguard Worker static const char kInvalidEscape[]; 80*635a8641SAndroid Build Coastguard Worker static const char kSyntaxError[]; 81*635a8641SAndroid Build Coastguard Worker static const char kUnexpectedToken[]; 82*635a8641SAndroid Build Coastguard Worker static const char kTrailingComma[]; 83*635a8641SAndroid Build Coastguard Worker static const char kTooMuchNesting[]; 84*635a8641SAndroid Build Coastguard Worker static const char kUnexpectedDataAfterRoot[]; 85*635a8641SAndroid Build Coastguard Worker static const char kUnsupportedEncoding[]; 86*635a8641SAndroid Build Coastguard Worker static const char kUnquotedDictionaryKey[]; 87*635a8641SAndroid Build Coastguard Worker static const char kInputTooLarge[]; 88*635a8641SAndroid Build Coastguard Worker 89*635a8641SAndroid Build Coastguard Worker // Constructs a reader. 90*635a8641SAndroid Build Coastguard Worker JSONReader(int options = JSON_PARSE_RFC, int max_depth = kStackMaxDepth); 91*635a8641SAndroid Build Coastguard Worker 92*635a8641SAndroid Build Coastguard Worker ~JSONReader(); 93*635a8641SAndroid Build Coastguard Worker 94*635a8641SAndroid Build Coastguard Worker // Reads and parses |json|, returning a Value. 95*635a8641SAndroid Build Coastguard Worker // If |json| is not a properly formed JSON string, returns nullptr. 96*635a8641SAndroid Build Coastguard Worker // Wrap this in base::FooValue::From() to check the Value is of type Foo and 97*635a8641SAndroid Build Coastguard Worker // convert to a FooValue at the same time. 98*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<Value> Read(StringPiece json, 99*635a8641SAndroid Build Coastguard Worker int options = JSON_PARSE_RFC, 100*635a8641SAndroid Build Coastguard Worker int max_depth = kStackMaxDepth); 101*635a8641SAndroid Build Coastguard Worker 102*635a8641SAndroid Build Coastguard Worker // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out| 103*635a8641SAndroid Build Coastguard Worker // are optional. If specified and nullptr is returned, they will be populated 104*635a8641SAndroid Build Coastguard Worker // an error code and a formatted error message (including error location if 105*635a8641SAndroid Build Coastguard Worker // appropriate). Otherwise, they will be unmodified. 106*635a8641SAndroid Build Coastguard Worker static std::unique_ptr<Value> ReadAndReturnError( 107*635a8641SAndroid Build Coastguard Worker StringPiece json, 108*635a8641SAndroid Build Coastguard Worker int options, // JSONParserOptions 109*635a8641SAndroid Build Coastguard Worker int* error_code_out, 110*635a8641SAndroid Build Coastguard Worker std::string* error_msg_out, 111*635a8641SAndroid Build Coastguard Worker int* error_line_out = nullptr, 112*635a8641SAndroid Build Coastguard Worker int* error_column_out = nullptr); 113*635a8641SAndroid Build Coastguard Worker 114*635a8641SAndroid Build Coastguard Worker // Converts a JSON parse error code into a human readable message. 115*635a8641SAndroid Build Coastguard Worker // Returns an empty string if error_code is JSON_NO_ERROR. 116*635a8641SAndroid Build Coastguard Worker static std::string ErrorCodeToString(JsonParseError error_code); 117*635a8641SAndroid Build Coastguard Worker 118*635a8641SAndroid Build Coastguard Worker // Non-static version of Read() above. 119*635a8641SAndroid Build Coastguard Worker std::unique_ptr<Value> ReadToValue(StringPiece json); 120*635a8641SAndroid Build Coastguard Worker 121*635a8641SAndroid Build Coastguard Worker // Returns the error code if the last call to ReadToValue() failed. 122*635a8641SAndroid Build Coastguard Worker // Returns JSON_NO_ERROR otherwise. 123*635a8641SAndroid Build Coastguard Worker JsonParseError error_code() const; 124*635a8641SAndroid Build Coastguard Worker 125*635a8641SAndroid Build Coastguard Worker // Converts error_code_ to a human-readable string, including line and column 126*635a8641SAndroid Build Coastguard Worker // numbers if appropriate. 127*635a8641SAndroid Build Coastguard Worker std::string GetErrorMessage() const; 128*635a8641SAndroid Build Coastguard Worker 129*635a8641SAndroid Build Coastguard Worker private: 130*635a8641SAndroid Build Coastguard Worker std::unique_ptr<internal::JSONParser> parser_; 131*635a8641SAndroid Build Coastguard Worker }; 132*635a8641SAndroid Build Coastguard Worker 133*635a8641SAndroid Build Coastguard Worker } // namespace base 134*635a8641SAndroid Build Coastguard Worker 135*635a8641SAndroid Build Coastguard Worker #endif // BASE_JSON_JSON_READER_H_ 136