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