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/ValueObject.h"
26 #include "lldb/DataFormatters/FormatClasses.h"
27 #include "lldb/DataFormatters/TypeFormat.h"
28 #include "lldb/DataFormatters/TypeSummary.h"
29 #include "lldb/DataFormatters/TypeSynthetic.h"
30 #include "lldb/DataFormatters/TypeValidator.h"
31 #include "lldb/Symbol/CompilerType.h"
32 #include "lldb/Utility/RegularExpression.h"
33 #include "lldb/Utility/StringLexer.h"
35 namespace lldb_private {
37 class IFormatChangeListener {
39 virtual ~IFormatChangeListener() = default;
41 virtual void Changed() = 0;
43 virtual uint32_t GetCurrentRevision() = 0;
46 // if the user tries to add formatters for, say, "struct Foo" those will not
47 // match any type because of the way we strip qualifiers from typenames this
48 // method looks for the case where the user is adding a "class","struct","enum"
49 // or "union" Foo and strips the unnecessary qualifier
50 static inline ConstString GetValidTypeName_Impl(const ConstString &type) {
54 std::string type_cstr(type.AsCString());
55 lldb_utility::StringLexer type_lexer(type_cstr);
57 type_lexer.AdvanceIf("class ");
58 type_lexer.AdvanceIf("enum ");
59 type_lexer.AdvanceIf("struct ");
60 type_lexer.AdvanceIf("union ");
62 while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
65 return ConstString(type_lexer.GetUnlexed());
68 template <typename KeyType, typename ValueType> class FormattersContainer;
70 template <typename KeyType, typename ValueType> class FormatMap {
72 typedef typename ValueType::SharedPointer ValueSP;
73 typedef std::map<KeyType, ValueSP> MapType;
74 typedef typename MapType::iterator MapIterator;
75 typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback;
77 FormatMap(IFormatChangeListener *lst)
78 : m_map(), m_map_mutex(), listener(lst) {}
80 void Add(KeyType name, const ValueSP &entry) {
82 entry->GetRevision() = listener->GetCurrentRevision();
84 entry->GetRevision() = 0;
86 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
92 bool Delete(KeyType name) {
93 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
94 MapIterator iter = m_map.find(name);
95 if (iter == m_map.end())
104 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
110 bool Get(KeyType name, ValueSP &entry) {
111 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
112 MapIterator iter = m_map.find(name);
113 if (iter == m_map.end())
115 entry = iter->second;
119 void ForEach(ForEachCallback callback) {
121 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
122 MapIterator pos, end = m_map.end();
123 for (pos = m_map.begin(); pos != end; pos++) {
124 KeyType type = pos->first;
125 if (!callback(type, pos->second))
131 uint32_t GetCount() { return m_map.size(); }
133 ValueSP GetValueAtIndex(size_t index) {
134 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
135 MapIterator iter = m_map.begin();
136 MapIterator end = m_map.end();
146 KeyType GetKeyAtIndex(size_t index) {
147 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
148 MapIterator iter = m_map.begin();
149 MapIterator end = m_map.end();
161 std::recursive_mutex m_map_mutex;
162 IFormatChangeListener *listener;
164 MapType &map() { return m_map; }
166 std::recursive_mutex &mutex() { return m_map_mutex; }
168 friend class FormattersContainer<KeyType, ValueType>;
169 friend class FormatManager;
172 template <typename KeyType, typename ValueType> class FormattersContainer {
174 typedef FormatMap<KeyType, ValueType> BackEndType;
177 typedef typename BackEndType::MapType MapType;
178 typedef typename MapType::iterator MapIterator;
179 typedef typename MapType::key_type MapKeyType;
180 typedef typename MapType::mapped_type MapValueType;
181 typedef typename BackEndType::ForEachCallback ForEachCallback;
182 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
185 friend class TypeCategoryImpl;
187 FormattersContainer(std::string name, IFormatChangeListener *lst)
188 : m_format_map(lst), m_name(name) {}
190 void Add(const MapKeyType &type, const MapValueType &entry) {
191 Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
194 bool Delete(ConstString type) {
195 return Delete_Impl(type, static_cast<KeyType *>(nullptr));
198 bool Get(ValueObject &valobj, MapValueType &entry,
199 lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) {
200 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
201 CompilerType ast_type(valobj.GetCompilerType());
202 bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
204 entry = MapValueType(entry);
206 entry = MapValueType();
212 bool Get(ConstString type, MapValueType &entry) {
213 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
216 bool GetExact(ConstString type, MapValueType &entry) {
217 return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
220 MapValueType GetAtIndex(size_t index) {
221 return m_format_map.GetValueAtIndex(index);
224 lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
225 return GetTypeNameSpecifierAtIndex_Impl(index,
226 static_cast<KeyType *>(nullptr));
229 void Clear() { m_format_map.Clear(); }
231 void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
233 uint32_t GetCount() { return m_format_map.GetCount(); }
236 BackEndType m_format_map;
239 DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
241 void Add_Impl(const MapKeyType &type, const MapValueType &entry,
242 lldb::RegularExpressionSP *dummy) {
243 m_format_map.Add(type, entry);
246 void Add_Impl(const ConstString &type, const MapValueType &entry,
247 ConstString *dummy) {
248 m_format_map.Add(GetValidTypeName_Impl(type), entry);
251 bool Delete_Impl(ConstString type, ConstString *dummy) {
252 return m_format_map.Delete(type);
255 bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) {
256 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
257 MapIterator pos, end = m_format_map.map().end();
258 for (pos = m_format_map.map().begin(); pos != end; pos++) {
259 lldb::RegularExpressionSP regex = pos->first;
260 if (type.GetStringRef() == regex->GetText()) {
261 m_format_map.map().erase(pos);
262 if (m_format_map.listener)
263 m_format_map.listener->Changed();
270 bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
271 return m_format_map.Get(type, entry);
274 bool GetExact_Impl(ConstString type, MapValueType &entry,
275 ConstString *dummy) {
276 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
279 lldb::TypeNameSpecifierImplSP
280 GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
281 ConstString key = m_format_map.GetKeyAtIndex(index);
283 return lldb::TypeNameSpecifierImplSP(
284 new TypeNameSpecifierImpl(key.AsCString(), false));
286 return lldb::TypeNameSpecifierImplSP();
289 lldb::TypeNameSpecifierImplSP
290 GetTypeNameSpecifierAtIndex_Impl(size_t index,
291 lldb::RegularExpressionSP *dummy) {
292 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
293 if (regex.get() == nullptr)
294 return lldb::TypeNameSpecifierImplSP();
295 return lldb::TypeNameSpecifierImplSP(
296 new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true));
299 bool Get_Impl(ConstString key, MapValueType &value,
300 lldb::RegularExpressionSP *dummy) {
301 llvm::StringRef key_str = key.GetStringRef();
302 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
303 MapIterator pos, end = m_format_map.map().end();
304 for (pos = m_format_map.map().begin(); pos != end; pos++) {
305 lldb::RegularExpressionSP regex = pos->first;
306 if (regex->Execute(key_str)) {
314 bool GetExact_Impl(ConstString key, MapValueType &value,
315 lldb::RegularExpressionSP *dummy) {
316 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
317 MapIterator pos, end = m_format_map.map().end();
318 for (pos = m_format_map.map().begin(); pos != end; pos++) {
319 lldb::RegularExpressionSP regex = pos->first;
320 if (regex->GetText() == key.GetStringRef()) {
328 bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
330 for (const FormattersMatchCandidate &candidate : candidates) {
331 if (Get(candidate.GetTypeName(), entry)) {
332 if (candidate.IsMatch(entry) == false) {
337 *reason = candidate.GetReason();
346 } // namespace lldb_private
348 #endif // lldb_FormattersContainer_h_