FormattersContainer.h revision 314564
1296417Sdim//===-- FormattersContainer.h -----------------------------------*- C++ -*-===// 2262182Semaste// 3262182Semaste// The LLVM Compiler Infrastructure 4262182Semaste// 5262182Semaste// This file is distributed under the University of Illinois Open Source 6262182Semaste// License. See LICENSE.TXT for details. 7262182Semaste// 8262182Semaste//===----------------------------------------------------------------------===// 9262182Semaste 10262182Semaste#ifndef lldb_FormattersContainer_h_ 11262182Semaste#define lldb_FormattersContainer_h_ 12262182Semaste 13262182Semaste// C Includes 14262182Semaste// C++ Includes 15296417Sdim#include <functional> 16296417Sdim#include <map> 17296417Sdim#include <memory> 18309124Sdim#include <mutex> 19296417Sdim#include <string> 20262182Semaste 21262182Semaste// Other libraries and framework includes 22262182Semaste// Project includes 23262182Semaste#include "lldb/lldb-public.h" 24262182Semaste 25262182Semaste#include "lldb/Core/RegularExpression.h" 26262182Semaste#include "lldb/Core/ValueObject.h" 27262182Semaste#include "lldb/DataFormatters/FormatClasses.h" 28262182Semaste#include "lldb/DataFormatters/TypeFormat.h" 29262182Semaste#include "lldb/DataFormatters/TypeSummary.h" 30262182Semaste#include "lldb/DataFormatters/TypeSynthetic.h" 31280031Sdim#include "lldb/DataFormatters/TypeValidator.h" 32296417Sdim#include "lldb/Symbol/CompilerType.h" 33280031Sdim#include "lldb/Utility/StringLexer.h" 34280031Sdim 35262182Semastenamespace lldb_private { 36314564Sdim 37314564Sdimclass IFormatChangeListener { 38262182Semastepublic: 39314564Sdim virtual ~IFormatChangeListener() = default; 40296417Sdim 41314564Sdim virtual void Changed() = 0; 42296417Sdim 43314564Sdim virtual uint32_t GetCurrentRevision() = 0; 44262182Semaste}; 45314564Sdim 46262182Semaste// if the user tries to add formatters for, say, "struct Foo" 47314564Sdim// those will not match any type because of the way we strip qualifiers from 48314564Sdim// typenames 49314564Sdim// this method looks for the case where the user is adding a 50314564Sdim// "class","struct","enum" or "union" Foo 51262182Semaste// and strips the unnecessary qualifier 52314564Sdimstatic inline ConstString GetValidTypeName_Impl(const ConstString &type) { 53314564Sdim if (type.IsEmpty()) 54314564Sdim return type; 55314564Sdim 56314564Sdim std::string type_cstr(type.AsCString()); 57314564Sdim lldb_utility::StringLexer type_lexer(type_cstr); 58314564Sdim 59314564Sdim type_lexer.AdvanceIf("class "); 60314564Sdim type_lexer.AdvanceIf("enum "); 61314564Sdim type_lexer.AdvanceIf("struct "); 62314564Sdim type_lexer.AdvanceIf("union "); 63314564Sdim 64314564Sdim while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first) 65314564Sdim ; 66314564Sdim 67314564Sdim return ConstString(type_lexer.GetUnlexed()); 68262182Semaste} 69280031Sdim 70314564Sdimtemplate <typename KeyType, typename ValueType> class FormattersContainer; 71262182Semaste 72314564Sdimtemplate <typename KeyType, typename ValueType> class FormatMap { 73262182Semastepublic: 74314564Sdim typedef typename ValueType::SharedPointer ValueSP; 75314564Sdim typedef std::map<KeyType, ValueSP> MapType; 76314564Sdim typedef typename MapType::iterator MapIterator; 77314564Sdim typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback; 78309124Sdim 79314564Sdim FormatMap(IFormatChangeListener *lst) 80314564Sdim : m_map(), m_map_mutex(), listener(lst) {} 81309124Sdim 82314564Sdim void Add(KeyType name, const ValueSP &entry) { 83314564Sdim if (listener) 84314564Sdim entry->GetRevision() = listener->GetCurrentRevision(); 85314564Sdim else 86314564Sdim entry->GetRevision() = 0; 87262182Semaste 88314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 89314564Sdim m_map[name] = entry; 90314564Sdim if (listener) 91314564Sdim listener->Changed(); 92314564Sdim } 93309124Sdim 94314564Sdim bool Delete(KeyType name) { 95314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 96314564Sdim MapIterator iter = m_map.find(name); 97314564Sdim if (iter == m_map.end()) 98314564Sdim return false; 99314564Sdim m_map.erase(name); 100314564Sdim if (listener) 101314564Sdim listener->Changed(); 102314564Sdim return true; 103314564Sdim } 104309124Sdim 105314564Sdim void Clear() { 106314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 107314564Sdim m_map.clear(); 108314564Sdim if (listener) 109314564Sdim listener->Changed(); 110314564Sdim } 111309124Sdim 112314564Sdim bool Get(KeyType name, ValueSP &entry) { 113314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 114314564Sdim MapIterator iter = m_map.find(name); 115314564Sdim if (iter == m_map.end()) 116314564Sdim return false; 117314564Sdim entry = iter->second; 118314564Sdim return true; 119314564Sdim } 120309124Sdim 121314564Sdim void ForEach(ForEachCallback callback) { 122314564Sdim if (callback) { 123314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 124314564Sdim MapIterator pos, end = m_map.end(); 125314564Sdim for (pos = m_map.begin(); pos != end; pos++) { 126314564Sdim KeyType type = pos->first; 127314564Sdim if (!callback(type, pos->second)) 128314564Sdim break; 129314564Sdim } 130262182Semaste } 131314564Sdim } 132309124Sdim 133314564Sdim uint32_t GetCount() { return m_map.size(); } 134309124Sdim 135314564Sdim ValueSP GetValueAtIndex(size_t index) { 136314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 137314564Sdim MapIterator iter = m_map.begin(); 138314564Sdim MapIterator end = m_map.end(); 139314564Sdim while (index > 0) { 140314564Sdim iter++; 141314564Sdim index--; 142314564Sdim if (end == iter) 143314564Sdim return ValueSP(); 144262182Semaste } 145314564Sdim return iter->second; 146314564Sdim } 147309124Sdim 148314564Sdim KeyType GetKeyAtIndex(size_t index) { 149314564Sdim std::lock_guard<std::recursive_mutex> guard(m_map_mutex); 150314564Sdim MapIterator iter = m_map.begin(); 151314564Sdim MapIterator end = m_map.end(); 152314564Sdim while (index > 0) { 153314564Sdim iter++; 154314564Sdim index--; 155314564Sdim if (end == iter) 156314564Sdim return KeyType(); 157262182Semaste } 158314564Sdim return iter->first; 159314564Sdim } 160309124Sdim 161262182Semasteprotected: 162314564Sdim MapType m_map; 163314564Sdim std::recursive_mutex m_map_mutex; 164314564Sdim IFormatChangeListener *listener; 165309124Sdim 166314564Sdim MapType &map() { return m_map; } 167309124Sdim 168314564Sdim std::recursive_mutex &mutex() { return m_map_mutex; } 169309124Sdim 170314564Sdim friend class FormattersContainer<KeyType, ValueType>; 171314564Sdim friend class FormatManager; 172262182Semaste}; 173314564Sdim 174314564Sdimtemplate <typename KeyType, typename ValueType> class FormattersContainer { 175262182Semasteprotected: 176314564Sdim typedef FormatMap<KeyType, ValueType> BackEndType; 177314564Sdim 178262182Semastepublic: 179314564Sdim typedef typename BackEndType::MapType MapType; 180314564Sdim typedef typename MapType::iterator MapIterator; 181314564Sdim typedef typename MapType::key_type MapKeyType; 182314564Sdim typedef typename MapType::mapped_type MapValueType; 183314564Sdim typedef typename BackEndType::ForEachCallback ForEachCallback; 184314564Sdim typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>> 185314564Sdim SharedPointer; 186262182Semaste 187314564Sdim friend class TypeCategoryImpl; 188314564Sdim 189314564Sdim FormattersContainer(std::string name, IFormatChangeListener *lst) 190314564Sdim : m_format_map(lst), m_name(name) {} 191314564Sdim 192314564Sdim void Add(const MapKeyType &type, const MapValueType &entry) { 193314564Sdim Add_Impl(type, entry, static_cast<KeyType *>(nullptr)); 194314564Sdim } 195314564Sdim 196314564Sdim bool Delete(ConstString type) { 197314564Sdim return Delete_Impl(type, static_cast<KeyType *>(nullptr)); 198314564Sdim } 199314564Sdim 200314564Sdim bool Get(ValueObject &valobj, MapValueType &entry, 201314564Sdim lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) { 202314564Sdim uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice; 203314564Sdim CompilerType ast_type(valobj.GetCompilerType()); 204314564Sdim bool ret = Get(valobj, ast_type, entry, use_dynamic, value); 205314564Sdim if (ret) 206314564Sdim entry = MapValueType(entry); 207314564Sdim else 208314564Sdim entry = MapValueType(); 209314564Sdim if (why) 210314564Sdim *why = value; 211314564Sdim return ret; 212314564Sdim } 213314564Sdim 214314564Sdim bool Get(ConstString type, MapValueType &entry) { 215314564Sdim return Get_Impl(type, entry, static_cast<KeyType *>(nullptr)); 216314564Sdim } 217314564Sdim 218314564Sdim bool GetExact(ConstString type, MapValueType &entry) { 219314564Sdim return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr)); 220314564Sdim } 221314564Sdim 222314564Sdim MapValueType GetAtIndex(size_t index) { 223314564Sdim return m_format_map.GetValueAtIndex(index); 224314564Sdim } 225314564Sdim 226314564Sdim lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) { 227314564Sdim return GetTypeNameSpecifierAtIndex_Impl(index, 228314564Sdim static_cast<KeyType *>(nullptr)); 229314564Sdim } 230314564Sdim 231314564Sdim void Clear() { m_format_map.Clear(); } 232314564Sdim 233314564Sdim void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); } 234314564Sdim 235314564Sdim uint32_t GetCount() { return m_format_map.GetCount(); } 236314564Sdim 237262182Semasteprotected: 238314564Sdim BackEndType m_format_map; 239314564Sdim std::string m_name; 240262182Semaste 241314564Sdim DISALLOW_COPY_AND_ASSIGN(FormattersContainer); 242262182Semaste 243314564Sdim void Add_Impl(const MapKeyType &type, const MapValueType &entry, 244314564Sdim lldb::RegularExpressionSP *dummy) { 245314564Sdim m_format_map.Add(type, entry); 246314564Sdim } 247262182Semaste 248314564Sdim void Add_Impl(const ConstString &type, const MapValueType &entry, 249314564Sdim ConstString *dummy) { 250314564Sdim m_format_map.Add(GetValidTypeName_Impl(type), entry); 251314564Sdim } 252262182Semaste 253314564Sdim bool Delete_Impl(ConstString type, ConstString *dummy) { 254314564Sdim return m_format_map.Delete(type); 255314564Sdim } 256262182Semaste 257314564Sdim bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) { 258314564Sdim std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 259314564Sdim MapIterator pos, end = m_format_map.map().end(); 260314564Sdim for (pos = m_format_map.map().begin(); pos != end; pos++) { 261314564Sdim lldb::RegularExpressionSP regex = pos->first; 262314564Sdim if (type.GetStringRef() == regex->GetText()) { 263314564Sdim m_format_map.map().erase(pos); 264314564Sdim if (m_format_map.listener) 265314564Sdim m_format_map.listener->Changed(); 266314564Sdim return true; 267314564Sdim } 268262182Semaste } 269314564Sdim return false; 270314564Sdim } 271262182Semaste 272314564Sdim bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) { 273314564Sdim return m_format_map.Get(type, entry); 274314564Sdim } 275314564Sdim 276314564Sdim bool GetExact_Impl(ConstString type, MapValueType &entry, 277314564Sdim ConstString *dummy) { 278314564Sdim return Get_Impl(type, entry, static_cast<KeyType *>(nullptr)); 279314564Sdim } 280314564Sdim 281314564Sdim lldb::TypeNameSpecifierImplSP 282314564Sdim GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) { 283314564Sdim ConstString key = m_format_map.GetKeyAtIndex(index); 284314564Sdim if (key) 285314564Sdim return lldb::TypeNameSpecifierImplSP( 286314564Sdim new TypeNameSpecifierImpl(key.AsCString(), false)); 287314564Sdim else 288314564Sdim return lldb::TypeNameSpecifierImplSP(); 289314564Sdim } 290314564Sdim 291314564Sdim lldb::TypeNameSpecifierImplSP 292314564Sdim GetTypeNameSpecifierAtIndex_Impl(size_t index, 293314564Sdim lldb::RegularExpressionSP *dummy) { 294314564Sdim lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index); 295314564Sdim if (regex.get() == nullptr) 296314564Sdim return lldb::TypeNameSpecifierImplSP(); 297314564Sdim return lldb::TypeNameSpecifierImplSP( 298314564Sdim new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true)); 299314564Sdim } 300314564Sdim 301314564Sdim bool Get_Impl(ConstString key, MapValueType &value, 302314564Sdim lldb::RegularExpressionSP *dummy) { 303314564Sdim llvm::StringRef key_str = key.GetStringRef(); 304314564Sdim std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 305314564Sdim MapIterator pos, end = m_format_map.map().end(); 306314564Sdim for (pos = m_format_map.map().begin(); pos != end; pos++) { 307314564Sdim lldb::RegularExpressionSP regex = pos->first; 308314564Sdim if (regex->Execute(key_str)) { 309314564Sdim value = pos->second; 310314564Sdim return true; 311314564Sdim } 312262182Semaste } 313314564Sdim return false; 314314564Sdim } 315309124Sdim 316314564Sdim bool GetExact_Impl(ConstString key, MapValueType &value, 317314564Sdim lldb::RegularExpressionSP *dummy) { 318314564Sdim std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex()); 319314564Sdim MapIterator pos, end = m_format_map.map().end(); 320314564Sdim for (pos = m_format_map.map().begin(); pos != end; pos++) { 321314564Sdim lldb::RegularExpressionSP regex = pos->first; 322314564Sdim if (regex->GetText() == key.GetStringRef()) { 323314564Sdim value = pos->second; 324314564Sdim return true; 325314564Sdim } 326262182Semaste } 327314564Sdim return false; 328314564Sdim } 329262182Semaste 330314564Sdim bool Get(const FormattersMatchVector &candidates, MapValueType &entry, 331314564Sdim uint32_t *reason) { 332314564Sdim for (const FormattersMatchCandidate &candidate : candidates) { 333314564Sdim if (Get(candidate.GetTypeName(), entry)) { 334314564Sdim if (candidate.IsMatch(entry) == false) { 335314564Sdim entry.reset(); 336314564Sdim continue; 337314564Sdim } else { 338314564Sdim if (reason) 339314564Sdim *reason = candidate.GetReason(); 340314564Sdim return true; 341262182Semaste } 342314564Sdim } 343262182Semaste } 344314564Sdim return false; 345314564Sdim } 346262182Semaste}; 347262182Semaste 348262182Semaste} // namespace lldb_private 349262182Semaste 350296417Sdim#endif // lldb_FormattersContainer_h_ 351