diff --git a/treeplayer/inc/TFormLeafInfo.h b/treeplayer/inc/TFormLeafInfo.h index 4f44493192c93eceb0b3e6a454371ce3710c0d72..b5d0f6069e3cb702a88ad0369c32e6dcb978b326 100644 --- a/treeplayer/inc/TFormLeafInfo.h +++ b/treeplayer/inc/TFormLeafInfo.h @@ -1,4 +1,4 @@ -// @(#)root/treeplayer:$Name: $:$Id: TFormLeafInfo.h,v 1.1 2003/05/09 19:57:53 pcanal Exp $ +// @(#)root/treeplayer:$Name: $:$Id: TFormLeafInfo.h,v 1.1 2004/06/17 17:37:10 brun Exp $ // Author: Philippe Canal 01/06/2004 /************************************************************************* @@ -83,7 +83,7 @@ public: virtual Int_t GetVirtVarDim(); virtual Int_t GetSize(Int_t index); virtual Int_t GetSumOfSizes(); - virtual void LoadSizes(TBranchElement* branch); + virtual void LoadSizes(TBranch* branch); virtual void SetPrimaryIndex(Int_t index); virtual void SetSize(Int_t index, Int_t val); virtual void UpdateSizes(TArrayI *garr); @@ -188,6 +188,7 @@ public: virtual Bool_t Update(); virtual Int_t GetCounterValue(TLeaf* leaf); + virtual Int_t GetCounterValue(TLeaf* leaf, Int_t instance); virtual Bool_t HasCounter() const; virtual Double_t ReadValue(char *where, Int_t instance = 0); virtual Double_t GetValue(TLeaf *leaf, Int_t instance = 0); @@ -197,6 +198,33 @@ public: virtual void *GetLocalValuePointer(char *thisobj, Int_t instance = 0); }; +//______________________________________________________________________________ +// +// TFormLeafInfoCollectionSize is used to return the size of a collection +// +class TFormLeafInfoCollectionSize : public TFormLeafInfo { + TClass *fCollClass; + TString fCollClassName; + TVirtualCollectionProxy *fCollProxy; +public: + TFormLeafInfoCollectionSize(TClass*); + TFormLeafInfoCollectionSize(TClass* classptr,Long_t offset,TStreamerElement* element); + TFormLeafInfoCollectionSize(); + TFormLeafInfoCollectionSize(const TFormLeafInfoCollectionSize& orig); + + ~TFormLeafInfoCollectionSize(); + + virtual TFormLeafInfo* DeepCopy() const; + + virtual Bool_t Update(); + + virtual void *GetValuePointer(TLeaf *leaf, Int_t instance = 0); + virtual void *GetValuePointer(char *from, Int_t instance = 0); + virtual void *GetLocalValuePointer(TLeaf *leaf, Int_t instance = 0); + virtual void *GetLocalValuePointer( char *from, Int_t instance = 0); + virtual Double_t ReadValue(char *where, Int_t instance = 0); +}; + //______________________________________________________________________________ // // TFormLeafInfoPointer is a small helper class to implement reading a data @@ -264,6 +292,10 @@ public: Int_t fVirtDim; // number of the virtual dimension to which this object correspond. Int_t fPrimaryIndex; // Index of the dimensions that is indexing the second dimension's size +protected: + TFormLeafInfoMultiVarDim(TClass* classptr, Long_t offset, + TStreamerElement* element) : TFormLeafInfo(classptr,offset,element) {} +public: TFormLeafInfoMultiVarDim(TClass* classptr, Long_t offset, TStreamerElement* element, TFormLeafInfo* parent); TFormLeafInfoMultiVarDim(); @@ -278,7 +310,7 @@ public: // return TFormLeafInfo::ReadValue(where,instance); //} - virtual void LoadSizes(TBranchElement* branch); + virtual void LoadSizes(TBranch* branch); virtual Int_t GetPrimaryIndex(); virtual void SetPrimaryIndex(Int_t index); virtual void SetSize(Int_t index, Int_t val); @@ -308,6 +340,29 @@ public: virtual Double_t ReadValue(char * /*where*/, Int_t /*instance*/ = 0); }; +//______________________________________________________________________________ +// +// TFormLeafInfoMultiVarDimDirect is a small helper class to implement reading +// a data member on a variable size array inside a TClonesArray object stored +// in a TTree. This is the version used for split access + +class TFormLeafInfoMultiVarDimCollection : public TFormLeafInfoMultiVarDim { +public: + TFormLeafInfoMultiVarDimCollection(TClass* motherclassptr, Long_t offset, + TClass* elementclassptr, TFormLeafInfo *parent); + TFormLeafInfoMultiVarDimCollection(TClass* classptr, Long_t offset, + TStreamerElement* element, TFormLeafInfo* parent); + TFormLeafInfoMultiVarDimCollection(); + TFormLeafInfoMultiVarDimCollection(const TFormLeafInfoMultiVarDimCollection& orig); + + virtual TFormLeafInfo* DeepCopy() const; + + virtual Int_t GetArrayLength() { return 0; } + virtual void LoadSizes(TBranch* branch); + virtual Double_t GetValue(TLeaf *leaf, Int_t instance = 0); + virtual Double_t ReadValue(char * /*where*/, Int_t /*instance*/ = 0); +}; + //______________________________________________________________________________ // // TFormLeafInfoCast is a small helper class to implement casting an object to diff --git a/treeplayer/src/TFormLeafInfo.cxx b/treeplayer/src/TFormLeafInfo.cxx index 0d4e79adcebefb6eb2796d79aa53b262b4d90674..2ddeed8921d316809781746ad4c755ab753b5e90 100644 --- a/treeplayer/src/TFormLeafInfo.cxx +++ b/treeplayer/src/TFormLeafInfo.cxx @@ -1,4 +1,4 @@ -// @(#)root/treeplayer:$Name: $:$Id: TFormLeafInfo.cxx,v 1.12 2005/01/19 07:52:45 brun Exp $ +// @(#)root/treeplayer:$Name: $:$Id: TFormLeafInfo.cxx,v 1.13 2005/01/19 18:30:58 brun Exp $ // Author: Philippe Canal 01/06/2004 /************************************************************************* @@ -354,7 +354,7 @@ Int_t TFormLeafInfo::GetSumOfSizes() } //______________________________________________________________________________ -void TFormLeafInfo::LoadSizes(TBranchElement* branch) +void TFormLeafInfo::LoadSizes(TBranch* branch) { if (fNext) fNext->LoadSizes(branch); } @@ -1156,19 +1156,36 @@ Bool_t TFormLeafInfoCollection::HasCounter() const } //______________________________________________________________________________ -Int_t TFormLeafInfoCollection::GetCounterValue(TLeaf* leaf) { +Int_t TFormLeafInfoCollection::GetCounterValue(TLeaf* leaf) +{ // Return the current size of the the TClonesArray - if (fCounter) { return (Int_t)fCounter->ReadValue((char*)GetLocalValuePointer(leaf)); } - Assert(fCollProxy); void *ptr = GetLocalValuePointer(leaf); + if (fCounter) { return (Int_t)fCounter->ReadValue((char*)ptr); } + Assert(fCollProxy); if (ptr==0) return 0; TVirtualCollectionProxy::TPushPop helper(fCollProxy, ptr); return (Int_t)fCollProxy->Size(); } //______________________________________________________________________________ -Double_t TFormLeafInfoCollection::ReadValue(char *where, Int_t instance) { +Int_t TFormLeafInfoCollection::GetCounterValue(TLeaf* leaf, Int_t instance) +{ + // Return the current size of the the TClonesArray + + void *ptr = GetLocalValuePointer(leaf,instance); + if (fCounter) { + return (Int_t)fCounter->ReadValue((char*)ptr); + } + Assert(fCollProxy); + if (ptr==0) return 0; + TVirtualCollectionProxy::TPushPop helper(fCollProxy, ptr); + return (Int_t)fCollProxy->Size(); +} + +//______________________________________________________________________________ +Double_t TFormLeafInfoCollection::ReadValue(char *where, Int_t instance) +{ // Return the value of the underlying data member inside the // clones array. @@ -1184,7 +1201,8 @@ Double_t TFormLeafInfoCollection::ReadValue(char *where, Int_t instance) { } Assert(fCollProxy); - TVirtualCollectionProxy::TPushPop helper(fCollProxy, where); + void *ptr = GetLocalValuePointer(where,instance); + TVirtualCollectionProxy::TPushPop helper(fCollProxy, ptr); // Note we take advantage of having only one physically variable // dimension: @@ -1213,12 +1231,14 @@ void* TFormLeafInfoCollection::GetLocalValuePointer(TLeaf *leaf, Int_t /*instanc } //______________________________________________________________________________ -void* TFormLeafInfoCollection::GetLocalValuePointer(char *where, Int_t instance) { +void* TFormLeafInfoCollection::GetLocalValuePointer(char *where, Int_t instance) +{ return TFormLeafInfo::GetLocalValuePointer(where,instance); } //______________________________________________________________________________ -Double_t TFormLeafInfoCollection::GetValue(TLeaf *leaf, Int_t instance) { +Double_t TFormLeafInfoCollection::GetValue(TLeaf *leaf, Int_t instance) +{ // Return the value of the underlying data member inside the // clones array. @@ -1299,11 +1319,126 @@ void * TFormLeafInfoCollection::GetValuePointer(char *where, Int_t instance) { return collection; } +//______________________________________________________________________________ +// +// TFormLeafInfoCollectionSize is used to return the size of a collection +// +//______________________________________________________________________________ + +//______________________________________________________________________________ +TFormLeafInfoCollectionSize::TFormLeafInfoCollectionSize(TClass* classptr) : + TFormLeafInfo(), fCollClass(classptr), fCollProxy(0) +{ + if (fCollClass + && fCollClass!=TClonesArray::Class() + && fCollClass->GetCollectionProxy()) { + + fCollProxy = fCollClass->GetCollectionProxy()->Generate(); + fCollClassName = fCollClass->GetName(); + } +} + +//______________________________________________________________________________ +TFormLeafInfoCollectionSize::TFormLeafInfoCollectionSize( + TClass* classptr,Long_t offset,TStreamerElement* element) : + TFormLeafInfo(classptr,offset,element), fCollClass(element->GetClassPointer()), fCollProxy(0) +{ + if (fCollClass + && fCollClass!=TClonesArray::Class() + && fCollClass->GetCollectionProxy()) { + + fCollProxy = fCollClass->GetCollectionProxy()->Generate(); + fCollClassName = fCollClass->GetName(); + } +} + +//______________________________________________________________________________ +TFormLeafInfoCollectionSize::TFormLeafInfoCollectionSize() : + TFormLeafInfo(), fCollClass(0), fCollProxy(0) +{ +} + +//______________________________________________________________________________ +TFormLeafInfoCollectionSize::TFormLeafInfoCollectionSize( + const TFormLeafInfoCollectionSize& orig) : TFormLeafInfo(), + fCollClass(orig.fCollClass), + fCollClassName(orig.fCollClassName), + fCollProxy(orig.fCollProxy?orig.fCollProxy->Generate():0) +{ + +} + +//______________________________________________________________________________ +TFormLeafInfoCollectionSize::~TFormLeafInfoCollectionSize() +{ + delete fCollProxy; +} + +//______________________________________________________________________________ +TFormLeafInfo* TFormLeafInfoCollectionSize::DeepCopy() const +{ + return new TFormLeafInfoCollectionSize(*this); +} + +//______________________________________________________________________________ +Bool_t TFormLeafInfoCollectionSize::Update() +{ + Bool_t changed = kFALSE; + TClass *new_class = gROOT->GetClass(fCollClassName); + if (new_class!=fCollClass) { + delete fCollProxy; fCollProxy = 0; + fCollClass = new_class; + if (fCollClass && fCollClass->GetCollectionProxy()) { + fCollProxy = fCollClass->GetCollectionProxy()->Generate(); + } + changed = kTRUE; + } + return changed; +} + +//______________________________________________________________________________ +void *TFormLeafInfoCollectionSize::GetValuePointer(TLeaf *leaf, Int_t instance) +{ + Error("GetValuePointer","This should never be called"); + return 0; +} + +//______________________________________________________________________________ +void *TFormLeafInfoCollectionSize::GetValuePointer(char *from, Int_t instance) +{ + Error("GetValuePointer","This should never be called"); + return 0; +} + +//______________________________________________________________________________ +void *TFormLeafInfoCollectionSize::GetLocalValuePointer(TLeaf *leaf, Int_t instance) +{ + Error("GetLocalValuePointer","This should never be called"); + return 0; +} + +//______________________________________________________________________________ +void *TFormLeafInfoCollectionSize::GetLocalValuePointer( char *from, Int_t instance) +{ + Error("GetLocalValuePointer","This should never be called"); + return 0; +} + +//______________________________________________________________________________ +Double_t TFormLeafInfoCollectionSize::ReadValue(char *where, Int_t instance) +{ + Assert(fCollProxy); + if (where==0) return 0; + void *ptr = fElement ? TFormLeafInfo::GetLocalValuePointer(where) : where; + TVirtualCollectionProxy::TPushPop helper(fCollProxy, ptr); + return (Int_t)fCollProxy->Size(); +} //______________________________________________________________________________ // // TFormLeafInfoPointer is a small helper class to implement reading a data // member by following a pointer inside a branch of TTree. +//______________________________________________________________________________ //______________________________________________________________________________ TFormLeafInfoPointer::TFormLeafInfoPointer(TClass* classptr, @@ -1610,7 +1745,7 @@ Double_t TFormLeafInfoMethod::ReadValue(char *where, Int_t instance) //______________________________________________________________________________ // -// TFormLeafInfoMultiVarDim is a small helper class to implement reading a +// TFormLeafInfoMultiVarDim is a helper class to implement reading a // data member on a variable size array inside a TClonesArray object stored in // a TTree. This is the version used when the data member is inside a // non-splitted object. @@ -1674,26 +1809,29 @@ TFormLeafInfoMultiVarDim:: ~TFormLeafInfoMultiVarDim() //} //______________________________________________________________________________ -void TFormLeafInfoMultiVarDim::LoadSizes(TBranchElement* branch) +void TFormLeafInfoMultiVarDim::LoadSizes(TBranch* branch) { if (fElement) { - if (fCounter) fNsize = (Int_t)fCounter->GetValue((TLeaf*)branch->GetListOfLeaves()->At(0)); - else fNsize = fCounter2->GetCounterValue((TLeaf*)branch->GetListOfLeaves()->At(0)); + TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0); + if (fCounter) fNsize = (Int_t)fCounter->GetValue(leaf); + else fNsize = fCounter2->GetCounterValue(leaf); if (fNsize > fSizes.GetSize()) fSizes.Set(fNsize); fSumOfSizes = 0; for (Int_t i=0; i<fNsize; i++) { - Int_t size = (Int_t)fCounter2->GetValue((TLeaf*)branch->GetListOfLeaves()->At(0),i); + Int_t size = (Int_t)fCounter2->GetValue(leaf,i); fSumOfSizes += size; fSizes.AddAt( size, i ); } return; } if (!fCounter2 || !fCounter) return; - fNsize =((TBranchElement*) branch->GetBranchCount())->GetNdata(); + TBranchElement *br = dynamic_cast<TBranchElement*>(branch); + Assert(br); + fNsize = br->GetBranchCount()->GetNdata(); if (fNsize > fSizes.GetSize()) fSizes.Set(fNsize); fSumOfSizes = 0; for (Int_t i=0; i<fNsize; i++) { - Int_t size = (Int_t)fCounter2->GetValue((TLeaf*)branch->GetBranchCount2()->GetListOfLeaves()->At(0),i); + Int_t size = (Int_t)fCounter2->GetValue((TLeaf*)br->GetBranchCount2()->GetListOfLeaves()->At(0),i); fSumOfSizes += size; fSizes.AddAt( size, i ); } @@ -1777,13 +1915,12 @@ void TFormLeafInfoMultiVarDim::UpdateSizes(TArrayI *garr) } } - - //______________________________________________________________________________ // // TFormLeafInfoMultiVarDimDirect is a small helper class to implement reading // a data member on a variable size array inside a TClonesArray object stored // in a TTree. This is the version used for split access +//______________________________________________________________________________ //______________________________________________________________________________ TFormLeafInfoMultiVarDimDirect::TFormLeafInfoMultiVarDimDirect() : @@ -1816,10 +1953,110 @@ Double_t TFormLeafInfoMultiVarDimDirect::ReadValue(char * /*where*/, Int_t /*ins return 0; } +//______________________________________________________________________________ +// +// TFormLeafInfoMultiVarDimCollection is a small helper class to implement reading +// a data member on a variable size array inside a TClonesArray object stored +// in a TTree. This is the version used for split access + +//______________________________________________________________________________ +TFormLeafInfoMultiVarDimCollection::TFormLeafInfoMultiVarDimCollection( + TClass* motherclassptr, + Long_t offset, + TClass* elementclassptr, + TFormLeafInfo *parent) : + TFormLeafInfoMultiVarDim(motherclassptr,offset, + new TStreamerElement("collection","in class", + 0, + TStreamerInfo::kAny, + elementclassptr + ? elementclassptr->GetName() + : ( motherclassptr + ? motherclassptr->GetName() + : "Unknwon") + ) + ) +{ + Assert(parent); + fCounter = parent->DeepCopy(); + fCounter2 = parent->DeepCopy(); + TFormLeafInfo ** next = &(fCounter2->fNext); + while(*next != 0) next = &( (*next)->fNext); + *next = new TFormLeafInfoCollectionSize(elementclassptr); +} + +//______________________________________________________________________________ +TFormLeafInfoMultiVarDimCollection::TFormLeafInfoMultiVarDimCollection( + TClass* motherclassptr, + Long_t offset, + TStreamerElement* element, + TFormLeafInfo *parent) : + TFormLeafInfoMultiVarDim(motherclassptr,offset,element) +{ + Assert(parent && element); + fCounter = parent->DeepCopy(); + fCounter2 = parent->DeepCopy(); + TFormLeafInfo ** next = &(fCounter2->fNext); + while(*next != 0) next = &( (*next)->fNext); + *next = new TFormLeafInfoCollectionSize(motherclassptr,offset,element); +} + +//______________________________________________________________________________ +TFormLeafInfoMultiVarDimCollection::TFormLeafInfoMultiVarDimCollection() : + TFormLeafInfoMultiVarDim() +{ +} + +//______________________________________________________________________________ +TFormLeafInfoMultiVarDimCollection::TFormLeafInfoMultiVarDimCollection( + const TFormLeafInfoMultiVarDimCollection& orig) : + TFormLeafInfoMultiVarDim(orig) +{ +} + +//______________________________________________________________________________ +TFormLeafInfo* TFormLeafInfoMultiVarDimCollection::DeepCopy() const +{ + return new TFormLeafInfoMultiVarDimCollection(*this); +} + +//______________________________________________________________________________ +Double_t TFormLeafInfoMultiVarDimCollection::GetValue(TLeaf *leaf, Int_t instance) +{ + /* The proper indexing and unwinding of index need to be done by prior leafinfo in the chain. */ + Error("GetValue","This should never be called"); + return 0; +} + +//______________________________________________________________________________ +void TFormLeafInfoMultiVarDimCollection::LoadSizes(TBranch* branch) +{ + Assert(fCounter2); + + TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0); + fNsize = (Int_t)fCounter->GetCounterValue(leaf); + + if (fNsize > fSizes.GetSize()) fSizes.Set(fNsize); + fSumOfSizes = 0; + for (Int_t i=0; i<fNsize; i++) { + Int_t size = (Int_t)fCounter2->GetValue(leaf,i); + fSumOfSizes += size; + fSizes.AddAt( size, i ); + } + return; +} + +//______________________________________________________________________________ +Double_t TFormLeafInfoMultiVarDimCollection::ReadValue(char *where, Int_t instance) +{ + return fNext->ReadValue(where,instance); +} + //______________________________________________________________________________ // // TFormLeafInfoCast is a small helper class to implement casting an object to // a different type (equivalent to dynamic_cast) +//______________________________________________________________________________ //______________________________________________________________________________ TFormLeafInfoCast::TFormLeafInfoCast(TClass* classptr, TClass* casted) : diff --git a/treeplayer/src/TTreeFormula.cxx b/treeplayer/src/TTreeFormula.cxx index 6d62691c5f537d259902162c7df53bac848aec5f..0e2d6ec07a662f51aa2ed41c7803d7a4f6a52f65 100644 --- a/treeplayer/src/TTreeFormula.cxx +++ b/treeplayer/src/TTreeFormula.cxx @@ -1,4 +1,4 @@ -// @(#)root/treeplayer:$Name: $:$Id: TTreeFormula.cxx,v 1.163 2005/02/09 10:19:54 brun Exp $ +// @(#)root/treeplayer:$Name: $:$Id: TTreeFormula.cxx,v 1.164 2005/02/18 09:15:08 rdm Exp $ // Author: Rene Brun 19/01/96 /************************************************************************* @@ -306,10 +306,10 @@ void TTreeFormula::DefineDimensions(Int_t code, Int_t size, if (info) { fManager->EnableMultiVarDims(); - if (fIndexes[code][info->fDim]<0) { + //if (fIndexes[code][info->fDim]<0) { // removed because the index might be out of bounds! info->fVirtDim = virt_dim; fManager->AddVarDims(virt_dim); // if (!fVarDims[virt_dim]) fVarDims[virt_dim] = new TArrayI; - } + //} } Int_t vsize = 0; @@ -434,10 +434,14 @@ Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo) { } else if (elem->GetClassPointer() && elem->GetClassPointer()->GetCollectionProxy() ) { - ndim = 1; - size = -1; - - Assert( typeid(*leafinfo) == typeid(TFormLeafInfoCollection) ); + if ( typeid(*leafinfo) == typeid(TFormLeafInfoCollection) ) { + ndim = 1; + size = -1; + } else { + Assert( fHasMultipleVarDim[code] ); + ndim = 1; + size = 1; + } } else if (elem->GetArrayDim()>0) { @@ -599,7 +603,8 @@ Int_t TTreeFormula::DefineAlternate(const char *expression) if (alternate->GetManager()->GetMultiplicity() != 0 ) { Error("DefinedVariable","The 2nd arguments in %s can not be an array (%s,%d)!", - expression,alternate->GetTitle(),alternate->GetManager()->GetMultiplicity()); + expression,alternate->GetTitle(), + alternate->GetManager()->GetMultiplicity()); return -1; } @@ -608,13 +613,15 @@ Int_t TTreeFormula::DefineAlternate(const char *expression) short isstring = 0; if (primary->IsString()) { if (!alternate->IsString()) { - Error("DefinedVariable","The 2nd arguments in %s has to return the same type as the 1st argument (string)!", + Error("DefinedVariable", + "The 2nd arguments in %s has to return the same type as the 1st argument (string)!", expression); return -1; } isstring = 1; } else if (alternate->IsString()) { - Error("DefinedVariable","The 2nd arguments in %s has to return the same type as the 1st argument (numerical type)!", + Error("DefinedVariable", + "The 2nd arguments in %s has to return the same type as the 1st argument (numerical type)!", expression); return -1; } @@ -646,482 +653,558 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression, Int_t action = 0; - if (leaf) { // We found a Leaf. + Assert(leaf); - Int_t numberOfVarDim = 0; - char *current; + Int_t numberOfVarDim = 0; + char *current; - char scratch[kMaxLen]; scratch[0] = '\0'; - char work[kMaxLen]; work[0] = '\0'; + char scratch[kMaxLen]; scratch[0] = '\0'; + char work[kMaxLen]; work[0] = '\0'; - const char *right = subExpression; - TString name = fullExpression; + const char *right = subExpression; + TString name = fullExpression; - TBranch *branch = leaf->GetBranch(); - Long64_t readentry = fTree->GetReadEntry(); - if (readentry==-1) readentry=0; + TBranch *branch = leaf->GetBranch(); + Long64_t readentry = fTree->GetReadEntry(); + if (readentry==-1) readentry=0; - Int_t code = fNcodes-1; + Int_t code = fNcodes-1; - // Make a check to prevent problem with some corrupted files (missing TStreamerInfo). - if (leaf->IsA()==TLeafElement::Class()) { - TBranchElement *br = ((TBranchElement*)leaf->GetBranch()); + // Make a check to prevent problem with some corrupted files (missing TStreamerInfo). + if (leaf->IsA()==TLeafElement::Class()) { + TBranchElement *br = ((TBranchElement*)leaf->GetBranch()); - if ( br->GetInfo() == 0 ) { - Error("DefinedVariable","Missing StreamerInfo for %s. We will be unable to read!", - name.Data()); + if ( br->GetInfo() == 0 ) { + Error("DefinedVariable","Missing StreamerInfo for %s. We will be unable to read!", + name.Data()); + return -2; + } + TBranchElement *mom = (TBranchElement*)br->GetMother(); + if (mom!=br) { + if (mom->GetInfo()==0) { + Error("DefinedVariable","Missing StreamerInfo for %s." + " We will be unable to read!", + mom->GetName()); return -2; } - TBranchElement *mom = (TBranchElement*)br->GetMother(); - if (mom!=br) { - if (mom->GetInfo()==0) { - Error("DefinedVariable","Missing StreamerInfo for %s. We will be unable to read!", - mom->GetName()); - return -2; - } - if (mom->GetType()<0 && mom->GetAddress()==0) { - Error("DefinedVariable","Address not set when the type of the branch is negatif for for %s. We will be unable to read!", - mom->GetName()); - return -2; - } + if (mom->GetType()<0 && mom->GetAddress()==0) { + Error("DefinedVariable", + "Address not set when the type of the branch is negatif for for %s." + " We will be unable to read!", + mom->GetName()); + return -2; } } + } - // We need to record the location in the list of leaves because - // the tree might actually be a chain and in that case the leaf will - // change from tree to tree!. + // We need to record the location in the list of leaves because + // the tree might actually be a chain and in that case the leaf will + // change from tree to tree!. + + // Let's reconstruct the name of the leaf, including the possible friend alias + TTree *realtree = fTree->GetTree(); + const char* alias = 0; + if (realtree) alias = realtree->GetFriendAlias(leaf->GetBranch()->GetTree()); + if (alias) sprintf(scratch,"%s.%s",alias,leaf->GetName()); + else strcpy(scratch,leaf->GetName()); + + TTree *tleaf = leaf->GetBranch()->GetTree(); + fCodes[code] = tleaf->GetListOfLeaves()->IndexOf(leaf); + TNamed *named = new TNamed(scratch,leaf->GetBranch()->GetName()); + fLeafNames.AddAtAndExpand(named,code); + fLeaves.AddAtAndExpand(leaf,code); + + // If the leaf belongs to a friend tree which has an index, we might + // be in the case where some entry do not exist. + if (tleaf != realtree && tleaf->GetTreeIndex()) { + // reset the multiplicity + if (fMultiplicity == 0) fMultiplicity = 1; + } - // Let's reconstruct the name of the leaf, including the possible friend alias - TTree *realtree = fTree->GetTree(); - const char* alias = 0; - if (realtree) alias = realtree->GetFriendAlias(leaf->GetBranch()->GetTree()); - if (alias) sprintf(scratch,"%s.%s",alias,leaf->GetName()); - else strcpy(scratch,leaf->GetName()); + // Analyze the content of 'right' - TTree *tleaf = leaf->GetBranch()->GetTree(); - fCodes[code] = tleaf->GetListOfLeaves()->IndexOf(leaf); - TNamed *named = new TNamed(scratch,leaf->GetBranch()->GetName()); - fLeafNames.AddAtAndExpand(named,code); - fLeaves.AddAtAndExpand(leaf,code); - - // If the leaf belongs to a friend tree which has an index, we might - // be in the case where some entry do not exist. - if (tleaf != realtree && tleaf->GetTreeIndex()) { - // reset the multiplicity - if (fMultiplicity == 0) fMultiplicity = 1; - } - - // Analyze the content of 'right' - - // Try to find out the class (if any) of the object in the leaf. - TClass * cl = 0; - TFormLeafInfo *maininfo = 0; - TFormLeafInfo *previnfo = 0; - - if (leaf->InheritsFrom("TLeafObject") ) { - TBranchObject *bobj = (TBranchObject*)leaf->GetBranch(); - cl = gROOT->GetClass(bobj->GetClassName()); - } else if (leaf->InheritsFrom("TLeafElement")) { - TBranchElement *BranchEl = (TBranchElement *)leaf->GetBranch(); - TStreamerInfo *info = BranchEl->GetInfo(); - TStreamerElement *element = 0; - Int_t type = BranchEl->GetStreamerType(); - switch(type) { - case TStreamerInfo::kBase: - case TStreamerInfo::kObject: - case TStreamerInfo::kTString: - case TStreamerInfo::kTNamed: - case TStreamerInfo::kTObject: - case TStreamerInfo::kAny: - case TStreamerInfo::kAnyP: - case TStreamerInfo::kAnyp: - case TStreamerInfo::kSTL: - case TStreamerInfo::kSTLp: - case TStreamerInfo::kObjectp: - case TStreamerInfo::kObjectP: { - element = (TStreamerElement *)info->GetElems()[BranchEl->GetID()]; - if (element) cl = element->GetClassPointer(); - } - break; - case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL: - case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp: - case TStreamerInfo::kOffsetL + TStreamerInfo::kAny: - case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp: - case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP: - case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp: - case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP: - case TStreamerInfo::kOffsetL + TStreamerInfo::kObject: { - element = (TStreamerElement *)info->GetElems()[BranchEl->GetID()]; - if (element){ - cl = element->GetClassPointer(); - } - } - break; - case -1: { - cl = info->GetClass(); + // Try to find out the class (if any) of the object in the leaf. + TClass * cl = 0; + TFormLeafInfo *maininfo = 0; + TFormLeafInfo *previnfo = 0; + Bool_t unwindCollection = kFALSE; + + if (leaf->InheritsFrom("TLeafObject") ) { + TBranchObject *bobj = (TBranchObject*)leaf->GetBranch(); + cl = gROOT->GetClass(bobj->GetClassName()); + } else if (leaf->InheritsFrom("TLeafElement")) { + TBranchElement *BranchEl = (TBranchElement *)leaf->GetBranch(); + TStreamerInfo *info = BranchEl->GetInfo(); + TStreamerElement *element = 0; + Int_t type = BranchEl->GetStreamerType(); + switch(type) { + case TStreamerInfo::kBase: + case TStreamerInfo::kObject: + case TStreamerInfo::kTString: + case TStreamerInfo::kTNamed: + case TStreamerInfo::kTObject: + case TStreamerInfo::kAny: + case TStreamerInfo::kAnyP: + case TStreamerInfo::kAnyp: + case TStreamerInfo::kSTL: + case TStreamerInfo::kSTLp: + case TStreamerInfo::kObjectp: + case TStreamerInfo::kObjectP: { + element = (TStreamerElement *)info->GetElems()[BranchEl->GetID()]; + if (element) cl = element->GetClassPointer(); + } + break; + case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL: + case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kAny: + case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObject: { + element = (TStreamerElement *)info->GetElems()[BranchEl->GetID()]; + if (element){ + cl = element->GetClassPointer(); } - break; } + break; + case -1: { + cl = info->GetClass(); + } + break; + } - // If we got a class object, we need to verify whether it is on a - // split TClonesArray sub branch. - if (cl && BranchEl->GetBranchCount()) { - if (BranchEl->GetType()==31) { - // This is inside a TClonesArray. - - if (!element) { - Warning("DefineVariable","Missing TStreamerElement in object in TClonesArray section"); - return -2; - } - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE); - - // The following code was commmented out because in THIS case - // the dimension are actually handled by parsing the title and name of the leaf - // and branch (see a little further) - // The dimension needs to be handled! - // numberOfVarDim += RegisterDimensions(code,clonesinfo); - - maininfo = clonesinfo; - - // We skip some cases because we can assume we have an object. - Int_t offset; - info->GetStreamerElement(element->GetName(),offset); - if (type == TStreamerInfo::kObjectp || - type == TStreamerInfo::kObjectP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP || - type == TStreamerInfo::kSTLp || - type == TStreamerInfo::kAnyp || - type == TStreamerInfo::kAnyP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) { - previnfo = new TFormLeafInfoPointer(cl,offset+BranchEl->GetOffset(),element); - } else { - previnfo = new TFormLeafInfo(cl,offset+BranchEl->GetOffset(),element); - } - maininfo->fNext = previnfo; - - } else if (BranchEl->GetType()==41) { - - // This is inside a Collection - - if (!element) { - Warning("DefineVariable","Missing TStreamerElement in object in Collection section"); - return -2; - } - // First we need to recover the collection. - TBranchElement *count = BranchEl->GetBranchCount(); - TFormLeafInfo* collectioninfo; - if ( count->GetID() >= 0 ) { - TStreamerElement *collectionElement = (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()]; - TClass *collectionCl = collectionElement->GetClassPointer(); - - collectioninfo = new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE); - } else { - TClass *collectionCl = gROOT->GetClass(count->GetClassName()); - collectioninfo = new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE); - } - - // The following code was commmented out because in THIS case - // the dimension are actually handled by parsing the title and name of the leaf - // and branch (see a little further) - // The dimension needs to be handled! - // numberOfVarDim += RegisterDimensions(code,clonesinfo); - - maininfo = collectioninfo; - - // We skip some cases because we can assume we have an object. - Int_t offset; - info->GetStreamerElement(element->GetName(),offset); - if (type == TStreamerInfo::kObjectp || - type == TStreamerInfo::kObjectP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP || - type == TStreamerInfo::kSTLp || - type == TStreamerInfo::kAnyp || - type == TStreamerInfo::kAnyP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) { - previnfo = new TFormLeafInfoPointer(cl,offset+BranchEl->GetOffset(),element); - } else { - previnfo = new TFormLeafInfo(cl,offset+BranchEl->GetOffset(),element); - } - maininfo->fNext = previnfo; + // If we got a class object, we need to verify whether it is on a + // split TClonesArray sub branch. + if (cl && BranchEl->GetBranchCount()) { + if (BranchEl->GetType()==31) { + // This is inside a TClonesArray. + if (!element) { + Warning("DefineVariable", + "Missing TStreamerElement in object in TClonesArray section"); + return -2; } + TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE); - } else if (BranchEl->GetType()==3) { - - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE); + // The following code was commmented out because in THIS case + // the dimension are actually handled by parsing the title and name of the leaf + // and branch (see a little further) // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,clonesinfo); + // numberOfVarDim += RegisterDimensions(code,clonesinfo); maininfo = clonesinfo; - previnfo = maininfo; - } else if (BranchEl->GetType()==4) { + // We skip some cases because we can assume we have an object. + Int_t offset; + info->GetStreamerElement(element->GetName(),offset); + if (type == TStreamerInfo::kObjectp || + type == TStreamerInfo::kObjectP || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP || + type == TStreamerInfo::kSTLp || + type == TStreamerInfo::kAnyp || + type == TStreamerInfo::kAnyP || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) { + previnfo = new TFormLeafInfoPointer(cl,offset+BranchEl->GetOffset(),element); + } else { + previnfo = new TFormLeafInfo(cl,offset+BranchEl->GetOffset(),element); + } + maininfo->fNext = previnfo; + unwindCollection = kTRUE; - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + } else if (BranchEl->GetType()==41) { - maininfo = collectioninfo; - previnfo = maininfo; + // This is inside a Collection - } else if (BranchEl->GetStreamerType()==-1 && cl && cl->GetCollectionProxy()) { + if (!element) { + Warning("DefineVariable","Missing TStreamerElement in object in Collection section"); + return -2; + } + // First we need to recover the collection. + TBranchElement *count = BranchEl->GetBranchCount(); + TFormLeafInfo* collectioninfo; + if ( count->GetID() >= 0 ) { + TStreamerElement *collectionElement = + (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()]; + TClass *collectionCl = collectionElement->GetClassPointer(); + + collectioninfo = + new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE); + } else { + TClass *collectionCl = gROOT->GetClass(count->GetClassName()); + collectioninfo = + new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE); + } - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE); + // The following code was commmented out because in THIS case + // the dimension are actually handled by parsing the title and name of the leaf + // and branch (see a little further) // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + // numberOfVarDim += RegisterDimensions(code,clonesinfo); maininfo = collectioninfo; - if (cl->GetCollectionProxy()->GetValueClass()==0 && - cl->GetCollectionProxy()->GetType()>0) { - collectioninfo->fNext = - new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType()); - previnfo = collectioninfo->fNext; + // We skip some cases because we can assume we have an object. + Int_t offset; + info->GetStreamerElement(element->GetName(),offset); + if (type == TStreamerInfo::kObjectp || + type == TStreamerInfo::kObjectP || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP || + type == TStreamerInfo::kSTLp || + type == TStreamerInfo::kAnyp || + type == TStreamerInfo::kAnyP || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp || + type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) { + previnfo = new TFormLeafInfoPointer(cl,offset+BranchEl->GetOffset(),element); } else { - previnfo = collectioninfo; + previnfo = new TFormLeafInfo(cl,offset+BranchEl->GetOffset(),element); } + maininfo->fNext = previnfo; + unwindCollection = kTRUE; + } - } else if (strlen(right)==0 && cl && element && !element->IsaPointer() && final) { + } else if (BranchEl->GetType()==3) { - if (element->GetClassPointer() && element->GetClassPointer()->GetCollectionProxy() - && element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0 - && element->GetClassPointer()->GetCollectionProxy()->GetType()>0) { + TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,clonesinfo); - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl,BranchEl->GetOffset(),element); + maininfo = clonesinfo; + previnfo = maininfo; - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + } else if (BranchEl->GetType()==4) { - collectioninfo->fNext = new TFormLeafInfoNumerical(element->GetClassPointer()->GetCollectionProxy()->GetType()); + TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); - maininfo = collectioninfo; - previnfo = maininfo->fNext; + maininfo = collectioninfo; + previnfo = maininfo; - } else { + } else if (BranchEl->GetStreamerType()==-1 && cl && cl->GetCollectionProxy()) { - maininfo = new TFormLeafInfoDirect(BranchEl); - previnfo = maininfo; + TFormLeafInfo *collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); - } + maininfo = collectioninfo; + previnfo = collectioninfo; + + if (cl->GetCollectionProxy()->GetValueClass()!=0 && + cl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0) { - } - } + TFormLeafInfo *multi = new TFormLeafInfoMultiVarDimCollection(cl,0, + cl->GetCollectionProxy()->GetValueClass(),collectioninfo); - // Treat the dimension information in the leaf name, title and 2nd branch count - numberOfVarDim += RegisterDimensions(code,leaf); + fHasMultipleVarDim[code] = kTRUE; + numberOfVarDim += RegisterDimensions(code,multi); + previnfo->fNext = multi; + cl = cl->GetCollectionProxy()->GetValueClass(); + multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false); + previnfo = multi->fNext; - if (cl) { - Int_t offset; - Int_t nchname = strlen(right); - TFormLeafInfo *leafinfo = 0; - TStreamerElement* element = 0; - - // Let see if the leaf was attempted to be casted. - // Since there would have been something like - // ((cast_class*)leafname)->.... we need to use - // paran_level+2 - // Also we disable this functionality in case of TClonesArray - // because it is not yet allowed to have 'inheritance' (or virtuality) - // in play in a TClonesArray. - TClass * casted = (TClass*) castqueue.At(paran_level+2); - if (casted && cl != TClonesArray::Class()) { - if ( ! casted->InheritsFrom(cl) ) { - Error("DefinedVariable","%s does not inherit from %s. Casting not possible!", - casted->GetName(),cl->GetName()); - return -2; - } - leafinfo = new TFormLeafInfoCast(cl,casted); - fHasCast = kTRUE; - if (maininfo==0) { - maininfo = leafinfo; - } - if (previnfo==0) { - previnfo = leafinfo; - } else { - previnfo->fNext = leafinfo; - previnfo = leafinfo; - } - leafinfo = 0; + } + if (cl->GetCollectionProxy()->GetValueClass()==0 && + cl->GetCollectionProxy()->GetType()>0) { - cl = casted; - castqueue.AddAt(0,paran_level); + previnfo->fNext = + new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType()); + previnfo = previnfo->fNext; + } else { + // nothing to do } - Int_t i; - for (i=0, current = &(work[0]); i<=nchname;i++ ) { - // We will treated the terminator as a token. - if (right[i] == '(') { - // Right now we do not allow nested paranthesis - do { - *current++ = right[i++]; - } while(right[i]!=')' && right[i]); - *current++ = right[i++]; - *current='\0'; - char *params = strchr(work,'('); - if (params) { - *params = 0; params++; - } else params = (char *) ")"; - if (cl==0) { - Error("DefinedVariable","Can not call '%s' with a class",work); - return -1; - } - if (cl->GetClassInfo()==0 && !cl->GetCollectionProxy()) { - Error("DefinedVariable","Class probably unavailable:%s",cl->GetName()); - return -2; - } - if (cl == TClonesArray::Class()) { - // We are NEVER interested in the ClonesArray object but only - // in its contents. - // We need to retrieve the class of its content. + } else if (strlen(right)==0 && cl && element && final) { - TBranch *branch = leaf->GetBranch(); - branch->GetEntry(readentry); - TClonesArray * clones; - if (previnfo) clones = (TClonesArray*)previnfo->GetLocalValuePointer(leaf,0); - else { - if (branch==((TBranchElement*)branch)->GetMother() - || !leaf->IsOnTerminalBranch() ) { - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); - } + TClass *elemCl = element->GetClassPointer(); + if (elemCl && elemCl->GetCollectionProxy() + && elemCl->GetCollectionProxy()->GetValueClass() + && elemCl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()) { - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0, kTRUE); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,clonesinfo); + TFormLeafInfo *collectioninfo = + new TFormLeafInfoCollection(cl, 0, elemCl); - previnfo = clonesinfo; - maininfo = clonesinfo; + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); - clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); - //clones = *(TClonesArray**)((TBranchElement*)branch)->GetAdress(); - } else { - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); - } + maininfo = collectioninfo; + previnfo = collectioninfo; + + TFormLeafInfo *multi = + new TFormLeafInfoMultiVarDimCollection(elemCl, 0, + elemCl->GetCollectionProxy()->GetValueClass(), + collectioninfo); + + fHasMultipleVarDim[code] = kTRUE; + numberOfVarDim += RegisterDimensions(code,multi); + previnfo->fNext = multi; + cl = elemCl->GetCollectionProxy()->GetValueClass(); + multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false); + previnfo = multi->fNext; - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,clonesinfo); + if (cl->GetCollectionProxy()->GetValueClass()==0 && + cl->GetCollectionProxy()->GetType()>0) { - previnfo = clonesinfo; - maininfo = clonesinfo; + previnfo->fNext = + new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType()); + previnfo = previnfo->fNext; + } - clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); - } - } - TClass * inside_cl = clones->GetClass(); - if (1 || inside_cl) cl = inside_cl; + } else if (elemCl && elemCl->GetCollectionProxy() + && elemCl->GetCollectionProxy()->GetValueClass()==0 + && elemCl->GetCollectionProxy()->GetType()>0) { - } else if (cl && cl->GetCollectionProxy() ) { + // At this point we have an element which is inside a class (which is not + // a collection) and this element of a collection of numerical type. + // (Note: it is not possible to have more than one variable dimension + // unless we were supporting variable size C-style array of collection). - // We are NEVER (for now!) interested in the ClonesArray object but only - // in its contents. - // We need to retrieve the class of its content. + TFormLeafInfo* collectioninfo = + new TFormLeafInfoCollection(cl, 0, elemCl); - if (previnfo==0) { + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); - if (branch==((TBranchElement*)branch)->GetMother() - || !leaf->IsOnTerminalBranch() ) { + collectioninfo->fNext = + new TFormLeafInfoNumerical(elemCl->GetCollectionProxy()->GetType()); - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); - } + maininfo = collectioninfo; + previnfo = maininfo->fNext; - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(mother_cl, 0,cl,kTRUE); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + } else if (!element->IsaPointer()) { - previnfo = collectioninfo; - maininfo = collectioninfo; + maininfo = new TFormLeafInfoDirect(BranchEl); + previnfo = maininfo; - } else { + } - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); - } + } + } + + // Treat the dimension information in the leaf name, title and 2nd branch count + numberOfVarDim += RegisterDimensions(code,leaf); - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(mother_cl, 0, cl); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + if (cl) { + if (unwindCollection) { + // So far we should get here only if we encounter a split collection of a class that contains + // directly a collection. + Assert(numberOfVarDim==1 && maininfo); - previnfo = collectioninfo; - maininfo = collectioninfo; + if (cl && cl->GetCollectionProxy()) { + TFormLeafInfo *multi = + new TFormLeafInfoMultiVarDimCollection(cl, 0, cl, maininfo); + fHasMultipleVarDim[code] = kTRUE; + numberOfVarDim += RegisterDimensions(code,multi); + previnfo->fNext = multi; - } + multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false); + previnfo = multi->fNext; - } + if (cl->GetCollectionProxy()->GetValueClass()==0 && + cl->GetCollectionProxy()->GetType()>0) { - TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass(); - if (inside_cl) cl = inside_cl; - else if (cl->GetCollectionProxy()->GetType()>0) { - Warning("DefinedVariable","Can not call method on content of %s in %s\n", - cl->GetName(),name.Data()); + previnfo->fNext = + new TFormLeafInfoNumerical(cl->GetCollectionProxy()->GetType()); + previnfo = previnfo->fNext; + } + } + } + Int_t offset; + Int_t nchname = strlen(right); + TFormLeafInfo *leafinfo = 0; + TStreamerElement* element = 0; + + // Let see if the leaf was attempted to be casted. + // Since there would have been something like + // ((cast_class*)leafname)->.... we need to use + // paran_level+2 + // Also we disable this functionality in case of TClonesArray + // because it is not yet allowed to have 'inheritance' (or virtuality) + // in play in a TClonesArray. + TClass * casted = (TClass*) castqueue.At(paran_level+2); + if (casted && cl != TClonesArray::Class()) { + if ( ! casted->InheritsFrom(cl) ) { + Error("DefinedVariable","%s does not inherit from %s. Casting not possible!", + casted->GetName(),cl->GetName()); + return -2; + } + leafinfo = new TFormLeafInfoCast(cl,casted); + fHasCast = kTRUE; + if (maininfo==0) { + maininfo = leafinfo; + } + if (previnfo==0) { + previnfo = leafinfo; + } else { + previnfo->fNext = leafinfo; + previnfo = leafinfo; + } + leafinfo = 0; + + cl = casted; + castqueue.AddAt(0,paran_level); + } + + Int_t i; + for (i=0, current = &(work[0]); i<=nchname;i++ ) { + // We will treated the terminator as a token. + if (right[i] == '(') { + // Right now we do not allow nested paranthesis + do { + *current++ = right[i++]; + } while(right[i]!=')' && right[i]); + *current++ = right[i++]; + *current='\0'; + char *params = strchr(work,'('); + if (params) { + *params = 0; params++; + } else params = (char *) ")"; + if (cl==0) { + Error("DefinedVariable","Can not call '%s' with a class",work); + return -1; + } + if (cl->GetClassInfo()==0 && !cl->GetCollectionProxy()) { + Error("DefinedVariable","Class probably unavailable:%s",cl->GetName()); + return -2; + } + if (cl == TClonesArray::Class()) { + // We are NEVER interested in the ClonesArray object but only + // in its contents. + // We need to retrieve the class of its content. + + TBranch *branch = leaf->GetBranch(); + branch->GetEntry(readentry); + TClonesArray * clones; + if (previnfo) clones = (TClonesArray*)previnfo->GetLocalValuePointer(leaf,0); + else { + Bool_t top = (branch==((TBranchElement*)branch)->GetMother() + || !leaf->IsOnTerminalBranch()); + TClass *mother_cl; + if (leaf->IsA()==TLeafObject::Class()) { + // in this case mother_cl is not really used + mother_cl = cl; + } else { + mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); } + TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0, top); + + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,clonesinfo); + previnfo = clonesinfo; + maininfo = clonesinfo; + + clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); } + TClass * inside_cl = clones->GetClass(); + if (1 || inside_cl) cl = inside_cl; + + } else if (cl && cl->GetCollectionProxy() ) { + + // We are NEVER (for now!) interested in the ClonesArray object but only + // in its contents. + // We need to retrieve the class of its content. + + if (previnfo==0) { + + Bool_t top = (branch==((TBranchElement*)branch)->GetMother() + || !leaf->IsOnTerminalBranch()); + + TClass *mother_cl; + if (leaf->IsA()==TLeafObject::Class()) { + // in this case mother_cl is not really used + mother_cl = cl; + } else { + mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); + } + + TFormLeafInfo* collectioninfo = + new TFormLeafInfoCollection(mother_cl, 0,cl,top); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); + + previnfo = collectioninfo; + maininfo = collectioninfo; - TMethodCall *method; - if (cl->GetClassInfo()==0) { - Error("DefinedVariable","Can not call method %s on class without dictionary (%s)!", - right,cl->GetName()); - return -2; } - method = new TMethodCall(cl, work, params); - if (!method->GetMethod()) { - Error("DefinedVariable","Unknown method:%s",right); - return -1; + + TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass(); + if (inside_cl) cl = inside_cl; + else if (cl->GetCollectionProxy()->GetType()>0) { + Warning("DefinedVariable","Can not call method on content of %s in %s\n", + cl->GetName(),name.Data()); } - switch(method->ReturnType()) { - case TMethodCall::kLong: - leafinfo = new TFormLeafInfoMethod(cl,method); - cl = 0; - break; - case TMethodCall::kDouble: - leafinfo = new TFormLeafInfoMethod(cl,method); - cl = 0; - break; - case TMethodCall::kString: + } + + TMethodCall *method; + if (cl->GetClassInfo()==0) { + Error("DefinedVariable", + "Can not call method %s on class without dictionary (%s)!", + right,cl->GetName()); + return -2; + } + method = new TMethodCall(cl, work, params); + if (!method->GetMethod()) { + Error("DefinedVariable","Unknown method:%s",right); + return -1; + } + switch(method->ReturnType()) { + case TMethodCall::kLong: + leafinfo = new TFormLeafInfoMethod(cl,method); + cl = 0; + break; + case TMethodCall::kDouble: + leafinfo = new TFormLeafInfoMethod(cl,method); + cl = 0; + break; + case TMethodCall::kString: + leafinfo = new TFormLeafInfoMethod(cl,method); + // 1 will be replaced by -1 when we know how to use strlen + numberOfVarDim += RegisterDimensions(code,1); //NOTE: changed from 0 + cl = 0; + break; + case TMethodCall::kOther: + { + TString return_type = + gInterpreter->TypeName(method->GetMethod()->GetReturnTypeName()); leafinfo = new TFormLeafInfoMethod(cl,method); - // 1 will be replaced by -1 when we know how to use strlen - numberOfVarDim += RegisterDimensions(code,1); //NOTE: changed from 0 - cl = 0; - break; - case TMethodCall::kOther: - {TString return_type = gInterpreter->TypeName(method->GetMethod()->GetReturnTypeName()); - leafinfo = new TFormLeafInfoMethod(cl,method); - if (return_type != "void") { - cl = gROOT->GetClass(return_type.Data()); - } else { - cl = 0; - } - }; break; - default: - Error("DefineVariable","Method %s from %s has an impossible return type %d", - work,cl->GetName(),method->ReturnType()); - return -2; - } + if (return_type != "void") { + cl = gROOT->GetClass(return_type.Data()); + } else { + cl = 0; + } + }; break; + default: + Error("DefineVariable","Method %s from %s has an impossible return type %d", + work,cl->GetName(),method->ReturnType()); + return -2; + } + if (maininfo==0) { + maininfo = leafinfo; + } + if (previnfo==0) { + previnfo = leafinfo; + } else { + previnfo->fNext = leafinfo; + previnfo = leafinfo; + } + leafinfo = 0; + current = &(work[0]); + *current = 0; + continue; + } else if (right[i] == ')') { + // We should have the end of a cast operator. Let's introduce a TFormLeafCast + // in the chain. + TClass * casted = (TClass*) castqueue.At(--paran_level); + if (casted) { + leafinfo = new TFormLeafInfoCast(cl,casted); + fHasCast = kTRUE; + if (maininfo==0) { maininfo = leafinfo; } @@ -1134,379 +1217,433 @@ Int_t TTreeFormula::ParseWithLeaf(TLeaf *leaf, const char *subExpression, leafinfo = 0; current = &(work[0]); *current = 0; + + cl = casted; continue; - } else if (right[i] == ')') { - // We should have the end of a cast operator. Let's introduce a TFormLeafCast - // in the chain. - TClass * casted = (TClass*) castqueue.At(--paran_level); - if (casted) { - leafinfo = new TFormLeafInfoCast(cl,casted); - fHasCast = kTRUE; - - if (maininfo==0) { - maininfo = leafinfo; - } - if (previnfo==0) { - previnfo = leafinfo; - } else { - previnfo->fNext = leafinfo; - previnfo = leafinfo; - } - leafinfo = 0; - current = &(work[0]); - *current = 0; - cl = casted; - continue; + } + } else if (i > 0 && (right[i] == '.' || right[i] == '[' || right[i] == '\0') ) { + // A delimiter happened let's see if what we have seen + // so far does point to a data member. + *current = '\0'; + + // skip it all if there is nothing to look at + if (strlen(work)==0) continue; + + Bool_t mustderef = kFALSE; + if (cl == TClonesArray::Class()) { + // We are NEVER interested in the ClonesArray object but only + // in its contents. + // We need to retrieve the class of its content. + + TBranch *branch = leaf->GetBranch(); + branch->GetEntry(readentry); + TClonesArray * clones; + if (maininfo) { + clones = (TClonesArray*)maininfo->GetLocalValuePointer(leaf,0); + } else { + // we have a unsplit TClonesArray leaves + // or we did not yet match any of the sub-branches! - } - } else if (i > 0 && (right[i] == '.' || right[i] == '[' || right[i] == '\0') ) { - // A delimiter happened let's see if what we have seen - // so far does point to a data member. - *current = '\0'; + TClass *mother_cl; + if (leaf->IsA()==TLeafObject::Class()) { + // in this case mother_cl is not really used + mother_cl = cl; + } else { + mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); + } - // skip it all if there is nothing to look at - if (strlen(work)==0) continue; + TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,clonesinfo); - Bool_t mustderef = kFALSE; - if (cl == TClonesArray::Class()) { - // We are NEVER interested in the ClonesArray object but only - // in its contents. - // We need to retrieve the class of its content. + mustderef = kTRUE; + previnfo = clonesinfo; + maininfo = clonesinfo; - TBranch *branch = leaf->GetBranch(); - branch->GetEntry(readentry); - TClonesArray * clones; - if (maininfo) clones = (TClonesArray*)maininfo->GetLocalValuePointer(leaf,0); - else { - // we have a unsplit TClonesArray leaves - // or we did not yet match any of the sub-branches! - - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); + if (branch->GetListOfBranches()->GetLast()>=0) { + if (branch->IsA() != TBranchElement::Class()) { + Error("DefinedVariable","Unimplemented usage of ClonesArray"); + return -2; } + //branch = ((TBranchElement*)branch)->GetMother(); + clones = (TClonesArray*)((TBranchElement*)branch)->GetObject(); + } else + clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); + } + // NOTE clones can be zero! + if (clones==0) { + Warning("DefinedVariable", + "TClonesArray object was not retrievable for %s!", + name.Data()); + return -1; + } + TClass * inside_cl = clones->GetClass(); + if (1 || inside_cl) cl = inside_cl; + // if inside_cl is nul ... we have a problem of inconsistency :( + if (0 && strlen(work)==0) { + // However in this case we have NO content :( + // so let get the number of objects + //strcpy(work,"fLast"); + } + } else if (cl && cl->GetCollectionProxy() ) { - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,clonesinfo); - - mustderef = kTRUE; - previnfo = clonesinfo; - maininfo = clonesinfo; - - if (branch->GetListOfBranches()->GetLast()>=0) { - if (branch->IsA() != TBranchElement::Class()) { - Error("DefinedVariable","Unimplemented usage of ClonesArray"); - return -2; - } - //branch = ((TBranchElement*)branch)->GetMother(); - clones = (TClonesArray*)((TBranchElement*)branch)->GetObject(); - } else - clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); - } - // NOTE clones can be zero! - if (clones==0) { - Warning("DefinedVariable","TClonesArray object was not retrievable for %s!", - name.Data()); - return -1; - } - TClass * inside_cl = clones->GetClass(); - if (1 || inside_cl) cl = inside_cl; - // if inside_cl is nul ... we have a problem of inconsistency :( - if (0 && strlen(work)==0) { - // However in this case we have NO content :( - // so let get the number of objects - //strcpy(work,"fLast"); - } - } else if (cl && cl->GetCollectionProxy() ) { - - // We are NEVER interested in the Collection object but only - // in its contents. - // We need to retrieve the class of its content. + // We are NEVER interested in the Collection object but only + // in its contents. + // We need to retrieve the class of its content. - TBranch *branch = leaf->GetBranch(); - branch->GetEntry(readentry); + TBranch *branch = leaf->GetBranch(); + branch->GetEntry(readentry); - if (maininfo==0) { + if (maininfo==0) { - // we have a unsplit Collection leaves - // or we did not yet match any of the sub-branches! + // we have a unsplit Collection leaf + // or we did not yet match any of the sub-branches! - TClass *mother_cl; - if (leaf->IsA()==TLeafObject::Class()) { - // in this case mother_cl is not really used - mother_cl = cl; - } else { - mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); - } + TClass *mother_cl; + if (leaf->IsA()==TLeafObject::Class()) { + // in this case mother_cl is not really used + mother_cl = cl; + } else { + mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass(); + } - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(mother_cl, 0, cl); - // The dimension needs to be handled! - numberOfVarDim += RegisterDimensions(code,collectioninfo); + TFormLeafInfo* collectioninfo = + new TFormLeafInfoCollection(mother_cl, 0, cl); + // The dimension needs to be handled! + numberOfVarDim += RegisterDimensions(code,collectioninfo); - mustderef = kTRUE; - previnfo = collectioninfo; - maininfo = collectioninfo; + mustderef = kTRUE; + previnfo = collectioninfo; + maininfo = collectioninfo; - } //else if (branch->GetStreamerType()==0) { + } //else if (branch->GetStreamerType()==0) { - //} - - TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass(); + //} - if (!inside_cl && cl->GetCollectionProxy()->GetType() > 0) { - Warning("DefinedVariable","No data member in content of %s in %s\n", - cl->GetName(),name.Data()); - } - if (1 || inside_cl) cl = inside_cl; - // if inside_cl is nul ... we have a problem of inconsistency :( - } + TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass(); - if (!cl) { - Warning("DefinedVariable","Missing class for %s!",name.Data()); - } else { - element = cl->GetStreamerInfo()->GetStreamerElement(work,offset); + if (!inside_cl && cl->GetCollectionProxy()->GetType() > 0) { + Warning("DefinedVariable","No data member in content of %s in %s\n", + cl->GetName(),name.Data()); } + if (1 || inside_cl) cl = inside_cl; + // if inside_cl is nul ... we have a problem of inconsistency :( + } - if (!element) { - // We allow for looking for a data member inside a class inside - // a TClonesArray without mentioning the TClonesArrays variable name - TIter next( cl->GetStreamerInfo()->GetElements() ); - TStreamerElement * curelem; - while ((curelem = (TStreamerElement*)next())) { - if (curelem->GetClassPointer() == TClonesArray::Class()) { - Int_t clones_offset; - cl->GetStreamerInfo()->GetStreamerElement(curelem->GetName(),clones_offset); - TFormLeafInfo* clonesinfo = new TFormLeafInfo(cl, clones_offset, curelem); - TClonesArray * clones; - leaf->GetBranch()->GetEntry(readentry); - - if (previnfo) { - previnfo->fNext = clonesinfo; - clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0); - previnfo->fNext = 0; - } else { - clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); - } + if (!cl) { + Warning("DefinedVariable","Missing class for %s!",name.Data()); + } else { + element = cl->GetStreamerInfo()->GetStreamerElement(work,offset); + } - TClass *sub_cl = clones->GetClass(); - element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset); - delete clonesinfo; + if (!element) { + // We allow for looking for a data member inside a class inside + // a TClonesArray without mentioning the TClonesArrays variable name + TIter next( cl->GetStreamerInfo()->GetElements() ); + TStreamerElement * curelem; + while ((curelem = (TStreamerElement*)next())) { + if (curelem->GetClassPointer() == TClonesArray::Class()) { + Int_t clones_offset; + cl->GetStreamerInfo()->GetStreamerElement(curelem->GetName(),clones_offset); + TFormLeafInfo* clonesinfo = + new TFormLeafInfo(cl, clones_offset, curelem); + TClonesArray * clones; + leaf->GetBranch()->GetEntry(readentry); + + if (previnfo) { + previnfo->fNext = clonesinfo; + clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0); + previnfo->fNext = 0; + } else { + clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0); + } - if (element) { - leafinfo = new TFormLeafInfoClones(cl,clones_offset,curelem); - numberOfVarDim += RegisterDimensions(code,leafinfo); - if (maininfo==0) maininfo = leafinfo; - if (previnfo==0) previnfo = leafinfo; - else { - previnfo->fNext = leafinfo; - previnfo = leafinfo; - } - leafinfo = 0; - cl = sub_cl; - break; + TClass *sub_cl = clones->GetClass(); + element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset); + delete clonesinfo; + + if (element) { + leafinfo = new TFormLeafInfoClones(cl,clones_offset,curelem); + numberOfVarDim += RegisterDimensions(code,leafinfo); + if (maininfo==0) maininfo = leafinfo; + if (previnfo==0) previnfo = leafinfo; + else { + previnfo->fNext = leafinfo; + previnfo = leafinfo; } - } else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) { - - Int_t coll_offset; - cl->GetStreamerInfo()->GetStreamerElement(curelem->GetName(),coll_offset); + leafinfo = 0; + cl = sub_cl; + break; + } + } else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) { - TClass *sub_cl = curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass(); - if (sub_cl) element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset); + Int_t coll_offset; + cl->GetStreamerInfo()->GetStreamerElement(curelem->GetName(),coll_offset); - if (element) { + TClass *sub_cl = + curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass(); + if (sub_cl) { + element = sub_cl->GetStreamerInfo()->GetStreamerElement(work,offset); + } + if (element) { + if (numberOfVarDim>1) { + leafinfo = new TFormLeafInfo(cl,coll_offset,curelem); + } else if (numberOfVarDim==1) { + TClass *elemCl = element->GetClassPointer(); + Assert(maininfo); + leafinfo = + new TFormLeafInfoMultiVarDimCollection(cl,coll_offset, + curelem,maininfo); + fHasMultipleVarDim[code] = kTRUE; + leafinfo->fNext = new TFormLeafInfoCollection(cl,coll_offset,curelem); + numberOfVarDim += RegisterDimensions(code,leafinfo); + } else { leafinfo = new TFormLeafInfoCollection(cl,coll_offset,curelem); numberOfVarDim += RegisterDimensions(code,leafinfo); - if (maininfo==0) maininfo = leafinfo; - if (previnfo==0) previnfo = leafinfo; - else { - previnfo->fNext = leafinfo; - previnfo = leafinfo; - } - leafinfo = 0; - cl = sub_cl; - break; } + if (maininfo==0) maininfo = leafinfo; + if (previnfo==0) previnfo = leafinfo; + else { + previnfo->fNext = leafinfo; + previnfo = leafinfo; + } + if (leafinfo->fNext) { + previnfo = leafinfo->fNext; + } + leafinfo = 0; + cl = sub_cl; + break; } } - } - if (element) { - Int_t type = element->GetNewType(); - if (type<60 && type!=0) { - // This is a basic type ... - if (numberOfVarDim>=1 && type>40) { - // We have a variable array within a variable array! - leafinfo = new TFormLeafInfoMultiVarDim(cl,offset,element,maininfo); - // fDataMembers.AddAtAndExpand(leafinfo,code); - fHasMultipleVarDim[code] = kTRUE; + } + + if (element) { + Int_t type = element->GetNewType(); + if (type<60 && type!=0) { + // This is a basic type ... + if (numberOfVarDim>=1 && type>40) { + // We have a variable array within a variable array! + leafinfo = new TFormLeafInfoMultiVarDim(cl,offset,element,maininfo); + // fDataMembers.AddAtAndExpand(leafinfo,code); + fHasMultipleVarDim[code] = kTRUE; + } else { + if (leafinfo) { + // leafinfo->fOffset += offset; + leafinfo->AddOffset(offset,element); } else { - if (leafinfo) { - // leafinfo->fOffset += offset; - leafinfo->AddOffset(offset,element); - } else { - leafinfo = new TFormLeafInfo(cl,offset,element); - } + leafinfo = new TFormLeafInfo(cl,offset,element); } - } else if (type == TStreamerInfo::kObjectp || - type == TStreamerInfo::kObjectP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP || - type == TStreamerInfo::kSTLp || - type == TStreamerInfo::kAnyp || - type == TStreamerInfo::kAnyP || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) { - - // this is a pointer to be followed. + } + } else { + Bool_t object = kFALSE; + Bool_t pointer = kFALSE; + Bool_t objarr = kFALSE; + switch(type) { + case TStreamerInfo::kObjectp: + case TStreamerInfo::kObjectP: + case TStreamerInfo::kSTLp: + case TStreamerInfo::kAnyp: + case TStreamerInfo::kAnyP: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP: + case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp: + case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP: + pointer = kTRUE; + break; + case TStreamerInfo::kBase: + case TStreamerInfo::kAny : + case TStreamerInfo::kSTL: + case TStreamerInfo::kObject: + case TStreamerInfo::kTString: + case TStreamerInfo::kTNamed: + case TStreamerInfo::kTObject: + object = kTRUE; + break; + case TStreamerInfo::kOffsetL + TStreamerInfo::kAny: + case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL: + case TStreamerInfo::kOffsetL + TStreamerInfo::kObject: + objarr = kTRUE; + break; + case TStreamerInfo::kStreamer: + case TStreamerInfo::kStreamLoop: + // Unsupported case. + Error("DefinedVariable", + "%s is a datamember of %s BUT is not yet of a supported type (%d)", + right,cl->GetName(),type); + return -2; + default: + // Unknown and Unsupported case. + Error("DefinedVariable", + "%s is a datamember of %s BUT is not of a unknown type (%d)", + right,cl->GetName(),type); + return -2; + } + + if (object && leafinfo) { + // leafinfo->fOffset += offset; + leafinfo->AddOffset(offset,element); + } else if (objarr) { + // This is an embedded array of objects. We can not increase the offset. + leafinfo = new TFormLeafInfo(cl,offset,element); + mustderef = kTRUE; + } else { if (element->GetClassPointer() == TClonesArray::Class()) { leafinfo = new TFormLeafInfoClones(cl,offset,element); mustderef = kTRUE; - } else if (element->GetClassPointer() && element->GetClassPointer()->GetCollectionProxy()) { + } else if (element->GetClassPointer() + && element->GetClassPointer()->GetCollectionProxy()) { - leafinfo = new TFormLeafInfoCollection(cl,offset,element); mustderef = kTRUE; - if (element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0) { - leafinfo->fNext = new TFormLeafInfoNumerical(element->GetClassPointer()->GetCollectionProxy()->GetType()); + if (numberOfVarDim>1) { + leafinfo = new TFormLeafInfo(cl,offset,element); + } else if (numberOfVarDim==1) { + TClass *elemCl = element->GetClassPointer(); + Assert(maininfo); + leafinfo = + new TFormLeafInfoMultiVarDimCollection(cl,offset,element,maininfo); + + fHasMultipleVarDim[code] = kTRUE; + //numberOfVarDim += RegisterDimensions(code,leafinfo); + //cl = cl->GetCollectionProxy()->GetValueClass(); + + //if (maininfo==0) maininfo = leafinfo; + //if (previnfo==0) previnfo = leafinfo; + //else { + // previnfo->fNext = leafinfo; + // previnfo = leafinfo; + //} + leafinfo->fNext = new TFormLeafInfoCollection(cl, offset, element); + if (element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0) { + TFormLeafInfo *info = new TFormLeafInfoNumerical( + element->GetClassPointer()->GetCollectionProxy()->GetType()); + if (leafinfo->fNext) leafinfo->fNext->fNext = info; + else leafinfo->fNext = info; + } + } else { + leafinfo = new TFormLeafInfoCollection(cl, offset, element); + + TClass *elemCl = element->GetClassPointer(); + TClass *valueCl = elemCl->GetCollectionProxy()->GetValueClass(); + if (!maininfo) maininfo = leafinfo; + + if (valueCl!=0 && valueCl->GetCollectionProxy()!=0) { + + numberOfVarDim += RegisterDimensions(code,leafinfo); + if (previnfo==0) previnfo = leafinfo; + else { + previnfo->fNext = leafinfo; + previnfo = leafinfo; + } + leafinfo = new TFormLeafInfoMultiVarDimCollection(elemCl,0, + elemCl->GetCollectionProxy()->GetValueClass(),maininfo); + //numberOfVarDim += RegisterDimensions(code,previnfo->fNext); + fHasMultipleVarDim[code] = kTRUE; + //previnfo = previnfo->fNext; + leafinfo->fNext = new TFormLeafInfoCollection(elemCl,0, + valueCl); + elemCl = valueCl; + } + if (elemCl->GetCollectionProxy() && + elemCl->GetCollectionProxy()->GetValueClass()==0) { + TFormLeafInfo *info = new TFormLeafInfoNumerical( + elemCl->GetCollectionProxy()->GetType()); + if (leafinfo->fNext) leafinfo->fNext->fNext = info; + else leafinfo->fNext = info; + } } - } else { + } else if (pointer) { + // this is a pointer to be followed. leafinfo = new TFormLeafInfoPointer(cl,offset,element); mustderef = kTRUE; - } - } else if (type == TStreamerInfo::kBase || - type == TStreamerInfo::kAny || - type == TStreamerInfo::kSTL || - type == TStreamerInfo::kObject || - type == TStreamerInfo::kTString || - type == TStreamerInfo::kTNamed || - type == TStreamerInfo::kTObject ) { - - // this is an embedded object. We can increase the offset. - if (leafinfo) { - // leafinfo->fOffset += offset; - leafinfo->AddOffset(offset,element); } else { - if (element->GetClassPointer() == TClonesArray::Class()) { - leafinfo = new TFormLeafInfoClones(cl,offset,element); - mustderef = kTRUE; - } else if (element->GetClassPointer()->GetCollectionProxy()) { - leafinfo = new TFormLeafInfoCollection(cl,offset,element); - mustderef = kTRUE; - if (element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0) { - leafinfo->fNext = new TFormLeafInfoNumerical(element->GetClassPointer()->GetCollectionProxy()->GetType()); - } - } else { - leafinfo = new TFormLeafInfo(cl,offset,element); - } + // this is an embedded object. + Assert(object); + leafinfo = new TFormLeafInfo(cl,offset,element); } - } else if (type == TStreamerInfo::kOffsetL + TStreamerInfo::kAny || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTL || - type == TStreamerInfo::kOffsetL + TStreamerInfo::kObject) { - // This is an embedded array of objects. We can not increase the offset. - - leafinfo = new TFormLeafInfo(cl,offset,element); - mustderef = kTRUE; - - } else if (type == TStreamerInfo::kBase || - type == TStreamerInfo::kStreamer || - type == TStreamerInfo::kStreamLoop ) { - // Unsupported case. - Error("DefinedVariable","%s is a datamember of %s BUT is not yet of a supported type (%d)", - right,cl->GetName(),type); - return -2; - } else { - // Unknown and Unsupported case. - Error("DefinedVariable","%s is a datamember of %s BUT is not of a supported type (%d)", - right,cl->GetName(),type); - return -2; } - } else { - Error("DefinedVariable","%s is not a datamember of %s",work,cl->GetName()); - return -1; - } + } + } else { + Error("DefinedVariable","%s is not a datamember of %s",work,cl->GetName()); + return -1; + } - numberOfVarDim += RegisterDimensions(code,leafinfo); - if (maininfo==0) { - maininfo = leafinfo; - } - if (previnfo==0) { - previnfo = leafinfo; - } else if (previnfo!=leafinfo) { - previnfo->fNext = leafinfo; - previnfo = leafinfo; - } - if (previnfo->fNext) previnfo = previnfo->fNext; + numberOfVarDim += RegisterDimensions(code,leafinfo); + if (maininfo==0) { + maininfo = leafinfo; + } + if (previnfo==0) { + previnfo = leafinfo; + } else if (previnfo!=leafinfo) { + previnfo->fNext = leafinfo; + previnfo = leafinfo; + } + while (previnfo->fNext) previnfo = previnfo->fNext; - if (mustderef) leafinfo = 0; - if (right[i]!='\0') { - cl = element->GetClassPointer(); - } - current = &(work[0]); - *current = 0; + if (mustderef) leafinfo = 0; + if (right[i]!='\0') { + cl = element->GetClassPointer(); + } + current = &(work[0]); + *current = 0; - Assert(right[i] != '['); // We are supposed to have removed all dimensions already! - - } else - *current++ = right[i]; - } - if (maininfo) { - fDataMembers.AddAtAndExpand(maininfo,code); - fLookupType[code] = kDataMember; - } + Assert(right[i] != '['); // We are supposed to have removed all dimensions already! + + } else + *current++ = right[i]; } - - if (strlen(work)!=0) { - // We have something left to analyze. Let's make this an error case! - return -1; + if (maininfo) { + fDataMembers.AddAtAndExpand(maininfo,code); + fLookupType[code] = kDataMember; } + } - if (IsLeafString(code)) { - if (fLookupType[code]==kDirect && leaf->InheritsFrom("TLeafElement")) { - TBranchElement * br = (TBranchElement*)leaf->GetBranch(); - if (br->GetType()==31) { - // sub branch of a TClonesArray - TStreamerInfo *info = br->GetInfo(); - TClass* cl = info->GetClass(); - TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()]; - TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE); - Int_t offset; - info->GetStreamerElement(element->GetName(),offset); - clonesinfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element); - fDataMembers.AddAtAndExpand(clonesinfo,code); - fLookupType[code]=kDataMember; - - } else if (br->GetType()==41) { - // sub branch of a Collection - - TStreamerInfo *info = br->GetInfo(); - TClass* cl = info->GetClass(); - TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()]; - TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, element, kTRUE); - Int_t offset; - info->GetStreamerElement(element->GetName(),offset); - collectioninfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element); - fDataMembers.AddAtAndExpand(collectioninfo,code); - fLookupType[code]=kDataMember; + if (strlen(work)!=0) { + // We have something left to analyze. Let's make this an error case! + return -1; + } - } else { - fDataMembers.AddAtAndExpand(new TFormLeafInfoDirect(br),code); - fLookupType[code]=kDataMember; - } + if (IsLeafString(code)) { + if (fLookupType[code]==kDirect && leaf->InheritsFrom("TLeafElement")) { + TBranchElement * br = (TBranchElement*)leaf->GetBranch(); + if (br->GetType()==31) { + // sub branch of a TClonesArray + TStreamerInfo *info = br->GetInfo(); + TClass* cl = info->GetClass(); + TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()]; + TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE); + Int_t offset; + info->GetStreamerElement(element->GetName(),offset); + clonesinfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element); + fDataMembers.AddAtAndExpand(clonesinfo,code); + fLookupType[code]=kDataMember; + + } else if (br->GetType()==41) { + // sub branch of a Collection + + TStreamerInfo *info = br->GetInfo(); + TClass* cl = info->GetClass(); + TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()]; + TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(cl, 0, element, kTRUE); + Int_t offset; + info->GetStreamerElement(element->GetName(),offset); + collectioninfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element); + fDataMembers.AddAtAndExpand(collectioninfo,code); + fLookupType[code]=kDataMember; + + } else { + fDataMembers.AddAtAndExpand(new TFormLeafInfoDirect(br),code); + fLookupType[code]=kDataMember; } - return kDefinedString; } - return action; + return kDefinedString; } - return action; } @@ -2560,9 +2697,13 @@ Int_t TTreeFormula::GetRealInstance(Int_t instance, Int_t codeindex) { // Let's update fCumulSizes for the rest of the code. Int_t vdim = info->GetVarDim(); - fCumulSizes[codeindex][vdim] = info->GetSize(local_index) - *fCumulSizes[codeindex][vdim+1]; - for(Int_t k=vdim -1; k>0; k++) { + Int_t isize = info->GetSize(local_index); + if (fIndexes[codeindex][vdim]>isize) { + // We are out of bounds! + return fNdata[0]+1; + } + fCumulSizes[codeindex][vdim] = isize*fCumulSizes[codeindex][vdim+1]; + for(Int_t k=vdim -1; k>0; --k) { fCumulSizes[codeindex][k] = fCumulSizes[codeindex][k+1]*fFixedSizes[codeindex][k]; } } else { @@ -4024,19 +4165,29 @@ Bool_t TTreeFormula::LoadCurrentDim() { } else { fNdata[i] = size*fCumulSizes[i][1]; } - if (leafinfo->GetVarDim()>=0) { + Int_t vdim = leafinfo->GetVarDim(); + if (vdim>=0) { // Here we need to add the code to take in consideration the // double variable length // We fill up the array of sizes in the TLeafInfo: // here we can assume that branch is a TBranch element because the other style does NOT support this type // of complexity. - leafinfo->LoadSizes(dynamic_cast<TBranchElement*>(branch)); + leafinfo->LoadSizes(branch); hasBranchCount2 = kTRUE; - if (leafinfo->GetVirtVarDim()>=0) leafinfo->UpdateSizes(fManager->fVarDims[leafinfo->GetVirtVarDim()]); + if (fIndexes[i][0]==-1&&fIndexes[i][vdim] >= 0) { + for(int z=0; z<size; ++z) { + if (fIndexes[i][vdim] >= leafinfo->GetSize(z)) { + leafinfo->SetSize(z,0); + // --fManager->fUsedSizes[0]; + } else if (fIndexes[i][vdim] >= 0 ) { + leafinfo->SetSize(z,1); + } + } + } + leafinfo->UpdateSizes(fManager->fVarDims[vdim]); // Refresh the fCumulSizes[i] to have '1' for the // double variable dimensions - Int_t vdim = leafinfo->GetVarDim(); fCumulSizes[i][vdim] = fCumulSizes[i][vdim+1]; for(Int_t k=vdim -1; k>=0; k--) { fCumulSizes[i][k] = fCumulSizes[i][k+1]*fFixedSizes[i][k];