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_
16 // Other libraries and framework includes
17 #include "clang/AST/DeclCXX.h"
18 #include "clang/AST/Type.h"
19 #include "clang/AST/DeclObjC.h"
22 #include "lldb/lldb-public.h"
24 #include "lldb/Core/Log.h"
25 #include "lldb/Core/RegularExpression.h"
26 #include "lldb/Core/ValueObject.h"
28 #include "lldb/DataFormatters/FormatClasses.h"
29 #include "lldb/DataFormatters/TypeFormat.h"
30 #include "lldb/DataFormatters/TypeSummary.h"
31 #include "lldb/DataFormatters/TypeSynthetic.h"
33 #include "lldb/Symbol/ClangASTContext.h"
34 #include "lldb/Symbol/ClangASTType.h"
36 #include "lldb/Target/ObjCLanguageRuntime.h"
37 #include "lldb/Target/Process.h"
38 #include "lldb/Target/StackFrame.h"
39 #include "lldb/Target/TargetList.h"
41 namespace lldb_private {
43 // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization
44 // class DataVisualization is the high-level front-end of this feature
45 // clients should refer to that class as the entry-point into the data formatters
46 // unless they have a good reason to bypass it and prefer to use this file's objects directly
47 class IFormatChangeListener
54 ~IFormatChangeListener () {}
57 GetCurrentRevision () = 0;
64 return ( (c == ' ') || (c == '\t') || (c == '\v') || (c == '\f') );
68 HasPrefix (const char* str1, const char* str2)
70 return ( ::strstr(str1, str2) == str1 );
73 // if the user tries to add formatters for, say, "struct Foo"
74 // those will not match any type because of the way we strip qualifiers from typenames
75 // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo
76 // and strips the unnecessary qualifier
77 static inline ConstString
78 GetValidTypeName_Impl (const ConstString& type)
82 if ((bool)type == false)
85 const char* type_cstr = type.AsCString();
87 if ( HasPrefix(type_cstr, "class ") )
89 else if ( HasPrefix(type_cstr, "enum ") )
91 else if ( HasPrefix(type_cstr, "struct ") )
93 else if ( HasPrefix(type_cstr, "union ") )
99 type_cstr += strip_len;
100 while (IsWhitespace(*type_cstr) && ++type_cstr)
103 return ConstString(type_cstr);
106 template<typename KeyType, typename ValueType>
107 class FormattersContainer;
109 template<typename KeyType, typename ValueType>
114 typedef typename ValueType::SharedPointer ValueSP;
115 typedef std::map<KeyType, ValueSP> MapType;
116 typedef typename MapType::iterator MapIterator;
117 typedef bool(*CallbackType)(void*, KeyType, const ValueSP&);
119 FormatMap(IFormatChangeListener* lst) :
121 m_map_mutex(Mutex::eMutexTypeRecursive),
128 const ValueSP& entry)
131 entry->GetRevision() = listener->GetCurrentRevision();
133 entry->GetRevision() = 0;
135 Mutex::Locker locker(m_map_mutex);
142 Delete (KeyType name)
144 Mutex::Locker locker(m_map_mutex);
145 MapIterator iter = m_map.find(name);
146 if (iter == m_map.end())
157 Mutex::Locker locker(m_map_mutex);
167 Mutex::Locker locker(m_map_mutex);
168 MapIterator iter = m_map.find(name);
169 if (iter == m_map.end())
171 entry = iter->second;
176 LoopThrough (CallbackType callback, void* param)
180 Mutex::Locker locker(m_map_mutex);
181 MapIterator pos, end = m_map.end();
182 for (pos = m_map.begin(); pos != end; pos++)
184 KeyType type = pos->first;
185 if (!callback(param, type, pos->second))
198 GetValueAtIndex (size_t index)
200 Mutex::Locker locker(m_map_mutex);
201 MapIterator iter = m_map.begin();
202 MapIterator end = m_map.end();
214 GetKeyAtIndex (size_t index)
216 Mutex::Locker locker(m_map_mutex);
217 MapIterator iter = m_map.begin();
218 MapIterator end = m_map.end();
232 IFormatChangeListener* listener;
246 friend class FormattersContainer<KeyType, ValueType>;
247 friend class FormatManager;
251 template<typename KeyType, typename ValueType>
252 class FormattersContainer
255 typedef FormatMap<KeyType,ValueType> BackEndType;
258 typedef typename BackEndType::MapType MapType;
259 typedef typename MapType::iterator MapIterator;
260 typedef typename MapType::key_type MapKeyType;
261 typedef typename MapType::mapped_type MapValueType;
262 typedef typename BackEndType::CallbackType CallbackType;
263 typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
265 friend class TypeCategoryImpl;
267 FormattersContainer(std::string name,
268 IFormatChangeListener* lst) :
271 m_id_cs(ConstString("id"))
276 Add (const MapKeyType &type, const MapValueType& entry)
278 Add_Impl(type, entry, (KeyType*)NULL);
282 Delete (ConstString type)
284 return Delete_Impl(type, (KeyType*)NULL);
288 Get(ValueObject& valobj,
290 lldb::DynamicValueType use_dynamic,
291 uint32_t* why = NULL)
293 uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
294 ClangASTType ast_type(valobj.GetClangType());
295 bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
297 entry = MapValueType(entry);
299 entry = MapValueType();
306 Get (ConstString type, MapValueType& entry)
308 return Get_Impl(type, entry, (KeyType*)NULL);
312 GetExact (ConstString type, MapValueType& entry)
314 return GetExact_Impl(type, entry, (KeyType*)NULL);
318 GetAtIndex (size_t index)
320 return m_format_map.GetValueAtIndex(index);
323 lldb::TypeNameSpecifierImplSP
324 GetTypeNameSpecifierAtIndex (size_t index)
326 return GetTypeNameSpecifierAtIndex_Impl(index, (KeyType*)NULL);
332 m_format_map.Clear();
336 LoopThrough (CallbackType callback, void* param)
338 m_format_map.LoopThrough(callback,param);
344 return m_format_map.GetCount();
349 BackEndType m_format_map;
353 DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
358 Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
360 m_format_map.Add(type,entry);
363 void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
365 m_format_map.Add(GetValidTypeName_Impl(type), entry);
369 Delete_Impl (ConstString type, ConstString *dummy)
371 return m_format_map.Delete(type);
375 Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
377 Mutex& x_mutex = m_format_map.mutex();
378 lldb_private::Mutex::Locker locker(x_mutex);
379 MapIterator pos, end = m_format_map.map().end();
380 for (pos = m_format_map.map().begin(); pos != end; pos++)
382 lldb::RegularExpressionSP regex = pos->first;
383 if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
385 m_format_map.map().erase(pos);
386 if (m_format_map.listener)
387 m_format_map.listener->Changed();
395 Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
397 return m_format_map.Get(type, entry);
401 GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
403 return Get_Impl(type,entry, (KeyType*)0);
406 lldb::TypeNameSpecifierImplSP
407 GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
409 ConstString key = m_format_map.GetKeyAtIndex(index);
411 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
414 return lldb::TypeNameSpecifierImplSP();
417 lldb::TypeNameSpecifierImplSP
418 GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
420 lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
421 if (regex.get() == NULL)
422 return lldb::TypeNameSpecifierImplSP();
423 return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
428 Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
430 const char* key_cstr = key.AsCString();
433 Mutex& x_mutex = m_format_map.mutex();
434 lldb_private::Mutex::Locker locker(x_mutex);
435 MapIterator pos, end = m_format_map.map().end();
436 for (pos = m_format_map.map().begin(); pos != end; pos++)
438 lldb::RegularExpressionSP regex = pos->first;
439 if (regex->Execute(key_cstr))
449 GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
451 Mutex& x_mutex = m_format_map.mutex();
452 lldb_private::Mutex::Locker locker(x_mutex);
453 MapIterator pos, end = m_format_map.map().end();
454 for (pos = m_format_map.map().begin(); pos != end; pos++)
456 lldb::RegularExpressionSP regex = pos->first;
457 if (strcmp(regex->GetText(),key.AsCString()) == 0)
467 Get (const FormattersMatchVector& candidates,
471 for (const FormattersMatchCandidate& candidate : candidates)
473 // FIXME: could we do the IsMatch() check first?
474 if (Get(candidate.GetTypeName(),entry))
476 if (candidate.IsMatch(entry) == false)
484 *reason = candidate.GetReason();
493 } // namespace lldb_private
495 #endif // lldb_FormattersContainer_h_