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