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 // C Includes 14 // C++ Includes 15 16 #include <functional> 17 #include <map> 18 #include <string> 19 #include <utility> 20 #include <vector> 21 22 #include "llvm/ADT/StringRef.h" 23 24 // Other libraries and framework includes 25 // Project includes 26 #include "lldb/lldb-defines.h" 27 #include "lldb/Core/ConstString.h" 28 #include "lldb/Core/Stream.h" 29 30 namespace lldb_private { 31 32 //---------------------------------------------------------------------- 33 /// @class StructuredData StructuredData.h "lldb/Core/StructuredData.h" 34 /// @brief A class which can hold structured data 35 /// 36 /// The StructuredData class is designed to hold the data from a JSON 37 /// or plist style file -- a serialized data structure with dictionaries 38 /// (maps, hashes), arrays, and concrete values like integers, floating 39 /// point numbers, strings, booleans. 40 /// 41 /// StructuredData does not presuppose any knowledge of the schema for 42 /// the data it is holding; it can parse JSON data, for instance, and 43 /// other parts of lldb can iterate through the parsed data set to find 44 /// keys and values that may be present. 45 //---------------------------------------------------------------------- 46 47 class StructuredData 48 { 49 public: 50 51 class Object; 52 class Array; 53 class Integer; 54 class Float; 55 class Boolean; 56 class String; 57 class Dictionary; 58 class Generic; 59 60 typedef std::shared_ptr<Object> ObjectSP; 61 typedef std::shared_ptr<Array> ArraySP; 62 typedef std::shared_ptr<Integer> IntegerSP; 63 typedef std::shared_ptr<Float> FloatSP; 64 typedef std::shared_ptr<Boolean> BooleanSP; 65 typedef std::shared_ptr<String> StringSP; 66 typedef std::shared_ptr<Dictionary> DictionarySP; 67 typedef std::shared_ptr<Generic> GenericSP; 68 69 enum class Type 70 { 71 eTypeInvalid = -1, 72 eTypeNull = 0, 73 eTypeGeneric, 74 eTypeArray, 75 eTypeInteger, 76 eTypeFloat, 77 eTypeBoolean, 78 eTypeString, 79 eTypeDictionary 80 }; 81 82 class Object : 83 public std::enable_shared_from_this<Object> 84 { 85 public: 86 87 Object (Type t = Type::eTypeInvalid) : m_type(t)88 m_type (t) 89 { 90 } 91 ~Object()92 virtual ~Object () 93 { 94 } 95 96 virtual bool IsValid()97 IsValid() const 98 { 99 return true; 100 } 101 102 virtual void Clear()103 Clear () 104 { 105 m_type = Type::eTypeInvalid; 106 } 107 108 Type GetType()109 GetType () const 110 { 111 return m_type; 112 } 113 114 void SetType(Type t)115 SetType (Type t) 116 { 117 m_type = t; 118 } 119 120 Array * GetAsArray()121 GetAsArray () 122 { 123 if (m_type == Type::eTypeArray) 124 return (Array *)this; 125 return NULL; 126 } 127 128 Dictionary * GetAsDictionary()129 GetAsDictionary () 130 { 131 if (m_type == Type::eTypeDictionary) 132 return (Dictionary *)this; 133 return NULL; 134 } 135 136 Integer * GetAsInteger()137 GetAsInteger () 138 { 139 if (m_type == Type::eTypeInteger) 140 return (Integer *)this; 141 return NULL; 142 } 143 144 uint64_t 145 GetIntegerValue (uint64_t fail_value = 0) 146 { 147 Integer *integer = GetAsInteger (); 148 if (integer) 149 return integer->GetValue(); 150 return fail_value; 151 } 152 153 Float * GetAsFloat()154 GetAsFloat () 155 { 156 if (m_type == Type::eTypeFloat) 157 return (Float *)this; 158 return NULL; 159 } 160 161 double 162 GetFloatValue (double fail_value = 0.0) 163 { 164 Float *f = GetAsFloat (); 165 if (f) 166 return f->GetValue(); 167 return fail_value; 168 } 169 170 Boolean * GetAsBoolean()171 GetAsBoolean () 172 { 173 if (m_type == Type::eTypeBoolean) 174 return (Boolean *)this; 175 return NULL; 176 } 177 178 bool 179 GetBooleanValue (bool fail_value = false) 180 { 181 Boolean *b = GetAsBoolean (); 182 if (b) 183 return b->GetValue(); 184 return fail_value; 185 } 186 187 String * GetAsString()188 GetAsString () 189 { 190 if (m_type == Type::eTypeString) 191 return (String *)this; 192 return NULL; 193 } 194 195 std::string 196 GetStringValue(const char *fail_value = NULL) 197 { 198 String *s = GetAsString (); 199 if (s) 200 return s->GetValue(); 201 202 if (fail_value && fail_value[0]) 203 return std::string(fail_value); 204 205 return std::string(); 206 } 207 208 Generic * GetAsGeneric()209 GetAsGeneric() 210 { 211 if (m_type == Type::eTypeGeneric) 212 return (Generic *)this; 213 return NULL; 214 } 215 216 ObjectSP 217 GetObjectForDotSeparatedPath (llvm::StringRef path); 218 219 void DumpToStdout() const; 220 221 virtual void 222 Dump (Stream &s) const = 0; 223 224 private: 225 Type m_type; 226 }; 227 228 class Array : public Object 229 { 230 public: Array()231 Array () : 232 Object (Type::eTypeArray) 233 { 234 } 235 236 virtual ~Array()237 ~Array() 238 { 239 } 240 241 bool ForEach(std::function<bool (Object * object)> const & foreach_callback)242 ForEach (std::function <bool(Object* object)> const &foreach_callback) const 243 { 244 for (const auto &object_sp : m_items) 245 { 246 if (foreach_callback(object_sp.get()) == false) 247 return false; 248 } 249 return true; 250 } 251 252 253 size_t GetSize()254 GetSize() const 255 { 256 return m_items.size(); 257 } 258 259 ObjectSP 260 operator[](size_t idx) 261 { 262 if (idx < m_items.size()) 263 return m_items[idx]; 264 return ObjectSP(); 265 } 266 267 ObjectSP GetItemAtIndex(size_t idx)268 GetItemAtIndex(size_t idx) const 269 { 270 assert(idx < GetSize()); 271 if (idx < m_items.size()) 272 return m_items[idx]; 273 return ObjectSP(); 274 } 275 276 template <class IntType> 277 bool GetItemAtIndexAsInteger(size_t idx,IntType & result)278 GetItemAtIndexAsInteger(size_t idx, IntType &result) const 279 { 280 ObjectSP value = GetItemAtIndex(idx); 281 if (auto int_value = value->GetAsInteger()) 282 { 283 result = static_cast<IntType>(int_value->GetValue()); 284 return true; 285 } 286 return false; 287 } 288 289 template <class IntType> 290 bool GetItemAtIndexAsInteger(size_t idx,IntType & result,IntType default_val)291 GetItemAtIndexAsInteger(size_t idx, IntType &result, IntType default_val) const 292 { 293 bool success = GetItemAtIndexAsInteger(idx, result); 294 if (!success) 295 result = default_val; 296 return success; 297 } 298 299 bool GetItemAtIndexAsString(size_t idx,std::string & result)300 GetItemAtIndexAsString(size_t idx, std::string &result) const 301 { 302 ObjectSP value = GetItemAtIndex(idx); 303 if (auto string_value = value->GetAsString()) 304 { 305 result = string_value->GetValue(); 306 return true; 307 } 308 return false; 309 } 310 311 bool GetItemAtIndexAsString(size_t idx,std::string & result,const std::string & default_val)312 GetItemAtIndexAsString(size_t idx, std::string &result, const std::string &default_val) const 313 { 314 bool success = GetItemAtIndexAsString(idx, result); 315 if (!success) 316 result = default_val; 317 return success; 318 } 319 320 bool GetItemAtIndexAsString(size_t idx,ConstString & result)321 GetItemAtIndexAsString(size_t idx, ConstString &result) const 322 { 323 ObjectSP value = GetItemAtIndex(idx); 324 if (!value) 325 return false; 326 if (auto string_value = value->GetAsString()) 327 { 328 result = ConstString(string_value->GetValue()); 329 return true; 330 } 331 return false; 332 } 333 334 bool GetItemAtIndexAsString(size_t idx,ConstString & result,const char * default_val)335 GetItemAtIndexAsString(size_t idx, ConstString &result, const char *default_val) const 336 { 337 bool success = GetItemAtIndexAsString(idx, result); 338 if (!success) 339 result.SetCString(default_val); 340 return success; 341 } 342 343 bool GetItemAtIndexAsDictionary(size_t idx,Dictionary * & result)344 GetItemAtIndexAsDictionary(size_t idx, Dictionary *&result) const 345 { 346 ObjectSP value = GetItemAtIndex(idx); 347 result = value->GetAsDictionary(); 348 return (result != nullptr); 349 } 350 351 bool GetItemAtIndexAsArray(size_t idx,Array * & result)352 GetItemAtIndexAsArray(size_t idx, Array *&result) const 353 { 354 ObjectSP value = GetItemAtIndex(idx); 355 result = value->GetAsArray(); 356 return (result != nullptr); 357 } 358 359 void Push(ObjectSP item)360 Push(ObjectSP item) 361 { 362 m_items.push_back(item); 363 } 364 365 void AddItem(ObjectSP item)366 AddItem(ObjectSP item) 367 { 368 m_items.push_back(item); 369 } 370 371 void Dump(Stream &s) const override; 372 373 protected: 374 typedef std::vector<ObjectSP> collection; 375 collection m_items; 376 }; 377 378 379 class Integer : public Object 380 { 381 public: 382 Integer (uint64_t i = 0) : Object(Type::eTypeInteger)383 Object (Type::eTypeInteger), 384 m_value (i) 385 { 386 } 387 ~Integer()388 virtual ~Integer() 389 { 390 } 391 392 void SetValue(uint64_t value)393 SetValue (uint64_t value) 394 { 395 m_value = value; 396 } 397 398 uint64_t GetValue()399 GetValue () 400 { 401 return m_value; 402 } 403 404 void Dump(Stream &s) const override; 405 406 protected: 407 uint64_t m_value; 408 }; 409 410 class Float : public Object 411 { 412 public: 413 Float (double d = 0.0) : Object(Type::eTypeFloat)414 Object (Type::eTypeFloat), 415 m_value (d) 416 { 417 } 418 ~Float()419 virtual ~Float() 420 { 421 } 422 423 void SetValue(double value)424 SetValue (double value) 425 { 426 m_value = value; 427 } 428 429 double GetValue()430 GetValue () 431 { 432 return m_value; 433 } 434 435 void Dump(Stream &s) const override; 436 437 protected: 438 double m_value; 439 }; 440 441 class Boolean : public Object 442 { 443 public: 444 Boolean (bool b = false) : Object(Type::eTypeBoolean)445 Object (Type::eTypeBoolean), 446 m_value (b) 447 { 448 } 449 ~Boolean()450 virtual ~Boolean() 451 { 452 } 453 454 void SetValue(bool value)455 SetValue (bool value) 456 { 457 m_value = value; 458 } 459 460 bool GetValue()461 GetValue () 462 { 463 return m_value; 464 } 465 466 void Dump(Stream &s) const override; 467 468 protected: 469 bool m_value; 470 }; 471 472 473 474 class String : public Object 475 { 476 public: 477 String (const char *cstr = NULL) : Object(Type::eTypeString)478 Object (Type::eTypeString), 479 m_value () 480 { 481 if (cstr) 482 m_value = cstr; 483 } 484 String(const std::string & s)485 String (const std::string &s) : 486 Object (Type::eTypeString), 487 m_value (s) 488 { 489 } 490 String(const std::string && s)491 String (const std::string &&s) : 492 Object (Type::eTypeString), 493 m_value (s) 494 { 495 } 496 497 void SetValue(const std::string & string)498 SetValue (const std::string &string) 499 { 500 m_value = string; 501 } 502 503 const std::string & GetValue()504 GetValue () 505 { 506 return m_value; 507 } 508 509 void Dump(Stream &s) const override; 510 511 protected: 512 std::string m_value; 513 }; 514 515 class Dictionary : public Object 516 { 517 public: 518 Dictionary()519 Dictionary () : 520 Object (Type::eTypeDictionary), 521 m_dict () 522 { 523 } 524 ~Dictionary()525 virtual ~Dictionary() 526 { 527 } 528 529 size_t GetSize()530 GetSize() const 531 { 532 return m_dict.size(); 533 } 534 535 void ForEach(std::function<bool (ConstString key,Object * object)> const & callback)536 ForEach (std::function <bool(ConstString key, Object* object)> const &callback) const 537 { 538 for (const auto &pair : m_dict) 539 { 540 if (callback (pair.first, pair.second.get()) == false) 541 break; 542 } 543 } 544 545 ObjectSP GetKeys()546 GetKeys() const 547 { 548 ObjectSP object_sp(new Array ()); 549 Array *array = object_sp->GetAsArray(); 550 collection::const_iterator iter; 551 for (iter = m_dict.begin(); iter != m_dict.end(); ++iter) 552 { 553 ObjectSP key_object_sp(new String()); 554 key_object_sp->GetAsString()->SetValue(iter->first.AsCString()); 555 array->Push(key_object_sp); 556 } 557 return object_sp; 558 } 559 560 ObjectSP GetValueForKey(llvm::StringRef key)561 GetValueForKey(llvm::StringRef key) const 562 { 563 ObjectSP value_sp; 564 if (!key.empty()) 565 { 566 ConstString key_cs(key); 567 for (collection::const_iterator iter = m_dict.begin(); iter != m_dict.end(); ++iter) 568 { 569 if (key_cs == iter->first) 570 { 571 value_sp = iter->second; 572 break; 573 } 574 } 575 } 576 return value_sp; 577 } 578 579 template <class IntType> 580 bool GetValueForKeyAsInteger(llvm::StringRef key,IntType & result)581 GetValueForKeyAsInteger(llvm::StringRef key, IntType &result) const 582 { 583 ObjectSP value = GetValueForKey(key); 584 if (!value) 585 return false; 586 if (auto int_value = value->GetAsInteger()) 587 { 588 result = static_cast<IntType>(int_value->GetValue()); 589 return true; 590 } 591 return false; 592 } 593 594 template <class IntType> 595 bool GetValueForKeyAsInteger(llvm::StringRef key,IntType & result,IntType default_val)596 GetValueForKeyAsInteger(llvm::StringRef key, IntType &result, IntType default_val) const 597 { 598 bool success = GetValueForKeyAsInteger<IntType>(key, result); 599 if (!success) 600 result = default_val; 601 return success; 602 } 603 604 bool GetValueForKeyAsString(llvm::StringRef key,std::string & result)605 GetValueForKeyAsString(llvm::StringRef key, std::string &result) const 606 { 607 ObjectSP value = GetValueForKey(key); 608 if (!value) 609 return false; 610 if (auto string_value = value->GetAsString()) 611 { 612 result = string_value->GetValue(); 613 return true; 614 } 615 return false; 616 } 617 618 bool GetValueForKeyAsString(llvm::StringRef key,std::string & result,const char * default_val)619 GetValueForKeyAsString(llvm::StringRef key, std::string &result, const char *default_val) const 620 { 621 bool success = GetValueForKeyAsString(key, result); 622 if (!success) 623 { 624 if (default_val) 625 result = default_val; 626 else 627 result.clear(); 628 } 629 return success; 630 } 631 632 bool GetValueForKeyAsString(llvm::StringRef key,ConstString & result)633 GetValueForKeyAsString(llvm::StringRef key, ConstString &result) const 634 { 635 ObjectSP value = GetValueForKey(key); 636 if (!value) 637 return false; 638 if (auto string_value = value->GetAsString()) 639 { 640 result = ConstString(string_value->GetValue()); 641 return true; 642 } 643 return false; 644 } 645 646 bool GetValueForKeyAsString(llvm::StringRef key,ConstString & result,const char * default_val)647 GetValueForKeyAsString(llvm::StringRef key, ConstString &result, const char *default_val) const 648 { 649 bool success = GetValueForKeyAsString(key, result); 650 if (!success) 651 result.SetCString(default_val); 652 return success; 653 } 654 655 bool GetValueForKeyAsDictionary(llvm::StringRef key,Dictionary * & result)656 GetValueForKeyAsDictionary(llvm::StringRef key, Dictionary *&result) const 657 { 658 result = nullptr; 659 ObjectSP value = GetValueForKey(key); 660 if (!value) 661 return false; 662 result = value->GetAsDictionary(); 663 return true; 664 } 665 666 bool GetValueForKeyAsArray(llvm::StringRef key,Array * & result)667 GetValueForKeyAsArray(llvm::StringRef key, Array *&result) const 668 { 669 result = nullptr; 670 ObjectSP value = GetValueForKey(key); 671 if (!value) 672 return false; 673 result = value->GetAsArray(); 674 return true; 675 } 676 677 bool HasKey(llvm::StringRef key)678 HasKey(llvm::StringRef key) const 679 { 680 ConstString key_cs(key); 681 collection::const_iterator search = m_dict.find(key_cs); 682 return search != m_dict.end(); 683 } 684 685 void AddItem(llvm::StringRef key,ObjectSP value)686 AddItem (llvm::StringRef key, ObjectSP value) 687 { 688 ConstString key_cs(key); 689 m_dict[key_cs] = value; 690 } 691 692 void AddIntegerItem(llvm::StringRef key,uint64_t value)693 AddIntegerItem (llvm::StringRef key, uint64_t value) 694 { 695 AddItem (key, ObjectSP (new Integer(value))); 696 } 697 698 void AddFloatItem(llvm::StringRef key,double value)699 AddFloatItem (llvm::StringRef key, double value) 700 { 701 AddItem (key, ObjectSP (new Float(value))); 702 } 703 704 void AddStringItem(llvm::StringRef key,std::string value)705 AddStringItem (llvm::StringRef key, std::string value) 706 { 707 AddItem (key, ObjectSP (new String(std::move(value)))); 708 } 709 710 void AddBooleanItem(llvm::StringRef key,bool value)711 AddBooleanItem (llvm::StringRef key, bool value) 712 { 713 AddItem (key, ObjectSP (new Boolean(value))); 714 } 715 716 void Dump(Stream &s) const override; 717 718 protected: 719 typedef std::map<ConstString, ObjectSP> collection; 720 collection m_dict; 721 }; 722 723 class Null : public Object 724 { 725 public: Null()726 Null () : 727 Object (Type::eTypeNull) 728 { 729 } 730 ~Null()731 virtual ~Null() 732 { 733 } 734 735 bool IsValid()736 IsValid() const override 737 { 738 return false; 739 } 740 741 void Dump(Stream &s) const override; 742 743 protected: 744 }; 745 746 class Generic : public Object 747 { 748 public: 749 explicit Generic(void *object = nullptr) : Object(Type::eTypeGeneric)750 Object (Type::eTypeGeneric), 751 m_object (object) 752 { 753 } 754 755 void SetValue(void * value)756 SetValue(void *value) 757 { 758 m_object = value; 759 } 760 761 void * GetValue()762 GetValue() const 763 { 764 return m_object; 765 } 766 767 bool IsValid()768 IsValid() const override 769 { 770 return m_object != nullptr; 771 } 772 773 void Dump(Stream &s) const override; 774 775 private: 776 void *m_object; 777 }; 778 779 static ObjectSP 780 ParseJSON (std::string json_text); 781 782 }; // class StructuredData 783 784 785 } // namespace lldb_private 786 787 #endif // liblldb_StructuredData_h_ 788