Logo ROOT  
Reference Guide
TTreeProxyGenerator.cxx
Go to the documentation of this file.
1// @(#)root/treeplayer:$Id$
2// Author: Philippe Canal 06/06/2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers and al. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12/*
13 TODO:
14 Have separate names for the wrapper classes in the cases of: [done]
15 clones/non clones
16 split/non split
17 split levels
18
19 Have a solution for passing top+"."+middle to the parents classes [probably done .. need testing]
20
21 Have a solution for the return by references of abstract classes [not done]
22
23 Have object inside ClonesArray properly treated! [done]
24 Why is there 2 TRef proxy classes? [done]
25
26 check why some inheritance are TObjProxy and not TPx_
27
28 Be smart enough to avoid issue about having 2 classes one unrolled and one non unrolled!
29
30 When using in interpreted mode understand why the reloading reloads the calling script and then crashes :(
31
32 CINT does not properly call the custom operators when doing return fNtrack.
33
34 CINT does not handle fMatrix[2][1] well.
35
36 The user's function in script.h are not exposed by ACLiC.
37
38 Review the method to avoid the useless refreshing of the generated file
39 - for most efficiency it would require a different name for each tree
40*/
41
42#include "TTreeProxyGenerator.h"
43
47
48#include "TList.h"
49#include "Varargs.h"
50#include <stdio.h>
51
52class TTree;
53class TBranch;
55
56#include "TClass.h"
57#include "TClassEdit.h"
58#include "TClonesArray.h"
59#include "TError.h"
60#include "TROOT.h"
61#include "TObjString.h"
62
63#include "TTreeFormula.h"
64#include "TFormLeafInfo.h"
65
66
67#include "TBranchElement.h"
68#include "TChain.h"
69#include "TFile.h"
70#include "TFriendElement.h"
71#include "TLeaf.h"
72#include "TLeafC.h"
73#include "TTree.h"
75#include "TStreamerElement.h"
76#include "TSystem.h"
77#include "TLeafObject.h"
79
80void Debug(Int_t level, const char *va_(fmt), ...)
81{
82 // Use this function in case an error occured.
83
84 if (gDebug>=level) {
85 va_list ap;
86 va_start(ap,va_(fmt));
87 ErrorHandler(kInfo,"TTreeProxyGenerator",va_(fmt), ap);
88 va_end(ap);
89 }
90}
91
92namespace {
93
94 Bool_t AreDifferent(const TString& from, const TString& to)
95 {
96 FILE *left = fopen(from.Data(),"r");
97 FILE *right = fopen(to.Data(),"r");
98
99 char leftbuffer[256];
100 char rightbuffer[256];
101
102 char *lvalue,*rvalue;
103
105
106 do {
107 lvalue = fgets(leftbuffer, sizeof(leftbuffer), left);
108 rvalue = fgets(rightbuffer, sizeof(rightbuffer), right);
109
110 if (lvalue&&rvalue) {
111 if (strstr(lvalue,"by ROOT version")) {
112 // skip the comment line with the time and date
113 } else {
114 areEqual = areEqual && (0 == strncmp(lvalue,rvalue,sizeof(leftbuffer)));
115 }
116 }
117 if (lvalue&&!rvalue) areEqual = kFALSE;
118 if (rvalue&&!lvalue) areEqual = kFALSE;
119
120 } while(areEqual && lvalue && rvalue);
121
122 fclose(left);
123 fclose(right);
124
125 return !areEqual;
126 }
127}
128
129namespace ROOT {
130namespace Internal {
131
132 TString GetArrayType(TStreamerElement *element, const char *subtype,
134 {
135 TString result;
136 int ndim = 0;
139 const char *countname = elem->GetCountName();
140 if (countname && strlen(countname)>0) ndim = 1;
141 }
142 ndim += element->GetArrayDim();
143
144 TString middle;
145 if (container == TTreeProxyGenerator::kClones) {
146 middle = "Cla";
147 } else if (container == TTreeProxyGenerator::kSTL) {
148 middle = "Stl";
149 }
150
151 if (ndim==0) {
152 result = "T";
153 result += middle;
154 result += subtype;
155 result += "Proxy";
156 } else if (ndim==1) {
157 result = "T";
158 result += middle;
159 result += "Array";
160 result += subtype;
161 result += "Proxy";
162 } else {
163 result = "T";
164 result += middle;
165 result += "ArrayProxy<";
166 for(Int_t ind = ndim - 2; ind > 0; --ind) {
167 result += "TMultiArrayType<";
168 }
169 result += "TArrayType<";
170 result += element->GetTypeName();
171 result += ",";
172 result += element->GetMaxIndex(ndim-1);
173 result += "> ";
174 for(Int_t ind = ndim - 2; ind > 0; --ind) {
175 result += ",";
176 result += element->GetMaxIndex(ind);
177 result += "> ";
178 }
179 result += ">";
180 }
181 return result;
182
183 /*
184 if (!strcmp("unsigned int", name))
185 sprintf(line, "%u", *(unsigned int *)buf);
186 else if (!strcmp("int", name))
187 sprintf(line, "%d", *(int *)buf);
188 else if (!strcmp("unsigned long", name))
189 sprintf(line, "%lu", *(unsigned long *)buf);
190 else if (!strcmp("long", name))
191 sprintf(line, "%ld", *(long *)buf);
192 else if (!strcmp("unsigned short", name))
193 sprintf(line, "%hu", *(unsigned short *)buf);
194 else if (!strcmp("short", name))
195 sprintf(line, "%hd", *(short *)buf);
196 else if (!strcmp("unsigned char", name))
197 sprintf(line, "%u", *(unsigned char *)buf);
198 else if (!strcmp("bool", name))
199 sprintf(line, "%u", *(unsigned char *)buf);
200 else if (!strcmp("char", name))
201 sprintf(line, "%d", *(char *)buf);
202 else if (!strcmp("float", name))
203 sprintf(line, "%g", *(float *)buf);
204 else if (!strcmp("double", name))
205 sprintf(line, "%g", *(double *)buf);
206 */
207 }
208
210 const char *script,
211 const char *fileprefix,
212 const char *option, UInt_t maxUnrolling) :
213 TTreeGeneratorBase(tree, option),
214 fMaxDatamemberType(2),
215 fScript(script),
216 fCutScript(),
217 fPrefix(fileprefix),
218 fHeaderFileName(),
219 fOptions(0),
220 fMaxUnrolling(maxUnrolling),
221 fCurrentListOfTopProxies(&fListOfTopProxies)
222 {
223 // Constructor.
224
225 ParseOptions();
226
228
229 WriteProxy();
230 }
231
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),
238 fScript(script),
239 fCutScript(cutscript),
240 fPrefix(fileprefix),
241 fHeaderFileName(),
242 fOptions(0),
243 fMaxUnrolling(maxUnrolling),
244 fCurrentListOfTopProxies(&fListOfTopProxies)
245 {
246 // Constructo.
247
248 ParseOptions();
249
251
252 WriteProxy();
253 }
254
256 {
257 // Return true if we should create a nested class representing this class
258
259 return cl!=0 && cl->TestBit(TClass::kIsEmulation);
260 }
261
264 {
265 // Add a Class Descriptor.
266
267 if (desc==0) return 0;
268
271
272 int count = 0;
273 while (existing) {
274 if (! existing->IsEquivalent( desc ) ) {
275 TString newname = desc->GetRawSymbol();
276 count++;
277 newname += "_";
278 newname += count;
279
280 desc->SetName(newname);
282 } else {
283 // we already have the exact same class
284 delete desc;
285 return existing;
286 }
287 }
288 fListOfClasses.Add(desc);
289 return desc;
290 }
291
293 {
294 // Add Friend descriptor.
295
296 if (desc==0) return;
297
298 TFriendProxyDescriptor *existing =
300
301 int count = 0;
302 while (existing) {
303 if (! existing->IsEquivalent( desc ) ) {
304 TString newname = desc->GetName();
305 count++;
306 newname += "_";
307 newname += count;
308
309 desc->SetName(newname);
310 existing = (TFriendProxyDescriptor*)fListOfFriends(desc->GetName());
311
312 } else {
313
314 desc->SetDuplicate();
315 break;
316 }
317 }
318
319 // Insure uniqueness of the title also.
320 TString basetitle = desc->GetTitle();
321 TIter next( &fListOfFriends );
322 while ( (existing = (TFriendProxyDescriptor*)next()) ) {
323 if (strcmp(existing->GetTitle(),desc->GetTitle())==0) {
324
325 TString newtitle = basetitle;
326 count++;
327 newtitle += "_";
328 newtitle += count;
329
330 desc->SetTitle(newtitle);
331
332 // Restart of the begining of the loop.
333 next = &fListOfFriends;
334 }
335 }
336
337 fListOfFriends.Add(desc);
338 }
339
340 void TTreeProxyGenerator::AddForward( const char *classname )
341 {
342 // Add a forward declaration request.
343
344 TObject *obj = fListOfForwards.FindObject(classname);
345 if (obj) return;
346
347 if (strstr(classname,"<")!=0) {
348 // this is a template instantiation.
349 // let's ignore it for now
350
351 if (gDebug>=6) Warning("AddForward","Forward declaration of templated class not implemented yet.");
352 } else if (strcmp(classname,"string")==0) {
353 // no need to forward declare string
354 } else {
355 fListOfForwards.Add(new TNamed(classname,Form("class %s;\n",classname)));
356 }
357 return;
358 }
359
361 {
362 // Add a forward declaration request.
363
364 if (cl) AddForward(cl->GetName());
365 }
366
367 void TTreeProxyGenerator::AddPragma(const char *pragma_text)
368 {
369 // Add a forward declaration request.
370
371 TIter i( &fListOfPragmas );
372 for(TObjString *n = (TObjString*) i(); n; n = (TObjString*)i() ) {
373 if (pragma_text == n->GetString()) {
374 return;
375 }
376 }
377
378 fListOfPragmas.Add( new TObjString( pragma_text ) );
379
380 }
381
383 {
384 // Add a branch descriptor.
385
386 if (desc) {
387 TBranchProxyDescriptor *existing =
389 if (existing) {
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());
393 } else {
395 UInt_t len = strlen(desc->GetTypeName());
396 if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
397 }
398 }
399 }
400
401 void TTreeProxyGenerator::AddMissingClassAsEnum(const char *clname, Bool_t isscope)
402 {
403 // Generate an enum for a given type if it is not known in the list of class
404 // unless the type itself a template.
405
406 if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
407
408 TObject *obj = fListOfForwards.FindObject(clname);
409 if (obj) return;
410
411 // The class does not exist, let's create it if ew can.
412 if (clname[strlen(clname)-1]=='>') {
413 // Template instantiation.
414 fListOfForwards.Add(new TNamed(clname,TString::Format("template <> class %s { public: operator int() { return 0; } };\n", clname).Data()));
415 } else if (isscope) {
416 // a scope
417
418 } else {
419 // Class or enum we know nothing about, let's assume it is an enum.
420 fListOfForwards.Add(new TNamed(clname,TString::Format("enum %s { kDefault_%s };\n", clname, clname).Data()));
421 }
422 }
423 }
424
426 {
427 // Check if the template parameter refers to an enum and/or a missing class (we can't tell those 2 apart unless
428 // the name as template syntax).
429
430 UInt_t len = strlen(clname);
431 UInt_t nest = 0;
432 UInt_t last = 0;
433 //Bool_t istemplate = kFALSE; // mark whether the current right most entity is a class template.
434
435 for (UInt_t i = 0; i < len; ++i) {
436 switch (clname[i]) {
437 case ':':
438 if (nest == 0 && clname[i+1] == ':') {
439 TString incName(clname, i);
440 AddMissingClassAsEnum(incName.Data(), kTRUE);
441 //istemplate = kFALSE;
442 }
443 break;
444 case '<':
445 ++nest;
446 if (nest == 1) last = i + 1;
447 break;
448 case '>':
449 if (nest == 0) return; // The name is not well formed, give up.
450 --nest; /* intentional fall throught to the next case */
451 case ',':
452 if ((clname[i] == ',' && nest == 1) || (clname[i] == '>' && nest == 0)) {
453 TString incName(clname + last, i - last);
455 if (clname[i] == '>' && nest == 1) incName.Append(">");
456
457 if (isdigit(incName[0])) {
458 // Not a class name, nothing to do.
459 } else {
461 }
462 last = i + 1;
463 }
464 }
465 }
467 }
468
471 {
472 // Analyze the sub-branch and populate the TTreeProxyGenerator or the topdesc with
473 // its findings.
474
475 if (info==0) info = branch->GetInfo();
476
477 TIter branches( branch->GetListOfBranches() );
478
479 return AnalyzeBranches( level, topdesc, branches, info );
480 }
481
484 TIter &branches,
486 {
487 // Analyze the list of sub branches of a TBranchElement by looping over
488 // the streamer elements and create the appropriate class proxies.
489
490/*
491
492 Find the content class name (GetClassName)
493 Record wether this is a collection or not
494
495 Find the StreamerInfo
496
497 For each streamerelement
498 if element is base
499 if name match, loop over subbranches
500 otherwise loop over current branches
501 else if eleement is object (or pointer to object?)
502 if name match go ahead, loop over subbranches
503 if name does not match. loop over current branches (fix names).
504 else
505 add branch.
506
507*/
508 UInt_t lookedAt = 0;
509 EContainer container = kNone;
510 TString middle;
511 TString proxyTypeName;
513 TString containerName;
514 TString subBranchPrefix;
515 Bool_t skipped = false;
516
517 {
518 TIter peek = branches;
519 TBranchElement *branch = (TBranchElement*)peek();
520 if (topdesc && topdesc->IsClones()) {
521 container = kClones;
522 middle = "Cla";
524 containerName = "TClonesArray";
525 } else if (topdesc && topdesc->IsSTL()) {
526 container = kSTL;
527 middle = "Stl";
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) {
532 container = kClones;
533 middle = "Cla";
535 containerName = "TClonesArray";
536 } else {
537 container = kSTL;
538 middle = "Stl";
539 outer_isclones = TBranchProxyClassDescriptor::kSTL;
540 containerName = branch->GetMother()->GetClassName();
541 }
542 } else if (branch->GetType() == 3) {
544 containerName = "TClonesArray";
545 } else if (branch->GetType() == 4) {
546 outer_isclones = TBranchProxyClassDescriptor::kSTL;
547 containerName = branch->GetMother()->GetSubBranch(branch)->GetClassName();
548 }
549 if (topdesc) {
550 subBranchPrefix = topdesc->GetSubBranchPrefix();
551 } else {
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 = "";
558 }
559 }
560 }
561 TIter elements( info->GetElements() );
562 for( TStreamerElement *element = (TStreamerElement*)elements();
563 element;
564 element = (TStreamerElement*)elements() )
565 {
566 Bool_t isBase = false;
567 Bool_t usedBranch = kTRUE;
568 TString prefix;
569 TIter peek = branches;
570 TBranchElement *branch = (TBranchElement*)peek();
571
572 if (branch==0) {
573 if (topdesc) {
574 Error("AnalyzeBranches","Ran out of branches when looking in branch %s, class %s",
575 topdesc->GetBranchName(), info->GetName());
576 } else {
577 Error("AnalyzeBranches","Ran out of branches when looking in class %s, element %s",
578 info->GetName(),element->GetName());
579 }
580 return lookedAt;
581 }
582
583 if (info->GetClass()->GetCollectionProxy() && strcmp(element->GetName(),"This")==0) {
584 // Skip the artifical streamer element.
585 continue;
586 }
587
588 if (element->GetType()==-1) {
589 // This is an ignored TObject base class.
590 continue;
591 }
592
593 TString branchname = branch->GetName();
594 TString branchEndname;
595 {
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();
600 Int_t pos;
601 pos = branchEndname.Index(".");
602 if (pos!=-1) {
603 if (subBranchPrefix.Length() &&
604 branchEndname.BeginsWith( subBranchPrefix ) ) {
605 // brprefix += topdesc->GetSubBranchPrefix();
606 branchEndname.Remove(0,subBranchPrefix.Length()+1);
607 }
608 }
609 }
610
611 Bool_t ispointer = false;
612 switch(element->GetType()) {
613
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; }
630
631 case TVirtualStreamerInfo::kCharStar: { proxyTypeName = GetArrayType(element,"Char",container); break; }
632
633 // array of basic types array[8]
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; }
650
651 // pointer to an array of basic types array[n]
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; }
668
669 // array counter //[n]
670 case TVirtualStreamerInfo::kCounter: { proxyTypeName = "T" + middle + "IntProxy"; break; }
671
672
681 // set as pointers and fall through to the next switches
682 ispointer = true;
691 TClass *cl = element->GetClassPointer();
692 R__ASSERT(cl);
693
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()) {
699 cname = GetContainedClassName(branch, element, ispointer);
700 containerName = "TClonesArray";
701 } else if (cl->GetCollectionProxy()) {
703 containerName = cl->GetName();
704 TClass *valueClass = cl->GetCollectionProxy()->GetValueClass();
705 if (valueClass) cname = valueClass->GetName();
706 else {
708 proxyTypeName = Form("TStlSimpleProxy<%s >", cl->GetName());
709// AddPragma(Form("#pragma create TClass %s;\n", cl->GetName()));
710 if (!cl->IsLoaded()) AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
711 }
712 }
713
714 TBranch *parent = branch->GetMother()->GetSubBranch(branch);
715 TVirtualStreamerInfo *objInfo = 0;
716 if (branch->GetListOfBranches()->GetEntries()) {
717 objInfo = ((TBranchElement*)branch->GetListOfBranches()->At(0))->GetInfo();
718 } else {
719 objInfo = branch->GetInfo();
720 }
721 if (element->IsBase()) {
722 isBase = true;
723 prefix = "base";
724
725 if (cl == TObject::Class() && info->GetClass()->CanIgnoreTObjectStreamer())
726 {
727 continue;
728 }
729
730 TBranchProxyClassDescriptor *cldesc = 0;
731
732 if (branchEndname == element->GetName()) {
733 // We have a proper node for the base class, recurse
734
735 if (branch->GetListOfBranches()->GetEntries() == 0) {
736 // The branch contains a non-split base class that we are unfolding!
737
738 // See AnalyzeTree for similar code!
739 TBranchProxyClassDescriptor *local_cldesc = 0;
740
741 TVirtualStreamerInfo *binfo = branch->GetInfo();
742 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
743 binfo = cl->GetStreamerInfo(); // might be the wrong version
744 }
745 local_cldesc = new TBranchProxyClassDescriptor(cl->GetName(), binfo,
746 branch->GetName(),
747 isclones, 0 /* unsplit object */,
748 containerName);
749
750 TStreamerElement *elem = 0;
751
752 TIter next(binfo->GetElements());
753 while( (elem = (TStreamerElement*)next()) ) {
754 AnalyzeElement(branch,elem,level+1,local_cldesc,"");
755
756 }
757 if (NeedToEmulate(cl,0)) {
758 proxyTypeName = local_cldesc->GetName();
759 local_cldesc = AddClass(local_cldesc);
760 }
761
762 } else {
763
764 Int_t pos = branchname.Last('.');
765 if (pos != -1) {
766 branchname.Remove(pos);
767 }
768 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
769 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
770 branchname,
771 local_prefix,
772 isclones, branch->GetSplitLevel(),
773 containerName);
774 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
775 }
776 } else {
777 // We do not have a proper node for the base class, we need to loop over
778 // the next branches
779 Int_t pos = branchname.Last('.');
780 if (pos != -1) {
781 branchname.Remove(pos);
782 }
783 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
784 objInfo = GetBaseClass( element );
785 if (objInfo == 0) {
786 // There is no data in this base class
787 continue;
788 }
789 cl = objInfo->GetClass();
790 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
791 branchname,
792 local_prefix,
793 isclones, branch->GetSplitLevel(),
794 containerName);
795 usedBranch = kFALSE;
796 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
797 }
798
799 TBranchProxyClassDescriptor *added = AddClass(cldesc);
800 if (added) proxyTypeName = added->GetName();
801
802 } else {
803 TBranchProxyClassDescriptor *cldesc = 0;
804
805 if (branchEndname == element->GetName()) {
806
807 // We have a proper node for the base class, recurse
808 if (branch->GetListOfBranches()->GetEntries() == 0) {
809 // The branch contains a non-split object that we are unfolding!
810
811 // See AnalyzeTree for similar code!
812 TBranchProxyClassDescriptor *local_cldesc = 0;
813
814 TVirtualStreamerInfo *binfo = branch->GetInfo();
815 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
816 binfo = cl->GetStreamerInfo(); // might be the wrong version
817 }
818 local_cldesc = new TBranchProxyClassDescriptor(cl->GetName(), binfo,
819 branch->GetName(),
820 isclones, 0 /* unsplit object */,
821 containerName);
822
823 TStreamerElement *elem = 0;
824
825 TIter next(binfo->GetElements());
826 while( (elem = (TStreamerElement*)next()) ) {
827 AnalyzeElement(branch,elem,level+1,local_cldesc,"");
828 }
829
830 if (NeedToEmulate(cl,0)) {
831 proxyTypeName = local_cldesc->GetName();
832 local_cldesc = AddClass(local_cldesc);
833 }
834
835 } else {
836
837 if (isclones != TBranchProxyClassDescriptor::kOut) {
838 // We have to guess the version number!
839 cl = TClass::GetClass(cname);
840 objInfo = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
841 }
842 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
843 branch->GetName(),
844 branch->GetName(),
845 isclones, branch->GetSplitLevel(),
846 containerName);
847 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
848 }
849 } else {
850 // We do not have a proper node for the base class, we need to loop over
851 // the next branches
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('.');
857 if (pos != -1) {
858 branchname.Remove(pos);
859 }
860 if (isclones != TBranchProxyClassDescriptor::kOut) {
861 // We have to guess the version number!
862 cl = TClass::GetClass(cname);
863 objInfo = GetStreamerInfo(branch, branches, cl);
864 }
865 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
866 branchname,
867 local_prefix,
868 isclones, branch->GetSplitLevel(),
869 containerName);
870 usedBranch = kFALSE;
871 skipped = kTRUE;
872 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
873 }
874
875 TBranchProxyClassDescriptor *added = AddClass(cldesc);
876 if (added) proxyTypeName = added->GetName();
877
878 }
879
880 AddForward(cl);
881 AddHeader(cl);
882 break;
883 }
884
885 default:
886 Error("AnalyzeBranch",
887 "Unsupported type for %s (%d).",
888 branch->GetName(),element->GetType());
889
890 }
891
892 TString dataMemberName = element->GetName();
893 if (topdesc) {
894 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
895 proxyTypeName, branchname, true, skipped ), isBase );
896 } else {
897 dataMemberName.Prepend(prefix);
898 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
899 proxyTypeName, branchname, true, skipped ) );
900 }
901
902 if (usedBranch) {
903 branches.Next();
904 ++lookedAt;
905 }
906 }
907 return lookedAt;
908 }
909
912 {
913 // Analyze the leaf and populate the `TTreeProxyGenerator or
914 // the topdesc with its findings.
915
916 if (leaf->IsA()==TLeafObject::Class()) {
917 Error("AnalyzeOldLeaf","TLeafObject not supported yet");
918 return 0;
919 }
920
921 TString leafTypeName = leaf->GetTypeName();
922 Int_t pos = leafTypeName.Last('_');
923 if (pos!=-1) leafTypeName.Remove(pos);
924
925 // Int_t len = leaf->GetLen();
926 // TLeaf *leafcount = leaf->GetLeafCount();
927
928 UInt_t dim = 0;
929 std::vector<Int_t> maxDim;
930 //maxDim[0] = maxDim[1] = maxDim[2] = 1;
931
932 TString dimensions;
933 TString temp = leaf->GetName();
934 pos = temp.Index("[");
935 if (pos!=-1) {
936 if (pos) temp.Remove(0,pos);
937 dimensions.Append(temp);
938 }
939 temp = leaf->GetTitle();
940 pos = temp.Index("[");
941 if (pos!=-1) {
942 if (pos) temp.Remove(0,pos);
943 dimensions.Append(temp);
944 }
945
946 Int_t dimlen = dimensions.Length();
947
948 if (dimlen) {
949 const char *current = dimensions.Data();
950
951 Int_t index;
952 Int_t scanindex ;
953 while (current) {
954 current++;
955 if (current[0] == ']') {
956 maxDim.push_back(-1); // maxDim[dim] = -1; // Loop over all elements;
957 } else {
958 scanindex = sscanf(current,"%d",&index);
959 if (scanindex) {
960 maxDim.push_back(index); // maxDim[dim] = index;
961 } else {
962 maxDim.push_back(-2); // maxDim[dim] = -2; // Index is calculated via a variable.
963 }
964 }
965 dim ++;
966 current = (char*)strstr( current, "[" );
967 }
968
969 }
970 //char *twodim = (char*)strstr(leaf->GetTitle(),"][");
971
972 //if (leafcount) {
973 // len = leafcount->GetMaximum();
974 //}
975 if (dim == 0 && leaf->IsA() == TLeafC::Class()) {
976 // For C style strings.
977 dim = 1;
978 }
979
981 switch (dim) {
982 case 0: {
983 type = "T";
984 type += leafTypeName;
985 type += "Proxy";
986 break;
987 }
988 case 1: {
989 type = "TArray";
990 type += leafTypeName;
991 type += "Proxy";
992 break;
993 }
994 default: {
995 type = "TArrayProxy<";
996 for(Int_t ind = dim - 2; ind > 0; --ind) {
997 type += "TMultiArrayType<";
998 }
999 type += "TArrayType<";
1000 type += leaf->GetTypeName();
1001 type += ",";
1002 type += maxDim[dim-1];
1003 type += "> ";
1004 for(Int_t ind = dim - 2; ind > 0; --ind) {
1005 type += ",";
1006 type += maxDim[ind];
1007 type += "> ";
1008 }
1009 type += ">";
1010 break;
1011 }
1012 }
1013
1014 TString branchName = leaf->GetBranch()->GetName();
1015 TString dataMemberName = leaf->GetName();
1016
1017 if (topdesc) {
1018 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1019 type,
1020 branchName.Data(),
1021 true, false, true ),
1022 0 );
1023 } else {
1024 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1025 type,
1026 branchName.Data(),
1027 true, false, true ) );
1028 }
1029
1030 return 0;
1031
1032 }
1033
1036 {
1037 // Analyze the branch and populate the TTreeProxyGenerator or the topdesc with
1038 // its findings. Sometimes several branch of the mom are also analyzed,
1039 // the number of such branches is returned (this happens in the case of
1040 // embedded objects inside an object inside a clones array split more than
1041 // one level.
1042
1043 UInt_t extraLookedAt = 0;
1044 TString prefix;
1045
1046 TString branchName = branch->GetName();
1047
1048 TObjArray *leaves = branch->GetListOfLeaves();
1049 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
1050
1051 if (nleaves>1) {
1052
1053 // Create a holder
1054 TString type = "unknown";
1056 if (cldesc) {
1057 type = cldesc->GetName();
1058
1059 for(int l=0;l<nleaves;l++) {
1060 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1061 extraLookedAt += AnalyzeOldLeaf(leaf,level+1,cldesc);
1062 }
1063 }
1064
1065 TString dataMemberName = branchName;
1066
1067 if (topdesc) {
1068 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1069 type,
1070 branchName.Data() ),
1071 0 );
1072 } else {
1073 // leafname.Prepend(prefix);
1074 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1075 type,
1076 branchName.Data() ) );
1077 }
1078
1079 } else {
1080
1081 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
1082 extraLookedAt += AnalyzeOldLeaf(leaf,level,topdesc);
1083
1084 }
1085
1086
1087 return extraLookedAt;
1088
1089 }
1090
1092 {
1093 // Analyze a TTree and its (potential) friends.
1094
1095 TIter next( tree->GetListOfBranches() );
1096 TBranch *branch;
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 );
1104 }
1105
1107 TClass *cl = TClass::GetClass(classname);
1108 TString type = "unknown";
1109 if (cl) {
1111 TString containerName = "";
1112 if (cl==TClonesArray::Class()) {
1114 containerName = "TClonesArray";
1115 if (branch->IsA()==TBranchElement::Class()) {
1116 const char *cname = ((TBranchElement*)branch)->GetClonesName();
1117 TClass *ncl = TClass::GetClass(cname);
1118 if (ncl) {
1119 cl = ncl;
1120 info = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
1121 } else {
1122 Error("AnalyzeTree",
1123 "Introspection of TClonesArray in older file not implemented yet.");
1124 }
1125 } else {
1126 TClonesArray **ptr = (TClonesArray**)branch->GetAddress();
1127 TClonesArray *clones = 0;
1128 if (ptr==0) {
1129 clones = new TClonesArray;
1130 branch->SetAddress(&clones);
1131 ptr = &clones;
1132 }
1133 branch->GetEntry(0);
1134 TClass *ncl = *ptr ? (*ptr)->GetClass() : 0;
1135 if (ncl) {
1136 cl = ncl;
1137 } else {
1138 Error("AnalyzeTree",
1139 "Introspection of TClonesArray for %s failed.",branch->GetName());
1140 }
1141 }
1142 } else if (cl->GetCollectionProxy()) {
1144 containerName = cl->GetName();
1145 if (cl->GetCollectionProxy()->GetValueClass()) {
1146 cl = cl->GetCollectionProxy()->GetValueClass();
1147 } else {
1149 type = Form("TStlSimpleProxy<%s >", cl->GetName());
1150 AddHeader(cl);
1151 if (!cl->IsLoaded()) AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1152 AddDescriptor( new TBranchProxyDescriptor( branchname, type, branchname ) );
1153 continue;
1154 }
1155 }
1156 if (cl) {
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(); // the 2nd hand need to be fixed
1161 desc = new TBranchProxyClassDescriptor(cl->GetName(), beinfo, branchname,
1162 isclones, branch->GetSplitLevel(),containerName);
1163 info = beinfo;
1164 } else {
1165 type = Form("TObjProxy<%s >",cl->GetName());
1166 }
1167 }
1168 }
1169
1170 if ( branch->GetListOfBranches()->GetEntries() == 0 ) {
1171
1172 if (cl) {
1173 // We have a non-split object!
1174
1175 if (desc) {
1177 TStreamerElement *elem = 0;
1178
1179 TIter cnext(cinfo->GetElements());
1180 while( (elem = (TStreamerElement*)cnext()) ) {
1181 AnalyzeElement(branch,elem,1,desc,"");
1182 }
1183
1184 desc = AddClass(desc);
1185 if (desc) {
1186 type = desc->GetName();
1187
1188 TString dataMemberName = branchname;
1189
1190 AddDescriptor( new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1191 }
1192 } else {
1193 // We have a top level non split.
1195 type,
1196 branch->GetName(),
1197 true, false, false ) );
1198 }
1199 } else {
1200
1201 // We have a top level raw type.
1202 AnalyzeOldBranch(branch, 0, 0);
1203 }
1204
1205 } else {
1206
1207 // We have a split object
1208
1209 TIter subnext( branch->GetListOfBranches() );
1210 if (desc) {
1211 AnalyzeBranches(1,desc,dynamic_cast<TBranchElement*>(branch),info);
1212 }
1213 desc = AddClass(desc);
1214 if (desc) {
1215 type = desc->GetName();
1216 TString dataMemberName = branchname;
1217 AddDescriptor( new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1218 }
1219 if ( branchname[strlen(branchname)-1] != '.' ) {
1220 // If there is no dot also include the data member directly
1221
1222 AnalyzeBranches(1,0,dynamic_cast<TBranchElement*>(branch),info);
1223
1224 subnext.Reset();
1225 }
1226
1227 } // if split or non split
1228 }
1229
1230 // Now let's add the TTreeFriend (if any)
1231 if (tree->GetListOfFriends()) {
1232 TFriendElement *fe;
1233 Int_t count = 0;
1234
1235 TIter nextfriend(tree->GetListOfFriends());
1236 while ((fe = (TFriendElement*)nextfriend())) {
1237 TTree *t = fe->GetTree();
1239 desc = new TFriendProxyDescriptor(t->GetName(), fe->GetName(), count);
1240
1241 AddFriend( desc );
1242
1244 AnalyzeTree(t);
1245
1246 count++;
1247 }
1248 }
1250 }
1251
1253 UInt_t level, TBranchProxyClassDescriptor *topdesc,
1254 const char *path)
1255 {
1256 // Analyze the element and populate the TTreeProxyGenerator or the topdesc with
1257 // its findings.
1258
1259 TString dataMemberName;
1260 TString pxDataMemberName;
1261 TString type;
1262
1263 // TString prefix;
1264 Bool_t isBase = false;
1265 TString cname;
1266 TString middle;
1268 TString containerName;
1269 EContainer container = kNone;
1270 if (topdesc) {
1271 if (topdesc->IsClones()) {
1272 container = kClones;
1273 middle = "Cla";
1275 containerName = "TClonesArray";
1276 } else if (topdesc->IsSTL()) {
1277 container = kSTL;
1278 middle = "Stl";
1280 containerName = topdesc->GetContainerName();
1281 }
1282 }
1283
1284 if (!element) return;
1285
1286 if (strcmp(element->GetName(),"This")==0) {
1287 TClass *cl = element->GetClassPointer();
1288 containerName = cl->GetName();
1289 cl = cl->GetCollectionProxy()->GetValueClass();
1290 if (!cl) {
1291 // Skip the artifical streamer element.
1292 return;
1293 }
1294 // else return;
1295
1296 // In case the content is a class, move forward
1297 AddForward(cl);
1298 AddHeader(cl);
1299
1300 if (level<=fMaxUnrolling) {
1301
1302 // See AnalyzeTree for similar code!
1303 // TBranchProxyClassDescriptor *cldesc;
1304 if (cl && cl->CanSplit()) {
1305 // cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1306 // branch->GetName(),
1307 // isclones, 0 /* non-split object */,
1308 // containerName);
1309
1311 TStreamerElement *elem = 0;
1312
1313 TString subpath = path;
1314 if (subpath.Length()>0) subpath += ".";
1315 subpath += dataMemberName;
1316
1317 TIter next(info->GetElements());
1318 while( (elem = (TStreamerElement*)next()) ) {
1319 AnalyzeElement(branch, elem, level+1, topdesc, subpath.Data());
1320 }
1321
1322 // TBranchProxyClassDescriptor *added = AddClass(cldesc);
1323 // if (added) type = added->GetName();
1324 }
1325 }
1326 return;
1327 }
1328
1329 if (element->GetType()==-1) {
1330 // This is an ignored TObject base class.
1331 return;
1332 }
1333
1334
1335 // Bool_t ispointer = false;
1336 switch(element->GetType()) {
1337
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; }
1354
1355 case TVirtualStreamerInfo::kCharStar: { type = GetArrayType(element,"Char",container); break; }
1356
1357 // array of basic types array[8]
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; }
1374
1375 // pointer to an array of basic types array[n]
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; }
1392
1393 // array counter //[n]
1394 case TVirtualStreamerInfo::kCounter: { type = "T" + middle + "IntProxy"; break; }
1395
1396
1405 // set as pointers and fall through to the next switches
1406 // ispointer = true;
1416 TClass *cl = element->GetClassPointer();
1417 if (cl) {
1418 type = Form("T%sObjProxy<%s >",
1419 middle.Data(),cl->GetName());
1420 cname = cl->GetName();
1421 if (cl==TClonesArray::Class()) {
1423 containerName = "TClonesArray";
1424
1425 Long64_t i = branch->GetTree()->GetReadEntry();
1426 if (i<0) i = 0;
1427 branch->GetEntry(i);
1428
1429 //char *obj = branch->GetObject();
1430
1431 // now need to follow it through to this pointer!
1432
1433 TClonesArray *arr;
1434
1435 TString fullpath = branch->GetName();
1436 fullpath += ".";
1437 if (path && strlen(path)>0) fullpath.Append(path).Append(".");
1438 fullpath += element->GetName();
1439
1440 TTreeFormula *formula = new TTreeFormula("clones",fullpath,branch->GetTree());
1441
1442 TFormLeafInfo *leafinfo = formula->GetLeafInfo(0);
1443 TLeaf *leaf = formula->GetLeaf(0);
1444 R__ASSERT(leaf && leafinfo);
1445
1446 arr = (TClonesArray*)leafinfo->GetLocalValuePointer(leaf,0);
1447
1448 /*
1449 if (ispointer) {
1450 arr = (TClonesArray*)*(void**)(obj+lOffset);
1451 } else {
1452 arr = (TClonesArray*)(obj+lOffset);
1453 }
1454 */
1455 if (arr) cname = arr->GetClass()->GetName();
1456
1457 if (cname.Length()==0) {
1458 Error("AnalyzeTree",
1459 "Introspection of TClonesArray in older file not implemented yet.");
1460 }
1461 delete formula;
1462 } else if (cl->GetCollectionProxy()) {
1464 containerName = cl->GetName();
1465 cl = cl->GetCollectionProxy()->GetValueClass();
1466 }
1467 }
1468 else Error("AnalyzeTree","missing class for %s.",branch->GetName());
1469 if (element->IsA()==TStreamerBase::Class()) {
1470 // prefix = "base";
1471 isBase = true;
1472 }
1473 AddForward(cl);
1474 AddHeader(cl);
1475 break;
1476 }
1477
1478 default:
1479 Error("AnalyzeTree",
1480 "Unsupported type for %s %s %d",
1481 branch->GetName(), element->GetName(), element->GetType());
1482
1483 }
1484
1485 dataMemberName = element->GetName();
1486
1487 if (level<=fMaxUnrolling) {
1488
1489 // See AnalyzeTree for similar code!
1491
1492 TClass *cl = TClass::GetClass(cname);
1493 if (cl && cl->CanSplit()) {
1494 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1495 branch->GetName(),
1496 isclones, 0 /* non-split object */,
1497 containerName);
1498
1500 TStreamerElement *elem = 0;
1501
1502 TString subpath = path;
1503 if (subpath.Length()>0) subpath += ".";
1504 subpath += dataMemberName;
1505
1506 TIter next(info->GetElements());
1507 while( (elem = (TStreamerElement*)next()) ) {
1508 AnalyzeElement(branch, elem, level+1, cldesc, subpath.Data());
1509 }
1510
1511 TBranchProxyClassDescriptor *added = AddClass(cldesc);
1512 if (added) type = added->GetName();
1513 }
1514
1515 }
1516
1517 pxDataMemberName = /* prefix + */ dataMemberName;
1518 if (topdesc) {
1519 topdesc->AddDescriptor( new TBranchProxyDescriptor( pxDataMemberName.Data(), type,
1520 dataMemberName.Data(), false),
1521 isBase );
1522 } else {
1523 Error("AnalyzeTree","topdesc should not be null in TTreeProxyGenerator::AnalyzeElement.");
1524 }
1525 }
1526
1527 /////////////////////////////////////////////////////////////////////////////
1528 /// Parse the options string.
1529
1531 {
1532 TString opt = fOptionStr;
1533
1534 fOptions = 0;
1535 if ( opt.Contains("nohist") ) {
1536 opt.ReplaceAll("nohist","");
1537 fOptions |= kNoHist;
1538 }
1539 }
1540
1541 /////////////////////////////////////////////////////////////////////////////
1542 /// Add the "pragma C++ class" if needed and return
1543 /// true if it has been added _or_ if it is known to
1544 /// not be needed.
1545 /// (I.e. return kFALSE if a container of this class
1546 /// can not have a "pragma C++ class"
1547
1549 {
1550 if (!cl) return kFALSE;
1551 if (cl->GetCollectionProxy()) {
1552 TClass *valcl = cl->GetCollectionProxy()->GetValueClass();
1553 if (!valcl) {
1554 if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1555 return kTRUE;
1556 } else if (R__AddPragmaForClass(gen, valcl)) {
1557 if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1558 return kTRUE;
1559 }
1560 }
1561 if (cl->IsLoaded()) return kTRUE;
1562 return kFALSE;
1563 }
1564
1565 /////////////////////////////////////////////////////////////////////////////
1566 /// Add the "pragma C++ class" if needed and return
1567 /// true if it has been added _or_ if it is known to
1568 /// not be needed.
1569 /// (I.e. return kFALSE if a container of this class
1570 /// can not have a "pragma C++ class"
1571
1572 static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen, const char *classname)
1573 {
1574 return R__AddPragmaForClass( gen, TClass::GetClass(classname) );
1575
1576 }
1577
1578 /////////////////////////////////////////////////////////////////////////////
1579 /// Check whether the file exist and do something useful if it does
1580
1582 {
1583 if (fScript.Length()==0) {
1584 Error("WriteProxy","No user script has been specified.");
1585 return;
1586 }
1587
1588 TString fileLocation = gSystem->GetDirName(fScript);
1589
1590 TString incPath = gSystem->GetIncludePath(); // of the form -Idir1 -Idir2 -Idir3
1591 incPath.Append(":").Prepend(" ");
1592 incPath.ReplaceAll(" -I",":"); // of form :dir1 :dir2:dir3
1593 while ( incPath.Index(" :") != -1 ) {
1594 incPath.ReplaceAll(" :",":");
1595 }
1596 incPath.Prepend(fileLocation+":.:");
1597
1598 const char *filename = gSystem->Which(incPath,fScript);
1599 if (!filename) {
1600 Error("WriteProxy","Can not find the user's script: %s",fScript.Data());
1601 return;
1602 }
1603 const char *cutfilename = nullptr;
1604 if (fCutScript.Length()) {
1605 fileLocation = gSystem->GetDirName(fCutScript);
1606 incPath.Prepend(fileLocation+":.:");
1607 cutfilename = gSystem->Which(incPath,fCutScript);
1608 if (!cutfilename) {
1609 Error("WriteProxy","Can not find the user's cut script: %s",fCutScript.Data());
1610 delete [] filename;
1611 return;
1612 }
1613 }
1614
1616 TString classname = gSystem->BaseName(fPrefix);
1617
1618 // Check if there is already an extension and extract it.
1619 Ssiz_t pos = classname.Last('.');
1620 if (pos != kNPOS) {
1621 classname.Remove(pos);
1622 } else {
1623 fHeaderFileName.Append(".h");
1624 }
1625
1626 // Check to see if the target file exist.
1627 // If they do we will generate the proxy in temporary file and modify the original
1628 // if and only if it is different.
1629
1630 Bool_t updating = kFALSE;
1631 if (gSystem->GetPathInfo( fHeaderFileName, 0, (Long_t*)0, 0, 0 ) == 0) {
1632 // file already exist
1633 updating = kTRUE;
1634 }
1635
1636
1637 TString treefile;
1638 Bool_t ischain = fTree->InheritsFrom(TChain::Class());
1640 treefile = fTree->GetDirectory()->GetFile()->GetName();
1641 else
1642 treefile = "Memory Directory";
1643
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());
1648 delete [] filename;
1649 delete [] cutfilename;
1650 return;
1651 }
1652 scriptfunc.Replace( dot_pos, fScript.Length()-dot_pos, "");
1653 TString scriptHeader = scriptfunc;
1654 const char * extensions[] = { ".h", ".hh", ".hpp", ".hxx", ".hPP", ".hXX" };
1655
1656 int i;
1657 for (i = 0; i < 6; i++ ) {
1658 TString possible = scriptHeader;
1659 possible.Append(extensions[i]);
1660 const char *name = gSystem->Which(incPath,possible);
1661 if (name) {
1662 scriptHeader = possible;
1663 fListOfHeaders.Add(new TNamed("script",Form("#include \"%s\"\n",
1664 scriptHeader.Data())));
1665 delete [] name;
1666 break;
1667 }
1668 }
1669 scriptfunc = gSystem->BaseName(scriptfunc);
1670
1671
1672 TString cutscriptfunc = fCutScript;
1673 if (cutfilename) {
1674 dot_pos = cutscriptfunc.Last('.');
1675 cutscriptfunc.Replace( dot_pos, fCutScript.Length()-dot_pos, "");
1676 TString cutscriptHeader = cutscriptfunc;
1677
1678 for (i = 0; i < 6; i++ ) {
1679 TString possible = cutscriptHeader;
1680 possible.Append(extensions[i]);
1681 const char *name = gSystem->Which(incPath,possible);
1682 if (name) {
1683 cutscriptHeader = possible;
1684 fListOfHeaders.Add(new TNamed("cutscript",Form("#include \"%s\"\n",
1685 cutscriptHeader.Data())));
1686 delete [] name;
1687 break;
1688 }
1689 }
1690 cutscriptfunc = gSystem->BaseName(cutscriptfunc);
1691 }
1692
1693 FILE *hf;
1694 TString tmpfilename = ".Proxy-";
1695 if (updating) {
1696 hf = gSystem->TempFileName(tmpfilename, "./");
1697 } else {
1698 hf = fopen(fHeaderFileName, "w");
1699 }
1700 if (hf == 0) {
1701 Error("WriteProxy","Unable to open the file %s for writing.",
1702 updating ? tmpfilename.Data() : fHeaderFileName.Data());
1703 delete [] filename;
1704 delete [] cutfilename;
1705 return;
1706 }
1707
1708 TDatime td;
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());
1712 if (!ischain) {
1713 fprintf(hf,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1714 fprintf(hf,"// found on file: %s\n",treefile.Data());
1715 } else {
1716 fprintf(hf,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1717 }
1718 fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
1719 fprintf(hf,"\n");
1720 fprintf(hf,"\n");
1721
1722 fprintf(hf,"#ifndef %s_h\n",classname.Data());
1723 fprintf(hf,"#define %s_h\n",classname.Data());
1724 fprintf(hf,"\n");
1725
1726
1727 // Interface versioning
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"); // questionable
1741 fprintf(hf,"using ROOT::Detail::TBranchProxy;\n"); // questionable
1742 fprintf(hf,"\n");
1743
1744 fprintf(hf,"// forward declarations needed by this particular proxy\n");
1745 TIter next( &fListOfForwards );
1746 TObject *current;
1747 while ( (current=next()) ) {
1748 if (strstr(current->GetTitle(),"::")==0) {
1749 // We can not forward declared nested classes (well we might be able to do so for
1750 // the one nested in a namespace but it is not clear yet if we can really reliably
1751 // find this information)
1752 fprintf(hf,"%s",current->GetTitle());
1753 }
1754 }
1755
1756 fprintf(hf,"\n\n");
1757 fprintf(hf,"// Header needed by this particular proxy\n");
1758 next = &fListOfHeaders;
1759 TObject *header;
1760 while ( (header = next()) ) {
1761 fprintf(hf,"%s",header->GetTitle());
1762 }
1763 fprintf(hf,"\n\n");
1764
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());
1775 fprintf(hf,"};\n");
1776 fprintf(hf,"\n\n");
1777
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");
1783
1784 fprintf(hf, " // Optional User methods\n");
1785 fprintf(hf, " TClass *fClass; // Pointer to this class's description\n");
1786
1787 if (fListOfClasses.LastIndex()>=0) {
1788 fprintf(hf, "\n // Wrapper class for each unwounded class\n");
1789 next = &fListOfClasses;
1791 while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1792 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1793 }
1794 }
1795
1796 if (fListOfFriends.LastIndex()>=0) {
1797 fprintf(hf, "\n // Wrapper class for each friend TTree\n");
1798 next = &fListOfFriends;
1800 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1801 if (!clp->IsDuplicate()) clp->OutputClassDecl(hf, 3, fMaxDatamemberType);
1802 }
1803 }
1804
1805 fprintf(hf, "\n // Proxy for each of the branches, leaves and friends of the tree\n");
1806 next = &fListOfTopProxies;
1808 while ( (data = (TBranchProxyDescriptor*)next()) ) {
1809 data->OutputDecl(hf, 3, fMaxDatamemberType);
1810 }
1811 if (fListOfFriends.LastIndex()>=0) {
1812 next = &fListOfFriends;
1814 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1815 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1816 }
1817 }
1818 fprintf(hf,"\n\n");
1819
1820 // Constructor
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());
1830 }
1831 next = &fListOfFriends;
1833 while ( (fpd = (TFriendProxyDescriptor*)next()) ) {
1834 fprintf(hf,",\n %-*s(&fDirector,tree,%d)",
1835 fMaxDatamemberType, fpd->GetTitle(), fpd->GetIndex());
1836 }
1837
1838 fprintf(hf, "\n { }\n");
1839
1840 // Other functions.
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");
1850 fprintf(hf,"\n");
1851 fprintf(hf," ClassDef(%s,0);\n",classname.Data());
1852 fprintf(hf,"\n\n");
1853
1854 fprintf(hf,"//inject the user's code\n");
1855 fprintf(hf,"#include \"%s\"\n",fScript.Data());
1856
1857 if (cutfilename) {
1858 fprintf(hf,"#include \"%s\"\n",fCutScript.Data());
1859 }
1860
1861 // Close the class.
1862 fprintf(hf,"};\n");
1863 fprintf(hf,"\n");
1864 fprintf(hf,"#endif\n");
1865 fprintf(hf,"\n\n");
1866
1867 fprintf(hf,"#ifdef __MAKECINT__\n");
1868 if (fListOfClasses.LastIndex()>=0) {
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()) {
1875 }
1876 }
1877 next = &fListOfPragmas;
1878 TObjString *prag;
1879 while ( (prag = (TObjString*)next()) ) {
1880 fprintf(hf,"%s",prag->String().Data());
1881 }
1882 }
1883 fprintf(hf,"#pragma link C++ class %s;\n",classname.Data());
1884 fprintf(hf,"#endif\n");
1885 fprintf(hf,"\n\n");
1886
1887 // Write the implementations.
1888 fprintf(hf,"inline %s::~%s() {\n",classname.Data(),classname.Data());
1889 fprintf(hf," // destructor. Clean up helpers.\n");
1890 fprintf(hf,"\n");
1891 fprintf(hf,"}\n");
1892 fprintf(hf,"\n");
1893 fprintf(hf,"inline void %s::Init(TTree *tree)\n",classname.Data());
1894 fprintf(hf,"{\n");
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");
1901 if (cutfilename) {
1902 fprintf(hf," htemp->SetTitle(\"%s {%s}\");\n",fScript.Data(),fCutScript.Data());
1903 } else {
1904 fprintf(hf," htemp->SetTitle(\"%s\");\n",fScript.Data());
1905 }
1906 fprintf(hf," fObject = htemp;\n");
1907 fprintf(hf," }\n");
1908 fprintf(hf,"}\n");
1909 fprintf(hf,"\n");
1910 fprintf(hf,"Bool_t %s::Notify()\n",classname.Data());
1911 fprintf(hf,"{\n");
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());
1916 fprintf(hf," \n");
1917 fprintf(hf," return kTRUE;\n");
1918 fprintf(hf,"}\n");
1919 fprintf(hf," \n");
1920
1921 // generate code for class member function Begin
1922 fprintf(hf,"\n");
1923 fprintf(hf,"inline void %s::Begin(TTree *tree)\n",classname.Data());
1924 fprintf(hf,"{\n");
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");
1928 fprintf(hf,"\n");
1929 fprintf(hf," TString option = GetOption();\n");
1930 fprintf(hf," %s_Begin(tree);\n",scriptfunc.Data());
1931 fprintf(hf,"\n");
1932 fprintf(hf,"}\n");
1933
1934 // generate code for class member function SlaveBegin
1935 fprintf(hf,"\n");
1936 fprintf(hf,"inline void %s::SlaveBegin(TTree *tree)\n",classname.Data());
1937 fprintf(hf,"{\n");
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");
1941 fprintf(hf,"\n");
1942 fprintf(hf," Init(tree);\n");
1943 fprintf(hf,"\n");
1944 fprintf(hf," %s_SlaveBegin(tree);\n",scriptfunc.Data());
1945 fprintf(hf,"\n");
1946 fprintf(hf,"}\n");
1947 fprintf(hf,"\n");
1948
1949 // generate code for class member function Process
1950 fprintf(hf,"inline Bool_t %s::Process(Long64_t entry)\n",classname.Data());
1951 fprintf(hf,"{\n");
1952
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"
1960 " //\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");
1969 fprintf(hf,"\n");
1970 fprintf(hf,"\n");
1971 fprintf(hf," fDirector.SetReadEntry(entry);\n");
1972 if (fOptions & kNoHist) {
1973 if (cutfilename) {
1974 fprintf(hf," if (%s()) %s();\n",cutscriptfunc.Data(),scriptfunc.Data());
1975 } else {
1976 fprintf(hf," %s();\n",scriptfunc.Data());
1977 }
1978 } else {
1979 if (cutfilename) {
1980 fprintf(hf," if (%s()) htemp->Fill(%s());\n",cutscriptfunc.Data(),scriptfunc.Data());
1981 } else {
1982 fprintf(hf," htemp->Fill(%s());\n",scriptfunc.Data());
1983 }
1984 }
1985 fprintf(hf," %s_Process(entry);\n",scriptfunc.Data());
1986 fprintf(hf," return kTRUE;\n");
1987 fprintf(hf,"\n");
1988 fprintf(hf,"}\n\n");
1989
1990 // generate code for class member function SlaveTerminate
1991 fprintf(hf,"inline void %s::SlaveTerminate()\n",classname.Data());
1992 fprintf(hf,"{\n");
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.");
1996 fprintf(hf,"\n");
1997 fprintf(hf," %s_SlaveTerminate();\n",scriptfunc.Data());
1998 fprintf(hf,"}\n\n");
1999
2000 // generate code for class member function Terminate
2001 fprintf(hf,"inline void %s::Terminate()\n",classname.Data());
2002 fprintf(hf,"{\n");
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");
2006 fprintf(hf," \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");
2012 fprintf(hf," }\n");
2013 fprintf(hf," %s_Terminate();\n",scriptfunc.Data());
2014 fprintf(hf,"}\n");
2015
2016 fclose(hf);
2017
2018 if (updating) {
2019 // over-write existing file only if needed.
2020 if (AreDifferent(fHeaderFileName,tmpfilename)) {
2022 gSystem->Rename(tmpfilename,fHeaderFileName);
2023 } else gSystem->Unlink(tmpfilename);
2024 }
2025 delete [] filename;
2026 delete [] cutfilename;
2027 }
2028
2029} // namespace Internal
2030} // namespace ROOT
void Class()
Definition: Class.C:29
const Ssiz_t kNPOS
Definition: RtypesCore.h:113
int Int_t
Definition: RtypesCore.h:43
const Bool_t kFALSE
Definition: RtypesCore.h:90
long Long_t
Definition: RtypesCore.h:52
bool Bool_t
Definition: RtypesCore.h:61
R__EXTERN Int_t gDebug
Definition: RtypesCore.h:117
long long Long64_t
Definition: RtypesCore.h:71
const Bool_t kTRUE
Definition: RtypesCore.h:89
#define R__ASSERT(e)
Definition: TError.h:96
void ErrorHandler(int level, const char *location, const char *fmt, va_list va)
General error handler function. It calls the user set error handler.
Definition: TError.cxx:202
void Error(const char *location, const char *msgfmt,...)
void Warning(const char *location, const char *msgfmt,...)
const Int_t kInfo
Definition: TError.h:37
char name[80]
Definition: TGX11.cxx:109
int type
Definition: TGX11.cxx:120
#define gROOT
Definition: TROOT.h:406
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:556
void Debug(Int_t level, const char *va_(fmt),...)
#define va_(arg)
Definition: Varargs.h:41
void AddDescriptor(TBranchProxyDescriptor *desc, Bool_t isBase)
virtual Bool_t IsEquivalent(const TBranchProxyClassDescriptor *other)
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
Bool_t IsEquivalent(const TFriendProxyDescriptor *other)
void OutputClassDecl(FILE *hf, int offset, UInt_t maxVarname)
void AddHeader(TClass *cl)
Add a header inclusion request.
TVirtualStreamerInfo * GetStreamerInfo(TBranch *branch, TIter current, TClass *cl)
Return the correct TStreamerInfo of class 'cl' in the list of branches (current) [Assuming these bran...
TVirtualStreamerInfo * GetBaseClass(TStreamerElement *element)
Check if element is a base class and if yes, return the base class.
TString GetContainedClassName(TBranchElement *branch, TStreamerElement *element, Bool_t ispointer)
Get name of class inside a container.
void AddMissingClassAsEnum(const char *clname, Bool_t isscope)
TBranchProxyClassDescriptor * AddClass(TBranchProxyClassDescriptor *desc)
void AddDescriptor(TBranchProxyDescriptor *desc)
void AddPragma(const char *pragma_text)
UInt_t AnalyzeOldLeaf(TLeaf *leaf, UInt_t level, TBranchProxyClassDescriptor *topdesc)
Bool_t NeedToEmulate(TClass *cl, UInt_t level)
UInt_t AnalyzeOldBranch(TBranch *branch, UInt_t level, TBranchProxyClassDescriptor *desc)
void AnalyzeElement(TBranch *branch, TStreamerElement *element, UInt_t level, TBranchProxyClassDescriptor *desc, const char *path)
TTreeProxyGenerator(TTree *tree, const char *script, const char *fileprefix, const char *option, UInt_t maxUnrolling)
void AddFriend(TFriendProxyDescriptor *desc)
void CheckForMissingClass(const char *clname)
UInt_t AnalyzeBranches(UInt_t level, TBranchProxyClassDescriptor *topdesc, TBranchElement *branch, TVirtualStreamerInfo *info=0)
void ParseOptions()
Parse the options string.
void WriteProxy()
Check whether the file exist and do something useful if it does.
A Branch for the case of an object.
TBranchElement * GetBranchCount() const
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
Int_t GetType() const
A TTree is a list of TBranches.
Definition: TBranch.h:91
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1312
virtual char * GetAddress() const
Definition: TBranch.h:210
TTree * GetTree() const
Definition: TBranch.h:250
TObjArray * GetListOfBranches()
Definition: TBranch.h:244
Int_t GetSplitLevel() const
Definition: TBranch.h:248
virtual Int_t GetEntry(Long64_t entry=0, Int_t getall=0)
Read all leaves of entry and return total number of bytes read.
Definition: TBranch.cxx:1591
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:2028
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2546
TObjArray * GetListOfLeaves()
Definition: TBranch.h:245
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1991
TClass instances represent classes, structs and namespaces in the ROOT type system.
Definition: TClass.h:80
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2300
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:391
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process's memory.
Definition: TClass.cxx:5875
TVirtualStreamerInfo * GetStreamerInfo(Int_t version=0, Bool_t isTransient=kFALSE) const
returns a pointer to the TVirtualStreamerInfo object for version If the object does not exist,...
Definition: TClass.cxx:4562
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2877
@ kIsEmulation
Definition: TClass.h:101
static TClass * GetClass(const char *name, Bool_t load=kTRUE, Bool_t silent=kFALSE)
Static method returning pointer to TClass of the specified class name.
Definition: TClass.cxx:2948
An array of clone (identical) objects.
Definition: TClonesArray.h:32
TClass * GetClass() const
Definition: TClonesArray.h:56
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
virtual TFile * GetFile() const
Definition: TDirectory.h:163
This class is a small helper class to implement reading a data member on an object stored in a TTree.
Definition: TFormLeafInfo.h:49
virtual void * GetLocalValuePointer(TLeaf *leaf, Int_t instance=0)
returns the address of the value pointed to by the TFormLeafInfo.
A TFriendElement TF describes a TTree object TF in a file.
virtual TTree * GetTree()
Return pointer to friend TTree.
TObject * Next()
Definition: TCollection.h:249
void Reset()
Definition: TCollection.h:252
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:49
virtual const char * GetTypeName() const
Definition: TLeaf.h:130
TBranch * GetBranch() const
Definition: TLeaf.h:107
virtual void Add(TObject *obj)
Definition: TList.h:87
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:577
The TNamed class is the base class for all named ROOT classes.
Definition: TNamed.h:29
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:164
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:140
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
An array of TObjects.
Definition: TObjArray.h:37
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:523
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:90
TObject * At(Int_t idx) const
Definition: TObjArray.h:166
Collectable string class.
Definition: TObjString.h:28
TString & String()
Definition: TObjString.h:48
Mother of all ROOT objects.
Definition: TObject.h:37
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
Definition: TObject.h:187
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:443
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:401
Int_t LastIndex() const
const char * GetCountName() const
Int_t GetType() const
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
Int_t GetArrayDim() const
Int_t GetMaxIndex(Int_t i) const
const char * GetTypeName() const
Basic string class.
Definition: TString.h:131
Ssiz_t Length() const
Definition: TString.h:405
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:677
const char * Data() const
Definition: TString.h:364
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:687
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:892
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:610
TString & Prepend(const char *cs)
Definition: TString.h:656
TString & Remove(Ssiz_t pos)
Definition: TString.h:668
TString & Append(const char *cs)
Definition: TString.h:559
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition: TString.cxx:2311
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:619
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:634
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3941
int GetPathInfo(const char *path, Long_t *id, Long_t *size, Long_t *flags, Long_t *modtime)
Get info about a file: id, size, flags, modification time.
Definition: TSystem.cxx:1393
virtual FILE * TempFileName(TString &base, const char *dir=nullptr)
Create a secure temporary file by appending a unique 6 letter string to base.
Definition: TSystem.cxx:1492
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition: TSystem.cxx:1345
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:930
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1541
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1027
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1376
Used to pass a selection expression to the Tree drawing routine.
Definition: TTreeFormula.h:58
virtual TLeaf * GetLeaf(Int_t n) const
Return leaf corresponding to serial number n.
TFormLeafInfo * GetLeafInfo(Int_t code) const
Return DataMember corresponding to code.
A TTree represents a columnar dataset.
Definition: TTree.h:78
TDirectory * GetDirectory() const
Definition: TTree.h:456
virtual Long64_t GetReadEntry() const
Definition: TTree.h:503
virtual TClass * GetValueClass() const =0
Abstract Interface class describing Streamer information for one class.
virtual TObjArray * GetElements() const =0
virtual TClass * GetClass() const =0
const Int_t n
Definition: legend1.C:16
static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen, TClass *cl)
Add the "pragma C++ class" if needed and return true if it has been added or if it is known to not be...
TString GetArrayType(TStreamerElement *element, const char *subtype, TTreeProxyGenerator::EContainer container)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Definition: StringConv.hxx:21
bool areEqual(const RULE *r1, const RULE *r2, bool moduloNameOrPattern=false)
bool IsStdClass(const char *type)
return true if the class belongs to the std namespace
std::string ShortType(const char *typeDesc, int mode)
Return the absolute type of typeDesc.
@ kDropTrailStar
Definition: TClassEdit.h:76
Definition: tree.py:1
auto * l
Definition: textangle.C:4