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