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