1 //===-- FormattersContainer.h -----------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef lldb_FormattersContainer_h_
11 #define lldb_FormattersContainer_h_
21 // Other libraries and framework includes
23 #include "lldb/lldb-public.h"
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"
35 namespace lldb_private {
37 class IFormatChangeListener {
39 virtual ~IFormatChangeListener() = default;
41 virtual void Changed() = 0;
43 virtual uint32_t GetCurrentRevision() = 0;
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
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) {
56 std::string type_cstr(type.AsCString());
57 lldb_utility::StringLexer type_lexer(type_cstr);
59 type_lexer.AdvanceIf("class ");
60 type_lexer.AdvanceIf("enum ");
61 type_lexer.AdvanceIf("struct ");
62 type_lexer.AdvanceIf("union ");
64 while (type_lexer.NextIf({' ', '\t', '\v', '\f'}).first)
67 return ConstString(type_lexer.GetUnlexed());
70 template <typename KeyType, typename ValueType> class FormattersContainer;
72 template <typename KeyType, typename ValueType> class FormatMap {
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;
79 FormatMap(IFormatChangeListener *lst)
80 : m_map(), m_map_mutex(), listener(lst) {}
82 void Add(KeyType name, const ValueSP &entry) {
84 entry->GetRevision() = listener->GetCurrentRevision();
86 entry->GetRevision() = 0;
88 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
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())
106 std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
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())
117 entry = iter->second;
121 void ForEach(ForEachCallback 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))
133 uint32_t GetCount() { return m_map.size(); }
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();
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();
163 std::recursive_mutex m_map_mutex;
164 IFormatChangeListener *listener;
166 MapType &map() { return m_map; }
168 std::recursive_mutex &mutex() { return m_map_mutex; }
170 friend class FormattersContainer<KeyType, ValueType>;
171 friend class FormatManager;
174 template <typename KeyType, typename ValueType> class FormattersContainer {
176 typedef FormatMap<KeyType, ValueType> BackEndType;
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>>
187 friend class TypeCategoryImpl;
189 FormattersContainer(std::string name, IFormatChangeListener *lst)
190 : m_format_map(lst), m_name(name) {}
192 void Add(const MapKeyType &type, const MapValueType &entry) {
193 Add_Impl(type, entry, static_cast<KeyType *>(nullptr));
196 bool Delete(ConstString type) {
197 return Delete_Impl(type, static_cast<KeyType *>(nullptr));
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);
206 entry = MapValueType(entry);
208 entry = MapValueType();
214 bool Get(ConstString type, MapValueType &entry) {
215 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
218 bool GetExact(ConstString type, MapValueType &entry) {
219 return GetExact_Impl(type, entry, static_cast<KeyType *>(nullptr));
222 MapValueType GetAtIndex(size_t index) {
223 return m_format_map.GetValueAtIndex(index);
226 lldb::TypeNameSpecifierImplSP GetTypeNameSpecifierAtIndex(size_t index) {
227 return GetTypeNameSpecifierAtIndex_Impl(index,
228 static_cast<KeyType *>(nullptr));
231 void Clear() { m_format_map.Clear(); }
233 void ForEach(ForEachCallback callback) { m_format_map.ForEach(callback); }
235 uint32_t GetCount() { return m_format_map.GetCount(); }
238 BackEndType m_format_map;
241 DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
243 void Add_Impl(const MapKeyType &type, const MapValueType &entry,
244 lldb::RegularExpressionSP *dummy) {
245 m_format_map.Add(type, entry);
248 void Add_Impl(const ConstString &type, const MapValueType &entry,
249 ConstString *dummy) {
250 m_format_map.Add(GetValidTypeName_Impl(type), entry);
253 bool Delete_Impl(ConstString type, ConstString *dummy) {
254 return m_format_map.Delete(type);
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();
272 bool Get_Impl(ConstString type, MapValueType &entry, ConstString *dummy) {
273 return m_format_map.Get(type, entry);
276 bool GetExact_Impl(ConstString type, MapValueType &entry,
277 ConstString *dummy) {
278 return Get_Impl(type, entry, static_cast<KeyType *>(nullptr));
281 lldb::TypeNameSpecifierImplSP
282 GetTypeNameSpecifierAtIndex_Impl(size_t index, ConstString *dummy) {
283 ConstString key = m_format_map.GetKeyAtIndex(index);
285 return lldb::TypeNameSpecifierImplSP(
286 new TypeNameSpecifierImpl(key.AsCString(), false));
288 return lldb::TypeNameSpecifierImplSP();
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));
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)) {
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()) {
330 bool Get(const FormattersMatchVector &candidates, MapValueType &entry,
332 for (const FormattersMatchCandidate &candidate : candidates) {
333 if (Get(candidate.GetTypeName(), entry)) {
334 if (candidate.IsMatch(entry) == false) {
339 *reason = candidate.GetReason();
348 } // namespace lldb_private
350 #endif // lldb_FormattersContainer_h_