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