]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h
Merge ^/head r313644 through r313895.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / Core / StructuredData.h
1 //===-- StructuredData.h ----------------------------------------*- 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 #ifndef liblldb_StructuredData_h_
11 #define liblldb_StructuredData_h_
12
13 // C Includes
14 // C++ Includes
15 #include <functional>
16 #include <map>
17 #include <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21
22 // Other libraries and framework includes
23 #include "llvm/ADT/StringRef.h"
24
25 // Project includes
26 #include "lldb/Core/ConstString.h"
27 #include "lldb/Core/Stream.h"
28 #include "lldb/lldb-defines.h"
29
30 namespace lldb_private {
31
32 //----------------------------------------------------------------------
33 /// @class StructuredData StructuredData.h "lldb/Core/StructuredData.h"
34 /// @brief A class which can hold structured data
35 ///
36 /// The StructuredData class is designed to hold the data from a JSON
37 /// or plist style file -- a serialized data structure with dictionaries
38 /// (maps, hashes), arrays, and concrete values like integers, floating
39 /// point numbers, strings, booleans.
40 ///
41 /// StructuredData does not presuppose any knowledge of the schema for
42 /// the data it is holding; it can parse JSON data, for instance, and
43 /// other parts of lldb can iterate through the parsed data set to find
44 /// keys and values that may be present.
45 //----------------------------------------------------------------------
46
47 class StructuredData {
48 public:
49   class Object;
50   class Array;
51   class Integer;
52   class Float;
53   class Boolean;
54   class String;
55   class Dictionary;
56   class Generic;
57
58   typedef std::shared_ptr<Object> ObjectSP;
59   typedef std::shared_ptr<Array> ArraySP;
60   typedef std::shared_ptr<Integer> IntegerSP;
61   typedef std::shared_ptr<Float> FloatSP;
62   typedef std::shared_ptr<Boolean> BooleanSP;
63   typedef std::shared_ptr<String> StringSP;
64   typedef std::shared_ptr<Dictionary> DictionarySP;
65   typedef std::shared_ptr<Generic> GenericSP;
66
67   enum class Type {
68     eTypeInvalid = -1,
69     eTypeNull = 0,
70     eTypeGeneric,
71     eTypeArray,
72     eTypeInteger,
73     eTypeFloat,
74     eTypeBoolean,
75     eTypeString,
76     eTypeDictionary
77   };
78
79   class Object : public std::enable_shared_from_this<Object> {
80   public:
81     Object(Type t = Type::eTypeInvalid) : m_type(t) {}
82
83     virtual ~Object() = default;
84
85     virtual bool IsValid() const { return true; }
86
87     virtual void Clear() { m_type = Type::eTypeInvalid; }
88
89     Type GetType() const { return m_type; }
90
91     void SetType(Type t) { m_type = t; }
92
93     Array *GetAsArray() {
94       return ((m_type == Type::eTypeArray) ? static_cast<Array *>(this)
95                                            : nullptr);
96     }
97
98     Dictionary *GetAsDictionary() {
99       return ((m_type == Type::eTypeDictionary)
100                   ? static_cast<Dictionary *>(this)
101                   : nullptr);
102     }
103
104     Integer *GetAsInteger() {
105       return ((m_type == Type::eTypeInteger) ? static_cast<Integer *>(this)
106                                              : nullptr);
107     }
108
109     uint64_t GetIntegerValue(uint64_t fail_value = 0) {
110       Integer *integer = GetAsInteger();
111       return ((integer != nullptr) ? integer->GetValue() : fail_value);
112     }
113
114     Float *GetAsFloat() {
115       return ((m_type == Type::eTypeFloat) ? static_cast<Float *>(this)
116                                            : nullptr);
117     }
118
119     double GetFloatValue(double fail_value = 0.0) {
120       Float *f = GetAsFloat();
121       return ((f != nullptr) ? f->GetValue() : fail_value);
122     }
123
124     Boolean *GetAsBoolean() {
125       return ((m_type == Type::eTypeBoolean) ? static_cast<Boolean *>(this)
126                                              : nullptr);
127     }
128
129     bool GetBooleanValue(bool fail_value = false) {
130       Boolean *b = GetAsBoolean();
131       return ((b != nullptr) ? b->GetValue() : fail_value);
132     }
133
134     String *GetAsString() {
135       return ((m_type == Type::eTypeString) ? static_cast<String *>(this)
136                                             : nullptr);
137     }
138
139     std::string GetStringValue(const char *fail_value = nullptr) {
140       String *s = GetAsString();
141       if (s)
142         return s->GetValue();
143
144       if (fail_value && fail_value[0])
145         return std::string(fail_value);
146
147       return std::string();
148     }
149
150     Generic *GetAsGeneric() {
151       return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this)
152                                              : nullptr);
153     }
154
155     ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
156
157     void DumpToStdout(bool pretty_print = true) const;
158
159     virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
160
161   private:
162     Type m_type;
163   };
164
165   class Array : public Object {
166   public:
167     Array() : Object(Type::eTypeArray) {}
168
169     ~Array() override = default;
170
171     bool
172     ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
173       for (const auto &object_sp : m_items) {
174         if (foreach_callback(object_sp.get()) == false)
175           return false;
176       }
177       return true;
178     }
179
180     size_t GetSize() const { return m_items.size(); }
181
182     ObjectSP operator[](size_t idx) {
183       if (idx < m_items.size())
184         return m_items[idx];
185       return ObjectSP();
186     }
187
188     ObjectSP GetItemAtIndex(size_t idx) const {
189       assert(idx < GetSize());
190       if (idx < m_items.size())
191         return m_items[idx];
192       return ObjectSP();
193     }
194
195     template <class IntType>
196     bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
197       ObjectSP value_sp = GetItemAtIndex(idx);
198       if (value_sp.get()) {
199         if (auto int_value = value_sp->GetAsInteger()) {
200           result = static_cast<IntType>(int_value->GetValue());
201           return true;
202         }
203       }
204       return false;
205     }
206
207     template <class IntType>
208     bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
209                                  IntType default_val) const {
210       bool success = GetItemAtIndexAsInteger(idx, result);
211       if (!success)
212         result = default_val;
213       return success;
214     }
215
216     bool GetItemAtIndexAsString(size_t idx, std::string &result) const {
217       ObjectSP value_sp = GetItemAtIndex(idx);
218       if (value_sp.get()) {
219         if (auto string_value = value_sp->GetAsString()) {
220           result = string_value->GetValue();
221           return true;
222         }
223       }
224       return false;
225     }
226
227     bool GetItemAtIndexAsString(size_t idx, std::string &result,
228                                 const std::string &default_val) const {
229       bool success = GetItemAtIndexAsString(idx, result);
230       if (!success)
231         result = default_val;
232       return success;
233     }
234
235     bool GetItemAtIndexAsString(size_t idx, ConstString &result) const {
236       ObjectSP value_sp = GetItemAtIndex(idx);
237       if (value_sp.get()) {
238         if (auto string_value = value_sp->GetAsString()) {
239           result = ConstString(string_value->GetValue());
240           return true;
241         }
242       }
243       return false;
244     }
245
246     bool GetItemAtIndexAsString(size_t idx, ConstString &result,
247                                 const char *default_val) const {
248       bool success = GetItemAtIndexAsString(idx, result);
249       if (!success)
250         result.SetCString(default_val);
251       return success;
252     }
253
254     bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
255       result = nullptr;
256       ObjectSP value_sp = GetItemAtIndex(idx);
257       if (value_sp.get()) {
258         result = value_sp->GetAsDictionary();
259         return (result != nullptr);
260       }
261       return false;
262     }
263
264     bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
265       result = nullptr;
266       ObjectSP value_sp = GetItemAtIndex(idx);
267       if (value_sp.get()) {
268         result = value_sp->GetAsArray();
269         return (result != nullptr);
270       }
271       return false;
272     }
273
274     void Push(ObjectSP item) { m_items.push_back(item); }
275
276     void AddItem(ObjectSP item) { m_items.push_back(item); }
277
278     void Dump(Stream &s, bool pretty_print = true) const override;
279
280   protected:
281     typedef std::vector<ObjectSP> collection;
282     collection m_items;
283   };
284
285   class Integer : public Object {
286   public:
287     Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {}
288
289     ~Integer() override = default;
290
291     void SetValue(uint64_t value) { m_value = value; }
292
293     uint64_t GetValue() { return m_value; }
294
295     void Dump(Stream &s, bool pretty_print = true) const override;
296
297   protected:
298     uint64_t m_value;
299   };
300
301   class Float : public Object {
302   public:
303     Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
304
305     ~Float() override = default;
306
307     void SetValue(double value) { m_value = value; }
308
309     double GetValue() { return m_value; }
310
311     void Dump(Stream &s, bool pretty_print = true) const override;
312
313   protected:
314     double m_value;
315   };
316
317   class Boolean : public Object {
318   public:
319     Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
320
321     ~Boolean() override = default;
322
323     void SetValue(bool value) { m_value = value; }
324
325     bool GetValue() { return m_value; }
326
327     void Dump(Stream &s, bool pretty_print = true) const override;
328
329   protected:
330     bool m_value;
331   };
332
333   class String : public Object {
334   public:
335     String(const char *cstr = nullptr) : Object(Type::eTypeString), m_value() {
336       if (cstr)
337         m_value = cstr;
338     }
339
340     String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
341
342     String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
343
344     void SetValue(const std::string &string) { m_value = string; }
345
346     const std::string &GetValue() { return m_value; }
347
348     void Dump(Stream &s, bool pretty_print = true) const override;
349
350   protected:
351     std::string m_value;
352   };
353
354   class Dictionary : public Object {
355   public:
356     Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
357
358     ~Dictionary() override = default;
359
360     size_t GetSize() const { return m_dict.size(); }
361
362     void ForEach(std::function<bool(ConstString key, Object *object)> const
363                      &callback) const {
364       for (const auto &pair : m_dict) {
365         if (callback(pair.first, pair.second.get()) == false)
366           break;
367       }
368     }
369
370     ObjectSP GetKeys() const {
371       ObjectSP object_sp(new Array());
372       Array *array = object_sp->GetAsArray();
373       collection::const_iterator iter;
374       for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
375         ObjectSP key_object_sp(new String());
376         key_object_sp->GetAsString()->SetValue(iter->first.AsCString());
377         array->Push(key_object_sp);
378       }
379       return object_sp;
380     }
381
382     ObjectSP GetValueForKey(llvm::StringRef key) const {
383       ObjectSP value_sp;
384       if (!key.empty()) {
385         ConstString key_cs(key);
386         collection::const_iterator iter = m_dict.find(key_cs);
387         if (iter != m_dict.end())
388           value_sp = iter->second;
389       }
390       return value_sp;
391     }
392
393     bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
394       bool success = false;
395       ObjectSP value_sp = GetValueForKey(key);
396       if (value_sp.get()) {
397         Boolean *result_ptr = value_sp->GetAsBoolean();
398         if (result_ptr) {
399           result = result_ptr->GetValue();
400           success = true;
401         }
402       }
403       return success;
404     }
405     template <class IntType>
406     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
407       ObjectSP value_sp = GetValueForKey(key);
408       if (value_sp) {
409         if (auto int_value = value_sp->GetAsInteger()) {
410           result = static_cast<IntType>(int_value->GetValue());
411           return true;
412         }
413       }
414       return false;
415     }
416
417     template <class IntType>
418     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
419                                  IntType default_val) const {
420       bool success = GetValueForKeyAsInteger<IntType>(key, result);
421       if (!success)
422         result = default_val;
423       return success;
424     }
425
426     bool GetValueForKeyAsString(llvm::StringRef key,
427                                 std::string &result) const {
428       ObjectSP value_sp = GetValueForKey(key);
429       if (value_sp.get()) {
430         if (auto string_value = value_sp->GetAsString()) {
431           result = string_value->GetValue();
432           return true;
433         }
434       }
435       return false;
436     }
437
438     bool GetValueForKeyAsString(llvm::StringRef key, std::string &result,
439                                 const char *default_val) const {
440       bool success = GetValueForKeyAsString(key, result);
441       if (!success) {
442         if (default_val)
443           result = default_val;
444         else
445           result.clear();
446       }
447       return success;
448     }
449
450     bool GetValueForKeyAsString(llvm::StringRef key,
451                                 ConstString &result) const {
452       ObjectSP value_sp = GetValueForKey(key);
453       if (value_sp.get()) {
454         if (auto string_value = value_sp->GetAsString()) {
455           result = ConstString(string_value->GetValue());
456           return true;
457         }
458       }
459       return false;
460     }
461
462     bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
463                                 const char *default_val) const {
464       bool success = GetValueForKeyAsString(key, result);
465       if (!success)
466         result.SetCString(default_val);
467       return success;
468     }
469
470     bool GetValueForKeyAsDictionary(llvm::StringRef key,
471                                     Dictionary *&result) const {
472       result = nullptr;
473       ObjectSP value_sp = GetValueForKey(key);
474       if (value_sp.get()) {
475         result = value_sp->GetAsDictionary();
476         return (result != nullptr);
477       }
478       return false;
479     }
480
481     bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
482       result = nullptr;
483       ObjectSP value_sp = GetValueForKey(key);
484       if (value_sp.get()) {
485         result = value_sp->GetAsArray();
486         return (result != nullptr);
487       }
488       return false;
489     }
490
491     bool HasKey(llvm::StringRef key) const {
492       ConstString key_cs(key);
493       collection::const_iterator search = m_dict.find(key_cs);
494       return search != m_dict.end();
495     }
496
497     void AddItem(llvm::StringRef key, ObjectSP value_sp) {
498       ConstString key_cs(key);
499       m_dict[key_cs] = value_sp;
500     }
501
502     void AddIntegerItem(llvm::StringRef key, uint64_t value) {
503       AddItem(key, ObjectSP(new Integer(value)));
504     }
505
506     void AddFloatItem(llvm::StringRef key, double value) {
507       AddItem(key, ObjectSP(new Float(value)));
508     }
509
510     void AddStringItem(llvm::StringRef key, std::string value) {
511       AddItem(key, ObjectSP(new String(std::move(value))));
512     }
513
514     void AddBooleanItem(llvm::StringRef key, bool value) {
515       AddItem(key, ObjectSP(new Boolean(value)));
516     }
517
518     void Dump(Stream &s, bool pretty_print = true) const override;
519
520   protected:
521     typedef std::map<ConstString, ObjectSP> collection;
522     collection m_dict;
523   };
524
525   class Null : public Object {
526   public:
527     Null() : Object(Type::eTypeNull) {}
528
529     ~Null() override = default;
530
531     bool IsValid() const override { return false; }
532
533     void Dump(Stream &s, bool pretty_print = true) const override;
534   };
535
536   class Generic : public Object {
537   public:
538     explicit Generic(void *object = nullptr)
539         : Object(Type::eTypeGeneric), m_object(object) {}
540
541     void SetValue(void *value) { m_object = value; }
542
543     void *GetValue() const { return m_object; }
544
545     bool IsValid() const override { return m_object != nullptr; }
546
547     void Dump(Stream &s, bool pretty_print = true) const override;
548
549   private:
550     void *m_object;
551   };
552
553   static ObjectSP ParseJSON(std::string json_text);
554
555   static ObjectSP ParseJSONFromFile(const FileSpec &file, Error &error);
556 };
557
558 } // namespace lldb_private
559
560 #endif // liblldb_StructuredData_h_