blob: 82af5bd497e904f85d6fdb0c5a9b1b8c46cbf37e [file] [log] [blame]
Enrico Granatae2e220a2013-09-12 00:48:47 +00001//===-- LibCxxUnorderedMap.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
Enrico Granata33e97e62015-09-04 21:01:18 +000010#include "LibCxx.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000011
12#include "lldb/Core/DataBufferHeap.h"
13#include "lldb/Core/Error.h"
14#include "lldb/Core/Stream.h"
15#include "lldb/Core/ValueObject.h"
16#include "lldb/Core/ValueObjectConstResult.h"
Enrico Granata419d7912015-09-04 00:33:51 +000017#include "lldb/DataFormatters/FormattersHelpers.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000018#include "lldb/Host/Endian.h"
19#include "lldb/Symbol/ClangASTContext.h"
Enrico Granatae2e220a2013-09-12 00:48:47 +000020#include "lldb/Target/Target.h"
21
22using namespace lldb;
23using namespace lldb_private;
24using namespace lldb_private::formatters;
25
Enrico Granatae85fe3a2014-10-22 20:34:38 +000026namespace lldb_private {
27 namespace formatters {
28 class LibcxxStdUnorderedMapSyntheticFrontEnd : public SyntheticChildrenFrontEnd
29 {
30 public:
31 LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
32
33 virtual size_t
34 CalculateNumChildren ();
35
36 virtual lldb::ValueObjectSP
37 GetChildAtIndex (size_t idx);
38
39 virtual bool
40 Update();
41
42 virtual bool
43 MightHaveChildren ();
44
45 virtual size_t
46 GetIndexOfChildWithName (const ConstString &name);
47
48 virtual
49 ~LibcxxStdUnorderedMapSyntheticFrontEnd ();
50 private:
51
52 ValueObject* m_tree;
53 size_t m_num_elements;
54 ValueObject* m_next_element;
55 std::map<size_t,lldb::ValueObjectSP> m_children;
56 std::vector<std::pair<ValueObject*, uint64_t> > m_elements_cache;
57 };
58 }
59}
60
Enrico Granatae2e220a2013-09-12 00:48:47 +000061lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::LibcxxStdUnorderedMapSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
62SyntheticChildrenFrontEnd(*valobj_sp.get()),
63m_tree(NULL),
64m_num_elements(0),
65m_next_element(nullptr),
66m_children(),
67m_elements_cache()
68{
69 if (valobj_sp)
70 Update();
71}
72
73size_t
74lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::CalculateNumChildren ()
75{
76 if (m_num_elements != UINT32_MAX)
77 return m_num_elements;
78 return 0;
79}
80
81lldb::ValueObjectSP
82lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetChildAtIndex (size_t idx)
83{
84 if (idx >= CalculateNumChildren())
85 return lldb::ValueObjectSP();
86 if (m_tree == NULL)
87 return lldb::ValueObjectSP();
88
89 auto cached = m_children.find(idx);
90 if (cached != m_children.end())
91 return cached->second;
92
93 while (idx >= m_elements_cache.size())
94 {
95 if (m_next_element == nullptr)
96 return lldb::ValueObjectSP();
97
98 Error error;
99 ValueObjectSP node_sp = m_next_element->Dereference(error);
100 if (!node_sp || error.Fail())
101 return lldb::ValueObjectSP();
102
103 ValueObjectSP value_sp = node_sp->GetChildMemberWithName(ConstString("__value_"), true);
104 ValueObjectSP hash_sp = node_sp->GetChildMemberWithName(ConstString("__hash_"), true);
105 if (!hash_sp || !value_sp)
106 return lldb::ValueObjectSP();
107 m_elements_cache.push_back({value_sp.get(),hash_sp->GetValueAsUnsigned(0)});
108 m_next_element = node_sp->GetChildMemberWithName(ConstString("__next_"),true).get();
109 if (!m_next_element || m_next_element->GetValueAsUnsigned(0) == 0)
110 m_next_element = nullptr;
111 }
112
113 std::pair<ValueObject*, uint64_t> val_hash = m_elements_cache[idx];
114 if (!val_hash.first)
115 return lldb::ValueObjectSP();
116 StreamString stream;
Deepak Panickal99fbc072014-03-03 15:39:47 +0000117 stream.Printf("[%" PRIu64 "]", (uint64_t)idx);
Enrico Granatae2e220a2013-09-12 00:48:47 +0000118 DataExtractor data;
Sean Callanan866e91c2014-02-28 22:27:53 +0000119 Error error;
120 val_hash.first->GetData(data, error);
121 if (error.Fail())
122 return lldb::ValueObjectSP();
Greg Clayton44d93782014-01-27 23:43:24 +0000123 const bool thread_and_frame_only_if_stopped = true;
124 ExecutionContext exe_ctx = val_hash.first->GetExecutionContextRef().Lock(thread_and_frame_only_if_stopped);
Enrico Granatae2e220a2013-09-12 00:48:47 +0000125 return val_hash.first->CreateValueObjectFromData(stream.GetData(),
126 data,
127 exe_ctx,
Greg Clayton99558cc42015-08-24 23:46:31 +0000128 val_hash.first->GetCompilerType());
Enrico Granatae2e220a2013-09-12 00:48:47 +0000129}
130
131bool
132lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::Update()
133{
134 m_num_elements = UINT32_MAX;
135 m_next_element = nullptr;
136 m_elements_cache.clear();
137 m_children.clear();
138 ValueObjectSP table_sp = m_backend.GetChildMemberWithName(ConstString("__table_"), true);
139 if (!table_sp)
140 return false;
141 ValueObjectSP num_elements_sp = table_sp->GetChildAtNamePath({ConstString("__p2_"),ConstString("__first_")});
142 if (!num_elements_sp)
143 return false;
144 m_num_elements = num_elements_sp->GetValueAsUnsigned(0);
145 m_tree = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
146 if (m_num_elements > 0)
147 m_next_element = table_sp->GetChildAtNamePath({ConstString("__p1_"),ConstString("__first_"),ConstString("__next_")}).get();
148 return false;
149}
150
151bool
152lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::MightHaveChildren ()
153{
154 return true;
155}
156
157size_t
158lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
159{
160 return ExtractIndexFromString(name.GetCString());
161}
162
163lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEnd::~LibcxxStdUnorderedMapSyntheticFrontEnd ()
164{}
165
166SyntheticChildrenFrontEnd*
167lldb_private::formatters::LibcxxStdUnorderedMapSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
168{
169 if (!valobj_sp)
170 return NULL;
171 return (new LibcxxStdUnorderedMapSyntheticFrontEnd(valobj_sp));
172}