1 //===-- LibCxxVector.cpp ----------------------------------------*- 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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 // Project includes
14 #include "LibCxx.h"
15 
16 #include "lldb/Core/ConstString.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/DataFormatters/FormattersHelpers.h"
19 
20 using namespace lldb;
21 using namespace lldb_private;
22 using namespace lldb_private::formatters;
23 
24 namespace lldb_private {
25     namespace formatters {
26         class LibcxxStdVectorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
27         {
28         public:
29             LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
30 
31             ~LibcxxStdVectorSyntheticFrontEnd() override;
32 
33             size_t
34             CalculateNumChildren() override;
35 
36             lldb::ValueObjectSP
37             GetChildAtIndex(size_t idx) override;
38 
39             bool
40             Update() override;
41 
42             bool
43             MightHaveChildren() override;
44 
45             size_t
46             GetIndexOfChildWithName(const ConstString &name) override;
47 
48         private:
49             ValueObject* m_start;
50             ValueObject* m_finish;
51             CompilerType m_element_type;
52             uint32_t m_element_size;
53             std::map<size_t,lldb::ValueObjectSP> m_children;
54         };
55     } // namespace formatters
56 } // namespace lldb_private
57 
58 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::LibcxxStdVectorSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
59 SyntheticChildrenFrontEnd(*valobj_sp.get()),
60 m_start(NULL),
61 m_finish(NULL),
62 m_element_type(),
63 m_element_size(0),
64 m_children()
65 {
66     if (valobj_sp)
67         Update();
68 }
69 
70 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::~LibcxxStdVectorSyntheticFrontEnd()
71 {
72     // these need to stay around because they are child objects who will follow their parent's life cycle
73     // delete m_start;
74     // delete m_finish;
75 }
76 
77 size_t
78 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::CalculateNumChildren ()
79 {
80     if (!m_start || !m_finish)
81         return 0;
82     uint64_t start_val = m_start->GetValueAsUnsigned(0);
83     uint64_t finish_val = m_finish->GetValueAsUnsigned(0);
84 
85     if (start_val == 0 || finish_val == 0)
86         return 0;
87 
88     if (start_val >= finish_val)
89         return 0;
90 
91     size_t num_children = (finish_val - start_val);
92     if (num_children % m_element_size)
93         return 0;
94     return num_children/m_element_size;
95 }
96 
97 lldb::ValueObjectSP
98 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetChildAtIndex (size_t idx)
99 {
100     if (!m_start || !m_finish)
101         return lldb::ValueObjectSP();
102 
103     auto cached = m_children.find(idx);
104     if (cached != m_children.end())
105         return cached->second;
106 
107     uint64_t offset = idx * m_element_size;
108     offset = offset + m_start->GetValueAsUnsigned(0);
109     StreamString name;
110     name.Printf("[%" PRIu64 "]", (uint64_t)idx);
111     ValueObjectSP child_sp = CreateValueObjectFromAddress(name.GetData(), offset, m_backend.GetExecutionContextRef(), m_element_type);
112     m_children[idx] = child_sp;
113     return child_sp;
114 }
115 
116 bool
117 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::Update()
118 {
119     m_start = m_finish = NULL;
120     m_children.clear();
121     ValueObjectSP data_type_finder_sp(m_backend.GetChildMemberWithName(ConstString("__end_cap_"),true));
122     if (!data_type_finder_sp)
123         return false;
124     data_type_finder_sp = data_type_finder_sp->GetChildMemberWithName(ConstString("__first_"),true);
125     if (!data_type_finder_sp)
126         return false;
127     m_element_type = data_type_finder_sp->GetCompilerType().GetPointeeType();
128     m_element_size = m_element_type.GetByteSize(nullptr);
129 
130     if (m_element_size > 0)
131     {
132         // store raw pointers or end up with a circular dependency
133         m_start = m_backend.GetChildMemberWithName(ConstString("__begin_"),true).get();
134         m_finish = m_backend.GetChildMemberWithName(ConstString("__end_"),true).get();
135     }
136     return false;
137 }
138 
139 bool
140 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::MightHaveChildren ()
141 {
142     return true;
143 }
144 
145 size_t
146 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
147 {
148     if (!m_start || !m_finish)
149         return UINT32_MAX;
150     return ExtractIndexFromString(name.GetCString());
151 }
152 
153 lldb_private::SyntheticChildrenFrontEnd*
154 lldb_private::formatters::LibcxxStdVectorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
155 {
156     if (!valobj_sp)
157         return NULL;
158     return (new LibcxxStdVectorSyntheticFrontEnd(valobj_sp));
159 }
160