54 class TStreamerElement;
80 void Debug(Int_t level,
const char *va_(fmt), ...)
86 va_start(ap,va_(fmt));
87 ErrorHandler(kInfo,
"TTreeProxyGenerator",va_(fmt), ap);
94 Bool_t AreDifferent(
const TString& from,
const TString& to)
96 FILE *left = fopen(from.Data(),
"r");
97 FILE *right = fopen(to.Data(),
"r");
100 char rightbuffer[256];
102 char *lvalue,*rvalue;
104 Bool_t areEqual = kTRUE;
107 lvalue = fgets(leftbuffer,
sizeof(leftbuffer), left);
108 rvalue = fgets(rightbuffer,
sizeof(rightbuffer), right);
110 if (lvalue&&rvalue) {
111 if (strstr(lvalue,
"by ROOT version")) {
114 areEqual = areEqual && (0 == strncmp(lvalue,rvalue,
sizeof(leftbuffer)));
117 if (lvalue&&!rvalue) areEqual = kFALSE;
118 if (rvalue&&!lvalue) areEqual = kFALSE;
120 }
while(areEqual && lvalue && rvalue);
132 TString GetArrayType(TStreamerElement *element,
const char *subtype,
133 TTreeProxyGenerator::EContainer container)
137 if (element->InheritsFrom(TStreamerBasicPointer::Class())) {
138 TStreamerBasicPointer * elem = (TStreamerBasicPointer*)element;
139 const char *countname = elem->GetCountName();
140 if (countname && strlen(countname)>0) ndim = 1;
142 ndim += element->GetArrayDim();
145 if (container == TTreeProxyGenerator::kClones) {
147 }
else if (container == TTreeProxyGenerator::kSTL) {
156 }
else if (ndim==1) {
165 result +=
"ArrayProxy<";
166 for(Int_t ind = ndim - 2; ind > 0; --ind) {
167 result +=
"TMultiArrayType<";
169 result +=
"TArrayType<";
170 result += element->GetTypeName();
172 result += element->GetMaxIndex(ndim-1);
174 for(Int_t ind = ndim - 2; ind > 0; --ind) {
176 result += element->GetMaxIndex(ind);
209 TTreeProxyGenerator::TTreeProxyGenerator(TTree* tree,
211 const char *fileprefix,
212 const char *option, UInt_t maxUnrolling) :
213 TTreeGeneratorBase(tree, option),
214 fMaxDatamemberType(2),
220 fMaxUnrolling(maxUnrolling),
221 fCurrentListOfTopProxies(&fListOfTopProxies)
232 TTreeProxyGenerator::TTreeProxyGenerator(TTree* tree,
233 const char *script,
const char *cutscript,
234 const char *fileprefix,
235 const char *option, UInt_t maxUnrolling) :
236 TTreeGeneratorBase(tree, option),
237 fMaxDatamemberType(2),
239 fCutScript(cutscript),
243 fMaxUnrolling(maxUnrolling),
244 fCurrentListOfTopProxies(&fListOfTopProxies)
255 Bool_t TTreeProxyGenerator::NeedToEmulate(TClass *cl, UInt_t )
259 return cl!=0 && cl->TestBit(TClass::kIsEmulation);
262 TBranchProxyClassDescriptor*
263 TTreeProxyGenerator::AddClass( TBranchProxyClassDescriptor* desc )
267 if (desc==0)
return 0;
269 TBranchProxyClassDescriptor *existing =
270 (TBranchProxyClassDescriptor*)fListOfClasses(desc->GetName());
274 if (! existing->IsEquivalent( desc ) ) {
275 TString newname = desc->GetRawSymbol();
280 desc->SetName(newname);
281 existing = (TBranchProxyClassDescriptor*)fListOfClasses(desc->GetName());
288 fListOfClasses.Add(desc);
292 void TTreeProxyGenerator::AddFriend( TFriendProxyDescriptor* desc )
298 TFriendProxyDescriptor *existing =
299 (TFriendProxyDescriptor*)fListOfFriends(desc->GetName());
303 if (! existing->IsEquivalent( desc ) ) {
304 TString newname = desc->GetName();
309 desc->SetName(newname);
310 existing = (TFriendProxyDescriptor*)fListOfFriends(desc->GetName());
314 desc->SetDuplicate();
320 TString basetitle = desc->GetTitle();
321 TIter next( &fListOfFriends );
322 while ( (existing = (TFriendProxyDescriptor*)next()) ) {
323 if (strcmp(existing->GetTitle(),desc->GetTitle())==0) {
325 TString newtitle = basetitle;
330 desc->SetTitle(newtitle);
333 next = &fListOfFriends;
337 fListOfFriends.Add(desc);
340 void TTreeProxyGenerator::AddForward(
const char *classname )
344 TObject *obj = fListOfForwards.FindObject(classname);
347 if (strstr(classname,
"<")!=0) {
351 if (gDebug>=6) Warning(
"AddForward",
"Forward declaration of templated class not implemented yet.");
352 }
else if (strcmp(classname,
"string")==0) {
355 fListOfForwards.Add(
new TNamed(classname,Form(
"class %s;\n",classname)));
360 void TTreeProxyGenerator::AddForward(TClass *cl)
364 if (cl) AddForward(cl->GetName());
367 void TTreeProxyGenerator::AddPragma(
const char *pragma_text)
371 TIter i( &fListOfPragmas );
372 for(TObjString *n = (TObjString*) i(); n; n = (TObjString*)i() ) {
373 if (pragma_text == n->GetString()) {
378 fListOfPragmas.Add(
new TObjString( pragma_text ) );
382 void TTreeProxyGenerator::AddDescriptor(TBranchProxyDescriptor *desc)
387 TBranchProxyDescriptor *existing =
388 (TBranchProxyDescriptor*)((*fCurrentListOfTopProxies)(desc->GetName()));
390 Warning(
"TTreeProxyGenerator",
"The branch name \"%s\" is duplicated. Only the first instance \n"
391 "\twill be available directly. The other instance(s) might be available via their complete name\n"
392 "\t(including the name of their mother branche's name).",desc->GetName());
394 fCurrentListOfTopProxies->Add(desc);
395 UInt_t len = strlen(desc->GetTypeName());
396 if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
401 void TTreeProxyGenerator::AddMissingClassAsEnum(
const char *clname, Bool_t isscope)
406 if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
408 TObject *obj = fListOfForwards.FindObject(clname);
412 if (clname[strlen(clname)-1]==
'>') {
414 fListOfForwards.Add(
new TNamed(clname,TString::Format(
"template <> class %s { public: operator int() { return 0; } };\n", clname).Data()));
415 }
else if (isscope) {
420 fListOfForwards.Add(
new TNamed(clname,TString::Format(
"enum %s { kDefault_%s };\n", clname, clname).Data()));
425 void TTreeProxyGenerator::CheckForMissingClass(
const char *clname)
430 UInt_t len = strlen(clname);
435 for (UInt_t i = 0; i < len; ++i) {
438 if (nest == 0 && clname[i+1] ==
':') {
439 TString incName(clname, i);
440 AddMissingClassAsEnum(incName.Data(), kTRUE);
446 if (nest == 1) last = i + 1;
449 if (nest == 0)
return;
452 if ((clname[i] ==
',' && nest == 1) || (clname[i] ==
'>' && nest == 0)) {
453 TString incName(clname + last, i - last);
454 incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
455 if (clname[i] ==
'>' && nest == 1) incName.Append(
">");
457 if (isdigit(incName[0])) {
460 AddMissingClassAsEnum(incName.Data(),kFALSE);
466 AddMissingClassAsEnum(TClassEdit::ShortType(clname, TClassEdit::kDropTrailStar | TClassEdit::kLong64).c_str(),kFALSE);
469 UInt_t TTreeProxyGenerator::AnalyzeBranches(UInt_t level,TBranchProxyClassDescriptor *topdesc,
470 TBranchElement *branch, TVirtualStreamerInfo *info)
475 if (info==0) info = branch->GetInfo();
477 TIter branches( branch->GetListOfBranches() );
479 return AnalyzeBranches( level, topdesc, branches, info );
482 UInt_t TTreeProxyGenerator::AnalyzeBranches(UInt_t level,
483 TBranchProxyClassDescriptor *topdesc,
485 TVirtualStreamerInfo *info)
509 EContainer container = kNone;
511 TString proxyTypeName;
512 TBranchProxyClassDescriptor::ELocation outer_isclones = TBranchProxyClassDescriptor::kOut;
513 TString containerName;
514 TString subBranchPrefix;
515 Bool_t skipped =
false;
518 TIter peek = branches;
519 TBranchElement *branch = (TBranchElement*)peek();
520 if (topdesc && topdesc->IsClones()) {
523 outer_isclones = TBranchProxyClassDescriptor::kClones;
524 containerName =
"TClonesArray";
525 }
else if (topdesc && topdesc->IsSTL()) {
528 outer_isclones = TBranchProxyClassDescriptor::kSTL;
529 containerName = topdesc->GetContainerName();
530 }
else if (!topdesc && branch && branch->GetBranchCount() == branch->GetMother()) {
531 if ( ((TBranchElement*)(branch->GetMother()))->GetType()==3) {
534 outer_isclones = TBranchProxyClassDescriptor::kClones;
535 containerName =
"TClonesArray";
539 outer_isclones = TBranchProxyClassDescriptor::kSTL;
540 containerName = branch->GetMother()->GetClassName();
542 }
else if (branch->GetType() == 3) {
543 outer_isclones = TBranchProxyClassDescriptor::kClones;
544 containerName =
"TClonesArray";
545 }
else if (branch->GetType() == 4) {
546 outer_isclones = TBranchProxyClassDescriptor::kSTL;
547 containerName = branch->GetMother()->GetSubBranch(branch)->GetClassName();
550 subBranchPrefix = topdesc->GetSubBranchPrefix();
552 TBranchElement *mom = (TBranchElement*)branch->GetMother();
553 subBranchPrefix = mom->GetName();
554 if (subBranchPrefix[subBranchPrefix.Length()-1]==
'.') {
555 subBranchPrefix.Remove(subBranchPrefix.Length()-1);
556 }
else if (mom->GetType()!=3 && mom->GetType() != 4) {
557 subBranchPrefix =
"";
561 TIter elements( info->GetElements() );
562 for( TStreamerElement *element = (TStreamerElement*)elements();
564 element = (TStreamerElement*)elements() )
566 Bool_t isBase =
false;
567 Bool_t usedBranch = kTRUE;
569 TIter peek = branches;
570 TBranchElement *branch = (TBranchElement*)peek();
574 Error(
"AnalyzeBranches",
"Ran out of branches when looking in branch %s, class %s",
575 topdesc->GetBranchName(), info->GetName());
577 Error(
"AnalyzeBranches",
"Ran out of branches when looking in class %s, element %s",
578 info->GetName(),element->GetName());
583 if (info->GetClass()->GetCollectionProxy() && strcmp(element->GetName(),
"This")==0) {
588 if (element->GetType()==-1) {
593 TString branchname = branch->GetName();
594 TString branchEndname;
596 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
597 if (leaf && outer_isclones == TBranchProxyClassDescriptor::kOut
598 && !(branch->GetType() == 3 || branch->GetType() == 4)) branchEndname = leaf->GetName();
599 else branchEndname = branch->GetName();
601 pos = branchEndname.Index(
".");
603 if (subBranchPrefix.Length() &&
604 branchEndname.BeginsWith( subBranchPrefix ) ) {
606 branchEndname.Remove(0,subBranchPrefix.Length()+1);
611 Bool_t ispointer =
false;
612 switch(element->GetType()) {
614 case TVirtualStreamerInfo::kBool: { proxyTypeName =
"T" + middle +
"BoolProxy";
break; }
615 case TVirtualStreamerInfo::kChar: { proxyTypeName =
"T" + middle +
"CharProxy";
break; }
616 case TVirtualStreamerInfo::kShort: { proxyTypeName =
"T" + middle +
"ShortProxy";
break; }
617 case TVirtualStreamerInfo::kInt: { proxyTypeName =
"T" + middle +
"IntProxy";
break; }
618 case TVirtualStreamerInfo::kLong: { proxyTypeName =
"T" + middle +
"LongProxy";
break; }
619 case TVirtualStreamerInfo::kLong64: { proxyTypeName =
"T" + middle +
"Long64Proxy";
break; }
620 case TVirtualStreamerInfo::kFloat: { proxyTypeName =
"T" + middle +
"FloatProxy";
break; }
621 case TVirtualStreamerInfo::kFloat16: { proxyTypeName =
"T" + middle +
"Float16Proxy";
break; }
622 case TVirtualStreamerInfo::kDouble: { proxyTypeName =
"T" + middle +
"DoubleProxy";
break; }
623 case TVirtualStreamerInfo::kDouble32:{ proxyTypeName =
"T" + middle +
"Double32Proxy";
break; }
624 case TVirtualStreamerInfo::kUChar: { proxyTypeName =
"T" + middle +
"UCharProxy";
break; }
625 case TVirtualStreamerInfo::kUShort: { proxyTypeName =
"T" + middle +
"UShortProxy";
break; }
626 case TVirtualStreamerInfo::kUInt: { proxyTypeName =
"T" + middle +
"UIntProxy";
break; }
627 case TVirtualStreamerInfo::kULong: { proxyTypeName =
"T" + middle +
"ULongProxy";
break; }
628 case TVirtualStreamerInfo::kULong64: { proxyTypeName =
"T" + middle +
"ULong64Proxy";
break; }
629 case TVirtualStreamerInfo::kBits: { proxyTypeName =
"T" + middle +
"UIntProxy";
break; }
631 case TVirtualStreamerInfo::kCharStar: { proxyTypeName = GetArrayType(element,
"Char",container);
break; }
634 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { proxyTypeName = GetArrayType(element,
"Bool",container );
break; }
635 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { proxyTypeName = GetArrayType(element,
"Char",container );
break; }
636 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { proxyTypeName = GetArrayType(element,
"Short",container );
break; }
637 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { proxyTypeName = GetArrayType(element,
"Int",container );
break; }
638 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { proxyTypeName = GetArrayType(element,
"Long",container );
break; }
639 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { proxyTypeName = GetArrayType(element,
"Long64",container );
break; }
640 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { proxyTypeName = GetArrayType(element,
"Float",container );
break; }
641 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { proxyTypeName = GetArrayType(element,
"Float16",container );
break; }
642 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { proxyTypeName = GetArrayType(element,
"Double",container );
break; }
643 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ proxyTypeName = GetArrayType(element,
"Double32",container );
break; }
644 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { proxyTypeName = GetArrayType(element,
"UChar",container );
break; }
645 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { proxyTypeName = GetArrayType(element,
"UShort",container );
break; }
646 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { proxyTypeName = GetArrayType(element,
"UInt",container );
break; }
647 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { proxyTypeName = GetArrayType(element,
"ULong",container );
break; }
648 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { proxyTypeName = GetArrayType(element,
"ULong64",container );
break; }
649 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { proxyTypeName = GetArrayType(element,
"UInt",container );
break; }
652 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { proxyTypeName = GetArrayType(element,
"Bool",container );
break; }
653 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { proxyTypeName = GetArrayType(element,
"Char",container );
break; }
654 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { proxyTypeName = GetArrayType(element,
"Short",container );
break; }
655 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { proxyTypeName = GetArrayType(element,
"Int",container );
break; }
656 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { proxyTypeName = GetArrayType(element,
"Long",container );
break; }
657 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { proxyTypeName = GetArrayType(element,
"Long64",container );
break; }
658 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { proxyTypeName = GetArrayType(element,
"Float",container );
break; }
659 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { proxyTypeName = GetArrayType(element,
"Float16",container );
break; }
660 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { proxyTypeName = GetArrayType(element,
"Double",container );
break; }
661 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ proxyTypeName = GetArrayType(element,
"Double32",container );
break; }
662 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { proxyTypeName = GetArrayType(element,
"UChar",container );
break; }
663 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { proxyTypeName = GetArrayType(element,
"UShort",container );
break; }
664 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { proxyTypeName = GetArrayType(element,
"UInt",container );
break; }
665 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { proxyTypeName = GetArrayType(element,
"ULong",container );
break; }
666 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { proxyTypeName = GetArrayType(element,
"ULong64",container );
break; }
667 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { proxyTypeName = GetArrayType(element,
"UInt",container );
break; }
670 case TVirtualStreamerInfo::kCounter: { proxyTypeName =
"T" + middle +
"IntProxy";
break; }
673 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectp:
674 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectP:
675 case TVirtualStreamerInfo::kObjectp:
676 case TVirtualStreamerInfo::kObjectP:
677 case TVirtualStreamerInfo::kAnyp:
678 case TVirtualStreamerInfo::kAnyP:
679 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectp:
680 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectP:
683 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObject:
684 case TVirtualStreamerInfo::kObject:
685 case TVirtualStreamerInfo::kTString:
686 case TVirtualStreamerInfo::kTNamed:
687 case TVirtualStreamerInfo::kTObject:
688 case TVirtualStreamerInfo::kAny:
689 case TVirtualStreamerInfo::kBase:
690 case TVirtualStreamerInfo::kSTL: {
691 TClass *cl = element->GetClassPointer();
694 proxyTypeName = Form(
"T%sObjProxy<%s >", middle.Data(), cl->GetName());
695 TString cname = cl->GetName();
696 TBranchProxyClassDescriptor::ELocation isclones = outer_isclones;
697 if (cl==TClonesArray::Class()) {
698 isclones = TBranchProxyClassDescriptor::kClones;
699 cname = GetContainedClassName(branch, element, ispointer);
700 containerName =
"TClonesArray";
701 }
else if (cl->GetCollectionProxy()) {
702 isclones = TBranchProxyClassDescriptor::kSTL;
703 containerName = cl->GetName();
704 TClass *valueClass = cl->GetCollectionProxy()->GetValueClass();
705 if (valueClass) cname = valueClass->GetName();
707 CheckForMissingClass(cname);
708 proxyTypeName = Form(
"TStlSimpleProxy<%s >", cl->GetName());
710 if (!cl->IsLoaded()) AddPragma(Form(
"#pragma link C++ class %s;\n", cl->GetName()));
714 TBranch *parent = branch->GetMother()->GetSubBranch(branch);
715 TVirtualStreamerInfo *objInfo = 0;
716 if (branch->GetListOfBranches()->GetEntries()) {
717 objInfo = ((TBranchElement*)branch->GetListOfBranches()->At(0))->GetInfo();
719 objInfo = branch->GetInfo();
721 if (element->IsBase()) {
725 if (cl == TObject::Class() && info->GetClass()->CanIgnoreTObjectStreamer())
730 TBranchProxyClassDescriptor *cldesc = 0;
732 if (branchEndname == element->GetName()) {
735 if (branch->GetListOfBranches()->GetEntries() == 0) {
739 TBranchProxyClassDescriptor *local_cldesc = 0;
741 TVirtualStreamerInfo *binfo = branch->GetInfo();
742 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
743 binfo = cl->GetStreamerInfo();
745 local_cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), binfo,
750 TStreamerElement *elem = 0;
752 TIter next(binfo->GetElements());
753 while( (elem = (TStreamerElement*)next()) ) {
754 AnalyzeElement(branch,elem,level+1,local_cldesc,
"");
757 if (NeedToEmulate(cl,0)) {
758 proxyTypeName = local_cldesc->GetName();
759 local_cldesc = AddClass(local_cldesc);
764 Int_t pos = branchname.Last(
'.');
766 branchname.Remove(pos);
768 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
769 cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
772 isclones, branch->GetSplitLevel(),
774 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
779 Int_t pos = branchname.Last(
'.');
781 branchname.Remove(pos);
783 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
784 objInfo = GetBaseClass( element );
789 cl = objInfo->GetClass();
790 cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
793 isclones, branch->GetSplitLevel(),
796 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
799 TBranchProxyClassDescriptor *added = AddClass(cldesc);
800 if (added) proxyTypeName = added->GetName();
803 TBranchProxyClassDescriptor *cldesc = 0;
805 if (branchEndname == element->GetName()) {
808 if (branch->GetListOfBranches()->GetEntries() == 0) {
812 TBranchProxyClassDescriptor *local_cldesc = 0;
814 TVirtualStreamerInfo *binfo = branch->GetInfo();
815 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
816 binfo = cl->GetStreamerInfo();
818 local_cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), binfo,
823 TStreamerElement *elem = 0;
825 TIter next(binfo->GetElements());
826 while( (elem = (TStreamerElement*)next()) ) {
827 AnalyzeElement(branch,elem,level+1,local_cldesc,
"");
830 if (NeedToEmulate(cl,0)) {
831 proxyTypeName = local_cldesc->GetName();
832 local_cldesc = AddClass(local_cldesc);
837 if (isclones != TBranchProxyClassDescriptor::kOut) {
839 cl = TClass::GetClass(cname);
840 objInfo = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
842 cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
845 isclones, branch->GetSplitLevel(),
847 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
852 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
853 if (local_prefix.Length()) local_prefix +=
".";
854 local_prefix += element->GetName();
855 objInfo = branch->GetInfo();
856 Int_t pos = branchname.Last(
'.');
858 branchname.Remove(pos);
860 if (isclones != TBranchProxyClassDescriptor::kOut) {
862 cl = TClass::GetClass(cname);
863 objInfo = GetStreamerInfo(branch, branches, cl);
865 cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
868 isclones, branch->GetSplitLevel(),
872 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
875 TBranchProxyClassDescriptor *added = AddClass(cldesc);
876 if (added) proxyTypeName = added->GetName();
886 Error(
"AnalyzeBranch",
887 "Unsupported type for %s (%d).",
888 branch->GetName(),element->GetType());
892 TString dataMemberName = element->GetName();
894 topdesc->AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
895 proxyTypeName, branchname,
true, skipped ), isBase );
897 dataMemberName.Prepend(prefix);
898 AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
899 proxyTypeName, branchname,
true, skipped ) );
910 UInt_t TTreeProxyGenerator::AnalyzeOldLeaf(TLeaf *leaf, UInt_t ,
911 TBranchProxyClassDescriptor *topdesc)
916 if (leaf->IsA()==TLeafObject::Class()) {
917 Error(
"AnalyzeOldLeaf",
"TLeafObject not supported yet");
921 TString leafTypeName = leaf->GetTypeName();
922 Int_t pos = leafTypeName.Last(
'_');
923 if (pos!=-1) leafTypeName.Remove(pos);
929 std::vector<Int_t> maxDim;
933 TString temp = leaf->GetName();
934 pos = temp.Index(
"[");
936 if (pos) temp.Remove(0,pos);
937 dimensions.Append(temp);
939 temp = leaf->GetTitle();
940 pos = temp.Index(
"[");
942 if (pos) temp.Remove(0,pos);
943 dimensions.Append(temp);
946 Int_t dimlen = dimensions.Length();
949 const char *current = dimensions.Data();
955 if (current[0] ==
']') {
956 maxDim.push_back(-1);
958 scanindex = sscanf(current,
"%d",&index);
960 maxDim.push_back(index);
962 maxDim.push_back(-2);
966 current = (
char*)strstr( current,
"[" );
975 if (dim == 0 && leaf->IsA() == TLeafC::Class()) {
984 type += leafTypeName;
990 type += leafTypeName;
995 type =
"TArrayProxy<";
996 for(Int_t ind = dim - 2; ind > 0; --ind) {
997 type +=
"TMultiArrayType<";
999 type +=
"TArrayType<";
1000 type += leaf->GetTypeName();
1002 type += maxDim[dim-1];
1004 for(Int_t ind = dim - 2; ind > 0; --ind) {
1006 type += maxDim[ind];
1014 TString branchName = leaf->GetBranch()->GetName();
1015 TString dataMemberName = leaf->GetName();
1018 topdesc->AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
1021 true,
false, true ),
1024 AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
1027 true,
false, true ) );
1034 UInt_t TTreeProxyGenerator::AnalyzeOldBranch(TBranch *branch, UInt_t level,
1035 TBranchProxyClassDescriptor *topdesc)
1043 UInt_t extraLookedAt = 0;
1046 TString branchName = branch->GetName();
1048 TObjArray *leaves = branch->GetListOfLeaves();
1049 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
1054 TString type =
"unknown";
1055 TBranchProxyClassDescriptor *cldesc = AddClass(
new TBranchProxyClassDescriptor(branch->GetName()) );
1057 type = cldesc->GetName();
1059 for(
int l=0;l<nleaves;l++) {
1060 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1061 extraLookedAt += AnalyzeOldLeaf(leaf,level+1,cldesc);
1065 TString dataMemberName = branchName;
1068 topdesc->AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
1070 branchName.Data() ),
1074 AddDescriptor(
new TBranchProxyDescriptor( dataMemberName.Data(),
1076 branchName.Data() ) );
1081 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
1082 extraLookedAt += AnalyzeOldLeaf(leaf,level,topdesc);
1087 return extraLookedAt;
1091 void TTreeProxyGenerator::AnalyzeTree(TTree *tree)
1095 TIter next( tree->GetListOfBranches() );
1097 while ( (branch = (TBranch*)next()) ) {
1098 TVirtualStreamerInfo *info = 0;
1099 const char *branchname = branch->GetName();
1100 const char *classname = branch->GetClassName();
1101 if (classname && strlen(classname)) {
1102 AddForward( classname );
1103 AddHeader( classname );
1106 TBranchProxyClassDescriptor *desc = 0;
1107 TClass *cl = TClass::GetClass(classname);
1108 TString type =
"unknown";
1110 TBranchProxyClassDescriptor::ELocation isclones = TBranchProxyClassDescriptor::kOut;
1111 TString containerName =
"";
1112 if (cl==TClonesArray::Class()) {
1113 isclones = TBranchProxyClassDescriptor::kClones;
1114 containerName =
"TClonesArray";
1115 if (branch->IsA()==TBranchElement::Class()) {
1116 const char *cname = ((TBranchElement*)branch)->GetClonesName();
1117 TClass *ncl = TClass::GetClass(cname);
1120 info = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
1122 Error(
"AnalyzeTree",
1123 "Introspection of TClonesArray in older file not implemented yet.");
1126 TClonesArray **ptr = (TClonesArray**)branch->GetAddress();
1127 TClonesArray *clones = 0;
1129 clones =
new TClonesArray;
1130 branch->SetAddress(&clones);
1133 branch->GetEntry(0);
1134 TClass *ncl = *ptr ? (*ptr)->GetClass() : 0;
1138 Error(
"AnalyzeTree",
1139 "Introspection of TClonesArray for %s failed.",branch->GetName());
1142 }
else if (cl->GetCollectionProxy()) {
1143 isclones = TBranchProxyClassDescriptor::kSTL;
1144 containerName = cl->GetName();
1145 if (cl->GetCollectionProxy()->GetValueClass()) {
1146 cl = cl->GetCollectionProxy()->GetValueClass();
1148 CheckForMissingClass(cl->GetName());
1149 type = Form(
"TStlSimpleProxy<%s >", cl->GetName());
1151 if (!cl->IsLoaded()) AddPragma(Form(
"#pragma link C++ class %s;\n", cl->GetName()));
1152 AddDescriptor(
new TBranchProxyDescriptor( branchname, type, branchname ) );
1157 if (NeedToEmulate(cl,0) || branch->GetListOfBranches()->GetEntries() || branch->GetSplitLevel() || fMaxUnrolling) {
1158 TBranchElement *be =
dynamic_cast<TBranchElement*
>(branch);
1159 TVirtualStreamerInfo *beinfo = (be && isclones == TBranchProxyClassDescriptor::kOut)
1160 ? be->GetInfo() : cl->GetStreamerInfo();
1161 desc =
new TBranchProxyClassDescriptor(cl->GetName(), beinfo, branchname,
1162 isclones, branch->GetSplitLevel(),containerName);
1165 type = Form(
"TObjProxy<%s >",cl->GetName());
1170 if ( branch->GetListOfBranches()->GetEntries() == 0 ) {
1176 TVirtualStreamerInfo *cinfo = cl->GetStreamerInfo();
1177 TStreamerElement *elem = 0;
1179 TIter cnext(cinfo->GetElements());
1180 while( (elem = (TStreamerElement*)cnext()) ) {
1181 AnalyzeElement(branch,elem,1,desc,
"");
1184 desc = AddClass(desc);
1186 type = desc->GetName();
1188 TString dataMemberName = branchname;
1190 AddDescriptor(
new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1194 AddDescriptor(
new TBranchProxyDescriptor( branch->GetName(),
1197 true,
false, false ) );
1202 AnalyzeOldBranch(branch, 0, 0);
1209 TIter subnext( branch->GetListOfBranches() );
1211 AnalyzeBranches(1,desc,dynamic_cast<TBranchElement*>(branch),info);
1213 desc = AddClass(desc);
1215 type = desc->GetName();
1216 TString dataMemberName = branchname;
1217 AddDescriptor(
new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1219 if ( branchname[strlen(branchname)-1] !=
'.' ) {
1222 AnalyzeBranches(1,0,dynamic_cast<TBranchElement*>(branch),info);
1231 if (tree->GetListOfFriends()) {
1235 TIter nextfriend(tree->GetListOfFriends());
1236 while ((fe = (TFriendElement*)nextfriend())) {
1237 TTree *t = fe->GetTree();
1238 TFriendProxyDescriptor *desc;
1239 desc =
new TFriendProxyDescriptor(t->GetName(), fe->GetName(), count);
1243 fCurrentListOfTopProxies = desc->GetListOfTopProxies();
1249 fCurrentListOfTopProxies = &fListOfTopProxies;
1252 void TTreeProxyGenerator::AnalyzeElement(TBranch *branch, TStreamerElement *element,
1253 UInt_t level, TBranchProxyClassDescriptor *topdesc,
1259 TString dataMemberName;
1260 TString pxDataMemberName;
1264 Bool_t isBase =
false;
1267 TBranchProxyClassDescriptor::ELocation isclones = TBranchProxyClassDescriptor::kOut;
1268 TString containerName;
1269 EContainer container = kNone;
1271 if (topdesc->IsClones()) {
1272 container = kClones;
1274 isclones = TBranchProxyClassDescriptor::kClones;
1275 containerName =
"TClonesArray";
1276 }
else if (topdesc->IsSTL()) {
1279 isclones = TBranchProxyClassDescriptor::kSTL;
1280 containerName = topdesc->GetContainerName();
1284 if (!element)
return;
1286 if (strcmp(element->GetName(),
"This")==0) {
1287 TClass *cl = element->GetClassPointer();
1288 containerName = cl->GetName();
1289 cl = cl->GetCollectionProxy()->GetValueClass();
1300 if (level<=fMaxUnrolling) {
1304 if (cl && cl->CanSplit()) {
1310 TVirtualStreamerInfo *info = cl->GetStreamerInfo();
1311 TStreamerElement *elem = 0;
1313 TString subpath = path;
1314 if (subpath.Length()>0) subpath +=
".";
1315 subpath += dataMemberName;
1317 TIter next(info->GetElements());
1318 while( (elem = (TStreamerElement*)next()) ) {
1319 AnalyzeElement(branch, elem, level+1, topdesc, subpath.Data());
1329 if (element->GetType()==-1) {
1336 switch(element->GetType()) {
1338 case TVirtualStreamerInfo::kBool: { type =
"T" + middle +
"BoolProxy";
break; }
1339 case TVirtualStreamerInfo::kChar: { type =
"T" + middle +
"CharProxy";
break; }
1340 case TVirtualStreamerInfo::kShort: { type =
"T" + middle +
"ShortProxy";
break; }
1341 case TVirtualStreamerInfo::kInt: { type =
"T" + middle +
"IntProxy";
break; }
1342 case TVirtualStreamerInfo::kLong: { type =
"T" + middle +
"LongProxy";
break; }
1343 case TVirtualStreamerInfo::kLong64: { type =
"T" + middle +
"Long64Proxy";
break; }
1344 case TVirtualStreamerInfo::kFloat: { type =
"T" + middle +
"FloatProxy";
break; }
1345 case TVirtualStreamerInfo::kFloat16: { type =
"T" + middle +
"Float16Proxy";
break; }
1346 case TVirtualStreamerInfo::kDouble: { type =
"T" + middle +
"DoubleProxy";
break; }
1347 case TVirtualStreamerInfo::kDouble32:{ type =
"T" + middle +
"Double32Proxy";
break; }
1348 case TVirtualStreamerInfo::kUChar: { type =
"T" + middle +
"UCharProxy";
break; }
1349 case TVirtualStreamerInfo::kUShort: { type =
"T" + middle +
"UShortProxy";
break; }
1350 case TVirtualStreamerInfo::kUInt: { type =
"T" + middle +
"UIntProxy";
break; }
1351 case TVirtualStreamerInfo::kULong: { type =
"T" + middle +
"ULongProxy";
break; }
1352 case TVirtualStreamerInfo::kULong64: { type =
"T" + middle +
"ULong64Proxy";
break; }
1353 case TVirtualStreamerInfo::kBits: { type =
"T" + middle +
"UIntProxy";
break; }
1355 case TVirtualStreamerInfo::kCharStar: { type = GetArrayType(element,
"Char",container);
break; }
1358 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,
"Bool",container );
break; }
1359 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,
"Char",container );
break; }
1360 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,
"Short",container );
break; }
1361 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,
"Int",container );
break; }
1362 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,
"Long",container );
break; }
1363 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,
"Long64",container );
break; }
1364 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,
"Float",container );
break; }
1365 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,
"Float16",container );
break; }
1366 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,
"Double",container );
break; }
1367 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,
"Double32",container );
break; }
1368 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,
"UChar",container );
break; }
1369 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,
"UShort",container );
break; }
1370 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,
"UInt",container );
break; }
1371 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,
"ULong",container );
break; }
1372 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,
"ULong64",container );
break; }
1373 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,
"UInt",container );
break; }
1376 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,
"Bool",container );
break; }
1377 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,
"Char",container );
break; }
1378 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,
"Short",container );
break; }
1379 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,
"Int",container );
break; }
1380 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,
"Long",container );
break; }
1381 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,
"Long64",container );
break; }
1382 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,
"Float",container );
break; }
1383 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,
"Float16",container );
break; }
1384 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,
"Double",container );
break; }
1385 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,
"Double32",container );
break; }
1386 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,
"UChar",container );
break; }
1387 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,
"UShort",container );
break; }
1388 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,
"UInt",container );
break; }
1389 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,
"ULong",container );
break; }
1390 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,
"ULong64",container );
break; }
1391 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,
"UInt",container );
break; }
1394 case TVirtualStreamerInfo::kCounter: { type =
"T" + middle +
"IntProxy";
break; }
1397 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectp:
1398 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObjectP:
1399 case TVirtualStreamerInfo::kObjectp:
1400 case TVirtualStreamerInfo::kObjectP:
1401 case TVirtualStreamerInfo::kAnyp:
1402 case TVirtualStreamerInfo::kAnyP:
1403 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectp:
1404 case TVirtualStreamerInfo::kSTL + TVirtualStreamerInfo::kObjectP:
1407 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kObject:
1408 case TVirtualStreamerInfo::kObject:
1409 case TVirtualStreamerInfo::kTString:
1410 case TVirtualStreamerInfo::kTNamed:
1411 case TVirtualStreamerInfo::kTObject:
1412 case TVirtualStreamerInfo::kAny:
1413 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kAny:
1414 case TVirtualStreamerInfo::kSTL:
1415 case TVirtualStreamerInfo::kBase: {
1416 TClass *cl = element->GetClassPointer();
1418 type = Form(
"T%sObjProxy<%s >",
1419 middle.Data(),cl->GetName());
1420 cname = cl->GetName();
1421 if (cl==TClonesArray::Class()) {
1422 isclones = TBranchProxyClassDescriptor::kClones;
1423 containerName =
"TClonesArray";
1425 Long64_t i = branch->GetTree()->GetReadEntry();
1427 branch->GetEntry(i);
1435 TString fullpath = branch->GetName();
1437 if (path && strlen(path)>0) fullpath.Append(path).Append(
".");
1438 fullpath += element->GetName();
1440 TTreeFormula *formula =
new TTreeFormula(
"clones",fullpath,branch->GetTree());
1442 TFormLeafInfo *leafinfo = formula->GetLeafInfo(0);
1443 TLeaf *leaf = formula->GetLeaf(0);
1444 R__ASSERT(leaf && leafinfo);
1446 arr = (TClonesArray*)leafinfo->GetLocalValuePointer(leaf,0);
1455 if (arr) cname = arr->GetClass()->GetName();
1457 if (cname.Length()==0) {
1458 Error(
"AnalyzeTree",
1459 "Introspection of TClonesArray in older file not implemented yet.");
1462 }
else if (cl->GetCollectionProxy()) {
1463 isclones = TBranchProxyClassDescriptor::kSTL;
1464 containerName = cl->GetName();
1465 cl = cl->GetCollectionProxy()->GetValueClass();
1468 else Error(
"AnalyzeTree",
"missing class for %s.",branch->GetName());
1469 if (element->IsA()==TStreamerBase::Class()) {
1479 Error(
"AnalyzeTree",
1480 "Unsupported type for %s %s %d",
1481 branch->GetName(), element->GetName(), element->GetType());
1485 dataMemberName = element->GetName();
1487 if (level<=fMaxUnrolling) {
1490 TBranchProxyClassDescriptor *cldesc;
1492 TClass *cl = TClass::GetClass(cname);
1493 if (cl && cl->CanSplit()) {
1494 cldesc =
new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1499 TVirtualStreamerInfo *info = cl->GetStreamerInfo();
1500 TStreamerElement *elem = 0;
1502 TString subpath = path;
1503 if (subpath.Length()>0) subpath +=
".";
1504 subpath += dataMemberName;
1506 TIter next(info->GetElements());
1507 while( (elem = (TStreamerElement*)next()) ) {
1508 AnalyzeElement(branch, elem, level+1, cldesc, subpath.Data());
1511 TBranchProxyClassDescriptor *added = AddClass(cldesc);
1512 if (added) type = added->GetName();
1517 pxDataMemberName = dataMemberName;
1519 topdesc->AddDescriptor(
new TBranchProxyDescriptor( pxDataMemberName.Data(), type,
1520 dataMemberName.Data(),
false),
1523 Error(
"AnalyzeTree",
"topdesc should not be null in TTreeProxyGenerator::AnalyzeElement.");
1530 void TTreeProxyGenerator::ParseOptions()
1532 TString opt = fOptionStr;
1535 if ( opt.Contains(
"nohist") ) {
1536 opt.ReplaceAll(
"nohist",
"");
1537 fOptions |= kNoHist;
1548 static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen, TClass *cl)
1550 if (!cl)
return kFALSE;
1551 if (cl->GetCollectionProxy()) {
1552 TClass *valcl = cl->GetCollectionProxy()->GetValueClass();
1554 if (!cl->IsLoaded()) gen->AddPragma(Form(
"#pragma link C++ class %s;\n", cl->GetName()));
1556 }
else if (R__AddPragmaForClass(gen, valcl)) {
1557 if (!cl->IsLoaded()) gen->AddPragma(Form(
"#pragma link C++ class %s;\n", cl->GetName()));
1561 if (cl->IsLoaded())
return kTRUE;
1572 static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen,
const char *classname)
1574 return R__AddPragmaForClass( gen, TClass::GetClass(classname) );
1581 void TTreeProxyGenerator::WriteProxy()
1583 if (fScript.Length()==0) {
1584 Error(
"WriteProxy",
"No user script has been specified.");
1588 TString fileLocation = gSystem->DirName(fScript);
1590 TString incPath = gSystem->GetIncludePath();
1591 incPath.Append(
":").Prepend(
" ");
1592 incPath.ReplaceAll(
" -I",
":");
1593 while ( incPath.Index(
" :") != -1 ) {
1594 incPath.ReplaceAll(
" :",
":");
1596 incPath.Prepend(fileLocation+
":.:");
1598 const char *filename = gSystem->Which(incPath,fScript);
1600 Error(
"WriteProxy",
"Can not find the user's script: %s",fScript.Data());
1603 const char *cutfilename = 0;
1604 if (fCutScript.Length()) {
1605 fileLocation = gSystem->DirName(fCutScript);
1606 incPath.Prepend(fileLocation+
":.:");
1607 cutfilename = gSystem->Which(incPath,fCutScript);
1608 if (cutfilename==0) {
1609 Error(
"WriteProxy",
"Can not find the user's cut script: %s",fCutScript.Data());
1615 fHeaderFileName = fPrefix;
1616 TString classname = gSystem->BaseName(fPrefix);
1619 Ssiz_t pos = classname.Last(
'.');
1621 classname.Remove(pos);
1623 fHeaderFileName.Append(
".h");
1630 Bool_t updating = kFALSE;
1631 if (gSystem->GetPathInfo( fHeaderFileName, 0, (Long_t*)0, 0, 0 ) == 0) {
1638 Bool_t ischain = fTree->InheritsFrom(TChain::Class());
1639 if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile())
1640 treefile = fTree->GetDirectory()->GetFile()->GetName();
1642 treefile =
"Memory Directory";
1644 TString scriptfunc = fScript;
1645 Ssiz_t dot_pos = scriptfunc.Last(
'.');
1646 if (dot_pos == kNPOS) {
1647 Error(
"WriteProxy",
"User's script (%s) has no extension! Nothing will be written.",scriptfunc.Data());
1649 delete [] cutfilename;
1652 scriptfunc.Replace( dot_pos, fScript.Length()-dot_pos,
"");
1653 TString scriptHeader = scriptfunc;
1654 const char * extensions[] = {
".h",
".hh",
".hpp",
".hxx",
".hPP",
".hXX" };
1657 for (i = 0; i < 6; i++ ) {
1658 TString possible = scriptHeader;
1659 possible.Append(extensions[i]);
1660 const char *name = gSystem->Which(incPath,possible);
1662 scriptHeader = possible;
1663 fListOfHeaders.Add(
new TNamed(
"script",Form(
"#include \"%s\"\n",
1664 scriptHeader.Data())));
1669 scriptfunc = gSystem->BaseName(scriptfunc);
1672 TString cutscriptfunc = fCutScript;
1674 dot_pos = cutscriptfunc.Last(
'.');
1675 cutscriptfunc.Replace( dot_pos, fCutScript.Length()-dot_pos,
"");
1676 TString cutscriptHeader = cutscriptfunc;
1678 for (i = 0; i < 6; i++ ) {
1679 TString possible = cutscriptHeader;
1680 possible.Append(extensions[i]);
1681 const char *name = gSystem->Which(incPath,possible);
1683 cutscriptHeader = possible;
1684 fListOfHeaders.Add(
new TNamed(
"cutscript",Form(
"#include \"%s\"\n",
1685 cutscriptHeader.Data())));
1690 cutscriptfunc = gSystem->BaseName(cutscriptfunc);
1694 TString tmpfilename =
".Proxy-";
1696 hf = gSystem->TempFileName(tmpfilename,
"./");
1698 hf = fopen(fHeaderFileName,
"w");
1701 Error(
"WriteProxy",
"Unable to open the file %s for writing.",
1702 updating ? tmpfilename.Data() : fHeaderFileName.Data());
1704 delete [] cutfilename;
1709 fprintf(hf,
"/////////////////////////////////////////////////////////////////////////\n");
1710 fprintf(hf,
"// This class has been automatically generated \n");
1711 fprintf(hf,
"// (at %s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
1713 fprintf(hf,
"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1714 fprintf(hf,
"// found on file: %s\n",treefile.Data());
1716 fprintf(hf,
"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1718 fprintf(hf,
"/////////////////////////////////////////////////////////////////////////\n");
1722 fprintf(hf,
"#ifndef %s_h\n",classname.Data());
1723 fprintf(hf,
"#define %s_h\n",classname.Data());
1728 fprintf(hf,
"#define R__BRANCHPROXY_GENERATOR_VERSION 2\n\n");
1729 fprintf(hf,
"// ROOT headers needed by the proxy\n");
1730 fprintf(hf,
"#include <TROOT.h>\n");
1731 fprintf(hf,
"#include <TChain.h>\n");
1732 fprintf(hf,
"#include <TFile.h>\n");
1733 fprintf(hf,
"#include <TPad.h>\n");
1734 fprintf(hf,
"#include <TH1.h>\n");
1735 fprintf(hf,
"#include <TSelector.h>\n");
1736 fprintf(hf,
"#include <TBranchProxy.h>\n");
1737 fprintf(hf,
"#include <TBranchProxyDirector.h>\n");
1738 fprintf(hf,
"#include <TBranchProxyTemplate.h>\n");
1739 fprintf(hf,
"#include <TFriendProxy.h>\n");
1740 fprintf(hf,
"using namespace ROOT::Internal;\n");
1741 fprintf(hf,
"using ROOT::Detail::TBranchProxy;\n");
1744 fprintf(hf,
"// forward declarations needed by this particular proxy\n");
1745 TIter next( &fListOfForwards );
1747 while ( (current=next()) ) {
1748 if (strstr(current->GetTitle(),
"::")==0) {
1752 fprintf(hf,
"%s",current->GetTitle());
1757 fprintf(hf,
"// Header needed by this particular proxy\n");
1758 next = &fListOfHeaders;
1760 while ( (header = next()) ) {
1761 fprintf(hf,
"%s",header->GetTitle());
1765 fprintf(hf,
"class %s_Interface {\n", scriptfunc.Data());
1766 fprintf(hf,
" // This class defines the list of methods that are directly used by %s,\n",classname.Data());
1767 fprintf(hf,
" // and that can be overloaded in the user's script\n");
1768 fprintf(hf,
"public:\n");
1769 fprintf(hf,
" void %s_Begin(TTree*) {}\n",scriptfunc.Data());
1770 fprintf(hf,
" void %s_SlaveBegin(TTree*) {}\n",scriptfunc.Data());
1771 fprintf(hf,
" Bool_t %s_Notify() { return kTRUE; }\n",scriptfunc.Data());
1772 fprintf(hf,
" Bool_t %s_Process(Long64_t) { return kTRUE; }\n",scriptfunc.Data());
1773 fprintf(hf,
" void %s_SlaveTerminate() {}\n",scriptfunc.Data());
1774 fprintf(hf,
" void %s_Terminate() {}\n",scriptfunc.Data());
1778 fprintf(hf,
"class %s : public TSelector, public %s_Interface {\n", classname.Data(), scriptfunc.Data());
1779 fprintf(hf,
"public :\n");
1780 fprintf(hf,
" TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
1781 fprintf(hf,
" TH1 *htemp; //!pointer to the histogram\n");
1782 fprintf(hf,
" TBranchProxyDirector fDirector; //!Manages the proxys\n\n");
1784 fprintf(hf,
" // Optional User methods\n");
1785 fprintf(hf,
" TClass *fClass; // Pointer to this class's description\n");
1787 if (fListOfClasses.LastIndex()>=0) {
1788 fprintf(hf,
"\n // Wrapper class for each unwounded class\n");
1789 next = &fListOfClasses;
1790 TBranchProxyClassDescriptor *clp;
1791 while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1792 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1796 if (fListOfFriends.LastIndex()>=0) {
1797 fprintf(hf,
"\n // Wrapper class for each friend TTree\n");
1798 next = &fListOfFriends;
1799 TFriendProxyDescriptor *clp;
1800 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1801 if (!clp->IsDuplicate()) clp->OutputClassDecl(hf, 3, fMaxDatamemberType);
1805 fprintf(hf,
"\n // Proxy for each of the branches, leaves and friends of the tree\n");
1806 next = &fListOfTopProxies;
1807 TBranchProxyDescriptor *data;
1808 while ( (data = (TBranchProxyDescriptor*)next()) ) {
1809 data->OutputDecl(hf, 3, fMaxDatamemberType);
1811 if (fListOfFriends.LastIndex()>=0) {
1812 next = &fListOfFriends;
1813 TFriendProxyDescriptor *clp;
1814 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1815 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1821 fprintf(hf,
" %s(TTree *tree=0) : \n",classname.Data());
1822 fprintf(hf,
" fChain(0)");
1823 fprintf(hf,
",\n htemp(0)");
1824 fprintf(hf,
",\n fDirector(tree,-1)");
1825 fprintf(hf,
",\n fClass (TClass::GetClass(\"%s\"))",classname.Data());
1826 next = &fListOfTopProxies;
1827 while ( (data = (TBranchProxyDescriptor*)next()) ) {
1828 fprintf(hf,
",\n %-*s(&fDirector,\"%s\")",
1829 fMaxDatamemberType, data->GetDataName(), data->GetBranchName());
1831 next = &fListOfFriends;
1832 TFriendProxyDescriptor *fpd;
1833 while ( (fpd = (TFriendProxyDescriptor*)next()) ) {
1834 fprintf(hf,
",\n %-*s(&fDirector,tree,%d)",
1835 fMaxDatamemberType, fpd->GetTitle(), fpd->GetIndex());
1838 fprintf(hf,
"\n { }\n");
1841 fprintf(hf,
" ~%s();\n",classname.Data());
1842 fprintf(hf,
" Int_t Version() const {return 1;}\n");
1843 fprintf(hf,
" void Begin(::TTree *tree);\n");
1844 fprintf(hf,
" void SlaveBegin(::TTree *tree);\n");
1845 fprintf(hf,
" void Init(::TTree *tree);\n");
1846 fprintf(hf,
" Bool_t Notify();\n");
1847 fprintf(hf,
" Bool_t Process(Long64_t entry);\n");
1848 fprintf(hf,
" void SlaveTerminate();\n");
1849 fprintf(hf,
" void Terminate();\n");
1851 fprintf(hf,
" ClassDef(%s,0);\n",classname.Data());
1854 fprintf(hf,
"//inject the user's code\n");
1855 fprintf(hf,
"#include \"%s\"\n",fScript.Data());
1858 fprintf(hf,
"#include \"%s\"\n",fCutScript.Data());
1864 fprintf(hf,
"#endif\n");
1867 fprintf(hf,
"#ifdef __MAKECINT__\n");
1868 if (fListOfClasses.LastIndex()>=0) {
1869 TBranchProxyClassDescriptor *clp;
1870 next = &fListOfClasses;
1871 while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1872 fprintf(hf,
"#pragma link C++ class %s::%s-;\n",classname.Data(),clp->GetName());
1873 if (clp->GetContainerName().Length()) {
1874 R__AddPragmaForClass(
this, clp->GetContainerName());
1877 next = &fListOfPragmas;
1879 while ( (prag = (TObjString*)next()) ) {
1880 fprintf(hf,
"%s",prag->String().Data());
1883 fprintf(hf,
"#pragma link C++ class %s;\n",classname.Data());
1884 fprintf(hf,
"#endif\n");
1888 fprintf(hf,
"inline %s::~%s() {\n",classname.Data(),classname.Data());
1889 fprintf(hf,
" // destructor. Clean up helpers.\n");
1893 fprintf(hf,
"inline void %s::Init(TTree *tree)\n",classname.Data());
1895 fprintf(hf,
"// Set branch addresses\n");
1896 fprintf(hf,
" if (tree == 0) return;\n");
1897 fprintf(hf,
" fChain = tree;\n");
1898 fprintf(hf,
" fDirector.SetTree(fChain);\n");
1899 fprintf(hf,
" if (htemp == 0) {\n");
1900 fprintf(hf,
" htemp = fDirector.CreateHistogram(GetOption());\n");
1902 fprintf(hf,
" htemp->SetTitle(\"%s {%s}\");\n",fScript.Data(),fCutScript.Data());
1904 fprintf(hf,
" htemp->SetTitle(\"%s\");\n",fScript.Data());
1906 fprintf(hf,
" fObject = htemp;\n");
1910 fprintf(hf,
"Bool_t %s::Notify()\n",classname.Data());
1912 fprintf(hf,
" // Called when loading a new file.\n");
1913 fprintf(hf,
" // Get branch pointers.\n");
1914 fprintf(hf,
" fDirector.SetTree(fChain);\n");
1915 fprintf(hf,
" %s_Notify();\n",scriptfunc.Data());
1917 fprintf(hf,
" return kTRUE;\n");
1923 fprintf(hf,
"inline void %s::Begin(TTree *tree)\n",classname.Data());
1925 fprintf(hf,
" // The Begin() function is called at the start of the query.\n");
1926 fprintf(hf,
" // When running with PROOF Begin() is only called on the client.\n");
1927 fprintf(hf,
" // The tree argument is deprecated (on PROOF 0 is passed).\n");
1929 fprintf(hf,
" TString option = GetOption();\n");
1930 fprintf(hf,
" %s_Begin(tree);\n",scriptfunc.Data());
1936 fprintf(hf,
"inline void %s::SlaveBegin(TTree *tree)\n",classname.Data());
1938 fprintf(hf,
" // The SlaveBegin() function is called after the Begin() function.\n");
1939 fprintf(hf,
" // When running with PROOF SlaveBegin() is called on each slave server.\n");
1940 fprintf(hf,
" // The tree argument is deprecated (on PROOF 0 is passed).\n");
1942 fprintf(hf,
" Init(tree);\n");
1944 fprintf(hf,
" %s_SlaveBegin(tree);\n",scriptfunc.Data());
1950 fprintf(hf,
"inline Bool_t %s::Process(Long64_t entry)\n",classname.Data());
1953 fprintf(hf,
" // The Process() function is called for each entry in the tree (or possibly\n"
1954 " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1955 " // specifies which entry in the currently loaded tree is to be processed.\n"
1956 " // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()\n"
1957 " // to read either all or the required parts of the data. When processing\n"
1958 " // keyed objects with PROOF, the object is already loaded and is available\n"
1959 " // via the fObject pointer.\n"
1961 " // This function should contain the \"body\" of the analysis. It can contain\n"
1962 " // simple or elaborate selection criteria, run algorithms on the data\n"
1963 " // of the event and typically fill histograms.\n\n");
1964 fprintf(hf,
" // WARNING when a selector is used with a TChain, you must use\n");
1965 fprintf(hf,
" // the pointer to the current TTree to call GetEntry(entry).\n");
1966 fprintf(hf,
" // The entry is always the local entry number in the current tree.\n");
1967 fprintf(hf,
" // Assuming that fChain is the pointer to the TChain being processed,\n");
1968 fprintf(hf,
" // use fChain->GetTree()->GetEntry(entry).\n");
1971 fprintf(hf,
" fDirector.SetReadEntry(entry);\n");
1972 if (fOptions & kNoHist) {
1974 fprintf(hf,
" if (%s()) %s();\n",cutscriptfunc.Data(),scriptfunc.Data());
1976 fprintf(hf,
" %s();\n",scriptfunc.Data());
1980 fprintf(hf,
" if (%s()) htemp->Fill(%s());\n",cutscriptfunc.Data(),scriptfunc.Data());
1982 fprintf(hf,
" htemp->Fill(%s());\n",scriptfunc.Data());
1985 fprintf(hf,
" %s_Process(entry);\n",scriptfunc.Data());
1986 fprintf(hf,
" return kTRUE;\n");
1988 fprintf(hf,
"}\n\n");
1991 fprintf(hf,
"inline void %s::SlaveTerminate()\n",classname.Data());
1993 fprintf(hf,
" // The SlaveTerminate() function is called after all entries or objects\n"
1994 " // have been processed. When running with PROOF SlaveTerminate() is called\n"
1995 " // on each slave server.");
1997 fprintf(hf,
" %s_SlaveTerminate();\n",scriptfunc.Data());
1998 fprintf(hf,
"}\n\n");
2001 fprintf(hf,
"inline void %s::Terminate()\n",classname.Data());
2003 fprintf(hf,
" // Function called at the end of the event loop.\n");
2004 fprintf(hf,
" htemp = (TH1*)fObject;\n");
2005 fprintf(hf,
" Int_t drawflag = (htemp && htemp->GetEntries()>0);\n");
2007 fprintf(hf,
" if (gPad && !drawflag && !fOption.Contains(\"goff\") && !fOption.Contains(\"same\")) {\n");
2008 fprintf(hf,
" gPad->Clear();\n");
2009 fprintf(hf,
" } else {\n");
2010 fprintf(hf,
" if (fOption.Contains(\"goff\")) drawflag = false;\n");
2011 fprintf(hf,
" if (drawflag) htemp->Draw(fOption);\n");
2013 fprintf(hf,
" %s_Terminate();\n",scriptfunc.Data());
2020 if (AreDifferent(fHeaderFileName,tmpfilename)) {
2021 gSystem->Unlink(fHeaderFileName);
2022 gSystem->Rename(tmpfilename,fHeaderFileName);
2023 }
else gSystem->Unlink(tmpfilename);
2026 delete [] cutfilename;