1 //===-- LibCxxList.cpp -------------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "lldb/lldb-python.h"
12 #include "lldb/DataFormatters/CXXFormatterFunctions.h"
14 #include "lldb/Core/DataBufferHeap.h"
15 #include "lldb/Core/Error.h"
16 #include "lldb/Core/Stream.h"
17 #include "lldb/Core/ValueObject.h"
18 #include "lldb/Core/ValueObjectConstResult.h"
19 #include "lldb/Host/Endian.h"
20 #include "lldb/Symbol/ClangASTContext.h"
21 #include "lldb/Target/ObjCLanguageRuntime.h"
22 #include "lldb/Target/Target.h"
25 using namespace lldb_private;
26 using namespace lldb_private::formatters;
32 ListEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
33 ListEntry (const ListEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
34 ListEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
41 return m_entry_sp->GetChildMemberWithName(ConstString("__next_"), true);
49 return m_entry_sp->GetChildMemberWithName(ConstString("__prev_"), true);
57 return m_entry_sp->GetValueAsUnsigned(0);
63 return (value() == 0);
73 SetEntry (ValueObjectSP entry)
79 operator == (const ListEntry& rhs) const
81 return (rhs.m_entry_sp.get() == m_entry_sp.get());
85 ValueObjectSP m_entry_sp;
92 ListIterator (ListEntry entry) : m_entry(entry) {}
93 ListIterator (ValueObjectSP entry) : m_entry(entry) {}
94 ListIterator (const ListIterator& rhs) : m_entry(rhs.m_entry) {}
95 ListIterator (ValueObject* entry) : m_entry(entry) {}
100 return m_entry.GetEntry();
104 advance (size_t count)
107 return m_entry.GetEntry();
111 return m_entry.GetEntry();
118 return lldb::ValueObjectSP();
120 return m_entry.GetEntry();
124 operator == (const ListIterator& rhs) const
126 return (rhs.m_entry == m_entry);
133 m_entry.SetEntry(m_entry.next());
139 m_entry.SetEntry(m_entry.prev());
145 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::LibcxxStdListSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
146 SyntheticChildrenFrontEnd(*valobj_sp.get()),
147 m_list_capping_size(0),
160 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::HasLoop()
162 if (g_use_loop_detect == false)
164 ListEntry slow(m_head);
165 ListEntry fast1(m_head);
166 ListEntry fast2(m_head);
167 while (slow.next() && slow.next()->GetValueAsUnsigned(0) != m_node_address)
169 auto slow_value = slow.value();
170 fast1.SetEntry(fast2.next());
171 fast2.SetEntry(fast1.next());
172 if (fast1.value() == slow_value || fast2.value() == slow_value)
174 slow.SetEntry(slow.next());
180 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::CalculateNumChildren ()
182 if (m_count != UINT32_MAX)
184 if (!m_head || !m_tail || m_node_address == 0)
186 ValueObjectSP size_alloc(m_backend.GetChildMemberWithName(ConstString("__size_alloc_"), true));
189 ValueObjectSP first(size_alloc->GetChildMemberWithName(ConstString("__first_"), true));
192 m_count = first->GetValueAsUnsigned(UINT32_MAX);
195 if (m_count != UINT32_MAX)
203 uint64_t next_val = m_head->GetValueAsUnsigned(0);
204 uint64_t prev_val = m_tail->GetValueAsUnsigned(0);
205 if (next_val == 0 || prev_val == 0)
207 if (next_val == m_node_address)
209 if (next_val == prev_val)
214 ListEntry current(m_head);
215 while (current.next() && current.next()->GetValueAsUnsigned(0) != m_node_address)
218 current.SetEntry(current.next());
219 if (size > m_list_capping_size)
222 return m_count = (size-1);
227 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetChildAtIndex (size_t idx)
229 if (idx >= CalculateNumChildren())
230 return lldb::ValueObjectSP();
232 if (!m_head || !m_tail || m_node_address == 0)
233 return lldb::ValueObjectSP();
235 auto cached = m_children.find(idx);
236 if (cached != m_children.end())
237 return cached->second;
239 ListIterator current(m_head);
240 ValueObjectSP current_sp(current.advance(idx));
242 return lldb::ValueObjectSP();
243 current_sp = current_sp->GetChildMemberWithName(ConstString("__value_"), true);
245 return lldb::ValueObjectSP();
246 // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
248 current_sp->GetData(data);
250 name.Printf("[%zu]",idx);
251 return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
255 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::Update()
257 m_head = m_tail = NULL;
259 m_count = UINT32_MAX;
261 ValueObjectSP backend_addr(m_backend.AddressOf(err));
262 m_list_capping_size = 0;
263 if (m_backend.GetTargetSP())
264 m_list_capping_size = m_backend.GetTargetSP()->GetMaximumNumberOfChildrenToDisplay();
265 if (m_list_capping_size == 0)
266 m_list_capping_size = 255;
267 if (err.Fail() || backend_addr.get() == NULL)
269 m_node_address = backend_addr->GetValueAsUnsigned(0);
270 if (!m_node_address || m_node_address == LLDB_INVALID_ADDRESS)
272 ValueObjectSP impl_sp(m_backend.GetChildMemberWithName(ConstString("__end_"),true));
275 ClangASTType list_type = m_backend.GetClangType();
276 if (list_type.IsReferenceType())
277 list_type = list_type.GetNonReferenceType();
279 if (list_type.GetNumTemplateArguments() == 0)
281 lldb::TemplateArgumentKind kind;
282 m_element_type = list_type.GetTemplateArgument(0, kind);
283 m_head = impl_sp->GetChildMemberWithName(ConstString("__next_"), true).get();
284 m_tail = impl_sp->GetChildMemberWithName(ConstString("__prev_"), true).get();
289 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::MightHaveChildren ()
295 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
297 return ExtractIndexFromString(name.GetCString());
300 lldb_private::formatters::LibcxxStdListSyntheticFrontEnd::~LibcxxStdListSyntheticFrontEnd ()
303 SyntheticChildrenFrontEnd*
304 lldb_private::formatters::LibcxxStdListSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
308 return (new LibcxxStdListSyntheticFrontEnd(valobj_sp));