diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 | 
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2015-12-30 11:55:28 +0000 | 
| commit | e81d9d49145e432d917eea3a70d2ae74dcad1d89 (patch) | |
| tree | 9ed5e1a91f242e2cb5911577356e487a55c01b78 /source/Plugins/Language/Go/GoFormatterFunctions.cpp | |
| parent | 85d8ef8f1f0e0e063a8571944302be2d2026f823 (diff) | |
Notes
Diffstat (limited to 'source/Plugins/Language/Go/GoFormatterFunctions.cpp')
| -rw-r--r-- | source/Plugins/Language/Go/GoFormatterFunctions.cpp | 173 | 
1 files changed, 173 insertions, 0 deletions
diff --git a/source/Plugins/Language/Go/GoFormatterFunctions.cpp b/source/Plugins/Language/Go/GoFormatterFunctions.cpp new file mode 100644 index 0000000000000..1d7cd76b97392 --- /dev/null +++ b/source/Plugins/Language/Go/GoFormatterFunctions.cpp @@ -0,0 +1,173 @@ +//===-- GoFormatterFunctions.cpp---------------------------------*- C++ -*-===// +// +//                     The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +// C++ Includes +#include <map> + +// Other libraries and framework includes +// Project includes +#include "GoFormatterFunctions.h" +#include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/DataFormatters/StringPrinter.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::formatters; + +namespace +{ +class GoSliceSyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +  public: +    GoSliceSyntheticFrontEnd(ValueObject &valobj) +        : SyntheticChildrenFrontEnd(valobj) +    { +        Update(); +    } + +    ~GoSliceSyntheticFrontEnd() override = default; + +    size_t +    CalculateNumChildren() override +    { +        return m_len; +    } + +    lldb::ValueObjectSP +    GetChildAtIndex(size_t idx) override +    { +        if (idx < m_len) +        { +            ValueObjectSP &cached = m_children[idx]; +            if (!cached) +            { +                StreamString idx_name; +                idx_name.Printf("[%" PRIu64 "]", (uint64_t)idx); +                lldb::addr_t object_at_idx = m_base_data_address; +                object_at_idx += idx * m_type.GetByteSize(nullptr); +                cached = CreateValueObjectFromAddress(idx_name.GetData(), object_at_idx, +                                                      m_backend.GetExecutionContextRef(), m_type); +            } +            return cached; +        } +        return ValueObjectSP(); +    } + +    bool +    Update() override +    { +        size_t old_count = m_len; + +        ConstString array_const_str("array"); +        ValueObjectSP array_sp = m_backend.GetChildMemberWithName(array_const_str, true); +        if (!array_sp) +        { +            m_children.clear(); +            return old_count == 0; +        } +        m_type = array_sp->GetCompilerType().GetPointeeType(); +        m_base_data_address = array_sp->GetPointerValue(); + +        ConstString len_const_str("len"); +        ValueObjectSP len_sp = m_backend.GetChildMemberWithName(len_const_str, true); +        if (len_sp) +        { +            m_len = len_sp->GetValueAsUnsigned(0); +            m_children.clear(); +        } + +        return old_count == m_len; +    } + +    bool +    MightHaveChildren() override +    { +        return true; +    } + +    size_t +    GetIndexOfChildWithName(const ConstString &name) override +    { +        return ExtractIndexFromString(name.AsCString()); +    } + +  private: +    CompilerType m_type; +    lldb::addr_t m_base_data_address; +    size_t m_len; +    std::map<size_t, lldb::ValueObjectSP> m_children; +}; + +} // anonymous namespace + +bool +lldb_private::formatters::GoStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) +{ +    ProcessSP process_sp = valobj.GetProcessSP(); +    if (!process_sp) +        return false; + +    if (valobj.IsPointerType()) +    { +        Error err; +        ValueObjectSP deref = valobj.Dereference(err); +        if (!err.Success()) +            return false; +        return GoStringSummaryProvider(*deref, stream, opts); +    } + +    ConstString str_name("str"); +    ConstString len_name("len"); + +    ValueObjectSP data_sp = valobj.GetChildMemberWithName(str_name, true); +    ValueObjectSP len_sp = valobj.GetChildMemberWithName(len_name, true); +    if (!data_sp || !len_sp) +        return false; +    bool success; +    lldb::addr_t valobj_addr = data_sp->GetValueAsUnsigned(0, &success); + +    if (!success) +        return false; + +    uint64_t length = len_sp->GetValueAsUnsigned(0); +    if (length == 0) +    { +        stream.Printf("\"\""); +        return true; +    } + +    StringPrinter::ReadStringAndDumpToStreamOptions options(valobj); +    options.SetLocation(valobj_addr); +    options.SetProcessSP(process_sp); +    options.SetStream(&stream); +    options.SetSourceSize(length); +    options.SetNeedsZeroTermination(false); +    options.SetLanguage(eLanguageTypeGo); + +    if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options)) +    { +        stream.Printf("Summary Unavailable"); +        return true; +    } + +    return true; +} + +SyntheticChildrenFrontEnd * +lldb_private::formatters::GoSliceSyntheticFrontEndCreator(CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) +{ +    if (!valobj_sp) +        return nullptr; + +    lldb::ProcessSP process_sp(valobj_sp->GetProcessSP()); +    if (!process_sp) +        return nullptr; +    return new GoSliceSyntheticFrontEnd(*valobj_sp); +}  | 
