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 std::string GetStringValue(const char *fail_value = nullptr) {
147 String *s = GetAsString();
149 return s->GetValue();
151 if (fail_value && fail_value[0])
152 return std::string(fail_value);
154 return std::string();
157 Generic *GetAsGeneric() {
158 return ((m_type == Type::eTypeGeneric) ? static_cast<Generic *>(this)
162 ObjectSP GetObjectForDotSeparatedPath(llvm::StringRef path);
164 void DumpToStdout(bool pretty_print = true) const;
166 virtual void Dump(Stream &s, bool pretty_print = true) const = 0;
172 class Array : public Object {
174 Array() : Object(Type::eTypeArray) {}
176 ~Array() override = default;
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)
187 size_t GetSize() const { return m_items.size(); }
189 ObjectSP operator[](size_t idx) {
190 if (idx < m_items.size())
195 ObjectSP GetItemAtIndex(size_t idx) const {
196 assert(idx < GetSize());
197 if (idx < m_items.size())
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());
214 template <class IntType>
215 bool GetItemAtIndexAsInteger(size_t idx, IntType &result,
216 IntType default_val) const {
217 bool success = GetItemAtIndexAsInteger(idx, result);
219 result = default_val;
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();
234 bool GetItemAtIndexAsString(size_t idx, std::string &result,
235 const std::string &default_val) const {
236 bool success = GetItemAtIndexAsString(idx, result);
238 result = default_val;
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());
253 bool GetItemAtIndexAsString(size_t idx, ConstString &result,
254 const char *default_val) const {
255 bool success = GetItemAtIndexAsString(idx, result);
257 result.SetCString(default_val);
261 bool GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const {
263 ObjectSP value_sp = GetItemAtIndex(idx);
264 if (value_sp.get()) {
265 result = value_sp->GetAsDictionary();
266 return (result != nullptr);
271 bool GetItemAtIndexAsArray(size_t idx, Array *&result) const {
273 ObjectSP value_sp = GetItemAtIndex(idx);
274 if (value_sp.get()) {
275 result = value_sp->GetAsArray();
276 return (result != nullptr);
281 void Push(ObjectSP item) { m_items.push_back(item); }
283 void AddItem(ObjectSP item) { m_items.push_back(item); }
285 void Dump(Stream &s, bool pretty_print = true) const override;
288 typedef std::vector<ObjectSP> collection;
292 class Integer : public Object {
294 Integer(uint64_t i = 0) : Object(Type::eTypeInteger), m_value(i) {}
296 ~Integer() override = default;
298 void SetValue(uint64_t value) { m_value = value; }
300 uint64_t GetValue() { return m_value; }
302 void Dump(Stream &s, bool pretty_print = true) const override;
308 class Float : public Object {
310 Float(double d = 0.0) : Object(Type::eTypeFloat), m_value(d) {}
312 ~Float() override = default;
314 void SetValue(double value) { m_value = value; }
316 double GetValue() { return m_value; }
318 void Dump(Stream &s, bool pretty_print = true) const override;
324 class Boolean : public Object {
326 Boolean(bool b = false) : Object(Type::eTypeBoolean), m_value(b) {}
328 ~Boolean() override = default;
330 void SetValue(bool value) { m_value = value; }
332 bool GetValue() { return m_value; }
334 void Dump(Stream &s, bool pretty_print = true) const override;
340 class String : public Object {
342 String(const char *cstr = nullptr) : Object(Type::eTypeString), m_value() {
347 String(const std::string &s) : Object(Type::eTypeString), m_value(s) {}
349 String(const std::string &&s) : Object(Type::eTypeString), m_value(s) {}
351 void SetValue(const std::string &string) { m_value = string; }
353 const std::string &GetValue() { return m_value; }
355 void Dump(Stream &s, bool pretty_print = true) const override;
361 class Dictionary : public Object {
363 Dictionary() : Object(Type::eTypeDictionary), m_dict() {}
365 ~Dictionary() override = default;
367 size_t GetSize() const { return m_dict.size(); }
369 void ForEach(std::function<bool(ConstString key, Object *object)> const
371 for (const auto &pair : m_dict) {
372 if (callback(pair.first, pair.second.get()) == false)
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);
388 ObjectSP GetValueForKey(llvm::StringRef key) const {
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;
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();
405 result = result_ptr->GetValue();
411 template <class IntType>
412 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const {
413 ObjectSP value_sp = GetValueForKey(key);
415 if (auto int_value = value_sp->GetAsInteger()) {
416 result = static_cast<IntType>(int_value->GetValue());
423 template <class IntType>
424 bool GetValueForKeyAsInteger(llvm::StringRef key, IntType &result,
425 IntType default_val) const {
426 bool success = GetValueForKeyAsInteger<IntType>(key, result);
428 result = default_val;
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();
444 bool GetValueForKeyAsString(llvm::StringRef key, std::string &result,
445 const char *default_val) const {
446 bool success = GetValueForKeyAsString(key, result);
449 result = default_val;
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());
468 bool GetValueForKeyAsString(llvm::StringRef key, ConstString &result,
469 const char *default_val) const {
470 bool success = GetValueForKeyAsString(key, result);
472 result.SetCString(default_val);
476 bool GetValueForKeyAsDictionary(llvm::StringRef key,
477 Dictionary *&result) const {
479 ObjectSP value_sp = GetValueForKey(key);
480 if (value_sp.get()) {
481 result = value_sp->GetAsDictionary();
482 return (result != nullptr);
487 bool GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const {
489 ObjectSP value_sp = GetValueForKey(key);
490 if (value_sp.get()) {
491 result = value_sp->GetAsArray();
492 return (result != nullptr);
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();
503 void AddItem(llvm::StringRef key, ObjectSP value_sp) {
504 ConstString key_cs(key);
505 m_dict[key_cs] = value_sp;
508 void AddIntegerItem(llvm::StringRef key, uint64_t value) {
509 AddItem(key, std::make_shared<Integer>(value));
512 void AddFloatItem(llvm::StringRef key, double value) {
513 AddItem(key, std::make_shared<Float>(value));
516 void AddStringItem(llvm::StringRef key, std::string value) {
517 AddItem(key, std::make_shared<String>(std::move(value)));
520 void AddBooleanItem(llvm::StringRef key, bool value) {
521 AddItem(key, std::make_shared<Boolean>(value));
524 void Dump(Stream &s, bool pretty_print = true) const override;
527 typedef std::map<ConstString, ObjectSP> collection;
531 class Null : public Object {
533 Null() : Object(Type::eTypeNull) {}
535 ~Null() override = default;
537 bool IsValid() const override { return false; }
539 void Dump(Stream &s, bool pretty_print = true) const override;
542 class Generic : public Object {
544 explicit Generic(void *object = nullptr)
545 : Object(Type::eTypeGeneric), m_object(object) {}
547 void SetValue(void *value) { m_object = value; }
549 void *GetValue() const { return m_object; }
551 bool IsValid() const override { return m_object != nullptr; }
553 void Dump(Stream &s, bool pretty_print = true) const override;
559 static ObjectSP ParseJSON(std::string json_text);
561 static ObjectSP ParseJSONFromFile(const FileSpec &file, Error &error);
564 } // namespace lldb_private
566 #endif // liblldb_StructuredData_h_