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_
19 #include "lldb/lldb-public.h"
21 #include "lldb/Core/ValueObject.h"
22 #include "lldb/DataFormatters/FormatClasses.h"
23 #include "lldb/DataFormatters/TypeFormat.h"
24 #include "lldb/DataFormatters/TypeSummary.h"
25 #include "lldb/DataFormatters/TypeSynthetic.h"
26 #include "lldb/DataFormatters/TypeValidator.h"
27 #include "lldb/Symbol/CompilerType.h"
28 #include "lldb/Utility/RegularExpression.h"
29 #include "lldb/Utility/StringLexer.h"
31 namespace lldb_private {
33 class IFormatChangeListener {
35 virtual ~IFormatChangeListener() = default;
37 virtual void Changed() = 0;
39 virtual uint32_t GetCurrentRevision() = 0;
42 // if the user tries to add formatters for, say, "struct Foo" those will not
43 // match any type because of the way we strip qualifiers from typenames this
44 // method looks for the case where the user is adding a "class","struct","enum"
45 // or "union" Foo and strips the unnecessary qualifier
46 static inline ConstString GetValidTypeName_Impl(const ConstString &type) {
50 std::string type_cstr(type.AsCString());
51 lldb_utility::StringLexer type_lexer(type_cstr);
53 type_lexer.AdvanceIf("class ");
54 type_lexer.AdvanceIf("enum ");
55 type_lexer.AdvanceIf("struct ");
56 type_lexer.AdvanceIf("union ");
58 while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
61 return ConstString(type_lexer.GetUnlexed());
64 template <typename KeyType, typename ValueType> class FormattersContainer;
66 template <typename KeyType, typename ValueType> class FormatMap {
68 typedef typename ValueType::SharedPointer ValueSP;
69 typedef std::map<KeyType, ValueSP> MapType;
70 typedef typename MapType::iterator MapIterator;
71 typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback;
73 FormatMap(IFormatChangeListener *lst)
74 : m_map(), m_map_mutex(), listener(lst) {}
76 void Add(KeyType name, const ValueSP &entry) {
78 entry->GetRevision() = listener->GetCurrentRevision();
80 entry->GetRevision() = 0;
82 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
88 bool Delete(KeyType name) {
89 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
90 MapIterator iter = m_map.find(name);
91 if (iter == m_map.end())
100 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
106 bool Get(KeyType name, ValueSP &entry) {
107 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
108 MapIterator iter = m_map.find(name);
109 if (iter == m_map.end())
111 entry = iter->second;
115 void ForEach(ForEachCallback callback) {
117 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
118 MapIterator pos, end = m_map.end();
119 for (pos = m_map.begin(); pos != end; pos++) {
120 KeyType type = pos->first;
121 if (!callback(type, pos->second))
127 uint32_t GetCount() { return m_map.size(); }
129 ValueSP GetValueAtIndex(size_t index) {
130 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
131 MapIterator iter = m_map.begin();
132 MapIterator end = m_map.end();
142 KeyType GetKeyAtIndex(size_t index) {
143 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
144 MapIterator iter = m_map.begin();
145 MapIterator end = m_map.end();
157 std::recursive_mutex m_map_mutex;
158 IFormatChangeListener *listener;
160 MapType &map() { return m_map; }
162 std::recursive_mutex &mutex() { return m_map_mutex; }
164 friend class FormattersContainer<KeyType, ValueType>;
165 friend class FormatManager;
168 template <typename KeyType, typename ValueType> class FormattersContainer {
170 typedef FormatMap<KeyType, ValueType> BackEndType;
173 typedef typename BackEndType::MapType MapType;
174 typedef typename MapType::iterator MapIterator;
175 typedef typename MapType::key_type MapKeyType;
176 typedef typename MapType::mapped_type MapValueType;
177 typedef typename BackEndType::ForEachCallback ForEachCallback;
178 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
181 friend class TypeCategoryImpl;
183 FormattersContainer(std::string name, IFormatChangeListener *lst)
184 : m_format_map(lst), m_name(name) {}
186 void Add(const MapKeyType &type, const MapValueType &entry) {
187 Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
190 bool Delete(ConstString type) {
191 return Delete_Impl(type, static_cast<KeyType *>(nullptr));
194 bool Get(ValueObject &valobj, MapValueType &entry,
195 lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) {
196 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
197 CompilerType ast_type(valobj.GetCompilerType());
198 bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
200 entry = MapValueType(entry);
202 entry = MapValueType();
208 bool Get(ConstString type, MapValueType &entry) {
209 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
212 bool GetExact(ConstString type, MapValueType &entry) {
213 return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
216 MapValueType GetAtIndex(size_t index) {
217 return m_format_map.GetValueAtIndex(index);
220 lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
221 return GetTypeNameSpecifierAtIndex_Impl(index,
222 static_cast<KeyType *>(nullptr));
225 void Clear() { m_format_map.Clear(); }
227 void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
229 uint32_t GetCount() { return m_format_map.GetCount(); }
232 BackEndType m_format_map;
235 DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
237 void Add_Impl(const MapKeyType &type, const MapValueType &entry,
238 lldb::RegularExpressionSP *dummy) {
239 m_format_map.Add(type, entry);
242 void Add_Impl(const ConstString &type, const MapValueType &entry,
243 ConstString *dummy) {
244 m_format_map.Add(GetValidTypeName_Impl(type), entry);
247 bool Delete_Impl(ConstString type, ConstString *dummy) {
248 return m_format_map.Delete(type);
251 bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) {
252 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
253 MapIterator pos, end = m_format_map.map().end();
254 for (pos = m_format_map.map().begin(); pos != end; pos++) {
255 lldb::RegularExpressionSP regex = pos->first;
256 if (type.GetStringRef() == regex->GetText()) {
257 m_format_map.map().erase(pos);
258 if (m_format_map.listener)
259 m_format_map.listener->Changed();
266 bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
267 return m_format_map.Get(type, entry);
270 bool GetExact_Impl(ConstString type, MapValueType &entry,
271 ConstString *dummy) {
272 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
275 lldb::TypeNameSpecifierImplSP
276 GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
277 ConstString key = m_format_map.GetKeyAtIndex(index);
279 return lldb::TypeNameSpecifierImplSP(
280 new TypeNameSpecifierImpl(key.AsCString(), false));
282 return lldb::TypeNameSpecifierImplSP();
285 lldb::TypeNameSpecifierImplSP
286 GetTypeNameSpecifierAtIndex_Impl(size_t index,
287 lldb::RegularExpressionSP *dummy) {
288 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
289 if (regex.get() == nullptr)
290 return lldb::TypeNameSpecifierImplSP();
291 return lldb::TypeNameSpecifierImplSP(
292 new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true));
295 bool Get_Impl(ConstString key, MapValueType &value,
296 lldb::RegularExpressionSP *dummy) {
297 llvm::StringRef key_str = key.GetStringRef();
298 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
299 MapIterator pos, end = m_format_map.map().end();
300 for (pos = m_format_map.map().begin(); pos != end; pos++) {
301 lldb::RegularExpressionSP regex = pos->first;
302 if (regex->Execute(key_str)) {
310 bool GetExact_Impl(ConstString key, MapValueType &value,
311 lldb::RegularExpressionSP *dummy) {
312 std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
313 MapIterator pos, end = m_format_map.map().end();
314 for (pos = m_format_map.map().begin(); pos != end; pos++) {
315 lldb::RegularExpressionSP regex = pos->first;
316 if (regex->GetText() == key.GetStringRef()) {
324 bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
326 for (const FormattersMatchCandidate &candidate : candidates) {
327 if (Get(candidate.GetTypeName(), entry)) {
328 if (candidate.IsMatch(entry) == false) {
333 *reason = candidate.GetReason();
342 } // namespace lldb_private
344 #endif // lldb_FormattersContainer_h_