#include <iostream>
#include "TEnum.h"
#include "TEnumConstant.h"
#include "TInterpreter.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TClassTable.h"
#include "TProtoClass.h"
#include "TROOT.h"
#include "TListOfEnums.h"
ClassImp(TEnum)
TEnum::TEnum(const char *name, void *info, TClass *cls)
: fInfo(info), fClass(cls)
{
SetName(name);
if (cls) {
fConstantList.SetOwner(kTRUE);
}
if (0 != strcmp("",GetTitle())){
fQualName = std::string(GetTitle()) + "::" + GetName();
}
else if (GetClass()){
fQualName = std::string(GetClass()->GetName()) + "::" + GetName();
}
else {
fQualName = GetName();
}
}
TEnum::~TEnum()
{
}
void TEnum::AddConstant(TEnumConstant *constant)
{
fConstantList.Add(constant);
}
Bool_t TEnum::IsValid()
{
if (!fInfo && UpdateInterpreterStateMarker()) {
DeclId_t newId = gInterpreter->GetEnum(fClass, fName);
if (newId) {
Update(newId);
}
return newId != 0;
}
return fInfo != 0;
}
Long_t TEnum::Property() const
{
return kIsEnum;
}
void TEnum::Update(DeclId_t id)
{
fInfo = (void *)id;
}
TEnum *TEnum::GetEnum(const std::type_info &ti, ESearchAction sa)
{
int errorCode = 0;
char *demangledEnumName = TClassEdit::DemangleName(ti.name(), errorCode);
if (errorCode != 0) {
if (!demangledEnumName) {
free(demangledEnumName);
}
std::cerr << "ERROR TEnum::GetEnum - A problem occurred while demangling name.\n";
return nullptr;
}
const char *constDemangledEnumName = demangledEnumName;
TEnum *en = TEnum::GetEnum(constDemangledEnumName, sa);
free(demangledEnumName);
return en;
}
TEnum *TEnum::GetEnum(const char *enumName, ESearchAction sa)
{
TEnum *theEnum = nullptr;
auto findEnumInList = [](const TCollection * l, const char * enName, ESearchAction sa_local) {
TObject *obj;
if (sa_local & kInterpLookup) {
obj = l->FindObject(enName);
} else {
auto enumTable = dynamic_cast<const TListOfEnums *>(l);
obj = enumTable->GetObject(enName);
}
return static_cast<TEnum *>(obj);
};
auto searchEnum = [&theEnum, findEnumInList](const char * scopeName, const char * enName, ESearchAction sa_local) {
if (sa_local == (kALoadAndInterpLookup)) {
auto scope = TClass::GetClass(scopeName, true);
TEnum *en = nullptr;
if (scope) en = findEnumInList(scope->GetListOfEnums(), enName, sa_local);
return en;
}
R__LOCKGUARD(gInterpreterMutex);
if (auto tClassScope = static_cast<TClass *>(gROOT->GetListOfClasses()->FindObject(scopeName))) {
bool canLoadEnums (sa_local & kInterpLookup);
const bool scopeIsNamespace (tClassScope->Property() & kIsNamespace);
const bool autoParseSuspended = gInterpreter->IsAutoParsingSuspended();
const bool suspendAutoParse = autoParseSuspended || scopeIsNamespace;
TInterpreter::SuspendAutoParsing autoParseRaii(gInterpreter, suspendAutoParse);
if (scopeIsNamespace && !autoParseSuspended){
canLoadEnums=true;
}
auto listOfEnums = tClassScope->GetListOfEnums(canLoadEnums);
theEnum = findEnumInList(listOfEnums, enName, sa_local);
}
else if (auto tProtoClassscope = static_cast<TProtoClass *>((gClassTable->GetProtoNorm(scopeName)))) {
auto listOfEnums = tProtoClassscope->GetListOfEnums();
if (listOfEnums) theEnum = findEnumInList(listOfEnums, enName, sa_local);
}
return theEnum;
};
const char *lastPos = TClassEdit::GetUnqualifiedName(enumName);
if (strchr(lastPos,'<')) {
return nullptr;
}
if (lastPos != enumName) {
const auto enName = lastPos;
const auto scopeNameSize = ((Long64_t)lastPos - (Long64_t)enumName) / sizeof(decltype(*lastPos)) - 2;
char scopeName[scopeNameSize + 1];
strncpy(scopeName, enumName, scopeNameSize);
scopeName[scopeNameSize] = '\0';
theEnum = searchEnum(scopeName, enName, kNone);
if (!theEnum && (sa & kAutoload)) {
const auto libsLoaded = gInterpreter->AutoLoad(scopeName);
if (libsLoaded == 0){
gInterpreter->AutoLoad(enumName);
}
theEnum = searchEnum(scopeName, enName, kAutoload);
}
if (!theEnum && (sa & kALoadAndInterpLookup)) {
if (gDebug > 0) {
printf("TEnum::GetEnum: Header Parsing - The enumerator %s is not known to the typesystem: an interpreter lookup will be performed. This can imply parsing of headers. This can be avoided selecting the numerator in the linkdef/selection file.\n", enumName);
}
theEnum = searchEnum(scopeName, enName, kALoadAndInterpLookup);
}
} else {
theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kNone);
if (!theEnum && (sa & kAutoload)) {
gInterpreter->AutoLoad(enumName);
theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kAutoload);
}
if (!theEnum && (sa & kALoadAndInterpLookup)) {
if (gDebug > 0) {
printf("TEnum::GetEnum: Header Parsing - The enumerator %s is not known to the typesystem: an interpreter lookup will be performed. This can imply parsing of headers. This can be avoided selecting the numerator in the linkdef/selection file.\n", enumName);
}
theEnum = findEnumInList(gROOT->GetListOfEnums(), enumName, kALoadAndInterpLookup);
}
}
return theEnum;
}