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/LLDBLog.h" 13 #include "lldb/Utility/Log.h" 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 const FormattersMatchCandidate &candidate_type, 158 TypeCategoryImpl::FormatCategoryItems items, bool only_enabled, 159 const char **matching_category, 160 TypeCategoryImpl::FormatCategoryItems *matching_type) { 161 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 162 163 MapIterator pos, end = m_map.end(); 164 for (pos = m_map.begin(); pos != end; pos++) { 165 if (pos->second->AnyMatches(candidate_type, items, only_enabled, 166 matching_category, matching_type)) 167 return true; 168 } 169 return false; 170 } 171 172 template <typename ImplSP> 173 void TypeCategoryMap::Get(FormattersMatchData &match_data, ImplSP &retval) { 174 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 175 176 ActiveCategoriesIterator begin, end = m_active_categories.end(); 177 178 Log *log = GetLog(LLDBLog::DataFormatters); 179 180 if (log) { 181 for (auto match : match_data.GetMatchesVector()) { 182 LLDB_LOGF( 183 log, 184 "[%s] candidate match = %s %s %s %s", 185 __FUNCTION__, 186 match.GetTypeName().GetCString(), 187 match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers", 188 match.DidStripReference() ? "strip-reference" : "no-strip-reference", 189 match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef"); 190 } 191 } 192 193 for (begin = m_active_categories.begin(); begin != end; begin++) { 194 lldb::TypeCategoryImplSP category_sp = *begin; 195 ImplSP current_format; 196 LLDB_LOGF(log, "[%s] Trying to use category %s", __FUNCTION__, 197 category_sp->GetName()); 198 if (!category_sp->Get( 199 match_data.GetValueObject().GetObjectRuntimeLanguage(), 200 match_data.GetMatchesVector(), current_format)) 201 continue; 202 203 retval = std::move(current_format); 204 return; 205 } 206 LLDB_LOGF(log, "[%s] nothing found - returning empty SP", __FUNCTION__); 207 } 208 209 /// Explicit instantiations for the three types. 210 /// \{ 211 template void 212 TypeCategoryMap::Get<lldb::TypeFormatImplSP>(FormattersMatchData &match_data, 213 lldb::TypeFormatImplSP &retval); 214 template void 215 TypeCategoryMap::Get<lldb::TypeSummaryImplSP>(FormattersMatchData &match_data, 216 lldb::TypeSummaryImplSP &retval); 217 template void TypeCategoryMap::Get<lldb::SyntheticChildrenSP>( 218 FormattersMatchData &match_data, lldb::SyntheticChildrenSP &retval); 219 /// \} 220 221 void TypeCategoryMap::ForEach(ForEachCallback callback) { 222 if (callback) { 223 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 224 225 // loop through enabled categories in respective order 226 { 227 ActiveCategoriesIterator begin, end = m_active_categories.end(); 228 for (begin = m_active_categories.begin(); begin != end; begin++) { 229 lldb::TypeCategoryImplSP category = *begin; 230 if (!callback(category)) 231 break; 232 } 233 } 234 235 // loop through disabled categories in just any order 236 { 237 MapIterator pos, end = m_map.end(); 238 for (pos = m_map.begin(); pos != end; pos++) { 239 if (pos->second->IsEnabled()) 240 continue; 241 if (!callback(pos->second)) 242 break; 243 } 244 } 245 } 246 } 247 248 TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) { 249 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 250 251 if (index < m_map.size()) { 252 MapIterator pos, end = m_map.end(); 253 for (pos = m_map.begin(); pos != end; pos++) { 254 if (index == 0) 255 return pos->second; 256 index--; 257 } 258 } 259 260 return TypeCategoryImplSP(); 261 } 262