Files
UnrealEngine/Engine/Source/Runtime/VerseCompiler/Private/uLang/Toolchain/ModularFeatureManager.cpp
2025-05-18 13:04:45 +08:00

196 lines
6.4 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "uLang/Toolchain/ModularFeatureManager.h"
#include "uLang/Toolchain/ModularFeature.h" // for IModularFeature
#include "uLang/Common/Containers/Array.h"
#include "uLang/Common/Containers/SharedPointer.h"
namespace uLang
{
namespace Private
{
class CModularFeatureRegistry : public Private::IModularFeatureRegistry
{
public:
void Add(const TSRef<Private::IModularFeature>& NewFeature, const RegistryId FeatureId);
bool Remove(const TSRef<Private::IModularFeature>& ToRemove);
void MergeIn(const CModularFeatureRegistry& OtherRegistry);
void SortDatabase();
CSymbolTable _Symbols;
struct SRegisteredFeature
{
SRegisteredFeature(const TSRef<Private::IModularFeature>& InFeature, const RegistryId InRegId, const CSymbolTable& SymTable)
: _RegistrySym(SymTable.Get(InRegId))
, _FeatureInst(InFeature)
{}
CSymbol _RegistrySym;
TSRef<Private::IModularFeature> _FeatureInst;
};
TArray<SRegisteredFeature> _Database;
};
void CModularFeatureRegistry::Add(const TSRef<Private::IModularFeature>& NewFeature, const RegistryId FeatureId)
{
_Database.Emplace(NewFeature, FeatureId, _Symbols);
SortDatabase();
}
bool CModularFeatureRegistry::Remove(const TSRef<Private::IModularFeature>& ToRemove)
{
int32_t FoundIndex = _Database.IndexOfByPredicate([&ToRemove](const SRegisteredFeature& Entry)
{
return Entry._FeatureInst == ToRemove;
});
if (FoundIndex != uLang::IndexNone)
{
_Database.RemoveAt(FoundIndex);
}
return (FoundIndex != uLang::IndexNone);
}
void CModularFeatureRegistry::MergeIn(const CModularFeatureRegistry& OtherRegistry)
{
_Database.Reserve(_Database.Num() + OtherRegistry._Database.Num());
for (const SRegisteredFeature& OtherFeature : OtherRegistry._Database)
{
CSymbol FixupSymbol = OtherFeature._RegistrySym;
_Symbols.ReAdd(FixupSymbol);
_Database.Emplace(OtherFeature._FeatureInst, FixupSymbol.GetId(), _Symbols);
}
SortDatabase();
}
void CModularFeatureRegistry::SortDatabase()
{
// Determines if Lhs should come before Rhs?
auto FeatureSort = [](const SRegisteredFeature& Lhs, const SRegisteredFeature& Rhs)->bool
{
if (Lhs._RegistrySym == Rhs._RegistrySym)
{
return Lhs._FeatureInst->GetPriority() > Rhs._FeatureInst->GetPriority();
}
return Lhs._RegistrySym > Rhs._RegistrySym;
};
_Database.Sort(FeatureSort);
}
} // namespace Private
namespace Private_ModularFeatureManagerImpl
{
static TOptional<TSRef<Private::CModularFeatureRegistry>>& GetMaybeRegistry()
{
static TOptional<TSRef<Private::CModularFeatureRegistry>> FeatureRegistry;
return FeatureRegistry;
}
const TSRef<Private::CModularFeatureRegistry>& GetRegistryRef()
{
TOptional<TSRef<Private::CModularFeatureRegistry>>& MaybeRegistry = GetMaybeRegistry();
if (!MaybeRegistry.IsSet())
{
MaybeRegistry.Emplace(TSRef<Private::CModularFeatureRegistry>::New());
}
return MaybeRegistry.GetValue();
}
struct SFindFeatureFunctor
{
SFindFeatureFunctor(Private::RegistryId InFeatureId) : _FeatureId(InFeatureId) {}
ULANG_FORCEINLINE bool operator()(const Private::CModularFeatureRegistry::SRegisteredFeature& Entry) const
{
return Entry._RegistrySym.GetId() == _FeatureId;
}
Private::RegistryId _FeatureId = SymbolId_Null;
};
} // namespace Private_ModularFeatureManagerImpl
const TSRef<Private::IModularFeatureRegistry>& Private::CModularFeatureRegistrar::GetRegistry()
{
return Private_ModularFeatureManagerImpl::GetRegistryRef().As<Private::IModularFeatureRegistry>();
}
void Private::CModularFeatureRegistrar::SetRegistry(const TSRef<IModularFeatureRegistry>& InRegistry)
{
// Safe downcast, since we've limited the IModularFeatureRegistry ctor to CModularFeatureRegistry instances
const TSRef<CModularFeatureRegistry>& NewRegistry = InRegistry.As<CModularFeatureRegistry>();
using namespace Private_ModularFeatureManagerImpl;
TOptional<TSRef<CModularFeatureRegistry>>& CurrentRegistry = GetMaybeRegistry();
if (CurrentRegistry.IsSet())
{
NewRegistry->MergeIn(**CurrentRegistry);
}
CurrentRegistry = NewRegistry;
}
void Private::CModularFeatureRegistrar::Register(const TSRef<IModularFeature>& NewModularFeature, const RegistryId FeatureId)
{
const TSRef<Private::CModularFeatureRegistry>& Registry = Private_ModularFeatureManagerImpl::GetRegistryRef();
Registry->Add(NewModularFeature, FeatureId);
}
bool Private::CModularFeatureRegistrar::Unregister(const TSRef<IModularFeature>& ModularFeature)
{
const TSRef<Private::CModularFeatureRegistry>& Registry = Private_ModularFeatureManagerImpl::GetRegistryRef();
return Registry->Remove(ModularFeature);
}
Private::RegistryId Private::CModularFeatureRegistrar::GetRegistryId(const char* FeatureName)
{
const TSRef<Private::CModularFeatureRegistry>& Registry = Private_ModularFeatureManagerImpl::GetRegistryRef();
return Registry->_Symbols.AddChecked(FeatureName).GetId();
}
int32_t Private::GetModularFeatureCount(const RegistryId FeatureId)
{
using namespace Private_ModularFeatureManagerImpl;
const TSRef<Private::CModularFeatureRegistry>& Registry = GetRegistryRef();
int32_t Count = 0;
const int32_t FeatureOffset = Registry->_Database.IndexOfByPredicate(SFindFeatureFunctor(FeatureId));
if (FeatureOffset >= 0)
{
for (Count = 1; Registry->_Database.IsValidIndex(FeatureOffset + Count) && Registry->_Database[FeatureOffset + Count]._RegistrySym.GetId() == FeatureId;)
{
++Count;
}
}
return Count;
}
TSPtr<Private::IModularFeature> Private::GetModularFeature(const RegistryId FeatureId, const int32_t Index)
{
using namespace Private_ModularFeatureManagerImpl;
const TSRef<Private::CModularFeatureRegistry>& Registry = GetRegistryRef();
const int32_t FeatureOffset = Registry->_Database.IndexOfByPredicate(SFindFeatureFunctor(FeatureId));
if (FeatureOffset >= 0)
{
if (Registry->_Database.IsValidIndex(FeatureOffset + Index))
{
const Private::CModularFeatureRegistry::SRegisteredFeature& RegisteredFeature = Registry->_Database[FeatureOffset + Index];
if (RegisteredFeature._RegistrySym.GetId() == FeatureId)
{
return RegisteredFeature._FeatureInst;
}
}
}
return TSPtr<Private::IModularFeature>();
}
} // namespace uLang