1 //===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef lldb_FormattersContainer_h_
11 #define lldb_FormattersContainer_h_
21 // Other libraries and framework includes
23 #include "lldb/lldb-public.h"
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"
35 namespace lldb_private {
37 class IFormatChangeListener
41 ~IFormatChangeListener() = default;
47 GetCurrentRevision () = 0;
50 // if the user tries to add formatters for, say, "struct Foo"
51 // those will not match any type because of the way we strip qualifiers from typenames
52 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
53 // and strips the unnecessary qualifier
54 static inline ConstString
55 GetValidTypeName_Impl (const ConstString& type)
60 std::string type_cstr(type.AsCString());
61 lldb_utility::StringLexer type_lexer(type_cstr);
63 type_lexer.AdvanceIf("class ");
64 type_lexer.AdvanceIf("enum ");
65 type_lexer.AdvanceIf("struct ");
66 type_lexer.AdvanceIf("union ");
68 while (type_lexer.NextIf({' ','\t','\v','\f'}).first)
71 return ConstString(type_lexer.GetUnlexed());
74 template<typename KeyType, typename ValueType>
75 class FormattersContainer;
77 template<typename KeyType, typename ValueType>
81 typedef typename ValueType::SharedPointer ValueSP;
82 typedef std::map<KeyType, ValueSP> MapType;
83 typedef typename MapType::iterator MapIterator;
84 typedef std::function<bool(KeyType, const ValueSP&)> ForEachCallback;
86 FormatMap(IFormatChangeListener *lst) : m_map(), m_map_mutex(), listener(lst) {}
89 Add(KeyType name, const ValueSP &entry)
92 entry->GetRevision() = listener->GetCurrentRevision();
94 entry->GetRevision() = 0;
96 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
105 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
106 MapIterator iter = m_map.find(name);
107 if (iter == m_map.end())
118 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
125 Get(KeyType name, ValueSP &entry)
127 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
128 MapIterator iter = m_map.find(name);
129 if (iter == m_map.end())
131 entry = iter->second;
136 ForEach(ForEachCallback callback)
140 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
141 MapIterator pos, end = m_map.end();
142 for (pos = m_map.begin(); pos != end; pos++)
144 KeyType type = pos->first;
145 if (!callback(type, pos->second))
158 GetValueAtIndex(size_t index)
160 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
161 MapIterator iter = m_map.begin();
162 MapIterator end = m_map.end();
174 GetKeyAtIndex(size_t index)
176 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
177 MapIterator iter = m_map.begin();
178 MapIterator end = m_map.end();
191 std::recursive_mutex m_map_mutex;
192 IFormatChangeListener* listener;
200 std::recursive_mutex &
206 friend class FormattersContainer<KeyType, ValueType>;
207 friend class FormatManager;
210 template<typename KeyType, typename ValueType>
211 class FormattersContainer
214 typedef FormatMap<KeyType,ValueType> BackEndType;
217 typedef typename BackEndType::MapType MapType;
218 typedef typename MapType::iterator MapIterator;
219 typedef typename MapType::key_type MapKeyType;
220 typedef typename MapType::mapped_type MapValueType;
221 typedef typename BackEndType::ForEachCallback ForEachCallback;
222 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
224 friend class TypeCategoryImpl;
226 FormattersContainer(std::string name,
227 IFormatChangeListener* lst) :
234 Add (const MapKeyType &type, const MapValueType& entry)
236 Add_Impl(type, entry, static_cast<KeyType*>(nullptr));
240 Delete (ConstString type)
242 return Delete_Impl(type, static_cast<KeyType*>(nullptr));
246 Get(ValueObject& valobj,
248 lldb::DynamicValueType use_dynamic,
249 uint32_t* why = nullptr)
251 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
252 CompilerType ast_type(valobj.GetCompilerType());
253 bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
255 entry = MapValueType(entry);
257 entry = MapValueType();
264 Get (ConstString type, MapValueType& entry)
266 return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
270 GetExact (ConstString type, MapValueType& entry)
272 return GetExact_Impl(type, entry, static_cast<KeyType*>(nullptr));
276 GetAtIndex (size_t index)
278 return m_format_map.GetValueAtIndex(index);
281 lldb::TypeNameSpecifierImplSP
282 GetTypeNameSpecifierAtIndex (size_t index)
284 return GetTypeNameSpecifierAtIndex_Impl(index, static_cast<KeyType*>(nullptr));
290 m_format_map.Clear();
294 ForEach (ForEachCallback callback)
296 m_format_map.ForEach(callback);
302 return m_format_map.GetCount();
306 BackEndType m_format_map;
309 DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
312 Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
314 m_format_map.Add(type,entry);
317 void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
319 m_format_map.Add(GetValidTypeName_Impl(type), entry);
323 Delete_Impl (ConstString type, ConstString *dummy)
325 return m_format_map.Delete(type);
329 Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy)
331 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
332 MapIterator pos, end = m_format_map.map().end();
333 for (pos = m_format_map.map().begin(); pos != end; pos++)
335 lldb::RegularExpressionSP regex = pos->first;
336 if (::strcmp(type.AsCString(), regex->GetText()) == 0)
338 m_format_map.map().erase(pos);
339 if (m_format_map.listener)
340 m_format_map.listener->Changed();
348 Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
350 return m_format_map.Get(type, entry);
354 GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
356 return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
359 lldb::TypeNameSpecifierImplSP
360 GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
362 ConstString key = m_format_map.GetKeyAtIndex(index);
364 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
367 return lldb::TypeNameSpecifierImplSP();
370 lldb::TypeNameSpecifierImplSP
371 GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
373 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
374 if (regex.get() == nullptr)
375 return lldb::TypeNameSpecifierImplSP();
376 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
381 Get_Impl(ConstString key, MapValueType &value, lldb::RegularExpressionSP *dummy)
383 const char *key_cstr = key.AsCString();
386 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
387 MapIterator pos, end = m_format_map.map().end();
388 for (pos = m_format_map.map().begin(); pos != end; pos++)
390 lldb::RegularExpressionSP regex = pos->first;
391 if (regex->Execute(key_cstr))
401 GetExact_Impl(ConstString key, MapValueType &value, lldb::RegularExpressionSP *dummy)
403 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
404 MapIterator pos, end = m_format_map.map().end();
405 for (pos = m_format_map.map().begin(); pos != end; pos++)
407 lldb::RegularExpressionSP regex = pos->first;
408 if (strcmp(regex->GetText(), key.AsCString()) == 0)
418 Get (const FormattersMatchVector& candidates,
422 for (const FormattersMatchCandidate& candidate : candidates)
424 if (Get(candidate.GetTypeName(),entry))
426 if (candidate.IsMatch(entry) == false)
434 *reason = candidate.GetReason();
443 } // namespace lldb_private
445 #endif // lldb_FormattersContainer_h_