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 MapEntry (ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
33 MapEntry (const MapEntry& rhs) : m_entry_sp(rhs.m_entry_sp) {}
34 MapEntry (ValueObject* entry) : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
41 return m_entry_sp->GetChildMemberWithName(ConstString("__left_"), true);
49 return m_entry_sp->GetChildMemberWithName(ConstString("__right_"), true);
57 return m_entry_sp->GetChildMemberWithName(ConstString("__parent_"), true);
65 return m_entry_sp->GetValueAsUnsigned(0);
73 return m_entry_sp->GetError().Fail();
79 return (value() == 0);
89 SetEntry (ValueObjectSP entry)
95 operator == (const MapEntry& rhs) const
97 return (rhs.m_entry_sp.get() == m_entry_sp.get());
101 ValueObjectSP m_entry_sp;
108 MapIterator (MapEntry entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
109 MapIterator (ValueObjectSP entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
110 MapIterator (const MapIterator& rhs) : m_entry(rhs.m_entry),m_max_depth(rhs.m_max_depth), m_error(false) {}
111 MapIterator (ValueObject* entry, size_t depth = 0) : m_entry(entry), m_max_depth(depth), m_error(false) {}
116 return m_entry.GetEntry();
120 advance (size_t count)
123 return lldb::ValueObjectSP();
125 return m_entry.GetEntry();
129 return m_entry.GetEntry();
135 return lldb::ValueObjectSP();
139 return lldb::ValueObjectSP();
141 if (steps > m_max_depth)
142 return lldb::ValueObjectSP();
144 return m_entry.GetEntry();
150 m_entry.SetEntry(increment(m_entry.GetEntry()));
155 tree_min (ValueObjectSP x_sp)
159 return ValueObjectSP();
160 MapEntry left(x.left());
162 while (left.null() == false)
167 return lldb::ValueObjectSP();
169 x.SetEntry(left.GetEntry());
170 left.SetEntry(x.left());
172 if (steps > m_max_depth)
173 return lldb::ValueObjectSP();
179 tree_max (ValueObjectSP x_sp)
183 return ValueObjectSP();
184 MapEntry right(x.right());
186 while (right.null() == false)
189 return lldb::ValueObjectSP();
190 x.SetEntry(right.GetEntry());
191 right.SetEntry(x.right());
193 if (steps > m_max_depth)
194 return lldb::ValueObjectSP();
200 is_left_child (ValueObjectSP x_sp)
205 MapEntry rhs(x.parent());
206 rhs.SetEntry(rhs.left());
207 return x.value() == rhs.value();
211 increment (ValueObjectSP x_sp)
215 return ValueObjectSP();
216 MapEntry right(node.right());
217 if (right.null() == false)
218 return tree_min(right.GetEntry());
220 while (!is_left_child(node.GetEntry()))
225 return lldb::ValueObjectSP();
227 node.SetEntry(node.parent());
229 if (steps > m_max_depth)
230 return lldb::ValueObjectSP();
232 return node.parent();
240 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::LibcxxStdMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
241 SyntheticChildrenFrontEnd(*valobj_sp.get()),
245 m_skip_size(UINT32_MAX),
254 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::CalculateNumChildren ()
256 if (m_count != UINT32_MAX)
260 ValueObjectSP m_item(m_tree->GetChildMemberWithName(ConstString("__pair3_"), true));
263 m_item = m_item->GetChildMemberWithName(ConstString("__first_"), true);
266 m_count = m_item->GetValueAsUnsigned(0);
271 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetDataType()
273 if (m_element_type.GetOpaqueQualType() && m_element_type.GetASTContext())
275 m_element_type.Clear();
278 deref = m_root_node->Dereference(error);
279 if (!deref || error.Fail())
281 deref = deref->GetChildMemberWithName(ConstString("__value_"), true);
284 m_element_type = deref->GetClangType();
289 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetValueOffset (const lldb::ValueObjectSP& node)
291 if (m_skip_size != UINT32_MAX)
295 ClangASTType node_type(node->GetClangType());
297 if (node_type.GetIndexOfFieldWithName("__value_", NULL, &bit_offset) == UINT32_MAX)
299 m_skip_size = bit_offset / 8u;
303 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
305 if (idx >= CalculateNumChildren())
306 return lldb::ValueObjectSP();
307 if (m_tree == NULL || m_root_node == NULL)
308 return lldb::ValueObjectSP();
310 auto cached = m_children.find(idx);
311 if (cached != m_children.end())
312 return cached->second;
314 bool need_to_skip = (idx > 0);
315 MapIterator iterator(m_root_node, CalculateNumChildren());
316 ValueObjectSP iterated_sp(iterator.advance(idx));
317 if (iterated_sp.get() == NULL)
319 // this tree is garbage - stop
320 m_tree = NULL; // this will stop all future searches until an Update() happens
328 iterated_sp = iterated_sp->Dereference(error);
329 if (!iterated_sp || error.Fail())
332 return lldb::ValueObjectSP();
334 GetValueOffset(iterated_sp);
335 iterated_sp = iterated_sp->GetChildMemberWithName(ConstString("__value_"), true);
339 return lldb::ValueObjectSP();
344 // because of the way our debug info is made, we need to read item 0 first
345 // so that we can cache information used to generate other elements
346 if (m_skip_size == UINT32_MAX)
348 if (m_skip_size == UINT32_MAX)
351 return lldb::ValueObjectSP();
353 iterated_sp = iterated_sp->GetSyntheticChildAtOffset(m_skip_size, m_element_type, true);
357 return lldb::ValueObjectSP();
364 return lldb::ValueObjectSP();
366 // at this point we have a valid
367 // we need to copy current_sp into a new object otherwise we will end up with all items named __value_
369 iterated_sp->GetData(data);
371 name.Printf("[%zu]",idx);
372 return (m_children[idx] = ValueObject::CreateValueObjectFromData(name.GetData(), data, m_backend.GetExecutionContextRef(), m_element_type));
376 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::Update()
378 m_count = UINT32_MAX;
379 m_tree = m_root_node = NULL;
381 m_tree = m_backend.GetChildMemberWithName(ConstString("__tree_"), true).get();
384 m_root_node = m_tree->GetChildMemberWithName(ConstString("__begin_node_"), true).get();
389 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::MightHaveChildren ()
395 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
397 return ExtractIndexFromString(name.GetCString());
400 lldb_private::formatters::LibcxxStdMapSyntheticFrontEnd::~LibcxxStdMapSyntheticFrontEnd ()
403 SyntheticChildrenFrontEnd*
404 lldb_private::formatters::LibcxxStdMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
408 return (new LibcxxStdMapSyntheticFrontEnd(valobj_sp));