11c3bbb01SEd Maste //===--------------------- JSON.cpp -----------------------------*- C++ -*-===//
21c3bbb01SEd Maste //
31c3bbb01SEd Maste //                     The LLVM Compiler Infrastructure
41c3bbb01SEd Maste //
51c3bbb01SEd Maste // This file is distributed under the University of Illinois Open Source
61c3bbb01SEd Maste // License. See LICENSE.TXT for details.
71c3bbb01SEd Maste //
81c3bbb01SEd Maste //===----------------------------------------------------------------------===//
91c3bbb01SEd Maste 
101c3bbb01SEd Maste #include "lldb/Utility/JSON.h"
111c3bbb01SEd Maste 
12*b5893f02SDimitry Andric #include "lldb/Utility/Stream.h"
13f678e45dSDimitry Andric #include "lldb/Utility/StreamString.h"
14f678e45dSDimitry Andric #include "llvm/ADT/StringRef.h"
159f2f44ceSEd Maste #include "llvm/Support/ErrorHandling.h"
16f678e45dSDimitry Andric 
17*b5893f02SDimitry Andric #include <inttypes.h>
18435933ddSDimitry Andric #include <limits.h>
19*b5893f02SDimitry Andric #include <stddef.h>
20*b5893f02SDimitry Andric #include <utility>
21b91a7dfcSDimitry Andric 
221c3bbb01SEd Maste using namespace lldb_private;
231c3bbb01SEd Maste 
json_string_quote_metachars(const std::string & s)24435933ddSDimitry Andric std::string JSONString::json_string_quote_metachars(const std::string &s) {
25acac075bSDimitry Andric   if (s.find_first_of("\\\n\"") == std::string::npos)
261c3bbb01SEd Maste     return s;
271c3bbb01SEd Maste 
281c3bbb01SEd Maste   std::string output;
291c3bbb01SEd Maste   const size_t s_size = s.size();
301c3bbb01SEd Maste   const char *s_chars = s.c_str();
31435933ddSDimitry Andric   for (size_t i = 0; i < s_size; i++) {
321c3bbb01SEd Maste     unsigned char ch = *(s_chars + i);
33acac075bSDimitry Andric     if (ch == '"' || ch == '\\' || ch == '\n') {
341c3bbb01SEd Maste       output.push_back('\\');
35acac075bSDimitry Andric       if (ch == '\n') ch = 'n';
361c3bbb01SEd Maste     }
371c3bbb01SEd Maste     output.push_back(ch);
381c3bbb01SEd Maste   }
391c3bbb01SEd Maste   return output;
401c3bbb01SEd Maste }
411c3bbb01SEd Maste 
JSONString()42435933ddSDimitry Andric JSONString::JSONString() : JSONValue(JSONValue::Kind::String), m_data() {}
431c3bbb01SEd Maste 
JSONString(const char * s)44435933ddSDimitry Andric JSONString::JSONString(const char *s)
45435933ddSDimitry Andric     : JSONValue(JSONValue::Kind::String), m_data(s ? s : "") {}
461c3bbb01SEd Maste 
JSONString(const std::string & s)47435933ddSDimitry Andric JSONString::JSONString(const std::string &s)
48435933ddSDimitry Andric     : JSONValue(JSONValue::Kind::String), m_data(s) {}
491c3bbb01SEd Maste 
Write(Stream & s)50435933ddSDimitry Andric void JSONString::Write(Stream &s) {
511c3bbb01SEd Maste   s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str());
521c3bbb01SEd Maste }
531c3bbb01SEd Maste 
GetAsUnsigned() const54435933ddSDimitry Andric uint64_t JSONNumber::GetAsUnsigned() const {
55435933ddSDimitry Andric   switch (m_data_type) {
569f2f44ceSEd Maste   case DataType::Unsigned:
579f2f44ceSEd Maste     return m_data.m_unsigned;
589f2f44ceSEd Maste   case DataType::Signed:
599f2f44ceSEd Maste     return (uint64_t)m_data.m_signed;
609f2f44ceSEd Maste   case DataType::Double:
619f2f44ceSEd Maste     return (uint64_t)m_data.m_double;
629f2f44ceSEd Maste   }
639f2f44ceSEd Maste   llvm_unreachable("Unhandled data type");
641c3bbb01SEd Maste }
651c3bbb01SEd Maste 
GetAsSigned() const66435933ddSDimitry Andric int64_t JSONNumber::GetAsSigned() const {
67435933ddSDimitry Andric   switch (m_data_type) {
689f2f44ceSEd Maste   case DataType::Unsigned:
699f2f44ceSEd Maste     return (int64_t)m_data.m_unsigned;
709f2f44ceSEd Maste   case DataType::Signed:
719f2f44ceSEd Maste     return m_data.m_signed;
729f2f44ceSEd Maste   case DataType::Double:
739f2f44ceSEd Maste     return (int64_t)m_data.m_double;
749f2f44ceSEd Maste   }
759f2f44ceSEd Maste   llvm_unreachable("Unhandled data type");
76b91a7dfcSDimitry Andric }
77b91a7dfcSDimitry Andric 
GetAsDouble() const78435933ddSDimitry Andric double JSONNumber::GetAsDouble() const {
79435933ddSDimitry Andric   switch (m_data_type) {
809f2f44ceSEd Maste   case DataType::Unsigned:
819f2f44ceSEd Maste     return (double)m_data.m_unsigned;
829f2f44ceSEd Maste   case DataType::Signed:
839f2f44ceSEd Maste     return (double)m_data.m_signed;
849f2f44ceSEd Maste   case DataType::Double:
859f2f44ceSEd Maste     return m_data.m_double;
869f2f44ceSEd Maste   }
879f2f44ceSEd Maste   llvm_unreachable("Unhandled data type");
881c3bbb01SEd Maste }
891c3bbb01SEd Maste 
Write(Stream & s)90435933ddSDimitry Andric void JSONNumber::Write(Stream &s) {
91435933ddSDimitry Andric   switch (m_data_type) {
929f2f44ceSEd Maste   case DataType::Unsigned:
939f2f44ceSEd Maste     s.Printf("%" PRIu64, m_data.m_unsigned);
949f2f44ceSEd Maste     break;
959f2f44ceSEd Maste   case DataType::Signed:
969f2f44ceSEd Maste     s.Printf("%" PRId64, m_data.m_signed);
979f2f44ceSEd Maste     break;
989f2f44ceSEd Maste   case DataType::Double:
999f2f44ceSEd Maste     s.Printf("%g", m_data.m_double);
1009f2f44ceSEd Maste     break;
1019f2f44ceSEd Maste   }
1021c3bbb01SEd Maste }
1031c3bbb01SEd Maste 
JSONTrue()104435933ddSDimitry Andric JSONTrue::JSONTrue() : JSONValue(JSONValue::Kind::True) {}
1051c3bbb01SEd Maste 
Write(Stream & s)106435933ddSDimitry Andric void JSONTrue::Write(Stream &s) { s.Printf("true"); }
1071c3bbb01SEd Maste 
JSONFalse()108435933ddSDimitry Andric JSONFalse::JSONFalse() : JSONValue(JSONValue::Kind::False) {}
1091c3bbb01SEd Maste 
Write(Stream & s)110435933ddSDimitry Andric void JSONFalse::Write(Stream &s) { s.Printf("false"); }
1111c3bbb01SEd Maste 
JSONNull()112435933ddSDimitry Andric JSONNull::JSONNull() : JSONValue(JSONValue::Kind::Null) {}
1131c3bbb01SEd Maste 
Write(Stream & s)114435933ddSDimitry Andric void JSONNull::Write(Stream &s) { s.Printf("null"); }
1151c3bbb01SEd Maste 
JSONObject()116435933ddSDimitry Andric JSONObject::JSONObject() : JSONValue(JSONValue::Kind::Object) {}
1171c3bbb01SEd Maste 
Write(Stream & s)118435933ddSDimitry Andric void JSONObject::Write(Stream &s) {
1191c3bbb01SEd Maste   bool first = true;
1201c3bbb01SEd Maste   s.PutChar('{');
1211c3bbb01SEd Maste   auto iter = m_elements.begin(), end = m_elements.end();
122435933ddSDimitry Andric   for (; iter != end; iter++) {
1231c3bbb01SEd Maste     if (first)
1241c3bbb01SEd Maste       first = false;
1251c3bbb01SEd Maste     else
1261c3bbb01SEd Maste       s.PutChar(',');
1271c3bbb01SEd Maste     JSONString key(iter->first);
1281c3bbb01SEd Maste     JSONValue::SP value(iter->second);
1291c3bbb01SEd Maste     key.Write(s);
1301c3bbb01SEd Maste     s.PutChar(':');
1311c3bbb01SEd Maste     value->Write(s);
1321c3bbb01SEd Maste   }
1331c3bbb01SEd Maste   s.PutChar('}');
1341c3bbb01SEd Maste }
1351c3bbb01SEd Maste 
SetObject(const std::string & key,JSONValue::SP value)136435933ddSDimitry Andric bool JSONObject::SetObject(const std::string &key, JSONValue::SP value) {
1371c3bbb01SEd Maste   if (key.empty() || nullptr == value.get())
1381c3bbb01SEd Maste     return false;
1391c3bbb01SEd Maste   m_elements[key] = value;
1401c3bbb01SEd Maste   return true;
1411c3bbb01SEd Maste }
1421c3bbb01SEd Maste 
GetObject(const std::string & key)143435933ddSDimitry Andric JSONValue::SP JSONObject::GetObject(const std::string &key) {
1441c3bbb01SEd Maste   auto iter = m_elements.find(key), end = m_elements.end();
1451c3bbb01SEd Maste   if (iter == end)
1461c3bbb01SEd Maste     return JSONValue::SP();
1471c3bbb01SEd Maste   return iter->second;
1481c3bbb01SEd Maste }
1491c3bbb01SEd Maste 
JSONArray()150435933ddSDimitry Andric JSONArray::JSONArray() : JSONValue(JSONValue::Kind::Array) {}
1511c3bbb01SEd Maste 
Write(Stream & s)152435933ddSDimitry Andric void JSONArray::Write(Stream &s) {
1531c3bbb01SEd Maste   bool first = true;
1541c3bbb01SEd Maste   s.PutChar('[');
1551c3bbb01SEd Maste   auto iter = m_elements.begin(), end = m_elements.end();
156435933ddSDimitry Andric   for (; iter != end; iter++) {
1571c3bbb01SEd Maste     if (first)
1581c3bbb01SEd Maste       first = false;
1591c3bbb01SEd Maste     else
1601c3bbb01SEd Maste       s.PutChar(',');
1611c3bbb01SEd Maste     (*iter)->Write(s);
1621c3bbb01SEd Maste   }
1631c3bbb01SEd Maste   s.PutChar(']');
1641c3bbb01SEd Maste }
1651c3bbb01SEd Maste 
SetObject(Index i,JSONValue::SP value)166435933ddSDimitry Andric bool JSONArray::SetObject(Index i, JSONValue::SP value) {
1671c3bbb01SEd Maste   if (value.get() == nullptr)
1681c3bbb01SEd Maste     return false;
169435933ddSDimitry Andric   if (i < m_elements.size()) {
1701c3bbb01SEd Maste     m_elements[i] = value;
1711c3bbb01SEd Maste     return true;
1721c3bbb01SEd Maste   }
173435933ddSDimitry Andric   if (i == m_elements.size()) {
1741c3bbb01SEd Maste     m_elements.push_back(value);
1751c3bbb01SEd Maste     return true;
1761c3bbb01SEd Maste   }
1771c3bbb01SEd Maste   return false;
1781c3bbb01SEd Maste }
1791c3bbb01SEd Maste 
AppendObject(JSONValue::SP value)180435933ddSDimitry Andric bool JSONArray::AppendObject(JSONValue::SP value) {
1811c3bbb01SEd Maste   if (value.get() == nullptr)
1821c3bbb01SEd Maste     return false;
1831c3bbb01SEd Maste   m_elements.push_back(value);
1841c3bbb01SEd Maste   return true;
1851c3bbb01SEd Maste }
1861c3bbb01SEd Maste 
GetObject(Index i)187435933ddSDimitry Andric JSONValue::SP JSONArray::GetObject(Index i) {
1881c3bbb01SEd Maste   if (i < m_elements.size())
1891c3bbb01SEd Maste     return m_elements[i];
1901c3bbb01SEd Maste   return JSONValue::SP();
1911c3bbb01SEd Maste }
1921c3bbb01SEd Maste 
GetNumElements()193435933ddSDimitry Andric JSONArray::Size JSONArray::GetNumElements() { return m_elements.size(); }
194b91a7dfcSDimitry Andric 
JSONParser(llvm::StringRef data)195a580b014SDimitry Andric JSONParser::JSONParser(llvm::StringRef data) : StringExtractor(data) {}
196b91a7dfcSDimitry Andric 
GetToken(std::string & value)197435933ddSDimitry Andric JSONParser::Token JSONParser::GetToken(std::string &value) {
198b91a7dfcSDimitry Andric   StreamString error;
199b91a7dfcSDimitry Andric 
200b91a7dfcSDimitry Andric   value.clear();
201b91a7dfcSDimitry Andric   SkipSpaces();
202b91a7dfcSDimitry Andric   const uint64_t start_index = m_index;
203b91a7dfcSDimitry Andric   const char ch = GetChar();
204435933ddSDimitry Andric   switch (ch) {
205435933ddSDimitry Andric   case '{':
206435933ddSDimitry Andric     return Token::ObjectStart;
207435933ddSDimitry Andric   case '}':
208435933ddSDimitry Andric     return Token::ObjectEnd;
209435933ddSDimitry Andric   case '[':
210435933ddSDimitry Andric     return Token::ArrayStart;
211435933ddSDimitry Andric   case ']':
212435933ddSDimitry Andric     return Token::ArrayEnd;
213435933ddSDimitry Andric   case ',':
214435933ddSDimitry Andric     return Token::Comma;
215435933ddSDimitry Andric   case ':':
216435933ddSDimitry Andric     return Token::Colon;
217435933ddSDimitry Andric   case '\0':
218435933ddSDimitry Andric     return Token::EndOfFile;
219b91a7dfcSDimitry Andric   case 't':
220b91a7dfcSDimitry Andric     if (GetChar() == 'r')
221b91a7dfcSDimitry Andric       if (GetChar() == 'u')
222b91a7dfcSDimitry Andric         if (GetChar() == 'e')
223b91a7dfcSDimitry Andric           return Token::True;
224b91a7dfcSDimitry Andric     break;
225b91a7dfcSDimitry Andric 
226b91a7dfcSDimitry Andric   case 'f':
227b91a7dfcSDimitry Andric     if (GetChar() == 'a')
228b91a7dfcSDimitry Andric       if (GetChar() == 'l')
229b91a7dfcSDimitry Andric         if (GetChar() == 's')
230b91a7dfcSDimitry Andric           if (GetChar() == 'e')
231b91a7dfcSDimitry Andric             return Token::False;
232b91a7dfcSDimitry Andric     break;
233b91a7dfcSDimitry Andric 
234b91a7dfcSDimitry Andric   case 'n':
235b91a7dfcSDimitry Andric     if (GetChar() == 'u')
236b91a7dfcSDimitry Andric       if (GetChar() == 'l')
237b91a7dfcSDimitry Andric         if (GetChar() == 'l')
238b91a7dfcSDimitry Andric           return Token::Null;
239b91a7dfcSDimitry Andric     break;
240b91a7dfcSDimitry Andric 
241435933ddSDimitry Andric   case '"': {
242435933ddSDimitry Andric     while (1) {
243b91a7dfcSDimitry Andric       bool was_escaped = false;
244b91a7dfcSDimitry Andric       int escaped_ch = GetEscapedChar(was_escaped);
245435933ddSDimitry Andric       if (escaped_ch == -1) {
246435933ddSDimitry Andric         error.Printf(
247435933ddSDimitry Andric             "error: an error occurred getting a character from offset %" PRIu64,
248435933ddSDimitry Andric             start_index);
249b91a7dfcSDimitry Andric         value = std::move(error.GetString());
2505517e702SDimitry Andric         return Token::Status;
251b91a7dfcSDimitry Andric 
252435933ddSDimitry Andric       } else {
253b91a7dfcSDimitry Andric         const bool is_end_quote = escaped_ch == '"';
254b91a7dfcSDimitry Andric         const bool is_null = escaped_ch == 0;
255435933ddSDimitry Andric         if (was_escaped || (!is_end_quote && !is_null)) {
256435933ddSDimitry Andric           if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX) {
257b91a7dfcSDimitry Andric             value.append(1, (char)escaped_ch);
258435933ddSDimitry Andric           } else {
259435933ddSDimitry Andric             error.Printf("error: wide character support is needed for unicode "
260435933ddSDimitry Andric                          "character 0x%4.4x at offset %" PRIu64,
261435933ddSDimitry Andric                          escaped_ch, start_index);
262b91a7dfcSDimitry Andric             value = std::move(error.GetString());
2635517e702SDimitry Andric             return Token::Status;
264b91a7dfcSDimitry Andric           }
265435933ddSDimitry Andric         } else if (is_end_quote) {
266b91a7dfcSDimitry Andric           return Token::String;
267435933ddSDimitry Andric         } else if (is_null) {
268b91a7dfcSDimitry Andric           value = "error: missing end quote for string";
2695517e702SDimitry Andric           return Token::Status;
270b91a7dfcSDimitry Andric         }
271b91a7dfcSDimitry Andric       }
272b91a7dfcSDimitry Andric     }
273435933ddSDimitry Andric   } break;
274b91a7dfcSDimitry Andric 
275b91a7dfcSDimitry Andric   case '-':
276b91a7dfcSDimitry Andric   case '0':
277b91a7dfcSDimitry Andric   case '1':
278b91a7dfcSDimitry Andric   case '2':
279b91a7dfcSDimitry Andric   case '3':
280b91a7dfcSDimitry Andric   case '4':
281b91a7dfcSDimitry Andric   case '5':
282b91a7dfcSDimitry Andric   case '6':
283b91a7dfcSDimitry Andric   case '7':
284b91a7dfcSDimitry Andric   case '8':
285435933ddSDimitry Andric   case '9': {
286b91a7dfcSDimitry Andric     bool done = false;
287b91a7dfcSDimitry Andric     bool got_decimal_point = false;
288b91a7dfcSDimitry Andric     uint64_t exp_index = 0;
289b91a7dfcSDimitry Andric     bool got_int_digits = (ch >= '0') && (ch <= '9');
290b91a7dfcSDimitry Andric     bool got_frac_digits = false;
291b91a7dfcSDimitry Andric     bool got_exp_digits = false;
292435933ddSDimitry Andric     while (!done) {
293b91a7dfcSDimitry Andric       const char next_ch = PeekChar();
294435933ddSDimitry Andric       switch (next_ch) {
295b91a7dfcSDimitry Andric       case '0':
296b91a7dfcSDimitry Andric       case '1':
297b91a7dfcSDimitry Andric       case '2':
298b91a7dfcSDimitry Andric       case '3':
299b91a7dfcSDimitry Andric       case '4':
300b91a7dfcSDimitry Andric       case '5':
301b91a7dfcSDimitry Andric       case '6':
302b91a7dfcSDimitry Andric       case '7':
303b91a7dfcSDimitry Andric       case '8':
304b91a7dfcSDimitry Andric       case '9':
305435933ddSDimitry Andric         if (exp_index != 0) {
306b91a7dfcSDimitry Andric           got_exp_digits = true;
307435933ddSDimitry Andric         } else if (got_decimal_point) {
308b91a7dfcSDimitry Andric           got_frac_digits = true;
309435933ddSDimitry Andric         } else {
310b91a7dfcSDimitry Andric           got_int_digits = true;
311b91a7dfcSDimitry Andric         }
312b91a7dfcSDimitry Andric         ++m_index; // Skip this character
313b91a7dfcSDimitry Andric         break;
314b91a7dfcSDimitry Andric 
315b91a7dfcSDimitry Andric       case '.':
316435933ddSDimitry Andric         if (got_decimal_point) {
317435933ddSDimitry Andric           error.Printf("error: extra decimal point found at offset %" PRIu64,
318435933ddSDimitry Andric                        start_index);
319b91a7dfcSDimitry Andric           value = std::move(error.GetString());
3205517e702SDimitry Andric           return Token::Status;
321435933ddSDimitry Andric         } else {
322b91a7dfcSDimitry Andric           got_decimal_point = true;
323b91a7dfcSDimitry Andric           ++m_index; // Skip this character
324b91a7dfcSDimitry Andric         }
325b91a7dfcSDimitry Andric         break;
326b91a7dfcSDimitry Andric 
327b91a7dfcSDimitry Andric       case 'e':
328b91a7dfcSDimitry Andric       case 'E':
329435933ddSDimitry Andric         if (exp_index != 0) {
330435933ddSDimitry Andric           error.Printf(
331435933ddSDimitry Andric               "error: extra exponent character found at offset %" PRIu64,
332435933ddSDimitry Andric               start_index);
333b91a7dfcSDimitry Andric           value = std::move(error.GetString());
3345517e702SDimitry Andric           return Token::Status;
335435933ddSDimitry Andric         } else {
336b91a7dfcSDimitry Andric           exp_index = m_index;
337b91a7dfcSDimitry Andric           ++m_index; // Skip this character
338b91a7dfcSDimitry Andric         }
339b91a7dfcSDimitry Andric         break;
340b91a7dfcSDimitry Andric 
341b91a7dfcSDimitry Andric       case '+':
342b91a7dfcSDimitry Andric       case '-':
343b91a7dfcSDimitry Andric         // The '+' and '-' can only come after an exponent character...
344435933ddSDimitry Andric         if (exp_index == m_index - 1) {
345b91a7dfcSDimitry Andric           ++m_index; // Skip the exponent sign character
346435933ddSDimitry Andric         } else {
347435933ddSDimitry Andric           error.Printf("error: unexpected %c character at offset %" PRIu64,
348435933ddSDimitry Andric                        next_ch, start_index);
349b91a7dfcSDimitry Andric           value = std::move(error.GetString());
3505517e702SDimitry Andric           return Token::Status;
351b91a7dfcSDimitry Andric         }
3524bb0738eSEd Maste         break;
353b91a7dfcSDimitry Andric 
354b91a7dfcSDimitry Andric       default:
355b91a7dfcSDimitry Andric         done = true;
356b91a7dfcSDimitry Andric         break;
357b91a7dfcSDimitry Andric       }
358b91a7dfcSDimitry Andric     }
359b91a7dfcSDimitry Andric 
360435933ddSDimitry Andric     if (m_index > start_index) {
361b91a7dfcSDimitry Andric       value = m_packet.substr(start_index, m_index - start_index);
362435933ddSDimitry Andric       if (got_decimal_point) {
363435933ddSDimitry Andric         if (exp_index != 0) {
364b91a7dfcSDimitry Andric           // We have an exponent, make sure we got exponent digits
365435933ddSDimitry Andric           if (got_exp_digits) {
366b91a7dfcSDimitry Andric             return Token::Float;
367435933ddSDimitry Andric           } else {
368435933ddSDimitry Andric             error.Printf("error: got exponent character but no exponent digits "
369435933ddSDimitry Andric                          "at offset in float value \"%s\"",
370435933ddSDimitry Andric                          value.c_str());
371435933ddSDimitry Andric             value = std::move(error.GetString());
3725517e702SDimitry Andric             return Token::Status;
373b91a7dfcSDimitry Andric           }
374435933ddSDimitry Andric         } else {
375435933ddSDimitry Andric           // No exponent, but we need at least one decimal after the decimal
376435933ddSDimitry Andric           // point
377435933ddSDimitry Andric           if (got_frac_digits) {
378435933ddSDimitry Andric             return Token::Float;
379435933ddSDimitry Andric           } else {
380435933ddSDimitry Andric             error.Printf("error: no digits after decimal point \"%s\"",
381435933ddSDimitry Andric                          value.c_str());
382b91a7dfcSDimitry Andric             value = std::move(error.GetString());
3835517e702SDimitry Andric             return Token::Status;
384b91a7dfcSDimitry Andric           }
385b91a7dfcSDimitry Andric         }
386435933ddSDimitry Andric       } else {
387b91a7dfcSDimitry Andric         // No decimal point
388435933ddSDimitry Andric         if (got_int_digits) {
389b91a7dfcSDimitry Andric           // We need at least some integer digits to make an integer
390b91a7dfcSDimitry Andric           return Token::Integer;
391435933ddSDimitry Andric         } else {
392b91a7dfcSDimitry Andric           error.Printf("error: no digits negate sign \"%s\"", value.c_str());
393b91a7dfcSDimitry Andric           value = std::move(error.GetString());
3945517e702SDimitry Andric           return Token::Status;
395b91a7dfcSDimitry Andric         }
396b91a7dfcSDimitry Andric       }
397435933ddSDimitry Andric     } else {
398435933ddSDimitry Andric       error.Printf("error: invalid number found at offset %" PRIu64,
399435933ddSDimitry Andric                    start_index);
400b91a7dfcSDimitry Andric       value = std::move(error.GetString());
4015517e702SDimitry Andric       return Token::Status;
402b91a7dfcSDimitry Andric     }
403435933ddSDimitry Andric   } break;
404b91a7dfcSDimitry Andric   default:
405b91a7dfcSDimitry Andric     break;
406b91a7dfcSDimitry Andric   }
407435933ddSDimitry Andric   error.Printf("error: failed to parse token at offset %" PRIu64
408435933ddSDimitry Andric                " (around character '%c')",
409435933ddSDimitry Andric                start_index, ch);
410b91a7dfcSDimitry Andric   value = std::move(error.GetString());
4115517e702SDimitry Andric   return Token::Status;
412b91a7dfcSDimitry Andric }
413b91a7dfcSDimitry Andric 
GetEscapedChar(bool & was_escaped)414435933ddSDimitry Andric int JSONParser::GetEscapedChar(bool &was_escaped) {
415b91a7dfcSDimitry Andric   was_escaped = false;
416b91a7dfcSDimitry Andric   const char ch = GetChar();
417435933ddSDimitry Andric   if (ch == '\\') {
418b91a7dfcSDimitry Andric     was_escaped = true;
419b91a7dfcSDimitry Andric     const char ch2 = GetChar();
420435933ddSDimitry Andric     switch (ch2) {
421b91a7dfcSDimitry Andric     case '"':
422b91a7dfcSDimitry Andric     case '\\':
423b91a7dfcSDimitry Andric     case '/':
424b91a7dfcSDimitry Andric     default:
425b91a7dfcSDimitry Andric       break;
426b91a7dfcSDimitry Andric 
427435933ddSDimitry Andric     case 'b':
428435933ddSDimitry Andric       return '\b';
429435933ddSDimitry Andric     case 'f':
430435933ddSDimitry Andric       return '\f';
431435933ddSDimitry Andric     case 'n':
432435933ddSDimitry Andric       return '\n';
433435933ddSDimitry Andric     case 'r':
434435933ddSDimitry Andric       return '\r';
435435933ddSDimitry Andric     case 't':
436435933ddSDimitry Andric       return '\t';
437435933ddSDimitry Andric     case 'u': {
438b91a7dfcSDimitry Andric       const int hi_byte = DecodeHexU8();
439b91a7dfcSDimitry Andric       const int lo_byte = DecodeHexU8();
440b91a7dfcSDimitry Andric       if (hi_byte >= 0 && lo_byte >= 0)
441b91a7dfcSDimitry Andric         return hi_byte << 8 | lo_byte;
442b91a7dfcSDimitry Andric       return -1;
443435933ddSDimitry Andric     } break;
444b91a7dfcSDimitry Andric     }
445b91a7dfcSDimitry Andric     return ch2;
446b91a7dfcSDimitry Andric   }
447b91a7dfcSDimitry Andric   return ch;
448b91a7dfcSDimitry Andric }
449b91a7dfcSDimitry Andric 
ParseJSONObject()450435933ddSDimitry Andric JSONValue::SP JSONParser::ParseJSONObject() {
451435933ddSDimitry Andric   // The "JSONParser::Token::ObjectStart" token should have already been
4524ba319b5SDimitry Andric   // consumed by the time this function is called
453b91a7dfcSDimitry Andric   std::unique_ptr<JSONObject> dict_up(new JSONObject());
454b91a7dfcSDimitry Andric 
455b91a7dfcSDimitry Andric   std::string value;
456b91a7dfcSDimitry Andric   std::string key;
457435933ddSDimitry Andric   while (1) {
458b91a7dfcSDimitry Andric     JSONParser::Token token = GetToken(value);
459b91a7dfcSDimitry Andric 
460435933ddSDimitry Andric     if (token == JSONParser::Token::String) {
461b91a7dfcSDimitry Andric       key.swap(value);
462b91a7dfcSDimitry Andric       token = GetToken(value);
463435933ddSDimitry Andric       if (token == JSONParser::Token::Colon) {
464b91a7dfcSDimitry Andric         JSONValue::SP value_sp = ParseJSONValue();
465b91a7dfcSDimitry Andric         if (value_sp)
466b91a7dfcSDimitry Andric           dict_up->SetObject(key, value_sp);
467b91a7dfcSDimitry Andric         else
468b91a7dfcSDimitry Andric           break;
469b91a7dfcSDimitry Andric       }
470435933ddSDimitry Andric     } else if (token == JSONParser::Token::ObjectEnd) {
471b91a7dfcSDimitry Andric       return JSONValue::SP(dict_up.release());
472435933ddSDimitry Andric     } else if (token == JSONParser::Token::Comma) {
473b91a7dfcSDimitry Andric       continue;
474435933ddSDimitry Andric     } else {
475b91a7dfcSDimitry Andric       break;
476b91a7dfcSDimitry Andric     }
477b91a7dfcSDimitry Andric   }
478b91a7dfcSDimitry Andric   return JSONValue::SP();
479b91a7dfcSDimitry Andric }
480b91a7dfcSDimitry Andric 
ParseJSONArray()481435933ddSDimitry Andric JSONValue::SP JSONParser::ParseJSONArray() {
482435933ddSDimitry Andric   // The "JSONParser::Token::ObjectStart" token should have already been
4834ba319b5SDimitry Andric   // consumed by the time this function is called
484b91a7dfcSDimitry Andric   std::unique_ptr<JSONArray> array_up(new JSONArray());
485b91a7dfcSDimitry Andric 
486b91a7dfcSDimitry Andric   std::string value;
487b91a7dfcSDimitry Andric   std::string key;
488435933ddSDimitry Andric   while (1) {
489b91a7dfcSDimitry Andric     JSONValue::SP value_sp = ParseJSONValue();
490b91a7dfcSDimitry Andric     if (value_sp)
491b91a7dfcSDimitry Andric       array_up->AppendObject(value_sp);
492b91a7dfcSDimitry Andric     else
493b91a7dfcSDimitry Andric       break;
494b91a7dfcSDimitry Andric 
495b91a7dfcSDimitry Andric     JSONParser::Token token = GetToken(value);
496435933ddSDimitry Andric     if (token == JSONParser::Token::Comma) {
497b91a7dfcSDimitry Andric       continue;
498435933ddSDimitry Andric     } else if (token == JSONParser::Token::ArrayEnd) {
499b91a7dfcSDimitry Andric       return JSONValue::SP(array_up.release());
500435933ddSDimitry Andric     } else {
501b91a7dfcSDimitry Andric       break;
502b91a7dfcSDimitry Andric     }
503b91a7dfcSDimitry Andric   }
504b91a7dfcSDimitry Andric   return JSONValue::SP();
505b91a7dfcSDimitry Andric }
506b91a7dfcSDimitry Andric 
ParseJSONValue()507435933ddSDimitry Andric JSONValue::SP JSONParser::ParseJSONValue() {
508b91a7dfcSDimitry Andric   std::string value;
509b91a7dfcSDimitry Andric   const JSONParser::Token token = GetToken(value);
510435933ddSDimitry Andric   switch (token) {
511b91a7dfcSDimitry Andric   case JSONParser::Token::ObjectStart:
512b91a7dfcSDimitry Andric     return ParseJSONObject();
513b91a7dfcSDimitry Andric 
514b91a7dfcSDimitry Andric   case JSONParser::Token::ArrayStart:
515b91a7dfcSDimitry Andric     return ParseJSONArray();
516b91a7dfcSDimitry Andric 
517435933ddSDimitry Andric   case JSONParser::Token::Integer: {
518435933ddSDimitry Andric     if (value.front() == '-') {
519f678e45dSDimitry Andric       int64_t sval = 0;
520f678e45dSDimitry Andric       if (!llvm::StringRef(value).getAsInteger(0, sval))
5219f2f44ceSEd Maste         return JSONValue::SP(new JSONNumber(sval));
522435933ddSDimitry Andric     } else {
523f678e45dSDimitry Andric       uint64_t uval = 0;
524f678e45dSDimitry Andric       if (!llvm::StringRef(value).getAsInteger(0, uval))
525b91a7dfcSDimitry Andric         return JSONValue::SP(new JSONNumber(uval));
526b91a7dfcSDimitry Andric     }
527435933ddSDimitry Andric   } break;
528b91a7dfcSDimitry Andric 
529435933ddSDimitry Andric   case JSONParser::Token::Float: {
530f678e45dSDimitry Andric     double D;
531f678e45dSDimitry Andric     if (!llvm::StringRef(value).getAsDouble(D))
532f678e45dSDimitry Andric       return JSONValue::SP(new JSONNumber(D));
533435933ddSDimitry Andric   } break;
534b91a7dfcSDimitry Andric 
535b91a7dfcSDimitry Andric   case JSONParser::Token::String:
536b91a7dfcSDimitry Andric     return JSONValue::SP(new JSONString(value));
537b91a7dfcSDimitry Andric 
538b91a7dfcSDimitry Andric   case JSONParser::Token::True:
539b91a7dfcSDimitry Andric     return JSONValue::SP(new JSONTrue());
540b91a7dfcSDimitry Andric 
541b91a7dfcSDimitry Andric   case JSONParser::Token::False:
542b91a7dfcSDimitry Andric     return JSONValue::SP(new JSONFalse());
543b91a7dfcSDimitry Andric 
544b91a7dfcSDimitry Andric   case JSONParser::Token::Null:
545b91a7dfcSDimitry Andric     return JSONValue::SP(new JSONNull());
546b91a7dfcSDimitry Andric 
547b91a7dfcSDimitry Andric   default:
548b91a7dfcSDimitry Andric     break;
549b91a7dfcSDimitry Andric   }
550b91a7dfcSDimitry Andric   return JSONValue::SP();
551b91a7dfcSDimitry Andric }
552