1 //===-- TypeCategoryMap.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/DataFormatters/TypeCategoryMap.h" 10 11 #include "lldb/DataFormatters/FormatClasses.h" 12 #include "lldb/Utility/Log.h" 13 14 15 using namespace lldb; 16 using namespace lldb_private; 17 18 TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst) 19 : m_map_mutex(), listener(lst), m_map(), m_active_categories() { 20 ConstString default_cs("default"); 21 lldb::TypeCategoryImplSP default_sp = 22 lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs)); 23 Add(default_cs, default_sp); 24 Enable(default_cs, First); 25 } 26 27 void TypeCategoryMap::Add(KeyType name, const ValueSP &entry) { 28 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 29 m_map[name] = entry; 30 if (listener) 31 listener->Changed(); 32 } 33 34 bool TypeCategoryMap::Delete(KeyType name) { 35 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 36 MapIterator iter = m_map.find(name); 37 if (iter == m_map.end()) 38 return false; 39 m_map.erase(name); 40 Disable(name); 41 if (listener) 42 listener->Changed(); 43 return true; 44 } 45 46 bool TypeCategoryMap::Enable(KeyType category_name, Position pos) { 47 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 48 ValueSP category; 49 if (!Get(category_name, category)) 50 return false; 51 return Enable(category, pos); 52 } 53 54 bool TypeCategoryMap::Disable(KeyType category_name) { 55 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 56 ValueSP category; 57 if (!Get(category_name, category)) 58 return false; 59 return Disable(category); 60 } 61 62 bool TypeCategoryMap::Enable(ValueSP category, Position pos) { 63 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 64 if (category.get()) { 65 Position pos_w = pos; 66 if (pos == First || m_active_categories.size() == 0) 67 m_active_categories.push_front(category); 68 else if (pos == Last || pos == m_active_categories.size()) 69 m_active_categories.push_back(category); 70 else if (pos < m_active_categories.size()) { 71 ActiveCategoriesList::iterator iter = m_active_categories.begin(); 72 while (pos_w) { 73 pos_w--, iter++; 74 } 75 m_active_categories.insert(iter, category); 76 } else 77 return false; 78 category->Enable(true, pos); 79 return true; 80 } 81 return false; 82 } 83 84 bool TypeCategoryMap::Disable(ValueSP category) { 85 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 86 if (category.get()) { 87 m_active_categories.remove_if(delete_matching_categories(category)); 88 category->Disable(); 89 return true; 90 } 91 return false; 92 } 93 94 void TypeCategoryMap::EnableAllCategories() { 95 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 96 std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP()); 97 MapType::iterator iter = m_map.begin(), end = m_map.end(); 98 for (; iter != end; ++iter) { 99 if (iter->second->IsEnabled()) 100 continue; 101 auto pos = iter->second->GetLastEnabledPosition(); 102 if (pos >= sorted_categories.size()) { 103 auto iter = std::find_if( 104 sorted_categories.begin(), sorted_categories.end(), 105 [](const ValueSP &sp) -> bool { return sp.get() == nullptr; }); 106 pos = std::distance(sorted_categories.begin(), iter); 107 } 108 sorted_categories.at(pos) = iter->second; 109 } 110 decltype(sorted_categories)::iterator viter = sorted_categories.begin(), 111 vend = sorted_categories.end(); 112 for (; viter != vend; viter++) 113 if (*viter) 114 Enable(*viter, Last); 115 } 116 117 void TypeCategoryMap::DisableAllCategories() { 118 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 119 for (Position p = First; !m_active_categories.empty(); p++) { 120 m_active_categories.front()->SetEnabledPosition(p); 121 Disable(m_active_categories.front()); 122 } 123 } 124 125 void TypeCategoryMap::Clear() { 126 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 127 m_map.clear(); 128 m_active_categories.clear(); 129 if (listener) 130 listener->Changed(); 131 } 132 133 bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) { 134 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 135 MapIterator iter = m_map.find(name); 136 if (iter == m_map.end()) 137 return false; 138 entry = iter->second; 139 return true; 140 } 141 142 bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) { 143 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 144 MapIterator iter = m_map.begin(); 145 MapIterator end = m_map.end(); 146 while (pos > 0) { 147 iter++; 148 pos--; 149 if (iter == end) 150 return false; 151 } 152 entry = iter->second; 153 return false; 154 } 155 156 bool TypeCategoryMap::AnyMatches( 157 ConstString type_name, TypeCategoryImpl::FormatCategoryItems items, 158 bool only_enabled, const char **matching_category, 159 TypeCategoryImpl::FormatCategoryItems *matching_type) { 160 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 161 162 MapIterator pos, end = m_map.end(); 163 for (pos = m_map.begin(); pos != end; pos++) { 164 if (pos->second->AnyMatches(type_name, items, only_enabled, 165 matching_category, matching_type)) 166 return true; 167 } 168 return false; 169 } 170 171 template <typename ImplSP> 172 void TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) { 173 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 174 175 ActiveCategoriesIterator begin, end = m_active_categories.end(); 176 177 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS)); 178 179 if (log) { 180 for (auto match : match_data.GetMatchesVector()) { 181 LLDB_LOGF( 182 log, 183 "[%s] candidate match = %s %s %s %s", 184 __FUNCTION__, 185 match.GetTypeName().GetCString(), 186 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", 187 match.DidStripReference() ? "strip-reference" : "no-strip-reference", 188 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef"); 189 } 190 } 191 192 for (begin = m_active_categories.begin(); begin != end; begin++) { 193 lldb::TypeCategoryImplSP category_sp = *begin; 194 ImplSP current_format; 195 LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__, 196 category_sp->GetName()); 197 if (!category_sp->Get( 198 match_data.GetValueObject().GetObjectRuntimeLanguage(), 199 match_data.GetMatchesVector(), current_format)) 200 continue; 201 202 retval = std::move(current_format); 203 return; 204 } 205 LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__); 206 } 207 208 /// Explicit instantiations for the three types. 209 /// \{ 210 template void 211 TypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data, 212 lldb::TypeFormatImplSP &retval); 213 template void 214 TypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data, 215 lldb::TypeSummaryImplSP &retval); 216 template void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>( 217 FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval); 218 /// \} 219 220 void TypeCategoryMap::ForEach(ForEachCallback callback) { 221 if (callback) { 222 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 223 224 // loop through enabled categories in respective order 225 { 226 ActiveCategoriesIterator begin, end = m_active_categories.end(); 227 for (begin = m_active_categories.begin(); begin != end; begin++) { 228 lldb::TypeCategoryImplSP category = *begin; 229 if (!callback(category)) 230 break; 231 } 232 } 233 234 // loop through disabled categories in just any order 235 { 236 MapIterator pos, end = m_map.end(); 237 for (pos = m_map.begin(); pos != end; pos++) { 238 if (pos->second->IsEnabled()) 239 continue; 240 if (!callback(pos->second)) 241 break; 242 } 243 } 244 } 245 } 246 247 TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) { 248 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 249 250 if (index < m_map.size()) { 251 MapIterator pos, end = m_map.end(); 252 for (pos = m_map.begin(); pos != end; pos++) { 253 if (index == 0) 254 return pos->second; 255 index--; 256 } 257 } 258 259 return TypeCategoryImplSP(); 260 } 261