]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/Core/StructuredData.h
Merge ^/head r316992 through r317215.
[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 Error;
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     std::string GetStringValue(const char *fail_value = nullptr) {
147       String *s = GetAsString();
148       if (s)
149         return s->GetValue();
150
151       if (fail_value && fail_value[0])
152         return std::string(fail_value);
153
154       return std::string();
155     }
156
157     Generic *GetAsGeneric() {
158       return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this)
159                                              : nullptr);
160     }
161
162     ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
163
164     void DumpToStdout(bool pretty_print = true) const;
165
166     virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
167
168   private:
169     Type m_type;
170   };
171
172   class Array : public Object {
173   public:
174     Array() : Object(Type::eTypeArray) {}
175
176     ~Array() override = default;
177
178     bool
179     ForEach(std::function<bool(Object *object)> const &foreach_callback) const {
180       for (const auto &object_sp : m_items) {
181         if (foreach_callback(object_sp.get()) == false)
182           return false;
183       }
184       return true;
185     }
186
187     size_t GetSize() const { return m_items.size(); }
188
189     ObjectSP operator[](size_t idx) {
190       if (idx < m_items.size())
191         return m_items[idx];
192       return ObjectSP();
193     }
194
195     ObjectSP GetItemAtIndex(size_t idx) const {
196       assert(idx < GetSize());
197       if (idx < m_items.size())
198         return m_items[idx];
199       return ObjectSP();
200     }
201
202     template <class IntType>
203     bool GetItemAtIndexAsInteger(size_t idx, IntType &result) const {
204       ObjectSP value_sp = GetItemAtIndex(idx);
205       if (value_sp.get()) {
206         if (auto int_value = value_sp->GetAsInteger()) {
207           result = static_cast<IntType>(int_value->GetValue());
208           return true;
209         }
210       }
211       return false;
212     }
213
214     template <class IntType>
215     bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
216                                  IntType default_val) const {
217       bool success = GetItemAtIndexAsInteger(idx, result);
218       if (!success)
219         result = default_val;
220       return success;
221     }
222
223     bool GetItemAtIndexAsString(size_t idx, std::string &result) const {
224       ObjectSP value_sp = GetItemAtIndex(idx);
225       if (value_sp.get()) {
226         if (auto string_value = value_sp->GetAsString()) {
227           result = string_value->GetValue();
228           return true;
229         }
230       }
231       return false;
232     }
233
234     bool GetItemAtIndexAsString(size_t idx, std::string &result,
235                                 const std::string &default_val) const {
236       bool success = GetItemAtIndexAsString(idx, result);
237       if (!success)
238         result = default_val;
239       return success;
240     }
241
242     bool GetItemAtIndexAsString(size_t idx, ConstString &result) const {
243       ObjectSP value_sp = GetItemAtIndex(idx);
244       if (value_sp.get()) {
245         if (auto string_value = value_sp->GetAsString()) {
246           result = ConstString(string_value->GetValue());
247           return true;
248         }
249       }
250       return false;
251     }
252
253     bool GetItemAtIndexAsString(size_t idx, ConstString &result,
254                                 const char *default_val) const {
255       bool success = GetItemAtIndexAsString(idx, result);
256       if (!success)
257         result.SetCString(default_val);
258       return success;
259     }
260
261     bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
262       result = nullptr;
263       ObjectSP value_sp = GetItemAtIndex(idx);
264       if (value_sp.get()) {
265         result = value_sp->GetAsDictionary();
266         return (result != nullptr);
267       }
268       return false;
269     }
270
271     bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
272       result = nullptr;
273       ObjectSP value_sp = GetItemAtIndex(idx);
274       if (value_sp.get()) {
275         result = value_sp->GetAsArray();
276         return (result != nullptr);
277       }
278       return false;
279     }
280
281     void Push(ObjectSP item) { m_items.push_back(item); }
282
283     void AddItem(ObjectSP item) { m_items.push_back(item); }
284
285     void Dump(Stream &s, bool pretty_print = true) const override;
286
287   protected:
288     typedef std::vector<ObjectSP> collection;
289     collection m_items;
290   };
291
292   class Integer : public Object {
293   public:
294     Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {}
295
296     ~Integer() override = default;
297
298     void SetValue(uint64_t value) { m_value = value; }
299
300     uint64_t GetValue() { return m_value; }
301
302     void Dump(Stream &s, bool pretty_print = true) const override;
303
304   protected:
305     uint64_t m_value;
306   };
307
308   class Float : public Object {
309   public:
310     Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
311
312     ~Float() override = default;
313
314     void SetValue(double value) { m_value = value; }
315
316     double GetValue() { return m_value; }
317
318     void Dump(Stream &s, bool pretty_print = true) const override;
319
320   protected:
321     double m_value;
322   };
323
324   class Boolean : public Object {
325   public:
326     Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
327
328     ~Boolean() override = default;
329
330     void SetValue(bool value) { m_value = value; }
331
332     bool GetValue() { return m_value; }
333
334     void Dump(Stream &s, bool pretty_print = true) const override;
335
336   protected:
337     bool m_value;
338   };
339
340   class String : public Object {
341   public:
342     String(const char *cstr = nullptr) : Object(Type::eTypeString), m_value() {
343       if (cstr)
344         m_value = cstr;
345     }
346
347     String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
348
349     String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
350
351     void SetValue(const std::string &string) { m_value = string; }
352
353     const std::string &GetValue() { return m_value; }
354
355     void Dump(Stream &s, bool pretty_print = true) const override;
356
357   protected:
358     std::string m_value;
359   };
360
361   class Dictionary : public Object {
362   public:
363     Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
364
365     ~Dictionary() override = default;
366
367     size_t GetSize() const { return m_dict.size(); }
368
369     void ForEach(std::function<bool(ConstString key, Object *object)> const
370                      &callback) const {
371       for (const auto &pair : m_dict) {
372         if (callback(pair.first, pair.second.get()) == false)
373           break;
374       }
375     }
376
377     ObjectSP GetKeys() const {
378       auto object_sp = std::make_shared<Array>();
379       collection::const_iterator iter;
380       for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) {
381         auto key_object_sp = std::make_shared<String>();
382         key_object_sp->SetValue(iter->first.AsCString());
383         object_sp->Push(key_object_sp);
384       }
385       return object_sp;
386     }
387
388     ObjectSP GetValueForKey(llvm::StringRef key) const {
389       ObjectSP value_sp;
390       if (!key.empty()) {
391         ConstString key_cs(key);
392         collection::const_iterator iter = m_dict.find(key_cs);
393         if (iter != m_dict.end())
394           value_sp = iter->second;
395       }
396       return value_sp;
397     }
398
399     bool GetValueForKeyAsBoolean(llvm::StringRef key, bool &result) const {
400       bool success = false;
401       ObjectSP value_sp = GetValueForKey(key);
402       if (value_sp.get()) {
403         Boolean *result_ptr = value_sp->GetAsBoolean();
404         if (result_ptr) {
405           result = result_ptr->GetValue();
406           success = true;
407         }
408       }
409       return success;
410     }
411     template <class IntType>
412     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
413       ObjectSP value_sp = GetValueForKey(key);
414       if (value_sp) {
415         if (auto int_value = value_sp->GetAsInteger()) {
416           result = static_cast<IntType>(int_value->GetValue());
417           return true;
418         }
419       }
420       return false;
421     }
422
423     template <class IntType>
424     bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
425                                  IntType default_val) const {
426       bool success = GetValueForKeyAsInteger<IntType>(key, result);
427       if (!success)
428         result = default_val;
429       return success;
430     }
431
432     bool GetValueForKeyAsString(llvm::StringRef key,
433                                 std::string &result) const {
434       ObjectSP value_sp = GetValueForKey(key);
435       if (value_sp.get()) {
436         if (auto string_value = value_sp->GetAsString()) {
437           result = string_value->GetValue();
438           return true;
439         }
440       }
441       return false;
442     }
443
444     bool GetValueForKeyAsString(llvm::StringRef key, std::string &result,
445                                 const char *default_val) const {
446       bool success = GetValueForKeyAsString(key, result);
447       if (!success) {
448         if (default_val)
449           result = default_val;
450         else
451           result.clear();
452       }
453       return success;
454     }
455
456     bool GetValueForKeyAsString(llvm::StringRef key,
457                                 ConstString &result) const {
458       ObjectSP value_sp = GetValueForKey(key);
459       if (value_sp.get()) {
460         if (auto string_value = value_sp->GetAsString()) {
461           result = ConstString(string_value->GetValue());
462           return true;
463         }
464       }
465       return false;
466     }
467
468     bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
469                                 const char *default_val) const {
470       bool success = GetValueForKeyAsString(key, result);
471       if (!success)
472         result.SetCString(default_val);
473       return success;
474     }
475
476     bool GetValueForKeyAsDictionary(llvm::StringRef key,
477                                     Dictionary *&result) const {
478       result = nullptr;
479       ObjectSP value_sp = GetValueForKey(key);
480       if (value_sp.get()) {
481         result = value_sp->GetAsDictionary();
482         return (result != nullptr);
483       }
484       return false;
485     }
486
487     bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
488       result = nullptr;
489       ObjectSP value_sp = GetValueForKey(key);
490       if (value_sp.get()) {
491         result = value_sp->GetAsArray();
492         return (result != nullptr);
493       }
494       return false;
495     }
496
497     bool HasKey(llvm::StringRef key) const {
498       ConstString key_cs(key);
499       collection::const_iterator search = m_dict.find(key_cs);
500       return search != m_dict.end();
501     }
502
503     void AddItem(llvm::StringRef key, ObjectSP value_sp) {
504       ConstString key_cs(key);
505       m_dict[key_cs] = value_sp;
506     }
507
508     void AddIntegerItem(llvm::StringRef key, uint64_t value) {
509       AddItem(key, std::make_shared<Integer>(value));
510     }
511
512     void AddFloatItem(llvm::StringRef key, double value) {
513       AddItem(key, std::make_shared<Float>(value));
514     }
515
516     void AddStringItem(llvm::StringRef key, std::string value) {
517       AddItem(key, std::make_shared<String>(std::move(value)));
518     }
519
520     void AddBooleanItem(llvm::StringRef key, bool value) {
521       AddItem(key, std::make_shared<Boolean>(value));
522     }
523
524     void Dump(Stream &s, bool pretty_print = true) const override;
525
526   protected:
527     typedef std::map<ConstString, ObjectSP> collection;
528     collection m_dict;
529   };
530
531   class Null : public Object {
532   public:
533     Null() : Object(Type::eTypeNull) {}
534
535     ~Null() override = default;
536
537     bool IsValid() const override { return false; }
538
539     void Dump(Stream &s, bool pretty_print = true) const override;
540   };
541
542   class Generic : public Object {
543   public:
544     explicit Generic(void *object = nullptr)
545         : Object(Type::eTypeGeneric), m_object(object) {}
546
547     void SetValue(void *value) { m_object = value; }
548
549     void *GetValue() const { return m_object; }
550
551     bool IsValid() const override { return m_object != nullptr; }
552
553     void Dump(Stream &s, bool pretty_print = true) const override;
554
555   private:
556     void *m_object;
557   };
558
559   static ObjectSP ParseJSON(std::string json_text);
560
561   static ObjectSP ParseJSONFromFile(const FileSpec &file, Error &error);
562 };
563
564 } // namespace lldb_private
565
566 #endif // liblldb_StructuredData_h_