FormattersContainer.h revision 314564
1//===-- FormattersContainer.h -----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#ifndef lldb_FormattersContainer_h_ 11#define lldb_FormattersContainer_h_ 12 13// C Includes 14// C++ Includes 15#include <functional> 16#include <map> 17#include <memory> 18#include <mutex> 19#include <string> 20 21// Other libraries and framework includes 22// Project includes 23#include "lldb/lldb-public.h" 24 25#include "lldb/Core/RegularExpression.h" 26#include "lldb/Core/ValueObject.h" 27#include "lldb/DataFormatters/FormatClasses.h" 28#include "lldb/DataFormatters/TypeFormat.h" 29#include "lldb/DataFormatters/TypeSummary.h" 30#include "lldb/DataFormatters/TypeSynthetic.h" 31#include "lldb/DataFormatters/TypeValidator.h" 32#include "lldb/Symbol/CompilerType.h" 33#include "lldb/Utility/StringLexer.h" 34 35namespace lldb_private { 36 37class IFormatChangeListener { 38public: 39 virtual ~IFormatChangeListener() = default; 40 41 virtual void Changed() = 0; 42 43 virtual uint32_t GetCurrentRevision() = 0; 44}; 45 46// if the user tries to add formatters for, say, "struct Foo" 47// those will not match any type because of the way we strip qualifiers from 48// typenames 49// this method looks for the case where the user is adding a 50// "class","struct","enum" or "union" Foo 51// and strips the unnecessary qualifier 52static inline ConstString GetValidTypeName_Impl(const ConstString &type) { 53 if (type.IsEmpty()) 54 return type; 55 56 std::string type_cstr(type.AsCString()); 57 lldb_utility::StringLexer type_lexer(type_cstr); 58 59 type_lexer.AdvanceIf("class "); 60 type_lexer.AdvanceIf("enum "); 61 type_lexer.AdvanceIf("struct "); 62 type_lexer.AdvanceIf("union "); 63 64 while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first) 65 ; 66 67 return ConstString(type_lexer.GetUnlexed()); 68} 69 70template <typename KeyType, typename ValueType> class FormattersContainer; 71 72template <typename KeyType, typename ValueType> class FormatMap { 73public: 74 typedef typename ValueType::SharedPointer ValueSP; 75 typedef std::map<KeyType, ValueSP> MapType; 76 typedef typename MapType::iterator MapIterator; 77 typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback; 78 79 FormatMap(IFormatChangeListener *lst) 80 : m_map(), m_map_mutex(), listener(lst) {} 81 82 void Add(KeyType name, const ValueSP &entry) { 83 if (listener) 84 entry->GetRevision() = listener->GetCurrentRevision(); 85 else 86 entry->GetRevision() = 0; 87 88 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 89 m_map[name] = entry; 90 if (listener) 91 listener->Changed(); 92 } 93 94 bool Delete(KeyType name) { 95 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 96 MapIterator iter = m_map.find(name); 97 if (iter == m_map.end()) 98 return false; 99 m_map.erase(name); 100 if (listener) 101 listener->Changed(); 102 return true; 103 } 104 105 void Clear() { 106 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 107 m_map.clear(); 108 if (listener) 109 listener->Changed(); 110 } 111 112 bool Get(KeyType name, ValueSP &entry) { 113 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 114 MapIterator iter = m_map.find(name); 115 if (iter == m_map.end()) 116 return false; 117 entry = iter->second; 118 return true; 119 } 120 121 void ForEach(ForEachCallback callback) { 122 if (callback) { 123 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 124 MapIterator pos, end = m_map.end(); 125 for (pos = m_map.begin(); pos != end; pos++) { 126 KeyType type = pos->first; 127 if (!callback(type, pos->second)) 128 break; 129 } 130 } 131 } 132 133 uint32_t GetCount() { return m_map.size(); } 134 135 ValueSP GetValueAtIndex(size_t index) { 136 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 137 MapIterator iter = m_map.begin(); 138 MapIterator end = m_map.end(); 139 while (index > 0) { 140 iter++; 141 index--; 142 if (end == iter) 143 return ValueSP(); 144 } 145 return iter->second; 146 } 147 148 KeyType GetKeyAtIndex(size_t index) { 149 std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 150 MapIterator iter = m_map.begin(); 151 MapIterator end = m_map.end(); 152 while (index > 0) { 153 iter++; 154 index--; 155 if (end == iter) 156 return KeyType(); 157 } 158 return iter->first; 159 } 160 161protected: 162 MapType m_map; 163 std::recursive_mutex m_map_mutex; 164 IFormatChangeListener *listener; 165 166 MapType &map() { return m_map; } 167 168 std::recursive_mutex &mutex() { return m_map_mutex; } 169 170 friend class FormattersContainer<KeyType, ValueType>; 171 friend class FormatManager; 172}; 173 174template <typename KeyType, typename ValueType> class FormattersContainer { 175protected: 176 typedef FormatMap<KeyType, ValueType> BackEndType; 177 178public: 179 typedef typename BackEndType::MapType MapType; 180 typedef typename MapType::iterator MapIterator; 181 typedef typename MapType::key_type MapKeyType; 182 typedef typename MapType::mapped_type MapValueType; 183 typedef typename BackEndType::ForEachCallback ForEachCallback; 184 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>> 185 SharedPointer; 186 187 friend class TypeCategoryImpl; 188 189 FormattersContainer(std::string name, IFormatChangeListener *lst) 190 : m_format_map(lst), m_name(name) {} 191 192 void Add(const MapKeyType &type, const MapValueType &entry) { 193 Add_Impl(type, entry, static_cast<KeyType *>(nullptr)); 194 } 195 196 bool Delete(ConstString type) { 197 return Delete_Impl(type, static_cast<KeyType *>(nullptr)); 198 } 199 200 bool Get(ValueObject &valobj, MapValueType &entry, 201 lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) { 202 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; 203 CompilerType ast_type(valobj.GetCompilerType()); 204 bool ret = Get(valobj, ast_type, entry, use_dynamic, value); 205 if (ret) 206 entry = MapValueType(entry); 207 else 208 entry = MapValueType(); 209 if (why) 210 *why = value; 211 return ret; 212 } 213 214 bool Get(ConstString type, MapValueType &entry) { 215 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr)); 216 } 217 218 bool GetExact(ConstString type, MapValueType &entry) { 219 return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr)); 220 } 221 222 MapValueType GetAtIndex(size_t index) { 223 return m_format_map.GetValueAtIndex(index); 224 } 225 226 lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) { 227 return GetTypeNameSpecifierAtIndex_Impl(index, 228 static_cast<KeyType *>(nullptr)); 229 } 230 231 void Clear() { m_format_map.Clear(); } 232 233 void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); } 234 235 uint32_t GetCount() { return m_format_map.GetCount(); } 236 237protected: 238 BackEndType m_format_map; 239 std::string m_name; 240 241 DISALLOW_COPY_AND_ASSIGN(FormattersContainer); 242 243 void Add_Impl(const MapKeyType &type, const MapValueType &entry, 244 lldb::RegularExpressionSP *dummy) { 245 m_format_map.Add(type, entry); 246 } 247 248 void Add_Impl(const ConstString &type, const MapValueType &entry, 249 ConstString *dummy) { 250 m_format_map.Add(GetValidTypeName_Impl(type), entry); 251 } 252 253 bool Delete_Impl(ConstString type, ConstString *dummy) { 254 return m_format_map.Delete(type); 255 } 256 257 bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) { 258 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 259 MapIterator pos, end = m_format_map.map().end(); 260 for (pos = m_format_map.map().begin(); pos != end; pos++) { 261 lldb::RegularExpressionSP regex = pos->first; 262 if (type.GetStringRef() == regex->GetText()) { 263 m_format_map.map().erase(pos); 264 if (m_format_map.listener) 265 m_format_map.listener->Changed(); 266 return true; 267 } 268 } 269 return false; 270 } 271 272 bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) { 273 return m_format_map.Get(type, entry); 274 } 275 276 bool GetExact_Impl(ConstString type, MapValueType &entry, 277 ConstString *dummy) { 278 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr)); 279 } 280 281 lldb::TypeNameSpecifierImplSP 282 GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) { 283 ConstString key = m_format_map.GetKeyAtIndex(index); 284 if (key) 285 return lldb::TypeNameSpecifierImplSP( 286 new TypeNameSpecifierImpl(key.AsCString(), false)); 287 else 288 return lldb::TypeNameSpecifierImplSP(); 289 } 290 291 lldb::TypeNameSpecifierImplSP 292 GetTypeNameSpecifierAtIndex_Impl(size_t index, 293 lldb::RegularExpressionSP *dummy) { 294 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); 295 if (regex.get() == nullptr) 296 return lldb::TypeNameSpecifierImplSP(); 297 return lldb::TypeNameSpecifierImplSP( 298 new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true)); 299 } 300 301 bool Get_Impl(ConstString key, MapValueType &value, 302 lldb::RegularExpressionSP *dummy) { 303 llvm::StringRef key_str = key.GetStringRef(); 304 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 305 MapIterator pos, end = m_format_map.map().end(); 306 for (pos = m_format_map.map().begin(); pos != end; pos++) { 307 lldb::RegularExpressionSP regex = pos->first; 308 if (regex->Execute(key_str)) { 309 value = pos->second; 310 return true; 311 } 312 } 313 return false; 314 } 315 316 bool GetExact_Impl(ConstString key, MapValueType &value, 317 lldb::RegularExpressionSP *dummy) { 318 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 319 MapIterator pos, end = m_format_map.map().end(); 320 for (pos = m_format_map.map().begin(); pos != end; pos++) { 321 lldb::RegularExpressionSP regex = pos->first; 322 if (regex->GetText() == key.GetStringRef()) { 323 value = pos->second; 324 return true; 325 } 326 } 327 return false; 328 } 329 330 bool Get(const FormattersMatchVector &candidates, MapValueType &entry, 331 uint32_t *reason) { 332 for (const FormattersMatchCandidate &candidate : candidates) { 333 if (Get(candidate.GetTypeName(), entry)) { 334 if (candidate.IsMatch(entry) == false) { 335 entry.reset(); 336 continue; 337 } else { 338 if (reason) 339 *reason = candidate.GetReason(); 340 return true; 341 } 342 } 343 } 344 return false; 345 } 346}; 347 348} // namespace lldb_private 349 350#endif // lldb_FormattersContainer_h_ 351