#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 "TError.h"
#include "TExMap.h"
#include "THashList.h"
#include "TInterpreter.h"
#include "TMemberInspector.h"
#include "TMethod.h"
#include "TMethodArg.h"
#include "TMethodCall.h"
#include "TObjArray.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>
using namespace std;
TVirtualMutex* gCINTMutex = 0;
void *gMmallocDesc = 0;
namespace {
class TMmallocDescTemp {
private:
void *fSave;
public:
TMmallocDescTemp(void *value = 0) : fSave(gMmallocDesc) { gMmallocDesc = value; }
~TMmallocDescTemp() { gMmallocDesc = fSave; }
};
}
#if __cplusplus >= 201103L
std::atomic<Int_t> TClass::fgClassCount;
#else
Int_t TClass::fgClassCount;
#endif
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
};
}
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
}
void TClass::AddClass(TClass *cl)
{
if (!cl) return;
R__LOCKGUARD2(gCINTMutex);
gROOT->GetListOfClasses()->Add(cl);
if (cl->GetTypeInfo()) {
GetIdMap()->Add(cl->GetTypeInfo()->name(),cl);
}
}
void TClass::RemoveClass(TClass *oldcl)
{
if (!oldcl) return;
R__LOCKGUARD2(gCINTMutex);
gROOT->GetListOfClasses()->Remove(oldcl);
if (oldcl->GetTypeInfo()) {
GetIdMap()->Remove(oldcl->GetTypeInfo()->name());
}
}
class TDumpMembers : public TMemberInspector {
public:
TDumpMembers() { }
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
};
void TDumpMembers::Inspect(TClass *cl, const char *pname, const char *mname, const void *add)
{
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;
TString memberTypeName;
const char *memberName;
const char *memberFullTypeName;
const char *memberTitle;
Bool_t isapointer;
Bool_t isbasic;
if (TDataMember *member = cl->GetDataMember(mname)) {
memberTypeName = member->GetTypeName();
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();
memberTypeName = memberFullTypeName;
memberTypeName = memberTypeName.Strip(TString::kTrailing, '*');
if (memberTypeName.Index("const ")==0) memberTypeName.Remove(0,6);
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 && strcmp(memberTypeName,"UInt_t") == 0) {
isdate = kTRUE;
}
Bool_t isbits = kFALSE;
if (strcmp(memberName,"fBits") == 0 && strcmp(memberTypeName,"UInt_t") == 0) {
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)
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 {
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 {
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;
THashTable* TClass::fgClassShortTypedefHash = 0;
TClass::TNameMapNode::TNameMapNode (const char* typedf, const char* orig)
: TObjString (typedf),
fOrigName (orig)
{
}
class TBuildRealData : public TMemberInspector {
private:
void *fRealDataObject;
TClass *fRealDataClass;
UInt_t fBits;
public:
TBuildRealData(void *obj, TClass *cl) : fBits(0) {
fRealDataObject = obj;
fRealDataClass = cl;
}
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
void SetBit(UInt_t f, Bool_t set);
void SetBit(UInt_t f) { fBits |= f & TObject::kBitMask; }
void ResetBit(UInt_t f) { fBits &= ~(f & TObject::kBitMask); }
Bool_t TestBit(UInt_t f) const { return (Bool_t) ((fBits & f) != 0); }
Int_t TestBits(UInt_t f) const { return (Int_t) (fBits & f); }
void InvertBit(UInt_t f) { fBits ^= f & TObject::kBitMask; }
};
void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add)
{
TDataMember* dm = cl->GetDataMember(mname);
if (!dm) {
return;
}
Bool_t isTransient = kFALSE;
if (!dm->IsPersistent()) {
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 (isTransient) { rd->SetBit(TRealData::kTransient); };
fRealDataClass->GetListOfRealData()->Add(rd);
} else {
TRealData* rd = new TRealData(rname, offset, dm);
if (isTransient) { rd->SetBit(TRealData::kTransient); };
fRealDataClass->GetListOfRealData()->Add(rd);
}
} else {
TRealData* rd = new TRealData(rname, offset, dm);
if (isTransient) { rd->SetBit(TRealData::kTransient); };
if (!dm->IsBasic()) {
rd->SetIsObject(kTRUE);
TClass* dmclass = TClass::GetClass(dm->GetTypeName(), kTRUE, isTransient || TestBit(TRealData::kTransient));
if (!dmclass) {
dmclass = TClass::GetClass(dm->GetTrueTypeName(), kTRUE, isTransient || TestBit(TRealData::kTransient));
}
if (dmclass) {
if (dmclass->Property()) {
if (dmclass->Property() & kIsAbstract) {
fprintf(stderr, "TBuildRealDataRecursive::Inspect(): data member class: '%s' is abstract.\n", dmclass->GetName());
}
}
if ((dmclass != cl) && !dm->IsaPointer()) {
if (dmclass->GetCollectionProxy()) {
TClass* valcl = dmclass->GetCollectionProxy()->GetValueClass();
if (valcl && !(valcl->Property() & kIsAbstract)) valcl->BuildRealData(0, isTransient || TestBit(TRealData::kTransient));
} else {
dmclass->BuildRealData(const_cast<void*>(add), isTransient || TestBit(TRealData::kTransient));
}
}
}
}
fRealDataClass->GetListOfRealData()->Add(rd);
}
}
class TAutoInspector : public TMemberInspector {
public:
Int_t fCount;
TBrowser *fBrowser;
TAutoInspector(TBrowser *b) {
fBrowser = b; fCount = 0; }
virtual ~TAutoInspector() { }
virtual void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
};
void TAutoInspector::Inspect(TClass *cl, const char *tit, const char *name,
const void *addr)
{
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 = gCint->DataMemberInfo_Factory(classInfo);
TString mname;
int found=0;
while (gCint->DataMemberInfo_Next(m)) {
mname = gCint->DataMemberInfo_Name(m);
mname.ReplaceAll("*","");
if ((found = (iname==mname))) break;
}
assert(found);
Long_t prop = gCint->DataMemberInfo_Property(m) | gCint->DataMemberInfo_TypeProperty(m);
if (prop & G__BIT_ISSTATIC) return;
if (prop & G__BIT_ISFUNDAMENTAL) return;
if (prop & G__BIT_ISENUM) return;
if (mname == "G__virtualinfo") return;
int size = sizeof(void*);
int nmax = 1;
if (prop & G__BIT_ISARRAY) {
for (int dim = 0; dim < gCint->DataMemberInfo_ArrayDim(m); dim++) nmax *= gCint->DataMemberInfo_MaxIndex(m,dim);
}
std::string clmName(TClassEdit::ShortType(gCint->DataMemberInfo_TypeName(m),
TClassEdit::kDropTrailStar) );
TClass * clm = TClass::GetClass(clmName.c_str());
R__ASSERT(clm);
if (!(prop&G__BIT_ISPOINTER)) {
size = clm->Size();
if (size==0) size = gCint->DataMemberInfo_TypeSize(m);
}
gCint->DataMemberInfo_Delete(m);
TVirtualCollectionProxy *proxy = clm->GetCollectionProxy();
for(int i=0; i<nmax; i++) {
char *ptr = (char*)addr + i*size;
void *obj = (prop&G__BIT_ISPOINTER) ? *((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), 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), fInterShowMembers(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), fSizeof(-1),
fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE),
fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gCINTMutex);
fDeclFileLine = -2;
}
TClass::TClass(const char *name, Bool_t silent) :
TDictionary(name),
fPersistentRef(0),
fStreamerInfo(0), fConversionStreamerInfo(0), fRealData(0),
fBase(0), fData(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), fInterShowMembers(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), fSizeof(-1),
fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE),
fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gCINTMutex);
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 (!fClassInfo) {
gInterpreter->InitializeDictionaries();
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(gCint->ClassInfo_Title(fClassInfo));
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), 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), fInterShowMembers(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), fSizeof(-1),
fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE),
fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gCINTMutex);
Init(name,cversion, 0, 0, 0, dfil, ifil, dl, il,silent);
SetBit(kUnloaded);
}
TClass::TClass(const char *name, Version_t cversion,
const type_info &info, TVirtualIsAProxy *isa,
ShowMembersFunc_t showmembers,
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), 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), fInterShowMembers(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), fSizeof(-1),
fCanSplit(-1), fProperty(0),fVersionUsed(kFALSE),
fIsOffsetStreamerSet(kFALSE), fOffsetStreamer(0), fStreamerType(TClass::kDefault),
fCurrentInfo(0), fLastReadInfo(0), fRefProxy(0),
fSchemaRules(0), fStreamerImpl(&TClass::StreamerDefault)
{
R__LOCKGUARD2(gCINTMutex);
Init(name, cversion, &info, isa, showmembers, dfil, ifil, dl, il, 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->GetStreamerInfos()->Clear();
oldcl->ReplaceWith(this);
delete oldcl;
}
void TClass::Init(const char *name, Version_t cversion,
const type_info *typeinfo, TVirtualIsAProxy *isa,
ShowMembersFunc_t showmembers,
const char *dfil, const char *ifil, Int_t dl, Int_t il,
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);
fShowMembers = showmembers;
fStreamerInfo = new TObjArray(fClassVersion+2+10,-1);
fProperty = -1;
ResetInstanceCount();
TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(fName.Data());
if (oldcl && oldcl->TestBit(kLoading)) {
return;
}
TClass **persistentRef = 0;
if (oldcl) {
#if __cplusplus >= 201103L
persistentRef = oldcl->fPersistentRef.exchange(0);
#else
persistentRef = oldcl->fPersistentRef;
oldcl->fPersistentRef = 0;
#endif
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->GetStreamerInfos()->Clear();
fSchemaRules = oldcl->fSchemaRules;
oldcl->fSchemaRules = 0;
}
SetBit(kLoading);
TClass::AddClass(this);
Bool_t isStl = TClassEdit::IsSTLCont(fName);
if (!fClassInfo) {
Bool_t shouldLoad = kFALSE;
if (gInterpreter->CheckClassInfo(fName)) shouldLoad = kTRUE;
else if (fImplFileLine>=0) {
shouldLoad = ! isStl;
}
if (shouldLoad) {
if (!gInterpreter)
::Fatal("TClass::TClass", "gInterpreter not initialized");
gInterpreter->SetClassInfo(this);
if (!fClassInfo) {
gInterpreter->InitializeDictionaries();
gInterpreter->SetClassInfo(this);
if (IsZombie()) {
TClass::RemoveClass(this);
return;
}
}
}
}
if (!silent && !fClassInfo && !isStl && fName.First('@')==kNPOS)
::Warning("TClass::TClass", "no dictionary for class %s is available", fName.Data());
fgClassCount++;
SetUniqueID(fgClassCount);
TString resolvedThis;
if (strchr (name, '<')) {
if ( fName != name) {
if (!fgClassTypedefHash) {
fgClassTypedefHash = new THashTable (100, 5);
fgClassTypedefHash->SetOwner (kTRUE);
}
fgClassTypedefHash->Add (new TNameMapNode (name, fName));
SetBit (kHasNameMapNode);
TString resolvedShort = TClassEdit::ResolveTypedef(fName, kTRUE);
if (resolvedShort != fName) {
fgClassShortTypedefHash->Add (new TNameMapNode (resolvedShort, fName));
}
}
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 (resolvedThis.Length() > 0 && fgClassTypedefHash) {
if (resolvedThis != fName) {
oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
if (oldcl && oldcl != this) {
#if __cplusplus >= 201103L
persistentRef = oldcl->fPersistentRef.exchange(0);
#else
persistentRef = oldcl->fPersistentRef;
oldcl->fPersistentRef = 0;
#endif
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) {
#if __cplusplus >= 201103L
persistentRef = oldcl->fPersistentRef.exchange(0);
#else
persistentRef = oldcl->fPersistentRef;
oldcl->fPersistentRef = 0;
#endif
ForceReload (oldcl);
}
}
}
if (fClassInfo) SetTitle(gCint->ClassInfo_Title(fClassInfo));
if (persistentRef) {
fPersistentRef = persistentRef;
} else {
fPersistentRef = new TClass*;
}
*fPersistentRef = this;
ResetBit(kLoading);
if ( isStl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
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);
}
}
TClass::TClass(const TClass& cl) :
TDictionary(cl),
fPersistentRef(0),
fStreamerInfo(cl.fStreamerInfo),
fConversionStreamerInfo(0),
fRealData(cl.fRealData),
fBase(cl.fBase),
fData(cl.fData),
fMethod(cl.fMethod),
fAllPubData(cl.fAllPubData),
fAllPubMethod(cl.fAllPubMethod),
fClassMenuList(0),
fDeclFileName(cl.fDeclFileName),
fImplFileName(cl.fImplFileName),
fDeclFileLine(cl.fDeclFileLine),
fImplFileLine(cl.fImplFileLine),
fInstanceCount(cl.fInstanceCount),
fOnHeap(cl.fOnHeap),
fCheckSum(cl.fCheckSum),
fCollectionProxy(cl.fCollectionProxy),
fClassVersion(cl.fClassVersion),
fClassInfo(cl.fClassInfo),
fContextMenuTitle(cl.fContextMenuTitle),
fTypeInfo(cl.fTypeInfo),
fShowMembers(cl.fShowMembers),
fInterShowMembers(0),
fStreamer(cl.fStreamer),
fSharedLibs(cl.fSharedLibs),
fIsA(cl.fIsA),
fGlobalIsA(cl.fGlobalIsA),
fIsAMethod(0),
fMerge(cl.fMerge),
fResetAfterMerge(cl.fResetAfterMerge),
fNew(cl.fNew),
fNewArray(cl.fNewArray),
fDelete(cl.fDelete),
fDeleteArray(cl.fDeleteArray),
fDestructor(cl.fDestructor),
fDirAutoAdd(cl.fDirAutoAdd),
fStreamerFunc(cl.fStreamerFunc),
fSizeof(cl.fSizeof),
fCanSplit(cl.fCanSplit),
fProperty(0),
fVersionUsed(),
fIsOffsetStreamerSet(cl.fIsOffsetStreamerSet),
fOffsetStreamer(cl.fOffsetStreamer),
fStreamerType(cl.fStreamerType),
fCurrentInfo(0),
fLastReadInfo(0),
fRefProxy(cl.fRefProxy),
fSchemaRules(cl.fSchemaRules),
fStreamerImpl(0)
{
R__ASSERT(0 );
}
TClass& TClass::operator=(const TClass& cl)
{
if(this!=&cl) {
R__ASSERT(0 );
}
return *this;
}
TClass::~TClass()
{
R__LOCKGUARD(gCINTMutex);
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;
}
}
}
if (fgClassShortTypedefHash && TestBit (kHasNameMapNode)) {
TString resolvedShort =
TClassEdit::ResolveTypedef
(TClassEdit::ShortType(GetName(),
TClassEdit::kDropStlDefault).c_str(),
kTRUE);
TIter next (fgClassShortTypedefHash->GetListForObject (resolvedShort));
while ( TNameMapNode* htmp = static_cast<TNameMapNode*> (next()) ) {
if (resolvedShort == htmp->String() && htmp->fOrigName == GetName()) {
fgClassShortTypedefHash->Remove (htmp);
delete htmp;
break;
}
}
}
delete fStreamer; fStreamer =0;
delete fAllPubData; fAllPubData =0;
delete fAllPubMethod; fAllPubMethod=0;
#if __cplusplus >= 201103L
delete fPersistentRef.load();
#else
delete fPersistentRef;
#endif
if (fBase)
fBase->Delete();
delete fBase; fBase=0;
if (fData)
fData->Delete();
delete fData; fData = 0;
if (fMethod)
fMethod->Delete();
delete fMethod; fMethod=0;
if (fRealData)
fRealData->Delete();
delete fRealData; fRealData=0;
if (fStreamerInfo)
fStreamerInfo->Delete();
delete fStreamerInfo; fStreamerInfo=0;
if (fDeclFileLine >= -1)
TClass::RemoveClass(this);
gCint->ClassInfo_Delete(fClassInfo);
fClassInfo=0;
if (fClassMenuList)
fClassMenuList->Delete();
delete fClassMenuList; fClassMenuList=0;
fIsOffsetStreamerSet=kFALSE;
#if __cplusplus >= 201103L
if (fInterShowMembers) gCint->CallFunc_Delete(fInterShowMembers.load());
#else
if (fInterShowMembers) gCint->CallFunc_Delete(fInterShowMembers);
#endif
if ( fIsA ) delete fIsA;
if ( fRefProxy ) fRefProxy->Release();
fRefProxy = 0;
delete fStreamer;
delete fCollectionProxy;
#if __cplusplus >= 201103L
delete fIsAMethod.load();
#else
delete fIsAMethod;
#endif
delete fSchemaRules;
if (fConversionStreamerInfo) {
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;
}
#if __cplusplus >= 201103L
delete fConversionStreamerInfo.load();
#else
delete fConversionStreamerInfo;
#endif
}
}
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 || !strlen(filename)) {
::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(gCINTMutex);
TClass *cl = TClass::GetClass( ruleobj->GetTargetClass() );
if (!cl) {
cl = new TClass(ruleobj->GetTargetClass(), 1, 0, 0, -1, -1, kTRUE);
cl->SetBit(TClass::kIsEmulation);
}
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(gCINTMutex);
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,0);
return insp.fCount;
}
return 0;
}
void TClass::Browse(TBrowser *b)
{
if (!fClassInfo) 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(gCINTMutex);
if (fRealData) {
return;
}
if (fClassVersion == 0) {
isTransient = kTRUE;
}
TMmallocDescTemp setreset;
if (!fClassInfo || TClassEdit::IsSTLCont(GetName(), 0) || TClassEdit::IsSTLBitset(GetName())) {
fRealData = new TList;
BuildEmulatedRealData("", 0, this);
return;
}
void* realDataObject = pointer;
if ((!pointer) && (Property() & kIsAbstract)) {
return;
}
if (!realDataObject) {
if (!strcmp(GetName(), "TROOT")) {
realDataObject = gROOT;
} else if (!strcmp(GetName(), "TGWin32")) {
realDataObject = gVirtualX;
} else if (!strcmp(GetName(), "TGQt")) {
realDataObject = gVirtualX;
} else {
realDataObject = New();
if (fRealData) {
Int_t delta = GetBaseClassOffset(TObject::Class());
if (delta >= 0) {
TObject* tobj = (TObject*) (((char*) realDataObject) + delta);
tobj->SetBit(kZombie);
delete tobj;
tobj = 0;
} else {
Destructor(realDataObject);
realDataObject = 0;
}
return;
}
}
}
if (realDataObject) {
fRealData = new TList;
TBuildRealData brd(realDataObject, this);
Bool_t wasTransient = brd.TestBit(TRealData::kTransient);
if (isTransient) {
brd.SetBit(TRealData::kTransient);
}
if ( ! CallShowMembers(realDataObject, brd) ) {
if ( brd.TestBit(TRealData::kTransient) ) {
delete fRealData;
fRealData = 0;
} else {
Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
}
}
if (isTransient && !wasTransient) {
brd.ResetBit(TRealData::kTransient);
}
TBaseClass* base = 0;
TIter next(GetListOfBases());
while ((base = (TBaseClass*) next())) {
if (base->IsSTLContainer()) {
continue;
}
TClass* c = base->GetClassPointer();
if (c) {
c->BuildRealData(((char*) realDataObject) + base->GetDelta(), isTransient);
}
}
}
if (!pointer && realDataObject && (realDataObject != gROOT) && (realDataObject != gVirtualX)) {
Int_t delta = GetBaseClassOffset(TObject::Class());
if (delta >= 0) {
TObject* tobj = (TObject*) (((char*) realDataObject) + delta);
tobj->SetBit(kZombie);
delete tobj;
tobj = 0;
} else {
Destructor(realDataObject);
realDataObject = 0;
}
}
}
void TClass::BuildEmulatedRealData(const char *name, Long_t offset, TClass *cl)
{
R__LOCKGUARD(gCINTMutex);
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(gCINTMutex);
if (!fIsOffsetStreamerSet && fClassInfo) {
TMmallocDescTemp setreset;
fIsOffsetStreamerSet = kTRUE;
fOffsetStreamer = const_cast<TClass*>(this)->GetBaseClassOffset(TObject::Class());
if (fStreamerType == kTObject) {
fStreamerImpl = &TClass::StreamerTObjectInitialized;
}
}
}
Bool_t TClass::CallShowMembers(void* obj, TMemberInspector &insp,
Int_t isATObject) const
{
if (fShowMembers) {
fShowMembers(obj, insp);
return kTRUE;
} else {
if (isATObject == -1 && IsLoaded()) {
isATObject = (Int_t) (InheritsFrom(TObject::Class()));
}
if (isATObject == 1) {
if (!fIsOffsetStreamerSet) {
CalculateStreamerOffset();
}
TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
realTObject->ShowMembers(insp);
return kTRUE;
} else if (fClassInfo) {
if (!fInterShowMembers) {
R__LOCKGUARD2(gCINTMutex);
if(!fInterShowMembers) {
CallFunc_t* ism = gCint->CallFunc_Factory();
Long_t offset = 0;
gCint->CallFunc_SetFuncProto(ism,fClassInfo,"ShowMembers", "TMemberInspector&", &offset);
if (fIsOffsetStreamerSet && offset != fOffsetStreamer) {
Error("CallShowMembers", "Logic Error: offset for Streamer() and ShowMembers() differ!");
fInterShowMembers = 0;
return kFALSE;
}
fInterShowMembers = ism;
}
}
void* interShowMembers = fInterShowMembers;
if (!gCint->CallFunc_IsValid(interShowMembers)) {
if (strcmp(GetName(), "string") == 0) {
return kTRUE;
}
return kFALSE;
} else {
R__LOCKGUARD2(gCINTMutex);
gCint->CallFunc_ResetArg(interShowMembers);
gCint->CallFunc_SetArg(interShowMembers,(Long_t) &insp);
void* address = (void*) (((Long_t) obj) + fOffsetStreamer);
gCint->CallFunc_Exec((CallFunc_t*)interShowMembers,address);
return kTRUE;
}
} else if (TVirtualStreamerInfo* sinfo = GetStreamerInfo()) {
sinfo->CallShowMembers(obj,insp);
return kTRUE;
}
}
return kFALSE;
}
void TClass::InterpretedShowMembers(void* obj, TMemberInspector &insp)
{
if (!fClassInfo) return;
DataMemberInfo_t* dmi = gCint->DataMemberInfo_Factory(fClassInfo);
TString name("*");
while (gCint->DataMemberInfo_Next(dmi)) {
name.Remove(1);
name += gCint->DataMemberInfo_Name(dmi);
if (name == "*G__virtualinfo") continue;
Long_t prop = gCint->DataMemberInfo_Property(dmi) | gCint->DataMemberInfo_TypeProperty(dmi);
if (prop & (G__BIT_ISSTATIC | G__BIT_ISENUM))
continue;
Bool_t isPointer = gCint->DataMemberInfo_TypeProperty(dmi) & G__BIT_ISPOINTER;
if (prop & G__BIT_ISARRAY) {
int arrdim = gCint->DataMemberInfo_ArrayDim(dmi);
for (int dim = 0; dim < arrdim; dim++) {
int nelem = gCint->DataMemberInfo_MaxIndex(dmi, dim);
name += TString::Format("[%d]", nelem);
}
}
const char* inspname = name;
if (!isPointer) {
++inspname;
}
void* maddr = ((char*)obj) + gCint->DataMemberInfo_Offset(dmi);
insp.Inspect(this, insp.GetParent(), inspname, maddr);
if (!isPointer && !(prop & G__BIT_ISFUNDAMENTAL)) {
std::string clmName(TClassEdit::ShortType(gCint->DataMemberInfo_TypeName(dmi),
TClassEdit::kDropTrailStar) );
TClass* clm = TClass::GetClass(clmName.c_str());
if (clm) {
insp.InspectMember(clm, maddr, name);
}
}
}
gCint->DataMemberInfo_Delete(dmi);
BaseClassInfo_t* bci = gCint->BaseClassInfo_Factory(fClassInfo);
while (gCint->BaseClassInfo_Next(bci)) {
const char* bclname = gCint->BaseClassInfo_Name(bci);
TClass* bcl = TClass::GetClass(bclname);
void* baddr = ((char*)obj) + gCint->BaseClassInfo_Offset(bci);
if (bcl) {
bcl->CallShowMembers(baddr, insp);
} else {
Warning("InterpretedShowMembers()", "Unknown class %s", bclname);
}
}
gCint->BaseClassInfo_Delete(bci);
}
Bool_t TClass::CanSplit() const
{
if (fCanSplit >= 0) {
return fCanSplit != 0;
}
if (this == TObject::Class()) return kTRUE;
if (fName == "TClonesArray") return kTRUE;
if (fRefProxy) return kFALSE;
if (InheritsFrom("TRef")) return kFALSE;
if (InheritsFrom("TRefArray")) return kFALSE;
if (InheritsFrom("TArray")) return kFALSE;
if (fName.BeginsWith("TVectorT<")) return kFALSE;
if (fName.BeginsWith("TMatrixT<")) return kFALSE;
if (InheritsFrom("TCollection") && !InheritsFrom("TClonesArray")) return kFALSE;
if (InheritsFrom("TTree")) return kFALSE;
if (GetShowMembersWrapper()==0 && GetStreamer()!=0) {
if (GetCollectionProxy()==0) {
return kFALSE;
} else {
if (GetCollectionProxy()->HasPointers()) return kFALSE;
TClass *valueClass = GetCollectionProxy()->GetValueClass();
if (valueClass == 0) return kFALSE;
if (valueClass==TString::Class() || valueClass==TClass::GetClass("string"))
return kFALSE;
if (!valueClass->CanSplit()) return kFALSE;
if (valueClass->GetCollectionProxy() != 0) return kFALSE;
Int_t stl = -TClassEdit::IsSTLCont(GetName(), 0);
if ((stl==TClassEdit::kMap || stl==TClassEdit::kMultiMap)
&& valueClass->GetClassInfo()==0)
{
return kFALSE;
}
}
}
if (Size()==1) {
return kFALSE;
}
TClass *ncThis = const_cast<TClass*>(this);
TIter nextb(ncThis->GetListOfBases());
TBaseClass *base;
while((base = (TBaseClass*)nextb())) {
if (!TClass::GetClass(base->GetName())) return kFALSE;
}
return kTRUE;
}
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(gCINTMutex);
TClass::RemoveClass(const_cast<TClass*>(this));
TClass *copy;
if (fTypeInfo) {
copy = new TClass(GetName(),
fClassVersion,
*fTypeInfo,
new TIsAProxy(*fTypeInfo),
fShowMembers,
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;
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 (!fClassInfo) 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(void *obj) const
{
Printf("==>Dumping object at:%lx, class=%s\n",(Long_t)obj,GetName());
TDumpMembers dm;
if (!CallShowMembers(obj, dm)) {
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;
}
#if __cplusplus >= 201103L
temp->ReturnType();
TMethodCall* expected = nullptr;
if( not fIsAMethod.compare_exchange_strong(expected,temp) ) {
delete temp;
}
#else
fIsAMethod = temp;
#endif
}
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 (!fClassInfo) return 0;
TObjLink *lnk = GetListOfBases() ? fBase->FirstLink() : 0;
while (lnk) {
TClass *c, *c1;
TBaseClass *base = (TBaseClass*) lnk->GetObject();
c = base->GetClassPointer();
if (c) {
if (strcmp(c->GetName(), classname) == 0) return c;
c1 = c->GetBaseClass(classname);
if (c1) return c1;
}
lnk = lnk->Next();
}
return 0;
}
TClass *TClass::GetBaseClass(const TClass *cl)
{
if (cl == this) return this;
if (!fClassInfo) 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 (!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() & G__BIT_ISVIRTUALBASE) != 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 *cl)
{
Int_t offset = GetBaseClassOffsetRecurse (cl);
if (offset == -2) {
if (cl->GetClassInfo()) {
R__LOCKGUARD(gCINTMutex);
Long_t base_tagnum = gCint->ClassInfo_Tagnum(cl->GetClassInfo());
BaseClassInfo_t *t = gCint->BaseClassInfo_Factory(GetClassInfo());
while (gCint->BaseClassInfo_Next(t,0)) {
if (gCint->BaseClassInfo_Tagnum(t) == base_tagnum) {
if ((gCint->BaseClassInfo_Property(t) & G__BIT_ISVIRTUALBASE) != 0) {
break;
}
int off = gCint->BaseClassInfo_Offset(t);
gCint->BaseClassInfo_Delete(t);
return off;
}
}
gCint->BaseClassInfo_Delete(t);
}
offset = -1;
}
return offset;
}
TClass *TClass::GetBaseDataMember(const char *datamember)
{
if (!fClassInfo) 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
{
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;
}
TVirtualIsAProxy* TClass::GetIsAProxy() const
{
return fIsA;
}
TClass *TClass::GetClass(const char *name, Bool_t load, Bool_t silent)
{
if (!name || !strlen(name)) return 0;
R__LOCKGUARD(gCINTMutex);
if (!gROOT->GetListOfClasses()) return 0;
TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
if (cl && cl->IsLoaded()) return cl;
TClassEdit::TSplitType splitname( name, TClassEdit::kLong64 );
if (!cl) {
std::string resolvedName;
splitname.ShortType(resolvedName, TClassEdit::kDropStlDefault);
if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
if (!cl) {
resolvedName = TClassEdit::ResolveTypedef(resolvedName.c_str(),kTRUE);
if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
}
if (!cl) {
resolvedName = TClassEdit::GetLong64_Name(resolvedName);
if (resolvedName != name) cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName.c_str());
}
}
if (cl) {
if (cl->IsLoaded()) return cl;
load = kTRUE;
if (splitname.IsSTLCont()) {
TClassRef clref = cl;
const char * itypename = gCint->GetInterpreterTypeName(name);
if (clref->IsLoaded()) {
return clref;
}
if (itypename) {
std::string altname( TClassEdit::ShortType(itypename, TClassEdit::kDropStlDefault) );
if (altname != name) {
gROOT->GetListOfClasses()->Remove(cl);
#if __cplusplus >= 201103L
TClass **persistentRef = cl->fPersistentRef.exchange(0);
#else
TClass **persistentRef = cl->fPersistentRef;
cl->fPersistentRef = 0;
#endif
TClass *newcl = GetClass(altname.c_str(),load);
#if __cplusplus >= 201103L
persistentRef = newcl->fPersistentRef.exchange(persistentRef);
#else
TClass **todelete = newcl->fPersistentRef;
newcl->fPersistentRef = persistentRef;
persistentRef = todelete;
#endif
*(newcl->fPersistentRef) = newcl;
*persistentRef = 0;
assert(newcl!=cl);
newcl->ForceReload(cl);
if (newcl->fCollectionProxy) {
newcl->fCollectionProxy->fClass.fClassPtr = newcl->fPersistentRef;
}
if (newcl->fStreamer) {
TVirtualCollectionProxy *pr = dynamic_cast<TVirtualCollectionProxy*>(newcl->fStreamer);
if(pr) pr->fClass.fClassPtr = newcl->fPersistentRef;
}
delete persistentRef;
return newcl;
}
}
}
} else {
if (!splitname.IsSTLCont()) {
TDataType *objType = gROOT->GetType(name, load);
if (objType) {
const char *typdfName = objType->GetTypeName();
if (typdfName && strcmp(typdfName, name)) {
TString alternateName(typdfName);
cl = TClass::GetClass(alternateName, load);
return cl;
}
}
} else {
cl = gROOT->FindSTLClass(name,kFALSE,silent);
if (cl) {
if (cl->IsLoaded()) return cl;
return TClass::GetClass(cl->GetName(),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;
static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
if (strcmp(name,full_string_name)==0
|| ( strncmp(name,"std::",5)==0 && ((strcmp(name+5,"string")==0)||(strcmp(name+5,full_string_name)==0)))) {
return TClass::GetClass("string");
}
if (splitname.IsSTLCont()) {
return gROOT->FindSTLClass(name,kTRUE,silent);
} else if ( strncmp(name,"std::",5)==0 ) {
return TClass::GetClass(name+5,load);
} else if ( strstr(name,"std::") != 0 ) {
TString rname( TClassEdit::ResolveTypedef(name,kTRUE) );
if (rname != name) {
return TClass::GetClass( rname, load );
}
}
if (!strcmp(name, "long long")||!strcmp(name,"unsigned long long"))
return 0;
Int_t nch = strlen(name)*2;
char *modifiable_name = new char[nch];
strlcpy(modifiable_name,name,nch);
if (gInterpreter->CheckClassInfo(modifiable_name)) {
const char *altname = gInterpreter->GetInterpreterTypeName(modifiable_name,kTRUE);
if (strcmp(altname,name)!=0) {
delete [] modifiable_name;
return GetClass(altname,load);
}
TClass *ncl = new TClass(name, 1, 0, 0, -1, -1, silent);
if (!ncl->IsZombie()) {
delete [] modifiable_name;
return ncl;
}
delete ncl;
}
delete [] modifiable_name;
return 0;
}
THashTable *TClass::GetClassShortTypedefHash() {
return fgClassShortTypedefHash;
}
TClass *TClass::GetClass(const type_info& typeinfo, Bool_t load, Bool_t )
{
R__LOCKGUARD2(gCINTMutex);
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;
VoidFuncPtr_t dict = TClassTable::GetDict(typeinfo);
if (dict) {
(dict)();
cl = GetClass(typeinfo,kFALSE);
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;
}
}
return 0;
}
VoidFuncPtr_t TClass::GetDict (const char *cname)
{
return TClassTable::GetDict(cname);
}
VoidFuncPtr_t TClass::GetDict (const type_info& info)
{
return TClassTable::GetDict(info);
}
TDataMember *TClass::GetDataMember(const char *datamember) const
{
if (!fClassInfo) return 0;
const Int_t size_buffer = 256;
char memb[size_buffer];
char *s = (char*)datamember;
while (*s == '*') s++;
size_t len = strlen(s);
if (len > size_buffer - 2)
len = size_buffer - 2;
strncpy(memb, s, len);
memb[len] = 0;
if ((s = strchr(memb, '['))) {
*s = 0;
len = strlen(memb);
}
TDataMember *dm;
TIter next(((TClass*)this)->GetListOfDataMembers());
while ((dm = (TDataMember *) next()))
if (len >= size_buffer - 2) {
if (strncmp(memb, dm->GetName(), len) == 0)
return dm;
} else
if (strcmp(memb, dm->GetName()) == 0)
return dm;
return 0;
}
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;
}
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 (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetListOfBases", "gInterpreter not initialized");
R__LOCKGUARD(gCINTMutex);
if(!fBase) {
gInterpreter->CreateListOfBaseClasses(this);
}
}
return fBase;
}
TList *TClass::GetListOfDataMembers()
{
R__LOCKGUARD(gCINTMutex);
if (!fClassInfo) {
if (!fData) fData = new TList;
return fData;
}
if (!fData) {
if (!gInterpreter)
Fatal("GetListOfDataMembers", "gInterpreter not initialized");
gInterpreter->CreateListOfDataMembers(this);
}
return fData;
}
TList *TClass::GetListOfMethods()
{
R__LOCKGUARD(gCINTMutex);
if (!fClassInfo) {
if (!fMethod) fMethod = new THashList;
return fMethod;
}
if (!fMethod) {
if (!gInterpreter)
Fatal("GetListOfMethods", "gInterpreter not initialized");
TMmallocDescTemp setreset;
gInterpreter->CreateListOfMethods(this);
} else {
gInterpreter->UpdateListOfMethods(this);
}
return fMethod;
}
TList *TClass::GetListOfAllPublicMethods()
{
R__LOCKGUARD(gCINTMutex);
if (!fAllPubMethod) {
fAllPubMethod = new TList;
fAllPubMethod->AddAll(GetListOfMethods());
TIter nextBaseClass(GetListOfBases());
TBaseClass *pB;
TMethod *p;
while ((pB = (TBaseClass*) nextBaseClass())) {
if (!pB->GetClassPointer()) continue;
if (!(pB->Property() & kIsPublic)) continue;
TIter next(pB->GetClassPointer()->GetListOfAllPublicMethods());
TList temp;
while ((p = (TMethod*) next()))
if (!fAllPubMethod->Contains(p->GetName()))
temp.Add(p);
fAllPubMethod->AddAll(&temp);
temp.Clear();
}
TIter next(fAllPubMethod);
while ((p = (TMethod*) next()))
if (!(p->Property() & kIsPublic)) fAllPubMethod->Remove(p);
}
return fAllPubMethod;
}
TList *TClass::GetListOfAllPublicDataMembers()
{
R__LOCKGUARD(gCINTMutex);
if (!fAllPubData) {
fAllPubData = new TList;
TIter next(GetListOfDataMembers());
TDataMember *p;
while ((p = (TDataMember*) next()))
if (p->Property() & kIsPublic) fAllPubData->Add(p);
TIter next_BaseClass(GetListOfBases());
TBaseClass *pB;
while ((pB = (TBaseClass*) next_BaseClass())) {
if (!pB->GetClassPointer()) continue;
if (!(pB->Property() & kIsPublic)) continue;
fAllPubData->AddAll(pB->GetClassPointer()->GetListOfAllPublicDataMembers() );
}
}
return fAllPubData;
}
void TClass::GetMenuItems(TList *list)
{
if (!fClassInfo) 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::IsFolder(void *obj) const
{
return Browse(obj,(TBrowser*)0);
}
void TClass::ReplaceWith(TClass *newcl, Bool_t recurse) const
{
R__LOCKGUARD(gCINTMutex);
TIter nextClass(gROOT->GetListOfClasses());
TClass *acl;
TVirtualStreamerInfo *info;
TList tobedeleted;
TString corename( TClassEdit::ResolveTypedef(newcl->GetName()) );
if ( strchr( corename.Data(), '<' ) == 0 ) {
recurse = kFALSE;
}
while ((acl = (TClass*)nextClass())) {
if (recurse && acl!=newcl && acl!=this) {
TString aclCorename( TClassEdit::ResolveTypedef(acl->GetName()) );
if (aclCorename == corename) {
acl->ReplaceWith(newcl, kFALSE);
tobedeleted.Add(acl);
}
}
TIter nextInfo(acl->GetStreamerInfos());
while ((info = (TVirtualStreamerInfo*)nextInfo())) {
info->Update(this, newcl);
}
if (acl->GetCollectionProxy() && acl->GetCollectionProxy()->GetValueClass()==this) {
acl->GetCollectionProxy()->SetValueClass(newcl);
}
if (acl->GetStreamer()) {
TVirtualCollectionProxy *pr = dynamic_cast<TVirtualCollectionProxy*>(acl->GetStreamer());
if (pr && pr->GetValueClass()==this) {
pr->SetValueClass(newcl);
}
}
}
TIter delIter( &tobedeleted );
while ((acl = (TClass*)delIter())) {
delete acl;
}
}
void TClass::ResetClassInfo(Long_t tagnum)
{
if (!fClassInfo || gCint->ClassInfo_Tagnum(fClassInfo) != tagnum) {
if (!fClassInfo)
fClassInfo = gInterpreter->ClassInfo_Factory();
gCint->ClassInfo_Init(fClassInfo,(Int_t)tagnum);
delete fAllPubData; fAllPubData =0;
delete fAllPubMethod; fAllPubMethod=0;
if (fBase)
fBase->Delete();
delete fBase; fBase = 0;
if (fData)
fData->Delete();
delete fData; fData = 0;
if (fMethod)
fMethod->Delete();
delete fMethod; fMethod=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) {
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(gCINTMutex);
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 (!fClassInfo && !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;
}
TMethod *TClass::GetMethodAny(const char *method)
{
if (!fClassInfo) return 0;
return (TMethod*) GetListOfMethods()->FindObject(method);
}
TMethod *TClass::GetMethodAllAny(const char *method)
{
if (!fClassInfo) 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)
{
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetMethod", "gInterpreter not initialized");
Long_t faddr = (Long_t)gInterpreter->GetInterfaceMethod(this, method,
params);
if (!faddr) return 0;
TMethod *m;
#if defined(R__WIN32)
m = GetClassMethod(method,params);
#else
if (faddr == (Long_t)gCint->GetExecByteCode()) {
m = GetClassMethod(method,params);
} else {
m = GetClassMethod(faddr);
}
#endif
if (m) return m;
TBaseClass *base;
TIter next(GetListOfBases());
while ((base = (TBaseClass *) next())) {
TClass *c = base->GetClassPointer();
if (c) {
m = c->GetMethod(method,params);
if (m) return m;
}
}
Error("GetMethod",
"\nDid not find matching TMethod <%s> with \"%s\" for %s",
method,params,GetName());
return 0;
}
TMethod *TClass::GetMethodWithPrototype(const char *method, const char *proto)
{
if (!fClassInfo) return 0;
if (!gInterpreter)
Fatal("GetMethod", "gInterpreter not initialized");
Long_t faddr = (Long_t)gInterpreter->GetInterfaceMethodWithPrototype(this,
method, proto);
if (!faddr) return 0;
TMethod *m = GetClassMethod(faddr);
if (m) return m;
TBaseClass *base;
TIter next(GetListOfBases());
while ((base = (TBaseClass *) next())) {
TClass *c = base->GetClassPointer();
if (c) {
m = c->GetMethodWithPrototype(method,proto);
if (m) return m;
}
}
Error("GetMethod", "Did not find matching TMethod (should never happen)");
return 0;
}
TMethod *TClass::GetClassMethod(Long_t faddr)
{
if (!fClassInfo) 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)
{
if (!fClassInfo) return 0;
TList* bucketForMethod = ((THashList*)GetListOfMethods())->GetListForObject(name);
if (bucketForMethod) {
R__LOCKGUARD2(gCINTMutex);
CallFunc_t *func = gCint->CallFunc_Factory();
Long_t offset;
gCint->CallFunc_SetFunc(func,GetClassInfo(), name, params, &offset);
MethodInfo_t *info = gCint->CallFunc_FactoryMethod(func);
TMethod request(info,this);
TMethod *m;
TIter next(bucketForMethod);
while ((m = (TMethod *) next())) {
if (!strcmp(name,m->GetName())
&&!strcmp(request.GetSignature(),m->GetSignature())) {
gCint->CallFunc_Delete(func);
return m;
}
}
gCint->CallFunc_Delete(func);
}
return 0;
}
Int_t TClass::GetNdata()
{
if (!fClassInfo) return 0;
TList *lm = GetListOfDataMembers();
if (lm)
return lm->GetSize();
else
return 0;
}
Int_t TClass::GetNmethods()
{
if (!fClassInfo) 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(gCINTMutex);
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) {
if (fClassInfo && fRealData==0 && (gCint->ClassInfo_Property(fClassInfo) & kIsAbstract) ) {
return 0;
}
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 (fClassInfo || 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(gCINTMutex);
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(gCINTMutex);
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 ignr)
{
R__LOCKGUARD2(gCINTMutex);
if ( ignr && TestBit(kIgnoreTObjectStreamer)) return;
if (!ignr && !TestBit(kIgnoreTObjectStreamer)) return;
TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
if (sinfo) {
if (sinfo->IsCompiled()) {
Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
return;
}
}
if (ignr) SetBit (kIgnoreTObjectStreamer);
else ResetBit(kIgnoreTObjectStreamer);
}
Bool_t TClass::InheritsFrom(const char *classname) const
{
if (strcmp(GetName(), classname) == 0) return kTRUE;
if (!fClassInfo) return InheritsFrom(TClass::GetClass(classname));
if (((TClass *)this)->GetBaseClass(classname)) return kTRUE;
return kFALSE;
}
Bool_t TClass::InheritsFrom(const TClass *cl) const
{
if (cl == this) return kTRUE;
if (!fClassInfo) {
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 (!fClassInfo) 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;
}
void *TClass::New(ENewType defConstructor) const
{
void* p = 0;
if (fNew) {
TClass__GetCallingNew() = defConstructor;
p = fNew(0);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (fClassInfo) {
TClass__GetCallingNew() = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo());
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!fClassInfo && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->New();
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!fClassInfo && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
if(statsave) {
SetObjectStat(kFALSE);
}
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
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 {
Error("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 (fClassInfo) {
TClass__GetCallingNew() = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->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 (!fClassInfo && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->New(arena);
TClass__GetCallingNew() = kRealNew;
} else if (!fClassInfo && !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 (fClassInfo) {
TClass__GetCallingNew() = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo(),nElements);
TClass__GetCallingNew() = kRealNew;
if (!p) {
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
}
} else if (!fClassInfo && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->NewArray(nElements);
TClass__GetCallingNew() = kRealNew;
} else if (!fClassInfo && !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 (fClassInfo) {
TClass__GetCallingNew() = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->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 (!fClassInfo && fCollectionProxy) {
TClass__GetCallingNew() = defConstructor;
p = fCollectionProxy->NewArray(nElements, arena);
TClass__GetCallingNew() = kRealNew;
} else if (!fClassInfo && !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 & kEmulated) {
}
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 (fClassInfo) {
if (dtorOnly) {
R__LOCKGUARD2(gCINTMutex);
gCint->ClassInfo_Destruct(fClassInfo,p);
} else {
R__LOCKGUARD2(gCINTMutex);
gCint->ClassInfo_Delete(fClassInfo,p);
}
} else if (!fClassInfo && fCollectionProxy) {
fCollectionProxy->Destructor(p, dtorOnly);
} else if (!fClassInfo && !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 (fClassInfo) {
R__LOCKGUARD2(gCINTMutex);
gCint->ClassInfo_DeleteArray(GetClassInfo(),ary, dtorOnly);
} else if (!fClassInfo && fCollectionProxy) {
fCollectionProxy->DeleteArray(ary, dtorOnly);
} else if (!fClassInfo && !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(gCINTMutex);
if(!fCurrentInfo) {
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 (fClassInfo) return gCint->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;
}
void TClass::Store(TBuffer &b) const
{
b.WriteString(GetName());
}
TClass *ROOT::CreateClass(const char *cname, Version_t id,
const type_info &info, TVirtualIsAProxy *isa,
ShowMembersFunc_t show,
const char *dfil, const char *ifil,
Int_t dl, Int_t il)
{
TMmallocDescTemp setreset;
return new TClass(cname, id, info, isa, show, 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 (GetImplFileLine()>=0 && !TestBit(kUnloaded));
}
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() && fClassInfo && fClassVersion==1 && IsForeign() )
{
SetClassVersion(-1);
}
else if (IsLoaded() && fClassInfo && fStreamerInfo && (!IsForeign()||fClassVersion>1) )
{
R__LOCKGUARD(gCINTMutex);
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(gCINTMutex);
if (fProperty!=(-1)) return fProperty;
TMmallocDescTemp setreset;
Long_t dummy;
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->GetBaseClassOffset(TObject::Class());
if (delta==0) kl->SetBit(kStartWithTObject);
kl->fStreamerType = kTObject;
kl->fStreamerImpl = &TClass::StreamerTObject;
}
if (fClassInfo) {
if (!gCint->ClassInfo_HasMethod(fClassInfo,"Streamer") ||
!gCint->ClassInfo_IsValidMethod(fClassInfo,"Streamer","TBuffer&",&dummy) ) {
kl->SetBit(kIsForeign);
kl->fStreamerType = kForeign;
kl->fStreamerImpl = &TClass::StreamerStreamerInfo;
} else if ( kl->fStreamerType == TClass::kDefault ) {
if ( gCint->ClassInfo_FileName(fClassInfo)
&& strcmp( gCint->ClassInfo_FileName(fClassInfo),"{CINTEX dictionary translator}")==0) {
kl->SetBit(kIsForeign);
}
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->fProperty = gCint->ClassInfo_Property(fClassInfo);
} else {
if (fStreamer) {
kl->fStreamerType = kExternal;
kl->fStreamerImpl = &TClass::StreamerExternal;
}
kl->fStreamerType |= kEmulated;
switch (fStreamerType) {
case kEmulated:
case kForeign|kEmulated:
case kInstrumented|kEmulated: kl->fStreamerImpl = &TClass::StreamerStreamerInfo; break;
case kExternal|kEmulated: kl->fStreamerImpl = &TClass::StreamerExternal; break;
case kTObject|kEmulated: kl->fStreamerImpl = &TClass::StreamerTObjectEmulated; break;
case TClass::kDefault: kl->fStreamerImpl = &TClass::StreamerDefault; break;
}
return 0;
}
return fProperty;
}
void TClass::SetCollectionProxy(const ROOT::TCollectionProxyInfo &info)
{
R__LOCKGUARD(gCINTMutex);
delete fCollectionProxy;
TVirtualCollectionProxy *p = TVirtualStreamerInfo::Factory()->GenExplicitProxy(info,this);
fCollectionProxy = p;
AdoptStreamer(TVirtualStreamerInfo::Factory()->GenExplicitClassStreamer(info,this));
}
void TClass::SetContextMenuTitle(const char *title)
{
fContextMenuTitle = title;
}
void TClass::SetGlobalIsA(IsAGlobalFunc_t func)
{
fGlobalIsA = func;
}
void TClass::SetUnloaded()
{
delete fIsA; fIsA = 0;
int autoload_old = gCint->SetClassAutoloading(0);
gInterpreter->SetClassInfo(this,kTRUE);
gCint->SetClassAutoloading(autoload_old);
fDeclFileName = 0;
fDeclFileLine = 0;
fImplFileName = 0;
fImplFileLine = 0;
fTypeInfo = 0;
if (fMethod) {
fMethod->Delete();
delete fMethod;
fMethod=0;
}
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
{
R__LOCKGUARD(gCINTMutex);
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) {
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());
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) && prop&kIsEnum) id = id*3 + 1;
int i;
for (i=0; i<il; i++) id = id*3+name[i];
if (code > kWithTypeDef ) {
type = TClassEdit::GetLong64_Name(TClassEdit::ResolveTypedef(tdm->GetFullTypeName(),true));
if (TClassEdit::IsSTLCont(type))
type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault );
} 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 = 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(gCINTMutex);
if ( fRefProxy ) {
fRefProxy->Release();
}
fRefProxy = proxy;
if ( fRefProxy ) {
fRefProxy->SetClass(this);
}
}
void TClass::AdoptMemberStreamer(const char *name, TMemberStreamer *p)
{
if (!fRealData) return;
R__LOCKGUARD(gCINTMutex);
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(void *object, TBuffer &b, const TClass *onfile_class) const
{
TClassStreamer *streamer = gThreadTsd ? GetStreamer() : fStreamer;
streamer->Stream(b,object,onfile_class);
}
void TClass::StreamerTObject(void *object, TBuffer &b, const TClass * ) const
{
if (!fIsOffsetStreamerSet) {
CalculateStreamerOffset();
}
TObject *tobj = (TObject*)((Long_t)object + fOffsetStreamer);
tobj->Streamer(b);
}
void TClass::StreamerTObjectInitialized(void *object, TBuffer &b, const TClass * ) const
{
TObject *tobj = (TObject*)((Long_t)object + fOffsetStreamer);
tobj->Streamer(b);
}
void TClass::StreamerTObjectEmulated(void *object, TBuffer &b, const TClass *onfile_class) const
{
if (b.IsReading()) {
b.ReadClassEmulated(this, object, onfile_class);
} else {
b.WriteClassBuffer(this, object);
}
}
void TClass::StreamerInstrumented(void *object, TBuffer &b, const TClass * ) const
{
fStreamerFunc(b,object);
}
void TClass::StreamerStreamerInfo(void *object, TBuffer &b, const TClass *onfile_class) const
{
if (b.IsReading()) {
b.ReadClassBuffer(this, object, onfile_class);
} else {
b.WriteClassBuffer(this, object);
}
}
void TClass::StreamerDefault(void *object, TBuffer &b, const TClass *onfile_class) const
{
if (fProperty==(-1)) {
Property();
if (fStreamerImpl == &TClass::StreamerDefault) {
Fatal("StreamerDefault", "fStreamerImpl not properly initialized (%d)", fStreamerType);
} else {
(this->*fStreamerImpl)(object,b,onfile_class);
}
} else {
Fatal("StreamerDefault", "fStreamerType not properly initialized (%d)", fStreamerType);
}
}
void TClass::AdoptStreamer(TClassStreamer *str)
{
R__LOCKGUARD(gCINTMutex);
if (fStreamer) delete fStreamer;
if (str) {
fStreamerType = kExternal | ( fStreamerType&kEmulated );
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)
{
if (fProperty != -1 &&
( (fStreamerFunc == 0 && strm != 0) || (fStreamerFunc != 0 && strm == 0) ) )
{
fStreamerFunc = strm;
fProperty = -1;
Property();
} else {
fStreamerFunc = strm;
}
}
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(gCINTMutex);
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(gCINTMutex);
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) {
std::map<std::string, TObjArray*>::iterator it;
R__LOCKGUARD(gCINTMutex);
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(gCINTMutex);
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) {
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) {
std::map<std::string, TObjArray*>::iterator it;
R__LOCKGUARD(gCINTMutex);
it = (*fConversionStreamerInfo).find( cl->GetName() );
if( it != (*fConversionStreamerInfo).end() ) {
arr = it->second;
}
if (arr) {
info = FindStreamerInfo( arr, checksum );
}
}
if( info )
return info;
R__LOCKGUARD(gCINTMutex);
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) {
fConversionStreamerInfo = new std::map<std::string, TObjArray*>();
}
(*fConversionStreamerInfo)[cl->GetName()] = arr;
}
arr->AddAtAndExpand( info, info->GetClassVersion() );
return info;
}
Bool_t TClass::HasDefaultConstructor() const
{
if (fNew) return kTRUE;
if (GetClassInfo()) {
R__LOCKGUARD(gCINTMutex);
return gCint->ClassInfo_HasDefaultConstructor(GetClassInfo());
}
if (fCollectionProxy) {
return kTRUE;
}
if (fCurrentInfo) {
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;
}