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