1 //===--------------------- JSON.cpp -----------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/Utility/JSON.h"
13 #include "lldb/Core/StreamString.h"
14 #include "lldb/Host/StringConvert.h"
15 #include "llvm/Support/ErrorHandling.h"
17 using namespace lldb_private;
20 JSONString::json_string_quote_metachars (const std::string &s)
22 if (s.find('"') == std::string::npos)
26 const size_t s_size = s.size();
27 const char *s_chars = s.c_str();
28 for (size_t i = 0; i < s_size; i++)
30 unsigned char ch = *(s_chars + i);
33 output.push_back ('\\');
35 output.push_back (ch);
40 JSONString::JSONString () :
41 JSONValue(JSONValue::Kind::String),
46 JSONString::JSONString (const char* s) :
47 JSONValue(JSONValue::Kind::String),
52 JSONString::JSONString (const std::string& s) :
53 JSONValue(JSONValue::Kind::String),
59 JSONString::Write (Stream& s)
61 s.Printf("\"%s\"", json_string_quote_metachars(m_data).c_str());
65 JSONNumber::GetAsUnsigned() const
69 case DataType::Unsigned:
70 return m_data.m_unsigned;
71 case DataType::Signed:
72 return (uint64_t)m_data.m_signed;
73 case DataType::Double:
74 return (uint64_t)m_data.m_double;
76 llvm_unreachable("Unhandled data type");
80 JSONNumber::GetAsSigned() const
84 case DataType::Unsigned:
85 return (int64_t)m_data.m_unsigned;
86 case DataType::Signed:
87 return m_data.m_signed;
88 case DataType::Double:
89 return (int64_t)m_data.m_double;
91 llvm_unreachable("Unhandled data type");
95 JSONNumber::GetAsDouble() const
99 case DataType::Unsigned:
100 return (double)m_data.m_unsigned;
101 case DataType::Signed:
102 return (double)m_data.m_signed;
103 case DataType::Double:
104 return m_data.m_double;
106 llvm_unreachable("Unhandled data type");
110 JSONNumber::Write (Stream& s)
114 case DataType::Unsigned:
115 s.Printf("%" PRIu64, m_data.m_unsigned);
117 case DataType::Signed:
118 s.Printf("%" PRId64, m_data.m_signed);
120 case DataType::Double:
121 s.Printf("%g", m_data.m_double);
126 JSONTrue::JSONTrue () :
127 JSONValue(JSONValue::Kind::True)
132 JSONTrue::Write(Stream& s)
137 JSONFalse::JSONFalse () :
138 JSONValue(JSONValue::Kind::False)
143 JSONFalse::Write(Stream& s)
148 JSONNull::JSONNull () :
149 JSONValue(JSONValue::Kind::Null)
154 JSONNull::Write(Stream& s)
159 JSONObject::JSONObject () :
160 JSONValue(JSONValue::Kind::Object)
165 JSONObject::Write (Stream& s)
169 auto iter = m_elements.begin(), end = m_elements.end();
170 for (;iter != end; iter++)
176 JSONString key(iter->first);
177 JSONValue::SP value(iter->second);
186 JSONObject::SetObject (const std::string& key,
189 if (key.empty() || nullptr == value.get())
191 m_elements[key] = value;
196 JSONObject::GetObject (const std::string& key)
198 auto iter = m_elements.find(key), end = m_elements.end();
200 return JSONValue::SP();
204 JSONArray::JSONArray () :
205 JSONValue(JSONValue::Kind::Array)
210 JSONArray::Write (Stream& s)
214 auto iter = m_elements.begin(), end = m_elements.end();
215 for (;iter != end; iter++)
227 JSONArray::SetObject (Index i,
230 if (value.get() == nullptr)
232 if (i < m_elements.size())
234 m_elements[i] = value;
237 if (i == m_elements.size())
239 m_elements.push_back(value);
246 JSONArray::AppendObject (JSONValue::SP value)
248 if (value.get() == nullptr)
250 m_elements.push_back(value);
255 JSONArray::GetObject (Index i)
257 if (i < m_elements.size())
258 return m_elements[i];
259 return JSONValue::SP();
263 JSONArray::GetNumElements ()
265 return m_elements.size();
269 JSONParser::JSONParser (const char *cstr) :
270 StringExtractor(cstr)
275 JSONParser::GetToken (std::string &value)
281 const uint64_t start_index = m_index;
282 const char ch = GetChar();
285 case '{': return Token::ObjectStart;
286 case '}': return Token::ObjectEnd;
287 case '[': return Token::ArrayStart;
288 case ']': return Token::ArrayEnd;
289 case ',': return Token::Comma;
290 case ':': return Token::Colon;
291 case '\0': return Token::EndOfFile;
293 if (GetChar() == 'r')
294 if (GetChar() == 'u')
295 if (GetChar() == 'e')
300 if (GetChar() == 'a')
301 if (GetChar() == 'l')
302 if (GetChar() == 's')
303 if (GetChar() == 'e')
308 if (GetChar() == 'u')
309 if (GetChar() == 'l')
310 if (GetChar() == 'l')
318 bool was_escaped = false;
319 int escaped_ch = GetEscapedChar(was_escaped);
320 if (escaped_ch == -1)
322 error.Printf("error: an error occurred getting a character from offset %" PRIu64, start_index);
323 value = std::move(error.GetString());
329 const bool is_end_quote = escaped_ch == '"';
330 const bool is_null = escaped_ch == 0;
331 if (was_escaped || (!is_end_quote && !is_null))
333 if (CHAR_MIN <= escaped_ch && escaped_ch <= CHAR_MAX)
335 value.append(1, (char)escaped_ch);
339 error.Printf("error: wide character support is needed for unicode character 0x%4.4x at offset %" PRIu64, escaped_ch, start_index);
340 value = std::move(error.GetString());
344 else if (is_end_quote)
346 return Token::String;
350 value = "error: missing end quote for string";
371 bool got_decimal_point = false;
372 uint64_t exp_index = 0;
373 bool got_int_digits = (ch >= '0') && (ch <= '9');
374 bool got_frac_digits = false;
375 bool got_exp_digits = false;
378 const char next_ch = PeekChar();
393 got_exp_digits = true;
395 else if (got_decimal_point)
397 got_frac_digits = true;
401 got_int_digits = true;
403 ++m_index; // Skip this character
407 if (got_decimal_point)
409 error.Printf("error: extra decimal point found at offset %" PRIu64, start_index);
410 value = std::move(error.GetString());
415 got_decimal_point = true;
416 ++m_index; // Skip this character
424 error.Printf("error: extra exponent character found at offset %" PRIu64, start_index);
425 value = std::move(error.GetString());
431 ++m_index; // Skip this character
437 // The '+' and '-' can only come after an exponent character...
438 if (exp_index == m_index - 1)
440 ++m_index; // Skip the exponent sign character
444 error.Printf("error: unexpected %c character at offset %" PRIu64, next_ch, start_index);
445 value = std::move(error.GetString());
455 if (m_index > start_index)
457 value = m_packet.substr(start_index, m_index - start_index);
458 if (got_decimal_point)
462 // We have an exponent, make sure we got exponent digits
469 error.Printf("error: got exponent character but no exponent digits at offset in float value \"%s\"", value.c_str());
470 value = std::move(error.GetString());
476 // No exponent, but we need at least one decimal after the decimal point
483 error.Printf("error: no digits after decimal point \"%s\"", value.c_str());
484 value = std::move(error.GetString());
494 // We need at least some integer digits to make an integer
495 return Token::Integer;
499 error.Printf("error: no digits negate sign \"%s\"", value.c_str());
500 value = std::move(error.GetString());
507 error.Printf("error: invalid number found at offset %" PRIu64, start_index);
508 value = std::move(error.GetString());
516 error.Printf("error: failed to parse token at offset %" PRIu64 " (around character '%c')", start_index, ch);
517 value = std::move(error.GetString());
522 JSONParser::GetEscapedChar(bool &was_escaped)
525 const char ch = GetChar();
529 const char ch2 = GetChar();
538 case 'b': return '\b';
539 case 'f': return '\f';
540 case 'n': return '\n';
541 case 'r': return '\r';
542 case 't': return '\t';
545 const int hi_byte = DecodeHexU8();
546 const int lo_byte = DecodeHexU8();
547 if (hi_byte >=0 && lo_byte >= 0)
548 return hi_byte << 8 | lo_byte;
559 JSONParser::ParseJSONObject ()
561 // The "JSONParser::Token::ObjectStart" token should have already been consumed
562 // by the time this function is called
563 std::unique_ptr<JSONObject> dict_up(new JSONObject());
569 JSONParser::Token token = GetToken(value);
571 if (token == JSONParser::Token::String)
574 token = GetToken(value);
575 if (token == JSONParser::Token::Colon)
577 JSONValue::SP value_sp = ParseJSONValue();
579 dict_up->SetObject(key, value_sp);
584 else if (token == JSONParser::Token::ObjectEnd)
586 return JSONValue::SP(dict_up.release());
588 else if (token == JSONParser::Token::Comma)
597 return JSONValue::SP();
601 JSONParser::ParseJSONArray ()
603 // The "JSONParser::Token::ObjectStart" token should have already been consumed
604 // by the time this function is called
605 std::unique_ptr<JSONArray> array_up(new JSONArray());
611 JSONValue::SP value_sp = ParseJSONValue();
613 array_up->AppendObject(value_sp);
617 JSONParser::Token token = GetToken(value);
618 if (token == JSONParser::Token::Comma)
622 else if (token == JSONParser::Token::ArrayEnd)
624 return JSONValue::SP(array_up.release());
631 return JSONValue::SP();
635 JSONParser::ParseJSONValue ()
638 const JSONParser::Token token = GetToken(value);
641 case JSONParser::Token::ObjectStart:
642 return ParseJSONObject();
644 case JSONParser::Token::ArrayStart:
645 return ParseJSONArray();
647 case JSONParser::Token::Integer:
649 if (value.front() == '-')
651 bool success = false;
652 int64_t sval = StringConvert::ToSInt64(value.c_str(), 0, 0, &success);
654 return JSONValue::SP(new JSONNumber(sval));
658 bool success = false;
659 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
661 return JSONValue::SP(new JSONNumber(uval));
666 case JSONParser::Token::Float:
668 bool success = false;
669 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
671 return JSONValue::SP(new JSONNumber(val));
675 case JSONParser::Token::String:
676 return JSONValue::SP(new JSONString(value));
678 case JSONParser::Token::True:
679 return JSONValue::SP(new JSONTrue());
681 case JSONParser::Token::False:
682 return JSONValue::SP(new JSONFalse());
684 case JSONParser::Token::Null:
685 return JSONValue::SP(new JSONNull());
690 return JSONValue::SP();