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 <cstdio>
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#include "TBranchElement.h"
67#include "TChain.h"
68#include "TFile.h"
69#include "TFriendElement.h"
70#include "TLeaf.h"
71#include "TLeafC.h"
72#include "TTree.h"
74#include "TStreamerElement.h"
75#include "TSystem.h"
76#include "TLeafObject.h"
78
79void Debug(Int_t level, const char *va_(fmt), ...)
80{
81 // Use this function in case an error occurred.
82
83 if (gDebug>=level) {
84 va_list ap;
85 va_start(ap,va_(fmt));
86 ErrorHandler(kInfo,"TTreeProxyGenerator",va_(fmt), ap);
87 va_end(ap);
88 }
89}
90
91namespace {
92
93 Bool_t AreDifferent(const TString& from, const TString& to)
94 {
95 FILE *left = fopen(from.Data(),"r");
96 FILE *right = fopen(to.Data(),"r");
97
98 char leftbuffer[256];
99 char rightbuffer[256];
100
101 char *lvalue,*rvalue;
102
104
105 do {
106 lvalue = fgets(leftbuffer, sizeof(leftbuffer), left);
107 rvalue = fgets(rightbuffer, sizeof(rightbuffer), right);
108
109 if (lvalue&&rvalue) {
110 if (strstr(lvalue,"by ROOT version")) {
111 // skip the comment line with the time and date
112 } else {
113 areEqual = areEqual && (0 == strncmp(lvalue,rvalue,sizeof(leftbuffer)));
114 }
115 }
116 if (lvalue&&!rvalue) areEqual = kFALSE;
117 if (rvalue&&!lvalue) areEqual = kFALSE;
118
119 } while(areEqual && lvalue && rvalue);
120
121 fclose(left);
122 fclose(right);
123
124 return !areEqual;
125 }
126}
127
128namespace ROOT {
129namespace Internal {
130
131 TString GetArrayType(TStreamerElement *element, const char *subtype,
133 {
134 TString result;
135 int ndim = 0;
138 const char *countname = elem->GetCountName();
139 if (countname && strlen(countname)>0) ndim = 1;
140 }
141 ndim += element->GetArrayDim();
142
143 TString middle;
144 if (container == TTreeProxyGenerator::kClones) {
145 middle = "Cla";
146 } else if (container == TTreeProxyGenerator::kSTL) {
147 middle = "Stl";
148 }
149
150 if (ndim==0) {
151 result = "T";
152 result += middle;
153 result += subtype;
154 result += "Proxy";
155 } else if (ndim==1) {
156 result = "T";
157 result += middle;
158 result += "Array";
159 result += subtype;
160 result += "Proxy";
161 } else {
162 result = "T";
163 result += middle;
164 result += "ArrayProxy<";
165 for(Int_t ind = ndim - 2; ind > 0; --ind) {
166 result += "TMultiArrayType<";
167 }
168 result += "TArrayType<";
169 result += element->GetTypeName();
170 result += ",";
171 result += element->GetMaxIndex(ndim-1);
172 result += "> ";
173 for(Int_t ind = ndim - 2; ind > 0; --ind) {
174 result += ",";
175 result += element->GetMaxIndex(ind);
176 result += "> ";
177 }
178 result += ">";
179 }
180 return result;
181
182 /*
183 if (!strcmp("unsigned int", name))
184 sprintf(line, "%u", *(unsigned int *)buf);
185 else if (!strcmp("int", name))
186 sprintf(line, "%d", *(int *)buf);
187 else if (!strcmp("unsigned long", name))
188 sprintf(line, "%lu", *(unsigned long *)buf);
189 else if (!strcmp("long", name))
190 sprintf(line, "%ld", *(long *)buf);
191 else if (!strcmp("unsigned short", name))
192 sprintf(line, "%hu", *(unsigned short *)buf);
193 else if (!strcmp("short", name))
194 sprintf(line, "%hd", *(short *)buf);
195 else if (!strcmp("unsigned char", name))
196 sprintf(line, "%u", *(unsigned char *)buf);
197 else if (!strcmp("bool", name))
198 sprintf(line, "%u", *(unsigned char *)buf);
199 else if (!strcmp("char", name))
200 sprintf(line, "%d", *(char *)buf);
201 else if (!strcmp("float", name))
202 sprintf(line, "%g", *(float *)buf);
203 else if (!strcmp("double", name))
204 sprintf(line, "%g", *(double *)buf);
205 */
206 }
207
208 ////////////////////////////////////////////////////////////////////////////////
209 /// Constructor.
210
212 const char *script,
213 const char *fileprefix,
214 const char *option, UInt_t maxUnrolling) :
215 TTreeGeneratorBase(tree, option),
216 fMaxDatamemberType(2),
217 fScript(script),
218 fCutScript(),
219 fPrefix(fileprefix),
220 fHeaderFileName(),
221 fOptions(0),
222 fMaxUnrolling(maxUnrolling),
223 fCurrentListOfTopProxies(&fListOfTopProxies)
224 {
225 ParseOptions();
226
228
229 WriteProxy();
230 }
231
232 ////////////////////////////////////////////////////////////////////////////////
233 /// Constructor.
234
236 const char *script, const char *cutscript,
237 const char *fileprefix,
238 const char *option, UInt_t maxUnrolling) :
239 TTreeGeneratorBase(tree, option),
240 fMaxDatamemberType(2),
241 fScript(script),
242 fCutScript(cutscript),
243 fPrefix(fileprefix),
244 fHeaderFileName(),
245 fOptions(0),
246 fMaxUnrolling(maxUnrolling),
247 fCurrentListOfTopProxies(&fListOfTopProxies)
248 {
249 ParseOptions();
250
252
253 WriteProxy();
254 }
255
256 ////////////////////////////////////////////////////////////////////////////////
257 /// Return true if we should create a nested class representing this class
258
260 {
261 return cl!=0 && cl->TestBit(TClass::kIsEmulation);
262 }
263
264 ////////////////////////////////////////////////////////////////////////////////
265 /// Add a Class Descriptor.
266
269 {
270 if (desc==0) return 0;
271
274
275 int count = 0;
276 while (existing) {
277 if (! existing->IsEquivalent( desc ) ) {
278 TString newname = desc->GetRawSymbol();
279 count++;
280 newname += "_";
281 newname += count;
282
283 desc->SetName(newname);
285 } else {
286 // we already have the exact same class
287 delete desc;
288 return existing;
289 }
290 }
291 fListOfClasses.Add(desc);
292 return desc;
293 }
294
295 ////////////////////////////////////////////////////////////////////////////////
296 /// Add Friend descriptor.
297
299 {
300 if (desc==0) return;
301
302 TFriendProxyDescriptor *existing =
304
305 int count = 0;
306 while (existing) {
307 if (! existing->IsEquivalent( desc ) ) {
308 TString newname = desc->GetName();
309 count++;
310 newname += "_";
311 newname += count;
312
313 desc->SetName(newname);
314 existing = (TFriendProxyDescriptor*)fListOfFriends(desc->GetName());
315
316 } else {
317
318 desc->SetDuplicate();
319 break;
320 }
321 }
322
323 // Insure uniqueness of the title also.
324 TString basetitle = desc->GetTitle();
325 TIter next( &fListOfFriends );
326 while ( (existing = (TFriendProxyDescriptor*)next()) ) {
327 if (strcmp(existing->GetTitle(),desc->GetTitle())==0) {
328
329 TString newtitle = basetitle;
330 count++;
331 newtitle += "_";
332 newtitle += count;
333
334 desc->SetTitle(newtitle);
335
336 // Restart of the beginning of the loop.
337 next = &fListOfFriends;
338 }
339 }
340
341 fListOfFriends.Add(desc);
342 }
343
344 ////////////////////////////////////////////////////////////////////////////////
345 /// Add a forward declaration request.
346
347 void TTreeProxyGenerator::AddForward( const char *classname )
348 {
349 TObject *obj = fListOfForwards.FindObject(classname);
350 if (obj) return;
351
352 if (strstr(classname,"<")!=0) {
353 // this is a template instantiation.
354 // let's ignore it for now
355
356 if (gDebug>=6) Warning("AddForward","Forward declaration of templated class not implemented yet.");
357 } else if (strcmp(classname,"string")==0) {
358 // no need to forward declare string
359 } else {
360 fListOfForwards.Add(new TNamed(classname,Form("class %s;\n",classname)));
361 }
362 return;
363 }
364
365 ////////////////////////////////////////////////////////////////////////////////
366 /// Add a forward declaration request.
367
369 {
370 if (cl) AddForward(cl->GetName());
371 }
372
373 ////////////////////////////////////////////////////////////////////////////////
374 /// Add a forward declaration request.
375
376 void TTreeProxyGenerator::AddPragma(const char *pragma_text)
377 {
378 TIter i( &fListOfPragmas );
379 for(TObjString *n = (TObjString*) i(); n; n = (TObjString*)i() ) {
380 if (pragma_text == n->GetString()) {
381 return;
382 }
383 }
384
385 fListOfPragmas.Add( new TObjString( pragma_text ) );
386
387 }
388
389 ////////////////////////////////////////////////////////////////////////////////
390 /// Add a branch descriptor.
391
393 {
394 if (desc) {
395 TBranchProxyDescriptor *existing =
397 if (existing) {
398 Warning("TTreeProxyGenerator","The branch name \"%s\" is duplicated. Only the first instance \n"
399 "\twill be available directly. The other instance(s) might be available via their complete name\n"
400 "\t(including the name of their mother branche's name).",desc->GetName());
401 } else {
403 UInt_t len = strlen(desc->GetTypeName());
404 if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
405 }
406 }
407 }
408
409 ////////////////////////////////////////////////////////////////////////////////
410 /// Generate an enum for a given type if it is not known in the list of class
411 /// unless the type itself a template.
412
413 void TTreeProxyGenerator::AddMissingClassAsEnum(const char *clname, Bool_t isscope)
414 {
415 if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
416
417 TObject *obj = fListOfForwards.FindObject(clname);
418 if (obj) return;
419
420 // The class does not exist, let's create it if ew can.
421 if (clname[strlen(clname)-1]=='>') {
422 // Template instantiation.
423 fListOfForwards.Add(new TNamed(clname,TString::Format("template <> class %s { public: operator int() { return 0; } };\n", clname).Data()));
424 } else if (isscope) {
425 // a scope
426
427 } else {
428 // Class or enum we know nothing about, let's assume it is an enum.
429 fListOfForwards.Add(new TNamed(clname,TString::Format("enum %s { kDefault_%s };\n", clname, clname).Data()));
430 }
431 }
432 }
433
434 ////////////////////////////////////////////////////////////////////////////////
435 /// Check if the template parameter refers to an enum and/or a missing class (we can't tell those 2 apart unless
436 /// the name as template syntax).
437
439 {
440 UInt_t len = strlen(clname);
441 UInt_t nest = 0;
442 UInt_t last = 0;
443 //Bool_t istemplate = kFALSE; // mark whether the current right most entity is a class template.
444
445 for (UInt_t i = 0; i < len; ++i) {
446 switch (clname[i]) {
447 case ':':
448 if (nest == 0 && clname[i+1] == ':') {
449 TString incName(clname, i);
450 AddMissingClassAsEnum(incName.Data(), kTRUE);
451 //istemplate = kFALSE;
452 }
453 break;
454 case '<':
455 ++nest;
456 if (nest == 1) last = i + 1;
457 break;
458 case '>':
459 if (nest == 0) return; // The name is not well formed, give up.
460 --nest; /* intentional fall through to the next case */
461 case ',':
462 if ((clname[i] == ',' && nest == 1) || (clname[i] == '>' && nest == 0)) {
463 TString incName(clname + last, i - last);
465 if (clname[i] == '>' && nest == 1) incName.Append(">");
466
467 if (isdigit(incName[0])) {
468 // Not a class name, nothing to do.
469 } else {
471 }
472 last = i + 1;
473 }
474 }
475 }
477 }
478
479 ////////////////////////////////////////////////////////////////////////////////
480 /// Analyze the sub-branch and populate the TTreeProxyGenerator or the topdesc with
481 /// its findings.
482
485 {
486 if (info==0) info = branch->GetInfo();
487
488 TIter branches( branch->GetListOfBranches() );
489
490 return AnalyzeBranches( level, topdesc, branches, info );
491 }
492
493 ////////////////////////////////////////////////////////////////////////////////
494 /// Analyze the list of sub branches of a TBranchElement by looping over
495 /// the streamer elements and create the appropriate class proxies.
496
499 TIter &branches,
501 {
502/*
503
504 Find the content class name (GetClassName)
505 Record wether this is a collection or not
506
507 Find the StreamerInfo
508
509 For each streamerelement
510 if element is base
511 if name match, loop over subbranches
512 otherwise loop over current branches
513 else if eleement is object (or pointer to object?)
514 if name match go ahead, loop over subbranches
515 if name does not match. loop over current branches (fix names).
516 else
517 add branch.
518
519*/
520 UInt_t lookedAt = 0;
521 EContainer container = kNone;
522 TString middle;
523 TString proxyTypeName;
525 TString containerName;
526 TString subBranchPrefix;
527 Bool_t skipped = false;
528
529 {
530 TIter peek = branches;
531 TBranchElement *branch = (TBranchElement*)peek();
532 if (topdesc && topdesc->IsClones()) {
533 container = kClones;
534 middle = "Cla";
536 containerName = "TClonesArray";
537 } else if (topdesc && topdesc->IsSTL()) {
538 container = kSTL;
539 middle = "Stl";
540 outer_isclones = TBranchProxyClassDescriptor::kSTL;
541 containerName = topdesc->GetContainerName();
542 } else if (!topdesc && branch && branch->GetBranchCount() == branch->GetMother()) {
543 if ( ((TBranchElement*)(branch->GetMother()))->GetType()==3) {
544 container = kClones;
545 middle = "Cla";
547 containerName = "TClonesArray";
548 } else {
549 container = kSTL;
550 middle = "Stl";
551 outer_isclones = TBranchProxyClassDescriptor::kSTL;
552 containerName = branch->GetMother()->GetClassName();
553 }
554 } else if (branch->GetType() == 3) {
556 containerName = "TClonesArray";
557 } else if (branch->GetType() == 4) {
558 outer_isclones = TBranchProxyClassDescriptor::kSTL;
559 containerName = branch->GetMother()->GetSubBranch(branch)->GetClassName();
560 }
561 if (topdesc) {
562 subBranchPrefix = topdesc->GetSubBranchPrefix();
563 } else {
564 TBranchElement *mom = (TBranchElement*)branch->GetMother();
565 subBranchPrefix = mom->GetName();
566 if (subBranchPrefix[subBranchPrefix.Length()-1]=='.') {
567 subBranchPrefix.Remove(subBranchPrefix.Length()-1);
568 } else if (mom->GetType()!=3 && mom->GetType() != 4) {
569 subBranchPrefix = "";
570 }
571 }
572 }
573 TIter elements( info->GetElements() );
574 for( TStreamerElement *element = (TStreamerElement*)elements();
575 element;
576 element = (TStreamerElement*)elements() )
577 {
578 Bool_t isBase = false;
579 Bool_t usedBranch = kTRUE;
580 TString prefix;
581 TIter peek = branches;
582 TBranchElement *branch = (TBranchElement*)peek();
583
584 if (branch==0) {
585 if (topdesc) {
586 Error("AnalyzeBranches","Ran out of branches when looking in branch %s, class %s",
587 topdesc->GetBranchName(), info->GetName());
588 } else {
589 Error("AnalyzeBranches","Ran out of branches when looking in class %s, element %s",
590 info->GetName(),element->GetName());
591 }
592 return lookedAt;
593 }
594
595 if (info->GetClass()->GetCollectionProxy() && strcmp(element->GetName(),"This")==0) {
596 // Skip the artificial streamer element.
597 continue;
598 }
599
600 if (element->GetType()==-1) {
601 // This is an ignored TObject base class.
602 continue;
603 }
604
605 TString branchname = branch->GetName();
606 TString branchEndname;
607 {
608 TLeaf *leaf = (TLeaf*)branch->GetListOfLeaves()->At(0);
609 if (leaf && outer_isclones == TBranchProxyClassDescriptor::kOut
610 && !(branch->GetType() == 3 || branch->GetType() == 4)) branchEndname = leaf->GetName();
611 else branchEndname = branch->GetName();
612 Int_t pos;
613 pos = branchEndname.Index(".");
614 if (pos!=-1) {
615 if (subBranchPrefix.Length() &&
616 branchEndname.BeginsWith( subBranchPrefix ) ) {
617 // brprefix += topdesc->GetSubBranchPrefix();
618 branchEndname.Remove(0,subBranchPrefix.Length()+1);
619 }
620 }
621 }
622
623 Bool_t ispointer = false;
624 switch(element->GetType()) {
625
626 case TVirtualStreamerInfo::kBool: { proxyTypeName = "T" + middle + "BoolProxy"; break; }
627 case TVirtualStreamerInfo::kChar: { proxyTypeName = "T" + middle + "CharProxy"; break; }
628 case TVirtualStreamerInfo::kShort: { proxyTypeName = "T" + middle + "ShortProxy"; break; }
629 case TVirtualStreamerInfo::kInt: { proxyTypeName = "T" + middle + "IntProxy"; break; }
630 case TVirtualStreamerInfo::kLong: { proxyTypeName = "T" + middle + "LongProxy"; break; }
631 case TVirtualStreamerInfo::kLong64: { proxyTypeName = "T" + middle + "Long64Proxy"; break; }
632 case TVirtualStreamerInfo::kFloat: { proxyTypeName = "T" + middle + "FloatProxy"; break; }
633 case TVirtualStreamerInfo::kFloat16: { proxyTypeName = "T" + middle + "Float16Proxy"; break; }
634 case TVirtualStreamerInfo::kDouble: { proxyTypeName = "T" + middle + "DoubleProxy"; break; }
635 case TVirtualStreamerInfo::kDouble32:{ proxyTypeName = "T" + middle + "Double32Proxy"; break; }
636 case TVirtualStreamerInfo::kUChar: { proxyTypeName = "T" + middle + "UCharProxy"; break; }
637 case TVirtualStreamerInfo::kUShort: { proxyTypeName = "T" + middle + "UShortProxy"; break; }
638 case TVirtualStreamerInfo::kUInt: { proxyTypeName = "T" + middle + "UIntProxy"; break; }
639 case TVirtualStreamerInfo::kULong: { proxyTypeName = "T" + middle + "ULongProxy"; break; }
640 case TVirtualStreamerInfo::kULong64: { proxyTypeName = "T" + middle + "ULong64Proxy"; break; }
641 case TVirtualStreamerInfo::kBits: { proxyTypeName = "T" + middle + "UIntProxy"; break; }
642
643 case TVirtualStreamerInfo::kCharStar: { proxyTypeName = GetArrayType(element,"Char",container); break; }
644
645 // array of basic types array[8]
646 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { proxyTypeName = GetArrayType(element,"Bool",container ); break; }
647 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { proxyTypeName = GetArrayType(element,"Char",container ); break; }
648 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { proxyTypeName = GetArrayType(element,"Short",container ); break; }
649 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { proxyTypeName = GetArrayType(element,"Int",container ); break; }
650 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { proxyTypeName = GetArrayType(element,"Long",container ); break; }
651 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { proxyTypeName = GetArrayType(element,"Long64",container ); break; }
652 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { proxyTypeName = GetArrayType(element,"Float",container ); break; }
653 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { proxyTypeName = GetArrayType(element,"Float16",container ); break; }
654 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { proxyTypeName = GetArrayType(element,"Double",container ); break; }
655 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ proxyTypeName = GetArrayType(element,"Double32",container ); break; }
656 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { proxyTypeName = GetArrayType(element,"UChar",container ); break; }
657 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { proxyTypeName = GetArrayType(element,"UShort",container ); break; }
658 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { proxyTypeName = GetArrayType(element,"UInt",container ); break; }
659 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { proxyTypeName = GetArrayType(element,"ULong",container ); break; }
660 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { proxyTypeName = GetArrayType(element,"ULong64",container ); break; }
661 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { proxyTypeName = GetArrayType(element,"UInt",container ); break; }
662
663 // pointer to an array of basic types array[n]
664 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { proxyTypeName = GetArrayType(element,"Bool",container ); break; }
665 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { proxyTypeName = GetArrayType(element,"Char",container ); break; }
666 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { proxyTypeName = GetArrayType(element,"Short",container ); break; }
667 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { proxyTypeName = GetArrayType(element,"Int",container ); break; }
668 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { proxyTypeName = GetArrayType(element,"Long",container ); break; }
669 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { proxyTypeName = GetArrayType(element,"Long64",container ); break; }
670 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { proxyTypeName = GetArrayType(element,"Float",container ); break; }
671 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { proxyTypeName = GetArrayType(element,"Float16",container ); break; }
672 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { proxyTypeName = GetArrayType(element,"Double",container ); break; }
673 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ proxyTypeName = GetArrayType(element,"Double32",container ); break; }
674 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { proxyTypeName = GetArrayType(element,"UChar",container ); break; }
675 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { proxyTypeName = GetArrayType(element,"UShort",container ); break; }
676 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { proxyTypeName = GetArrayType(element,"UInt",container ); break; }
677 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { proxyTypeName = GetArrayType(element,"ULong",container ); break; }
678 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { proxyTypeName = GetArrayType(element,"ULong64",container ); break; }
679 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { proxyTypeName = GetArrayType(element,"UInt",container ); break; }
680
681 // array counter //[n]
682 case TVirtualStreamerInfo::kCounter: { proxyTypeName = "T" + middle + "IntProxy"; break; }
683
684
693 // set as pointers and fall through to the next switches
694 ispointer = true;
703 TClass *cl = element->GetClassPointer();
704 R__ASSERT(cl);
705
706 proxyTypeName = Form("T%sObjProxy<%s >", middle.Data(), cl->GetName());
707 TString cname = cl->GetName();
708 TBranchProxyClassDescriptor::ELocation isclones = outer_isclones;
709 if (cl==TClonesArray::Class()) {
711 cname = GetContainedClassName(branch, element, ispointer);
712 containerName = "TClonesArray";
713 } else if (cl->GetCollectionProxy()) {
715 containerName = cl->GetName();
716 TClass *valueClass = cl->GetCollectionProxy()->GetValueClass();
717 if (valueClass) cname = valueClass->GetName();
718 else {
720 proxyTypeName = Form("TStlSimpleProxy<%s >", cl->GetName());
721// AddPragma(Form("#pragma create TClass %s;\n", cl->GetName()));
722 if (!cl->IsLoaded()) AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
723 }
724 }
725
726 TBranch *parent = branch->GetMother()->GetSubBranch(branch);
727 TVirtualStreamerInfo *objInfo = 0;
728 if (branch->GetListOfBranches()->GetEntries()) {
729 objInfo = ((TBranchElement*)branch->GetListOfBranches()->At(0))->GetInfo();
730 } else {
731 objInfo = branch->GetInfo();
732 }
733 if (element->IsBase()) {
734 isBase = true;
735 prefix = "base";
736
737 if (cl == TObject::Class() && info->GetClass()->CanIgnoreTObjectStreamer())
738 {
739 continue;
740 }
741
742 TBranchProxyClassDescriptor *cldesc = 0;
743
744 if (branchEndname == element->GetName()) {
745 // We have a proper node for the base class, recurse
746
747 if (branch->GetListOfBranches()->GetEntries() == 0) {
748 // The branch contains a non-split base class that we are unfolding!
749
750 // See AnalyzeTree for similar code!
751 TBranchProxyClassDescriptor *local_cldesc = 0;
752
753 TVirtualStreamerInfo *binfo = branch->GetInfo();
754 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
755 binfo = cl->GetStreamerInfo(); // might be the wrong version
756 }
757 local_cldesc = new TBranchProxyClassDescriptor(cl->GetName(), binfo,
758 branch->GetName(),
759 isclones, 0 /* unsplit object */,
760 containerName);
761
762 TStreamerElement *elem = 0;
763
764 TIter next(binfo->GetElements());
765 while( (elem = (TStreamerElement*)next()) ) {
766 AnalyzeElement(branch,elem,level+1,local_cldesc,"");
767
768 }
769 if (NeedToEmulate(cl,0)) {
770 proxyTypeName = local_cldesc->GetName();
771 local_cldesc = AddClass(local_cldesc);
772 }
773
774 } else {
775
776 Int_t pos = branchname.Last('.');
777 if (pos != -1) {
778 branchname.Remove(pos);
779 }
780 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
781 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
782 branchname,
783 local_prefix,
784 isclones, branch->GetSplitLevel(),
785 containerName);
786 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
787 }
788 } else {
789 // We do not have a proper node for the base class, we need to loop over
790 // the next branches
791 Int_t pos = branchname.Last('.');
792 if (pos != -1) {
793 branchname.Remove(pos);
794 }
795 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
796 objInfo = GetBaseClass( element );
797 if (objInfo == 0) {
798 // There is no data in this base class
799 continue;
800 }
801 cl = objInfo->GetClass();
802 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
803 branchname,
804 local_prefix,
805 isclones, branch->GetSplitLevel(),
806 containerName);
807 usedBranch = kFALSE;
808 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
809 }
810
811 TBranchProxyClassDescriptor *added = AddClass(cldesc);
812 if (added) proxyTypeName = added->GetName();
813
814 } else {
815 TBranchProxyClassDescriptor *cldesc = 0;
816
817 if (branchEndname == element->GetName()) {
818
819 // We have a proper node for the base class, recurse
820 if (branch->GetListOfBranches()->GetEntries() == 0) {
821 // The branch contains a non-split object that we are unfolding!
822
823 // See AnalyzeTree for similar code!
824 TBranchProxyClassDescriptor *local_cldesc = 0;
825
826 TVirtualStreamerInfo *binfo = branch->GetInfo();
827 if (strcmp(cl->GetName(),binfo->GetName())!=0) {
828 binfo = cl->GetStreamerInfo(); // might be the wrong version
829 }
830 local_cldesc = new TBranchProxyClassDescriptor(cl->GetName(), binfo,
831 branch->GetName(),
832 isclones, 0 /* unsplit object */,
833 containerName);
834
835 TStreamerElement *elem = 0;
836
837 TIter next(binfo->GetElements());
838 while( (elem = (TStreamerElement*)next()) ) {
839 AnalyzeElement(branch,elem,level+1,local_cldesc,"");
840 }
841
842 if (NeedToEmulate(cl,0)) {
843 proxyTypeName = local_cldesc->GetName();
844 local_cldesc = AddClass(local_cldesc);
845 }
846
847 } else {
848
849 if (isclones != TBranchProxyClassDescriptor::kOut) {
850 // We have to guess the version number!
851 cl = TClass::GetClass(cname);
852 objInfo = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
853 }
854 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
855 branch->GetName(),
856 branch->GetName(),
857 isclones, branch->GetSplitLevel(),
858 containerName);
859 lookedAt += AnalyzeBranches( level+1, cldesc, branch, objInfo);
860 }
861 } else {
862 // We do not have a proper node for the base class, we need to loop over
863 // the next branches
864 TString local_prefix = topdesc ? topdesc->GetSubBranchPrefix() : parent->GetName();
865 if (local_prefix.Length()) local_prefix += ".";
866 local_prefix += element->GetName();
867 objInfo = branch->GetInfo();
868 Int_t pos = branchname.Last('.');
869 if (pos != -1) {
870 branchname.Remove(pos);
871 }
872 if (isclones != TBranchProxyClassDescriptor::kOut) {
873 // We have to guess the version number!
874 cl = TClass::GetClass(cname);
875 objInfo = GetStreamerInfo(branch, branches, cl);
876 }
877 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), objInfo,
878 branchname,
879 local_prefix,
880 isclones, branch->GetSplitLevel(),
881 containerName);
882 usedBranch = kFALSE;
883 skipped = kTRUE;
884 lookedAt += AnalyzeBranches( level, cldesc, branches, objInfo );
885 }
886
887 TBranchProxyClassDescriptor *added = AddClass(cldesc);
888 if (added) proxyTypeName = added->GetName();
889
890 }
891
892 AddForward(cl);
893 AddHeader(cl);
894 break;
895 }
896
897 default:
898 Error("AnalyzeBranch",
899 "Unsupported type for %s (%d).",
900 branch->GetName(),element->GetType());
901
902 }
903
904 TString dataMemberName = element->GetName();
905 if (topdesc) {
906 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
907 proxyTypeName, branchname, true, skipped ), isBase );
908 } else {
909 dataMemberName.Prepend(prefix);
910 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
911 proxyTypeName, branchname, true, skipped ) );
912 }
913
914 if (usedBranch) {
915 branches.Next();
916 ++lookedAt;
917 }
918 }
919 return lookedAt;
920 }
921
922 ////////////////////////////////////////////////////////////////////////////////
923 /// Analyze the leaf and populate the `TTreeProxyGenerator or
924 /// the topdesc with its findings.
925
928 {
929 if (leaf->IsA()==TLeafObject::Class()) {
930 Error("AnalyzeOldLeaf","TLeafObject not supported yet");
931 return 0;
932 }
933
934 TString leafTypeName = leaf->GetTypeName();
935 Int_t pos = leafTypeName.Last('_');
936 if (pos!=-1) leafTypeName.Remove(pos);
937
938 // Int_t len = leaf->GetLen();
939 // TLeaf *leafcount = leaf->GetLeafCount();
940
941 UInt_t dim = 0;
942 std::vector<Int_t> maxDim;
943 //maxDim[0] = maxDim[1] = maxDim[2] = 1;
944
945 TString dimensions;
946 TString temp = leaf->GetName();
947 pos = temp.Index("[");
948 if (pos!=-1) {
949 if (pos) temp.Remove(0,pos);
950 dimensions.Append(temp);
951 }
952 temp = leaf->GetTitle();
953 pos = temp.Index("[");
954 if (pos!=-1) {
955 if (pos) temp.Remove(0,pos);
956 dimensions.Append(temp);
957 }
958
959 Int_t dimlen = dimensions.Length();
960
961 if (dimlen) {
962 const char *current = dimensions.Data();
963
964 Int_t index;
965 Int_t scanindex ;
966 while (current) {
967 current++;
968 if (current[0] == ']') {
969 maxDim.push_back(-1); // maxDim[dim] = -1; // Loop over all elements;
970 } else {
971 scanindex = sscanf(current,"%d",&index);
972 if (scanindex) {
973 maxDim.push_back(index); // maxDim[dim] = index;
974 } else {
975 maxDim.push_back(-2); // maxDim[dim] = -2; // Index is calculated via a variable.
976 }
977 }
978 dim ++;
979 current = (char*)strstr( current, "[" );
980 }
981
982 }
983 //char *twodim = (char*)strstr(leaf->GetTitle(),"][");
984
985 //if (leafcount) {
986 // len = leafcount->GetMaximum();
987 //}
988 if (dim == 0 && leaf->IsA() == TLeafC::Class()) {
989 // For C style strings.
990 dim = 1;
991 }
992
994 switch (dim) {
995 case 0: {
996 type = "T";
997 type += leafTypeName;
998 type += "Proxy";
999 break;
1000 }
1001 case 1: {
1002 type = "TArray";
1003 type += leafTypeName;
1004 type += "Proxy";
1005 break;
1006 }
1007 default: {
1008 type = "TArrayProxy<";
1009 for(Int_t ind = dim - 2; ind > 0; --ind) {
1010 type += "TMultiArrayType<";
1011 }
1012 type += "TArrayType<";
1013 type += leaf->GetTypeName();
1014 type += ",";
1015 type += maxDim[dim-1];
1016 type += "> ";
1017 for(Int_t ind = dim - 2; ind > 0; --ind) {
1018 type += ",";
1019 type += maxDim[ind];
1020 type += "> ";
1021 }
1022 type += ">";
1023 break;
1024 }
1025 }
1026
1027 TString branchName = leaf->GetBranch()->GetName();
1028 TString dataMemberName = leaf->GetName();
1029
1030 if (topdesc) {
1031 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1032 type,
1033 branchName.Data(),
1034 true, false, true ),
1035 0 );
1036 } else {
1037 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1038 type,
1039 branchName.Data(),
1040 true, false, true ) );
1041 }
1042
1043 return 0;
1044
1045 }
1046
1047 ////////////////////////////////////////////////////////////////////////////////
1048 /// Analyze the branch and populate the TTreeProxyGenerator or the topdesc with
1049 /// its findings. Sometimes several branch of the mom are also analyzed,
1050 /// the number of such branches is returned (this happens in the case of
1051 /// embedded objects inside an object inside a clones array split more than
1052 /// one level.
1053
1056 {
1057 UInt_t extraLookedAt = 0;
1058 TString prefix;
1059
1060 TString branchName = branch->GetName();
1061
1062 TObjArray *leaves = branch->GetListOfLeaves();
1063 Int_t nleaves = leaves ? leaves->GetEntriesFast() : 0;
1064
1065 if (nleaves>1) {
1066
1067 // Create a holder
1068 TString type = "unknown";
1070 if (cldesc) {
1071 type = cldesc->GetName();
1072
1073 for(int l=0;l<nleaves;l++) {
1074 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(l);
1075 extraLookedAt += AnalyzeOldLeaf(leaf,level+1,cldesc);
1076 }
1077 }
1078
1079 TString dataMemberName = branchName;
1080
1081 if (topdesc) {
1082 topdesc->AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1083 type,
1084 branchName.Data() ),
1085 0 );
1086 } else {
1087 // leafname.Prepend(prefix);
1088 AddDescriptor( new TBranchProxyDescriptor( dataMemberName.Data(),
1089 type,
1090 branchName.Data() ) );
1091 }
1092
1093 } else {
1094
1095 TLeaf *leaf = (TLeaf*)leaves->UncheckedAt(0);
1096 extraLookedAt += AnalyzeOldLeaf(leaf,level,topdesc);
1097
1098 }
1099
1100
1101 return extraLookedAt;
1102
1103 }
1104
1105 ////////////////////////////////////////////////////////////////////////////////
1106 /// Analyze a TTree and its (potential) friends.
1107
1109 {
1110 TIter next( tree->GetListOfBranches() );
1111 TBranch *branch;
1112 while ( (branch = (TBranch*)next()) ) {
1113 TVirtualStreamerInfo *info = 0;
1114 const char *branchname = branch->GetName();
1115 const char *classname = branch->GetClassName();
1116 if (classname && strlen(classname)) {
1117 AddForward( classname );
1118 AddHeader( classname );
1119 }
1120
1122 TClass *cl = TClass::GetClass(classname);
1123 TString type = "unknown";
1124 if (cl) {
1126 TString containerName = "";
1127 if (cl==TClonesArray::Class()) {
1129 containerName = "TClonesArray";
1130 if (branch->IsA()==TBranchElement::Class()) {
1131 const char *cname = ((TBranchElement*)branch)->GetClonesName();
1132 TClass *ncl = TClass::GetClass(cname);
1133 if (ncl) {
1134 cl = ncl;
1135 info = GetStreamerInfo(branch,branch->GetListOfBranches(),cl);
1136 } else {
1137 Error("AnalyzeTree",
1138 "Introspection of TClonesArray in older file not implemented yet.");
1139 }
1140 } else {
1141 TClonesArray **ptr = (TClonesArray**)branch->GetAddress();
1142 TClonesArray *clones = 0;
1143 if (ptr==0) {
1144 clones = new TClonesArray;
1145 branch->SetAddress(&clones);
1146 ptr = &clones;
1147 }
1148 branch->GetEntry(0);
1149 TClass *ncl = *ptr ? (*ptr)->GetClass() : 0;
1150 if (ncl) {
1151 cl = ncl;
1152 } else {
1153 Error("AnalyzeTree",
1154 "Introspection of TClonesArray for %s failed.",branch->GetName());
1155 }
1156 }
1157 } else if (cl->GetCollectionProxy()) {
1159 containerName = cl->GetName();
1160 if (cl->GetCollectionProxy()->GetValueClass()) {
1161 cl = cl->GetCollectionProxy()->GetValueClass();
1162 } else {
1164 type = Form("TStlSimpleProxy<%s >", cl->GetName());
1165 AddHeader(cl);
1166 if (!cl->IsLoaded()) AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1167 AddDescriptor( new TBranchProxyDescriptor( branchname, type, branchname ) );
1168 continue;
1169 }
1170 }
1171 if (cl) {
1172 if (NeedToEmulate(cl,0) || branch->GetListOfBranches()->GetEntries() || branch->GetSplitLevel() || fMaxUnrolling) {
1173 TBranchElement *be = dynamic_cast<TBranchElement*>(branch);
1174 TVirtualStreamerInfo *beinfo = (be && isclones == TBranchProxyClassDescriptor::kOut)
1175 ? be->GetInfo() : cl->GetStreamerInfo(); // the 2nd hand need to be fixed
1176 desc = new TBranchProxyClassDescriptor(cl->GetName(), beinfo, branchname,
1177 isclones, branch->GetSplitLevel(),containerName);
1178 info = beinfo;
1179 } else {
1180 type = Form("TObjProxy<%s >",cl->GetName());
1181 }
1182 }
1183 }
1184
1185 if ( branch->GetListOfBranches()->GetEntries() == 0 ) {
1186
1187 if (cl) {
1188 // We have a non-split object!
1189
1190 if (desc) {
1192 TStreamerElement *elem = 0;
1193
1194 TIter cnext(cinfo->GetElements());
1195 while( (elem = (TStreamerElement*)cnext()) ) {
1196 AnalyzeElement(branch,elem,1,desc,"");
1197 }
1198
1199 desc = AddClass(desc);
1200 if (desc) {
1201 type = desc->GetName();
1202
1203 TString dataMemberName = branchname;
1204
1205 AddDescriptor( new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1206 }
1207 } else {
1208 // We have a top level non split.
1210 type,
1211 branch->GetName(),
1212 true, false, false ) );
1213 }
1214 } else {
1215
1216 // We have a top level raw type.
1217 AnalyzeOldBranch(branch, 0, 0);
1218 }
1219
1220 } else {
1221
1222 // We have a split object
1223
1224 TIter subnext( branch->GetListOfBranches() );
1225 if (desc) {
1226 AnalyzeBranches(1,desc,dynamic_cast<TBranchElement*>(branch),info);
1227 }
1228 desc = AddClass(desc);
1229 if (desc) {
1230 type = desc->GetName();
1231 TString dataMemberName = branchname;
1232 AddDescriptor( new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1233 }
1234 if ( branchname[strlen(branchname)-1] != '.' ) {
1235 // If there is no dot also include the data member directly
1236
1237 AnalyzeBranches(1,0,dynamic_cast<TBranchElement*>(branch),info);
1238
1239 subnext.Reset();
1240 }
1241
1242 } // if split or non split
1243 }
1244
1245 // Now let's add the TTreeFriend (if any)
1246 if (tree->GetTree()->GetListOfFriends()) {
1247 TFriendElement *fe;
1248 Int_t count = 0;
1249
1250 TIter nextfriend(tree->GetTree()->GetListOfFriends());
1251 while ((fe = (TFriendElement*)nextfriend())) {
1252 TTree *t = fe->GetTree();
1254 desc = new TFriendProxyDescriptor(t->GetName(), fe->GetName(), count);
1255
1256 AddFriend( desc );
1257
1259 AnalyzeTree(t);
1260
1261 count++;
1262 }
1263 }
1265 }
1266
1267 ////////////////////////////////////////////////////////////////////////////////
1268 /// Analyze the element and populate the TTreeProxyGenerator or the topdesc with
1269 /// its findings.
1270
1272 UInt_t level, TBranchProxyClassDescriptor *topdesc,
1273 const char *path)
1274 {
1275 TString dataMemberName;
1276 TString pxDataMemberName;
1277 TString type;
1278
1279 // TString prefix;
1280 Bool_t isBase = false;
1281 TString cname;
1282 TString middle;
1284 TString containerName;
1285 EContainer container = kNone;
1286 if (topdesc) {
1287 if (topdesc->IsClones()) {
1288 container = kClones;
1289 middle = "Cla";
1291 containerName = "TClonesArray";
1292 } else if (topdesc->IsSTL()) {
1293 container = kSTL;
1294 middle = "Stl";
1296 containerName = topdesc->GetContainerName();
1297 }
1298 }
1299
1300 if (!element) return;
1301
1302 if (strcmp(element->GetName(),"This")==0) {
1303 TClass *cl = element->GetClassPointer();
1304 containerName = cl->GetName();
1305 cl = cl->GetCollectionProxy()->GetValueClass();
1306 if (!cl) {
1307 // Skip the artificial streamer element.
1308 return;
1309 }
1310 // else return;
1311
1312 // In case the content is a class, move forward
1313 AddForward(cl);
1314 AddHeader(cl);
1315
1316 if (level<=fMaxUnrolling) {
1317
1318 // See AnalyzeTree for similar code!
1319 // TBranchProxyClassDescriptor *cldesc;
1320 if (cl && cl->CanSplit()) {
1321 // cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1322 // branch->GetName(),
1323 // isclones, 0 /* non-split object */,
1324 // containerName);
1325
1327 TStreamerElement *elem = 0;
1328
1329 TString subpath = path;
1330 if (subpath.Length()>0) subpath += ".";
1331 subpath += dataMemberName;
1332
1333 TIter next(info->GetElements());
1334 while( (elem = (TStreamerElement*)next()) ) {
1335 AnalyzeElement(branch, elem, level+1, topdesc, subpath.Data());
1336 }
1337
1338 // TBranchProxyClassDescriptor *added = AddClass(cldesc);
1339 // if (added) type = added->GetName();
1340 }
1341 }
1342 return;
1343 }
1344
1345 if (element->GetType()==-1) {
1346 // This is an ignored TObject base class.
1347 return;
1348 }
1349
1350
1351 // Bool_t ispointer = false;
1352 switch(element->GetType()) {
1353
1354 case TVirtualStreamerInfo::kBool: { type = "T" + middle + "BoolProxy"; break; }
1355 case TVirtualStreamerInfo::kChar: { type = "T" + middle + "CharProxy"; break; }
1356 case TVirtualStreamerInfo::kShort: { type = "T" + middle + "ShortProxy"; break; }
1357 case TVirtualStreamerInfo::kInt: { type = "T" + middle + "IntProxy"; break; }
1358 case TVirtualStreamerInfo::kLong: { type = "T" + middle + "LongProxy"; break; }
1359 case TVirtualStreamerInfo::kLong64: { type = "T" + middle + "Long64Proxy"; break; }
1360 case TVirtualStreamerInfo::kFloat: { type = "T" + middle + "FloatProxy"; break; }
1361 case TVirtualStreamerInfo::kFloat16: { type = "T" + middle + "Float16Proxy"; break; }
1362 case TVirtualStreamerInfo::kDouble: { type = "T" + middle + "DoubleProxy"; break; }
1363 case TVirtualStreamerInfo::kDouble32:{ type = "T" + middle + "Double32Proxy"; break; }
1364 case TVirtualStreamerInfo::kUChar: { type = "T" + middle + "UCharProxy"; break; }
1365 case TVirtualStreamerInfo::kUShort: { type = "T" + middle + "UShortProxy"; break; }
1366 case TVirtualStreamerInfo::kUInt: { type = "T" + middle + "UIntProxy"; break; }
1367 case TVirtualStreamerInfo::kULong: { type = "T" + middle + "ULongProxy"; break; }
1368 case TVirtualStreamerInfo::kULong64: { type = "T" + middle + "ULong64Proxy"; break; }
1369 case TVirtualStreamerInfo::kBits: { type = "T" + middle + "UIntProxy"; break; }
1370
1371 case TVirtualStreamerInfo::kCharStar: { type = GetArrayType(element,"Char",container); break; }
1372
1373 // array of basic types array[8]
1374 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,"Bool",container ); break; }
1375 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,"Char",container ); break; }
1376 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,"Short",container ); break; }
1377 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,"Int",container ); break; }
1378 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,"Long",container ); break; }
1379 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,"Long64",container ); break; }
1380 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,"Float",container ); break; }
1381 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,"Float16",container ); break; }
1382 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,"Double",container ); break; }
1383 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,"Double32",container ); break; }
1384 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,"UChar",container ); break; }
1385 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,"UShort",container ); break; }
1386 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,"UInt",container ); break; }
1387 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,"ULong",container ); break; }
1388 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,"ULong64",container ); break; }
1389 case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,"UInt",container ); break; }
1390
1391 // pointer to an array of basic types array[n]
1392 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,"Bool",container ); break; }
1393 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,"Char",container ); break; }
1394 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,"Short",container ); break; }
1395 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,"Int",container ); break; }
1396 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,"Long",container ); break; }
1397 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,"Long64",container ); break; }
1398 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,"Float",container ); break; }
1399 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,"Float16",container ); break; }
1400 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,"Double",container ); break; }
1401 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,"Double32",container ); break; }
1402 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,"UChar",container ); break; }
1403 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,"UShort",container ); break; }
1404 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,"UInt",container ); break; }
1405 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,"ULong",container ); break; }
1406 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,"ULong64",container ); break; }
1407 case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,"UInt",container ); break; }
1408
1409 // array counter //[n]
1410 case TVirtualStreamerInfo::kCounter: { type = "T" + middle + "IntProxy"; break; }
1411
1412
1421 // set as pointers and fall through to the next switches
1422 // ispointer = true;
1432 TClass *cl = element->GetClassPointer();
1433 if (cl) {
1434 type = Form("T%sObjProxy<%s >",
1435 middle.Data(),cl->GetName());
1436 cname = cl->GetName();
1437 if (cl==TClonesArray::Class()) {
1439 containerName = "TClonesArray";
1440
1441 Long64_t i = branch->GetTree()->GetReadEntry();
1442 if (i<0) i = 0;
1443 branch->GetEntry(i);
1444
1445 //char *obj = branch->GetObject();
1446
1447 // now need to follow it through to this pointer!
1448
1449 TClonesArray *arr;
1450
1451 TString fullpath = branch->GetName();
1452 fullpath += ".";
1453 if (path && strlen(path)>0) fullpath.Append(path).Append(".");
1454 fullpath += element->GetName();
1455
1456 TTreeFormula *formula = new TTreeFormula("clones",fullpath,branch->GetTree());
1457
1458 TFormLeafInfo *leafinfo = formula->GetLeafInfo(0);
1459 TLeaf *leaf = formula->GetLeaf(0);
1460 R__ASSERT(leaf && leafinfo);
1461
1462 arr = (TClonesArray*)leafinfo->GetLocalValuePointer(leaf,0);
1463
1464 /*
1465 if (ispointer) {
1466 arr = (TClonesArray*)*(void**)(obj+lOffset);
1467 } else {
1468 arr = (TClonesArray*)(obj+lOffset);
1469 }
1470 */
1471 if (arr) cname = arr->GetClass()->GetName();
1472
1473 if (cname.Length()==0) {
1474 Error("AnalyzeTree",
1475 "Introspection of TClonesArray in older file not implemented yet.");
1476 }
1477 delete formula;
1478 } else if (cl->GetCollectionProxy()) {
1480 containerName = cl->GetName();
1481 cl = cl->GetCollectionProxy()->GetValueClass();
1482 }
1483 }
1484 else Error("AnalyzeTree","missing class for %s.",branch->GetName());
1485 if (element->IsA()==TStreamerBase::Class()) {
1486 // prefix = "base";
1487 isBase = true;
1488 }
1489 AddForward(cl);
1490 AddHeader(cl);
1491 break;
1492 }
1493
1494 default:
1495 Error("AnalyzeTree",
1496 "Unsupported type for %s %s %d",
1497 branch->GetName(), element->GetName(), element->GetType());
1498
1499 }
1500
1501 dataMemberName = element->GetName();
1502
1503 if (level<=fMaxUnrolling) {
1504
1505 // See AnalyzeTree for similar code!
1507
1508 TClass *cl = TClass::GetClass(cname);
1509 if (cl && cl->CanSplit()) {
1510 cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1511 branch->GetName(),
1512 isclones, 0 /* non-split object */,
1513 containerName);
1514
1516 TStreamerElement *elem = 0;
1517
1518 TString subpath = path;
1519 if (subpath.Length()>0) subpath += ".";
1520 subpath += dataMemberName;
1521
1522 TIter next(info->GetElements());
1523 while( (elem = (TStreamerElement*)next()) ) {
1524 AnalyzeElement(branch, elem, level+1, cldesc, subpath.Data());
1525 }
1526
1527 TBranchProxyClassDescriptor *added = AddClass(cldesc);
1528 if (added) type = added->GetName();
1529 }
1530
1531 }
1532
1533 pxDataMemberName = /* prefix + */ dataMemberName;
1534 if (topdesc) {
1535 topdesc->AddDescriptor( new TBranchProxyDescriptor( pxDataMemberName.Data(), type,
1536 dataMemberName.Data(), false),
1537 isBase );
1538 } else {
1539 Error("AnalyzeTree","topdesc should not be null in TTreeProxyGenerator::AnalyzeElement.");
1540 }
1541 }
1542
1543 ////////////////////////////////////////////////////////////////////////////////
1544 /// Parse the options string.
1545
1547 {
1548 TString opt = fOptionStr;
1549
1550 fOptions = 0;
1551 if ( opt.Contains("nohist") ) {
1552 opt.ReplaceAll("nohist","");
1553 fOptions |= kNoHist;
1554 }
1555 }
1556
1557 ////////////////////////////////////////////////////////////////////////////////
1558 /// Add the "pragma C++ class" if needed and return
1559 /// true if it has been added _or_ if it is known to
1560 /// not be needed.
1561 /// (I.e. return kFALSE if a container of this class
1562 /// can not have a "pragma C++ class"
1563
1565 {
1566 if (!cl) return kFALSE;
1567 if (cl->GetCollectionProxy()) {
1568 TClass *valcl = cl->GetCollectionProxy()->GetValueClass();
1569 if (!valcl) {
1570 if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1571 return kTRUE;
1572 } else if (R__AddPragmaForClass(gen, valcl)) {
1573 if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1574 return kTRUE;
1575 }
1576 }
1577 if (cl->IsLoaded()) return kTRUE;
1578 return kFALSE;
1579 }
1580
1581 ////////////////////////////////////////////////////////////////////////////////
1582 /// Add the "pragma C++ class" if needed and return
1583 /// true if it has been added _or_ if it is known to
1584 /// not be needed.
1585 /// (I.e. return kFALSE if a container of this class
1586 /// can not have a "pragma C++ class"
1587
1588 static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen, const char *classname)
1589 {
1590 return R__AddPragmaForClass( gen, TClass::GetClass(classname) );
1591
1592 }
1593
1594 ////////////////////////////////////////////////////////////////////////////////
1595 /// Check whether the file exist and do something useful if it does
1596
1598 {
1599 if (fScript.Length()==0) {
1600 Error("WriteProxy","No user script has been specified.");
1601 return;
1602 }
1603
1604 TString fileLocation = gSystem->GetDirName(fScript);
1605
1606 TString incPath = gSystem->GetIncludePath(); // of the form -Idir1 -Idir2 -Idir3
1607 incPath.Append(":").Prepend(" ");
1608 incPath.ReplaceAll(" -I",":"); // of form :dir1 :dir2:dir3
1609 while ( incPath.Index(" :") != -1 ) {
1610 incPath.ReplaceAll(" :",":");
1611 }
1612 incPath.Prepend(fileLocation+":.:");
1613
1614 const char *filename = gSystem->Which(incPath,fScript);
1615 if (!filename) {
1616 Error("WriteProxy","Can not find the user's script: %s",fScript.Data());
1617 return;
1618 }
1619 const char *cutfilename = nullptr;
1620 if (fCutScript.Length()) {
1621 fileLocation = gSystem->GetDirName(fCutScript);
1622 incPath.Prepend(fileLocation+":.:");
1623 cutfilename = gSystem->Which(incPath,fCutScript);
1624 if (!cutfilename) {
1625 Error("WriteProxy","Can not find the user's cut script: %s",fCutScript.Data());
1626 delete [] filename;
1627 return;
1628 }
1629 }
1630
1632 TString classname = gSystem->BaseName(fPrefix);
1633
1634 // Check if there is already an extension and extract it.
1635 Ssiz_t pos = classname.Last('.');
1636 if (pos != kNPOS) {
1637 classname.Remove(pos);
1638 } else {
1639 fHeaderFileName.Append(".h");
1640 }
1641
1642 // Check to see if the target file exist.
1643 // If they do we will generate the proxy in temporary file and modify the original
1644 // if and only if it is different.
1645
1646 Bool_t updating = kFALSE;
1647 if (gSystem->GetPathInfo( fHeaderFileName, 0, (Long_t*)0, 0, 0 ) == 0) {
1648 // file already exist
1649 updating = kTRUE;
1650 }
1651
1652
1653 TString treefile;
1654 Bool_t ischain = fTree->InheritsFrom(TChain::Class());
1656 treefile = fTree->GetDirectory()->GetFile()->GetName();
1657 else
1658 treefile = "Memory Directory";
1659
1660 TString scriptfunc = fScript;
1661 Ssiz_t dot_pos = scriptfunc.Last('.');
1662 if (dot_pos == kNPOS) {
1663 Error("WriteProxy","User's script (%s) has no extension! Nothing will be written.",scriptfunc.Data());
1664 delete [] filename;
1665 delete [] cutfilename;
1666 return;
1667 }
1668 scriptfunc.Replace( dot_pos, fScript.Length()-dot_pos, "");
1669 TString scriptHeader = scriptfunc;
1670 const char * extensions[] = { ".h", ".hh", ".hpp", ".hxx", ".hPP", ".hXX" };
1671
1672 int i;
1673 for (i = 0; i < 6; i++ ) {
1674 TString possible = scriptHeader;
1675 possible.Append(extensions[i]);
1676 const char *name = gSystem->Which(incPath,possible);
1677 if (name) {
1678 scriptHeader = possible;
1679 fListOfHeaders.Add(new TNamed("script",Form("#include \"%s\"\n",
1680 scriptHeader.Data())));
1681 delete [] name;
1682 break;
1683 }
1684 }
1685 scriptfunc = gSystem->BaseName(scriptfunc);
1686
1687
1688 TString cutscriptfunc = fCutScript;
1689 if (cutfilename) {
1690 dot_pos = cutscriptfunc.Last('.');
1691 cutscriptfunc.Replace( dot_pos, fCutScript.Length()-dot_pos, "");
1692 TString cutscriptHeader = cutscriptfunc;
1693
1694 for (i = 0; i < 6; i++ ) {
1695 TString possible = cutscriptHeader;
1696 possible.Append(extensions[i]);
1697 const char *name = gSystem->Which(incPath,possible);
1698 if (name) {
1699 cutscriptHeader = possible;
1700 fListOfHeaders.Add(new TNamed("cutscript",Form("#include \"%s\"\n",
1701 cutscriptHeader.Data())));
1702 delete [] name;
1703 break;
1704 }
1705 }
1706 cutscriptfunc = gSystem->BaseName(cutscriptfunc);
1707 }
1708
1709 FILE *hf;
1710 TString tmpfilename = ".Proxy-";
1711 if (updating) {
1712 hf = gSystem->TempFileName(tmpfilename, "./");
1713 } else {
1714 hf = fopen(fHeaderFileName, "w");
1715 }
1716 if (hf == 0) {
1717 Error("WriteProxy","Unable to open the file %s for writing.",
1718 updating ? tmpfilename.Data() : fHeaderFileName.Data());
1719 delete [] filename;
1720 delete [] cutfilename;
1721 return;
1722 }
1723
1724 TDatime td;
1725 fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
1726 fprintf(hf, "// This class has been automatically generated \n");
1727 fprintf(hf, "// (at %s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
1728 if (!ischain) {
1729 fprintf(hf,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1730 fprintf(hf,"// found on file: %s\n",treefile.Data());
1731 } else {
1732 fprintf(hf,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1733 }
1734 fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
1735 fprintf(hf,"\n");
1736 fprintf(hf,"\n");
1737
1738 fprintf(hf,"#ifndef %s_h\n",classname.Data());
1739 fprintf(hf,"#define %s_h\n",classname.Data());
1740 fprintf(hf,"\n");
1741
1742
1743 // Interface versioning
1744 fprintf(hf,"#define R__BRANCHPROXY_GENERATOR_VERSION 2\n\n");
1745 fprintf(hf,"// ROOT headers needed by the proxy\n");
1746 fprintf(hf,"#include <TROOT.h>\n");
1747 fprintf(hf,"#include <TChain.h>\n");
1748 fprintf(hf,"#include <TFile.h>\n");
1749 fprintf(hf,"#include <TPad.h>\n");
1750 fprintf(hf,"#include <TH1.h>\n");
1751 fprintf(hf,"#include <TSelector.h>\n");
1752 fprintf(hf,"#include <TBranchProxy.h>\n");
1753 fprintf(hf,"#include <TBranchProxyDirector.h>\n");
1754 fprintf(hf,"#include <TBranchProxyTemplate.h>\n");
1755 fprintf(hf,"#include <TFriendProxy.h>\n");
1756 fprintf(hf,"using namespace ROOT::Internal;\n"); // questionable
1757 fprintf(hf,"using ROOT::Detail::TBranchProxy;\n"); // questionable
1758 fprintf(hf,"\n");
1759
1760 fprintf(hf,"// forward declarations needed by this particular proxy\n");
1761 TIter next( &fListOfForwards );
1762 TObject *current;
1763 while ( (current=next()) ) {
1764 if (strstr(current->GetTitle(),"::")==0) {
1765 // We can not forward declared nested classes (well we might be able to do so for
1766 // the one nested in a namespace but it is not clear yet if we can really reliably
1767 // find this information)
1768 fprintf(hf,"%s",current->GetTitle());
1769 }
1770 }
1771
1772 fprintf(hf,"\n\n");
1773 fprintf(hf,"// Header needed by this particular proxy\n");
1774 next = &fListOfHeaders;
1775 TObject *header;
1776 while ( (header = next()) ) {
1777 fprintf(hf,"%s",header->GetTitle());
1778 }
1779 fprintf(hf,"\n\n");
1780
1781 fprintf(hf,"class %s_Interface {\n", scriptfunc.Data());
1782 fprintf(hf," // This class defines the list of methods that are directly used by %s,\n",classname.Data());
1783 fprintf(hf," // and that can be overloaded in the user's script\n");
1784 fprintf(hf,"public:\n");
1785 fprintf(hf," void %s_Begin(TTree*) {}\n",scriptfunc.Data());
1786 fprintf(hf," void %s_SlaveBegin(TTree*) {}\n",scriptfunc.Data());
1787 fprintf(hf," Bool_t %s_Notify() { return kTRUE; }\n",scriptfunc.Data());
1788 fprintf(hf," Bool_t %s_Process(Long64_t) { return kTRUE; }\n",scriptfunc.Data());
1789 fprintf(hf," void %s_SlaveTerminate() {}\n",scriptfunc.Data());
1790 fprintf(hf," void %s_Terminate() {}\n",scriptfunc.Data());
1791 fprintf(hf,"};\n");
1792 fprintf(hf,"\n\n");
1793
1794 fprintf(hf, "class %s : public TSelector, public %s_Interface {\n", classname.Data(), scriptfunc.Data());
1795 fprintf(hf, "public :\n");
1796 fprintf(hf, " TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
1797 fprintf(hf, " TH1 *htemp; //!pointer to the histogram\n");
1798 fprintf(hf, " TBranchProxyDirector fDirector; //!Manages the proxys\n\n");
1799
1800 fprintf(hf, " // Optional User methods\n");
1801 fprintf(hf, " TClass *fClass; // Pointer to this class's description\n");
1802
1803 if (fListOfClasses.LastIndex()>=0) {
1804 fprintf(hf, "\n // Wrapper class for each unwounded class\n");
1805 next = &fListOfClasses;
1807 while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1808 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1809 }
1810 }
1811
1812 if (fListOfFriends.LastIndex()>=0) {
1813 fprintf(hf, "\n // Wrapper class for each friend TTree\n");
1814 next = &fListOfFriends;
1816 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1817 if (!clp->IsDuplicate()) clp->OutputClassDecl(hf, 3, fMaxDatamemberType);
1818 }
1819 }
1820
1821 fprintf(hf, "\n // Proxy for each of the branches, leaves and friends of the tree\n");
1822 next = &fListOfTopProxies;
1824 while ( (data = (TBranchProxyDescriptor*)next()) ) {
1825 data->OutputDecl(hf, 3, fMaxDatamemberType);
1826 }
1827 if (fListOfFriends.LastIndex()>=0) {
1828 next = &fListOfFriends;
1830 while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1831 clp->OutputDecl(hf, 3, fMaxDatamemberType);
1832 }
1833 }
1834 fprintf(hf,"\n\n");
1835
1836 // Constructor
1837 fprintf(hf, " %s(TTree *tree=0) : \n",classname.Data());
1838 fprintf(hf, " fChain(0)");
1839 fprintf(hf, ",\n htemp(0)");
1840 fprintf(hf, ",\n fDirector(tree,-1)");
1841 fprintf(hf, ",\n fClass (TClass::GetClass(\"%s\"))",classname.Data());
1842 next = &fListOfTopProxies;
1843 while ( (data = (TBranchProxyDescriptor*)next()) ) {
1844 fprintf(hf,",\n %-*s(&fDirector,\"%s\")",
1845 fMaxDatamemberType, data->GetDataName(), data->GetBranchName());
1846 }
1847 next = &fListOfFriends;
1849 while ( (fpd = (TFriendProxyDescriptor*)next()) ) {
1850 fprintf(hf,",\n %-*s(&fDirector,tree,%d)",
1851 fMaxDatamemberType, fpd->GetTitle(), fpd->GetIndex());
1852 }
1853
1854 fprintf(hf, "\n { }\n");
1855
1856 // Other functions.
1857 fprintf(hf," ~%s();\n",classname.Data());
1858 fprintf(hf," Int_t Version() const {return 1;}\n");
1859 fprintf(hf," void Begin(::TTree *tree);\n");
1860 fprintf(hf," void SlaveBegin(::TTree *tree);\n");
1861 fprintf(hf," void Init(::TTree *tree);\n");
1862 fprintf(hf," Bool_t Notify();\n");
1863 fprintf(hf," Bool_t Process(Long64_t entry);\n");
1864 fprintf(hf," void SlaveTerminate();\n");
1865 fprintf(hf," void Terminate();\n");
1866 fprintf(hf,"\n");
1867 fprintf(hf," ClassDef(%s,0);\n",classname.Data());
1868 fprintf(hf,"\n\n");
1869
1870 fprintf(hf,"//inject the user's code\n");
1871 fprintf(hf,"#include \"%s\"\n",fScript.Data());
1872
1873 if (cutfilename) {
1874 fprintf(hf,"#include \"%s\"\n",fCutScript.Data());
1875 }
1876
1877 // Close the class.
1878 fprintf(hf,"};\n");
1879 fprintf(hf,"\n");
1880 fprintf(hf,"#endif\n");
1881 fprintf(hf,"\n\n");
1882
1883 fprintf(hf,"#ifdef __MAKECINT__\n");
1884 if (fListOfClasses.LastIndex()>=0) {
1886 next = &fListOfClasses;
1887 while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1888 fprintf(hf,"#pragma link C++ class %s::%s-;\n",classname.Data(),clp->GetName());
1889 if (clp->GetContainerName().Length()) {
1891 }
1892 }
1893 next = &fListOfPragmas;
1894 TObjString *prag;
1895 while ( (prag = (TObjString*)next()) ) {
1896 fprintf(hf,"%s",prag->String().Data());
1897 }
1898 }
1899 fprintf(hf,"#pragma link C++ class %s;\n",classname.Data());
1900 fprintf(hf,"#endif\n");
1901 fprintf(hf,"\n\n");
1902
1903 // Write the implementations.
1904 fprintf(hf,"inline %s::~%s() {\n",classname.Data(),classname.Data());
1905 fprintf(hf," // destructor. Clean up helpers.\n");
1906 fprintf(hf,"\n");
1907 fprintf(hf,"}\n");
1908 fprintf(hf,"\n");
1909 fprintf(hf,"inline void %s::Init(TTree *tree)\n",classname.Data());
1910 fprintf(hf,"{\n");
1911 fprintf(hf,"// Set branch addresses\n");
1912 fprintf(hf," if (tree == 0) return;\n");
1913 fprintf(hf," fChain = tree;\n");
1914 fprintf(hf," fDirector.SetTree(fChain);\n");
1915 fprintf(hf," if (htemp == 0) {\n");
1916 fprintf(hf," htemp = fDirector.CreateHistogram(GetOption());\n");
1917 if (cutfilename) {
1918 fprintf(hf," htemp->SetTitle(\"%s {%s}\");\n",fScript.Data(),fCutScript.Data());
1919 } else {
1920 fprintf(hf," htemp->SetTitle(\"%s\");\n",fScript.Data());
1921 }
1922 fprintf(hf," fObject = htemp;\n");
1923 fprintf(hf," }\n");
1924 fprintf(hf,"}\n");
1925 fprintf(hf,"\n");
1926 fprintf(hf,"Bool_t %s::Notify()\n",classname.Data());
1927 fprintf(hf,"{\n");
1928 fprintf(hf," // Called when loading a new file.\n");
1929 fprintf(hf," // Get branch pointers.\n");
1930 fprintf(hf," fDirector.SetTree(fChain);\n");
1931 fprintf(hf," %s_Notify();\n",scriptfunc.Data());
1932 fprintf(hf," \n");
1933 fprintf(hf," return kTRUE;\n");
1934 fprintf(hf,"}\n");
1935 fprintf(hf," \n");
1936
1937 // generate code for class member function Begin
1938 fprintf(hf,"\n");
1939 fprintf(hf,"inline void %s::Begin(TTree *tree)\n",classname.Data());
1940 fprintf(hf,"{\n");
1941 fprintf(hf," // The Begin() function is called at the start of the query.\n");
1942 fprintf(hf," // When running with PROOF Begin() is only called on the client.\n");
1943 fprintf(hf," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1944 fprintf(hf,"\n");
1945 fprintf(hf," TString option = GetOption();\n");
1946 fprintf(hf," %s_Begin(tree);\n",scriptfunc.Data());
1947 fprintf(hf,"\n");
1948 fprintf(hf,"}\n");
1949
1950 // generate code for class member function SlaveBegin
1951 fprintf(hf,"\n");
1952 fprintf(hf,"inline void %s::SlaveBegin(TTree *tree)\n",classname.Data());
1953 fprintf(hf,"{\n");
1954 fprintf(hf," // The SlaveBegin() function is called after the Begin() function.\n");
1955 fprintf(hf," // When running with PROOF SlaveBegin() is called on each slave server.\n");
1956 fprintf(hf," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1957 fprintf(hf,"\n");
1958 fprintf(hf," Init(tree);\n");
1959 fprintf(hf,"\n");
1960 fprintf(hf," %s_SlaveBegin(tree);\n",scriptfunc.Data());
1961 fprintf(hf,"\n");
1962 fprintf(hf,"}\n");
1963 fprintf(hf,"\n");
1964
1965 // generate code for class member function Process
1966 fprintf(hf,"inline Bool_t %s::Process(Long64_t entry)\n",classname.Data());
1967 fprintf(hf,"{\n");
1968
1969 fprintf(hf," // The Process() function is called for each entry in the tree (or possibly\n"
1970 " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1971 " // specifies which entry in the currently loaded tree is to be processed.\n"
1972 " // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()\n"
1973 " // to read either all or the required parts of the data. When processing\n"
1974 " // keyed objects with PROOF, the object is already loaded and is available\n"
1975 " // via the fObject pointer.\n"
1976 " //\n"
1977 " // This function should contain the \"body\" of the analysis. It can contain\n"
1978 " // simple or elaborate selection criteria, run algorithms on the data\n"
1979 " // of the event and typically fill histograms.\n\n");
1980 fprintf(hf," // WARNING when a selector is used with a TChain, you must use\n");
1981 fprintf(hf," // the pointer to the current TTree to call GetEntry(entry).\n");
1982 fprintf(hf," // The entry is always the local entry number in the current tree.\n");
1983 fprintf(hf," // Assuming that fChain is the pointer to the TChain being processed,\n");
1984 fprintf(hf," // use fChain->GetTree()->GetEntry(entry).\n");
1985 fprintf(hf,"\n");
1986 fprintf(hf,"\n");
1987 fprintf(hf," fDirector.SetReadEntry(entry);\n");
1988 if (fOptions & kNoHist) {
1989 if (cutfilename) {
1990 fprintf(hf," if (%s()) %s();\n",cutscriptfunc.Data(),scriptfunc.Data());
1991 } else {
1992 fprintf(hf," %s();\n",scriptfunc.Data());
1993 }
1994 } else {
1995 if (cutfilename) {
1996 fprintf(hf," if (%s()) htemp->Fill(%s());\n",cutscriptfunc.Data(),scriptfunc.Data());
1997 } else {
1998 fprintf(hf," htemp->Fill(%s());\n",scriptfunc.Data());
1999 }
2000 }
2001 fprintf(hf," %s_Process(entry);\n",scriptfunc.Data());
2002 fprintf(hf," return kTRUE;\n");
2003 fprintf(hf,"\n");
2004 fprintf(hf,"}\n\n");
2005
2006 // generate code for class member function SlaveTerminate
2007 fprintf(hf,"inline void %s::SlaveTerminate()\n",classname.Data());
2008 fprintf(hf,"{\n");
2009 fprintf(hf," // The SlaveTerminate() function is called after all entries or objects\n"
2010 " // have been processed. When running with PROOF SlaveTerminate() is called\n"
2011 " // on each slave server.");
2012 fprintf(hf,"\n");
2013 fprintf(hf," %s_SlaveTerminate();\n",scriptfunc.Data());
2014 fprintf(hf,"}\n\n");
2015
2016 // generate code for class member function Terminate
2017 fprintf(hf,"inline void %s::Terminate()\n",classname.Data());
2018 fprintf(hf,"{\n");
2019 fprintf(hf," // Function called at the end of the event loop.\n");
2020 fprintf(hf," htemp = (TH1*)fObject;\n");
2021 fprintf(hf," Int_t drawflag = (htemp && htemp->GetEntries()>0);\n");
2022 fprintf(hf," \n");
2023 fprintf(hf," if (gPad && !drawflag && !fOption.Contains(\"goff\") && !fOption.Contains(\"same\")) {\n");
2024 fprintf(hf," gPad->Clear();\n");
2025 fprintf(hf," } else {\n");
2026 fprintf(hf," if (fOption.Contains(\"goff\")) drawflag = false;\n");
2027 fprintf(hf," if (drawflag) htemp->Draw(fOption);\n");
2028 fprintf(hf," }\n");
2029 fprintf(hf," %s_Terminate();\n",scriptfunc.Data());
2030 fprintf(hf,"}\n");
2031
2032 fclose(hf);
2033
2034 if (updating) {
2035 // over-write existing file only if needed.
2036 if (AreDifferent(fHeaderFileName,tmpfilename)) {
2038 gSystem->Rename(tmpfilename,fHeaderFileName);
2039 } else gSystem->Unlink(tmpfilename);
2040 }
2041 delete [] filename;
2042 delete [] cutfilename;
2043 }
2044
2045} // namespace Internal
2046} // namespace ROOT
void Class()
Definition: Class.C:29
const Ssiz_t kNPOS
Definition: RtypesCore.h:124
int Int_t
Definition: RtypesCore.h:45
int Ssiz_t
Definition: RtypesCore.h:67
unsigned int UInt_t
Definition: RtypesCore.h:46
const Bool_t kFALSE
Definition: RtypesCore.h:101
long Long_t
Definition: RtypesCore.h:54
bool Bool_t
Definition: RtypesCore.h:63
long long Long64_t
Definition: RtypesCore.h:80
const Bool_t kTRUE
Definition: RtypesCore.h:100
#define R__ASSERT(e)
Definition: TError.h:118
void ErrorHandler(int level, const char *location, const char *fmt, std::va_list va)
General error handler function. It calls the user set error handler.
Definition: TError.cxx:111
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition: TError.cxx:187
constexpr Int_t kInfo
Definition: TError.h:44
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition: TError.cxx:231
char name[80]
Definition: TGX11.cxx:110
int type
Definition: TGX11.cxx:121
Int_t gDebug
Definition: TROOT.cxx:592
#define gROOT
Definition: TROOT.h:404
char * Form(const char *fmt,...)
R__EXTERN TSystem * gSystem
Definition: TSystem.h:559
void Debug(Int_t level, const char *va_(fmt),...)
#define va_(arg)
Definition: Varargs.h:41
const char * GetBranchName() const
Get the branch name.
const char * GetRawSymbol() const
Get the real symbol name.
const char * GetSubBranchPrefix() const
Get the prefix from the branch name.
Bool_t IsClones() const
Return true if this proxy is for a TClonesArray.
void AddDescriptor(TBranchProxyDescriptor *desc, Bool_t isBase)
Add a descriptor to this proxy.
void OutputDecl(FILE *hf, int offset, UInt_t)
Output the declaration and implementation of this emulation class.
virtual Bool_t IsEquivalent(const TBranchProxyClassDescriptor *other)
Return true if this description is the 'same' as the other decription.
TString GetContainerName() const
Return the name of the container holding this class, if any.
Bool_t IsSTL() const
Return true if this proxy is for a TClonesArray.
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
Output the declaration corresponding to this proxy.
const char * GetBranchName()
Get the branch name.
const char * GetTypeName()
Get the name of the type of the data member.
const char * GetDataName()
Get the name of the data member.
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
Print the declaration needed for this descriptor.
Bool_t IsEquivalent(const TFriendProxyDescriptor *other)
Return true if this descriptor and the other are equivalent (describe the same entity).
void OutputClassDecl(FILE *hf, int offset, UInt_t maxVarname)
Print the declaration needed for this descriptor.
Base class for code generators like TTreeProxyGenerator and TTreeReaderGenerator.
TList fListOfHeaders
List of included headers.
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.
TTree * fTree
Pointer to the tree.
TString fOptionStr
User options as a string.
void AddMissingClassAsEnum(const char *clname, Bool_t isscope)
Generate an enum for a given type if it is not known in the list of class unless the type itself a te...
void AnalyzeTree(TTree *tree)
Analyze a TTree and its (potential) friends.
TBranchProxyClassDescriptor * AddClass(TBranchProxyClassDescriptor *desc)
Add a Class Descriptor.
void AddDescriptor(TBranchProxyDescriptor *desc)
Add a branch descriptor.
void AddPragma(const char *pragma_text)
Add a forward declaration request.
UInt_t AnalyzeOldLeaf(TLeaf *leaf, UInt_t level, TBranchProxyClassDescriptor *topdesc)
Analyze the leaf and populate the `TTreeProxyGenerator or the topdesc with its findings.
Bool_t NeedToEmulate(TClass *cl, UInt_t level)
Return true if we should create a nested class representing this class.
UInt_t AnalyzeOldBranch(TBranch *branch, UInt_t level, TBranchProxyClassDescriptor *desc)
Analyze the branch and populate the TTreeProxyGenerator or the topdesc with its findings.
void AnalyzeElement(TBranch *branch, TStreamerElement *element, UInt_t level, TBranchProxyClassDescriptor *desc, const char *path)
Analyze the element and populate the TTreeProxyGenerator or the topdesc with its findings.
TTreeProxyGenerator(TTree *tree, const char *script, const char *fileprefix, const char *option, UInt_t maxUnrolling)
Constructor.
void AddFriend(TFriendProxyDescriptor *desc)
Add Friend descriptor.
void CheckForMissingClass(const char *clname)
Check if the template parameter refers to an enum and/or a missing class (we can't tell those 2 apart...
UInt_t AnalyzeBranches(UInt_t level, TBranchProxyClassDescriptor *topdesc, TBranchElement *branch, TVirtualStreamerInfo *info=0)
Analyze the sub-branch and populate the TTreeProxyGenerator or the topdesc with its findings.
void ParseOptions()
Parse the options string.
void AddForward(TClass *cl)
Add a forward declaration request.
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:89
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any.
Definition: TBranch.cxx:1322
virtual char * GetAddress() const
Definition: TBranch.h:208
TTree * GetTree() const
Definition: TBranch.h:248
TObjArray * GetListOfBranches()
Definition: TBranch.h:242
Int_t GetSplitLevel() const
Definition: TBranch.h:246
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:1644
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:2081
virtual void SetAddress(void *add)
Set address of this branch.
Definition: TBranch.cxx:2599
TObjArray * GetListOfLeaves()
Definition: TBranch.h:243
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:2044
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:2307
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:5905
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:4592
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2884
@ 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:2955
An array of clone (identical) objects.
Definition: TClonesArray.h:29
TClass * GetClass() const
Definition: TClonesArray.h:53
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:102
virtual TFile * GetFile() const
Definition: TDirectory.h:211
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:251
void Reset()
Definition: TCollection.h:254
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:57
virtual const char * GetTypeName() const
Definition: TLeaf.h:139
TBranch * GetBranch() const
Definition: TLeaf.h:116
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:578
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:445
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:403
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:136
Ssiz_t Length() const
Definition: TString.h:410
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:682
const char * Data() const
Definition: TString.h:369
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:692
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:916
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:615
TString & Prepend(const char *cs)
Definition: TString.h:661
TString & Remove(Ssiz_t pos)
Definition: TString.h:673
TString & Append(const char *cs)
Definition: TString.h:564
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:2336
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:624
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:639
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3960
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:1398
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:1497
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition: TSystem.cxx:1350
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:935
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1546
virtual TString GetDirName(const char *pathname)
Return the directory name in pathname.
Definition: TSystem.cxx:1032
virtual int Unlink(const char *name)
Unlink, i.e.
Definition: TSystem.cxx:1381
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:79
TDirectory * GetDirectory() const
Definition: TTree.h:458
virtual Long64_t GetReadEntry() const
Definition: TTree.h:505
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...
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:77
Definition: tree.py:1
auto * l
Definition: textangle.C:4