blob: efc104f1f3e8d28229e85289ec7f3b0eb6496558 [file] [log] [blame]
Jason Molenda705b1802014-06-13 02:37:02 +00001//===---------------------StructuredData.cpp ---------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lldb/Core/StructuredData.h"
11
12#include <errno.h>
13#include <stdlib.h>
14#include <inttypes.h>
15
Zachary Turner0641ca12015-03-17 20:04:04 +000016#include "lldb/Core/StreamString.h"
Greg Clayton98424c42015-07-06 23:40:40 +000017#include "lldb/Host/StringConvert.h"
18#include "lldb/Utility/JSON.h"
Zachary Turner0641ca12015-03-17 20:04:04 +000019
Jason Molenda705b1802014-06-13 02:37:02 +000020using namespace lldb_private;
21
22
Greg Clayton98424c42015-07-06 23:40:40 +000023//----------------------------------------------------------------------
24// Functions that use a JSONParser to parse JSON into StructuredData
25//----------------------------------------------------------------------
26static 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
30static StructuredData::ObjectSP
Greg Clayton98424c42015-07-06 23:40:40 +000031ParseJSONObject (JSONParser &json_parser)
Jason Molenda705b1802014-06-13 02:37:02 +000032{
Greg Clayton98424c42015-07-06 23:40:40 +000033 // The "JSONParser::Token::ObjectStart" token should have already been consumed
34 // by the time this function is called
35 std::unique_ptr<StructuredData::Dictionary> dict_up(new StructuredData::Dictionary());
Jason Molenda705b1802014-06-13 02:37:02 +000036
Greg Clayton98424c42015-07-06 23:40:40 +000037 std::string value;
38 std::string key;
39 while (1)
Jason Molenda705b1802014-06-13 02:37:02 +000040 {
Greg Clayton98424c42015-07-06 23:40:40 +000041 JSONParser::Token token = json_parser.GetToken(value);
Jason Molenda705b1802014-06-13 02:37:02 +000042
Greg Clayton98424c42015-07-06 23:40:40 +000043 if (token == JSONParser::Token::String)
Jason Molenda705b1802014-06-13 02:37:02 +000044 {
Greg Clayton98424c42015-07-06 23:40:40 +000045 key.swap(value);
46 token = json_parser.GetToken(value);
47 if (token == JSONParser::Token::Colon)
48 {
49 StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
50 if (value_sp)
51 dict_up->AddItem(key, value_sp);
52 else
53 break;
54 }
Jason Molenda705b1802014-06-13 02:37:02 +000055 }
Greg Clayton98424c42015-07-06 23:40:40 +000056 else if (token == JSONParser::Token::ObjectEnd)
Jason Molenda705b1802014-06-13 02:37:02 +000057 {
Greg Clayton98424c42015-07-06 23:40:40 +000058 return StructuredData::ObjectSP(dict_up.release());
Jason Molenda705b1802014-06-13 02:37:02 +000059 }
Greg Clayton98424c42015-07-06 23:40:40 +000060 else if (token == JSONParser::Token::Comma)
Jason Molenda705b1802014-06-13 02:37:02 +000061 {
Greg Clayton98424c42015-07-06 23:40:40 +000062 continue;
Jason Molenda705b1802014-06-13 02:37:02 +000063 }
64 else
65 {
Greg Clayton98424c42015-07-06 23:40:40 +000066 break;
Jason Molenda705b1802014-06-13 02:37:02 +000067 }
68 }
Greg Clayton98424c42015-07-06 23:40:40 +000069 return StructuredData::ObjectSP();
Jason Molenda705b1802014-06-13 02:37:02 +000070}
71
72static StructuredData::ObjectSP
Greg Clayton98424c42015-07-06 23:40:40 +000073ParseJSONArray (JSONParser &json_parser)
Jason Molenda705b1802014-06-13 02:37:02 +000074{
Greg Clayton98424c42015-07-06 23:40:40 +000075 // The "JSONParser::Token::ObjectStart" token should have already been consumed
76 // by the time this function is called
77 std::unique_ptr<StructuredData::Array> array_up(new StructuredData::Array());
Jason Molenda705b1802014-06-13 02:37:02 +000078
Greg Clayton98424c42015-07-06 23:40:40 +000079 std::string value;
80 std::string key;
81 while (1)
82 {
83 StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
84 if (value_sp)
85 array_up->AddItem(value_sp);
86 else
87 break;
88
89 JSONParser::Token token = json_parser.GetToken(value);
90 if (token == JSONParser::Token::Comma)
Jason Molenda705b1802014-06-13 02:37:02 +000091 {
Greg Clayton98424c42015-07-06 23:40:40 +000092 continue;
Jason Molenda705b1802014-06-13 02:37:02 +000093 }
Greg Clayton98424c42015-07-06 23:40:40 +000094 else if (token == JSONParser::Token::ArrayEnd)
Jason Molenda705b1802014-06-13 02:37:02 +000095 {
Greg Clayton98424c42015-07-06 23:40:40 +000096 return StructuredData::ObjectSP(array_up.release());
97 }
98 else
99 {
100 break;
Jason Molenda705b1802014-06-13 02:37:02 +0000101 }
102 }
Greg Clayton98424c42015-07-06 23:40:40 +0000103 return StructuredData::ObjectSP();
Jason Molenda705b1802014-06-13 02:37:02 +0000104}
105
106static StructuredData::ObjectSP
Greg Clayton98424c42015-07-06 23:40:40 +0000107ParseJSONValue (JSONParser &json_parser)
Jason Molenda705b1802014-06-13 02:37:02 +0000108{
Greg Clayton98424c42015-07-06 23:40:40 +0000109 std::string value;
110 const JSONParser::Token token = json_parser.GetToken(value);
111 switch (token)
Jason Molenda705b1802014-06-13 02:37:02 +0000112 {
Greg Clayton98424c42015-07-06 23:40:40 +0000113 case JSONParser::Token::ObjectStart:
114 return ParseJSONObject(json_parser);
Jason Molenda705b1802014-06-13 02:37:02 +0000115
Greg Clayton98424c42015-07-06 23:40:40 +0000116 case JSONParser::Token::ArrayStart:
117 return ParseJSONArray(json_parser);
118
119 case JSONParser::Token::Integer:
120 {
121 bool success = false;
122 uint64_t uval = StringConvert::ToUInt64(value.c_str(), 0, 0, &success);
123 if (success)
124 return StructuredData::ObjectSP(new StructuredData::Integer(uval));
125 }
126 break;
127
128 case JSONParser::Token::Float:
129 {
130 bool success = false;
131 double val = StringConvert::ToDouble(value.c_str(), 0.0, &success);
132 if (success)
133 return StructuredData::ObjectSP(new StructuredData::Float(val));
134 }
135 break;
136
137 case JSONParser::Token::String:
138 return StructuredData::ObjectSP(new StructuredData::String(value));
139
140 case JSONParser::Token::True:
141 case JSONParser::Token::False:
142 return StructuredData::ObjectSP(new StructuredData::Boolean(token == JSONParser::Token::True));
143
144 case JSONParser::Token::Null:
145 return StructuredData::ObjectSP(new StructuredData::Null());
146
147 default:
148 break;
149 }
150 return StructuredData::ObjectSP();
151
152}
Jason Molenda705b1802014-06-13 02:37:02 +0000153
154StructuredData::ObjectSP
155StructuredData::ParseJSON (std::string json_text)
156{
Greg Clayton98424c42015-07-06 23:40:40 +0000157 JSONParser json_parser(json_text.c_str());
158 StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
Jason Molenda705b1802014-06-13 02:37:02 +0000159 return object_sp;
160}
161
162StructuredData::ObjectSP
163StructuredData::Object::GetObjectForDotSeparatedPath (llvm::StringRef path)
164{
165 if (this->GetType() == Type::eTypeDictionary)
166 {
167 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
168 std::string key = match.first.str();
169 ObjectSP value = this->GetAsDictionary()->GetValueForKey (key.c_str());
170 if (value.get())
171 {
172 // Do we have additional words to descend? If not, return the
173 // value we're at right now.
174 if (match.second.empty())
175 {
176 return value;
177 }
178 else
179 {
180 return value->GetObjectForDotSeparatedPath (match.second);
181 }
182 }
183 return ObjectSP();
184 }
185
186 if (this->GetType() == Type::eTypeArray)
187 {
188 std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
189 if (match.second.size() == 0)
190 {
191 return this->shared_from_this();
192 }
193 errno = 0;
194 uint64_t val = strtoul (match.second.str().c_str(), NULL, 10);
195 if (errno == 0)
196 {
197 return this->GetAsArray()->GetItemAtIndex(val);
198 }
199 return ObjectSP();
200 }
201
202 return this->shared_from_this();
203}
204
205void
Zachary Turner0641ca12015-03-17 20:04:04 +0000206StructuredData::Object::DumpToStdout() const
207{
208 StreamString stream;
209 Dump(stream);
Greg Clayton66b82942015-05-27 03:23:26 +0000210 printf("%s\n", stream.GetString().c_str());
Zachary Turner0641ca12015-03-17 20:04:04 +0000211}
212
213void
214StructuredData::Array::Dump(Stream &s) const
Jason Molenda705b1802014-06-13 02:37:02 +0000215{
Greg Clayton66b82942015-05-27 03:23:26 +0000216 bool first = true;
217 s << "[\n";
218 s.IndentMore();
219 for (const auto &item_sp : m_items)
Jason Molenda705b1802014-06-13 02:37:02 +0000220 {
Greg Clayton66b82942015-05-27 03:23:26 +0000221 if (first)
222 first = false;
223 else
224 s << ",\n";
225
226 s.Indent();
227 item_sp->Dump(s);
Jason Molenda705b1802014-06-13 02:37:02 +0000228 }
Greg Clayton66b82942015-05-27 03:23:26 +0000229 s.IndentLess();
230 s.EOL();
231 s.Indent();
Jason Molenda705b1802014-06-13 02:37:02 +0000232 s << "]";
233}
234
235void
236StructuredData::Integer::Dump (Stream &s) const
237{
238 s.Printf ("%" PRIu64, m_value);
239}
240
241
242void
243StructuredData::Float::Dump (Stream &s) const
244{
Greg Clayton98424c42015-07-06 23:40:40 +0000245 s.Printf ("%lg", m_value);
Jason Molenda705b1802014-06-13 02:37:02 +0000246}
247
248void
249StructuredData::Boolean::Dump (Stream &s) const
250{
251 if (m_value == true)
252 s.PutCString ("true");
253 else
254 s.PutCString ("false");
255}
256
257
258void
259StructuredData::String::Dump (Stream &s) const
260{
261 std::string quoted;
262 const size_t strsize = m_value.size();
263 for (size_t i = 0; i < strsize ; ++i)
264 {
265 char ch = m_value[i];
266 if (ch == '"')
267 quoted.push_back ('\\');
268 quoted.push_back (ch);
269 }
270 s.Printf ("\"%s\"", quoted.c_str());
271}
272
273void
274StructuredData::Dictionary::Dump (Stream &s) const
275{
Greg Clayton66b82942015-05-27 03:23:26 +0000276 bool first = true;
277 s << "{\n";
278 s.IndentMore();
279 for (const auto &pair : m_dict)
Jason Molenda705b1802014-06-13 02:37:02 +0000280 {
Greg Clayton66b82942015-05-27 03:23:26 +0000281 if (first)
282 first = false;
Jason Molenda705b1802014-06-13 02:37:02 +0000283 else
Greg Clayton66b82942015-05-27 03:23:26 +0000284 s << ",\n";
285 s.Indent();
286 s << "\"" << pair.first.AsCString() << "\" : ";
287 pair.second->Dump(s);
Jason Molenda705b1802014-06-13 02:37:02 +0000288 }
Greg Clayton66b82942015-05-27 03:23:26 +0000289 s.IndentLess();
290 s.EOL();
291 s.Indent();
Jason Molenda705b1802014-06-13 02:37:02 +0000292 s << "}";
293}
294
295void
296StructuredData::Null::Dump (Stream &s) const
297{
298 s << "null";
299}
Zachary Turner0641ca12015-03-17 20:04:04 +0000300
301void
302StructuredData::Generic::Dump(Stream &s) const
303{
304 s << "0x" << m_object;
305}