#include "TBranchSTL.h"
#include "TList.h"
#include "TBranchElement.h"
#include "TBasket.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include <string>
#include <utility>
ClassImp(TBranchSTL)
TBranchSTL::TBranchSTL():
   fCollProxy( 0 ),
   fParent(0),
   fIndArrayCl( 0 ),
   fInfo( 0 ),
   fObject( 0 ),
   fID( -2 )
{
   
   fIndArrayCl = TClass::GetClass( "TIndArray" );
   fBranchVector.reserve( 25 );
   fNleaves = 0;
}
TBranchSTL::TBranchSTL( TTree *tree, const char *name,
                          TVirtualCollectionProxy *collProxy,
                          Int_t buffsize, Int_t splitlevel )
{
   
   
   fTree         = tree;
   fCollProxy    = collProxy;
   fBasketSize   = buffsize;
   fSplitLevel   = splitlevel;
   fContName     = collProxy->GetCollectionClass()->GetName();
   fClCheckSum   = 0;
   fClassVersion = 1;
   fID           = -2;
   fInfo         = 0;
   fMother = this;
   fParent = 0;
   fDirectory = fTree->GetDirectory();
   fFileName = "";
   SetName( name );
   fIndArrayCl = TClass::GetClass( "TIndArray" );
   fBranchVector.reserve( 25 );
   fNleaves = 0;
   
   
   
   fBasketBytes = new Int_t[fMaxBaskets];
   fBasketEntry = new Long64_t[fMaxBaskets];
   fBasketSeek = new Long64_t[fMaxBaskets]; 
   for (Int_t i = 0; i < fMaxBaskets; ++i) {
      fBasketBytes[i] = 0;
      fBasketEntry[i] = 0;
      fBasketSeek[i] = 0;
   } 
   
   
   
   TBasket* basket = new TBasket(name, fTree->GetName(), this);
   fBaskets.Add(basket);
}
TBranchSTL::TBranchSTL( TBranch* parent, const char* name,
                          TVirtualCollectionProxy* collProxy,
                          Int_t buffsize, Int_t splitlevel,
                          TStreamerInfo* info, Int_t id )
{
   
   
   fTree         = parent->GetTree();
   fCollProxy    = collProxy;
   fBasketSize   = buffsize;
   fSplitLevel   = splitlevel;
   fContName     = collProxy->GetCollectionClass()->GetName();
   fClassName    = info->GetClass()->GetName();
   fClassVersion = info->GetClassVersion();
   fClCheckSum   = info->GetClass()->GetCheckSum();
   fInfo         = info;
   fID           = id;
   fMother = parent ? parent->GetMother() : this;
   fParent = parent;
   fDirectory = fTree->GetDirectory();
   fFileName = "";
   fNleaves = 0;
   SetName( name );
   fIndArrayCl = TClass::GetClass( "TIndArray" );
   fBranchVector.reserve( 25 );
   
   
   
   fBasketBytes = new Int_t[fMaxBaskets];
   fBasketEntry = new Long64_t[fMaxBaskets];
   fBasketSeek = new Long64_t[fMaxBaskets]; 
   for (Int_t i = 0; i < fMaxBaskets; ++i) {
      fBasketBytes[i] = 0;
      fBasketEntry[i] = 0;
      fBasketSeek[i] = 0;
   } 
   
   
   
   TBasket* basket = new TBasket(name, fTree->GetName(), this);
   fBaskets.Add(basket);
}
TBranchSTL::~TBranchSTL()
{
   
   BranchMap_t::iterator brIter;
   for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter ) {
      (*brIter).second.fPointers->clear();
      delete (*brIter).second.fPointers;
   }
}
Int_t TBranchSTL::Fill()
{
   
   
   
   BranchMap_t::iterator brIter;
   for( brIter = fBranchMap.begin(); brIter != fBranchMap.end(); ++brIter )
      (*brIter).second.fPointers->clear();
   
   
   
   if( fAddress != fObject ) {
      
      
      
      if( fObject == 0 ) {
         Int_t bytes      = 0;
         Int_t totalBytes = 0;
         
         
         
         fInd.SetNumItems( 0 );
         bytes = TBranch::Fill();
         if( bytes < 0 ) {
            Error( "Fill", "The IO error while writing the indices!");      
            return -1;
         }
         totalBytes += bytes;
         
         
         
         for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
            TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
            bytes = br->Fill();
            if( bytes < 0 ) {
               Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
               return -1;
            }
            totalBytes += bytes;
         }
         return totalBytes;
      } 
   }
   
   
   
   TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
   UInt_t size = fCollProxy->Size();
   
   
   
   if( fInd.GetCapacity() < size )
      fInd.Reserve( size );
   fInd.SetNumItems( size );
  
   
   
   
   TClass*               cl         = fCollProxy->GetValueClass();
   TClass*               actClass   = 0;
   TClass*               vectClass  = 0;
   char*                 element    = 0;
   std::vector<void*>*   elPointers = 0;
   TBranchElement*       elBranch   = 0;
   UInt_t                elOffset   = 0;
   UChar_t               maxID      = fBranches.GetEntriesFast()+1;
   UChar_t               elID;
   ElementBranchHelper_t bHelper;
   Int_t                 totalBytes = 0;
   Int_t                 bytes      = 0;
   TString               brName;
   for( UInt_t i = 0; i < size; ++i ) {
      
      
      
      element = *(char**)fCollProxy->At( i );
      if( !element )
         fInd.At(i) = 0;
      actClass = cl->GetActualClass( element );
      brIter = fBranchMap.find( actClass );
      
      
      
      if( brIter == fBranchMap.end() ) {
         
         
         
         std::string vectClName("vector<");
         vectClName += actClass->GetName() + std::string("*>");
         vectClass = TClass::GetClass( vectClName.c_str() );
         if( !vectClass ) {
            Warning( "Fill", "Unable to find dictionary for class %s", vectClName.c_str() );
            continue;
         }
         
         
         
         
         elPointers = new std::vector<void*>();
         brName.Form( "%s.%s", GetName(), actClass->GetName() );
         elBranch   = new TBranchElement( this, brName,
                                          vectClass->GetCollectionProxy(),
                                          fBasketSize, fSplitLevel-1  );
         elID = maxID++;
         elBranch->SetFirstEntry( fEntryNumber );
         fBranches.Add( elBranch );
         bHelper.fId         = elID;
         bHelper.fBranch     = elBranch;
         bHelper.fPointers   = elPointers;
         bHelper.fBaseOffset = actClass->GetBaseClassOffset( cl );
         brIter = fBranchMap.insert(std::make_pair(actClass, bHelper ) ).first;
         elBranch->SetAddress( &((*brIter).second.fPointers) );
      }
      
      
      
      else {
         elPointers = (*brIter).second.fPointers;
         elBranch   = (*brIter).second.fBranch;
         elID       = (*brIter).second.fId;
         elOffset   = (*brIter).second.fBaseOffset;
      }
      
      
      
      elPointers->push_back( element + elOffset );
      fInd.At(i) = elID;
   }
   
   
   
   bytes = TBranch::Fill();
   if( bytes < 0 ) {
      Error( "Fill", "The IO error while writing the indices!");      
      return -1;
   }
   totalBytes += bytes;
   
   
   
   for( Int_t i = 0; i < fBranches.GetEntriesFast(); ++i ) {
      TBranch *br = (TBranch *)fBranches.UncheckedAt(i);
      bytes = br->Fill();
      if( bytes < 0 ) {
         Error( "Fill", "The IO error while writing the branch %s!", br->GetName() );
         return -1;
      }
      totalBytes += bytes;
   }
   return totalBytes;
}
Int_t TBranchSTL::GetEntry( Long64_t entry, Int_t getall )
{
   
   
   
   if( TestBit( kDoNotProcess ) && !getall )
      return 0;
   if ( (entry < fFirstEntry) || (entry >= fEntryNumber) )
      return 0;
   
   
   
   if( !fCollProxy ) {
      TClass *cl = TClass::GetClass( fContName );
      if( !cl ) {
         Error( "GetEntry", "Dictionary class not found for: %s", fContName.Data() );
         return -1;
      }
      fCollProxy = cl->GetCollectionProxy();
      if( !fCollProxy ) {
         Error( "GetEntry", "No collection proxy!"  );
         return -1;
      }
   }
   
   
   
   Int_t totalBytes = 0;
   Int_t bytes = TBranch::GetEntry( entry, getall );
   totalBytes += bytes;
   if( bytes == 0 )
      return 0;
   if( bytes < 0 ) {
      Error( "GetEntry", "IO error! Unable to get the indices!"  );
      return -1;
   }
   Int_t size = fInd.GetNumItems();
   
   
   
   UInt_t nBranches = fBranches.GetEntriesFast();
   TClass*               elClass   = fCollProxy->GetValueClass();
   TClass*               tmpClass  = 0;
   if( fBranchVector.size() < nBranches )
      fBranchVector.resize( nBranches );
   
   
   
   if( fAddress != fObject ) {
      *((void **)fAddress) = fCollProxy->New();
      fObject = *(char**)fAddress;
   }
   TVirtualCollectionProxy::TPushPop helper( fCollProxy, fObject );
   fCollProxy->Allocate( size, kTRUE );
   
   
   
   UChar_t             index      = 0;
   void**              element    = 0;
   std::vector<void*>* elemVect   = 0;
   TBranchElement*     elemBranch = 0;
  
   for( Int_t i = 0; i < size; ++i ) {
      element = (void**)fCollProxy->At(i);
      index   = fInd.At(i);
    
      
      
      
      if( index == 0 ) {
         *element = 0;
         continue;
      }
      
      
      
      if( index > nBranches ) {
         Error( "GetEntry", "Index %d out of range, unable to find the branch, setting pointer to 0",
                index );
         *element = 0;
         continue;
      }
      
      
      
      index--;
      elemVect = fBranchVector[index].fPointers;
      if( !elemVect ) {
         elemBranch = (TBranchElement *)fBranches.UncheckedAt(index);
         elemBranch->SetAddress( &(fBranchVector[index].fPointers) );
         bytes = elemBranch->GetEntry( entry, getall );
      
         if( bytes == 0 ) {
            Error( "GetEntry", "No entry for index %d, setting pointer to 0", index );
            *element = 0;
            fBranchVector[index].fPosition++;
            continue;
         }
         if( bytes <= 0 ) {
            Error( "GetEntry", "I/O error while getting entry for index %d, setting pointer to 0", index );
            *element = 0;
            fBranchVector[index].fPosition++;
            continue;
         }
         totalBytes += bytes;
         elemVect = fBranchVector[index].fPointers;
         
         
         
         tmpClass = elemBranch->GetCollectionProxy()->GetValueClass();
         fBranchVector[index].fBaseOffset = tmpClass->GetBaseClassOffset( elClass );
         fBranchVector[index].fPosition = 0;
      }
      
      
      
      *element =  ((char*)(*elemVect)[fBranchVector[index].fPosition++])
        - fBranchVector[index].fBaseOffset;
   }
   
   
   
   for( UInt_t i = 0; i < fBranchVector.size(); ++i ) {
      delete fBranchVector[i].fPointers;
      fBranchVector[i].fPointers = 0;
   }
   return totalBytes;
}
void TBranchSTL::Browse( TBrowser *b )
{
   
   Int_t nbranches = fBranches.GetEntriesFast();
   if (nbranches > 0) {
      TList persistentBranches;
      TBranch* branch=0;
      TIter iB(&fBranches);
      while( (branch = (TBranch*)iB()) )
         persistentBranches.Add(branch);
      persistentBranches.Browse( b );
   }
}
Bool_t TBranchSTL::IsFolder() const
{
   
   
   if( fBranches.GetEntriesFast() >= 1 )
      return kTRUE;
   return kFALSE;
}
void TBranchSTL::FillLeaves( TBuffer& b )
{
      
   
   b.WriteClassBuffer( fIndArrayCl, &fInd );
}
void TBranchSTL::ReadLeaves( TBuffer& b )
{
   
   
   b.ReadClassBuffer( fIndArrayCl, &fInd );
}
void TBranchSTL::SetAddress( void* addr )
{
   
   
   
   if( fID < 0 ) {
      fAddress = (char*)addr;
      fObject  = *(char**)addr;
   }
   
   
   
   else {
      
      
      
      GetInfo();
      TStreamerElement *el = (TStreamerElement*)fInfo->GetElements()->At( fID );
      
      
      
      if( el->IsaPointer() ) {
         fAddress = (char*)addr+el->GetOffset();
         fObject  = *(char**)fAddress;
      } else {
         fAddress = (char*)addr+el->GetOffset();
         fObject  = (char*)addr+el->GetOffset();
      }
   }
}
TStreamerInfo* TBranchSTL::GetInfo()
{
   
   
   
   if( !fInfo ) {
      
      
      
      TClass *cl = TClass::GetClass( fClassName );
      
      
      
      Bool_t optim = TVirtualStreamerInfo::CanOptimize();
      TVirtualStreamerInfo::Optimize( kFALSE );
      fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
      
      
      
      if( fClCheckSum && cl->IsForeign() ) {
         
         
         
         Int_t ninfos = cl->GetStreamerInfos()->GetEntriesFast() - 1;
         for( Int_t i = -1; i < ninfos; ++i ) {
            TVirtualStreamerInfo* info = (TVirtualStreamerInfo*) cl->GetStreamerInfos()->UncheckedAt(i);
            if( !info )
               continue;
            
            
            
            if( info->GetCheckSum() == fClCheckSum ) {
               fClassVersion = i;
               fInfo = (TStreamerInfo*)cl->GetStreamerInfo( fClassVersion );
            }
         }
      }
      TVirtualStreamerInfo::Optimize( optim );
      fInfo->BuildOld();
   }
   return fInfo;
}
Last change: Tue May 13 17:07:09 2008
Last generated: 2008-05-13 17:07
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.