xref: /aosp_15_r20/external/libchrome/base/json/json_reader.h (revision 635a864187cb8b6c713ff48b7e790a6b21769273)
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