Logo ROOT   6.10/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 
209  TTreeProxyGenerator::TTreeProxyGenerator(TTree* tree,
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),
238  fScript(script),
239  fCutScript(cutscript),
240  fPrefix(fileprefix),
241  fHeaderFileName(),
242  fOptions(0),
243  fMaxUnrolling(maxUnrolling),
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();
321  TIter next( &fListOfFriends );
322  while ( (existing = (TFriendProxyDescriptor*)next()) ) {
323  if (strcmp(existing->GetTitle(),desc->GetTitle())==0) {
324 
325  TString newtitle = basetitle;
326  count++;
327  newtitle += "_";
328  newtitle += count;
329 
330  desc->SetTitle(newtitle);
331 
332  // Restart of the begining of the loop.
333  next = &fListOfFriends;
334  }
335  }
336 
337  fListOfFriends.Add(desc);
338  }
339 
340  void TTreeProxyGenerator::AddForward( const char *classname )
341  {
342  // Add a forward declaration request.
343 
344  TObject *obj = fListOfForwards.FindObject(classname);
345  if (obj) return;
346 
347  if (strstr(classname,"<")!=0) {
348  // this is a template instantiation.
349  // let's ignore it for now
350 
351  if (gDebug>=6) Warning("AddForward","Forward declaration of templated class not implemented yet.");
352  } else if (strcmp(classname,"string")==0) {
353  // no need to forward declare string
354  } else {
355  fListOfForwards.Add(new TNamed(classname,Form("class %s;\n",classname)));
356  }
357  return;
358  }
359 
361  {
362  // Add a forward declaration request.
363 
364  if (cl) AddForward(cl->GetName());
365  }
366 
367  void TTreeProxyGenerator::AddPragma(const char *pragma_text)
368  {
369  // Add a forward declaration request.
370 
371  TIter i( &fListOfPragmas );
372  for(TObjString *n = (TObjString*) i(); n; n = (TObjString*)i() ) {
373  if (pragma_text == n->GetString()) {
374  return;
375  }
376  }
377 
378  fListOfPragmas.Add( new TObjString( pragma_text ) );
379 
380  }
381 
383  {
384  // Add a branch descriptor.
385 
386  if (desc) {
387  TBranchProxyDescriptor *existing =
389  if (existing) {
390  Warning("TTreeProxyGenerator","The branch name \"%s\" is duplicated. Only the first instance \n"
391  "\twill be available directly. The other instance(s) might be available via their complete name\n"
392  "\t(including the name of their mother branche's name).",desc->GetName());
393  } else {
395  UInt_t len = strlen(desc->GetTypeName());
396  if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
397  }
398  }
399  }
400 
401  void TTreeProxyGenerator::AddMissingClassAsEnum(const char *clname, Bool_t isscope)
402  {
403  // Generate an enum for a given type if it is not known in the list of class
404  // unless the type itself a template.
405 
406  if (!TClassEdit::IsStdClass(clname) && !TClass::GetClass(clname) && gROOT->GetType(clname) == 0) {
407 
408  TObject *obj = fListOfForwards.FindObject(clname);
409  if (obj) return;
410 
411  // The class does not exist, let's create it if ew can.
412  if (clname[strlen(clname)-1]=='>') {
413  // Template instantiation.
414  fListOfForwards.Add(new TNamed(clname,TString::Format("template <> class %s { public: operator int() { return 0; } };\n", clname).Data()));
415  } else if (isscope) {
416  // a scope
417 
418  } else {
419  // Class or enum we know nothing about, let's assume it is an enum.
420  fListOfForwards.Add(new TNamed(clname,TString::Format("enum %s { kDefault_%s };\n", clname, clname).Data()));
421  }
422  }
423  }
424 
426  {
427  // Check if the template parameter refers to an enum and/or a missing class (we can't tell those 2 apart unless
428  // the name as template syntax).
429 
430  UInt_t len = strlen(clname);
431  UInt_t nest = 0;
432  UInt_t last = 0;
433  //Bool_t istemplate = kFALSE; // mark whether the current right most entity is a class template.
434 
435  for (UInt_t i = 0; i < len; ++i) {
436  switch (clname[i]) {
437  case ':':
438  if (nest == 0 && clname[i+1] == ':') {
439  TString incName(clname, i);
440  AddMissingClassAsEnum(incName.Data(), kTRUE);
441  //istemplate = kFALSE;
442  }
443  break;
444  case '<':
445  ++nest;
446  if (nest == 1) last = i + 1;
447  break;
448  case '>':
449  if (nest == 0) return; // The name is not well formed, give up.
450  --nest; /* intentional fall throught to the next case */
451  case ',':
452  if ((clname[i] == ',' && nest == 1) || (clname[i] == '>' && nest == 0)) {
453  TString incName(clname + last, i - last);
454  incName = TClassEdit::ShortType(incName.Data(), TClassEdit::kDropTrailStar | TClassEdit::kLong64);
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  }
466  AddMissingClassAsEnum(TClassEdit::ShortType(clname, TClassEdit::kDropTrailStar | TClassEdit::kLong64).c_str(),kFALSE);
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) || branch->GetListOfBranches()->GetEntries() || branch->GetSplitLevel() || fMaxUnrolling) {
1158  TBranchElement *be = dynamic_cast<TBranchElement*>(branch);
1159  TVirtualStreamerInfo *beinfo = (be && isclones == TBranchProxyClassDescriptor::kOut)
1160  ? be->GetInfo() : cl->GetStreamerInfo(); // the 2nd hand need to be fixed
1161  desc = new TBranchProxyClassDescriptor(cl->GetName(), beinfo, branchname,
1162  isclones, branch->GetSplitLevel(),containerName);
1163  info = beinfo;
1164  } else {
1165  type = Form("TObjProxy<%s >",cl->GetName());
1166  }
1167  }
1168  }
1169 
1170  if ( branch->GetListOfBranches()->GetEntries() == 0 ) {
1171 
1172  if (cl) {
1173  // We have a non-split object!
1174 
1175  if (desc) {
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  } else {
1193  // We have a top level non split.
1194  AddDescriptor( new TBranchProxyDescriptor( branch->GetName(),
1195  type,
1196  branch->GetName(),
1197  true, false, false ) );
1198  }
1199  } else {
1200 
1201  // We have a top level raw type.
1202  AnalyzeOldBranch(branch, 0, 0);
1203  }
1204 
1205  } else {
1206 
1207  // We have a split object
1208 
1209  TIter subnext( branch->GetListOfBranches() );
1210  if (desc) {
1211  AnalyzeBranches(1,desc,dynamic_cast<TBranchElement*>(branch),info);
1212  }
1213  desc = AddClass(desc);
1214  if (desc) {
1215  type = desc->GetName();
1216  TString dataMemberName = branchname;
1217  AddDescriptor( new TBranchProxyDescriptor( dataMemberName, type, branchname ) );
1218  }
1219  if ( branchname[strlen(branchname)-1] != '.' ) {
1220  // If there is no dot also include the data member directly
1221 
1222  AnalyzeBranches(1,0,dynamic_cast<TBranchElement*>(branch),info);
1223 
1224  subnext.Reset();
1225  }
1226 
1227  } // if split or non split
1228  }
1229 
1230  // Now let's add the TTreeFriend (if any)
1231  if (tree->GetListOfFriends()) {
1232  TFriendElement *fe;
1233  Int_t count = 0;
1234 
1235  TIter nextfriend(tree->GetListOfFriends());
1236  while ((fe = (TFriendElement*)nextfriend())) {
1237  TTree *t = fe->GetTree();
1238  TFriendProxyDescriptor *desc;
1239  desc = new TFriendProxyDescriptor(t->GetName(), fe->GetName(), count);
1240 
1241  AddFriend( desc );
1242 
1244  AnalyzeTree(t);
1245 
1246  count++;
1247  }
1248  }
1250  }
1251 
1253  UInt_t level, TBranchProxyClassDescriptor *topdesc,
1254  const char *path)
1255  {
1256  // Analyze the element and populate the TTreeProxyGenerator or the topdesc with
1257  // its findings.
1258 
1259  TString dataMemberName;
1260  TString pxDataMemberName;
1261  TString type;
1262 
1263  // TString prefix;
1264  Bool_t isBase = false;
1265  TString cname;
1266  TString middle;
1268  TString containerName;
1269  EContainer container = kNone;
1270  if (topdesc) {
1271  if (topdesc->IsClones()) {
1272  container = kClones;
1273  middle = "Cla";
1275  containerName = "TClonesArray";
1276  } else if (topdesc->IsSTL()) {
1277  container = kSTL;
1278  middle = "Stl";
1280  containerName = topdesc->GetContainerName();
1281  }
1282  }
1283 
1284  if (!element) return;
1285 
1286  if (strcmp(element->GetName(),"This")==0) {
1287  TClass *cl = element->GetClassPointer();
1288  containerName = cl->GetName();
1289  cl = cl->GetCollectionProxy()->GetValueClass();
1290  if (!cl) {
1291  // Skip the artifical streamer element.
1292  return;
1293  }
1294  // else return;
1295 
1296  // In case the content is a class, move forward
1297  AddForward(cl);
1298  AddHeader(cl);
1299 
1300  if (level<=fMaxUnrolling) {
1301 
1302  // See AnalyzeTree for similar code!
1303  // TBranchProxyClassDescriptor *cldesc;
1304  if (cl && cl->CanSplit()) {
1305  // cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1306  // branch->GetName(),
1307  // isclones, 0 /* non-split object */,
1308  // containerName);
1309 
1310  TVirtualStreamerInfo *info = cl->GetStreamerInfo();
1311  TStreamerElement *elem = 0;
1312 
1313  TString subpath = path;
1314  if (subpath.Length()>0) subpath += ".";
1315  subpath += dataMemberName;
1316 
1317  TIter next(info->GetElements());
1318  while( (elem = (TStreamerElement*)next()) ) {
1319  AnalyzeElement(branch, elem, level+1, topdesc, subpath.Data());
1320  }
1321 
1322  // TBranchProxyClassDescriptor *added = AddClass(cldesc);
1323  // if (added) type = added->GetName();
1324  }
1325  }
1326  return;
1327  }
1328 
1329  if (element->GetType()==-1) {
1330  // This is an ignored TObject base class.
1331  return;
1332  }
1333 
1334 
1335  // Bool_t ispointer = false;
1336  switch(element->GetType()) {
1337 
1338  case TVirtualStreamerInfo::kBool: { type = "T" + middle + "BoolProxy"; break; }
1339  case TVirtualStreamerInfo::kChar: { type = "T" + middle + "CharProxy"; break; }
1340  case TVirtualStreamerInfo::kShort: { type = "T" + middle + "ShortProxy"; break; }
1341  case TVirtualStreamerInfo::kInt: { type = "T" + middle + "IntProxy"; break; }
1342  case TVirtualStreamerInfo::kLong: { type = "T" + middle + "LongProxy"; break; }
1343  case TVirtualStreamerInfo::kLong64: { type = "T" + middle + "Long64Proxy"; break; }
1344  case TVirtualStreamerInfo::kFloat: { type = "T" + middle + "FloatProxy"; break; }
1345  case TVirtualStreamerInfo::kFloat16: { type = "T" + middle + "Float16Proxy"; break; }
1346  case TVirtualStreamerInfo::kDouble: { type = "T" + middle + "DoubleProxy"; break; }
1347  case TVirtualStreamerInfo::kDouble32:{ type = "T" + middle + "Double32Proxy"; break; }
1348  case TVirtualStreamerInfo::kUChar: { type = "T" + middle + "UCharProxy"; break; }
1349  case TVirtualStreamerInfo::kUShort: { type = "T" + middle + "UShortProxy"; break; }
1350  case TVirtualStreamerInfo::kUInt: { type = "T" + middle + "UIntProxy"; break; }
1351  case TVirtualStreamerInfo::kULong: { type = "T" + middle + "ULongProxy"; break; }
1352  case TVirtualStreamerInfo::kULong64: { type = "T" + middle + "ULong64Proxy"; break; }
1353  case TVirtualStreamerInfo::kBits: { type = "T" + middle + "UIntProxy"; break; }
1354 
1355  case TVirtualStreamerInfo::kCharStar: { type = GetArrayType(element,"Char",container); break; }
1356 
1357  // array of basic types array[8]
1358  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,"Bool",container ); break; }
1359  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,"Char",container ); break; }
1360  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,"Short",container ); break; }
1361  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,"Int",container ); break; }
1362  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,"Long",container ); break; }
1363  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,"Long64",container ); break; }
1364  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,"Float",container ); break; }
1365  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,"Float16",container ); break; }
1366  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,"Double",container ); break; }
1367  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,"Double32",container ); break; }
1368  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,"UChar",container ); break; }
1369  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,"UShort",container ); break; }
1370  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,"UInt",container ); break; }
1371  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,"ULong",container ); break; }
1372  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,"ULong64",container ); break; }
1373  case TVirtualStreamerInfo::kOffsetL + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,"UInt",container ); break; }
1374 
1375  // pointer to an array of basic types array[n]
1376  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBool: { type = GetArrayType(element,"Bool",container ); break; }
1377  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kChar: { type = GetArrayType(element,"Char",container ); break; }
1378  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kShort: { type = GetArrayType(element,"Short",container ); break; }
1379  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kInt: { type = GetArrayType(element,"Int",container ); break; }
1380  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong: { type = GetArrayType(element,"Long",container ); break; }
1381  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kLong64: { type = GetArrayType(element,"Long64",container ); break; }
1382  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat: { type = GetArrayType(element,"Float",container ); break; }
1383  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kFloat16: { type = GetArrayType(element,"Float16",container ); break; }
1384  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble: { type = GetArrayType(element,"Double",container ); break; }
1385  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kDouble32:{ type = GetArrayType(element,"Double32",container ); break; }
1386  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUChar: { type = GetArrayType(element,"UChar",container ); break; }
1387  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUShort: { type = GetArrayType(element,"UShort",container ); break; }
1388  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kUInt: { type = GetArrayType(element,"UInt",container ); break; }
1389  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong: { type = GetArrayType(element,"ULong",container ); break; }
1390  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kULong64: { type = GetArrayType(element,"ULong64",container ); break; }
1391  case TVirtualStreamerInfo::kOffsetP + TVirtualStreamerInfo::kBits: { type = GetArrayType(element,"UInt",container ); break; }
1392 
1393  // array counter //[n]
1394  case TVirtualStreamerInfo::kCounter: { type = "T" + middle + "IntProxy"; break; }
1395 
1396 
1405  // set as pointers and fall through to the next switches
1406  // ispointer = true;
1416  TClass *cl = element->GetClassPointer();
1417  if (cl) {
1418  type = Form("T%sObjProxy<%s >",
1419  middle.Data(),cl->GetName());
1420  cname = cl->GetName();
1421  if (cl==TClonesArray::Class()) {
1423  containerName = "TClonesArray";
1424 
1425  Long64_t i = branch->GetTree()->GetReadEntry();
1426  if (i<0) i = 0;
1427  branch->GetEntry(i);
1428 
1429  //char *obj = branch->GetObject();
1430 
1431  // now need to follow it through to this pointer!
1432 
1433  TClonesArray *arr;
1434 
1435  TString fullpath = branch->GetName();
1436  fullpath += ".";
1437  if (path && strlen(path)>0) fullpath.Append(path).Append(".");
1438  fullpath += element->GetName();
1439 
1440  TTreeFormula *formula = new TTreeFormula("clones",fullpath,branch->GetTree());
1441 
1442  TFormLeafInfo *leafinfo = formula->GetLeafInfo(0);
1443  TLeaf *leaf = formula->GetLeaf(0);
1444  R__ASSERT(leaf && leafinfo);
1445 
1446  arr = (TClonesArray*)leafinfo->GetLocalValuePointer(leaf,0);
1447 
1448  /*
1449  if (ispointer) {
1450  arr = (TClonesArray*)*(void**)(obj+lOffset);
1451  } else {
1452  arr = (TClonesArray*)(obj+lOffset);
1453  }
1454  */
1455  if (arr) cname = arr->GetClass()->GetName();
1456 
1457  if (cname.Length()==0) {
1458  Error("AnalyzeTree",
1459  "Introspection of TClonesArray in older file not implemented yet.");
1460  }
1461  delete formula;
1462  } else if (cl->GetCollectionProxy()) {
1464  containerName = cl->GetName();
1465  cl = cl->GetCollectionProxy()->GetValueClass();
1466  }
1467  }
1468  else Error("AnalyzeTree","missing class for %s.",branch->GetName());
1469  if (element->IsA()==TStreamerBase::Class()) {
1470  // prefix = "base";
1471  isBase = true;
1472  }
1473  AddForward(cl);
1474  AddHeader(cl);
1475  break;
1476  }
1477 
1478  default:
1479  Error("AnalyzeTree",
1480  "Unsupported type for %s %s %d",
1481  branch->GetName(), element->GetName(), element->GetType());
1482 
1483  }
1484 
1485  dataMemberName = element->GetName();
1486 
1487  if (level<=fMaxUnrolling) {
1488 
1489  // See AnalyzeTree for similar code!
1491 
1492  TClass *cl = TClass::GetClass(cname);
1493  if (cl && cl->CanSplit()) {
1494  cldesc = new TBranchProxyClassDescriptor(cl->GetName(), cl->GetStreamerInfo(),
1495  branch->GetName(),
1496  isclones, 0 /* non-split object */,
1497  containerName);
1498 
1499  TVirtualStreamerInfo *info = cl->GetStreamerInfo();
1500  TStreamerElement *elem = 0;
1501 
1502  TString subpath = path;
1503  if (subpath.Length()>0) subpath += ".";
1504  subpath += dataMemberName;
1505 
1506  TIter next(info->GetElements());
1507  while( (elem = (TStreamerElement*)next()) ) {
1508  AnalyzeElement(branch, elem, level+1, cldesc, subpath.Data());
1509  }
1510 
1511  TBranchProxyClassDescriptor *added = AddClass(cldesc);
1512  if (added) type = added->GetName();
1513  }
1514 
1515  }
1516 
1517  pxDataMemberName = /* prefix + */ dataMemberName;
1518  if (topdesc) {
1519  topdesc->AddDescriptor( new TBranchProxyDescriptor( pxDataMemberName.Data(), type,
1520  dataMemberName.Data(), false),
1521  isBase );
1522  } else {
1523  Error("AnalyzeTree","topdesc should not be null in TTreeProxyGenerator::AnalyzeElement.");
1524  }
1525  }
1526 
1527  /////////////////////////////////////////////////////////////////////////////
1528  /// Parse the options string.
1529 
1531  {
1532  TString opt = fOptionStr;
1533 
1534  fOptions = 0;
1535  if ( opt.Contains("nohist") ) {
1536  opt.ReplaceAll("nohist","");
1537  fOptions |= kNoHist;
1538  }
1539  }
1540 
1541  /////////////////////////////////////////////////////////////////////////////
1542  /// Add the "pragma C++ class" if needed and return
1543  /// true if it has been added _or_ if it is known to
1544  /// not be needed.
1545  /// (I.e. return kFALSE if a container of this class
1546  /// can not have a "pragma C++ class"
1547 
1549  {
1550  if (!cl) return kFALSE;
1551  if (cl->GetCollectionProxy()) {
1552  TClass *valcl = cl->GetCollectionProxy()->GetValueClass();
1553  if (!valcl) {
1554  if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1555  return kTRUE;
1556  } else if (R__AddPragmaForClass(gen, valcl)) {
1557  if (!cl->IsLoaded()) gen->AddPragma(Form("#pragma link C++ class %s;\n", cl->GetName()));
1558  return kTRUE;
1559  }
1560  }
1561  if (cl->IsLoaded()) return kTRUE;
1562  return kFALSE;
1563  }
1564 
1565  /////////////////////////////////////////////////////////////////////////////
1566  /// Add the "pragma C++ class" if needed and return
1567  /// true if it has been added _or_ if it is known to
1568  /// not be needed.
1569  /// (I.e. return kFALSE if a container of this class
1570  /// can not have a "pragma C++ class"
1571 
1572  static Bool_t R__AddPragmaForClass(TTreeProxyGenerator *gen, const char *classname)
1573  {
1574  return R__AddPragmaForClass( gen, TClass::GetClass(classname) );
1575 
1576  }
1577 
1578  /////////////////////////////////////////////////////////////////////////////
1579  /// Check whether the file exist and do something useful if it does
1580 
1582  {
1583  if (fScript.Length()==0) {
1584  Error("WriteProxy","No user script has been specified.");
1585  return;
1586  }
1587 
1588  TString fileLocation = gSystem->DirName(fScript);
1589 
1590  TString incPath = gSystem->GetIncludePath(); // of the form -Idir1 -Idir2 -Idir3
1591  incPath.Append(":").Prepend(" ");
1592  incPath.ReplaceAll(" -I",":"); // of form :dir1 :dir2:dir3
1593  while ( incPath.Index(" :") != -1 ) {
1594  incPath.ReplaceAll(" :",":");
1595  }
1596  incPath.Prepend(fileLocation+":.:");
1597 
1598  const char *filename = gSystem->Which(incPath,fScript);
1599  if (filename==0) {
1600  Error("WriteProxy","Can not find the user's script: %s",fScript.Data());
1601  return;
1602  }
1603  const char *cutfilename = 0;
1604  if (fCutScript.Length()) {
1605  fileLocation = gSystem->DirName(fCutScript);
1606  incPath.Prepend(fileLocation+":.:");
1607  cutfilename = gSystem->Which(incPath,fCutScript);
1608  if (cutfilename==0) {
1609  Error("WriteProxy","Can not find the user's cut script: %s",fCutScript.Data());
1610  delete [] filename;
1611  return;
1612  }
1613  }
1614 
1616  TString classname = gSystem->BaseName(fPrefix);
1617 
1618  // Check if there is already an extension and extract it.
1619  Ssiz_t pos = classname.Last('.');
1620  if (pos != kNPOS) {
1621  classname.Remove(pos);
1622  } else {
1623  fHeaderFileName.Append(".h");
1624  }
1625 
1626  // Check to see if the target file exist.
1627  // If they do we will generate the proxy in temporary file and modify the original
1628  // if and only if it is different.
1629 
1630  Bool_t updating = kFALSE;
1631  if (gSystem->GetPathInfo( fHeaderFileName, 0, (Long_t*)0, 0, 0 ) == 0) {
1632  // file already exist
1633  updating = kTRUE;
1634  }
1635 
1636 
1637  TString treefile;
1638  Bool_t ischain = fTree->InheritsFrom(TChain::Class());
1639  if (fTree->GetDirectory() && fTree->GetDirectory()->GetFile())
1640  treefile = fTree->GetDirectory()->GetFile()->GetName();
1641  else
1642  treefile = "Memory Directory";
1643 
1644  TString scriptfunc = fScript;
1645  Ssiz_t dot_pos = scriptfunc.Last('.');
1646  if (dot_pos == kNPOS) {
1647  Error("WriteProxy","User's script (%s) has no extension! Nothing will be written.",scriptfunc.Data());
1648  delete [] filename;
1649  delete [] cutfilename;
1650  return;
1651  }
1652  scriptfunc.Replace( dot_pos, fScript.Length()-dot_pos, "");
1653  TString scriptHeader = scriptfunc;
1654  const char * extensions[] = { ".h", ".hh", ".hpp", ".hxx", ".hPP", ".hXX" };
1655 
1656  int i;
1657  for (i = 0; i < 6; i++ ) {
1658  TString possible = scriptHeader;
1659  possible.Append(extensions[i]);
1660  const char *name = gSystem->Which(incPath,possible);
1661  if (name) {
1662  scriptHeader = possible;
1663  fListOfHeaders.Add(new TNamed("script",Form("#include \"%s\"\n",
1664  scriptHeader.Data())));
1665  delete [] name;
1666  break;
1667  }
1668  }
1669  scriptfunc = gSystem->BaseName(scriptfunc);
1670 
1671 
1672  TString cutscriptfunc = fCutScript;
1673  if (cutfilename) {
1674  dot_pos = cutscriptfunc.Last('.');
1675  cutscriptfunc.Replace( dot_pos, fCutScript.Length()-dot_pos, "");
1676  TString cutscriptHeader = cutscriptfunc;
1677 
1678  for (i = 0; i < 6; i++ ) {
1679  TString possible = cutscriptHeader;
1680  possible.Append(extensions[i]);
1681  const char *name = gSystem->Which(incPath,possible);
1682  if (name) {
1683  cutscriptHeader = possible;
1684  fListOfHeaders.Add(new TNamed("cutscript",Form("#include \"%s\"\n",
1685  cutscriptHeader.Data())));
1686  delete [] name;
1687  break;
1688  }
1689  }
1690  cutscriptfunc = gSystem->BaseName(cutscriptfunc);
1691  }
1692 
1693  FILE *hf;
1694  TString tmpfilename = ".Proxy-";
1695  if (updating) {
1696  hf = gSystem->TempFileName(tmpfilename, "./");
1697  } else {
1698  hf = fopen(fHeaderFileName, "w");
1699  }
1700  if (hf == 0) {
1701  Error("WriteProxy","Unable to open the file %s for writing.",
1702  updating ? tmpfilename.Data() : fHeaderFileName.Data());
1703  delete [] filename;
1704  delete [] cutfilename;
1705  return;
1706  }
1707 
1708  TDatime td;
1709  fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
1710  fprintf(hf, "// This class has been automatically generated \n");
1711  fprintf(hf, "// (at %s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
1712  if (!ischain) {
1713  fprintf(hf,"// from TTree %s/%s\n",fTree->GetName(),fTree->GetTitle());
1714  fprintf(hf,"// found on file: %s\n",treefile.Data());
1715  } else {
1716  fprintf(hf,"// from TChain %s/%s\n",fTree->GetName(),fTree->GetTitle());
1717  }
1718  fprintf(hf, "/////////////////////////////////////////////////////////////////////////\n");
1719  fprintf(hf,"\n");
1720  fprintf(hf,"\n");
1721 
1722  fprintf(hf,"#ifndef %s_h\n",classname.Data());
1723  fprintf(hf,"#define %s_h\n",classname.Data());
1724  fprintf(hf,"\n");
1725 
1726 
1727  // Interface versioning
1728  fprintf(hf,"#define R__BRANCHPROXY_GENERATOR_VERSION 2\n\n");
1729  fprintf(hf,"// ROOT headers needed by the proxy\n");
1730  fprintf(hf,"#include <TROOT.h>\n");
1731  fprintf(hf,"#include <TChain.h>\n");
1732  fprintf(hf,"#include <TFile.h>\n");
1733  fprintf(hf,"#include <TPad.h>\n");
1734  fprintf(hf,"#include <TH1.h>\n");
1735  fprintf(hf,"#include <TSelector.h>\n");
1736  fprintf(hf,"#include <TBranchProxy.h>\n");
1737  fprintf(hf,"#include <TBranchProxyDirector.h>\n");
1738  fprintf(hf,"#include <TBranchProxyTemplate.h>\n");
1739  fprintf(hf,"#include <TFriendProxy.h>\n");
1740  fprintf(hf,"using namespace ROOT::Internal;\n"); // questionable
1741  fprintf(hf,"using ROOT::Detail::TBranchProxy;\n"); // questionable
1742  fprintf(hf,"\n");
1743 
1744  fprintf(hf,"// forward declarations needed by this particular proxy\n");
1745  TIter next( &fListOfForwards );
1746  TObject *current;
1747  while ( (current=next()) ) {
1748  if (strstr(current->GetTitle(),"::")==0) {
1749  // We can not forward declared nested classes (well we might be able to do so for
1750  // the one nested in a namespace but it is not clear yet if we can really reliably
1751  // find this information)
1752  fprintf(hf,"%s",current->GetTitle());
1753  }
1754  }
1755 
1756  fprintf(hf,"\n\n");
1757  fprintf(hf,"// Header needed by this particular proxy\n");
1758  next = &fListOfHeaders;
1759  TObject *header;
1760  while ( (header = next()) ) {
1761  fprintf(hf,"%s",header->GetTitle());
1762  }
1763  fprintf(hf,"\n\n");
1764 
1765  fprintf(hf,"class %s_Interface {\n", scriptfunc.Data());
1766  fprintf(hf," // This class defines the list of methods that are directly used by %s,\n",classname.Data());
1767  fprintf(hf," // and that can be overloaded in the user's script\n");
1768  fprintf(hf,"public:\n");
1769  fprintf(hf," void %s_Begin(TTree*) {}\n",scriptfunc.Data());
1770  fprintf(hf," void %s_SlaveBegin(TTree*) {}\n",scriptfunc.Data());
1771  fprintf(hf," Bool_t %s_Notify() { return kTRUE; }\n",scriptfunc.Data());
1772  fprintf(hf," Bool_t %s_Process(Long64_t) { return kTRUE; }\n",scriptfunc.Data());
1773  fprintf(hf," void %s_SlaveTerminate() {}\n",scriptfunc.Data());
1774  fprintf(hf," void %s_Terminate() {}\n",scriptfunc.Data());
1775  fprintf(hf,"};\n");
1776  fprintf(hf,"\n\n");
1777 
1778  fprintf(hf, "class %s : public TSelector, public %s_Interface {\n", classname.Data(), scriptfunc.Data());
1779  fprintf(hf, "public :\n");
1780  fprintf(hf, " TTree *fChain; //!pointer to the analyzed TTree or TChain\n");
1781  fprintf(hf, " TH1 *htemp; //!pointer to the histogram\n");
1782  fprintf(hf, " TBranchProxyDirector fDirector; //!Manages the proxys\n\n");
1783 
1784  fprintf(hf, " // Optional User methods\n");
1785  fprintf(hf, " TClass *fClass; // Pointer to this class's description\n");
1786 
1787  if (fListOfClasses.LastIndex()>=0) {
1788  fprintf(hf, "\n // Wrapper class for each unwounded class\n");
1789  next = &fListOfClasses;
1791  while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1792  clp->OutputDecl(hf, 3, fMaxDatamemberType);
1793  }
1794  }
1795 
1796  if (fListOfFriends.LastIndex()>=0) {
1797  fprintf(hf, "\n // Wrapper class for each friend TTree\n");
1798  next = &fListOfFriends;
1800  while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1801  if (!clp->IsDuplicate()) clp->OutputClassDecl(hf, 3, fMaxDatamemberType);
1802  }
1803  }
1804 
1805  fprintf(hf, "\n // Proxy for each of the branches, leaves and friends of the tree\n");
1806  next = &fListOfTopProxies;
1808  while ( (data = (TBranchProxyDescriptor*)next()) ) {
1809  data->OutputDecl(hf, 3, fMaxDatamemberType);
1810  }
1811  if (fListOfFriends.LastIndex()>=0) {
1812  next = &fListOfFriends;
1814  while ( (clp = (TFriendProxyDescriptor*)next()) ) {
1815  clp->OutputDecl(hf, 3, fMaxDatamemberType);
1816  }
1817  }
1818  fprintf(hf,"\n\n");
1819 
1820  // Constructor
1821  fprintf(hf, " %s(TTree *tree=0) : \n",classname.Data());
1822  fprintf(hf, " fChain(0)");
1823  fprintf(hf, ",\n htemp(0)");
1824  fprintf(hf, ",\n fDirector(tree,-1)");
1825  fprintf(hf, ",\n fClass (TClass::GetClass(\"%s\"))",classname.Data());
1826  next = &fListOfTopProxies;
1827  while ( (data = (TBranchProxyDescriptor*)next()) ) {
1828  fprintf(hf,",\n %-*s(&fDirector,\"%s\")",
1829  fMaxDatamemberType, data->GetDataName(), data->GetBranchName());
1830  }
1831  next = &fListOfFriends;
1833  while ( (fpd = (TFriendProxyDescriptor*)next()) ) {
1834  fprintf(hf,",\n %-*s(&fDirector,tree,%d)",
1835  fMaxDatamemberType, fpd->GetTitle(), fpd->GetIndex());
1836  }
1837 
1838  fprintf(hf, "\n { }\n");
1839 
1840  // Other functions.
1841  fprintf(hf," ~%s();\n",classname.Data());
1842  fprintf(hf," Int_t Version() const {return 1;}\n");
1843  fprintf(hf," void Begin(::TTree *tree);\n");
1844  fprintf(hf," void SlaveBegin(::TTree *tree);\n");
1845  fprintf(hf," void Init(::TTree *tree);\n");
1846  fprintf(hf," Bool_t Notify();\n");
1847  fprintf(hf," Bool_t Process(Long64_t entry);\n");
1848  fprintf(hf," void SlaveTerminate();\n");
1849  fprintf(hf," void Terminate();\n");
1850  fprintf(hf,"\n");
1851  fprintf(hf," ClassDef(%s,0);\n",classname.Data());
1852  fprintf(hf,"\n\n");
1853 
1854  fprintf(hf,"//inject the user's code\n");
1855  fprintf(hf,"#include \"%s\"\n",fScript.Data());
1856 
1857  if (cutfilename) {
1858  fprintf(hf,"#include \"%s\"\n",fCutScript.Data());
1859  }
1860 
1861  // Close the class.
1862  fprintf(hf,"};\n");
1863  fprintf(hf,"\n");
1864  fprintf(hf,"#endif\n");
1865  fprintf(hf,"\n\n");
1866 
1867  fprintf(hf,"#ifdef __MAKECINT__\n");
1868  if (fListOfClasses.LastIndex()>=0) {
1870  next = &fListOfClasses;
1871  while ( (clp = (TBranchProxyClassDescriptor*)next()) ) {
1872  fprintf(hf,"#pragma link C++ class %s::%s-;\n",classname.Data(),clp->GetName());
1873  if (clp->GetContainerName().Length()) {
1874  R__AddPragmaForClass(this, clp->GetContainerName());
1875  }
1876  }
1877  next = &fListOfPragmas;
1878  TObjString *prag;
1879  while ( (prag = (TObjString*)next()) ) {
1880  fprintf(hf,"%s",prag->String().Data());
1881  }
1882  }
1883  fprintf(hf,"#pragma link C++ class %s;\n",classname.Data());
1884  fprintf(hf,"#endif\n");
1885  fprintf(hf,"\n\n");
1886 
1887  // Write the implementations.
1888  fprintf(hf,"inline %s::~%s() {\n",classname.Data(),classname.Data());
1889  fprintf(hf," // destructor. Clean up helpers.\n");
1890  fprintf(hf,"\n");
1891  fprintf(hf,"}\n");
1892  fprintf(hf,"\n");
1893  fprintf(hf,"inline void %s::Init(TTree *tree)\n",classname.Data());
1894  fprintf(hf,"{\n");
1895  fprintf(hf,"// Set branch addresses\n");
1896  fprintf(hf," if (tree == 0) return;\n");
1897  fprintf(hf," fChain = tree;\n");
1898  fprintf(hf," fDirector.SetTree(fChain);\n");
1899  fprintf(hf," if (htemp == 0) {\n");
1900  fprintf(hf," htemp = fDirector.CreateHistogram(GetOption());\n");
1901  if (cutfilename) {
1902  fprintf(hf," htemp->SetTitle(\"%s {%s}\");\n",fScript.Data(),fCutScript.Data());
1903  } else {
1904  fprintf(hf," htemp->SetTitle(\"%s\");\n",fScript.Data());
1905  }
1906  fprintf(hf," fObject = htemp;\n");
1907  fprintf(hf," }\n");
1908  fprintf(hf,"}\n");
1909  fprintf(hf,"\n");
1910  fprintf(hf,"Bool_t %s::Notify()\n",classname.Data());
1911  fprintf(hf,"{\n");
1912  fprintf(hf," // Called when loading a new file.\n");
1913  fprintf(hf," // Get branch pointers.\n");
1914  fprintf(hf," fDirector.SetTree(fChain);\n");
1915  fprintf(hf," %s_Notify();\n",scriptfunc.Data());
1916  fprintf(hf," \n");
1917  fprintf(hf," return kTRUE;\n");
1918  fprintf(hf,"}\n");
1919  fprintf(hf," \n");
1920 
1921  // generate code for class member function Begin
1922  fprintf(hf,"\n");
1923  fprintf(hf,"inline void %s::Begin(TTree *tree)\n",classname.Data());
1924  fprintf(hf,"{\n");
1925  fprintf(hf," // The Begin() function is called at the start of the query.\n");
1926  fprintf(hf," // When running with PROOF Begin() is only called on the client.\n");
1927  fprintf(hf," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1928  fprintf(hf,"\n");
1929  fprintf(hf," TString option = GetOption();\n");
1930  fprintf(hf," %s_Begin(tree);\n",scriptfunc.Data());
1931  fprintf(hf,"\n");
1932  fprintf(hf,"}\n");
1933 
1934  // generate code for class member function SlaveBegin
1935  fprintf(hf,"\n");
1936  fprintf(hf,"inline void %s::SlaveBegin(TTree *tree)\n",classname.Data());
1937  fprintf(hf,"{\n");
1938  fprintf(hf," // The SlaveBegin() function is called after the Begin() function.\n");
1939  fprintf(hf," // When running with PROOF SlaveBegin() is called on each slave server.\n");
1940  fprintf(hf," // The tree argument is deprecated (on PROOF 0 is passed).\n");
1941  fprintf(hf,"\n");
1942  fprintf(hf," Init(tree);\n");
1943  fprintf(hf,"\n");
1944  fprintf(hf," %s_SlaveBegin(tree);\n",scriptfunc.Data());
1945  fprintf(hf,"\n");
1946  fprintf(hf,"}\n");
1947  fprintf(hf,"\n");
1948 
1949  // generate code for class member function Process
1950  fprintf(hf,"inline Bool_t %s::Process(Long64_t entry)\n",classname.Data());
1951  fprintf(hf,"{\n");
1952 
1953  fprintf(hf," // The Process() function is called for each entry in the tree (or possibly\n"
1954  " // keyed object in the case of PROOF) to be processed. The entry argument\n"
1955  " // specifies which entry in the currently loaded tree is to be processed.\n"
1956  " // It can be passed to either TTree::GetEntry() or TBranch::GetEntry()\n"
1957  " // to read either all or the required parts of the data. When processing\n"
1958  " // keyed objects with PROOF, the object is already loaded and is available\n"
1959  " // via the fObject pointer.\n"
1960  " //\n"
1961  " // This function should contain the \"body\" of the analysis. It can contain\n"
1962  " // simple or elaborate selection criteria, run algorithms on the data\n"
1963  " // of the event and typically fill histograms.\n\n");
1964  fprintf(hf," // WARNING when a selector is used with a TChain, you must use\n");
1965  fprintf(hf," // the pointer to the current TTree to call GetEntry(entry).\n");
1966  fprintf(hf," // The entry is always the local entry number in the current tree.\n");
1967  fprintf(hf," // Assuming that fChain is the pointer to the TChain being processed,\n");
1968  fprintf(hf," // use fChain->GetTree()->GetEntry(entry).\n");
1969  fprintf(hf,"\n");
1970  fprintf(hf,"\n");
1971  fprintf(hf," fDirector.SetReadEntry(entry);\n");
1972  if (fOptions & kNoHist) {
1973  if (cutfilename) {
1974  fprintf(hf," if (%s()) %s();\n",cutscriptfunc.Data(),scriptfunc.Data());
1975  } else {
1976  fprintf(hf," %s();\n",scriptfunc.Data());
1977  }
1978  } else {
1979  if (cutfilename) {
1980  fprintf(hf," if (%s()) htemp->Fill(%s());\n",cutscriptfunc.Data(),scriptfunc.Data());
1981  } else {
1982  fprintf(hf," htemp->Fill(%s());\n",scriptfunc.Data());
1983  }
1984  }
1985  fprintf(hf," %s_Process(entry);\n",scriptfunc.Data());
1986  fprintf(hf," return kTRUE;\n");
1987  fprintf(hf,"\n");
1988  fprintf(hf,"}\n\n");
1989 
1990  // generate code for class member function SlaveTerminate
1991  fprintf(hf,"inline void %s::SlaveTerminate()\n",classname.Data());
1992  fprintf(hf,"{\n");
1993  fprintf(hf," // The SlaveTerminate() function is called after all entries or objects\n"
1994  " // have been processed. When running with PROOF SlaveTerminate() is called\n"
1995  " // on each slave server.");
1996  fprintf(hf,"\n");
1997  fprintf(hf," %s_SlaveTerminate();\n",scriptfunc.Data());
1998  fprintf(hf,"}\n\n");
1999 
2000  // generate code for class member function Terminate
2001  fprintf(hf,"inline void %s::Terminate()\n",classname.Data());
2002  fprintf(hf,"{\n");
2003  fprintf(hf," // Function called at the end of the event loop.\n");
2004  fprintf(hf," htemp = (TH1*)fObject;\n");
2005  fprintf(hf," Int_t drawflag = (htemp && htemp->GetEntries()>0);\n");
2006  fprintf(hf," \n");
2007  fprintf(hf," if (gPad && !drawflag && !fOption.Contains(\"goff\") && !fOption.Contains(\"same\")) {\n");
2008  fprintf(hf," gPad->Clear();\n");
2009  fprintf(hf," } else {\n");
2010  fprintf(hf," if (fOption.Contains(\"goff\")) drawflag = false;\n");
2011  fprintf(hf," if (drawflag) htemp->Draw(fOption);\n");
2012  fprintf(hf," }\n");
2013  fprintf(hf," %s_Terminate();\n",scriptfunc.Data());
2014  fprintf(hf,"}\n");
2015 
2016  fclose(hf);
2017 
2018  if (updating) {
2019  // over-write existing file only if needed.
2020  if (AreDifferent(fHeaderFileName,tmpfilename)) {
2022  gSystem->Rename(tmpfilename,fHeaderFileName);
2023  } else gSystem->Unlink(tmpfilename);
2024  }
2025  delete [] filename;
2026  delete [] cutfilename;
2027  }
2028 
2029 } // namespace Internal
2030 } // namespace ROOT
virtual const char * BaseName(const char *pathname)
Base name of a file name. Base name of /user/root is root.
Definition: TSystem.cxx:931
virtual Bool_t IsEquivalent(const TBranchProxyClassDescriptor *other)
virtual const char * GetName() const
Returns name of object.
Definition: TNamed.h:47
virtual const char * GetClassName() const
Return the name of the user class whose content is stored in this branch, if any. ...
Definition: TBranch.cxx:1256
A TLeaf describes individual elements of a TBranch See TBranch structure in TTree.
Definition: TLeaf.h:32
Bool_t NeedToEmulate(TClass *cl, UInt_t level)
Bool_t CanSplit() const
Return true if the data member of this TClass can be saved separately.
Definition: TClass.cxx:2232
An array of TObjects.
Definition: TObjArray.h:37
UInt_t AnalyzeBranches(UInt_t level, TBranchProxyClassDescriptor *topdesc, TBranchElement *branch, TVirtualStreamerInfo *info=0)
virtual TTree * GetTree()
Return pointer to friend TTree.
Int_t GetSplitLevel() const
Definition: TBranch.h:186
long long Long64_t
Definition: RtypesCore.h:69
void OutputClassDecl(FILE *hf, int offset, UInt_t maxVarname)
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
Int_t GetType() const
Namespace for new ROOT classes and functions.
Definition: StringConv.hxx:21
virtual TClass * GetClass() const =0
Collectable string class.
Definition: TObjString.h:28
virtual TClass * GetValueClass() const =0
void ParseOptions()
Parse the options string.
const Ssiz_t kNPOS
Definition: RtypesCore.h:115
TString & ReplaceAll(const TString &s1, const TString &s2)
Definition: TString.h:640
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:1370
Bool_t TestBit(UInt_t f) const
Definition: TObject.h:159
virtual TClass * GetClassPointer() const
Returns a pointer to the TClass of this element.
virtual void SetName(const char *name)
Set the name of the TNamed.
Definition: TNamed.cxx:131
TBranch * GetSubBranch(const TBranch *br) const
Find the parent branch of child.
Definition: TBranch.cxx:1646
virtual const char * GetTypeName() const
Definition: TLeaf.h:76
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:4360
void AddHeader(TClass *cl)
Add a header inclusion request.
virtual TList * GetListOfFriends() const
Definition: TTree.h:407
void AddFriend(TFriendProxyDescriptor *desc)
void AddPragma(const char *pragma_text)
TStreamerInfo * GetInfo() const
Get streamer info for the branch class.
#define R__ASSERT(e)
Definition: TError.h:96
#define gROOT
Definition: TROOT.h:375
Ssiz_t Index(const char *pat, Ssiz_t i=0, ECaseCompare cmp=kExact) const
Definition: TString.h:587
Basic string class.
Definition: TString.h:129
void AddDescriptor(TBranchProxyDescriptor *desc)
TVirtualCollectionProxy * GetCollectionProxy() const
Return the proxy describing the collection (if any).
Definition: TClass.cxx:2814
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:1003
bool Bool_t
Definition: RtypesCore.h:59
virtual char * Which(const char *search, const char *file, EAccessMode mode=kFileExists)
Find location of file in a search path.
Definition: TSystem.cxx:1518
void WriteProxy()
Check whether the file exist and do something useful if it does.
TString & Prepend(const char *cs)
Definition: TString.h:609
TObject * At(Int_t idx) const
Definition: TObjArray.h:165
Int_t GetArrayDim() const
TString GetContainedClassName(TBranchElement *branch, TStreamerElement *element, Bool_t ispointer)
Get name of class inside a container.
Bool_t IsEquivalent(const TFriendProxyDescriptor *other)
virtual TObject * FindObject(const char *name) const
Find an object in this list using its name.
Definition: TList.cxx:501
TString & Replace(Ssiz_t pos, Ssiz_t n, const char *s)
Definition: TString.h:630
TBranchElement * GetBranchCount() const
virtual int Rename(const char *from, const char *to)
Rename a file.
Definition: TSystem.cxx:1326
void AddDescriptor(TBranchProxyDescriptor *desc, Bool_t isBase)
virtual int Unlink(const char *name)
Unlink, i.e. remove, a file.
Definition: TSystem.cxx:1353
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:2345
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:1469
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:29
virtual Long64_t GetReadEntry() const
Definition: TTree.h:424
Bool_t IsLoaded() const
Return true if the shared library of this class is currently in the a process&#39;s memory.
Definition: TClass.cxx:5549
TString & Append(const char *cs)
Definition: TString.h:497
std::vector< std::vector< double > > Data
#define va_(arg)
Definition: Varargs.h:41
TObjArray * GetListOfBranches()
Definition: TBranch.h:182
virtual TFile * GetFile() const
Definition: TDirectory.h:145
Used to pass a selection expression to the Tree drawing routine.
Definition: TTreeFormula.h:58
TString GetArrayType(TStreamerElement *element, const char *subtype, TTreeProxyGenerator::EContainer container)
TTreeProxyGenerator(TTree *tree, const char *script, const char *fileprefix, const char *option, UInt_t maxUnrolling)
const Int_t kInfo
Definition: TError.h:37
R__EXTERN TSystem * gSystem
Definition: TSystem.h:539
void OutputDecl(FILE *hf, int offset, UInt_t maxVarname)
virtual Bool_t InheritsFrom(const char *classname) const
Returns kTRUE if object inherits from class "classname".
Definition: TObject.cxx:436
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
Definition: TString.h:563
TObject * Next()
Definition: TCollection.h:153
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...
Int_t GetMaxIndex(Int_t i) const
TVirtualStreamerInfo * GetStreamerInfo(TBranch *branch, TIter current, TClass *cl)
Return the correct TStreamerInfo of class &#39;cl&#39; in the list of branches (current) [Assuming these bran...
unsigned int UInt_t
Definition: RtypesCore.h:42
Int_t GetEntriesFast() const
Definition: TObjArray.h:64
char * Form(const char *fmt,...)
Ssiz_t Length() const
Definition: TString.h:388
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:1291
Bool_t CanIgnoreTObjectStreamer()
Definition: TClass.h:348
The ROOT global object gROOT contains a list of all defined classes.
Definition: TClass.h:71
void Warning(const char *location, const char *msgfmt,...)
void Debug(Int_t level, const char *va_(fmt),...)
TString & String()
Definition: TObjString.h:49
Int_t LastIndex() const
A Branch for the case of an object.
const Bool_t kFALSE
Definition: RtypesCore.h:92
TString & Remove(Ssiz_t pos)
Definition: TString.h:621
long Long_t
Definition: RtypesCore.h:50
int Ssiz_t
Definition: RtypesCore.h:63
virtual const char * GetIncludePath()
Get the list of include path.
Definition: TSystem.cxx:3805
TObject * UncheckedAt(Int_t i) const
Definition: TObjArray.h:89
virtual TLeaf * GetLeaf(Int_t n) const
Return leaf corresponding to serial number n.
Ssiz_t Last(char c) const
Find last occurrence of a character c.
Definition: TString.cxx:875
virtual TObjArray * GetElements() const =0
TDirectory * GetDirectory() const
Definition: TTree.h:380
This class is a small helper class to implement reading a data member on an object stored in a TTree...
Definition: TFormLeafInfo.h:49
int type
Definition: TGX11.cxx:120
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Definition: TString.h:572
const char * AsString() const
Return the date & time as a string (ctime() format).
Definition: TDatime.cxx:101
TObjArray * GetListOfLeaves()
Definition: TBranch.h:183
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:2885
TClass * GetClass() const
Definition: TClonesArray.h:57
Mother of all ROOT objects.
Definition: TObject.h:37
virtual const char * GetTitle() const
Returns title of object.
Definition: TObject.cxx:408
An array of clone (identical) objects.
Definition: TClonesArray.h:32
void AddMissingClassAsEnum(const char *clname, Bool_t isscope)
UInt_t AnalyzeOldBranch(TBranch *branch, UInt_t level, TBranchProxyClassDescriptor *desc)
const char * GetTypeName() const
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:77
const char * GetCountName() const
A TFriendElement TF describes a TTree object TF in a file.
TFormLeafInfo * GetLeafInfo(Int_t code) const
Return DataMember corresponding to code.
TTree * GetTree() const
Definition: TBranch.h:188
Int_t GetEntries() const
Return the number of objects in array (i.e.
Definition: TObjArray.cxx:494
R__EXTERN Int_t gDebug
Definition: Rtypes.h:83
void CheckForMissingClass(const char *clname)
Definition: tree.py:1
A TTree object has a header with a name and a title.
Definition: TTree.h:78
double result[121]
TBranch * GetBranch() const
Definition: TLeaf.h:65
A TTree is a list of TBranches.
Definition: TBranch.h:57
Abstract Interface class describing Streamer information for one class.
virtual void SetTitle(const char *title="")
Set the title of the TNamed.
Definition: TNamed.cxx:155
TVirtualStreamerInfo * GetBaseClass(TStreamerElement *element)
Check if element is a base class and if yes, return the base class.
const Bool_t kTRUE
Definition: RtypesCore.h:91
Int_t GetType() const
const Int_t n
Definition: legend1.C:16
TBranch * GetMother() const
Get our top-level parent branch in the tree.
Definition: TBranch.cxx:1625
void Error(ErrorHandler_t func, int code, const char *va_(fmt),...)
Write error message and call a handler, if required.
virtual const char * GetTitle() const
Returns title of object.
Definition: TNamed.h:48
This class stores the date and time with a precision of one second in an unsigned 32 bit word (950130...
Definition: TDatime.h:37
TBranchProxyClassDescriptor * AddClass(TBranchProxyClassDescriptor *desc)
const char * Data() const
Definition: TString.h:347