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