xref: /aosp_15_r20/external/libchrome/base/json/json_parser.cc (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 #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