1314564Sdim//===-- TypeCategoryMap.cpp ----------------------------------------*- C++ 2314564Sdim//-*-===// 3254721Semaste// 4353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 5353358Sdim// See https://llvm.org/LICENSE.txt for license information. 6353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "lldb/DataFormatters/TypeCategoryMap.h" 11254721Semaste 12258884Semaste#include "lldb/DataFormatters/FormatClasses.h" 13321369Sdim#include "lldb/Utility/Log.h" 14258884Semaste 15254721Semaste 16254721Semasteusing namespace lldb; 17254721Semasteusing namespace lldb_private; 18254721Semaste 19309124SdimTypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst) 20314564Sdim : m_map_mutex(), listener(lst), m_map(), m_active_categories() { 21314564Sdim ConstString default_cs("default"); 22314564Sdim lldb::TypeCategoryImplSP default_sp = 23314564Sdim lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs)); 24314564Sdim Add(default_cs, default_sp); 25314564Sdim Enable(default_cs, First); 26254721Semaste} 27254721Semaste 28314564Sdimvoid TypeCategoryMap::Add(KeyType name, const ValueSP &entry) { 29314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 30314564Sdim m_map[name] = entry; 31314564Sdim if (listener) 32314564Sdim listener->Changed(); 33254721Semaste} 34254721Semaste 35314564Sdimbool TypeCategoryMap::Delete(KeyType name) { 36314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 37314564Sdim MapIterator iter = m_map.find(name); 38314564Sdim if (iter == m_map.end()) 39314564Sdim return false; 40314564Sdim m_map.erase(name); 41314564Sdim Disable(name); 42314564Sdim if (listener) 43314564Sdim listener->Changed(); 44314564Sdim return true; 45254721Semaste} 46254721Semaste 47314564Sdimbool TypeCategoryMap::Enable(KeyType category_name, Position pos) { 48314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 49314564Sdim ValueSP category; 50314564Sdim if (!Get(category_name, category)) 51314564Sdim return false; 52314564Sdim return Enable(category, pos); 53254721Semaste} 54254721Semaste 55314564Sdimbool TypeCategoryMap::Disable(KeyType category_name) { 56314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 57314564Sdim ValueSP category; 58314564Sdim if (!Get(category_name, category)) 59254721Semaste return false; 60314564Sdim return Disable(category); 61254721Semaste} 62254721Semaste 63314564Sdimbool TypeCategoryMap::Enable(ValueSP category, Position pos) { 64314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 65314564Sdim if (category.get()) { 66314564Sdim Position pos_w = pos; 67314564Sdim if (pos == First || m_active_categories.size() == 0) 68314564Sdim m_active_categories.push_front(category); 69314564Sdim else if (pos == Last || pos == m_active_categories.size()) 70314564Sdim m_active_categories.push_back(category); 71314564Sdim else if (pos < m_active_categories.size()) { 72314564Sdim ActiveCategoriesList::iterator iter = m_active_categories.begin(); 73314564Sdim while (pos_w) { 74314564Sdim pos_w--, iter++; 75314564Sdim } 76314564Sdim m_active_categories.insert(iter, category); 77314564Sdim } else 78314564Sdim return false; 79314564Sdim category->Enable(true, pos); 80314564Sdim return true; 81314564Sdim } 82314564Sdim return false; 83254721Semaste} 84254721Semaste 85314564Sdimbool TypeCategoryMap::Disable(ValueSP category) { 86314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 87314564Sdim if (category.get()) { 88314564Sdim m_active_categories.remove_if(delete_matching_categories(category)); 89314564Sdim category->Disable(); 90314564Sdim return true; 91314564Sdim } 92314564Sdim return false; 93280031Sdim} 94280031Sdim 95314564Sdimvoid TypeCategoryMap::EnableAllCategories() { 96314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 97314564Sdim std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP()); 98314564Sdim MapType::iterator iter = m_map.begin(), end = m_map.end(); 99314564Sdim for (; iter != end; ++iter) { 100314564Sdim if (iter->second->IsEnabled()) 101314564Sdim continue; 102314564Sdim auto pos = iter->second->GetLastEnabledPosition(); 103314564Sdim if (pos >= sorted_categories.size()) { 104314564Sdim auto iter = std::find_if( 105314564Sdim sorted_categories.begin(), sorted_categories.end(), 106314564Sdim [](const ValueSP &sp) -> bool { return sp.get() == nullptr; }); 107314564Sdim pos = std::distance(sorted_categories.begin(), iter); 108280031Sdim } 109314564Sdim sorted_categories.at(pos) = iter->second; 110314564Sdim } 111314564Sdim decltype(sorted_categories)::iterator viter = sorted_categories.begin(), 112314564Sdim vend = sorted_categories.end(); 113314564Sdim for (; viter != vend; viter++) 114353358Sdim if (*viter) 115314564Sdim Enable(*viter, Last); 116280031Sdim} 117280031Sdim 118314564Sdimvoid TypeCategoryMap::DisableAllCategories() { 119314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 120344779Sdim for (Position p = First; !m_active_categories.empty(); p++) { 121314564Sdim m_active_categories.front()->SetEnabledPosition(p); 122314564Sdim Disable(m_active_categories.front()); 123314564Sdim } 124254721Semaste} 125254721Semaste 126314564Sdimvoid TypeCategoryMap::Clear() { 127314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 128314564Sdim m_map.clear(); 129314564Sdim m_active_categories.clear(); 130314564Sdim if (listener) 131314564Sdim listener->Changed(); 132254721Semaste} 133254721Semaste 134314564Sdimbool TypeCategoryMap::Get(KeyType name, ValueSP &entry) { 135314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 136314564Sdim MapIterator iter = m_map.find(name); 137314564Sdim if (iter == m_map.end()) 138254721Semaste return false; 139314564Sdim entry = iter->second; 140314564Sdim return true; 141254721Semaste} 142254721Semaste 143314564Sdimbool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) { 144314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 145314564Sdim MapIterator iter = m_map.begin(); 146314564Sdim MapIterator end = m_map.end(); 147314564Sdim while (pos > 0) { 148314564Sdim iter++; 149314564Sdim pos--; 150314564Sdim if (iter == end) 151314564Sdim return false; 152314564Sdim } 153314564Sdim entry = iter->second; 154314564Sdim return false; 155314564Sdim} 156309124Sdim 157314564Sdimbool TypeCategoryMap::AnyMatches( 158314564Sdim ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, 159314564Sdim bool only_enabled, const char **matching_category, 160314564Sdim TypeCategoryImpl::FormatCategoryItems *matching_type) { 161314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 162314564Sdim 163314564Sdim MapIterator pos, end = m_map.end(); 164314564Sdim for (pos = m_map.begin(); pos != end; pos++) { 165314564Sdim if (pos->second->AnyMatches(type_name, items, only_enabled, 166314564Sdim matching_category, matching_type)) 167314564Sdim return true; 168314564Sdim } 169314564Sdim return false; 170254721Semaste} 171254721Semaste 172360784Sdimtemplate <typename ImplSP> 173360784Sdimvoid TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) { 174314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 175309124Sdim 176314564Sdim uint32_t reason_why; 177314564Sdim ActiveCategoriesIterator begin, end = m_active_categories.end(); 178314564Sdim 179314564Sdim Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 180314564Sdim 181314564Sdim if (log) { 182314564Sdim for (auto match : match_data.GetMatchesVector()) { 183360784Sdim LLDB_LOGF( 184360784Sdim log, 185360784Sdim "[%s] candidate match = %s %s %s %s reason = %" PRIu32, 186360784Sdim __FUNCTION__, 187314564Sdim match.GetTypeName().GetCString(), 188314564Sdim match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", 189314564Sdim match.DidStripReference() ? "strip-reference" : "no-strip-reference", 190314564Sdim match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef", 191314564Sdim match.GetReason()); 192296417Sdim } 193314564Sdim } 194296417Sdim 195314564Sdim for (begin = m_active_categories.begin(); begin != end; begin++) { 196314564Sdim lldb::TypeCategoryImplSP category_sp = *begin; 197360784Sdim ImplSP current_format; 198360784Sdim LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__, 199360784Sdim category_sp->GetName()); 200360784Sdim if (!category_sp->Get( 201360784Sdim match_data.GetValueObject().GetObjectRuntimeLanguage(), 202360784Sdim match_data.GetMatchesVector(), current_format, &reason_why)) 203314564Sdim continue; 204258054Semaste 205360784Sdim retval = std::move(current_format); 206360784Sdim return; 207314564Sdim } 208360784Sdim LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__); 209254721Semaste} 210254721Semaste 211360784Sdim/// Explicit instantiations for the three types. 212360784Sdim/// \{ 213360784Sdimtemplate void 214360784SdimTypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data, 215360784Sdim lldb::TypeFormatImplSP &retval); 216360784Sdimtemplate void 217360784SdimTypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data, 218360784Sdim lldb::TypeSummaryImplSP &retval); 219360784Sdimtemplate void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>( 220360784Sdim FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval); 221360784Sdim/// \} 222309124Sdim 223314564Sdimvoid TypeCategoryMap::ForEach(ForEachCallback callback) { 224314564Sdim if (callback) { 225314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 226314564Sdim 227314564Sdim // loop through enabled categories in respective order 228254721Semaste { 229314564Sdim ActiveCategoriesIterator begin, end = m_active_categories.end(); 230314564Sdim for (begin = m_active_categories.begin(); begin != end; begin++) { 231314564Sdim lldb::TypeCategoryImplSP category = *begin; 232314564Sdim if (!callback(category)) 233314564Sdim break; 234314564Sdim } 235314564Sdim } 236309124Sdim 237314564Sdim // loop through disabled categories in just any order 238314564Sdim { 239314564Sdim MapIterator pos, end = m_map.end(); 240314564Sdim for (pos = m_map.begin(); pos != end; pos++) { 241314564Sdim if (pos->second->IsEnabled()) 242314564Sdim continue; 243314564Sdim if (!callback(pos->second)) 244314564Sdim break; 245314564Sdim } 246254721Semaste } 247314564Sdim } 248254721Semaste} 249254721Semaste 250314564SdimTypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) { 251314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 252309124Sdim 253314564Sdim if (index < m_map.size()) { 254314564Sdim MapIterator pos, end = m_map.end(); 255314564Sdim for (pos = m_map.begin(); pos != end; pos++) { 256314564Sdim if (index == 0) 257314564Sdim return pos->second; 258314564Sdim index--; 259254721Semaste } 260314564Sdim } 261314564Sdim 262314564Sdim return TypeCategoryImplSP(); 263254721Semaste} 264