mirror of
https://github.com/opnsense/src.git
synced 2026-02-28 04:10:49 -05:00
454 lines
12 KiB
C++
454 lines
12 KiB
C++
//===-- FormattersContainer.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_FormattersContainer_h_
|
|
#define lldb_FormattersContainer_h_
|
|
|
|
// C Includes
|
|
// C++ Includes
|
|
#include <functional>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <string>
|
|
|
|
// Other libraries and framework includes
|
|
// Project includes
|
|
#include "lldb/lldb-public.h"
|
|
|
|
#include "lldb/Core/RegularExpression.h"
|
|
#include "lldb/Core/ValueObject.h"
|
|
#include "lldb/DataFormatters/FormatClasses.h"
|
|
#include "lldb/DataFormatters/TypeFormat.h"
|
|
#include "lldb/DataFormatters/TypeSummary.h"
|
|
#include "lldb/DataFormatters/TypeSynthetic.h"
|
|
#include "lldb/DataFormatters/TypeValidator.h"
|
|
#include "lldb/Symbol/CompilerType.h"
|
|
#include "lldb/Utility/StringLexer.h"
|
|
|
|
namespace lldb_private {
|
|
|
|
class IFormatChangeListener
|
|
{
|
|
public:
|
|
virtual
|
|
~IFormatChangeListener() = default;
|
|
|
|
virtual void
|
|
Changed () = 0;
|
|
|
|
virtual uint32_t
|
|
GetCurrentRevision () = 0;
|
|
};
|
|
|
|
// 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 inline ConstString
|
|
GetValidTypeName_Impl (const ConstString& type)
|
|
{
|
|
if (type.IsEmpty())
|
|
return type;
|
|
|
|
std::string type_cstr(type.AsCString());
|
|
lldb_utility::StringLexer type_lexer(type_cstr);
|
|
|
|
type_lexer.AdvanceIf("class ");
|
|
type_lexer.AdvanceIf("enum ");
|
|
type_lexer.AdvanceIf("struct ");
|
|
type_lexer.AdvanceIf("union ");
|
|
|
|
while (type_lexer.NextIf({' ','\t','\v','\f'}).first)
|
|
;
|
|
|
|
return ConstString(type_lexer.GetUnlexed());
|
|
}
|
|
|
|
template<typename KeyType, typename ValueType>
|
|
class FormattersContainer;
|
|
|
|
template<typename KeyType, typename ValueType>
|
|
class FormatMap
|
|
{
|
|
public:
|
|
typedef typename ValueType::SharedPointer ValueSP;
|
|
typedef std::map<KeyType, ValueSP> MapType;
|
|
typedef typename MapType::iterator MapIterator;
|
|
typedef std::function<bool(KeyType, const ValueSP&)> ForEachCallback;
|
|
|
|
FormatMap(IFormatChangeListener* lst) :
|
|
m_map(),
|
|
m_map_mutex(Mutex::eMutexTypeRecursive),
|
|
listener(lst)
|
|
{
|
|
}
|
|
|
|
void
|
|
Add(KeyType name,
|
|
const ValueSP& entry)
|
|
{
|
|
if (listener)
|
|
entry->GetRevision() = listener->GetCurrentRevision();
|
|
else
|
|
entry->GetRevision() = 0;
|
|
|
|
Mutex::Locker locker(m_map_mutex);
|
|
m_map[name] = entry;
|
|
if (listener)
|
|
listener->Changed();
|
|
}
|
|
|
|
bool
|
|
Delete (KeyType name)
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
MapIterator iter = m_map.find(name);
|
|
if (iter == m_map.end())
|
|
return false;
|
|
m_map.erase(name);
|
|
if (listener)
|
|
listener->Changed();
|
|
return true;
|
|
}
|
|
|
|
void
|
|
Clear ()
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
m_map.clear();
|
|
if (listener)
|
|
listener->Changed();
|
|
}
|
|
|
|
bool
|
|
Get(KeyType name,
|
|
ValueSP& entry)
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
MapIterator iter = m_map.find(name);
|
|
if (iter == m_map.end())
|
|
return false;
|
|
entry = iter->second;
|
|
return true;
|
|
}
|
|
|
|
void
|
|
ForEach (ForEachCallback callback)
|
|
{
|
|
if (callback)
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
MapIterator pos, end = m_map.end();
|
|
for (pos = m_map.begin(); pos != end; pos++)
|
|
{
|
|
KeyType type = pos->first;
|
|
if (!callback(type, pos->second))
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t
|
|
GetCount ()
|
|
{
|
|
return m_map.size();
|
|
}
|
|
|
|
ValueSP
|
|
GetValueAtIndex (size_t index)
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
MapIterator iter = m_map.begin();
|
|
MapIterator end = m_map.end();
|
|
while (index > 0)
|
|
{
|
|
iter++;
|
|
index--;
|
|
if (end == iter)
|
|
return ValueSP();
|
|
}
|
|
return iter->second;
|
|
}
|
|
|
|
KeyType
|
|
GetKeyAtIndex (size_t index)
|
|
{
|
|
Mutex::Locker locker(m_map_mutex);
|
|
MapIterator iter = m_map.begin();
|
|
MapIterator end = m_map.end();
|
|
while (index > 0)
|
|
{
|
|
iter++;
|
|
index--;
|
|
if (end == iter)
|
|
return KeyType();
|
|
}
|
|
return iter->first;
|
|
}
|
|
|
|
protected:
|
|
MapType m_map;
|
|
Mutex m_map_mutex;
|
|
IFormatChangeListener* listener;
|
|
|
|
MapType&
|
|
map ()
|
|
{
|
|
return m_map;
|
|
}
|
|
|
|
Mutex&
|
|
mutex ()
|
|
{
|
|
return m_map_mutex;
|
|
}
|
|
|
|
friend class FormattersContainer<KeyType, ValueType>;
|
|
friend class FormatManager;
|
|
};
|
|
|
|
template<typename KeyType, typename ValueType>
|
|
class FormattersContainer
|
|
{
|
|
protected:
|
|
typedef FormatMap<KeyType,ValueType> BackEndType;
|
|
|
|
public:
|
|
typedef typename BackEndType::MapType MapType;
|
|
typedef typename MapType::iterator MapIterator;
|
|
typedef typename MapType::key_type MapKeyType;
|
|
typedef typename MapType::mapped_type MapValueType;
|
|
typedef typename BackEndType::ForEachCallback ForEachCallback;
|
|
typedef typename std::shared_ptr<FormattersContainer<KeyType, ValueType> > SharedPointer;
|
|
|
|
friend class TypeCategoryImpl;
|
|
|
|
FormattersContainer(std::string name,
|
|
IFormatChangeListener* lst) :
|
|
m_format_map(lst),
|
|
m_name(name)
|
|
{
|
|
}
|
|
|
|
void
|
|
Add (const MapKeyType &type, const MapValueType& entry)
|
|
{
|
|
Add_Impl(type, entry, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
bool
|
|
Delete (ConstString type)
|
|
{
|
|
return Delete_Impl(type, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
bool
|
|
Get(ValueObject& valobj,
|
|
MapValueType& entry,
|
|
lldb::DynamicValueType use_dynamic,
|
|
uint32_t* why = nullptr)
|
|
{
|
|
uint32_t value = lldb_private::eFormatterChoiceCriterionDirectChoice;
|
|
CompilerType ast_type(valobj.GetCompilerType());
|
|
bool ret = Get(valobj, ast_type, entry, use_dynamic, value);
|
|
if (ret)
|
|
entry = MapValueType(entry);
|
|
else
|
|
entry = MapValueType();
|
|
if (why)
|
|
*why = value;
|
|
return ret;
|
|
}
|
|
|
|
bool
|
|
Get (ConstString type, MapValueType& entry)
|
|
{
|
|
return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
bool
|
|
GetExact (ConstString type, MapValueType& entry)
|
|
{
|
|
return GetExact_Impl(type, entry, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
MapValueType
|
|
GetAtIndex (size_t index)
|
|
{
|
|
return m_format_map.GetValueAtIndex(index);
|
|
}
|
|
|
|
lldb::TypeNameSpecifierImplSP
|
|
GetTypeNameSpecifierAtIndex (size_t index)
|
|
{
|
|
return GetTypeNameSpecifierAtIndex_Impl(index, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
void
|
|
Clear ()
|
|
{
|
|
m_format_map.Clear();
|
|
}
|
|
|
|
void
|
|
ForEach (ForEachCallback callback)
|
|
{
|
|
m_format_map.ForEach(callback);
|
|
}
|
|
|
|
uint32_t
|
|
GetCount ()
|
|
{
|
|
return m_format_map.GetCount();
|
|
}
|
|
|
|
protected:
|
|
BackEndType m_format_map;
|
|
std::string m_name;
|
|
|
|
DISALLOW_COPY_AND_ASSIGN(FormattersContainer);
|
|
|
|
void
|
|
Add_Impl (const MapKeyType &type, const MapValueType& entry, lldb::RegularExpressionSP *dummy)
|
|
{
|
|
m_format_map.Add(type,entry);
|
|
}
|
|
|
|
void Add_Impl (const ConstString &type, const MapValueType& entry, ConstString *dummy)
|
|
{
|
|
m_format_map.Add(GetValidTypeName_Impl(type), entry);
|
|
}
|
|
|
|
bool
|
|
Delete_Impl (ConstString type, ConstString *dummy)
|
|
{
|
|
return m_format_map.Delete(type);
|
|
}
|
|
|
|
bool
|
|
Delete_Impl (ConstString type, lldb::RegularExpressionSP *dummy)
|
|
{
|
|
Mutex& x_mutex = m_format_map.mutex();
|
|
lldb_private::Mutex::Locker locker(x_mutex);
|
|
MapIterator pos, end = m_format_map.map().end();
|
|
for (pos = m_format_map.map().begin(); pos != end; pos++)
|
|
{
|
|
lldb::RegularExpressionSP regex = pos->first;
|
|
if ( ::strcmp(type.AsCString(),regex->GetText()) == 0)
|
|
{
|
|
m_format_map.map().erase(pos);
|
|
if (m_format_map.listener)
|
|
m_format_map.listener->Changed();
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Get_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
|
|
{
|
|
return m_format_map.Get(type, entry);
|
|
}
|
|
|
|
bool
|
|
GetExact_Impl (ConstString type, MapValueType& entry, ConstString *dummy)
|
|
{
|
|
return Get_Impl(type, entry, static_cast<KeyType*>(nullptr));
|
|
}
|
|
|
|
lldb::TypeNameSpecifierImplSP
|
|
GetTypeNameSpecifierAtIndex_Impl (size_t index, ConstString *dummy)
|
|
{
|
|
ConstString key = m_format_map.GetKeyAtIndex(index);
|
|
if (key)
|
|
return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(key.AsCString(),
|
|
false));
|
|
else
|
|
return lldb::TypeNameSpecifierImplSP();
|
|
}
|
|
|
|
lldb::TypeNameSpecifierImplSP
|
|
GetTypeNameSpecifierAtIndex_Impl (size_t index, lldb::RegularExpressionSP *dummy)
|
|
{
|
|
lldb::RegularExpressionSP regex = m_format_map.GetKeyAtIndex(index);
|
|
if (regex.get() == nullptr)
|
|
return lldb::TypeNameSpecifierImplSP();
|
|
return lldb::TypeNameSpecifierImplSP(new TypeNameSpecifierImpl(regex->GetText(),
|
|
true));
|
|
}
|
|
|
|
bool
|
|
Get_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
|
|
{
|
|
const char* key_cstr = key.AsCString();
|
|
if (!key_cstr)
|
|
return false;
|
|
Mutex& x_mutex = m_format_map.mutex();
|
|
lldb_private::Mutex::Locker locker(x_mutex);
|
|
MapIterator pos, end = m_format_map.map().end();
|
|
for (pos = m_format_map.map().begin(); pos != end; pos++)
|
|
{
|
|
lldb::RegularExpressionSP regex = pos->first;
|
|
if (regex->Execute(key_cstr))
|
|
{
|
|
value = pos->second;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
GetExact_Impl (ConstString key, MapValueType& value, lldb::RegularExpressionSP *dummy)
|
|
{
|
|
Mutex& x_mutex = m_format_map.mutex();
|
|
lldb_private::Mutex::Locker locker(x_mutex);
|
|
MapIterator pos, end = m_format_map.map().end();
|
|
for (pos = m_format_map.map().begin(); pos != end; pos++)
|
|
{
|
|
lldb::RegularExpressionSP regex = pos->first;
|
|
if (strcmp(regex->GetText(),key.AsCString()) == 0)
|
|
{
|
|
value = pos->second;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool
|
|
Get (const FormattersMatchVector& candidates,
|
|
MapValueType& entry,
|
|
uint32_t *reason)
|
|
{
|
|
for (const FormattersMatchCandidate& candidate : candidates)
|
|
{
|
|
if (Get(candidate.GetTypeName(),entry))
|
|
{
|
|
if (candidate.IsMatch(entry) == false)
|
|
{
|
|
entry.reset();
|
|
continue;
|
|
}
|
|
else
|
|
{
|
|
if(reason)
|
|
*reason = candidate.GetReason();
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
|
|
} // namespace lldb_private
|
|
|
|
#endif // lldb_FormattersContainer_h_
|