| //===-- FormatManager.h -------------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef lldb_FormatManager_h_ |
| #define lldb_FormatManager_h_ |
| |
| // C Includes |
| // C++ Includes |
| |
| // Other libraries and framework includes |
| // Project includes |
| #include "lldb/lldb-public.h" |
| #include "lldb/lldb-enumerations.h" |
| |
| #include "lldb/Core/FormatNavigator.h" |
| #include "lldb/Interpreter/ScriptInterpreterPython.h" |
| #include "lldb/Target/ExecutionContext.h" |
| #include "lldb/Target/Platform.h" |
| |
| using lldb::LogSP; |
| |
| namespace lldb_private { |
| |
| // this file (and its. cpp) contain the low-level implementation of LLDB Data Visualization |
| // class DataVisualization is the high-level front-end of this feature |
| // clients should refer to that class as the entry-point into the data formatters |
| // unless they have a good reason to bypass it and prefer to use this file's objects directly |
| |
| class CategoryMap; |
| |
| class TypeCategoryImpl |
| { |
| private: |
| |
| typedef FormatNavigator<ConstString, TypeSummaryImpl> SummaryNavigator; |
| typedef FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl> RegexSummaryNavigator; |
| |
| typedef FormatNavigator<ConstString, TypeFilterImpl> FilterNavigator; |
| typedef FormatNavigator<lldb::RegularExpressionSP, TypeFilterImpl> RegexFilterNavigator; |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| typedef FormatNavigator<ConstString, TypeSyntheticImpl> SynthNavigator; |
| typedef FormatNavigator<lldb::RegularExpressionSP, TypeSyntheticImpl> RegexSynthNavigator; |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| typedef SummaryNavigator::MapType SummaryMap; |
| typedef RegexSummaryNavigator::MapType RegexSummaryMap; |
| typedef FilterNavigator::MapType FilterMap; |
| typedef RegexFilterNavigator::MapType RegexFilterMap; |
| #ifndef LLDB_DISABLE_PYTHON |
| typedef SynthNavigator::MapType SynthMap; |
| typedef RegexSynthNavigator::MapType RegexSynthMap; |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| public: |
| |
| typedef uint16_t FormatCategoryItems; |
| static const uint16_t ALL_ITEM_TYPES = UINT16_MAX; |
| |
| typedef SummaryNavigator::SharedPointer SummaryNavigatorSP; |
| typedef RegexSummaryNavigator::SharedPointer RegexSummaryNavigatorSP; |
| typedef FilterNavigator::SharedPointer FilterNavigatorSP; |
| typedef RegexFilterNavigator::SharedPointer RegexFilterNavigatorSP; |
| #ifndef LLDB_DISABLE_PYTHON |
| typedef SynthNavigator::SharedPointer SynthNavigatorSP; |
| typedef RegexSynthNavigator::SharedPointer RegexSynthNavigatorSP; |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| TypeCategoryImpl (IFormatChangeListener* clist, |
| ConstString name); |
| |
| SummaryNavigatorSP |
| GetSummaryNavigator () |
| { |
| return SummaryNavigatorSP(m_summary_nav); |
| } |
| |
| RegexSummaryNavigatorSP |
| GetRegexSummaryNavigator () |
| { |
| return RegexSummaryNavigatorSP(m_regex_summary_nav); |
| } |
| |
| FilterNavigatorSP |
| GetFilterNavigator () |
| { |
| return FilterNavigatorSP(m_filter_nav); |
| } |
| |
| RegexFilterNavigatorSP |
| GetRegexFilterNavigator () |
| { |
| return RegexFilterNavigatorSP(m_regex_filter_nav); |
| } |
| |
| lldb::TypeNameSpecifierImplSP |
| GetTypeNameSpecifierForSummaryAtIndex (uint32_t index) |
| { |
| if (index < m_summary_nav->GetCount()) |
| return m_summary_nav->GetTypeNameSpecifierAtIndex(index); |
| else |
| return m_regex_summary_nav->GetTypeNameSpecifierAtIndex(index-m_summary_nav->GetCount()); |
| } |
| |
| SummaryNavigator::MapValueType |
| GetSummaryAtIndex (uint32_t index) |
| { |
| if (index < m_summary_nav->GetCount()) |
| return m_summary_nav->GetAtIndex(index); |
| else |
| return m_regex_summary_nav->GetAtIndex(index-m_summary_nav->GetCount()); |
| } |
| |
| FilterNavigator::MapValueType |
| GetFilterAtIndex (uint32_t index) |
| { |
| if (index < m_filter_nav->GetCount()) |
| return m_filter_nav->GetAtIndex(index); |
| else |
| return m_regex_filter_nav->GetAtIndex(index-m_filter_nav->GetCount()); |
| } |
| |
| lldb::TypeNameSpecifierImplSP |
| GetTypeNameSpecifierForFilterAtIndex (uint32_t index) |
| { |
| if (index < m_filter_nav->GetCount()) |
| return m_filter_nav->GetTypeNameSpecifierAtIndex(index); |
| else |
| return m_regex_filter_nav->GetTypeNameSpecifierAtIndex(index-m_filter_nav->GetCount()); |
| } |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| SynthNavigatorSP |
| GetSyntheticNavigator () |
| { |
| return SynthNavigatorSP(m_synth_nav); |
| } |
| |
| RegexSynthNavigatorSP |
| GetRegexSyntheticNavigator () |
| { |
| return RegexSynthNavigatorSP(m_regex_synth_nav); |
| } |
| |
| SynthNavigator::MapValueType |
| GetSyntheticAtIndex (uint32_t index) |
| { |
| if (index < m_synth_nav->GetCount()) |
| return m_synth_nav->GetAtIndex(index); |
| else |
| return m_regex_synth_nav->GetAtIndex(index-m_synth_nav->GetCount()); |
| } |
| |
| lldb::TypeNameSpecifierImplSP |
| GetTypeNameSpecifierForSyntheticAtIndex (uint32_t index) |
| { |
| if (index < m_synth_nav->GetCount()) |
| return m_synth_nav->GetTypeNameSpecifierAtIndex(index); |
| else |
| return m_regex_synth_nav->GetTypeNameSpecifierAtIndex(index - m_synth_nav->GetCount()); |
| } |
| |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| bool |
| IsEnabled () const |
| { |
| return m_enabled; |
| } |
| |
| uint32_t |
| GetEnabledPosition() |
| { |
| if (m_enabled == false) |
| return UINT32_MAX; |
| else |
| return m_enabled_position; |
| } |
| |
| bool |
| Get (ValueObject& valobj, |
| lldb::TypeSummaryImplSP& entry, |
| lldb::DynamicValueType use_dynamic, |
| uint32_t* reason = NULL); |
| |
| bool |
| Get (ValueObject& valobj, |
| lldb::SyntheticChildrenSP& entry, |
| lldb::DynamicValueType use_dynamic, |
| uint32_t* reason = NULL); |
| |
| void |
| Clear (FormatCategoryItems items = ALL_ITEM_TYPES); |
| |
| bool |
| Delete (ConstString name, |
| FormatCategoryItems items = ALL_ITEM_TYPES); |
| |
| uint32_t |
| GetCount (FormatCategoryItems items = ALL_ITEM_TYPES); |
| |
| const char* |
| GetName () |
| { |
| return m_name.GetCString(); |
| } |
| |
| bool |
| AnyMatches (ConstString type_name, |
| FormatCategoryItems items = ALL_ITEM_TYPES, |
| bool only_enabled = true, |
| const char** matching_category = NULL, |
| FormatCategoryItems* matching_type = NULL); |
| |
| typedef STD_SHARED_PTR(TypeCategoryImpl) SharedPointer; |
| |
| private: |
| SummaryNavigator::SharedPointer m_summary_nav; |
| RegexSummaryNavigator::SharedPointer m_regex_summary_nav; |
| FilterNavigator::SharedPointer m_filter_nav; |
| RegexFilterNavigator::SharedPointer m_regex_filter_nav; |
| #ifndef LLDB_DISABLE_PYTHON |
| SynthNavigator::SharedPointer m_synth_nav; |
| RegexSynthNavigator::SharedPointer m_regex_synth_nav; |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| bool m_enabled; |
| |
| IFormatChangeListener* m_change_listener; |
| |
| Mutex m_mutex; |
| |
| ConstString m_name; |
| |
| uint32_t m_enabled_position; |
| |
| void |
| Enable (bool value, |
| uint32_t position) |
| { |
| Mutex::Locker(m_mutex); |
| m_enabled = value; |
| m_enabled_position = position; |
| if (m_change_listener) |
| m_change_listener->Changed(); |
| } |
| |
| void |
| Disable () |
| { |
| Enable(false, UINT32_MAX); |
| } |
| |
| friend class CategoryMap; |
| |
| friend class FormatNavigator<ConstString, TypeSummaryImpl>; |
| friend class FormatNavigator<lldb::RegularExpressionSP, TypeSummaryImpl>; |
| |
| friend class FormatNavigator<ConstString, TypeFilterImpl>; |
| friend class FormatNavigator<lldb::RegularExpressionSP, TypeFilterImpl>; |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| friend class FormatNavigator<ConstString, TypeSyntheticImpl>; |
| friend class FormatNavigator<lldb::RegularExpressionSP, TypeSyntheticImpl>; |
| #endif // #ifndef LLDB_DISABLE_PYTHON |
| |
| |
| }; |
| |
| class CategoryMap |
| { |
| private: |
| typedef ConstString KeyType; |
| typedef TypeCategoryImpl ValueType; |
| typedef ValueType::SharedPointer ValueSP; |
| typedef std::list<lldb::TypeCategoryImplSP> ActiveCategoriesList; |
| typedef ActiveCategoriesList::iterator ActiveCategoriesIterator; |
| |
| public: |
| typedef std::map<KeyType, ValueSP> MapType; |
| typedef MapType::iterator MapIterator; |
| typedef bool(*CallbackType)(void*, const ValueSP&); |
| typedef uint32_t Position; |
| |
| static const Position First = 0; |
| static const Position Default = 1; |
| static const Position Last = UINT32_MAX; |
| |
| CategoryMap (IFormatChangeListener* lst) : |
| m_map_mutex(Mutex::eMutexTypeRecursive), |
| listener(lst), |
| m_map(), |
| m_active_categories() |
| { |
| ConstString default_cs("default"); |
| lldb::TypeCategoryImplSP default_sp = lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs)); |
| Add(default_cs,default_sp); |
| Enable(default_cs,First); |
| } |
| |
| void |
| Add (KeyType name, |
| const ValueSP& entry) |
| { |
| Mutex::Locker(m_map_mutex); |
| m_map[name] = entry; |
| if (listener) |
| listener->Changed(); |
| } |
| |
| bool |
| Delete (KeyType name) |
| { |
| Mutex::Locker(m_map_mutex); |
| MapIterator iter = m_map.find(name); |
| if (iter == m_map.end()) |
| return false; |
| m_map.erase(name); |
| Disable(name); |
| if (listener) |
| listener->Changed(); |
| return true; |
| } |
| |
| bool |
| Enable (KeyType category_name, |
| Position pos = Default) |
| { |
| Mutex::Locker(m_map_mutex); |
| ValueSP category; |
| if (!Get(category_name,category)) |
| return false; |
| return Enable(category, pos); |
| } |
| |
| bool |
| Disable (KeyType category_name) |
| { |
| Mutex::Locker(m_map_mutex); |
| ValueSP category; |
| if (!Get(category_name,category)) |
| return false; |
| return Disable(category); |
| } |
| |
| bool |
| Enable (ValueSP category, |
| Position pos = Default) |
| { |
| Mutex::Locker(m_map_mutex); |
| if (category.get()) |
| { |
| Position pos_w = pos; |
| if (pos == First) |
| m_active_categories.push_front(category); |
| else if (pos == Last || pos == m_active_categories.size()) |
| m_active_categories.push_back(category); |
| else if (pos < m_active_categories.size()) |
| { |
| ActiveCategoriesList::iterator iter = m_active_categories.begin(); |
| while (pos_w) |
| { |
| pos_w--,iter++; |
| } |
| m_active_categories.insert(iter,category); |
| } |
| else |
| return false; |
| category->Enable(true, |
| pos); |
| return true; |
| } |
| return false; |
| } |
| |
| bool |
| Disable (ValueSP category) |
| { |
| Mutex::Locker(m_map_mutex); |
| if (category.get()) |
| { |
| m_active_categories.remove_if(delete_matching_categories(category)); |
| category->Disable(); |
| return true; |
| } |
| return false; |
| } |
| |
| void |
| Clear () |
| { |
| Mutex::Locker(m_map_mutex); |
| m_map.clear(); |
| m_active_categories.clear(); |
| if (listener) |
| listener->Changed(); |
| } |
| |
| bool |
| Get (KeyType name, |
| ValueSP& entry) |
| { |
| Mutex::Locker(m_map_mutex); |
| MapIterator iter = m_map.find(name); |
| if (iter == m_map.end()) |
| return false; |
| entry = iter->second; |
| return true; |
| } |
| |
| bool |
| Get (uint32_t pos, |
| ValueSP& entry) |
| { |
| Mutex::Locker(m_map_mutex); |
| MapIterator iter = m_map.begin(); |
| MapIterator end = m_map.end(); |
| while (pos > 0) |
| { |
| iter++; |
| pos--; |
| if (iter == end) |
| return false; |
| } |
| entry = iter->second; |
| return false; |
| } |
| |
| void |
| LoopThrough (CallbackType callback, void* param); |
| |
| lldb::TypeCategoryImplSP |
| GetAtIndex (uint32_t); |
| |
| bool |
| AnyMatches (ConstString type_name, |
| TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, |
| bool only_enabled = true, |
| const char** matching_category = NULL, |
| TypeCategoryImpl::FormatCategoryItems* matching_type = NULL); |
| |
| uint32_t |
| GetCount () |
| { |
| return m_map.size(); |
| } |
| |
| lldb::TypeSummaryImplSP |
| GetSummaryFormat (ValueObject& valobj, |
| lldb::DynamicValueType use_dynamic); |
| |
| lldb::SyntheticChildrenSP |
| GetSyntheticChildren (ValueObject& valobj, |
| lldb::DynamicValueType use_dynamic); |
| |
| private: |
| |
| class delete_matching_categories |
| { |
| lldb::TypeCategoryImplSP ptr; |
| public: |
| delete_matching_categories(lldb::TypeCategoryImplSP p) : ptr(p) |
| {} |
| |
| bool operator()(const lldb::TypeCategoryImplSP& other) |
| { |
| return ptr.get() == other.get(); |
| } |
| }; |
| |
| Mutex m_map_mutex; |
| IFormatChangeListener* listener; |
| |
| MapType m_map; |
| ActiveCategoriesList m_active_categories; |
| |
| MapType& map () |
| { |
| return m_map; |
| } |
| |
| ActiveCategoriesList& active_list () |
| { |
| return m_active_categories; |
| } |
| |
| Mutex& mutex () |
| { |
| return m_map_mutex; |
| } |
| |
| friend class FormatNavigator<KeyType, ValueType>; |
| friend class FormatManager; |
| }; |
| |
| class FormatManager : public IFormatChangeListener |
| { |
| typedef FormatNavigator<ConstString, TypeFormatImpl> ValueNavigator; |
| typedef ValueNavigator::MapType ValueMap; |
| typedef FormatMap<ConstString, TypeSummaryImpl> NamedSummariesMap; |
| typedef CategoryMap::MapType::iterator CategoryMapIterator; |
| public: |
| |
| typedef CategoryMap::CallbackType CategoryCallback; |
| |
| FormatManager (); |
| |
| ValueNavigator& |
| GetValueNavigator () |
| { |
| return m_value_nav; |
| } |
| |
| NamedSummariesMap& |
| GetNamedSummaryNavigator () |
| { |
| return m_named_summaries_map; |
| } |
| |
| void |
| EnableCategory (const ConstString& category_name, |
| CategoryMap::Position pos = CategoryMap::Default) |
| { |
| m_categories_map.Enable(category_name, |
| pos); |
| } |
| |
| void |
| DisableCategory (const ConstString& category_name) |
| { |
| m_categories_map.Disable(category_name); |
| } |
| |
| void |
| EnableCategory (const lldb::TypeCategoryImplSP& category, |
| CategoryMap::Position pos = CategoryMap::Default) |
| { |
| m_categories_map.Enable(category, |
| pos); |
| } |
| |
| void |
| DisableCategory (const lldb::TypeCategoryImplSP& category) |
| { |
| m_categories_map.Disable(category); |
| } |
| |
| bool |
| DeleteCategory (const ConstString& category_name) |
| { |
| return m_categories_map.Delete(category_name); |
| } |
| |
| void |
| ClearCategories () |
| { |
| return m_categories_map.Clear(); |
| } |
| |
| uint32_t |
| GetCategoriesCount () |
| { |
| return m_categories_map.GetCount(); |
| } |
| |
| lldb::TypeCategoryImplSP |
| GetCategoryAtIndex (uint32_t index) |
| { |
| return m_categories_map.GetAtIndex(index); |
| } |
| |
| void |
| LoopThroughCategories (CategoryCallback callback, void* param) |
| { |
| m_categories_map.LoopThrough(callback, param); |
| } |
| |
| lldb::TypeCategoryImplSP |
| GetCategory (const char* category_name = NULL, |
| bool can_create = true) |
| { |
| if (!category_name) |
| return GetCategory(m_default_category_name); |
| return GetCategory(ConstString(category_name)); |
| } |
| |
| lldb::TypeCategoryImplSP |
| GetCategory (const ConstString& category_name, |
| bool can_create = true); |
| |
| lldb::TypeSummaryImplSP |
| GetSummaryFormat (ValueObject& valobj, |
| lldb::DynamicValueType use_dynamic) |
| { |
| return m_categories_map.GetSummaryFormat(valobj, use_dynamic); |
| } |
| |
| lldb::SyntheticChildrenSP |
| GetSyntheticChildren (ValueObject& valobj, |
| lldb::DynamicValueType use_dynamic) |
| { |
| return m_categories_map.GetSyntheticChildren(valobj, use_dynamic); |
| } |
| |
| bool |
| AnyMatches (ConstString type_name, |
| TypeCategoryImpl::FormatCategoryItems items = TypeCategoryImpl::ALL_ITEM_TYPES, |
| bool only_enabled = true, |
| const char** matching_category = NULL, |
| TypeCategoryImpl::FormatCategoryItems* matching_type = NULL) |
| { |
| return m_categories_map.AnyMatches(type_name, |
| items, |
| only_enabled, |
| matching_category, |
| matching_type); |
| } |
| |
| static bool |
| GetFormatFromCString (const char *format_cstr, |
| bool partial_match_ok, |
| lldb::Format &format); |
| |
| static char |
| GetFormatAsFormatChar (lldb::Format format); |
| |
| static const char * |
| GetFormatAsCString (lldb::Format format); |
| |
| // if the user tries to add formatters for, say, "struct Foo" |
| // those will not match any type because of the way we strip qualifiers from typenames |
| // this method looks for the case where the user is adding a "class","struct","enum" or "union" Foo |
| // and strips the unnecessary qualifier |
| static ConstString |
| GetValidTypeName (const ConstString& type); |
| |
| // when DataExtractor dumps a vectorOfT, it uses a predefined format for each item |
| // this method returns it, or eFormatInvalid if vector_format is not a vectorOf |
| static lldb::Format |
| GetSingleItemFormat (lldb::Format vector_format); |
| |
| void |
| Changed () |
| { |
| __sync_add_and_fetch(&m_last_revision, +1); |
| } |
| |
| uint32_t |
| GetCurrentRevision () |
| { |
| return m_last_revision; |
| } |
| |
| ~FormatManager () |
| { |
| } |
| |
| private: |
| ValueNavigator m_value_nav; |
| NamedSummariesMap m_named_summaries_map; |
| uint32_t m_last_revision; |
| CategoryMap m_categories_map; |
| |
| ConstString m_default_category_name; |
| ConstString m_system_category_name; |
| ConstString m_gnu_cpp_category_name; |
| ConstString m_libcxx_category_name; |
| ConstString m_objc_category_name; |
| ConstString m_corefoundation_category_name; |
| ConstString m_coregraphics_category_name; |
| ConstString m_coreservices_category_name; |
| ConstString m_vectortypes_category_name; |
| ConstString m_appkit_category_name; |
| |
| CategoryMap& |
| GetCategories () |
| { |
| return m_categories_map; |
| } |
| |
| // WARNING: these are temporary functions that setup formatters |
| // while a few of these actually should be globally available and setup by LLDB itself |
| // most would actually belong to the users' lldbinit file or to some other form of configurable |
| // storage |
| void |
| LoadSTLFormatters(); |
| |
| void |
| LoadLibcxxFormatters(); |
| |
| void |
| LoadSystemFormatters(); |
| |
| #ifndef LLDB_DISABLE_PYTHON |
| void |
| LoadObjCFormatters(); |
| #endif |
| }; |
| |
| } // namespace lldb_private |
| |
| #endif // lldb_FormatManager_h_ |