TBranchSTL.cxx

Go to the documentation of this file.
00001 // @(#)root/tree:$Id: TBranchSTL.cxx 36169 2010-10-07 16:06:18Z pcanal $
00002 // Author Lukasz Janyst <ljanyst@cern.ch>  23/01/2008
00003 
00004 //////////////////////////////////////////////////////////////////////////
00005 //                                                                      //
00006 // TBranchSTL                                                           //
00007 //                                                                      //
00008 // A Branch handling STL collection of pointers (vectors, lists, queues,//
00009 // sets and multisets) while storing them in split mode                 //
00010 //                                                                      //
00011 //////////////////////////////////////////////////////////////////////////
00012 
00013 
00014 #include "TBranchSTL.h"
00015 #include "TList.h"
00016 #include "TBranchElement.h"
00017 #include "TBasket.h"
00018 #include "TStreamerInfo.h"
00019 #include "TStreamerElement.h"
00020 #include <string>
00021 #include <utility>
00022 
00023 #include "TError.h"
00024 
00025 ClassImp(TBranchSTL)
00026 
00027 //------------------------------------------------------------------------------
00028 TBranchSTL::TBranchSTL():
00029    fCollProxy( 0 ),
00030    fParent( 0 ),
00031    fIndArrayCl( 0 ),
00032    fClassVersion( 0 ),
00033    fClCheckSum( 0 ),
00034    fInfo( 0 ),
00035    fObject( 0 ),
00036    fID( -2 )
00037 {
00038    // Default constructor.
00039 
00040    fIndArrayCl = TClass::GetClass( "TIndArray" );
00041    fBranchVector.reserve( 25 );
00042    fNleaves = 0;
00043    fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00044 }
00045 
00046 //------------------------------------------------------------------------------
00047 TBranchSTL::TBranchSTL( TTree *tree, const char *name,
00048                         TVirtualCollectionProxy *collProxy,
00049                         Int_t buffsize, Int_t splitlevel )
00050 {
00051    // Normal constructor, called from TTree.
00052 
00053    fTree         = tree;
00054    fCollProxy    = collProxy;
00055    fBasketSize   = buffsize;
00056    fSplitLevel   = splitlevel;
00057    fContName     = collProxy->GetCollectionClass()->GetName();
00058    fClCheckSum   = 0;
00059    fClassVersion = 1;
00060    fID           = -2;
00061    fInfo         = 0;
00062    fMother = this;
00063    fParent = 0;
00064    fDirectory = fTree->GetDirectory();
00065    fFileName = "";
00066    SetName( name );
00067    fIndArrayCl = TClass::GetClass( "TIndArray" );
00068    fBranchVector.reserve( 25 );
00069    fNleaves = 0;
00070    fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00071 
00072    //---------------------------------------------------------------------------
00073    // Allocate and initialize the basket control arrays
00074    //---------------------------------------------------------------------------
00075    fBasketBytes = new Int_t[fMaxBaskets];
00076    fBasketEntry = new Long64_t[fMaxBaskets];
00077    fBasketSeek = new Long64_t[fMaxBaskets];
00078 
00079    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00080       fBasketBytes[i] = 0;
00081       fBasketEntry[i] = 0;
00082       fBasketSeek[i] = 0;
00083    }
00084 
00085 }
00086 
00087 //------------------------------------------------------------------------------
00088 TBranchSTL::TBranchSTL( TBranch* parent, const char* name,
00089                         TVirtualCollectionProxy* collProxy,
00090                         Int_t buffsize, Int_t splitlevel,
00091                         TStreamerInfo* info, Int_t id )
00092 {
00093    // Normal constructor, called from another branch.
00094 
00095    fTree         = parent->GetTree();
00096    fCollProxy    = collProxy;
00097    fBasketSize   = buffsize;
00098    fSplitLevel   = splitlevel;
00099    fContName     = collProxy->GetCollectionClass()->GetName();
00100    fClassName    = info->GetClass()->GetName();
00101    fClassVersion = info->GetClassVersion();
00102    fClCheckSum   = info->GetClass()->GetCheckSum();
00103    fInfo         = info;
00104    fID           = id;
00105    fMother = parent->GetMother();
00106    fParent = parent;
00107    fDirectory = fTree->GetDirectory();
00108    fFileName = "";
00109    fNleaves = 0;
00110    fReadLeaves = (ReadLeaves_t)&TBranchSTL::ReadLeavesImpl;
00111 
00112    SetName( name );
00113    fIndArrayCl = TClass::GetClass( "TIndArray" );
00114    fBranchVector.reserve( 25 );
00115 
00116    //---------------------------------------------------------------------------
00117    // Allocate and initialize the basket control arrays
00118    //---------------------------------------------------------------------------
00119    fBasketBytes = new Int_t[fMaxBaskets];
00120    fBasketEntry = new Long64_t[fMaxBaskets];
00121    fBasketSeek = new Long64_t[fMaxBaskets];
00122 
00123    for (Int_t i = 0; i < fMaxBaskets; ++i) {
00124       fBasketBytes[i] = 0;
00125       fBasketEntry[i] = 0;
00126       fBasketSeek[i] = 0;
00127    }
00128 
00129 }
00130 
00131 //------------------------------------------------------------------------------
00132 TBranchSTL::~TBranchSTL()
00133 {
00134    //destructor
00135    BranchMap_t::iterator brIter;
00136    for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter ) {
00137       (*brIter).second.fPointers->clear();
00138       delete (*brIter).second.fPointers;
00139    }
00140 }
00141 
00142 //------------------------------------------------------------------------------
00143 void TBranchSTL::Browse( TBrowser *b )
00144 {
00145    //browse a STL branch
00146    Int_t nbranches = fBranches.GetEntriesFast();
00147    if (nbranches > 0) {
00148       TList persistentBranches;
00149       TBranch* branch=0;
00150       TIter iB(&fBranches);
00151       while( (branch = (TBranch*)iB()) )
00152          persistentBranches.Add(branch);
00153       persistentBranches.Browse( b );
00154    }
00155 }
00156 
00157 //------------------------------------------------------------------------------
00158 Int_t TBranchSTL::Fill()
00159 {
00160    //---------------------------------------------------------------------------
00161    // Cleanup after revious fill
00162    //---------------------------------------------------------------------------
00163    BranchMap_t::iterator brIter;
00164    for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter )
00165       (*brIter).second.fPointers->clear();
00166 
00167    //---------------------------------------------------------------------------
00168    // Check if we're dealing with the null pointer here
00169    //---------------------------------------------------------------------------
00170    if( fAddress != fObject ) {
00171       //------------------------------------------------------------------------
00172       // We have received a zero pointer - treat it as an empty collection
00173       //------------------------------------------------------------------------
00174       if( fObject == 0 ) {
00175          Int_t bytes      = 0;
00176          Int_t totalBytes = 0;
00177 
00178          //---------------------------------------------------------------------
00179          // Store the indices
00180          //---------------------------------------------------------------------
00181          fInd.SetNumItems( 0 );
00182          bytes = TBranch::Fill();
00183 
00184          if( bytes < 0 ) {
00185             Error( "Fill", "The IO error while writing the indices!");
00186             return -1;
00187          }
00188          totalBytes += bytes;
00189 
00190          //---------------------------------------------------------------------
00191          // Store the branches
00192          //---------------------------------------------------------------------
00193          for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00194             TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00195             bytes = br->Fill();
00196             if( bytes < 0 ) {
00197                Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
00198                return -1;
00199             }
00200             totalBytes += bytes;
00201          }
00202          return totalBytes;
00203       }
00204    }
00205 
00206    //---------------------------------------------------------------------------
00207    // Set upt the collection proxy
00208    //---------------------------------------------------------------------------
00209    TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
00210    UInt_t size = fCollProxy->Size();
00211 
00212    //---------------------------------------------------------------------------
00213    // Set up the container of indices
00214    //---------------------------------------------------------------------------
00215    if( fInd.GetCapacity() < size )
00216       fInd.Reserve( size );
00217 
00218    fInd.SetNumItems( size );
00219 
00220    //---------------------------------------------------------------------------
00221    // Loop over the elements and create branches as needed
00222    //---------------------------------------------------------------------------
00223    TClass*               cl         = fCollProxy->GetValueClass();
00224    TClass*               actClass   = 0;
00225    TClass*               vectClass  = 0;
00226    char*                 element    = 0;
00227    std::vector<void*>*   elPointers = 0;
00228    TBranchElement*       elBranch   = 0;
00229    UInt_t                elOffset   = 0;
00230    UChar_t               maxID      = fBranches.GetEntriesFast()+1;
00231    UChar_t               elID;
00232    ElementBranchHelper_t bHelper;
00233    Int_t                 totalBytes = 0;
00234    Int_t                 bytes      = 0;
00235    TString               brName;
00236 
00237    for( UInt_t i = 0; i < size; ++i ) {
00238       //------------------------------------------------------------------------
00239       // Determine the actual class of current element
00240       //------------------------------------------------------------------------
00241       element = *(char**)fCollProxy->At( i );
00242       if( !element ) {
00243          fInd.At(i) = 0;
00244          continue;
00245       }
00246 
00247       // coverity[dereference] since this is a TBranchSTL by definition the collection contains pointers to objects. 
00248       actClass = cl->GetActualClass( element );
00249       brIter = fBranchMap.find( actClass );
00250 
00251       //------------------------------------------------------------------------
00252       // The branch was not found - create a new one
00253       //------------------------------------------------------------------------
00254       if( brIter == fBranchMap.end() ) {
00255          //---------------------------------------------------------------------
00256          // Find the dictionary for vector of pointers to this class
00257          //---------------------------------------------------------------------
00258          std::string vectClName("vector<");
00259          vectClName += actClass->GetName() + std::string("*>");
00260          vectClass = TClass::GetClass( vectClName.c_str() );
00261          if( !vectClass ) {
00262             Warning( "Fill", "Unable to find dictionary for class %s", vectClName.c_str() );
00263             continue;
00264          }
00265 
00266          //---------------------------------------------------------------------
00267          // Create the vector of pointers to objects of this type and new branch
00268          // for it
00269          //---------------------------------------------------------------------
00270          elPointers = new std::vector<void*>();//vectClass->GetCollectionProxy()->New();
00271          brName.Form( "%s.%s", GetName(), actClass->GetName() );
00272          elBranch   = new TBranchElement( this, brName,
00273                                           vectClass->GetCollectionProxy(),
00274                                           fBasketSize, fSplitLevel-1  );
00275          elID = maxID++;
00276          elBranch->SetFirstEntry( fEntryNumber );
00277 
00278 
00279          fBranches.Add( elBranch );
00280 
00281          bHelper.fId         = elID;
00282          bHelper.fBranch     = elBranch;
00283          bHelper.fPointers   = elPointers;
00284          bHelper.fBaseOffset = actClass->GetBaseClassOffset( cl );
00285 
00286          brIter = fBranchMap.insert(std::make_pair(actClass, bHelper ) ).first;
00287          elBranch->SetAddress( &((*brIter).second.fPointers) );
00288       }
00289       //------------------------------------------------------------------------
00290       // The branch for this type already exists - set up the pointers
00291       //------------------------------------------------------------------------
00292       else {
00293          elPointers = (*brIter).second.fPointers;
00294          elBranch   = (*brIter).second.fBranch;
00295          elID       = (*brIter).second.fId;
00296          elOffset   = (*brIter).second.fBaseOffset;
00297       }
00298 
00299       //-------------------------------------------------------------------------
00300       // Add the element to the appropriate vector
00301       //-------------------------------------------------------------------------
00302       elPointers->push_back( element + elOffset );
00303       fInd.At(i) = elID;
00304    }
00305 
00306    //----------------------------------------------------------------------------
00307    // Store the indices
00308    //----------------------------------------------------------------------------
00309    bytes = TBranch::Fill();
00310    if( bytes < 0 ) {
00311       Error( "Fill", "The IO error while writing the indices!");
00312       return -1;
00313    }
00314    totalBytes += bytes;
00315 
00316    //----------------------------------------------------------------------------
00317    // Fill the branches
00318    //----------------------------------------------------------------------------
00319    for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00320       TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00321       bytes = br->Fill();
00322       if( bytes < 0 ) {
00323          Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
00324          return -1;
00325       }
00326       totalBytes += bytes;
00327    }
00328 
00329    return totalBytes;
00330 }
00331 
00332 //------------------------------------------------------------------------------
00333 Int_t TBranchSTL::GetEntry( Long64_t entry, Int_t getall )
00334 {
00335    //---------------------------------------------------------------------------
00336    // Check if we should be doing this at all
00337    //---------------------------------------------------------------------------
00338    if( TestBit( kDoNotProcess ) && !getall )
00339       return 0;
00340 
00341    if ( (entry < fFirstEntry) || (entry >= fEntryNumber) )
00342       return 0;
00343 
00344    if( !fAddress )
00345       return 0;
00346 
00347    //---------------------------------------------------------------------------
00348    // Set up the collection proxy
00349    //---------------------------------------------------------------------------
00350    if( !fCollProxy ) {
00351       TClass *cl = TClass::GetClass( fContName );
00352 
00353       if( !cl ) {
00354          Error( "GetEntry", "Dictionary class not found for: %s", fContName.Data() );
00355          return -1;
00356       }
00357 
00358       fCollProxy = cl->GetCollectionProxy();
00359       if( !fCollProxy ) {
00360          Error( "GetEntry", "No collection proxy!"  );
00361          return -1;
00362       }
00363    }
00364 
00365    //---------------------------------------------------------------------------
00366    // Get the indices
00367    //---------------------------------------------------------------------------
00368    Int_t totalBytes = 0;
00369    Int_t bytes = TBranch::GetEntry( entry, getall );
00370    totalBytes += bytes;
00371 
00372    if( bytes == 0 )
00373       return 0;
00374 
00375    if( bytes < 0 ) {
00376       Error( "GetEntry", "IO error! Unable to get the indices!"  );
00377       return -1;
00378    }
00379 
00380    Int_t size = fInd.GetNumItems();
00381 
00382    //---------------------------------------------------------------------------
00383    // Set up vector pointers
00384    //---------------------------------------------------------------------------
00385    UInt_t nBranches = fBranches.GetEntriesFast();
00386    TClass*               elClass   = fCollProxy->GetValueClass();
00387    TClass*               tmpClass  = 0;
00388 
00389    if( fBranchVector.size() < nBranches )
00390       fBranchVector.resize( nBranches );
00391 
00392    //---------------------------------------------------------------------------
00393    // Create the object
00394    //---------------------------------------------------------------------------
00395    if( fAddress != fObject ) {
00396       *((void **)fAddress) = fCollProxy->New();
00397       fObject = *(char**)fAddress;
00398    }
00399    TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
00400    void* env = fCollProxy->Allocate( size, kTRUE );
00401 
00402    //---------------------------------------------------------------------------
00403    // Process entries
00404    //---------------------------------------------------------------------------
00405    UChar_t             index      = 0;
00406    void**              element    = 0;
00407    std::vector<void*>* elemVect   = 0;
00408    TBranchElement*     elemBranch = 0;
00409 
00410    for( Int_t i = 0; i < size; ++i ) {
00411       element = (void**)fCollProxy->At(i);
00412       index   = fInd.At(i);
00413 
00414       //------------------------------------------------------------------------
00415       // The case of zero pointers
00416       //------------------------------------------------------------------------
00417       if( index == 0 ) {
00418          *element = 0;
00419          continue;
00420       }
00421 
00422       //-------------------------------------------------------------------------
00423       // Index out of range!
00424       //------------------------------------------------------------------------
00425       if( index > nBranches ) {
00426          Error( "GetEntry", "Index %d out of range, unable to find the branch, setting pointer to 0",
00427                 index );
00428          *element = 0;
00429          continue;
00430       }
00431 
00432       //------------------------------------------------------------------------
00433       // Load unloaded branch
00434       //------------------------------------------------------------------------
00435       index--;
00436       elemVect = fBranchVector[index].fPointers;
00437       if( !elemVect ) {
00438          elemBranch = (TBranchElement *)fBranches.UncheckedAt(index);
00439          elemBranch->SetAddress( &(fBranchVector[index].fPointers) );
00440 
00441          bytes = elemBranch->GetEntry( entry, getall );
00442 
00443          if( bytes == 0 ) {
00444             Error( "GetEntry", "No entry for index %d, setting pointer to 0", index );
00445             *element = 0;
00446             fBranchVector[index].fPosition++;
00447             continue;
00448          }
00449 
00450          if( bytes <= 0 ) {
00451             Error( "GetEntry", "I/O error while getting entry for index %d, setting pointer to 0", index );
00452             *element = 0;
00453             fBranchVector[index].fPosition++;
00454             continue;
00455          }
00456          totalBytes += bytes;
00457          elemVect = fBranchVector[index].fPointers;
00458 
00459          //---------------------------------------------------------------------
00460          // Calculate the base class offset
00461          //---------------------------------------------------------------------
00462          TVirtualCollectionProxy *proxy = elemBranch->GetCollectionProxy();
00463          if (!proxy) {
00464             proxy =  TClass::GetClass(elemBranch->GetClassName())->GetCollectionProxy();
00465          }
00466          if (proxy) {
00467             tmpClass = proxy->GetValueClass();
00468             if (tmpClass && elClass) {
00469                fBranchVector[index].fBaseOffset = tmpClass->GetBaseClassOffset( elClass );
00470                fBranchVector[index].fPosition = 0;
00471             } else {
00472                Error("GetEntry","Missing TClass for %s (%s)",elemBranch->GetName(),elemBranch->GetClassName());
00473             }
00474          } else {
00475             Error("GetEntry","Missing CollectionProxy for %s (%s)",elemBranch->GetName(),elemBranch->GetClassName());
00476          }
00477       }
00478 
00479       //------------------------------------------------------------------------
00480       // Set up the element
00481       //------------------------------------------------------------------------
00482       *element =  ((char*)(*elemVect)[fBranchVector[index].fPosition++])
00483         - fBranchVector[index].fBaseOffset;
00484 
00485    }
00486 
00487    fCollProxy->Commit(env);
00488 
00489    //---------------------------------------------------------------------------
00490    // Cleanup
00491    //---------------------------------------------------------------------------
00492    for( UInt_t i = 0; i < fBranchVector.size(); ++i ) {
00493       delete fBranchVector[i].fPointers;
00494       fBranchVector[i].fPointers = 0;
00495    }
00496 
00497    return totalBytes;
00498 }
00499 
00500 //------------------------------------------------------------------------------
00501 TStreamerInfo* TBranchSTL::GetInfo() const
00502 {
00503    //---------------------------------------------------------------------------
00504    // Check if we don't have the streamer info
00505    //---------------------------------------------------------------------------
00506    if( !fInfo ) {
00507       //------------------------------------------------------------------------
00508       // Get the class info
00509       //------------------------------------------------------------------------
00510       TClass *cl = TClass::GetClass( fClassName );
00511 
00512       //------------------------------------------------------------------------
00513       // Get unoptimized streamer info
00514       //------------------------------------------------------------------------
00515       fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
00516 
00517       //------------------------------------------------------------------------
00518       // If the checksum is there and we're dealing with the foreign class
00519       //------------------------------------------------------------------------
00520       if( fClCheckSum && cl->IsForeign() ) {
00521          //---------------------------------------------------------------------
00522          // Loop over the infos
00523          //---------------------------------------------------------------------
00524          Int_t ninfos = cl->GetStreamerInfos()->GetEntriesFast() - 1;
00525          for( Int_t i = -1; i < ninfos; ++i ) {
00526             TVirtualStreamerInfo* info = (TVirtualStreamerInfo*) cl->GetStreamerInfos()->UncheckedAt(i);
00527             if( !info )
00528                continue;
00529 
00530             //------------------------------------------------------------------
00531             // If the checksum matches then retriev the info
00532             //------------------------------------------------------------------
00533             if( info->GetCheckSum() == fClCheckSum ) {
00534                fClassVersion = i;
00535                fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
00536             }
00537          }
00538       }
00539       fInfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00540       fInfo->BuildOld();
00541    }
00542    return fInfo;
00543 }
00544 
00545 //------------------------------------------------------------------------------
00546 Bool_t TBranchSTL::IsFolder() const
00547 {
00548    //branch declared folder if at least one entry
00549 
00550    if( fBranches.GetEntriesFast() >= 1 )
00551       return kTRUE;
00552    return kFALSE;
00553 }
00554 
00555 //------------------------------------------------------------------------------
00556 void TBranchSTL::FillLeaves( TBuffer& b )
00557 {
00558    //TO BE DOCUMENTED
00559 
00560    b.WriteClassBuffer( fIndArrayCl, &fInd );
00561 }
00562 
00563 //------------------------------------------------------------------------------
00564 void TBranchSTL::Print(const char *option) const
00565 {
00566    // Print the branch parameters.
00567 
00568    if (strncmp(option,"debugAddress",strlen("debugAddress"))==0) {
00569       if (strlen(GetName())>24) Printf("%-24s\n%-24s ", GetName(),"");
00570       else Printf("%-24s ", GetName());
00571 
00572       TBranchElement *parent = dynamic_cast<TBranchElement*>(GetMother()->GetSubBranch(this));
00573       Int_t ind = parent ? parent->GetListOfBranches()->IndexOf(this) : -1;
00574       TVirtualStreamerInfo *info = GetInfo();
00575       Int_t *branchOffset = parent ? parent->GetBranchOffset() : 0;
00576 
00577       Printf("%-16s %2d SplitCollPtr %-16s %-16s %8x %-16s n/a\n",
00578              info ? info->GetName() : "StreamerInfo unvailable", fID,
00579              GetClassName(), fParent ? fParent->GetName() : "n/a",
00580              (branchOffset && parent && ind>=0) ? branchOffset[ind] : 0,
00581              fObject);
00582       for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00583          TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00584          br->Print("debugAddressSub");
00585       }
00586    } else if (strncmp(option,"debugInfo",strlen("debugInfo"))==0)  {
00587       Printf("Branch %s uses:\n",GetName());
00588       if (fID>=0) {
00589          ULong_t* elems = GetInfo()->GetElems();
00590          ((TStreamerElement*) elems[fID])->ls();
00591       }
00592       for (Int_t i = 0; i < fBranches.GetEntriesFast(); ++i) {
00593          TBranchElement* subbranch = (TBranchElement*)fBranches.At(i);
00594          subbranch->Print("debugInfoSub");
00595       }
00596       return;
00597    } else {
00598       TBranch::Print(option);
00599       for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
00600          TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
00601          br->Print(option);
00602       }
00603    }
00604 }
00605 
00606 //------------------------------------------------------------------------------
00607 void TBranchSTL::ReadLeavesImpl( TBuffer& b )
00608 {
00609    //TO BE DOCUMENTED
00610 
00611    b.ReadClassBuffer( fIndArrayCl, &fInd );
00612 }
00613 
00614 //------------------------------------------------------------------------------
00615 void TBranchSTL::SetAddress( void* addr )
00616 {
00617    //---------------------------------------------------------------------------
00618    // We are the top level branch
00619    //---------------------------------------------------------------------------
00620    if( fID < 0 ) {
00621       fAddress = (char*)addr;
00622       fObject  = *(char**)addr;
00623    }
00624    //---------------------------------------------------------------------------
00625    // We are a data member of some other class
00626    //---------------------------------------------------------------------------
00627    else {
00628       //------------------------------------------------------------------------
00629       // Get the appropriate streamer element
00630       //------------------------------------------------------------------------
00631       GetInfo();
00632       TStreamerElement *el = (TStreamerElement*)fInfo->GetElements()->At( fID );
00633 
00634       //------------------------------------------------------------------------
00635       // Set up the addresses
00636       //------------------------------------------------------------------------
00637       if( el->IsaPointer() ) {
00638          fAddress = (char*)addr+el->GetOffset();
00639          fObject  = *(char**)fAddress;
00640       } else {
00641          fAddress = (char*)addr+el->GetOffset();
00642          fObject  = (char*)addr+el->GetOffset();
00643       }
00644    }
00645 }

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