blob: 9b77ab13f4dd64a2846908f4d1467a6467f66f7e [file] [log] [blame]
//===-- 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_