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