15ffd83dbSDimitry Andric //===-- TypeCategoryMap.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "lldb/DataFormatters/TypeCategoryMap.h"
100b57cec5SDimitry Andric
110b57cec5SDimitry Andric #include "lldb/DataFormatters/FormatClasses.h"
1281ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
130b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric using namespace lldb;
160b57cec5SDimitry Andric using namespace lldb_private;
170b57cec5SDimitry Andric
TypeCategoryMap(IFormatChangeListener * lst)180b57cec5SDimitry Andric TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
190b57cec5SDimitry Andric : m_map_mutex(), listener(lst), m_map(), m_active_categories() {
200b57cec5SDimitry Andric ConstString default_cs("default");
210b57cec5SDimitry Andric lldb::TypeCategoryImplSP default_sp =
220b57cec5SDimitry Andric lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs));
230b57cec5SDimitry Andric Add(default_cs, default_sp);
240b57cec5SDimitry Andric Enable(default_cs, First);
250b57cec5SDimitry Andric }
260b57cec5SDimitry Andric
Add(KeyType name,const TypeCategoryImplSP & entry)275f757f3fSDimitry Andric void TypeCategoryMap::Add(KeyType name, const TypeCategoryImplSP &entry) {
280b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
290b57cec5SDimitry Andric m_map[name] = entry;
300b57cec5SDimitry Andric if (listener)
310b57cec5SDimitry Andric listener->Changed();
320b57cec5SDimitry Andric }
330b57cec5SDimitry Andric
Delete(KeyType name)340b57cec5SDimitry Andric bool TypeCategoryMap::Delete(KeyType name) {
350b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
360b57cec5SDimitry Andric MapIterator iter = m_map.find(name);
370b57cec5SDimitry Andric if (iter == m_map.end())
380b57cec5SDimitry Andric return false;
390b57cec5SDimitry Andric m_map.erase(name);
400b57cec5SDimitry Andric Disable(name);
410b57cec5SDimitry Andric if (listener)
420b57cec5SDimitry Andric listener->Changed();
430b57cec5SDimitry Andric return true;
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric
Enable(KeyType category_name,Position pos)460b57cec5SDimitry Andric bool TypeCategoryMap::Enable(KeyType category_name, Position pos) {
470b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
485f757f3fSDimitry Andric TypeCategoryImplSP category;
490b57cec5SDimitry Andric if (!Get(category_name, category))
500b57cec5SDimitry Andric return false;
510b57cec5SDimitry Andric return Enable(category, pos);
520b57cec5SDimitry Andric }
530b57cec5SDimitry Andric
Disable(KeyType category_name)540b57cec5SDimitry Andric bool TypeCategoryMap::Disable(KeyType category_name) {
550b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
565f757f3fSDimitry Andric TypeCategoryImplSP category;
570b57cec5SDimitry Andric if (!Get(category_name, category))
580b57cec5SDimitry Andric return false;
590b57cec5SDimitry Andric return Disable(category);
600b57cec5SDimitry Andric }
610b57cec5SDimitry Andric
Enable(TypeCategoryImplSP category,Position pos)625f757f3fSDimitry Andric bool TypeCategoryMap::Enable(TypeCategoryImplSP category, Position pos) {
630b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
640b57cec5SDimitry Andric if (category.get()) {
650b57cec5SDimitry Andric Position pos_w = pos;
660b57cec5SDimitry Andric if (pos == First || m_active_categories.size() == 0)
670b57cec5SDimitry Andric m_active_categories.push_front(category);
680b57cec5SDimitry Andric else if (pos == Last || pos == m_active_categories.size())
690b57cec5SDimitry Andric m_active_categories.push_back(category);
700b57cec5SDimitry Andric else if (pos < m_active_categories.size()) {
710b57cec5SDimitry Andric ActiveCategoriesList::iterator iter = m_active_categories.begin();
720b57cec5SDimitry Andric while (pos_w) {
730b57cec5SDimitry Andric pos_w--, iter++;
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric m_active_categories.insert(iter, category);
760b57cec5SDimitry Andric } else
770b57cec5SDimitry Andric return false;
780b57cec5SDimitry Andric category->Enable(true, pos);
790b57cec5SDimitry Andric return true;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric return false;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric
Disable(TypeCategoryImplSP category)845f757f3fSDimitry Andric bool TypeCategoryMap::Disable(TypeCategoryImplSP category) {
850b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
860b57cec5SDimitry Andric if (category.get()) {
870b57cec5SDimitry Andric m_active_categories.remove_if(delete_matching_categories(category));
880b57cec5SDimitry Andric category->Disable();
890b57cec5SDimitry Andric return true;
900b57cec5SDimitry Andric }
910b57cec5SDimitry Andric return false;
920b57cec5SDimitry Andric }
930b57cec5SDimitry Andric
EnableAllCategories()940b57cec5SDimitry Andric void TypeCategoryMap::EnableAllCategories() {
950b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
965f757f3fSDimitry Andric std::vector<TypeCategoryImplSP> sorted_categories(m_map.size(), TypeCategoryImplSP());
970b57cec5SDimitry Andric MapType::iterator iter = m_map.begin(), end = m_map.end();
980b57cec5SDimitry Andric for (; iter != end; ++iter) {
990b57cec5SDimitry Andric if (iter->second->IsEnabled())
1000b57cec5SDimitry Andric continue;
1010b57cec5SDimitry Andric auto pos = iter->second->GetLastEnabledPosition();
1020b57cec5SDimitry Andric if (pos >= sorted_categories.size()) {
1030b57cec5SDimitry Andric auto iter = std::find_if(
1040b57cec5SDimitry Andric sorted_categories.begin(), sorted_categories.end(),
1055f757f3fSDimitry Andric [](const TypeCategoryImplSP &sp) -> bool { return sp.get() == nullptr; });
1060b57cec5SDimitry Andric pos = std::distance(sorted_categories.begin(), iter);
1070b57cec5SDimitry Andric }
1080b57cec5SDimitry Andric sorted_categories.at(pos) = iter->second;
1090b57cec5SDimitry Andric }
1100b57cec5SDimitry Andric decltype(sorted_categories)::iterator viter = sorted_categories.begin(),
1110b57cec5SDimitry Andric vend = sorted_categories.end();
1120b57cec5SDimitry Andric for (; viter != vend; viter++)
1130b57cec5SDimitry Andric if (*viter)
1140b57cec5SDimitry Andric Enable(*viter, Last);
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric
DisableAllCategories()1170b57cec5SDimitry Andric void TypeCategoryMap::DisableAllCategories() {
1180b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
1190b57cec5SDimitry Andric for (Position p = First; !m_active_categories.empty(); p++) {
1200b57cec5SDimitry Andric m_active_categories.front()->SetEnabledPosition(p);
1210b57cec5SDimitry Andric Disable(m_active_categories.front());
1220b57cec5SDimitry Andric }
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric
Clear()1250b57cec5SDimitry Andric void TypeCategoryMap::Clear() {
1260b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
1270b57cec5SDimitry Andric m_map.clear();
1280b57cec5SDimitry Andric m_active_categories.clear();
1290b57cec5SDimitry Andric if (listener)
1300b57cec5SDimitry Andric listener->Changed();
1310b57cec5SDimitry Andric }
1320b57cec5SDimitry Andric
Get(KeyType name,TypeCategoryImplSP & entry)1335f757f3fSDimitry Andric bool TypeCategoryMap::Get(KeyType name, TypeCategoryImplSP &entry) {
1340b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
1350b57cec5SDimitry Andric MapIterator iter = m_map.find(name);
1360b57cec5SDimitry Andric if (iter == m_map.end())
1370b57cec5SDimitry Andric return false;
1380b57cec5SDimitry Andric entry = iter->second;
1390b57cec5SDimitry Andric return true;
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric
AnyMatches(const FormattersMatchCandidate & candidate_type,TypeCategoryImpl::FormatCategoryItems items,bool only_enabled,const char ** matching_category,TypeCategoryImpl::FormatCategoryItems * matching_type)1420b57cec5SDimitry Andric bool TypeCategoryMap::AnyMatches(
143bdd1243dSDimitry Andric const FormattersMatchCandidate &candidate_type,
144bdd1243dSDimitry Andric TypeCategoryImpl::FormatCategoryItems items, bool only_enabled,
145bdd1243dSDimitry Andric const char **matching_category,
1460b57cec5SDimitry Andric TypeCategoryImpl::FormatCategoryItems *matching_type) {
1470b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
1480b57cec5SDimitry Andric
1490b57cec5SDimitry Andric MapIterator pos, end = m_map.end();
1500b57cec5SDimitry Andric for (pos = m_map.begin(); pos != end; pos++) {
151bdd1243dSDimitry Andric if (pos->second->AnyMatches(candidate_type, items, only_enabled,
1520b57cec5SDimitry Andric matching_category, matching_type))
1530b57cec5SDimitry Andric return true;
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric return false;
1560b57cec5SDimitry Andric }
1570b57cec5SDimitry Andric
158480093f4SDimitry Andric template <typename ImplSP>
Get(FormattersMatchData & match_data,ImplSP & retval)159480093f4SDimitry Andric void TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) {
1600b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
1610b57cec5SDimitry Andric
1620b57cec5SDimitry Andric ActiveCategoriesIterator begin, end = m_active_categories.end();
1630b57cec5SDimitry Andric
16481ad6265SDimitry Andric Log *log = GetLog(LLDBLog::DataFormatters);
1650b57cec5SDimitry Andric
1660b57cec5SDimitry Andric if (log) {
1670b57cec5SDimitry Andric for (auto match : match_data.GetMatchesVector()) {
1689dba64beSDimitry Andric LLDB_LOGF(
1699dba64beSDimitry Andric log,
1705ffd83dbSDimitry Andric "[%s] candidate match = %s %s %s %s",
171480093f4SDimitry Andric __FUNCTION__,
1720b57cec5SDimitry Andric match.GetTypeName().GetCString(),
1730b57cec5SDimitry Andric match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
1740b57cec5SDimitry Andric match.DidStripReference() ? "strip-reference" : "no-strip-reference",
1755ffd83dbSDimitry Andric match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef");
1760b57cec5SDimitry Andric }
1770b57cec5SDimitry Andric }
1780b57cec5SDimitry Andric
1790b57cec5SDimitry Andric for (begin = m_active_categories.begin(); begin != end; begin++) {
1800b57cec5SDimitry Andric lldb::TypeCategoryImplSP category_sp = *begin;
181480093f4SDimitry Andric ImplSP current_format;
182480093f4SDimitry Andric LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__,
1830b57cec5SDimitry Andric category_sp->GetName());
184480093f4SDimitry Andric if (!category_sp->Get(
185480093f4SDimitry Andric match_data.GetValueObject().GetObjectRuntimeLanguage(),
1865ffd83dbSDimitry Andric match_data.GetMatchesVector(), current_format))
1870b57cec5SDimitry Andric continue;
188480093f4SDimitry Andric
189480093f4SDimitry Andric retval = std::move(current_format);
190480093f4SDimitry Andric return;
1910b57cec5SDimitry Andric }
192480093f4SDimitry Andric LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__);
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric
195480093f4SDimitry Andric /// Explicit instantiations for the three types.
196480093f4SDimitry Andric /// \{
197480093f4SDimitry Andric template void
198480093f4SDimitry Andric TypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data,
199480093f4SDimitry Andric lldb::TypeFormatImplSP &retval);
200480093f4SDimitry Andric template void
201480093f4SDimitry Andric TypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data,
202480093f4SDimitry Andric lldb::TypeSummaryImplSP &retval);
203480093f4SDimitry Andric template void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>(
204480093f4SDimitry Andric FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval);
205480093f4SDimitry Andric /// \}
2060b57cec5SDimitry Andric
ForEach(ForEachCallback callback)2070b57cec5SDimitry Andric void TypeCategoryMap::ForEach(ForEachCallback callback) {
2080b57cec5SDimitry Andric if (callback) {
2090b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
2100b57cec5SDimitry Andric
2110b57cec5SDimitry Andric // loop through enabled categories in respective order
2120b57cec5SDimitry Andric {
2130b57cec5SDimitry Andric ActiveCategoriesIterator begin, end = m_active_categories.end();
2140b57cec5SDimitry Andric for (begin = m_active_categories.begin(); begin != end; begin++) {
2150b57cec5SDimitry Andric lldb::TypeCategoryImplSP category = *begin;
2160b57cec5SDimitry Andric if (!callback(category))
2170b57cec5SDimitry Andric break;
2180b57cec5SDimitry Andric }
2190b57cec5SDimitry Andric }
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric // loop through disabled categories in just any order
2220b57cec5SDimitry Andric {
2230b57cec5SDimitry Andric MapIterator pos, end = m_map.end();
2240b57cec5SDimitry Andric for (pos = m_map.begin(); pos != end; pos++) {
2250b57cec5SDimitry Andric if (pos->second->IsEnabled())
2260b57cec5SDimitry Andric continue;
2270b57cec5SDimitry Andric if (!callback(pos->second))
2280b57cec5SDimitry Andric break;
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric }
2320b57cec5SDimitry Andric }
2330b57cec5SDimitry Andric
GetAtIndex(uint32_t index)2340b57cec5SDimitry Andric TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) {
2350b57cec5SDimitry Andric std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric if (index < m_map.size()) {
2380b57cec5SDimitry Andric MapIterator pos, end = m_map.end();
2390b57cec5SDimitry Andric for (pos = m_map.begin(); pos != end; pos++) {
2400b57cec5SDimitry Andric if (index == 0)
2410b57cec5SDimitry Andric return pos->second;
2420b57cec5SDimitry Andric index--;
2430b57cec5SDimitry Andric }
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric
2460b57cec5SDimitry Andric return TypeCategoryImplSP();
2470b57cec5SDimitry Andric }
248