TBranchProxyClassDescriptor.cxx

Go to the documentation of this file.
00001 // @(#)root/treeplayer:$Id: TBranchProxyClassDescriptor.cxx 36449 2010-10-28 20:52:17Z pcanal $
00002 // Author: Philippe Canal 06/06/2004
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers and al.        *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TBranchProxyClassDescriptor                                          //
00015 //                                                                      //
00016 // Hold the processed information about a TClass used in a TBranch while//
00017 // TTreeProxyGenerator is parsing the TTree information.                //
00018 // Also contains the routine use to generate the appropriate code       //
00019 // fragment in the result of MakeProxy.                                 //
00020 //                                                                      //
00021 //////////////////////////////////////////////////////////////////////////
00022 
00023 #include "TBranchProxyDescriptor.h"
00024 #include "TBranchProxyClassDescriptor.h"
00025 
00026 #include "TClass.h"
00027 #include "TClassEdit.h"
00028 #include "TError.h"
00029 #include "TVirtualStreamerInfo.h"
00030 #include "TVirtualCollectionProxy.h"
00031 
00032 ClassImp(ROOT::TBranchProxyClassDescriptor);
00033 
00034 namespace ROOT {
00035 
00036    void TBranchProxyClassDescriptor::NameToSymbol() {
00037 
00038       // Make the typename a proper class name without having the really deal with
00039       // namespace and templates.
00040 
00041       fRawSymbol = TClassEdit::ShortType(GetName(),2); // Drop default allocator from the name.
00042       fRawSymbol.ReplaceAll(":","_");
00043       fRawSymbol.ReplaceAll("<","_");
00044       fRawSymbol.ReplaceAll(">","_");
00045       fRawSymbol.ReplaceAll(",","Cm");
00046       fRawSymbol.ReplaceAll(" ","");
00047       fRawSymbol.ReplaceAll("*","st");
00048       fRawSymbol.ReplaceAll("&","rf");
00049       if (IsClones())
00050          fRawSymbol.Prepend("TClaPx_");
00051       else if (IsSTL()) 
00052          fRawSymbol.Prepend("TStlPx_");
00053       else
00054          fRawSymbol.Prepend("TPx_");
00055       if (fRawSymbol.Length() && fRawSymbol[fRawSymbol.Length()-1]=='.')
00056          fRawSymbol.Remove(fRawSymbol.Length()-1);
00057 
00058       SetName(fRawSymbol);
00059    }
00060 
00061    TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *type,
00062                                                             TVirtualStreamerInfo *info,
00063                                                             const char *branchname,
00064                                                             ELocation isclones,
00065                                                             UInt_t splitlevel,
00066                                                             const TString &containerName) :
00067       TNamed(type,type),
00068       fIsClones(isclones),
00069       fContainerName(containerName),
00070       fIsLeafList(false),
00071       fSplitLevel(splitlevel),
00072       fBranchName(branchname),
00073       fSubBranchPrefix(branchname),
00074       fInfo(info),
00075       fMaxDatamemberType(3)
00076    {
00077       // Constructor.
00078 
00079       R__ASSERT( strcmp(fInfo->GetName(), type)==0 );
00080       NameToSymbol();
00081       if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
00082    }
00083 
00084    TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *branchname) :
00085       TNamed(branchname,branchname),
00086       fIsClones(kOut),
00087       fContainerName(),
00088       fIsLeafList(true),
00089       fSplitLevel(0),
00090       fBranchName(branchname),
00091       fSubBranchPrefix(branchname),
00092       fInfo(0),
00093       fMaxDatamemberType(3)
00094    {
00095       // Constructor for a branch constructed from a leaf list.
00096 
00097       NameToSymbol();
00098       if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
00099    }
00100 
00101    TBranchProxyClassDescriptor::TBranchProxyClassDescriptor(const char *type, TVirtualStreamerInfo *info,
00102                                                             const char *branchname,
00103                                                             const char *branchPrefix, ELocation isclones,
00104                                                             UInt_t splitlevel,
00105                                                             const TString &containerName) :
00106       TNamed(type,type),
00107       fIsClones(isclones),
00108       fContainerName(containerName),
00109       fIsLeafList(true),
00110       fSplitLevel(splitlevel),
00111       fBranchName(branchname),
00112       fSubBranchPrefix(branchPrefix),
00113       fInfo(info),
00114       fMaxDatamemberType(3)
00115    {
00116       // Constructor.
00117 
00118       R__ASSERT( strcmp(fInfo->GetName(), type)==0 );
00119       NameToSymbol();
00120       if (fSubBranchPrefix.Length() && fSubBranchPrefix[fSubBranchPrefix.Length()-1]=='.') fSubBranchPrefix.Remove(fSubBranchPrefix.Length()-1);
00121    }
00122 
00123    const char* TBranchProxyClassDescriptor::GetBranchName() const
00124    {
00125       // Get the branch name
00126       return fBranchName.Data();
00127    }
00128 
00129    const char* TBranchProxyClassDescriptor::GetSubBranchPrefix() const
00130    {
00131       // Get the prefix from the branch name
00132       return fSubBranchPrefix.Data();
00133    }
00134 
00135    const char* TBranchProxyClassDescriptor::GetRawSymbol() const
00136    {
00137       // Get the real symbol name
00138 
00139       return fRawSymbol;
00140    }
00141 
00142    UInt_t TBranchProxyClassDescriptor::GetSplitLevel() const {
00143       // Return the split level of the branch.
00144       return fSplitLevel;
00145    }
00146 
00147    Bool_t TBranchProxyClassDescriptor::IsEquivalent(const TBranchProxyClassDescriptor* other)
00148    {
00149       // Return true if this description is the 'same' as the other decription.
00150 
00151       if ( !other ) return kFALSE;
00152       // Purposely do not test on the name!
00153       if ( strcmp(GetTitle(),other->GetTitle()) ) return kFALSE;
00154       // if ( fBranchName != other->fBranchName ) return kFALSE;
00155       // if ( fSubBranchPrefix != other->fSubBranchPrefix ) return kFALSE;
00156 
00157       if (fIsClones != other->fIsClones) return kFALSE;
00158       if (fIsClones != kOut) {
00159          if (fContainerName != other->fContainerName) return kFALSE;
00160       }
00161 
00162       TBranchProxyDescriptor *desc;
00163       TBranchProxyDescriptor *othdesc;
00164 
00165       if ( fListOfBaseProxies.GetSize() != other->fListOfBaseProxies.GetSize() ) return kFALSE;
00166       TIter next(&fListOfBaseProxies);
00167       TIter othnext(&other->fListOfBaseProxies);
00168       while ( (desc=(TBranchProxyDescriptor*)next()) ) {
00169          othdesc=(TBranchProxyDescriptor*)othnext();
00170          if (!desc->IsEquivalent(othdesc,kTRUE) ) return kFALSE;
00171       }
00172 
00173       if ( fListOfSubProxies.GetSize() != other->fListOfSubProxies.GetSize() ) return kFALSE;
00174       next = &fListOfSubProxies;
00175       othnext = &(other->fListOfSubProxies);
00176 
00177       while ( (desc=(TBranchProxyDescriptor*)next()) ) {
00178          othdesc=(TBranchProxyDescriptor*)othnext();
00179          if (!desc->IsEquivalent(othdesc,kTRUE)) return kFALSE;
00180          if (desc->IsSplit()) {
00181             TString leftname (  desc->GetBranchName() );
00182             TString rightname(  othdesc->GetBranchName() );
00183 
00184             if (leftname.Index(GetBranchName())==0) leftname.Remove( 0,strlen(GetBranchName()));
00185             if (leftname.Length() && leftname[0]=='.') leftname.Remove(0,1);
00186             if (rightname.Index(other->GetBranchName())==0) rightname.Remove(0,strlen(other->GetBranchName()));
00187             if (rightname.Length() && rightname[0]=='.') rightname.Remove(0,1);
00188             if (leftname != rightname ) return kFALSE;
00189          }
00190       }
00191       return true;
00192    }
00193 
00194    void TBranchProxyClassDescriptor::AddDescriptor(TBranchProxyDescriptor *desc, Bool_t isBase)
00195    {
00196       // Add a descriptor to this proxy.
00197 
00198       if (desc) {
00199          if (isBase) {
00200             fListOfBaseProxies.Add(desc);
00201          } else {
00202             fListOfSubProxies.Add(desc);
00203             UInt_t len = strlen(desc->GetTypeName());
00204             if ((len+2)>fMaxDatamemberType) fMaxDatamemberType = len+2;
00205          }
00206       }
00207    }
00208 
00209    Bool_t TBranchProxyClassDescriptor::IsLoaded() const
00210    {
00211       // Return true if the class needed by the branch is loaded
00212       return IsLoaded(GetTitle());
00213    }
00214       
00215    Bool_t TBranchProxyClassDescriptor::IsLoaded(const char *classname)
00216    {
00217       // Return true if the class needed by the branch is loaded
00218       TClass *cl = TClass::GetClass(classname);
00219       while (cl) {
00220          if (cl->IsLoaded()) return kTRUE;
00221          if (!cl->GetCollectionProxy()) return kFALSE;
00222          if (!cl->GetCollectionProxy()->GetValueClass()) return kTRUE; // stl container of simple type are always 'loaded'
00223          cl = cl->GetCollectionProxy()->GetValueClass();
00224       }
00225       return kFALSE;
00226    }
00227 
00228    Bool_t TBranchProxyClassDescriptor::IsClones() const
00229    {
00230       // Return true if this proxy is for a TClonesArray.
00231       return fIsClones==kClones || fIsClones==kInsideClones;
00232    }
00233 
00234    Bool_t TBranchProxyClassDescriptor::IsSTL() const
00235    {
00236       // Return true if this proxy is for a TClonesArray.
00237       return fIsClones==kSTL || fIsClones==kInsideSTL;
00238    }
00239 
00240    TBranchProxyClassDescriptor::ELocation TBranchProxyClassDescriptor::GetIsClones() const
00241    {
00242       // Return whether the branch is inside, nested in or outside of a TClonesArray
00243       return fIsClones;
00244    }
00245 
00246    TString TBranchProxyClassDescriptor::GetContainerName() const
00247    {
00248       // Return the name of the container holding this class, if any.
00249       return fContainerName;
00250    }
00251 
00252    void TBranchProxyClassDescriptor::OutputDecl(FILE *hf, int offset, UInt_t /* maxVarname */)
00253    {
00254       // Output the declaration and implementation of this emulation class
00255 
00256       TBranchProxyDescriptor *desc;
00257 
00258 
00259       // Start the class declaration with the eventual list of base classes
00260       fprintf(hf,"%-*sstruct %s\n", offset," ", GetName() );
00261 
00262       if (fListOfBaseProxies.GetSize()) {
00263          fprintf(hf,"%-*s   : ", offset," ");
00264 
00265          TIter next(&fListOfBaseProxies);
00266 
00267          desc = (TBranchProxyDescriptor*)next();
00268          fprintf(hf,"public %s", desc->GetTypeName());
00269 
00270          while ( (desc = (TBranchProxyDescriptor*)next()) ) {
00271             fprintf(hf,",\n%-*spublic %s", offset+5," ", desc->GetTypeName());
00272          }
00273 
00274          fprintf(hf,"\n");
00275       }
00276       fprintf(hf,"%-*s{\n", offset," ");
00277 
00278 
00279       // Write the constructor
00280       fprintf(hf,"%-*s   %s(TBranchProxyDirector* director,const char *top,const char *mid=0) :",
00281               offset," ", GetName());
00282 
00283       Bool_t wroteFirst = kFALSE;
00284 
00285       if (fListOfBaseProxies.GetSize()) {
00286 
00287          TIter next(&fListOfBaseProxies);
00288 
00289          desc = (TBranchProxyDescriptor*)next();
00290          fprintf(hf,"\n%-*s%-*s(director, top, mid)",  offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
00291          wroteFirst = true;
00292 
00293          while ( (desc = (TBranchProxyDescriptor*)next()) ) {
00294             fprintf(hf,",\n%-*s%-*s(director, top, mid)",  offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
00295          }
00296 
00297       }
00298       fprintf(hf,"%s\n%-*s      %-*s(top,mid)",wroteFirst?",":"",offset," ",fMaxDatamemberType,"ffPrefix");
00299       wroteFirst = true;
00300 
00301       TString objInit = "top, mid";
00302       if ( GetIsClones() == kInsideClones || GetIsClones() == kInsideSTL ) {
00303          if (fListOfSubProxies.GetSize()) {
00304             desc = (TBranchProxyDescriptor*)fListOfSubProxies.At(0);
00305             if (desc && desc->IsSplit()) {
00306 
00307                // In the case of a split sub object is TClonesArray, the
00308                // object itself does not have its own branch, so we need to
00309                // use its first (semantic) sub-branch as a proxy
00310 
00311                TString main = GetBranchName();
00312                TString sub = desc->GetBranchName();
00313                sub.Remove(0,main.Length()+1);
00314 
00315                objInit  = "ffPrefix, ";
00316                objInit += "\"";
00317                objInit += sub;
00318                objInit += "\"";
00319 
00320                objInit = "top, \"\", mid";
00321             }
00322          }
00323       }
00324 
00325       fprintf(hf,"%s\n%-*s      %-*s(director, %s)",
00326               ",",offset," ",fMaxDatamemberType,"obj",objInit.Data());
00327 
00328       TIter next(&fListOfSubProxies);
00329       while ( (desc = (TBranchProxyDescriptor*)next()) ) {
00330          fprintf(hf,",");
00331          desc->OutputInit(hf,offset,fMaxDatamemberType,GetSubBranchPrefix());
00332       }
00333       fprintf(hf,"\n%-*s   {};\n",offset," ");
00334 
00335 
00336       // Write the 2nd constructor
00337       fprintf(hf,"%-*s   %s(TBranchProxyDirector* director, TBranchProxy *parent, const char *membername, const char *top=0, const char *mid=0) :",
00338               offset," ", GetName());
00339 
00340       wroteFirst = kFALSE;
00341 
00342       if (fListOfBaseProxies.GetSize()) {
00343 
00344          TIter nextbase(&fListOfBaseProxies);
00345 
00346          // This is guarantee to return a non zero value due to the if (fListOfBaseProxies.GetSize())
00347          desc = (TBranchProxyDescriptor*)nextbase();
00348          fprintf(hf,"\n%-*s%-*s(director, parent, membername)",  offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
00349          wroteFirst = true;
00350 
00351          while ( (desc = (TBranchProxyDescriptor*)nextbase()) ) {
00352             fprintf(hf,",\n%-*s%-*s(director, parent, membername)",  offset+6, " ", fMaxDatamemberType,desc->GetTypeName());
00353          }
00354 
00355       }
00356       fprintf(hf,"%s\n%-*s      %-*s(top,mid)",wroteFirst?",":"",offset," ",fMaxDatamemberType,"ffPrefix");
00357       wroteFirst = true;
00358 
00359       if ( true ||  IsLoaded() || IsClones() || IsSTL() ) {
00360          fprintf(hf,"%s\n%-*s      %-*s(director, parent, membername)",
00361                  ",",offset," ",fMaxDatamemberType,"obj");
00362       }
00363 
00364       next.Reset();
00365       while ( (desc = (TBranchProxyDescriptor*)next()) ) {
00366          fprintf(hf,",");
00367          desc->OutputInit(hf,offset,fMaxDatamemberType,GetSubBranchPrefix());
00368       }
00369       fprintf(hf,"\n%-*s   {};\n",offset," ");
00370 
00371 
00372       // Declare the data members.
00373       fprintf(hf,"%-*s%-*s %s;\n",  offset+3," ",  fMaxDatamemberType, "TBranchProxyHelper", "ffPrefix");
00374 
00375       // If the real class is available, make it available via the arrow operator:
00376       if (IsLoaded()) {
00377 
00378          const char *type = GetTitle(); /* IsClones() ? "TClonesArray" : GetTitle(); */
00379          fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
00380          //Can the real type contain a leading 'const'? If so the following is incorrect.
00381          if ( IsClones() ) {
00382             fprintf(hf,"%-*sconst %s* operator[](Int_t i) { return obj.At(i); }\n", offset+3," ",type);
00383             fprintf(hf,"%-*sconst %s* operator[](UInt_t i) { return obj.At(i); }\n", offset+3," ",type);
00384             fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
00385             fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
00386             fprintf(hf,"%-*sTClaObjProxy<%s > obj;\n", offset+3, " ", type);
00387          } else if ( IsSTL() ) {
00388             if (fContainerName.Length() && IsLoaded(fContainerName)) {
00389                fprintf(hf,"%-*sconst %s& At(UInt_t i) {\n",offset+3," ",type);
00390                TClass *stlCl = TClass::GetClass(fContainerName);
00391                TClass *cl = TClass::GetClass(GetTitle());
00392                if (cl->GetMethodWithPrototype(cl->GetName(),"TRootIOCtor*")) {  
00393                   fprintf(hf,"%-*s   static %s default_val((TRootIOCtor*)0);\n",offset+3," ",type);
00394                } else {
00395                   fprintf(hf,"%-*s   static %s default_val;\n",offset+3," ",type);
00396                }
00397                fprintf(hf,"%-*s   if (!obj.Read()) return default_val;\n",offset+3," ");
00398                if (stlCl->GetCollectionProxy()->GetValueClass() == cl) {
00399                   fprintf(hf,"%-*s   %s *temp = & obj.GetPtr()->at(i);\n",offset+3," ",type);                  
00400                } else {
00401                   fprintf(hf,"%-*s   %s *temp = (%s *)( obj.GetProxy()->GetStlStart(i) );\n",offset+3," ",type,type);
00402                }
00403                //fprintf(hf,"%-*s   %s *temp = (%s *)( obj.GetPtr()->at(i)) + obj.GetOffset() );\n",offset+3," ",type,type);
00404                   //fprintf(hf,"%-*s   %s *temp = (%s *)(void*)(&obj.At(i));\n",offset+3," ",type,type);
00405                fprintf(hf,"%-*s   if (temp) return *temp; else return default_val;\n",offset+3," ");
00406                fprintf(hf,"%-*s}\n",offset+3," ");
00407 
00408                fprintf(hf,"%-*sconst %s& operator[](Int_t i) { return At(i); }\n", offset+3," ",type);
00409                fprintf(hf,"%-*sconst %s& operator[](UInt_t i) { return At(i); }\n", offset+3," ",type);
00410                fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetPtr()->size(); }\n",offset+3," ");
00411                fprintf(hf,"%-*sconst %s* operator->() { return obj.GetPtr(); }\n", offset+3," ",fContainerName.Data());
00412                fprintf(hf,"%-*soperator %s*() { return obj.GetPtr(); }\n", offset+3," ",fContainerName.Data());
00413                fprintf(hf,"%-*sTObjProxy<%s > obj;\n", offset+3, " ", fContainerName.Data());
00414             } else {
00415                fprintf(hf,"%-*sconst %s& operator[](Int_t i) { return obj.At(i); }\n", offset+3," ",type);
00416                fprintf(hf,"%-*sconst %s& operator[](UInt_t i) { return obj.At(i); }\n", offset+3," ",type);
00417                fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
00418                fprintf(hf,"%-*sTStlObjProxy<%s > obj;\n", offset+3, " ", type);
00419             }
00420          } else {
00421             fprintf(hf,"%-*sconst %s* operator->() { return obj.GetPtr(); }\n", offset+3," ",type);
00422             fprintf(hf,"%-*sTObjProxy<%s > obj;\n", offset+3, " ", type);
00423          }
00424 
00425       } else if ( IsClones()) {
00426 
00427          fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
00428          fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
00429          fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
00430          fprintf(hf,"%-*sTClaProxy obj;\n", offset+3," ");
00431 
00432       } else if ( IsSTL()) {
00433 
00434          fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
00435          fprintf(hf,"%-*sInt_t GetEntries() { return obj.GetEntries(); }\n",offset+3," ");
00436          // fprintf(hf,"%-*sconst TClonesArray* operator->() { return obj.GetPtr(); }\n", offset+3," ");
00437          fprintf(hf,"%-*sTStlProxy obj;\n", offset+3," ");
00438 
00439       } else {
00440 
00441          fprintf(hf,"%-*sInjecTBranchProxyInterface();\n", offset+3," ");
00442          fprintf(hf,"%-*sTBranchProxy obj;\n", offset+3," ");
00443 
00444       }
00445 
00446       fprintf(hf,"\n");
00447 
00448       next.Reset();
00449       while( (desc = ( TBranchProxyDescriptor *)next()) ) {
00450          desc->OutputDecl(hf,offset+3,fMaxDatamemberType);
00451       }
00452       fprintf(hf,"%-*s};\n",offset," ");
00453 
00454       //TBranchProxyDescriptor::OutputDecl(hf,offset,maxVarname);
00455    }
00456 
00457 }

Generated on Tue Jul 5 15:42:57 2011 for ROOT_528-00b_version by  doxygen 1.5.1