#include "TBranchObject.h"
#include "TBasket.h"
#include "TBranchClones.h"
#include "TBrowser.h"
#include "TClass.h"
#include "TClonesArray.h"
#include "TDataMember.h"
#include "TDataType.h"
#include "TFile.h"
#include "TLeafObject.h"
#include "TRealData.h"
#include "TStreamerInfo.h"
#include "TTree.h"
#include "TVirtualPad.h"
ClassImp(TBranchObject)
TBranchObject::TBranchObject()
: TBranch()
{
fNleaves = 1;
fOldObject = 0;
}
TBranchObject::TBranchObject(TTree *tree, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t splitlevel, Int_t compress, Bool_t isptrptr )
: TBranch()
{
Init(tree,0,name,classname,addobj,basketsize,splitlevel,compress,isptrptr);
}
TBranchObject::TBranchObject(TBranch *parent, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t splitlevel, Int_t compress, Bool_t isptrptr )
: TBranch()
{
Init(0,parent,name,classname,addobj,basketsize,splitlevel,compress,isptrptr);
}
void TBranchObject::Init(TTree *tree, TBranch *parent, const char* name, const char* classname, void* addobj, Int_t basketsize, Int_t , Int_t compress, Bool_t isptrptr)
{
if (tree==0 && parent!=0) tree = parent->GetTree();
fTree = tree;
fMother = parent ? parent->GetMother() : this;
fParent = parent;
TClass* cl = TClass::GetClass(classname);
if (!cl) {
Error("TBranchObject", "Cannot find class:%s", classname);
return;
}
if (!isptrptr) {
fOldObject = (TObject*)addobj;
addobj = &fOldObject;
}
char** apointer = (char**) addobj;
TObject* obj = (TObject*) (*apointer);
Bool_t delobj = kFALSE;
if (!obj) {
obj = (TObject*) cl->New();
delobj = kTRUE;
}
tree->BuildStreamerInfo(cl, obj);
if (delobj) {
cl->Destructor(obj);
}
SetName(name);
SetTitle(name);
fCompress = compress;
if ((compress == -1) && tree->GetDirectory()) {
TFile* bfile = tree->GetDirectory()->GetFile();
if (bfile) {
fCompress = bfile->GetCompressionSettings();
}
}
if (basketsize < 100) {
basketsize = 100;
}
fBasketSize = basketsize;
fAddress = (char*) addobj;
fClassName = classname;
fBasketBytes = new Int_t[fMaxBaskets];
fBasketEntry = new Long64_t[fMaxBaskets];
fBasketSeek = new Long64_t[fMaxBaskets];
fOldObject = 0;
for (Int_t i = 0; i < fMaxBaskets; ++i) {
fBasketBytes[i] = 0;
fBasketEntry[i] = 0;
fBasketSeek[i] = 0;
}
TLeaf* leaf = new TLeafObject(this, name, classname);
leaf->SetAddress(addobj);
fNleaves = 1;
fLeaves.Add(leaf);
tree->GetListOfLeaves()->Add(leaf);
SetAutoDelete(kTRUE);
fDirectory = fTree->GetDirectory();
fFileName = "";
}
TBranchObject::~TBranchObject()
{
fBranches.Delete();
}
void TBranchObject::Browse(TBrowser* b)
{
Int_t nbranches = fBranches.GetEntriesFast();
if (nbranches > 1) {
fBranches.Browse(b);
}
if (GetBrowsables() && GetBrowsables()->GetSize()) {
GetBrowsables()->Browse(b);
}
}
Int_t TBranchObject::Fill()
{
Int_t nbytes = 0;
Int_t nbranches = fBranches.GetEntriesFast();
if (nbranches) {
++fEntries;
UpdateAddress();
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches[i];
if (!branch->TestBit(kDoNotProcess)) {
Int_t bc = branch->Fill();
nbytes += bc;
}
}
} else {
if (!TestBit(kDoNotProcess)) {
Int_t bc = TBranch::Fill();
nbytes += bc;
}
}
return nbytes;
}
Int_t TBranchObject::GetEntry(Long64_t entry, Int_t getall)
{
if (TestBit(kDoNotProcess) && !getall) {
return 0;
}
Int_t nbytes;
Int_t nbranches = fBranches.GetEntriesFast();
if (nbranches) {
if (fAddress == 0) {
SetupAddresses();
}
nbytes = 0;
Int_t nb;
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches[i];
if (branch) {
nb = branch->GetEntry(entry, getall);
if (nb < 0) {
return nb;
}
nbytes += nb;
}
}
} else {
nbytes = TBranch::GetEntry(entry, getall);
}
return nbytes;
}
Int_t TBranchObject::GetExpectedType(TClass *&expectedClass,EDataType &expectedType)
{
expectedClass = 0;
expectedType = kOther_t;
TLeafObject* lobj = (TLeafObject*) GetListOfLeaves()->At(0);
if (!lobj) {
Error("GetExpectedType", "Did not find any leaves in %s",GetName());
return 1;
}
expectedClass = lobj->GetClass();
return 0;
}
Bool_t TBranchObject::IsFolder() const
{
Int_t nbranches = fBranches.GetEntriesFast();
if (nbranches >= 1) {
return kTRUE;
}
TList* browsables = const_cast<TBranchObject*>(this)->GetBrowsables();
return browsables && browsables->GetSize();
}
void TBranchObject::Print(Option_t* option) const
{
Int_t nbranches = fBranches.GetEntriesFast();
if (nbranches) {
Printf("*Branch :%-9s : %-54s *", GetName(), GetTitle());
Printf("*Entries : %8d : BranchObject (see below) *", Int_t(fEntries));
Printf("*............................................................................*");
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches.At(i);
if (branch) {
branch->Print(option);
}
}
} else {
TBranch::Print(option);
}
}
void TBranchObject::Reset(Option_t* option)
{
TBranch::Reset(option);
Int_t nbranches = fBranches.GetEntriesFast();
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches[i];
branch->Reset(option);
}
}
void TBranchObject::ResetAfterMerge(TFileMergeInfo *info)
{
TBranch::ResetAfterMerge(info);
Int_t nbranches = fBranches.GetEntriesFast();
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches[i];
branch->ResetAfterMerge(info);
}
}
void TBranchObject::SetAddress(void* add)
{
if (TestBit(kDoNotProcess)) {
return;
}
if (Long_t(add) == -1) {
SetBit(kWarn);
return;
}
fReadEntry = -1;
Int_t nbranches = fBranches.GetEntriesFast();
TLeaf* leaf = (TLeaf*) fLeaves.UncheckedAt(0);
if (leaf) {
leaf->SetAddress(add);
}
fAddress = (char*) add;
char** ppointer = (char**) add;
char* obj = 0;
if (ppointer) {
obj = *ppointer;
}
TClass* cl = TClass::GetClass(fClassName.Data());
if (!cl) {
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* br = (TBranch*) fBranches[i];
br->SetAddress(obj);
}
return;
}
if (ppointer && !obj) {
obj = (char*) cl->New();
*ppointer = obj;
}
if (!cl->GetListOfRealData()) {
cl->BuildRealData(obj);
}
if (cl->InheritsFrom(TClonesArray::Class())) {
if (ppointer) {
TClonesArray* clones = (TClonesArray*) *ppointer;
if (!clones) {
Error("SetAddress", "Pointer to TClonesArray is null");
return;
}
TClass* clm = clones->GetClass();
if (clm) {
clm->BuildRealData();
clm->GetStreamerInfo();
}
}
}
char* fullname = new char[200];
const char* bname = GetName();
Int_t isDot = 0;
if (bname[strlen(bname)-1] == '.') {
isDot = 1;
}
char* pointer = 0;
TRealData* rd = 0;
TIter next(cl->GetListOfRealData());
while ((rd = (TRealData*) next())) {
if (rd->TestBit(TRealData::kTransient)) continue;
TDataMember* dm = rd->GetDataMember();
if (!dm || !dm->IsPersistent()) {
continue;
}
const char* rdname = rd->GetName();
TDataType* dtype = dm->GetDataType();
Int_t code = 0;
if (dtype) {
code = dm->GetDataType()->GetType();
}
Int_t offset = rd->GetThisOffset();
if (ppointer) {
pointer = obj + offset;
}
TBranch* branch = 0;
if (dm->IsaPointer()) {
TClass* clobj = 0;
if (!dm->IsBasic()) {
clobj = TClass::GetClass(dm->GetTypeName());
}
if (clobj && clobj->InheritsFrom(TClonesArray::Class())) {
if (isDot) {
snprintf(fullname,200, "%s%s", bname, &rdname[1]);
} else {
snprintf(fullname,200, "%s", &rdname[1]);
}
branch = (TBranch*) fBranches.FindObject(fullname);
} else {
if (!clobj) {
const char* index = dm->GetArrayIndex();
if (strlen(index) == 0) {
if (code == 1) {
if (isDot) {
snprintf(fullname,200, "%s%s", bname, &rdname[0]);
} else {
snprintf(fullname,200, "%s", &rdname[0]);
}
} else {
continue;
}
}
if (isDot) {
snprintf(fullname,200, "%s%s", bname, &rdname[0]);
} else {
snprintf(fullname,200, "%s", &rdname[0]);
}
UInt_t cursor;
UInt_t pos;
for (cursor = 0, pos = 0; cursor < strlen(fullname); ++cursor) {
if (fullname[cursor] != '*') {
fullname[pos++] = fullname[cursor];
}
}
fullname[pos] = '\0';
branch = (TBranch*) fBranches.FindObject(fullname);
} else {
if (!clobj->InheritsFrom(TObject::Class())) {
continue;
}
if (isDot) {
snprintf(fullname,200, "%s%s", bname, &rdname[1]);
} else {
snprintf(fullname,200, "%s", &rdname[1]);
}
branch = (TBranch*) fBranches.FindObject(fullname);
}
}
} else {
if (dm->IsBasic()) {
if (isDot) {
snprintf(fullname,200, "%s%s", bname, &rdname[0]);
} else {
snprintf(fullname,200, "%s", &rdname[0]);
}
branch = (TBranch*) fBranches.FindObject(fullname);
}
}
if (branch) {
branch->SetAddress(pointer);
}
}
delete[] fullname;
}
void TBranchObject::SetAutoDelete(Bool_t autodel)
{
TBranch::SetAutoDelete(autodel);
Int_t nbranches = fBranches.GetEntriesFast();
for (Int_t i=0;i<nbranches;i++) {
TBranch *branch = (TBranch*)fBranches[i];
branch->SetAutoDelete(autodel);
}
}
void TBranchObject::SetBasketSize(Int_t buffsize)
{
TBranch::SetBasketSize(buffsize);
Int_t nbranches = fBranches.GetEntriesFast();
for (Int_t i = 0; i < nbranches; ++i) {
TBranch* branch = (TBranch*) fBranches[i];
branch->SetBasketSize(fBasketSize);
}
}
void TBranchObject::Streamer(TBuffer& R__b)
{
if (R__b.IsReading()) {
R__b.ReadClassBuffer(TBranchObject::Class(), this);
} else {
TDirectory* dirsav = fDirectory;
fDirectory = 0;
R__b.WriteClassBuffer(TBranchObject::Class(), this);
R__b.ForceWriteInfo(TClass::GetClass(fClassName.Data())->GetStreamerInfo(), kTRUE);
if (!dirsav) {
return;
}
if (!dirsav->IsWritable()) {
fDirectory = dirsav;
return;
}
TDirectory* pdirectory = fTree->GetDirectory();
if (!pdirectory) {
fDirectory = dirsav;
return;
}
const char* treeFileName = pdirectory->GetFile()->GetName();
TBranch* mother = GetMother();
const char* motherFileName = treeFileName;
if (mother && (mother != this)) {
motherFileName = mother->GetFileName();
}
if ((fFileName.Length() > 0) && strcmp(motherFileName, fFileName.Data())) {
dirsav->WriteTObject(this);
}
fDirectory = dirsav;
}
}
void TBranchObject::SetupAddresses()
{
if (fAddress == 0) {
if (!TestBit(kWarn)) {
TClass* cl = TClass::GetClass(fClassName);
if (cl) {
TObject** voidobj = (TObject**) new Long_t[1];
*voidobj = (TObject*) cl->New();
SetAddress(voidobj);
} else {
Warning("GetEntry", "Cannot get class: %s", fClassName.Data());
SetBit(kWarn);
}
}
}
}
void TBranchObject::UpdateAddress()
{
void** ppointer = (void**) fAddress;
if (!ppointer) {
return;
}
TObject* obj = (TObject*) (*ppointer);
if (obj != fOldObject) {
fOldObject = obj;
SetAddress(fAddress);
}
}