]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Utility/StructuredData.cpp
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Utility / StructuredData.cpp
1 //===---------------------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/Utility/StructuredData.h"
11 #include "lldb/Utility/DataBuffer.h"
12 #include "lldb/Utility/FileSpec.h"
13 #include "lldb/Utility/JSON.h"
14 #include "lldb/Utility/Status.h"
15 #include "lldb/Utility/Stream.h"
16 #include "lldb/Utility/StreamString.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/Support/MemoryBuffer.h"
19 #include <cerrno>
20 #include <cstdlib>
21 #include <inttypes.h>
22 #include <limits>
23
24 using namespace lldb_private;
25
26 //----------------------------------------------------------------------
27 // Functions that use a JSONParser to parse JSON into StructuredData
28 //----------------------------------------------------------------------
29 static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser);
30 static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser);
31 static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser);
32
33 StructuredData::ObjectSP
34 StructuredData::ParseJSONFromFile(const FileSpec &input_spec, Status &error) {
35   StructuredData::ObjectSP return_sp;
36
37   auto buffer_or_error = llvm::MemoryBuffer::getFile(input_spec.GetPath());
38   if (!buffer_or_error) {
39     error.SetErrorStringWithFormatv("could not open input file: {0} - {1}.",
40                                     input_spec.GetPath(),
41                                     buffer_or_error.getError().message());
42     return return_sp;
43   }
44
45   JSONParser json_parser(buffer_or_error.get()->getBuffer());
46   return_sp = ParseJSONValue(json_parser);
47   return return_sp;
48 }
49
50 static StructuredData::ObjectSP ParseJSONObject(JSONParser &json_parser) {
51   // The "JSONParser::Token::ObjectStart" token should have already been
52   // consumed by the time this function is called
53   auto dict_up = llvm::make_unique<StructuredData::Dictionary>();
54
55   std::string value;
56   std::string key;
57   while (1) {
58     JSONParser::Token token = json_parser.GetToken(value);
59
60     if (token == JSONParser::Token::String) {
61       key.swap(value);
62       token = json_parser.GetToken(value);
63       if (token == JSONParser::Token::Colon) {
64         StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
65         if (value_sp)
66           dict_up->AddItem(key, value_sp);
67         else
68           break;
69       }
70     } else if (token == JSONParser::Token::ObjectEnd) {
71       return StructuredData::ObjectSP(dict_up.release());
72     } else if (token == JSONParser::Token::Comma) {
73       continue;
74     } else {
75       break;
76     }
77   }
78   return StructuredData::ObjectSP();
79 }
80
81 static StructuredData::ObjectSP ParseJSONArray(JSONParser &json_parser) {
82   // The "JSONParser::Token::ObjectStart" token should have already been
83   // consumed by the time this function is called
84   auto array_up = llvm::make_unique<StructuredData::Array>();
85
86   std::string value;
87   std::string key;
88   while (1) {
89     StructuredData::ObjectSP value_sp = ParseJSONValue(json_parser);
90     if (value_sp)
91       array_up->AddItem(value_sp);
92     else
93       break;
94
95     JSONParser::Token token = json_parser.GetToken(value);
96     if (token == JSONParser::Token::Comma) {
97       continue;
98     } else if (token == JSONParser::Token::ArrayEnd) {
99       return StructuredData::ObjectSP(array_up.release());
100     } else {
101       break;
102     }
103   }
104   return StructuredData::ObjectSP();
105 }
106
107 static StructuredData::ObjectSP ParseJSONValue(JSONParser &json_parser) {
108   std::string value;
109   const JSONParser::Token token = json_parser.GetToken(value);
110   switch (token) {
111   case JSONParser::Token::ObjectStart:
112     return ParseJSONObject(json_parser);
113
114   case JSONParser::Token::ArrayStart:
115     return ParseJSONArray(json_parser);
116
117   case JSONParser::Token::Integer: {
118     uint64_t uval;
119     if (llvm::to_integer(value, uval, 0))
120       return std::make_shared<StructuredData::Integer>(uval);
121   } break;
122
123   case JSONParser::Token::Float: {
124     double val;
125     if (llvm::to_float(value, val))
126       return std::make_shared<StructuredData::Float>(val);
127   } break;
128
129   case JSONParser::Token::String:
130     return std::make_shared<StructuredData::String>(value);
131
132   case JSONParser::Token::True:
133   case JSONParser::Token::False:
134     return std::make_shared<StructuredData::Boolean>(token ==
135                                                      JSONParser::Token::True);
136
137   case JSONParser::Token::Null:
138     return std::make_shared<StructuredData::Null>();
139
140   default:
141     break;
142   }
143   return StructuredData::ObjectSP();
144 }
145
146 StructuredData::ObjectSP StructuredData::ParseJSON(std::string json_text) {
147   JSONParser json_parser(json_text);
148   StructuredData::ObjectSP object_sp = ParseJSONValue(json_parser);
149   return object_sp;
150 }
151
152 StructuredData::ObjectSP
153 StructuredData::Object::GetObjectForDotSeparatedPath(llvm::StringRef path) {
154   if (this->GetType() == lldb::eStructuredDataTypeDictionary) {
155     std::pair<llvm::StringRef, llvm::StringRef> match = path.split('.');
156     std::string key = match.first.str();
157     ObjectSP value = this->GetAsDictionary()->GetValueForKey(key);
158     if (value.get()) {
159       // Do we have additional words to descend?  If not, return the value
160       // we're at right now.
161       if (match.second.empty()) {
162         return value;
163       } else {
164         return value->GetObjectForDotSeparatedPath(match.second);
165       }
166     }
167     return ObjectSP();
168   }
169
170   if (this->GetType() == lldb::eStructuredDataTypeArray) {
171     std::pair<llvm::StringRef, llvm::StringRef> match = path.split('[');
172     if (match.second.empty()) {
173       return this->shared_from_this();
174     }
175     errno = 0;
176     uint64_t val = strtoul(match.second.str().c_str(), nullptr, 10);
177     if (errno == 0) {
178       return this->GetAsArray()->GetItemAtIndex(val);
179     }
180     return ObjectSP();
181   }
182
183   return this->shared_from_this();
184 }
185
186 void StructuredData::Object::DumpToStdout(bool pretty_print) const {
187   StreamString stream;
188   Dump(stream, pretty_print);
189   llvm::outs() << stream.GetString();
190 }
191
192 void StructuredData::Array::Dump(Stream &s, bool pretty_print) const {
193   bool first = true;
194   s << "[";
195   if (pretty_print) {
196     s << "\n";
197     s.IndentMore();
198   }
199   for (const auto &item_sp : m_items) {
200     if (first) {
201       first = false;
202     } else {
203       s << ",";
204       if (pretty_print)
205         s << "\n";
206     }
207
208     if (pretty_print)
209       s.Indent();
210     item_sp->Dump(s, pretty_print);
211   }
212   if (pretty_print) {
213     s.IndentLess();
214     s.EOL();
215     s.Indent();
216   }
217   s << "]";
218 }
219
220 void StructuredData::Integer::Dump(Stream &s, bool pretty_print) const {
221   s.Printf("%" PRIu64, m_value);
222 }
223
224 void StructuredData::Float::Dump(Stream &s, bool pretty_print) const {
225   s.Printf("%lg", m_value);
226 }
227
228 void StructuredData::Boolean::Dump(Stream &s, bool pretty_print) const {
229   if (m_value)
230     s.PutCString("true");
231   else
232     s.PutCString("false");
233 }
234
235 void StructuredData::String::Dump(Stream &s, bool pretty_print) const {
236   std::string quoted;
237   const size_t strsize = m_value.size();
238   for (size_t i = 0; i < strsize; ++i) {
239     char ch = m_value[i];
240     if (ch == '"' || ch == '\\')
241       quoted.push_back('\\');
242     quoted.push_back(ch);
243   }
244   s.Printf("\"%s\"", quoted.c_str());
245 }
246
247 void StructuredData::Dictionary::Dump(Stream &s, bool pretty_print) const {
248   bool first = true;
249   s << "{";
250   if (pretty_print) {
251     s << "\n";
252     s.IndentMore();
253   }
254   for (const auto &pair : m_dict) {
255     if (first)
256       first = false;
257     else {
258       s << ",";
259       if (pretty_print)
260         s << "\n";
261     }
262     if (pretty_print)
263       s.Indent();
264     s << "\"" << pair.first.AsCString() << "\" : ";
265     pair.second->Dump(s, pretty_print);
266   }
267   if (pretty_print) {
268     s.IndentLess();
269     s.EOL();
270     s.Indent();
271   }
272   s << "}";
273 }
274
275 void StructuredData::Null::Dump(Stream &s, bool pretty_print) const {
276   s << "null";
277 }
278
279 void StructuredData::Generic::Dump(Stream &s, bool pretty_print) const {
280   s << "0x" << m_object;
281 }