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