]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[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 #include <functional>
14 #include <map>
15 #include <memory>
16 #include <mutex>
17 #include <string>
18
19 #include "lldb/lldb-public.h"
20
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"
30
31 namespace lldb_private {
32
33 class IFormatChangeListener {
34 public:
35   virtual ~IFormatChangeListener() = default;
36
37   virtual void Changed() = 0;
38
39   virtual uint32_t GetCurrentRevision() = 0;
40 };
41
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) {
47   if (type.IsEmpty())
48     return type;
49
50   std::string type_cstr(type.AsCString());
51   lldb_utility::StringLexer type_lexer(type_cstr);
52
53   type_lexer.AdvanceIf("class ");
54   type_lexer.AdvanceIf("enum ");
55   type_lexer.AdvanceIf("struct ");
56   type_lexer.AdvanceIf("union ");
57
58   while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
59     ;
60
61   return ConstString(type_lexer.GetUnlexed());
62 }
63
64 template <typename KeyType, typename ValueType> class FormattersContainer;
65
66 template <typename KeyType, typename ValueType> class FormatMap {
67 public:
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;
72
73   FormatMap(IFormatChangeListener *lst)
74       : m_map(), m_map_mutex(), listener(lst) {}
75
76   void Add(KeyType name, const ValueSP &entry) {
77     if (listener)
78       entry->GetRevision() = listener->GetCurrentRevision();
79     else
80       entry->GetRevision() = 0;
81
82     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
83     m_map[name] = entry;
84     if (listener)
85       listener->Changed();
86   }
87
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())
92       return false;
93     m_map.erase(name);
94     if (listener)
95       listener->Changed();
96     return true;
97   }
98
99   void Clear() {
100     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
101     m_map.clear();
102     if (listener)
103       listener->Changed();
104   }
105
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())
110       return false;
111     entry = iter->second;
112     return true;
113   }
114
115   void ForEach(ForEachCallback callback) {
116     if (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))
122           break;
123       }
124     }
125   }
126
127   uint32_t GetCount() { return m_map.size(); }
128
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();
133     while (index > 0) {
134       iter++;
135       index--;
136       if (end == iter)
137         return ValueSP();
138     }
139     return iter->second;
140   }
141
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();
146     while (index > 0) {
147       iter++;
148       index--;
149       if (end == iter)
150         return KeyType();
151     }
152     return iter->first;
153   }
154
155 protected:
156   MapType m_map;
157   std::recursive_mutex m_map_mutex;
158   IFormatChangeListener *listener;
159
160   MapType &map() { return m_map; }
161
162   std::recursive_mutex &mutex() { return m_map_mutex; }
163
164   friend class FormattersContainer<KeyType, ValueType>;
165   friend class FormatManager;
166 };
167
168 template <typename KeyType, typename ValueType> class FormattersContainer {
169 protected:
170   typedef FormatMap<KeyType, ValueType> BackEndType;
171
172 public:
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>>
179       SharedPointer;
180
181   friend class TypeCategoryImpl;
182
183   FormattersContainer(std::string name, IFormatChangeListener *lst)
184       : m_format_map(lst), m_name(name) {}
185
186   void Add(const MapKeyType &type, const MapValueType &entry) {
187     Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
188   }
189
190   bool Delete(ConstString type) {
191     return Delete_Impl(type, static_cast<KeyType *>(nullptr));
192   }
193
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);
199     if (ret)
200       entry = MapValueType(entry);
201     else
202       entry = MapValueType();
203     if (why)
204       *why = value;
205     return ret;
206   }
207
208   bool Get(ConstString type, MapValueType &entry) {
209     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
210   }
211
212   bool GetExact(ConstString type, MapValueType &entry) {
213     return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
214   }
215
216   MapValueType GetAtIndex(size_t index) {
217     return m_format_map.GetValueAtIndex(index);
218   }
219
220   lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
221     return GetTypeNameSpecifierAtIndex_Impl(index,
222                                             static_cast<KeyType *>(nullptr));
223   }
224
225   void Clear() { m_format_map.Clear(); }
226
227   void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
228
229   uint32_t GetCount() { return m_format_map.GetCount(); }
230
231 protected:
232   BackEndType m_format_map;
233   std::string m_name;
234
235   DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
236
237   void Add_Impl(const MapKeyType &type, const MapValueType &entry,
238                 lldb::RegularExpressionSP *dummy) {
239     m_format_map.Add(type, entry);
240   }
241
242   void Add_Impl(const ConstString &type, const MapValueType &entry,
243                 ConstString *dummy) {
244     m_format_map.Add(GetValidTypeName_Impl(type), entry);
245   }
246
247   bool Delete_Impl(ConstString type, ConstString *dummy) {
248     return m_format_map.Delete(type);
249   }
250
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();
260         return true;
261       }
262     }
263     return false;
264   }
265
266   bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
267     return m_format_map.Get(type, entry);
268   }
269
270   bool GetExact_Impl(ConstString type, MapValueType &entry,
271                      ConstString *dummy) {
272     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
273   }
274
275   lldb::TypeNameSpecifierImplSP
276   GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
277     ConstString key = m_format_map.GetKeyAtIndex(index);
278     if (key)
279       return lldb::TypeNameSpecifierImplSP(
280           new TypeNameSpecifierImpl(key.AsCString(), false));
281     else
282       return lldb::TypeNameSpecifierImplSP();
283   }
284
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));
293   }
294
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)) {
303         value = pos->second;
304         return true;
305       }
306     }
307     return false;
308   }
309
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()) {
317         value = pos->second;
318         return true;
319       }
320     }
321     return false;
322   }
323
324   bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
325            uint32_t *reason) {
326     for (const FormattersMatchCandidate &candidate : candidates) {
327       if (Get(candidate.GetTypeName(), entry)) {
328         if (candidate.IsMatch(entry) == false) {
329           entry.reset();
330           continue;
331         } else {
332           if (reason)
333             *reason = candidate.GetReason();
334           return true;
335         }
336       }
337     }
338     return false;
339   }
340 };
341
342 } // namespace lldb_private
343
344 #endif // lldb_FormattersContainer_h_