]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/include/lldb/DataFormatters/FormattersContainer.h
MFV r329803:
[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"
47 // those will not match any type because of the way we strip qualifiers from
48 // typenames
49 // this method looks for the case where the user is adding a
50 // "class","struct","enum" or "union" Foo
51 // and strips the unnecessary qualifier
52 static inline ConstString GetValidTypeName_Impl(const ConstString &type) {
53   if (type.IsEmpty())
54     return type;
55
56   std::string type_cstr(type.AsCString());
57   lldb_utility::StringLexer type_lexer(type_cstr);
58
59   type_lexer.AdvanceIf("class ");
60   type_lexer.AdvanceIf("enum ");
61   type_lexer.AdvanceIf("struct ");
62   type_lexer.AdvanceIf("union ");
63
64   while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
65     ;
66
67   return ConstString(type_lexer.GetUnlexed());
68 }
69
70 template <typename KeyType, typename ValueType> class FormattersContainer;
71
72 template <typename KeyType, typename ValueType> class FormatMap {
73 public:
74   typedef typename ValueType::SharedPointer ValueSP;
75   typedef std::map<KeyType, ValueSP> MapType;
76   typedef typename MapType::iterator MapIterator;
77   typedef std::function<bool(KeyType, const ValueSP &)> ForEachCallback;
78
79   FormatMap(IFormatChangeListener *lst)
80       : m_map(), m_map_mutex(), listener(lst) {}
81
82   void Add(KeyType name, const ValueSP &entry) {
83     if (listener)
84       entry->GetRevision() = listener->GetCurrentRevision();
85     else
86       entry->GetRevision() = 0;
87
88     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
89     m_map[name] = entry;
90     if (listener)
91       listener->Changed();
92   }
93
94   bool Delete(KeyType name) {
95     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
96     MapIterator iter = m_map.find(name);
97     if (iter == m_map.end())
98       return false;
99     m_map.erase(name);
100     if (listener)
101       listener->Changed();
102     return true;
103   }
104
105   void Clear() {
106     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
107     m_map.clear();
108     if (listener)
109       listener->Changed();
110   }
111
112   bool Get(KeyType name, ValueSP &entry) {
113     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
114     MapIterator iter = m_map.find(name);
115     if (iter == m_map.end())
116       return false;
117     entry = iter->second;
118     return true;
119   }
120
121   void ForEach(ForEachCallback callback) {
122     if (callback) {
123       std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
124       MapIterator pos, end = m_map.end();
125       for (pos = m_map.begin(); pos != end; pos++) {
126         KeyType type = pos->first;
127         if (!callback(type, pos->second))
128           break;
129       }
130     }
131   }
132
133   uint32_t GetCount() { return m_map.size(); }
134
135   ValueSP GetValueAtIndex(size_t index) {
136     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
137     MapIterator iter = m_map.begin();
138     MapIterator end = m_map.end();
139     while (index > 0) {
140       iter++;
141       index--;
142       if (end == iter)
143         return ValueSP();
144     }
145     return iter->second;
146   }
147
148   KeyType GetKeyAtIndex(size_t index) {
149     std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
150     MapIterator iter = m_map.begin();
151     MapIterator end = m_map.end();
152     while (index > 0) {
153       iter++;
154       index--;
155       if (end == iter)
156         return KeyType();
157     }
158     return iter->first;
159   }
160
161 protected:
162   MapType m_map;
163   std::recursive_mutex m_map_mutex;
164   IFormatChangeListener *listener;
165
166   MapType &map() { return m_map; }
167
168   std::recursive_mutex &mutex() { return m_map_mutex; }
169
170   friend class FormattersContainer<KeyType, ValueType>;
171   friend class FormatManager;
172 };
173
174 template <typename KeyType, typename ValueType> class FormattersContainer {
175 protected:
176   typedef FormatMap<KeyType, ValueType> BackEndType;
177
178 public:
179   typedef typename BackEndType::MapType MapType;
180   typedef typename MapType::iterator MapIterator;
181   typedef typename MapType::key_type MapKeyType;
182   typedef typename MapType::mapped_type MapValueType;
183   typedef typename BackEndType::ForEachCallback ForEachCallback;
184   typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType>>
185       SharedPointer;
186
187   friend class TypeCategoryImpl;
188
189   FormattersContainer(std::string name, IFormatChangeListener *lst)
190       : m_format_map(lst), m_name(name) {}
191
192   void Add(const MapKeyType &type, const MapValueType &entry) {
193     Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
194   }
195
196   bool Delete(ConstString type) {
197     return Delete_Impl(type, static_cast<KeyType *>(nullptr));
198   }
199
200   bool Get(ValueObject &valobj, MapValueType &entry,
201            lldb::DynamicValueType use_dynamic, uint32_t *why = nullptr) {
202     uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
203     CompilerType ast_type(valobj.GetCompilerType());
204     bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
205     if (ret)
206       entry = MapValueType(entry);
207     else
208       entry = MapValueType();
209     if (why)
210       *why = value;
211     return ret;
212   }
213
214   bool Get(ConstString type, MapValueType &entry) {
215     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
216   }
217
218   bool GetExact(ConstString type, MapValueType &entry) {
219     return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
220   }
221
222   MapValueType GetAtIndex(size_t index) {
223     return m_format_map.GetValueAtIndex(index);
224   }
225
226   lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
227     return GetTypeNameSpecifierAtIndex_Impl(index,
228                                             static_cast<KeyType *>(nullptr));
229   }
230
231   void Clear() { m_format_map.Clear(); }
232
233   void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
234
235   uint32_t GetCount() { return m_format_map.GetCount(); }
236
237 protected:
238   BackEndType m_format_map;
239   std::string m_name;
240
241   DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
242
243   void Add_Impl(const MapKeyType &type, const MapValueType &entry,
244                 lldb::RegularExpressionSP *dummy) {
245     m_format_map.Add(type, entry);
246   }
247
248   void Add_Impl(const ConstString &type, const MapValueType &entry,
249                 ConstString *dummy) {
250     m_format_map.Add(GetValidTypeName_Impl(type), entry);
251   }
252
253   bool Delete_Impl(ConstString type, ConstString *dummy) {
254     return m_format_map.Delete(type);
255   }
256
257   bool Delete_Impl(ConstString type, lldb::RegularExpressionSP *dummy) {
258     std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
259     MapIterator pos, end = m_format_map.map().end();
260     for (pos = m_format_map.map().begin(); pos != end; pos++) {
261       lldb::RegularExpressionSP regex = pos->first;
262       if (type.GetStringRef() == regex->GetText()) {
263         m_format_map.map().erase(pos);
264         if (m_format_map.listener)
265           m_format_map.listener->Changed();
266         return true;
267       }
268     }
269     return false;
270   }
271
272   bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
273     return m_format_map.Get(type, entry);
274   }
275
276   bool GetExact_Impl(ConstString type, MapValueType &entry,
277                      ConstString *dummy) {
278     return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
279   }
280
281   lldb::TypeNameSpecifierImplSP
282   GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
283     ConstString key = m_format_map.GetKeyAtIndex(index);
284     if (key)
285       return lldb::TypeNameSpecifierImplSP(
286           new TypeNameSpecifierImpl(key.AsCString(), false));
287     else
288       return lldb::TypeNameSpecifierImplSP();
289   }
290
291   lldb::TypeNameSpecifierImplSP
292   GetTypeNameSpecifierAtIndex_Impl(size_t index,
293                                    lldb::RegularExpressionSP *dummy) {
294     lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
295     if (regex.get() == nullptr)
296       return lldb::TypeNameSpecifierImplSP();
297     return lldb::TypeNameSpecifierImplSP(
298         new TypeNameSpecifierImpl(regex->GetText().str().c_str(), true));
299   }
300
301   bool Get_Impl(ConstString key, MapValueType &value,
302                 lldb::RegularExpressionSP *dummy) {
303     llvm::StringRef key_str = key.GetStringRef();
304     std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
305     MapIterator pos, end = m_format_map.map().end();
306     for (pos = m_format_map.map().begin(); pos != end; pos++) {
307       lldb::RegularExpressionSP regex = pos->first;
308       if (regex->Execute(key_str)) {
309         value = pos->second;
310         return true;
311       }
312     }
313     return false;
314   }
315
316   bool GetExact_Impl(ConstString key, MapValueType &value,
317                      lldb::RegularExpressionSP *dummy) {
318     std::lock_guard<std::recursive_mutex> guard(m_format_map.mutex());
319     MapIterator pos, end = m_format_map.map().end();
320     for (pos = m_format_map.map().begin(); pos != end; pos++) {
321       lldb::RegularExpressionSP regex = pos->first;
322       if (regex->GetText() == key.GetStringRef()) {
323         value = pos->second;
324         return true;
325       }
326     }
327     return false;
328   }
329
330   bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
331            uint32_t *reason) {
332     for (const FormattersMatchCandidate &candidate : candidates) {
333       if (Get(candidate.GetTypeName(), entry)) {
334         if (candidate.IsMatch(entry) == false) {
335           entry.reset();
336           continue;
337         } else {
338           if (reason)
339             *reason = candidate.GetReason();
340           return true;
341         }
342       }
343     }
344     return false;
345   }
346 };
347
348 } // namespace lldb_private
349
350 #endif // lldb_FormattersContainer_h_