Index: include/lldb/API/SBStructuredData.h =================================================================== --- include/lldb/API/SBStructuredData.h +++ include/lldb/API/SBStructuredData.h @@ -17,6 +17,16 @@ class SBStructuredData { public: + enum Type { + eTypeInvalid = -1, + eTypeArray = 0, + eTypeInteger, + eTypeFloat, + eTypeBoolean, + eTypeString, + eTypeDictionary + }; + SBStructuredData(); SBStructuredData(const lldb::SBStructuredData &rhs); @@ -37,9 +47,56 @@ lldb::SBError GetDescription(lldb::SBStream &stream) const; + //------------------------------------------------------------------ + /// Return the type of data in this data structure + //------------------------------------------------------------------ + lldb::SBStructuredData::Type GetType() const; + + //------------------------------------------------------------------ + /// Return the size (i.e. number of elements) in this data structure + /// if it is an array or dictionary type. For other types, 0 will be + // returned. + //------------------------------------------------------------------ + size_t GetSize() const; + + //------------------------------------------------------------------ + /// Return the value corresponding to a key if this data structure + /// is a dictionary type. + //------------------------------------------------------------------ + lldb::SBStructuredData GetValueForKey(const char *key) const; + + //------------------------------------------------------------------ + /// Return the value corresponding to an index if this data structure + /// is array. + //------------------------------------------------------------------ + lldb::SBStructuredData GetItemAtIndex(size_t idx) const; + + //------------------------------------------------------------------ + /// Return the integer value if this data structure is an integer type. + //------------------------------------------------------------------ + uint64_t GetIntegerValue(uint64_t fail_value = 0) const; + + //------------------------------------------------------------------ + /// Return the floating point value if this data structure is a floating + /// type. + //------------------------------------------------------------------ + double GetFloatValue(double fail_value = 0.0) const; + + //------------------------------------------------------------------ + /// Return the boolean value if this data structure is a boolean type. + //------------------------------------------------------------------ + bool GetBooleanValue(bool fail_value = false) const; + + //------------------------------------------------------------------ + /// Return the string value if this data structure is a string type. + //------------------------------------------------------------------ + size_t GetStringValue(char *dst, size_t dst_len) const; + protected: friend class SBTraceOptions; + SBStructuredData(const lldb::StructuredDataImplUP &impl_up); + StructuredDataImplUP m_impl_up; }; } Index: include/lldb/Core/StructuredDataImpl.h =================================================================== --- include/lldb/Core/StructuredDataImpl.h +++ include/lldb/Core/StructuredDataImpl.h @@ -10,6 +10,7 @@ #ifndef liblldb_StructuredDataImpl_h_ #define liblldb_StructuredDataImpl_h_ +#include "llvm/ADT/StringRef.h" #include "lldb/Core/Event.h" #include "lldb/Core/StructuredData.h" #include "lldb/Target/StructuredDataPlugin.h" @@ -86,6 +87,71 @@ m_data_sp = obj; } + StructuredData::Type GetType() const { + return (m_data_sp ? m_data_sp->GetType() + : StructuredData::Type::eTypeInvalid); + } + + size_t GetSize() const { + if (!m_data_sp) + return 0; + + if (m_data_sp->GetType() == StructuredData::Type::eTypeDictionary) { + StructuredData::Dictionary *dict = + static_cast( + m_data_sp.get()); + return (dict->GetSize()); + } else if (m_data_sp->GetType() == StructuredData::Type::eTypeArray) { + StructuredData::Array *array = + static_cast(m_data_sp.get()); + return (array->GetSize()); + } else + return 0; + } + + StructuredData::ObjectSP GetValueForKey(const char *key) const { + if (!m_data_sp || + (m_data_sp->GetType() != StructuredData::Type::eTypeDictionary)) + return StructuredData::ObjectSP(); + + StructuredData::Dictionary *dict = + static_cast( + m_data_sp.get()); + return (dict->GetValueForKey(llvm::StringRef(key))); + } + + StructuredData::ObjectSP GetItemAtIndex(size_t idx) const { + if (!m_data_sp || + (m_data_sp->GetType() != StructuredData::Type::eTypeArray)) + return StructuredData::ObjectSP(); + + StructuredData::Array *array = + static_cast(m_data_sp.get()); + return (array->GetItemAtIndex(idx)); + } + + uint64_t GetIntegerValue(uint64_t fail_value = 0) const { + return (m_data_sp ? m_data_sp->GetIntegerValue(fail_value) : fail_value); + } + + double GetFloatValue(double fail_value = 0.0) const { + return (m_data_sp ? m_data_sp->GetFloatValue(fail_value) : fail_value); + } + + bool GetBooleanValue(bool fail_value = false) const { + return (m_data_sp ? m_data_sp->GetBooleanValue(fail_value) : fail_value); + } + + size_t GetStringValue(char *dst, size_t dst_len) const { + if (!m_data_sp || !dst || !dst_len) + return 0; + + std::string result = m_data_sp->GetStringValue(); + if (result.empty()) + return 0; + return (::snprintf(dst, dst_len, "%s", result.c_str())); + } + private: lldb::StructuredDataPluginWP m_plugin_wp; Index: packages/Python/lldbsuite/test/python_api/sbstructureddata/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/python_api/sbstructureddata/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/python_api/sbstructureddata/TestStructuredDataAPI.py @@ -0,0 +1,222 @@ +""" +Test some SBStructuredData API. +""" + +from __future__ import print_function + +import os +import re +import time + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestStructuredDataAPI(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + self.structured_data_api_test() + + def setUp(self): + TestBase.setUp(self) + self.line = line_number( + 'main.c', '// Set break point at this line') + + @add_test_categories(['pyapi']) + def structured_data_api_test(self): + exe = os.path.join(os.getcwd(), "a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint inside function 'main'. + breakpoint = target.BreakpointCreateByLocation("main.c", self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + + error = lldb.SBError() + s = lldb.SBStream() + s.Print( + "{\"key_dict\":{\"key_string\":\"STRING\",\"key_int\":3,\"key_float\":2.99,\"key_bool\":true,\"key_array\":[\"23\",\"arr\"]}}") + example = lldb.SBStructuredData() + + # Check SetFromJSON API for dictionaries, integers, floating point + # values, strings and arrays + error = example.SetFromJSON(s) + if not error.Success(): + self.fail("FAILED: " + error.GetCString()) + + # Tests for invalid data type + self.invalid_struct_test(example) + + dict_struct = lldb.SBStructuredData() + dict_struct = example.GetValueForKey("key_dict") + + # Tests for dictionary data type + self.dictionary_struct_test(example) + + # Tests for string data type + self.string_struct_test(dict_struct) + + # Tests for integer data type + self.int_struct_test(dict_struct) + + # Tests for floating point data type + self.double_struct_test(dict_struct) + + # Tests for boolean data type + self.bool_struct_test(dict_struct) + + # Tests for array data type + self.array_struct_test(dict_struct) + + def invalid_struct_test(self, example): + invalid_struct = lldb.SBStructuredData() + invalid_struct = example.GetValueForKey("invalid_key") + if invalid_struct.IsValid(): + self.fail("An invalid object should have been returned") + + # Check Type API + if not invalid_struct.GetType() == lldb.SBStructuredData.eTypeInvalid: + self.fail("Wrong type returned: " + str(invalid_struct.GetType())) + + def dictionary_struct_test(self, example): + # Check API returning a valid SBStructuredData of 'dictionary' type + dict_struct = lldb.SBStructuredData() + dict_struct = example.GetValueForKey("key_dict") + if not dict_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not dict_struct.GetType() == lldb.SBStructuredData.eTypeDictionary: + self.fail("Wrong type returned: " + str(dict_struct.GetType())) + + # Check Size API for 'dictionary' type + if not dict_struct.GetSize() == 5: + self.fail("Wrong no of elements returned: " + + str(dict_struct.GetSize())) + + def string_struct_test(self, dict_struct): + string_struct = lldb.SBStructuredData() + string_struct = dict_struct.GetValueForKey("key_string") + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not string_struct.GetType() == lldb.SBStructuredData.eTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + + # Check API returning 'string' value + output = string_struct.GetStringValue(25) + if not "STRING" in output: + self.fail("wrong output: " + output) + + # Calling wrong API on a SBStructuredData + # (e.g. getting an integer from a string type structure) + output = string_struct.GetIntegerValue() + if output: + self.fail( + "Valid integer value " + + str(output) + + " returned for a string object") + + def int_struct_test(self, dict_struct): + # Check a valid SBStructuredData containing an 'integer' by + int_struct = lldb.SBStructuredData() + int_struct = dict_struct.GetValueForKey("key_int") + if not int_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not int_struct.GetType() == lldb.SBStructuredData.eTypeInteger: + self.fail("Wrong type returned: " + str(int_struct.GetType())) + + # Check API returning 'integer' value + output = int_struct.GetIntegerValue() + if not output == 3: + self.fail("wrong output: " + str(output)) + + # Calling wrong API on a SBStructuredData + # (e.g. getting a string value from an integer type structure) + output = int_struct.GetStringValue(25) + if output: + self.fail( + "Valid string " + + output + + " returned for an integer object") + + def double_struct_test(self, dict_struct): + floating_point_struct = lldb.SBStructuredData() + floating_point_struct = dict_struct.GetValueForKey("key_float") + if not floating_point_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not floating_point_struct.GetType() == lldb.SBStructuredData.eTypeFloat: + self.fail("Wrong type returned: " + + str(floating_point_struct.GetType())) + + # Check API returning 'double' value + output = floating_point_struct.GetFloatValue() + if not output == 2.99: + self.fail("wrong output: " + str(output)) + + def bool_struct_test(self, dict_struct): + bool_struct = lldb.SBStructuredData() + bool_struct = dict_struct.GetValueForKey("key_bool") + if not bool_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not bool_struct.GetType() == lldb.SBStructuredData.eTypeBoolean: + self.fail("Wrong type returned: " + str(bool_struct.GetType())) + + # Check API returning 'bool' value + output = bool_struct.GetBooleanValue() + if not output: + self.fail("wrong output: " + str(output)) + + def array_struct_test(self, dict_struct): + # Check API returning a valid SBStructuredData of 'array' type + array_struct = lldb.SBStructuredData() + array_struct = dict_struct.GetValueForKey("key_array") + if not array_struct.IsValid(): + self.fail("A valid object should have been returned") + + # Check Type API + if not array_struct.GetType() == lldb.SBStructuredData.eTypeArray: + self.fail("Wrong type returned: " + str(array_struct.GetType())) + + # Check Size API for 'array' type + if not array_struct.GetSize() == 2: + self.fail("Wrong no of elements returned: " + + str(array_struct.GetSize())) + + # Check API returning a valid SBStructuredData for different 'array' + # indices + string_struct = array_struct.GetItemAtIndex(0) + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + if not string_struct.GetType() == lldb.SBStructuredData.eTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + output = string_struct.GetStringValue(5) + if not output == "23": + self.fail("wrong output: " + str(output)) + + string_struct = array_struct.GetItemAtIndex(1) + if not string_struct.IsValid(): + self.fail("A valid object should have been returned") + if not string_struct.GetType() == lldb.SBStructuredData.eTypeString: + self.fail("Wrong type returned: " + str(string_struct.GetType())) + output = string_struct.GetStringValue(5) + if not output == "arr": + self.fail("wrong output: " + str(output)) Index: packages/Python/lldbsuite/test/python_api/sbstructureddata/main.c =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/python_api/sbstructureddata/main.c @@ -0,0 +1,15 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#include + +int main (int argc, char const *argv[]) +{ + uint32_t a = 0xE0A35F10; // Set break point at this line. + return 0; +} Index: scripts/interface/SBStructuredData.i =================================================================== --- scripts/interface/SBStructuredData.i +++ scripts/interface/SBStructuredData.i @@ -18,21 +18,49 @@ class SBStructuredData { public: - + + enum Type { + eTypeInvalid = -1, + eTypeArray = 0, + eTypeInteger, + eTypeFloat, + eTypeBoolean, + eTypeString, + eTypeDictionary + }; + SBStructuredData(); - + SBStructuredData(const lldb::SBStructuredData &rhs); SBStructuredData(const lldb::EventSP &event_sp); ~SBStructuredData(); - + bool IsValid() const; - + void Clear(); + lldb::SBStructuredData &operator=(const lldb::SBStructuredData &rhs); + + lldb::SBStructuredData::Type GetType() const; + + size_t GetSize() const; + + lldb::SBStructuredData GetValueForKey(const char *key) const; + + lldb::SBStructuredData GetItemAtIndex(size_t idx) const; + + uint64_t GetIntegerValue(uint64_t fail_value = 0) const; + + double GetFloatValue(double fail_value = 0.0) const; + + bool GetBooleanValue(bool fail_value = false) const; + + size_t GetStringValue(char *dst, size_t dst_len) const; + lldb::SBError GetAsJSON(lldb::SBStream &stream) const; Index: source/API/SBStructuredData.cpp =================================================================== --- source/API/SBStructuredData.cpp +++ source/API/SBStructuredData.cpp @@ -31,6 +31,9 @@ SBStructuredData::SBStructuredData(const lldb::EventSP &event_sp) : m_impl_up(new StructuredDataImpl(event_sp)) {} +SBStructuredData::SBStructuredData(const lldb::StructuredDataImplUP &impl_up) + : m_impl_up(new StructuredDataImpl(*(impl_up.get()))) {} + SBStructuredData::~SBStructuredData() {} SBStructuredData &SBStructuredData:: @@ -67,3 +70,73 @@ sb_error.SetError(error); return sb_error; } + +lldb::SBStructuredData::Type SBStructuredData::GetType() const { + if (!m_impl_up) + return SBStructuredData::Type::eTypeInvalid; + + StructuredData::Type type = m_impl_up->GetType(); + SBStructuredData::Type result = SBStructuredData::Type::eTypeInvalid; + + switch (type) { + case StructuredData::Type::eTypeArray: + result = SBStructuredData::Type::eTypeArray; + break; + case StructuredData::Type::eTypeInteger: + result = SBStructuredData::Type::eTypeInteger; + break; + case StructuredData::Type::eTypeFloat: + result = SBStructuredData::Type::eTypeFloat; + break; + case StructuredData::Type::eTypeBoolean: + result = SBStructuredData::Type::eTypeBoolean; + break; + case StructuredData::Type::eTypeString: + result = SBStructuredData::Type::eTypeString; + break; + case StructuredData::Type::eTypeDictionary: + result = SBStructuredData::Type::eTypeDictionary; + break; + default: + break; + } + return result; +} + +size_t SBStructuredData::GetSize() const { + return (m_impl_up ? m_impl_up->GetSize() : 0); +} + +lldb::SBStructuredData SBStructuredData::GetValueForKey(const char *key) const { + if (!m_impl_up) + return SBStructuredData(); + + StructuredDataImplUP impl_up(new StructuredDataImpl()); + impl_up->SetObjectSP(m_impl_up->GetValueForKey(key)); + return lldb::SBStructuredData(impl_up); +} + +lldb::SBStructuredData SBStructuredData::GetItemAtIndex(size_t idx) const { + if (!m_impl_up) + return SBStructuredData(); + + StructuredDataImplUP impl_up(new StructuredDataImpl()); + impl_up->SetObjectSP(m_impl_up->GetItemAtIndex(idx)); + return lldb::SBStructuredData(impl_up); +} + +uint64_t SBStructuredData::GetIntegerValue(uint64_t fail_value) const { + return (m_impl_up ? m_impl_up->GetIntegerValue(fail_value) : fail_value); +} + +double SBStructuredData::GetFloatValue(double fail_value) const { + return (m_impl_up ? m_impl_up->GetFloatValue(fail_value) : fail_value); +} + +bool SBStructuredData::GetBooleanValue(bool fail_value) const { + return (m_impl_up ? m_impl_up->GetBooleanValue(fail_value) : fail_value); +} + +size_t SBStructuredData::GetStringValue(char *dst, size_t dst_len) const { + return (m_impl_up ? m_impl_up->GetStringValue(dst, dst_len) : 0); +}