| //===-- FormatClasses.h -----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef lldb_FormatClasses_h_ |
| #define lldb_FormatClasses_h_ |
| |
| // C Includes |
| #include <stdint.h> |
| #include <unistd.h> |
| |
| // C++ Includes |
| #include <string> |
| #include <vector> |
| |
| // Other libraries and framework includes |
| |
| // Project includes |
| #include "lldb/lldb-public.h" |
| #include "lldb/lldb-enumerations.h" |
| |
| #include "lldb/Core/ValueObject.h" |
| #include "lldb/Interpreter/ScriptInterpreterPython.h" |
| #include "lldb/Symbol/Type.h" |
| |
| namespace lldb_private { |
| |
| class TypeFormatImpl |
| { |
| public: |
| class Flags |
| { |
| public: |
| |
| Flags () : |
| m_flags (lldb::eTypeOptionCascade) |
| {} |
| |
| Flags (const Flags& other) : |
| m_flags (other.m_flags) |
| {} |
| |
| Flags (uint32_t value) : |
| m_flags (value) |
| {} |
| |
| Flags& |
| operator = (const Flags& rhs) |
| { |
| if (&rhs != this) |
| m_flags = rhs.m_flags; |
| |
| return *this; |
| } |
| |
| Flags& |
| operator = (const uint32_t& rhs) |
| { |
| m_flags = rhs; |
| return *this; |
| } |
| |
| Flags& |
| Clear() |
| { |
| m_flags = 0; |
| return *this; |
| } |
| |
| bool |
| GetCascades () const |
| { |
| return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; |
| } |
| |
| Flags& |
| SetCascades (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionCascade; |
| else |
| m_flags &= ~lldb::eTypeOptionCascade; |
| return *this; |
| } |
| |
| bool |
| GetSkipPointers () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; |
| } |
| |
| Flags& |
| SetSkipPointers (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipPointers; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipPointers; |
| return *this; |
| } |
| |
| bool |
| GetSkipReferences () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; |
| } |
| |
| Flags& |
| SetSkipReferences (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipReferences; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipReferences; |
| return *this; |
| } |
| |
| uint32_t |
| GetValue () |
| { |
| return m_flags; |
| } |
| |
| void |
| SetValue (uint32_t value) |
| { |
| m_flags = value; |
| } |
| |
| private: |
| uint32_t m_flags; |
| }; |
| |
| TypeFormatImpl (lldb::Format f = lldb::eFormatInvalid, |
| const Flags& flags = Flags()); |
| |
| typedef STD_SHARED_PTR(TypeFormatImpl) SharedPointer; |
| typedef bool(*ValueCallback)(void*, ConstString, const lldb::TypeFormatImplSP&); |
| |
| ~TypeFormatImpl () |
| { |
| } |
| |
| bool |
| Cascades () const |
| { |
| return m_flags.GetCascades(); |
| } |
| bool |
| SkipsPointers () const |
| { |
| return m_flags.GetSkipPointers(); |
| } |
| bool |
| SkipsReferences () const |
| { |
| return m_flags.GetSkipReferences(); |
| } |
| |
| void |
| SetCascades (bool value) |
| { |
| m_flags.SetCascades(value); |
| } |
| |
| void |
| SetSkipsPointers (bool value) |
| { |
| m_flags.SetSkipPointers(value); |
| } |
| |
| void |
| SetSkipsReferences (bool value) |
| { |
| m_flags.SetSkipReferences(value); |
| } |
| |
| lldb::Format |
| GetFormat () const |
| { |
| return m_format; |
| } |
| |
| void |
| SetFormat (lldb::Format fmt) |
| { |
| m_format = fmt; |
| } |
| |
| uint32_t |
| GetOptions () |
| { |
| return m_flags.GetValue(); |
| } |
| |
| void |
| SetOptions (uint32_t value) |
| { |
| m_flags.SetValue(value); |
| } |
| |
| uint32_t& |
| GetRevision () |
| { |
| return m_my_revision; |
| } |
| |
| std::string |
| GetDescription(); |
| |
| protected: |
| Flags m_flags; |
| lldb::Format m_format; |
| uint32_t m_my_revision; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TypeFormatImpl); |
| }; |
| |
| class SyntheticChildrenFrontEnd |
| { |
| protected: |
| ValueObject &m_backend; |
| public: |
| |
| SyntheticChildrenFrontEnd(ValueObject &backend) : |
| m_backend(backend) |
| {} |
| |
| virtual |
| ~SyntheticChildrenFrontEnd() |
| { |
| } |
| |
| virtual uint32_t |
| CalculateNumChildren() = 0; |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex (uint32_t idx, bool can_create) = 0; |
| |
| virtual uint32_t |
| GetIndexOfChildWithName (const ConstString &name) = 0; |
| |
| // this function is assumed to always succeed and it if fails, the front-end should know to deal |
| // with it in the correct way (most probably, by refusing to return any children) |
| // the return value of Update() should actually be interpreted as "ValueObjectSyntheticFilter cache is good/bad" |
| // if =true, ValueObjectSyntheticFilter is allowed to use the children it fetched previously and cached |
| // if =false, ValueObjectSyntheticFilter must throw away its cache, and query again for children |
| virtual bool |
| Update() = 0; |
| |
| typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; |
| typedef std::auto_ptr<SyntheticChildrenFrontEnd> AutoPointer; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyntheticChildrenFrontEnd); |
| }; |
| |
| class SyntheticChildren |
| { |
| public: |
| |
| class Flags |
| { |
| public: |
| |
| Flags () : |
| m_flags (lldb::eTypeOptionCascade) |
| {} |
| |
| Flags (const Flags& other) : |
| m_flags (other.m_flags) |
| {} |
| |
| Flags (uint32_t value) : |
| m_flags (value) |
| {} |
| |
| Flags& |
| operator = (const Flags& rhs) |
| { |
| if (&rhs != this) |
| m_flags = rhs.m_flags; |
| |
| return *this; |
| } |
| |
| Flags& |
| operator = (const uint32_t& rhs) |
| { |
| m_flags = rhs; |
| return *this; |
| } |
| |
| Flags& |
| Clear() |
| { |
| m_flags = 0; |
| return *this; |
| } |
| |
| bool |
| GetCascades () const |
| { |
| return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; |
| } |
| |
| Flags& |
| SetCascades (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionCascade; |
| else |
| m_flags &= ~lldb::eTypeOptionCascade; |
| return *this; |
| } |
| |
| bool |
| GetSkipPointers () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; |
| } |
| |
| Flags& |
| SetSkipPointers (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipPointers; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipPointers; |
| return *this; |
| } |
| |
| bool |
| GetSkipReferences () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; |
| } |
| |
| Flags& |
| SetSkipReferences (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipReferences; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipReferences; |
| return *this; |
| } |
| |
| uint32_t |
| GetValue () |
| { |
| return m_flags; |
| } |
| |
| void |
| SetValue (uint32_t value) |
| { |
| m_flags = value; |
| } |
| |
| private: |
| uint32_t m_flags; |
| }; |
| |
| SyntheticChildren (const Flags& flags) : |
| m_flags(flags) |
| { |
| } |
| |
| virtual |
| ~SyntheticChildren () |
| { |
| } |
| |
| bool |
| Cascades () const |
| { |
| return m_flags.GetCascades(); |
| } |
| bool |
| SkipsPointers () const |
| { |
| return m_flags.GetSkipPointers(); |
| } |
| bool |
| SkipsReferences () const |
| { |
| return m_flags.GetSkipReferences(); |
| } |
| |
| void |
| SetCascades (bool value) |
| { |
| m_flags.SetCascades(value); |
| } |
| |
| void |
| SetSkipsPointers (bool value) |
| { |
| m_flags.SetSkipPointers(value); |
| } |
| |
| void |
| SetSkipsReferences (bool value) |
| { |
| m_flags.SetSkipReferences(value); |
| } |
| |
| uint32_t |
| GetOptions () |
| { |
| return m_flags.GetValue(); |
| } |
| |
| void |
| SetOptions (uint32_t value) |
| { |
| m_flags.SetValue(value); |
| } |
| |
| virtual bool |
| IsScripted () = 0; |
| |
| virtual std::string |
| GetDescription () = 0; |
| |
| virtual SyntheticChildrenFrontEnd::AutoPointer |
| GetFrontEnd (ValueObject &backend) = 0; |
| |
| typedef STD_SHARED_PTR(SyntheticChildren) SharedPointer; |
| typedef bool(*SyntheticChildrenCallback)(void*, ConstString, const SyntheticChildren::SharedPointer&); |
| |
| uint32_t& |
| GetRevision () |
| { |
| return m_my_revision; |
| } |
| |
| protected: |
| uint32_t m_my_revision; |
| Flags m_flags; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyntheticChildren); |
| }; |
| |
| class TypeFilterImpl : public SyntheticChildren |
| { |
| std::vector<std::string> m_expression_paths; |
| public: |
| TypeFilterImpl(const SyntheticChildren::Flags& flags) : |
| SyntheticChildren(flags), |
| m_expression_paths() |
| { |
| } |
| |
| void |
| AddExpressionPath (const char* path) |
| { |
| AddExpressionPath(std::string(path)); |
| } |
| |
| void |
| Clear() |
| { |
| m_expression_paths.clear(); |
| } |
| |
| int |
| GetCount() const |
| { |
| return m_expression_paths.size(); |
| } |
| |
| const char* |
| GetExpressionPathAtIndex(int i) const |
| { |
| return m_expression_paths[i].c_str(); |
| } |
| |
| bool |
| SetExpressionPathAtIndex (int i, const char* path) |
| { |
| return SetExpressionPathAtIndex(i, std::string(path)); |
| } |
| |
| void |
| AddExpressionPath (std::string path) |
| { |
| bool need_add_dot = true; |
| if (path[0] == '.' || |
| (path[0] == '-' && path[1] == '>') || |
| path[0] == '[') |
| need_add_dot = false; |
| // add a '.' symbol to help forgetful users |
| if(!need_add_dot) |
| m_expression_paths.push_back(path); |
| else |
| m_expression_paths.push_back(std::string(".") + path); |
| } |
| |
| bool |
| SetExpressionPathAtIndex (int i, std::string path) |
| { |
| if (i >= GetCount()) |
| return false; |
| bool need_add_dot = true; |
| if (path[0] == '.' || |
| (path[0] == '-' && path[1] == '>') || |
| path[0] == '[') |
| need_add_dot = false; |
| // add a '.' symbol to help forgetful users |
| if(!need_add_dot) |
| m_expression_paths[i] = path; |
| else |
| m_expression_paths[i] = std::string(".") + path; |
| return true; |
| } |
| |
| bool |
| IsScripted() |
| { |
| return false; |
| } |
| |
| std::string |
| GetDescription(); |
| |
| class FrontEnd : public SyntheticChildrenFrontEnd |
| { |
| private: |
| TypeFilterImpl* filter; |
| public: |
| |
| FrontEnd(TypeFilterImpl* flt, |
| ValueObject &backend) : |
| SyntheticChildrenFrontEnd(backend), |
| filter(flt) |
| {} |
| |
| virtual |
| ~FrontEnd() |
| { |
| } |
| |
| virtual uint32_t |
| CalculateNumChildren() |
| { |
| return filter->GetCount(); |
| } |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex (uint32_t idx, bool can_create) |
| { |
| if (idx >= filter->GetCount()) |
| return lldb::ValueObjectSP(); |
| return m_backend.GetSyntheticExpressionPathChild(filter->GetExpressionPathAtIndex(idx), can_create); |
| } |
| |
| virtual bool |
| Update() { return false; } |
| |
| virtual uint32_t |
| GetIndexOfChildWithName (const ConstString &name) |
| { |
| const char* name_cstr = name.GetCString(); |
| for (int i = 0; i < filter->GetCount(); i++) |
| { |
| const char* expr_cstr = filter->GetExpressionPathAtIndex(i); |
| if (expr_cstr) |
| { |
| if (*expr_cstr == '.') |
| expr_cstr++; |
| else if (*expr_cstr == '-' && *(expr_cstr+1) == '>') |
| expr_cstr += 2; |
| } |
| if (!::strcmp(name_cstr, expr_cstr)) |
| return i; |
| } |
| return UINT32_MAX; |
| } |
| |
| typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FrontEnd); |
| }; |
| |
| virtual SyntheticChildrenFrontEnd::AutoPointer |
| GetFrontEnd(ValueObject &backend) |
| { |
| return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TypeFilterImpl); |
| }; |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| |
| class TypeSyntheticImpl : public SyntheticChildren |
| { |
| std::string m_python_class; |
| std::string m_python_code; |
| public: |
| |
| TypeSyntheticImpl(const SyntheticChildren::Flags& flags, |
| const char* pclass, |
| const char* pcode = NULL) : |
| SyntheticChildren(flags), |
| m_python_class(), |
| m_python_code() |
| { |
| if (pclass) |
| m_python_class = pclass; |
| if (pcode) |
| m_python_code = pcode; |
| } |
| |
| const char* |
| GetPythonClassName() |
| { |
| return m_python_class.c_str(); |
| } |
| |
| const char* |
| GetPythonCode() |
| { |
| return m_python_code.c_str(); |
| } |
| |
| void |
| SetPythonClassName (const char* fname) |
| { |
| m_python_class.assign(fname); |
| m_python_code.clear(); |
| } |
| |
| void |
| SetPythonCode (const char* script) |
| { |
| m_python_code.assign(script); |
| } |
| |
| std::string |
| GetDescription(); |
| |
| bool |
| IsScripted() |
| { |
| return true; |
| } |
| |
| class FrontEnd : public SyntheticChildrenFrontEnd |
| { |
| private: |
| std::string m_python_class; |
| lldb::ScriptInterpreterObjectSP m_wrapper_sp; |
| ScriptInterpreter *m_interpreter; |
| public: |
| |
| FrontEnd(std::string pclass, |
| ValueObject &backend); |
| |
| virtual |
| ~FrontEnd(); |
| |
| virtual uint32_t |
| CalculateNumChildren() |
| { |
| if (!m_wrapper_sp || m_interpreter == NULL) |
| return 0; |
| return m_interpreter->CalculateNumChildren(m_wrapper_sp); |
| } |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex (uint32_t idx, bool can_create); |
| |
| virtual bool |
| Update() |
| { |
| if (!m_wrapper_sp || m_interpreter == NULL) |
| return false; |
| |
| return m_interpreter->UpdateSynthProviderInstance(m_wrapper_sp); |
| } |
| |
| virtual uint32_t |
| GetIndexOfChildWithName (const ConstString &name) |
| { |
| if (!m_wrapper_sp || m_interpreter == NULL) |
| return UINT32_MAX; |
| return m_interpreter->GetIndexOfChildWithName(m_wrapper_sp, name.GetCString()); |
| } |
| |
| typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FrontEnd); |
| }; |
| |
| virtual SyntheticChildrenFrontEnd::AutoPointer |
| GetFrontEnd(ValueObject &backend) |
| { |
| return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(m_python_class, backend)); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TypeSyntheticImpl); |
| }; |
| |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| class SyntheticArrayView : public SyntheticChildren |
| { |
| public: |
| |
| struct SyntheticArrayRange |
| { |
| private: |
| int m_low; |
| int m_high; |
| SyntheticArrayRange* m_next; |
| |
| public: |
| |
| SyntheticArrayRange () : |
| m_low(-1), |
| m_high(-2), |
| m_next(NULL) |
| {} |
| |
| SyntheticArrayRange (int L) : |
| m_low(L), |
| m_high(L), |
| m_next(NULL) |
| {} |
| |
| SyntheticArrayRange (int L, int H) : |
| m_low(L), |
| m_high(H), |
| m_next(NULL) |
| {} |
| |
| SyntheticArrayRange (int L, int H, SyntheticArrayRange* N) : |
| m_low(L), |
| m_high(H), |
| m_next(N) |
| {} |
| |
| inline int |
| GetLow () |
| { |
| return m_low; |
| } |
| |
| inline int |
| GetHigh () |
| { |
| return m_high; |
| } |
| |
| inline void |
| SetLow (int L) |
| { |
| m_low = L; |
| } |
| |
| inline void |
| SetHigh (int H) |
| { |
| m_high = H; |
| } |
| |
| inline int |
| GetSelfCount() |
| { |
| return GetHigh() - GetLow() + 1; |
| } |
| |
| int |
| GetCount() |
| { |
| int count = GetSelfCount(); |
| if (m_next) |
| count += m_next->GetCount(); |
| return count; |
| } |
| |
| inline SyntheticArrayRange* |
| GetNext() |
| { |
| return m_next; |
| } |
| |
| void |
| SetNext(SyntheticArrayRange* N) |
| { |
| if (m_next) |
| delete m_next; |
| m_next = N; |
| } |
| |
| void |
| SetNext(int L, int H) |
| { |
| if (m_next) |
| delete m_next; |
| m_next = new SyntheticArrayRange(L, H); |
| } |
| |
| void |
| SetNext(int L) |
| { |
| if (m_next) |
| delete m_next; |
| m_next = new SyntheticArrayRange(L); |
| } |
| |
| ~SyntheticArrayRange() |
| { |
| delete m_next; |
| m_next = NULL; |
| } |
| |
| }; |
| |
| SyntheticArrayView(const SyntheticChildren::Flags& flags) : |
| SyntheticChildren(flags), |
| m_head(), |
| m_tail(&m_head) |
| { |
| } |
| |
| void |
| AddRange(int L, int H) |
| { |
| m_tail->SetLow(L); |
| m_tail->SetHigh(H); |
| m_tail->SetNext(new SyntheticArrayRange()); |
| m_tail = m_tail->GetNext(); |
| } |
| |
| int |
| GetCount() |
| { |
| return m_head.GetCount(); |
| } |
| |
| int |
| GetRealIndexForIndex(int i); |
| |
| bool |
| IsScripted() |
| { |
| return false; |
| } |
| |
| std::string |
| GetDescription(); |
| |
| class FrontEnd : public SyntheticChildrenFrontEnd |
| { |
| private: |
| SyntheticArrayView* filter; |
| public: |
| |
| FrontEnd(SyntheticArrayView* flt, |
| ValueObject &backend) : |
| SyntheticChildrenFrontEnd(backend), |
| filter(flt) |
| {} |
| |
| virtual |
| ~FrontEnd() |
| { |
| } |
| |
| virtual uint32_t |
| CalculateNumChildren() |
| { |
| return filter->GetCount(); |
| } |
| |
| virtual lldb::ValueObjectSP |
| GetChildAtIndex (uint32_t idx, bool can_create) |
| { |
| if (idx >= filter->GetCount()) |
| return lldb::ValueObjectSP(); |
| return m_backend.GetSyntheticArrayMember(filter->GetRealIndexForIndex(idx), can_create); |
| } |
| |
| virtual bool |
| Update() { return false; } |
| |
| virtual uint32_t |
| GetIndexOfChildWithName (const ConstString &name_cs); |
| |
| typedef STD_SHARED_PTR(SyntheticChildrenFrontEnd) SharedPointer; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(FrontEnd); |
| }; |
| |
| virtual SyntheticChildrenFrontEnd::AutoPointer |
| GetFrontEnd(ValueObject &backend) |
| { |
| return SyntheticChildrenFrontEnd::AutoPointer(new FrontEnd(this, backend)); |
| } |
| private: |
| SyntheticArrayRange m_head; |
| SyntheticArrayRange *m_tail; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SyntheticArrayView); |
| }; |
| |
| |
| class TypeSummaryImpl |
| { |
| public: |
| class Flags |
| { |
| public: |
| |
| Flags () : |
| m_flags (lldb::eTypeOptionCascade) |
| {} |
| |
| Flags (const Flags& other) : |
| m_flags (other.m_flags) |
| {} |
| |
| Flags (uint32_t value) : |
| m_flags (value) |
| {} |
| |
| Flags& |
| operator = (const Flags& rhs) |
| { |
| if (&rhs != this) |
| m_flags = rhs.m_flags; |
| |
| return *this; |
| } |
| |
| Flags& |
| operator = (const uint32_t& rhs) |
| { |
| m_flags = rhs; |
| return *this; |
| } |
| |
| Flags& |
| Clear() |
| { |
| m_flags = 0; |
| return *this; |
| } |
| |
| bool |
| GetCascades () const |
| { |
| return (m_flags & lldb::eTypeOptionCascade) == lldb::eTypeOptionCascade; |
| } |
| |
| Flags& |
| SetCascades (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionCascade; |
| else |
| m_flags &= ~lldb::eTypeOptionCascade; |
| return *this; |
| } |
| |
| bool |
| GetSkipPointers () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipPointers) == lldb::eTypeOptionSkipPointers; |
| } |
| |
| Flags& |
| SetSkipPointers (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipPointers; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipPointers; |
| return *this; |
| } |
| |
| bool |
| GetSkipReferences () const |
| { |
| return (m_flags & lldb::eTypeOptionSkipReferences) == lldb::eTypeOptionSkipReferences; |
| } |
| |
| Flags& |
| SetSkipReferences (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionSkipReferences; |
| else |
| m_flags &= ~lldb::eTypeOptionSkipReferences; |
| return *this; |
| } |
| |
| bool |
| GetDontShowChildren () const |
| { |
| return (m_flags & lldb::eTypeOptionHideChildren) == lldb::eTypeOptionHideChildren; |
| } |
| |
| Flags& |
| SetDontShowChildren (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionHideChildren; |
| else |
| m_flags &= ~lldb::eTypeOptionHideChildren; |
| return *this; |
| } |
| |
| bool |
| GetDontShowValue () const |
| { |
| return (m_flags & lldb::eTypeOptionHideValue) == lldb::eTypeOptionHideValue; |
| } |
| |
| Flags& |
| SetDontShowValue (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionHideValue; |
| else |
| m_flags &= ~lldb::eTypeOptionHideValue; |
| return *this; |
| } |
| |
| bool |
| GetShowMembersOneLiner () const |
| { |
| return (m_flags & lldb::eTypeOptionShowOneLiner) == lldb::eTypeOptionShowOneLiner; |
| } |
| |
| Flags& |
| SetShowMembersOneLiner (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionShowOneLiner; |
| else |
| m_flags &= ~lldb::eTypeOptionShowOneLiner; |
| return *this; |
| } |
| |
| bool |
| GetHideItemNames () const |
| { |
| return (m_flags & lldb::eTypeOptionHideNames) == lldb::eTypeOptionHideNames; |
| } |
| |
| Flags& |
| SetHideItemNames (bool value = true) |
| { |
| if (value) |
| m_flags |= lldb::eTypeOptionHideNames; |
| else |
| m_flags &= ~lldb::eTypeOptionHideNames; |
| return *this; |
| } |
| |
| uint32_t |
| GetValue () |
| { |
| return m_flags; |
| } |
| |
| void |
| SetValue (uint32_t value) |
| { |
| m_flags = value; |
| } |
| |
| private: |
| uint32_t m_flags; |
| }; |
| |
| TypeSummaryImpl (const TypeSummaryImpl::Flags& flags); |
| |
| bool |
| Cascades () const |
| { |
| return m_flags.GetCascades(); |
| } |
| bool |
| SkipsPointers () const |
| { |
| return m_flags.GetSkipPointers(); |
| } |
| bool |
| SkipsReferences () const |
| { |
| return m_flags.GetSkipReferences(); |
| } |
| |
| bool |
| DoesPrintChildren () const |
| { |
| return !m_flags.GetDontShowChildren(); |
| } |
| |
| bool |
| DoesPrintValue () const |
| { |
| return !m_flags.GetDontShowValue(); |
| } |
| |
| bool |
| IsOneliner () const |
| { |
| return m_flags.GetShowMembersOneLiner(); |
| } |
| |
| bool |
| HideNames () const |
| { |
| return m_flags.GetHideItemNames(); |
| } |
| |
| void |
| SetCascades (bool value) |
| { |
| m_flags.SetCascades(value); |
| } |
| |
| void |
| SetSkipsPointers (bool value) |
| { |
| m_flags.SetSkipPointers(value); |
| } |
| |
| void |
| SetSkipsReferences (bool value) |
| { |
| m_flags.SetSkipReferences(value); |
| } |
| |
| void |
| SetDoesPrintChildren (bool value) |
| { |
| m_flags.SetDontShowChildren(!value); |
| } |
| |
| void |
| SetDoesPrintValue (bool value) |
| { |
| m_flags.SetDontShowValue(!value); |
| } |
| |
| void |
| SetIsOneliner (bool value) |
| { |
| m_flags.SetShowMembersOneLiner(value); |
| } |
| |
| void |
| SetHideNames (bool value) |
| { |
| m_flags.SetHideItemNames(value); |
| } |
| |
| uint32_t |
| GetOptions () |
| { |
| return m_flags.GetValue(); |
| } |
| |
| void |
| SetOptions (uint32_t value) |
| { |
| m_flags.SetValue(value); |
| } |
| |
| virtual |
| ~TypeSummaryImpl () |
| { |
| } |
| |
| // we are using a ValueObject* instead of a ValueObjectSP because we do not need to hold on to this for |
| // extended periods of time and we trust the ValueObject to stay around for as long as it is required |
| // for us to generate its summary |
| virtual bool |
| FormatObject (ValueObject *valobj, |
| std::string& dest) = 0; |
| |
| virtual std::string |
| GetDescription () = 0; |
| |
| virtual bool |
| IsScripted() = 0; |
| |
| uint32_t& |
| GetRevision () |
| { |
| return m_my_revision; |
| } |
| |
| typedef STD_SHARED_PTR(TypeSummaryImpl) SharedPointer; |
| typedef bool(*SummaryCallback)(void*, ConstString, const lldb::TypeSummaryImplSP&); |
| typedef bool(*RegexSummaryCallback)(void*, lldb::RegularExpressionSP, const lldb::TypeSummaryImplSP&); |
| |
| protected: |
| uint32_t m_my_revision; |
| Flags m_flags; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TypeSummaryImpl); |
| }; |
| |
| // simple string-based summaries, using ${var to show data |
| struct StringSummaryFormat : public TypeSummaryImpl |
| { |
| std::string m_format; |
| |
| StringSummaryFormat(const TypeSummaryImpl::Flags& flags, |
| const char* f); |
| |
| const char* |
| GetSummaryString () const |
| { |
| return m_format.c_str(); |
| } |
| |
| void |
| SetSummaryString (const char* data) |
| { |
| if (data) |
| m_format.assign(data); |
| else |
| m_format.clear(); |
| } |
| |
| virtual |
| ~StringSummaryFormat() |
| { |
| } |
| |
| virtual bool |
| FormatObject(ValueObject *valobj, |
| std::string& dest); |
| |
| virtual std::string |
| GetDescription(); |
| |
| virtual bool |
| IsScripted() |
| { |
| return false; |
| } |
| |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(StringSummaryFormat); |
| }; |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| |
| // Python-based summaries, running script code to show data |
| struct ScriptSummaryFormat : public TypeSummaryImpl |
| { |
| std::string m_function_name; |
| std::string m_python_script; |
| lldb::ScriptInterpreterObjectSP m_script_function_sp; |
| |
| ScriptSummaryFormat(const TypeSummaryImpl::Flags& flags, |
| const char *function_name, |
| const char* python_script = NULL); |
| |
| const char* |
| GetFunctionName () const |
| { |
| return m_function_name.c_str(); |
| } |
| |
| const char* |
| GetPythonScript () const |
| { |
| return m_python_script.c_str(); |
| } |
| |
| void |
| SetFunctionName (const char* function_name) |
| { |
| if (function_name) |
| m_function_name.assign(function_name); |
| else |
| m_function_name.clear(); |
| m_python_script.clear(); |
| } |
| |
| void |
| SetPythonScript (const char* script) |
| { |
| if (script) |
| m_python_script.assign(script); |
| else |
| m_python_script.clear(); |
| } |
| |
| virtual |
| ~ScriptSummaryFormat() |
| { |
| } |
| |
| virtual bool |
| FormatObject(ValueObject *valobj, |
| std::string& dest); |
| |
| virtual std::string |
| GetDescription(); |
| |
| virtual bool |
| IsScripted() |
| { |
| return true; |
| } |
| |
| typedef STD_SHARED_PTR(ScriptSummaryFormat) SharedPointer; |
| |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ScriptSummaryFormat); |
| }; |
| |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| // TODO: at the moment, this class is only used as a backing store for SBTypeNameSpecifier in the public API |
| // In the future, this might be used as the basic unit for typename-to-formatter matching, replacing |
| // the current plain/regexp distinction in FormatNavigator<> |
| class TypeNameSpecifierImpl |
| { |
| public: |
| |
| TypeNameSpecifierImpl() : |
| m_is_regex(false), |
| m_type() |
| { |
| } |
| |
| TypeNameSpecifierImpl (const char* name, bool is_regex) : |
| m_is_regex(is_regex), |
| m_type() |
| { |
| if (name) |
| m_type.m_type_name.assign(name); |
| } |
| |
| // if constructing with a given type, is_regex cannot be true since we are |
| // giving an exact type to match |
| TypeNameSpecifierImpl (lldb::TypeSP type) : |
| m_is_regex(false), |
| m_type() |
| { |
| if (type) |
| { |
| m_type.m_type_name.assign(type->GetName().GetCString()); |
| m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); |
| } |
| } |
| |
| TypeNameSpecifierImpl (ClangASTType type) : |
| m_is_regex(false), |
| m_type() |
| { |
| if (type.IsValid()) |
| { |
| m_type.m_type_name.assign(type.GetConstTypeName().GetCString()); |
| m_type.m_typeimpl_sp = lldb::TypeImplSP(new TypeImpl(type)); |
| } |
| } |
| |
| const char* |
| GetName() |
| { |
| if (m_type.m_type_name.size()) |
| return m_type.m_type_name.c_str(); |
| return NULL; |
| } |
| |
| lldb::TypeSP |
| GetTypeSP () |
| { |
| if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) |
| return m_type.m_typeimpl_sp->GetTypeSP(); |
| return lldb::TypeSP(); |
| } |
| |
| ClangASTType |
| GetClangASTType () |
| { |
| if (m_type.m_typeimpl_sp && m_type.m_typeimpl_sp->IsValid()) |
| return m_type.m_typeimpl_sp->GetClangASTType(); |
| return ClangASTType(); |
| } |
| |
| bool |
| IsRegex() |
| { |
| return m_is_regex; |
| } |
| |
| private: |
| bool m_is_regex; |
| // this works better than TypeAndOrName because the latter only wraps a TypeSP |
| // whereas TypeImplSP can also be backed by a ClangASTType which is more commonly |
| // used in LLDB. moreover, TypeImplSP is also what is currently backing SBType |
| struct TypeOrName |
| { |
| std::string m_type_name; |
| lldb::TypeImplSP m_typeimpl_sp; |
| }; |
| TypeOrName m_type; |
| |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TypeNameSpecifierImpl); |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // lldb_FormatClasses_h_ |