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
24namespace lldb_private {
25
26template <typename FormatterImpl> class FormatterContainerPair {
27public:
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
60private:
61  ExactMatchContainerSP m_exact_sp;
62  RegexMatchContainerSP m_regex_sp;
63};
64
65class TypeCategoryImpl {
66private:
67  typedef FormatterContainerPair<TypeFormatImpl> FormatContainer;
68  typedef FormatterContainerPair<TypeSummaryImpl> SummaryContainer;
69  typedef FormatterContainerPair<TypeFilterImpl> FilterContainer;
70  typedef FormatterContainerPair<SyntheticChildren> SynthContainer;
71
72public:
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
320private:
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