#include "TClass.h"
#include "Riostream.h"
#include "TBaseClass.h"
#include "TBrowser.h"
#include "TBuffer.h"
#include "TClassGenerator.h"
#include "TClassEdit.h"
#include "TClassMenuItem.h"
#include "TClassRef.h"
#include "TClassTable.h"
#include "TDataMember.h"
#include "TDataType.h"
#include "TEnum.h"
#include "TError.h"
#include "TExMap.h"
#include "TFunctionTemplate.h"
#include "THashList.h"
#include "TInterpreter.h"
#include "TMemberInspector.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TMethodCall.h"
#include "TObjArray.h"
#include "TProtoClass.h"
#include "TROOT.h"
#include "TRealData.h"
#include "TStreamer.h"
#include "TStreamerElement.h"
#include "TVirtualStreamerInfo.h"
#include "TVirtualCollectionProxy.h"
#include "TVirtualIsAProxy.h"
#include "TVirtualRefProxy.h"
#include "TVirtualMutex.h"
#include "TVirtualPad.h"
#include "THashTable.h"
#include "TSchemaRuleSet.h"
#include "TGenericClassInfo.h"
#include "TIsAProxy.h"
#include "TSchemaRule.h"
#include "TSystem.h"
#include "TThreadSlots.h"
#include <cstdio>
#include <cctype>
#include <set>
#include <sstream>
#include <string>
#include <map>
#include <typeinfo>
#include <cmath>
#include <assert.h>
#include <vector>
#include <memory>
#include "TListOfDataMembers.h"
#include "TListOfFunctions.h"
#include "TListOfFunctionTemplates.h"
#include "TListOfEnums.h"
#include "TListOfEnumsWithLock.h"
#include "TViewPubDataMembers.h"
#include "TViewPubFunctions.h"
using namespace std;
TVirtualMutex* gInterpreterMutex = 0;
void *gMmallocDesc = 0;
namespace {
class TMmallocDescTemp {
private:
void *fSave;
public:
TMmallocDescTemp(void *value = 0) : fSave(gMmallocDesc) { gMmallocDesc = value; }
~TMmallocDescTemp() { gMmallocDesc = fSave; }
};
}
std::atomic<Int_t> TClass::fgClassCount;
TClass::TDeclNameRegistry::TDeclNameRegistry(Int_t verbLevel): fVerbLevel(verbLevel){}
void TClass::TDeclNameRegistry::AddQualifiedName(const char *name)
{
auto strLen = strlen(name);
if (strLen == 0) return;
const char* endCharPtr = strchr(name, '<');
endCharPtr = !endCharPtr ? &name[strLen] : endCharPtr;
const char* beginCharPtr = endCharPtr;
while (beginCharPtr!=name){
if (*beginCharPtr==':'){
beginCharPtr++;
break;
}
beginCharPtr--;
}
beginCharPtr = beginCharPtr!=endCharPtr ? beginCharPtr : name;
std::string s(beginCharPtr, endCharPtr);
if (fVerbLevel>1)
printf("TDeclNameRegistry::AddQualifiedName Adding key %s for class/namespace %s\n", s.c_str(), name);
TClass::TSpinLockGuard slg(fSpinLock);
fClassNamesSet.insert(s);
}
Bool_t TClass::TDeclNameRegistry::HasDeclName(const char *name) const
{
Bool_t found = false;
{
TClass::TSpinLockGuard slg(fSpinLock);
found = fClassNamesSet.find(name) != fClassNamesSet.end();
}
return found;
}
TClass::TDeclNameRegistry::~TDeclNameRegistry()
{
if (fVerbLevel>1){
printf("TDeclNameRegistry Destructor. List of names:\n");
for(auto const & key:fClassNamesSet){
printf(" - %s\n",key.c_str());
}
}
}
TClass::TSpinLockGuard::TSpinLockGuard(std::atomic_flag& aflag):fAFlag(aflag)
{
while (fAFlag.test_and_set(std::memory_order_acquire));
}
TClass::TSpinLockGuard::~TSpinLockGuard()
{
fAFlag.clear(std::memory_order_release);
}
TClass::InsertTClassInRegistryRAII::InsertTClassInRegistryRAII(TClass::EState &state,
const char *name,
TDeclNameRegistry &emuRegistry): fState(state),fName(name), fNoInfoOrEmuOrFwdDeclNameRegistry(emuRegistry) {}
TClass::InsertTClassInRegistryRAII::~InsertTClassInRegistryRAII() {
if (fState == TClass::kNoInfo ||
fState == TClass::kEmulated ||
fState == TClass::kForwardDeclared){
fNoInfoOrEmuOrFwdDeclNameRegistry.AddQualifiedName(fName);
}
}
TClass::TDeclNameRegistry TClass::fNoInfoOrEmuOrFwdDeclNameRegistry;
TClass::ENewType &TClass__GetCallingNew() {
TTHREAD_TLS(TClass::ENewType) fgCallingNew = TClass::kRealNew;
return fgCallingNew;
}
struct ObjRepoValue {
ObjRepoValue(const TClass *what, Version_t version) : fClass(what),fVersion(version) {}
const TClass *fClass;
Version_t fVersion;
};
static TVirtualMutex* gOVRMutex = 0;
typedef std::multimap<void*, ObjRepoValue> RepoCont_t;
static RepoCont_t gObjectVersionRepository;
static void RegisterAddressInRepository(const char * , void *location, const TClass *what)
{
Version_t version = what->GetClassVersion();
{
R__LOCKGUARD2(gOVRMutex);
gObjectVersionRepository.insert(RepoCont_t::value_type(location, RepoCont_t::mapped_type(what,version)));
}
#if 0
std::pair<RepoCont_t::iterator, Bool_t> tmp = gObjectVersionRepository.insert(RepoCont_t::value_type>(location, RepoCont_t::mapped_type(what,version)));
if (!tmp.second) {
Warning(where, "Reregistering an object of class '%s' version %d at address %p", what->GetName(), version, p);
gObjectVersionRepository.erase(tmp.first);
tmp = gObjectVersionRepository.insert(RepoCont_t::value_type>(location, RepoCont_t::mapped_type(what,version)));
if (!tmp.second) {
Warning(where, "Failed to reregister an object of class '%s' version %d at address %p", what->GetName(), version, location);
}
}
#endif
}
static void UnregisterAddressInRepository(const char * , void *location, const TClass *what)
{
R__LOCKGUARD2(gOVRMutex);
RepoCont_t::iterator cur = gObjectVersionRepository.find(location);
for (; cur != gObjectVersionRepository.end();) {
RepoCont_t::iterator tmp = cur++;
if ((tmp->first == location) && (tmp->second.fVersion == what->GetClassVersion())) {
gObjectVersionRepository.erase(tmp);
} else {
break;
}
}
}
static void MoveAddressInRepository(const char * , void *oldadd, void *newadd, const TClass *what)
{
size_t objsize = what->Size();
long delta = (char*)newadd - (char*)oldadd;
R__LOCKGUARD2(gOVRMutex);
RepoCont_t::iterator cur = gObjectVersionRepository.find(oldadd);
for (; cur != gObjectVersionRepository.end();) {
RepoCont_t::iterator tmp = cur++;
if (oldadd <= tmp->first && tmp->first < ( ((char*)oldadd) + objsize) ) {
gObjectVersionRepository.insert(RepoCont_t::value_type(((char*)tmp->first)+delta, RepoCont_t::mapped_type(tmp->second.fClass,tmp->second.fVersion)));
gObjectVersionRepository.erase(tmp);
} else {
break;
}
}
}
namespace ROOT {
#define R__USE_STD_MAP
class TMapTypeToTClass {
#if defined R__USE_STD_MAP
public:
#ifdef R__GLOBALSTL
typedef map<string,TClass*> IdMap_t;
#else
typedef std::map<std::string,TClass*> IdMap_t;
#endif
typedef IdMap_t::key_type key_type;
typedef IdMap_t::const_iterator const_iterator;
typedef IdMap_t::size_type size_type;
#ifdef R__WIN32
typedef TClass* mapped_type;
#else
typedef IdMap_t::mapped_type mapped_type;
#endif
private:
IdMap_t fMap;
public:
void Add(const key_type &key, mapped_type &obj)
{
fMap[key] = obj;
}
mapped_type Find(const key_type &key) const
{
IdMap_t::const_iterator iter = fMap.find(key);
mapped_type cl = 0;
if (iter != fMap.end()) cl = iter->second;
return cl;
}
void Remove(const key_type &key) {
fMap.erase(key);
}
#else
private:
TMap fMap;
public:
#ifdef R__COMPLETE_MEM_TERMINATION
TMapTypeToTClass() {
TIter next(&fMap);
TObjString *key;
while((key = (TObjString*)next())) {
delete key;
}
}
#endif
void Add(const char *key, TClass *&obj) {
TObjString *realkey = new TObjString(key);
fMap.Add(realkey, obj);
}
TClass* Find(const char *key) const {
const TPair *a = (const TPair *)fMap.FindObject(key);
if (a) return (TClass*) a->Value();
return 0;
}
void Remove(const char *key) {
TObjString realkey(key);
TObject *actual = fMap.Remove(&realkey);
delete actual;
}
#endif
};
class TMapDeclIdToTClass {
public:
typedef multimap<TDictionary::DeclId_t, TClass*> DeclIdMap_t;
typedef DeclIdMap_t::key_type key_type;
typedef DeclIdMap_t::mapped_type mapped_type;
typedef DeclIdMap_t::const_iterator const_iterator;
typedef std::pair <const_iterator, const_iterator> equal_range;
typedef DeclIdMap_t::size_type size_type;
private:
DeclIdMap_t fMap;
public:
void Add(const key_type &key, mapped_type obj)
{
std::pair<const key_type, mapped_type> pair = make_pair(key, obj);
fMap.insert(pair);
}
size_type CountElementsWithKey(const key_type &key)
{
return fMap.count(key);
}
equal_range Find(const key_type &key) const
{
return fMap.equal_range(key);
}
void Remove(const key_type &key) {
fMap.erase(key);
}
};
}
IdMap_t *TClass::GetIdMap() {
#ifdef R__COMPLETE_MEM_TERMINATION
static IdMap_t gIdMapObject;
return &gIdMap;
#else
static IdMap_t *gIdMap = new IdMap_t;
return gIdMap;
#endif
}
DeclIdMap_t *TClass::GetDeclIdMap() {
#ifdef R__COMPLETE_MEM_TERMINATION
static DeclIdMap_t gDeclIdMapObject;
return &gIdMap;
#else
static DeclIdMap_t *gDeclIdMap = new DeclIdMap_t;
return gDeclIdMap;
#endif
}
void TClass::AddClass(TClass *cl)
{
if (!cl) return;
R__LOCKGUARD2(gInterpreterMutex);
gROOT->GetListOfClasses()->Add(cl);
if (cl->GetTypeInfo()) {
GetIdMap()->Add(cl->GetTypeInfo()->name(),cl);
}
if (cl->fClassInfo) {
GetDeclIdMap()->Add((void*)(cl->fClassInfo), cl);
}
}
void TClass::AddClassToDeclIdMap(TDictionary::DeclId_t id, TClass* cl)
{
if (!cl || !id) return;
GetDeclIdMap()->Add(id, cl);
}
void TClass::RemoveClass(TClass *oldcl)
{
if (!oldcl) return;
R__LOCKGUARD2(gInterpreterMutex);
gROOT->GetListOfClasses()->Remove(oldcl);
if (oldcl->GetTypeInfo()) {
GetIdMap()->Remove(oldcl->GetTypeInfo()->name());
}
if (oldcl->fClassInfo) {
}
}
void TClass::RemoveClassDeclId(TDictionary::DeclId_t id)
{
if (!id) return;
GetDeclIdMap()->Remove(id);
}
void ROOT::Class_ShowMembers(TClass *cl, const void *obj, TMemberInspector&insp)
{
gInterpreter->InspectMembers(insp, obj, cl, kFALSE);
}
class TDumpMembers : public TMemberInspector {
bool fNoAddr;
public:
TDumpMembers(bool noAddr): fNoAddr(noAddr) { }
using TMemberInspector::Inspect;
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
};
void TDumpMembers::Inspect(TClass *cl, const char *pname, const char *mname, const void *add, Bool_t )
{
const Int_t kvalue = 30;
#ifdef R__B64
const Int_t ktitle = 50;
#else
const Int_t ktitle = 42;
#endif
const Int_t kline = 1024;
Int_t cdate = 0;
Int_t ctime = 0;
UInt_t *cdatime = 0;
char line[kline];
TDataType *membertype;
EDataType memberDataType = kNoType_t;
const char *memberName;
const char *memberFullTypeName;
const char *memberTitle;
Bool_t isapointer;
Bool_t isbasic;
if (TDataMember *member = cl->GetDataMember(mname)) {
if (member->GetDataType()) {
memberDataType = (EDataType)member->GetDataType()->GetType();
}
memberName = member->GetName();
memberFullTypeName = member->GetFullTypeName();
memberTitle = member->GetTitle();
isapointer = member->IsaPointer();
isbasic = member->IsBasic();
membertype = member->GetDataType();
} else if (!cl->IsLoaded()) {
TVirtualStreamerInfo *info = cl->GetStreamerInfo();
if (!info) return;
const char *cursor = mname;
while ( (*cursor)=='*' ) ++cursor;
TString elname( cursor );
Ssiz_t pos = elname.Index("[");
if ( pos != kNPOS ) {
elname.Remove( pos );
}
TStreamerElement *element = (TStreamerElement*)info->GetElements()->FindObject(elname.Data());
if (!element) return;
memberFullTypeName = element->GetTypeName();
memberDataType = (EDataType)element->GetType();
memberName = element->GetName();
memberTitle = element->GetTitle();
isapointer = element->IsaPointer() || element->GetType() == TVirtualStreamerInfo::kCharStar;
membertype = gROOT->GetType(memberFullTypeName);
isbasic = membertype !=0;
} else {
return;
}
Bool_t isdate = kFALSE;
if (strcmp(memberName,"fDatime") == 0 && memberDataType == kUInt_t) {
isdate = kTRUE;
}
Bool_t isbits = kFALSE;
if (strcmp(memberName,"fBits") == 0 && memberDataType == kUInt_t) {
isbits = kTRUE;
}
TClass * dataClass = TClass::GetClass(memberFullTypeName);
Bool_t isTString = (dataClass == TString::Class());
static TClassRef stdClass("std::string");
Bool_t isStdString = (dataClass == stdClass);
Int_t i;
for (i = 0;i < kline; i++) line[i] = ' ';
line[kline-1] = 0;
snprintf(line,kline,"%s%s ",pname,mname);
i = strlen(line); line[i] = ' ';
char *pointer = (char*)add;
char **ppointer = (char**)(pointer);
if (isapointer) {
char **p3pointer = (char**)(*ppointer);
if (!p3pointer)
snprintf(&line[kvalue],kline-kvalue,"->0");
else if (!isbasic) {
if (!fNoAddr) {
snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
}
} else if (membertype) {
if (!strcmp(membertype->GetTypeName(), "char")) {
i = strlen(*ppointer);
if (kvalue+i > kline) i=kline-1-kvalue;
Bool_t isPrintable = kTRUE;
for (Int_t j = 0; j < i; j++) {
if (!std::isprint((*ppointer)[j])) {
isPrintable = kFALSE;
break;
}
}
if (isPrintable) {
strncpy(line + kvalue, *ppointer, i);
line[kvalue+i] = 0;
} else {
line[kvalue] = 0;
}
} else {
strncpy(&line[kvalue], membertype->AsString(p3pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(p3pointer))));
}
} else if (!strcmp(memberFullTypeName, "char*") ||
!strcmp(memberFullTypeName, "const char*")) {
i = strlen(*ppointer);
if (kvalue+i >= kline) i=kline-1-kvalue;
Bool_t isPrintable = kTRUE;
for (Int_t j = 0; j < i; j++) {
if (!std::isprint((*ppointer)[j])) {
isPrintable = kFALSE;
break;
}
}
if (isPrintable) {
strncpy(line + kvalue, *ppointer, i);
line[kvalue+i] = 0;
} else {
line[kvalue] = 0;
}
} else {
if (!fNoAddr) {
snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)p3pointer);
}
}
} else if (membertype) {
if (isdate) {
cdatime = (UInt_t*)pointer;
TDatime::GetDateTime(cdatime[0],cdate,ctime);
snprintf(&line[kvalue],kline-kvalue,"%d/%d",cdate,ctime);
} else if (isbits) {
snprintf(&line[kvalue],kline-kvalue,"0x%08x", *(UInt_t*)pointer);
} else {
strncpy(&line[kvalue], membertype->AsString(pointer), TMath::Min(kline-1-kvalue,(int)strlen(membertype->AsString(pointer))));
}
} else {
if (isStdString) {
std::string *str = (std::string*)pointer;
snprintf(&line[kvalue],kline-kvalue,"%s",str->c_str());
} else if (isTString) {
TString *str = (TString*)pointer;
snprintf(&line[kvalue],kline-kvalue,"%s",str->Data());
} else {
if (!fNoAddr) {
snprintf(&line[kvalue],kline-kvalue,"->%lx ", (Long_t)pointer);
}
}
}
if (isdate == kFALSE && strcmp(memberFullTypeName, "char*") && strcmp(memberFullTypeName, "const char*")) {
i = strlen(&line[0]); line[i] = ' ';
Int_t lentit = strlen(memberTitle);
if (lentit > 250-ktitle) lentit = 250-ktitle;
strncpy(&line[ktitle],memberTitle,lentit);
line[ktitle+lentit] = 0;
}
Printf("%s", line);
}
THashTable* TClass::fgClassTypedefHash = 0;
TClass::TNameMapNode::TNameMapNode (const char* typedf, const char* orig)
: TObjString (typedf),
fOrigName (orig)
{
}
class TBuildRealData : public TMemberInspector {
private:
void *fRealDataObject;
TClass *fRealDataClass;
public:
TBuildRealData(void *obj, TClass *cl) {
fRealDataObject = obj;
fRealDataClass = cl;
}
using TMemberInspector::Inspect;
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
};
void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add, Bool_t isTransient)
{
TDataMember* dm = cl->GetDataMember(mname);
if (!dm) {
return;
}
Bool_t isTransientMember = kFALSE;
if (!dm->IsPersistent()) {
isTransientMember = kTRUE;
isTransient = kTRUE;
}
TString rname( pname );
if (cl != fRealDataClass) {
if (!fRealDataClass->InheritsFrom(cl)) {
Ssiz_t dot = rname.Index('.');
if (dot == kNPOS) {
return;
}
rname[dot] = '\0';
if (!fRealDataClass->GetDataMember(rname)) {
if (!fRealDataClass->GetBaseDataMember(rname)) {
return;
}
}
rname[dot] = '.';
}
}
rname += mname;
Long_t offset = Long_t(((Long_t) add) - ((Long_t) fRealDataObject));
if (dm->IsaPointer()) {
if (!dm->IsBasic()) {
TRealData* rd = new TRealData(rname, offset, dm);
if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
fRealDataClass->GetListOfRealData()->Add(rd);
} else {
TRealData* rd = new TRealData(rname, offset, dm);
if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
fRealDataClass->GetListOfRealData()->Add(rd);
}
} else {
TRealData* rd = new TRealData(rname, offset, dm);
if (isTransientMember) { rd->SetBit(TRealData::kTransient); };
if (!dm->IsBasic()) {
rd->SetIsObject(kTRUE);
TClass* dmclass = TClass::GetClass(dm->GetTypeName(), kTRUE, isTransient);
if (!dmclass) {
dmclass = TClass::GetClass(dm->GetTrueTypeName(), kTRUE, isTransient);
}
if (dmclass) {
if ((dmclass != cl) && !dm->IsaPointer()) {
if (dmclass->GetCollectionProxy()) {
TClass* valcl = dmclass->GetCollectionProxy()->GetValueClass();
if (valcl) {
Bool_t wantBuild = kTRUE;
if (valcl->Property() & kIsAbstract) wantBuild = kFALSE;
if ( (isTransient)
&& (dmclass->GetCollectionProxy()->GetProperties() & TVirtualCollectionProxy::kIsEmulated)
&& (!valcl->IsLoaded()) ) {
wantBuild = kFALSE;
}
if (wantBuild) valcl->BuildRealData(0, isTransient);
}
} else {
void* addrForRecursion = 0;
if (GetObjectValidity() == kValidObjectGiven)
addrForRecursion = const_cast<void*>(add);
dmclass->BuildRealData(addrForRecursion, isTransient);
}
}
}
}
fRealDataClass->GetListOfRealData()->Add(rd);
}
}
class TAutoInspector : public TMemberInspector {
public:
Int_t fCount;
TBrowser *fBrowser;
TAutoInspector(TBrowser *b) {
fBrowser = b; fCount = 0; }
virtual ~TAutoInspector() { }
using TMemberInspector::Inspect;
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr, Bool_t isTransient);
};
void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
const void *addr, Bool_t )
{
if(tit && strchr(tit,'.')) return ;
if (fCount && !fBrowser) return;
TString ts;
if (!cl) return;
if (*name == '*') name++;
int ln = strcspn(name,"[ ");
TString iname(name,ln);
ClassInfo_t *classInfo = cl->GetClassInfo();
if (!classInfo) return;
DataMemberInfo_t *m = gCling->DataMemberInfo_Factory(classInfo);
TString mname;
int found=0;
while (gCling->DataMemberInfo_Next(m)) {
mname = gCling->DataMemberInfo_Name(m);
mname.ReplaceAll("*","");
if ((found = (iname==mname))) break;
}
assert(found);
Long_t prop = gCling->DataMemberInfo_Property(m) | gCling->DataMemberInfo_TypeProperty(m);
if (prop & kIsStatic) return;
if (prop & kIsFundamental) return;
if (prop & kIsEnum) return;
if (mname == "G__virtualinfo") return;
int size = sizeof(void*);
int nmax = 1;
if (prop & kIsArray) {
for (int dim = 0; dim < gCling->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCling->DataMemberInfo_MaxIndex(m,dim);
}
std::string clmName(TClassEdit::ShortType(gCling->DataMemberInfo_TypeName(m),
TClassEdit::kDropTrailStar) );
TClass * clm = TClass::GetClass(clmName.c_str());
R__ASSERT(clm);
if (!(prop & kIsPointer)) {
size = clm->Size();
if (size==0) size = gCling->DataMemberInfo_TypeSize(m);
}
gCling->DataMemberInfo_Delete(m);
TVirtualCollectionProxy *proxy = clm->GetCollectionProxy();
for(int i=0; i<nmax; i++) {
char *ptr = (char*)addr + i*size;
void *obj = (prop & kIsPointer) ? *((void**)ptr) : (TObject*)ptr;
if (!obj) continue;
fCount++;
if (!fBrowser) return;
TString bwname;
TClass *actualClass = clm->GetActualClass(obj);
if (clm->IsTObject()) {
TObject *tobj = (TObject*)clm->DynamicCast(TObject::Class(),obj);
bwname = tobj->GetName();
} else {
bwname = actualClass->GetName();
bwname += "::";
bwname += mname;
}
if (!clm->IsTObject() ||
bwname.Length()==0 ||
strcmp(bwname.Data(),actualClass->GetName())==0) {
bwname = name;
int l = strcspn(bwname.Data(),"[ ");
if (l<bwname.Length() && bwname[l]=='[') {
char cbuf[12]; snprintf(cbuf,12,"[%02d]",i);
ts.Replace(0,999,bwname,l);
ts += cbuf;
bwname = (const char*)ts;
}
}
if (proxy==0) {
fBrowser->Add(obj,clm,bwname);
} else {
TClass *valueCl = proxy->GetValueClass();
if (valueCl==0) {
fBrowser->Add( obj, clm, bwname );
} else {
TVirtualCollectionProxy::TPushPop env(proxy, obj);
TClass *actualCl = 0;
int sz = proxy->Size();
char fmt[] = {"#%09d"};
fmt[3] = '0'+(int)log10(double(sz))+1;
char buf[20];
for (int ii=0;ii<sz;ii++) {
void *p = proxy->At(ii);
if (proxy->HasPointers()) {
p = *((void**)p);
if(!p) continue;
actualCl = valueCl->GetActualClass(p);
p = actualCl->DynamicCast(valueCl,p,0);
}
fCount++;
snprintf(buf,20,fmt,ii);
ts = bwname;
ts += buf;
fBrowser->Add( p, actualCl, ts );
}
}
}
}
}
ClassImp(TClass)
TClass::TClass() :
TDictionary(),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
fDeclFileLine = -2;
}
TClass::TClass(const char *name, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
if (!gROOT)
::Fatal("TClass::TClass", "ROOT system not initialized");
fDeclFileLine = -2;
SetBit(kLoading);
if (!gInterpreter)
::Fatal("TClass::TClass", "gInterpreter not initialized");
gInterpreter->SetClassInfo(this);
if (!silent && !fClassInfo && fName.First('@')==kNPOS)
::Warning("TClass::TClass", "no dictionary for class %s is available", name);
ResetBit(kLoading);
if (fClassInfo) SetTitle(gCling->ClassInfo_Title(fClassInfo));
fConversionStreamerInfo = 0;
}
TClass::TClass(const char *name, Version_t cversion, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
Init(name, cversion, 0, 0, 0, 0, -1, -1, 0, silent);
}
TClass::TClass(const char *name, Version_t cversion, EState theState, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(theState),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
if (theState == kNamespaceForMeta){
fProperty = kIsNamespace;
theState = kForwardDeclared;
}
if (theState != kForwardDeclared && theState != kEmulated)
::Fatal("TClass::TClass",
"A TClass entry cannot be initialized in a state different from kForwardDeclared or kEmulated.");
Init(name, cversion, 0, 0, 0, 0, -1, -1, 0, silent);
}
TClass::TClass(ClassInfo_t *classInfo, Version_t cversion,
const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
TDictionary(""),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
if (!gROOT)
::Fatal("TClass::TClass", "ROOT system not initialized");
fDeclFileLine = -2;
SetBit(kLoading);
if (!gInterpreter)
::Fatal("TClass::TClass", "gInterpreter not initialized");
if (!classInfo || !gInterpreter->ClassInfo_IsValid(classInfo)) {
MakeZombie();
fState = kNoInfo;
} else {
fName = gInterpreter->ClassInfo_FullName(classInfo);
R__LOCKGUARD2(gInterpreterMutex);
Init(fName, cversion, 0, 0, dfil, ifil, dl, il, classInfo, silent);
}
ResetBit(kLoading);
fConversionStreamerInfo = 0;
}
TClass::TClass(const char *name, Version_t cversion,
const char *dfil, const char *ifil, Int_t dl, Int_t il, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0), fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kNoInfo),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
Init(name,cversion, 0, 0, dfil, ifil, dl, il, 0, silent);
}
TClass::TClass(const char *name, Version_t cversion,
const type_info &info, TVirtualIsAProxy *isa,
const char *dfil, const char *ifil, Int_t dl, Int_t il,
Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(0), fEnums(0), fFuncTemplate(0), fMethod(0), fAllPubData(0),
fAllPubMethod(0),
fClassMenuList(0),
fDeclFileName(""), fImplFileName(""), fDeclFileLine(0), fImplFileLine(0),
fInstanceCount(0), fOnHeap(0),
fCheckSum(0), fCollectionProxy(0), fClassVersion(0), fClassInfo(0),
fTypeInfo(0), fShowMembers(0),
fStreamer(0), fIsA(0), fGlobalIsA(0), fIsAMethod(0),
fMerge(0), fResetAfterMerge(0), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fStreamerFunc(0), fConvStreamerFunc(0), fSizeof(-1),
fCanSplit(-1), fProperty(0), fClassProperty(0), fHasRootPcmInfo(kFALSE), fCanLoadClassInfo(kFALSE),
fIsOffsetStreamerSet(kFALSE), fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fState(kHasTClassInit),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gInterpreterMutex);
Init(name, cversion, &info, isa, dfil, ifil, dl, il, 0, silent);
}
void TClass::ForceReload (TClass* oldcl)
{
TClass::RemoveClass(oldcl);
if (oldcl->CanIgnoreTObjectStreamer()) {
IgnoreTObjectStreamer();
}
TVirtualStreamerInfo *info;
TIter next(oldcl->GetStreamerInfos());
while ((info = (TVirtualStreamerInfo*)next())) {
info->Clear("build");
info->SetClass(this);
fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
}
oldcl->fStreamerInfo->Clear();
oldcl->ReplaceWith(this);
delete oldcl;
}
void TClass::Init(const char *name, Version_t cversion,
const type_info *typeinfo, TVirtualIsAProxy *isa,
const char *dfil, const char *ifil, Int_t dl, Int_t il,
ClassInfo_t *givenInfo,
Bool_t silent)
{
if (!gROOT)
::Fatal("TClass::TClass", "ROOT system not initialized");
fName = TClassEdit::ShortType(name, TClassEdit::kDropStlDefault).c_str();
fClassVersion = cversion;
fDeclFileName = dfil ? dfil : "";
fImplFileName = ifil ? ifil : "";
fDeclFileLine = dl;
fImplFileLine = il;
fTypeInfo = typeinfo;
fIsA = isa;
if ( fIsA ) fIsA->SetClass(this);
fStreamerInfo = new TObjArray(fClassVersion+2+10,-1);
fProperty = -1;
fClassProperty = 0;
ResetInstanceCount();
TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
InsertTClassInRegistryRAII insertRAII(fState,fName,fNoInfoOrEmuOrFwdDeclNameRegistry);
if (oldcl && oldcl->TestBit(kLoading)) {
return;
}
TClass **persistentRef = 0;
if (oldcl) {
persistentRef = oldcl->fPersistentRef.exchange(0);
TClass::RemoveClass(oldcl);
if (oldcl->CanIgnoreTObjectStreamer()) {
IgnoreTObjectStreamer();
}
TVirtualStreamerInfo *info;
TIter next(oldcl->GetStreamerInfos());
while ((info = (TVirtualStreamerInfo*)next())) {
info->Clear("build");
info->SetClass(this);
fStreamerInfo->AddAtAndExpand(info,info->GetClassVersion());
}
oldcl->fStreamerInfo->Clear();
fSchemaRules = oldcl->fSchemaRules;
oldcl->fSchemaRules = 0;
}
SetBit(kLoading);
TClass::AddClass(this);
Bool_t isStl = TClassEdit::IsSTLCont(fName);
if (!gInterpreter) {
::Fatal("TClass::Init", "gInterpreter not initialized");
}
if (givenInfo) {
if (!gInterpreter->ClassInfo_IsValid(givenInfo) ||
!(gInterpreter->ClassInfo_Property(givenInfo) & (kIsClass | kIsStruct | kIsNamespace)) ||
(!gInterpreter->ClassInfo_IsLoaded(givenInfo) && (gInterpreter->ClassInfo_Property(givenInfo) & (kIsNamespace))) )
{
if (!TClassEdit::IsSTLCont(fName.Data())) {
MakeZombie();
fState = kNoInfo;
TClass::RemoveClass(this);
return;
}
}
fClassInfo = gInterpreter->ClassInfo_Factory(givenInfo);
}
if (fState!=kForwardDeclared && !fClassInfo) {
if (fState == kHasTClassInit) {
fCanLoadClassInfo = kTRUE;
TProtoClass *proto = TClassTable::GetProtoNorm(GetName());
if (proto && proto->FillTClass(this)) {
fHasRootPcmInfo = kTRUE;
}
}
if (!fHasRootPcmInfo && gInterpreter->CheckClassInfo(fName, kTRUE)) {
gInterpreter->SetClassInfo(this);
if (!fClassInfo) {
if (IsZombie()) {
TClass::RemoveClass(this);
return;
}
}
}
}
if (!silent && (!fClassInfo && !fCanLoadClassInfo) && !isStl && fName.First('@')==kNPOS &&
!TClassEdit::IsInterpreterDetail(fName.Data()) ) {
if (fState == kHasTClassInit) {
::Error("TClass::Init", "no interpreter information for class %s is available eventhough it has a TClass initialization routine.", fName.Data());
} else {
::Warning("TClass::Init", "no dictionary for class %s is available", fName.Data());
}
}
fgClassCount++;
SetUniqueID(fgClassCount);
TString resolvedThis;
if (!givenInfo && strchr (name, '<')) {
if ( fName != name) {
if (!fgClassTypedefHash) {
fgClassTypedefHash = new THashTable (100, 5);
fgClassTypedefHash->SetOwner (kTRUE);
}
fgClassTypedefHash->Add (new TNameMapNode (name, fName));
SetBit (kHasNameMapNode);
}
resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
if (resolvedThis != name) {
if (!fgClassTypedefHash) {
fgClassTypedefHash = new THashTable (100, 5);
fgClassTypedefHash->SetOwner (kTRUE);
}
fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, fName));
SetBit (kHasNameMapNode);
}
}
if (oldcl) {
oldcl->ReplaceWith(this);
delete oldcl;
} else if (!givenInfo && resolvedThis.Length() > 0 && fgClassTypedefHash) {
if (resolvedThis != fName) {
oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
if (oldcl && oldcl != this) {
persistentRef = oldcl->fPersistentRef.exchange(0);
ForceReload (oldcl);
}
}
TIter next( fgClassTypedefHash->GetListForObject(resolvedThis) );
while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
if (resolvedThis != htmp->String()) continue;
oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(htmp->fOrigName);
if (oldcl && oldcl != this) {
persistentRef = oldcl->fPersistentRef.exchange(0);
ForceReload (oldcl);
}
}
}
if (fClassInfo) {
SetTitle(gCling->ClassInfo_Title(fClassInfo));
if ( fDeclFileName == 0 || fDeclFileName[0] == '\0' ) {
fDeclFileName = gInterpreter->ClassInfo_FileName( fClassInfo );
}
}
if (persistentRef) {
fPersistentRef = persistentRef;
} else {
fPersistentRef = new TClass*;
}
*fPersistentRef = this;
if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
if (fState != kHasTClassInit) {
fCollectionProxy = TVirtualStreamerInfo::Factory()->GenEmulatedProxy( GetName(), silent );
if (fCollectionProxy) {
fSizeof = fCollectionProxy->Sizeof();
GetSchemaRules(kTRUE);
} else if (!silent) {
Warning("Init","Collection proxy for %s was not properly initialized!",GetName());
}
if (fStreamer==0) {
fStreamer = TVirtualStreamerInfo::Factory()->GenEmulatedClassStreamer( GetName(), silent );
}
}
} else if (!strncmp(GetName(),"std::pair<",10) || !strncmp(GetName(),"pair<",5) ) {
GetSchemaRules(kTRUE);
}
ResetBit(kLoading);
}
TClass::~TClass()
{
R__LOCKGUARD(gInterpreterMutex);
if (fgClassTypedefHash && TestBit (kHasNameMapNode)) {
TString resolvedThis = TClassEdit::ResolveTypedef (GetName(), kTRUE);
TIter next (fgClassTypedefHash->GetListForObject (resolvedThis));
while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
if (resolvedThis == htmp->String() && htmp->fOrigName == GetName()) {
fgClassTypedefHash->Remove (htmp);
delete htmp;
break;
}
}
}
delete fStreamer; fStreamer =0;
delete fAllPubData; fAllPubData =0;
delete fAllPubMethod; fAllPubMethod=0;
delete fPersistentRef.load();
if (fBase)
fBase->Delete();
delete fBase; fBase=0;
if (fData)
fData->Delete();
delete fData; fData = 0;
if (fEnums)
(*fEnums).Delete();
delete fEnums.load(); fEnums = 0;
if (fFuncTemplate)
fFuncTemplate->Delete();
delete fFuncTemplate; fFuncTemplate = 0;
if (fMethod)
(*fMethod).Delete();
delete fMethod.load(); fMethod=0;
if (fRealData)
fRealData->Delete();
delete fRealData; fRealData=0;
if (fStreamerInfo)
fStreamerInfo->Delete();
delete fStreamerInfo; fStreamerInfo=0;
if (fDeclFileLine >= -1)
TClass::RemoveClass(this);
gCling->ClassInfo_Delete(fClassInfo);
fClassInfo=0;
if (fClassMenuList)
fClassMenuList->Delete();
delete fClassMenuList; fClassMenuList=0;
fIsOffsetStreamerSet=kFALSE;
if ( fIsA ) delete fIsA;
if ( fRefProxy ) fRefProxy->Release();
fRefProxy = 0;
delete fStreamer;
delete fCollectionProxy;
delete fIsAMethod.load();
delete fSchemaRules;
if (fConversionStreamerInfo.load()) {
std::map<std::string, TObjArray*>::iterator it;
std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
delete it->second;
}
delete fConversionStreamerInfo.load();
}
}
namespace {
Int_t ReadRulesContent(FILE *f)
{
R__ASSERT(f!=0);
TString rule(1024);
int c, state = 0;
Int_t count = 0;
while ((c = fgetc(f)) != EOF) {
if (c == 13)
continue;
if (c == '\n') {
if (state != 3) {
state = 0;
if (rule.Length() > 0) {
if (TClass::AddRule(rule)) {
++count;
}
rule.Clear();
}
}
continue;
}
switch (state) {
case 0:
switch (c) {
case ' ':
case '\t':
break;
case '#':
state = 1;
break;
default:
state = 2;
break;
}
break;
case 1:
break;
case 2:
switch (c) {
case '\\':
state = 3;
default:
break;
}
break;
}
switch (state) {
case 2:
rule.Append(c);
break;
}
}
return count;
}
}
Int_t TClass::ReadRules()
{
static const char *suffix = "class.rules";
TString sname = suffix;
#ifdef ROOTETCDIR
gSystem->PrependPathName(ROOTETCDIR, sname);
#else
TString etc = gRootDir;
#ifdef WIN32
etc += "\\etc";
#else
etc += "/etc";
#endif
gSystem->PrependPathName(etc, sname);
#endif
Int_t res = -1;
FILE * f = fopen(sname,"r");
if (f != 0) {
res = ReadRulesContent(f);
fclose(f);
}
return res;
}
Int_t TClass::ReadRules( const char *filename )
{
if (!filename || !filename[0]) {
::Error("TClass::ReadRules", "no file name specified");
return -1;
}
FILE * f = fopen(filename,"r");
if (f == 0) {
::Error("TClass::ReadRules","Failed to open %s\n",filename);
return -1;
}
Int_t count = ReadRulesContent(f);
fclose(f);
return count;
}
Bool_t TClass::AddRule( const char *rule )
{
ROOT::TSchemaRule *ruleobj = new ROOT::TSchemaRule();
if (! ruleobj->SetFromRule( rule ) ) {
delete ruleobj;
return kFALSE;
}
R__LOCKGUARD(gInterpreterMutex);
TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
if (!cl) {
cl = gInterpreter->GenerateTClass(ruleobj->GetTargetClass(), kTRUE, kTRUE);
}
ROOT::TSchemaRuleSet* rset = cl->GetSchemaRules( kTRUE );
TString errmsg;
if( !rset->AddRule( ruleobj, ROOT::TSchemaRuleSet::kCheckConflict, &errmsg ) ) {
::Warning( "TClass::AddRule", "The rule for class: \"%s\": version, \"%s\" and data members: \"%s\" has been skipped because it conflicts with one of the other rules (%s).",
ruleobj->GetTargetClass(), ruleobj->GetVersion(), ruleobj->GetTargetString(), errmsg.Data() );
delete ruleobj;
return kFALSE;
}
return kTRUE;
}
void TClass::AdoptSchemaRules( ROOT::TSchemaRuleSet *rules )
{
R__LOCKGUARD(gInterpreterMutex);
delete fSchemaRules;
fSchemaRules = rules;
fSchemaRules->SetClass( this );
}
const ROOT::TSchemaRuleSet* TClass::GetSchemaRules() const
{
return fSchemaRules;
}
ROOT::TSchemaRuleSet* TClass::GetSchemaRules(Bool_t create)
{
if (create && fSchemaRules == 0) {
fSchemaRules = new ROOT::TSchemaRuleSet();
fSchemaRules->SetClass( this );
}
return fSchemaRules;
}
void TClass::AddImplFile(const char* filename, int line) {
fImplFileName = filename;
fImplFileLine = line;
}
Int_t TClass::AutoBrowse(TObject *obj, TBrowser *b)
{
if (!obj) return 0;
TAutoInspector insp(b);
obj->ShowMembers(insp);
return insp.fCount;
}
Int_t TClass::Browse(void *obj, TBrowser *b) const
{
if (!obj) return 0;
TClass *actual = GetActualClass(obj);
if (IsTObject()) {
if (!fIsOffsetStreamerSet) {
CalculateStreamerOffset();
}
TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
realTObject->Browse(b);
return 1;
} else if (actual != this) {
return actual->Browse(obj, b);
} else if (GetCollectionProxy()) {
} else {
TAutoInspector insp(b);
CallShowMembers(obj,insp,kFALSE);
return insp.fCount;
}
return 0;
}
void TClass::Browse(TBrowser *b)
{
if (!HasInterpreterInfo()) return;
if (b) {
if (!fRealData) BuildRealData();
b->Add(GetListOfDataMembers(), "Data Members");
b->Add(GetListOfRealData(), "Real Data Members");
b->Add(GetListOfMethods(), "Methods");
b->Add(GetListOfBases(), "Base Classes");
}
}
void TClass::BuildRealData(void* pointer, Bool_t isTransient)
{
R__LOCKGUARD(gInterpreterMutex);
if (fRealData) {
return;
}
if (fClassVersion == 0) {
isTransient = kTRUE;
}
TMmallocDescTemp setreset;
if (!HasInterpreterInfo() || TClassEdit::IsSTLCont(GetName(), 0) || TClassEdit::IsSTLBitset(GetName())) {
fRealData = new TList;
BuildEmulatedRealData("", 0, this);
return;
}
static TClassRef clRefString("std::string");
if (clRefString == this) {
return;
}
if (!isTransient && GetState() != kHasTClassInit
&& TClassEdit::IsStdClass(GetName())
&& strncmp(GetName(), "pair<", 5) != 0) {
Error("BuildRealData", "Inspection for %s not supported!", GetName());
}
fRealData = new TList;
TBuildRealData brd(pointer, this);
if ( ! CallShowMembers(pointer, brd, isTransient) ) {
if ( isTransient ) {
delete fRealData;
fRealData = 0;
} else {
Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
}
}
TBaseClass* base = 0;
TIter next(GetListOfBases());
while ((base = (TBaseClass*) next())) {
if (base->IsSTLContainer()) {
continue;
}
TClass* c = base->GetClassPointer();
if (c) {
c->BuildRealData(0, isTransient);
}
}
}
void TClass::BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
{
R__LOCKGUARD(gInterpreterMutex);
TVirtualStreamerInfo *info;
if (Property() & kIsAbstract) {
info = GetStreamerInfoAbstractEmulated();
} else {
info = GetStreamerInfo();
}
if (!info) {
Error("BuildEmulatedRealData","Missing StreamerInfo for %s",GetName());
return;
}
TIter next(info->GetElements());
TStreamerElement *element;
while ((element = (TStreamerElement*)next())) {
Int_t etype = element->GetType();
Long_t eoffset = element->GetOffset();
TClass *cle = element->GetClassPointer();
if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
continue;
} else if (etype == TVirtualStreamerInfo::kTObject ||
etype == TVirtualStreamerInfo::kTNamed ||
etype == TVirtualStreamerInfo::kObject ||
etype == TVirtualStreamerInfo::kAny) {
TString rdname; rdname.Form("%s%s",name,element->GetFullName());
TRealData *rd = new TRealData(rdname,offset+eoffset,0);
if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
cl->GetListOfRealData()->Add(rd);
rdname.Form("%s%s.",name,element->GetFullName());
if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl);
} else {
TString rdname; rdname.Form("%s%s",name,element->GetFullName());
TRealData *rd = new TRealData(rdname,offset+eoffset,0);
if (gDebug > 0) printf(" Class: %s, adding TRealData=%s, offset=%ld\n",cl->GetName(),rd->GetName(),rd->GetThisOffset());
cl->GetListOfRealData()->Add(rd);
}
}
next.Reset();
while ((element = (TStreamerElement*)next())) {
Int_t etype = element->GetType();
if (element->IsBase() || etype == TVirtualStreamerInfo::kBase) {
Long_t eoffset = element->GetOffset();
TClass *cle = element->GetClassPointer();
if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl);
}
}
}
void TClass::CalculateStreamerOffset() const
{
R__LOCKGUARD(gInterpreterMutex);
if (!fIsOffsetStreamerSet && HasInterpreterInfo()) {
TMmallocDescTemp setreset;
fOffsetStreamer = const_cast<TClass*>(this)->GetBaseClassOffsetRecurse(TObject::Class());
if (fStreamerType == kTObject) {
fStreamerImpl = &TClass::StreamerTObjectInitialized;
}
fIsOffsetStreamerSet = kTRUE;
}
}
Bool_t TClass::CallShowMembers(const void* obj, TMemberInspector &insp, Bool_t isTransient) const
{
if (fShowMembers) {
fShowMembers(obj, insp, isTransient);
return kTRUE;
} else {
if (fCanLoadClassInfo) LoadClassInfo();
if (fClassInfo) {
if (strcmp(GetName(), "string") == 0) {
return kTRUE;
}
gInterpreter->InspectMembers(insp, obj, this, isTransient);
return kTRUE;
} else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
sinfo->CallShowMembers(obj, insp, isTransient);
return kTRUE;
}
}
return kFALSE;
}
void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp, Bool_t isTransient)
{
return gInterpreter->InspectMembers(insp, obj, this, isTransient);
}
Bool_t TClass::CanSplit() const
{
if (fCanSplit >= 0) {
return fCanSplit != 0;
}
R__LOCKGUARD(gInterpreterMutex);
TClass *This = const_cast<TClass*>(this);
if (this == TObject::Class()) { This->fCanSplit = 1; return kTRUE; }
if (fName == "TClonesArray") { This->fCanSplit = 1; return kTRUE; }
if (fRefProxy) { This->fCanSplit = 0; return kFALSE; }
if (fName.BeginsWith("TVectorT<")) { This->fCanSplit = 0; return kFALSE; }
if (fName.BeginsWith("TMatrixT<")) { This->fCanSplit = 0; return kFALSE; }
if (fName == "string") { This->fCanSplit = 0; return kFALSE; }
if (fName == "std::string") { This->fCanSplit = 0; return kFALSE; }
if (GetCollectionProxy()!=0) {
if (GetCollectionProxy()->HasPointers()) { This->fCanSplit = 0; return kFALSE; }
TClass *valueClass = GetCollectionProxy()->GetValueClass();
if (valueClass == 0) { This->fCanSplit = 0; return kFALSE; }
static TClassRef stdStringClass("std::string");
if (valueClass==TString::Class() || valueClass==stdStringClass)
{ This->fCanSplit = 0; return kFALSE; }
if (!valueClass->CanSplit()) { This->fCanSplit = 0; return kFALSE; }
if (valueClass->GetCollectionProxy() != 0) { This->fCanSplit = 0; return kFALSE; }
Int_t stl = -TClassEdit::IsSTLCont(GetName(), 0);
if ((stl==ROOT::kSTLmap || stl==ROOT::kSTLmultimap)
&& !valueClass->HasDataMemberInfo()==0)
{
This->fCanSplit = 0;
return kFALSE;
}
This->fCanSplit = 1;
return kTRUE;
}
if (GetStreamer()!=0) {
This->fCanSplit = 0;
return kFALSE;
} else if ( TestBit(TClass::kHasCustomStreamerMember) ) {
This->fCanSplit = 0;
return kFALSE;
}
if (Size()==1) {
This->fCanSplit = 0;
return kFALSE;
}
if (InheritsFrom("TRef")) { This->fCanSplit = 0; return kFALSE; }
if (InheritsFrom("TRefArray")) { This->fCanSplit = 0; return kFALSE; }
if (InheritsFrom("TArray")) { This->fCanSplit = 0; return kFALSE; }
if (InheritsFrom("TCollection") && !InheritsFrom("TClonesArray")) { This->fCanSplit = 0; return kFALSE; }
if (InheritsFrom("TTree")) { This->fCanSplit = 0; return kFALSE; }
TClass *ncThis = const_cast<TClass*>(this);
TIter nextb(ncThis->GetListOfBases());
TBaseClass *base;
while((base = (TBaseClass*)nextb())) {
if (!base->GetClassPointer()) { This->fCanSplit = 0; return kFALSE; }
}
This->fCanSplit = 1;
return kTRUE;
}
Long_t TClass::ClassProperty() const
{
if (fProperty == -1) Property();
return fClassProperty;
}
TObject *TClass::Clone(const char *new_name) const
{
if (new_name == 0 || new_name[0]=='\0' || fName == new_name) {
Error("Clone","The name of the class must be changed when cloning a TClass object.");
return 0;
}
R__LOCKGUARD2(gInterpreterMutex);
TClass::RemoveClass(const_cast<TClass*>(this));
TClass *copy;
if (fTypeInfo) {
copy = new TClass(GetName(),
fClassVersion,
*fTypeInfo,
new TIsAProxy(*fTypeInfo),
GetDeclFileName(),
GetImplFileName(),
GetDeclFileLine(),
GetImplFileLine());
} else {
copy = new TClass(GetName(),
fClassVersion,
GetDeclFileName(),
GetImplFileName(),
GetDeclFileLine(),
GetImplFileLine());
}
copy->fShowMembers = fShowMembers;
TClass::RemoveClass(copy);
copy->fName = new_name;
TClass::AddClass(copy);
copy->SetNew(fNew);
copy->SetNewArray(fNewArray);
copy->SetDelete(fDelete);
copy->SetDeleteArray(fDeleteArray);
copy->SetDestructor(fDestructor);
copy->SetDirectoryAutoAdd(fDirAutoAdd);
copy->fStreamerFunc = fStreamerFunc;
copy->fConvStreamerFunc = fConvStreamerFunc;
if (fStreamer) {
copy->AdoptStreamer(fStreamer->Generate());
}
if (fCollectionProxy && !copy->IsZombie()) {
copy->CopyCollectionProxy(*fCollectionProxy);
}
copy->SetClassSize(fSizeof);
if (fRefProxy) {
copy->AdoptReferenceProxy( fRefProxy->Clone() );
}
TClass::AddClass(const_cast<TClass*>(this));
return copy;
}
void TClass::CopyCollectionProxy(const TVirtualCollectionProxy &orig)
{
delete fCollectionProxy;
fCollectionProxy = orig.Generate();
}
void TClass::Draw(Option_t *option)
{
if (!HasInterpreterInfo()) return;
TVirtualPad *padsav = gPad;
TString opt=option;
if (!padsav || !opt.Contains("same")) {
TVirtualPad *padclass = (TVirtualPad*)(gROOT->GetListOfCanvases())->FindObject("R__class");
if (!padclass) {
gROOT->ProcessLine("new TCanvas(\"R__class\",\"class\",20,20,1000,750);");
} else {
padclass->cd();
}
}
if (gPad) gPad->DrawClassObject(this,option);
if (padsav) padsav->cd();
}
void TClass::Dump(const void *obj, Bool_t noAddr ) const
{
Long_t prObj = noAddr ? 0 : (Long_t)obj;
if (IsTObject()) {
if (!fIsOffsetStreamerSet) {
CalculateStreamerOffset();
}
TObject *tobj = (TObject*)((Long_t)obj + fOffsetStreamer);
if (sizeof(this) == 4)
Printf("==> Dumping object at: 0x%08lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
else
Printf("==> Dumping object at: 0x%016lx, name=%s, class=%s\n",prObj,tobj->GetName(),GetName());
} else {
if (sizeof(this) == 4)
Printf("==> Dumping object at: 0x%08lx, class=%s\n",prObj,GetName());
else
Printf("==> Dumping object at: 0x%016lx, class=%s\n",prObj,GetName());
}
TDumpMembers dm(noAddr);
if (!CallShowMembers(obj, dm, kFALSE)) {
Info("Dump", "No ShowMembers function, dumping disabled");
}
}
char *TClass::EscapeChars(const char *text) const
{
static const UInt_t maxsize = 255;
static char name[maxsize+2];
UInt_t nch = strlen(text);
UInt_t icur = 0;
for (UInt_t i = 0; i < nch && icur < maxsize; ++i, ++icur) {
if (text[i] == '\"' || text[i] == '[' || text[i] == '~' ||
text[i] == ']' || text[i] == '&' || text[i] == '#' ||
text[i] == '!' || text[i] == '^' || text[i] == '<' ||
text[i] == '?' || text[i] == '>') {
name[icur] = '@';
++icur;
}
name[icur] = text[i];
}
name[icur] = 0;
return name;
}
TClass *TClass::GetActualClass(const void *object) const
{
if (object==0) return (TClass*)this;
if (!IsLoaded()) {
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (sinfo) {
return sinfo->GetActualClass(object);
}
return (TClass*)this;
}
if (fIsA) {
return (*fIsA)(object);
} else if (fGlobalIsA) {
return fGlobalIsA(this,object);
} else {
if (fIsAMethod==0) {
TMethodCall* temp = new TMethodCall((TClass*)this, "IsA", "");
if (!temp->GetMethod()) {
delete temp;
Error("IsA","Can not find any IsA function for %s!",GetName());
return (TClass*)this;
}
temp->ReturnType();
TMethodCall* expected = nullptr;
if( not fIsAMethod.compare_exchange_strong(expected,temp) ) {
delete temp;
}
}
char * char_result = 0;
(*fIsAMethod).Execute((void*)object, &char_result);
return (TClass*)char_result;
}
}
TClass *TClass::GetBaseClass(const char *classname)
{
if (strcmp(GetName(), classname) == 0) return this;
if (!HasDataMemberInfo()) return 0;
TClass *search = TClass::GetClass(classname,kTRUE,kTRUE);
if (search) return GetBaseClass(search);
else return 0;
}
TClass *TClass::GetBaseClass(const TClass *cl)
{
if (cl == this) return this;
if (!HasDataMemberInfo()) return 0;
TObjLink *lnk = GetListOfBases() ? fBase->FirstLink() : 0;
while (lnk) {
TClass *c, *c1;
TBaseClass *base = (TBaseClass*) lnk->GetObject();
c = base->GetClassPointer();
if (c) {
if (cl == c) return c;
c1 = c->GetBaseClass(cl);
if (c1) return c1;
}
lnk = lnk->Next();
}
return 0;
}
Int_t TClass::GetBaseClassOffsetRecurse(const TClass *cl)
{
if (cl == this) return 0;
if (!fBase) {
if (fCanLoadClassInfo) LoadClassInfo();
if (!fClassInfo) {
TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
if (!sinfo) return -1;
TStreamerElement *element;
Int_t offset = 0;
TObjArray &elems = *(sinfo->GetElements());
Int_t size = elems.GetLast()+1;
for(Int_t i=0; i<size; i++) {
element = (TStreamerElement*)elems[i];
if (element->IsA() == TStreamerBase::Class()) {
TStreamerBase *base = (TStreamerBase*)element;
TClass *baseclass = base->GetClassPointer();
if (!baseclass) return -1;
Int_t subOffset = baseclass->GetBaseClassOffsetRecurse(cl);
if (subOffset == -2) return -2;
if (subOffset != -1) return offset+subOffset;
offset += baseclass->Size();
}
}
return -1;
}
}
TClass *c;
Int_t off;
TBaseClass *inh;
TObjLink *lnk = 0;
if (fBase==0) lnk = GetListOfBases()->FirstLink();
else lnk = fBase->FirstLink();
while (lnk) {
inh = (TBaseClass *)lnk->GetObject();
c = inh->GetClassPointer(kTRUE);
if (c) {
if (cl == c) {
if ((inh->Property() & kIsVirtualBase) != 0)
return -2;
return inh->GetDelta();
}
off = c->GetBaseClassOffsetRecurse(cl);
if (off == -2) return -2;
if (off != -1) {
return off + inh->GetDelta();
}
}
lnk = lnk->Next();
}
return -1;
}
Int_t TClass::GetBaseClassOffset(const TClass *toBase, void *address, bool isDerivedObject)
{
R__LOCKGUARD(gInterpreterMutex);
if ((!address ) &&
(!HasInterpreterInfoInMemory() || !toBase->HasInterpreterInfoInMemory())) {
Int_t offset = GetBaseClassOffsetRecurse (toBase);
if (offset != -2) {
return offset;
}
return offset;
}
ClassInfo_t* derived = GetClassInfo();
ClassInfo_t* base = toBase->GetClassInfo();
if(derived && base) {
return gCling->ClassInfo_GetBaseOffset(derived, base, address, isDerivedObject);
}
else {
Int_t offset = GetBaseClassOffsetRecurse (toBase);
if (offset != -2) {
return offset;
}
}
return -1;
}
TClass *TClass::GetBaseDataMember(const char *datamember)
{
if (!HasDataMemberInfo()) return 0;
TDataMember *dm = GetDataMember(datamember);
if (dm) return this;
TBaseClass *inh;
TIter next(GetListOfBases());
while ((inh = (TBaseClass *) next())) {
TClass *c = inh->GetClassPointer();
if (c) {
TClass *cdm = c->GetBaseDataMember(datamember);
if (cdm) return cdm;
}
}
return 0;
}
namespace {
struct TClassLocalStorage {
TClassLocalStorage() : fCollectionProxy(0), fStreamer(0) {};
TVirtualCollectionProxy *fCollectionProxy;
TClassStreamer *fStreamer;
static TClassLocalStorage *GetStorage(const TClass *cl)
{
void **thread_ptr = (*gThreadTsd)(0,ROOT::kClassThreadSlot);
if (thread_ptr) {
if (*thread_ptr==0) *thread_ptr = new TExMap();
TExMap *lmap = (TExMap*)(*thread_ptr);
ULong_t hash = TString::Hash(&cl, sizeof(void*));
ULong_t local = 0;
UInt_t slot;
if ((local = (ULong_t)lmap->GetValue(hash, (Long_t)cl, slot)) != 0) {
} else {
local = (ULong_t) new TClassLocalStorage();
lmap->AddAt(slot, hash, (Long_t)cl, local);
}
return (TClassLocalStorage*)local;
}
return 0;
}
};
}
TVirtualCollectionProxy *TClass::GetCollectionProxy() const
{
assert(TestBit(kLoading) || !TClassEdit::IsSTLCont(fName) || fCollectionProxy || 0 == "The TClass for the STL collection has no collection proxy!");
if (gThreadTsd && fCollectionProxy) {
TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
if (local == 0) return fCollectionProxy;
if (local->fCollectionProxy==0) local->fCollectionProxy = fCollectionProxy->Generate();
return local->fCollectionProxy;
}
return fCollectionProxy;
}
TClassStreamer *TClass::GetStreamer() const
{
if (gThreadTsd && fStreamer) {
TClassLocalStorage *local = TClassLocalStorage::GetStorage(this);
if (local==0) return fStreamer;
if (local->fStreamer==0) {
local->fStreamer = fStreamer->Generate();
const type_info &orig = ( typeid(*fStreamer) );
if (!local->fStreamer) {
Warning("GetStreamer","For %s, the TClassStreamer (%s) passed's call to Generate failed!",GetName(),orig.name());
} else {
const type_info © = ( typeid(*local->fStreamer) );
if (strcmp(orig.name(),copy.name())!=0) {
Warning("GetStreamer","For %s, the TClassStreamer passed does not properly implement the Generate method (%s vs %s)\n",GetName(),orig.name(),copy.name());
}
}
}
return local->fStreamer;
}
return fStreamer;
}
ClassStreamerFunc_t TClass::GetStreamerFunc() const
{
return fStreamerFunc;
}
ClassConvStreamerFunc_t TClass::GetConvStreamerFunc() const
{
return fConvStreamerFunc;
}
TVirtualIsAProxy* TClass::GetIsAProxy() const
{
return fIsA;
}
TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
{
if (!name || !name[0]) return 0;
if (strstr(name, "(anonymous)")) return 0;
if (strncmp(name,"class ",6)==0) name += 6;
if (strncmp(name,"struct ",7)==0) name += 7;
R__LOCKGUARD(gInterpreterMutex);
if (!gROOT->GetListOfClasses()) return 0;
TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
if (cl) {
if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
load = kTRUE;
}
DictFuncPtr_t dict = TClassTable::GetDictNorm(name);
if (dict) {
if (!cl && !load) return 0;
TClass *loadedcl = (dict)();
if (loadedcl) {
loadedcl->PostLoadCheck();
return loadedcl;
}
}
std::string normalizedName;
Bool_t checkTable = kFALSE;
if (!cl) {
int oldAutoloadVal = gCling->SetClassAutoloading(false);
TClassEdit::GetNormalizedName(normalizedName, name);
gCling->SetClassAutoloading(oldAutoloadVal);
if (normalizedName != name) {
cl = (TClass*)gROOT->GetListOfClasses()->FindObject(normalizedName.c_str());
if (cl) {
if (cl->IsLoaded() || cl->TestBit(kUnloading)) return cl;
load = kTRUE;
}
checkTable = kTRUE;
}
} else {
normalizedName = cl->GetName();
checkTable = load && (normalizedName != name);
}
if (!load) return 0;
TClass *loadedcl = 0;
if (checkTable) {
loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
} else {
if (gInterpreter->AutoLoad(normalizedName.c_str(),kTRUE)) {
loadedcl = LoadClassDefault(normalizedName.c_str(),silent);
}
if (!loadedcl){
if (TDataType* theDataType = gROOT->GetType(normalizedName.c_str())){
auto underlyingTypeName = theDataType->GetTypeName();
auto underlyingTypeDict = TClassTable::GetDictNorm(underlyingTypeName.Data());
if (underlyingTypeDict){
loadedcl = underlyingTypeDict();
}
}
}
}
if (loadedcl) return loadedcl;
loadedcl = LoadClassCustom(normalizedName.c_str(),silent);
if (loadedcl) return loadedcl;
if (cl) return cl;
if (TClassEdit::IsSTLCont( normalizedName.c_str() )) {
return gInterpreter->GenerateTClass(normalizedName.c_str(), kTRUE, silent);
}
{
std::string::size_type posLess = normalizedName.find('<');
if (posLess != std::string::npos) {
gCling->AutoParse(normalizedName.substr(0, posLess).c_str());
}
}
if (gDebug>0){
printf("TClass::GetClass: Header Parsing - The representation of %s was not found in the type system. A lookup in the interpreter is about to be tried: this can cause parsing. This can be avoided selecting %s in the linkdef/selection file.\n",normalizedName.c_str(), normalizedName.c_str());
}
if (normalizedName.length() &&
gInterpreter->CheckClassInfo(normalizedName.c_str(), kTRUE , kTRUE )) {
std::string alternative;
gInterpreter->GetInterpreterTypeName(normalizedName.c_str(),alternative,kTRUE);
const char *altname = alternative.c_str();
if ( strncmp(altname,"std::",5)==0 ) {
altname += 5;
}
if (altname != normalizedName && strcmp(altname,name) != 0) {
return GetClass(altname,load);
}
TClass *ncl = gInterpreter->GenerateTClass(normalizedName.c_str(), kFALSE, silent);
if (!ncl->IsZombie()) {
return ncl;
}
delete ncl;
}
return 0;
}
TClass *TClass::GetClass(const type_info& typeinfo, Bool_t load, Bool_t )
{
R__LOCKGUARD2(gInterpreterMutex);
if (!gROOT->GetListOfClasses()) return 0;
TClass* cl = GetIdMap()->Find(typeinfo.name());
if (cl) {
if (cl->IsLoaded()) return cl;
load = kTRUE;
} else {
}
if (!load) return 0;
DictFuncPtr_t dict = TClassTable::GetDict(typeinfo);
if (dict) {
cl = (dict)();
if (cl) cl->PostLoadCheck();
return cl;
}
if (cl) return cl;
TIter next(gROOT->GetListOfClassGenerators());
TClassGenerator *gen;
while( (gen = (TClassGenerator*) next()) ) {
cl = gen->GetClass(typeinfo,load);
if (cl) {
cl->PostLoadCheck();
return cl;
}
}
int autoload_old = gCling->SetClassAutoloading(1);
if (!autoload_old) {
gCling->SetClassAutoloading(0);
}
if (autoload_old && gInterpreter->AutoLoad(typeinfo,kTRUE)) {
gCling->SetClassAutoloading(0);
cl = GetClass(typeinfo, load);
gCling->SetClassAutoloading(1);
if (cl) {
return cl;
}
}
cl = gInterpreter->GetClass(typeinfo, load);
return cl;
}
TClass *TClass::GetClass(ClassInfo_t *info, Bool_t load, Bool_t silent)
{
if (!info || !gCling->ClassInfo_IsValid(info)) return 0;
if (!gROOT->GetListOfClasses()) return 0;
TString name( gCling->ClassInfo_FullName(info) );
TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
if (cl) {
if (cl->IsLoaded()) return cl;
load = kTRUE;
}
if (!load) return 0;
TClass *loadedcl = 0;
if (cl) loadedcl = gROOT->LoadClass(cl->GetName(),silent);
else loadedcl = gROOT->LoadClass(name,silent);
if (loadedcl) return loadedcl;
if (cl) return cl;
TClass *ncl = gInterpreter->GenerateTClass(info, silent);
if (!ncl->IsZombie()) {
return ncl;
} else {
delete ncl;
return 0;
}
}
Bool_t TClass::HasNoInfoOrEmuOrFwdDeclaredDecl(const char* name){
return fNoInfoOrEmuOrFwdDeclNameRegistry.HasDeclName(name);
}
Bool_t TClass::GetClass(DeclId_t id, std::vector<TClass*> &classes)
{
if (!gROOT->GetListOfClasses()) return 0;
DeclIdMap_t* map = GetDeclIdMap();
DeclIdMap_t::equal_range iter = map->Find(id);
if (iter.first == iter.second) return false;
std::vector<TClass*>::iterator vectIt = classes.begin();
for (DeclIdMap_t::const_iterator it = iter.first; it != iter.second; ++it)
vectIt = classes.insert(vectIt, it->second);
return true;
}
DictFuncPtr_t TClass::GetDict (const char *cname)
{
return TClassTable::GetDict(cname);
}
DictFuncPtr_t TClass::GetDict (const type_info& info)
{
return TClassTable::GetDict(info);
}
TDataMember *TClass::GetDataMember(const char *datamember) const
{
if ((!(fData && fData->IsLoaded()) && !HasInterpreterInfo())
|| datamember == 0) return 0;
const char *start_name = datamember;
while (*start_name == '*') ++start_name;
if (const char *s = strchr(start_name, '[')){
UInt_t len = s-start_name;
TString name(start_name,len);
return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(name.Data());
} else {
return (TDataMember *)((TClass*)this)->GetListOfDataMembers(kFALSE)->FindObject(start_name);
}
}
Long_t TClass::GetDataMemberOffset(const char *name) const
{
TRealData *rd = GetRealData(name);
if (rd) return rd->GetThisOffset();
if (strchr(name,'[')==0) {
TVirtualStreamerInfo *info = const_cast<TClass*>(this)->GetCurrentStreamerInfo();
if (info) {
return info->GetOffset(name);
}
}
return 0;
}
TRealData* TClass::GetRealData(const char* name) const
{
if (!fRealData) {
const_cast<TClass*>(this)->BuildRealData();
}
if (!fRealData) {
return 0;
}
if (!name) {
return 0;
}
TRealData* rd = (TRealData*) fRealData->FindObject(name);
if (rd) {
return rd;
}
std::string givenName(name);
std::string::size_type firstBracket = givenName.find_first_of("[");
if (firstBracket != std::string::npos) {
std::string nameNoDim(givenName.substr(0, firstBracket));
TObjLink* lnk = fRealData->FirstLink();
while (lnk) {
TObject* obj = lnk->GetObject();
std::string objName(obj->GetName());
std::string::size_type pos = objName.find_first_of("[");
if (pos != std::string::npos) {
objName.erase(pos);
if (objName == nameNoDim) {
return static_cast<TRealData*>(obj);
}
}
lnk = lnk->Next();
}
}
std::ostringstream ptrname;
ptrname << "*" << givenName;
rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
if (rd) {
return rd;
}
std::string::size_type firstDot = givenName.find_first_of(".");
if (firstDot == std::string::npos) {
return 0;
}
std::string::size_type lastDot = givenName.find_last_of(".");
std::ostringstream starname;
starname << givenName.substr(0, lastDot) << ".*" << givenName.substr(lastDot + 1);
rd = (TRealData*) fRealData->FindObject(starname.str().c_str());
if (rd) {
return rd;
}
std::string firstDotName(givenName.substr(firstDot + 1));
rd = (TRealData*) fRealData->FindObject(firstDotName.c_str());
if (rd) {
return rd;
}
std::string::size_type firstDotBracket = firstDotName.find_first_of("[");
if (firstDotBracket != std::string::npos) {
std::string nameNoDim(firstDotName.substr(0, firstDotBracket));
TObjLink* lnk = fRealData->FirstLink();
while (lnk) {
TObject* obj = lnk->GetObject();
std::string objName(obj->GetName());
std::string::size_type pos = objName.find_first_of("[");
if (pos != std::string::npos) {
objName.erase(pos);
if (objName == nameNoDim) {
return static_cast<TRealData*>(obj);
}
}
lnk = lnk->Next();
}
}
ptrname.str("");
ptrname << "*" << firstDotName;
rd = (TRealData*) fRealData->FindObject(ptrname.str().c_str());
if (rd) {
return rd;
}
std::string::size_type bracket = starname.str().find_first_of("[");
if (bracket == std::string::npos) {
return 0;
}
rd = (TRealData*) fRealData->FindObject(starname.str().substr(0, bracket).c_str());
if (rd) {
return rd;
}
return 0;
}
TFunctionTemplate *TClass::GetFunctionTemplate(const char *name)
{
if (!gInterpreter || !HasInterpreterInfo()) return 0;
if (!fFuncTemplate) fFuncTemplate = new TListOfFunctionTemplates(this);
return (TFunctionTemplate*)fFuncTemplate->FindObject(name);
}
const char *TClass::GetSharedLibs()
{
if (!gInterpreter) return 0;
if (fSharedLibs.IsNull())
fSharedLibs = gInterpreter->GetClassSharedLibs(fName);
return !fSharedLibs.IsNull() ? fSharedLibs.Data() : 0;
}
TList *TClass::GetListOfBases()
{
if (!fBase) {
if (fCanLoadClassInfo) {
if (fState == kHasTClassInit) {
R__LOCKGUARD(gInterpreterMutex);
TProtoClass *proto = TClassTable::GetProtoNorm(GetName());
if (proto && proto->FillTClass(this)) {
fHasRootPcmInfo = kTRUE;
}
}
if (!fHasRootPcmInfo && !fCanLoadClassInfo) {
LoadClassInfo();
}
}
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetListOfBases", "gInterpreter not initialized");
R__LOCKGUARD(gInterpreterMutex);
if(!fBase) {
gInterpreter->CreateListOfBaseClasses(this);
}
}
return fBase;
}
TList *TClass::GetListOfEnums(Bool_t load )
{
auto temp = fEnums.load();
if (temp) {
if (load) {
if (fProperty == -1) Property();
if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
R__LOCKGUARD2(gROOTMutex);
temp->Load();
}
}
return temp;
}
if (!load) {
if (fProperty == -1) Property();
if (! ((kIsClass | kIsStruct | kIsUnion) & fProperty) ) {
R__LOCKGUARD(gInterpreterMutex);
if (fEnums) {
return fEnums.load();
}
fEnums = new TListOfEnumsWithLock(this);
return fEnums;
}
static TListOfEnums s_list;
return &s_list;
}
R__LOCKGUARD(gInterpreterMutex);
if (fEnums) {
if (load) (*fEnums).Load();
return fEnums.load();
}
if (fProperty == -1) Property();
if ( (kIsClass | kIsStruct | kIsUnion) & fProperty) {
temp = new TListOfEnums(this);
} else {
temp = new TListOfEnumsWithLock(this);
}
temp->Load();
fEnums = temp;
return temp;
}
TList *TClass::GetListOfDataMembers(Bool_t load )
{
R__LOCKGUARD(gInterpreterMutex);
if (!fData) {
if (fCanLoadClassInfo && fState == kHasTClassInit) {
TProtoClass *proto = TClassTable::GetProtoNorm(GetName());
if (proto && proto->FillTClass(this)) {
fHasRootPcmInfo = kTRUE;
return fData;
}
}
fData = new TListOfDataMembers(this);
}
if (Property() & (kIsClass|kIsStruct|kIsUnion)) {
if (!fData->IsLoaded()) fData->Load();
} else if (load) fData->Load();
return fData;
}
TList *TClass::GetListOfFunctionTemplates(Bool_t load )
{
R__LOCKGUARD(gInterpreterMutex);
if (!fFuncTemplate) fFuncTemplate = new TListOfFunctionTemplates(this);
if (load) fFuncTemplate->Load();
return fFuncTemplate;
}
TList *TClass::GetListOfMethods(Bool_t load )
{
R__LOCKGUARD(gInterpreterMutex);
if (!fMethod) GetMethodList();
if (load) {
if (gDebug>0) Info("GetListOfMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
(*fMethod).Load();
}
return fMethod;
}
TCollection *TClass::GetListOfMethodOverloads(const char* name) const
{
return const_cast<TClass*>(this)->GetMethodList()->GetListForObject(name);
}
const TList *TClass::GetListOfAllPublicMethods(Bool_t load )
{
R__LOCKGUARD(gInterpreterMutex);
if (!fAllPubMethod) fAllPubMethod = new TViewPubFunctions(this);
if (load) {
if (gDebug>0) Info("GetListOfAllPublicMethods","Header Parsing - Asking for all the methods of class %s: this can involve parsing.",GetName());
fAllPubMethod->Load();
}
return fAllPubMethod;
}
TList *TClass::GetListOfAllPublicDataMembers(Bool_t load )
{
R__LOCKGUARD(gInterpreterMutex);
if (!fAllPubData) fAllPubData = new TViewPubDataMembers(this);
if (load) fAllPubData->Load();
return fAllPubData;
}
void TClass::GetMenuItems(TList *list)
{
if (!HasInterpreterInfo()) return;
TIter nextBase(GetListOfBases(), kIterBackward);
TBaseClass *baseClass;
while ((baseClass = (TBaseClass *) nextBase())) {
TClass *base = baseClass->GetClassPointer();
if (base) base->GetMenuItems(list);
}
TMethod *method, *m;
TIter next(GetListOfMethods(), kIterBackward);
while ((method = (TMethod*)next())) {
m = (TMethod*)list->FindObject(method->GetName());
if (method->IsMenuItem() != kMenuNoMenu) {
if (!m)
list->AddFirst(method);
} else {
if (m && m->GetNargs() == method->GetNargs())
list->Remove(m);
}
}
}
Bool_t TClass::HasDictionary()
{
return IsLoaded();
}
Bool_t TClass::HasDictionarySelection(const char* clname)
{
if (TClass* cl = (TClass*)gROOT->GetListOfClasses()->FindObject(clname))
return cl->IsLoaded();
return gClassTable->GetDict(clname) || gInterpreter->GetClassSharedLibs(clname);
}
void TClass::GetMissingDictionariesForBaseClasses(TCollection& result, TCollection& visited, bool recurse)
{
TList* lb = GetListOfBases();
if (!lb) return;
TIter nextBase(lb);
TBaseClass* base = 0;
while ((base = (TBaseClass*)nextBase())) {
TClass* baseCl = base->Class();
if (baseCl) {
baseCl->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
}
}
}
void TClass::GetMissingDictionariesForMembers(TCollection& result, TCollection& visited, bool recurse)
{
TListOfDataMembers* ldm = (TListOfDataMembers*)GetListOfDataMembers();
if (!ldm) return ;
TIter nextMemb(ldm);
TDataMember * dm = 0;
while ((dm = (TDataMember*)nextMemb())) {
if(!dm->IsPersistent()) {
continue;
}
if (dm->Property() & kIsStatic) {
continue;
}
TClass* dmTClass = 0;
if (dm->GetDataType()) {
dmTClass = dm->GetDataType()->Class();
} else if (dm->GetTypeName()) {
dmTClass = TClass::GetClass(dm->GetTypeName());
}
if (dmTClass) {
dmTClass->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
}
}
}
void TClass::GetMissingDictionariesForPairElements(TCollection& result, TCollection& visited, bool recurse)
{
TVirtualStreamerInfo *SI = (TVirtualStreamerInfo*)this->GetStreamerInfo();
for (int i = 0; i < 2; i++) {
TClass* pairElement = ((TStreamerElement*)SI->GetElements()->At(i))->GetClass();
if (pairElement) {
pairElement->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
}
}
}
void TClass::GetMissingDictionariesWithRecursionCheck(TCollection& result, TCollection& visited, bool recurse)
{
if (result.FindObject(this) || visited.FindObject(this)) return;
static TClassRef sCIString("string");
if (this == sCIString) return;
if (strncmp(fName, "pair<", 5) == 0) {
GetMissingDictionariesForPairElements(result, visited, recurse);
return;
}
if (!HasDictionary()) {
result.Add(this);
}
visited.Add(this);
if (!TestBit(TClass::kHasCustomStreamerMember)) {
if (GetCollectionProxy()) {
TClass* t = 0;
if ((t = GetCollectionProxy()->GetValueClass())) {
if (!t->HasDictionary()) {
t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
}
}
} else {
if (recurse) {
GetMissingDictionariesForMembers(result, visited, recurse);
}
GetMissingDictionariesForBaseClasses(result, visited, recurse);
}
}
}
void TClass::GetMissingDictionaries(THashTable& result, bool recurse)
{
if (result.FindObject(this)) return;
static TClassRef sCIString("string");
if (this == sCIString) return;
THashTable visited;
if (strncmp(fName, "pair<", 5) == 0) {
GetMissingDictionariesForPairElements(result, visited, recurse);
return;
}
if (!HasDictionary()) {
result.Add(this);
}
visited.Add(this);
if (!TestBit(TClass::kHasCustomStreamerMember)) {
if (GetCollectionProxy()) {
TClass* t = 0;
if ((t = GetCollectionProxy()->GetValueClass())) {
if (!t->HasDictionary()) {
t->GetMissingDictionariesWithRecursionCheck(result, visited, recurse);
}
}
} else {
GetMissingDictionariesForMembers(result, visited, recurse);
GetMissingDictionariesForBaseClasses(result, visited, recurse);
}
}
}
Bool_t TClass::IsFolder(void *obj) const
{
return Browse(obj,(TBrowser*)0);
}
void TClass::ReplaceWith(TClass *newcl) const
{
R__LOCKGUARD(gInterpreterMutex);
TIter nextClass(gROOT->GetListOfClasses());
TClass *acl;
TVirtualStreamerInfo *info;
TList tobedeleted;
Bool_t autoload = gInterpreter->SetClassAutoloading(kFALSE);
while ((acl = (TClass*)nextClass())) {
if (acl == newcl) continue;
TIter nextInfo(acl->GetStreamerInfos());
while ((info = (TVirtualStreamerInfo*)nextInfo())) {
info->Update(this, newcl);
}
if (acl->GetCollectionProxy()) {
acl->GetCollectionProxy()->UpdateValueClass(this, newcl);
}
}
TIter delIter( &tobedeleted );
while ((acl = (TClass*)delIter())) {
delete acl;
}
gInterpreter->UnRegisterTClassUpdate(this);
gInterpreter->SetClassAutoloading(autoload);
}
void TClass::ResetClassInfo(Long_t )
{
Warning("ResetClassInfo(Long_t tagnum)","Call to deprecated interface (does nothing)");
}
void TClass::ResetClassInfo()
{
R__LOCKGUARD2(gInterpreterMutex);
InsertTClassInRegistryRAII insertRAII(fState,fName,fNoInfoOrEmuOrFwdDeclNameRegistry);
if (fClassInfo) {
TClass::RemoveClassDeclId(gInterpreter->GetDeclId(fClassInfo));
gInterpreter->ClassInfo_Delete(fClassInfo);
fClassInfo = 0;
}
ResetCaches();
if (fState != TClass::kHasTClassInit) {
if (fStreamerInfo->GetEntries() != 0) {
fState = TClass::kEmulated;
} else {
fState = TClass::kForwardDeclared;
}
} else {
fCanLoadClassInfo = kTRUE;
}
}
void TClass::ResetCaches()
{
R__ASSERT(!TestBit(kLoading) && "Resetting the caches does not make sense during loading!" );
if (fData)
fData->Unload();
if (fEnums)
(*fEnums).Unload();
if (fMethod)
(*fMethod).Unload();
delete fAllPubData; fAllPubData = 0;
if (fBase)
fBase->Delete();
delete fBase; fBase = 0;
if (fRealData)
fRealData->Delete();
delete fRealData; fRealData=0;
}
void TClass::ResetMenuList()
{
if (fClassMenuList)
fClassMenuList->Delete();
else
fClassMenuList = new TList();
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, this));
}
void TClass::ls(Option_t *options) const
{
TNamed::ls(options);
if (options==0 || options[0]==0) return;
if (strstr(options,"streamerinfo")!=0) {
GetStreamerInfos()->ls(options);
if (fConversionStreamerInfo.load()) {
std::map<std::string, TObjArray*>::iterator it;
std::map<std::string, TObjArray*>::iterator end = (*fConversionStreamerInfo).end();
for( it = (*fConversionStreamerInfo).begin(); it != end; ++it ) {
it->second->ls(options);
}
}
}
}
void TClass::MakeCustomMenuList()
{
R__LOCKGUARD(gInterpreterMutex);
TClassMenuItem *menuItem;
GetMenuList()->Delete();
TList* methodList = new TList;
GetMenuItems(methodList);
TMethod *method;
TMethodArg *methodArg;
TClass *classPtr = 0;
TIter next(methodList);
while ((method = (TMethod*) next())) {
if (classPtr != method->GetClass()) {
menuItem = new TClassMenuItem(TClassMenuItem::kPopupSeparator, this);
fClassMenuList->AddLast(menuItem);
classPtr = method->GetClass();
}
TString sig;
TList* margsList = method->GetListOfMethodArgs();
TIter nextarg(margsList);
while ((methodArg = (TMethodArg*)nextarg())) {
sig = sig+","+methodArg->GetFullTypeName();
}
if (sig.Length()!=0) sig.Remove(0,1);
menuItem = new TClassMenuItem(TClassMenuItem::kPopupUserFunction, this,
method->GetName(), method->GetName(),0,
sig.Data(),-1,TClassMenuItem::kIsSelf);
if (method->IsMenuItem() == kMenuToggle) menuItem->SetToggle();
fClassMenuList->Add(menuItem);
}
delete methodList;
}
void TClass::Move(void *arenaFrom, void *arenaTo) const
{
if ((GetState() <= kEmulated) && !fCollectionProxy) {
MoveAddressInRepository("TClass::Move",arenaFrom,arenaTo,this);
}
}
TList *TClass::GetMenuList() const {
if (!fClassMenuList) {
fClassMenuList = new TList();
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, const_cast<TClass*>(this)));
}
return fClassMenuList;
}
TListOfFunctions *TClass::GetMethodList()
{
if (!fMethod) {
std::unique_ptr<TListOfFunctions> temp{ new TListOfFunctions(this) };
TListOfFunctions* expected = nullptr;
if(fMethod.compare_exchange_strong(expected, temp.get()) ) {
temp.release();
}
}
return fMethod;
}
TMethod *TClass::GetMethodAny(const char *method)
{
if (!HasInterpreterInfo()) return 0;
return (TMethod*) GetMethodList()->FindObject(method);
}
TMethod *TClass::GetMethodAllAny(const char *method)
{
if (!HasInterpreterInfo()) return 0;
TMethod* m = GetMethodAny(method);
if (m) return m;
TBaseClass *base;
TIter nextb(GetListOfBases());
while ((base = (TBaseClass *) nextb())) {
TClass *c = base->GetClassPointer();
if (c) {
m = c->GetMethodAllAny(method);
if (m) return m;
}
}
return 0;
}
TMethod *TClass::GetMethod(const char *method, const char *params,
Bool_t objectIsConst )
{
if (fCanLoadClassInfo) LoadClassInfo();
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetMethod", "gInterpreter not initialized");
TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
method, params,
objectIsConst);
if (!decl) return 0;
TMethod* f = FindClassOrBaseMethodWithId(decl);
if (f) return f;
Error("GetMethod",
"\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
method,params,objectIsConst ? "const " : "", GetName());
return 0;
}
TMethod* TClass::FindClassOrBaseMethodWithId(DeclId_t declId) {
TFunction *f = GetMethodList()->Get(declId);
if (f) return (TMethod*)f;
TBaseClass *base;
TIter next(GetListOfBases());
while ((base = (TBaseClass *) next())) {
TClass *clBase = base->GetClassPointer();
if (clBase) {
f = clBase->FindClassOrBaseMethodWithId(declId);
if (f) return (TMethod*)f;
}
}
return 0;
}
TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto,
Bool_t objectIsConst ,
ROOT::EFunctionMatchMode mode )
{
if (fCanLoadClassInfo) LoadClassInfo();
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetMethodWithPrototype", "gInterpreter not initialized");
TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
method, proto,
objectIsConst, mode);
if (!decl) return 0;
TMethod* f = FindClassOrBaseMethodWithId(decl);
if (f) return f;
Error("GetMethodWithPrototype",
"\nDid not find matching TMethod <%s> with \"%s\" %sfor %s",
method,proto,objectIsConst ? "const " : "", GetName());
return 0;
}
TMethod *TClass::GetClassMethod(Long_t faddr)
{
if (!HasInterpreterInfo()) return 0;
TMethod *m;
TIter next(GetListOfMethods());
while ((m = (TMethod *) next())) {
if (faddr == (Long_t)m->InterfaceMethod())
return m;
}
return 0;
}
TMethod *TClass::GetClassMethod(const char *name, const char* params,
Bool_t objectIsConst )
{
if (fCanLoadClassInfo) LoadClassInfo();
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetClassMethod", "gInterpreter not initialized");
TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithValues(fClassInfo,
name, params,
objectIsConst);
if (!decl) return 0;
TFunction *f = GetMethodList()->Get(decl);
return (TMethod*)f;
}
TMethod *TClass::GetClassMethodWithPrototype(const char *name, const char* proto,
Bool_t objectIsConst ,
ROOT::EFunctionMatchMode mode )
{
if (fCanLoadClassInfo) LoadClassInfo();
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetClassMethodWithPrototype", "gInterpreter not initialized");
TInterpreter::DeclId_t decl = gInterpreter->GetFunctionWithPrototype(fClassInfo,
name, proto,
objectIsConst,
mode);
if (!decl) return 0;
TFunction *f = GetMethodList()->Get(decl);
return (TMethod*)f;
}
Int_t TClass::GetNdata()
{
if (!HasDataMemberInfo()) return 0;
TList *lm = GetListOfDataMembers();
if (lm)
return lm->GetSize();
else
return 0;
}
Int_t TClass::GetNmethods()
{
if (!HasInterpreterInfo()) return 0;
TList *lm = GetListOfMethods();
if (lm)
return lm->GetSize();
else
return 0;
}
TVirtualStreamerInfo* TClass::GetStreamerInfo(Int_t version ) const
{
TVirtualStreamerInfo *guess = fLastReadInfo;
if (guess && guess->GetClassVersion() == version) {
return guess;
}
R__LOCKGUARD(gInterpreterMutex);
if (version == 0) {
version = fClassVersion;
}
if (!fStreamerInfo) {
TMmallocDescTemp setreset;
fStreamerInfo = new TObjArray(version + 10, -2);
} else {
Int_t ninfos = fStreamerInfo->GetSize();
if ((version < -1) || (version >= ninfos)) {
Error("GetStreamerInfo", "class: %s, attempting to access a wrong version: %d", GetName(), version);
version = 0;
}
}
TVirtualStreamerInfo* sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
if (!sinfo && (version != fClassVersion)) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(fClassVersion);
}
if (!sinfo) {
TMmallocDescTemp setreset;
sinfo = TVirtualStreamerInfo::Factory()->NewInfo(const_cast<TClass*>(this));
fStreamerInfo->AddAtAndExpand(sinfo, fClassVersion);
if (gDebug > 0) {
printf("Creating StreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
}
if (HasDataMemberInfo() || fCollectionProxy) {
sinfo->Build();
}
} else {
if (!sinfo->IsCompiled()) {
sinfo->BuildOld();
}
}
if (version == fClassVersion) {
fCurrentInfo = sinfo;
}
if (sinfo->IsCompiled()) fLastReadInfo = sinfo;
return sinfo;
}
TVirtualStreamerInfo* TClass::GetStreamerInfoAbstractEmulated(Int_t version ) const
{
R__LOCKGUARD(gInterpreterMutex);
TString newname( GetName() );
newname += "@@emulated";
TClass *emulated = TClass::GetClass(newname);
TVirtualStreamerInfo* sinfo = 0;
if (emulated) {
sinfo = emulated->GetStreamerInfo(version);
}
if (!sinfo) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(version);
if (!sinfo && (version != fClassVersion)) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(fClassVersion);
}
if (!sinfo) {
Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->UncheckedAt(i);
}
}
if (sinfo) {
sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
if (sinfo) {
sinfo->SetClass(0);
sinfo->SetName( newname );
sinfo->BuildCheck();
sinfo->BuildOld();
sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
} else
Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
}
}
return sinfo;
}
TVirtualStreamerInfo* TClass::FindStreamerInfoAbstractEmulated(UInt_t checksum) const
{
R__LOCKGUARD(gInterpreterMutex);
TString newname( GetName() );
newname += "@@emulated";
TClass *emulated = TClass::GetClass(newname);
TVirtualStreamerInfo* sinfo = 0;
if (emulated) {
sinfo = emulated->FindStreamerInfo(checksum);
}
if (!sinfo) {
sinfo = (TVirtualStreamerInfo*) FindStreamerInfo(checksum);
if (!sinfo && (checksum != fCheckSum)) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->At(fClassVersion);
}
if (!sinfo) {
Int_t ninfos = fStreamerInfo->GetEntriesFast() - 1;
for (Int_t i = -1; sinfo == 0 && i < ninfos; ++i) {
sinfo = (TVirtualStreamerInfo*) fStreamerInfo->UncheckedAt(i);
}
}
if (sinfo) {
sinfo = dynamic_cast<TVirtualStreamerInfo*>( sinfo->Clone() );
if (sinfo) {
sinfo->SetClass(0);
sinfo->SetName( newname );
sinfo->BuildCheck();
sinfo->BuildOld();
sinfo->GetClass()->AddRule(TString::Format("sourceClass=%s targetClass=%s",GetName(),newname.Data()));
} else
Error("GetStreamerInfoAbstractEmulated", "could not create TVirtualStreamerInfo");
}
}
return sinfo;
}
void TClass::IgnoreTObjectStreamer(Bool_t doIgnore)
{
R__LOCKGUARD2(gInterpreterMutex);
if ( doIgnore && TestBit(kIgnoreTObjectStreamer)) return;
if (!doIgnore && !TestBit(kIgnoreTObjectStreamer)) return;
TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
if (sinfo) {
if (sinfo->IsCompiled()) {
Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
return;
}
}
if (doIgnore) SetBit (kIgnoreTObjectStreamer);
else ResetBit(kIgnoreTObjectStreamer);
}
Bool_t TClass::InheritsFrom(const char *classname) const
{
if (strcmp(GetName(), classname) == 0) return kTRUE;
return InheritsFrom(TClass::GetClass(classname,kTRUE,kTRUE));
}
Bool_t TClass::InheritsFrom(const TClass *cl) const
{
if (!cl) return kFALSE;
if (cl == this) return kTRUE;
if (!HasDataMemberInfo()) {
TVirtualStreamerInfo *sinfo = ((TClass *)this)->GetCurrentStreamerInfo();
if (sinfo==0) sinfo = GetStreamerInfo();
TIter next(sinfo->GetElements());
TStreamerElement *element;
while ((element = (TStreamerElement*)next())) {
if (element->IsA() == TStreamerBase::Class()) {
TClass *clbase = element->GetClassPointer();
if (!clbase) return kFALSE;
if (clbase->InheritsFrom(cl)) return kTRUE;
}
}
return kFALSE;
}
if (((TClass *)this)->GetBaseClass(cl)) return kTRUE;
return kFALSE;
}
void *TClass::DynamicCast(const TClass *cl, void *obj, Bool_t up)
{
if (cl == this) return obj;
if (!HasDataMemberInfo()) return 0;
Int_t off;
if ((off = GetBaseClassOffset(cl)) != -1) {
if (up)
return (void*)((Long_t)obj+off);
else
return (void*)((Long_t)obj-off);
}
return 0;
}
const void *TClass::DynamicCast(const TClass *cl, const void *obj, Bool_t up)
{
return DynamicCast(cl,const_cast<void*>(obj),up);
}
void *TClass::New(ENewType defConstructor, Bool_t quiet) const
{
void* p = 0;
if (fNew) {
TClass__GetCallingNew() = defConstructor;
p = fNew(0);
TClass__GetCallingNew() = kRealNew;
if (!p && !quiet) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (HasInterpreterInfo()) {
TClass__GetCallingNew() = defConstructor;
p = gCling->ClassInfo_New(GetClassInfo());
TClass__GetCallingNew() = kRealNew;
if (!p && !quiet) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!HasInterpreterInfo() && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->New();
TClass__GetCallingNew() = kRealNew;
if (!p && !quiet) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
if(statsave) {
SetObjectStat(kFALSE);
}
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo && !quiet) {
Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
return 0;
}
TClass__GetCallingNew() = defConstructor;
p = sinfo->New();
TClass__GetCallingNew() = kRealNew;
if(statsave) {
SetObjectStat(statsave);
}
if (p) {
RegisterAddressInRepository("New",p,this);
} else {
Error("New", "Failed to construct class '%s' using streamer info", GetName());
}
} else {
Fatal("New", "This cannot happen!");
}
return p;
}
void *TClass::New(void *arena, ENewType defConstructor) const
{
void* p = 0;
if (fNew) {
TClass__GetCallingNew() = defConstructor;
p = fNew(arena);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (HasInterpreterInfo()) {
TClass__GetCallingNew() = defConstructor;
p = gCling->ClassInfo_New(GetClassInfo(),arena);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (!HasInterpreterInfo() && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->New(arena);
TClass__GetCallingNew() = kRealNew;
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
if(statsave) {
SetObjectStat(kFALSE);
}
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
Error("New with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
return 0;
}
TClass__GetCallingNew() = defConstructor;
p = sinfo->New(arena);
TClass__GetCallingNew() = kRealNew;
if(statsave) {
SetObjectStat(statsave);
}
if (p) {
RegisterAddressInRepository("TClass::New with placement",p,this);
}
} else {
Error("New with placement", "This cannot happen!");
}
return p;
}
void *TClass::NewArray(Long_t nElements, ENewType defConstructor) const
{
void* p = 0;
if (fNewArray) {
TClass__GetCallingNew() = defConstructor;
p = fNewArray(nElements, 0);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
}
} else if (HasInterpreterInfo()) {
TClass__GetCallingNew() = defConstructor;
p = gCling->ClassInfo_New(GetClassInfo(),nElements);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
}
} else if (!HasInterpreterInfo() && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->NewArray(nElements);
TClass__GetCallingNew() = kRealNew;
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
if(statsave) {
SetObjectStat(kFALSE);
}
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
return 0;
}
TClass__GetCallingNew() = defConstructor;
p = sinfo->NewArray(nElements);
TClass__GetCallingNew() = kRealNew;
if(statsave) {
SetObjectStat(statsave);
}
if (p) {
RegisterAddressInRepository("TClass::NewArray",p,this);
}
} else {
Error("NewArray", "This cannot happen!");
}
return p;
}
void *TClass::NewArray(Long_t nElements, void *arena, ENewType defConstructor) const
{
void* p = 0;
if (fNewArray) {
TClass__GetCallingNew() = defConstructor;
p = fNewArray(nElements, arena);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (HasInterpreterInfo()) {
TClass__GetCallingNew() = defConstructor;
p = gCling->ClassInfo_New(GetClassInfo(),nElements, arena);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (!HasInterpreterInfo() && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->NewArray(nElements, arena);
TClass__GetCallingNew() = kRealNew;
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
if(statsave) {
SetObjectStat(kFALSE);
}
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
Error("NewArray with placement", "Cannot construct class '%s' version %d at address %p, no streamer info available!", GetName(), fClassVersion, arena);
return 0;
}
TClass__GetCallingNew() = defConstructor;
p = sinfo->NewArray(nElements, arena);
TClass__GetCallingNew() = kRealNew;
if(statsave) {
SetObjectStat(statsave);
}
if (fStreamerType & kEmulatedStreamer) {
}
if (p) {
RegisterAddressInRepository("TClass::NewArray with placement",p,this);
}
} else {
Error("NewArray with placement", "This cannot happen!");
}
return p;
}
void TClass::Destructor(void *obj, Bool_t dtorOnly)
{
if (obj == 0) return;
void* p = obj;
if (dtorOnly && fDestructor) {
fDestructor(p);
} else if ((!dtorOnly) && fDelete) {
fDelete(p);
} else if (HasInterpreterInfo()) {
if (dtorOnly) {
gCling->ClassInfo_Destruct(fClassInfo,p);
} else {
gCling->ClassInfo_Delete(fClassInfo,p);
}
} else if (!HasInterpreterInfo() && fCollectionProxy) {
fCollectionProxy->Destructor(p, dtorOnly);
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t inRepo = kTRUE;
Bool_t verFound = kFALSE;
std::multiset<Version_t> knownVersions;
R__LOCKGUARD2(gOVRMutex);
{
RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
if (iter == gObjectVersionRepository.end()) {
inRepo = kFALSE;
} else {
for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
Version_t ver = iter->second.fVersion;
knownVersions.insert(ver);
if (ver == fClassVersion && this == iter->second.fClass) {
verFound = kTRUE;
}
}
}
}
if (!inRepo || verFound) {
TVirtualStreamerInfo* si = GetStreamerInfo();
if (si) {
si->Destructor(p, dtorOnly);
} else {
Error("Destructor", "No streamer info available for class '%s' version %d at address %p, cannot destruct emulated object!", GetName(), fClassVersion, p);
Error("Destructor", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
Int_t i = fStreamerInfo->LowerBound();
for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
Error("Destructor", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
if (fStreamerInfo->At(i) != 0) {
Error("Destructor", "Doing Dump() ...");
((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
}
}
}
} else {
Error("Destructor", "Loaded class %s version %d is not registered for addr %p", GetName(), fClassVersion, p);
#if 0
TVirtualStreamerInfo* si = (TVirtualStreamerInfo*) fStreamerInfo->At(objVer);
if (si) {
si->Destructor(p, dtorOnly);
} else {
Error("Destructor2", "No streamer info available for class '%s' version %d, cannot destruct object at addr: %p", GetName(), objVer, p);
Error("Destructor2", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
Int_t i = fStreamerInfo->LowerBound();
for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
Error("Destructor2", "fStreamerInfo->At(%d): %p", i, fStreamerInfo->At(i));
if (fStreamerInfo->At(i) != 0) {
Error("Destructor2", "Doing Dump() ...");
((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
}
}
}
#endif
}
if (inRepo && verFound && p) {
UnregisterAddressInRepository("TClass::Destructor",p,this);
}
} else {
Error("Destructor", "This cannot happen! (class %s)", GetName());
}
}
void TClass::DeleteArray(void *ary, Bool_t dtorOnly)
{
if (ary == 0) return;
void* p = ary;
if (fDeleteArray) {
if (dtorOnly) {
Error("DeleteArray", "Destructor only is not supported!");
} else {
fDeleteArray(ary);
}
} else if (HasInterpreterInfo()) {
gCling->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
} else if (!HasInterpreterInfo() && fCollectionProxy) {
fCollectionProxy->DeleteArray(ary, dtorOnly);
} else if (!HasInterpreterInfo() && !fCollectionProxy) {
Bool_t inRepo = kTRUE;
Bool_t verFound = kFALSE;
std::multiset<Version_t> knownVersions;
{
R__LOCKGUARD2(gOVRMutex);
RepoCont_t::iterator iter = gObjectVersionRepository.find(p);
if (iter == gObjectVersionRepository.end()) {
inRepo = kFALSE;
} else {
for (; (iter != gObjectVersionRepository.end()) && (iter->first == p); ++iter) {
Version_t ver = iter->second.fVersion;
knownVersions.insert(ver);
if (ver == fClassVersion && this == iter->second.fClass ) {
verFound = kTRUE;
}
}
}
}
if (!inRepo || verFound) {
TVirtualStreamerInfo* si = GetStreamerInfo();
if (si) {
si->DeleteArray(ary, dtorOnly);
} else {
Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), fClassVersion, ary);
Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
Int_t i = fStreamerInfo->LowerBound();
for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
if (fStreamerInfo->At(i)) {
Error("DeleteArray", "Doing Dump() ...");
((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
}
}
}
} else {
Error("DeleteArray", "Loaded class version %d is not registered for addr %p", fClassVersion, p);
#if 0
TVirtualStreamerInfo* si = (TVirtualStreamerInfo*) fStreamerInfo->At(objVer);
if (si) {
si->DeleteArray(ary, dtorOnly);
} else {
Error("DeleteArray", "No streamer info available for class '%s' version %d at address %p, cannot destruct object!", GetName(), objVer, ary);
Error("DeleteArray", "length of fStreamerInfo is %d", fStreamerInfo->GetSize());
Int_t i = fStreamerInfo->LowerBound();
for (Int_t v = 0; v < fStreamerInfo->GetSize(); ++v, ++i) {
Error("DeleteArray", "fStreamerInfo->At(%d): %p", v, fStreamerInfo->At(i));
if (fStreamerInfo->At(i)) {
Error("DeleteArray", "Doing Dump() ...");
((TVirtualStreamerInfo*)fStreamerInfo->At(i))->Dump();
}
}
}
#endif
}
if (inRepo && verFound && p) {
UnregisterAddressInRepository("TClass::DeleteArray",p,this);
}
} else {
Error("DeleteArray", "This cannot happen! (class '%s')", GetName());
}
}
void TClass::SetCanSplit(Int_t splitmode)
{
fCanSplit = splitmode;
}
void TClass::SetClassVersion(Version_t version)
{
fClassVersion = version;
fCurrentInfo = 0;
}
TVirtualStreamerInfo* TClass::DetermineCurrentStreamerInfo()
{
R__LOCKGUARD2(gInterpreterMutex);
if(!fCurrentInfo.load()) {
fCurrentInfo=(TVirtualStreamerInfo*)(fStreamerInfo->At(fClassVersion));
}
return fCurrentInfo;
}
void TClass::SetCurrentStreamerInfo(TVirtualStreamerInfo *info)
{
fCurrentInfo = info;
}
Int_t TClass::Size() const
{
if (fSizeof!=-1) return fSizeof;
if (fCollectionProxy) return fCollectionProxy->Sizeof();
if (HasInterpreterInfo()) return gCling->ClassInfo_Size(GetClassInfo());
return GetStreamerInfo()->GetSize();
}
TClass *TClass::Load(TBuffer &b)
{
UInt_t maxsize = 256;
char *s = new char[maxsize];
Int_t pos = b.Length();
b.ReadString(s, maxsize);
while (strlen(s) == (maxsize - 1)) {
b.SetBufferOffset(pos);
maxsize = 2*maxsize;
delete [] s;
s = new char[maxsize];
b.ReadString(s, maxsize);
}
TClass *cl = TClass::GetClass(s, kTRUE);
if (!cl)
::Error("TClass::Load", "dictionary of class %s not found", s);
delete [] s;
return cl;
}
TClass *TClass::LoadClass(const char *requestedname, Bool_t silent)
{
R__LOCKGUARD(gInterpreterMutex);
TClass *result = LoadClassDefault(requestedname, silent);
if (result) return result;
else return LoadClassCustom(requestedname,silent);
}
TClass *TClass::LoadClassDefault(const char *requestedname, Bool_t )
{
DictFuncPtr_t dict = TClassTable::GetDictNorm(requestedname);
if (!dict) {
if (gInterpreter->AutoLoad(requestedname,kTRUE)) {
dict = TClassTable::GetDictNorm(requestedname);
}
}
if (dict) {
TClass *ncl = (dict)();
if (ncl) ncl->PostLoadCheck();
return ncl;
}
return 0;
}
TClass *TClass::LoadClassCustom(const char *requestedname, Bool_t silent)
{
TIter next(gROOT->GetListOfClassGenerators());
TClassGenerator *gen;
while ((gen = (TClassGenerator*) next())) {
TClass *cl = gen->GetClass(requestedname, kTRUE, silent);
if (cl) {
cl->PostLoadCheck();
return cl;
}
}
return 0;
}
void TClass::LoadClassInfo() const
{
R__LOCKGUARD(gInterpreterMutex);
if (!fCanLoadClassInfo) return;
gInterpreter->AutoParse(GetName());
if (!fClassInfo) gInterpreter->SetClassInfo(const_cast<TClass*>(this));
if (!gInterpreter->IsAutoParsingSuspended()) {
if (!fClassInfo) {
::Error("TClass::LoadClassInfo",
"no interpreter information for class %s is available eventhough it has a TClass initialization routine.",
fName.Data());
}
fCanLoadClassInfo = kFALSE;
}
}
void TClass::Store(TBuffer &b) const
{
b.WriteString(GetName());
}
TClass *ROOT::CreateClass(const char *cname, Version_t id,
const type_info &info, TVirtualIsAProxy *isa,
const char *dfil, const char *ifil,
Int_t dl, Int_t il)
{
TMmallocDescTemp setreset;
return new TClass(cname, id, info, isa, dfil, ifil, dl, il);
}
TClass *ROOT::CreateClass(const char *cname, Version_t id,
const char *dfil, const char *ifil,
Int_t dl, Int_t il)
{
TMmallocDescTemp setreset;
return new TClass(cname, id, dfil, ifil, dl, il);
}
TClass::ENewType TClass::IsCallingNew()
{
return TClass__GetCallingNew();
}
Bool_t TClass::IsLoaded() const
{
return fState == kHasTClassInit;
}
Bool_t TClass::IsStartingWithTObject() const
{
if (fProperty==(-1)) Property();
return TestBit(kStartWithTObject);
}
Bool_t TClass::IsTObject() const
{
if (fProperty==(-1)) Property();
return TestBit(kIsTObject);
}
Bool_t TClass::IsForeign() const
{
if (fProperty==(-1)) Property();
return TestBit(kIsForeign);
}
void TClass::PostLoadCheck()
{
if (IsLoaded() && HasInterpreterInfo() && fClassVersion==1 && IsForeign() )
{
SetClassVersion(-1);
}
else if (IsLoaded() && HasDataMemberInfo() && fStreamerInfo && (!IsForeign()||fClassVersion>1) )
{
R__LOCKGUARD(gInterpreterMutex);
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)(fStreamerInfo->At(fClassVersion));
if (info && GetListOfDataMembers() && !GetCollectionProxy()
&& (info->GetCheckSum()!=GetCheckSum() && !info->CompareContent(this,0,kFALSE,kFALSE, 0) && !(MatchLegacyCheckSum(info->GetCheckSum()))))
{
Bool_t warn = ! TestBit(kWarned);
if (warn && info->GetOldVersion()<=2) {
TIter nextBC(GetListOfBases());
TBaseClass *bc;
while ((bc=(TBaseClass*)nextBC()))
{if (TClassEdit::IsSTLCont(bc->GetName())) warn = kFALSE;}
}
if (warn) {
if (info->GetOnFileClassVersion()==1 && fClassVersion>1) {
Warning("PostLoadCheck","\n\
The class %s transitioned from not having a specified class version\n\
to having a specified class version (the current class version is %d).\n\
However too many different non-versioned layouts of the class have\n\
already been loaded so far. To work around this problem you can\n\
load fewer 'old' file in the same ROOT session or load the C++ library\n\
describing the class %s before opening the files or increase the version\n\
number of the class for example ClassDef(%s,%d).\n\
Do not try to write objects with the current class definition,\n\
the files might not be readable.\n",
GetName(), fClassVersion, GetName(), GetName(), fStreamerInfo->GetLast()+1);
} else {
Warning("PostLoadCheck","\n\
The StreamerInfo version %d for the class %s which was read\n\
from a file previously opened has the same version as the active class\n\
but a different checksum. You should update the version to ClassDef(%s,%d).\n\
Do not try to write objects with the current class definition,\n\
the files will not be readable.\n"
, fClassVersion, GetName(), GetName(), fStreamerInfo->GetLast()+1);
}
info->CompareContent(this,0,kTRUE,kTRUE,0);
SetBit(kWarned);
}
}
}
}
Long_t TClass::Property() const
{
R__LOCKGUARD(gInterpreterMutex);
if (fProperty!=(-1)) return fProperty;
if (TestBit(kLoading)) return fProperty;
TMmallocDescTemp setreset;
TClass *kl = const_cast<TClass*>(this);
kl->fStreamerType = TClass::kDefault;
kl->fStreamerImpl = &TClass::StreamerDefault;
if (InheritsFrom(TObject::Class())) {
kl->SetBit(kIsTObject);
Int_t delta = kl->GetBaseClassOffsetRecurse(TObject::Class());
if (delta==0) kl->SetBit(kStartWithTObject);
kl->fStreamerType = kTObject;
kl->fStreamerImpl = &TClass::StreamerTObject;
}
if (HasInterpreterInfo()) {
if (!const_cast<TClass*>(this)->GetClassMethodWithPrototype("Streamer","TBuffer&",kFALSE)) {
kl->SetBit(kIsForeign);
kl->fStreamerType = kForeign;
kl->fStreamerImpl = &TClass::StreamerStreamerInfo;
} else if ( kl->fStreamerType == TClass::kDefault ) {
if (kl->fConvStreamerFunc) {
kl->fStreamerType = kInstrumented;
kl->fStreamerImpl = &TClass::ConvStreamerInstrumented;
} else if (kl->fStreamerFunc) {
kl->fStreamerType = kInstrumented;
kl->fStreamerImpl = &TClass::StreamerInstrumented;
} else {
kl->fStreamerType = kInstrumented;
kl->fStreamerImpl = &TClass::StreamerStreamerInfo;
}
}
if (fStreamer) {
kl->fStreamerType = kExternal;
kl->fStreamerImpl = &TClass::StreamerExternal;
}
kl->fClassProperty = gCling->ClassInfo_ClassProperty(GetClassInfo());
kl->fProperty = gCling->ClassInfo_Property(fClassInfo);
} else {
if (fStreamer) {
kl->fStreamerType = kExternal;
kl->fStreamerImpl = &TClass::StreamerExternal;
}
kl->fStreamerType |= kEmulatedStreamer;
kl->SetStreamerImpl();
return 0;
}
return fProperty;
}
void TClass::SetStreamerImpl()
{
switch (fStreamerType) {
case kTObject: fStreamerImpl = &TClass::StreamerTObject; break;
case kForeign: fStreamerImpl = &TClass::StreamerStreamerInfo; break;
case kExternal: fStreamerImpl = &TClass::StreamerExternal; break;
case kInstrumented: {
if (fConvStreamerFunc) fStreamerImpl = &TClass::ConvStreamerInstrumented;
else if (fStreamerFunc) fStreamerImpl = &TClass::StreamerInstrumented;
else fStreamerImpl = &TClass::StreamerStreamerInfo;
break;
}
case kEmulatedStreamer:
case kForeign|kEmulatedStreamer:
case kInstrumented|kEmulatedStreamer: fStreamerImpl = &TClass::StreamerStreamerInfo; break;
case kExternal|kEmulatedStreamer: fStreamerImpl = &TClass::StreamerExternal; break;
case kTObject|kEmulatedStreamer: fStreamerImpl = &TClass::StreamerTObjectEmulated; break;
case TClass::kDefault: fStreamerImpl = &TClass::StreamerDefault; break;
default:
Error("SetStreamerImpl","Unexpected value of fStreamerType: %d",fStreamerType);
}
}
void TClass::SetCollectionProxy(const ROOT::TCollectionProxyInfo &info)
{
R__LOCKGUARD(gInterpreterMutex);
delete fCollectionProxy;
TVirtualCollectionProxy *p = TVirtualStreamerInfo::Factory()->GenExplicitProxy(info,this);
fCollectionProxy = p;
AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
if (fCollectionProxy && !fSchemaRules) {
GetSchemaRules(kTRUE);
}
fCanSplit = -1;
}
void TClass::SetContextMenuTitle(const char *title)
{
fContextMenuTitle = title;
}
void TClass::SetGlobalIsA(IsAGlobalFunc_t func)
{
fGlobalIsA = func;
}
void TClass::SetUnloaded()
{
if (TestBit(kUnloaded) && !TestBit(kUnloading)) {
return;
}
SetBit(kUnloading);
if (fState != kLoaded) {
Fatal("SetUnloaded","The TClass for %s is being unloaded when in state %d\n",
GetName(),(int)fState);
}
fState = kForwardDeclared;
delete fIsA; fIsA = 0;
{
int autoload_old = gCling->SetClassAutoloading(0);
TInterpreter::SuspendAutoParsing autoParseRaii(gCling);
gInterpreter->SetClassInfo(this,kTRUE);
gCling->SetClassAutoloading(autoload_old);
}
fDeclFileName = 0;
fDeclFileLine = 0;
fImplFileName = 0;
fImplFileLine = 0;
fTypeInfo = 0;
if (fMethod) {
(*fMethod).Unload();
}
if (fData) {
fData->Unload();
}
if (fEnums) {
(*fEnums).Unload();
}
if (fState <= kForwardDeclared && fStreamerInfo->GetEntries() != 0) {
fState = kEmulated;
}
ResetBit(kUnloading);
SetBit(kUnloaded);
}
TVirtualStreamerInfo *TClass::SetStreamerInfo(Int_t , const char * )
{
return 0;
}
Bool_t TClass::MatchLegacyCheckSum(UInt_t checksum) const
{
for(UInt_t i = 1; i < kLatestCheckSum; ++i) {
if ( checksum == GetCheckSum( (ECheckSum) i ) ) return kTRUE;
}
return kFALSE;
}
UInt_t TClass::GetCheckSum(ECheckSum code) const
{
bool isvalid;
return GetCheckSum(code,isvalid);
}
UInt_t TClass::GetCheckSum(Bool_t &isvalid) const
{
return GetCheckSum(kCurrentCheckSum,isvalid);
}
UInt_t TClass::GetCheckSum(ECheckSum code, Bool_t &isvalid) const
{
R__LOCKGUARD(gInterpreterMutex);
isvalid = kTRUE;
if (fCheckSum && code == kCurrentCheckSum) return fCheckSum;
if (code == kCurrentCheckSum) code = kLatestCheckSum;
UInt_t id = 0;
int il;
TString name = GetName();
TString type;
il = name.Length();
for (int i=0; i<il; i++) id = id*3+name[i];
TList *tlb = ((TClass*)this)->GetListOfBases();
if (tlb && !GetCollectionProxy()) {
TIter nextBase(tlb);
TBaseClass *tbc=0;
while((tbc=(TBaseClass*)nextBase())) {
name = tbc->GetName();
Bool_t isSTL = TClassEdit::IsSTLCont(name);
if (isSTL)
name = TClassEdit::ShortType( name, TClassEdit::kDropStlDefault );
il = name.Length();
for (int i=0; i<il; i++) id = id*3+name[i];
if (code > kNoBaseCheckSum && !isSTL) {
if (tbc->GetClassPointer() == 0) {
Error("GetCheckSum","Calculating the checksum for (%s) requires the base class (%s) meta information to be available!",
GetName(),tbc->GetName());
isvalid = kFALSE;
return 0;
} else
id = id*3 + tbc->GetClassPointer()->GetCheckSum();
}
}
}
TList *tlm = ((TClass*)this)->GetListOfDataMembers();
if (tlm) {
TIter nextMemb(tlm);
TDataMember *tdm=0;
Long_t prop = 0;
while((tdm=(TDataMember*)nextMemb())) {
if (!tdm->IsPersistent()) continue;
prop = (tdm->Property());
TDataType* tdt = tdm->GetDataType();
if (tdt) prop |= tdt->Property();
if ( prop&kIsStatic) continue;
name = tdm->GetName(); il = name.Length();
if ( (code > kNoEnum) && code != kReflex && code != kReflexNoComment && prop&kIsEnum)
id = id*3 + 1;
int i;
for (i=0; i<il; i++) id = id*3+name[i];
if (code > kWithTypeDef || code == kReflexNoComment) {
type = tdm->GetTrueTypeName();
if (TClassEdit::IsSTLCont(type))
type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
if (code == kReflex || code == kReflexNoComment) {
if (prop&kIsEnum) {
type = "int";
} else {
type.ReplaceAll("ULong64_t","unsigned long long");
type.ReplaceAll("Long64_t","long long");
type.ReplaceAll("<signed char","<char");
type.ReplaceAll(",signed char",",char");
if (type=="signed char") type = "char";
}
}
} else {
type = tdm->GetFullTypeName();
if (TClassEdit::IsSTLCont(type))
type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
}
il = type.Length();
for (i=0; i<il; i++) id = id*3+type[i];
int dim = tdm->GetArrayDim();
if (prop&kIsArray) {
for (int ii=0;ii<dim;ii++) id = id*3+tdm->GetMaxIndex(ii);
}
if (code > kNoRange) {
const char *left;
if (code > TClass::kNoRangeCheck)
left = TVirtualStreamerInfo::GetElementCounterStart(tdm->GetTitle());
else
left = strstr(tdm->GetTitle(),"[");
if (left) {
const char *right = strstr(left,"]");
if (right) {
++left;
while (left != right) {
id = id*3 + *left;
++left;
}
}
}
}
}
}
if (code==kLatestCheckSum) fCheckSum = id;
return id;
}
void TClass::AdoptReferenceProxy(TVirtualRefProxy* proxy)
{
R__LOCKGUARD(gInterpreterMutex);
if ( fRefProxy ) {
fRefProxy->Release();
}
fRefProxy = proxy;
if ( fRefProxy ) {
fRefProxy->SetClass(this);
}
fCanSplit = -1;
}
void TClass::AdoptMemberStreamer(const char *name, TMemberStreamer *p)
{
if (!fRealData) return;
R__LOCKGUARD(gInterpreterMutex);
TIter next(fRealData);
TRealData *rd;
while ((rd = (TRealData*)next())) {
if (strcmp(rd->GetName(),name) == 0) {
rd->AdoptStreamer(p);
break;
}
}
return;
}
void TClass::SetMemberStreamer(const char *name, MemberStreamerFunc_t p)
{
AdoptMemberStreamer(name,new TMemberStreamer(p));
}
Int_t TClass::ReadBuffer(TBuffer &b, void *pointer, Int_t version, UInt_t start, UInt_t count)
{
return b.ReadClassBuffer(this,pointer,version,start,count);
}
Int_t TClass::ReadBuffer(TBuffer &b, void *pointer)
{
return b.ReadClassBuffer(this,pointer);
}
Int_t TClass::WriteBuffer(TBuffer &b, void *pointer, const char * )
{
b.WriteClassBuffer(this,pointer);
return 0;
}
void TClass::StreamerExternal(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
{
TClassStreamer *streamer = gThreadTsd ? pThis->GetStreamer() : pThis->fStreamer;
streamer->Stream(b,object,onfile_class);
}
void TClass::StreamerTObject(const TClass* pThis, void *object, TBuffer &b, const TClass * )
{
if (!pThis->fIsOffsetStreamerSet) {
pThis->CalculateStreamerOffset();
}
TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
tobj->Streamer(b);
}
void TClass::StreamerTObjectInitialized(const TClass* pThis, void *object, TBuffer &b, const TClass * )
{
TObject *tobj = (TObject*)((Long_t)object + pThis->fOffsetStreamer);
tobj->Streamer(b);
}
void TClass::StreamerTObjectEmulated(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
{
if (b.IsReading()) {
b.ReadClassEmulated(pThis, object, onfile_class);
} else {
b.WriteClassBuffer(pThis, object);
}
}
void TClass::StreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass * )
{
pThis->fStreamerFunc(b,object);
}
void TClass::ConvStreamerInstrumented(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
{
pThis->fConvStreamerFunc(b,object,onfile_class);
}
void TClass::StreamerStreamerInfo(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
{
if (b.IsReading()) {
b.ReadClassBuffer(pThis, object, onfile_class);
} else {
b.WriteClassBuffer(pThis, object);
}
}
void TClass::StreamerDefault(const TClass* pThis, void *object, TBuffer &b, const TClass *onfile_class)
{
if (pThis->fProperty==(-1)) {
pThis->Property();
}
if (pThis->fStreamerImpl == &TClass::StreamerDefault) {
pThis->Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", pThis->fStreamerType);
} else {
(*pThis->fStreamerImpl)(pThis,object,b,onfile_class);
}
}
void TClass::AdoptStreamer(TClassStreamer *str)
{
R__LOCKGUARD(gInterpreterMutex);
if (fStreamer) delete fStreamer;
if (str) {
fStreamerType = kExternal | ( fStreamerType&kEmulatedStreamer );
fStreamer = str;
fStreamerImpl = &TClass::StreamerExternal;
} else if (fStreamer) {
fStreamer = str;
fStreamerType = TClass::kDefault;
if (fProperty != -1) {
fProperty = -1;
Property();
}
}
}
void TClass::SetStreamerFunc(ClassStreamerFunc_t strm)
{
R__LOCKGUARD(gInterpreterMutex);
if (fProperty != -1 && !fConvStreamerFunc &&
( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) )
{
fStreamerFunc = strm;
if (HasInterpreterInfo() && fStreamerType != kTObject && !fStreamer) {
fStreamerType = kInstrumented;
fStreamerImpl = &TClass::StreamerInstrumented;
}
} else {
fStreamerFunc = strm;
}
fCanSplit = -1;
}
void TClass::SetConvStreamerFunc(ClassConvStreamerFunc_t strm)
{
R__LOCKGUARD(gInterpreterMutex);
if (fProperty != -1 &&
( (fConvStreamerFunc == 0 && strm != 0) || (fConvStreamerFunc != 0 && strm == 0) ) )
{
fConvStreamerFunc = strm;
if (HasInterpreterInfo() && fStreamerType != kTObject && !fStreamer) {
fStreamerType = kInstrumented;
fStreamerImpl = &TClass::ConvStreamerInstrumented;
}
} else {
fConvStreamerFunc = strm;
}
fCanSplit = -1;
}
void TClass::SetMerge(ROOT::MergeFunc_t newMerge)
{
fMerge = newMerge;
}
void TClass::SetResetAfterMerge(ROOT::ResetAfterMergeFunc_t newReset)
{
fResetAfterMerge = newReset;
}
void TClass::SetNew(ROOT::NewFunc_t newFunc)
{
fNew = newFunc;
}
void TClass::SetNewArray(ROOT::NewArrFunc_t newArrayFunc)
{
fNewArray = newArrayFunc;
}
void TClass::SetDelete(ROOT::DelFunc_t deleteFunc)
{
fDelete = deleteFunc;
}
void TClass::SetDeleteArray(ROOT::DelArrFunc_t deleteArrayFunc)
{
fDeleteArray = deleteArrayFunc;
}
void TClass::SetDestructor(ROOT::DesFunc_t destructorFunc)
{
fDestructor = destructorFunc;
}
void TClass::SetDirectoryAutoAdd(ROOT::DirAutoAdd_t autoAddFunc)
{
fDirAutoAdd = autoAddFunc;
}
TVirtualStreamerInfo *TClass::FindStreamerInfo(UInt_t checksum) const
{
TVirtualStreamerInfo *guess = fLastReadInfo;
if (guess && guess->GetCheckSum() == checksum) {
return guess;
} else {
if (fCheckSum == checksum) return GetStreamerInfo();
R__LOCKGUARD(gInterpreterMutex);
Int_t ninfos = fStreamerInfo->GetEntriesFast()-1;
for (Int_t i=-1;i<ninfos;++i) {
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)fStreamerInfo->UncheckedAt(i);
if (info && info->GetCheckSum() == checksum) {
info->BuildOld();
if (info->IsCompiled()) fLastReadInfo = info;
return info;
}
}
return 0;
}
}
TVirtualStreamerInfo *TClass::FindStreamerInfo(TObjArray* arr, UInt_t checksum) const
{
R__LOCKGUARD(gInterpreterMutex);
Int_t ninfos = arr->GetEntriesFast()-1;
for (Int_t i=-1;i<ninfos;i++) {
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)arr->UncheckedAt(i);
if (!info) continue;
if (info->GetCheckSum() == checksum) {
R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
return info;
}
}
return 0;
}
TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const char* classname, Int_t version ) const
{
TClass *cl = TClass::GetClass( classname );
if( !cl )
return 0;
return GetConversionStreamerInfo( cl, version );
}
TVirtualStreamerInfo *TClass::GetConversionStreamerInfo( const TClass* cl, Int_t version ) const
{
if( !cl )
return 0;
if( cl == this )
return GetStreamerInfo( version );
TObjArray* arr = 0;
if (fConversionStreamerInfo.load()) {
std::map<std::string, TObjArray*>::iterator it;
R__LOCKGUARD(gInterpreterMutex);
it = (*fConversionStreamerInfo).find( cl->GetName() );
if( it != (*fConversionStreamerInfo).end() ) {
arr = it->second;
}
if( arr && version > -1 && version < arr->GetSize() && arr->At( version ) )
return (TVirtualStreamerInfo*) arr->At( version );
}
R__LOCKGUARD(gInterpreterMutex);
const TObjArray *clSI = cl->GetStreamerInfos();
TVirtualStreamerInfo* info = 0;
if( version >= -1 && version < clSI->GetSize() )
info = (TVirtualStreamerInfo*)clSI->At( version );
if (!info && cl->GetCollectionProxy()) {
info = cl->GetStreamerInfo();
}
if( !info )
return 0;
info = (TVirtualStreamerInfo*)info->Clone();
if( !info->BuildFor( this ) ) {
delete info;
return 0;
}
if (!info->IsCompiled()) {
info->BuildOld();
}
if (!arr) {
arr = new TObjArray(version+10, -1);
if (!fConversionStreamerInfo.load()) {
fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
}
(*fConversionStreamerInfo)[cl->GetName()] = arr;
}
arr->AddAtAndExpand( info, info->GetClassVersion() );
return info;
}
TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const char* classname, UInt_t checksum ) const
{
TClass *cl = TClass::GetClass( classname );
if( !cl )
return 0;
return FindConversionStreamerInfo( cl, checksum );
}
TVirtualStreamerInfo *TClass::FindConversionStreamerInfo( const TClass* cl, UInt_t checksum ) const
{
if( !cl )
return 0;
if( cl == this )
return FindStreamerInfo( checksum );
TObjArray* arr = 0;
TVirtualStreamerInfo* info = 0;
if (fConversionStreamerInfo.load()) {
std::map<std::string, TObjArray*>::iterator it;
R__LOCKGUARD(gInterpreterMutex);
it = (*fConversionStreamerInfo).find( cl->GetName() );
if( it != (*fConversionStreamerInfo).end() ) {
arr = it->second;
}
if (arr) {
info = FindStreamerInfo( arr, checksum );
}
}
if( info )
return info;
R__LOCKGUARD(gInterpreterMutex);
info = cl->FindStreamerInfo( checksum );
if( !info )
return 0;
info = (TVirtualStreamerInfo*)info->Clone();
if( !info->BuildFor( this ) ) {
delete info;
return 0;
}
if (!info->IsCompiled()) {
info->BuildOld();
}
if (!arr) {
arr = new TObjArray(16, -2);
if (!fConversionStreamerInfo.load()) {
fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
}
(*fConversionStreamerInfo)[cl->GetName()] = arr;
}
arr->AddAtAndExpand( info, info->GetClassVersion() );
return info;
}
void TClass::RegisterStreamerInfo(TVirtualStreamerInfo *info)
{
if (info) {
R__LOCKGUARD(gInterpreterMutex);
Int_t slot = info->GetClassVersion();
if (fStreamerInfo->GetSize() > (slot-fStreamerInfo->LowerBound())
&& fStreamerInfo->At(slot) != 0
&& fStreamerInfo->At(slot) != info) {
Error("RegisterStreamerInfo",
"Register StreamerInfo for %s on non-empty slot (%d).",
GetName(),slot);
}
fStreamerInfo->AddAtAndExpand(info, slot);
if (fState <= kForwardDeclared) {
fState = kEmulated;
}
}
}
void TClass::RemoveStreamerInfo(Int_t slot)
{
if (fStreamerInfo->GetSize() >= slot) {
R__LOCKGUARD(gInterpreterMutex);
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)fStreamerInfo->At(slot);
fStreamerInfo->RemoveAt(fClassVersion);
delete info;
if (fState == kEmulated && fStreamerInfo->GetEntries() == 0) {
fState = kForwardDeclared;
}
}
}
Bool_t TClass::HasDefaultConstructor() const
{
if (fNew) return kTRUE;
if (HasInterpreterInfo()) {
R__LOCKGUARD(gInterpreterMutex);
return gCling->ClassInfo_HasDefaultConstructor(GetClassInfo());
}
if (fCollectionProxy) {
return kTRUE;
}
if (fCurrentInfo.load()) {
return kTRUE;
}
return kFALSE;
}
ROOT::MergeFunc_t TClass::GetMerge() const
{
return fMerge;
}
ROOT::ResetAfterMergeFunc_t TClass::GetResetAfterMerge() const
{
return fResetAfterMerge;
}
ROOT::NewFunc_t TClass::GetNew() const
{
return fNew;
}
ROOT::NewArrFunc_t TClass::GetNewArray() const
{
return fNewArray;
}
ROOT::DelFunc_t TClass::GetDelete() const
{
return fDelete;
}
ROOT::DelArrFunc_t TClass::GetDeleteArray() const
{
return fDeleteArray;
}
ROOT::DesFunc_t TClass::GetDestructor() const
{
return fDestructor;
}
ROOT::DirAutoAdd_t TClass::GetDirectoryAutoAdd() const
{
return fDirAutoAdd;
}