1*dda28197Spatrick //===-- TypeCategoryMap.cpp -----------------------------------------------===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9061da546Spatrick #include "lldb/DataFormatters/TypeCategoryMap.h" 10061da546Spatrick 11061da546Spatrick #include "lldb/DataFormatters/FormatClasses.h" 12061da546Spatrick #include "lldb/Utility/Log.h" 13061da546Spatrick 14061da546Spatrick 15061da546Spatrick using namespace lldb; 16061da546Spatrick using namespace lldb_private; 17061da546Spatrick 18061da546Spatrick TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst) 19061da546Spatrick : m_map_mutex(), listener(lst), m_map(), m_active_categories() { 20061da546Spatrick ConstString default_cs("default"); 21061da546Spatrick lldb::TypeCategoryImplSP default_sp = 22061da546Spatrick lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs)); 23061da546Spatrick Add(default_cs, default_sp); 24061da546Spatrick Enable(default_cs, First); 25061da546Spatrick } 26061da546Spatrick 27061da546Spatrick void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) { 28061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 29061da546Spatrick m_map[name] = entry; 30061da546Spatrick if (listener) 31061da546Spatrick listener->Changed(); 32061da546Spatrick } 33061da546Spatrick 34061da546Spatrick bool TypeCategoryMap::Delete(KeyType name) { 35061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 36061da546Spatrick MapIterator iter = m_map.find(name); 37061da546Spatrick if (iter == m_map.end()) 38061da546Spatrick return false; 39061da546Spatrick m_map.erase(name); 40061da546Spatrick Disable(name); 41061da546Spatrick if (listener) 42061da546Spatrick listener->Changed(); 43061da546Spatrick return true; 44061da546Spatrick } 45061da546Spatrick 46061da546Spatrick bool TypeCategoryMap::Enable(KeyType category_name, Position pos) { 47061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 48061da546Spatrick ValueSP category; 49061da546Spatrick if (!Get(category_name, category)) 50061da546Spatrick return false; 51061da546Spatrick return Enable(category, pos); 52061da546Spatrick } 53061da546Spatrick 54061da546Spatrick bool TypeCategoryMap::Disable(KeyType category_name) { 55061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 56061da546Spatrick ValueSP category; 57061da546Spatrick if (!Get(category_name, category)) 58061da546Spatrick return false; 59061da546Spatrick return Disable(category); 60061da546Spatrick } 61061da546Spatrick 62061da546Spatrick bool TypeCategoryMap::Enable(ValueSP category, Position pos) { 63061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 64061da546Spatrick if (category.get()) { 65061da546Spatrick Position pos_w = pos; 66061da546Spatrick if (pos == First || m_active_categories.size() == 0) 67061da546Spatrick m_active_categories.push_front(category); 68061da546Spatrick else if (pos == Last || pos == m_active_categories.size()) 69061da546Spatrick m_active_categories.push_back(category); 70061da546Spatrick else if (pos < m_active_categories.size()) { 71061da546Spatrick ActiveCategoriesList::iterator iter = m_active_categories.begin(); 72061da546Spatrick while (pos_w) { 73061da546Spatrick pos_w--, iter++; 74061da546Spatrick } 75061da546Spatrick m_active_categories.insert(iter, category); 76061da546Spatrick } else 77061da546Spatrick return false; 78061da546Spatrick category->Enable(true, pos); 79061da546Spatrick return true; 80061da546Spatrick } 81061da546Spatrick return false; 82061da546Spatrick } 83061da546Spatrick 84061da546Spatrick bool TypeCategoryMap::Disable(ValueSP category) { 85061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 86061da546Spatrick if (category.get()) { 87061da546Spatrick m_active_categories.remove_if(delete_matching_categories(category)); 88061da546Spatrick category->Disable(); 89061da546Spatrick return true; 90061da546Spatrick } 91061da546Spatrick return false; 92061da546Spatrick } 93061da546Spatrick 94061da546Spatrick void TypeCategoryMap::EnableAllCategories() { 95061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 96061da546Spatrick std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP()); 97061da546Spatrick MapType::iterator iter = m_map.begin(), end = m_map.end(); 98061da546Spatrick for (; iter != end; ++iter) { 99061da546Spatrick if (iter->second->IsEnabled()) 100061da546Spatrick continue; 101061da546Spatrick auto pos = iter->second->GetLastEnabledPosition(); 102061da546Spatrick if (pos >= sorted_categories.size()) { 103061da546Spatrick auto iter = std::find_if( 104061da546Spatrick sorted_categories.begin(), sorted_categories.end(), 105061da546Spatrick [](const ValueSP &sp) -> bool { return sp.get() == nullptr; }); 106061da546Spatrick pos = std::distance(sorted_categories.begin(), iter); 107061da546Spatrick } 108061da546Spatrick sorted_categories.at(pos) = iter->second; 109061da546Spatrick } 110061da546Spatrick decltype(sorted_categories)::iterator viter = sorted_categories.begin(), 111061da546Spatrick vend = sorted_categories.end(); 112061da546Spatrick for (; viter != vend; viter++) 113061da546Spatrick if (*viter) 114061da546Spatrick Enable(*viter, Last); 115061da546Spatrick } 116061da546Spatrick 117061da546Spatrick void TypeCategoryMap::DisableAllCategories() { 118061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 119061da546Spatrick for (Position p = First; !m_active_categories.empty(); p++) { 120061da546Spatrick m_active_categories.front()->SetEnabledPosition(p); 121061da546Spatrick Disable(m_active_categories.front()); 122061da546Spatrick } 123061da546Spatrick } 124061da546Spatrick 125061da546Spatrick void TypeCategoryMap::Clear() { 126061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 127061da546Spatrick m_map.clear(); 128061da546Spatrick m_active_categories.clear(); 129061da546Spatrick if (listener) 130061da546Spatrick listener->Changed(); 131061da546Spatrick } 132061da546Spatrick 133061da546Spatrick bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) { 134061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 135061da546Spatrick MapIterator iter = m_map.find(name); 136061da546Spatrick if (iter == m_map.end()) 137061da546Spatrick return false; 138061da546Spatrick entry = iter->second; 139061da546Spatrick return true; 140061da546Spatrick } 141061da546Spatrick 142061da546Spatrick bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) { 143061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 144061da546Spatrick MapIterator iter = m_map.begin(); 145061da546Spatrick MapIterator end = m_map.end(); 146061da546Spatrick while (pos > 0) { 147061da546Spatrick iter++; 148061da546Spatrick pos--; 149061da546Spatrick if (iter == end) 150061da546Spatrick return false; 151061da546Spatrick } 152061da546Spatrick entry = iter->second; 153061da546Spatrick return false; 154061da546Spatrick } 155061da546Spatrick 156061da546Spatrick bool TypeCategoryMap::AnyMatches( 157061da546Spatrick ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, 158061da546Spatrick bool only_enabled, const char **matching_category, 159061da546Spatrick TypeCategoryImpl::FormatCategoryItems *matching_type) { 160061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 161061da546Spatrick 162061da546Spatrick MapIterator pos, end = m_map.end(); 163061da546Spatrick for (pos = m_map.begin(); pos != end; pos++) { 164061da546Spatrick if (pos->second->AnyMatches(type_name, items, only_enabled, 165061da546Spatrick matching_category, matching_type)) 166061da546Spatrick return true; 167061da546Spatrick } 168061da546Spatrick return false; 169061da546Spatrick } 170061da546Spatrick 171061da546Spatrick template <typename ImplSP> 172061da546Spatrick void TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) { 173061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 174061da546Spatrick 175061da546Spatrick ActiveCategoriesIterator begin, end = m_active_categories.end(); 176061da546Spatrick 177061da546Spatrick Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 178061da546Spatrick 179061da546Spatrick if (log) { 180061da546Spatrick for (auto match : match_data.GetMatchesVector()) { 181061da546Spatrick LLDB_LOGF( 182061da546Spatrick log, 183*dda28197Spatrick "[%s] candidate match = %s %s %s %s", 184061da546Spatrick __FUNCTION__, 185061da546Spatrick match.GetTypeName().GetCString(), 186061da546Spatrick match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", 187061da546Spatrick match.DidStripReference() ? "strip-reference" : "no-strip-reference", 188*dda28197Spatrick match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef"); 189061da546Spatrick } 190061da546Spatrick } 191061da546Spatrick 192061da546Spatrick for (begin = m_active_categories.begin(); begin != end; begin++) { 193061da546Spatrick lldb::TypeCategoryImplSP category_sp = *begin; 194061da546Spatrick ImplSP current_format; 195061da546Spatrick LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__, 196061da546Spatrick category_sp->GetName()); 197061da546Spatrick if (!category_sp->Get( 198061da546Spatrick match_data.GetValueObject().GetObjectRuntimeLanguage(), 199*dda28197Spatrick match_data.GetMatchesVector(), current_format)) 200061da546Spatrick continue; 201061da546Spatrick 202061da546Spatrick retval = std::move(current_format); 203061da546Spatrick return; 204061da546Spatrick } 205061da546Spatrick LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__); 206061da546Spatrick } 207061da546Spatrick 208061da546Spatrick /// Explicit instantiations for the three types. 209061da546Spatrick /// \{ 210061da546Spatrick template void 211061da546Spatrick TypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data, 212061da546Spatrick lldb::TypeFormatImplSP &retval); 213061da546Spatrick template void 214061da546Spatrick TypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data, 215061da546Spatrick lldb::TypeSummaryImplSP &retval); 216061da546Spatrick template void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>( 217061da546Spatrick FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval); 218061da546Spatrick /// \} 219061da546Spatrick 220061da546Spatrick void TypeCategoryMap::ForEach(ForEachCallback callback) { 221061da546Spatrick if (callback) { 222061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 223061da546Spatrick 224061da546Spatrick // loop through enabled categories in respective order 225061da546Spatrick { 226061da546Spatrick ActiveCategoriesIterator begin, end = m_active_categories.end(); 227061da546Spatrick for (begin = m_active_categories.begin(); begin != end; begin++) { 228061da546Spatrick lldb::TypeCategoryImplSP category = *begin; 229061da546Spatrick if (!callback(category)) 230061da546Spatrick break; 231061da546Spatrick } 232061da546Spatrick } 233061da546Spatrick 234061da546Spatrick // loop through disabled categories in just any order 235061da546Spatrick { 236061da546Spatrick MapIterator pos, end = m_map.end(); 237061da546Spatrick for (pos = m_map.begin(); pos != end; pos++) { 238061da546Spatrick if (pos->second->IsEnabled()) 239061da546Spatrick continue; 240061da546Spatrick if (!callback(pos->second)) 241061da546Spatrick break; 242061da546Spatrick } 243061da546Spatrick } 244061da546Spatrick } 245061da546Spatrick } 246061da546Spatrick 247061da546Spatrick TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) { 248061da546Spatrick std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 249061da546Spatrick 250061da546Spatrick if (index < m_map.size()) { 251061da546Spatrick MapIterator pos, end = m_map.end(); 252061da546Spatrick for (pos = m_map.begin(); pos != end; pos++) { 253061da546Spatrick if (index == 0) 254061da546Spatrick return pos->second; 255061da546Spatrick index--; 256061da546Spatrick } 257061da546Spatrick } 258061da546Spatrick 259061da546Spatrick return TypeCategoryImplSP(); 260061da546Spatrick } 261