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