]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
Merge ^/head r336870 through r337615.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / include / lldb / DataFormatters / FormattersContainer.h
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/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"
34
35 namespace lldb_private {
36
37 class IFormatChangeListener {
38 public:
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" 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) {
51   if (type.IsEmpty())
52     return type;
53
54   std::string type_cstr(type.AsCString());
55   lldb_utility::StringLexer type_lexer(type_cstr);
56
57   type_lexer.AdvanceIf("class ");
58   type_lexer.AdvanceIf("enum ");
59   type_lexer.AdvanceIf("struct ");
60   type_lexer.AdvanceIf("union ");
61
62   while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
63     ;
64
65   return ConstString(type_lexer.GetUnlexed());
66 }
67
68 template <typename KeyType, typename ValueType> class FormattersContainer;
69
70 template <typename KeyType, typename ValueType> class FormatMap {
71 public:
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;
76
77   FormatMap(IFormatChangeListener *lst)
78       : m_map(), m_map_mutex(), listener(lst) {}
79
80   void Add(KeyType name, const ValueSP &entry) {
81     if (listener)
82       entry->GetRevision() = listener->GetCurrentRevision();
83     else
84       entry->GetRevision() = 0;
85
86     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
87     m_map[name] = entry;
88     if (listener)
89       listener->Changed();
90   }
91
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())
96       return false;
97     m_map.erase(name);
98     if (listener)
99       listener->Changed();
100     return true;
101   }
102
103   void Clear() {
104     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
105     m_map.clear();
106     if (listener)
107       listener->Changed();
108   }
109
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())
114       return false;
115     entry = iter->second;
116     return true;
117   }
118
119   void ForEach(ForEachCallback callback) {
120     if (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))
126           break;
127       }
128     }
129   }
130
131   uint32_t GetCount() { return m_map.size(); }
132
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();
137     while (index > 0) {
138       iter++;
139       index--;
140       if (end == iter)
141         return ValueSP();
142     }
143     return iter->second;
144   }
145
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();
150     while (index > 0) {
151       iter++;
152       index--;
153       if (end == iter)
154         return KeyType();
155     }
156     return iter->first;
157   }
158
159 protected:
160   MapType m_map;
161   std::recursive_mutex m_map_mutex;
162   IFormatChangeListener *listener;
163
164   MapType &map() { return m_map; }
165
166   std::recursive_mutex &mutex() { return m_map_mutex; }
167
168   friend class FormattersContainer<KeyType, ValueType>;
169   friend class FormatManager;
170 };
171
172 template <typename KeyType, typename ValueType> class FormattersContainer {
173 protected:
174   typedef FormatMap<KeyType, ValueType> BackEndType;
175
176 public:
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>>
183       SharedPointer;
184
185   friend class TypeCategoryImpl;
186
187   FormattersContainer(std::string name, IFormatChangeListener *lst)
188       : m_format_map(lst), m_name(name) {}
189
190   void Add(const MapKeyType &type, const MapValueType &entry) {
191     Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
192   }
193
194   bool Delete(ConstString type) {
195     return Delete_Impl(type, static_cast<KeyType *>(nullptr));
196   }
197
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);
203     if (ret)
204       entry = MapValueType(entry);
205     else
206       entry = MapValueType();
207     if (why)
208       *why = value;
209     return ret;
210   }
211
212   bool Get(ConstString type, MapValueType &entry) {
213     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
214   }
215
216   bool GetExact(ConstString type, MapValueType &entry) {
217     return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
218   }
219
220   MapValueType GetAtIndex(size_t index) {
221     return m_format_map.GetValueAtIndex(index);
222   }
223
224   lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
225     return GetTypeNameSpecifierAtIndex_Impl(index,
226                                             static_cast<KeyType *>(nullptr));
227   }
228
229   void Clear() { m_format_map.Clear(); }
230
231   void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
232
233   uint32_t GetCount() { return m_format_map.GetCount(); }
234
235 protected:
236   BackEndType m_format_map;
237   std::string m_name;
238
239   DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
240
241   void Add_Impl(const MapKeyType &type, const MapValueType &entry,
242                 lldb::RegularExpressionSP *dummy) {
243     m_format_map.Add(type, entry);
244   }
245
246   void Add_Impl(const ConstString &type, const MapValueType &entry,
247                 ConstString *dummy) {
248     m_format_map.Add(GetValidTypeName_Impl(type), entry);
249   }
250
251   bool Delete_Impl(ConstString type, ConstString *dummy) {
252     return m_format_map.Delete(type);
253   }
254
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();
264         return true;
265       }
266     }
267     return false;
268   }
269
270   bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
271     return m_format_map.Get(type, entry);
272   }
273
274   bool GetExact_Impl(ConstString type, MapValueType &entry,
275                      ConstString *dummy) {
276     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
277   }
278
279   lldb::TypeNameSpecifierImplSP
280   GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
281     ConstString key = m_format_map.GetKeyAtIndex(index);
282     if (key)
283       return lldb::TypeNameSpecifierImplSP(
284           new TypeNameSpecifierImpl(key.AsCString(), false));
285     else
286       return lldb::TypeNameSpecifierImplSP();
287   }
288
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));
297   }
298
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)) {
307         value = pos->second;
308         return true;
309       }
310     }
311     return false;
312   }
313
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()) {
321         value = pos->second;
322         return true;
323       }
324     }
325     return false;
326   }
327
328   bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
329            uint32_t *reason) {
330     for (const FormattersMatchCandidate &candidate : candidates) {
331       if (Get(candidate.GetTypeName(), entry)) {
332         if (candidate.IsMatch(entry) == false) {
333           entry.reset();
334           continue;
335         } else {
336           if (reason)
337             *reason = candidate.GetReason();
338           return true;
339         }
340       }
341     }
342     return false;
343   }
344 };
345
346 } // namespace lldb_private
347
348 #endif // lldb_FormattersContainer_h_