1 //===-- TypeCategoryMap.cpp ----------------------------------------*- C++
2 //-*-===//
3 //
4 // The LLVM Compiler Infrastructure
5 //
6 // This file is distributed under the University of Illinois Open Source
7 // License. See LICENSE.TXT for details.
8 //
9 //===----------------------------------------------------------------------===//
10
11 #include "lldb/DataFormatters/TypeCategoryMap.h"
12
13 #include "lldb/DataFormatters/FormatClasses.h"
14 #include "lldb/Utility/Log.h"
15
16
17 using namespace lldb;
18 using namespace lldb_private;
19
TypeCategoryMap(IFormatChangeListener * lst)20 TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
21 : m_map_mutex(), listener(lst), m_map(), m_active_categories() {
22 ConstString default_cs("default");
23 lldb::TypeCategoryImplSP default_sp =
24 lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs));
25 Add(default_cs, default_sp);
26 Enable(default_cs, First);
27 }
28
Add(KeyType name,const ValueSP & entry)29 void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) {
30 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
31 m_map[name] = entry;
32 if (listener)
33 listener->Changed();
34 }
35
Delete(KeyType name)36 bool TypeCategoryMap::Delete(KeyType name) {
37 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
38 MapIterator iter = m_map.find(name);
39 if (iter == m_map.end())
40 return false;
41 m_map.erase(name);
42 Disable(name);
43 if (listener)
44 listener->Changed();
45 return true;
46 }
47
Enable(KeyType category_name,Position pos)48 bool TypeCategoryMap::Enable(KeyType category_name, Position pos) {
49 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
50 ValueSP category;
51 if (!Get(category_name, category))
52 return false;
53 return Enable(category, pos);
54 }
55
Disable(KeyType category_name)56 bool TypeCategoryMap::Disable(KeyType category_name) {
57 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
58 ValueSP category;
59 if (!Get(category_name, category))
60 return false;
61 return Disable(category);
62 }
63
Enable(ValueSP category,Position pos)64 bool TypeCategoryMap::Enable(ValueSP category, Position pos) {
65 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
66 if (category.get()) {
67 Position pos_w = pos;
68 if (pos == First || m_active_categories.size() == 0)
69 m_active_categories.push_front(category);
70 else if (pos == Last || pos == m_active_categories.size())
71 m_active_categories.push_back(category);
72 else if (pos < m_active_categories.size()) {
73 ActiveCategoriesList::iterator iter = m_active_categories.begin();
74 while (pos_w) {
75 pos_w--, iter++;
76 }
77 m_active_categories.insert(iter, category);
78 } else
79 return false;
80 category->Enable(true, pos);
81 return true;
82 }
83 return false;
84 }
85
Disable(ValueSP category)86 bool TypeCategoryMap::Disable(ValueSP category) {
87 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
88 if (category.get()) {
89 m_active_categories.remove_if(delete_matching_categories(category));
90 category->Disable();
91 return true;
92 }
93 return false;
94 }
95
EnableAllCategories()96 void TypeCategoryMap::EnableAllCategories() {
97 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
98 std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP());
99 MapType::iterator iter = m_map.begin(), end = m_map.end();
100 for (; iter != end; ++iter) {
101 if (iter->second->IsEnabled())
102 continue;
103 auto pos = iter->second->GetLastEnabledPosition();
104 if (pos >= sorted_categories.size()) {
105 auto iter = std::find_if(
106 sorted_categories.begin(), sorted_categories.end(),
107 [](const ValueSP &sp) -> bool { return sp.get() == nullptr; });
108 pos = std::distance(sorted_categories.begin(), iter);
109 }
110 sorted_categories.at(pos) = iter->second;
111 }
112 decltype(sorted_categories)::iterator viter = sorted_categories.begin(),
113 vend = sorted_categories.end();
114 for (; viter != vend; viter++)
115 if (viter->get())
116 Enable(*viter, Last);
117 }
118
DisableAllCategories()119 void TypeCategoryMap::DisableAllCategories() {
120 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
121 for (Position p = First; !m_active_categories.empty(); p++) {
122 m_active_categories.front()->SetEnabledPosition(p);
123 Disable(m_active_categories.front());
124 }
125 }
126
Clear()127 void TypeCategoryMap::Clear() {
128 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
129 m_map.clear();
130 m_active_categories.clear();
131 if (listener)
132 listener->Changed();
133 }
134
Get(KeyType name,ValueSP & entry)135 bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) {
136 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
137 MapIterator iter = m_map.find(name);
138 if (iter == m_map.end())
139 return false;
140 entry = iter->second;
141 return true;
142 }
143
Get(uint32_t pos,ValueSP & entry)144 bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) {
145 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
146 MapIterator iter = m_map.begin();
147 MapIterator end = m_map.end();
148 while (pos > 0) {
149 iter++;
150 pos--;
151 if (iter == end)
152 return false;
153 }
154 entry = iter->second;
155 return false;
156 }
157
AnyMatches(ConstString type_name,TypeCategoryImpl::FormatCategoryItems items,bool only_enabled,const char ** matching_category,TypeCategoryImpl::FormatCategoryItems * matching_type)158 bool TypeCategoryMap::AnyMatches(
159 ConstString type_name, TypeCategoryImpl::FormatCategoryItems items,
160 bool only_enabled, const char **matching_category,
161 TypeCategoryImpl::FormatCategoryItems *matching_type) {
162 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
163
164 MapIterator pos, end = m_map.end();
165 for (pos = m_map.begin(); pos != end; pos++) {
166 if (pos->second->AnyMatches(type_name, items, only_enabled,
167 matching_category, matching_type))
168 return true;
169 }
170 return false;
171 }
172
173 lldb::TypeFormatImplSP
GetFormat(FormattersMatchData & match_data)174 TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
175 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
176
177 uint32_t reason_why;
178 ActiveCategoriesIterator begin, end = m_active_categories.end();
179
180 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
181
182 if (log) {
183 for (auto match : match_data.GetMatchesVector()) {
184 log->Printf(
185 "[CategoryMap::GetFormat] candidate match = %s %s %s %s reason = "
186 "%" PRIu32,
187 match.GetTypeName().GetCString(),
188 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
189 match.DidStripReference() ? "strip-reference" : "no-strip-reference",
190 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
191 match.GetReason());
192 }
193 }
194
195 for (begin = m_active_categories.begin(); begin != end; begin++) {
196 lldb::TypeCategoryImplSP category_sp = *begin;
197 lldb::TypeFormatImplSP current_format;
198 if (log)
199 log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s",
200 category_sp->GetName());
201 if (!category_sp->Get(match_data.GetValueObject(),
202 match_data.GetMatchesVector(), current_format,
203 &reason_why))
204 continue;
205 return current_format;
206 }
207 if (log)
208 log->Printf(
209 "[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
210 return lldb::TypeFormatImplSP();
211 }
212
213 lldb::TypeSummaryImplSP
GetSummaryFormat(FormattersMatchData & match_data)214 TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) {
215 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
216
217 uint32_t reason_why;
218 ActiveCategoriesIterator begin, end = m_active_categories.end();
219
220 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
221
222 if (log) {
223 for (auto match : match_data.GetMatchesVector()) {
224 log->Printf(
225 "[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s "
226 "reason = %" PRIu32,
227 match.GetTypeName().GetCString(),
228 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
229 match.DidStripReference() ? "strip-reference" : "no-strip-reference",
230 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
231 match.GetReason());
232 }
233 }
234
235 for (begin = m_active_categories.begin(); begin != end; begin++) {
236 lldb::TypeCategoryImplSP category_sp = *begin;
237 lldb::TypeSummaryImplSP current_format;
238 if (log)
239 log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s",
240 category_sp->GetName());
241 if (!category_sp->Get(match_data.GetValueObject(),
242 match_data.GetMatchesVector(), current_format,
243 &reason_why))
244 continue;
245 return current_format;
246 }
247 if (log)
248 log->Printf(
249 "[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
250 return lldb::TypeSummaryImplSP();
251 }
252
253 #ifndef LLDB_DISABLE_PYTHON
254 lldb::SyntheticChildrenSP
GetSyntheticChildren(FormattersMatchData & match_data)255 TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) {
256 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
257
258 uint32_t reason_why;
259
260 ActiveCategoriesIterator begin, end = m_active_categories.end();
261
262 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
263
264 if (log) {
265 for (auto match : match_data.GetMatchesVector()) {
266 log->Printf(
267 "[CategoryMap::GetSyntheticChildren] candidate match = %s %s %s %s "
268 "reason = %" PRIu32,
269 match.GetTypeName().GetCString(),
270 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
271 match.DidStripReference() ? "strip-reference" : "no-strip-reference",
272 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
273 match.GetReason());
274 }
275 }
276
277 for (begin = m_active_categories.begin(); begin != end; begin++) {
278 lldb::TypeCategoryImplSP category_sp = *begin;
279 lldb::SyntheticChildrenSP current_format;
280 if (log)
281 log->Printf(
282 "[CategoryMap::GetSyntheticChildren] Trying to use category %s",
283 category_sp->GetName());
284 if (!category_sp->Get(match_data.GetValueObject(),
285 match_data.GetMatchesVector(), current_format,
286 &reason_why))
287 continue;
288 return current_format;
289 }
290 if (log)
291 log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning "
292 "empty SP");
293 return lldb::SyntheticChildrenSP();
294 }
295 #endif
296
297 lldb::TypeValidatorImplSP
GetValidator(FormattersMatchData & match_data)298 TypeCategoryMap::GetValidator(FormattersMatchData &match_data) {
299 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
300
301 uint32_t reason_why;
302 ActiveCategoriesIterator begin, end = m_active_categories.end();
303
304 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
305
306 if (log) {
307 for (auto match : match_data.GetMatchesVector()) {
308 log->Printf(
309 "[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = "
310 "%" PRIu32,
311 match.GetTypeName().GetCString(),
312 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
313 match.DidStripReference() ? "strip-reference" : "no-strip-reference",
314 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
315 match.GetReason());
316 }
317 }
318
319 for (begin = m_active_categories.begin(); begin != end; begin++) {
320 lldb::TypeCategoryImplSP category_sp = *begin;
321 lldb::TypeValidatorImplSP current_format;
322 if (log)
323 log->Printf("[CategoryMap::GetValidator] Trying to use category %s",
324 category_sp->GetName());
325 if (!category_sp->Get(match_data.GetValueObject(),
326 match_data.GetMatchesVector(), current_format,
327 &reason_why))
328 continue;
329 return current_format;
330 }
331 if (log)
332 log->Printf(
333 "[CategoryMap::GetValidator] nothing found - returning empty SP");
334 return lldb::TypeValidatorImplSP();
335 }
336
ForEach(ForEachCallback callback)337 void TypeCategoryMap::ForEach(ForEachCallback callback) {
338 if (callback) {
339 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
340
341 // loop through enabled categories in respective order
342 {
343 ActiveCategoriesIterator begin, end = m_active_categories.end();
344 for (begin = m_active_categories.begin(); begin != end; begin++) {
345 lldb::TypeCategoryImplSP category = *begin;
346 if (!callback(category))
347 break;
348 }
349 }
350
351 // loop through disabled categories in just any order
352 {
353 MapIterator pos, end = m_map.end();
354 for (pos = m_map.begin(); pos != end; pos++) {
355 if (pos->second->IsEnabled())
356 continue;
357 if (!callback(pos->second))
358 break;
359 }
360 }
361 }
362 }
363
GetAtIndex(uint32_t index)364 TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) {
365 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
366
367 if (index < m_map.size()) {
368 MapIterator pos, end = m_map.end();
369 for (pos = m_map.begin(); pos != end; pos++) {
370 if (index == 0)
371 return pos->second;
372 index--;
373 }
374 }
375
376 return TypeCategoryImplSP();
377 }
378