1 //===-- TypeCategory.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_DATAFORMATTERS_TYPECATEGORY_H
10 #define LLDB_DATAFORMATTERS_TYPECATEGORY_H
11 
12 #include <initializer_list>
13 #include <memory>
14 #include <mutex>
15 #include <string>
16 #include <vector>
17 
18 #include "lldb/lldb-enumerations.h"
19 #include "lldb/lldb-public.h"
20 
21 #include "lldb/DataFormatters/FormatClasses.h"
22 #include "lldb/DataFormatters/FormattersContainer.h"
23 
24 namespace lldb_private {
25 
26 template <typename FormatterImpl> class FormatterContainerPair {
27 public:
28   typedef FormattersContainer<FormatterImpl> ExactMatchContainer;
29   typedef FormattersContainer<FormatterImpl> RegexMatchContainer;
30 
31   typedef TypeMatcher ExactMatchMap;
32   typedef TypeMatcher RegexMatchMap;
33 
34   typedef typename ExactMatchContainer::ValueSP MapValueType;
35 
36   typedef typename ExactMatchContainer::SharedPointer ExactMatchContainerSP;
37   typedef typename RegexMatchContainer::SharedPointer RegexMatchContainerSP;
38 
39   typedef
40       typename ExactMatchContainer::ForEachCallback ExactMatchForEachCallback;
41   typedef
42       typename RegexMatchContainer::ForEachCallback RegexMatchForEachCallback;
43 
44   FormatterContainerPair(IFormatChangeListener *clist)
45       : m_exact_sp(new ExactMatchContainer(clist)),
46         m_regex_sp(new RegexMatchContainer(clist)) {}
47 
48   ~FormatterContainerPair() = default;
49 
50   ExactMatchContainerSP GetExactMatch() const { return m_exact_sp; }
51 
52   RegexMatchContainerSP GetRegexMatch() const { return m_regex_sp; }
53 
54   uint32_t GetCount() {
55     return GetExactMatch()->GetCount() + GetRegexMatch()->GetCount();
56   }
57 
58 private:
59   ExactMatchContainerSP m_exact_sp;
60   RegexMatchContainerSP m_regex_sp;
61 };
62 
63 class TypeCategoryImpl {
64 private:
65   typedef FormatterContainerPair<TypeFormatImpl> FormatContainer;
66   typedef FormatterContainerPair<TypeSummaryImpl> SummaryContainer;
67   typedef FormatterContainerPair<TypeFilterImpl> FilterContainer;
68   typedef FormatterContainerPair<SyntheticChildren> SynthContainer;
69 
70 public:
71   typedef uint16_t FormatCategoryItems;
72   static const uint16_t ALL_ITEM_TYPES = UINT16_MAX;
73 
74   typedef FormatContainer::ExactMatchContainerSP FormatContainerSP;
75   typedef FormatContainer::RegexMatchContainerSP RegexFormatContainerSP;
76 
77   typedef SummaryContainer::ExactMatchContainerSP SummaryContainerSP;
78   typedef SummaryContainer::RegexMatchContainerSP RegexSummaryContainerSP;
79 
80   typedef FilterContainer::ExactMatchContainerSP FilterContainerSP;
81   typedef FilterContainer::RegexMatchContainerSP RegexFilterContainerSP;
82 
83   typedef SynthContainer::ExactMatchContainerSP SynthContainerSP;
84   typedef SynthContainer::RegexMatchContainerSP RegexSynthContainerSP;
85 
86   template <typename T> class ForEachCallbacks {
87   public:
88     ForEachCallbacks() = default;
89     ~ForEachCallbacks() = default;
90 
91     template <typename U = TypeFormatImpl>
92     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
93     SetExact(FormatContainer::ExactMatchForEachCallback callback) {
94       m_format_exact = std::move(callback);
95       return *this;
96     }
97     template <typename U = TypeFormatImpl>
98     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
99     SetWithRegex(FormatContainer::RegexMatchForEachCallback callback) {
100       m_format_regex = std::move(callback);
101       return *this;
102     }
103 
104     template <typename U = TypeSummaryImpl>
105     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
106     SetExact(SummaryContainer::ExactMatchForEachCallback callback) {
107       m_summary_exact = std::move(callback);
108       return *this;
109     }
110     template <typename U = TypeSummaryImpl>
111     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
112     SetWithRegex(SummaryContainer::RegexMatchForEachCallback callback) {
113       m_summary_regex = std::move(callback);
114       return *this;
115     }
116 
117     template <typename U = TypeFilterImpl>
118     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
119     SetExact(FilterContainer::ExactMatchForEachCallback callback) {
120       m_filter_exact = std::move(callback);
121       return *this;
122     }
123     template <typename U = TypeFilterImpl>
124     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
125     SetWithRegex(FilterContainer::RegexMatchForEachCallback callback) {
126       m_filter_regex = std::move(callback);
127       return *this;
128     }
129 
130     template <typename U = SyntheticChildren>
131     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
132     SetExact(SynthContainer::ExactMatchForEachCallback callback) {
133       m_synth_exact = std::move(callback);
134       return *this;
135     }
136     template <typename U = SyntheticChildren>
137     typename std::enable_if<std::is_same<U, T>::value, ForEachCallbacks &>::type
138     SetWithRegex(SynthContainer::RegexMatchForEachCallback callback) {
139       m_synth_regex = std::move(callback);
140       return *this;
141     }
142 
143     FormatContainer::ExactMatchForEachCallback GetFormatExactCallback() const {
144       return m_format_exact;
145     }
146     FormatContainer::RegexMatchForEachCallback GetFormatRegexCallback() const {
147       return m_format_regex;
148     }
149 
150     SummaryContainer::ExactMatchForEachCallback
151     GetSummaryExactCallback() const {
152       return m_summary_exact;
153     }
154     SummaryContainer::RegexMatchForEachCallback
155     GetSummaryRegexCallback() const {
156       return m_summary_regex;
157     }
158 
159     FilterContainer::ExactMatchForEachCallback GetFilterExactCallback() const {
160       return m_filter_exact;
161     }
162     FilterContainer::RegexMatchForEachCallback GetFilterRegexCallback() const {
163       return m_filter_regex;
164     }
165 
166     SynthContainer::ExactMatchForEachCallback GetSynthExactCallback() const {
167       return m_synth_exact;
168     }
169     SynthContainer::RegexMatchForEachCallback GetSynthRegexCallback() const {
170       return m_synth_regex;
171     }
172 
173   private:
174     FormatContainer::ExactMatchForEachCallback m_format_exact;
175     FormatContainer::RegexMatchForEachCallback m_format_regex;
176 
177     SummaryContainer::ExactMatchForEachCallback m_summary_exact;
178     SummaryContainer::RegexMatchForEachCallback m_summary_regex;
179 
180     FilterContainer::ExactMatchForEachCallback m_filter_exact;
181     FilterContainer::RegexMatchForEachCallback m_filter_regex;
182 
183     SynthContainer::ExactMatchForEachCallback m_synth_exact;
184     SynthContainer::RegexMatchForEachCallback m_synth_regex;
185   };
186 
187   TypeCategoryImpl(IFormatChangeListener *clist, ConstString name);
188 
189   template <typename T> void ForEach(const ForEachCallbacks<T> &foreach) {
190     GetTypeFormatsContainer()->ForEach(foreach.GetFormatExactCallback());
191     GetRegexTypeFormatsContainer()->ForEach(foreach.GetFormatRegexCallback());
192 
193     GetTypeSummariesContainer()->ForEach(foreach.GetSummaryExactCallback());
194     GetRegexTypeSummariesContainer()->ForEach(
195         foreach.GetSummaryRegexCallback());
196 
197     GetTypeFiltersContainer()->ForEach(foreach.GetFilterExactCallback());
198     GetRegexTypeFiltersContainer()->ForEach(foreach.GetFilterRegexCallback());
199 
200     GetTypeSyntheticsContainer()->ForEach(foreach.GetSynthExactCallback());
201     GetRegexTypeSyntheticsContainer()->ForEach(foreach.GetSynthRegexCallback());
202   }
203 
204   FormatContainerSP GetTypeFormatsContainer() {
205     return m_format_cont.GetExactMatch();
206   }
207 
208   RegexFormatContainerSP GetRegexTypeFormatsContainer() {
209     return m_format_cont.GetRegexMatch();
210   }
211 
212   FormatContainer &GetFormatContainer() { return m_format_cont; }
213 
214   SummaryContainerSP GetTypeSummariesContainer() {
215     return m_summary_cont.GetExactMatch();
216   }
217 
218   RegexSummaryContainerSP GetRegexTypeSummariesContainer() {
219     return m_summary_cont.GetRegexMatch();
220   }
221 
222   SummaryContainer &GetSummaryContainer() { return m_summary_cont; }
223 
224   FilterContainerSP GetTypeFiltersContainer() {
225     return m_filter_cont.GetExactMatch();
226   }
227 
228   RegexFilterContainerSP GetRegexTypeFiltersContainer() {
229     return m_filter_cont.GetRegexMatch();
230   }
231 
232   FilterContainer &GetFilterContainer() { return m_filter_cont; }
233 
234   FormatContainer::MapValueType
235   GetFormatForType(lldb::TypeNameSpecifierImplSP type_sp);
236 
237   SummaryContainer::MapValueType
238   GetSummaryForType(lldb::TypeNameSpecifierImplSP type_sp);
239 
240   FilterContainer::MapValueType
241   GetFilterForType(lldb::TypeNameSpecifierImplSP type_sp);
242 
243   SynthContainer::MapValueType
244   GetSyntheticForType(lldb::TypeNameSpecifierImplSP type_sp);
245 
246   lldb::TypeNameSpecifierImplSP
247   GetTypeNameSpecifierForFormatAtIndex(size_t index);
248 
249   lldb::TypeNameSpecifierImplSP
250   GetTypeNameSpecifierForSummaryAtIndex(size_t index);
251 
252   FormatContainer::MapValueType GetFormatAtIndex(size_t index);
253 
254   SummaryContainer::MapValueType GetSummaryAtIndex(size_t index);
255 
256   FilterContainer::MapValueType GetFilterAtIndex(size_t index);
257 
258   lldb::TypeNameSpecifierImplSP
259   GetTypeNameSpecifierForFilterAtIndex(size_t index);
260 
261   SynthContainerSP GetTypeSyntheticsContainer() {
262     return m_synth_cont.GetExactMatch();
263   }
264 
265   RegexSynthContainerSP GetRegexTypeSyntheticsContainer() {
266     return m_synth_cont.GetRegexMatch();
267   }
268 
269   SynthContainer &GetSyntheticsContainer() { return m_synth_cont; }
270 
271   SynthContainer::MapValueType GetSyntheticAtIndex(size_t index);
272 
273   lldb::TypeNameSpecifierImplSP
274   GetTypeNameSpecifierForSyntheticAtIndex(size_t index);
275 
276   bool IsEnabled() const { return m_enabled; }
277 
278   uint32_t GetEnabledPosition() {
279     if (!m_enabled)
280       return UINT32_MAX;
281     else
282       return m_enabled_position;
283   }
284 
285   bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
286            lldb::TypeFormatImplSP &entry);
287 
288   bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
289            lldb::TypeSummaryImplSP &entry);
290 
291   bool Get(lldb::LanguageType lang, const FormattersMatchVector &candidates,
292            lldb::SyntheticChildrenSP &entry);
293 
294   void Clear(FormatCategoryItems items = ALL_ITEM_TYPES);
295 
296   bool Delete(ConstString name, FormatCategoryItems items = ALL_ITEM_TYPES);
297 
298   uint32_t GetCount(FormatCategoryItems items = ALL_ITEM_TYPES);
299 
300   const char *GetName() { return m_name.GetCString(); }
301 
302   size_t GetNumLanguages();
303 
304   lldb::LanguageType GetLanguageAtIndex(size_t idx);
305 
306   void AddLanguage(lldb::LanguageType lang);
307 
308   std::string GetDescription();
309 
310   bool AnyMatches(ConstString type_name,
311                   FormatCategoryItems items = ALL_ITEM_TYPES,
312                   bool only_enabled = true,
313                   const char **matching_category = nullptr,
314                   FormatCategoryItems *matching_type = nullptr);
315 
316   typedef std::shared_ptr<TypeCategoryImpl> SharedPointer;
317 
318 private:
319   FormatContainer m_format_cont;
320   SummaryContainer m_summary_cont;
321   FilterContainer m_filter_cont;
322   SynthContainer m_synth_cont;
323 
324   bool m_enabled;
325 
326   IFormatChangeListener *m_change_listener;
327 
328   std::recursive_mutex m_mutex;
329 
330   ConstString m_name;
331 
332   std::vector<lldb::LanguageType> m_languages;
333 
334   uint32_t m_enabled_position;
335 
336   void Enable(bool value, uint32_t position);
337 
338   void Disable() { Enable(false, UINT32_MAX); }
339 
340   bool IsApplicable(lldb::LanguageType lang);
341 
342   uint32_t GetLastEnabledPosition() { return m_enabled_position; }
343 
344   void SetEnabledPosition(uint32_t p) { m_enabled_position = p; }
345 
346   friend class FormatManager;
347   friend class LanguageCategory;
348   friend class TypeCategoryMap;
349 
350   friend class FormattersContainer<TypeFormatImpl>;
351 
352   friend class FormattersContainer<TypeSummaryImpl>;
353 
354   friend class FormattersContainer<TypeFilterImpl>;
355 
356   friend class FormattersContainer<ScriptedSyntheticChildren>;
357 };
358 
359 } // namespace lldb_private
360 
361 #endif // LLDB_DATAFORMATTERS_TYPECATEGORY_H
362