blob: d2da672f13dcb551d8e4b9c64f1f2b41fcd29ae7 [file] [log] [blame]
//===-- TypeCategoryMap.cpp ----------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/DataFormatters/TypeCategoryMap.h"
#include "lldb/DataFormatters/FormatClasses.h"
#include "lldb/Utility/Log.h"
// C Includes
// C++ Includes
// Other libraries and framework includes
// Project includes
using namespace lldb;
using namespace lldb_private;
TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
: m_map_mutex(), 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 TypeCategoryMap::Add(KeyType name, const ValueSP &entry) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
m_map[name] = entry;
if (listener)
listener->Changed();
}
bool TypeCategoryMap::Delete(KeyType name) {
std::lock_guard<std::recursive_mutex> guard(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 TypeCategoryMap::Enable(KeyType category_name, Position pos) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
ValueSP category;
if (!Get(category_name, category))
return false;
return Enable(category, pos);
}
bool TypeCategoryMap::Disable(KeyType category_name) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
ValueSP category;
if (!Get(category_name, category))
return false;
return Disable(category);
}
bool TypeCategoryMap::Enable(ValueSP category, Position pos) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
if (category.get()) {
Position pos_w = pos;
if (pos == First || m_active_categories.size() == 0)
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 TypeCategoryMap::Disable(ValueSP category) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
if (category.get()) {
m_active_categories.remove_if(delete_matching_categories(category));
category->Disable();
return true;
}
return false;
}
void TypeCategoryMap::EnableAllCategories() {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
std::vector<ValueSP> sorted_categories(m_map.size(), ValueSP());
MapType::iterator iter = m_map.begin(), end = m_map.end();
for (; iter != end; ++iter) {
if (iter->second->IsEnabled())
continue;
auto pos = iter->second->GetLastEnabledPosition();
if (pos >= sorted_categories.size()) {
auto iter = std::find_if(
sorted_categories.begin(), sorted_categories.end(),
[](const ValueSP &sp) -> bool { return sp.get() == nullptr; });
pos = std::distance(sorted_categories.begin(), iter);
}
sorted_categories.at(pos) = iter->second;
}
decltype(sorted_categories)::iterator viter = sorted_categories.begin(),
vend = sorted_categories.end();
for (; viter != vend; viter++)
if (viter->get())
Enable(*viter, Last);
}
void TypeCategoryMap::DisableAllCategories() {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
Position p = First;
for (; false == m_active_categories.empty(); p++) {
m_active_categories.front()->SetEnabledPosition(p);
Disable(m_active_categories.front());
}
}
void TypeCategoryMap::Clear() {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
m_map.clear();
m_active_categories.clear();
if (listener)
listener->Changed();
}
bool TypeCategoryMap::Get(KeyType name, ValueSP &entry) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
MapIterator iter = m_map.find(name);
if (iter == m_map.end())
return false;
entry = iter->second;
return true;
}
bool TypeCategoryMap::Get(uint32_t pos, ValueSP &entry) {
std::lock_guard<std::recursive_mutex> guard(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;
}
bool TypeCategoryMap::AnyMatches(
ConstString type_name, TypeCategoryImpl::FormatCategoryItems items,
bool only_enabled, const char **matching_category,
TypeCategoryImpl::FormatCategoryItems *matching_type) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
MapIterator pos, end = m_map.end();
for (pos = m_map.begin(); pos != end; pos++) {
if (pos->second->AnyMatches(type_name, items, only_enabled,
matching_category, matching_type))
return true;
}
return false;
}
lldb::TypeFormatImplSP
TypeCategoryMap::GetFormat(FormattersMatchData &match_data) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
if (log) {
for (auto match : match_data.GetMatchesVector()) {
log->Printf(
"[CategoryMap::GetFormat] candidate match = %s %s %s %s reason = "
"%" PRIu32,
match.GetTypeName().GetCString(),
match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
match.DidStripReference() ? "strip-reference" : "no-strip-reference",
match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
match.GetReason());
}
}
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeFormatImplSP current_format;
if (log)
log->Printf("[TypeCategoryMap::GetFormat] Trying to use category %s",
category_sp->GetName());
if (!category_sp->Get(match_data.GetValueObject(),
match_data.GetMatchesVector(), current_format,
&reason_why))
continue;
return current_format;
}
if (log)
log->Printf(
"[TypeCategoryMap::GetFormat] nothing found - returning empty SP");
return lldb::TypeFormatImplSP();
}
lldb::TypeSummaryImplSP
TypeCategoryMap::GetSummaryFormat(FormattersMatchData &match_data) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
if (log) {
for (auto match : match_data.GetMatchesVector()) {
log->Printf(
"[CategoryMap::GetSummaryFormat] candidate match = %s %s %s %s "
"reason = %" PRIu32,
match.GetTypeName().GetCString(),
match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
match.DidStripReference() ? "strip-reference" : "no-strip-reference",
match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
match.GetReason());
}
}
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeSummaryImplSP current_format;
if (log)
log->Printf("[CategoryMap::GetSummaryFormat] Trying to use category %s",
category_sp->GetName());
if (!category_sp->Get(match_data.GetValueObject(),
match_data.GetMatchesVector(), current_format,
&reason_why))
continue;
return current_format;
}
if (log)
log->Printf(
"[CategoryMap::GetSummaryFormat] nothing found - returning empty SP");
return lldb::TypeSummaryImplSP();
}
#ifndef LLDB_DISABLE_PYTHON
lldb::SyntheticChildrenSP
TypeCategoryMap::GetSyntheticChildren(FormattersMatchData &match_data) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
if (log) {
for (auto match : match_data.GetMatchesVector()) {
log->Printf(
"[CategoryMap::GetSyntheticChildren] candidate match = %s %s %s %s "
"reason = %" PRIu32,
match.GetTypeName().GetCString(),
match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
match.DidStripReference() ? "strip-reference" : "no-strip-reference",
match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
match.GetReason());
}
}
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::SyntheticChildrenSP current_format;
if (log)
log->Printf(
"[CategoryMap::GetSyntheticChildren] Trying to use category %s",
category_sp->GetName());
if (!category_sp->Get(match_data.GetValueObject(),
match_data.GetMatchesVector(), current_format,
&reason_why))
continue;
return current_format;
}
if (log)
log->Printf("[CategoryMap::GetSyntheticChildren] nothing found - returning "
"empty SP");
return lldb::SyntheticChildrenSP();
}
#endif
lldb::TypeValidatorImplSP
TypeCategoryMap::GetValidator(FormattersMatchData &match_data) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
uint32_t reason_why;
ActiveCategoriesIterator begin, end = m_active_categories.end();
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_DATAFORMATTERS));
if (log) {
for (auto match : match_data.GetMatchesVector()) {
log->Printf(
"[CategoryMap::GetValidator] candidate match = %s %s %s %s reason = "
"%" PRIu32,
match.GetTypeName().GetCString(),
match.DidStripPointer() ? "strip-pointers" : "no-strip-pointers",
match.DidStripReference() ? "strip-reference" : "no-strip-reference",
match.DidStripTypedef() ? "strip-typedef" : "no-strip-typedef",
match.GetReason());
}
}
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category_sp = *begin;
lldb::TypeValidatorImplSP current_format;
if (log)
log->Printf("[CategoryMap::GetValidator] Trying to use category %s",
category_sp->GetName());
if (!category_sp->Get(match_data.GetValueObject(),
match_data.GetMatchesVector(), current_format,
&reason_why))
continue;
return current_format;
}
if (log)
log->Printf(
"[CategoryMap::GetValidator] nothing found - returning empty SP");
return lldb::TypeValidatorImplSP();
}
void TypeCategoryMap::ForEach(ForEachCallback callback) {
if (callback) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
// loop through enabled categories in respective order
{
ActiveCategoriesIterator begin, end = m_active_categories.end();
for (begin = m_active_categories.begin(); begin != end; begin++) {
lldb::TypeCategoryImplSP category = *begin;
if (!callback(category))
break;
}
}
// loop through disabled categories in just any order
{
MapIterator pos, end = m_map.end();
for (pos = m_map.begin(); pos != end; pos++) {
if (pos->second->IsEnabled())
continue;
if (!callback(pos->second))
break;
}
}
}
}
TypeCategoryImplSP TypeCategoryMap::GetAtIndex(uint32_t index) {
std::lock_guard<std::recursive_mutex> guard(m_map_mutex);
if (index < m_map.size()) {
MapIterator pos, end = m_map.end();
for (pos = m_map.begin(); pos != end; pos++) {
if (index == 0)
return pos->second;
index--;
}
}
return TypeCategoryImplSP();
}