125 fDidBooleanOptimization(false), fDimensionSetup(nullptr)
158 :
ROOT::v5::
TFormula(), fTree(tree), fQuickLoad(false), fNeedLoading(true),
159 fDidBooleanOptimization(false), fDimensionSetup(nullptr)
168 const std::vector<std::string>& aliases)
169 :
ROOT::v5::
TFormula(), fTree(tree), fQuickLoad(false), fNeedLoading(true),
170 fDidBooleanOptimization(false), fDimensionSetup(nullptr), fAliasesUsed(aliases)
210 if(savedir) savedir->
cd();
215 Warning(
"TTreeFormula",
"Too many items in expression:%s",expression);
225 if (!leafc)
continue;
268 for(k0 = 0; k0 <
fNcodes; k0++) {
273 Error(
"TTreeFormula",
274 "Index %d for dimension #%d in %s is too high (max is %d)",
277 if(savedir) savedir->
cd();
306 if (readentry >= 0) {
311 if (readentry >= 0) {
318 if(savedir) savedir->
cd();
340 for (
int j=0; j<
fNcodes; j++) {
368 bool scalarindex =
false;
374 switch (index_multiplicity) {
405 const char * current;
414 if (current[0] !=
'[') current--;
417 scanindex = sscanf(current,
"%d",&
size);
421 if (scanindex==0)
size = -1;
430 current = (
char*)strstr( current,
"[" );
444 return (
size==-1) ? 1 : 0;
452 bool useCollectionObject) {
485 if (maininfo==0 || maininfo==leafinfo || 1) {
491 delete currentinfo->
fNext;
516 }
else if (
c &&
c->GetReferenceProxy() &&
c->GetReferenceProxy()->HasCounter() ) {
547 }
while (current<ndim);
584 Int_t numberOfVarDim = 0;
589 const char *tname = leaf->
GetTitle();
590 char *leaf_dim = (
char*)strstr( tname,
"[" );
593 char *branch_dim = (
char*)strstr(bname,
"[");
594 if (branch_dim) branch_dim++;
596 bool isString =
false;
606 if (!branch_dim || strncmp(branch_dim,leaf_dim,strlen(branch_dim))) {
609 }
else if (branch_dim && strncmp(branch_dim,leaf_dim,strlen(branch_dim))==0
610 && strlen(leaf_dim)>strlen(branch_dim)
611 && (leaf_dim+strlen(branch_dim))[0]==
'[') {
630 "Noticed an incorrect in-memory TBranchElement object (%s).\nIt has a BranchCount2 but no BranchCount!\nThe result might be incorrect!",
632 return numberOfVarDim;
638 "Already in kDataMember mode when handling multiple variable dimensions");
646 return numberOfVarDim;
659 static const char *altfunc =
"Alt$(";
660 static const char *minfunc =
"MinIf$(";
661 static const char *maxfunc =
"MaxIf$(";
665 if ( strncmp(expression,altfunc,strlen(altfunc))==0
666 && expression[strlen(expression)-1]==
')' ) {
668 start = strlen(altfunc);
670 if ( strncmp(expression,maxfunc,strlen(maxfunc))==0
671 && expression[strlen(expression)-1]==
')' ) {
673 start = strlen(maxfunc);
675 if ( strncmp(expression,minfunc,strlen(minfunc))==0
676 && expression[strlen(expression)-1]==
')' ) {
678 start = strlen(minfunc);
688 for(
unsigned int i=start;i<strlen(expression);++i) {
689 switch (expression[i]) {
690 case '(': paran++;
break;
691 case ')': paran--;
break;
692 case '"': instr = instr ? 0 : 1;
break;
693 case '[': brack++;
break;
694 case ']': brack--;
break;
696 if (expression[i]==
',' && paran==0 && instr==0 && brack==0) {
697 part1 = full( start, i-start );
698 part2 = full( i+1, full.Length() -1 - (i+1) );
710 Error(
"DefinedVariable",
"The 2nd arguments in %s can not be an array (%s,%d)!",
719 Error(
"DefinedVariable",
720 "The 2nd arguments in %s has to return the same type as the 1st argument (string)!",
726 Error(
"DefinedVariable",
727 "The 2nd arguments in %s has to return the same type as the 1st argument (numerical type)!",
736 Error(
"DefinedVariable",
737 "The arguments of %s can not be strings!",
768 Int_t numberOfVarDim = 0;
771 char scratch[
kMaxLen]; scratch[0] =
'\0';
772 char work[
kMaxLen]; work[0] =
'\0';
774 const char *right = subExpression;
779 if (readentry < 0) readentry=0;
781 bool useLeafReferenceObject =
false;
791 if ( br->
GetInfo() == nullptr ) {
792 Error(
"DefinedVariable",
"Missing StreamerInfo for %s. We will be unable to read!",
804 Error(
"DefinedVariable",
"Missing StreamerInfo for %s."
805 " We will be unable to read!",
810 Error(
"DefinedVariable",
"Address not set when the type of the branch is negative for for %s. We will be unable to read!", mom->
GetName());
823 const char* alias =
nullptr;
826 if (!alias && realtree!=
fTree) {
831 Int_t leafname_len = 0;
833 leafname_len = strlen(alias) + strlen(leaf->
GetName()) + 1;
837 leafname_len = strlen(leaf->
GetName());
840 if (leafname_len >
kMaxLen - 1) {
841 Error(
"TTreeFormula",
842 "Length of leafname (%d) exceeds maximum allowed by the buffer (%d), formula will be truncated.",
848 TTree *tleaf = realtree;
855 if (mother_name[strlen(mother_name)-1]!=
'.') {
856 br_extended_name = mother_name;
857 br_extended_name.
Append(
'.');
862 if (dim >= 0) br_extended_name.
Remove(dim);
882 bool unwindCollection =
false;
950 "Missing TStreamerElement in object in TClonesArray section");
961 maininfo = clonesinfo;
980 maininfo->
fNext = previnfo;
981 unwindCollection =
true;
983 }
else if (branchEl->
GetType()==41) {
988 Warning(
"DefinedVariable",
"Missing TStreamerElement in object in Collection section");
994 if ( count->
GetID() >= 0 ) {
1013 maininfo = collectioninfo;
1032 maininfo->
fNext = previnfo;
1033 unwindCollection =
true;
1035 }
else if ( branchEl->
GetType()==3) {
1037 if (useLeafCollectionObject) {
1042 numberOfVarDim +=
RegisterDimensions(code,clonesinfo,maininfo,useLeafCollectionObject);
1045 maininfo = clonesinfo;
1046 previnfo = maininfo;
1048 }
else if (!useLeafCollectionObject && branchEl->
GetType()==4) {
1051 if (useLeafCollectionObject) {
1056 numberOfVarDim +=
RegisterDimensions(code,collectioninfo,maininfo,useLeafCollectionObject);
1059 maininfo = collectioninfo;
1060 previnfo = maininfo;
1064 if (useLeafCollectionObject) {
1067 maininfo = collectioninfo;
1068 previnfo = collectioninfo;
1075 maininfo = collectioninfo;
1076 previnfo = collectioninfo;
1086 previnfo->
fNext = multi;
1089 previnfo = multi->
fNext;
1097 previnfo = previnfo->
fNext;
1103 }
else if (strlen(right)==0 && cl && element &&
final) {
1106 if (!useLeafCollectionObject
1117 maininfo = collectioninfo;
1118 previnfo = collectioninfo;
1127 previnfo->
fNext = multi;
1130 previnfo = multi->
fNext;
1137 previnfo = previnfo->
fNext;
1140 }
else if (!useLeafCollectionObject
1156 collectioninfo->
fNext =
1159 maininfo = collectioninfo;
1160 previnfo = maininfo->
fNext;
1162 }
else if (!useLeafCollectionObject
1173 previnfo = maininfo;
1178 if ( useLeafCollectionObject || fullExpression[0] ==
'@' || fullExpression[strlen(scratch)] ==
'@' ) {
1179 useLeafReferenceObject =
true;
1196 Error(
"DefinedVariable",
"Failed to access class type of reference target (%s)",element->
GetName());
1203 if (subExpression && subExpression[0]) {
1204 Error(
"ParseWithLeaf",
"Found a numerical leaf but the name has trailing characters: \"%s\"", subExpression);
1213 if (unwindCollection) {
1216 R__ASSERT(numberOfVarDim==1 && maininfo);
1223 previnfo->
fNext = multi;
1226 previnfo = multi->
fNext;
1233 previnfo = previnfo->
fNext;
1241 previnfo->
fNext = multi;
1244 previnfo = multi->
fNext;
1253 Int_t nchname = strlen(right);
1268 Error(
"DefinedVariable",
"%s does not inherit from %s. Casting not possible!",
1274 if (maininfo==
nullptr) {
1275 maininfo = leafinfo;
1277 if (previnfo==
nullptr) {
1278 previnfo = leafinfo;
1280 previnfo->
fNext = leafinfo;
1281 previnfo = leafinfo;
1286 castqueue.
AddAt(
nullptr,paran_level);
1290 bool prevUseCollectionObject = useLeafCollectionObject;
1291 bool useCollectionObject = useLeafCollectionObject;
1292 bool useReferenceObject = useLeafReferenceObject;
1293 bool prevUseReferenceObject = useLeafReferenceObject;
1294 for (i=0, current = &(work[0]); i<=nchname;i++ ) {
1296 if (right[i] ==
'(') {
1299 *current++ = right[i++];
1300 }
while(right[i]!=
')' && right[i]);
1301 *current++ = right[i];
1303 char *params = strchr(work,
'(');
1305 *params = 0; params++;
1306 }
else params = (
char *)
")";
1308 Error(
"DefinedVariable",
"Can not call '%s' with a class",work);
1312 Error(
"DefinedVariable",
"Class probably unavailable:%s",cl->
GetName());
1339 previnfo = clonesinfo;
1340 maininfo = clonesinfo;
1354 if (previnfo==
nullptr) {
1372 previnfo = collectioninfo;
1373 maininfo = collectioninfo;
1378 if (inside_cl) cl = inside_cl;
1380 Warning(
"DefinedVariable",
"Can not call method on content of %s in %s\n",
1387 Error(
"DefinedVariable",
1388 "Could not discover the TClass corresponding to (%s)!",
1392 method =
new TMethodCall(cl,
"GetEntriesFast",
"");
1394 if (maininfo==
nullptr) {
1396 if (useLeafCollectionObject) {
1402 maininfo=previnfo=collectioninfo;
1408 Error(
"DefinedVariable",
1409 "Can not call method %s on class without dictionary (%s)!",
1417 Error(
"DefinedVariable",
"Unknown method:%s in %s",right,cl->
GetName());
1442 Error(
"DefineVariable",
"Method %s from %s has an impossible return type %d",
1447 if (maininfo==
nullptr) {
1448 maininfo = leafinfo;
1450 if (previnfo==
nullptr) {
1451 previnfo = leafinfo;
1453 previnfo->
fNext = leafinfo;
1454 previnfo = leafinfo;
1457 current = &(work[0]);
1459 prevUseCollectionObject =
false;
1460 prevUseReferenceObject =
false;
1461 useCollectionObject =
false;
1464 if (numberOfVarDim>1) {
1465 Warning(
"DefinedVariable",
"TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
1468 useCollectionObject =
true;
1469 }
else if (numberOfVarDim==0) {
1473 }
else if (numberOfVarDim==1) {
1478 previnfo->
fNext = leafinfo;
1479 previnfo = leafinfo;
1485 previnfo->
fNext = leafinfo;
1486 previnfo = leafinfo;
1490 }
else if (right[i] ==
')') {
1493 TClass * casted = (
TClass*) ((
int(--paran_level)>=0) ? castqueue.
At(paran_level) :
nullptr);
1498 if (maininfo==
nullptr) {
1499 maininfo = leafinfo;
1501 if (previnfo==
nullptr) {
1502 previnfo = leafinfo;
1504 previnfo->
fNext = leafinfo;
1505 previnfo = leafinfo;
1508 current = &(work[0]);
1515 }
else if (i > 0 && (right[i] ==
'.' || right[i] ==
'[' || right[i] ==
'\0') ) {
1518 bool needClass =
true;
1522 if (strlen(work)==0)
continue;
1524 prevUseCollectionObject = useCollectionObject;
1525 prevUseReferenceObject = useReferenceObject;
1527 useReferenceObject =
true;
1528 useCollectionObject =
true;
1530 for(
l=0;work[
l+1]!=0;++
l) work[
l] = work[
l+1];
1532 }
else if (work[strlen(work)-1]==
'@') {
1533 useReferenceObject =
true;
1534 useCollectionObject =
true;
1535 work[strlen(work)-1] =
'\0';
1537 useReferenceObject =
false;
1538 useCollectionObject =
false;
1541 bool mustderef =
false;
1549 prevUseReferenceObject =
false;
1552 previnfo = previnfo->
fNext;
1556 for(
Long64_t entry=0; entry<leaf->
GetBranch()->GetEntries()-readentry; ++entry) {
1594 previnfo = clonesinfo;
1595 maininfo = clonesinfo;
1599 Error(
"DefinedVariable",
"Unimplemented usage of ClonesArray");
1608 if (clones==
nullptr) {
1610 "TClonesArray object was not retrievable for %s!",
1619 if (1 || inside_cl) cl = inside_cl;
1621 if (0 && strlen(work)==0) {
1636 if (maininfo==
nullptr) {
1655 previnfo = collectioninfo;
1656 maininfo = collectioninfo;
1665 Error(
"DefinedVariable",
"Could you not find the inner class for %s with coll type = %d",
1669 Warning(
"DefinedVariable",
"No data member in content of %s in %s\n",
1678 Warning(
"DefinedVariable",
"Missing class for %s!",
name.Data());
1683 if (!element && !prevUseCollectionObject) {
1690 Int_t clones_offset = 0;
1698 previnfo->
fNext = clonesinfo;
1700 previnfo->
fNext =
nullptr;
1712 if (maininfo==
nullptr) maininfo = leafinfo;
1713 if (previnfo==
nullptr) previnfo = leafinfo;
1715 previnfo->
fNext = leafinfo;
1716 previnfo = leafinfo;
1724 Int_t coll_offset = 0;
1733 if (numberOfVarDim>1) {
1734 Warning(
"DefinedVariable",
"TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
1737 useCollectionObject =
true;
1738 }
else if (numberOfVarDim==1) {
1750 if (maininfo==
nullptr) maininfo = leafinfo;
1751 if (previnfo==
nullptr) previnfo = leafinfo;
1753 previnfo->
fNext = leafinfo;
1754 previnfo = leafinfo;
1756 if (leafinfo->
fNext) {
1757 previnfo = leafinfo->
fNext;
1772 if (numberOfVarDim>=1 &&
type>40) {
1777 if (leafinfo &&
type<=40 ) {
1784 bool object =
false;
1785 bool pointer =
false;
1786 bool objarr =
false;
1817 Error(
"DefinedVariable",
1818 "%s is a datamember of %s BUT is not yet of a supported type (%d)",
1823 Error(
"DefinedVariable",
1824 "%s is a datamember of %s BUT is not of a unknown type (%d)",
1829 if (
object && !useCollectionObject &&
1835 if (
object && leafinfo) {
1837 }
else if (objarr) {
1852 if (numberOfVarDim>1) {
1853 Warning(
"DefinedVariable",
"TTreeFormula support only 2 level of variables size collections. Assuming '@' notation for the collection %s.",
1856 useCollectionObject =
true;
1857 }
else if (numberOfVarDim==1) {
1877 else leafinfo->
fNext = info;
1884 if (!maininfo) maininfo = leafinfo;
1889 if (previnfo==
nullptr) previnfo = leafinfo;
1891 previnfo->
fNext = leafinfo;
1892 previnfo = leafinfo;
1907 else leafinfo->
fNext = info;
1923 prevUseReferenceObject =
false;
1926 }
else if (pointer) {
1938 if (cl)
Error(
"DefinedVariable",
"%s is not a datamember of %s",work,cl->
GetName());
1944 if (maininfo==
nullptr) {
1945 maininfo = leafinfo;
1947 if (previnfo==
nullptr) {
1948 previnfo = leafinfo;
1949 }
else if (previnfo!=leafinfo) {
1950 previnfo->
fNext = leafinfo;
1951 previnfo = leafinfo;
1953 while (previnfo->
fNext) previnfo = previnfo->
fNext;
1955 if ( right[i] !=
'\0' ) {
1956 if ( !needClass && mustderef ) {
1962 if ( inf->IsReference() ) {
1973 Error(
"DefinedVariable",
"Failed to access class type of reference target (%s)",element->
GetName());
1979 Error(
"DefinedVariable",
"Failed to access class type of reference target (%s)",element->
GetName());
1983 else if ( needClass ) {
1987 if (mustderef) leafinfo =
nullptr;
1988 current = &(work[0]);
1997 nchname = strlen(right);
2001 *current++ = right[i];
2010 if (strlen(work)!=0) {
2022 if (!last)
return action;
2026 if (last && last->
GetClass() != objClass) {
2038 last->
fNext = collectioninfo;
2050 if (!last)
return action;
2054 const char *funcname =
nullptr;
2058 }
else if (objClass == stdStringClass) {
2101 method =
new TMethodCall(objClass,
"AsString",
"");
2154 const char *funcname =
nullptr;
2157 }
else if (objClass == stdStringClass) {
2197 if (readentry < 0) readentry=0;
2198 const char *
cname = expression;
2199 char first[
kMaxLen]; first[0] =
'\0';
2200 char second[
kMaxLen*2]; second[0] =
'\0';
2201 char right[
kMaxLen*2]; right[0] =
'\0';
2202 char work[
kMaxLen]; work[0] =
'\0';
2203 char left[
kMaxLen]; left[0] =
'\0';
2206 std::string currentname;
2207 Int_t previousdot = 0;
2209 TLeaf *tmp_leaf=
nullptr;
2210 TBranch *branch=
nullptr, *tmp_branch=
nullptr;
2213 bool foundAtSign =
false;
2214 bool startWithParan =
false;
2216 for (i=0, current = &(work[0]); i<=nchname && !
final;i++ ) {
2218 *current++ =
cname[i];
2220 if (
cname[i] ==
'(') {
2223 if (current==work+1) {
2226 startWithParan =
true;
2238 if (
cname[i] ==
')') {
2239 if (paran_level==0) {
2240 Error(
"DefinedVariable",
"Unmatched parenthesis in %s",fullExpression);
2245 if (startWithParan) {
2246 startWithParan =
false;
2255 current = &(work[0]);
2259 }
else if (
gROOT->GetType(cast_name)) {
2261 current = &(work[0]);
2264 "Casting to primary types like \"%s\" is not supported yet",cast_name.
Data());
2271 char *params = strchr(work,
'(');
2273 *params = 0; params++;
2275 if (branch && !leaf) {
2286 TLeaf* leafcur =
nullptr;
2287 while (!leaf && (leafcur = (
TLeaf*) next())) {
2297 if (strlen(left) && left[strlen(left)-1]==
'.') left[strlen(left)-1]=0;
2299 if (aliasValue && strcspn(aliasValue,
"+*/-%&!=<>|")==strlen(aliasValue)) {
2302 if (find(aliasUsed.begin(),
2304 left) != aliasUsed.end()) {
2305 Error(
"DefinedVariable",
2306 "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
2307 "\tbecause \"%s\" is used [recursively] in its own definition!",
2308 left,aliasValue,fullExpression,left);
2311 aliasUsed.push_back(left);
2312 TString newExpression = aliasValue;
2313 newExpression += (
cname+strlen(left));
2315 castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
2317 Error(
"DefinedVariable",
2318 "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
2335 strlcpy(right,work,2*
kMaxLen);
2336 strncat(right,
"(",2*
kMaxLen-1-strlen(right));
2337 strncat(right,params,2*
kMaxLen-1-strlen(right));
2341 i += strlen(params);
2344 current = &(work[0]);
2358 for(
l=0;work[
l+1]!=0;++
l) work[
l] = work[
l+1];
2361 }
else if (
len>=2 && work[
len-2]==
'@') {
2367 foundAtSign =
false;
2370 if (left[0]==0) strlcpy(left,work,
kMaxLen);
2371 if (!leaf && !branch) {
2375 std::string treename(first);
2376 if (!treename.empty() && treename[treename.size()-1]==
'.') {
2377 treename.erase(treename.size()-1);
2379 if (treename==
"This" ) {
2416 if (
cname[i]) first[strlen(first)-1]=
'\0';
2430 useLeafCollectionObject = foundAtSign;
2432 current = &(work[0]);
2435 else if (branch && (foundAtSign ||
cname[i] != 0) ) {
2440 if (leaf==
nullptr) {
2449 useLeafCollectionObject = foundAtSign;
2450 foundAtSign =
false;
2451 current = &(work[0]);
2461 useLeafCollectionObject = foundAtSign;
2462 foundAtSign =
false;
2463 current = &(work[0]);
2465 }
else if (leaf || branch) {
2466 if (leaf && branch) {
2480 current = &(work[0]);
2493 if (foundAtSign) strncat(right,
"@",2*
kMaxLen-1-strlen(right));
2494 if (
cname[i]==
'.') strncat(right,
".",2*
kMaxLen-1-strlen(right));
2497 current = &(work[0]);
2500 }
else if (
cname[i] ==
'.') {
2507 while(!branch && (branchcur=(
TBranch*)next()) ) {
2512 current = &(work[0]);
2519 Error(
"DefinedVariable",
"Unexpected control flow!");
2525 if (
cname[i]) work[strlen(work)-1] =
'\0';
2526 snprintf(scratch,
sizeof(scratch),
"%s.%s",first,work);
2527 snprintf(scratch2,
sizeof(scratch2),
"%s.%s.%s",first,second,work);
2530 currentname = &(work[previousdot+1]);
2537 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(scratch);
2538 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(scratch2);
2539 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(currentname.c_str());
2549 if (!tmp_branch) tmp_branch = branch->
FindBranch(scratch);
2550 if (!tmp_branch) tmp_branch = branch->
FindBranch(scratch2);
2551 if (!tmp_branch) tmp_branch = branch->
FindBranch(currentname.c_str());
2559 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(scratch);
2560 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(scratch2);
2561 if (!tmp_leaf) tmp_leaf = branch->
FindLeaf(currentname.c_str());
2572 if (second[0]) strncat(second,
".",2*
kMaxLen-1-strlen(second));
2573 strncat(second,work,2*
kMaxLen-1-strlen(second));
2575 useLeafCollectionObject = foundAtSign;
2576 foundAtSign =
false;
2579 current = &(work[0]);
2585 Int_t where = strlen(work);
2587 work[where+1] =
cname[i];
2589 previousdot = where+1;
2591 previousdot = strlen(work);
2592 work[strlen(work)] =
cname[i];
2602 strncat(right,work,2*
kMaxLen-1-strlen(right));
2606 if (strlen(right) && right[strlen(right)-1]!=
'.' &&
cname[i]!=
'.') {
2610 strncat(right,
".",2*
kMaxLen-1-strlen(right));
2615 if (!
final && branch) {
2618 if (!leaf)
return -1;
2624 if (strlen(right)==0) strlcpy(right,work,2*
kMaxLen);
2627 if (leaf==
nullptr && left[0]!=0) {
2628 if (left[strlen(left)-1]==
'.') left[strlen(left)-1]=0;
2632 if (aliasValue && strcspn(aliasValue,
"()[]+*/-%&!=<>|")==strlen(aliasValue)) {
2635 if (find(aliasUsed.begin(),
2637 left) != aliasUsed.end()) {
2638 Error(
"DefinedVariable",
2639 "The substitution of the branch alias \"%s\" by \"%s\" in \"%s\" failed\n"\
2640 "\tbecause \"%s\" is used [recursively] in its own definition!",
2641 left,aliasValue,fullExpression,left);
2644 aliasUsed.push_back(left);
2645 TString newExpression = aliasValue;
2646 newExpression += (
cname+strlen(left));
2648 castqueue, aliasUsed, useLeafCollectionObject, fullExpression);
2650 Error(
"DefinedVariable",
2651 "The substitution of the alias \"%s\" by \"%s\" failed.",left,aliasValue);
2702 if (!
fTree)
return -1;
2706 Error(
"TTreeFormula",
"The length of the variable name (%d) exceeds the maximum allowed (%d)",
name.Length(),
kMaxLen);
2711 if (
name ==
"Entry$") {
2717 if (
name ==
"LocalEntry$") {
2723 if (
name ==
"Entries$") {
2731 if (
name ==
"LocalEntries$") {
2739 if (
name ==
"Iteration$") {
2745 if (
name ==
"Length$") {
2751 static const char *
lenfunc =
"Length$(";
2752 if (strncmp(
name.Data(),
"Length$(",strlen(
lenfunc))==0
2764 static const char *minfunc =
"Min$(";
2765 if (strncmp(
name.Data(),
"Min$(",strlen(minfunc))==0
2777 static const char *maxfunc =
"Max$(";
2778 if (strncmp(
name.Data(),
"Max$(",strlen(maxfunc))==0
2790 static const char *sumfunc =
"Sum$(";
2791 if (strncmp(
name.Data(),
"Sum$(",strlen(sumfunc))==0
2810 if (res<0)
return res;
2818 char dims[
kMaxLen]; dims[0] =
'\0';
2827 for(i=0,k=0; i<cnamelen; ++i, ++k) {
2828 if (
cname[i] ==
'[') {
2830 int bracket_level = 1;
2832 for (j=++i; j<cnamelen && (bracket_level>0 ||
cname[j]==
'['); j++, i++) {
2833 if (
cname[j]==
'[') bracket_level++;
2834 else if (
cname[j]==
']') bracket_level--;
2836 if (bracket_level != 0) {
2840 strncat(dims,&
cname[bracket],j-bracket);
2847 bool useLeafCollectionObject =
false;
2849 TLeaf *leaf =
nullptr;
2854 if (res<0)
return res;
2856 if (!leaf && res!=2) {
2865 Error(
"DefinedVariable",
2866 "The substitution of the alias \"%s\" by \"%s\" failed\n"\
2867 "\tbecause \"%s\" is recursively used in its own definition!",
2873 if (strcspn(aliasValue,
"()+*/-%&!=<>|")!=strlen(aliasValue)) {
2879 aliasSofar.push_back(
cname );
2881 TString subValue( aliasValue );
2890 Error(
"DefinedVariable",
2891 "The substitution of the alias \"%s\" by \"%s\" failed.",
cname,aliasValue);
2906 TString thisAlias( aliasValue );
2914 Error(
"Compile",
" Bad numerical expression : \"%s\"",thisAlias.
Data());
2915 }
else if (aliasRes==-2) {
2916 Error(
"Compile",
" Part of the Variable \"%s\" exists but some of it is not accessible or useable",thisAlias.
Data());
2919 Error(
"DefinedVariable",
2920 "The substitution of the alias \"%s\" by \"%s\" failed.",
cname,aliasValue);
2929 if (leaf || res==2) {
2932 Error(
"DefinedVariable",
"the branch \"%s\" has to be enabled to be used",leaf->
GetBranch()->
GetName());
2941 char *current = &( dims[0] );
2948 if (current[0] ==
']') {
2951 scanindex = sscanf(current,
"%d",&
index);
2957 char *end = (
char*)(varindex.
Data());
2958 for(
char bracket_level = 0;*end!=0;end++) {
2959 if (*end==
'[') bracket_level++;
2960 if (bracket_level==0 && *end==
']')
break;
2961 if (*end==
']') bracket_level--;
2971 current += strlen(varindex)+1;
2979 current = (
char*)strstr( current,
"[" );
2986 res =
ParseWithLeaf(leaf,leftover,
final,paran_level,castqueue,useLeafCollectionObject,
name);
2987 if (res<0)
return res;
2988 if (res>0) action = res;
3016 }
else if (strlen(gcut->
GetVarX())) {
3025 for(
Int_t i2 = 1; i2<
n; i2++) {
3026 if (
x[i2] < min) min =
x[i2];
3027 if (
x[i2] > max) max =
x[i2];
3046 Error(
"DefinedVariable",
"Found a TCutG without leaf information (%s)",
3083 while ((leafcur = (
TLeaf*)nextleaf())) {
3111 if (clonesinfo) {
delete clonesinfo; clonesinfo =
nullptr; }
3131 bool toplevel = (branch == branch->
GetMother());
3135 if (clones) cl = clones->
GetClass();
3177 leafinfo = clonesinfo;
3189 Int_t clones_offset = 0;
3194 else leafinfo->
fNext = sub_clonesinfo;
3195 else leafinfo = sub_clonesinfo;
3201 delete leafinfo; clonesinfo =
nullptr;
3206 if (!clones)
continue;
3267 }
else if (
type > 60) {
3326 Error(
"BranchHasMethod",
"A TClonesArray was stored in a branch type no yet support (i.e. neither TBranchObject nor TBranchElement): %s",branch->
IsA()->
GetName());
3329 cl = clones ? clones->
GetClass() :
nullptr;
3363 Int_t real_instance = 0;
3398 if (local_index<0) {
3399 Error(
"EvalInstance",
"Index %s is out of bound (%d) in formula %s",
3406 real_instance = local_index *
fCumulSizes[codeindex][1];
3431 if (local_index<0) {
3432 Error(
"EvalInstance",
"Index %s is out of bound (%d) in formula %s",
3452 if (check)
return fNdata[0]+1;
3457 }
while(
instance >= virt_accum && local_index<maxloop);
3463 if (local_index==(maxloop-1) && (
instance >= virt_accum)) {
3465 if (check)
return fNdata[0]+1;
3471 if (check)
return fNdata[0]+1;
3479 local_index =
fIndexes[codeindex][0];
3506 if (
fIndexes[codeindex][vdim]>=0) {
3509 if (isize!=1 &&
fIndexes[codeindex][vdim]>isize) {
3514 for(
Int_t k=vdim -1; k>0; --k) {
3518 real_instance = local_index *
fCumulSizes[codeindex][1];
3522 for (
Int_t dim = 1; dim < max_dim; dim++) {
3533 if (
fIndexes[codeindex][dim]==-2) {
3540 if (local_index<0 ||
3542 Error(
"EvalInstance",
"Index %s is out of bound (%d/%d) in formula %s",
3550 real_instance += local_index *
fCumulSizes[codeindex][dim+1];
3554 if (
fIndexes[codeindex][max_dim]>=0) {
3555 if (!info) real_instance +=
fIndexes[codeindex][max_dim];
3563 if (info && local_index>=
fCumulSizes[codeindex][max_dim]) {
3567 if (
fIndexes[codeindex][max_dim]==-2) {
3573 if (local_index<0 ||
3575 Error(
"EvalInstance",
"Index %s is of out bound (%d/%d) in formula %s",
3583 real_instance += local_index;
3588 return real_instance;
3627 if (elem==
nullptr) {
3642 if (!obj)
return nullptr;
3646 default:
return nullptr;
3686 else if (real_instance>=
fNdata[0])
return nullptr;
3692 if (real_instance) {
3693 Warning(
"EvalObject",
"Not yet implement for kDirect and arrays (for %s).\nPlease contact the developers",
GetName());
3700 default:
return nullptr;
3712 const Int_t kMAXSTRINGFOUND = 10;
3713 const char *stringStack[kMAXSTRINGFOUND];
3724 }
else if (real_instance>=
fNdata[0]) {
3737 return stringStack[0];
3740#define TT_EVAL_INIT \
3741 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(0); \
3743 const Int_t real_instance = GetRealInstance(instance,0); \
3745 if (instance==0) fNeedLoading = true; \
3746 if (real_instance>=fNdata[0]) return 0; \
3752 if (fNeedLoading) { \
3753 fNeedLoading = false; \
3754 TBranch *br = leaf->GetBranch(); \
3755 if (br && br->GetTree()) { \
3756 Long64_t tentry = br->GetTree()->GetReadEntry(); \
3757 R__LoadBranch(br,tentry,fQuickLoad); \
3759 Error("TTreeFormula::TT_EVAL_INIT", \
3760 "Could not init branch associated to this leaf (%s).", leaf->GetName()); \
3768 if (fLookupType[0]==kDirect) { \
3769 label = (char*)leaf->GetValuePointer(); \
3771 label = (char*)GetLeafInfo(0)->GetValuePointer(leaf,instance); \
3773 Int_t bin = fAxis->FindBin(label); \
3777#define TREE_EVAL_INIT \
3778 const Int_t real_instance = GetRealInstance(instance,0); \
3780 if (real_instance>=fNdata[0]) return 0; \
3786 label = (char*)GetLeafInfo(0)->GetValuePointer((TLeaf*)0x0,instance); \
3787 Int_t bin = fAxis->FindBin(label); \
3791#define TT_EVAL_INIT_LOOP \
3792 TLeaf *leaf = (TLeaf*)fLeaves.UncheckedAt(code); \
3795 const Int_t real_instance = GetRealInstance(instance,code); \
3798 TBranch *branch = (TBranch*)fBranches.UncheckedAt(code); \
3800 if (branch->GetTree()) { \
3801 Long64_t treeEntry = branch->GetTree()->GetReadEntry(); \
3802 R__LoadBranch(branch,treeEntry,fQuickLoad); \
3804 Error("TTreeFormula::TT_EVAL_INIT_LOOP", \
3805 "Could not init branch associated to this leaf (%s).", leaf->GetName()); \
3807 } else if (fDidBooleanOptimization) { \
3808 branch = leaf->GetBranch(); \
3809 if (branch->GetTree()) { \
3810 Long64_t treeEntry = branch->GetTree()->GetReadEntry(); \
3811 if (branch->GetReadEntry() != treeEntry) branch->GetEntry( treeEntry ); \
3813 Error("TTreeFormula::TT_EVAL_INIT_LOOP", \
3814 "Could not init branch associated to this leaf (%s).", leaf->GetName()); \
3821 if (fDidBooleanOptimization) { \
3822 TBranch *br = leaf->GetBranch(); \
3823 if (br->GetTree()) { \
3824 Long64_t treeEntry = br->GetTree()->GetReadEntry(); \
3825 if (br->GetReadEntry() != treeEntry) br->GetEntry( treeEntry ); \
3827 Error("TTreeFormula::TT_EVAL_INIT_LOOP", \
3828 "Could not init branch associated to this leaf (%s).", leaf->GetName()); \
3832 if (real_instance>=fNdata[code]) return 0;
3834#define TREE_EVAL_INIT_LOOP \
3836 const Int_t real_instance = GetRealInstance(instance,code); \
3838 if (real_instance>=fNdata[code]) return 0;
3844 for (
int i=0; i<
len; ++i) res +=
sum->EvalInstance<T>(i);
3853 for (
int i=1; i<
len; ++i) {
3868 for (
int i=1; i<
len; ++i) {
3887 }
while (!condval && i<
len);
3888 if (!condval && i==
len) {
3897 for (; i<
len; ++i) {
3919 }
while (!condval && i<
len);
3920 if (!condval && i==
len) {
3929 for (; i<
len; ++i) {
3944template <
typename T>
T fmod_local(T
x, T
y) {
return fmod(
x,
y); }
3961 if( !strncmp(
fExpr[op],
"0x", 2) || !strncmp(
fExpr[op],
"0X", 2) ) {
3963 sscanf(
fExpr[op],
"%llx", &val );
3993 return leaf->GetTypedValue<T>(real_instance);
4051 const Int_t kMAXSTRINGFOUND = 10;
4052 const char *stringStackLocal[kMAXSTRINGFOUND];
4053 const char **stringStack = stringStackArg?stringStackArg:stringStackLocal;
4069 if (newaction==
kConstant) { pos++; tab[pos-1] = GetConstant<T>(oper &
kTFOperMask);
continue; }
4073 case kEnd :
return tab[0];
4074 case kAdd : pos--; tab[pos-1] += tab[pos];
continue;
4075 case kSubstract : pos--; tab[pos-1] -= tab[pos];
continue;
4076 case kMultiply : pos--; tab[pos-1] *= tab[pos];
continue;
4077 case kDivide : pos--;
if (tab[pos] == 0) tab[pos-1] = 0;
4078 else tab[pos-1] /= tab[pos];
4083 tab[pos-1] = T(int1 % int2);
4103 case kacosh:
if (tab[pos-1] < 1) {tab[pos-1] = 0;}
4112 case kfmod : pos--; tab[pos-1] = fmod_local(tab[pos-1],tab[pos]);
continue;
4113 case kpow : pos--; tab[pos-1] =
TMath::Power(tab[pos-1],tab[pos]);
continue;
4114 case ksq : tab[pos-1] = tab[pos-1]*tab[pos-1];
continue;
4117 case kstrstr : pos2 -= 2; pos++;
if (strstr(stringStack[pos2],stringStack[pos2+1])) tab[pos-1]=1;
4121 case kmin : pos--; tab[pos-1] = std::min(tab[pos-1],tab[pos]);
continue;
4122 case kmax : pos--; tab[pos-1] = std::max(tab[pos-1],tab[pos]);
continue;
4124 case klog :
if (tab[pos-1] > 0) tab[pos-1] =
TMath::Log(tab[pos-1]);
4125 else {tab[pos-1] = 0;}
4128 if (dexp < -700) {tab[pos-1] = 0;
continue;}
4129 if (dexp > 700) {tab[pos-1] =
TMath::Exp(700);
continue;}
4133 else {tab[pos-1] = 0;}
4139 case ksign :
if (tab[pos-1] < 0) tab[pos-1] = -1;
else tab[pos-1] = 1;
4141 case kint : tab[pos-1] = T(
Long64_t(tab[pos-1]));
continue;
4142 case kSignInv: tab[pos-1] = -1 * tab[pos-1];
continue;
4145 case kAnd : pos--;
if (tab[pos-1]!=0 && tab[pos]!=0) tab[pos-1]=1;
4148 case kOr : pos--;
if (tab[pos-1]!=0 || tab[pos]!=0) tab[pos-1]=1;
4152 case kEqual : pos--; tab[pos-1] = (tab[pos-1] == tab[pos]) ? 1 : 0;
continue;
4153 case kNotEqual : pos--; tab[pos-1] = (tab[pos-1] != tab[pos]) ? 1 : 0;
continue;
4154 case kLess : pos--; tab[pos-1] = (tab[pos-1] < tab[pos]) ? 1 : 0;
continue;
4155 case kGreater : pos--; tab[pos-1] = (tab[pos-1] > tab[pos]) ? 1 : 0;
continue;
4156 case kLessThan : pos--; tab[pos-1] = (tab[pos-1] <= tab[pos]) ? 1 : 0;
continue;
4157 case kGreaterThan: pos--; tab[pos-1] = (tab[pos-1] >= tab[pos]) ? 1 : 0;
continue;
4158 case kNot : tab[pos-1] = (tab[pos-1] != 0) ? 0 : 1;
continue;
4160 case kStringEqual : pos2 -= 2; pos++;
if (!strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
4163 case kStringNotEqual: pos2 -= 2; pos++;
if (strcmp(stringStack[pos2+1],stringStack[pos2])) tab[pos-1]=1;
4188 pos2++; stringStack[pos2-1] = (
char*)
fExpr[i].Data();
4202 int op = param % 10;
4204 if (op == 1 && (!tab[pos-1]) ) {
4213 }
else if (op == 2 && tab[pos-1] ) {
4224 int toskip = param / 10;
4235 int fno = param / 1000;
4236 int nargs = param % 1000;
4244 UInt_t argloc = pos-nargs;
4245 for(
Int_t j=0;j<nargs;j++,argloc++,pos--) {
4246 SetMethodParam(method, tab[argloc]);
4269 switch (lookupType) {
4284 GetTypedValue<T>(leaf,real_instance);
continue; }
4286 GetTypedValue<T>((
TLeaf*)
nullptr,real_instance);
continue; }
4291 default: tab[pos++] = 0;
continue;
4304 tab[pos++] = gcut->
IsInside(xcut,ycut);
4333 tab[pos] = param; pos++;
4351 T param = FindMin<T>(primary,condition);
4353 tab[pos] = param; pos++;
4360 T param = FindMax<T>(primary,condition);
4362 tab[pos] = param; pos++;
4372 if (instance < primary->
GetNdata()) {
4378 tab[pos] = param; pos++;
4392 if (instance < primary->
GetNdata()) {
4430 if (real_instance>=
fNdata[string_code])
return 0;
4452template double TTreeFormula::EvalInstance<double> (
int,
char const**);
4453template long double TTreeFormula::EvalInstance<long double> (
int,
char const**);
4454template long long TTreeFormula::EvalInstance<long long> (
int,
char const**);
4507 void* thisobj =
nullptr;
4520 Warning(
"GetValueFromMethod",
"No streamer info for branch %s.", branch->
GetName());
4530 thisobj = *((
char**) (address +
offset));
4580 Warning(
"GetValuePointerFromMethod",
"No streamer info for branch %s.", branch->
GetName());
4590 thisobj = *((
char**) (address +
offset));
4646 if (
fNoper > 1)
return false;
4705 if (
fAxis)
return true;
4716 if (!strcmp(leaf->
GetTypeName(),
"Int_t"))
return true;
4717 if (!strcmp(leaf->
GetTypeName(),
"Short_t"))
return true;
4718 if (!strcmp(leaf->
GetTypeName(),
"UInt_t"))
return true;
4719 if (!strcmp(leaf->
GetTypeName(),
"UShort_t"))
return true;
4720 if (!strcmp(leaf->
GetTypeName(),
"Bool_t"))
return true;
4721 if (!strcmp(leaf->
GetTypeName(),
"Char_t"))
return true;
4722 if (!strcmp(leaf->
GetTypeName(),
"UChar_t"))
return true;
4723 if (!strcmp(leaf->
GetTypeName(),
"Long64_t"))
return true;
4724 if (!strcmp(leaf->
GetTypeName(),
"ULong64_t"))
return true;
4725 if (!strcmp(leaf->
GetTypeName(),
"string"))
return true;