Logo ROOT   6.30.04
Reference Guide
 All Namespaces Files Pages
TBranchProxyClassDescriptor.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 /** \class TBranchProxyClassDescriptor
13 Hold the processed information about a TClass used in a TBranch while
14 TTreeProxyGenerator is parsing the TTree information.
15 Also contains the routine use to generate the appropriate code
16 fragment in the result of MakeProxy.
17 */
18 
19 #include "TBranchProxyDescriptor.h"
21 
22 #include "TClass.h"
23 #include "TClassEdit.h"
24 #include "TError.h"
25 #include "TVirtualStreamerInfo.h"
27 
28 ClassImp(ROOT::Internal::TBranchProxyClassDescriptor);
29 
30 namespace ROOT {
31 namespace Internal {
32 
33  void TBranchProxyClassDescriptor::NameToSymbol() {
34 
35  // Make the typename a proper class name without having the really deal with
36  // namespace and templates.
37 
38  fRawSymbol = TClassEdit::ShortType(GetName(),2); // Drop default allocator from the name.
39  fRawSymbol.ReplaceAll(":","_");
40  fRawSymbol.ReplaceAll("<","_");
41  fRawSymbol.ReplaceAll(">","_");
42  fRawSymbol.ReplaceAll(",","Cm");
43  fRawSymbol.ReplaceAll(" ","");
44  fRawSymbol.ReplaceAll("*","st");
45  fRawSymbol.ReplaceAll("&","rf");
46  if (IsClones())
47  fRawSymbol.Prepend("TClaPx_");
48  else if (IsSTL())
49  fRawSymbol.Prepend("TStlPx_");
50  else
51  fRawSymbol.Prepend("TPx_");
52  if (fRawSymbol.Length() && fRawSymbol[fRawSymbol.Length()-1]=='.')
53  fRawSymbol.Remove(fRawSymbol.Length()-1);
54 
55  SetName(fRawSymbol);
56  }
57 
58  TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *type,
59  TVirtualStreamerInfo *info,
60  const char *branchname,
61  ELocation isclones,
62  UInt_t splitlevel,
63  const TString &containerName) :
64  TNamed(type,type),
65  fIsClones(isclones),
66  fContainerName(containerName),
67  fIsLeafList(false),
68  fSplitLevel(splitlevel),
69  fBranchName(branchname),
70  fSubBranchPrefix(branchname),
71  fInfo(info),
72  fMaxDatamemberType(3)
73  {
74  // Constructor.
75 
76  R__ASSERT( strcmp(fInfo->GetName(), type)==0 );
77  NameToSymbol();
78  if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
79  }
80 
81  TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *branchname) :
82  TNamed(branchname,branchname),
83  fIsClones(kOut),
84  fContainerName(),
85  fIsLeafList(true),
86  fSplitLevel(0),
87  fBranchName(branchname),
88  fSubBranchPrefix(branchname),
89  fInfo(0),
90  fMaxDatamemberType(3)
91  {
92  // Constructor for a branch constructed from a leaf list.
93 
94  NameToSymbol();
95  if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
96  }
97 
98  TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *type, TVirtualStreamerInfo *info,
99  const char *branchname,
100  const char *branchPrefix, ELocation isclones,
101  UInt_t splitlevel,
102  const TString &containerName) :
103  TNamed(type,type),
104  fIsClones(isclones),
105  fContainerName(containerName),
106  fIsLeafList(true),
107  fSplitLevel(splitlevel),
108  fBranchName(branchname),
109  fSubBranchPrefix(branchPrefix),
110  fInfo(info),
111  fMaxDatamemberType(3)
112  {
113  // Constructor.
114 
115  R__ASSERT( strcmp(fInfo->GetName(), type)==0 );
116  NameToSymbol();
117  if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
118  }
119 
120  const char* TBranchProxyClassDescriptor::GetBranchName() const
121  {
122  // Get the branch name
123  return fBranchName.Data();
124  }
125 
126  const char* TBranchProxyClassDescriptor::GetSubBranchPrefix() const
127  {
128  // Get the prefix from the branch name
129  return fSubBranchPrefix.Data();
130  }
131 
132  const char* TBranchProxyClassDescriptor::GetRawSymbol() const
133  {
134  // Get the real symbol name
135 
136  return fRawSymbol;
137  }
138 
139  UInt_t TBranchProxyClassDescriptor::GetSplitLevel() const {
140  // Return the split level of the branch.
141  return fSplitLevel;
142  }
143 
144  Bool_t TBranchProxyClassDescriptor::IsEquivalent(const TBranchProxyClassDescriptor* other)
145  {
146  // Return true if this description is the 'same' as the other decription.
147 
148  if ( !other ) return kFALSE;
149  // Purposely do not test on the name!
150  if ( strcmp(GetTitle(),other->GetTitle()) ) return kFALSE;
151  // if ( fBranchName != other->fBranchName ) return kFALSE;
152  // if ( fSubBranchPrefix != other->fSubBranchPrefix ) return kFALSE;
153 
154  if (fIsClones != other->fIsClones) return kFALSE;
155  if (fIsClones != kOut) {
156  if (fContainerName != other->fContainerName) return kFALSE;
157  }
158 
159  TBranchProxyDescriptor *desc;
160  TBranchProxyDescriptor *othdesc;
161 
162  if ( fListOfBaseProxies.GetSize() != other->fListOfBaseProxies.GetSize() ) return kFALSE;
163  TIter next(&fListOfBaseProxies);
164  TIter othnext(&other->fListOfBaseProxies);
165  while ( (desc=(TBranchProxyDescriptor*)next()) ) {
166  othdesc=(TBranchProxyDescriptor*)othnext();
167  if (!desc->IsEquivalent(othdesc,kTRUE) ) return kFALSE;
168  }
169 
170  if ( fListOfSubProxies.GetSize() != other->fListOfSubProxies.GetSize() ) return kFALSE;
171  next = &fListOfSubProxies;
172  othnext = &(other->fListOfSubProxies);
173 
174  while ( (desc=(TBranchProxyDescriptor*)next()) ) {
175  othdesc=(TBranchProxyDescriptor*)othnext();
176  if (!desc->IsEquivalent(othdesc,kTRUE)) return kFALSE;
177  if (desc->IsSplit()) {
178  TString leftname ( desc->GetBranchName() );
179  TString rightname( othdesc->GetBranchName() );
180 
181  if (leftname.Index(GetBranchName())==0) leftname.Remove( 0,strlen(GetBranchName()));
182  if (leftname.Length() && leftname[0]=='.') leftname.Remove(0,1);
183  if (rightname.Index(other->GetBranchName())==0) rightname.Remove(0,strlen(other->GetBranchName()));
184  if (rightname.Length() && rightname[0]=='.') rightname.Remove(0,1);
185  if (leftname != rightname ) return kFALSE;
186  }
187  }
188  return true;
189  }
190 
191  void TBranchProxyClassDescriptor::AddDescriptor(TBranchProxyDescriptor *desc, Bool_t isBase)
192  {
193  // Add a descriptor to this proxy.
194 
195  if (desc) {
196  if (isBase) {
197  fListOfBaseProxies.Add(desc);
198  } else {
199  fListOfSubProxies.Add(desc);
200  UInt_t len = strlen(desc->GetTypeName());
201  if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
202  }
203  }
204  }
205 
206  Bool_t TBranchProxyClassDescriptor::IsLoaded() const
207  {
208  // Return true if the class needed by the branch is loaded
209  return IsLoaded(GetTitle());
210  }
211 
212  Bool_t TBranchProxyClassDescriptor::IsLoaded(const char *classname)
213  {
214  // Return true if the class needed by the branch is loaded
215  TClass *cl = TClass::GetClass(classname);
216  while (cl) {
217  if (cl->IsLoaded()) return kTRUE;
218  if (!cl->GetCollectionProxy()) return kFALSE;
219  if (!cl->GetCollectionProxy()->GetValueClass()) return kTRUE; // stl container of simple type are always 'loaded'
220  cl = cl->GetCollectionProxy()->GetValueClass();
221  }
222  return kFALSE;
223  }
224 
225  Bool_t TBranchProxyClassDescriptor::IsClones() const
226  {
227  // Return true if this proxy is for a TClonesArray.
228  return fIsClones==kClones || fIsClones==kInsideClones;
229  }
230 
231  Bool_t TBranchProxyClassDescriptor::IsSTL() const
232  {
233  // Return true if this proxy is for a TClonesArray.
234  return fIsClones==kSTL || fIsClones==kInsideSTL;
235  }
236 
237  TBranchProxyClassDescriptor::ELocation TBranchProxyClassDescriptor::GetIsClones() const
238  {
239  // Return whether the branch is inside, nested in or outside of a TClonesArray
240  return fIsClones;
241  }
242 
243  TString TBranchProxyClassDescriptor::GetContainerName() const
244  {
245  // Return the name of the container holding this class, if any.
246  return fContainerName;
247  }
248 
249  void TBranchProxyClassDescriptor::OutputDecl(FILE *hf, int offset, UInt_t /* maxVarname */)
250  {
251  // Output the declaration and implementation of this emulation class
252 
253  TBranchProxyDescriptor *desc;
254 
255 
256  // Start the class declaration with the eventual list of base classes
257  fprintf(hf,"%-*sstruct %s\n", offset," ", GetName() );
258 
259  if (fListOfBaseProxies.GetSize()) {
260  fprintf(hf,"%-*s : ", offset," ");
261 
262  TIter next(&fListOfBaseProxies);
263 
264  desc = (TBranchProxyDescriptor*)next();
265  fprintf(hf,"public %s", desc->GetTypeName());
266 
267  while ( (desc = (TBranchProxyDescriptor*)next()) ) {
268  fprintf(hf,",\n%-*spublic %s", offset+5," ", desc->GetTypeName());
269  }
270 
271  fprintf(hf,"\n");
272  }
273  fprintf(hf,"%-*s{\n", offset," ");
274 
275 
276  // Write the constructor
277  fprintf(hf,"%-*s %s(TBranchProxyDirector* director,const char *top,const char *mid=0) :",
278  offset," ", GetName());
279 
280  Bool_t wroteFirst = kFALSE;
281 
282  if (fListOfBaseProxies.GetSize()) {
283 
284  TIter next(&fListOfBaseProxies);
285 
286  desc = (TBranchProxyDescriptor*)next();
287  fprintf(hf,"\n%-*s%-*s(director, top, mid)", offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
288  wroteFirst = true;
289 
290  while ( (desc = (TBranchProxyDescriptor*)next()) ) {
291  fprintf(hf,",\n%-*s%-*s(director, top, mid)", offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
292  }
293 
294  }
295  fprintf(hf,"%s\n%-*s %-*s(top,mid)",wroteFirst?",":"",offset," ",fMaxDatamemberType,"ffPrefix");
296  wroteFirst = true;
297 
298  TString objInit = "top, mid";
299  if ( GetIsClones() == kInsideClones || GetIsClones() == kInsideSTL ) {
300  if (fListOfSubProxies.GetSize()) {
301  desc = (TBranchProxyDescriptor*)fListOfSubProxies.At(0);
302  if (desc && desc->IsSplit()) {
303 
304  // In the case of a split sub object is TClonesArray, the
305  // object itself does not have its own branch, so we need to
306  // use its first (semantic) sub-branch as a proxy
307 
308  TString main = GetBranchName();
309  TString sub = desc->GetBranchName();
310  sub.Remove(0,main.Length()+1);
311 
312  objInit = "ffPrefix, ";
313  objInit += "\"";
314  objInit += sub;
315  objInit += "\"";
316 
317  objInit = "top, \"\", mid";
318  }
319  }
320  }
321 
322  fprintf(hf,"%s\n%-*s %-*s(director, %s)",
323  ",",offset," ",fMaxDatamemberType,"obj",objInit.Data());
324 
325  TIter next(&fListOfSubProxies);
326  while ( (desc = (TBranchProxyDescriptor*)next()) ) {
327  fprintf(hf,",");
328  desc->OutputInit(hf,offset,fMaxDatamemberType,GetSubBranchPrefix());
329  }
330  fprintf(hf,"\n%-*s {};\n",offset," ");
331 
332 
333  // Write the 2nd constructor
334  fprintf(hf,"%-*s %s(TBranchProxyDirector* director, TBranchProxy *parent, const char *membername, const char *top=0, const char *mid=0) :",
335  offset," ", GetName());
336 
337  wroteFirst = kFALSE;
338 
339  if (fListOfBaseProxies.GetSize()) {
340 
341  TIter nextbase(&fListOfBaseProxies);
342 
343  // This is guarantee to return a non zero value due to the if (fListOfBaseProxies.GetSize())
344  desc = (TBranchProxyDescriptor*)nextbase();
345  fprintf(hf,"\n%-*s%-*s(director, parent, membername, top, mid)", offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
346  wroteFirst = true;
347 
348  while ( (desc = (TBranchProxyDescriptor*)nextbase()) ) {
349  fprintf(hf,",\n%-*s%-*s(director, parent, membername, top, mid)", offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
350  }
351 
352  }
353  fprintf(hf,"%s\n%-*s %-*s(top,mid)",wroteFirst?",":"",offset," ",fMaxDatamemberType,"ffPrefix");
354  wroteFirst = true;
355 
356  if ( true || IsLoaded() || IsClones() || IsSTL() ) {
357  fprintf(hf,"%s\n%-*s %-*s(director, parent, membername, top, mid)",
358  ",",offset," ",fMaxDatamemberType,"obj");
359  }
360 
361  next.Reset();
362  while ( (desc = (TBranchProxyDescriptor*)next()) ) {
363  fprintf(hf,",");
364  desc->OutputInit(hf,offset,fMaxDatamemberType,GetSubBranchPrefix());
365  }
366  fprintf(hf,"\n%-*s {};\n",offset," ");
367 
368 
369  // Declare the data members.
370  fprintf(hf,"%-*s%-*s %s;\n", offset+3," ", fMaxDatamemberType, "ROOT::Internal::TBranchProxyHelper", "ffPrefix");
371 
372  // If the real class is available, make it available via the arrow operator:
373  if (IsLoaded()) {
374 
375  const char *type = GetTitle(); /* IsClones() ? "TClonesArray" : GetTitle(); */
376  fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
377  //Can the real type contain a leading 'const'? If so the following is incorrect.
378  if ( IsClones() ) {
379  fprintf(hf,"%-*sconst %s* operator[](Int_t i) { return obj.At(i); }\n", offset+3," ",type);
380  fprintf(hf,"%-*sconst %s* operator[](UInt_t i) { return obj.At(i); }\n", offset+3," ",type);
381  fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
382  fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
383  fprintf(hf,"%-*sTClaObjProxy<%s > obj;\n", offset+3, " ", type);
384  } else if ( IsSTL() ) {
385  if (fContainerName.Length() && IsLoaded(fContainerName)) {
386  fprintf(hf,"%-*sconst %s& At(UInt_t i) {\n",offset+3," ",type);
387  TClass *stlCl = TClass::GetClass(fContainerName);
388  TClass *cl = TClass::GetClass(GetTitle());
389  if (cl->GetMethodWithPrototype(cl->GetName(),"TRootIOCtor*")) {
390  fprintf(hf,"%-*s static %s default_val((TRootIOCtor*)0);\n",offset+3," ",type);
391  } else {
392  fprintf(hf,"%-*s static %s default_val;\n",offset+3," ",type);
393  }
394  fprintf(hf,"%-*s if (!obj.Read()) return default_val;\n",offset+3," ");
395  if (stlCl->GetCollectionProxy()->GetValueClass() == cl) {
396  fprintf(hf,"%-*s %s *temp = & obj.GetPtr()->at(i);\n",offset+3," ",type);
397  } else {
398  fprintf(hf,"%-*s %s *temp = (%s *)( obj.GetProxy()->GetStlStart(i) );\n",offset+3," ",type,type);
399  }
400  //fprintf(hf,"%-*s %s *temp = (%s *)( obj.GetPtr()->at(i)) + obj.GetOffset() );\n",offset+3," ",type,type);
401  //fprintf(hf,"%-*s %s *temp = (%s *)(void*)(&obj.At(i));\n",offset+3," ",type,type);
402  fprintf(hf,"%-*s if (temp) return *temp; else return default_val;\n",offset+3," ");
403  fprintf(hf,"%-*s}\n",offset+3," ");
404 
405  fprintf(hf,"%-*sconst %s& operator[](Int_t i) { return At(i); }\n", offset+3," ",type);
406  fprintf(hf,"%-*sconst %s& operator[](UInt_t i) { return At(i); }\n", offset+3," ",type);
407  fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetPtr()->size(); }\n",offset+3," ");
408  fprintf(hf,"%-*sconst %s* operator->() { return obj.GetPtr(); }\n", offset+3," ",fContainerName.Data());
409  fprintf(hf,"%-*soperator %s*() { return obj.GetPtr(); }\n", offset+3," ",fContainerName.Data());
410  fprintf(hf,"%-*sTObjProxy<%s > obj;\n", offset+3, " ", fContainerName.Data());
411  } else {
412  fprintf(hf,"%-*sconst %s& operator[](Int_t i) { return obj.At(i); }\n", offset+3," ",type);
413  fprintf(hf,"%-*sconst %s& operator[](UInt_t i) { return obj.At(i); }\n", offset+3," ",type);
414  fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
415  fprintf(hf,"%-*sTStlObjProxy<%s > obj;\n", offset+3, " ", type);
416  }
417  } else {
418  fprintf(hf,"%-*sconst %s* operator->() { return obj.GetPtr(); }\n", offset+3," ",type);
419  fprintf(hf,"%-*sTObjProxy<%s > obj;\n", offset+3, " ", type);
420  }
421 
422  } else if ( IsClones()) {
423 
424  fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
425  fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
426  fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
427  fprintf(hf,"%-*sTClaProxy obj;\n", offset+3," ");
428 
429  } else if ( IsSTL()) {
430 
431  fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
432  fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
433  // fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
434  fprintf(hf,"%-*sTStlProxy obj;\n", offset+3," ");
435 
436  } else {
437 
438  fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
439  fprintf(hf,"%-*sTBranchProxy obj;\n", offset+3," ");
440 
441  }
442 
443  fprintf(hf,"\n");
444 
445  next.Reset();
446  while( (desc = ( TBranchProxyDescriptor *)next()) ) {
447  desc->OutputDecl(hf,offset+3,fMaxDatamemberType);
448  }
449  fprintf(hf,"%-*s};\n",offset," ");
450 
451  //TBranchProxyDescriptor::OutputDecl(hf,offset,maxVarname);
452  }
453 
454 } // namespace Internal
455 } // namespace ROOT