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