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