00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012 #include "TROOT.h"
00013 #include "TTreeFormula.h"
00014 #include "TTree.h"
00015 #include "TBranch.h"
00016 #include "TBranchObject.h"
00017 #include "TFunction.h"
00018 #include "TClonesArray.h"
00019 #include "TLeafB.h"
00020 #include "TLeafC.h"
00021 #include "TLeafObject.h"
00022 #include "TDataMember.h"
00023 #include "TMethodCall.h"
00024 #include "TCutG.h"
00025 #include "TRandom.h"
00026 #include "TInterpreter.h"
00027 #include "TDataType.h"
00028 #include "TStreamerInfo.h"
00029 #include "TStreamerElement.h"
00030 #include "TBranchElement.h"
00031 #include "TLeafElement.h"
00032 #include "TArrayI.h"
00033 #include "TAxis.h"
00034 #include "TError.h"
00035 #include "TVirtualCollectionProxy.h"
00036 #include "TString.h"
00037 #include "TTimeStamp.h"
00038 #include "TMath.h"
00039
00040 #include "TVirtualRefProxy.h"
00041 #include "TTreeFormulaManager.h"
00042 #include "TFormLeafInfo.h"
00043 #include "TMethod.h"
00044 #include "TBaseClass.h"
00045 #include "TFormLeafInfoReference.h"
00046
00047 #include "TEntryList.h"
00048
00049 #include <ctype.h>
00050 #include <stdio.h>
00051 #include <math.h>
00052 #include <stdlib.h>
00053 #include <typeinfo>
00054 #include <algorithm>
00055
00056 const Int_t kMaxLen = 1024;
00057 R__EXTERN TTree *gTree;
00058
00059
00060
00061 ClassImp(TTreeFormula)
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096 inline static void R__LoadBranch(TBranch* br, Long64_t entry, Bool_t quickLoad)
00097 {
00098 if (!quickLoad || (br->GetReadEntry() != entry)) {
00099 br->GetEntry(entry);
00100 }
00101 }
00102
00103
00104
00105
00106
00107 class TDimensionInfo : public TObject {
00108 public:
00109 Int_t fCode;
00110 Int_t fOper;
00111 Int_t fSize;
00112 TFormLeafInfoMultiVarDim* fMultiDim;
00113 TDimensionInfo(Int_t code, Int_t oper, Int_t size, TFormLeafInfoMultiVarDim* multiDim)
00114 : fCode(code), fOper(oper), fSize(size), fMultiDim(multiDim) {};
00115 ~TDimensionInfo() {};
00116 };
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 TTreeFormula::TTreeFormula(): TFormula(), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
00131 fDidBooleanOptimization(kFALSE), fDimensionSetup(0)
00132
00133 {
00134
00135
00136 fTree = 0;
00137 fLookupType = 0;
00138 fNindex = 0;
00139 fNcodes = 0;
00140 fAxis = 0;
00141 fHasCast = 0;
00142 fManager = 0;
00143 fMultiplicity = 0;
00144
00145 Int_t j,k;
00146 for (j=0; j<kMAXCODES; j++) {
00147 fNdimensions[j] = 0;
00148 fCodes[j] = 0;
00149 fNdata[j] = 1;
00150 fHasMultipleVarDim[j] = kFALSE;
00151 for (k = 0; k<kMAXFORMDIM; k++) {
00152 fIndexes[j][k] = -1;
00153 fCumulSizes[j][k] = 1;
00154 fVarIndexes[j][k] = 0;
00155 }
00156 }
00157 }
00158
00159
00160 TTreeFormula::TTreeFormula(const char *name,const char *expression, TTree *tree)
00161 :TFormula(), fTree(tree), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
00162 fDidBooleanOptimization(kFALSE), fDimensionSetup(0)
00163 {
00164
00165
00166 Init(name,expression);
00167 }
00168
00169
00170 TTreeFormula::TTreeFormula(const char *name,const char *expression, TTree *tree,
00171 const std::vector<std::string>& aliases)
00172 :TFormula(), fTree(tree), fQuickLoad(kFALSE), fNeedLoading(kTRUE),
00173 fDidBooleanOptimization(kFALSE), fDimensionSetup(0), fAliasesUsed(aliases)
00174 {
00175
00176 Init(name,expression);
00177 }
00178
00179
00180 void TTreeFormula::Init(const char*name, const char* expression)
00181 {
00182
00183
00184 TDirectory *const savedir=gDirectory;
00185
00186 fNindex = kMAXFOUND;
00187 fLookupType = new Int_t[fNindex];
00188 fNcodes = 0;
00189 fMultiplicity = 0;
00190 fAxis = 0;
00191 fHasCast = 0;
00192 Int_t i,j,k;
00193 fManager = new TTreeFormulaManager;
00194 fManager->Add(this);
00195
00196 for (j=0; j<kMAXCODES; j++) {
00197 fNdimensions[j] = 0;
00198 fLookupType[j] = kDirect;
00199 fCodes[j] = 0;
00200 fNdata[j] = 1;
00201 fHasMultipleVarDim[j] = kFALSE;
00202 for (k = 0; k<kMAXFORMDIM; k++) {
00203 fIndexes[j][k] = -1;
00204 fCumulSizes[j][k] = 1;
00205 fVarIndexes[j][k] = 0;
00206 }
00207 }
00208
00209 fDimensionSetup = new TList;
00210
00211 if (Compile(expression)) {
00212 fTree = 0; fNdim = 0;
00213 if(savedir) savedir->cd();
00214 return;
00215 }
00216
00217 if (fNcodes >= kMAXFOUND) {
00218 Warning("TTreeFormula","Too many items in expression:%s",expression);
00219 fNcodes = kMAXFOUND;
00220 }
00221 SetName(name);
00222
00223 for (i=0;i<fNoper;i++) {
00224
00225 if (GetAction(i)==kDefinedString) {
00226 Int_t string_code = GetActionParam(i);
00227 TLeaf *leafc = (TLeaf*)fLeaves.UncheckedAt(string_code);
00228 if (!leafc) continue;
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241 if (fNcodes == 1) {
00242
00243
00244
00245 SetBit(kIsCharacter);
00246 }
00247 continue;
00248 }
00249 if (GetAction(i)==kJump && GetActionParam(i)==(fNoper-1)) {
00250
00251 if (IsString(fNoper-1)) SetBit(kIsCharacter);
00252 }
00253 }
00254 if (fNoper==1 && GetAction(0)==kAliasString) {
00255 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
00256 R__ASSERT(subform);
00257 if (subform->TestBit(kIsCharacter)) SetBit(kIsCharacter);
00258 } else if (fNoper==2 && GetAction(0)==kAlternateString) {
00259 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
00260 R__ASSERT(subform);
00261 if (subform->TestBit(kIsCharacter)) SetBit(kIsCharacter);
00262 }
00263
00264 fManager->Sync();
00265
00266
00267 Int_t k0,k1;
00268 for(k0 = 0; k0 < fNcodes; k0++) {
00269 for(k1 = 0; k1 < fNdimensions[k0]; k1++ ) {
00270
00271 if ( fIndexes[k0][k1]>=0 && fFixedSizes[k0][k1]>=0
00272 && fIndexes[k0][k1]>=fFixedSizes[k0][k1]) {
00273 Error("TTreeFormula",
00274 "Index %d for dimension #%d in %s is too high (max is %d)",
00275 fIndexes[k0][k1],k1+1, expression,fFixedSizes[k0][k1]-1);
00276 fTree = 0; fNdim = 0;
00277 if(savedir) savedir->cd();
00278 return;
00279 }
00280 }
00281 }
00282
00283
00284 for(k=0; k<fNcodes; k++) {
00285 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(k);
00286 TBranch *branch = 0;
00287 if (leaf) {
00288 branch = leaf->GetBranch();
00289 if (fBranches.FindObject(branch)) branch = 0;
00290 }
00291 fBranches.AddAtAndExpand(branch,k);
00292 }
00293
00294 if (IsInteger(kFALSE)) SetBit(kIsInteger);
00295
00296 if (TestBit(TTreeFormula::kNeedEntries)) {
00297
00298
00299
00300
00301
00302 Long64_t readentry = fTree->GetReadEntry();
00303 Int_t treenumber = fTree->GetTreeNumber();
00304 fTree->GetEntries();
00305 if (treenumber != fTree->GetTreeNumber()) {
00306 if (readentry != -1) {
00307 fTree->LoadTree(readentry);
00308 }
00309 UpdateFormulaLeaves();
00310 } else {
00311 if (readentry != -1) {
00312 fTree->LoadTree(readentry);
00313 }
00314 }
00315
00316 }
00317
00318 if(savedir) savedir->cd();
00319 }
00320
00321
00322 TTreeFormula::~TTreeFormula()
00323 {
00324
00325
00326 if (fManager) {
00327 fManager->Remove(this);
00328 if (fManager->fFormulas.GetLast()<0) {
00329 delete fManager;
00330 fManager = 0;
00331 }
00332 }
00333
00334
00335 fLeafNames.Delete();
00336 fDataMembers.Delete();
00337 fMethods.Delete();
00338 fAliases.Delete();
00339 if (fLookupType) delete [] fLookupType;
00340 for (int j=0; j<fNcodes; j++) {
00341 for (int k = 0; k<fNdimensions[j]; k++) {
00342 if (fVarIndexes[j][k]) delete fVarIndexes[j][k];
00343 fVarIndexes[j][k] = 0;
00344 }
00345 }
00346 if (fDimensionSetup) {
00347 fDimensionSetup->Delete();
00348 delete fDimensionSetup;
00349 }
00350 }
00351
00352
00353 void TTreeFormula::DefineDimensions(Int_t code, Int_t size,
00354 TFormLeafInfoMultiVarDim * info,
00355 Int_t& virt_dim) {
00356
00357
00358 if (info) {
00359 fManager->EnableMultiVarDims();
00360
00361 info->fVirtDim = virt_dim;
00362 fManager->AddVarDims(virt_dim);
00363
00364 }
00365
00366 Int_t vsize = 0;
00367
00368 if (fIndexes[code][fNdimensions[code]]==-2) {
00369 TTreeFormula *indexvar = fVarIndexes[code][fNdimensions[code]];
00370
00371 Int_t index_multiplicity = indexvar->GetMultiplicity();
00372 switch (index_multiplicity) {
00373 case -1:
00374 case 0:
00375 case 2:
00376 vsize = indexvar->GetNdata();
00377 break;
00378 case 1:
00379 vsize = -1;
00380 break;
00381 };
00382 } else vsize = size;
00383
00384 fCumulSizes[code][fNdimensions[code]] = size;
00385
00386 if ( fIndexes[code][fNdimensions[code]] < 0 ) {
00387 fManager->UpdateUsedSize(virt_dim, vsize);
00388 }
00389
00390 fNdimensions[code] ++;
00391
00392 }
00393
00394
00395 Int_t TTreeFormula::RegisterDimensions(const char *info, Int_t code)
00396 {
00397
00398
00399
00400 const char * current;
00401 Int_t size, scanindex, vardim;
00402
00403 current = info;
00404 vardim = 0;
00405
00406
00407
00408
00409 if (current[0] != '[') current--;
00410 while (current) {
00411 current++;
00412 scanindex = sscanf(current,"%d",&size);
00413
00414
00415
00416 if (scanindex==0) size = -1;
00417
00418 vardim += RegisterDimensions(code, size);
00419
00420 if (fNdimensions[code] >= kMAXFORMDIM) {
00421
00422
00423 break;
00424 }
00425 current = (char*)strstr( current, "[" );
00426 }
00427 return vardim;
00428 }
00429
00430
00431
00432 Int_t TTreeFormula::RegisterDimensions(Int_t code, Int_t size, TFormLeafInfoMultiVarDim * multidim) {
00433
00434
00435 TDimensionInfo * info = new TDimensionInfo(code,fNoper,size,multidim);
00436 fDimensionSetup->Add(info);
00437 fCumulSizes[code][fNdimensions[code]] = size;
00438 fNdimensions[code] ++;
00439 return (size==-1) ? 1 : 0;
00440 }
00441
00442
00443 Int_t TTreeFormula::RegisterDimensions(Int_t code, TFormLeafInfo *leafinfo,
00444 TFormLeafInfo * ,
00445 Bool_t useCollectionObject) {
00446
00447
00448 Int_t ndim, size, current, vardim;
00449 vardim = 0;
00450
00451 const TStreamerElement * elem = leafinfo->fElement;
00452 TClass* c = elem ? elem->GetClassPointer() : 0;
00453
00454 TFormLeafInfoMultiVarDim * multi = dynamic_cast<TFormLeafInfoMultiVarDim * >(leafinfo);
00455 if (multi) {
00456
00457 fManager->EnableMultiVarDims();
00458 multi->fDim = fNdimensions[code];
00459 return RegisterDimensions(code, -1, multi);
00460 }
00461 if (elem->IsA() == TStreamerBasicPointer::Class()) {
00462
00463 if (elem->GetArrayDim()>0) {
00464
00465 ndim = elem->GetArrayDim();
00466 size = elem->GetMaxIndex(0);
00467 vardim += RegisterDimensions(code, -1);
00468 } else {
00469 ndim = 1;
00470 size = -1;
00471 }
00472
00473 TStreamerBasicPointer *array = (TStreamerBasicPointer*)elem;
00474 TClass *cl = leafinfo->fClass;
00475 Int_t offset;
00476 TStreamerElement* counter = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(array->GetCountName(),offset);
00477 #if 1
00478 leafinfo->fCounter = new TFormLeafInfo(cl,offset,counter);
00479 #else
00480 if (maininfo==0 || maininfo==leafinfo || 1) {
00481 leafinfo->fCounter = new TFormLeafInfo(cl,offset,counter);
00482 } else {
00483 leafinfo->fCounter = maininfo->DeepCopy();
00484 TFormLeafInfo *currentinfo = leafinfo->fCounter;
00485 while(currentinfo->fNext && currentinfo->fNext->fNext) currentinfo=currentinfo->fNext;
00486 delete currentinfo->fNext;
00487 currentinfo->fNext = new TFormLeafInfo(cl,offset,counter);
00488 }
00489 #endif
00490 } else if (!useCollectionObject && elem->GetClassPointer() == TClonesArray::Class() ) {
00491
00492 ndim = 1;
00493 size = -1;
00494
00495 TClass * clonesClass = TClonesArray::Class();
00496 Int_t c_offset;
00497 TStreamerElement *counter = ((TStreamerInfo*)clonesClass->GetStreamerInfo())->GetStreamerElement("fLast",c_offset);
00498 leafinfo->fCounter = new TFormLeafInfo(clonesClass,c_offset,counter);
00499
00500 } else if (!useCollectionObject && elem->GetClassPointer() && elem->GetClassPointer()->GetCollectionProxy() ) {
00501
00502 if ( typeid(*leafinfo) == typeid(TFormLeafInfoCollection) ) {
00503 ndim = 1;
00504 size = -1;
00505 } else {
00506 R__ASSERT( fHasMultipleVarDim[code] );
00507 ndim = 1;
00508 size = 1;
00509 }
00510
00511 } else if ( c && c->GetReferenceProxy() && c->GetReferenceProxy()->HasCounter() ) {
00512 ndim = 1;
00513 size = -1;
00514 } else if (elem->GetArrayDim()>0) {
00515
00516 ndim = elem->GetArrayDim();
00517 size = elem->GetMaxIndex(0);
00518
00519 } else if ( elem->GetNewType()== TStreamerInfo::kCharStar) {
00520
00521
00522
00523
00524
00525
00526 ndim = 1;
00527 size = 1;
00528
00529 } else return 0;
00530
00531 current = 0;
00532 do {
00533 vardim += RegisterDimensions(code, size);
00534
00535 if (fNdimensions[code] >= kMAXFORMDIM) {
00536
00537
00538 break;
00539 }
00540 current++;
00541 size = elem->GetMaxIndex(current);
00542 } while (current<ndim);
00543
00544 return vardim;
00545 }
00546
00547
00548 Int_t TTreeFormula::RegisterDimensions(Int_t code, TBranchElement *branch) {
00549
00550
00551 TBranchElement * leafcount2 = branch->GetBranchCount2();
00552 if (leafcount2) {
00553
00554 TBranchElement *leafcount = dynamic_cast<TBranchElement*>(branch->GetBranchCount());
00555
00556 R__ASSERT(leafcount);
00557
00558 fManager->EnableMultiVarDims();
00559 TFormLeafInfoMultiVarDim * info = new TFormLeafInfoMultiVarDimDirect();
00560 fDataMembers.AddAtAndExpand(info, code);
00561 fHasMultipleVarDim[code] = kTRUE;
00562
00563 info->fCounter = new TFormLeafInfoDirect(leafcount);
00564 info->fCounter2 = new TFormLeafInfoDirect(leafcount2);
00565 info->fDim = fNdimensions[code];
00566
00567
00568
00569
00570 return RegisterDimensions(code, -1, info);
00571 }
00572 return 0;
00573 }
00574
00575
00576 Int_t TTreeFormula::RegisterDimensions(Int_t code, TLeaf *leaf) {
00577
00578
00579 Int_t numberOfVarDim = 0;
00580
00581
00582
00583
00584 const char *tname = leaf->GetTitle();
00585 char *leaf_dim = (char*)strstr( tname, "[" );
00586
00587 const char *bname = leaf->GetBranch()->GetName();
00588 char *branch_dim = (char*)strstr(bname,"[");
00589 if (branch_dim) branch_dim++;
00590
00591 Bool_t isString = kFALSE;
00592 if (leaf->IsA() == TLeafElement::Class()) {
00593 Int_t type =((TBranchElement*)leaf->GetBranch())->GetStreamerType();
00594 isString = (type == TStreamerInfo::kOffsetL+TStreamerInfo::kChar)
00595 || (type == TStreamerInfo::kCharStar);
00596 } else {
00597 isString = (leaf->IsA() == TLeafC::Class());
00598 }
00599 if (leaf_dim) {
00600 leaf_dim++;
00601 if (!branch_dim || strncmp(branch_dim,leaf_dim,strlen(branch_dim))) {
00602
00603 numberOfVarDim += RegisterDimensions( leaf_dim, code);
00604 } else if (branch_dim && strncmp(branch_dim,leaf_dim,strlen(branch_dim))==0
00605 && strlen(leaf_dim)>strlen(branch_dim)
00606 && (leaf_dim+strlen(branch_dim))[0]=='[') {
00607
00608 numberOfVarDim += RegisterDimensions( leaf_dim+strlen(branch_dim)+1, code);
00609 }
00610 }
00611 if (branch_dim) {
00612
00613 if (isString) {
00614 numberOfVarDim += RegisterDimensions( code, 1);
00615 } else {
00616 numberOfVarDim += RegisterDimensions( branch_dim, code);
00617 }
00618 }
00619 if (leaf->IsA() == TLeafElement::Class()) {
00620 TBranchElement* branch = (TBranchElement*) leaf->GetBranch();
00621 if (branch->GetBranchCount2()) {
00622
00623 if (!branch->GetBranchCount()) {
00624 Warning("DefinedVariable",
00625 "Noticed an incorrect in-memory TBranchElement object (%s).\nIt has a BranchCount2 but no BranchCount!\nThe result might be incorrect!",
00626 branch->GetName());
00627 return numberOfVarDim;
00628 }
00629
00630
00631 if (fLookupType[code] == kDataMember)
00632 Warning("DefinedVariable",
00633 "Already in kDataMember mode when handling multiple variable dimensions");
00634 fLookupType[code] = kDataMember;
00635
00636
00637 numberOfVarDim += RegisterDimensions( code, branch);
00638
00639 }
00640 }
00641 return numberOfVarDim;
00642 }
00643
00644
00645 Int_t TTreeFormula::DefineAlternate(const char *expression)
00646 {
00647
00648
00649
00650
00651
00652
00653
00654 static const char *altfunc = "Alt$(";
00655 static const char *minfunc = "MinIf$(";
00656 static const char *maxfunc = "MaxIf$(";
00657 Int_t action = 0;
00658 Int_t start = 0;
00659
00660 if ( strncmp(expression,altfunc,strlen(altfunc))==0
00661 && expression[strlen(expression)-1]==')' ) {
00662 action = kAlternate;
00663 start = strlen(altfunc);
00664 }
00665 if ( strncmp(expression,maxfunc,strlen(maxfunc))==0
00666 && expression[strlen(expression)-1]==')' ) {
00667 action = kMaxIf;
00668 start = strlen(maxfunc);
00669 }
00670 if ( strncmp(expression,minfunc,strlen(minfunc))==0
00671 && expression[strlen(expression)-1]==')' ) {
00672 action = kMinIf;
00673 start = strlen(minfunc);
00674 }
00675
00676 if (action) {
00677 TString full = expression;
00678 TString part1;
00679 TString part2;
00680 int paran = 0;
00681 int instr = 0;
00682 int brack = 0;
00683 for(unsigned int i=start;i<strlen(expression);++i) {
00684 switch (expression[i]) {
00685 case '(': paran++; break;
00686 case ')': paran--; break;
00687 case '"': instr = instr ? 0 : 1; break;
00688 case '[': brack++; break;
00689 case ']': brack--; break;
00690 };
00691 if (expression[i]==',' && paran==0 && instr==0 && brack==0) {
00692 part1 = full( start, i-start );
00693 part2 = full( i+1, full.Length() -1 - (i+1) );
00694 break;
00695 }
00696 }
00697 if (part1.Length() && part2.Length()) {
00698 TTreeFormula *primary = new TTreeFormula("primary",part1,fTree);
00699 TTreeFormula *alternate = new TTreeFormula("alternate",part2,fTree);
00700
00701 short isstring = 0;
00702
00703 if (action == kAlternate) {
00704 if (alternate->GetManager()->GetMultiplicity() != 0 ) {
00705 Error("DefinedVariable","The 2nd arguments in %s can not be an array (%s,%d)!",
00706 expression,alternate->GetTitle(),
00707 alternate->GetManager()->GetMultiplicity());
00708 return -1;
00709 }
00710
00711
00712 if (primary->IsString()) {
00713 if (!alternate->IsString()) {
00714 Error("DefinedVariable",
00715 "The 2nd arguments in %s has to return the same type as the 1st argument (string)!",
00716 expression);
00717 return -1;
00718 }
00719 isstring = 1;
00720 } else if (alternate->IsString()) {
00721 Error("DefinedVariable",
00722 "The 2nd arguments in %s has to return the same type as the 1st argument (numerical type)!",
00723 expression);
00724 return -1;
00725 }
00726 } else {
00727 primary->GetManager()->Add( alternate );
00728 primary->GetManager()->Sync();
00729 if (primary->IsString() || alternate->IsString()) {
00730 if (!alternate->IsString()) {
00731 Error("DefinedVariable",
00732 "The arguments of %s can not be strings!",
00733 expression);
00734 return -1;
00735 }
00736 }
00737 }
00738
00739 fAliases.AddAtAndExpand(primary,fNoper);
00740 fExpr[fNoper] = "";
00741 SetAction(fNoper, (Int_t)action + isstring, 0 );
00742 ++fNoper;
00743
00744 fAliases.AddAtAndExpand(alternate,fNoper);
00745 return (Int_t)kAlias + isstring;
00746 }
00747 }
00748 return 0;
00749 }
00750
00751
00752 Int_t TTreeFormula::ParseWithLeaf(TLeaf* leaf, const char* subExpression, Bool_t final, UInt_t paran_level, TObjArray& castqueue, Bool_t useLeafCollectionObject, const char* fullExpression)
00753 {
00754
00755
00756
00757
00758
00759
00760
00761 Int_t action = 0;
00762
00763 Int_t numberOfVarDim = 0;
00764 char *current;
00765
00766 char scratch[kMaxLen]; scratch[0] = '\0';
00767 char work[kMaxLen]; work[0] = '\0';
00768
00769 const char *right = subExpression;
00770 TString name = fullExpression;
00771
00772 TBranch *branch = leaf ? leaf->GetBranch() : 0;
00773 Long64_t readentry = fTree->GetTree()->GetReadEntry();
00774 if (readentry==-1) readentry=0;
00775
00776 Bool_t useLeafReferenceObject = false;
00777 Int_t code = fNcodes-1;
00778
00779
00780 if (leaf && leaf->IsA()==TLeafElement::Class()) {
00781 TBranchElement *br = 0;
00782 if( branch->IsA() == TBranchElement::Class() )
00783 {
00784 br = ((TBranchElement*)branch);
00785
00786 if ( br->GetInfo() == 0 ) {
00787 Error("DefinedVariable","Missing StreamerInfo for %s. We will be unable to read!",
00788 name.Data());
00789 return -2;
00790 }
00791 }
00792
00793 TBranch *bmom = branch->GetMother();
00794 if( bmom->IsA() == TBranchElement::Class() )
00795 {
00796 TBranchElement *mom = (TBranchElement*)br->GetMother();
00797 if (mom!=br) {
00798 if (mom->GetInfo()==0) {
00799 Error("DefinedVariable","Missing StreamerInfo for %s."
00800 " We will be unable to read!",
00801 mom->GetName());
00802 return -2;
00803 }
00804 if ((mom->GetType()) < -1 && !mom->GetAddress()) {
00805 Error("DefinedVariable", "Address not set when the type of the branch is negative for for %s. We will be unable to read!", mom->GetName());
00806 return -2;
00807 }
00808 }
00809 }
00810 }
00811
00812
00813
00814
00815
00816
00817 TTree *realtree = fTree->GetTree();
00818 const char* alias = 0;
00819 if (leaf) {
00820 if (realtree) alias = realtree->GetFriendAlias(leaf->GetBranch()->GetTree());
00821 if (!alias && realtree!=fTree) {
00822
00823 alias = fTree->GetFriendAlias(leaf->GetBranch()->GetTree());
00824 }
00825 }
00826 if (alias) snprintf(scratch,kMaxLen-1,"%s.%s",alias,leaf->GetName());
00827 else if (leaf) strlcpy(scratch,leaf->GetName(),kMaxLen);
00828
00829 TTree *tleaf = realtree;
00830 if (leaf) {
00831 tleaf = leaf->GetBranch()->GetTree();
00832 fCodes[code] = tleaf->GetListOfLeaves()->IndexOf(leaf);
00833 const char *mother_name = leaf->GetBranch()->GetMother()->GetName();
00834 TString br_extended_name;
00835 if (leaf->GetBranch()!=leaf->GetBranch()->GetMother()) {
00836 if (mother_name[strlen(mother_name)-1]!='.') {
00837 br_extended_name = mother_name;
00838 br_extended_name.Append('.');
00839 }
00840 }
00841 br_extended_name.Append( leaf->GetBranch()->GetName() );
00842 Ssiz_t dim = br_extended_name.First('[');
00843 if (dim >= 0) br_extended_name.Remove(dim);
00844
00845 TNamed *named = new TNamed(scratch,br_extended_name.Data());
00846 fLeafNames.AddAtAndExpand(named,code);
00847 fLeaves.AddAtAndExpand(leaf,code);
00848 }
00849
00850
00851
00852 if (tleaf != realtree && tleaf->GetTreeIndex()) {
00853
00854 if (fMultiplicity >= 0) fMultiplicity = 1;
00855 }
00856
00857
00858
00859
00860 TClass * cl = 0;
00861 TFormLeafInfo *maininfo = 0;
00862 TFormLeafInfo *previnfo = 0;
00863 Bool_t unwindCollection = kFALSE;
00864 static TClassRef stdStringClass = TClass::GetClass("string");
00865
00866 if (leaf==0) {
00867 TNamed *names = (TNamed*)fLeafNames.UncheckedAt(code);
00868 fLeafNames.AddAt(0,code);
00869 TTree *what = (TTree*)fLeaves.UncheckedAt(code);
00870 fLeaves.AddAt(0,code);
00871
00872 cl = what ? what->IsA() : TTree::Class();
00873 maininfo = new TFormLeafInfoTTree(fTree,names->GetName(),what);
00874 previnfo = maininfo;
00875
00876 delete names;
00877 } else if (leaf->InheritsFrom(TLeafObject::Class()) ) {
00878 TBranchObject *bobj = (TBranchObject*)leaf->GetBranch();
00879 cl = TClass::GetClass(bobj->GetClassName());
00880 } else if (leaf->InheritsFrom(TLeafElement::Class())) {
00881 TBranchElement *branchEl = (TBranchElement *)leaf->GetBranch();
00882 branchEl->SetupAddresses();
00883 TStreamerInfo *info = branchEl->GetInfo();
00884 TStreamerElement *element = 0;
00885 Int_t type = branchEl->GetStreamerType();
00886 switch(type) {
00887 case TStreamerInfo::kBase:
00888 case TStreamerInfo::kObject:
00889 case TStreamerInfo::kTString:
00890 case TStreamerInfo::kTNamed:
00891 case TStreamerInfo::kTObject:
00892 case TStreamerInfo::kAny:
00893 case TStreamerInfo::kAnyP:
00894 case TStreamerInfo::kAnyp:
00895 case TStreamerInfo::kSTL:
00896 case TStreamerInfo::kSTLp:
00897 case TStreamerInfo::kObjectp:
00898 case TStreamerInfo::kObjectP: {
00899 element = (TStreamerElement *)info->GetElems()[branchEl->GetID()];
00900 if (element) cl = element->GetClassPointer();
00901 }
00902 break;
00903 case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL:
00904 case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp:
00905 case TStreamerInfo::kOffsetL + TStreamerInfo::kAny:
00906 case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp:
00907 case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP:
00908 case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp:
00909 case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP:
00910 case TStreamerInfo::kOffsetL + TStreamerInfo::kObject: {
00911 element = (TStreamerElement *)info->GetElems()[branchEl->GetID()];
00912 if (element){
00913 cl = element->GetClassPointer();
00914 }
00915 }
00916 break;
00917 case -1: {
00918 cl = info->GetClass();
00919 }
00920 break;
00921 }
00922
00923
00924
00925 if (cl && branchEl->GetBranchCount()) {
00926 if (branchEl->GetType()==31) {
00927
00928
00929 if (!element) {
00930 Warning("DefineVariable",
00931 "Missing TStreamerElement in object in TClonesArray section");
00932 return -2;
00933 }
00934 TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE);
00935
00936
00937
00938
00939
00940
00941
00942 maininfo = clonesinfo;
00943
00944
00945 Int_t offset=0;
00946 info->GetStreamerElement(element->GetName(),offset);
00947 if (type == TStreamerInfo::kObjectp ||
00948 type == TStreamerInfo::kObjectP ||
00949 type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp ||
00950 type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP ||
00951 type == TStreamerInfo::kSTLp ||
00952 type == TStreamerInfo::kAnyp ||
00953 type == TStreamerInfo::kAnyP ||
00954 type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp ||
00955 type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp ||
00956 type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) {
00957 previnfo = new TFormLeafInfoPointer(cl,offset+branchEl->GetOffset(),element);
00958 } else {
00959 previnfo = new TFormLeafInfo(cl,offset+branchEl->GetOffset(),element);
00960 }
00961 maininfo->fNext = previnfo;
00962 unwindCollection = kTRUE;
00963
00964 } else if (branchEl->GetType()==41) {
00965
00966
00967
00968 if (!element) {
00969 Warning("DefineVariable","Missing TStreamerElement in object in Collection section");
00970 return -2;
00971 }
00972
00973 TBranchElement *count = branchEl->GetBranchCount();
00974 TFormLeafInfo* collectioninfo;
00975 if ( count->GetID() >= 0 ) {
00976 TStreamerElement *collectionElement =
00977 (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()];
00978 TClass *collectionCl = collectionElement->GetClassPointer();
00979
00980 collectioninfo =
00981 new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE);
00982 } else {
00983 TClass *collectionCl = TClass::GetClass(count->GetClassName());
00984 collectioninfo =
00985 new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE);
00986 }
00987
00988
00989
00990
00991
00992
00993
00994 maininfo = collectioninfo;
00995
00996
00997 Int_t offset=0;
00998 info->GetStreamerElement(element->GetName(),offset);
00999 if (type == TStreamerInfo::kObjectp ||
01000 type == TStreamerInfo::kObjectP ||
01001 type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp ||
01002 type == TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP ||
01003 type == TStreamerInfo::kSTLp ||
01004 type == TStreamerInfo::kAnyp ||
01005 type == TStreamerInfo::kAnyP ||
01006 type == TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp ||
01007 type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp ||
01008 type == TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP) {
01009 previnfo = new TFormLeafInfoPointer(cl,offset+branchEl->GetOffset(),element);
01010 } else {
01011 previnfo = new TFormLeafInfo(cl,offset+branchEl->GetOffset(),element);
01012 }
01013 maininfo->fNext = previnfo;
01014 unwindCollection = kTRUE;
01015 }
01016 } else if ( branchEl->GetType()==3) {
01017 TFormLeafInfo* clonesinfo;
01018 if (useLeafCollectionObject) {
01019 clonesinfo = new TFormLeafInfoCollectionObject(cl);
01020 } else {
01021 clonesinfo = new TFormLeafInfoClones(cl, 0, kTRUE);
01022
01023 numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,useLeafCollectionObject);
01024
01025 }
01026 maininfo = clonesinfo;
01027 previnfo = maininfo;
01028
01029 } else if (!useLeafCollectionObject && branchEl->GetType()==4) {
01030
01031 TFormLeafInfo* collectioninfo;
01032 if (useLeafCollectionObject) {
01033 collectioninfo = new TFormLeafInfoCollectionObject(cl);
01034 } else {
01035 collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
01036
01037 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,useLeafCollectionObject);
01038 }
01039
01040 maininfo = collectioninfo;
01041 previnfo = maininfo;
01042
01043 } else if (branchEl->GetStreamerType()==-1 && cl && cl->GetCollectionProxy()) {
01044
01045 if (useLeafCollectionObject) {
01046
01047 TFormLeafInfo *collectioninfo = new TFormLeafInfoCollectionObject(cl);
01048 maininfo = collectioninfo;
01049 previnfo = collectioninfo;
01050
01051 } else {
01052 TFormLeafInfo *collectioninfo = new TFormLeafInfoCollection(cl, 0, cl, kTRUE);
01053
01054 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01055
01056 maininfo = collectioninfo;
01057 previnfo = collectioninfo;
01058
01059 if (cl->GetCollectionProxy()->GetValueClass()!=0 &&
01060 cl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()!=0) {
01061
01062 TFormLeafInfo *multi = new TFormLeafInfoMultiVarDimCollection(cl,0,
01063 cl->GetCollectionProxy()->GetValueClass(),collectioninfo);
01064
01065 fHasMultipleVarDim[code] = kTRUE;
01066 numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
01067 previnfo->fNext = multi;
01068 cl = cl->GetCollectionProxy()->GetValueClass();
01069 multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false);
01070 previnfo = multi->fNext;
01071
01072 }
01073 if (cl->GetCollectionProxy()->GetValueClass()==0 &&
01074 cl->GetCollectionProxy()->GetType()>0) {
01075
01076 previnfo->fNext =
01077 new TFormLeafInfoNumerical(cl->GetCollectionProxy());
01078 previnfo = previnfo->fNext;
01079 } else {
01080
01081 }
01082 }
01083
01084 } else if (strlen(right)==0 && cl && element && final) {
01085
01086 TClass *elemCl = element->GetClassPointer();
01087 if (!useLeafCollectionObject
01088 && elemCl && elemCl->GetCollectionProxy()
01089 && elemCl->GetCollectionProxy()->GetValueClass()
01090 && elemCl->GetCollectionProxy()->GetValueClass()->GetCollectionProxy()) {
01091
01092 TFormLeafInfo *collectioninfo =
01093 new TFormLeafInfoCollection(cl, 0, elemCl);
01094
01095
01096 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01097
01098 maininfo = collectioninfo;
01099 previnfo = collectioninfo;
01100
01101 TFormLeafInfo *multi =
01102 new TFormLeafInfoMultiVarDimCollection(elemCl, 0,
01103 elemCl->GetCollectionProxy()->GetValueClass(),
01104 collectioninfo);
01105
01106 fHasMultipleVarDim[code] = kTRUE;
01107 numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
01108 previnfo->fNext = multi;
01109 cl = elemCl->GetCollectionProxy()->GetValueClass();
01110 multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false);
01111 previnfo = multi->fNext;
01112
01113 if (cl->GetCollectionProxy()->GetValueClass()==0 &&
01114 cl->GetCollectionProxy()->GetType()>0) {
01115
01116 previnfo->fNext =
01117 new TFormLeafInfoNumerical(cl->GetCollectionProxy());
01118 previnfo = previnfo->fNext;
01119 }
01120
01121 } else if (!useLeafCollectionObject
01122 && elemCl && elemCl->GetCollectionProxy()
01123 && elemCl->GetCollectionProxy()->GetValueClass()==0
01124 && elemCl->GetCollectionProxy()->GetType()>0) {
01125
01126
01127
01128
01129
01130
01131 TFormLeafInfo* collectioninfo =
01132 new TFormLeafInfoCollection(cl, 0, elemCl);
01133
01134
01135 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01136
01137 collectioninfo->fNext =
01138 new TFormLeafInfoNumerical(elemCl->GetCollectionProxy());
01139
01140 maininfo = collectioninfo;
01141 previnfo = maininfo->fNext;
01142
01143 } else if (!useLeafCollectionObject
01144 && elemCl && elemCl->GetCollectionProxy()) {
01145 if (elemCl->GetCollectionProxy()->GetValueClass()==TString::Class()) {
01146 right = "Data()";
01147 } else if (elemCl->GetCollectionProxy()->GetValueClass()==stdStringClass) {
01148 right = "c_str()";
01149 }
01150
01151 } else if (!element->IsaPointer()) {
01152
01153 maininfo = new TFormLeafInfoDirect(branchEl);
01154 previnfo = maininfo;
01155
01156 }
01157 }
01158 else if ( cl && cl->GetReferenceProxy() ) {
01159 if ( useLeafCollectionObject || fullExpression[0] == '@' || fullExpression[strlen(scratch)] == '@' ) {
01160 useLeafReferenceObject = true;
01161 }
01162 else {
01163 if ( !maininfo ) {
01164 maininfo = previnfo = new TFormLeafInfoReference(cl, element, 0);
01165 numberOfVarDim += RegisterDimensions(code,maininfo,maininfo,kFALSE);
01166 }
01167 cl = 0;
01168 for(int i=0; i<leaf->GetBranch()->GetEntries()-readentry; ++i) {
01169 R__LoadBranch(leaf->GetBranch(), readentry+i, fQuickLoad);
01170 cl = ((TFormLeafInfoReference*)maininfo)->GetValueClass(leaf);
01171 if ( cl ) break;
01172 }
01173 if ( !cl ) {
01174 Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
01175 return -1;
01176 }
01177 }
01178 }
01179 }
01180
01181
01182 if (leaf) numberOfVarDim += RegisterDimensions(code,leaf);
01183
01184 if (cl) {
01185 if (unwindCollection) {
01186
01187
01188 R__ASSERT(numberOfVarDim==1 && maininfo);
01189
01190 if (!useLeafCollectionObject && cl && cl->GetCollectionProxy()) {
01191 TFormLeafInfo *multi =
01192 new TFormLeafInfoMultiVarDimCollection(cl, 0, cl, maininfo);
01193 fHasMultipleVarDim[code] = kTRUE;
01194 numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
01195 previnfo->fNext = multi;
01196
01197 multi->fNext = new TFormLeafInfoCollection(cl, 0, cl, false);
01198 previnfo = multi->fNext;
01199
01200 if (cl->GetCollectionProxy()->GetValueClass()==0 &&
01201 cl->GetCollectionProxy()->GetType()>0) {
01202
01203 previnfo->fNext =
01204 new TFormLeafInfoNumerical(cl->GetCollectionProxy());
01205 previnfo = previnfo->fNext;
01206 }
01207 } else if (!useLeafCollectionObject && cl == TClonesArray::Class()) {
01208
01209 TFormLeafInfo *multi =
01210 new TFormLeafInfoMultiVarDimClones(cl, 0, cl, maininfo);
01211 fHasMultipleVarDim[code] = kTRUE;
01212 numberOfVarDim += RegisterDimensions(code,multi,maininfo,kFALSE);
01213 previnfo->fNext = multi;
01214
01215 multi->fNext = new TFormLeafInfoClones(cl, 0, false);
01216 previnfo = multi->fNext;
01217 }
01218 }
01219 Int_t offset=0;
01220 Int_t nchname = strlen(right);
01221 TFormLeafInfo *leafinfo = 0;
01222 TStreamerElement* element = 0;
01223
01224
01225
01226
01227
01228
01229
01230
01231 {
01232 TClass * casted = (TClass*) castqueue.At(paran_level+1);
01233 if (casted && cl != TClonesArray::Class()) {
01234 if ( ! casted->InheritsFrom(cl) ) {
01235 Error("DefinedVariable","%s does not inherit from %s. Casting not possible!",
01236 casted->GetName(),cl->GetName());
01237 return -2;
01238 }
01239 leafinfo = new TFormLeafInfoCast(cl,casted);
01240 fHasCast = kTRUE;
01241 if (maininfo==0) {
01242 maininfo = leafinfo;
01243 }
01244 if (previnfo==0) {
01245 previnfo = leafinfo;
01246 } else {
01247 previnfo->fNext = leafinfo;
01248 previnfo = leafinfo;
01249 }
01250 leafinfo = 0;
01251
01252 cl = casted;
01253 castqueue.AddAt(0,paran_level);
01254 }
01255 }
01256 Int_t i;
01257 Bool_t prevUseCollectionObject = useLeafCollectionObject;
01258 Bool_t useCollectionObject = useLeafCollectionObject;
01259 Bool_t useReferenceObject = useLeafReferenceObject;
01260 Bool_t prevUseReferenceObject = useLeafReferenceObject;
01261 for (i=0, current = &(work[0]); i<=nchname;i++ ) {
01262
01263 if (right[i] == '(') {
01264
01265 do {
01266 *current++ = right[i++];
01267 } while(right[i]!=')' && right[i]);
01268 *current++ = right[i];
01269 *current='\0';
01270 char *params = strchr(work,'(');
01271 if (params) {
01272 *params = 0; params++;
01273 } else params = (char *) ")";
01274 if (cl==0) {
01275 Error("DefinedVariable","Can not call '%s' with a class",work);
01276 return -1;
01277 }
01278 if (cl->GetClassInfo()==0 && !cl->GetCollectionProxy()) {
01279 Error("DefinedVariable","Class probably unavailable:%s",cl->GetName());
01280 return -2;
01281 }
01282 if (!useCollectionObject && cl == TClonesArray::Class()) {
01283
01284
01285
01286
01287 TBranch *clbranch = leaf->GetBranch();
01288 R__LoadBranch(clbranch,readentry,fQuickLoad);
01289 TClonesArray * clones;
01290 if (previnfo) clones = (TClonesArray*)previnfo->GetLocalValuePointer(leaf,0);
01291 else {
01292 Bool_t top = (clbranch==((TBranchElement*)clbranch)->GetMother()
01293 || !leaf->IsOnTerminalBranch());
01294 TClass *mother_cl;
01295 if (leaf->IsA()==TLeafObject::Class()) {
01296
01297 mother_cl = cl;
01298 } else {
01299 mother_cl = ((TBranchElement*)clbranch)->GetInfo()->GetClass();
01300 }
01301 TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0, top);
01302
01303
01304 numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,kFALSE);
01305
01306 previnfo = clonesinfo;
01307 maininfo = clonesinfo;
01308
01309 clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
01310 }
01311 TClass * inside_cl = clones->GetClass();
01312 cl = inside_cl;
01313
01314 }
01315 else if (!useCollectionObject && cl && cl->GetCollectionProxy() ) {
01316
01317
01318
01319
01320
01321 if (previnfo==0) {
01322
01323 Bool_t top = (branch==((TBranchElement*)branch)->GetMother()
01324 || !leaf->IsOnTerminalBranch());
01325
01326 TClass *mother_cl;
01327 if (leaf->IsA()==TLeafObject::Class()) {
01328
01329 mother_cl = cl;
01330 } else {
01331 mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
01332 }
01333
01334 TFormLeafInfo* collectioninfo =
01335 new TFormLeafInfoCollection(mother_cl, 0,cl,top);
01336
01337 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01338
01339 previnfo = collectioninfo;
01340 maininfo = collectioninfo;
01341
01342 }
01343
01344 TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass();
01345 if (inside_cl) cl = inside_cl;
01346 else if (cl->GetCollectionProxy()->GetType()>0) {
01347 Warning("DefinedVariable","Can not call method on content of %s in %s\n",
01348 cl->GetName(),name.Data());
01349 return -2;
01350 }
01351 }
01352 TMethodCall *method = 0;
01353 if (cl==0) {
01354 Error("DefinedVariable",
01355 "Could not discover the TClass corresponding to (%s)!",
01356 right);
01357 return -2;
01358 } else if (cl==TClonesArray::Class() && strcmp(work,"size")==0) {
01359 method = new TMethodCall(cl, "GetEntriesFast", "");
01360 } else if (cl->GetCollectionProxy() && strcmp(work,"size")==0) {
01361 if (maininfo==0) {
01362 TFormLeafInfo* collectioninfo=0;
01363 if (useLeafCollectionObject) {
01364
01365 Bool_t top = (branch==((TBranchElement*)branch)->GetMother()
01366 || !leaf->IsOnTerminalBranch());
01367 collectioninfo = new TFormLeafInfoCollectionObject(cl,top);
01368 }
01369 maininfo=previnfo=collectioninfo;
01370 }
01371 leafinfo = new TFormLeafInfoCollectionSize(cl);
01372 cl = 0;
01373 } else {
01374 if (cl->GetClassInfo()==0) {
01375 Error("DefinedVariable",
01376 "Can not call method %s on class without dictionary (%s)!",
01377 right,cl->GetName());
01378 return -2;
01379 }
01380 method = new TMethodCall(cl, work, params);
01381 }
01382 if (method) {
01383 if (!method->GetMethod()) {
01384 Error("DefinedVariable","Unknown method:%s in %s",right,cl->GetName());
01385 return -1;
01386 }
01387 switch(method->ReturnType()) {
01388 case TMethodCall::kLong:
01389 leafinfo = new TFormLeafInfoMethod(cl,method);
01390 cl = 0;
01391 break;
01392 case TMethodCall::kDouble:
01393 leafinfo = new TFormLeafInfoMethod(cl,method);
01394 cl = 0;
01395 break;
01396 case TMethodCall::kString:
01397 leafinfo = new TFormLeafInfoMethod(cl,method);
01398
01399 numberOfVarDim += RegisterDimensions(code,1);
01400 cl = 0;
01401 break;
01402 case TMethodCall::kOther:
01403 {
01404 TString return_type =
01405 gInterpreter->TypeName(method->GetMethod()->GetReturnTypeName());
01406 leafinfo = new TFormLeafInfoMethod(cl,method);
01407 cl = (return_type == "void") ? 0 : TClass::GetClass(return_type.Data());
01408 }
01409 break;
01410 default:
01411 Error("DefineVariable","Method %s from %s has an impossible return type %d",
01412 work,cl->GetName(),method->ReturnType());
01413 return -2;
01414 }
01415 }
01416 if (maininfo==0) {
01417 maininfo = leafinfo;
01418 }
01419 if (previnfo==0) {
01420 previnfo = leafinfo;
01421 } else {
01422 previnfo->fNext = leafinfo;
01423 previnfo = leafinfo;
01424 }
01425 leafinfo = 0;
01426 current = &(work[0]);
01427 *current = 0;
01428 prevUseCollectionObject = kFALSE;
01429 prevUseReferenceObject = kFALSE;
01430 useCollectionObject = kFALSE;
01431
01432 if (cl && cl->GetCollectionProxy()) {
01433 if (numberOfVarDim>1) {
01434 Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
01435 cl->GetName());
01436 leafinfo = new TFormLeafInfo(cl,0,0);
01437 useCollectionObject = kTRUE;
01438 } else if (numberOfVarDim==0) {
01439 R__ASSERT(maininfo);
01440 leafinfo = new TFormLeafInfoCollection(cl,0,cl);
01441 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01442 } else if (numberOfVarDim==1) {
01443 R__ASSERT(maininfo);
01444 leafinfo =
01445 new TFormLeafInfoMultiVarDimCollection(cl,0,
01446 (TStreamerElement*)0,maininfo);
01447 previnfo->fNext = leafinfo;
01448 previnfo = leafinfo;
01449 leafinfo = new TFormLeafInfoCollection(cl,0,cl);
01450
01451 fHasMultipleVarDim[code] = kTRUE;
01452 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01453 }
01454 previnfo->fNext = leafinfo;
01455 previnfo = leafinfo;
01456 leafinfo = 0;
01457 }
01458 continue;
01459 } else if (right[i] == ')') {
01460
01461
01462 TClass * casted = (TClass*) ((int(--paran_level)>=0) ? castqueue.At(paran_level) : 0);
01463 if (casted) {
01464 leafinfo = new TFormLeafInfoCast(cl,casted);
01465 fHasCast = kTRUE;
01466
01467 if (maininfo==0) {
01468 maininfo = leafinfo;
01469 }
01470 if (previnfo==0) {
01471 previnfo = leafinfo;
01472 } else {
01473 previnfo->fNext = leafinfo;
01474 previnfo = leafinfo;
01475 }
01476 leafinfo = 0;
01477 current = &(work[0]);
01478 *current = 0;
01479
01480 cl = casted;
01481 continue;
01482
01483 }
01484 } else if (i > 0 && (right[i] == '.' || right[i] == '[' || right[i] == '\0') ) {
01485
01486
01487 Bool_t needClass = kTRUE;
01488 *current = '\0';
01489
01490
01491 if (strlen(work)==0) continue;
01492
01493 prevUseCollectionObject = useCollectionObject;
01494 prevUseReferenceObject = useReferenceObject;
01495 if (work[0]=='@') {
01496 useReferenceObject = kTRUE;
01497 useCollectionObject = kTRUE;
01498 Int_t l = 0;
01499 for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
01500 work[l] = '\0';
01501 } else if (work[strlen(work)-1]=='@') {
01502 useReferenceObject = kTRUE;
01503 useCollectionObject = kTRUE;
01504 work[strlen(work)-1] = '\0';
01505 } else {
01506 useReferenceObject = kFALSE;
01507 useCollectionObject = kFALSE;
01508 }
01509
01510 Bool_t mustderef = kFALSE;
01511 if ( !prevUseReferenceObject && cl && cl->GetReferenceProxy() ) {
01512 R__LoadBranch(leaf->GetBranch(), readentry, fQuickLoad);
01513 if ( !maininfo ) {
01514 maininfo = previnfo = new TFormLeafInfoReference(cl, element, offset);
01515 if ( cl->GetReferenceProxy()->HasCounter() ) {
01516 numberOfVarDim += RegisterDimensions(code,-1);
01517 }
01518 prevUseReferenceObject = kFALSE;
01519 }
01520 needClass = kFALSE;
01521 mustderef = kTRUE;
01522 }
01523 else if (!prevUseCollectionObject && cl == TClonesArray::Class()) {
01524
01525
01526
01527
01528 TBranch *clbranch = leaf->GetBranch();
01529 R__LoadBranch(clbranch,readentry,fQuickLoad);
01530 TClonesArray * clones;
01531 if (maininfo) {
01532 clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0);
01533 } else {
01534
01535
01536
01537 TClass *mother_cl;
01538 if (leaf->IsA()==TLeafObject::Class()) {
01539
01540 mother_cl = cl;
01541 } else {
01542 mother_cl = ((TBranchElement*)clbranch)->GetInfo()->GetClass();
01543 }
01544
01545 TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0);
01546
01547 numberOfVarDim += RegisterDimensions(code,clonesinfo,maininfo,kFALSE);
01548
01549 mustderef = kTRUE;
01550 previnfo = clonesinfo;
01551 maininfo = clonesinfo;
01552
01553 if (clbranch->GetListOfBranches()->GetLast()>=0) {
01554 if (clbranch->IsA() != TBranchElement::Class()) {
01555 Error("DefinedVariable","Unimplemented usage of ClonesArray");
01556 return -2;
01557 }
01558
01559 clones = (TClonesArray*)((TBranchElement*)clbranch)->GetObject();
01560 } else
01561 clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
01562 }
01563
01564 if (clones==0) {
01565 Warning("DefinedVariable",
01566 "TClonesArray object was not retrievable for %s!",
01567 name.Data());
01568 return -1;
01569 }
01570 TClass * inside_cl = clones->GetClass();
01571 #if 1
01572 cl = inside_cl;
01573 #else
01574
01575 if (1 || inside_cl) cl = inside_cl;
01576
01577 if (0 && strlen(work)==0) {
01578
01579
01580
01581 }
01582 #endif
01583 } else if (!prevUseCollectionObject && cl && cl->GetCollectionProxy() ) {
01584
01585
01586
01587
01588
01589 TBranch *clbranch = leaf->GetBranch();
01590 R__LoadBranch(clbranch,readentry,fQuickLoad);
01591
01592 if (maininfo==0) {
01593
01594
01595
01596
01597 TClass *mother_cl;
01598 if (leaf->IsA()==TLeafObject::Class()) {
01599
01600 mother_cl = cl;
01601 } else {
01602 mother_cl = ((TBranchElement*)clbranch)->GetInfo()->GetClass();
01603 }
01604
01605 TFormLeafInfo* collectioninfo =
01606 new TFormLeafInfoCollection(mother_cl, 0, cl);
01607
01608 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01609
01610 mustderef = kTRUE;
01611 previnfo = collectioninfo;
01612 maininfo = collectioninfo;
01613
01614 }
01615
01616
01617
01618 TClass * inside_cl = cl->GetCollectionProxy()->GetValueClass();
01619
01620 if (!inside_cl && cl->GetCollectionProxy()->GetType() > 0) {
01621 Warning("DefinedVariable","No data member in content of %s in %s\n",
01622 cl->GetName(),name.Data());
01623 }
01624 cl = inside_cl;
01625
01626 }
01627
01628 if (!cl) {
01629 Warning("DefinedVariable","Missing class for %s!",name.Data());
01630 } else {
01631 element = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(work,offset);
01632 }
01633
01634 if (!element && !prevUseCollectionObject) {
01635
01636
01637 TIter next( cl->GetStreamerInfo()->GetElements() );
01638 TStreamerElement * curelem;
01639 while ((curelem = (TStreamerElement*)next())) {
01640 if (curelem->GetClassPointer() == TClonesArray::Class()) {
01641 Int_t clones_offset;
01642 ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),clones_offset);
01643 TFormLeafInfo* clonesinfo =
01644 new TFormLeafInfo(cl, clones_offset, curelem);
01645 TClonesArray * clones;
01646 R__LoadBranch(leaf->GetBranch(),readentry,fQuickLoad);
01647
01648 if (previnfo) {
01649 previnfo->fNext = clonesinfo;
01650 clones = (TClonesArray*)maininfo->GetValuePointer(leaf,0);
01651 previnfo->fNext = 0;
01652 } else {
01653 clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leaf,0);
01654 }
01655
01656 TClass *sub_cl = clones->GetClass();
01657 if (sub_cl) element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(work,offset);
01658 delete clonesinfo;
01659
01660 if (element) {
01661 leafinfo = new TFormLeafInfoClones(cl,clones_offset,curelem);
01662 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01663 if (maininfo==0) maininfo = leafinfo;
01664 if (previnfo==0) previnfo = leafinfo;
01665 else {
01666 previnfo->fNext = leafinfo;
01667 previnfo = leafinfo;
01668 }
01669 leafinfo = 0;
01670 cl = sub_cl;
01671 break;
01672 }
01673 } else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) {
01674
01675 Int_t coll_offset;
01676 ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),coll_offset);
01677
01678 TClass *sub_cl =
01679 curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass();
01680 if (sub_cl) {
01681 element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(work,offset);
01682 }
01683 if (element) {
01684 if (numberOfVarDim>1) {
01685 Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
01686 curelem->GetName());
01687 leafinfo = new TFormLeafInfo(cl,coll_offset,curelem);
01688 useCollectionObject = kTRUE;
01689 } else if (numberOfVarDim==1) {
01690 R__ASSERT(maininfo);
01691 leafinfo =
01692 new TFormLeafInfoMultiVarDimCollection(cl,coll_offset,
01693 curelem,maininfo);
01694 fHasMultipleVarDim[code] = kTRUE;
01695 leafinfo->fNext = new TFormLeafInfoCollection(cl,coll_offset,curelem);
01696 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01697 } else {
01698 leafinfo = new TFormLeafInfoCollection(cl,coll_offset,curelem);
01699 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01700 }
01701 if (maininfo==0) maininfo = leafinfo;
01702 if (previnfo==0) previnfo = leafinfo;
01703 else {
01704 previnfo->fNext = leafinfo;
01705 previnfo = leafinfo;
01706 }
01707 if (leafinfo->fNext) {
01708 previnfo = leafinfo->fNext;
01709 }
01710 leafinfo = 0;
01711 cl = sub_cl;
01712 break;
01713 }
01714 }
01715 }
01716
01717 }
01718
01719 if (element) {
01720 Int_t type = element->GetNewType();
01721 if (type<60 && type!=0) {
01722
01723 if (numberOfVarDim>=1 && type>40) {
01724
01725 leafinfo = new TFormLeafInfoMultiVarDim(cl,offset,element,maininfo);
01726 fHasMultipleVarDim[code] = kTRUE;
01727 } else {
01728 if (leafinfo && type<=40 ) {
01729 leafinfo->AddOffset(offset,element);
01730 } else {
01731 leafinfo = new TFormLeafInfo(cl,offset,element);
01732 }
01733 }
01734 } else {
01735 Bool_t object = kFALSE;
01736 Bool_t pointer = kFALSE;
01737 Bool_t objarr = kFALSE;
01738 switch(type) {
01739 case TStreamerInfo::kObjectp:
01740 case TStreamerInfo::kObjectP:
01741 case TStreamerInfo::kSTLp:
01742 case TStreamerInfo::kAnyp:
01743 case TStreamerInfo::kAnyP:
01744 case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectP:
01745 case TStreamerInfo::kOffsetL + TStreamerInfo::kSTLp:
01746 case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyp:
01747 case TStreamerInfo::kOffsetL + TStreamerInfo::kObjectp:
01748 case TStreamerInfo::kOffsetL + TStreamerInfo::kAnyP:
01749 pointer = kTRUE;
01750 break;
01751 case TStreamerInfo::kBase:
01752 case TStreamerInfo::kAny :
01753 case TStreamerInfo::kSTL:
01754 case TStreamerInfo::kObject:
01755 case TStreamerInfo::kTString:
01756 case TStreamerInfo::kTNamed:
01757 case TStreamerInfo::kTObject:
01758 object = kTRUE;
01759 break;
01760 case TStreamerInfo::kOffsetL + TStreamerInfo::kAny:
01761 case TStreamerInfo::kOffsetL + TStreamerInfo::kSTL:
01762 case TStreamerInfo::kOffsetL + TStreamerInfo::kObject:
01763 objarr = kTRUE;
01764 break;
01765 case TStreamerInfo::kStreamer:
01766 case TStreamerInfo::kStreamLoop:
01767
01768 Error("DefinedVariable",
01769 "%s is a datamember of %s BUT is not yet of a supported type (%d)",
01770 right,cl ? cl->GetName() : "unknown class",type);
01771 return -2;
01772 default:
01773
01774 Error("DefinedVariable",
01775 "%s is a datamember of %s BUT is not of a unknown type (%d)",
01776 right,cl ? cl->GetName() : "unknown class",type);
01777 return -2;
01778 }
01779
01780 if (object && !useCollectionObject &&
01781 ( element->GetClassPointer() == TClonesArray::Class()
01782 || element->GetClassPointer()->GetCollectionProxy() ) )
01783 {
01784 object = kFALSE;
01785 }
01786 if (object && leafinfo) {
01787 leafinfo->AddOffset(offset,element);
01788 } else if (objarr) {
01789
01790 leafinfo = new TFormLeafInfo(cl,offset,element);
01791 mustderef = kTRUE;
01792 } else {
01793
01794 if (!useCollectionObject && element->GetClassPointer() == TClonesArray::Class()) {
01795
01796 leafinfo = new TFormLeafInfoClones(cl,offset,element);
01797 mustderef = kTRUE;
01798
01799 } else if (!useCollectionObject && element->GetClassPointer()
01800 && element->GetClassPointer()->GetCollectionProxy()) {
01801
01802 mustderef = kTRUE;
01803 if (numberOfVarDim>1) {
01804 Warning("DefinedVariable","TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
01805 element->GetName());
01806 leafinfo = new TFormLeafInfo(cl,offset,element);
01807 useCollectionObject = kTRUE;
01808 } else if (numberOfVarDim==1) {
01809 R__ASSERT(maininfo);
01810 leafinfo =
01811 new TFormLeafInfoMultiVarDimCollection(cl,offset,element,maininfo);
01812
01813 fHasMultipleVarDim[code] = kTRUE;
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823 leafinfo->fNext = new TFormLeafInfoCollection(cl, offset, element);
01824 if (element->GetClassPointer()->GetCollectionProxy()->GetValueClass()==0) {
01825 TFormLeafInfo *info = new TFormLeafInfoNumerical(
01826 element->GetClassPointer()->GetCollectionProxy());
01827 if (leafinfo->fNext) leafinfo->fNext->fNext = info;
01828 else leafinfo->fNext = info;
01829 }
01830 } else {
01831 leafinfo = new TFormLeafInfoCollection(cl, offset, element);
01832
01833 TClass *elemCl = element->GetClassPointer();
01834 TClass *valueCl = elemCl->GetCollectionProxy()->GetValueClass();
01835 if (!maininfo) maininfo = leafinfo;
01836
01837 if (valueCl!=0 && valueCl->GetCollectionProxy()!=0) {
01838
01839 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,kFALSE);
01840 if (previnfo==0) previnfo = leafinfo;
01841 else {
01842 previnfo->fNext = leafinfo;
01843 previnfo = leafinfo;
01844 }
01845 leafinfo = new TFormLeafInfoMultiVarDimCollection(elemCl,0,
01846 elemCl->GetCollectionProxy()->GetValueClass(),maininfo);
01847
01848 fHasMultipleVarDim[code] = kTRUE;
01849
01850 leafinfo->fNext = new TFormLeafInfoCollection(elemCl,0,
01851 valueCl);
01852 elemCl = valueCl;
01853 }
01854 if (elemCl->GetCollectionProxy() &&
01855 elemCl->GetCollectionProxy()->GetValueClass()==0) {
01856 TFormLeafInfo *info = new TFormLeafInfoNumerical(elemCl->GetCollectionProxy());
01857 if (leafinfo->fNext) leafinfo->fNext->fNext = info;
01858 else leafinfo->fNext = info;
01859 }
01860 }
01861 } else if ( (object || pointer) && !useReferenceObject && element->GetClassPointer()->GetReferenceProxy() ) {
01862 TClass* c = element->GetClassPointer();
01863 R__LoadBranch(leaf->GetBranch(),readentry,fQuickLoad);
01864 if ( object ) {
01865 leafinfo = new TFormLeafInfoReference(c, element, offset);
01866 }
01867 else {
01868 leafinfo = new TFormLeafInfoPointer(cl,offset,element);
01869 leafinfo->fNext = new TFormLeafInfoReference(c, element, 0);
01870 }
01871
01872
01873
01874 prevUseReferenceObject = kFALSE;
01875 needClass = kFALSE;
01876 mustderef = kTRUE;
01877 } else if (pointer) {
01878
01879 leafinfo = new TFormLeafInfoPointer(cl,offset,element);
01880 mustderef = kTRUE;
01881 } else {
01882
01883 R__ASSERT(object);
01884 leafinfo = new TFormLeafInfo(cl,offset,element);
01885 }
01886 }
01887 }
01888 } else {
01889 if (cl) Error("DefinedVariable","%s is not a datamember of %s",work,cl->GetName());
01890
01891 return -1;
01892 }
01893
01894 numberOfVarDim += RegisterDimensions(code,leafinfo,maininfo,useCollectionObject);
01895 if (maininfo==0) {
01896 maininfo = leafinfo;
01897 }
01898 if (previnfo==0) {
01899 previnfo = leafinfo;
01900 } else if (previnfo!=leafinfo) {
01901 previnfo->fNext = leafinfo;
01902 previnfo = leafinfo;
01903 }
01904 while (previnfo->fNext) previnfo = previnfo->fNext;
01905
01906 if ( right[i] != '\0' ) {
01907 if ( !needClass && mustderef ) {
01908 maininfo->SetBranch(leaf->GetBranch());
01909 char *ptr = (char*)maininfo->GetValuePointer(leaf,0);
01910 TFormLeafInfoReference* refInfo = 0;
01911 if ( !maininfo->IsReference() ) {
01912 for( TFormLeafInfo* inf = maininfo->fNext; inf; inf = inf->fNext ) {
01913 if ( inf->IsReference() ) {
01914 refInfo = (TFormLeafInfoReference*)inf;
01915 }
01916 }
01917 }
01918 else {
01919 refInfo = (TFormLeafInfoReference*)maininfo;
01920 }
01921 if ( refInfo ) {
01922 cl = refInfo->GetValueClass(ptr);
01923 if ( !cl ) {
01924 Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
01925 return -1;
01926 }
01927 element = ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(work,offset);
01928 }
01929 else {
01930 Error("DefinedVariable","Failed to access class type of reference target (%s)",element->GetName());
01931 return -1;
01932 }
01933 }
01934 else if ( needClass ) {
01935 cl = element->GetClassPointer();
01936 }
01937 }
01938 if (mustderef) leafinfo = 0;
01939 current = &(work[0]);
01940 *current = 0;
01941
01942 R__ASSERT(right[i] != '[');
01943
01944 } else
01945 *current++ = right[i];
01946 }
01947 if (maininfo) {
01948 fDataMembers.AddAtAndExpand(maininfo,code);
01949 if (leaf) fLookupType[code] = kDataMember;
01950 else fLookupType[code] = kTreeMember;
01951 }
01952 }
01953
01954 if (strlen(work)!=0) {
01955
01956 return -1;
01957 }
01958
01959 TClass *objClass = EvalClass(code);
01960 if (objClass && !useLeafCollectionObject && objClass->GetCollectionProxy() && objClass->GetCollectionProxy()->GetValueClass()) {
01961 TFormLeafInfo *last = 0;
01962 if ( SwitchToFormLeafInfo(code) ) {
01963
01964 last = (TFormLeafInfo*)fDataMembers.At(code);
01965
01966 if (!last) return action;
01967 while (last->fNext) { last = last->fNext; }
01968
01969 }
01970 if (last && last->GetClass() != objClass) {
01971 TClass *mother_cl;
01972 if (leaf->IsA()==TLeafObject::Class()) {
01973
01974 mother_cl = cl;
01975 } else {
01976 mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
01977 }
01978
01979 TFormLeafInfo* collectioninfo = new TFormLeafInfoCollection(mother_cl, 0, objClass, kFALSE);
01980
01981 numberOfVarDim += RegisterDimensions(code,collectioninfo,maininfo,kFALSE);
01982 last->fNext = collectioninfo;
01983 }
01984 numberOfVarDim += RegisterDimensions(code,1);
01985 objClass = objClass->GetCollectionProxy()->GetValueClass();
01986 }
01987 if (IsLeafString(code) || objClass == TString::Class() || objClass == stdStringClass) {
01988
01989 TFormLeafInfo *last = 0;
01990 if ( SwitchToFormLeafInfo(code) ) {
01991
01992 last = (TFormLeafInfo*)fDataMembers.At(code);
01993
01994 if (!last) return action;
01995 while (last->fNext) { last = last->fNext; }
01996
01997 }
01998 const char *funcname = 0;
01999 if (objClass == TString::Class()) {
02000 funcname = "Data";
02001
02002 } else if (objClass == stdStringClass) {
02003 funcname = "c_str";
02004
02005 }
02006 if (funcname) {
02007 TMethodCall *method = new TMethodCall(objClass, funcname, "");
02008 if (last) {
02009 last->fNext = new TFormLeafInfoMethod(objClass,method);
02010 } else {
02011 fDataMembers.AddAtAndExpand(new TFormLeafInfoMethod(objClass,method),code);
02012 if (leaf) fLookupType[code] = kDataMember;
02013 else fLookupType[code] = kTreeMember;
02014 }
02015 }
02016 return kDefinedString;
02017 }
02018
02019 if (objClass) {
02020 TMethodCall *method = new TMethodCall(objClass, "AsDouble", "");
02021 if (method->IsValid()
02022 && (method->ReturnType() == TMethodCall::kLong || method->ReturnType() == TMethodCall::kDouble)) {
02023
02024 TFormLeafInfo *last = 0;
02025 if (SwitchToFormLeafInfo(code)) {
02026 last = (TFormLeafInfo*)fDataMembers.At(code);
02027
02028 if (!last) {
02029 delete method;
02030 return action;
02031 }
02032 while (last->fNext) { last = last->fNext; }
02033 }
02034 if (last) {
02035 last->fNext = new TFormLeafInfoMethod(objClass,method);
02036 } else {
02037 fDataMembers.AddAtAndExpand(new TFormLeafInfoMethod(objClass,method),code);
02038 if (leaf) fLookupType[code] = kDataMember;
02039 else fLookupType[code] = kTreeMember;
02040 }
02041
02042 return kDefinedVariable;
02043 }
02044 delete method;
02045 method = new TMethodCall(objClass, "AsString", "");
02046 if (method->IsValid()
02047 && method->ReturnType() == TMethodCall::kString) {
02048
02049 TFormLeafInfo *last = 0;
02050 if (SwitchToFormLeafInfo(code)) {
02051 last = (TFormLeafInfo*)fDataMembers.At(code);
02052
02053 if (!last) {
02054 delete method;
02055 return action;
02056 }
02057 while (last->fNext) { last = last->fNext; }
02058 }
02059 if (last) {
02060 last->fNext = new TFormLeafInfoMethod(objClass,method);
02061 } else {
02062 fDataMembers.AddAtAndExpand(new TFormLeafInfoMethod(objClass,method),code);
02063 if (leaf) fLookupType[code] = kDataMember;
02064 else fLookupType[code] = kTreeMember;
02065 }
02066
02067
02068 return kDefinedString;
02069 }
02070 if (method->IsValid()
02071 && method->ReturnType() == TMethodCall::kOther) {
02072
02073 TClass *rcl = 0;
02074 TFunction *f = method->GetMethod();
02075 if (f) rcl = TClass::GetClass(gInterpreter->TypeName(f->GetReturnTypeName()));
02076 if ((rcl == TString::Class() || rcl == stdStringClass) ) {
02077
02078 TFormLeafInfo *last = 0;
02079 if (SwitchToFormLeafInfo(code)) {
02080 last = (TFormLeafInfo*)fDataMembers.At(code);
02081
02082 if (!last) {
02083 delete method;
02084 return action;
02085 }
02086 while (last->fNext) { last = last->fNext; }
02087 }
02088 if (last) {
02089 last->fNext = new TFormLeafInfoMethod(objClass,method);
02090 last = last->fNext;
02091 } else {
02092 last = new TFormLeafInfoMethod(objClass,method);
02093 fDataMembers.AddAtAndExpand(last,code);
02094 if (leaf) fLookupType[code] = kDataMember;
02095 else fLookupType[code] = kTreeMember;
02096 }
02097
02098 objClass = rcl;
02099
02100 const char *funcname = 0;
02101 if (objClass == TString::Class()) {
02102 funcname = "Data";
02103 } else if (objClass == stdStringClass) {
02104 funcname = "c_str";
02105 }
02106 if (funcname) {
02107 method = new TMethodCall(objClass, funcname, "");
02108 last->fNext = new TFormLeafInfoMethod(objClass,method);
02109 }
02110 return kDefinedString;
02111 }
02112 }
02113 delete method;
02114 }
02115
02116 return action;
02117 }
02118
02119 Int_t TTreeFormula::FindLeafForExpression(const char* expression, TLeaf*& leaf, TString& leftover, Bool_t& final, UInt_t& paran_level, TObjArray& castqueue, std::vector<std::string>& aliasUsed, Bool_t& useLeafCollectionObject, const char* fullExpression)
02120 {
02121
02122
02123
02124
02125
02126
02127
02128
02129
02130
02131
02132
02133
02134
02135 if (fTree->GetTree()==0) {
02136 fTree->LoadTree(0);
02137 if (fTree->GetTree()==0) return -1;
02138 }
02139 Long64_t readentry = fTree->GetTree()->GetReadEntry();
02140 if (readentry==-1) readentry=0;
02141 const char *cname = expression;
02142 char first[kMaxLen]; first[0] = '\0';
02143 char second[kMaxLen]; second[0] = '\0';
02144 char right[kMaxLen]; right[0] = '\0';
02145 char work[kMaxLen]; work[0] = '\0';
02146 char left[kMaxLen]; left[0] = '\0';
02147 char scratch[kMaxLen];
02148 char scratch2[kMaxLen];
02149 std::string currentname;
02150 Int_t previousdot = 0;
02151 char *current;
02152 TLeaf *tmp_leaf=0;
02153 TBranch *branch=0, *tmp_branch=0;
02154 Int_t nchname = strlen(cname);
02155 Int_t i;
02156 Bool_t foundAtSign = kFALSE;
02157
02158 for (i=0, current = &(work[0]); i<=nchname && !final;i++ ) {
02159
02160 *current++ = cname[i];
02161
02162 if (cname[i] == '(') {
02163 ++paran_level;
02164
02165 if (current==work+1) {
02166
02167
02168 current--;
02169 }
02170 continue;
02171
02172
02173
02174
02175
02176
02177
02178 }
02179 if (cname[i] == ')') {
02180 if (paran_level==0) {
02181 Error("DefinedVariable","Unmatched paranthesis in %s",fullExpression);
02182 return -1;
02183 }
02184
02185 *(--current) = 0;
02186 paran_level--;
02187 TString cast_name = gInterpreter->TypeName(work);
02188 TClass *cast_cl = TClass::GetClass(cast_name);
02189 if (cast_cl) {
02190
02191 castqueue.AddAtAndExpand(cast_cl,paran_level);
02192 current = &(work[0]);
02193 *current = 0;
02194
02195 continue;
02196 } else if (gROOT->GetType(cast_name)) {
02197
02198 current = &(work[0]);
02199 *current = 0;
02200 Warning("DefinedVariable",
02201 "Casting to primary types like \"%s\" is not supported yet",cast_name.Data());
02202 continue;
02203 }
02204
02205 *(current++)=')';
02206 *current='\0';
02207 char *params = strchr(work,'(');
02208 if (params) {
02209 *params = 0; params++;
02210
02211 if (branch && !leaf) {
02212
02213
02214 if (BranchHasMethod(0, branch, work, params, readentry)) {
02215
02216 }
02217 }
02218
02219
02220
02221 TIter next(fTree->GetIteratorOnAllLeaves());
02222 TLeaf* leafcur = 0;
02223 while (!leaf && (leafcur = (TLeaf*) next())) {
02224 TBranch* br = leafcur->GetBranch();
02225 Bool_t yes = BranchHasMethod(leafcur, br, work, params, readentry);
02226 if (yes) {
02227 leaf = leafcur;
02228
02229 }
02230 }
02231 if (!leaf) {
02232
02233 if (strlen(left) && left[strlen(left)-1]=='.') left[strlen(left)-1]=0;
02234 const char *aliasValue = fTree->GetAlias(left);
02235 if (aliasValue && strcspn(aliasValue,"+*/-%&!=<>|")==strlen(aliasValue)) {
02236
02237
02238 if (find(aliasUsed.begin(),
02239 aliasUsed.end(),
02240 left) != aliasUsed.end()) {
02241 Error("DefinedVariable",
02242 "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
02243 "\tbecause \"%s\" is used [recursively] in its own definition!",
02244 left,aliasValue,fullExpression,left);
02245 return -3;
02246 }
02247 aliasUsed.push_back(left);
02248 TString newExpression = aliasValue;
02249 newExpression += (cname+strlen(left));
02250 Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level,
02251 castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
02252 if (res<0) {
02253 Error("DefinedVariable",
02254 "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
02255 return -3;
02256 }
02257 return res;
02258 }
02259
02260
02261
02262 return -1;
02263 }
02264
02265
02266
02267
02268
02269
02270
02271 strlcpy(right,work,kMaxLen);
02272 strncat(right,"(",kMaxLen-1-strlen(right));
02273 strncat(right,params,kMaxLen-1-strlen(right));
02274 final = kTRUE;
02275
02276
02277 current = &(work[0]);
02278 *current = 0;
02279 break;
02280 }
02281 }
02282 if (cname[i] == '.' || cname[i] == '\0' || cname[i] == ')') {
02283
02284
02285 *current = '\0';
02286
02287 Int_t len = strlen(work);
02288 if (work[0]=='@') {
02289 foundAtSign = kTRUE;
02290 Int_t l = 0;
02291 for(l=0;work[l+1]!=0;++l) work[l] = work[l+1];
02292 work[l] = '\0';
02293 --current;
02294 } else if (len>=2 && work[len-2]=='@') {
02295 foundAtSign = kTRUE;
02296 work[len-2] = cname[i];
02297 work[len-1] = '\0';
02298 --current;
02299 } else {
02300 foundAtSign = kFALSE;
02301 }
02302
02303 if (left[0]==0) strlcpy(left,work,kMaxLen);
02304 if (!leaf && !branch) {
02305
02306 strlcpy(first,work,kMaxLen);
02307
02308 std::string treename(first);
02309 if (treename.size() && treename[treename.size()-1]=='.') {
02310 treename.erase(treename.size()-1);
02311 }
02312 if (treename== "This" ) {
02313
02314 TNamed *named = new TNamed(fTree->GetName(),fTree->GetName());
02315 fLeafNames.AddAtAndExpand(named,fNcodes);
02316 fLeaves.AddAtAndExpand(fTree,fNcodes);
02317 if (cname[i]) leftover = &(cname[i+1]);
02318 return 2;
02319 }
02320
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336
02337
02338
02339
02340
02341
02342
02343
02344 branch = fTree->FindBranch(first);
02345 leaf = fTree->FindLeaf(first);
02346
02347
02348
02349 if (cname[i]) first[strlen(first)-1]='\0';
02350 if (!branch) branch = fTree->FindBranch(first);
02351 if (!leaf) leaf = fTree->FindLeaf(first);
02352 TClass* cl = 0;
02353 if ( branch && branch->InheritsFrom(TBranchElement::Class()) ) {
02354 int offset=0;
02355 TBranchElement* bElt = (TBranchElement*)branch;
02356 TStreamerInfo* info = bElt->GetInfo();
02357 TStreamerElement* element = info ? info->GetStreamerElement(first,offset) : 0;
02358 if (element) cl = element->GetClassPointer();
02359 if ( cl && !cl->GetReferenceProxy() ) cl = 0;
02360 }
02361 if ( cl ) {
02362 final = kTRUE;
02363 useLeafCollectionObject = foundAtSign;
02364
02365 current = &(work[0]);
02366 *current = 0;
02367 }
02368 else if (branch && (foundAtSign || cname[i] != 0) ) {
02369
02370
02371
02372
02373 if (leaf==0) {
02374
02375
02376 if (branch->InheritsFrom(TBranchElement::Class()) ) {
02377 Int_t type = ((TBranchElement*)branch)->GetType();
02378 if ( type == 3 || type ==4) {
02379
02380 leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
02381 if (foundAtSign) {
02382 useLeafCollectionObject = foundAtSign;
02383 foundAtSign = kFALSE;
02384 current = &(work[0]);
02385 *current = 0;
02386 ++i;
02387 break;
02388 }
02389 }
02390 }
02391 }
02392
02393
02394 useLeafCollectionObject = foundAtSign;
02395 foundAtSign = kFALSE;
02396 current = &(work[0]);
02397 *current = 0;
02398 } else if (leaf || branch) {
02399 if (leaf && branch) {
02400
02401
02402
02403
02404
02405
02406 }
02407 if (leaf && leaf->IsOnTerminalBranch()) {
02408
02409
02410 final = kTRUE;
02411 }
02412
02413 current = &(work[0]);
02414 *current = 0;
02415 } else {
02416
02417
02418 TLeaf *leafcur = GetLeafWithDatamember(first,work,readentry);
02419 if (leafcur) {
02420 leaf = leafcur;
02421 branch = leaf->GetBranch();
02422 if (leaf->IsOnTerminalBranch()) {
02423 final = kTRUE;
02424 strlcpy(right,first,kMaxLen);
02425
02426 if (foundAtSign) strncat(right,"@",kMaxLen-1-strlen(right));
02427 if (cname[i]=='.') strncat(right,".",kMaxLen-1-strlen(right));
02428
02429
02430 current = &(work[0]);
02431 *current = 0;
02432 };
02433 } else if (cname[i] == '.') {
02434
02435
02436
02437
02438 TBranch *branchcur;
02439 TIter next( fTree->GetListOfBranches() );
02440 while(!branch && (branchcur=(TBranch*)next()) ) {
02441 branch = branchcur->FindBranch(first);
02442 }
02443 if (branch) {
02444
02445 current = &(work[0]);
02446 *current = 0;
02447 }
02448 }
02449 }
02450 } else {
02451 if (final) {
02452 Error("DefinedVariable", "Unexpected control flow!");
02453 return -1;
02454 }
02455
02456
02457
02458 if (cname[i]) work[strlen(work)-1] = '\0';
02459 snprintf(scratch,sizeof(scratch),"%s.%s",first,work);
02460 snprintf(scratch2,sizeof(scratch2),"%s.%s.%s",first,second,work);
02461
02462 if (previousdot) {
02463 currentname = &(work[previousdot+1]);
02464 }
02465
02466
02467
02468 if (branch) {
02469 tmp_leaf = branch->FindLeaf(work);
02470 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(scratch);
02471 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(scratch2);
02472 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(currentname.c_str());
02473 }
02474 if (tmp_leaf && tmp_leaf->IsOnTerminalBranch() ) {
02475
02476
02477 final = kTRUE;
02478 }
02479
02480 if (branch) {
02481 tmp_branch = branch->FindBranch(work);
02482 if (!tmp_branch) tmp_branch = branch->FindBranch(scratch);
02483 if (!tmp_branch) tmp_branch = branch->FindBranch(scratch2);
02484 if (!tmp_branch) tmp_branch = branch->FindBranch(currentname.c_str());
02485 }
02486 if (tmp_branch) {
02487 branch=tmp_branch;
02488
02489
02490 if (!final) {
02491 tmp_leaf = branch->FindLeaf(work);
02492 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(scratch);
02493 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(scratch2);
02494 if (!tmp_leaf) tmp_leaf = branch->FindLeaf(currentname.c_str());
02495 if (tmp_leaf && tmp_leaf->IsOnTerminalBranch() ) {
02496
02497
02498 final = kTRUE;
02499 leaf = tmp_leaf;
02500 }
02501 }
02502 }
02503 if (tmp_leaf) {
02504
02505 if (second[0]) strncat(second,".",kMaxLen-1-strlen(second));
02506 strncat(second,work,kMaxLen-1-strlen(second));
02507 leaf = tmp_leaf;
02508 useLeafCollectionObject = foundAtSign;
02509 foundAtSign = kFALSE;
02510
02511
02512 current = &(work[0]);
02513 *current = 0;
02514 } else {
02515
02516 if (strlen(work)) {
02517 if (foundAtSign) {
02518 Int_t where = strlen(work);
02519 work[where] = '@';
02520 work[where+1] = cname[i];
02521 ++current;
02522 previousdot = where+1;
02523 } else {
02524 previousdot = strlen(work);
02525 work[strlen(work)] = cname[i];
02526 }
02527 } else --current;
02528 }
02529 }
02530 }
02531 }
02532
02533
02534 if (strlen(work)) {
02535 strncat(right,work,kMaxLen-1-strlen(right));
02536 }
02537
02538 if (i<nchname) {
02539 if (strlen(right) && right[strlen(right)-1]!='.' && cname[i]!='.') {
02540
02541
02542
02543 strncat(right,".",kMaxLen-1-strlen(right));
02544 }
02545 strncat(right,&cname[i],kMaxLen-1-strlen(right));
02546 }
02547
02548 if (!final && branch) {
02549 if (!leaf) {
02550 leaf = (TLeaf*)branch->GetListOfLeaves()->UncheckedAt(0);
02551 if (!leaf) return -1;
02552 }
02553 final = leaf->IsOnTerminalBranch();
02554 }
02555
02556 if (leaf && leaf->InheritsFrom(TLeafObject::Class()) ) {
02557 if (strlen(right)==0) strlcpy(right,work,kMaxLen);
02558 }
02559
02560 if (leaf==0 && left[0]!=0) {
02561 if (left[strlen(left)-1]=='.') left[strlen(left)-1]=0;
02562
02563
02564 const char *aliasValue = fTree->GetAlias(left);
02565 if (aliasValue && strcspn(aliasValue,"[]+*/-%&!=<>|")==strlen(aliasValue)) {
02566
02567
02568 if (find(aliasUsed.begin(),
02569 aliasUsed.end(),
02570 left) != aliasUsed.end()) {
02571 Error("DefinedVariable",
02572 "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
02573 "\tbecause \"%s\" is used [recursively] in its own definition!",
02574 left,aliasValue,fullExpression,left);
02575 return -3;
02576 }
02577 aliasUsed.push_back(left);
02578 TString newExpression = aliasValue;
02579 newExpression += (cname+strlen(left));
02580 Int_t res = FindLeafForExpression(newExpression, leaf, leftover, final, paran_level,
02581 castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
02582 if (res<0) {
02583 Error("DefinedVariable",
02584 "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
02585 return -3;
02586 }
02587 return res;
02588 }
02589 }
02590 leftover = right;
02591
02592 return 0;
02593 }
02594
02595
02596 Int_t TTreeFormula::DefinedVariable(TString &name, Int_t &action)
02597 {
02598
02599
02600
02601
02602
02603
02604
02605
02606
02607
02608
02609
02610
02611
02612
02613
02614
02615
02616
02617
02618
02619
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633 action = kDefinedVariable;
02634 if (!fTree) return -1;
02635
02636 fNpar = 0;
02637 if (name.Length() > kMaxLen) return -1;
02638 Int_t i,k;
02639
02640 if (name == "Entry$") {
02641 Int_t code = fNcodes++;
02642 fCodes[code] = 0;
02643 fLookupType[code] = kIndexOfEntry;
02644 return code;
02645 }
02646 if (name == "LocalEntry$") {
02647 Int_t code = fNcodes++;
02648 fCodes[code] = 0;
02649 fLookupType[code] = kIndexOfLocalEntry;
02650 return code;
02651 }
02652 if (name == "Entries$") {
02653 Int_t code = fNcodes++;
02654 fCodes[code] = 0;
02655 fLookupType[code] = kEntries;
02656 SetBit(kNeedEntries);
02657 fManager->SetBit(kNeedEntries);
02658 return code;
02659 }
02660 if (name == "Iteration$") {
02661 Int_t code = fNcodes++;
02662 fCodes[code] = 0;
02663 fLookupType[code] = kIteration;
02664 return code;
02665 }
02666 if (name == "Length$") {
02667 Int_t code = fNcodes++;
02668 fCodes[code] = 0;
02669 fLookupType[code] = kLength;
02670 return code;
02671 }
02672 static const char *lenfunc = "Length$(";
02673 if (strncmp(name.Data(),"Length$(",strlen(lenfunc))==0
02674 && name[name.Length()-1]==')') {
02675
02676 TString subform = name.Data()+strlen(lenfunc);
02677 subform.Remove( subform.Length() - 1 );
02678 TTreeFormula *lengthForm = new TTreeFormula("lengthForm",subform,fTree);
02679 fAliases.AddAtAndExpand(lengthForm,fNoper);
02680 Int_t code = fNcodes++;
02681 fCodes[code] = 0;
02682 fLookupType[code] = kLengthFunc;
02683 return code;
02684 }
02685 static const char *minfunc = "Min$(";
02686 if (strncmp(name.Data(),"Min$(",strlen(minfunc))==0
02687 && name[name.Length()-1]==')') {
02688
02689 TString subform = name.Data()+strlen(minfunc);
02690 subform.Remove( subform.Length() - 1 );
02691 TTreeFormula *minForm = new TTreeFormula("minForm",subform,fTree);
02692 fAliases.AddAtAndExpand(minForm,fNoper);
02693 Int_t code = fNcodes++;
02694 fCodes[code] = 0;
02695 fLookupType[code] = kMin;
02696 return code;
02697 }
02698 static const char *maxfunc = "Max$(";
02699 if (strncmp(name.Data(),"Max$(",strlen(maxfunc))==0
02700 && name[name.Length()-1]==')') {
02701
02702 TString subform = name.Data()+strlen(maxfunc);
02703 subform.Remove( subform.Length() - 1 );
02704 TTreeFormula *maxForm = new TTreeFormula("maxForm",subform,fTree);
02705 fAliases.AddAtAndExpand(maxForm,fNoper);
02706 Int_t code = fNcodes++;
02707 fCodes[code] = 0;
02708 fLookupType[code] = kMax;
02709 return code;
02710 }
02711 static const char *sumfunc = "Sum$(";
02712 if (strncmp(name.Data(),"Sum$(",strlen(sumfunc))==0
02713 && name[name.Length()-1]==')') {
02714
02715 TString subform = name.Data()+strlen(sumfunc);
02716 subform.Remove( subform.Length() - 1 );
02717 TTreeFormula *sumForm = new TTreeFormula("sumForm",subform,fTree);
02718 fAliases.AddAtAndExpand(sumForm,fNoper);
02719 Int_t code = fNcodes++;
02720 fCodes[code] = 0;
02721 fLookupType[code] = kSum;
02722 return code;
02723 }
02724
02725
02726
02727
02728 Int_t res = DefineAlternate(name.Data());
02729 if (res!=0) {
02730
02731 if (res<0) return res;
02732 action = res;
02733 return 0;
02734 }
02735
02736
02737
02738 char cname[kMaxLen]; strlcpy(cname,name.Data(),kMaxLen);
02739 char dims[kMaxLen]; dims[0] = '\0';
02740
02741 Bool_t final = kFALSE;
02742
02743 UInt_t paran_level = 0;
02744 TObjArray castqueue;
02745
02746
02747 Int_t cnamelen = strlen(cname);
02748 for(i=0,k=0; i<cnamelen; ++i, ++k) {
02749 if (cname[i] == '[') {
02750 int bracket = i;
02751 int bracket_level = 1;
02752 int j;
02753 for (j=++i; j<cnamelen && (bracket_level>0 || cname[j]=='['); j++, i++) {
02754 if (cname[j]=='[') bracket_level++;
02755 else if (cname[j]==']') bracket_level--;
02756 }
02757 if (bracket_level != 0) {
02758
02759 return -1;
02760 }
02761 strncat(dims,&cname[bracket],j-bracket);
02762
02763 }
02764 if (i!=k) cname[k] = cname[i];
02765 }
02766 cname[k]='\0';
02767
02768 Bool_t useLeafCollectionObject = kFALSE;
02769 TString leftover;
02770 TLeaf *leaf = 0;
02771 {
02772 std::vector<std::string> aliasSofar = fAliasesUsed;
02773 res = FindLeafForExpression(cname, leaf, leftover, final, paran_level, castqueue, aliasSofar, useLeafCollectionObject, name);
02774 }
02775 if (res<0) return res;
02776
02777 if (!leaf && res!=2) {
02778
02779 const char *aliasValue = fTree->GetAlias(cname);
02780 if (aliasValue) {
02781
02782
02783 if (find(fAliasesUsed.begin(),
02784 fAliasesUsed.end(),
02785 cname) != fAliasesUsed.end()) {
02786 Error("DefinedVariable",
02787 "The substitution of the alias \"%s\" by \"%s\" failed\n"\
02788 "\tbecause \"%s\" is recursively used in its own definition!",
02789 cname,aliasValue,cname);
02790 return -3;
02791 }
02792
02793
02794 if (strcspn(aliasValue,"+*/-%&!=<>|")!=strlen(aliasValue)) {
02795
02796
02797
02798
02799 std::vector<std::string> aliasSofar = fAliasesUsed;
02800 aliasSofar.push_back( cname );
02801
02802 TString subValue( aliasValue );
02803 if (dims[0]) {
02804 subValue += dims;
02805 }
02806
02807 TTreeFormula *subform = new TTreeFormula(cname,subValue,fTree,aliasSofar);
02808
02809 if (subform->GetNdim()==0) {
02810 delete subform;
02811 Error("DefinedVariable",
02812 "The substitution of the alias \"%s\" by \"%s\" failed.",cname,aliasValue);
02813 return -3;
02814 }
02815
02816 fManager->Add(subform);
02817 fAliases.AddAtAndExpand(subform,fNoper);
02818
02819 if (subform->IsString()) {
02820 action = kAliasString;
02821 return 0;
02822 } else {
02823 action = kAlias;
02824 return 0;
02825 }
02826 } else {
02827 TString thisAlias( aliasValue );
02828 thisAlias += dims;
02829 Int_t aliasRes = DefinedVariable(thisAlias,action);
02830 if (aliasRes<0) {
02831
02832
02833
02834 if (aliasRes==-1) {
02835 Error("Compile", " Bad numerical expression : \"%s\"",thisAlias.Data());
02836 } else if (aliasRes==-2) {
02837 Error("Compile", " Part of the Variable \"%s\" exists but some of it is not accessible or useable",thisAlias.Data());
02838
02839 }
02840 Error("DefinedVariable",
02841 "The substitution of the alias \"%s\" by \"%s\" failed.",cname,aliasValue);
02842 return -3;
02843 }
02844 return aliasRes;
02845 }
02846 }
02847 }
02848
02849
02850 if (leaf || res==2) {
02851
02852 if (leaf && leaf->GetBranch() && leaf->GetBranch()->TestBit(kDoNotProcess)) {
02853 Error("DefinedVariable","the branch \"%s\" has to be enabled to be used",leaf->GetBranch()->GetName());
02854 return -2;
02855 }
02856
02857 Int_t code = fNcodes++;
02858
02859
02860
02861 if (dims[0]) {
02862 char *current = &( dims[0] );
02863 Int_t dim = 0;
02864 TString varindex;
02865 Int_t index;
02866 Int_t scanindex ;
02867 while (current) {
02868 current++;
02869 if (current[0] == ']') {
02870 fIndexes[code][dim] = -1;
02871 } else {
02872 scanindex = sscanf(current,"%d",&index);
02873 if (scanindex) {
02874 fIndexes[code][dim] = index;
02875 } else {
02876 fIndexes[code][dim] = -2;
02877 varindex = current;
02878 char *end = (char*)(varindex.Data());
02879 for(char bracket_level = 0;*end!=0;end++) {
02880 if (*end=='[') bracket_level++;
02881 if (bracket_level==0 && *end==']') break;
02882 if (*end==']') bracket_level--;
02883 }
02884 *end = '\0';
02885 fVarIndexes[code][dim] = new TTreeFormula("index_var",
02886 varindex,
02887 fTree);
02888 current += strlen(varindex)+1;
02889 }
02890 }
02891 dim ++;
02892 if (dim >= kMAXFORMDIM) {
02893
02894 break;
02895 }
02896 current = (char*)strstr( current, "[" );
02897 }
02898 }
02899
02900
02901
02902
02903 res = ParseWithLeaf(leaf,leftover,final,paran_level,castqueue,useLeafCollectionObject,name);
02904 if (res<0) return res;
02905 if (res>0) action = res;
02906 return code;
02907 }
02908
02909
02910 TCutG *gcut = (TCutG*)gROOT->GetListOfSpecials()->FindObject(name.Data());
02911 if (gcut) {
02912 if (gcut->GetObjectX()) {
02913 if(!gcut->GetObjectX()->InheritsFrom(TTreeFormula::Class())) {
02914 delete gcut->GetObjectX(); gcut->SetObjectX(0);
02915 }
02916 }
02917 if (gcut->GetObjectY()) {
02918 if(!gcut->GetObjectY()->InheritsFrom(TTreeFormula::Class())) {
02919 delete gcut->GetObjectY(); gcut->SetObjectY(0);
02920 }
02921 }
02922
02923 Int_t code = fNcodes;
02924
02925 if (strlen(gcut->GetVarX()) && strlen(gcut->GetVarY()) ) {
02926
02927 TTreeFormula *fx = new TTreeFormula("f_x",gcut->GetVarX(),fTree);
02928 gcut->SetObjectX(fx);
02929
02930 TTreeFormula *fy = new TTreeFormula("f_y",gcut->GetVarY(),fTree);
02931 gcut->SetObjectY(fy);
02932
02933 fCodes[code] = -2;
02934
02935 } else if (strlen(gcut->GetVarX())) {
02936
02937
02938
02939 Double_t min = 0;
02940 Double_t max = 0;
02941 Int_t n = gcut->GetN();
02942 Double_t *x = gcut->GetX();
02943 min = max = x[0];
02944 for(Int_t i2 = 1; i2<n; i2++) {
02945 if (x[i2] < min) min = x[i2];
02946 if (x[i2] > max) max = x[i2];
02947 }
02948 TString formula = "(";
02949 formula += min;
02950 formula += "<=";
02951 formula += gcut->GetVarX();
02952 formula += " && ";
02953 formula += gcut->GetVarX();
02954 formula += "<=";
02955 formula += max;
02956 formula += ")";
02957
02958 TTreeFormula *fx = new TTreeFormula("f_x",formula.Data(),fTree);
02959 gcut->SetObjectX(fx);
02960
02961 fCodes[code] = -1;
02962
02963 } else {
02964
02965 Error("DefinedVariable","Found a TCutG without leaf information (%s)",
02966 gcut->GetName());
02967 return -1;
02968
02969 }
02970
02971 fExternalCuts.AddAtAndExpand(gcut,code);
02972 fNcodes++;
02973 fLookupType[code] = -1;
02974 return code;
02975 }
02976
02977
02978 TEntryList *elist = dynamic_cast<TEntryList*> (gDirectory->Get(name.Data()));
02979 if (elist) {
02980 Int_t code = fNcodes;
02981 fCodes[code] = 0;
02982 fExternalCuts.AddAtAndExpand(elist, code);
02983 fNcodes++;
02984 fLookupType[code] = kEntryList;
02985 return code;
02986
02987 }
02988
02989 return -1;
02990 }
02991
02992
02993 TLeaf* TTreeFormula::GetLeafWithDatamember(const char* topchoice, const char* nextchoice, Long64_t readentry) const
02994 {
02995
02996
02997
02998
02999 TClass * cl = 0;
03000 TIter nextleaf (fTree->GetIteratorOnAllLeaves());
03001 TFormLeafInfo* clonesinfo = 0;
03002 TLeaf *leafcur;
03003 while ((leafcur = (TLeaf*)nextleaf())) {
03004
03005
03006
03007
03008 cl = 0;
03009 if (leafcur->InheritsFrom(TLeafObject::Class()) &&
03010 leafcur->GetBranch()->GetListOfBranches()->Last()==0) {
03011 TLeafObject *lobj = (TLeafObject*)leafcur;
03012 cl = lobj->GetClass();
03013 } else if (leafcur->InheritsFrom(TLeafElement::Class()) && leafcur->IsOnTerminalBranch()) {
03014 TLeafElement * lElem = (TLeafElement*) leafcur;
03015 if (lElem->IsOnTerminalBranch()) {
03016 TBranchElement *branchEl = (TBranchElement *)leafcur->GetBranch();
03017 Int_t type = branchEl->GetStreamerType();
03018 if (type==-1) {
03019 cl = branchEl->GetInfo()->GetClass();
03020 } else if (type>60 || type==0) {
03021
03022
03023
03024 TStreamerElement* element = (TStreamerElement*)
03025 branchEl->GetInfo()->GetElems()[branchEl->GetID()];
03026 if (element) cl = element->GetClassPointer();
03027 else cl = 0;
03028 }
03029 }
03030
03031 }
03032 if (clonesinfo) { delete clonesinfo; clonesinfo = 0; }
03033 if (cl == TClonesArray::Class()) {
03034
03035
03036
03037 R__LoadBranch(leafcur->GetBranch(),readentry,fQuickLoad);
03038 TClonesArray * clones;
03039
03040 TBranch *branch = leafcur->GetBranch();
03041 if ( branch->IsA()==TBranchElement::Class()
03042 && ((TBranchElement*)branch)->GetType()==31) {
03043
03044
03045
03046
03047
03048
03049 continue;
03050
03051 } else {
03052 Bool_t toplevel = (branch == branch->GetMother());
03053 clonesinfo = new TFormLeafInfoClones(cl, 0, toplevel);
03054 clones = (TClonesArray*)clonesinfo->GetLocalValuePointer(leafcur,0);
03055 }
03056 if (clones) cl = clones->GetClass();
03057 } else if (cl && cl->GetCollectionProxy()) {
03058
03059
03060
03061
03062
03063 TBranch *branch = leafcur->GetBranch();
03064 if ( branch->IsA()==TBranchElement::Class()
03065 && ((TBranchElement*)branch)->GetType()==41) {
03066
03067
03068
03069
03070
03071
03072 continue;
03073
03074 } else {
03075 clonesinfo = new TFormLeafInfoCollection(cl, 0);
03076 }
03077 cl = cl->GetCollectionProxy()->GetValueClass();
03078 }
03079 if (cl) {
03080
03081
03082 Int_t offset;
03083 TStreamerInfo* info = (TStreamerInfo*)cl->GetStreamerInfo();
03084 TStreamerElement* element = info?info->GetStreamerElement(topchoice,offset):0;
03085 if (!element) {
03086 TIter nextel( cl->GetStreamerInfo()->GetElements() );
03087 TStreamerElement * curelem;
03088 while ((curelem = (TStreamerElement*)nextel())) {
03089
03090 if (curelem->GetClassPointer() == TClonesArray::Class()) {
03091
03092
03093
03094
03095 TBranch *branch = leafcur->GetBranch();
03096 TFormLeafInfo *leafinfo = 0;
03097 if (clonesinfo) {
03098 leafinfo = clonesinfo;
03099 } else if (branch->IsA()==TBranchElement::Class()
03100 && ((TBranchElement*)branch)->GetType()==31) {
03101
03102 TBranchElement *branchEl = (TBranchElement*)branch;
03103 TStreamerInfo *bel_info = branchEl->GetInfo();
03104 TClass * mother_cl = ((TBranchElement*)branch)->GetInfo()->GetClass();
03105 TStreamerElement *bel_element =
03106 (TStreamerElement *)bel_info->GetElems()[branchEl->GetID()];
03107 leafinfo = new TFormLeafInfoClones(mother_cl, 0, bel_element, kTRUE);
03108 }
03109
03110 Int_t clones_offset;
03111 ((TStreamerInfo*)cl->GetStreamerInfo())->GetStreamerElement(curelem->GetName(),clones_offset);
03112 TFormLeafInfo* sub_clonesinfo = new TFormLeafInfo(cl, clones_offset, curelem);
03113 if (leafinfo)
03114 if (leafinfo->fNext) leafinfo->fNext->fNext = sub_clonesinfo;
03115 else leafinfo->fNext = sub_clonesinfo;
03116 else leafinfo = sub_clonesinfo;
03117
03118 R__LoadBranch(branch,readentry,fQuickLoad);
03119
03120 TClonesArray * clones = (TClonesArray*)leafinfo->GetValuePointer(leafcur,0);
03121
03122 delete leafinfo; clonesinfo = 0;
03123
03124
03125
03126
03127 if (!clones) continue;
03128 TClass *sub_cl = clones->GetClass();
03129
03130
03131 element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(nextchoice,offset);
03132 if (element) break;
03133 }
03134 else if (curelem->GetClassPointer() && curelem->GetClassPointer()->GetCollectionProxy()) {
03135
03136 TClass *sub_cl = curelem->GetClassPointer()->GetCollectionProxy()->GetValueClass();
03137
03138 while(sub_cl && sub_cl->GetCollectionProxy())
03139 sub_cl = sub_cl->GetCollectionProxy()->GetValueClass();
03140
03141
03142 if (sub_cl) element = ((TStreamerInfo*)sub_cl->GetStreamerInfo())->GetStreamerElement(nextchoice,offset);
03143 if (element) break;
03144
03145 }
03146 }
03147 }
03148 if (element) break;
03149 else cl = 0;
03150 }
03151 }
03152 delete clonesinfo;
03153 if (cl) {
03154 return leafcur;
03155 } else {
03156 return 0;
03157 }
03158 }
03159
03160
03161 Bool_t TTreeFormula::BranchHasMethod(TLeaf* leafcur, TBranch* branch, const char* method, const char* params, Long64_t readentry) const
03162 {
03163
03164
03165
03166 TClass *cl = 0;
03167 TLeafObject* lobj = 0;
03168
03169
03170
03171
03172
03173
03174
03175 if (branch->TestBit(kDoNotProcess)) {
03176 return kFALSE;
03177 }
03178
03179
03180 if (branch->InheritsFrom(TBranchObject::Class())) {
03181 lobj = (TLeafObject*) branch->GetListOfLeaves()->At(0);
03182 cl = lobj->GetClass();
03183 } else if (branch->InheritsFrom(TBranchElement::Class())) {
03184 TBranchElement* branchEl = (TBranchElement*) branch;
03185 Int_t type = branchEl->GetStreamerType();
03186 if (type == -1) {
03187 cl = branchEl->GetInfo()->GetClass();
03188 } else if (type > 60) {
03189
03190
03191
03192 TStreamerElement* element = (TStreamerElement*) branchEl->GetInfo()->GetElems()[branchEl->GetID()];
03193 if (element) {
03194 cl = element->GetClassPointer();
03195 } else {
03196 cl = 0;
03197 }
03198 if ((cl == TClonesArray::Class()) && (branchEl->GetType() == 31)) {
03199
03200
03201
03202 cl = 0;
03203 }
03204
03205 }
03206 }
03207
03208 if (cl == TClonesArray::Class()) {
03209
03210
03211
03212
03213 TClonesArray* clones = 0;
03214 R__LoadBranch(branch, readentry, fQuickLoad);
03215 if (branch->InheritsFrom(TBranchObject::Class())) {
03216 clones = (TClonesArray*) lobj->GetObject();
03217 } else if (branch->InheritsFrom(TBranchElement::Class())) {
03218
03219
03220
03221 TBranchElement* bc = (TBranchElement*) branch;
03222 if (bc == bc->GetMother()) {
03223
03224
03225 clones = (TClonesArray*) bc->GetObject();
03226 } else if (!leafcur || !leafcur->IsOnTerminalBranch()) {
03227 TStreamerElement* element = (TStreamerElement*) bc->GetInfo()->GetElems()[bc->GetID()];
03228 if (element->IsaPointer()) {
03229 clones = *((TClonesArray**) bc->GetAddress());
03230
03231 } else {
03232
03233 clones = (TClonesArray*) bc->GetObject();
03234 }
03235 }
03236 if (!clones) {
03237 R__LoadBranch(bc, readentry, fQuickLoad);
03238 TClass* mother_cl;
03239 mother_cl = bc->GetInfo()->GetClass();
03240 TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(mother_cl, 0);
03241
03242 clones = (TClonesArray*) clonesinfo->GetLocalValuePointer(leafcur, 0);
03243
03244 delete clonesinfo;
03245 }
03246 } else {
03247 Error("BranchHasMethod","A TClonesArray was stored in a branch type no yet support (i.e. neither TBranchObject nor TBranchElement): %s",branch->IsA()->GetName());
03248 return kFALSE;
03249 }
03250 cl = clones->GetClass();
03251 } else if (cl && cl->GetCollectionProxy()) {
03252 cl = cl->GetCollectionProxy()->GetValueClass();
03253 }
03254
03255 if (cl) {
03256 if (cl->GetClassInfo()) {
03257 if (cl->GetMethodAllAny(method)) {
03258
03259
03260
03261
03262 TMethodCall* methodcall = new TMethodCall(cl, method, params);
03263 if (methodcall->GetMethod()) {
03264
03265
03266 return kTRUE;
03267 }
03268 delete methodcall;
03269 }
03270 }
03271 }
03272
03273 return kFALSE;
03274 }
03275
03276
03277 Int_t TTreeFormula::GetRealInstance(Int_t instance, Int_t codeindex) {
03278
03279
03280
03281
03282
03283 Int_t real_instance = 0;
03284 Int_t virt_dim;
03285
03286 Bool_t check = kFALSE;
03287 if (codeindex<0) {
03288 codeindex = 0;
03289 check = kTRUE;
03290 }
03291
03292 TFormLeafInfo * info = 0;
03293 Int_t max_dim = fNdimensions[codeindex];
03294 if ( max_dim ) {
03295 virt_dim = 0;
03296 max_dim--;
03297
03298 if (!fManager->fMultiVarDim) {
03299 if (fIndexes[codeindex][0]>=0) {
03300 real_instance = fIndexes[codeindex][0] * fCumulSizes[codeindex][1];
03301 } else {
03302 Int_t local_index;
03303 local_index = ( instance / fManager->fCumulUsedSizes[virt_dim+1]);
03304 if (fIndexes[codeindex][0]==-2) {
03305
03306 if (check) {
03307 Int_t index_real_instance = fVarIndexes[codeindex][0]->GetRealInstance(local_index,-1);
03308 if (index_real_instance > fVarIndexes[codeindex][0]->fNdata[0]) {
03309
03310 return fNdata[0]+1;
03311 }
03312 }
03313 if (fDidBooleanOptimization && local_index!=0) {
03314
03315 fVarIndexes[codeindex][0]->LoadBranches();
03316 }
03317 local_index = (Int_t)fVarIndexes[codeindex][0]->EvalInstance(local_index);
03318 if (local_index<0) {
03319 Error("EvalInstance","Index %s is out of bound (%d) in formula %s",
03320 fVarIndexes[codeindex][0]->GetTitle(),
03321 local_index,
03322 GetTitle());
03323 return fNdata[0]+1;
03324 }
03325 }
03326 real_instance = local_index * fCumulSizes[codeindex][1];
03327 virt_dim ++;
03328 }
03329 } else {
03330
03331
03332
03333
03334
03335
03336
03337
03338 if (fHasMultipleVarDim[codeindex]) {
03339 info = (TFormLeafInfo *)(fDataMembers.At(codeindex));
03340
03341 }
03342 Int_t local_index;
03343
03344 switch (fIndexes[codeindex][0]) {
03345 case -2:
03346 if (fDidBooleanOptimization && instance!=0) {
03347
03348 fVarIndexes[codeindex][0]->LoadBranches();
03349 }
03350 local_index = (Int_t)fVarIndexes[codeindex][0]->EvalInstance(instance);
03351 if (local_index<0) {
03352 Error("EvalInstance","Index %s is out of bound (%d) in formula %s",
03353 fVarIndexes[codeindex][0]->GetTitle(),
03354 local_index,
03355 GetTitle());
03356 local_index = 0;
03357 }
03358 break;
03359 case -1: {
03360 local_index = 0;
03361 Int_t virt_accum = 0;
03362 Int_t maxloop = fManager->fCumulUsedVarDims->GetSize();
03363 if (maxloop == 0) {
03364 local_index--;
03365 instance = fNdata[0]+1;
03366 if (check) return fNdata[0]+1;
03367 } else {
03368 do {
03369 virt_accum += fManager->fCumulUsedVarDims->GetArray()[local_index];
03370 local_index++;
03371 } while( instance >= virt_accum && local_index<maxloop);
03372 if (local_index==maxloop && (instance >= virt_accum)) {
03373 local_index--;
03374 instance = fNdata[0]+1;
03375 if (check) return fNdata[0]+1;
03376 } else {
03377 local_index--;
03378 if (fManager->fCumulUsedVarDims->At(local_index)) {
03379 instance -= (virt_accum - fManager->fCumulUsedVarDims->At(local_index));
03380 } else {
03381 instance = fNdata[0]+1;
03382 if (check) return fNdata[0]+1;
03383 }
03384 }
03385 }
03386 virt_dim ++;
03387 }
03388 break;
03389 default:
03390 local_index = fIndexes[codeindex][0];
03391 }
03392
03393
03394
03395
03396 if (fManager->fVarDims[kMAXFORMDIM]) {
03397 fManager->fCumulUsedSizes[kMAXFORMDIM] = fManager->fVarDims[kMAXFORMDIM]->At(local_index);
03398 } else {
03399 fManager->fCumulUsedSizes[kMAXFORMDIM] = fManager->fUsedSizes[kMAXFORMDIM];
03400 }
03401 for(Int_t d = kMAXFORMDIM-1; d>0; d--) {
03402 if (fManager->fVarDims[d]) {
03403 fManager->fCumulUsedSizes[d] = fManager->fCumulUsedSizes[d+1] * fManager->fVarDims[d]->At(local_index);
03404 } else {
03405 fManager->fCumulUsedSizes[d] = fManager->fCumulUsedSizes[d+1] * fManager->fUsedSizes[d];
03406 }
03407 }
03408 if (info) {
03409
03410
03411 info->SetPrimaryIndex(local_index);
03412 real_instance = 0;
03413
03414
03415 Int_t vdim = info->GetVarDim();
03416 Int_t isize = info->GetSize(local_index);
03417 if (fIndexes[codeindex][vdim]>=0) {
03418 info->SetSecondaryIndex(fIndexes[codeindex][vdim]);
03419 }
03420 if (isize!=1 && fIndexes[codeindex][vdim]>isize) {
03421
03422 return fNdata[0]+1;
03423 }
03424 fCumulSizes[codeindex][vdim] = isize*fCumulSizes[codeindex][vdim+1];
03425 for(Int_t k=vdim -1; k>0; --k) {
03426 fCumulSizes[codeindex][k] = fCumulSizes[codeindex][k+1]*fFixedSizes[codeindex][k];
03427 }
03428 } else {
03429 real_instance = local_index * fCumulSizes[codeindex][1];
03430 }
03431 }
03432 if (max_dim>0) {
03433 for (Int_t dim = 1; dim < max_dim; dim++) {
03434 if (fIndexes[codeindex][dim]>=0) {
03435 real_instance += fIndexes[codeindex][dim] * fCumulSizes[codeindex][dim+1];
03436 } else {
03437 Int_t local_index;
03438 if (virt_dim && fManager->fCumulUsedSizes[virt_dim]>1) {
03439 local_index = ( ( instance % fManager->fCumulUsedSizes[virt_dim] )
03440 / fManager->fCumulUsedSizes[virt_dim+1]);
03441 } else {
03442 local_index = ( instance / fManager->fCumulUsedSizes[virt_dim+1]);
03443 }
03444 if (fIndexes[codeindex][dim]==-2) {
03445
03446 if (fDidBooleanOptimization && local_index!=0) {
03447
03448 fVarIndexes[codeindex][dim]->LoadBranches();
03449 }
03450 local_index = (Int_t)fVarIndexes[codeindex][dim]->EvalInstance(local_index);
03451 if (local_index<0 ||
03452 local_index>=(fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1])) {
03453 Error("EvalInstance","Index %s is out of bound (%d/%d) in formula %s",
03454 fVarIndexes[codeindex][dim]->GetTitle(),
03455 local_index,
03456 (fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1]),
03457 GetTitle());
03458 local_index = (fCumulSizes[codeindex][dim]/fCumulSizes[codeindex][dim+1])-1;
03459 }
03460 }
03461 real_instance += local_index * fCumulSizes[codeindex][dim+1];
03462 virt_dim ++;
03463 }
03464 }
03465 if (fIndexes[codeindex][max_dim]>=0) {
03466 if (!info) real_instance += fIndexes[codeindex][max_dim];
03467 } else {
03468 Int_t local_index;
03469 if (virt_dim && fManager->fCumulUsedSizes[virt_dim]>1) {
03470 local_index = instance % fManager->fCumulUsedSizes[virt_dim];
03471 } else {
03472 local_index = instance;
03473 }
03474 if (info && local_index>=fCumulSizes[codeindex][max_dim]) {
03475
03476 return fNdata[0]+1;
03477 }
03478 if (fIndexes[codeindex][max_dim]==-2) {
03479 if (fDidBooleanOptimization && local_index!=0) {
03480
03481 fVarIndexes[codeindex][max_dim]->LoadBranches();
03482 }
03483 local_index = (Int_t)fVarIndexes[codeindex][max_dim]->EvalInstance(local_index);
03484 if (local_index<0 ||
03485 local_index>=fCumulSizes[codeindex][max_dim]) {
03486 Error("EvalInstance","Index %s is of out bound (%d/%d) in formula %s",
03487 fVarIndexes[codeindex][max_dim]->GetTitle(),
03488 local_index,
03489 fCumulSizes[codeindex][max_dim],
03490 GetTitle());
03491 local_index = fCumulSizes[codeindex][max_dim]-1;
03492 }
03493 }
03494 real_instance += local_index;
03495 }
03496 }
03497 }
03498
03499 return real_instance;
03500 }
03501
03502
03503 TClass* TTreeFormula::EvalClass() const
03504 {
03505
03506
03507
03508
03509
03510 if (fNoper != 1 || fNcodes <=0 ) return 0;
03511
03512 return EvalClass(0);
03513 }
03514
03515
03516 TClass* TTreeFormula::EvalClass(Int_t oper) const
03517 {
03518
03519
03520
03521
03522
03523 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(oper);
03524 switch(fLookupType[oper]) {
03525 case kDirect: {
03526 if (leaf->IsA()==TLeafObject::Class()) {
03527 return ((TLeafObject*)leaf)->GetClass();
03528 } else if ( leaf->IsA()==TLeafElement::Class()) {
03529 TBranchElement * branch = (TBranchElement*)((TLeafElement*)leaf)->GetBranch();
03530 TStreamerInfo * info = branch->GetInfo();
03531 Int_t id = branch->GetID();
03532 if (id>=0) {
03533 if (info==0 || info->GetElems()==0) {
03534
03535 return 0;
03536 }
03537 TStreamerElement* elem = (TStreamerElement*)info->GetElems()[id];
03538 if (elem==0) {
03539
03540 return 0;
03541 } else {
03542 return TClass::GetClass( elem->GetTypeName() );
03543 }
03544 } else return TClass::GetClass( branch->GetClassName() );
03545 } else {
03546 return 0;
03547 }
03548 }
03549 case kMethod: return 0;
03550 case kTreeMember:
03551 case kDataMember: {
03552 TObject *obj = fDataMembers.UncheckedAt(oper);
03553 if (!obj) return 0;
03554 return ((TFormLeafInfo*)obj)->GetClass();
03555 }
03556
03557 default: return 0;
03558 }
03559
03560
03561 }
03562
03563
03564 void* TTreeFormula::EvalObject(int instance)
03565 {
03566
03567
03568
03569
03570
03571
03572
03573 if (fNoper != 1 || fNcodes <=0 ) return 0;
03574
03575
03576 switch (fLookupType[0]) {
03577 case kIndexOfEntry:
03578 case kIndexOfLocalEntry:
03579 case kEntries:
03580 case kLength:
03581 case kLengthFunc:
03582 case kIteration:
03583 case kEntryList:
03584 return 0;
03585 }
03586
03587 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
03588
03589 Int_t real_instance = GetRealInstance(instance,0);
03590
03591 if (instance==0 || fNeedLoading) {
03592 fNeedLoading = kFALSE;
03593 R__LoadBranch(leaf->GetBranch(),
03594 leaf->GetBranch()->GetTree()->GetReadEntry(),
03595 fQuickLoad);
03596 }
03597 else if (real_instance>fNdata[0]) return 0;
03598 if (fAxis) {
03599 return 0;
03600 }
03601 switch(fLookupType[0]) {
03602 case kDirect: {
03603 if (real_instance) {
03604 Warning("EvalObject","Not yet implement for kDirect and arrays (for %s).\nPlease contact the developers",GetName());
03605 }
03606 return leaf->GetValuePointer();
03607 }
03608 case kMethod: return GetValuePointerFromMethod(0,leaf);
03609 case kTreeMember:
03610 case kDataMember: return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValuePointer(leaf,real_instance);
03611 default: return 0;
03612 }
03613
03614
03615 }
03616
03617
03618
03619 const char* TTreeFormula::EvalStringInstance(Int_t instance)
03620 {
03621
03622
03623 const Int_t kMAXSTRINGFOUND = 10;
03624 const char *stringStack[kMAXSTRINGFOUND];
03625
03626 if (fNoper==1 && fNcodes>0 && IsString()) {
03627 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
03628
03629 Int_t real_instance = GetRealInstance(instance,0);
03630
03631 if (instance==0 || fNeedLoading) {
03632 fNeedLoading = kFALSE;
03633 TBranch *branch = leaf->GetBranch();
03634 R__LoadBranch(branch,branch->GetTree()->GetReadEntry(),fQuickLoad);
03635 } else if (real_instance>=fNdata[0]) {
03636 return 0;
03637 }
03638
03639 if (fLookupType[0]==kDirect) {
03640 return (char*)leaf->GetValuePointer();
03641 } else {
03642 return (char*)GetLeafInfo(0)->GetValuePointer(leaf,real_instance);
03643 }
03644 }
03645
03646 EvalInstance(instance,stringStack);
03647
03648 return stringStack[0];
03649 }
03650
03651 #define TT_EVAL_INIT \
03652 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0); \
03653 \
03654 const Int_t real_instance = GetRealInstance(instance,0); \
03655 \
03656 if (instance==0) fNeedLoading = kTRUE; \
03657 if (real_instance>fNdata[0]) return 0; \
03658 \
03659
03660
03661 \
03662 \
03663 if (fNeedLoading) { \
03664 fNeedLoading = kFALSE; \
03665 TBranch *br = leaf->GetBranch(); \
03666 Long64_t tentry = br->GetTree()->GetReadEntry(); \
03667 R__LoadBranch(br,tentry,fQuickLoad); \
03668 } \
03669 \
03670 if (fAxis) { \
03671 char * label; \
03672
03673 \
03674 if (fLookupType[0]==kDirect) { \
03675 label = (char*)leaf->GetValuePointer(); \
03676 } else { \
03677 label = (char*)GetLeafInfo(0)->GetValuePointer(leaf,instance); \
03678 } \
03679 Int_t bin = fAxis->FindBin(label); \
03680 return bin-0.5; \
03681 }
03682
03683 #define TREE_EVAL_INIT \
03684 const Int_t real_instance = GetRealInstance(instance,0); \
03685 \
03686 if (real_instance>fNdata[0]) return 0; \
03687 \
03688 if (fAxis) { \
03689 char * label; \
03690
03691 \
03692 label = (char*)GetLeafInfo(0)->GetValuePointer((TLeaf*)0x0,instance); \
03693 Int_t bin = fAxis->FindBin(label); \
03694 return bin-0.5; \
03695 }
03696
03697 #define TT_EVAL_INIT_LOOP \
03698 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(code); \
03699 \
03700 \
03701 const Int_t real_instance = GetRealInstance(instance,code); \
03702 \
03703 if (willLoad) { \
03704 TBranch *branch = (TBranch*)fBranches.UncheckedAt(code); \
03705 if (branch) { \
03706 Long64_t treeEntry = branch->GetTree()->GetReadEntry(); \
03707 R__LoadBranch(branch,treeEntry,fQuickLoad); \
03708 } else if (fDidBooleanOptimization) { \
03709 branch = leaf->GetBranch(); \
03710 Long64_t treeEntry = branch->GetTree()->GetReadEntry(); \
03711 if (branch->GetReadEntry() != treeEntry) branch->GetEntry( treeEntry ); \
03712 } \
03713 } else { \
03714
03715
03716 \
03717 if (fDidBooleanOptimization) { \
03718 TBranch *br = leaf->GetBranch(); \
03719 Long64_t treeEntry = br->GetTree()->GetReadEntry(); \
03720 if (br->GetReadEntry() != treeEntry) br->GetEntry( treeEntry ); \
03721 } \
03722 } \
03723 if (real_instance>fNdata[code]) return 0;
03724
03725 #define TREE_EVAL_INIT_LOOP \
03726 \
03727 const Int_t real_instance = GetRealInstance(instance,code); \
03728 \
03729 if (real_instance>fNdata[code]) return 0;
03730
03731 namespace {
03732 Double_t Summing(TTreeFormula *sum) {
03733 Int_t len = sum->GetNdata();
03734 Double_t res = 0;
03735 for (int i=0; i<len; ++i) res += sum->EvalInstance(i);
03736 return res;
03737 }
03738 Double_t FindMin(TTreeFormula *arr) {
03739 Int_t len = arr->GetNdata();
03740 Double_t res = 0;
03741 if (len) {
03742 res = arr->EvalInstance(0);
03743 for (int i=1; i<len; ++i) {
03744 Double_t val = arr->EvalInstance(i);
03745 if (val < res) {
03746 res = val;
03747 }
03748 }
03749 }
03750 return res;
03751 }
03752 Double_t FindMax(TTreeFormula *arr) {
03753 Int_t len = arr->GetNdata();
03754 Double_t res = 0;
03755 if (len) {
03756 res = arr->EvalInstance(0);
03757 for (int i=1; i<len; ++i) {
03758 Double_t val = arr->EvalInstance(i);
03759 if (val > res) {
03760 res = val;
03761 }
03762 }
03763 }
03764 return res;
03765 }
03766 Double_t FindMin(TTreeFormula *arr, TTreeFormula *condition) {
03767 Int_t len = arr->GetNdata();
03768 Double_t res = 0;
03769 if (len) {
03770 int i = 0;
03771 Double_t condval;
03772 do {
03773 condval = condition->EvalInstance(i);
03774 ++i;
03775 } while (!condval && i<len);
03776 if (i==len) {
03777 return 0;
03778 }
03779 if (i!=1) {
03780
03781 arr->EvalInstance(0);
03782 }
03783
03784 res = arr->EvalInstance(i-1);
03785 for (; i<len; ++i) {
03786 condval = condition->EvalInstance(i);
03787 if (condval) {
03788 Double_t val = arr->EvalInstance(i);
03789 if (val < res) {
03790 res = val;
03791 }
03792 }
03793 }
03794 }
03795 return res;
03796 }
03797 Double_t FindMax(TTreeFormula *arr, TTreeFormula *condition) {
03798 Int_t len = arr->GetNdata();
03799 Double_t res = 0;
03800 if (len) {
03801 int i = 0;
03802 Double_t condval;
03803 do {
03804 condval = condition->EvalInstance(i);
03805 ++i;
03806 } while (!condval && i<len);
03807 if (i==len) {
03808 return 0;
03809 }
03810 if (i!=1) {
03811
03812 arr->EvalInstance(0);
03813 }
03814
03815 res = arr->EvalInstance(i-1);
03816 for (; i<len; ++i) {
03817 condval = condition->EvalInstance(i);
03818 if (condval) {
03819 Double_t val = arr->EvalInstance(i);
03820 if (val > res) {
03821 res = val;
03822 }
03823 }
03824 }
03825 }
03826 return res;
03827 }
03828 }
03829
03830
03831 Double_t TTreeFormula::EvalInstance(Int_t instance, const char *stringStackArg[])
03832 {
03833
03834
03835
03836
03837
03838
03839
03840 if (TestBit(kMissingLeaf)) return 0;
03841 if (fNoper == 1 && fNcodes > 0) {
03842
03843 switch (fLookupType[0]) {
03844 case kDirect: {
03845 TT_EVAL_INIT;
03846 Double_t result = leaf->GetValue(real_instance);
03847 return result;
03848 }
03849 case kMethod: {
03850 TT_EVAL_INIT;
03851 ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->SetBranch(leaf->GetBranch());
03852 return GetValueFromMethod(0,leaf);
03853 }
03854 case kDataMember: {
03855 TT_EVAL_INIT;
03856 ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->SetBranch(leaf->GetBranch());
03857 return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValue(leaf,real_instance);
03858 }
03859 case kTreeMember: {
03860 TREE_EVAL_INIT;
03861 return ((TFormLeafInfo*)fDataMembers.UncheckedAt(0))->GetValue((TLeaf*)0x0,real_instance);
03862 }
03863 case kIndexOfEntry: return (Double_t)fTree->GetReadEntry();
03864 case kIndexOfLocalEntry: return (Double_t)fTree->GetTree()->GetReadEntry();
03865 case kEntries: return (Double_t)fTree->GetEntries();
03866 case kLength: return fManager->fNdata;
03867 case kLengthFunc: return ((TTreeFormula*)fAliases.UncheckedAt(0))->GetNdata();
03868 case kIteration: return instance;
03869 case kSum: return Summing((TTreeFormula*)fAliases.UncheckedAt(0));
03870 case kMin: return FindMin((TTreeFormula*)fAliases.UncheckedAt(0));
03871 case kMax: return FindMax((TTreeFormula*)fAliases.UncheckedAt(0));
03872 case kEntryList: {
03873 TEntryList *elist = (TEntryList*)fExternalCuts.At(0);
03874 return elist->Contains(fTree->GetTree()->GetReadEntry());
03875 }
03876 case -1: break;
03877 }
03878 switch (fCodes[0]) {
03879 case -2: {
03880 TCutG *gcut = (TCutG*)fExternalCuts.At(0);
03881 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
03882 TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
03883 Double_t xcut = fx->EvalInstance(instance);
03884 Double_t ycut = fy->EvalInstance(instance);
03885 return gcut->IsInside(xcut,ycut);
03886 }
03887 case -1: {
03888 TCutG *gcut = (TCutG*)fExternalCuts.At(0);
03889 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
03890 return fx->EvalInstance(instance);
03891 }
03892 default: return 0;
03893 }
03894 }
03895
03896 Double_t tab[kMAXFOUND];
03897 const Int_t kMAXSTRINGFOUND = 10;
03898 const char *stringStackLocal[kMAXSTRINGFOUND];
03899 const char **stringStack = stringStackArg?stringStackArg:stringStackLocal;
03900
03901 const bool willLoad = (instance==0 || fNeedLoading); fNeedLoading = kFALSE;
03902 if (willLoad) fDidBooleanOptimization = kFALSE;
03903
03904 Int_t pos = 0;
03905 Int_t pos2 = 0;
03906 for (Int_t i=0; i<fNoper ; ++i) {
03907
03908 const Int_t oper = GetOper()[i];
03909 const Int_t newaction = oper >> kTFOperShift;
03910
03911 if (newaction<kDefinedVariable) {
03912
03913
03914
03915 if (newaction==kConstant) { pos++; tab[pos-1] = fConst[(oper & kTFOperMask)]; continue; }
03916
03917 switch(newaction) {
03918
03919 case kEnd : return tab[0];
03920 case kAdd : pos--; tab[pos-1] += tab[pos]; continue;
03921 case kSubstract : pos--; tab[pos-1] -= tab[pos]; continue;
03922 case kMultiply : pos--; tab[pos-1] *= tab[pos]; continue;
03923 case kDivide : pos--; if (tab[pos] == 0) tab[pos-1] = 0;
03924 else tab[pos-1] /= tab[pos];
03925 continue;
03926 case kModulo : {pos--;
03927 Long64_t int1((Long64_t)tab[pos-1]);
03928 Long64_t int2((Long64_t)tab[pos]);
03929 tab[pos-1] = Double_t(int1%int2);
03930 continue;}
03931
03932 case kcos : tab[pos-1] = TMath::Cos(tab[pos-1]); continue;
03933 case ksin : tab[pos-1] = TMath::Sin(tab[pos-1]); continue;
03934 case ktan : if (TMath::Cos(tab[pos-1]) == 0) {tab[pos-1] = 0;}
03935 else tab[pos-1] = TMath::Tan(tab[pos-1]);
03936 continue;
03937 case kacos : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
03938 else tab[pos-1] = TMath::ACos(tab[pos-1]);
03939 continue;
03940 case kasin : if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
03941 else tab[pos-1] = TMath::ASin(tab[pos-1]);
03942 continue;
03943 case katan : tab[pos-1] = TMath::ATan(tab[pos-1]); continue;
03944 case kcosh : tab[pos-1] = TMath::CosH(tab[pos-1]); continue;
03945 case ksinh : tab[pos-1] = TMath::SinH(tab[pos-1]); continue;
03946 case ktanh : if (TMath::CosH(tab[pos-1]) == 0) {tab[pos-1] = 0;}
03947 else tab[pos-1] = TMath::TanH(tab[pos-1]);
03948 continue;
03949 case kacosh: if (tab[pos-1] < 1) {tab[pos-1] = 0;}
03950 else tab[pos-1] = TMath::ACosH(tab[pos-1]);
03951 continue;
03952 case kasinh: tab[pos-1] = TMath::ASinH(tab[pos-1]); continue;
03953 case katanh: if (TMath::Abs(tab[pos-1]) > 1) {tab[pos-1] = 0;}
03954 else tab[pos-1] = TMath::ATanH(tab[pos-1]); continue;
03955 case katan2: pos--; tab[pos-1] = TMath::ATan2(tab[pos-1],tab[pos]); continue;
03956
03957 case kfmod : pos--; tab[pos-1] = fmod(tab[pos-1],tab[pos]); continue;
03958 case kpow : pos--; tab[pos-1] = TMath::Power(tab[pos-1],tab[pos]); continue;
03959 case ksq : tab[pos-1] = tab[pos-1]*tab[pos-1]; continue;
03960 case ksqrt : tab[pos-1] = TMath::Sqrt(TMath::Abs(tab[pos-1])); continue;
03961
03962 case kstrstr : pos2 -= 2; pos++;if (strstr(stringStack[pos2],stringStack[pos2+1])) tab[pos-1]=1;
03963 else tab[pos-1]=0; continue;
03964
03965 case kmin : pos--; tab[pos-1] = TMath::Min(tab[pos-1],tab[pos]); continue;
03966 case kmax : pos--; tab[pos-1] = TMath::Max(tab[pos-1],tab[pos]); continue;
03967
03968 case klog : if (tab[pos-1] > 0) tab[pos-1] = TMath::Log(tab[pos-1]);
03969 else {tab[pos-1] = 0;}
03970 continue;
03971 case kexp : { Double_t dexp = tab[pos-1];
03972 if (dexp < -700) {tab[pos-1] = 0; continue;}
03973 if (dexp > 700) {tab[pos-1] = TMath::Exp(700); continue;}
03974 tab[pos-1] = TMath::Exp(dexp); continue;
03975 }
03976 case klog10: if (tab[pos-1] > 0) tab[pos-1] = TMath::Log10(tab[pos-1]);
03977 else {tab[pos-1] = 0;}
03978 continue;
03979
03980 case kpi : pos++; tab[pos-1] = TMath::ACos(-1); continue;
03981
03982 case kabs : tab[pos-1] = TMath::Abs(tab[pos-1]); continue;
03983 case ksign : if (tab[pos-1] < 0) tab[pos-1] = -1; else tab[pos-1] = 1; continue;
03984 case kint : tab[pos-1] = Double_t(Int_t(tab[pos-1])); continue;
03985 case kSignInv: tab[pos-1] = -1 * tab[pos-1]; continue;
03986 case krndm : pos++; tab[pos-1] = gRandom->Rndm(1); continue;
03987
03988 case kAnd : pos--; if (tab[pos-1]!=0 && tab[pos]!=0) tab[pos-1]=1;
03989 else tab[pos-1]=0; continue;
03990 case kOr : pos--; if (tab[pos-1]!=0 || tab[pos]!=0) tab[pos-1]=1;
03991 else tab[pos-1]=0; continue;
03992
03993 case kEqual : pos--; tab[pos-1] = (tab[pos-1] == tab[pos]) ? 1 : 0; continue;
03994 case kNotEqual : pos--; tab[pos-1] = (tab[pos-1] != tab[pos]) ? 1 : 0; continue;
03995 case kLess : pos--; tab[pos-1] = (tab[pos-1] < tab[pos]) ? 1 : 0; continue;
03996 case kGreater : pos--; tab[pos-1] = (tab[pos-1] > tab[pos]) ? 1 : 0; continue;
03997 case kLessThan : pos--; tab[pos-1] = (tab[pos-1] <= tab[pos]) ? 1 : 0; continue;
03998 case kGreaterThan: pos--; tab[pos-1] = (tab[pos-1] >= tab[pos]) ? 1 : 0; continue;
03999 case kNot : tab[pos-1] = (tab[pos-1] != 0) ? 0 : 1; continue;
04000
04001 case kStringEqual : pos2 -= 2; pos++; if (!strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
04002 else tab[pos-1]=0; continue;
04003 case kStringNotEqual: pos2 -= 2; pos++;if (strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
04004 else tab[pos-1]=0; continue;
04005
04006 case kBitAnd : pos--; tab[pos-1]= ((Long64_t) tab[pos-1]) & ((Long64_t) tab[pos]); continue;
04007 case kBitOr : pos--; tab[pos-1]= ((Long64_t) tab[pos-1]) | ((Long64_t) tab[pos]); continue;
04008 case kLeftShift : pos--; tab[pos-1]= ((Long64_t) tab[pos-1]) <<((Long64_t) tab[pos]); continue;
04009 case kRightShift: pos--; tab[pos-1]= ((Long64_t) tab[pos-1]) >>((Long64_t) tab[pos]); continue;
04010
04011 case kJump : i = (oper & kTFOperMask); continue;
04012 case kJumpIf : pos--; if (!tab[pos]) i = (oper & kTFOperMask); continue;
04013
04014 case kStringConst: {
04015
04016 pos2++; stringStack[pos2-1] = (char*)fExpr[i].Data();
04017 continue;
04018 }
04019
04020 case kBoolOptimize: {
04021
04022
04023 int param = (oper & kTFOperMask);
04024 Bool_t skip = kFALSE;
04025 int op = param % 10;
04026
04027 if (op == 1 && (!tab[pos-1]) ) {
04028
04029
04030 skip = kTRUE;
04031
04032
04033
04034 tab[pos-1] = 0;
04035
04036 } else if (op == 2 && tab[pos-1] ) {
04037
04038
04039 skip = kTRUE;
04040
04041
04042
04043 tab[pos-1] = 1;
04044 }
04045
04046 if (skip) {
04047 int toskip = param / 10;
04048 i += toskip;
04049 if (willLoad) fDidBooleanOptimization = kTRUE;
04050 }
04051 continue;
04052 }
04053
04054 case kFunctionCall: {
04055
04056
04057 int param = (oper & kTFOperMask);
04058 int fno = param / 1000;
04059 int nargs = param % 1000;
04060
04061
04062 TMethodCall *method = (TMethodCall*)fFunctions.At(fno);
04063
04064
04065 method->ResetParam();
04066 if (nargs) {
04067 UInt_t argloc = pos-nargs;
04068 for(Int_t j=0;j<nargs;j++,argloc++,pos--) {
04069 method->SetParam( tab[argloc] );
04070 }
04071 }
04072 pos++;
04073 Double_t ret;
04074 method->Execute(ret);
04075 tab[pos-1] = ret;
04076
04077 continue;
04078 }
04079
04080
04081 }
04082
04083 } else {
04084
04085
04086
04087
04088 if (newaction == kDefinedVariable) {
04089
04090 const Int_t code = (oper & kTFOperMask);
04091 const Int_t lookupType = fLookupType[code];
04092 switch (lookupType) {
04093 case kIndexOfEntry: tab[pos++] = (Double_t)fTree->GetReadEntry(); continue;
04094 case kIndexOfLocalEntry: tab[pos++] = (Double_t)fTree->GetTree()->GetReadEntry(); continue;
04095 case kEntries: tab[pos++] = (Double_t)fTree->GetEntries(); continue;
04096 case kLength: tab[pos++] = fManager->fNdata; continue;
04097 case kLengthFunc: tab[pos++] = ((TTreeFormula*)fAliases.UncheckedAt(i))->GetNdata(); continue;
04098 case kIteration: tab[pos++] = instance; continue;
04099 case kSum: tab[pos++] = Summing((TTreeFormula*)fAliases.UncheckedAt(i)); continue;
04100 case kMin: tab[pos++] = FindMin((TTreeFormula*)fAliases.UncheckedAt(i)); continue;
04101 case kMax: tab[pos++] = FindMax((TTreeFormula*)fAliases.UncheckedAt(i)); continue;
04102
04103 case kDirect: { TT_EVAL_INIT_LOOP; tab[pos++] = leaf->GetValue(real_instance); continue; }
04104 case kMethod: { TT_EVAL_INIT_LOOP; tab[pos++] = GetValueFromMethod(code,leaf); continue; }
04105 case kDataMember: { TT_EVAL_INIT_LOOP; tab[pos++] = ((TFormLeafInfo*)fDataMembers.UncheckedAt(code))->
04106 GetValue(leaf,real_instance); continue; }
04107 case kTreeMember: { TREE_EVAL_INIT_LOOP; tab[pos++] = ((TFormLeafInfo*)fDataMembers.UncheckedAt(code))->
04108 GetValue((TLeaf*)0x0,real_instance); continue; }
04109 case kEntryList: { TEntryList *elist = (TEntryList*)fExternalCuts.At(code);
04110 tab[pos++] = elist->Contains(fTree->GetReadEntry());
04111 continue;}
04112 case -1: break;
04113 default: tab[pos++] = 0; continue;
04114 }
04115 switch (fCodes[code]) {
04116 case -2: {
04117 TCutG *gcut = (TCutG*)fExternalCuts.At(code);
04118 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
04119 TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
04120 Double_t xcut = fx->EvalInstance(instance);
04121 Double_t ycut = fy->EvalInstance(instance);
04122 tab[pos++] = gcut->IsInside(xcut,ycut);
04123 continue;
04124 }
04125 case -1: {
04126 TCutG *gcut = (TCutG*)fExternalCuts.At(code);
04127 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
04128 tab[pos++] = fx->EvalInstance(instance);
04129 continue;
04130 }
04131 default: {
04132 tab[pos++] = 0;
04133 continue;
04134 }
04135 }
04136 }
04137 switch(newaction) {
04138
04139
04140 case kAlias: {
04141 int aliasN = i;
04142 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(aliasN));
04143 R__ASSERT(subform);
04144
04145 Double_t param = subform->EvalInstance(instance);
04146
04147 tab[pos] = param; pos++;
04148 continue;
04149 }
04150
04151 case kAliasString: {
04152 int aliasN = i;
04153 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(aliasN));
04154 R__ASSERT(subform);
04155
04156 pos2++;
04157 stringStack[pos2-1] = subform->EvalStringInstance(instance);
04158 continue;
04159 }
04160 case kMinIf: {
04161 int alternateN = i;
04162 TTreeFormula *primary = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
04163 TTreeFormula *condition = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN+1));
04164 Double_t param = FindMin(primary,condition);
04165 ++i;
04166 tab[pos] = param; pos++;
04167 continue;
04168 }
04169 case kMaxIf: {
04170 int alternateN = i;
04171 TTreeFormula *primary = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
04172 TTreeFormula *condition = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN+1));
04173 Double_t param = FindMax(primary,condition);
04174 ++i;
04175 tab[pos] = param; pos++;
04176 continue;
04177 }
04178
04179
04180 case kAlternate: {
04181 int alternateN = i;
04182 TTreeFormula *primary = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
04183
04184
04185 if (instance < primary->GetNdata()) {
04186
04187 Double_t param = primary->EvalInstance(instance);
04188
04189 ++i;
04190
04191 tab[pos] = param; pos++;
04192 } else {
04193
04194
04195
04196
04197 }
04198 continue;
04199 }
04200 case kAlternateString: {
04201 int alternateN = i;
04202 TTreeFormula *primary = static_cast<TTreeFormula*>(fAliases.UncheckedAt(alternateN));
04203
04204
04205 if (instance < primary->GetNdata()) {
04206
04207 pos2++;
04208 stringStack[pos2-1] = primary->EvalStringInstance(instance);
04209
04210 ++i;
04211
04212 } else {
04213
04214
04215
04216
04217 }
04218 continue;
04219 }
04220
04221
04222 case kDefinedString: {
04223 Int_t string_code = (oper & kTFOperMask);
04224 TLeaf *leafc = (TLeaf*)fLeaves.UncheckedAt(string_code);
04225
04226
04227 const Int_t real_instance = GetRealInstance(instance,string_code);
04228
04229 if (instance==0 || fNeedLoading) {
04230 fNeedLoading = kFALSE;
04231 TBranch *branch = leafc->GetBranch();
04232 Long64_t readentry = branch->GetTree()->GetReadEntry();
04233 R__LoadBranch(branch,readentry,fQuickLoad);
04234 } else {
04235
04236
04237
04238 if (fDidBooleanOptimization) {
04239 TBranch *br = leafc->GetBranch();
04240 Long64_t treeEntry = br->GetTree()->GetReadEntry();
04241 R__LoadBranch(br,treeEntry,kTRUE);
04242 }
04243 if (real_instance>fNdata[string_code]) return 0;
04244 }
04245 pos2++;
04246 if (fLookupType[string_code]==kDirect) {
04247 stringStack[pos2-1] = (char*)leafc->GetValuePointer();
04248 } else {
04249 stringStack[pos2-1] = (char*)GetLeafInfo(string_code)->GetValuePointer(leafc,real_instance);
04250 }
04251 continue;
04252 }
04253
04254 }
04255 }
04256
04257 R__ASSERT(i<fNoper);
04258 }
04259
04260 Double_t result = tab[0];
04261 return result;
04262 }
04263
04264
04265 TFormLeafInfo *TTreeFormula::GetLeafInfo(Int_t code) const
04266 {
04267
04268
04269
04270
04271
04272
04273 return (TFormLeafInfo *)fDataMembers.UncheckedAt(code);
04274
04275 }
04276
04277
04278 TLeaf *TTreeFormula::GetLeaf(Int_t n) const
04279 {
04280
04281
04282
04283
04284 return (TLeaf*)fLeaves.UncheckedAt(n);
04285 }
04286
04287
04288 TMethodCall *TTreeFormula::GetMethodCall(Int_t code) const
04289 {
04290
04291
04292
04293
04294
04295
04296 return (TMethodCall *)fMethods.UncheckedAt(code);
04297
04298 }
04299
04300
04301 Int_t TTreeFormula::GetNdata()
04302 {
04303
04304
04305
04306
04307 return fManager->GetNdata();
04308 }
04309
04310
04311 Double_t TTreeFormula::GetValueFromMethod(Int_t i, TLeaf* leaf) const
04312 {
04313
04314
04315 TMethodCall* m = GetMethodCall(i);
04316
04317 if (!m) {
04318 return 0.0;
04319 }
04320
04321 void* thisobj = 0;
04322 if (leaf->InheritsFrom(TLeafObject::Class())) {
04323 thisobj = ((TLeafObject*) leaf)->GetObject();
04324 } else {
04325 TBranchElement* branch = (TBranchElement*) ((TLeafElement*) leaf)->GetBranch();
04326 Int_t id = branch->GetID();
04327
04328 Int_t offset = 0;
04329 if (id > -1) {
04330 TStreamerInfo* info = branch->GetInfo();
04331 if (info) {
04332 offset = info->GetOffsets()[id];
04333 } else {
04334 Warning("GetValueFromMethod", "No streamer info for branch %s.", branch->GetName());
04335 }
04336 }
04337 if (id < 0) {
04338 char* address = branch->GetObject();
04339 thisobj = address;
04340 } else {
04341
04342 char* address = branch->GetObject();
04343 if (address) {
04344 thisobj = *((char**) (address + offset));
04345 } else {
04346
04347 thisobj = branch->GetObject();
04348 }
04349 }
04350 }
04351
04352 TMethodCall::EReturnType r = m->ReturnType();
04353
04354 if (r == TMethodCall::kLong) {
04355 Long_t l;
04356 m->Execute(thisobj, l);
04357 return (Double_t) l;
04358 }
04359
04360 if (r == TMethodCall::kDouble) {
04361 Double_t d;
04362 m->Execute(thisobj, d);
04363 return d;
04364 }
04365
04366 m->Execute(thisobj);
04367
04368 return 0;
04369 }
04370
04371
04372 void* TTreeFormula::GetValuePointerFromMethod(Int_t i, TLeaf* leaf) const
04373 {
04374
04375
04376 TMethodCall* m = GetMethodCall(i);
04377
04378 if (!m) {
04379 return 0;
04380 }
04381
04382 void* thisobj;
04383 if (leaf->InheritsFrom(TLeafObject::Class())) {
04384 thisobj = ((TLeafObject*) leaf)->GetObject();
04385 } else {
04386 TBranchElement* branch = (TBranchElement*) ((TLeafElement*) leaf)->GetBranch();
04387 Int_t id = branch->GetID();
04388 Int_t offset = 0;
04389 if (id > -1) {
04390 TStreamerInfo* info = branch->GetInfo();
04391 if (info) {
04392 offset = info->GetOffsets()[id];
04393 } else {
04394 Warning("GetValuePointerFromMethod", "No streamer info for branch %s.", branch->GetName());
04395 }
04396 }
04397 if (id < 0) {
04398 char* address = branch->GetObject();
04399 thisobj = address;
04400 } else {
04401
04402 char* address = branch->GetObject();
04403 if (address) {
04404 thisobj = *((char**) (address + offset));
04405 } else {
04406
04407 thisobj = branch->GetObject();
04408 }
04409 }
04410 }
04411
04412 TMethodCall::EReturnType r = m->ReturnType();
04413
04414 if (r == TMethodCall::kLong) {
04415 Long_t l;
04416 m->Execute(thisobj, l);
04417 return 0;
04418 }
04419
04420 if (r == TMethodCall::kDouble) {
04421 Double_t d;
04422 m->Execute(thisobj, d);
04423 return 0;
04424 }
04425
04426 if (r == TMethodCall::kOther) {
04427 char* c;
04428 m->Execute(thisobj, &c);
04429 return c;
04430 }
04431
04432 m->Execute(thisobj);
04433
04434 return 0;
04435 }
04436
04437
04438 Bool_t TTreeFormula::IsInteger(Bool_t fast) const
04439 {
04440
04441
04442
04443
04444
04445 if (fast) {
04446 if (TestBit(kIsInteger)) return kTRUE;
04447 else return kFALSE;
04448 }
04449
04450 if (fNoper==2 && GetAction(0)==kAlternate) {
04451 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
04452 R__ASSERT(subform);
04453 return subform->IsInteger(kFALSE);
04454 }
04455
04456 if (GetAction(0)==kMinIf || GetAction(0)==kMaxIf) {
04457 return kFALSE;
04458 }
04459
04460 if (fNoper > 1) return kFALSE;
04461
04462 if (GetAction(0)==kAlias) {
04463 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
04464 R__ASSERT(subform);
04465 return subform->IsInteger(kFALSE);
04466 }
04467
04468 if (fLeaves.GetEntries() != 1) {
04469 switch (fLookupType[0]) {
04470 case kIndexOfEntry:
04471 case kIndexOfLocalEntry:
04472 case kEntries:
04473 case kLength:
04474 case kLengthFunc:
04475 case kIteration:
04476 return kTRUE;
04477 case kSum:
04478 case kMin:
04479 case kMax:
04480 case kEntryList:
04481 default:
04482 return kFALSE;
04483 }
04484 }
04485
04486 if (EvalClass()==TBits::Class()) return kTRUE;
04487
04488 if (IsLeafInteger(0) || IsLeafString(0)) return kTRUE;
04489 return kFALSE;
04490 }
04491
04492
04493 Bool_t TTreeFormula::IsLeafInteger(Int_t code) const
04494 {
04495
04496
04497
04498
04499 TLeaf *leaf = (TLeaf*)fLeaves.At(code);
04500 if (!leaf) {
04501 switch (fLookupType[code]) {
04502 case kIndexOfEntry:
04503 case kIndexOfLocalEntry:
04504 case kEntries:
04505 case kLength:
04506 case kLengthFunc:
04507 case kIteration:
04508 return kTRUE;
04509 case kSum:
04510 case kMin:
04511 case kMax:
04512 case kEntryList:
04513 default:
04514 return kFALSE;
04515 }
04516 }
04517 if (fAxis) return kTRUE;
04518 TFormLeafInfo * info;
04519 switch (fLookupType[code]) {
04520 case kMethod:
04521 case kTreeMember:
04522 case kDataMember:
04523 info = GetLeafInfo(code);
04524 return info->IsInteger();
04525 case kDirect:
04526 break;
04527 }
04528 if (!strcmp(leaf->GetTypeName(),"Int_t")) return kTRUE;
04529 if (!strcmp(leaf->GetTypeName(),"Short_t")) return kTRUE;
04530 if (!strcmp(leaf->GetTypeName(),"UInt_t")) return kTRUE;
04531 if (!strcmp(leaf->GetTypeName(),"UShort_t")) return kTRUE;
04532 if (!strcmp(leaf->GetTypeName(),"Bool_t")) return kTRUE;
04533 if (!strcmp(leaf->GetTypeName(),"Char_t")) return kTRUE;
04534 if (!strcmp(leaf->GetTypeName(),"UChar_t")) return kTRUE;
04535 if (!strcmp(leaf->GetTypeName(),"string")) return kTRUE;
04536 return kFALSE;
04537 }
04538
04539
04540 Bool_t TTreeFormula::IsString() const
04541 {
04542
04543
04544 return TestBit(kIsCharacter) || (fNoper==1 && IsString(0));
04545 }
04546
04547
04548 Bool_t TTreeFormula::IsString(Int_t oper) const
04549 {
04550
04551
04552
04553
04554
04555 if (TFormula::IsString(oper)) return kTRUE;
04556 if (GetAction(oper)==kDefinedString) return kTRUE;
04557 if (GetAction(oper)==kAliasString) return kTRUE;
04558 if (GetAction(oper)==kAlternateString) return kTRUE;
04559 return kFALSE;
04560 }
04561
04562
04563 Bool_t TTreeFormula::IsLeafString(Int_t code) const
04564 {
04565
04566 TLeaf *leaf = (TLeaf*)fLeaves.At(code);
04567 TFormLeafInfo * info;
04568 if (fLookupType[code]==kTreeMember) {
04569 info = GetLeafInfo(code);
04570 return info->IsString();
04571 }
04572
04573 switch(fLookupType[code]) {
04574 case kDirect:
04575 if ( !leaf->IsUnsigned() && (leaf->InheritsFrom(TLeafC::Class()) || leaf->InheritsFrom(TLeafB::Class()) ) ) {
04576
04577 if (leaf->GetLenStatic() > 1) return kTRUE;
04578
04579
04580
04581 if (leaf->GetLeafCount()) {
04582 const char* indexname = leaf->GetLeafCount()->GetName();
04583 if (indexname[strlen(indexname)-1] == '_' ) {
04584
04585 return kFALSE;
04586 } else {
04587
04588 return kTRUE;
04589 }
04590 }
04591 return kFALSE;
04592 } else if (leaf->InheritsFrom(TLeafElement::Class())) {
04593 TBranchElement * br = (TBranchElement*)leaf->GetBranch();
04594 Int_t bid = br->GetID();
04595 if (bid < 0) return kFALSE;
04596 if (br->GetInfo()==0 || br->GetInfo()->GetElems()==0) {
04597
04598
04599
04600 return kFALSE;
04601 }
04602 TStreamerElement * elem = (TStreamerElement*) br->GetInfo()->GetElems()[bid];
04603 if (!elem) {
04604
04605
04606
04607 return kFALSE;
04608 }
04609 if (elem->GetNewType()== TStreamerInfo::kOffsetL +kChar_t) {
04610
04611 if (fIndexes[code][fNdimensions[code]-1] != -1) return kFALSE;
04612 return kTRUE;
04613 }
04614 if ( elem->GetNewType()== TStreamerInfo::kCharStar) {
04615
04616 if (fNdimensions[code] && fIndexes[code][fNdimensions[code]-1] != -1) return kFALSE;
04617 return kTRUE;
04618 }
04619 return kFALSE;
04620 } else {
04621 return kFALSE;
04622 }
04623 case kMethod:
04624
04625
04626 return kFALSE;
04627 case kDataMember:
04628 info = GetLeafInfo(code);
04629 return info->IsString();
04630 default:
04631 return kFALSE;
04632 }
04633 }
04634
04635
04636 char *TTreeFormula::PrintValue(Int_t mode) const
04637 {
04638
04639
04640
04641
04642
04643
04644 return PrintValue(mode,0);
04645 }
04646
04647
04648 char *TTreeFormula::PrintValue(Int_t mode, Int_t instance, const char *decform) const
04649 {
04650
04651
04652
04653
04654
04655
04656
04657
04658 const int kMAXLENGTH = 1024;
04659 static char value[kMAXLENGTH];
04660
04661 if (mode == -2) {
04662 for (int i = 0; i < kMAXLENGTH-1; i++)
04663 value[i] = '*';
04664 value[kMAXLENGTH-1] = 0;
04665 } else if (mode == -1) {
04666 snprintf(value, kMAXLENGTH-1, "%s", GetTitle());
04667 } else if (mode == 0) {
04668 if ( (fNstring && fNval==0 && fNoper==1) ||
04669 (TestBit(kIsCharacter)) )
04670 {
04671 const char * val = 0;
04672 if (instance<fNdata[0]) {
04673 if (fLookupType[0]==kTreeMember) {
04674 val = (char*)GetLeafInfo(0)->GetValuePointer((TLeaf*)0x0,instance);
04675 } else {
04676 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0);
04677 TBranch *branch = leaf->GetBranch();
04678 Long64_t readentry = branch->GetTree()->GetReadEntry();
04679 R__LoadBranch(branch,readentry,fQuickLoad);
04680 if (fLookupType[0]==kDirect && fNoper==1) {
04681 val = (const char*)leaf->GetValuePointer();
04682 } else {
04683 val = ((TTreeFormula*)this)->EvalStringInstance(instance);
04684 }
04685 }
04686 }
04687 if (val) {
04688 strlcpy(value, val, kMAXLENGTH);
04689 } else {
04690 value[0] = '\0';
04691 }
04692 value[kMAXLENGTH-1] = 0;
04693 } else {
04694
04695
04696 Int_t real_instance = ((TTreeFormula*)this)->GetRealInstance(instance,-1);
04697 if (real_instance<fNdata[0]) {
04698 Ssiz_t len = strlen(decform);
04699 Char_t outputSizeLevel = 1;
04700 char *expo = 0;
04701 if (len>2) {
04702 switch (decform[len-2]) {
04703 case 'l':
04704 case 'L': {
04705 outputSizeLevel = 2;
04706 if (len>3 && tolower(decform[len-3])=='l') {
04707 outputSizeLevel = 3;
04708 }
04709 break;
04710 }
04711 case 'h': outputSizeLevel = 0; break;
04712 }
04713 }
04714 switch(decform[len-1]) {
04715 case 'c':
04716 case 'd':
04717 case 'i':
04718 {
04719 switch (outputSizeLevel) {
04720 case 0: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(Short_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04721 case 2: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(Long_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04722 case 3: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(Long64_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04723 case 1:
04724 default: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(Int_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04725 }
04726 break;
04727 }
04728 case 'o':
04729 case 'x':
04730 case 'X':
04731 case 'u':
04732 {
04733 switch (outputSizeLevel) {
04734 case 0: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(UShort_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04735 case 2: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(ULong_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04736 case 3: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(ULong64_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04737 case 1:
04738 default: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(UInt_t)((TTreeFormula*)this)->EvalInstance(instance)); break;
04739 }
04740 break;
04741 }
04742 case 'f':
04743 case 'e':
04744 case 'E':
04745 case 'g':
04746 case 'G':
04747 {
04748 switch (outputSizeLevel) {
04749 case 2: snprintf(value,kMAXLENGTH,Form("%%%s",decform),(long double)((TTreeFormula*)this)->EvalInstance(instance)); break;
04750 case 1:
04751 default: snprintf(value,kMAXLENGTH,Form("%%%s",decform),((TTreeFormula*)this)->EvalInstance(instance)); break;
04752 }
04753 expo = strchr(value,'e');
04754 break;
04755 }
04756 default:
04757 snprintf(value,kMAXLENGTH,Form("%%%sg",decform),((TTreeFormula*)this)->EvalInstance(instance));
04758 expo = strchr(value,'e');
04759 }
04760 if (expo) {
04761
04762
04763 UInt_t declen = atoi(decform);
04764 if (strlen(value)>declen) {
04765 UInt_t off = strlen(value)-declen;
04766 char *start = expo - off;
04767 UInt_t vlen = strlen(expo);
04768 for(UInt_t z=0;z<=vlen;++z) {
04769 start[z] = expo[z];
04770 }
04771
04772 }
04773 }
04774 } else {
04775 if (isalpha(decform[strlen(decform)-1])) {
04776 TString short_decform(decform);
04777 short_decform.Remove(short_decform.Length()-1);
04778 snprintf(value,kMAXLENGTH,Form(" %%%sc",short_decform.Data()),' ');
04779 } else {
04780 snprintf(value,kMAXLENGTH,Form(" %%%sc",decform),' ');
04781 }
04782
04783 }
04784 }
04785 }
04786 return &value[0];
04787 }
04788
04789
04790 void TTreeFormula::ResetLoading()
04791 {
04792
04793
04794 fNeedLoading = kTRUE;
04795 fDidBooleanOptimization = kFALSE;
04796
04797 for(Int_t i=0; i<fNcodes; ++i) {
04798 UInt_t max_dim = fNdimensions[i];
04799 for(UInt_t dim=0; dim<max_dim ;++dim) {
04800 if (fVarIndexes[i][dim]) {
04801 fVarIndexes[i][dim]->ResetLoading();
04802 }
04803 }
04804 }
04805 Int_t n = fAliases.GetLast();
04806 if ( fNoper < n ) {
04807 n = fNoper;
04808 }
04809 for(Int_t k=0; k <= n; ++k) {
04810 TTreeFormula *f = static_cast<TTreeFormula*>(fAliases.UncheckedAt(k));
04811 if (f) {
04812 f->ResetLoading();
04813 }
04814 }
04815 }
04816
04817
04818 void TTreeFormula::SetAxis(TAxis *axis)
04819 {
04820
04821
04822 if (!axis) {fAxis = 0; return;}
04823 if (TestBit(kIsCharacter)) {
04824 fAxis = axis;
04825 if (fNoper==1 && GetAction(0)==kAliasString){
04826 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
04827 R__ASSERT(subform);
04828 subform->SetAxis(axis);
04829 } else if (fNoper==2 && GetAction(0)==kAlternateString){
04830 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(0));
04831 R__ASSERT(subform);
04832 subform->SetAxis(axis);
04833 }
04834 }
04835 if (IsInteger()) axis->SetBit(TAxis::kIsInteger);
04836 }
04837
04838
04839 void TTreeFormula::Streamer(TBuffer &R__b)
04840 {
04841
04842
04843 if (R__b.IsReading()) {
04844 UInt_t R__s, R__c;
04845 Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
04846 if (R__v > 2) {
04847 R__b.ReadClassBuffer(TTreeFormula::Class(), this, R__v, R__s, R__c);
04848 return;
04849 }
04850
04851 TFormula::Streamer(R__b);
04852 R__b >> fTree;
04853 R__b >> fNcodes;
04854 R__b.ReadFastArray(fCodes, fNcodes);
04855 R__b >> fMultiplicity;
04856 Int_t instance;
04857 R__b >> instance;
04858 R__b >> fNindex;
04859 if (fNindex) {
04860 fLookupType = new Int_t[fNindex];
04861 R__b.ReadFastArray(fLookupType, fNindex);
04862 }
04863 fMethods.Streamer(R__b);
04864
04865
04866 } else {
04867 R__b.WriteClassBuffer(TTreeFormula::Class(),this);
04868 }
04869 }
04870
04871
04872 Bool_t TTreeFormula::StringToNumber(Int_t oper)
04873 {
04874
04875
04876
04877 Int_t code = GetActionParam(oper);
04878 if (GetAction(oper)==kDefinedString && fLookupType[code]==kDirect) {
04879 if (oper>0 && GetAction(oper-1)==kJump) {
04880
04881 return kFALSE;
04882 }
04883 TLeaf *leaf = (TLeaf*)fLeaves.At(code);
04884 if (leaf && (leaf->InheritsFrom(TLeafC::Class()) || leaf->InheritsFrom(TLeafB::Class()) ) ) {
04885 SetAction(oper, kDefinedVariable, code );
04886 fNval++;
04887 fNstring--;
04888 return kTRUE;
04889 }
04890 }
04891 return kFALSE;
04892 }
04893
04894
04895
04896 void TTreeFormula::UpdateFormulaLeaves()
04897 {
04898
04899
04900
04901
04902
04903
04904
04905
04906 TString names(kMaxLen);
04907 Int_t nleaves = fLeafNames.GetEntriesFast();
04908 ResetBit( kMissingLeaf );
04909 for (Int_t i=0;i<nleaves;i++) {
04910 if (!fTree) break;
04911 if (!fLeafNames[i]) continue;
04912 names.Form("%s/%s",fLeafNames[i]->GetTitle(),fLeafNames[i]->GetName());
04913 TLeaf *leaf = fTree->GetLeaf(names);
04914 fLeaves[i] = leaf;
04915 if (fBranches[i] && leaf) {
04916 fBranches[i]=leaf->GetBranch();
04917
04918
04919
04920
04921
04922 ((TBranch*)fBranches[i])->ResetReadEntry();
04923 }
04924 if (leaf==0) SetBit( kMissingLeaf );
04925 }
04926 for (Int_t j=0; j<kMAXCODES; j++) {
04927 for (Int_t k = 0; k<kMAXFORMDIM; k++) {
04928 if (fVarIndexes[j][k]) {
04929 fVarIndexes[j][k]->UpdateFormulaLeaves();
04930 }
04931 }
04932 if (fLookupType[j]==kDataMember || fLookupType[j]==kTreeMember) GetLeafInfo(j)->Update();
04933 if (j<fNval && fCodes[j]<0) {
04934 TCutG *gcut = (TCutG*)fExternalCuts.At(j);
04935 if (gcut) {
04936 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
04937 TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
04938 if (fx) fx->UpdateFormulaLeaves();
04939 if (fy) fy->UpdateFormulaLeaves();
04940 }
04941 }
04942 }
04943 for(Int_t k=0;k<fNoper;k++) {
04944 const Int_t oper = GetOper()[k];
04945 switch(oper >> kTFOperShift) {
04946 case kAlias:
04947 case kAliasString:
04948 case kAlternate:
04949 case kAlternateString:
04950 case kMinIf:
04951 case kMaxIf:
04952 {
04953 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(k));
04954 R__ASSERT(subform);
04955 subform->UpdateFormulaLeaves();
04956 break;
04957 }
04958 case kDefinedVariable:
04959 {
04960 Int_t code = GetActionParam(k);
04961 if (fCodes[code]==0) switch(fLookupType[code]) {
04962 case kLengthFunc:
04963 case kSum:
04964 case kMin:
04965 case kMax:
04966 {
04967 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(k));
04968 R__ASSERT(subform);
04969 subform->UpdateFormulaLeaves();
04970 break;
04971 }
04972 default:
04973 break;
04974 }
04975 }
04976 default:
04977 break;
04978 }
04979 }
04980 }
04981
04982
04983 void TTreeFormula::ResetDimensions() {
04984
04985
04986 Int_t i,k;
04987
04988
04989
04990
04991 TIter next(fDimensionSetup);
04992 Int_t last_code = -1;
04993 Int_t virt_dim = 0;
04994 for(TDimensionInfo * info; (info = (TDimensionInfo*)next()); ) {
04995 if (last_code!=info->fCode) {
04996
04997
04998
04999 virt_dim = 0;
05000 last_code = info->fCode;
05001 fNdimensions[last_code] = 0;
05002 }
05003
05004 if (GetAction(info->fOper)==kDefinedString) {
05005
05006
05007
05008 TDimensionInfo *nextinfo = (TDimensionInfo*)next();
05009 while(nextinfo && nextinfo->fCode==info->fCode) {
05010 DefineDimensions(info->fCode,info->fSize, info->fMultiDim, virt_dim);
05011 nextinfo = (TDimensionInfo*)next();
05012 }
05013 if (!nextinfo) break;
05014
05015 info = nextinfo;
05016 virt_dim = 0;
05017 last_code = info->fCode;
05018 fNdimensions[last_code] = 0;
05019
05020 info->fSize = 1;
05021 }
05022
05023
05024 DefineDimensions(info->fCode,info->fSize, info->fMultiDim, virt_dim);
05025 }
05026
05027 fMultiplicity = 0;
05028 for(i=0;i<fNoper;i++) {
05029 Int_t action = GetAction(i);
05030
05031 if (action==kMinIf || action==kMaxIf) {
05032
05033 ++i;
05034 continue;
05035 }
05036 if (action==kAlias || action==kAliasString) {
05037 TTreeFormula *subform = static_cast<TTreeFormula*>(fAliases.UncheckedAt(i));
05038 R__ASSERT(subform);
05039 switch(subform->GetMultiplicity()) {
05040 case 0: break;
05041 case 1: fMultiplicity = 1; break;
05042 case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
05043 }
05044 fManager->Add(subform);
05045
05046
05047 continue;
05048 }
05049 if (action==kDefinedString) {
05050
05051
05052
05053
05054
05055
05056
05057
05058
05059
05060
05061
05062
05063 }
05064 }
05065
05066 for (i=0;i<fNcodes;i++) {
05067 if (fCodes[i] < 0) {
05068 TCutG *gcut = (TCutG*)fExternalCuts.At(i);
05069 if (!gcut) continue;
05070 TTreeFormula *fx = (TTreeFormula *)gcut->GetObjectX();
05071 TTreeFormula *fy = (TTreeFormula *)gcut->GetObjectY();
05072
05073 if (fx) {
05074 switch(fx->GetMultiplicity()) {
05075 case 0: break;
05076 case 1: fMultiplicity = 1; break;
05077 case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
05078 }
05079 fManager->Add(fx);
05080 }
05081 if (fy) {
05082 switch(fy->GetMultiplicity()) {
05083 case 0: break;
05084 case 1: fMultiplicity = 1; break;
05085 case 2: if (fMultiplicity!=1) fMultiplicity = 2; break;
05086 }
05087 fManager->Add(fy);
05088 }
05089
05090 continue;
05091 }
05092
05093 if (fLookupType[i]==kIteration) {
05094 fMultiplicity = 1;
05095 continue;
05096 }
05097
05098 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
05099 if (!leaf) continue;
05100
05101
05102
05103
05104
05105
05106
05107
05108 if (leaf->GetLeafCount()) {
05109
05110 fMultiplicity = 1;
05111 } else if (fLookupType[i]==kDataMember) {
05112 TFormLeafInfo * leafinfo = GetLeafInfo(i);
05113 TStreamerElement * elem = leafinfo->fElement;
05114 if (fMultiplicity!=1) {
05115 if (leafinfo->HasCounter() ) fMultiplicity = 1;
05116 else if (elem && elem->GetArrayDim()>0) fMultiplicity = 2;
05117 else if (leaf->GetLenStatic()>1) fMultiplicity = 2;
05118 }
05119 } else {
05120 if (leaf->GetLenStatic()>1 && fMultiplicity!=1) fMultiplicity = 2;
05121 }
05122 if (fMultiplicity!=1) {
05123
05124
05125
05126 TTree *realtree = fTree ? fTree->GetTree() : 0;
05127 TTree *tleaf = leaf->GetBranch()->GetTree();
05128 if (tleaf && tleaf != realtree && tleaf->GetTreeIndex()) {
05129
05130 fMultiplicity = 1;
05131 }
05132 }
05133
05134 Int_t virt_dim2 = 0;
05135 for (k = 0; k < fNdimensions[i]; k++) {
05136
05137
05138 if ( (fCumulSizes[i][k]>=0) && (fIndexes[i][k] >= fCumulSizes[i][k]) ) {
05139
05140 fManager->CancelDimension(virt_dim2);
05141 }
05142 if ( fIndexes[i][k] < 0 ) virt_dim2++;
05143 fFixedSizes[i][k] = fCumulSizes[i][k];
05144 }
05145
05146
05147 for (k = fNdimensions[i]; (k > 0); k--) {
05148
05149
05150
05151 fCumulSizes[i][k-1] *= TMath::Abs(fCumulSizes[i][k]);
05152 }
05153
05154
05155 if (fCumulSizes[i][0]>0) fNdata[i] = fCumulSizes[i][0];
05156
05157
05158
05159
05160
05161 }
05162 }
05163
05164
05165 void TTreeFormula::LoadBranches()
05166 {
05167
05168
05169 Int_t i;
05170 for (i=0; i<fNoper ; ++i) {
05171 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
05172 if (leaf==0) continue;
05173
05174 TBranch *br = leaf->GetBranch();
05175 Long64_t treeEntry = br->GetTree()->GetReadEntry();
05176 R__LoadBranch(br,treeEntry,kTRUE);
05177
05178 TTreeFormula *alias = (TTreeFormula*)fAliases.UncheckedAt(i);
05179 if (alias) alias->LoadBranches();
05180
05181 Int_t max_dim = fNdimensions[i];
05182 for (Int_t dim = 0; dim < max_dim; ++dim) {
05183 if (fVarIndexes[i][dim]) fVarIndexes[i][dim]->LoadBranches();
05184 }
05185 }
05186 }
05187
05188
05189 Bool_t TTreeFormula::LoadCurrentDim() {
05190
05191
05192
05193 Int_t size;
05194 Bool_t outofbounds = kFALSE;
05195
05196 for (Int_t i=0;i<fNcodes;i++) {
05197 if (fCodes[i] < 0) continue;
05198
05199
05200
05201
05202
05203
05204
05205
05206
05207
05208
05209
05210 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(i);
05211 if (!leaf) {
05212 switch(fLookupType[i]) {
05213 case kDirect:
05214 case kMethod:
05215 case kTreeMember:
05216 case kDataMember:
05217 fNdata[i] = 0;
05218 outofbounds = kTRUE;
05219 }
05220 continue;
05221 }
05222
05223 TTree *realtree = fTree->GetTree();
05224 TTree *tleaf = leaf->GetBranch()->GetTree();
05225 if (tleaf && tleaf != realtree && tleaf->GetTreeIndex()) {
05226 if (tleaf->GetReadEntry()==-1) {
05227 fNdata[i] = 0;
05228 outofbounds = kTRUE;
05229 continue;
05230 } else {
05231 fNdata[i] = fCumulSizes[i][0];
05232 }
05233 }
05234 Bool_t hasBranchCount2 = kFALSE;
05235 if (leaf->GetLeafCount()) {
05236 TLeaf* leafcount = leaf->GetLeafCount();
05237 TBranch *branchcount = leafcount->GetBranch();
05238 TFormLeafInfo * info = 0;
05239 if (leaf->IsA() == TLeafElement::Class()) {
05240
05241
05242 Long64_t readentry = leaf->GetBranch()->GetTree()->GetReadEntry();
05243 if (readentry==-1) readentry=0;
05244 if (!branchcount->GetAddress()) {
05245 R__LoadBranch(branchcount, readentry, fQuickLoad);
05246 } else {
05247
05248
05249
05250 branchcount->TBranch::GetEntry(readentry);
05251 branchcount->ResetReadEntry();
05252 }
05253
05254 size = ((TBranchElement*)branchcount)->GetNdata();
05255
05256
05257
05258
05259 TBranchElement* branch = (TBranchElement*) leaf->GetBranch();
05260
05261
05262 if (fHasMultipleVarDim[i]) {
05263 info = (TFormLeafInfo* )fDataMembers.At(i);
05264 if (branch->GetBranchCount2()) R__LoadBranch(branch->GetBranchCount2(),readentry,fQuickLoad);
05265 else R__LoadBranch(branch,readentry,fQuickLoad);
05266
05267
05268
05269
05270 info->LoadSizes(branch);
05271 hasBranchCount2 = kTRUE;
05272 if (info->GetVirtVarDim()>=0) info->UpdateSizes(fManager->fVarDims[info->GetVirtVarDim()]);
05273
05274
05275
05276 Int_t vdim = info->GetVarDim();
05277 fCumulSizes[i][vdim] = fCumulSizes[i][vdim+1];
05278 for(Int_t k=vdim -1; k>=0; k--) {
05279 fCumulSizes[i][k] = fCumulSizes[i][k+1]*fFixedSizes[i][k];
05280 }
05281
05282
05283
05284
05285
05286
05287
05288
05289 }
05290 } else {
05291 Long64_t readentry = leaf->GetBranch()->GetTree()->GetReadEntry();
05292 if (readentry==-1) readentry=0;
05293 R__LoadBranch(branchcount,readentry,fQuickLoad);
05294 size = leaf->GetLen() / leaf->GetLenStatic();
05295 }
05296 if (hasBranchCount2) {
05297
05298 fNdata[i] = fCumulSizes[i][1] * ((TFormLeafInfo *)fDataMembers.At(i))->GetSumOfSizes();
05299 } else {
05300 fNdata[i] = size * fCumulSizes[i][1];
05301 }
05302 if (fIndexes[i][0]==-1) {
05303
05304
05305 if (fManager->fUsedSizes[0]==1 || (size<fManager->fUsedSizes[0]) ) fManager->fUsedSizes[0] = size;
05306 if (info && fIndexes[i][info->GetVarDim()]>=0) {
05307 for(Int_t j=0; j<size; j++) {
05308 if (fIndexes[i][info->GetVarDim()] >= info->GetSize(j)) {
05309 info->SetSize(j,0);
05310 if (size>fManager->fCumulUsedVarDims->GetSize()) fManager->fCumulUsedVarDims->Set(size);
05311 fManager->fCumulUsedVarDims->AddAt(-1,j);
05312 } else if (fIndexes[i][info->GetVarDim()]>=0) {
05313
05314 info->SetSize(j,1);
05315 if (size>fManager->fCumulUsedVarDims->GetSize()) fManager->fCumulUsedVarDims->Set(size);
05316 fManager->fCumulUsedVarDims->AddAt(1,j);
05317 }
05318 }
05319 }
05320 } else if (fIndexes[i][0] >= size) {
05321
05322 fManager->fUsedSizes[0] = 0;
05323 fNdata[i] = 0;
05324 outofbounds = kTRUE;
05325 } else if (hasBranchCount2) {
05326 TFormLeafInfo *info2;
05327 info2 = (TFormLeafInfo *)fDataMembers.At(i);
05328 if (fIndexes[i][0]<0
05329 || fIndexes[i][info2->GetVarDim()] >= info2->GetSize(fIndexes[i][0])) {
05330
05331 fManager->fUsedSizes[0] = 0;
05332 fNdata[i] = 0;
05333 outofbounds = kTRUE;
05334 }
05335 }
05336 } else if (fLookupType[i]==kDataMember) {
05337 TFormLeafInfo *leafinfo = (TFormLeafInfo*)fDataMembers.UncheckedAt(i);
05338 if (leafinfo->HasCounter()) {
05339 TBranch *branch = leaf->GetBranch();
05340 Long64_t readentry = branch->GetTree()->GetReadEntry();
05341 if (readentry==-1) readentry=0;
05342 R__LoadBranch(branch,readentry,fQuickLoad);
05343 size = (Int_t) leafinfo->GetCounterValue(leaf);
05344 if (fIndexes[i][0]==-1) {
05345
05346
05347 if (fManager->fUsedSizes[0]==1 || (size<fManager->fUsedSizes[0]) ) {
05348 fManager->fUsedSizes[0] = size;
05349 }
05350 } else if (fIndexes[i][0] >= size) {
05351
05352 fManager->fUsedSizes[0] = 0;
05353 fNdata[i] = 0;
05354 outofbounds = kTRUE;
05355 } else {
05356 fNdata[i] = size*fCumulSizes[i][1];
05357 }
05358 Int_t vdim = leafinfo->GetVarDim();
05359 if (vdim>=0) {
05360
05361
05362
05363
05364
05365 leafinfo->LoadSizes(branch);
05366 hasBranchCount2 = kTRUE;
05367 if (fIndexes[i][0]==-1&&fIndexes[i][vdim] >= 0) {
05368 for(int z=0; z<size; ++z) {
05369 if (fIndexes[i][vdim] >= leafinfo->GetSize(z)) {
05370 leafinfo->SetSize(z,0);
05371
05372 } else if (fIndexes[i][vdim] >= 0 ) {
05373 leafinfo->SetSize(z,1);
05374 }
05375 }
05376 }
05377 leafinfo->UpdateSizes(fManager->fVarDims[vdim]);
05378
05379
05380
05381 fCumulSizes[i][vdim] = fCumulSizes[i][vdim+1];
05382 for(Int_t k=vdim -1; k>=0; k--) {
05383 fCumulSizes[i][k] = fCumulSizes[i][k+1]*fFixedSizes[i][k];
05384 }
05385 fNdata[i] = fCumulSizes[i][1] * leafinfo->GetSumOfSizes();
05386 } else {
05387 fNdata[i] = size * fCumulSizes[i][1];
05388 }
05389 } else if (leafinfo->GetMultiplicity()==-1) {
05390 TBranch *branch = leaf->GetBranch();
05391 Long64_t readentry = branch->GetTree()->GetReadEntry();
05392 if (readentry==-1) readentry=0;
05393 R__LoadBranch(branch,readentry,fQuickLoad);
05394 if (leafinfo->GetNdata(leaf)==0) {
05395 outofbounds = kTRUE;
05396 }
05397 }
05398 }
05399
05400
05401 Int_t index;
05402 TFormLeafInfo * info = 0;
05403 if (fLookupType[i]!=kDirect) {
05404 info = (TFormLeafInfo *)fDataMembers.At(i);
05405 }
05406 for(Int_t k=0, virt_dim=0; k < fNdimensions[i]; k++) {
05407 if (fIndexes[i][k]<0) {
05408 if (fIndexes[i][k]==-2 && fManager->fVirtUsedSizes[virt_dim]<0) {
05409
05410
05411
05412 index = fVarIndexes[i][k]->GetNdata();
05413 if (index==1) {
05414
05415
05416 if (fVarIndexes[i][k]->GetManager()->GetMultiplicity()==1) {
05417 if (index<fManager->fUsedSizes[virt_dim]) fManager->fUsedSizes[virt_dim] = index;
05418 }
05419
05420 } else if (fManager->fUsedSizes[virt_dim]==-fManager->fVirtUsedSizes[virt_dim] ||
05421 index<fManager->fUsedSizes[virt_dim]) {
05422 fManager->fUsedSizes[virt_dim] = index;
05423 }
05424
05425 } else if (hasBranchCount2 && info && k==info->GetVarDim()) {
05426
05427 if (fIndexes[i][0]>=0) {
05428 index = info->GetSize(fIndexes[i][0]);
05429 if (fManager->fUsedSizes[virt_dim]==1 || (index!=1 && index<fManager->fUsedSizes[virt_dim]) )
05430 fManager->fUsedSizes[virt_dim] = index;
05431 }
05432 }
05433 virt_dim++;
05434 } else if (hasBranchCount2 && info && k==info->GetVarDim()) {
05435
05436
05437
05438
05439
05440
05441
05442
05443
05444 }
05445 }
05446 }
05447 return ! outofbounds;
05448
05449
05450
05451 }
05452
05453 void TTreeFormula::Convert(UInt_t oldversion)
05454 {
05455
05456
05457 enum { kOldAlias = 100000+10000+1,
05458 kOldAliasString = kOldAlias+1,
05459 kOldAlternate = kOldAlias+2,
05460 kOldAlternateString = kOldAliasString+2
05461 };
05462
05463 for (int k=0; k<fNoper; k++) {
05464
05465
05466 Int_t action = GetOper()[k];
05467
05468 switch (action) {
05469
05470 case kOldAlias: GetOper()[k] = -kOldAlias; break;
05471 case kOldAliasString: GetOper()[k] = -kOldAliasString; break;
05472 case kOldAlternate: GetOper()[k] = -kOldAlternate; break;
05473 case kOldAlternateString: GetOper()[k] = -kOldAlternateString; break;
05474 }
05475 }
05476
05477 TFormula::Convert(oldversion);
05478
05479 for (int i=0,offset=0; i<fNoper; i++) {
05480 Int_t action = GetOper()[i+offset];
05481
05482 switch (action) {
05483 case -kOldAlias: SetAction(i, kAlias, 0); break;
05484 case -kOldAliasString: SetAction(i, kAliasString, 0); break;
05485 case -kOldAlternate: SetAction(i, kAlternate, 0); break;
05486 case -kOldAlternateString: SetAction(i, kAlternateString, 0); break;
05487 }
05488 }
05489
05490 }
05491
05492
05493 Bool_t TTreeFormula::SwitchToFormLeafInfo(Int_t code)
05494 {
05495
05496
05497
05498
05499
05500
05501
05502
05503 TFormLeafInfo *last = 0;
05504 TLeaf *leaf = (TLeaf*)fLeaves.At(code);
05505 if (!leaf) return kFALSE;
05506
05507 if (fLookupType[code]==kDirect) {
05508 if (leaf->InheritsFrom(TLeafElement::Class())) {
05509 TBranchElement * br = (TBranchElement*)leaf->GetBranch();
05510 if (br->GetType()==31) {
05511
05512 TStreamerInfo *info = br->GetInfo();
05513 TClass* cl = info->GetClass();
05514 TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()];
05515 TFormLeafInfo* clonesinfo = new TFormLeafInfoClones(cl, 0, element, kTRUE);
05516 Int_t offset;
05517 info->GetStreamerElement(element->GetName(),offset);
05518 clonesinfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element);
05519 last = clonesinfo->fNext;
05520 fDataMembers.AddAtAndExpand(clonesinfo,code);
05521 fLookupType[code]=kDataMember;
05522
05523 } else if (br->GetType()==41) {
05524
05525
05526 TBranchElement *count = br->GetBranchCount();
05527 TFormLeafInfo* collectioninfo;
05528 if ( count->GetID() >= 0 ) {
05529 TStreamerElement *collectionElement =
05530 (TStreamerElement *)count->GetInfo()->GetElems()[count->GetID()];
05531 TClass *collectionCl = collectionElement->GetClassPointer();
05532
05533 collectioninfo =
05534 new TFormLeafInfoCollection(collectionCl, 0, collectionElement, kTRUE);
05535 } else {
05536 TClass *collectionCl = TClass::GetClass(count->GetClassName());
05537 collectioninfo =
05538 new TFormLeafInfoCollection(collectionCl, 0, collectionCl, kTRUE);
05539 }
05540
05541 TStreamerInfo *info = br->GetInfo();
05542 TClass* cl = info->GetClass();
05543 TStreamerElement *element = (TStreamerElement *)info->GetElems()[br->GetID()];
05544 Int_t offset;
05545 info->GetStreamerElement(element->GetName(),offset);
05546 collectioninfo->fNext = new TFormLeafInfo(cl,offset+br->GetOffset(),element);
05547 last = collectioninfo->fNext;
05548 fDataMembers.AddAtAndExpand(collectioninfo,code);
05549 fLookupType[code]=kDataMember;
05550
05551 } else if (br->GetID()<0) {
05552 return kFALSE;
05553 } else {
05554 last = new TFormLeafInfoDirect(br);
05555 fDataMembers.AddAtAndExpand(last,code);
05556 fLookupType[code]=kDataMember;
05557 }
05558 } else {
05559
05560
05561
05562 return kFALSE;
05563 }
05564 }
05565 return kTRUE;
05566 }