//*CMZ : 2.23/08 01/11/99 15.30.05 by Rene Brun
//*CMZ : 2.23/07 28/10/99 12.11.15 by Rene Brun
//*CMZ : 2.23/04 02/10/99 12.25.35 by Rene Brun
//*CMZ : 2.23/03 17/09/99 08.42.06 by Rene Brun
//*CMZ : 2.22/09 04/08/99 16.58.41 by Rene Brun
//*CMZ : 2.22/07 30/06/99 17.49.47 by Rene Brun
//*CMZ : 2.22/01 18/05/99 11.42.55 by Rene Brun
//*-- Author : Rene Brun 12/01/96
//*KEEP,CopyRight,T=C.
/*************************************************************************
* Copyright(c) 1995-1999, The ROOT System, All rights reserved. *
* Authors: Rene Brun and Fons Rademakers. *
* *
* For the licensing terms see $ROOTSYS/AA_LICENSE. *
* For the list of contributors see $ROOTSYS/AA_CREDITS. *
*************************************************************************/
//*KEND.
#include <string.h>
#include <stdio.h>
//*KEEP,TROOT.
#include "TROOT.h"
//*KEEP,TFile.
#include "TFile.h"
//*KEEP,TBranch,T=C++.
#include "TBranch.h"
//*KEEP,TTree.
#include "TTree.h"
//*KEEP,TBasket,T=C++.
#include "TBasket.h"
//*KEEP,TBrowser.
#include "TBrowser.h"
//*KEEP,TLeaf,T=C++.
#include "TLeaf.h"
//*KEEP,TLeafObject,T=C++.
#include "TLeafObject.h"
//*KEEP,TLeafB,T=C++.
#include "TLeafB.h"
//*KEEP,TLeafC,T=C++.
#include "TLeafC.h"
//*KEEP,TLeafI,T=C++.
#include "TLeafI.h"
//*KEEP,TLeafF,T=C++.
#include "TLeafF.h"
//*KEEP,TLeafS,T=C++.
#include "TLeafS.h"
//*KEEP,TLeafD,T=C++.
#include "TLeafD.h"
//*KEEP,TClonesArray,T=C++.
#include "TClonesArray.h"
//*KEEP,TVirtualPad.
#include "TVirtualPad.h"
//*KEND.
TBranch *gBranch;
R__EXTERN TTree *gTree;
const Int_t kMaxRAM = 10;
const Int_t kAutoDelete = BIT(15);
ClassImp(TBranch)
//////////////////////////////////////////////////////////////////////////
// //
// A TTree is a list of TBranches // //
// //
// A TBranch supports: //
// - The list of TLeaf describing this branch. //
// - The list of TBasket (branch buffers). //
// //
// See TBranch structure in TTree. //
// //
// See also specialized branches: //
// TBranchObject in case the branch is one object //
// TBranchClones in case the branch is an array of clone objects //
//////////////////////////////////////////////////////////////////////////
//______________________________________________________________________________
TBranch::TBranch(): TNamed()
{
//*-*-*-*-*-*Default constructor for Branch*-*-*-*-*-*-*-*-*-*
//*-* ===================================
fCompress = 0;
fBasketSize = 32000;
fEntryOffsetLen = 1000;
fMaxBaskets = 1000;
fReadBasket = 0;
fReadEntry = -1;
fWriteBasket = 0;
fEntries = 0;
fTotBytes = 0;
fZipBytes = 0;
fNBasketRAM = kMaxRAM+1;
fBasketRAM = new Int_t[kMaxRAM]; for (Int_t i=0;i<kMaxRAM;i++) fBasketRAM[i] = -1;
fBasketEntry = 0;
fBasketSeek = 0;
fEntryNumber = 0;
fNleaves = 0;
fTree = 0;
fAddress = 0;
fOffset = 0;
fDirectory = 0;
fFileName = "";
}
//______________________________________________________________________________
TBranch::TBranch(const Text_t *name, void *address, const Text_t *leaflist, Int_t basketsize, Int_t compress)
:TNamed(name,leaflist)
{
//*-*-*-*-*-*-*-*-*-*-*-*-*Create a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =====================
//
// * address is the address of the first item of a structure
// or the address of a pointer to an object (see example).
// * leaflist is the concatenation of all the variable names and types
// separated by a colon character :
// The variable name and the variable type are separated by a slash (/).
// The variable type may be 0,1 or 2 characters. If no type is given,
// the type of the variable is assumed to be the same as the previous
// variable. If the first variable does not have a type, it is assumed
// of type F by default. The list of currently supported types is given below:
// - C : a character string terminated by the 0 character
// - B : an 8 bit signed integer (Char_t)
// - b : an 8 bit unsigned integer (UChar_t)
// - S : a 16 bit signed integer (Short_t)
// - s : a 16 bit unsigned integer (UShort_t)
// - I : a 32 bit signed integer (Int_t)
// - i : a 32 bit unsigned integer (UInt_t)
// - F : a 32 bit floating point (Float_t)
// - D : a 64 bit floating point (Double_t)
//
// By default, a variable will be copied to the buffer with the number of
// bytes specified in the type descriptor character. However, if the type
// consists of 2 characters, the second character is an integer that
// specifies the number of bytes to be used when copying the variable
// to the output buffer. Example:
// X ; variable X, type Float_t
// Y/I : variable Y, type Int_t
// Y/I2 ; variable Y, type Int_t converted to a 16 bits integer
//
// See an example of a Branch definition in the TTree constructor.
//
// Note that in case the data type is an object, this branch can contain
// only this object.
//
// Note that this function is invoked by TTree::Branch
//
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
Int_t i;
fCompress = compress;
if (compress == -1) {
TFile *bfile = gTree->GetDirectory()->GetFile();
if (bfile) fCompress = bfile->GetCompressionLevel();
}
if (basketsize < 100) basketsize = 100;
fBasketSize = basketsize;
fEntryOffsetLen = 0;
fMaxBaskets = 1000;
fReadBasket = 0;
fReadEntry = -1;
fWriteBasket = 0;
fEntryNumber = 0;
fEntries = 0;
fTotBytes = 0;
fZipBytes = 0;
fOffset = 0;
fNleaves = 0;
fAddress = (char*)address;
fNBasketRAM = kMaxRAM+1;
fBasketRAM = new Int_t[kMaxRAM]; for (i=0;i<kMaxRAM;i++) fBasketRAM[i] = -1;
fBasketEntry = new Int_t[fMaxBaskets];
fBasketSeek = new Seek_t[fMaxBaskets];
fBasketEntry[0] = fEntryNumber;
for (i=0;i<fMaxBaskets;i++) {
fBasketEntry[i] = 0;
fBasketSeek[i] = 0;
}
//*-*- Decode the leaflist (search for : as separator)
char * varcur = (char*)leaflist;
char * var = varcur;
Int_t lenvar = 0;
Int_t offset = 0;
char *leafname = new char[64];
char *leaftype = new char[32];
strcpy(leaftype,"F");
while (1) {
lenvar++;
if (*var == ':' || *var == 0) {
strncpy(leafname,varcur,lenvar-1);
leafname[lenvar-1] = 0;
char *ctype = strstr(leafname,"/");
if (ctype) { *ctype=0; strcpy(leaftype,ctype+1);}
TLeaf *leaf = 0;
if (*leaftype == 'C') {
leaf = new TLeafC(leafname,leaftype);
} else if (*leaftype == 'B') {
leaf = new TLeafB(leafname,leaftype);
} else if (*leaftype == 'b') {
leaf = new TLeafB(leafname,leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'S') {
leaf = new TLeafS(leafname,leaftype);
} else if (*leaftype == 's') {
leaf = new TLeafS(leafname,leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'I') {
leaf = new TLeafI(leafname,leaftype);
} else if (*leaftype == 'i') {
leaf = new TLeafI(leafname,leaftype);
leaf->SetUnsigned();
} else if (*leaftype == 'F') {
leaf = new TLeafF(leafname,leaftype);
} else if (*leaftype == 'D') {
leaf = new TLeafD(leafname,leaftype);
}
if (!leaf) {
Error("TLeaf","Illegal data type");
return;
}
leaf->SetBranch(this);
leaf->SetAddress((char*)(fAddress+offset));
leaf->SetOffset(offset);
if (leaf->GetLeafCount()) fEntryOffsetLen = 1000;
if (leaf->InheritsFrom("TLeafC")) fEntryOffsetLen = 1000;
fNleaves++;
fLeaves.Add(leaf);
gTree->GetListOfLeaves()->Add(leaf);
if (*var == 0) break;
varcur = var+1;
offset += leaf->GetLenType()*leaf->GetLen();
lenvar = 0;
}
var++;
}
delete [] leafname;
delete [] leaftype;
//*-*- Create the first basket
fTree = gTree;
fDirectory = fTree->GetDirectory();
fFileName = "";
TBasket *basket = new TBasket(name,fTree->GetName(),this);
fBaskets.AddAt(basket,0);
}
//______________________________________________________________________________
TBranch::~TBranch()
{
//*-*-*-*-*-*Default destructor for a Branch*-*-*-*-*-*-*-*-*-*-*-*
//*-* ===============================
fLeaves.Delete();
fBaskets.Delete();
if (fBasketRAM) delete [] fBasketRAM;
if (fBasketEntry) delete [] fBasketEntry;
if (fBasketSeek) delete [] fBasketSeek;
// Warning. Must use FindObject by name instead of fDirectory->GetFile()
// because two branches<may point to the same file and the file
// already deleted in the previous branch
if (fDirectory && fDirectory != fTree->GetDirectory()) {
TFile *file = (TFile*)gROOT->GetListOfFiles()->FindObject(GetFileName());
if (file ) delete file;
}
fBasketEntry = 0;
fBasketSeek = 0;
fTree = 0;
fDirectory = 0;
}
//______________________________________________________________________________
void TBranch::Browse(TBrowser *b)
{
// Browser interface.
if (fNleaves > 1) {
fLeaves.Browse(b);
} else {
GetTree()->Draw(GetName());
if (gPad) gPad->Update();
}
}
//______________________________________________________________________________
void TBranch::DropBaskets()
{
// Loop on all branch baskets. Drop all except readbasket
Int_t j;
TBasket *basket;
if (fNBasketRAM < kMaxRAM) {
for (j=0;j<kMaxRAM;j++) {
if (j == fReadBasket || j == fWriteBasket) continue;
basket = (TBasket*)fBaskets.UncheckedAt(j);
if (!basket) continue;
basket->DropBuffers();
GetListOfBaskets()->RemoveAt(j);
delete basket;
fBasketRAM[j] = -1;
fNBasketRAM--;
}
Int_t i = 0;
for (j=0;j<kMaxRAM;j++) {
if (fBasketRAM[j] < 0) fBasketRAM[i] = fBasketRAM[j];
i++;
}
return;
}
Int_t nbaskets = GetListOfBaskets()->GetEntriesFast();
fNBasketRAM = 0;
for (j=0;j<nbaskets-1;j++) {
basket = (TBasket*)fBaskets.UncheckedAt(j);
if (!basket) continue;
if (fNBasketRAM < kMaxRAM) fBasketRAM[fNBasketRAM] = j;
fNBasketRAM++;
if (j == fReadBasket || j == fWriteBasket) continue;
basket->DropBuffers();
GetListOfBaskets()->RemoveAt(j);
delete basket;
fNBasketRAM--;
if (!fTree->MemoryFull(0)) break;
}
}
//______________________________________________________________________________
Int_t TBranch::Fill()
{
//*-*-*-*-*-*-*-*Loop on all leaves of this branch to fill Basket buffer*-*-*
//*-* =======================================================
if (TestBit(kDoNotProcess)) return 0;
TBasket *basket = GetBasket(fWriteBasket);
if (!basket) return 0;
TBuffer *buf = basket->GetBufferRef();
//*-*- Fill basket buffer
Int_t nsize = 0;
if (buf->IsReading()) {
basket->SetWriteMode();
}
buf->ResetMap();
Int_t lold = buf->Length();
basket->Update(lold);
fEntries++;
fEntryNumber++;
for (Int_t i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
leaf->FillBasket(*buf);
}
Int_t lnew = buf->Length();
Int_t nbytes = lnew - lold;
if (fEntryOffsetLen) {
Int_t nevbuf = basket->GetNevBuf();
nsize = nevbuf*sizeof(Int_t); //total size in bytes of EntryOffset table
} else {
if (!basket->GetNevBufSize()) basket->SetNevBufSize(nbytes);
}
//*-*- Should we create a new basket?
if (lnew +2*nsize +nbytes >= fBasketSize) {
Int_t nout = basket->WriteBuffer(); // Write buffer
fBasketSeek[fWriteBasket] = basket->GetSeekKey();
Int_t addbytes = basket->GetObjlen() + basket->GetKeylen() ;
if (fDirectory != gROOT && fDirectory->IsWritable()) {
delete basket;
fBaskets[fWriteBasket] = 0;
}
fZipBytes += nout;
fTotBytes += addbytes;
fTree->AddTotBytes(addbytes);
fTree->AddZipBytes(nout);
basket = new TBasket(GetName(),fTree->GetName(),this); // create a new basket
fWriteBasket++;
fBaskets.AddAtAndExpand(basket,fWriteBasket);
if (fWriteBasket >= fMaxBaskets) {
//Increase BasketEntry buffer of a minimum of 10 locations
// and a maximum of 50 per cent of current size
Int_t newsize = TMath::Max(10,Int_t(1.5*fMaxBaskets));
Int_t *newbuf = (Int_t*)TStorage::ReAlloc(fBasketEntry,
newsize*sizeof(Int_t),fMaxBaskets*sizeof(Int_t));
fBasketEntry = newbuf;
Seek_t *nseek = (Seek_t*)TStorage::ReAlloc(fBasketSeek,
newsize*sizeof(Seek_t),fMaxBaskets*sizeof(Seek_t));
fBasketSeek = nseek;
fMaxBaskets = newsize;
}
fBasketEntry[fWriteBasket] = fEntryNumber;
fBasketSeek[fWriteBasket] = 0;
}
return nbytes;
}
//______________________________________________________________________________
TBasket *TBranch::GetBasket(Int_t basketnumber)
{
//*-*-*-*-*Return pointer to basket basketnumber in this Branch*-*-*-*-*-*
//*-* ====================================================
static Int_t nerrors = 0;
// reference to an existing basket in memory ?
if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
TBasket *basket = (TBasket*)fBaskets.UncheckedAt(basketnumber);
if (basket) return basket;
// must create a new basket
gBranch = this;
// Int_t nb = fBasketSize;
Int_t nb = 128;
if (fCompress) nb = 128;
static TBuffer *buffer = 0;
if (buffer) buffer->SetBufferOffset(0);
else buffer = new TBuffer(TBuffer::kRead, nb);
basket = new TBasket();
char *buf = buffer->Buffer();
// get basket from the branch file
TDirectory *cursav = gDirectory;
TFile *file = GetFile(0);
file->Seek(fBasketSeek[basketnumber]);
if (fBasketSeek[basketnumber] + nb > file->GetEND()) nb = file->GetEND()-fBasketSeek[basketnumber];
file->ReadBuffer(buf,nb);
basket->Streamer(*buffer);
if (basket->GetSeekKey() != fBasketSeek[basketnumber]) {
cursav->cd();
nerrors++;
if (nerrors > 10) return 0;
if (nerrors == 10) {
printf(" file probably overwritten: stopping reporting error messagesn");
if (fBasketSeek[basketnumber] > 2000000000) {
printf("===>File is more than 2 Gigabytesn");
return 0;
}
if (fBasketSeek[basketnumber] > 1000000000) {
printf("===>Your file is may be bigger than the maximum file size allowed on your systemn");
printf(" Check your AFS maximum file size limit for examplen");
return 0;
}
}
Error("GetBasket","File problem at address:%d, basket seekkey=%d, branch:%s",fBasketSeek[basketnumber],basket->GetSeekKey(),GetName());
return 0;
}
if (basket->GetKeylen() > nb) {
Warning("GetBasket","Estimated keylen too small=%d",basket->GetKeylen());
}
if (basket->GetObjlen() + basket->GetKeylen() <= nb) {
buffer->SetBufferOffset(0);
basket->ReadBasketBuffers(buf);
}
cursav->cd();
// delete buffer;
fBaskets[basketnumber] = basket;
if (fNBasketRAM < kMaxRAM) fBasketRAM[fNBasketRAM] = basketnumber;
fNBasketRAM++;
return basket;
}
//______________________________________________________________________________
Seek_t TBranch::GetBasketSeek(Int_t basketnumber)
{
//*-*-*-*-*Return address of basket in the file*-*-*-*-*-*
//*-* ====================================
if (basketnumber <0 || basketnumber > fWriteBasket) return 0;
return fBasketSeek[basketnumber];
}
//______________________________________________________________________________
Int_t TBranch::GetEntry(Int_t entry)
{
//*-*-*-*-*-*Read all leaves of entry and return total number of bytes*-*-*
//*-* =========================================================
if (fReadEntry == entry) return 1;
if (entry < 0 || entry >= fEntryNumber) return 0;
Int_t nbytes;
Int_t first = fBasketEntry[fReadBasket];
Int_t last;
if (fReadBasket == fWriteBasket) last = fEntryNumber - 1;
else last = fBasketEntry[fReadBasket+1] - 1;
//
// Are we still in the same ReadBasket?
if (entry < first || entry > last) {
fReadBasket = TMath::BinarySearch(fWriteBasket+1, fBasketEntry, entry);
first = fBasketEntry[fReadBasket];
}
// We have found the basket containing this entry.
// make sure basket buffers are in memory.
TBasket *basket = GetBasket(fReadBasket);
if (!basket) return 0;
TBuffer *buf = basket->GetBufferRef();
if (!buf) {
basket->ReadBasketBuffers();
buf = basket->GetBufferRef();
}
// Set entry offset in buffer and read data from all leaves
buf->ResetMap();
if (!buf->IsReading()) {
basket->SetReadMode();
}
// Int_t bufbegin = basket->GetEntryPointer(entry-first);
Int_t bufbegin;
Int_t *entryOffset = basket->GetEntryOffset();
if (entryOffset) bufbegin = entryOffset[entry-first];
else bufbegin = basket->GetKeylen() + (entry-first)*basket->GetNevBufSize();
buf->SetBufferOffset(bufbegin);
for (Int_t i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
leaf->ReadBasket(*buf);
}
nbytes = buf->Length() - bufbegin;
fReadEntry = entry;
return nbytes;
}
//______________________________________________________________________________
Int_t TBranch::GetEntryExport(Int_t entry, TClonesArray *list, Int_t nentries)
{
//*-*-*-*-*-*Read all leaves of entry and return total number of bytes*-*-*
//*-* export buffers to real objects in the TClonesArray list.
//*-*
if (fReadEntry == entry) return 1;
if (entry < 0 || entry >= fEntryNumber) return 0;
Int_t nbytes;
Int_t first = fBasketEntry[fReadBasket];
Int_t last;
if (fReadBasket == fWriteBasket) last = fEntryNumber - 1;
else last = fBasketEntry[fReadBasket+1] - 1;
//
// Are we still in the same ReadBasket?
if (entry < first || entry > last) {
fReadBasket = TMath::BinarySearch(fWriteBasket+1, fBasketEntry, entry);
first = fBasketEntry[fReadBasket];
}
// We have found the basket containing this entry.
// make sure basket buffers are in memory.
TBasket *basket = GetBasket(fReadBasket);
if (!basket) return 0;
TBuffer *buf = basket->GetBufferRef();
if (!buf) {
basket->ReadBasketBuffers();
buf = basket->GetBufferRef();
}
// Set entry offset in buffer and read data from all leaves
// buf->ResetMap();
if (!buf->IsReading()) {
basket->SetReadMode();
}
// Int_t bufbegin = basket->GetEntryPointer(entry-first);
Int_t bufbegin;
Int_t *entryOffset = basket->GetEntryOffset();
if (entryOffset) bufbegin = entryOffset[entry-first];
else bufbegin = basket->GetKeylen() + (entry-first)*basket->GetNevBufSize();
buf->SetBufferOffset(bufbegin);
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
leaf->ReadBasketExport(*buf,list,nentries);
// leaf->ReadBasket(*buf);
// leaf->Export(list,nentries);
nbytes = buf->Length() - bufbegin;
fReadEntry = entry;
return nbytes;
}
//______________________________________________________________________________
TFile *TBranch::GetFile(Int_t mode)
{
// Return pointer to the file where branch buffers reside
if (fDirectory) return fDirectory->GetFile();
TFile *file;
// check if a file with this name is in the list of Root files
file = (TFile*)gROOT->GetListOfFiles()->FindObject(fFileName.Data());
if (file) {
fDirectory = (TDirectory*)file;
return file;
}
// Open file (new file if mode = 1)
if (mode) file = new TFile(fFileName.Data(),"recreate");
else file = new TFile(fFileName.Data());
if (file->IsZombie()) {delete file; return 0;}
fDirectory = (TDirectory*)file;
return file;
}
//______________________________________________________________________________
TLeaf *TBranch::GetLeaf(Text_t *name)
{
//*-*-*-*-*-*Return pointer to the 1st Leaf named name in thisBranch-*-*-*-*-*
//*-* =======================================================
Int_t i;
for (i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
if (!strcmp(leaf->GetName(),name)) return leaf;
}
return 0;
}
//______________________________________________________________________________
Int_t TBranch::GetRow(Int_t)
{
//*-*-*-*-*Return all elements of one row unpacked in internal array fValues*-*
//*-* =================================================================
return 1;
}
//______________________________________________________________________________
Bool_t TBranch::IsAutoDelete()
{
//*-*-*-*-*Return TRUE if an existing object in a TBranchObject must be deleted
//*-* ==================================================
return TestBit(kAutoDelete);
}
//______________________________________________________________________________
Bool_t TBranch::IsFolder()
{
//*-*-*-*-*Return TRUE if more than one leaf, FALSE otherwise*-*
//*-* ==================================================
if (fNleaves > 1) return kTRUE;
else return kFALSE;
}
//______________________________________________________________________________
void TBranch::Print(Option_t *)
{
//*-*-*-*-*-*-*-*-*-*-*-*Print TBranch parameters*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ========================
const int kLINEND = 77;
Float_t cx = 1;
int aLength = strlen (GetTitle());
aLength += (aLength / 54 + 1) * 80 + 100;
if (aLength < 200) aLength = 200;
char *bline = new char[aLength];
if (fZipBytes) cx = fTotBytes/fZipBytes;
sprintf(bline,"*Branch :%-9s : %-54s *",GetName(),GetTitle());
if (strlen(bline) > UInt_t(kLINEND)) {
int len=strlen(GetTitle());
char *tmp = new char[strlen(bline)+1];
strcpy(tmp, GetTitle());
sprintf(bline,"*Branch :%-9s : ",GetName());
int pos = strlen (bline);
int npos = pos;
int beg=0, end;
while (beg < len) {
for (end=beg+1; end < len-1; end ++)
if (tmp[end] == ':') break;
if (npos + end-beg+1 >= 78) {
while (npos < kLINEND) {
bline[pos ++] = ' ';
npos ++;
}
bline[pos ++] = '*';
bline[pos ++] = 'n';
bline[pos ++] = '*';
npos = 1;
for (; npos < 22; npos ++)
bline[pos ++] = ' ';
bline[pos-2] = '|';
}
for (int n = beg; n <= end; n ++)
bline[pos+n-beg] = tmp[n];
pos += end-beg+1;
npos += end-beg+1;
beg = end+1;
}
while (npos < kLINEND) {
bline[pos ++] = ' ';
npos ++;
}
bline[pos ++] = '*';
bline[pos] = '0';
delete[] tmp;
}
Printf(bline);
// Printf("*Branch :%-9s : %-60s *",GetName(),GetTitle());
Printf("*Entries : %8d : Total Size = %9d bytes File Size = %10d *",Int_t(fEntries),Int_t(fTotBytes),Int_t(fZipBytes));
Printf("*Baskets : %8d : Basket Size = %9d bytes Compression= %6.2f *",fWriteBasket,fBasketSize,cx);
Printf("*............................................................................*");
delete [] bline;
}
//______________________________________________________________________________
void TBranch::ReadBasket(TBuffer &)
{
//*-*-*-*-*-*-*-*Loop on all leaves of this branch to read Basket buffer*-*-*
//*-* =======================================================
// fLeaves->ReadBasket(basket);
}
//______________________________________________________________________________
void TBranch::Reset(Option_t *)
{
//*-*-*-*-*-*-*-*Reset a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ====================
//
// Existing buffers are deleted
// Entries, max and min are reset
//
fBaskets.Delete();
if (fBasketEntry) delete [] fBasketEntry;
if (fBasketSeek) delete [] fBasketSeek;
fBasketEntry = 0;
fReadBasket = 0;
fReadEntry = -1;
fWriteBasket = 0;
fEntries = 0;
fTotBytes = 0;
fZipBytes = 0;
fEntryNumber = 0;
fBasketEntry = new Int_t[fMaxBaskets];
fBasketSeek = new Seek_t[fMaxBaskets];
fBasketEntry[0] = fEntryNumber;
for (Int_t i=0;i<fMaxBaskets;i++) {
fBasketEntry[i] = 0;
fBasketSeek[i] = 0;
}
TBasket *basket = new TBasket(GetName(),fTree->GetName(),this);
fBaskets.AddAt(basket,0);
}
//______________________________________________________________________________
void TBranch::SetAddress(void *add)
{
//*-*-*-*-*-*-*-*Set address of this branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* ====================
//
fReadEntry = -1;
fAddress = (char*)add;
Int_t i,offset;
for (i=0;i<fNleaves;i++) {
TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
offset = leaf->GetOffset();
if (TestBit(kIsClone)) offset = 0;
leaf->SetAddress(fAddress+offset);
}
}
//______________________________________________________________________________
void TBranch::SetAutoDelete(Bool_t autodel)
{
//*-*-*-*-*-*-*-*Set the AutoDelete bit
//*-* ====================
// this bit is used by TBranchObject::ReadBasket to decide if an object
// referenced by a TBranchObject must be deleted or not before reading
// a new entry
// if autodel is kTRUE, this existing object will be deleted, a new object
// created by the default constructor, then object->Streamer
// if autodel is kFALSE, the existing object is not deleted. Root assumes
// that the user is taking care of deleting any internal object or array
// This can be done in Streamer itself.
if (autodel) SetBit(kAutoDelete,1);
else SetBit(kAutoDelete,0);
}
//______________________________________________________________________________
void TBranch::SetFile(TFile *file)
{
// Set file where this branch writes/reads its buffers
//
if (file == 0) file = fTree->GetCurrentFile();
fDirectory = (TDirectory*)file;
if (file == fTree->GetCurrentFile()) fFileName = "";
else fFileName = file->GetName();
}
//______________________________________________________________________________
void TBranch::SetFile(const char *fname)
{
// Set file where this branch writes/reads its buffers
// By default the branch buffers reside in the file where the Tree was created.
// Branches of the same Tree may be on different files.
//
// The Root file will be connected only when necessary.
// If called by TBranch::Fill (via TBasket::WriteFile), the file
// will be created with the option "recreate".
// If called by TBranch::GetEntry (via TBranch::GetBasket), the file
// will be open in read mode.
//
// To open a file in "update" mode, use TBranch::SetFile(TFile *file).
fFileName = fname;
fDirectory = 0;
}
//_______________________________________________________________________
void TBranch::Streamer(TBuffer &b)
{
//*-*-*-*-*-*-*-*-*Stream a class object*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-* =========================================
if (b.IsReading()) {
gBranch = this;
fTree = gTree;
gROOT->SetReadingBasket(kTRUE);
Version_t v = b.ReadVersion();
TNamed::Streamer(b);
b >> fCompress;
b >> fBasketSize;
b >> fEntryOffsetLen;
b >> fMaxBaskets;
b >> fWriteBasket;
b >> fEntryNumber;
b >> fEntries;
b >> fTotBytes;
b >> fZipBytes;
b >> fOffset;
fAddress = 0;
fBranches.Streamer(b);
gBranch = this; // must be set again, was changed in previous statement
fLeaves.Streamer(b);
fBaskets.Streamer(b);
fNleaves = fLeaves.GetEntriesFast();
fBasketEntry = new Int_t[fMaxBaskets];
Int_t n = b.ReadArray(fBasketEntry);
if (v < 2) {
fBasketSeek = new Seek_t[fMaxBaskets];
for (n=0;n<fWriteBasket;n++) {
fBasketSeek[n] = GetBasket(n)->GetSeekKey();
}
} else {
fBasketSeek = new Seek_t[fMaxBaskets];
n = b.ReadArray(fBasketSeek);
}
fDirectory = gDirectory;
if (v > 2) {
fFileName.Streamer(b);
if (fFileName.Length() != 0) fDirectory = 0;
}
if (v < 4) SetAutoDelete(kTRUE);
gROOT->SetReadingBasket(kFALSE);
} else {
b.WriteVersion(TBranch::IsA());
TNamed::Streamer(b);
b << fCompress;
b << fBasketSize;
b << fEntryOffsetLen;
b << fMaxBaskets;
b << fWriteBasket;
b << fEntryNumber;
b << fEntries;
b << fTotBytes;
b << fZipBytes;
b << fOffset;
fBranches.Streamer(b);
fLeaves.Streamer(b);
fBaskets.Streamer(b);
b.WriteArray(fBasketEntry,fMaxBaskets);
b.WriteArray(fBasketSeek, fMaxBaskets);
fFileName.Streamer(b);
// if branch is in a separate file save this branch
// as an independent key
if (fDirectory && fDirectory != fTree->GetDirectory()) {
TDirectory *cursav = gDirectory;
fDirectory->cd();
fDirectory = 0; // to avoid recusive calls
Write();
fDirectory = gDirectory;
cursav->cd();
}
}
}
ROOT page - Class index - Top of the page
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.