blob: 6e544c1d5370fb9aeb72a0c0b7415dc07be5366d [file] [log] [blame]
Kate Stoneb9c1b512016-09-06 20:57:50 +00001//===---------------------StructuredData.cpp ---------------------*- C++
2//-*-===//
Jason Molenda705b1802014-06-13 02:37:02 +00003//
4// The LLVM Compiler Infrastructure
5//
6// This file is distributed under the University of Illinois Open Source
7// License. See LICENSE.TXT for details.
8//
9//===----------------------------------------------------------------------===//
10
11#include "lldb/Core/StructuredData.h"
12
13#include <errno.h>
Jason Molenda705b1802014-06-13 02:37:02 +000014#include <inttypes.h>
Kate Stoneb9c1b512016-09-06 20:57:50 +000015#include <stdlib.h>
Jason Molenda705b1802014-06-13 02:37:02 +000016
Zachary Turner0641ca12015-03-17 20:04:04 +000017#include "lldb/Core/StreamString.h"
Greg Clayton98424c42015-07-06 23:40:40 +000018#include "lldb/Host/StringConvert.h"
19#include "lldb/Utility/JSON.h"
Zachary Turner0641ca12015-03-17 20:04:04 +000020
Jason Molenda705b1802014-06-13 02:37:02 +000021using namespace lldb_private;
22
Greg Clayton98424c42015-07-06 23:40:40 +000023//----------------------------------------------------------------------
24// Functions that use a JSONParser to parse JSON into StructuredData
25//----------------------------------------------------------------------
Kate Stoneb9c1b512016-09-06 20:57:50 +000026static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser);
27static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser);
28static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser);
Jason Molenda705b1802014-06-13 02:37:02 +000029
Kate Stoneb9c1b512016-09-06 20:57:50 +000030static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
31 // The "JSONParser::Token::ObjectStart" token should have already been
32 // consumed
33 // by the time this function is called
34 std::unique_ptr<StructuredData::Dictionary> dict_up(
35 new StructuredData::Dictionary());
Jason Molenda705b1802014-06-13 02:37:02 +000036
Kate Stoneb9c1b512016-09-06 20:57:50 +000037 std::string value;
38 std::string key;
39 while (1) {
40 JSONParser::Token token = json_parser.GetToken(value);
Jason Molenda705b1802014-06-13 02:37:02 +000041
Kate Stoneb9c1b512016-09-06 20:57:50 +000042 if (token == JSONParser::Token::String) {
43 key.swap(value);
44 token = json_parser.GetToken(value);
45 if (token == JSONParser::Token::Colon) {
Greg Clayton98424c42015-07-06 23:40:40 +000046 StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
47 if (value_sp)
Kate Stoneb9c1b512016-09-06 20:57:50 +000048 dict_up->AddItem(key, value_sp);
Greg Clayton98424c42015-07-06 23:40:40 +000049 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000050 break;
51 }
52 } else if (token == JSONParser::Token::ObjectEnd) {
53 return StructuredData::ObjectSP(dict_up.release());
54 } else if (token == JSONParser::Token::Comma) {
55 continue;
56 } else {
57 break;
Jason Molenda705b1802014-06-13 02:37:02 +000058 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000059 }
60 return StructuredData::ObjectSP();
Jason Molenda705b1802014-06-13 02:37:02 +000061}
62
Kate Stoneb9c1b512016-09-06 20:57:50 +000063static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) {
64 // The "JSONParser::Token::ObjectStart" token should have already been
65 // consumed
66 // by the time this function is called
67 std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array());
Jason Molenda705b1802014-06-13 02:37:02 +000068
Kate Stoneb9c1b512016-09-06 20:57:50 +000069 std::string value;
70 std::string key;
71 while (1) {
72 StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
73 if (value_sp)
74 array_up->AddItem(value_sp);
Jason Molenda705b1802014-06-13 02:37:02 +000075 else
Kate Stoneb9c1b512016-09-06 20:57:50 +000076 break;
Jason Molenda705b1802014-06-13 02:37:02 +000077
Kate Stoneb9c1b512016-09-06 20:57:50 +000078 JSONParser::Token token = json_parser.GetToken(value);
79 if (token == JSONParser::Token::Comma) {
80 continue;
81 } else if (token == JSONParser::Token::ArrayEnd) {
82 return StructuredData::ObjectSP(array_up.release());
83 } else {
84 break;
Jason Molenda705b1802014-06-13 02:37:02 +000085 }
Kate Stoneb9c1b512016-09-06 20:57:50 +000086 }
87 return StructuredData::ObjectSP();
Jason Molenda705b1802014-06-13 02:37:02 +000088}
89
Kate Stoneb9c1b512016-09-06 20:57:50 +000090static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) {
91 std::string value;
92 const JSONParser::Token token = json_parser.GetToken(value);
93 switch (token) {
94 case JSONParser::Token::ObjectStart:
95 return ParseJSONObject(json_parser);
96
97 case JSONParser::Token::ArrayStart:
98 return ParseJSONArray(json_parser);
99
100 case JSONParser::Token::Integer: {
101 bool success = false;
102 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
103 if (success)
104 return StructuredData::ObjectSP(new StructuredData::Integer(uval));
105 } break;
106
107 case JSONParser::Token::Float: {
108 bool success = false;
109 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
110 if (success)
111 return StructuredData::ObjectSP(new StructuredData::Float(val));
112 } break;
113
114 case JSONParser::Token::String:
115 return StructuredData::ObjectSP(new StructuredData::String(value));
116
117 case JSONParser::Token::True:
118 case JSONParser::Token::False:
119 return StructuredData::ObjectSP(
120 new StructuredData::Boolean(token == JSONParser::Token::True));
121
122 case JSONParser::Token::Null:
123 return StructuredData::ObjectSP(new StructuredData::Null());
124
125 default:
126 break;
127 }
128 return StructuredData::ObjectSP();
129}
130
131StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {
132 JSONParser json_parser(json_text.c_str());
133 StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
134 return object_sp;
135}
136
137StructuredData::ObjectSP
138StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
139 if (this->GetType() == Type::eTypeDictionary) {
140 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
141 std::string key = match.first.str();
142 ObjectSP value = this->GetAsDictionary()->GetValueForKey(key.c_str());
143 if (value.get()) {
144 // Do we have additional words to descend? If not, return the
145 // value we're at right now.
146 if (match.second.empty()) {
147 return value;
148 } else {
149 return value->GetObjectForDotSeparatedPath(match.second);
150 }
151 }
152 return ObjectSP();
153 }
154
155 if (this->GetType() == Type::eTypeArray) {
156 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
157 if (match.second.size() == 0) {
158 return this->shared_from_this();
159 }
160 errno = 0;
161 uint64_t val = strtoul(match.second.str().c_str(), NULL, 10);
162 if (errno == 0) {
163 return this->GetAsArray()->GetItemAtIndex(val);
164 }
165 return ObjectSP();
166 }
167
168 return this->shared_from_this();
169}
170
171void StructuredData::Object::DumpToStdout(bool pretty_print) const {
172 StreamString stream;
173 Dump(stream, pretty_print);
174 printf("%s\n", stream.GetString().c_str());
175}
176
177void StructuredData::Array::Dump(Stream &s, bool pretty_print) const {
178 bool first = true;
179 s << "[";
180 if (pretty_print) {
181 s << "\n";
182 s.IndentMore();
183 }
184 for (const auto &item_sp : m_items) {
185 if (first) {
186 first = false;
187 } else {
188 s << ",";
189 if (pretty_print)
Jason Molendae62dda22016-07-21 22:50:01 +0000190 s << "\n";
Jason Molendad9c9da52016-07-20 03:49:02 +0000191 }
Kate Stoneb9c1b512016-09-06 20:57:50 +0000192
193 if (pretty_print)
194 s.Indent();
195 item_sp->Dump(s, pretty_print);
196 }
197 if (pretty_print) {
198 s.IndentLess();
199 s.EOL();
200 s.Indent();
201 }
202 s << "]";
203}
204
205void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const {
206 s.Printf("%" PRIu64, m_value);
207}
208
209void StructuredData::Float::Dump(Stream &s, bool pretty_print) const {
210 s.Printf("%lg", m_value);
211}
212
213void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const {
214 if (m_value == true)
215 s.PutCString("true");
216 else
217 s.PutCString("false");
218}
219
220void StructuredData::String::Dump(Stream &s, bool pretty_print) const {
221 std::string quoted;
222 const size_t strsize = m_value.size();
223 for (size_t i = 0; i < strsize; ++i) {
224 char ch = m_value[i];
225 if (ch == '"')
226 quoted.push_back('\\');
227 quoted.push_back(ch);
228 }
229 s.Printf("\"%s\"", quoted.c_str());
230}
231
232void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const {
233 bool first = true;
234 s << "{";
235 if (pretty_print) {
236 s << "\n";
237 s.IndentMore();
238 }
239 for (const auto &pair : m_dict) {
240 if (first)
241 first = false;
242 else {
243 s << ",";
244 if (pretty_print)
245 s << "\n";
Jason Molenda705b1802014-06-13 02:37:02 +0000246 }
Jason Molendad9c9da52016-07-20 03:49:02 +0000247 if (pretty_print)
Kate Stoneb9c1b512016-09-06 20:57:50 +0000248 s.Indent();
249 s << "\"" << pair.first.AsCString() << "\" : ";
250 pair.second->Dump(s, pretty_print);
251 }
252 if (pretty_print) {
253 s.IndentLess();
254 s.EOL();
255 s.Indent();
256 }
257 s << "}";
Jason Molenda705b1802014-06-13 02:37:02 +0000258}
259
Kate Stoneb9c1b512016-09-06 20:57:50 +0000260void StructuredData::Null::Dump(Stream &s, bool pretty_print) const {
261 s << "null";
Jason Molenda705b1802014-06-13 02:37:02 +0000262}
Zachary Turner0641ca12015-03-17 20:04:04 +0000263
Kate Stoneb9c1b512016-09-06 20:57:50 +0000264void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const {
265 s << "0x" << m_object;
Zachary Turner0641ca12015-03-17 20:04:04 +0000266}