#include "TEntryList.h"
#include "TEntryListBlock.h"
#include "TError.h"
#include "TKey.h"
#include "TTree.h"
#include "TFile.h"
#include "TRegexp.h"
#include "TSystem.h"
ClassImp(TEntryList)
TEntryList::TEntryList() : fEntriesToProcess(0)
{
fLists = 0;
fCurrent = 0;
fBlocks = 0;
fN = 0;
fNBlocks = 0;
fTreeName = "";
fFileName = "";
fStringHash = 0;
fTreeNumber = -1;
fDirectory = 0;
fReapply = kFALSE;
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fShift = kFALSE;
}
TEntryList::TEntryList(const char *name, const char *title) :
TNamed(name, title),
fEntriesToProcess(0)
{
fLists = 0;
fCurrent = 0;
fBlocks = 0;
fN = 0;
fNBlocks = 0;
fTreeName = "";
fFileName = "";
fStringHash = 0;
fTreeNumber = -1;
fReapply = kFALSE;
fDirectory = gDirectory;
if (fDirectory) fDirectory->Append(this);
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fShift = kFALSE;
}
TEntryList::TEntryList(const char *name, const char *title, const TTree *tree):TNamed(name, title)
{
fLists = 0;
fCurrent = 0;
fBlocks = 0;
fN = 0;
fNBlocks = 0;
fTreeNumber = -1;
TEntryList::SetTree(tree);
fReapply = kFALSE;
fDirectory = gDirectory;
if (fDirectory) fDirectory->Append(this);
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fShift = kFALSE;
}
TEntryList::TEntryList(const char *name, const char *title, const char *treename, const char *filename) : TNamed(name, title),fEntriesToProcess(0)
{
fLists = 0;
fCurrent = 0;
fBlocks = 0;
fNBlocks = 0;
fN = 0;
SetTree(treename, filename);
fTreeNumber = -1;
fReapply = kFALSE;
fDirectory = gDirectory;
if (fDirectory) fDirectory->Append(this);
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fShift = kFALSE;
}
TEntryList::TEntryList(const TTree *tree) : fEntriesToProcess(0)
{
fLists = 0;
fCurrent = 0;
fBlocks = 0;
fNBlocks = 0;
fN = 0;
SetTree(tree);
fTreeNumber = -1;
fReapply = kFALSE;
fDirectory = gDirectory;
if (fDirectory) fDirectory->Append(this);
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fShift = kFALSE;
}
TEntryList::TEntryList(const TEntryList &elist) : TNamed(elist)
{
fNBlocks = elist.fNBlocks;
fTreeName = elist.fTreeName;
fFileName = elist.fFileName;
fStringHash = elist.fStringHash;
fTreeNumber = elist.fTreeNumber;
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fN = elist.fN;
fShift = elist.fShift;
fLists = 0;
fBlocks = 0;
fReapply = elist.fReapply;
fCurrent = 0;
fEntriesToProcess = elist.fEntriesToProcess;
if (elist.fLists){
fLists = new TList();
TEntryList *el1 = 0;
TEntryList *el2 = 0;
TIter next(elist.fLists);
while((el1 = (TEntryList*)next())){
el2 = new TEntryList(*el1);
if (el1==elist.fCurrent)
fCurrent = el2;
fLists->Add(el2);
}
} else {
if (elist.fBlocks){
TEntryListBlock *block1 = 0;
TEntryListBlock *block2 = 0;
fBlocks = new TObjArray();
for (Int_t i=0; i<fNBlocks; i++){
block1 = (TEntryListBlock*)elist.fBlocks->UncheckedAt(i);
block2 = new TEntryListBlock(*block1);
fBlocks->Add(block2);
}
}
fCurrent = this;
}
fDirectory = 0;
}
TEntryList::~TEntryList()
{
if (fBlocks){
fBlocks->Delete();
delete fBlocks;
}
fBlocks = 0;
if (fLists){
fLists->Delete();
delete fLists;
}
fLists = 0;
if (fDirectory) fDirectory->Remove(this);
fDirectory = 0;
}
void TEntryList::Add(const TEntryList *elist)
{
if (fN==0){
if (!fLists && fTreeName=="" && fFileName==""){
fNBlocks = elist->fNBlocks;
fTreeName = elist->fTreeName;
fFileName = elist->fFileName;
fStringHash = elist->fStringHash;
fTreeNumber = elist->fTreeNumber;
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fN = elist->fN;
if (elist->fLists){
fLists = new TList();
TEntryList *el1 = 0;
TEntryList *el2 = 0;
TIter next(elist->fLists);
while((el1 = (TEntryList*)next())){
el2 = new TEntryList(*el1);
if (el1==elist->fCurrent)
fCurrent = el2;
fLists->Add(el2);
}
} else {
if (elist->fBlocks){
TEntryListBlock *block1 = 0;
TEntryListBlock *block2 = 0;
fBlocks = new TObjArray();
for (Int_t i=0; i<fNBlocks; i++){
block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
block2 = new TEntryListBlock(*block1);
fBlocks->Add(block2);
}
}
fCurrent = 0;
}
return;
}
}
if (!fLists){
if (!elist->fLists){
if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) && !strcmp(elist->fFileName.Data(),fFileName.Data())){
if (!elist->fBlocks)
return;
if (!fBlocks){
TEntryListBlock *block1 = 0;
TEntryListBlock *block2 = 0;
fNBlocks = elist->fNBlocks;
fN = elist->fN;
fBlocks = new TObjArray();
for (Int_t i=0; i<fNBlocks; i++){
block1 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
block2 = new TEntryListBlock(*block1);
fBlocks->Add(block2);
}
return;
}
TEntryListBlock *block1=0;
TEntryListBlock *block2=0;
Int_t i;
Int_t nmin = TMath::Min(fNBlocks, elist->fNBlocks);
Long64_t nnew, nold;
for (i=0; i<nmin; i++){
block1 = (TEntryListBlock*)fBlocks->UncheckedAt(i);
block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
nold = block1->GetNPassed();
nnew = block1->Merge(block2);
fN = fN - nold + nnew;
}
if (fNBlocks<elist->fNBlocks){
Int_t nmax = elist->fNBlocks;
for (i=nmin; i<nmax; i++){
block2 = (TEntryListBlock*)elist->fBlocks->UncheckedAt(i);
block1 = new TEntryListBlock(*block2);
fBlocks->Add(block1);
fN+=block1->GetNPassed();
fNBlocks++;
}
}
fLastIndexQueried = -1;
fLastIndexReturned = 0;
} else {
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fLists = new TList();
TEntryList *el = new TEntryList();
el->fTreeName = fTreeName;
el->fFileName = fFileName;
el->fBlocks = fBlocks;
fBlocks = 0;
el->fNBlocks = fNBlocks;
el->fN = fN;
el->fLastIndexQueried = -1;
el->fLastIndexReturned = 0;
fLists->Add(el);
el = new TEntryList(*elist);
el->fLastIndexQueried = -1;
el->fLastIndexReturned = 0;
fLists->Add(el);
fN+=el->GetN();
fCurrent = 0;
}
} else {
TEntryList *el = 0;
TIter next(elist->fLists);
while ((el = (TEntryList*)next())){
Add(el);
}
fCurrent = 0;
}
} else {
if (!elist->fLists){
TIter next(fLists);
TEntryList *el = 0;
Bool_t found = kFALSE;
while ((el = (TEntryList*)next())){
if (!strcmp(el->fTreeName.Data(), elist->fTreeName.Data()) &&
!strcmp(el->fFileName.Data(), elist->fFileName.Data())){
Long64_t oldn = el->GetN();
el->Add(elist);
found = kTRUE;
fN = fN - oldn + el->GetN();
break;
}
}
if (!found){
el = new TEntryList(*elist);
el->fLastIndexQueried = -1;
el->fLastIndexReturned = 0;
fLists->Add(el);
fN+=el->GetN();
}
} else {
TEntryList *el = 0;
TIter next(elist->fLists);
while ((el = (TEntryList*)next())){
Add(el);
}
fCurrent = 0;
}
if (fCurrent){
if (fCurrent->fBlocks){
Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
block->ResetIndices();
fCurrent->fLastIndexReturned = 0;
fCurrent->fLastIndexQueried = -1;
}
}
fCurrent = 0;
}
}
Int_t TEntryList::Contains(Long64_t entry, TTree *tree)
{
if (!tree){
if (fBlocks) {
TEntryListBlock *block = 0;
Int_t nblock = entry/kBlockSize;
if (nblock >= fNBlocks) return 0;
block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
return block->Contains(entry-nblock*kBlockSize);
}
if (fLists) {
if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
return fCurrent->Contains(entry);
}
return 0;
} else {
Long64_t localEntry = tree->LoadTree(entry);
SetTree(tree->GetTree());
if (fCurrent)
return fCurrent->Contains(localEntry);
}
return 0;
}
void TEntryList::DirectoryAutoAdd(TDirectory* dir)
{
SetDirectory(dir);
}
Bool_t TEntryList::Enter(Long64_t entry, TTree *tree)
{
if (!tree){
if (!fLists) {
if (!fBlocks) fBlocks = new TObjArray();
TEntryListBlock *block = 0;
Long64_t nblock = entry/kBlockSize;
if (nblock >= fNBlocks) {
if (fNBlocks>0){
block = (TEntryListBlock*)fBlocks->UncheckedAt(fNBlocks-1);
if (!block) return 0;
block->OptimizeStorage();
}
for (Int_t i=fNBlocks; i<=nblock; i++){
block = new TEntryListBlock();
fBlocks->Add(block);
}
fNBlocks = nblock+1;
}
block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
if (block->Enter(entry-nblock*kBlockSize)) {
fN++;
return 1;
}
} else {
if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
if (fCurrent->Enter(entry)) {
if (fLists)
fN++;
return 1;
}
}
} else {
Long64_t localentry = tree->LoadTree(entry);
SetTree(tree->GetTree());
if (fCurrent){
if (fCurrent->Enter(localentry)) {
if (fLists)
fN++;
return 1;
}
}
}
return 0;
}
Bool_t TEntryList::Remove(Long64_t entry, TTree *tree)
{
if (!tree){
if (!fLists) {
if (!fBlocks) return 0;
TEntryListBlock *block = 0;
Long64_t nblock = entry/kBlockSize;
block = (TEntryListBlock*)fBlocks->UncheckedAt(nblock);
if (!block) return 0;
Long64_t blockindex = entry - nblock*kBlockSize;
if (block->Remove(blockindex)){
fN--;
return 1;
}
} else {
if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
if (fCurrent->Remove(entry)){
if (fLists)
fN--;
return 1;
}
}
} else {
Int_t localentry = tree->LoadTree(entry);
SetTree(tree->GetTree());
if (fCurrent){
if (fCurrent->Remove(localentry)) {
if (fLists)
fN--;
return 1;
}
}
}
return 0;
}
Long64_t TEntryList::GetEntry(Int_t index)
{
if (index>=fN){
return -1;
}
if (index==fLastIndexQueried+1){
return Next();
} else {
if (fBlocks) {
TEntryListBlock *block = 0;
Long64_t total_passed = 0;
Int_t i=0;
while (total_passed<=index && i<fNBlocks){
block=(TEntryListBlock*)fBlocks->UncheckedAt(i);
total_passed+=block->GetNPassed();
i++;
}
i--;
total_passed-=block->GetNPassed();
if (i!=fLastIndexReturned/kBlockSize){
block = (TEntryListBlock*)fBlocks->UncheckedAt(fLastIndexReturned/kBlockSize);
block->ResetIndices();
block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
}
Long64_t localindex = index - total_passed;
Long64_t blockindex = block->GetEntry(localindex);
if (blockindex < 0) return -1;
Long64_t res = i*kBlockSize + blockindex;
fLastIndexQueried = index;
fLastIndexReturned = res;
return res;
} else {
if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
TIter next(fLists);
TEntryList *templist;
Long64_t ntotal = 0;
if (fCurrent){
if (fCurrent->fBlocks){
Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
block->ResetIndices();
fCurrent->fLastIndexReturned = 0;
fCurrent->fLastIndexQueried = -1;
}
}
while ((templist = (TEntryList*)next())){
if (!fShift){
ntotal += templist->GetN();
} else {
if (templist->GetTreeNumber() >= 0)
ntotal += templist->GetN();
}
if (ntotal > index)
break;
}
fCurrent = templist;
if (!fCurrent) return -1;
Long64_t localentry = index - (ntotal - fCurrent->GetN());
fLastIndexQueried = index;
fLastIndexReturned = fCurrent->GetEntry(localentry);
return fLastIndexReturned;
}
}
return -1;
}
Long64_t TEntryList::GetEntryAndTree(Int_t index, Int_t &treenum)
{
Long64_t result = GetEntry(index);
if (fLists)
treenum = fCurrent->fTreeNumber;
else
treenum = fTreeNumber;
if (treenum<0) return -1;
return result;
}
void TEntryList::GetFileName(const char *filename, TString &fn, Bool_t *local)
{
TUrl u(filename, kTRUE);
if (local) *local = (!strcmp(u.GetProtocol(), "file")) ? kTRUE : kFALSE;
if (strlen(u.GetAnchor()) > 0) {
fn.Form("%s#%s", u.GetFile(), u.GetAnchor());
} else {
fn = u.GetFile();
}
return;
}
TEntryList *TEntryList::GetEntryList(const char *treename, const char *filename, Option_t *opt)
{
if (gDebug > 1)
Info("GetEntryList","tree: %s, file: %s",
(treename ? treename : "-"), (filename ? filename : "-"));
if (!treename || !filename) return 0;
TString option = opt;
option.ToUpper();
Bool_t nexp = option.Contains("NE");
TString fn;
Bool_t local;
GetFileName(filename, fn, &local);
if (nexp) local = kFALSE;
if (gDebug > 1)
Info("GetEntryList", "file: %s, local? %d", filename, local);
if (!fLists){
if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data()))){
return this;
} else {
if (!nexp && local){
gSystem->ExpandPathName(fn);
if (!gSystem->IsAbsoluteFileName(fn))
gSystem->PrependPathName(gSystem->pwd(), fn);
fn = gSystem->UnixPathName(fn);
if (!strcmp(treename, fTreeName.Data()) && !(strcmp(fn.Data(), fFileName.Data())))
return this;
}
return 0;
}
}
TString stotal = treename;
stotal.Append(fn);
ULong_t newhash = stotal.Hash();
TIter next(fLists);
TEntryList *templist;
while ((templist = (TEntryList*)next())){
if (templist->fStringHash==0){
stotal = templist->fTreeName + templist->fFileName;
templist->fStringHash = stotal.Hash();
}
if (gDebug > 1)
Info("GetEntryList", "file: %s (fn: %s), hash: %lu, element hash: %lu",
filename, fn.Data(), newhash, templist->fStringHash);
if (newhash == templist->fStringHash){
if (!strcmp(templist->GetTreeName(), treename) && !strcmp(templist->GetFileName(), fn.Data())){
return templist;
}
}
}
if (!nexp && local){
TString longname = fn;
gSystem->ExpandPathName(longname);
if (!gSystem->IsAbsoluteFileName(longname))
gSystem->PrependPathName(gSystem->pwd(), longname);
longname = gSystem->UnixPathName(longname);
stotal = treename;
stotal.Append(longname);
newhash = stotal.Hash();
next.Reset();
while ((templist = (TEntryList*)next())){
if (templist->fStringHash==0){
stotal = templist->fTreeName + templist->fFileName;
templist->fStringHash = stotal.Hash();
}
if (gDebug > 1)
Info("GetEntryList", "file: %s (longname: %s), hash: %lu, element hash: %lu",
filename, longname.Data(), newhash, templist->fStringHash);
if (newhash == templist->fStringHash){
if (templist->fTreeName == treename && templist->fFileName == longname){
return templist;
}
}
}
}
return 0;
}
Int_t TEntryList::Merge(TCollection *list)
{
if (!list) return -1;
TIter next(list);
TEntryList *elist = 0;
while ((elist = (TEntryList*)next())) {
if (!elist->InheritsFrom(TEntryList::Class())) {
Error("Add","Attempt to add object of class: %s to a %s",elist->ClassName(),this->ClassName());
return -1;
}
Add(elist);
}
return 0;
}
Long64_t TEntryList::Next()
{
Long64_t result;
if (fN == fLastIndexQueried+1 || fN==0){
return -1;
}
if (fBlocks){
Int_t iblock = fLastIndexReturned/kBlockSize;
TEntryListBlock *current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
result = current_block->Next();
if (result>=0) {
fLastIndexQueried++;
fLastIndexReturned = result+kBlockSize*iblock;
return fLastIndexReturned;
}
else {
while (result<0 && iblock<fNBlocks-1) {
current_block->ResetIndices();
iblock++;
current_block = (TEntryListBlock*)fBlocks->UncheckedAt(iblock);
current_block->ResetIndices();
result = current_block->Next();
}
if (result<0) {
fLastIndexQueried = -1;
fLastIndexReturned = 0;
return -1;
}
fLastIndexQueried++;
fLastIndexReturned = result+kBlockSize*iblock;
return fLastIndexReturned;
}
} else {
if (!fCurrent) {
fCurrent = (TEntryList*)fLists->First();
if (!fCurrent) return 0;
if (fShift) {
while (fCurrent->GetTreeNumber()<0) {
fCurrent = (TEntryList*)fLists->After(fCurrent);
if (!fCurrent) return 0;
}
}
}
result = fCurrent->Next();
if (result>=0) {
fLastIndexQueried++;
fLastIndexReturned = result;
return result;
} else {
if (fCurrent){
if (fCurrent->fBlocks){
Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
block->ResetIndices();
fCurrent->fLastIndexReturned = 0;
fCurrent->fLastIndexQueried = -1;
}
}
while (result<0 && fCurrent!=((TEntryList*)fLists->Last())){
if (!fCurrent) return 0;
fCurrent->fLastIndexQueried = -1;
fCurrent->fLastIndexReturned = 0;
fCurrent = (TEntryList*)fLists->After(fCurrent);
if (!fCurrent) return 0;
if (!fShift)
result = fCurrent->Next();
else {
if (fCurrent->GetTreeNumber() >= 0)
result = fCurrent->Next();
}
}
fLastIndexQueried++;
fLastIndexReturned = result;
return result;
}
}
}
void TEntryList::OptimizeStorage()
{
if (fBlocks){
TEntryListBlock *block = 0;
for (Int_t i=0; i<fNBlocks; i++){
block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
block->OptimizeStorage();
}
}
}
void TEntryList::Print(const Option_t* option) const
{
TString opt = option;
opt.ToUpper();
if (fBlocks) {
Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
if (opt.Contains("A")){
TEntryListBlock* block = 0;
for (Int_t i=0; i<fNBlocks; i++){
block = (TEntryListBlock*)fBlocks->UncheckedAt(i);
Int_t shift = i*kBlockSize;
block->PrintWithShift(shift);
}
}
}
else {
TEntryList *elist = 0;
if (fN>0){
TIter next(fLists);
while((elist = (TEntryList*)next())){
elist->Print(option);
}
} else {
if (!fLists) Printf("%s %s %lld", fTreeName.Data(), fFileName.Data(), fN);
else {
TIter next(fLists);
while ((elist = (TEntryList*)next())){
Printf("%s %s %lld", elist->GetTreeName(), elist->GetFileName(), elist->GetN());
}
}
}
}
}
void TEntryList::Reset()
{
if (fBlocks){
fBlocks->Delete();
delete fBlocks;
fBlocks = 0;
}
if (fLists){
if (!((TEntryList*)fLists->First())->GetDirectory()){
fLists->Delete();
}
delete fLists;
fLists = 0;
}
fCurrent = 0;
fBlocks = 0;
fNBlocks = 0;
fN = 0;
fTreeName = "";
fFileName = "";
fStringHash = 0;
fTreeNumber = -1;
fLastIndexQueried = -1;
fLastIndexReturned = 0;
fReapply = kFALSE;
}
void TEntryList::SetDirectory(TDirectory *dir)
{
if (fDirectory == dir) return;
if (fDirectory) fDirectory->Remove(this);
fDirectory = dir;
if (fDirectory) fDirectory->Append(this);
}
void TEntryList::SetTree(const char *treename, const char *filename)
{
TEntryList *elist = 0;
TString fn;
GetFileName(filename, fn);
TString stotal = treename;
stotal.Append(fn.Data());
ULong_t newhash = stotal.Hash();
if (fLists) {
if (!fCurrent) fCurrent = (TEntryList*)fLists->First();
if (fCurrent->fStringHash == 0){
stotal = fCurrent->fTreeName + fCurrent->fFileName;
fCurrent->fStringHash = stotal.Hash();
}
if (newhash == fCurrent->fStringHash){
if (!strcmp(fCurrent->fTreeName, treename) && !strcmp(fCurrent->fFileName, fn.Data())){
return;
}
}
TIter next(fLists);
while ((elist = (TEntryList*)next())){
if (newhash == elist->fStringHash){
if (elist->fTreeName == treename && elist->fFileName == fn.Data()) {
if (fCurrent->fBlocks){
Int_t currentblock = (fCurrent->fLastIndexReturned)/kBlockSize;
TEntryListBlock *block = (TEntryListBlock*)fCurrent->fBlocks->UncheckedAt(currentblock);
block->ResetIndices();
fCurrent->fLastIndexReturned = 0;
fCurrent->fLastIndexQueried = -1;
}
fCurrent = elist;
fLastIndexQueried = -3;
return;
}
}
}
elist = new TEntryList("", "", treename, fn.Data());
if (elist->GetDirectory()) {
elist->GetDirectory()->Remove(elist);
elist->SetDirectory(0);
}
fLists->Add(elist);
fCurrent = elist;
return;
} else {
if (fN==0 && fTreeName=="" && fFileName==""){
fTreeName = treename;
fFileName = fn;
stotal = fTreeName + fFileName;
fStringHash = newhash;
fCurrent = this;
} else {
if (fStringHash == 0){
stotal = fTreeName + fFileName;
fStringHash = stotal.Hash();
}
if (newhash != fStringHash){
fLists = new TList();
elist = new TEntryList();
elist->fTreeName = fTreeName;
elist->fFileName = fFileName;
elist->fStringHash = fStringHash;
elist->fN = fN;
elist->fTreeNumber = fTreeNumber;
elist->fBlocks = fBlocks;
fBlocks = 0;
elist->fNBlocks = fNBlocks;
fLists->Add(elist);
elist = new TEntryList("", "", treename, fn.Data());
if (elist->GetDirectory()) {
elist->GetDirectory()->Remove(elist);
elist->SetDirectory(0);
}
fLists->Add(elist);
fCurrent = elist;
fLastIndexQueried = -3;
}
else {
return;
}
}
}
}
void TEntryList::SetTree(const TTree *tree)
{
if (!tree) return;
auto thisTree = tree->GetTree();
if (!thisTree) return;
TString treename;
if (TFile::Class() == tree->GetDirectory()->IsA())
treename = thisTree->GetName();
else {
treename = TString::Format("%s/%s",tree->GetDirectory()->GetName(),thisTree->GetName());
}
TString filename;
if (tree->GetTree()->GetCurrentFile()){
filename = tree->GetTree()->GetCurrentFile()->GetName();
TUrl url(filename.Data(), kTRUE);
if (!strcmp(url.GetProtocol(), "file")){
gSystem->ExpandPathName(filename);
if (!gSystem->IsAbsoluteFileName(filename))
gSystem->PrependPathName(gSystem->pwd(), filename);
filename = gSystem->UnixPathName(filename);
url.SetFile(filename);
}
filename = url.GetUrl();
} else {
filename = "";
}
SetTree(treename, filename);
}
void TEntryList::Subtract(const TEntryList *elist)
{
TEntryList *templist = 0;
if (!fLists){
if (!fBlocks) return;
if (!elist->fLists){
if (!strcmp(elist->fTreeName.Data(),fTreeName.Data()) &&
!strcmp(elist->fFileName.Data(),fFileName.Data())){
Long64_t n2 = elist->GetN();
Long64_t entry;
for (Int_t i=0; i<n2; i++){
entry = (const_cast<TEntryList*>(elist))->GetEntry(i);
Remove(entry);
}
} else {
return;
}
} else {
TIter next1(elist->GetLists());
templist = 0;
Bool_t found = kFALSE;
while ((templist = (TEntryList*)next1())){
if (!strcmp(templist->fTreeName.Data(),fTreeName.Data()) &&
!strcmp(templist->fFileName.Data(),fFileName.Data())){
found = kTRUE;
break;
}
}
if (found) {
Subtract(templist);
}
}
} else {
TIter next2(fLists);
templist = 0;
Long64_t oldn=0;
while ((templist = (TEntryList*)next2())){
oldn = templist->GetN();
templist->Subtract(elist);
fN = fN - oldn + templist->GetN();
}
}
return;
}
TEntryList operator||(TEntryList &elist1, TEntryList &elist2)
{
TEntryList eresult = elist1;
eresult.Print("all");
eresult.Add(&elist2);
eresult.Print("all");
return eresult;
}
Int_t TEntryList::RelocatePaths(const char *newroot, const char *oldroot)
{
if (!newroot || (newroot && strlen(newroot) <= 0)) {
Warning("RelocatePaths", "the new location must be given!");
return -1;
}
if (strlen(GetName()) > 0)
Info("RelocatePaths", "'%s': relocating paths '%s' to '%s'",
GetName(), oldroot ? oldroot : "*", newroot);
Int_t nrl = 0, xnrl = 0;
if (fLists) {
TIter nxl(fLists);
TEntryList *enl = 0;
while ((enl = (TEntryList *) nxl())) {
if ((xnrl = enl->RelocatePaths(newroot, oldroot)) < 0) {
Warning("RelocatePaths", "problems relocating '%s'", enl->GetName());
} else {
nrl += xnrl;
}
}
}
TString temp;
Ssiz_t lo = 0;
if (oldroot && (lo = strlen(oldroot)) > 0) {
if (fFileName.BeginsWith(oldroot)) {
fFileName.Replace(0, lo, newroot);
nrl++;
}
} else {
Ssiz_t ilst = fFileName.Last('/');
if (ilst != kNPOS) {
fFileName.Replace(0, ilst, newroot);
} else {
fFileName.Insert(0, TString::Format("%s/", newroot));
}
nrl++;
}
if (fStringHash != 0) {
temp.Form("%s%s", fTreeName.Data(), fFileName.Data());
fStringHash = temp.Hash();
}
return nrl;
}
Int_t TEntryList::Relocate(const char *fn,
const char *newroot, const char *oldroot, const char *enlnm)
{
TFile *fl = TFile::Open(fn, "UPDATE");
if (!fl || (fl&& fl->IsZombie())) {
::Error("TEntryList::Relocate", "file '%s' cannot be open for updating", fn);
return -1;
}
Int_t nrl = 0;
TString nm(enlnm);
if (nm.IsNull()) nm = "*";
TRegexp nmrg(nm, kTRUE);
TIter nxk(fl->GetListOfKeys());
TKey *key = 0;
while ((key = (TKey *) nxk())) {
if (!strcmp(key->GetClassName(), "TEntryList")) {
TString knm(key->GetName());
if (knm.Index(nmrg) != kNPOS) {
TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(knm));
if (enl) {
Int_t xnrl = enl->RelocatePaths(newroot, oldroot);
if (xnrl >= 0) {
enl->Write(knm, TObject::kOverwrite);
nrl += xnrl;
} else {
::Error("TEntryList::Relocate", "problems relocating '%s' ...", enl->GetName());
}
}
}
}
}
fl->Close();
delete fl;
return nrl;
}
static Int_t GetCommonString(TString a, TString b, TString &c)
{
if (a == b) {
c = a;
return 3;
}
if (a.IsNull()) {
c = "";
return 1;
}
if (b.IsNull()) {
c = "";
return 2;
}
Bool_t ashort = (a.Length() > b.Length()) ? kFALSE : kTRUE;
Ssiz_t len = (ashort) ? a.Length() : b.Length();
Int_t lcom = 0;
for (Int_t i = 0; i < len; i++) {
if (a[i] != b[i]) break;
lcom++;
}
if (lcom == len) {
c = ashort ? a : b;
return ashort ? 1 : 2;
}
c = a(0,lcom);
return 0;
}
Int_t TEntryList::ScanPaths(TList *roots, Bool_t notify)
{
TList *xrl = roots ? roots : new TList;
Int_t nrl = 0;
if (fLists) {
TIter nxl(fLists);
TEntryList *enl = 0;
while ((enl = (TEntryList *) nxl()))
nrl += enl->ScanPaths(xrl, kFALSE);
}
Bool_t newobjs = kTRUE;
TString path = gSystem->DirName(fFileName), com;
TObjString *objs = 0;
TIter nxr(xrl);
while ((objs = (TObjString *) nxr())) {
Int_t rc = 0;
if ((rc = GetCommonString(path, objs->GetString(), com)) != 2) {
TUrl ucom(com);
if (strlen(ucom.GetFile()) > 0 && strcmp(ucom.GetFile(), "/")) {
objs->SetString(com.Data());
newobjs = kFALSE;
break;
}
}
}
if (newobjs) xrl->Add(new TObjString(path));
nrl = xrl->GetSize();
if (notify) {
Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
Printf(" * Entry-list: %s", GetName());
Printf(" * %d commont root paths found", nrl);
nxr.Reset();
while ((objs = (TObjString *) nxr())) {
Printf(" * %s", objs->GetName());
}
Printf(" * ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ *");
}
if (xrl != roots) {
xrl->SetOwner(kTRUE);
SafeDelete(xrl);
}
return nrl;
}
Int_t TEntryList::Scan(const char *fn, TList *roots)
{
TFile *fl = TFile::Open(fn);
if (!fl || (fl&& fl->IsZombie())) {
::Error("TEntryList::Relocate", "file '%s' cannot be open for reading", fn);
return -1;
}
Int_t nrs = 0;
TIter nxk(fl->GetListOfKeys());
TKey *key = 0;
while ((key = (TKey *) nxk())) {
if (!strcmp(key->GetClassName(), "TEntryList")) {
TEntryList *enl = dynamic_cast<TEntryList *>(fl->Get(key->GetName()));
if (enl) {
nrs += enl->ScanPaths(roots);
} else {
::Error("TEntryList::Scan", "object entry-list '%s' not found or not loadable!", key->GetName());
}
}
}
fl->Close();
delete fl;
return nrs;
}
void TEntryList::Streamer(TBuffer &b)
{
if (b.IsReading()) {
UInt_t R__s, R__c;
Version_t R__v = b.ReadVersion(&R__s, &R__c);
b.ReadClassBuffer(TEntryList::Class(), this, R__v, R__s, R__c);
if (R__v <= 1) {
GetFileName(fFileName.Data(), fFileName);
}
} else {
b.WriteClassBuffer(TEntryList::Class(), this);
}
}