1 //===-- StructuredData.h ----------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef liblldb_StructuredData_h_
11 #define liblldb_StructuredData_h_
13 #include "llvm/ADT/StringRef.h"
15 #include "lldb/Utility/ConstString.h"
16 #include "lldb/Utility/FileSpec.h" // for FileSpec
22 #include <type_traits> // for move
26 #include <assert.h> // for assert
27 #include <stddef.h> // for size_t
28 #include <stdint.h> // for uint64_t
30 namespace lldb_private {
33 namespace lldb_private {
37 namespace lldb_private {
39 //----------------------------------------------------------------------
40 /// @class StructuredData StructuredData.h "lldb/Core/StructuredData.h"
41 /// @brief A class which can hold structured data
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.
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 //----------------------------------------------------------------------
54 class StructuredData {
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;
86 class Object : public std::enable_shared_from_this<Object> {
88 Object(Type t = Type::eTypeInvalid) : m_type(t) {}
90 virtual ~Object() = default;
92 virtual bool IsValid() const { return true; }
94 virtual void Clear() { m_type = Type::eTypeInvalid; }
96 Type GetType() const { return m_type; }
98 void SetType(Type t) { m_type = t; }
100 Array *GetAsArray() {
101 return ((m_type == Type::eTypeArray) ? static_cast<Array *>(this)
105 Dictionary *GetAsDictionary() {
106 return ((m_type == Type::eTypeDictionary)
107 ? static_cast<Dictionary *>(this)
111 Integer *GetAsInteger() {
112 return ((m_type == Type::eTypeInteger) ? static_cast<Integer *>(this)
116 uint64_t GetIntegerValue(uint64_t fail_value = 0) {
117 Integer *integer = GetAsInteger();
118 return ((integer != nullptr) ? integer->GetValue() : fail_value);
121 Float *GetAsFloat() {
122 return ((m_type == Type::eTypeFloat) ? static_cast<Float *>(this)
126 double GetFloatValue(double fail_value = 0.0) {
127 Float *f = GetAsFloat();
128 return ((f != nullptr) ? f->GetValue() : fail_value);
131 Boolean *GetAsBoolean() {
132 return ((m_type == Type::eTypeBoolean) ? static_cast<Boolean *>(this)
136 bool GetBooleanValue(bool fail_value = false) {
137 Boolean *b = GetAsBoolean();
138 return ((b != nullptr) ? b->GetValue() : fail_value);
141 String *GetAsString() {
142 return ((m_type == Type::eTypeString) ? static_cast<String *>(this)
146 llvm::StringRef GetStringValue(const char *fail_value = nullptr) {
147 String *s = GetAsString();
149 return s->GetValue();
154 Generic *GetAsGeneric() {
155 return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this)
159 ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
161 void DumpToStdout(bool pretty_print = true) const;
163 virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
169 class Array : public Object {
171 Array() : Object(Type::eTypeArray) {}
173 ~Array() override = default;
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)
184 size_t GetSize() const { return m_items.size(); }
186 ObjectSP operator[](size_t idx) {
187 if (idx < m_items.size())
192 ObjectSP GetItemAtIndex(size_t idx) const {
193 assert(idx < GetSize());
194 if (idx < m_items.size())
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());
211 template <class IntType>
212 bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
213 IntType default_val) const {
214 bool success = GetItemAtIndexAsInteger(idx, result);
216 result = default_val;
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();
231 bool GetItemAtIndexAsString(size_t idx, llvm::StringRef &result,
232 llvm::StringRef default_val) const {
233 bool success = GetItemAtIndexAsString(idx, result);
235 result = default_val;
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());
250 bool GetItemAtIndexAsString(size_t idx, ConstString &result,
251 const char *default_val) const {
252 bool success = GetItemAtIndexAsString(idx, result);
254 result.SetCString(default_val);
258 bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
260 ObjectSP value_sp = GetItemAtIndex(idx);
261 if (value_sp.get()) {
262 result = value_sp->GetAsDictionary();
263 return (result != nullptr);
268 bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
270 ObjectSP value_sp = GetItemAtIndex(idx);
271 if (value_sp.get()) {
272 result = value_sp->GetAsArray();
273 return (result != nullptr);
278 void Push(ObjectSP item) { m_items.push_back(item); }
280 void AddItem(ObjectSP item) { m_items.push_back(item); }
282 void Dump(Stream &s, bool pretty_print = true) const override;
285 typedef std::vector<ObjectSP> collection;
289 class Integer : public Object {
291 Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {}
293 ~Integer() override = default;
295 void SetValue(uint64_t value) { m_value = value; }
297 uint64_t GetValue() { return m_value; }
299 void Dump(Stream &s, bool pretty_print = true) const override;
305 class Float : public Object {
307 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
309 ~Float() override = default;
311 void SetValue(double value) { m_value = value; }
313 double GetValue() { return m_value; }
315 void Dump(Stream &s, bool pretty_print = true) const override;
321 class Boolean : public Object {
323 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
325 ~Boolean() override = default;
327 void SetValue(bool value) { m_value = value; }
329 bool GetValue() { return m_value; }
331 void Dump(Stream &s, bool pretty_print = true) const override;
337 class String : public Object {
339 String() : Object(Type::eTypeString) {}
340 explicit String(llvm::StringRef S)
341 : Object(Type::eTypeString), m_value(S) {}
343 void SetValue(llvm::StringRef S) { m_value = S; }
345 llvm::StringRef GetValue() { return m_value; }
347 void Dump(Stream &s, bool pretty_print = true) const override;
353 class Dictionary : public Object {
355 Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
357 ~Dictionary() override = default;
359 size_t GetSize() const { return m_dict.size(); }
361 void ForEach(std::function<bool(ConstString key, Object *object)> const
363 for (const auto &pair : m_dict) {
364 if (callback(pair.first, pair.second.get()) == false)
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);
380 ObjectSP GetValueForKey(llvm::StringRef key) const {
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;
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();
397 result = result_ptr->GetValue();
403 template <class IntType>
404 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
405 ObjectSP value_sp = GetValueForKey(key);
407 if (auto int_value = value_sp->GetAsInteger()) {
408 result = static_cast<IntType>(int_value->GetValue());
415 template <class IntType>
416 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
417 IntType default_val) const {
418 bool success = GetValueForKeyAsInteger<IntType>(key, result);
420 result = default_val;
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();
436 bool GetValueForKeyAsString(llvm::StringRef key, llvm::StringRef &result,
437 const char *default_val) const {
438 bool success = GetValueForKeyAsString(key, result);
441 result = default_val;
443 result = llvm::StringRef();
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());
460 bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
461 const char *default_val) const {
462 bool success = GetValueForKeyAsString(key, result);
464 result.SetCString(default_val);
468 bool GetValueForKeyAsDictionary(llvm::StringRef key,
469 Dictionary *&result) const {
471 ObjectSP value_sp = GetValueForKey(key);
472 if (value_sp.get()) {
473 result = value_sp->GetAsDictionary();
474 return (result != nullptr);
479 bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
481 ObjectSP value_sp = GetValueForKey(key);
482 if (value_sp.get()) {
483 result = value_sp->GetAsArray();
484 return (result != nullptr);
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();
495 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
496 ConstString key_cs(key);
497 m_dict[key_cs] = value_sp;
500 void AddIntegerItem(llvm::StringRef key, uint64_t value) {
501 AddItem(key, std::make_shared<Integer>(value));
504 void AddFloatItem(llvm::StringRef key, double value) {
505 AddItem(key, std::make_shared<Float>(value));
508 void AddStringItem(llvm::StringRef key, llvm::StringRef value) {
509 AddItem(key, std::make_shared<String>(std::move(value)));
512 void AddBooleanItem(llvm::StringRef key, bool value) {
513 AddItem(key, std::make_shared<Boolean>(value));
516 void Dump(Stream &s, bool pretty_print = true) const override;
519 typedef std::map<ConstString, ObjectSP> collection;
523 class Null : public Object {
525 Null() : Object(Type::eTypeNull) {}
527 ~Null() override = default;
529 bool IsValid() const override { return false; }
531 void Dump(Stream &s, bool pretty_print = true) const override;
534 class Generic : public Object {
536 explicit Generic(void *object = nullptr)
537 : Object(Type::eTypeGeneric), m_object(object) {}
539 void SetValue(void *value) { m_object = value; }
541 void *GetValue() const { return m_object; }
543 bool IsValid() const override { return m_object != nullptr; }
545 void Dump(Stream &s, bool pretty_print = true) const override;
551 static ObjectSP ParseJSON(std::string json_text);
553 static ObjectSP ParseJSONFromFile(const FileSpec &file, Status &error);
556 } // namespace lldb_private
558 #endif // liblldb_StructuredData_h_