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 #include "base/json/json_parser.h"
6*635a8641SAndroid Build Coastguard Worker
7*635a8641SAndroid Build Coastguard Worker #include <cmath>
8*635a8641SAndroid Build Coastguard Worker #include <utility>
9*635a8641SAndroid Build Coastguard Worker #include <vector>
10*635a8641SAndroid Build Coastguard Worker
11*635a8641SAndroid Build Coastguard Worker #include "base/logging.h"
12*635a8641SAndroid Build Coastguard Worker #include "base/macros.h"
13*635a8641SAndroid Build Coastguard Worker #include "base/numerics/safe_conversions.h"
14*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_number_conversions.h"
15*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_piece.h"
16*635a8641SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
17*635a8641SAndroid Build Coastguard Worker #include "base/strings/stringprintf.h"
18*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversion_utils.h"
19*635a8641SAndroid Build Coastguard Worker #include "base/strings/utf_string_conversions.h"
20*635a8641SAndroid Build Coastguard Worker #include "base/third_party/icu/icu_utf.h"
21*635a8641SAndroid Build Coastguard Worker #include "base/values.h"
22*635a8641SAndroid Build Coastguard Worker
23*635a8641SAndroid Build Coastguard Worker namespace base {
24*635a8641SAndroid Build Coastguard Worker namespace internal {
25*635a8641SAndroid Build Coastguard Worker
26*635a8641SAndroid Build Coastguard Worker namespace {
27*635a8641SAndroid Build Coastguard Worker
28*635a8641SAndroid Build Coastguard Worker const int32_t kExtendedASCIIStart = 0x80;
29*635a8641SAndroid Build Coastguard Worker
30*635a8641SAndroid Build Coastguard Worker // Simple class that checks for maximum recursion/"stack overflow."
31*635a8641SAndroid Build Coastguard Worker class StackMarker {
32*635a8641SAndroid Build Coastguard Worker public:
StackMarker(int max_depth,int * depth)33*635a8641SAndroid Build Coastguard Worker StackMarker(int max_depth, int* depth)
34*635a8641SAndroid Build Coastguard Worker : max_depth_(max_depth), depth_(depth) {
35*635a8641SAndroid Build Coastguard Worker ++(*depth_);
36*635a8641SAndroid Build Coastguard Worker DCHECK_LE(*depth_, max_depth_);
37*635a8641SAndroid Build Coastguard Worker }
~StackMarker()38*635a8641SAndroid Build Coastguard Worker ~StackMarker() {
39*635a8641SAndroid Build Coastguard Worker --(*depth_);
40*635a8641SAndroid Build Coastguard Worker }
41*635a8641SAndroid Build Coastguard Worker
IsTooDeep() const42*635a8641SAndroid Build Coastguard Worker bool IsTooDeep() const { return *depth_ >= max_depth_; }
43*635a8641SAndroid Build Coastguard Worker
44*635a8641SAndroid Build Coastguard Worker private:
45*635a8641SAndroid Build Coastguard Worker const int max_depth_;
46*635a8641SAndroid Build Coastguard Worker int* const depth_;
47*635a8641SAndroid Build Coastguard Worker
48*635a8641SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(StackMarker);
49*635a8641SAndroid Build Coastguard Worker };
50*635a8641SAndroid Build Coastguard Worker
51*635a8641SAndroid Build Coastguard Worker constexpr uint32_t kUnicodeReplacementPoint = 0xFFFD;
52*635a8641SAndroid Build Coastguard Worker
53*635a8641SAndroid Build Coastguard Worker } // namespace
54*635a8641SAndroid Build Coastguard Worker
55*635a8641SAndroid Build Coastguard Worker // This is U+FFFD.
56*635a8641SAndroid Build Coastguard Worker const char kUnicodeReplacementString[] = "\xEF\xBF\xBD";
57*635a8641SAndroid Build Coastguard Worker
JSONParser(int options,int max_depth)58*635a8641SAndroid Build Coastguard Worker JSONParser::JSONParser(int options, int max_depth)
59*635a8641SAndroid Build Coastguard Worker : options_(options),
60*635a8641SAndroid Build Coastguard Worker max_depth_(max_depth),
61*635a8641SAndroid Build Coastguard Worker index_(0),
62*635a8641SAndroid Build Coastguard Worker stack_depth_(0),
63*635a8641SAndroid Build Coastguard Worker line_number_(0),
64*635a8641SAndroid Build Coastguard Worker index_last_line_(0),
65*635a8641SAndroid Build Coastguard Worker error_code_(JSONReader::JSON_NO_ERROR),
66*635a8641SAndroid Build Coastguard Worker error_line_(0),
67*635a8641SAndroid Build Coastguard Worker error_column_(0) {
68*635a8641SAndroid Build Coastguard Worker CHECK_LE(max_depth, JSONReader::kStackMaxDepth);
69*635a8641SAndroid Build Coastguard Worker }
70*635a8641SAndroid Build Coastguard Worker
71*635a8641SAndroid Build Coastguard Worker JSONParser::~JSONParser() = default;
72*635a8641SAndroid Build Coastguard Worker
Parse(StringPiece input)73*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::Parse(StringPiece input) {
74*635a8641SAndroid Build Coastguard Worker input_ = input;
75*635a8641SAndroid Build Coastguard Worker index_ = 0;
76*635a8641SAndroid Build Coastguard Worker line_number_ = 1;
77*635a8641SAndroid Build Coastguard Worker index_last_line_ = 0;
78*635a8641SAndroid Build Coastguard Worker
79*635a8641SAndroid Build Coastguard Worker error_code_ = JSONReader::JSON_NO_ERROR;
80*635a8641SAndroid Build Coastguard Worker error_line_ = 0;
81*635a8641SAndroid Build Coastguard Worker error_column_ = 0;
82*635a8641SAndroid Build Coastguard Worker
83*635a8641SAndroid Build Coastguard Worker // ICU and ReadUnicodeCharacter() use int32_t for lengths, so ensure
84*635a8641SAndroid Build Coastguard Worker // that the index_ will not overflow when parsing.
85*635a8641SAndroid Build Coastguard Worker if (!base::IsValueInRangeForNumericType<int32_t>(input.length())) {
86*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_TOO_LARGE, 0);
87*635a8641SAndroid Build Coastguard Worker return nullopt;
88*635a8641SAndroid Build Coastguard Worker }
89*635a8641SAndroid Build Coastguard Worker
90*635a8641SAndroid Build Coastguard Worker // When the input JSON string starts with a UTF-8 Byte-Order-Mark,
91*635a8641SAndroid Build Coastguard Worker // advance the start position to avoid the ParseNextToken function mis-
92*635a8641SAndroid Build Coastguard Worker // treating a Unicode BOM as an invalid character and returning NULL.
93*635a8641SAndroid Build Coastguard Worker ConsumeIfMatch("\xEF\xBB\xBF");
94*635a8641SAndroid Build Coastguard Worker
95*635a8641SAndroid Build Coastguard Worker // Parse the first and any nested tokens.
96*635a8641SAndroid Build Coastguard Worker Optional<Value> root(ParseNextToken());
97*635a8641SAndroid Build Coastguard Worker if (!root)
98*635a8641SAndroid Build Coastguard Worker return nullopt;
99*635a8641SAndroid Build Coastguard Worker
100*635a8641SAndroid Build Coastguard Worker // Make sure the input stream is at an end.
101*635a8641SAndroid Build Coastguard Worker if (GetNextToken() != T_END_OF_INPUT) {
102*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, 1);
103*635a8641SAndroid Build Coastguard Worker return nullopt;
104*635a8641SAndroid Build Coastguard Worker }
105*635a8641SAndroid Build Coastguard Worker
106*635a8641SAndroid Build Coastguard Worker return root;
107*635a8641SAndroid Build Coastguard Worker }
108*635a8641SAndroid Build Coastguard Worker
error_code() const109*635a8641SAndroid Build Coastguard Worker JSONReader::JsonParseError JSONParser::error_code() const {
110*635a8641SAndroid Build Coastguard Worker return error_code_;
111*635a8641SAndroid Build Coastguard Worker }
112*635a8641SAndroid Build Coastguard Worker
GetErrorMessage() const113*635a8641SAndroid Build Coastguard Worker std::string JSONParser::GetErrorMessage() const {
114*635a8641SAndroid Build Coastguard Worker return FormatErrorMessage(error_line_, error_column_,
115*635a8641SAndroid Build Coastguard Worker JSONReader::ErrorCodeToString(error_code_));
116*635a8641SAndroid Build Coastguard Worker }
117*635a8641SAndroid Build Coastguard Worker
error_line() const118*635a8641SAndroid Build Coastguard Worker int JSONParser::error_line() const {
119*635a8641SAndroid Build Coastguard Worker return error_line_;
120*635a8641SAndroid Build Coastguard Worker }
121*635a8641SAndroid Build Coastguard Worker
error_column() const122*635a8641SAndroid Build Coastguard Worker int JSONParser::error_column() const {
123*635a8641SAndroid Build Coastguard Worker return error_column_;
124*635a8641SAndroid Build Coastguard Worker }
125*635a8641SAndroid Build Coastguard Worker
126*635a8641SAndroid Build Coastguard Worker // StringBuilder ///////////////////////////////////////////////////////////////
127*635a8641SAndroid Build Coastguard Worker
StringBuilder()128*635a8641SAndroid Build Coastguard Worker JSONParser::StringBuilder::StringBuilder() : StringBuilder(nullptr) {}
129*635a8641SAndroid Build Coastguard Worker
StringBuilder(const char * pos)130*635a8641SAndroid Build Coastguard Worker JSONParser::StringBuilder::StringBuilder(const char* pos)
131*635a8641SAndroid Build Coastguard Worker : pos_(pos), length_(0) {}
132*635a8641SAndroid Build Coastguard Worker
133*635a8641SAndroid Build Coastguard Worker JSONParser::StringBuilder::~StringBuilder() = default;
134*635a8641SAndroid Build Coastguard Worker
135*635a8641SAndroid Build Coastguard Worker JSONParser::StringBuilder& JSONParser::StringBuilder::operator=(
136*635a8641SAndroid Build Coastguard Worker StringBuilder&& other) = default;
137*635a8641SAndroid Build Coastguard Worker
Append(uint32_t point)138*635a8641SAndroid Build Coastguard Worker void JSONParser::StringBuilder::Append(uint32_t point) {
139*635a8641SAndroid Build Coastguard Worker DCHECK(IsValidCharacter(point));
140*635a8641SAndroid Build Coastguard Worker
141*635a8641SAndroid Build Coastguard Worker if (point < kExtendedASCIIStart && !string_) {
142*635a8641SAndroid Build Coastguard Worker DCHECK_EQ(static_cast<char>(point), pos_[length_]);
143*635a8641SAndroid Build Coastguard Worker ++length_;
144*635a8641SAndroid Build Coastguard Worker } else {
145*635a8641SAndroid Build Coastguard Worker Convert();
146*635a8641SAndroid Build Coastguard Worker if (UNLIKELY(point == kUnicodeReplacementPoint)) {
147*635a8641SAndroid Build Coastguard Worker string_->append(kUnicodeReplacementString);
148*635a8641SAndroid Build Coastguard Worker } else {
149*635a8641SAndroid Build Coastguard Worker WriteUnicodeCharacter(point, &*string_);
150*635a8641SAndroid Build Coastguard Worker }
151*635a8641SAndroid Build Coastguard Worker }
152*635a8641SAndroid Build Coastguard Worker }
153*635a8641SAndroid Build Coastguard Worker
Convert()154*635a8641SAndroid Build Coastguard Worker void JSONParser::StringBuilder::Convert() {
155*635a8641SAndroid Build Coastguard Worker if (string_)
156*635a8641SAndroid Build Coastguard Worker return;
157*635a8641SAndroid Build Coastguard Worker string_.emplace(pos_, length_);
158*635a8641SAndroid Build Coastguard Worker }
159*635a8641SAndroid Build Coastguard Worker
DestructiveAsString()160*635a8641SAndroid Build Coastguard Worker std::string JSONParser::StringBuilder::DestructiveAsString() {
161*635a8641SAndroid Build Coastguard Worker if (string_)
162*635a8641SAndroid Build Coastguard Worker return std::move(*string_);
163*635a8641SAndroid Build Coastguard Worker return std::string(pos_, length_);
164*635a8641SAndroid Build Coastguard Worker }
165*635a8641SAndroid Build Coastguard Worker
166*635a8641SAndroid Build Coastguard Worker // JSONParser private //////////////////////////////////////////////////////////
167*635a8641SAndroid Build Coastguard Worker
PeekChars(int count)168*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> JSONParser::PeekChars(int count) {
169*635a8641SAndroid Build Coastguard Worker if (static_cast<size_t>(index_) + count > input_.length())
170*635a8641SAndroid Build Coastguard Worker return nullopt;
171*635a8641SAndroid Build Coastguard Worker // Using StringPiece::substr() is significantly slower (according to
172*635a8641SAndroid Build Coastguard Worker // base_perftests) than constructing a substring manually.
173*635a8641SAndroid Build Coastguard Worker return StringPiece(input_.data() + index_, count);
174*635a8641SAndroid Build Coastguard Worker }
175*635a8641SAndroid Build Coastguard Worker
PeekChar()176*635a8641SAndroid Build Coastguard Worker Optional<char> JSONParser::PeekChar() {
177*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> chars = PeekChars(1);
178*635a8641SAndroid Build Coastguard Worker if (chars)
179*635a8641SAndroid Build Coastguard Worker return (*chars)[0];
180*635a8641SAndroid Build Coastguard Worker return nullopt;
181*635a8641SAndroid Build Coastguard Worker }
182*635a8641SAndroid Build Coastguard Worker
ConsumeChars(int count)183*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> JSONParser::ConsumeChars(int count) {
184*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> chars = PeekChars(count);
185*635a8641SAndroid Build Coastguard Worker if (chars)
186*635a8641SAndroid Build Coastguard Worker index_ += count;
187*635a8641SAndroid Build Coastguard Worker return chars;
188*635a8641SAndroid Build Coastguard Worker }
189*635a8641SAndroid Build Coastguard Worker
ConsumeChar()190*635a8641SAndroid Build Coastguard Worker Optional<char> JSONParser::ConsumeChar() {
191*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> chars = ConsumeChars(1);
192*635a8641SAndroid Build Coastguard Worker if (chars)
193*635a8641SAndroid Build Coastguard Worker return (*chars)[0];
194*635a8641SAndroid Build Coastguard Worker return nullopt;
195*635a8641SAndroid Build Coastguard Worker }
196*635a8641SAndroid Build Coastguard Worker
pos()197*635a8641SAndroid Build Coastguard Worker const char* JSONParser::pos() {
198*635a8641SAndroid Build Coastguard Worker CHECK_LE(static_cast<size_t>(index_), input_.length());
199*635a8641SAndroid Build Coastguard Worker return input_.data() + index_;
200*635a8641SAndroid Build Coastguard Worker }
201*635a8641SAndroid Build Coastguard Worker
GetNextToken()202*635a8641SAndroid Build Coastguard Worker JSONParser::Token JSONParser::GetNextToken() {
203*635a8641SAndroid Build Coastguard Worker EatWhitespaceAndComments();
204*635a8641SAndroid Build Coastguard Worker
205*635a8641SAndroid Build Coastguard Worker Optional<char> c = PeekChar();
206*635a8641SAndroid Build Coastguard Worker if (!c)
207*635a8641SAndroid Build Coastguard Worker return T_END_OF_INPUT;
208*635a8641SAndroid Build Coastguard Worker
209*635a8641SAndroid Build Coastguard Worker switch (*c) {
210*635a8641SAndroid Build Coastguard Worker case '{':
211*635a8641SAndroid Build Coastguard Worker return T_OBJECT_BEGIN;
212*635a8641SAndroid Build Coastguard Worker case '}':
213*635a8641SAndroid Build Coastguard Worker return T_OBJECT_END;
214*635a8641SAndroid Build Coastguard Worker case '[':
215*635a8641SAndroid Build Coastguard Worker return T_ARRAY_BEGIN;
216*635a8641SAndroid Build Coastguard Worker case ']':
217*635a8641SAndroid Build Coastguard Worker return T_ARRAY_END;
218*635a8641SAndroid Build Coastguard Worker case '"':
219*635a8641SAndroid Build Coastguard Worker return T_STRING;
220*635a8641SAndroid Build Coastguard Worker case '0':
221*635a8641SAndroid Build Coastguard Worker case '1':
222*635a8641SAndroid Build Coastguard Worker case '2':
223*635a8641SAndroid Build Coastguard Worker case '3':
224*635a8641SAndroid Build Coastguard Worker case '4':
225*635a8641SAndroid Build Coastguard Worker case '5':
226*635a8641SAndroid Build Coastguard Worker case '6':
227*635a8641SAndroid Build Coastguard Worker case '7':
228*635a8641SAndroid Build Coastguard Worker case '8':
229*635a8641SAndroid Build Coastguard Worker case '9':
230*635a8641SAndroid Build Coastguard Worker case '-':
231*635a8641SAndroid Build Coastguard Worker return T_NUMBER;
232*635a8641SAndroid Build Coastguard Worker case 't':
233*635a8641SAndroid Build Coastguard Worker return T_BOOL_TRUE;
234*635a8641SAndroid Build Coastguard Worker case 'f':
235*635a8641SAndroid Build Coastguard Worker return T_BOOL_FALSE;
236*635a8641SAndroid Build Coastguard Worker case 'n':
237*635a8641SAndroid Build Coastguard Worker return T_NULL;
238*635a8641SAndroid Build Coastguard Worker case ',':
239*635a8641SAndroid Build Coastguard Worker return T_LIST_SEPARATOR;
240*635a8641SAndroid Build Coastguard Worker case ':':
241*635a8641SAndroid Build Coastguard Worker return T_OBJECT_PAIR_SEPARATOR;
242*635a8641SAndroid Build Coastguard Worker default:
243*635a8641SAndroid Build Coastguard Worker return T_INVALID_TOKEN;
244*635a8641SAndroid Build Coastguard Worker }
245*635a8641SAndroid Build Coastguard Worker }
246*635a8641SAndroid Build Coastguard Worker
EatWhitespaceAndComments()247*635a8641SAndroid Build Coastguard Worker void JSONParser::EatWhitespaceAndComments() {
248*635a8641SAndroid Build Coastguard Worker while (Optional<char> c = PeekChar()) {
249*635a8641SAndroid Build Coastguard Worker switch (*c) {
250*635a8641SAndroid Build Coastguard Worker case '\r':
251*635a8641SAndroid Build Coastguard Worker case '\n':
252*635a8641SAndroid Build Coastguard Worker index_last_line_ = index_;
253*635a8641SAndroid Build Coastguard Worker // Don't increment line_number_ twice for "\r\n".
254*635a8641SAndroid Build Coastguard Worker if (!(c == '\n' && index_ > 0 && input_[index_ - 1] == '\r')) {
255*635a8641SAndroid Build Coastguard Worker ++line_number_;
256*635a8641SAndroid Build Coastguard Worker }
257*635a8641SAndroid Build Coastguard Worker FALLTHROUGH;
258*635a8641SAndroid Build Coastguard Worker case ' ':
259*635a8641SAndroid Build Coastguard Worker case '\t':
260*635a8641SAndroid Build Coastguard Worker ConsumeChar();
261*635a8641SAndroid Build Coastguard Worker break;
262*635a8641SAndroid Build Coastguard Worker case '/':
263*635a8641SAndroid Build Coastguard Worker if (!EatComment())
264*635a8641SAndroid Build Coastguard Worker return;
265*635a8641SAndroid Build Coastguard Worker break;
266*635a8641SAndroid Build Coastguard Worker default:
267*635a8641SAndroid Build Coastguard Worker return;
268*635a8641SAndroid Build Coastguard Worker }
269*635a8641SAndroid Build Coastguard Worker }
270*635a8641SAndroid Build Coastguard Worker }
271*635a8641SAndroid Build Coastguard Worker
EatComment()272*635a8641SAndroid Build Coastguard Worker bool JSONParser::EatComment() {
273*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> comment_start = ConsumeChars(2);
274*635a8641SAndroid Build Coastguard Worker if (!comment_start)
275*635a8641SAndroid Build Coastguard Worker return false;
276*635a8641SAndroid Build Coastguard Worker
277*635a8641SAndroid Build Coastguard Worker if (comment_start == "//") {
278*635a8641SAndroid Build Coastguard Worker // Single line comment, read to newline.
279*635a8641SAndroid Build Coastguard Worker while (Optional<char> c = PeekChar()) {
280*635a8641SAndroid Build Coastguard Worker if (c == '\n' || c == '\r')
281*635a8641SAndroid Build Coastguard Worker return true;
282*635a8641SAndroid Build Coastguard Worker ConsumeChar();
283*635a8641SAndroid Build Coastguard Worker }
284*635a8641SAndroid Build Coastguard Worker } else if (comment_start == "/*") {
285*635a8641SAndroid Build Coastguard Worker char previous_char = '\0';
286*635a8641SAndroid Build Coastguard Worker // Block comment, read until end marker.
287*635a8641SAndroid Build Coastguard Worker while (Optional<char> c = PeekChar()) {
288*635a8641SAndroid Build Coastguard Worker if (previous_char == '*' && c == '/') {
289*635a8641SAndroid Build Coastguard Worker // EatWhitespaceAndComments will inspect pos(), which will still be on
290*635a8641SAndroid Build Coastguard Worker // the last / of the comment, so advance once more (which may also be
291*635a8641SAndroid Build Coastguard Worker // end of input).
292*635a8641SAndroid Build Coastguard Worker ConsumeChar();
293*635a8641SAndroid Build Coastguard Worker return true;
294*635a8641SAndroid Build Coastguard Worker }
295*635a8641SAndroid Build Coastguard Worker previous_char = *ConsumeChar();
296*635a8641SAndroid Build Coastguard Worker }
297*635a8641SAndroid Build Coastguard Worker
298*635a8641SAndroid Build Coastguard Worker // If the comment is unterminated, GetNextToken will report T_END_OF_INPUT.
299*635a8641SAndroid Build Coastguard Worker }
300*635a8641SAndroid Build Coastguard Worker
301*635a8641SAndroid Build Coastguard Worker return false;
302*635a8641SAndroid Build Coastguard Worker }
303*635a8641SAndroid Build Coastguard Worker
ParseNextToken()304*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ParseNextToken() {
305*635a8641SAndroid Build Coastguard Worker return ParseToken(GetNextToken());
306*635a8641SAndroid Build Coastguard Worker }
307*635a8641SAndroid Build Coastguard Worker
ParseToken(Token token)308*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ParseToken(Token token) {
309*635a8641SAndroid Build Coastguard Worker switch (token) {
310*635a8641SAndroid Build Coastguard Worker case T_OBJECT_BEGIN:
311*635a8641SAndroid Build Coastguard Worker return ConsumeDictionary();
312*635a8641SAndroid Build Coastguard Worker case T_ARRAY_BEGIN:
313*635a8641SAndroid Build Coastguard Worker return ConsumeList();
314*635a8641SAndroid Build Coastguard Worker case T_STRING:
315*635a8641SAndroid Build Coastguard Worker return ConsumeString();
316*635a8641SAndroid Build Coastguard Worker case T_NUMBER:
317*635a8641SAndroid Build Coastguard Worker return ConsumeNumber();
318*635a8641SAndroid Build Coastguard Worker case T_BOOL_TRUE:
319*635a8641SAndroid Build Coastguard Worker case T_BOOL_FALSE:
320*635a8641SAndroid Build Coastguard Worker case T_NULL:
321*635a8641SAndroid Build Coastguard Worker return ConsumeLiteral();
322*635a8641SAndroid Build Coastguard Worker default:
323*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
324*635a8641SAndroid Build Coastguard Worker return nullopt;
325*635a8641SAndroid Build Coastguard Worker }
326*635a8641SAndroid Build Coastguard Worker }
327*635a8641SAndroid Build Coastguard Worker
ConsumeDictionary()328*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ConsumeDictionary() {
329*635a8641SAndroid Build Coastguard Worker if (ConsumeChar() != '{') {
330*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
331*635a8641SAndroid Build Coastguard Worker return nullopt;
332*635a8641SAndroid Build Coastguard Worker }
333*635a8641SAndroid Build Coastguard Worker
334*635a8641SAndroid Build Coastguard Worker StackMarker depth_check(max_depth_, &stack_depth_);
335*635a8641SAndroid Build Coastguard Worker if (depth_check.IsTooDeep()) {
336*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
337*635a8641SAndroid Build Coastguard Worker return nullopt;
338*635a8641SAndroid Build Coastguard Worker }
339*635a8641SAndroid Build Coastguard Worker
340*635a8641SAndroid Build Coastguard Worker std::vector<Value::DictStorage::value_type> dict_storage;
341*635a8641SAndroid Build Coastguard Worker
342*635a8641SAndroid Build Coastguard Worker Token token = GetNextToken();
343*635a8641SAndroid Build Coastguard Worker while (token != T_OBJECT_END) {
344*635a8641SAndroid Build Coastguard Worker if (token != T_STRING) {
345*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, 1);
346*635a8641SAndroid Build Coastguard Worker return nullopt;
347*635a8641SAndroid Build Coastguard Worker }
348*635a8641SAndroid Build Coastguard Worker
349*635a8641SAndroid Build Coastguard Worker // First consume the key.
350*635a8641SAndroid Build Coastguard Worker StringBuilder key;
351*635a8641SAndroid Build Coastguard Worker if (!ConsumeStringRaw(&key)) {
352*635a8641SAndroid Build Coastguard Worker return nullopt;
353*635a8641SAndroid Build Coastguard Worker }
354*635a8641SAndroid Build Coastguard Worker
355*635a8641SAndroid Build Coastguard Worker // Read the separator.
356*635a8641SAndroid Build Coastguard Worker token = GetNextToken();
357*635a8641SAndroid Build Coastguard Worker if (token != T_OBJECT_PAIR_SEPARATOR) {
358*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
359*635a8641SAndroid Build Coastguard Worker return nullopt;
360*635a8641SAndroid Build Coastguard Worker }
361*635a8641SAndroid Build Coastguard Worker
362*635a8641SAndroid Build Coastguard Worker // The next token is the value. Ownership transfers to |dict|.
363*635a8641SAndroid Build Coastguard Worker ConsumeChar();
364*635a8641SAndroid Build Coastguard Worker Optional<Value> value = ParseNextToken();
365*635a8641SAndroid Build Coastguard Worker if (!value) {
366*635a8641SAndroid Build Coastguard Worker // ReportError from deeper level.
367*635a8641SAndroid Build Coastguard Worker return nullopt;
368*635a8641SAndroid Build Coastguard Worker }
369*635a8641SAndroid Build Coastguard Worker
370*635a8641SAndroid Build Coastguard Worker dict_storage.emplace_back(key.DestructiveAsString(),
371*635a8641SAndroid Build Coastguard Worker std::make_unique<Value>(std::move(*value)));
372*635a8641SAndroid Build Coastguard Worker
373*635a8641SAndroid Build Coastguard Worker token = GetNextToken();
374*635a8641SAndroid Build Coastguard Worker if (token == T_LIST_SEPARATOR) {
375*635a8641SAndroid Build Coastguard Worker ConsumeChar();
376*635a8641SAndroid Build Coastguard Worker token = GetNextToken();
377*635a8641SAndroid Build Coastguard Worker if (token == T_OBJECT_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
378*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
379*635a8641SAndroid Build Coastguard Worker return nullopt;
380*635a8641SAndroid Build Coastguard Worker }
381*635a8641SAndroid Build Coastguard Worker } else if (token != T_OBJECT_END) {
382*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
383*635a8641SAndroid Build Coastguard Worker return nullopt;
384*635a8641SAndroid Build Coastguard Worker }
385*635a8641SAndroid Build Coastguard Worker }
386*635a8641SAndroid Build Coastguard Worker
387*635a8641SAndroid Build Coastguard Worker ConsumeChar(); // Closing '}'.
388*635a8641SAndroid Build Coastguard Worker
389*635a8641SAndroid Build Coastguard Worker return Value(Value::DictStorage(std::move(dict_storage), KEEP_LAST_OF_DUPES));
390*635a8641SAndroid Build Coastguard Worker }
391*635a8641SAndroid Build Coastguard Worker
ConsumeList()392*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ConsumeList() {
393*635a8641SAndroid Build Coastguard Worker if (ConsumeChar() != '[') {
394*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
395*635a8641SAndroid Build Coastguard Worker return nullopt;
396*635a8641SAndroid Build Coastguard Worker }
397*635a8641SAndroid Build Coastguard Worker
398*635a8641SAndroid Build Coastguard Worker StackMarker depth_check(max_depth_, &stack_depth_);
399*635a8641SAndroid Build Coastguard Worker if (depth_check.IsTooDeep()) {
400*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_TOO_MUCH_NESTING, 0);
401*635a8641SAndroid Build Coastguard Worker return nullopt;
402*635a8641SAndroid Build Coastguard Worker }
403*635a8641SAndroid Build Coastguard Worker
404*635a8641SAndroid Build Coastguard Worker Value::ListStorage list_storage;
405*635a8641SAndroid Build Coastguard Worker
406*635a8641SAndroid Build Coastguard Worker Token token = GetNextToken();
407*635a8641SAndroid Build Coastguard Worker while (token != T_ARRAY_END) {
408*635a8641SAndroid Build Coastguard Worker Optional<Value> item = ParseToken(token);
409*635a8641SAndroid Build Coastguard Worker if (!item) {
410*635a8641SAndroid Build Coastguard Worker // ReportError from deeper level.
411*635a8641SAndroid Build Coastguard Worker return nullopt;
412*635a8641SAndroid Build Coastguard Worker }
413*635a8641SAndroid Build Coastguard Worker
414*635a8641SAndroid Build Coastguard Worker list_storage.push_back(std::move(*item));
415*635a8641SAndroid Build Coastguard Worker
416*635a8641SAndroid Build Coastguard Worker token = GetNextToken();
417*635a8641SAndroid Build Coastguard Worker if (token == T_LIST_SEPARATOR) {
418*635a8641SAndroid Build Coastguard Worker ConsumeChar();
419*635a8641SAndroid Build Coastguard Worker token = GetNextToken();
420*635a8641SAndroid Build Coastguard Worker if (token == T_ARRAY_END && !(options_ & JSON_ALLOW_TRAILING_COMMAS)) {
421*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_TRAILING_COMMA, 1);
422*635a8641SAndroid Build Coastguard Worker return nullopt;
423*635a8641SAndroid Build Coastguard Worker }
424*635a8641SAndroid Build Coastguard Worker } else if (token != T_ARRAY_END) {
425*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
426*635a8641SAndroid Build Coastguard Worker return nullopt;
427*635a8641SAndroid Build Coastguard Worker }
428*635a8641SAndroid Build Coastguard Worker }
429*635a8641SAndroid Build Coastguard Worker
430*635a8641SAndroid Build Coastguard Worker ConsumeChar(); // Closing ']'.
431*635a8641SAndroid Build Coastguard Worker
432*635a8641SAndroid Build Coastguard Worker return Value(std::move(list_storage));
433*635a8641SAndroid Build Coastguard Worker }
434*635a8641SAndroid Build Coastguard Worker
ConsumeString()435*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ConsumeString() {
436*635a8641SAndroid Build Coastguard Worker StringBuilder string;
437*635a8641SAndroid Build Coastguard Worker if (!ConsumeStringRaw(&string))
438*635a8641SAndroid Build Coastguard Worker return nullopt;
439*635a8641SAndroid Build Coastguard Worker
440*635a8641SAndroid Build Coastguard Worker return Value(string.DestructiveAsString());
441*635a8641SAndroid Build Coastguard Worker }
442*635a8641SAndroid Build Coastguard Worker
ConsumeStringRaw(StringBuilder * out)443*635a8641SAndroid Build Coastguard Worker bool JSONParser::ConsumeStringRaw(StringBuilder* out) {
444*635a8641SAndroid Build Coastguard Worker if (ConsumeChar() != '"') {
445*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNEXPECTED_TOKEN, 1);
446*635a8641SAndroid Build Coastguard Worker return false;
447*635a8641SAndroid Build Coastguard Worker }
448*635a8641SAndroid Build Coastguard Worker
449*635a8641SAndroid Build Coastguard Worker // StringBuilder will internally build a StringPiece unless a UTF-16
450*635a8641SAndroid Build Coastguard Worker // conversion occurs, at which point it will perform a copy into a
451*635a8641SAndroid Build Coastguard Worker // std::string.
452*635a8641SAndroid Build Coastguard Worker StringBuilder string(pos());
453*635a8641SAndroid Build Coastguard Worker
454*635a8641SAndroid Build Coastguard Worker while (PeekChar()) {
455*635a8641SAndroid Build Coastguard Worker uint32_t next_char = 0;
456*635a8641SAndroid Build Coastguard Worker if (!ReadUnicodeCharacter(input_.data(),
457*635a8641SAndroid Build Coastguard Worker static_cast<int32_t>(input_.length()),
458*635a8641SAndroid Build Coastguard Worker &index_,
459*635a8641SAndroid Build Coastguard Worker &next_char) ||
460*635a8641SAndroid Build Coastguard Worker !IsValidCharacter(next_char)) {
461*635a8641SAndroid Build Coastguard Worker if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
462*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_UNSUPPORTED_ENCODING, 1);
463*635a8641SAndroid Build Coastguard Worker return false;
464*635a8641SAndroid Build Coastguard Worker }
465*635a8641SAndroid Build Coastguard Worker ConsumeChar();
466*635a8641SAndroid Build Coastguard Worker string.Append(kUnicodeReplacementPoint);
467*635a8641SAndroid Build Coastguard Worker continue;
468*635a8641SAndroid Build Coastguard Worker }
469*635a8641SAndroid Build Coastguard Worker
470*635a8641SAndroid Build Coastguard Worker if (next_char == '"') {
471*635a8641SAndroid Build Coastguard Worker ConsumeChar();
472*635a8641SAndroid Build Coastguard Worker *out = std::move(string);
473*635a8641SAndroid Build Coastguard Worker return true;
474*635a8641SAndroid Build Coastguard Worker } else if (next_char != '\\') {
475*635a8641SAndroid Build Coastguard Worker // If this character is not an escape sequence...
476*635a8641SAndroid Build Coastguard Worker ConsumeChar();
477*635a8641SAndroid Build Coastguard Worker string.Append(next_char);
478*635a8641SAndroid Build Coastguard Worker } else {
479*635a8641SAndroid Build Coastguard Worker // And if it is an escape sequence, the input string will be adjusted
480*635a8641SAndroid Build Coastguard Worker // (either by combining the two characters of an encoded escape sequence,
481*635a8641SAndroid Build Coastguard Worker // or with a UTF conversion), so using StringPiece isn't possible -- force
482*635a8641SAndroid Build Coastguard Worker // a conversion.
483*635a8641SAndroid Build Coastguard Worker string.Convert();
484*635a8641SAndroid Build Coastguard Worker
485*635a8641SAndroid Build Coastguard Worker // Read past the escape '\' and ensure there's a character following.
486*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> escape_sequence = ConsumeChars(2);
487*635a8641SAndroid Build Coastguard Worker if (!escape_sequence) {
488*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
489*635a8641SAndroid Build Coastguard Worker return false;
490*635a8641SAndroid Build Coastguard Worker }
491*635a8641SAndroid Build Coastguard Worker
492*635a8641SAndroid Build Coastguard Worker switch ((*escape_sequence)[1]) {
493*635a8641SAndroid Build Coastguard Worker // Allowed esape sequences:
494*635a8641SAndroid Build Coastguard Worker case 'x': { // UTF-8 sequence.
495*635a8641SAndroid Build Coastguard Worker // UTF-8 \x escape sequences are not allowed in the spec, but they
496*635a8641SAndroid Build Coastguard Worker // are supported here for backwards-compatiblity with the old parser.
497*635a8641SAndroid Build Coastguard Worker escape_sequence = ConsumeChars(2);
498*635a8641SAndroid Build Coastguard Worker if (!escape_sequence) {
499*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
500*635a8641SAndroid Build Coastguard Worker return false;
501*635a8641SAndroid Build Coastguard Worker }
502*635a8641SAndroid Build Coastguard Worker
503*635a8641SAndroid Build Coastguard Worker int hex_digit = 0;
504*635a8641SAndroid Build Coastguard Worker if (!HexStringToInt(*escape_sequence, &hex_digit) ||
505*635a8641SAndroid Build Coastguard Worker !IsValidCharacter(hex_digit)) {
506*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_INVALID_ESCAPE, -2);
507*635a8641SAndroid Build Coastguard Worker return false;
508*635a8641SAndroid Build Coastguard Worker }
509*635a8641SAndroid Build Coastguard Worker
510*635a8641SAndroid Build Coastguard Worker string.Append(hex_digit);
511*635a8641SAndroid Build Coastguard Worker break;
512*635a8641SAndroid Build Coastguard Worker }
513*635a8641SAndroid Build Coastguard Worker case 'u': { // UTF-16 sequence.
514*635a8641SAndroid Build Coastguard Worker // UTF units are of the form \uXXXX.
515*635a8641SAndroid Build Coastguard Worker uint32_t code_point;
516*635a8641SAndroid Build Coastguard Worker if (!DecodeUTF16(&code_point)) {
517*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
518*635a8641SAndroid Build Coastguard Worker return false;
519*635a8641SAndroid Build Coastguard Worker }
520*635a8641SAndroid Build Coastguard Worker string.Append(code_point);
521*635a8641SAndroid Build Coastguard Worker break;
522*635a8641SAndroid Build Coastguard Worker }
523*635a8641SAndroid Build Coastguard Worker case '"':
524*635a8641SAndroid Build Coastguard Worker string.Append('"');
525*635a8641SAndroid Build Coastguard Worker break;
526*635a8641SAndroid Build Coastguard Worker case '\\':
527*635a8641SAndroid Build Coastguard Worker string.Append('\\');
528*635a8641SAndroid Build Coastguard Worker break;
529*635a8641SAndroid Build Coastguard Worker case '/':
530*635a8641SAndroid Build Coastguard Worker string.Append('/');
531*635a8641SAndroid Build Coastguard Worker break;
532*635a8641SAndroid Build Coastguard Worker case 'b':
533*635a8641SAndroid Build Coastguard Worker string.Append('\b');
534*635a8641SAndroid Build Coastguard Worker break;
535*635a8641SAndroid Build Coastguard Worker case 'f':
536*635a8641SAndroid Build Coastguard Worker string.Append('\f');
537*635a8641SAndroid Build Coastguard Worker break;
538*635a8641SAndroid Build Coastguard Worker case 'n':
539*635a8641SAndroid Build Coastguard Worker string.Append('\n');
540*635a8641SAndroid Build Coastguard Worker break;
541*635a8641SAndroid Build Coastguard Worker case 'r':
542*635a8641SAndroid Build Coastguard Worker string.Append('\r');
543*635a8641SAndroid Build Coastguard Worker break;
544*635a8641SAndroid Build Coastguard Worker case 't':
545*635a8641SAndroid Build Coastguard Worker string.Append('\t');
546*635a8641SAndroid Build Coastguard Worker break;
547*635a8641SAndroid Build Coastguard Worker case 'v': // Not listed as valid escape sequence in the RFC.
548*635a8641SAndroid Build Coastguard Worker string.Append('\v');
549*635a8641SAndroid Build Coastguard Worker break;
550*635a8641SAndroid Build Coastguard Worker // All other escape squences are illegal.
551*635a8641SAndroid Build Coastguard Worker default:
552*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_INVALID_ESCAPE, 0);
553*635a8641SAndroid Build Coastguard Worker return false;
554*635a8641SAndroid Build Coastguard Worker }
555*635a8641SAndroid Build Coastguard Worker }
556*635a8641SAndroid Build Coastguard Worker }
557*635a8641SAndroid Build Coastguard Worker
558*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 0);
559*635a8641SAndroid Build Coastguard Worker return false;
560*635a8641SAndroid Build Coastguard Worker }
561*635a8641SAndroid Build Coastguard Worker
562*635a8641SAndroid Build Coastguard Worker // Entry is at the first X in \uXXXX.
DecodeUTF16(uint32_t * out_code_point)563*635a8641SAndroid Build Coastguard Worker bool JSONParser::DecodeUTF16(uint32_t* out_code_point) {
564*635a8641SAndroid Build Coastguard Worker Optional<StringPiece> escape_sequence = ConsumeChars(4);
565*635a8641SAndroid Build Coastguard Worker if (!escape_sequence)
566*635a8641SAndroid Build Coastguard Worker return false;
567*635a8641SAndroid Build Coastguard Worker
568*635a8641SAndroid Build Coastguard Worker // Consume the UTF-16 code unit, which may be a high surrogate.
569*635a8641SAndroid Build Coastguard Worker int code_unit16_high = 0;
570*635a8641SAndroid Build Coastguard Worker if (!HexStringToInt(*escape_sequence, &code_unit16_high))
571*635a8641SAndroid Build Coastguard Worker return false;
572*635a8641SAndroid Build Coastguard Worker
573*635a8641SAndroid Build Coastguard Worker // If this is a high surrogate, consume the next code unit to get the
574*635a8641SAndroid Build Coastguard Worker // low surrogate.
575*635a8641SAndroid Build Coastguard Worker if (CBU16_IS_SURROGATE(code_unit16_high)) {
576*635a8641SAndroid Build Coastguard Worker // Make sure this is the high surrogate. If not, it's an encoding
577*635a8641SAndroid Build Coastguard Worker // error.
578*635a8641SAndroid Build Coastguard Worker if (!CBU16_IS_SURROGATE_LEAD(code_unit16_high))
579*635a8641SAndroid Build Coastguard Worker return false;
580*635a8641SAndroid Build Coastguard Worker
581*635a8641SAndroid Build Coastguard Worker // Make sure that the token has more characters to consume the
582*635a8641SAndroid Build Coastguard Worker // lower surrogate.
583*635a8641SAndroid Build Coastguard Worker if (!ConsumeIfMatch("\\u"))
584*635a8641SAndroid Build Coastguard Worker return false;
585*635a8641SAndroid Build Coastguard Worker
586*635a8641SAndroid Build Coastguard Worker escape_sequence = ConsumeChars(4);
587*635a8641SAndroid Build Coastguard Worker if (!escape_sequence)
588*635a8641SAndroid Build Coastguard Worker return false;
589*635a8641SAndroid Build Coastguard Worker
590*635a8641SAndroid Build Coastguard Worker int code_unit16_low = 0;
591*635a8641SAndroid Build Coastguard Worker if (!HexStringToInt(*escape_sequence, &code_unit16_low))
592*635a8641SAndroid Build Coastguard Worker return false;
593*635a8641SAndroid Build Coastguard Worker
594*635a8641SAndroid Build Coastguard Worker if (!CBU16_IS_TRAIL(code_unit16_low))
595*635a8641SAndroid Build Coastguard Worker return false;
596*635a8641SAndroid Build Coastguard Worker
597*635a8641SAndroid Build Coastguard Worker uint32_t code_point =
598*635a8641SAndroid Build Coastguard Worker CBU16_GET_SUPPLEMENTARY(code_unit16_high, code_unit16_low);
599*635a8641SAndroid Build Coastguard Worker if (!IsValidCharacter(code_point))
600*635a8641SAndroid Build Coastguard Worker return false;
601*635a8641SAndroid Build Coastguard Worker
602*635a8641SAndroid Build Coastguard Worker *out_code_point = code_point;
603*635a8641SAndroid Build Coastguard Worker } else {
604*635a8641SAndroid Build Coastguard Worker // Not a surrogate.
605*635a8641SAndroid Build Coastguard Worker DCHECK(CBU16_IS_SINGLE(code_unit16_high));
606*635a8641SAndroid Build Coastguard Worker if (!IsValidCharacter(code_unit16_high)) {
607*635a8641SAndroid Build Coastguard Worker if ((options_ & JSON_REPLACE_INVALID_CHARACTERS) == 0) {
608*635a8641SAndroid Build Coastguard Worker return false;
609*635a8641SAndroid Build Coastguard Worker }
610*635a8641SAndroid Build Coastguard Worker *out_code_point = kUnicodeReplacementPoint;
611*635a8641SAndroid Build Coastguard Worker return true;
612*635a8641SAndroid Build Coastguard Worker }
613*635a8641SAndroid Build Coastguard Worker
614*635a8641SAndroid Build Coastguard Worker *out_code_point = code_unit16_high;
615*635a8641SAndroid Build Coastguard Worker }
616*635a8641SAndroid Build Coastguard Worker
617*635a8641SAndroid Build Coastguard Worker return true;
618*635a8641SAndroid Build Coastguard Worker }
619*635a8641SAndroid Build Coastguard Worker
ConsumeNumber()620*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ConsumeNumber() {
621*635a8641SAndroid Build Coastguard Worker const char* num_start = pos();
622*635a8641SAndroid Build Coastguard Worker const int start_index = index_;
623*635a8641SAndroid Build Coastguard Worker int end_index = start_index;
624*635a8641SAndroid Build Coastguard Worker
625*635a8641SAndroid Build Coastguard Worker if (PeekChar() == '-')
626*635a8641SAndroid Build Coastguard Worker ConsumeChar();
627*635a8641SAndroid Build Coastguard Worker
628*635a8641SAndroid Build Coastguard Worker if (!ReadInt(false)) {
629*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
630*635a8641SAndroid Build Coastguard Worker return nullopt;
631*635a8641SAndroid Build Coastguard Worker }
632*635a8641SAndroid Build Coastguard Worker end_index = index_;
633*635a8641SAndroid Build Coastguard Worker
634*635a8641SAndroid Build Coastguard Worker // The optional fraction part.
635*635a8641SAndroid Build Coastguard Worker if (PeekChar() == '.') {
636*635a8641SAndroid Build Coastguard Worker ConsumeChar();
637*635a8641SAndroid Build Coastguard Worker if (!ReadInt(true)) {
638*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
639*635a8641SAndroid Build Coastguard Worker return nullopt;
640*635a8641SAndroid Build Coastguard Worker }
641*635a8641SAndroid Build Coastguard Worker end_index = index_;
642*635a8641SAndroid Build Coastguard Worker }
643*635a8641SAndroid Build Coastguard Worker
644*635a8641SAndroid Build Coastguard Worker // Optional exponent part.
645*635a8641SAndroid Build Coastguard Worker Optional<char> c = PeekChar();
646*635a8641SAndroid Build Coastguard Worker if (c == 'e' || c == 'E') {
647*635a8641SAndroid Build Coastguard Worker ConsumeChar();
648*635a8641SAndroid Build Coastguard Worker if (PeekChar() == '-' || PeekChar() == '+') {
649*635a8641SAndroid Build Coastguard Worker ConsumeChar();
650*635a8641SAndroid Build Coastguard Worker }
651*635a8641SAndroid Build Coastguard Worker if (!ReadInt(true)) {
652*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
653*635a8641SAndroid Build Coastguard Worker return nullopt;
654*635a8641SAndroid Build Coastguard Worker }
655*635a8641SAndroid Build Coastguard Worker end_index = index_;
656*635a8641SAndroid Build Coastguard Worker }
657*635a8641SAndroid Build Coastguard Worker
658*635a8641SAndroid Build Coastguard Worker // ReadInt is greedy because numbers have no easily detectable sentinel,
659*635a8641SAndroid Build Coastguard Worker // so save off where the parser should be on exit (see Consume invariant at
660*635a8641SAndroid Build Coastguard Worker // the top of the header), then make sure the next token is one which is
661*635a8641SAndroid Build Coastguard Worker // valid.
662*635a8641SAndroid Build Coastguard Worker int exit_index = index_;
663*635a8641SAndroid Build Coastguard Worker
664*635a8641SAndroid Build Coastguard Worker switch (GetNextToken()) {
665*635a8641SAndroid Build Coastguard Worker case T_OBJECT_END:
666*635a8641SAndroid Build Coastguard Worker case T_ARRAY_END:
667*635a8641SAndroid Build Coastguard Worker case T_LIST_SEPARATOR:
668*635a8641SAndroid Build Coastguard Worker case T_END_OF_INPUT:
669*635a8641SAndroid Build Coastguard Worker break;
670*635a8641SAndroid Build Coastguard Worker default:
671*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
672*635a8641SAndroid Build Coastguard Worker return nullopt;
673*635a8641SAndroid Build Coastguard Worker }
674*635a8641SAndroid Build Coastguard Worker
675*635a8641SAndroid Build Coastguard Worker index_ = exit_index;
676*635a8641SAndroid Build Coastguard Worker
677*635a8641SAndroid Build Coastguard Worker StringPiece num_string(num_start, end_index - start_index);
678*635a8641SAndroid Build Coastguard Worker
679*635a8641SAndroid Build Coastguard Worker int num_int;
680*635a8641SAndroid Build Coastguard Worker if (StringToInt(num_string, &num_int))
681*635a8641SAndroid Build Coastguard Worker return Value(num_int);
682*635a8641SAndroid Build Coastguard Worker
683*635a8641SAndroid Build Coastguard Worker double num_double;
684*635a8641SAndroid Build Coastguard Worker if (StringToDouble(num_string.as_string(), &num_double) &&
685*635a8641SAndroid Build Coastguard Worker std::isfinite(num_double)) {
686*635a8641SAndroid Build Coastguard Worker return Value(num_double);
687*635a8641SAndroid Build Coastguard Worker }
688*635a8641SAndroid Build Coastguard Worker
689*635a8641SAndroid Build Coastguard Worker return nullopt;
690*635a8641SAndroid Build Coastguard Worker }
691*635a8641SAndroid Build Coastguard Worker
ReadInt(bool allow_leading_zeros)692*635a8641SAndroid Build Coastguard Worker bool JSONParser::ReadInt(bool allow_leading_zeros) {
693*635a8641SAndroid Build Coastguard Worker size_t len = 0;
694*635a8641SAndroid Build Coastguard Worker char first = 0;
695*635a8641SAndroid Build Coastguard Worker
696*635a8641SAndroid Build Coastguard Worker while (Optional<char> c = PeekChar()) {
697*635a8641SAndroid Build Coastguard Worker if (!IsAsciiDigit(c))
698*635a8641SAndroid Build Coastguard Worker break;
699*635a8641SAndroid Build Coastguard Worker
700*635a8641SAndroid Build Coastguard Worker if (len == 0)
701*635a8641SAndroid Build Coastguard Worker first = *c;
702*635a8641SAndroid Build Coastguard Worker
703*635a8641SAndroid Build Coastguard Worker ++len;
704*635a8641SAndroid Build Coastguard Worker ConsumeChar();
705*635a8641SAndroid Build Coastguard Worker }
706*635a8641SAndroid Build Coastguard Worker
707*635a8641SAndroid Build Coastguard Worker if (len == 0)
708*635a8641SAndroid Build Coastguard Worker return false;
709*635a8641SAndroid Build Coastguard Worker
710*635a8641SAndroid Build Coastguard Worker if (!allow_leading_zeros && len > 1 && first == '0')
711*635a8641SAndroid Build Coastguard Worker return false;
712*635a8641SAndroid Build Coastguard Worker
713*635a8641SAndroid Build Coastguard Worker return true;
714*635a8641SAndroid Build Coastguard Worker }
715*635a8641SAndroid Build Coastguard Worker
ConsumeLiteral()716*635a8641SAndroid Build Coastguard Worker Optional<Value> JSONParser::ConsumeLiteral() {
717*635a8641SAndroid Build Coastguard Worker if (ConsumeIfMatch("true")) {
718*635a8641SAndroid Build Coastguard Worker return Value(true);
719*635a8641SAndroid Build Coastguard Worker } else if (ConsumeIfMatch("false")) {
720*635a8641SAndroid Build Coastguard Worker return Value(false);
721*635a8641SAndroid Build Coastguard Worker } else if (ConsumeIfMatch("null")) {
722*635a8641SAndroid Build Coastguard Worker return Value(Value::Type::NONE);
723*635a8641SAndroid Build Coastguard Worker } else {
724*635a8641SAndroid Build Coastguard Worker ReportError(JSONReader::JSON_SYNTAX_ERROR, 1);
725*635a8641SAndroid Build Coastguard Worker return nullopt;
726*635a8641SAndroid Build Coastguard Worker }
727*635a8641SAndroid Build Coastguard Worker }
728*635a8641SAndroid Build Coastguard Worker
ConsumeIfMatch(StringPiece match)729*635a8641SAndroid Build Coastguard Worker bool JSONParser::ConsumeIfMatch(StringPiece match) {
730*635a8641SAndroid Build Coastguard Worker if (match == PeekChars(match.size())) {
731*635a8641SAndroid Build Coastguard Worker ConsumeChars(match.size());
732*635a8641SAndroid Build Coastguard Worker return true;
733*635a8641SAndroid Build Coastguard Worker }
734*635a8641SAndroid Build Coastguard Worker return false;
735*635a8641SAndroid Build Coastguard Worker }
736*635a8641SAndroid Build Coastguard Worker
ReportError(JSONReader::JsonParseError code,int column_adjust)737*635a8641SAndroid Build Coastguard Worker void JSONParser::ReportError(JSONReader::JsonParseError code,
738*635a8641SAndroid Build Coastguard Worker int column_adjust) {
739*635a8641SAndroid Build Coastguard Worker error_code_ = code;
740*635a8641SAndroid Build Coastguard Worker error_line_ = line_number_;
741*635a8641SAndroid Build Coastguard Worker error_column_ = index_ - index_last_line_ + column_adjust;
742*635a8641SAndroid Build Coastguard Worker }
743*635a8641SAndroid Build Coastguard Worker
744*635a8641SAndroid Build Coastguard Worker // static
FormatErrorMessage(int line,int column,const std::string & description)745*635a8641SAndroid Build Coastguard Worker std::string JSONParser::FormatErrorMessage(int line, int column,
746*635a8641SAndroid Build Coastguard Worker const std::string& description) {
747*635a8641SAndroid Build Coastguard Worker if (line || column) {
748*635a8641SAndroid Build Coastguard Worker return StringPrintf("Line: %i, column: %i, %s",
749*635a8641SAndroid Build Coastguard Worker line, column, description.c_str());
750*635a8641SAndroid Build Coastguard Worker }
751*635a8641SAndroid Build Coastguard Worker return description;
752*635a8641SAndroid Build Coastguard Worker }
753*635a8641SAndroid Build Coastguard Worker
754*635a8641SAndroid Build Coastguard Worker } // namespace internal
755*635a8641SAndroid Build Coastguard Worker } // namespace base
756