]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/include/lldb/Utility/StructuredData.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm-project / 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 #include "llvm/Support/JSON.h"
14
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/Utility/Stream.h"
18 #include "lldb/lldb-enumerations.h"
19
20 #include <cassert>
21 #include <cstddef>
22 #include <cstdint>
23 #include <functional>
24 #include <map>
25 #include <memory>
26 #include <string>
27 #include <type_traits>
28 #include <utility>
29 #include <vector>
30
31 namespace lldb_private {
32 class Status;
33 }
34
35 namespace lldb_private {
36
37 /// \class StructuredData StructuredData.h "lldb/Utility/StructuredData.h"
38 /// A class which can hold structured data
39 ///
40 /// The StructuredData class is designed to hold the data from a JSON or plist
41 /// style file -- a serialized data structure with dictionaries (maps,
42 /// hashes), arrays, and concrete values like integers, floating point
43 /// numbers, strings, booleans.
44 ///
45 /// StructuredData does not presuppose any knowledge of the schema for the
46 /// data it is holding; it can parse JSON data, for instance, and other parts
47 /// of lldb can iterate through the parsed data set to find keys and values
48 /// that may be present.
49
50 class StructuredData {
51 public:
52   class Object;
53   class Array;
54   class Integer;
55   class Float;
56   class Boolean;
57   class String;
58   class Dictionary;
59   class Generic;
60
61   typedef std::shared_ptr<Object> ObjectSP;
62   typedef std::shared_ptr<Array> ArraySP;
63   typedef std::shared_ptr<Integer> IntegerSP;
64   typedef std::shared_ptr<Float> FloatSP;
65   typedef std::shared_ptr<Boolean> BooleanSP;
66   typedef std::shared_ptr<String> StringSP;
67   typedef std::shared_ptr<Dictionary> DictionarySP;
68   typedef std::shared_ptr<Generic> GenericSP;
69
70   class Object : public std::enable_shared_from_this<Object> {
71   public:
72     Object(lldb::StructuredDataType t = lldb::eStructuredDataTypeInvalid)
73         : m_type(t) {}
74
75     virtual ~Object() = default;
76
77     virtual bool IsValid() const { return true; }
78
79     virtual void Clear() { m_type = lldb::eStructuredDataTypeInvalid; }
80
81     lldb::StructuredDataType GetType() const { return m_type; }
82
83     void SetType(lldb::StructuredDataType t) { m_type = t; }
84
85     Array *GetAsArray() {
86       return ((m_type == lldb::eStructuredDataTypeArray)
87                   ? static_cast<Array *>(this)
88                   : nullptr);
89     }
90
91     Dictionary *GetAsDictionary() {
92       return ((m_type == lldb::eStructuredDataTypeDictionary)
93                   ? static_cast<Dictionary *>(this)
94                   : nullptr);
95     }
96
97     Integer *GetAsInteger() {
98       return ((m_type == lldb::eStructuredDataTypeInteger)
99                   ? static_cast<Integer *>(this)
100                   : nullptr);
101     }
102
103     uint64_t GetIntegerValue(uint64_t fail_value = 0) {
104       Integer *integer = GetAsInteger();
105       return ((integer != nullptr) ? integer->GetValue() : fail_value);
106     }
107
108     Float *GetAsFloat() {
109       return ((m_type == lldb::eStructuredDataTypeFloat)
110                   ? static_cast<Float *>(this)
111                   : nullptr);
112     }
113
114     double GetFloatValue(double fail_value = 0.0) {
115       Float *f = GetAsFloat();
116       return ((f != nullptr) ? f->GetValue() : fail_value);
117     }
118
119     Boolean *GetAsBoolean() {
120       return ((m_type == lldb::eStructuredDataTypeBoolean)
121                   ? static_cast<Boolean *>(this)
122                   : nullptr);
123     }
124
125     bool GetBooleanValue(bool fail_value = false) {
126       Boolean *b = GetAsBoolean();
127       return ((b != nullptr) ? b->GetValue() : fail_value);
128     }
129
130     String *GetAsString() {
131       return ((m_type == lldb::eStructuredDataTypeString)
132                   ? static_cast<String *>(this)
133                   : nullptr);
134     }
135
136     llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
137       String *s = GetAsString();
138       if (s)
139         return s->GetValue();
140
141       return fail_value;
142     }
143
144     Generic *GetAsGeneric() {
145       return ((m_type == lldb::eStructuredDataTypeGeneric)
146                   ? static_cast<Generic *>(this)
147                   : nullptr);
148     }
149
150     ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
151
152     void DumpToStdout(bool pretty_print = true) const;
153
154     virtual void Serialize(llvm::json::OStream &s) const = 0;
155
156     void Dump(lldb_private::Stream &s, bool pretty_print = true) const {
157       llvm::json::OStream jso(s.AsRawOstream(), pretty_print ? 2 : 0);
158       Serialize(jso);
159     }
160
161   private:
162     lldb::StructuredDataType m_type;
163   };
164
165   class Array : public Object {
166   public:
167     Array() : Object(lldb::eStructuredDataTypeArray) {}
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()))
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, llvm::StringRef &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, llvm::StringRef &result,
228                                 llvm::StringRef 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 Serialize(llvm::json::OStream &s) 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)
288         : Object(lldb::eStructuredDataTypeInteger), m_value(i) {}
289
290     ~Integer() override = default;
291
292     void SetValue(uint64_t value) { m_value = value; }
293
294     uint64_t GetValue() { return m_value; }
295
296     void Serialize(llvm::json::OStream &s) const override;
297
298   protected:
299     uint64_t m_value;
300   };
301
302   class Float : public Object {
303   public:
304     Float(double d = 0.0)
305         : Object(lldb::eStructuredDataTypeFloat), m_value(d) {}
306
307     ~Float() override = default;
308
309     void SetValue(double value) { m_value = value; }
310
311     double GetValue() { return m_value; }
312
313     void Serialize(llvm::json::OStream &s) const override;
314
315   protected:
316     double m_value;
317   };
318
319   class Boolean : public Object {
320   public:
321     Boolean(bool b = false)
322         : Object(lldb::eStructuredDataTypeBoolean), m_value(b) {}
323
324     ~Boolean() override = default;
325
326     void SetValue(bool value) { m_value = value; }
327
328     bool GetValue() { return m_value; }
329
330     void Serialize(llvm::json::OStream &s) const override;
331
332   protected:
333     bool m_value;
334   };
335
336   class String : public Object {
337   public:
338     String() : Object(lldb::eStructuredDataTypeString) {}
339     explicit String(llvm::StringRef S)
340         : Object(lldb::eStructuredDataTypeString), m_value(S) {}
341
342     void SetValue(llvm::StringRef S) { m_value = S; }
343
344     llvm::StringRef GetValue() { return m_value; }
345
346     void Serialize(llvm::json::OStream &s) const override;
347
348   protected:
349     std::string m_value;
350   };
351
352   class Dictionary : public Object {
353   public:
354     Dictionary() : Object(lldb::eStructuredDataTypeDictionary), m_dict() {}
355
356     ~Dictionary() override = default;
357
358     size_t GetSize() const { return m_dict.size(); }
359
360     void ForEach(std::function<bool(ConstString key, Object *object)> const
361                      &callback) const {
362       for (const auto &pair : m_dict) {
363         if (!callback(pair.first, pair.second.get()))
364           break;
365       }
366     }
367
368     ObjectSP GetKeys() const {
369       auto object_sp = std::make_shared<Array>();
370       collection::const_iterator iter;
371       for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
372         auto key_object_sp = std::make_shared<String>();
373         key_object_sp->SetValue(iter->first.AsCString());
374         object_sp->Push(key_object_sp);
375       }
376       return object_sp;
377     }
378
379     ObjectSP GetValueForKey(llvm::StringRef key) const {
380       ObjectSP value_sp;
381       if (!key.empty()) {
382         ConstString key_cs(key);
383         collection::const_iterator iter = m_dict.find(key_cs);
384         if (iter != m_dict.end())
385           value_sp = iter->second;
386       }
387       return value_sp;
388     }
389
390     bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
391       bool success = false;
392       ObjectSP value_sp = GetValueForKey(key);
393       if (value_sp.get()) {
394         Boolean *result_ptr = value_sp->GetAsBoolean();
395         if (result_ptr) {
396           result = result_ptr->GetValue();
397           success = true;
398         }
399       }
400       return success;
401     }
402     template <class IntType>
403     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
404       ObjectSP value_sp = GetValueForKey(key);
405       if (value_sp) {
406         if (auto int_value = value_sp->GetAsInteger()) {
407           result = static_cast<IntType>(int_value->GetValue());
408           return true;
409         }
410       }
411       return false;
412     }
413
414     template <class IntType>
415     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
416                                  IntType default_val) const {
417       bool success = GetValueForKeyAsInteger<IntType>(key, result);
418       if (!success)
419         result = default_val;
420       return success;
421     }
422
423     bool GetValueForKeyAsString(llvm::StringRef key,
424                                 llvm::StringRef &result) const {
425       ObjectSP value_sp = GetValueForKey(key);
426       if (value_sp.get()) {
427         if (auto string_value = value_sp->GetAsString()) {
428           result = string_value->GetValue();
429           return true;
430         }
431       }
432       return false;
433     }
434
435     bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
436                                 const char *default_val) const {
437       bool success = GetValueForKeyAsString(key, result);
438       if (!success) {
439         if (default_val)
440           result = default_val;
441         else
442           result = llvm::StringRef();
443       }
444       return success;
445     }
446
447     bool GetValueForKeyAsString(llvm::StringRef key,
448                                 ConstString &result) const {
449       ObjectSP value_sp = GetValueForKey(key);
450       if (value_sp.get()) {
451         if (auto string_value = value_sp->GetAsString()) {
452           result = ConstString(string_value->GetValue());
453           return true;
454         }
455       }
456       return false;
457     }
458
459     bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
460                                 const char *default_val) const {
461       bool success = GetValueForKeyAsString(key, result);
462       if (!success)
463         result.SetCString(default_val);
464       return success;
465     }
466
467     bool GetValueForKeyAsDictionary(llvm::StringRef key,
468                                     Dictionary *&result) const {
469       result = nullptr;
470       ObjectSP value_sp = GetValueForKey(key);
471       if (value_sp.get()) {
472         result = value_sp->GetAsDictionary();
473         return (result != nullptr);
474       }
475       return false;
476     }
477
478     bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
479       result = nullptr;
480       ObjectSP value_sp = GetValueForKey(key);
481       if (value_sp.get()) {
482         result = value_sp->GetAsArray();
483         return (result != nullptr);
484       }
485       return false;
486     }
487
488     bool HasKey(llvm::StringRef key) const {
489       ConstString key_cs(key);
490       collection::const_iterator search = m_dict.find(key_cs);
491       return search != m_dict.end();
492     }
493
494     void AddItem(llvm::StringRef key, ObjectSP value_sp) {
495       ConstString key_cs(key);
496       m_dict[key_cs] = value_sp;
497     }
498
499     void AddIntegerItem(llvm::StringRef key, uint64_t value) {
500       AddItem(key, std::make_shared<Integer>(value));
501     }
502
503     void AddFloatItem(llvm::StringRef key, double value) {
504       AddItem(key, std::make_shared<Float>(value));
505     }
506
507     void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
508       AddItem(key, std::make_shared<String>(std::move(value)));
509     }
510
511     void AddBooleanItem(llvm::StringRef key, bool value) {
512       AddItem(key, std::make_shared<Boolean>(value));
513     }
514
515     void Serialize(llvm::json::OStream &s) const override;
516
517   protected:
518     typedef std::map<ConstString, ObjectSP> collection;
519     collection m_dict;
520   };
521
522   class Null : public Object {
523   public:
524     Null() : Object(lldb::eStructuredDataTypeNull) {}
525
526     ~Null() override = default;
527
528     bool IsValid() const override { return false; }
529
530     void Serialize(llvm::json::OStream &s) const override;
531   };
532
533   class Generic : public Object {
534   public:
535     explicit Generic(void *object = nullptr)
536         : Object(lldb::eStructuredDataTypeGeneric), m_object(object) {}
537
538     void SetValue(void *value) { m_object = value; }
539
540     void *GetValue() const { return m_object; }
541
542     bool IsValid() const override { return m_object != nullptr; }
543
544     void Serialize(llvm::json::OStream &s) const override;
545
546   private:
547     void *m_object;
548   };
549
550   static ObjectSP ParseJSON(std::string json_text);
551   static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
552 };
553
554 } // namespace lldb_private
555
556 #endif // liblldb_StructuredData_h_