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