#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 "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 "TGenericClassInfo.h"
#include <cstdio>
#include <cctype>
#include <set>
#include <sstream>
#include <string>
#include <map>
#include <cmath>
#include <assert.h>
using namespace std;
TVirtualMutex* gCINTMutex = 0;
void *gMmallocDesc = 0;
Int_t TClass::fgClassCount;
TClass::ENewType TClass::fgCallingNew = kRealNew;
static std::multimap<void*, Version_t> gObjectVersionRepository;
static void RegisterAddressInRepository(const char * , void *location, const TClass *what)
{
Version_t version = what->GetClassVersion();
gObjectVersionRepository.insert(std::pair<void* const,Version_t>(location, version));
#if 0
std::pair<std::map<void*, Version_t>::iterator, Bool_t> tmp = gObjectVersionRepository.insert(std::pair<void*,Version_t>(location, 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(std::pair<void*,Version_t>(location, 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)
{
std::multimap<void*, Version_t>::iterator cur = gObjectVersionRepository.find(location);
for (; cur != gObjectVersionRepository.end();) {
std::multimap<void*, Version_t>::iterator tmp = cur++;
if ((tmp->first == location) && (tmp->second == what->GetClassVersion())) {
gObjectVersionRepository.erase(tmp);
} else {
break;
}
}
}
static void MoveAddressInRepository(const char *where, void *oldadd, void *newadd, const TClass *what)
{
UnregisterAddressInRepository(where,oldadd,what);
RegisterAddressInRepository(where,newadd,what);
}
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:
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::fgIdMap = new IdMap_t;
void TClass::AddClass(TClass *cl)
{
if (!cl) return;
gROOT->GetListOfClasses()->Add(cl);
if (cl->GetTypeInfo()) {
fgIdMap->Add(cl->GetTypeInfo()->name(),cl);
}
}
void TClass::RemoveClass(TClass *oldcl)
{
if (!oldcl) return;
gROOT->GetListOfClasses()->Remove(oldcl);
if (oldcl->GetTypeInfo()) {
fgIdMap->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];
TDataMember *member = cl->GetDataMember(mname);
if (!member) return;
TDataType *membertype = member->GetDataType();
Bool_t isdate = kFALSE;
if (strcmp(member->GetName(),"fDatime") == 0 && strcmp(member->GetTypeName(),"UInt_t") == 0) {
isdate = kTRUE;
}
Bool_t isbits = kFALSE;
if (strcmp(member->GetName(),"fBits") == 0 && strcmp(member->GetTypeName(),"UInt_t") == 0) {
isbits = kTRUE;
}
Int_t i;
for (i = 0;i < kline; i++) line[i] = ' ';
line[kline-1] = 0;
sprintf(line,"%s%s ",pname,mname);
i = strlen(line); line[i] = ' ';
char *pointer = (char*)add;
char **ppointer = (char**)(pointer);
if (member->IsaPointer()) {
char **p3pointer = (char**)(*ppointer);
if (!p3pointer)
sprintf(&line[kvalue],"->0");
else if (!member->IsBasic())
sprintf(&line[kvalue],"->%lx ", (Long_t)p3pointer);
else if (membertype) {
if (!strcmp(membertype->GetTypeName(), "char")) {
i = strlen(*ppointer);
if (kvalue+i >= kline) i=kline-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 {
strcpy(&line[kvalue], membertype->AsString(p3pointer));
}
} else if (!strcmp(member->GetFullTypeName(), "char*") ||
!strcmp(member->GetFullTypeName(), "const char*")) {
i = strlen(*ppointer);
if (kvalue+i >= kline) i=kline-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 {
sprintf(&line[kvalue],"->%lx ", (Long_t)p3pointer);
}
} else if (membertype)
if (isdate) {
cdatime = (UInt_t*)pointer;
TDatime::GetDateTime(cdatime[0],cdate,ctime);
sprintf(&line[kvalue],"%d/%d",cdate,ctime);
} else if (isbits) {
sprintf(&line[kvalue],"0x%08x", *(UInt_t*)pointer);
} else {
strcpy(&line[kvalue], membertype->AsString(pointer));
}
else
sprintf(&line[kvalue],"->%lx ", (Long_t)pointer);
if (isdate == kFALSE && strcmp(member->GetFullTypeName(), "char*") &&
strcmp(member->GetFullTypeName(), "const char*")) {
i = strlen(&line[0]); line[i] = ' ';
Int_t lentit = strlen(member->GetTitle());
if (lentit > 250-ktitle) lentit = 250-ktitle;
strncpy(&line[ktitle],member->GetTitle(),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;
public:
TBuildRealData(void *obj, TClass *cl) {
fRealDataObject = obj;
fRealDataClass = cl;
}
void Inspect(TClass *cl, const char *parent, const char *name, const void *addr);
};
void TBuildRealData::Inspect(TClass* cl, const char* pname, const char* mname, const void* add)
{
TDataMember* dm = cl->GetDataMember(mname);
if (!dm || !dm->IsPersistent()) {
return;
}
char rname[512];
strcpy(rname, pname);
if (cl != fRealDataClass) {
if (!fRealDataClass->InheritsFrom(cl)) {
char* dot = strchr(rname, '.');
if (!dot) {
return;
}
*dot = 0;
if (!fRealDataClass->GetDataMember(rname)) {
if (!fRealDataClass->GetBaseDataMember(rname)) {
return;
}
}
*dot = '.';
}
}
strcat(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);
fRealDataClass->GetListOfRealData()->Add(rd);
} else {
TRealData* rd = new TRealData(rname, offset, dm);
fRealDataClass->GetListOfRealData()->Add(rd);
}
} else {
TRealData* rd = new TRealData(rname, offset, dm);
if (!dm->IsBasic()) {
rd->SetIsObject(kTRUE);
TClass* dmclass = TClass::GetClass(dm->GetTypeName());
if (!dmclass) {
dmclass = TClass::GetClass(dm->GetTrueTypeName());
}
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->BuildRealData();
} else {
dmclass->BuildRealData(const_cast<void*>(add));
}
}
}
}
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_FactoryCopy(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]; sprintf(cbuf,"[%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++;
sprintf(buf,fmt,ii);
ts = bwname;
ts += buf;
fBrowser->Add( p, actualCl, ts );
}
}
}
}
}
ClassImp(TClass)
TClass::TClass() : TDictionary(), fNew(0), fNewArray(0), fDelete(0),
fDeleteArray(0), fDestructor(0), fDirAutoAdd(0), fSizeof(-1),
fVersionUsed(kFALSE), fOffsetStreamer(0), fStreamerType(kNone),
fCurrentInfo(0), fRefStart(0), fRefProxy(0)
{
fDeclFileLine = -2;
fBase = 0;
fData = 0;
fMethod = 0;
fRealData = 0;
fClassInfo = 0;
fAllPubData = 0;
fAllPubMethod = 0;
fCheckSum = 0;
fCollectionProxy= 0;
fStreamer = 0;
fStreamerInfo = 0;
fShowMembers = 0;
fIsA = 0;
fGlobalIsA = 0;
fIsAMethod = 0;
fTypeInfo = 0;
fInterStreamer = 0;
ResetInstanceCount();
fClassMenuList = new TList();
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, this));
fContextMenuTitle = "";
}
TClass::TClass(const char *name) : TDictionary(), fNew(0), fNewArray(0),
fDelete(0), fDeleteArray(0), fDestructor(0),
fDirAutoAdd(0),
fSizeof(-1), fVersionUsed(kFALSE),
fOffsetStreamer(0), fStreamerType(kNone),
fCurrentInfo(0), fRefStart(0), fRefProxy(0)
{
if (!gROOT)
::Fatal("TClass::TClass", "ROOT system not initialized");
SetName(name);
fClassVersion = 0;
fDeclFileName = "";
fImplFileName = "";
fDeclFileLine = -2;
fImplFileLine = 0;
fBase = 0;
fData = 0;
fMethod = 0;
fRealData = 0;
fClassInfo = 0;
fAllPubData = 0;
fAllPubMethod = 0;
fCheckSum = 0;
fCollectionProxy= 0;
fTypeInfo = 0;
fIsA = 0;
fGlobalIsA = 0;
fIsAMethod = 0;
fShowMembers = 0;
fStreamerInfo = 0;
fStreamer = 0;
fInterStreamer = 0;
ResetInstanceCount();
fClassMenuList = new TList();
fContextMenuTitle = "";
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, this));
if (!fClassInfo) {
SetBit(kLoading);
if (!gInterpreter)
::Fatal("TClass::TClass", "gInterpreter not initialized");
gInterpreter->SetClassInfo(this);
if (!fClassInfo) {
gInterpreter->InitializeDictionaries();
gInterpreter->SetClassInfo(this);
}
if (!fClassInfo)
::Warning("TClass::TClass", "no dictionary for class %s is available", name);
ResetBit(kLoading);
}
if (fClassInfo) SetTitle(gCint->ClassInfo_Title(fClassInfo));
}
TClass::TClass(const char *name, Version_t cversion,
const char *dfil, const char *ifil, Int_t dl, Int_t il)
: TDictionary(), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fSizeof(-1), fVersionUsed(kFALSE), fOffsetStreamer(0),
fStreamerType(kNone), fCurrentInfo(0), fRefStart(0), fRefProxy(0)
{
Init(name,cversion, 0, 0, 0, dfil, ifil, dl, il);
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)
: TDictionary(), fNew(0), fNewArray(0), fDelete(0), fDeleteArray(0),
fDestructor(0), fDirAutoAdd(0), fSizeof(-1), fVersionUsed(kFALSE), fOffsetStreamer(0),
fStreamerType(kNone), fCurrentInfo(0), fRefStart(0), fRefProxy(0)
{
Init(name, cversion, &info, isa, showmembers, dfil, ifil, dl, il);
}
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)
{
if (!gROOT)
::Fatal("TClass::TClass", "ROOT system not initialized");
SetName(name);
fClassVersion = cversion;
fDeclFileName = dfil ? dfil : "";
fImplFileName = ifil ? ifil : "";
fDeclFileLine = dl;
fImplFileLine = il;
fBase = 0;
fData = 0;
fMethod = 0;
fRealData = 0;
fClassInfo = 0;
fAllPubData = 0;
fAllPubMethod = 0;
fCheckSum = 0;
fCollectionProxy= 0;
fTypeInfo = typeinfo;
fIsA = isa;
if ( fIsA ) fIsA->SetClass(this);
fGlobalIsA = 0;
fIsAMethod = 0;
fShowMembers = showmembers;
fStreamer = 0;
fStreamerInfo = new TObjArray(fClassVersion+2+10,-1);
fProperty = -1;
fInterStreamer = 0;
fClassMenuList = 0;
fContextMenuTitle = "";
ResetInstanceCount();
TClass *oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
if (oldcl && oldcl->TestBit(kLoading)) {
return;
}
if (oldcl) {
gROOT->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();
}
SetBit(kLoading);
TClass::AddClass(this);
Bool_t isStl = kFALSE;
if (!fClassInfo) {
Bool_t shouldLoad = kFALSE;
isStl = TClassEdit::IsSTLCont(name);
if (gInterpreter->CheckClassInfo(name)) 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 (!fClassInfo && !isStl)
::Warning("TClass::TClass", "no dictionary for class %s is available", name);
fgClassCount++;
SetUniqueID(fgClassCount);
TString resolvedThis;
if (strchr (name, '<')) {
resolvedThis = TClassEdit::ResolveTypedef (name, kTRUE);
if (resolvedThis != name) {
if (!fgClassTypedefHash) {
fgClassTypedefHash = new THashTable (100, 5);
fgClassTypedefHash->SetOwner (kTRUE);
}
fgClassTypedefHash->Add (new TNameMapNode (resolvedThis, name));
SetBit (kHasNameMapNode);
}
TString resolvedShort =
TClassEdit::ResolveTypedef
(TClassEdit::ShortType(name,
TClassEdit::kDropStlDefault).c_str(),
kTRUE);
if (resolvedShort != name) {
if (!fgClassShortTypedefHash) {
fgClassShortTypedefHash = new THashTable (100, 5);
fgClassShortTypedefHash->SetOwner (kTRUE);
}
fgClassShortTypedefHash->Add (new TNameMapNode (resolvedShort, name));
SetBit (kHasNameMapNode);
}
}
if (oldcl) {
oldcl->ReplaceWith(this);
delete oldcl;
} else if (resolvedThis.Length() > 0 && fgClassTypedefHash) {
if (resolvedThis != name) {
oldcl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedThis);
if (oldcl && oldcl != this)
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) {
ForceReload (oldcl);
}
}
}
if (fClassInfo) SetTitle(gCint->ClassInfo_Title(fClassInfo));
ResetBit(kLoading);
fClassMenuList = new TList();
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList,this));
Int_t stl = TClassEdit::IsSTLCont(GetName(), 0);
if ( stl || !strncmp(GetName(),"stdext::hash_",13) || !strncmp(GetName(),"__gnu_cxx::hash_",16) ) {
fCollectionProxy = TVirtualStreamerInfo::Factory()->GenEmulatedProxy( GetName() );
fSizeof = fCollectionProxy->Sizeof();
if (fStreamer==0) {
fStreamer = TVirtualStreamerInfo::Factory()->GenEmulatedClassStreamer( GetName() );
}
}
}
TClass::TClass(const TClass& cl) :
TDictionary(cl),
fStreamerInfo(cl.fStreamerInfo),
fRealData(cl.fRealData),
fBase(cl.fBase),
fData(cl.fData),
fMethod(cl.fMethod),
fAllPubData(cl.fAllPubData),
fAllPubMethod(cl.fAllPubMethod),
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),
fClassMenuList(cl.fClassMenuList),
fTypeInfo(cl.fTypeInfo),
fShowMembers(cl.fShowMembers),
fStreamer(cl.fStreamer),
fSharedLibs(cl.fSharedLibs),
fIsA(cl.fIsA),
fGlobalIsA(cl.fGlobalIsA),
fIsAMethod(cl.fIsAMethod),
fNew(cl.fNew),
fNewArray(cl.fNewArray),
fDelete(cl.fDelete),
fDeleteArray(cl.fDeleteArray),
fDestructor(cl.fDestructor),
fDirAutoAdd(cl.fDirAutoAdd),
fSizeof(cl.fSizeof),
fVersionUsed(cl.fVersionUsed),
fProperty(cl.fProperty),
fInterStreamer(cl.fInterStreamer),
fOffsetStreamer(cl.fOffsetStreamer),
fStreamerType(cl.fStreamerType),
fCurrentInfo(cl.fCurrentInfo),
fRefStart(cl.fRefStart)
{
}
TClass& TClass::operator=(const TClass& cl)
{
if(this!=&cl) {
TDictionary::operator=(cl);
fStreamerInfo=cl.fStreamerInfo;
fRealData=cl.fRealData;
fBase=cl.fBase;
fData=cl.fData;
fMethod=cl.fMethod;
fAllPubData=cl.fAllPubData;
fAllPubMethod=cl.fAllPubMethod;
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;
fClassMenuList=cl.fClassMenuList;
fTypeInfo=cl.fTypeInfo;
fShowMembers=cl.fShowMembers;
fStreamer=cl.fStreamer;
fSharedLibs=cl.fSharedLibs;
fIsA=cl.fIsA;
fGlobalIsA=cl.fGlobalIsA;
fIsAMethod=cl.fIsAMethod;
fNew=cl.fNew;
fNewArray=cl.fNewArray;
fDelete=cl.fDelete;
fDeleteArray=cl.fDeleteArray;
fDestructor=cl.fDestructor;
fDirAutoAdd=cl.fDirAutoAdd;
fSizeof=cl.fSizeof;
fVersionUsed=cl.fVersionUsed;
fProperty=cl.fProperty;
fInterStreamer=cl.fInterStreamer;
fOffsetStreamer=cl.fOffsetStreamer;
fStreamerType=cl.fStreamerType;
fCurrentInfo=cl.fCurrentInfo;
fRefStart=cl.fRefStart;
}
return *this;
}
TClass::~TClass()
{
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 (fRefStart) {
fRefStart->ListReset();
fRefStart = 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;
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;
if ( fInterStreamer ) gCint->CallFunc_Delete((CallFunc_t*)fInterStreamer);
fInterStreamer=0;
if ( fIsA ) delete fIsA;
if ( fRefProxy ) fRefProxy->Release();
fRefProxy = 0;
delete fStreamer;
delete fCollectionProxy;
delete fIsAMethod;
}
void TClass::AddImplFile(const char* filename, int line) {
fImplFileName = filename;
fImplFileLine = line;
}
void TClass::AddRef(TClassRef *ref)
{
if (fRefStart==0) {
fRefStart = ref;
} else {
fRefStart->fPrevious = ref;
ref->fNext = fRefStart;
fRefStart = ref;
}
}
Int_t TClass::AutoBrowse(TObject *obj, TBrowser *b)
{
if (!obj) return 0;
char cbuf[1000]; *cbuf=0;
TAutoInspector insp(b);
obj->ShowMembers(insp,cbuf);
return insp.fCount;
}
Int_t TClass::Browse(void *obj, TBrowser *b) const
{
if (!obj) return 0;
if (fShowMembers) {
char cbuf[1000]; *cbuf=0;
TClass *actual = GetActualClass(obj);
if (actual!=this) {
actual->Browse(obj,b);
} else {
TAutoInspector insp(b);
fShowMembers(obj,insp,cbuf);
return insp.fCount;
}
} else if (GetCollectionProxy()) {
} else if (IsTObject()) {
if (!fInterStreamer)
const_cast<TClass*>(this)->CalculateStreamerOffset();
TObject* realTObject = (TObject*)((size_t)obj + fOffsetStreamer);
realTObject->Browse(b);
}
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)
{
if (fRealData) {
return;
}
if (!fClassInfo || TClassEdit::IsSTLCont(GetName(), 0)) {
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 (realDataObject) {
char parent[256];
parent[0] = 0;
fRealData = new TList;
TBuildRealData brd(realDataObject, this);
Bool_t isATObject = InheritsFrom(TObject::Class());
if (fShowMembers) {
fShowMembers(realDataObject, brd, parent);
} else {
if (isATObject) {
if (!fInterStreamer)
CalculateStreamerOffset();
TObject* realTObject = (TObject*)((size_t)realDataObject + fOffsetStreamer);
realTObject->ShowMembers(brd, parent);
} else {
R__LOCKGUARD2(gCINTMutex);
CallFunc_t *func = gCint->CallFunc_Factory();
void* address = 0;
Long_t offset = 0;
gCint->CallFunc_SetFuncProto(func,fClassInfo,"ShowMembers", "TMemberInspector&,char*", &offset);
if (!gCint->CallFunc_IsValid(func)) {
if (strcmp(GetName(), "string") != 0) {
Error("BuildRealData", "Cannot find any ShowMembers function for %s!", GetName());
}
} else {
gCint->CallFunc_SetArg(func,(long) &brd);
gCint->CallFunc_SetArg(func,(long) parent);
address = (void*) (((long) realDataObject) + offset);
gCint->CallFunc_Exec(func,address);
}
gCint->CallFunc_Delete(func);
}
}
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());
}
}
}
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)
{
TIter next(GetStreamerInfo()->GetElements());
TStreamerElement *element;
while ((element = (TStreamerElement*)next())) {
Int_t etype = element->GetType();
Long_t eoffset = element->GetOffset();
TClass *cle = element->GetClassPointer();
if (etype == TVirtualStreamerInfo::kTObject ||
etype == TVirtualStreamerInfo::kTNamed ||
etype == TVirtualStreamerInfo::kBase) {
if (cle) cle->BuildEmulatedRealData(name,offset+eoffset,cl);
} else if (etype == TVirtualStreamerInfo::kObject || etype == TVirtualStreamerInfo::kAny) {
TRealData *rd = new TRealData(Form("%s%s",name,element->GetFullName()),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);
TString rdname(Form("%s%s.",name,element->GetFullName()));
if (cle) cle->BuildEmulatedRealData(rdname,offset+eoffset,cl);
} else {
TString 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);
}
}
}
void TClass::CalculateStreamerOffset()
{
if (!fInterStreamer) {
CallFunc_t *f = gCint->CallFunc_Factory();
gCint->CallFunc_SetFuncProto(f,fClassInfo,"Streamer","TBuffer&",&fOffsetStreamer);
fInterStreamer = f;
fOffsetStreamer = GetBaseClassOffset(TObject::Class());
}
}
Bool_t TClass::CanSplit() const
{
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 (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;
}
}
}
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;
}
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());
char parent[256];
parent[0] = 0;
TDumpMembers dm;
if (fShowMembers) {
fShowMembers(obj,dm, parent);
} else {
R__LOCKGUARD2(gCINTMutex);
CallFunc_t *func = gCint->CallFunc_Factory();
void *address;
Long_t offset;
gCint->CallFunc_SetFuncProto(func,fClassInfo,"ShowMembers","TMemberInspector&,char*", &offset);
if (!gCint->CallFunc_IsValid(func)) {
Printf("==>No Showmembers functions ... dumping disabled\n");
} else {
gCint->CallFunc_SetArg(func,(long)&dm);
gCint->CallFunc_SetArg(func,(long)parent);
address = (void*)((long)obj + offset);
gCint->CallFunc_Exec(func,address);
}
gCint->CallFunc_Delete(func);
}
}
char *TClass::EscapeChars(const char *text) const
{
static char name[128];
Int_t nch = strlen(text);
if (nch > 127) nch = 127;
Int_t icur = -1;
for (Int_t i = 0; i < nch; 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+1] = 0;
return name;
}
TClass *TClass::GetActualClass(const void *object) const
{
if (object==0 || !IsLoaded() ) return (TClass*)this;
if (fIsA) {
return (*fIsA)(object);
} else if (fGlobalIsA) {
return fGlobalIsA(this,object);
} else {
if (fIsAMethod==0) {
fIsAMethod = new TMethodCall((TClass*)this, "IsA", "");
if (!fIsAMethod->GetMethod()) {
delete fIsAMethod;
fIsAMethod = 0;
Error("IsA","Can not find any IsA function for %s!",GetName());
return (TClass*)this;
}
}
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()) {
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,1);
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) );
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;
}
TVirtualIsAProxy* TClass::GetIsAProxy() const
{
return fIsA;
}
TClass *TClass::GetClass(const char *name, Bool_t load)
{
if (!name || !strlen(name)) return 0;
if (!gROOT->GetListOfClasses()) return 0;
TClass *cl = (TClass*)gROOT->GetListOfClasses()->FindObject(name);
if (!cl) {
TString resolvedName = TClassEdit::ResolveTypedef(name,kTRUE).c_str();
cl = (TClass*)gROOT->GetListOfClasses()->FindObject(resolvedName);
}
if (cl) {
if (cl->IsLoaded()) return cl;
load = kTRUE;
if (TClassEdit::IsSTLCont(name)) {
const char *altname = gCint->GetInterpreterTypeName(name);
if (altname && strcmp(altname,name)!=0) {
gROOT->GetListOfClasses()->Remove(cl);
TClass *newcl = GetClass(altname,load);
assert(newcl!=cl);
cl->ReplaceWith(newcl);
delete cl;
return newcl;
}
}
} else {
if (!TClassEdit::IsSTLCont(name)) {
TDataType *objType = gROOT->GetType(name, load);
if (objType) {
const char *typdfName = objType->GetTypeName();
if (typdfName && strcmp(typdfName, name)) {
cl = TClass::GetClass(typdfName, load);
return cl;
}
}
} else {
cl = gROOT->FindSTLClass(name,kFALSE);
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());
else loadedcl = gROOT->LoadClass(name);
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 (TClassEdit::IsSTLCont(name)) {
return gROOT->FindSTLClass(name,kTRUE);
} 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;
char *modifiable_name = new char[strlen(name)*2];
strcpy(modifiable_name,name);
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);
if (!ncl->IsZombie()) {
delete [] modifiable_name;
return ncl;
}
delete ncl;
}
delete [] modifiable_name;
return 0;
}
TClass *TClass::GetClass(const type_info& typeinfo, Bool_t load)
{
if (!gROOT->GetListOfClasses()) return 0;
TClass* cl = fgIdMap->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();
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");
gInterpreter->CreateListOfBaseClasses(this);
}
return fBase;
}
TList *TClass::GetListOfDataMembers()
{
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()
{
if (!fClassInfo) {
if (!fMethod) fMethod = new TList;
return fMethod;
}
if (!fMethod) {
if (!gInterpreter)
Fatal("GetListOfMethods", "gInterpreter not initialized");
gInterpreter->CreateListOfMethods(this);
}
return fMethod;
}
TList *TClass::GetListOfAllPublicMethods()
{
if (!fAllPubMethod) {
fAllPubMethod = new TList;
fAllPubMethod->AddAll(GetListOfMethods());
TIter nextBaseClass(GetListOfBases());
TBaseClass *pB;
TMethod *p;
while ((pB = (TBaseClass*) nextBaseClass())) {
if (!pB->GetClassPointer()) 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()
{
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;
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()) {
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::RemoveRef(TClassRef *ref)
{
if (ref==fRefStart) {
fRefStart = ref->fNext;
if (fRefStart) fRefStart->fPrevious = 0;
ref->fPrevious = ref->fNext = 0;
} else {
TClassRef *next = ref->fNext;
ref->fPrevious->fNext = next;
if (next) next->fPrevious = ref->fPrevious;
ref->fPrevious = ref->fNext = 0;
}
}
void TClass::ReplaceWith(TClass *newcl, Bool_t recurse) const
{
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);
}
}
TIter delIter( &tobedeleted );
while ((acl = (TClass*)delIter())) {
delete acl;
}
}
void TClass::ResetClassInfo(Long_t tagnum)
{
if (fClassInfo && gCint->ClassInfo_Tagnum(fClassInfo) != tagnum) {
gCint->ClassInfo_Init(fClassInfo,(Int_t)tagnum);
if (fBase) {
fBase->Delete();
delete fBase; fBase = 0;
}
}
}
void TClass::ResetMenuList()
{
if (fClassMenuList)
fClassMenuList->Delete();
else
fClassMenuList = new TList();
fClassMenuList->Add(new TClassMenuItem(TClassMenuItem::kPopupStandardList, this));
}
void TClass::MakeCustomMenuList()
{
TClassMenuItem *menuItem;
fClassMenuList->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);
}
}
TMethod *TClass::GetMethodAny(const char *method)
{
if (!fClassInfo) return 0;
TMethod *m;
TIter next(GetListOfMethods());
while ((m = (TMethod *) next())) {
if (strcmp(method, m->GetName()) == 0) return m;
}
return 0;
}
TMethod *TClass::GetMethodAllAny(const char *method)
{
if (!fClassInfo) return 0;
TMethod *m;
TIter next(GetListOfMethods());
while ((m = (TMethod *) next())) {
if (strcmp(method, m->GetName()) == 0) 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;
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(GetListOfMethods());
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
{
if (version == 0) {
version = fClassVersion;
}
if (!fStreamerInfo) {
fStreamerInfo = new TObjArray(version + 10, -1);
} 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) {
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->GetOffsets()) {
sinfo->BuildOld();
}
if (sinfo->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) {
sinfo->Compile();
}
}
if (version == fClassVersion) {
fCurrentInfo = sinfo;
}
return sinfo;
}
void TClass::IgnoreTObjectStreamer(Bool_t ignore)
{
if ( ignore && TestBit(kIgnoreTObjectStreamer)) return;
if (!ignore && !TestBit(kIgnoreTObjectStreamer)) return;
TVirtualStreamerInfo *sinfo = GetCurrentStreamerInfo();
if (sinfo) {
if (sinfo->GetOffsets()) {
Error("IgnoreTObjectStreamer","Must be called before the creation of StreamerInfo");
return;
}
}
if (ignore) 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)
{
void* p = 0;
if (fNew) {
fgCallingNew = defConstructor;
p = fNew(0);
fgCallingNew = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (fClassInfo) {
fgCallingNew = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo());
fgCallingNew = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!fClassInfo && fCollectionProxy) {
fgCallingNew = defConstructor;
p = fCollectionProxy->New();
fgCallingNew = kRealNew;
if (!p) {
Error("New", "cannot create object of class %s", GetName());
}
} else if (!fClassInfo && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
SetObjectStat(kFALSE);
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
Error("New", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
return 0;
}
fgCallingNew = defConstructor;
p = sinfo->New();
fgCallingNew = kRealNew;
SetObjectStat(statsave);
if (p) {
RegisterAddressInRepository("New",p,this);
}
} else {
Error("New", "This cannot happen!");
}
return p;
}
void *TClass::New(void *arena, ENewType defConstructor)
{
void* p = 0;
if (fNew) {
fgCallingNew = defConstructor;
p = fNew(arena);
fgCallingNew = kRealNew;
if (!p) {
Error("New with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (fClassInfo) {
fgCallingNew = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo(),arena);
fgCallingNew = 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) {
fgCallingNew = defConstructor;
p = fCollectionProxy->New(arena);
fgCallingNew = kRealNew;
} else if (!fClassInfo && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
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;
}
fgCallingNew = defConstructor;
p = sinfo->New(arena);
fgCallingNew = kRealNew;
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)
{
void* p = 0;
if (fNewArray) {
fgCallingNew = defConstructor;
p = fNewArray(nElements, 0);
fgCallingNew = kRealNew;
if (!p) {
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
}
} else if (fClassInfo) {
fgCallingNew = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo(),nElements);
fgCallingNew = kRealNew;
if (!p) {
Error("NewArray", "cannot create object of class %s version %d", GetName(), fClassVersion);
}
} else if (!fClassInfo && fCollectionProxy) {
fgCallingNew = defConstructor;
p = fCollectionProxy->NewArray(nElements);
fgCallingNew = kRealNew;
} else if (!fClassInfo && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
SetObjectStat(kFALSE);
TVirtualStreamerInfo* sinfo = GetStreamerInfo();
if (!sinfo) {
Error("NewArray", "Cannot construct class '%s' version %d, no streamer info available!", GetName(), fClassVersion);
return 0;
}
fgCallingNew = defConstructor;
p = sinfo->NewArray(nElements);
fgCallingNew = kRealNew;
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)
{
void* p = 0;
if (fNewArray) {
fgCallingNew = defConstructor;
p = fNewArray(nElements, arena);
fgCallingNew = kRealNew;
if (!p) {
Error("NewArray with placement", "cannot create object of class %s version %d at address %p", GetName(), fClassVersion, arena);
}
} else if (fClassInfo) {
fgCallingNew = defConstructor;
R__LOCKGUARD2(gCINTMutex);
p = gCint->ClassInfo_New(GetClassInfo(),nElements, arena);
fgCallingNew = 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) {
fgCallingNew = defConstructor;
p = fCollectionProxy->NewArray(nElements, arena);
fgCallingNew = kRealNew;
} else if (!fClassInfo && !fCollectionProxy) {
Bool_t statsave = GetObjectStat();
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;
}
fgCallingNew = defConstructor;
p = sinfo->NewArray(nElements, arena);
fgCallingNew = kRealNew;
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) {
gCint->ClassInfo_Destruct(fClassInfo,p);
} else {
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;
std::multimap<void*, Version_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;
knownVersions.insert(ver);
if (ver == fClassVersion) {
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;
std::multimap<void*, Version_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;
knownVersions.insert(ver);
if (ver == fClassVersion) {
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::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) {
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)
{
if (gMmallocDesc) {
void *msave = gMmallocDesc;
gMmallocDesc = 0;
TClass *cl = new TClass(cname, id, info, isa, show, dfil, ifil, dl, il);
gMmallocDesc = msave;
return cl;
}
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)
{
if (gMmallocDesc) {
void *msave = gMmallocDesc;
gMmallocDesc = 0;
TClass *cl = new TClass(cname, id, dfil, ifil, dl, il);
gMmallocDesc = msave;
return cl;
}
return new TClass(cname, id, dfil, ifil, dl, il);
}
TClass::ENewType TClass::IsCallingNew()
{
return fgCallingNew;
}
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) )
{
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)(fStreamerInfo->At(fClassVersion));
if (info && GetListOfDataMembers() && !GetCollectionProxy()
&& (info->GetCheckSum()!=GetCheckSum() && info->GetCheckSum()!=GetCheckSum(1) && info->GetCheckSum()!=GetCheckSum(2)))
{
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);
}
SetBit(kWarned);
}
}
}
}
Long_t TClass::Property() const
{
if (fProperty!=(-1)) return fProperty;
Long_t dummy;
TClass *kl = const_cast<TClass*>(this);
kl->fStreamerType = kNone;
if (InheritsFrom(TObject::Class())) {
kl->SetBit(kIsTObject);
Int_t delta = kl->GetBaseClassOffset(TObject::Class());
if (delta==0) kl->SetBit(kStartWithTObject);
kl->fStreamerType = kTObject;
}
if (fClassInfo) {
kl->fProperty = gCint->ClassInfo_Property(fClassInfo);
if (!gCint->ClassInfo_HasMethod(fClassInfo,"Streamer") ||
!gCint->ClassInfo_IsValidMethod(fClassInfo,"Streamer","TBuffer&",&dummy) ) {
kl->SetBit(kIsForeign);
kl->fStreamerType = kForeign;
} else if ( kl->fStreamerType == kNone ) {
if (strcmp( gCint->ClassInfo_FileName(fClassInfo),"{CINTEX dictionary translator}")==0) {
kl->SetBit(kIsForeign);
}
kl->fStreamerType = kInstrumented;
}
if (fStreamer) kl->fStreamerType = kExternal;
} else {
if (fStreamer) kl->fStreamerType = kExternal;
kl->fStreamerType |= kEmulated;
return 0;
}
return fProperty;
}
void TClass::SetCollectionProxy(const ROOT::TCollectionProxyInfo &info)
{
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;
}
UInt_t TClass::GetCheckSum(UInt_t code) const
{
if (fCheckSum && code == 0) return fCheckSum;
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();
il = name.Length();
for (int i=0; i<il; i++) id = id*3+name[i];
}
}
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 != 1) && prop&kIsEnum) id = id*3 + 1;
int i;
for (i=0; i<il; i++) id = id*3+name[i];
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 != 2) {
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==0) fCheckSum = id;
return id;
}
void TClass::AdoptReferenceProxy(TVirtualRefProxy* proxy)
{
if ( fRefProxy ) {
fRefProxy->Release();
}
fRefProxy = proxy;
if ( fRefProxy ) {
fRefProxy->SetClass(this);
}
}
void TClass::AdoptMemberStreamer(const char *name, TMemberStreamer *p)
{
if (!fRealData) return;
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::Streamer(void *object, TBuffer &b)
{
switch (fStreamerType) {
case kExternal:
case kExternal|kEmulated:
(*GetStreamer())(b,object);
return;
case kTObject:
{
if (!fInterStreamer)
CalculateStreamerOffset();
TObject *tobj = (TObject*)((Long_t)object + fOffsetStreamer);
tobj->Streamer(b);
}
return;
case kTObject|kEmulated : {
b.ReadClassEmulated(this, object);
}
return;
case kInstrumented:
{
CallFunc_t *func = (CallFunc_t*)fInterStreamer;
if (!func) {
func = gCint->CallFunc_Factory();
gCint->CallFunc_SetFuncProto(func,fClassInfo,"Streamer","TBuffer&",&fOffsetStreamer);
fInterStreamer = func;
} else {
gCint->CallFunc_SetArgs(func,"");
}
gCint->CallFunc_SetArg(func,(Long_t)&b);
gCint->CallFunc_Exec(func,(char*)((Long_t)object + fOffsetStreamer) );
}
return;
case kForeign:
case kForeign|kEmulated:
case kInstrumented|kEmulated:
case kEmulated:
{
if (b.IsReading()) {
b.ReadClassBuffer(this, object);
} else {
b.WriteClassBuffer(this, object);
}
}
return;
default:
{
if (fProperty==(-1)) {
Property();
Streamer(object,b);
} else {
Fatal("Streamer", "fStreamerType not properly initialized (%d)", fStreamerType);
}
}
}
}
void TClass::AdoptStreamer(TClassStreamer *str)
{
if (fStreamer) delete fStreamer;
fStreamer = str;
if (str) {
fStreamerType = kExternal | ( fStreamerType&kEmulated );
}
}
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
{
Int_t ninfos = GetStreamerInfos()->GetEntriesFast();
for (Int_t i=-1;i<ninfos;i++) {
TVirtualStreamerInfo *info = (TVirtualStreamerInfo*)GetStreamerInfos()->At(i);
if (!info) continue;
if (info->GetCheckSum() == checksum) {
R__ASSERT(i==info->GetClassVersion() || (i==-1&&info->GetClassVersion()==1));
return info;
}
}
return 0;
}
Bool_t TClass::HasDefaultConstructor() const
{
if (fNew) return kTRUE;
if (!GetClassInfo()) return kFALSE;
return gCint->ClassInfo_HasDefaultConstructor(GetClassInfo());
}
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;
}
Last change: Wed Jun 25 08:35:36 2008
Last generated: 2008-06-25 08:35
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.