xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/JSON.cpp (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1061da546Spatrick //===--------------------- JSON.cpp -----------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "JSON.h"
10061da546Spatrick 
11061da546Spatrick // C includes
12*be691f3bSpatrick #include <cassert>
13*be691f3bSpatrick #include <climits>
14061da546Spatrick 
15061da546Spatrick // C++ includes
16061da546Spatrick #include "lldb/Host/StringConvert.h"
17061da546Spatrick #include <iomanip>
18061da546Spatrick #include <sstream>
19061da546Spatrick 
20061da546Spatrick using namespace lldb_private;
21061da546Spatrick 
22061da546Spatrick std::string JSONString::json_string_quote_metachars(const std::string &s) {
23061da546Spatrick   if (s.find('"') == std::string::npos)
24061da546Spatrick     return s;
25061da546Spatrick 
26061da546Spatrick   std::string output;
27061da546Spatrick   const size_t s_size = s.size();
28061da546Spatrick   const char *s_chars = s.c_str();
29061da546Spatrick   for (size_t i = 0; i < s_size; i++) {
30061da546Spatrick     unsigned char ch = *(s_chars + i);
31061da546Spatrick     if (ch == '"') {
32061da546Spatrick       output.push_back('\\');
33061da546Spatrick     }
34061da546Spatrick     output.push_back(ch);
35061da546Spatrick   }
36061da546Spatrick   return output;
37061da546Spatrick }
38061da546Spatrick 
39061da546Spatrick JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {}
40061da546Spatrick 
41061da546Spatrick JSONString::JSONString(const char *s)
42061da546Spatrick     : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {}
43061da546Spatrick 
44061da546Spatrick JSONString::JSONString(const std::string &s)
45061da546Spatrick     : JSONValue(JSONValue::Kind::String), m_data(s) {}
46061da546Spatrick 
47061da546Spatrick void JSONString::Write(std::ostream &s) {
48061da546Spatrick   s << "\"" << json_string_quote_metachars(m_data).c_str() << "\"";
49061da546Spatrick }
50061da546Spatrick 
51061da546Spatrick uint64_t JSONNumber::GetAsUnsigned() const {
52061da546Spatrick   switch (m_data_type) {
53061da546Spatrick   case DataType::Unsigned:
54061da546Spatrick     return m_data.m_unsigned;
55061da546Spatrick   case DataType::Signed:
56061da546Spatrick     return (uint64_t)m_data.m_signed;
57061da546Spatrick   case DataType::Double:
58061da546Spatrick     return (uint64_t)m_data.m_double;
59061da546Spatrick   }
60061da546Spatrick }
61061da546Spatrick 
62061da546Spatrick int64_t JSONNumber::GetAsSigned() const {
63061da546Spatrick   switch (m_data_type) {
64061da546Spatrick   case DataType::Unsigned:
65061da546Spatrick     return (int64_t)m_data.m_unsigned;
66061da546Spatrick   case DataType::Signed:
67061da546Spatrick     return m_data.m_signed;
68061da546Spatrick   case DataType::Double:
69061da546Spatrick     return (int64_t)m_data.m_double;
70061da546Spatrick   }
71061da546Spatrick }
72061da546Spatrick 
73061da546Spatrick double JSONNumber::GetAsDouble() const {
74061da546Spatrick   switch (m_data_type) {
75061da546Spatrick   case DataType::Unsigned:
76061da546Spatrick     return (double)m_data.m_unsigned;
77061da546Spatrick   case DataType::Signed:
78061da546Spatrick     return (double)m_data.m_signed;
79061da546Spatrick   case DataType::Double:
80061da546Spatrick     return m_data.m_double;
81061da546Spatrick   }
82061da546Spatrick }
83061da546Spatrick 
84061da546Spatrick void JSONNumber::Write(std::ostream &s) {
85061da546Spatrick   switch (m_data_type) {
86061da546Spatrick   case DataType::Unsigned:
87061da546Spatrick     s << m_data.m_unsigned;
88061da546Spatrick     break;
89061da546Spatrick   case DataType::Signed:
90061da546Spatrick     s << m_data.m_signed;
91061da546Spatrick     break;
92061da546Spatrick   case DataType::Double:
93061da546Spatrick     // Set max precision to emulate %g.
94061da546Spatrick     s << std::setprecision(std::numeric_limits<double>::digits10 + 1);
95061da546Spatrick     s << m_data.m_double;
96061da546Spatrick     break;
97061da546Spatrick   }
98061da546Spatrick }
99061da546Spatrick 
100061da546Spatrick JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {}
101061da546Spatrick 
102061da546Spatrick void JSONTrue::Write(std::ostream &s) { s << "true"; }
103061da546Spatrick 
104061da546Spatrick JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {}
105061da546Spatrick 
106061da546Spatrick void JSONFalse::Write(std::ostream &s) { s << "false"; }
107061da546Spatrick 
108061da546Spatrick JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {}
109061da546Spatrick 
110061da546Spatrick void JSONNull::Write(std::ostream &s) { s << "null"; }
111061da546Spatrick 
112061da546Spatrick JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {}
113061da546Spatrick 
114061da546Spatrick void JSONObject::Write(std::ostream &s) {
115061da546Spatrick   bool first = true;
116061da546Spatrick   s << '{';
117061da546Spatrick   auto iter = m_elements.begin(), end = m_elements.end();
118061da546Spatrick   for (; iter != end; iter++) {
119061da546Spatrick     if (first)
120061da546Spatrick       first = false;
121061da546Spatrick     else
122061da546Spatrick       s << ',';
123061da546Spatrick     JSONString key(iter->first);
124061da546Spatrick     JSONValue::SP value(iter->second);
125061da546Spatrick     key.Write(s);
126061da546Spatrick     s << ':';
127061da546Spatrick     value->Write(s);
128061da546Spatrick   }
129061da546Spatrick   s << '}';
130061da546Spatrick }
131061da546Spatrick 
132061da546Spatrick bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) {
133061da546Spatrick   if (key.empty() || nullptr == value.get())
134061da546Spatrick     return false;
135061da546Spatrick   m_elements[key] = value;
136061da546Spatrick   return true;
137061da546Spatrick }
138061da546Spatrick 
139061da546Spatrick JSONValue::SP JSONObject::GetObject(const std::string &key) const {
140061da546Spatrick   auto iter = m_elements.find(key), end = m_elements.end();
141061da546Spatrick   if (iter == end)
142061da546Spatrick     return JSONValue::SP();
143061da546Spatrick   return iter->second;
144061da546Spatrick }
145061da546Spatrick 
146061da546Spatrick bool JSONObject::GetObjectAsBool(const std::string &key, bool &value) const {
147061da546Spatrick   auto value_sp = GetObject(key);
148061da546Spatrick   if (!value_sp) {
149061da546Spatrick     // The given key doesn't exist, so we have no value.
150061da546Spatrick     return false;
151061da546Spatrick   }
152061da546Spatrick 
153061da546Spatrick   if (JSONTrue::classof(value_sp.get())) {
154061da546Spatrick     // We have the value, and it is true.
155061da546Spatrick     value = true;
156061da546Spatrick     return true;
157061da546Spatrick   } else if (JSONFalse::classof(value_sp.get())) {
158061da546Spatrick     // We have the value, and it is false.
159061da546Spatrick     value = false;
160061da546Spatrick     return true;
161061da546Spatrick   } else {
162061da546Spatrick     // We don't have a valid bool value for the given key.
163061da546Spatrick     return false;
164061da546Spatrick   }
165061da546Spatrick }
166061da546Spatrick 
167061da546Spatrick bool JSONObject::GetObjectAsString(const std::string &key,
168061da546Spatrick                                    std::string &value) const {
169061da546Spatrick   auto value_sp = GetObject(key);
170061da546Spatrick   if (!value_sp) {
171061da546Spatrick     // The given key doesn't exist, so we have no value.
172061da546Spatrick     return false;
173061da546Spatrick   }
174061da546Spatrick 
175061da546Spatrick   if (!JSONString::classof(value_sp.get()))
176061da546Spatrick     return false;
177061da546Spatrick 
178061da546Spatrick   value = static_cast<JSONString *>(value_sp.get())->GetData();
179061da546Spatrick   return true;
180061da546Spatrick }
181061da546Spatrick 
182061da546Spatrick JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {}
183061da546Spatrick 
184061da546Spatrick void JSONArray::Write(std::ostream &s) {
185061da546Spatrick   bool first = true;
186061da546Spatrick   s << '[';
187061da546Spatrick   auto iter = m_elements.begin(), end = m_elements.end();
188061da546Spatrick   for (; iter != end; iter++) {
189061da546Spatrick     if (first)
190061da546Spatrick       first = false;
191061da546Spatrick     else
192061da546Spatrick       s << ',';
193061da546Spatrick     (*iter)->Write(s);
194061da546Spatrick   }
195061da546Spatrick   s << ']';
196061da546Spatrick }
197061da546Spatrick 
198061da546Spatrick bool JSONArray::SetObject(Index i, JSONValue::SP value) {
199061da546Spatrick   if (value.get() == nullptr)
200061da546Spatrick     return false;
201061da546Spatrick   if (i < m_elements.size()) {
202061da546Spatrick     m_elements[i] = value;
203061da546Spatrick     return true;
204061da546Spatrick   }
205061da546Spatrick   if (i == m_elements.size()) {
206061da546Spatrick     m_elements.push_back(value);
207061da546Spatrick     return true;
208061da546Spatrick   }
209061da546Spatrick   return false;
210061da546Spatrick }
211061da546Spatrick 
212061da546Spatrick bool JSONArray::AppendObject(JSONValue::SP value) {
213061da546Spatrick   if (value.get() == nullptr)
214061da546Spatrick     return false;
215061da546Spatrick   m_elements.push_back(value);
216061da546Spatrick   return true;
217061da546Spatrick }
218061da546Spatrick 
219061da546Spatrick JSONValue::SP JSONArray::GetObject(Index i) {
220061da546Spatrick   if (i < m_elements.size())
221061da546Spatrick     return m_elements[i];
222061da546Spatrick   return JSONValue::SP();
223061da546Spatrick }
224061da546Spatrick 
225061da546Spatrick JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); }
226061da546Spatrick 
227061da546Spatrick JSONParser::JSONParser(const char *cstr) : StdStringExtractor(cstr) {}
228061da546Spatrick 
229061da546Spatrick JSONParser::Token JSONParser::GetToken(std::string &value) {
230061da546Spatrick   std::ostringstream error;
231061da546Spatrick 
232061da546Spatrick   value.clear();
233061da546Spatrick   SkipSpaces();
234061da546Spatrick   const uint64_t start_index = m_index;
235061da546Spatrick   const char ch = GetChar();
236061da546Spatrick   switch (ch) {
237061da546Spatrick   case '{':
238061da546Spatrick     return Token::ObjectStart;
239061da546Spatrick   case '}':
240061da546Spatrick     return Token::ObjectEnd;
241061da546Spatrick   case '[':
242061da546Spatrick     return Token::ArrayStart;
243061da546Spatrick   case ']':
244061da546Spatrick     return Token::ArrayEnd;
245061da546Spatrick   case ',':
246061da546Spatrick     return Token::Comma;
247061da546Spatrick   case ':':
248061da546Spatrick     return Token::Colon;
249061da546Spatrick   case '\0':
250061da546Spatrick     return Token::EndOfFile;
251061da546Spatrick   case 't':
252061da546Spatrick     if (GetChar() == 'r')
253061da546Spatrick       if (GetChar() == 'u')
254061da546Spatrick         if (GetChar() == 'e')
255061da546Spatrick           return Token::True;
256061da546Spatrick     break;
257061da546Spatrick 
258061da546Spatrick   case 'f':
259061da546Spatrick     if (GetChar() == 'a')
260061da546Spatrick       if (GetChar() == 'l')
261061da546Spatrick         if (GetChar() == 's')
262061da546Spatrick           if (GetChar() == 'e')
263061da546Spatrick             return Token::False;
264061da546Spatrick     break;
265061da546Spatrick 
266061da546Spatrick   case 'n':
267061da546Spatrick     if (GetChar() == 'u')
268061da546Spatrick       if (GetChar() == 'l')
269061da546Spatrick         if (GetChar() == 'l')
270061da546Spatrick           return Token::Null;
271061da546Spatrick     break;
272061da546Spatrick 
273061da546Spatrick   case '"': {
274061da546Spatrick     while (true) {
275061da546Spatrick       bool was_escaped = false;
276061da546Spatrick       int escaped_ch = GetEscapedChar(was_escaped);
277061da546Spatrick       if (escaped_ch == -1) {
278061da546Spatrick         error << "error: an error occurred getting a character from offset "
279061da546Spatrick               << start_index;
280061da546Spatrick         value = error.str();
281061da546Spatrick         return Token::Status;
282061da546Spatrick 
283061da546Spatrick       } else {
284061da546Spatrick         const bool is_end_quote = escaped_ch == '"';
285061da546Spatrick         const bool is_null = escaped_ch == 0;
286061da546Spatrick         if (was_escaped || (!is_end_quote && !is_null)) {
287061da546Spatrick           if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) {
288061da546Spatrick             value.append(1, (char)escaped_ch);
289061da546Spatrick           } else {
290061da546Spatrick             error << "error: wide character support is needed for unicode "
291061da546Spatrick                      "character 0x"
292061da546Spatrick                   << std::setprecision(4) << std::hex << escaped_ch;
293061da546Spatrick             error << " at offset " << start_index;
294061da546Spatrick             value = error.str();
295061da546Spatrick             return Token::Status;
296061da546Spatrick           }
297061da546Spatrick         } else if (is_end_quote) {
298061da546Spatrick           return Token::String;
299061da546Spatrick         } else if (is_null) {
300061da546Spatrick           value = "error: missing end quote for string";
301061da546Spatrick           return Token::Status;
302061da546Spatrick         }
303061da546Spatrick       }
304061da546Spatrick     }
305061da546Spatrick   } break;
306061da546Spatrick 
307061da546Spatrick   case '-':
308061da546Spatrick   case '0':
309061da546Spatrick   case '1':
310061da546Spatrick   case '2':
311061da546Spatrick   case '3':
312061da546Spatrick   case '4':
313061da546Spatrick   case '5':
314061da546Spatrick   case '6':
315061da546Spatrick   case '7':
316061da546Spatrick   case '8':
317061da546Spatrick   case '9': {
318061da546Spatrick     bool done = false;
319061da546Spatrick     bool got_decimal_point = false;
320061da546Spatrick     uint64_t exp_index = 0;
321061da546Spatrick     bool got_int_digits = (ch >= '0') && (ch <= '9');
322061da546Spatrick     bool got_frac_digits = false;
323061da546Spatrick     bool got_exp_digits = false;
324061da546Spatrick     while (!done) {
325061da546Spatrick       const char next_ch = PeekChar();
326061da546Spatrick       switch (next_ch) {
327061da546Spatrick       case '0':
328061da546Spatrick       case '1':
329061da546Spatrick       case '2':
330061da546Spatrick       case '3':
331061da546Spatrick       case '4':
332061da546Spatrick       case '5':
333061da546Spatrick       case '6':
334061da546Spatrick       case '7':
335061da546Spatrick       case '8':
336061da546Spatrick       case '9':
337061da546Spatrick         if (exp_index != 0) {
338061da546Spatrick           got_exp_digits = true;
339061da546Spatrick         } else if (got_decimal_point) {
340061da546Spatrick           got_frac_digits = true;
341061da546Spatrick         } else {
342061da546Spatrick           got_int_digits = true;
343061da546Spatrick         }
344061da546Spatrick         ++m_index; // Skip this character
345061da546Spatrick         break;
346061da546Spatrick 
347061da546Spatrick       case '.':
348061da546Spatrick         if (got_decimal_point) {
349061da546Spatrick           error << "error: extra decimal point found at offset " << start_index;
350061da546Spatrick           value = error.str();
351061da546Spatrick           return Token::Status;
352061da546Spatrick         } else {
353061da546Spatrick           got_decimal_point = true;
354061da546Spatrick           ++m_index; // Skip this character
355061da546Spatrick         }
356061da546Spatrick         break;
357061da546Spatrick 
358061da546Spatrick       case 'e':
359061da546Spatrick       case 'E':
360061da546Spatrick         if (exp_index != 0) {
361061da546Spatrick           error << "error: extra exponent character found at offset "
362061da546Spatrick                 << start_index;
363061da546Spatrick           value = error.str();
364061da546Spatrick           return Token::Status;
365061da546Spatrick         } else {
366061da546Spatrick           exp_index = m_index;
367061da546Spatrick           ++m_index; // Skip this character
368061da546Spatrick         }
369061da546Spatrick         break;
370061da546Spatrick 
371061da546Spatrick       case '+':
372061da546Spatrick       case '-':
373061da546Spatrick         // The '+' and '-' can only come after an exponent character...
374061da546Spatrick         if (exp_index == m_index - 1) {
375061da546Spatrick           ++m_index; // Skip the exponent sign character
376061da546Spatrick         } else {
377061da546Spatrick           error << "error: unexpected " << next_ch << " character at offset "
378061da546Spatrick                 << start_index;
379061da546Spatrick           value = error.str();
380061da546Spatrick           return Token::Status;
381061da546Spatrick         }
382061da546Spatrick         break;
383061da546Spatrick 
384061da546Spatrick       default:
385061da546Spatrick         done = true;
386061da546Spatrick         break;
387061da546Spatrick       }
388061da546Spatrick     }
389061da546Spatrick 
390061da546Spatrick     if (m_index > start_index) {
391061da546Spatrick       value = m_packet.substr(start_index, m_index - start_index);
392061da546Spatrick       if (got_decimal_point) {
393061da546Spatrick         if (exp_index != 0) {
394061da546Spatrick           // We have an exponent, make sure we got exponent digits
395061da546Spatrick           if (got_exp_digits) {
396061da546Spatrick             return Token::Float;
397061da546Spatrick           } else {
398061da546Spatrick             error << "error: got exponent character but no exponent digits at "
399061da546Spatrick                      "offset in float value \""
400061da546Spatrick                   << value.c_str() << "\"";
401061da546Spatrick             value = error.str();
402061da546Spatrick             return Token::Status;
403061da546Spatrick           }
404061da546Spatrick         } else {
405061da546Spatrick           // No exponent, but we need at least one decimal after the decimal
406061da546Spatrick           // point
407061da546Spatrick           if (got_frac_digits) {
408061da546Spatrick             return Token::Float;
409061da546Spatrick           } else {
410061da546Spatrick             error << "error: no digits after decimal point \"" << value.c_str()
411061da546Spatrick                   << "\"";
412061da546Spatrick             value = error.str();
413061da546Spatrick             return Token::Status;
414061da546Spatrick           }
415061da546Spatrick         }
416061da546Spatrick       } else {
417061da546Spatrick         // No decimal point
418061da546Spatrick         if (got_int_digits) {
419061da546Spatrick           // We need at least some integer digits to make an integer
420061da546Spatrick           return Token::Integer;
421061da546Spatrick         } else {
422061da546Spatrick           error << "error: no digits negate sign \"" << value.c_str() << "\"";
423061da546Spatrick           value = error.str();
424061da546Spatrick           return Token::Status;
425061da546Spatrick         }
426061da546Spatrick       }
427061da546Spatrick     } else {
428061da546Spatrick       error << "error: invalid number found at offset " << start_index;
429061da546Spatrick       value = error.str();
430061da546Spatrick       return Token::Status;
431061da546Spatrick     }
432061da546Spatrick   } break;
433061da546Spatrick   default:
434061da546Spatrick     break;
435061da546Spatrick   }
436061da546Spatrick   error << "error: failed to parse token at offset " << start_index
437061da546Spatrick         << " (around character '" << ch << "')";
438061da546Spatrick   value = error.str();
439061da546Spatrick   return Token::Status;
440061da546Spatrick }
441061da546Spatrick 
442061da546Spatrick int JSONParser::GetEscapedChar(bool &was_escaped) {
443061da546Spatrick   was_escaped = false;
444061da546Spatrick   const char ch = GetChar();
445061da546Spatrick   if (ch == '\\') {
446061da546Spatrick     was_escaped = true;
447061da546Spatrick     const char ch2 = GetChar();
448061da546Spatrick     switch (ch2) {
449061da546Spatrick     case '"':
450061da546Spatrick     case '\\':
451061da546Spatrick     case '/':
452061da546Spatrick     default:
453061da546Spatrick       break;
454061da546Spatrick 
455061da546Spatrick     case 'b':
456061da546Spatrick       return '\b';
457061da546Spatrick     case 'f':
458061da546Spatrick       return '\f';
459061da546Spatrick     case 'n':
460061da546Spatrick       return '\n';
461061da546Spatrick     case 'r':
462061da546Spatrick       return '\r';
463061da546Spatrick     case 't':
464061da546Spatrick       return '\t';
465061da546Spatrick     case 'u': {
466061da546Spatrick       const int hi_byte = DecodeHexU8();
467061da546Spatrick       const int lo_byte = DecodeHexU8();
468061da546Spatrick       if (hi_byte >= 0 && lo_byte >= 0)
469061da546Spatrick         return hi_byte << 8 | lo_byte;
470061da546Spatrick       return -1;
471061da546Spatrick     } break;
472061da546Spatrick     }
473061da546Spatrick     return ch2;
474061da546Spatrick   }
475061da546Spatrick   return ch;
476061da546Spatrick }
477061da546Spatrick 
478061da546Spatrick JSONValue::SP JSONParser::ParseJSONObject() {
479061da546Spatrick   // The "JSONParser::Token::ObjectStart" token should have already been
480061da546Spatrick   // consumed
481061da546Spatrick   // by the time this function is called
482061da546Spatrick   std::unique_ptr<JSONObject> dict_up(new JSONObject());
483061da546Spatrick 
484061da546Spatrick   std::string value;
485061da546Spatrick   std::string key;
486061da546Spatrick   while (true) {
487061da546Spatrick     JSONParser::Token token = GetToken(value);
488061da546Spatrick 
489061da546Spatrick     if (token == JSONParser::Token::String) {
490061da546Spatrick       key.swap(value);
491061da546Spatrick       token = GetToken(value);
492061da546Spatrick       if (token == JSONParser::Token::Colon) {
493061da546Spatrick         JSONValue::SP value_sp = ParseJSONValue();
494061da546Spatrick         if (value_sp)
495061da546Spatrick           dict_up->SetObject(key, value_sp);
496061da546Spatrick         else
497061da546Spatrick           break;
498061da546Spatrick       }
499061da546Spatrick     } else if (token == JSONParser::Token::ObjectEnd) {
500061da546Spatrick       return JSONValue::SP(dict_up.release());
501061da546Spatrick     } else if (token == JSONParser::Token::Comma) {
502061da546Spatrick       continue;
503061da546Spatrick     } else {
504061da546Spatrick       break;
505061da546Spatrick     }
506061da546Spatrick   }
507061da546Spatrick   return JSONValue::SP();
508061da546Spatrick }
509061da546Spatrick 
510061da546Spatrick JSONValue::SP JSONParser::ParseJSONArray() {
511061da546Spatrick   // The "JSONParser::Token::ObjectStart" token should have already been
512061da546Spatrick   // consumed
513061da546Spatrick   // by the time this function is called
514061da546Spatrick   std::unique_ptr<JSONArray> array_up(new JSONArray());
515061da546Spatrick 
516061da546Spatrick   std::string value;
517061da546Spatrick   std::string key;
518061da546Spatrick   while (true) {
519061da546Spatrick     JSONParser::Token token = GetToken(value);
520061da546Spatrick     if (token == JSONParser::Token::ArrayEnd)
521061da546Spatrick       return JSONValue::SP(array_up.release());
522061da546Spatrick     JSONValue::SP value_sp = ParseJSONValue(value, token);
523061da546Spatrick     if (value_sp)
524061da546Spatrick       array_up->AppendObject(value_sp);
525061da546Spatrick     else
526061da546Spatrick       break;
527061da546Spatrick 
528061da546Spatrick     token = GetToken(value);
529061da546Spatrick     if (token == JSONParser::Token::Comma) {
530061da546Spatrick       continue;
531061da546Spatrick     } else if (token == JSONParser::Token::ArrayEnd) {
532061da546Spatrick       return JSONValue::SP(array_up.release());
533061da546Spatrick     } else {
534061da546Spatrick       break;
535061da546Spatrick     }
536061da546Spatrick   }
537061da546Spatrick   return JSONValue::SP();
538061da546Spatrick }
539061da546Spatrick 
540061da546Spatrick JSONValue::SP JSONParser::ParseJSONValue() {
541061da546Spatrick   std::string value;
542061da546Spatrick   const JSONParser::Token token = GetToken(value);
543061da546Spatrick   return ParseJSONValue(value, token);
544061da546Spatrick }
545061da546Spatrick 
546061da546Spatrick JSONValue::SP JSONParser::ParseJSONValue(const std::string &value,
547061da546Spatrick                                          const Token &token) {
548061da546Spatrick   switch (token) {
549061da546Spatrick   case JSONParser::Token::ObjectStart:
550061da546Spatrick     return ParseJSONObject();
551061da546Spatrick 
552061da546Spatrick   case JSONParser::Token::ArrayStart:
553061da546Spatrick     return ParseJSONArray();
554061da546Spatrick 
555061da546Spatrick   case JSONParser::Token::Integer: {
556061da546Spatrick     if (value.front() == '-') {
557061da546Spatrick       bool success = false;
558061da546Spatrick       int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
559061da546Spatrick       if (success)
560061da546Spatrick         return JSONValue::SP(new JSONNumber(sval));
561061da546Spatrick     } else {
562061da546Spatrick       bool success = false;
563061da546Spatrick       uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
564061da546Spatrick       if (success)
565061da546Spatrick         return JSONValue::SP(new JSONNumber(uval));
566061da546Spatrick     }
567061da546Spatrick   } break;
568061da546Spatrick 
569061da546Spatrick   case JSONParser::Token::Float: {
570061da546Spatrick     bool success = false;
571061da546Spatrick     double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
572061da546Spatrick     if (success)
573061da546Spatrick       return JSONValue::SP(new JSONNumber(val));
574061da546Spatrick   } break;
575061da546Spatrick 
576061da546Spatrick   case JSONParser::Token::String:
577061da546Spatrick     return JSONValue::SP(new JSONString(value));
578061da546Spatrick 
579061da546Spatrick   case JSONParser::Token::True:
580061da546Spatrick     return JSONValue::SP(new JSONTrue());
581061da546Spatrick 
582061da546Spatrick   case JSONParser::Token::False:
583061da546Spatrick     return JSONValue::SP(new JSONFalse());
584061da546Spatrick 
585061da546Spatrick   case JSONParser::Token::Null:
586061da546Spatrick     return JSONValue::SP(new JSONNull());
587061da546Spatrick 
588061da546Spatrick   default:
589061da546Spatrick     break;
590061da546Spatrick   }
591061da546Spatrick   return JSONValue::SP();
592061da546Spatrick }
593