// @(#)root/tree:$Name:  $:$Id: TBranchElement.cxx,v 1.178 2005/08/29 10:57:28 brun Exp $
// Authors Rene Brun , Philippe Canal, Markus Frank  14/01/2001

/*************************************************************************
 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TBranchElement                                                       //
//                                                                      //
// A Branch for the case of an object                                   //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

#include "TROOT.h"
#include "TFile.h"
#include "TBranchElement.h"
#include "TBranchObject.h"
#include "TBranchRef.h"
#include "TClonesArray.h"
#include "TTree.h"
#include "TBasket.h"
#include "TLeafElement.h"
#include "TVirtualPad.h"
#include "TClass.h"
#include "TClassEdit.h"
#include "TDataType.h"
#include "TDataMember.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TBrowser.h"
#include "TFolder.h"
#include "TRealData.h"
#include "Api.h"
#include "TError.h"
#include "TVirtualCollectionProxy.h"

const Int_t kMaxLen = 1024;
R__EXTERN  TTree *gTree;

ClassImp(TBranchElement)

//______________________________________________________________________________
 TBranchElement::TBranchElement(): TBranch(), fCurrentClass(), fParentClass(), fBranchClass()
{
//*-*-*-*-*-*Default constructor for BranchElement*-*-*-*-*-*-*-*-*-*
//*-*        ====================================

   fNleaves       = 1;
   fInfo          = 0;
   fBranchCount   = 0;
   fBranchCount2  = 0;
   fObject        = 0;
   fMaximum       = 0;
   fBranchPointer = 0;
   fNdata         = 1;
   fSTLtype       = TClassEdit::kNotSTL;
   fCollProxy     = 0;
   fCheckSum      = 0;
   fBranchOffset  = 0;
   fBranchTypes   = 0;
   fParentOffset  = 0;
   fInit = fInitOffsets = kFALSE;
}


//______________________________________________________________________________
 TBranchElement::TBranchElement(const char *bname, TStreamerInfo *sinfo, Int_t id, char *pointer, Int_t basketsize, Int_t splitlevel, Int_t btype)
    :TBranch(), fCurrentClass(), fParentClass(), fBranchClass(sinfo->GetClass())
{
// Create a BranchElement
//
// If splitlevel > 0 this branch in turn is split into sub branches

   fCollProxy = 0;
   if (gDebug > 0) {
      printf("BranchElement, bname=%s, sinfo=%s, id=%d, splitlevel=%d\n",bname,sinfo->GetName(),id,splitlevel);
   }
   char name[kMaxLen];
   strcpy(name,bname);

   SetName(name);
   SetTitle(name);

   fSplitLevel   = splitlevel;
   if (id < 0)     splitlevel = 0;

   TClass *cl    = sinfo->GetClass();
   fInfo         = sinfo;
   fCheckSum     = sinfo->GetCheckSum();
   fID           = id;  
   fInit         = kTRUE;
   fStreamerType = -1;
   fType         = 0;
   fBranchCount  = 0;
   fBranchCount2 = 0;
   fObject       = 0;
   fBranchPointer= 0;
   fNdata        = 1;
   fSTLtype      = TClassEdit::kNotSTL;
   fClassVersion = cl->GetClassVersion();
   fTree         = gTree;
   fMaximum      = 0;
   fBranchOffset = 0;
   fParentOffset = 0;
   fBranchTypes  = 0;
   fInitOffsets  = kFALSE;
   ULong_t *elems = sinfo->GetElems();
   TStreamerElement *element = 0;
   TBranchElement *brcount = 0;
   if (id >= 0) {
      element = (TStreamerElement *)elems[id];
      fStreamerType = element->GetType();
      if (fStreamerType == TStreamerInfo::kObject
         || fStreamerType == TStreamerInfo::kBase
         || fStreamerType == TStreamerInfo::kTNamed
         || fStreamerType == TStreamerInfo::kTObject
         || fStreamerType == TStreamerInfo::kObjectp
         || fStreamerType == TStreamerInfo::kObjectP) {
         if (cl->InheritsFrom(TObject::Class())) SetBit(kBranchObject);
      }
      if (element->IsA() == TStreamerBasicPointer::Class()) {
         TStreamerBasicPointer *bp = (TStreamerBasicPointer *)element;
         char countname[kMaxLen];
         strcpy(countname,bname);
         char *dot = strrchr(countname,'.');
         if (dot) *(dot+1) = 0;
         else countname[0] = 0;
         strcat(countname,bp->GetCountName());
         brcount = (TBranchElement *)fTree->GetBranch(countname);
         sprintf(countname,"%s[%s]",name,bp->GetCountName());
         SetTitle(countname);
      }
   } else {
      if (cl->InheritsFrom(TObject::Class())) SetBit(kBranchObject);
   }

   // Set the bit kAutoDelete to specify that when reading
   // the object should be deleted before calling Streamer.
   // It is foreseen to not set this bit in a future version.
   //SetAutoDelete(kTRUE);
   SetAutoDelete(kFALSE);

   fDirectory   = fTree->GetDirectory();
   fFileName    = "";
   fClassName   = sinfo->GetName();
   if (gDebug > 1) printf("Building Branch=%s, class=%s, info=%s, version=%d, id=%d, fStreamerType=%d, btype=%d\n",bname,cl->GetName(),sinfo->GetName(),fClassVersion,id,fStreamerType,btype);
   fCompress = -1;
   if (gTree->GetDirectory()) {
      TFile *bfile = gTree->GetDirectory()->GetFile();
      if (bfile) fCompress = bfile->GetCompressionLevel();
   }
   //change defaults set in TBranch constructor
   fEntryOffsetLen = 0;
   if (btype || fStreamerType <= 0
             || fStreamerType == 7
             || fStreamerType > 15) fEntryOffsetLen = 1000;
   if (basketsize < 100+fEntryOffsetLen) basketsize = 100+fEntryOffsetLen;
   fBasketSize     = basketsize;
   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;
   }

   // Create a basket for the terminal branch
   TBasket *basket = new TBasket(name,fTree->GetName(),this);
   fBaskets.Add(basket);

   // save pointer (if non null). Will be used in Unroll in case we find
   // a TClonesArray in a derived class.
   if (pointer) fBranchPointer = pointer;

   // create sub branches if requested by splitlevel

   if (splitlevel > 0) {
      const char* elem_type = element->GetTypeName();
      fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(elem_type));
      TClass *clm;
      if (element->CannotSplit()) {
         //printf("element: %s/%s will not be split\n",element->GetName(),element->GetTitle());
         fSplitLevel = 0;
      } else if (element->IsA() == TStreamerBase::Class()) {
         // ===> develop the base class
         fType = 1;
         clm = gROOT->GetClass(element->GetName());
         Int_t nbranches = fBranches.GetEntriesFast();
         if (!strcmp(name,clm->GetName())) Unroll("",cl,clm,basketsize,splitlevel,0);
         else                              Unroll(name,clm,clm,basketsize,splitlevel,0);
         if (!strcmp(name,clm->GetName())) return;
         if (strchr(bname,'.')) return;
         if (nbranches == fBranches.GetEntriesFast()) {
            if (strlen(bname)) sprintf(name,"%s.%s",bname,clm->GetName());
            else               sprintf(name,"%s",clm->GetName());
            SetName(name);
            SetTitle(name);
         }
         return;

      } else if (!strcmp(elem_type,"TClonesArray") || !strcmp(elem_type,"TClonesArray*")) {
         Bool_t ispointer = !strcmp(elem_type,"TClonesArray*");
         TClonesArray *clones;
         if (ispointer) {
            char **ppointer = (char**)(pointer);
            clones = (TClonesArray*)(*ppointer);
         } else {
            clones = (TClonesArray*)pointer;
         }
         basket->DeleteEntryOffset(); //entryoffset not required for the clonesarray counter
         fEntryOffsetLen = 0;
         if (!clones) return;
         clm = clones->GetClass();
         if (!clm) return;
         // ===> Create a leafcount
         TLeaf *leaf     = new TLeafElement(name,fID, fStreamerType);
         leaf->SetBranch(this);
         fNleaves = 1;
         fLeaves.Add(leaf);
         fTree->GetListOfLeaves()->Add(leaf);
         // Create a basket for the leafcount
         TBasket *basket2 = new TBasket(name,fTree->GetName(),this);
         fBaskets.Add(basket2);
         // ===> create sub branches for each data member of a TClonesArray
         fType = 3;
         //check that the contained objects class name is part of the element title
         //This name is mandatory when reading the Tree later on and
         //the parent class with the pointer to the TClonesArray is not available.
         //This info will be used by TStreamerInfo::New
         fClonesName = clm->GetName();
         char aname[100];
         sprintf(aname," (%s)",clm->GetName());
         TString atitle = element->GetTitle();
         if (!atitle.Contains(aname)) {
            atitle += aname;
            element->SetTitle(atitle.Data());
         }
         char branchname[kMaxLen];
         sprintf(branchname,"%s_",name);
         SetTitle(branchname);
         leaf->SetName(branchname);
         leaf->SetTitle(branchname);
         Unroll(name,clm,clm,basketsize,splitlevel,31);
         BuildTitle(name);
         return;

      } else if ( (fSTLtype>= TClassEdit::kVector   && fSTLtype<= TClassEdit::kMultiSet) || 
                  (fSTLtype>=-TClassEdit::kMultiSet && fSTLtype<=-TClassEdit::kVector) ) {
         // case of vector<>, list<> deque<>, set<>, multiset<>
         TClass *contCl = gROOT->GetClass(elem_type);
         fCollProxy = contCl->GetCollectionProxy()->Generate();
         clm = fCollProxy->GetValueClass();

         // See if we can split:
         Bool_t cansplit = kTRUE;
         if (clm==0) {
            cansplit = kFALSE;
         } else if (clm==TString::Class() || clm==gROOT->GetClass("string")) {
            cansplit = kFALSE;
         } else if (fCollProxy->HasPointers()) {
            cansplit = kFALSE;
         } else if ( !clm->CanSplit() ) {
            cansplit = kFALSE;
         } else if ( clm->GetCollectionProxy() != 0 ) {
            // A collection was stored in a collection, we do not know how to split it.
            cansplit = kFALSE;
         }

         // ===> Create a leafcount
         if (cansplit) {

            TLeaf *leaf     = new TLeafElement(name,fID, fStreamerType);
            leaf->SetBranch(this);
            fNleaves = 1;
            fLeaves.Add(leaf);
            fTree->GetListOfLeaves()->Add(leaf);
            // Create a basket for the leafcount
            TBasket *basket2 = new TBasket(name,fTree->GetName(),this);
            fBaskets.Add(basket2);

            // ===> create sub branches for each data member of a TClonesArray
            fType = 4;

            //check that the contained objects class name is part of the element title
            //This name is mandatory when reading the Tree later on and
            //the parent class with the pointer to the TClonesArray is not available.
            //This info will be used by TStreamerInfo::New
            fClonesName = clm->GetName();
            char aname[100];
            sprintf(aname," (%s)",clm->GetName());
            TString atitle = element->GetTitle();
            if (!atitle.Contains(aname)) {
               atitle += aname;
               element->SetTitle(atitle.Data());
            }
            char branchname[kMaxLen];
            sprintf(branchname,"%s_",name);
            SetTitle(branchname);
            leaf->SetName(branchname);
            leaf->SetTitle(branchname);
            Unroll(name,clm,clm,basketsize,splitlevel,41);
            BuildTitle(name);
            return;
         }

      } else if (!strchr(elem_type,'*') &&
                 (fStreamerType == TStreamerInfo::kObject || fStreamerType == TStreamerInfo::kAny)) {
         // ===> create sub branches for members that are classes
         fType = 2;
         clm = gROOT->GetClass(elem_type);
         if (Unroll(name,clm,clm,basketsize,splitlevel,0) >= 0) return;

      }
   }

   TLeaf *leaf = new TLeafElement(GetTitle(),fID, fStreamerType);
   leaf->SetTitle(GetTitle());
   leaf->SetBranch(this);
   fNleaves = 1;
   fLeaves.Add(leaf);
   gTree->GetListOfLeaves()->Add(leaf);
   if (brcount) SetBranchCount(brcount);
}

//______________________________________________________________________________
 TBranchElement::TBranchElement(const char *bname, TClonesArray *clones, Int_t basketsize, Int_t splitlevel, Int_t compress)
    :TBranch(), fInfo(TClonesArray::Class()->GetStreamerInfo()), 
     fCurrentClass(),fParentClass(), fBranchClass(fInfo->GetClass())
{
// Create a BranchElement
//
// If splitlevel > 0 this branch in turn is split into sub branches

   fCollProxy = 0;
   fSplitLevel    = splitlevel;
   fID            = 0;
   fInit          = kTRUE;
   fStreamerType  = -1;
   fType          = 0;
   fClassVersion  = TClonesArray::Class()->GetClassVersion();
   fCheckSum      = fInfo->GetCheckSum();
   fBranchCount   = 0;
   fBranchCount2  = 0;
   fObject        = 0;
   fBranchPointer = 0;
   fMaximum       = 0;
   fBranchOffset  = 0;
   fParentOffset  = 0;
   fBranchTypes   = 0;
   fSTLtype       = TClassEdit::kNotSTL;
   fInitOffsets   = kFALSE;

   fTree          = gTree;
   fDirectory     = fTree->GetDirectory();
   fFileName      = "";

   SetName(bname);
   const char* name = GetName();
   SetTitle(name);
   fClassName = fInfo->GetName();
   fCompress = compress;
   if (compress == -1 && fTree->GetDirectory()) {
      TFile *bfile = fTree->GetDirectory()->GetFile();
      if (bfile) fCompress = bfile->GetCompressionLevel();
   }

   if (basketsize < 100) basketsize = 100;
   fBasketSize     = basketsize;
   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;
   }

   // Create a basket for the terminal branch
   TBasket *basket = new TBasket(name,fTree->GetName(),this);
   fBaskets.Add(basket);

   // Set the bit kAutoDelete to specify that when reading
   // the object should be deleted before calling Streamer.
   // It is foreseen to not set this bit in a future version.
   //SetAutoDelete(kTRUE);
   SetAutoDelete(kFALSE);


   // create sub branches if requested by splitlevel
   if (splitlevel > 0) {
      // ===> Create a leafcount
      TLeaf *leaf     = new TLeafElement(name,fID, fStreamerType);
      leaf->SetBranch(this);
      fNleaves = 1;
      fLeaves.Add(leaf);
      fTree->GetListOfLeaves()->Add(leaf);
      // Create a basket for the leafcount
      TBasket *basket = new TBasket(name,fTree->GetName(),this);
      fBaskets.Add(basket);
      // ===> create sub branches for each data member of a TClonesArray
      fType = 3;
      TClass *clm = clones->GetClass();
      if (!clm) return;
      fClonesName = clm->GetName();
      std::string branchname = name + std::string("_");
      SetTitle(branchname.c_str());
      leaf->SetName(branchname.c_str());
      leaf->SetTitle(branchname.c_str());
      Unroll(name,clm,clm,basketsize,splitlevel,31);
      BuildTitle(name);
      return;
   }

   SetBit(kBranchObject);

   TLeaf *leaf     = new TLeafElement(GetTitle(),fID, fStreamerType);
   leaf->SetTitle(GetTitle());
   leaf->SetBranch(this);
   fNleaves = 1;
   fLeaves.Add(leaf);
   gTree->GetListOfLeaves()->Add(leaf);
}
//______________________________________________________________________________
 TBranchElement::TBranchElement(const char *bname, TVirtualCollectionProxy *cont, Int_t basketsize, Int_t splitlevel, Int_t compress)
  : TBranch(),fCurrentClass(),fParentClass(), fBranchClass(cont->GetCollectionClass())
{
   // Create a BranchElement
   //
   // If splitlevel > 0 this branch in turn is split into sub branches

   fCollProxy = cont->Generate();
   char name[kMaxLen];
   strcpy(name,bname);
   if (name[strlen(name)-1]=='.') name[strlen(name)-1]=0;
   fInitOffsets   = kFALSE;
   fSplitLevel    = splitlevel;
   fInfo          = 0;
   fID            = -1;
   fInit          = kTRUE;
   fStreamerType  = -1; // TStreamerInfo::kSTLp;
   fType          = 0;
   fClassVersion  = cont->GetCollectionClass()->GetClassVersion();
   fBranchCount   = 0;
   fBranchCount2  = 0;
   fObject        = 0;
   fBranchPointer = 0;
   fMaximum       = 0;
   fBranchOffset  = 0;
   fParentOffset  = 0;
   fBranchTypes   = 0;
   fSTLtype       = TClassEdit::kNotSTL;

   fTree          = gTree;
   fDirectory     = fTree->GetDirectory();
   fFileName      = "";

   SetName(name);
   SetTitle(name);
   //Bool_t Implemented=kFALSE;
   //Assert(Implemented);
   fClassName    = fBranchClass->GetName();
   fCompress = compress;
   if (compress == -1 && fTree->GetDirectory()) {
      TFile *bfile = fTree->GetDirectory()->GetFile();
      if (bfile) fCompress = bfile->GetCompressionLevel();
   }

   if (basketsize < 100) basketsize = 100;
   fBasketSize     = basketsize;
   fBasketBytes    = new Int_t[fMaxBaskets];
   fBasketEntry    = new Long64_t[fMaxBaskets];
   fBasketSeek     = new Long64_t[fMaxBaskets];

   fBasketEntry[0] = fEntryNumber;
   fBasketBytes[0] = 0;

   // Create a basket for the terminal branch
   TBasket *basket = new TBasket(name,fTree->GetName(),this);
   fBaskets.Add(basket);

   // Set the bit kAutoDelete to specify that when reading
   // the object should be deleted before calling Streamer.
   // It is foreseen to not set this bit in a future version.
   //SetAutoDelete(kTRUE);
   SetAutoDelete(kFALSE);


   // create sub branches if requested by splitlevel
   if (splitlevel > 0 && fBranchClass->CanSplit()) {
      // ===> Create a leafcount
      TLeaf *leaf     = new TLeafElement(name,fID, fStreamerType);
      leaf->SetBranch(this);
      fNleaves = 1;
      fLeaves.Add(leaf);
      fTree->GetListOfLeaves()->Add(leaf);
      // Create a basket for the leafcount
      TBasket *basket = new TBasket(name,fTree->GetName(),this);
      fBaskets.Add(basket);
      // ===> create sub branches for each data member of a TSTLCont
      fType = 4;
      TClass *clm = cont->GetValueClass();
      if (!clm) return;
      fClonesName = clm->GetName();
      char branchname[kMaxLen];
      sprintf(branchname,"%s_",name);
      SetTitle(branchname);
      leaf->SetName(branchname);
      leaf->SetTitle(branchname);
      Unroll(name,clm,clm,basketsize,splitlevel,41);
      BuildTitle(name);
      return;
   }

   TLeaf *leaf     = new TLeafElement(GetTitle(),fID, fStreamerType);
   leaf->SetTitle(GetTitle());
   leaf->SetBranch(this);
   fNleaves = 1;
   fLeaves.Add(leaf);
   gTree->GetListOfLeaves()->Add(leaf);
}

//______________________________________________________________________________
 TBranchElement::~TBranchElement()
{
//*-*-*-*-*-*Default destructor for a BranchElement*-*-*-*-*-*-*-*-*-*-*-*
//*-*        =====================================

   if ( fType==4      ) delete fCollProxy;
   if ( fBranchOffset ) delete [] fBranchOffset;
   if ( fBranchTypes  ) delete [] fBranchTypes;

   fCollProxy=0;
   fBranches.Delete();

   //SetAddress may have allocated an object. Must delete it
   if (TestBit(kDeleteObject)) {
      if (fObject) {
         //TObject *obj = (TObject*)fObject;
         // objects of emulated classes allocated in SetAddress should be deleted
         //printf("deleting fObject=%x of class: %s, branch: %s, fAddress=%x\n",obj,fClassName.Data(),GetName(),fAddress);
         //delete obj;
      }
   }
}

//______________________________________________________________________________
 TBranch *TBranchElement::Branch(const char *subname, void *address, const char *leaflist,Int_t bufsize)
{
//  Create a sub-branch of this branch (simple variable case)
//  ==================================
//
//     This Branch constructor is provided to support non-objects in
//     a Tree. The variables described in leaflist may be simple variables
//     or structures.
//    See the two following constructors for writing objects in a Tree.
//
//    By default the branch buffers are stored in the same file as the Tree.
//    use TBranch::SetFile to specify a different file

   gTree = fTree;
   std::string name(GetName()+std::string(".")+subname);
   TBranch *branch = new TBranch(name.c_str(),address,leaflist,bufsize);
   if (branch->IsZombie()) {
      delete branch;
      return 0;
   }
   TLeaf *leaf;
   TIter next(branch->GetListOfLeaves());
   while ((leaf = (TLeaf*)next())) {
      std::string name(GetName()+std::string(".")+leaf->GetName());
      leaf->SetName(name.c_str());
   }
   fBranches.Add(branch);
   return branch;
}


//______________________________________________________________________________
 Int_t TBranchElement::Branch(const char *foldername, Int_t bufsize, Int_t splitlevel)
{
//   This function creates one sub-branch for each element in the folder.
//   The function returns the total number of branches created.

   TObject *ob = gROOT->FindObjectAny(foldername);
   if (!ob) return 0;
   if (ob->IsA() != TFolder::Class()) return 0;
   Int_t nbranches = GetListOfBranches()->GetEntries();
   TFolder *folder = (TFolder*)ob;
   TIter next(folder->GetListOfFolders());
   TObject *obj;
   char occur[20];
   while ((obj=next())) {
      std::string curname(foldername+std::string("/")+obj->GetName());
      if (obj->IsA() == TFolder::Class()) {
        Branch(curname.c_str(), bufsize, splitlevel-1);
      } else {
        void *add = (void*)folder->GetListOfFolders()->GetObjectRef(obj);
        for (size_t i=curname.find('/'); i != std::string::npos; i=curname.find('/')) {
           curname[i] = '.';
        }
        Int_t noccur = folder->Occurence(obj);
        if (noccur > 0) {
           sprintf(occur,"_%d",noccur);
           curname += occur;
        }
        TBranchElement *br;
        br = (TBranchElement*)Branch(curname.c_str(),obj->ClassName(), add, bufsize, splitlevel-1);
        br->SetBranchFolder();
      }
   }
   return GetListOfBranches()->GetEntries() - nbranches;
}


//______________________________________________________________________________
 TBranch *TBranchElement::Branch(const char *subname, const char *classname, void *add, Int_t bufsize, Int_t splitlevel)
{
//  Create a sub-branch of this branch (with a class)
//  ==================================
//
//    Build a TBranchElement for an object of class classname.
//    addobj is the address of a pointer to an object of class classname.
//    The class dictionary must be available (ClassDef in class header).
//
//    This option requires access to the library where the corresponding class
//    is defined. Accessing one single data member in the object implies
//    reading the full object.
//
//    By default the branch buffers are stored in the same file as the parent branch.
//    use TBranch::SetFile to specify a different file
//
//    see IMPORTANT NOTE about branch names in TTree::Bronch
//
//   Use splitlevel < 0 instead of splitlevel=0 when the class
//   has a custom Streamer

   gTree = fTree;
   TClass *cl = gROOT->GetClass(classname);
   if (!cl) {
      Error("Branch","Cannot find class:%s",classname);
      return 0;
   }

   //if splitlevel <= 0 and class has a custom Streamer, we must create
   //a TBranchObject. We cannot assume that TClass::ReadBuffer is consistent
   //with the custom Streamer. The penalty is that one cannot process
   //this Tree without the class library containing the class.
   //The following convention is used for the RootFlag
   // #pragma link C++ class TExMap;     rootflag = 0
   // #pragma link C++ class TList-;     rootflag = 1
   // #pragma link C++ class TArray!;    rootflag = 2
   // #pragma link C++ class TArrayC-!;  rootflag = 3
   // #pragma link C++ class TBits+;     rootflag = 4
   // #pragma link C++ class Txxxx+!;    rootflag = 6

   char **ppointer = (char**)add;
   char *objadd = *ppointer;
   std::string name(GetName()+std::string(".")+subname);
   if (cl == TClonesArray::Class()) {
      TClonesArray *clones = (TClonesArray *)objadd;
      if (!clones) {
         Error("Branch","Pointer to TClonesArray is null");
         return 0;
      }
      if (!clones->GetClass()) {
         Error("Branch","TClonesArray with no class defined in branch: %s",name.c_str());
         return 0;
      }
      G__ClassInfo *classinfo = clones->GetClass()->GetClassInfo();
      if (!classinfo) {
         Error("Bronch","TClonesArray with no dictionary defined in branch: %s",name.c_str());
         return 0;
      }
      if (splitlevel > 0) {
         if (classinfo->RootFlag() & 1)
            Warning("Branch","Using split mode on a class: %s with a custom Streamer",clones->GetClass()->GetName());
      } else {
         if (classinfo->RootFlag() & 1) clones->BypassStreamer(kFALSE);
         TBranchObject *branch = new TBranchObject(name.c_str(),classname,add,bufsize,0);
         fBranches.Add(branch);
         return branch;
      }
   }

   Bool_t hasCustomStreamer = kFALSE;
   if (!cl->GetClassInfo()) {
      Error("Branch","Cannot find dictionary for class: %s",classname);
      return 0;
   }
   if (cl->GetClassInfo()->RootFlag() & 1)  hasCustomStreamer = kTRUE;
   if (splitlevel < 0 || (splitlevel == 0 && hasCustomStreamer)) {
      TBranchObject *branch = new TBranchObject(name.c_str(),classname,add,bufsize,0);
      fBranches.Add(branch);
      return branch;
   }

   //hopefully normal case
   Bool_t delobj = kFALSE;
   //====> special case of TClonesArray
   if(cl == TClonesArray::Class()) {
      TBranchElement *branch = new TBranchElement(name.c_str(),(TClonesArray*)objadd,bufsize,splitlevel);
      fBranches.Add(branch);
      branch->SetAddress(add);
      return branch;
   }
   //====>

   if (!objadd) {
      objadd = (char*)cl->New();
      *ppointer = objadd;
      delobj = kTRUE;
   }
   //build the StreamerInfo if first time for the class
   Bool_t optim = TStreamerInfo::CanOptimize();
   if (splitlevel > 0) TStreamerInfo::Optimize(kFALSE);
   TStreamerInfo *sinfo = fTree->BuildStreamerInfo(cl,objadd);
   TStreamerInfo::Optimize(optim);

   // create a dummy top level  branch object
   Int_t id = -1;
   if (splitlevel > 0) id = -2;
   size_t dot = name.find('.');
   size_t nch = name.length();
   Bool_t dotlast = kFALSE;
   if (nch && name[nch-1] == '.') dotlast = kTRUE;
   TBranchElement *branch = new TBranchElement(name.c_str(),sinfo,id,objadd,bufsize,splitlevel);
   fBranches.Add(branch);
   if (splitlevel > 0) {
      // Loop on all public data members of the class and its base classes
      TObjArray *blist = branch->GetListOfBranches();
      TIter next(sinfo->GetElements());
      TStreamerElement *element;
      id = 0;
      while ((element = (TStreamerElement*)next())) {
         std::string bname(name);
         char *pointer = (char*)objadd + element->GetOffset();
         Bool_t isBase = element->IsA() == TStreamerBase::Class();
         if (isBase) {
            TClass *clbase = element->GetClassPointer();
            if (clbase == TObject::Class() && cl->CanIgnoreTObjectStreamer()) continue;
         }
         if ( dot != std::string::npos ) {
            if (dotlast) {
               bname += element->GetFullName();
            } else if ( !isBase) {
               bname += ".";
               bname += element->GetFullName();
            }
         } else {
            bname = element->GetFullName();
         }
         TBranchElement *bre = new TBranchElement(bname.c_str(),sinfo,id,pointer,bufsize,splitlevel-1);
         blist->Add(bre);
         id++;
      }
   }
   branch->SetAddress(add);

   if (delobj) {delete objadd; *ppointer=0;}
   return branch;
}


//______________________________________________________________________________
 void TBranchElement::Browse(TBrowser *b)
{
   Int_t nbranches = fBranches.GetEntriesFast();
   if (nbranches > 0) {
      TList persistentBranches;
      TBranch* branch=0;
      TIter iB(&fBranches);
      while((branch=(TBranch*)iB())) {
         if (branch->IsFolder()) persistentBranches.Add(branch);
         else {
            // only show branches corresponding to persistent members
            TClass* cl=0;
            if (strlen(GetClonesName()))
               // this works both for top level branches and for sub-branches,
               // as GetClonesName() is properly updated for sub-branches
               cl=gROOT->GetClass(GetClonesName());
            else {
               cl=gROOT->GetClass(GetClassName());
               
               // check if we're in a sub-branch of this class
               // we can only find out asking the streamer given our ID
               ULong_t *elems=0;
               TStreamerElement *element=0;
               TClass* clsub=0;
               if (fID>=0 && GetInfo() 
                   && ((elems=GetInfo()->GetElems()))
                   && ((element=(TStreamerElement *)elems[fID]))
                   && ((clsub=element->GetClassPointer())))
                  cl=clsub;
            }
            if (cl) {
               TString strMember=branch->GetName();
               Size_t mempos=strMember.Last('.');
               if (mempos!=kNPOS)
                  strMember.Remove(0, (Int_t)mempos+1);
               mempos=strMember.First('[');
               if (mempos!=kNPOS)
                  strMember.Remove((Int_t)mempos);
               TDataMember* m=cl->GetDataMember(strMember);
               if (!m || m->IsPersistent()) persistentBranches.Add(branch);
            } else persistentBranches.Add(branch);
         } // branch if not a folder
      }
      persistentBranches.Browse(b);      
      // add all public const methods without params
      if (GetBrowsables() && GetBrowsables()->GetSize())
         GetBrowsables()->Browse(b);
   } else {
      if (GetBrowsables() && GetBrowsables()->GetSize()) {
         GetBrowsables()->Browse(b);
         return;
      }
      // Get the name and strip any extra brackets
      // in order to get the full arrays.
      TString slash("/"), escapedSlash("\\/");
      TString name = GetName();
      Int_t pos = name.First('[');
      if (pos!=kNPOS) name.Remove(pos);

      TString mothername;
      if (GetMother()) {
         mothername = GetMother()->GetName();
         pos = mothername.First('[');
         if (pos!=kNPOS) mothername.Remove(pos);

         Int_t len = mothername.Length();
         if (len) {
            if (mothername(len-1)!='.') {
               // We do not know for sure whether the mother's name is
               // already preprended.  So we need to check:
               //    a) it is prepended
               //    b) it is NOT the name of a daugher (i.e. mothername.mothername exist)
               TString doublename = mothername;
               doublename.Append(".");
               Int_t isthere = (name.Index(doublename)==0);
               if (!isthere) {
                  name.Prepend(doublename);
               } else {
                  if (GetMother()->FindBranch(mothername)) {
                     doublename.Append(mothername);
                     isthere = (name.Index(doublename)==0);
                     if (!isthere) {
                        mothername.Append(".");
                        name.Prepend(mothername);
                     }
                  } else {
                     // Nothing to do because the mother's name is
                     // already in the name.
                  }
               }
            } else {
               // If the mother's name end with a dot then
               // the daughter probably already contains the mother's name
               if (name.Index(mothername)==kNPOS) {
                  name.Prepend(mothername);
               }
            }
         }
      }
      name.ReplaceAll(slash, escapedSlash);
      GetTree()->Draw(name, "", b ? b->GetDrawOption() : "");
      if (gPad) gPad->Update();
   }
}


//______________________________________________________________________________
 void TBranchElement::BuildTitle(const char *name)
{
   //set branch/leaf name/title in case of a TClonesArray sub-branch

   char branchname[kMaxLen];
   Int_t nbranches = fBranches.GetEntries();
   for (Int_t i=0;i<nbranches;i++) {
      TBranchElement *bre = (TBranchElement*)fBranches.At(i);
      Assert(fType==3 || fType==4 );
      bre->SetType(fType*10+1);
      bre->fCollProxy = GetCollectionProxy();
      bre->BuildTitle(name);
      const char *fin = strrchr(bre->GetTitle(),'.');
      if (fin == 0) continue;
      bre->SetBranchCount(this); //primary branchcount
      TLeafElement *lf = (TLeafElement*)bre->GetListOfLeaves()->At(0);
      //if branch name is of the form fTracks.fCovar[3][4]
      //set the title to fCovar[fTracks_]

      strcpy(branchname,fin+1);
      char *dim = (char*)strstr(branchname,"[");
      Int_t nch = strlen(branchname);
      if (dim) {
         *dim = 0;
         nch = dim-branchname;
      }
      sprintf(branchname+nch,"[%s_]",name);

      bre->SetTitle(branchname);
      if (lf) lf->SetTitle(branchname);

      // is there a secondary branchcount ?
      //fBranchCount2 points to the secondary branchcount
      //in case a TClonesArray element has itself a branchcount.
      //Example in Event class with TClonesArray fTracks of Track objects.
      //if the Track object has two members
      //  Int_t    fNpoint;
      //  Float_t *fPoints;  //[fNpoint]
      //In this case the TBranchElement fTracks.fPoints has
      // -its primary branchcount pointing to the branch fTracks
      // -its secondary branchcount pointing to fTracks.fNpoint
      Int_t stype = bre->GetStreamerType();
      if (stype > 40 && stype < 55) {
         char name2[kMaxLen];
         strcpy(name2,bre->GetName());
         char *bn = strrchr(name2,'.');
         if (!bn) continue;
         TStreamerBasicPointer *el = (TStreamerBasicPointer*)bre->GetInfo()->GetElements()->FindObject(bn+1);
         strcpy(bn+1,el->GetCountName());
         TBranchElement *bc2 = (TBranchElement*)fBranches.FindObject(name2);
         bre->SetBranchCount2(bc2);
         //printf("Branch:%s has a secondary branchcount, bc2=%s\n",bre->GetName(),bc2->GetName());
      }
   }
}


//______________________________________________________________________________
 Int_t TBranchElement::Fill()
{
//*-*-*-*-*-*-*-*Loop on all leaves of this branch to fill Basket buffer*-*-*
//*-*            =======================================================
//
// The function returns the number of bytes committed to the 
// individual branch(es).
// If a write error occurs, the number of bytes returned is -1.
// If no data are written, because e.g. the branch is disabled,
// the number of bytes returned is 0.
//

   Int_t nbytes = 0, nwrite = 0, nerror = 0;
   Int_t nbranches = fBranches.GetEntriesFast();
   // update addresses if top level branch
   if (fID < 0) {
      if (!fAddress) {
         Error("Fill","attempt to fill branch %s while addresss is not set",GetName());
         return 0;
      }
      void *add1  = fObject;
      void **add2 = (void**)fAddress;
      if (add1 != *add2) {
         SetAddress(fAddress);
      }

   }

   //if the tree has a TRefTable, set the current branch if branch is not a basic type
   if (fType > 0 && fType < 10) {
      TBranchRef *bref = fTree->GetBranchRef();
      if (bref) bref->SetParent(this);
   }

   if (nbranches) {
     if (fType == 3 || fType == 4)  {
       nbytes += (nwrite = TBranch::Fill());  //TClonesArray counter
       if ( nwrite < 0 )  {
         Error("Fill","Failed filling branch:%s, nbytes=%d",GetName(),nwrite);
         nerror++;
       }
     }
     else  {
       fEntries++;
     }
     for (Int_t i=0;i<nbranches;i++)  {
        TBranchElement *branch = (TBranchElement*)fBranches[i];
        if (!branch->TestBit(kDoNotProcess))  {
          nbytes += (nwrite = branch->Fill());
          if ( nwrite < 0 )  {
            Error("Fill","Failed filling branch:%s.%s, nbytes=%d",GetName(),branch->GetName(),nwrite);
            nerror++;
          }
        }
     }
   } else {
     if (!TestBit(kDoNotProcess)) {
       nbytes += (nwrite = TBranch::Fill());
       if ( nwrite < 0 )  {
         Error("Fill","Failed filling branch:%s, nbytes=%d",GetName(),nwrite);
         nerror++;
       }
     }
   }
   if (fTree->Debug() > 0) {
      Long64_t entry = fEntries;
      if (entry >= fTree->GetDebugMin() && entry <= fTree->GetDebugMax()) {
         printf("Fill: %lld, branch=%s, nbytes=%d\n",entry,GetName(),nbytes);
      }
   }
   return nerror==0 ? nbytes : -1;
}

//______________________________________________________________________________
 void TBranchElement::FillLeaves(TBuffer &b)
{
//  Fill buffers of this branch

  if (!fObject) return;
  if (fType <= 2 && TestBit(kBranchObject)) b.MapObject((TObject*)fObject);

  if (fType == 4) {           // STL vector/list of objects
     if (!fObject) {
        b << 0;
     } else {
        TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(),fObject);
        Int_t n = fCollProxy->Size();
        if (n > fMaximum) fMaximum = n;
        b << n;
     }
  } else if (fType == 41) {   // sub branch of an STL class

     //char **ppointer = (char**)fAddress;
     if (!fObject) return;
     TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(),fObject);// NOTE: this wont work if a pointer to vector is split!
     Int_t n = fCollProxy->Size();
     fInfo->WriteBufferSTL(b,fCollProxy,n,fID,fOffset);

  } else if (fType == 3) {   //top level branch of a TClonesArray
     if (fTree->GetMakeClass()) {
        TClass *cl = gROOT->GetClass(GetClonesName());
        cl->GetStreamerInfo()->ForceWriteInfo((TFile *)b.GetParent());
        Int_t *n = (Int_t*)fAddress;
        b << *n;
        return;
     }
     TClonesArray *clones = (TClonesArray*)fObject;
     if (!clones) {
        b << 0;
     } else {
        Int_t n = clones->GetEntriesFast();
        if (n > fMaximum) fMaximum = n;
        b << n;
     }
  } else if (fType == 31) {   // sub branch of a TClonesArray
     if (fTree->GetMakeClass()) {
        Int_t atype = fStreamerType;
        if (atype > 54) return;
        if (!fAddress) return;
        Int_t *nn = (Int_t*)fBranchCount->GetAddress();
        Int_t n = *nn;
        if (atype>40) {
           printf("Clonesa: %s, n=%d, sorry not supported yet\n",GetName(),n);
        }
        if (atype > 20) {
           atype -= 20;
           TLeafElement *leaf = (TLeafElement*)fLeaves.UncheckedAt(0);
           n *= leaf->GetLenStatic();
        }
        switch (atype) {
          case  1:  {b.WriteFastArray((Char_t*)   fAddress, n); break;}
          case  2:  {b.WriteFastArray((Short_t*)  fAddress, n); break;}
          case  3:  {b.WriteFastArray((Int_t*)    fAddress, n); break;}
          case  4:  {b.WriteFastArray((Long_t*)   fAddress, n); break;}
          case  5:  {b.WriteFastArray((Float_t*)  fAddress, n); break;}
          case  6:  {b.WriteFastArray((Int_t*)    fAddress, n); break;}
          case  8:  {b.WriteFastArray((Double_t*) fAddress, n); break;}
          case 11:  {b.WriteFastArray((UChar_t*)  fAddress, n); break;}
          case 12:  {b.WriteFastArray((UShort_t*) fAddress, n); break;}
          case 13:  {b.WriteFastArray((UInt_t*)   fAddress, n); break;}
          case 14:  {b.WriteFastArray((ULong_t*)  fAddress, n); break;}
          case 15:  {b.WriteFastArray((UInt_t*)   fAddress, n); break;}
          case 16:  {b.WriteFastArray((Long64_t*) fAddress, n); break;}
          case 17:  {b.WriteFastArray((ULong64_t*)fAddress, n); break;}
          case 18:  {b.WriteFastArray((Bool_t*)   fAddress, n); break;}
          case  9:  {Double_t *xx = (Double_t*)fAddress;
                     for (Int_t ii=0;ii<n;ii++) b << (Float_t)xx[ii];
                     break;}
        }
        return;
     }
     TClonesArray *clones = (TClonesArray*)fObject;
     if (!clones) return;
     Int_t n = clones->GetEntriesFast();
     fInfo->WriteBufferClones(b,clones,n,fID,fOffset);
  } else if (fType <= 2) {
     Int_t n = fInfo->WriteBufferAux(b,&fObject,fID,1,0,0); // NOTE: expanded
     if (fStreamerType == 6) {
        if (n > fMaximum) fMaximum = n;
     }
  }
}

//______________________________________________________________________________
 Int_t TBranchElement::GetDataMemberOffset(const TClass *cl, const char *name)
{
// This function is for internal use only!
// Return the offset if 'name' is found in the list of real data for cl
// Output an error message if the 'name' is NOT found (to prevent reliance on the previous
// implementation.

// The previous implementation of the class had the following comments:

// Return the offset if 'name' is found in the list of real data for cl
// return offset od member name in class cl
// check for the following cases Otto and Axel
//
// Return the opposite of the offset if name is of the form 'XXX.YYY' where
//    XXX is a name found in the list of real data for cl
//
// case Otto
//    class TUsrSevtData2:public TMrbSubevent_Caen {
//    class TMrbSubevent_Caen:public TObject {
//       TUsrHitBuffer fHitBuffer;
//    class TUsrHitBuffer:public TObject {
//       Int_t fHighWater;
//       TClonesArray *fHits;
//    code below to get the correct address for fHitBuffer.fHits
//
//    i.e. this is the case where we have a TClonesArray inside an object
//    which is embedded into another (which is stored in a branch)
//
// case Axel
//    class jet: public TLorentzVector {
//    TClonesArray* caJet=new TClonesArray("jet");
//    TTree* tree=new TTree("test","test",99);
//    tree->Branch("jet", "TClonesArray",&caJet, 32000);
//
//    i.e this is the case where we have an embedded object inside an object
//    stored in a TClonesArray

   Int_t offset = 0;
   TRealData *rd = cl->GetRealData(name);

   if (!rd) {
      Error("GetDataMemberOffset","obsolete call with (%s,%s)\n",
            cl->GetName(),name);
   } else {
      offset = rd->GetThisOffset();
   }

   if (gDebug > 3) {
      printf("GetDataMemberOffset(%s,%s) => %d\n",
              cl->GetName(),name,offset);
   }
   return offset;
}

//______________________________________________________________________________
 void TBranchElement::SetupAddresses() 
{
   // If the branch address had not yet been set, 
   // we set all addresses starting with the top level parent branch

   // This is requires to be done in order for GetOffset
   // to be guarantee correct and for GetEntry to be run.
   if (fAddress == 0 && fTree->GetMakeClass() == 0) {
      if (TestBit(kDoNotProcess)) return;
      TBranchElement *mother = (TBranchElement*)GetMother();
      TClass *cl = gROOT->GetClass(mother->GetClassName());
      if (fInfo && fInfo->GetOffsets()) fInfo->BuildOld();
      if (!mother || !cl) return;
      if (!mother->GetAddress()) {
         Bool_t motherStatus = mother->TestBit(kDoNotProcess);
         mother->ResetBit(kDoNotProcess);
         mother->SetAddress(0);
         mother->SetBit(kDoNotProcess,motherStatus);
      }
   }
}

//______________________________________________________________________________
 Int_t TBranchElement::GetEntry(Long64_t entry, Int_t getall)
{
//*-*-*-*-*Read all branches of a BranchElement and return total number of bytes
//*-*      ====================================================================
//   If entry = 0 take current entry number + 1
//   If entry < 0 reset entry number to 0
//
//  The function returns the number of bytes read from the input buffer.
//  If entry does not exist  the function returns 0.
//  If an I/O error occurs,  the function returns -1.
//
//  See IMPORTANT REMARKS in TTree::GetEntry

   Int_t nbranches = fBranches.GetEntriesFast();

   Int_t nbytes = 0;

   if (fAddress == 0 && fTree->GetMakeClass() == 0) {
      SetupAddresses();
   }

   if (nbranches) {
      //branch has daughters
      //one must always read the branch counter.
      //In the case when one reads consecutively twice the same entry,
      //the user may have cleared the TClonesArray between the 2 GetEntry
      if ( fType == 3 || fType == 4 )  {
        fReadEntry = entry;
        nbytes += TBranch::GetEntry(entry, getall);
      }
      Int_t i;
      switch(fSTLtype)  {
        case TClassEdit::kSet:
        case TClassEdit::kMultiSet:
        case TClassEdit::kMap:
        case TClassEdit::kMultiMap:
          break;
        default:
          for (i=0;i<nbranches;i++)  {
            TBranch *branch = (TBranch*)fBranches[i];
            Int_t    nb = branch->GetEntry(entry, getall);
            if (nb < 0) return nb;
            nbytes += nb;
          }
          break;
      }
   } else {
      //terminal branch
      if (fBranchCount && fBranchCount->GetReadEntry() != entry) nbytes += fBranchCount->TBranch::GetEntry(entry,getall);
      nbytes += TBranch::GetEntry(entry, getall);
   }

   // if Tree has a TBranchRef, set the ReadEntry in the TBranchRef
   TBranchRef *bref = fTree->GetBranchRef();
   if (bref) {
      bref->SetParent(this);
      bref->SetReadEntry(entry);
   }

   if (fTree->Debug() > 0) {
      if (entry >= fTree->GetDebugMin() && entry <= fTree->GetDebugMax()) {
         printf("GetEntry: %lld, branch=%s, nbytes=%d\n",entry,GetName(),nbytes);
      }
   }
   return nbytes;
}

//______________________________________________________________________________
 const char *TBranchElement::GetIconName() const
{
   // Return icon name depending on type of branch element.

   if (IsFolder())
      return "TBranchElement-folder";
   else
      return "TBranchElement-leaf";
}

//______________________________________________________________________________
 Bool_t TBranchElement::CheckBranchID()  
{
   // Need to reassign branches in case schema evolution has scrambled leaf list.

   if ( GetID() >= 0 ) {
      size_t pos;
      std::string s( GetName() );
      pos = s.rfind('.');
      if ( pos != std::string::npos )  {
         s = s.substr(pos+1);
      }
      while ( (pos=s.rfind('[')) != std::string::npos ) {
         s = s.substr(0,pos);
      }
      int offset = 0;
      TStreamerElement* elt = fInfo->GetStreamerElement(s.c_str(),offset);
      if ( elt )   {
         size_t ndata = fInfo->GetNdata();
         ULong_t *elems = fInfo->GetElems();

         for(size_t i=0; i < ndata; ++i )  {
            if ( (TStreamerElement*)elems[i] == elt )  {
               fID = i;
               break;
            }
         }
      }
      else  {
         // Element may be missing, if data member got removed.
         // Warning("CheckBranchID","Cannot find streamer element:%s",s.c_str());
      }
   }
   return kTRUE;
}

//______________________________________________________________________________
 TStreamerInfo *TBranchElement::GetInfo()
{
  //return pointer to TStreamerinfo object for the class of this branch
  //rebuild the info if not yet done

   Bool_t optim = TStreamerInfo::CanOptimize();
   if (fInfo) {
      if (!fInfo->GetOffsets()) {
         TStreamerInfo::Optimize(kFALSE);
         fInfo->Compile();
         TStreamerInfo::Optimize(optim);
      }
      if (!fInit) fInit = CheckBranchID();
      return fInfo;
   }
   TClass *cl = fBranchClass;
   if (cl) {
      TStreamerInfo::Optimize(kFALSE);
      if (cl == TClonesArray::Class()) fClassVersion = TClonesArray::Class()->GetClassVersion();
      fInfo = cl->GetStreamerInfo(fClassVersion);
      if (fCheckSum != 0 && (cl->IsForeign() ||
                             (!cl->IsLoaded() && 
                              fClassVersion==1 && 
                              cl->GetStreamerInfos()->At(1)!=0 && 
                              fCheckSum!= ((TStreamerInfo*)cl->GetStreamerInfos()->At(1))->GetCheckSum()))) {
         Int_t ninfos = cl->GetStreamerInfos()->GetEntriesFast();
         for (Int_t i=1;i<ninfos;i++) {
            TStreamerInfo *info = (TStreamerInfo*)cl->GetStreamerInfos()->At(i);
            if (!info) continue;
            if (info->GetCheckSum() == fCheckSum) {
               fClassVersion = i;
               fInfo = cl->GetStreamerInfo(fClassVersion);
               break;
            }
         }
      }
      if (fInfo && !fInfo->GetOffsets()) {
         fInfo->Compile();
      }
      TStreamerInfo::Optimize(optim);
      if ( !fInit ) fInit = CheckBranchID();
   }
   return fInfo;
}

//______________________________________________________________________________
 Int_t TBranchElement::GetMaximum() const
{
// Return maximum count value of the branchcount if any

   if (fBranchCount) return fBranchCount->GetMaximum();
   return fMaximum;
}

//______________________________________________________________________________
 const char *TBranchElement::GetTypeName() const
{
   // return type name of element in the branch

   if (fType == 3  || fType == 4) {
      return "Int_t";
   }
   if (fStreamerType <=0 || fStreamerType >= 60) return fClassName.Data();
   const char *types[19] = {"",
                            "Char_t","Short_t","Int_t","Long_t","Float_t",
                            "Int_t","",
                            "Double_t","Double32_t",
                            "",
                            "UChar_t","UShort_t","UInt_t","ULong_t","UInt_t",
                            "Long64_t","ULong64_t","Bool_t"};
   Int_t itype = fStreamerType%20;
   return types[itype];
}

//______________________________________________________________________________
 Double_t TBranchElement::GetValue(Int_t j, Int_t len, Bool_t subarr) const
{
// Returns branch value. If the leaf is an array, j is the index in the array
// If leaf is an array inside a TClonesArray, len should be the length of the
// array.  If subarr is true, then len is actually the index within the sub-array

   if (j == 0 && fBranchCount) {
      Int_t entry = fTree->GetReadEntry();
      fBranchCount->TBranch::GetEntry(entry);
      if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
   }

   if (fTree->GetMakeClass()) {
     if (!fAddress) return 0;
     if (fType == 3 || fType == 4 ) {    //top level branch of a TClonesArray
       return (Double_t)fNdata;
     } else if (fType == 31 || fType == 41) {    // sub branch of a TClonesArray
       Int_t atype = fStreamerType;
       if (atype < 20) atype += 20;
       return fInfo->GetValue(fAddress,atype,j,1);
     } else if (fType <= 2) {     // branch in split mode
       if (fStreamerType > 40 && fStreamerType < 55) {
          Int_t atype = fStreamerType - 20;
          return fInfo->GetValue(fAddress,atype,j,1);
       } else {
          return fInfo->GetValue(fObject,fID,j,-1);
       }
     }
   }

   if (fType == 31) {
      TClonesArray *clones = (TClonesArray*)fObject;
      if (subarr) return fInfo->GetValueClones(clones,fID, j, len,fOffset);
      else return fInfo->GetValueClones(clones,fID, j/len, j%len,fOffset);
   }  else if (fType == 41) {
      TVirtualCollectionProxy::TPushPop helper(fCollProxy,fObject);
      if (subarr) return fInfo->GetValueSTL(fCollProxy,fID, j, len,fOffset);
      else return fInfo->GetValueSTL(fCollProxy,fID, j/len, j%len,fOffset);
   } else {
      if (fInfo) return fInfo->GetValue(fObject,fID,j,-1);
      return 0;
   }
}

//______________________________________________________________________________
 void *TBranchElement::GetValuePointer() const
{
// Returns pointer to first data element of this branch
// Currently used only for members of type character

   if (fBranchCount) {
      Int_t entry = fTree->GetReadEntry();
      fBranchCount->TBranch::GetEntry(entry);
      if (fBranchCount2) fBranchCount2->TBranch::GetEntry(entry);
   }
   if (fTree->GetMakeClass()) {
     if (!fAddress) return 0;
     if (fType == 3) {    //top level branch of a TClonesArray
       //return &fNdata;
       return 0;
     } else if (fType == 4) {    //top level branch of a TClonesArray
       //return &fNdata;
       return 0;
     } else if (fType == 31) {    // sub branch of a TClonesArray
       //Int_t atype = fStreamerType;
       //if (atype < 20) atype += 20;
       //return fInfo->GetValue(fAddress,atype,j,1);
       return 0;
     } else if (fType == 41) {    // sub branch of a TClonesArray
       //Int_t atype = fStreamerType;
       //if (atype < 20) atype += 20;
       //return fInfo->GetValue(fAddress,atype,j,1);
       return 0;
     } else if (fType <= 2) {     // branch in split mode
       if (fStreamerType > 40 && fStreamerType < 55) {
          //Int_t atype = fStreamerType - 20;
          //return fInfo->GetValue(fAddress,atype,j,1);
          return 0;
       } else {
          //return fInfo->GetValue(fObject,fID,j,-1);
          return 0;
       }
     }
   }

   if (fType == 31) {
      //TClonesArray *clones = (TClonesArray*)fObject;
      //if (subarr) return fInfo->GetValueClones(clones,fID, j, len,fOffset);
      //else return fInfo->GetValueClones(clones,fID, j/len, j%len,fOffset);
      return 0;
   } else if (fType == 41) {
      //TClonesArray *clones = (TClonesArray*)fObject;
      //if (subarr) return fInfo->GetValueClones(clones,fID, j, len,fOffset);
      //else return fInfo->GetValueClones(clones,fID, j/len, j%len,fOffset);
      return 0;
   } else {
      //return fInfo->GetValue(fObject,fID,j,-1);
      if (!fInfo || !fObject) return 0;
      char **val = (char**)(fObject+fInfo->GetOffsets()[fID]);
      return *val;
   }
}

//______________________________________________________________________________
 Bool_t TBranchElement::IsFolder() const
{
//*-*-*-*-*Return TRUE if more than one leaf, FALSE otherwise*-*
//*-*      ==================================================

   Int_t nbranches = fBranches.GetEntriesFast();
   if (nbranches >= 1) return kTRUE;
   TList* browsables= const_cast<TBranchElement*>(this)->GetBrowsables();
   return (browsables && browsables->GetSize());
}

//______________________________________________________________________________
 Bool_t TBranchElement::IsMissingCollection() const
{
   // In version of ROOT older than 4.00/03, if a collection (TClonesArray
   // or stl container) was split but the pointer to the collection was zeroed
   // out, nothing was saved.  Hence there is no __easy__ way to detect the
   // case.  In newer version, a zero is inserted so that a 'missing' collection
   // appears as an empty collection.
   // This function helps in detecting this case so that we can recover nicely.

   Bool_t ismissing = kFALSE;

   TBasket *basket = (TBasket*)fBaskets.UncheckedAt(fReadBasket);
   if (basket && fTree) {
      Int_t entry = fTree->GetReadEntry();
      Int_t first  = fBasketEntry[fReadBasket];
      Int_t last;
      if (fReadBasket == fWriteBasket) last = fEntryNumber - 1;
      else                             last = fBasketEntry[fReadBasket+1] - 1;
      Int_t *entryOffset = basket->GetEntryOffset();
      Int_t bufbegin ;
      Int_t bufnext;
      if (entryOffset) {
         bufbegin = entryOffset[entry-first];

         if (entry<last) {
            bufnext = entryOffset[entry+1-first];
         } else {
            bufnext = basket->GetLast();
         }
         if (bufnext==bufbegin) {
            ismissing = kTRUE;
         } else {
            // fixed length buffer so this is not the case here.
            if (basket->GetNevBufSize()==0) {
               ismissing = kTRUE;
            }
         }
      }
   }
   return ismissing;
}

//______________________________________________________________________________
 void TBranchElement::Print(Option_t *option) const
{
//*-*-*-*-*-*-*-*-*-*-*-*Print TBranch parameters*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*                    ========================

   Int_t nbranches = fBranches.GetEntriesFast();
   if (nbranches) {
      if (fID == -2) {
         if (strcmp(GetName(),GetTitle()) == 0) {
            Printf("*Branch  :%-66s *",GetName());
         } else {
            Printf("*Branch  :%-9s : %-54s *",GetName(),GetTitle());
         }
         Printf("*Entries : %8d : BranchElement (see below)                              *",Int_t(fEntries));
         Printf("*............................................................................*");
      }
      if (fType >= 2) {
         TBranch::Print(option);
      }
      for (Int_t i=0;i<nbranches;i++)  {
         TBranch *branch = (TBranch*)fBranches.At(i);
         branch->Print(option);
      }
   } else {
      TBranch::Print(option);
   }
}

//______________________________________________________________________________
 void TBranchElement::PrintValue(Int_t lenmax) const
{
// Prints leaf value

  if (fTree->GetMakeClass()) {
     if (!fAddress) return;
     if (fType == 3 || fType == 4) {    //top level branch of a TClonesArray
       printf(" %-15s = %d\n",GetName(),fNdata);
       return;
     } else if (fType == 31 || fType == 41) {    // sub branch of a TClonesArray
       Int_t n = TMath::Min(10,fNdata);
       Int_t atype = fStreamerType+TStreamerInfo::kOffsetL;
       // TStreamerInfo::kOffsetL + TStreamerInfo::kChar is printed as a character strings
       // and hence could print weird character.  So let's do let damage and print an unsigned
       // char instead (not perfect but better).
       if (fStreamerType==TStreamerInfo::kChar) atype=TStreamerInfo::kOffsetL + TStreamerInfo::kUChar;
       if (atype > 54) {
          //more logic required here (like in ReadLeaves)
          printf(" %-15s = %d\n",GetName(),fNdata);
          return;
       }
       if (fStreamerType > 20) {
          atype -= 20;
          TLeafElement *leaf = (TLeafElement*)fLeaves.UncheckedAt(0);
          n *= leaf->GetLenStatic();
       }
       if (fInfo) fInfo->PrintValue(GetName(),fAddress,atype,n,lenmax);
       return;
     } else if (fType <= 2) {     // branch in split mode
       if (fStreamerType > 40 && fStreamerType < 55) {
          Int_t atype = fStreamerType - 20;
          Int_t n = (Int_t)((TBranchElement*)fBranchCount)->GetValue(0,0);
          if (fInfo) fInfo->PrintValue(GetName(),fAddress,atype,n,lenmax);
       } else {
          if (fInfo) fInfo->PrintValue(GetName(),fObject,fID,-1,lenmax);
       }
       return;
     }
     return;
  }
   if (fType == 3) {
      printf(" %-15s = %d\n",GetName(),fNdata);
   } else if (fType == 31) {
      TClonesArray *clones = (TClonesArray*)fObject;
      if (fInfo) fInfo->PrintValueClones(GetName(),clones,fID,fOffset,lenmax);
   } else if (fType == 41) {
      TVirtualCollectionProxy::TPushPop helper(fCollProxy,fObject); // Object);
      if (fInfo) fInfo->PrintValueSTL(GetName(),fCollProxy,fID,fOffset,lenmax);
   } else {
      if (fInfo) fInfo->PrintValue(GetName(),fObject,fID,-1,lenmax);
   }
}

//______________________________________________________________________________
 void TBranchElement::ReadLeaves(TBuffer &b)
{
// Read buffers for this branch

  if (fTree->GetMakeClass()) {
     if (fType == 3 || fType == 4) {    //top level branch of a TClonesArray
       Int_t *n = (Int_t*)fAddress;
       b >> n[0];
       if (n[0]<0 || n[0]>fMaximum) {
          if (IsMissingCollection()) {
             n[0] = 0;
             b.SetBufferOffset( b.Length() - sizeof(n) );
          } else {
             Error("ReadLeaves",
                   "Incorrect size read for the container in %s\nThe size read is %d when the maximum is %d\nThe size is reset to 0 for this entry (%d)",
                   GetName(),n,fMaximum,GetReadEntry());
             n[0] = 0;
          }
       }
       fNdata = n[0];
       if ( fType == 4)   {
          Int_t i, nbranches = fBranches.GetEntriesFast();
          switch(fSTLtype)  {
            case TClassEdit::kSet:
            case TClassEdit::kMultiSet:
            case TClassEdit::kMap:
            case TClassEdit::kMultiMap:
              for (i=0;i<nbranches;i++)  {
                TBranch *branch = (TBranch*)fBranches[i];
                Int_t    nb = branch->GetEntry(GetReadEntry(), 1);
                if (nb < 0) break;
              }
              break;
            default:
              break;
          }
       }
       return;
     } else if (fType == 31 || fType == 41) {    // sub branch of a TClonesArray
       fNdata = fBranchCount->GetNdata();
       Int_t atype = fStreamerType;
       if (atype > 54) return;
       if (!fAddress) return;
       Int_t n = fNdata;
       if (atype>40) {
          atype -= 40;
          if (!fBranchCount2) return;
          const char *len_where = (char*)fBranchCount2->fAddress;
          if (!len_where) return;
          Int_t len_atype = fBranchCount2->fStreamerType;
          Int_t length;
          Int_t k;
          Char_t isArray;
          for( k=0; k<n; k++) {
             char **where = &(((char**)fAddress)[k]);
             delete [] *where;
             *where = 0;
             switch(len_atype) {
                case  1:  {length = ((Char_t*)   len_where)[k]; break;}
                case  2:  {length = ((Short_t*)  len_where)[k]; break;}
                case  3:  {length = ((Int_t*)    len_where)[k]; break;}
                case  4:  {length = ((Long_t*)   len_where)[k]; break;}
                   //case  5:  {length = ((Float_t*) len_where)[k]; break;}
                case  6:  {length = ((Int_t*)    len_where)[k]; break;}
                   //case  8:  {length = ((Double_t*)len_where)[k]; break;}
                case 11:  {length = ((UChar_t*)  len_where)[k]; break;}
                case 12:  {length = ((UShort_t*) len_where)[k]; break;}
                case 13:  {length = ((UInt_t*)   len_where)[k]; break;}
                case 14:  {length = ((ULong_t*)  len_where)[k]; break;}
                case 15:  {length = ((UInt_t*)   len_where)[k]; break;}
                case 16:  {length = ((Long64_t*) len_where)[k]; break;}
                case 17:  {length = ((ULong64_t*)len_where)[k]; break;}
                case 18:  {length = ((Bool_t*)   len_where)[k]; break;}                   
                default: continue;
             }
             b >> isArray;
             if (length <= 0)  continue;
             if (isArray == 0) continue;
             switch (atype) {
                case  1:  {*where=new char[sizeof(Char_t)*length]; b.ReadFastArray((Char_t*) *where, length); break;}
                case  2:  {*where=new char[sizeof(Short_t)*length]; b.ReadFastArray((Short_t*) *where, length); break;}
                case  3:  {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*)   *where, length); break;}
                case  4:  {*where=new char[sizeof(Long_t)*length]; b.ReadFastArray((Long_t*)  *where, length); break;}
                case  5:  {*where=new char[sizeof(Float_t)*length]; b.ReadFastArray((Float_t*) *where, length); break;}
                case  6:  {*where=new char[sizeof(Int_t)*length]; b.ReadFastArray((Int_t*)   *where, length); break;}
                case  8:  {*where=new char[sizeof(Double_t)*length]; b.ReadFastArray((Double_t*)*where, length); break;}
                case 11:  {*where=new char[sizeof(UChar_t)*length]; b.ReadFastArray((UChar_t*) *where, length); break;}
                case 12:  {*where=new char[sizeof(UShort_t)*length]; b.ReadFastArray((UShort_t*)*where, length); break;}
                case 13:  {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*)  *where, length); break;}
                case 14:  {*where=new char[sizeof(ULong_t)*length]; b.ReadFastArray((ULong_t*) *where, length); break;}
                case 15:  {*where=new char[sizeof(UInt_t)*length]; b.ReadFastArray((UInt_t*)  *where, length); break;}
                case 16:  {*where=new char[sizeof(Long64_t)*length]; b.ReadFastArray((Long64_t*)  *where, length); break;}
                case 17:  {*where=new char[sizeof(ULong64_t)*length]; b.ReadFastArray((ULong64_t*)*where, length); break;}
                case 18:  {*where=new char[sizeof(Bool_t)*length]; b.ReadFastArray((Bool_t*) *where, length); break;}
            }
          }
          return;
       }
       if (atype > 20) {
          atype -= 20;
          TLeafElement *leaf = (TLeafElement*)fLeaves.UncheckedAt(0);
          n *= leaf->GetLenStatic();
       }
       switch (atype) {
          case  1:  {b.ReadFastArray((Char_t*)  fAddress, n); break;}
          case  2:  {b.ReadFastArray((Short_t*) fAddress, n); break;}
          case  3:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
          case  4:  {b.ReadFastArray((Long_t*)  fAddress, n); break;}
          case  5:  {b.ReadFastArray((Float_t*) fAddress, n); break;}
          case  6:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
          case  8:  {b.ReadFastArray((Double_t*)fAddress, n); break;}
          case 11:  {b.ReadFastArray((UChar_t*) fAddress, n); break;}
          case 12:  {b.ReadFastArray((UShort_t*)fAddress, n); break;}
          case 13:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
          case 14:  {b.ReadFastArray((ULong_t*) fAddress, n); break;}
          case 15:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
          case 16:  {b.ReadFastArray((Long64_t*)fAddress, n); break;}
          case 17:  {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
          case 18:  {b.ReadFastArray((Bool_t*)  fAddress, n); break;}
          case  9:  {Double_t *xx = (Double_t*)fAddress;
                     Float_t afloat;
                     for (Int_t ii=0;ii<n;ii++) {
                        b >> afloat; xx[ii] = Double_t(afloat);
                     } break;}
       }
       return;
     } else if (fType <= 2) {     // branch in split mode
       if (fStreamerType > 40 && fStreamerType < 55) {
          Int_t atype = fStreamerType - 40;
          Int_t n = (Int_t)fBranchCount->GetValue(0,0);
          fNdata = n;
          Char_t isArray;
          b >> isArray;
          switch (atype) {
             case  1:  {b.ReadFastArray((Char_t*)  fAddress, n); break;}
             case  2:  {b.ReadFastArray((Short_t*) fAddress, n); break;}
             case  3:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
             case  4:  {b.ReadFastArray((Long_t*)  fAddress, n); break;}
             case  5:  {b.ReadFastArray((Float_t*) fAddress, n); break;}
             case  6:  {b.ReadFastArray((Int_t*)   fAddress, n); break;}
             case  8:  {b.ReadFastArray((Double_t*)fAddress, n); break;}
             case 11:  {b.ReadFastArray((UChar_t*) fAddress, n); break;}
             case 12:  {b.ReadFastArray((UShort_t*)fAddress, n); break;}
             case 13:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
             case 14:  {b.ReadFastArray((ULong_t*) fAddress, n); break;}
             case 15:  {b.ReadFastArray((UInt_t*)  fAddress, n); break;}
             case 16:  {b.ReadFastArray((Long64_t*) fAddress, n); break;}
             case 17:  {b.ReadFastArray((ULong64_t*)fAddress, n); break;}
             case 18:  {b.ReadFastArray((Bool_t*)   fAddress, n); break;}
             case  9:  {Double_t *xx = (Double_t*)fAddress;
                        Float_t afloat;
                        for (Int_t ii=0;ii<n;ii++) {
                           b>> afloat; xx[ii] = Double_t(afloat);
                        } break;}
          }
       } else {
          fNdata = 1;
          if (fAddress) {
          //char **arr = &fObject;
             fInfo->ReadBuffer(b,(char**)&fObject,fID);
          } else {
             fNdata = 0;
          }
       }
       return;
     }
  }

  if (fType <=2 && TestBit(kBranchObject)) {
     b.MapObject((TObject*)fObject);
  }

  if (fType == 4) {           // STL vector/list of objects
     //Error("ReadLeaves","STL split mode not yet implemented (error 1)\n");
     Int_t n;
     b >> n;
     if (n<0 || n>fMaximum) {
        if (IsMissingCollection()) {
           n = 0;
           b.SetBufferOffset( b.Length() - sizeof(n) );
        } else {
           Error("ReadLeaves",
                 "Incorrect size read for the container in %s\n\tThe size read is %d while the maximum is %d\n\tThe size is reset to 0 for this entry (%d)",
                 GetName(),n,fMaximum,GetReadEntry());
           n = 0;
        }
     }
     fNdata = n;
     if (!fObject) return;
     if ( fType == 4)   {
        // Note: Proxy-helper needs to "embrace" the entire
        //       streaming of this STL container if the container
        //       is a set/multiset/map/multimap (what we do not
        //       know here).
        //       For vector/list/deque Allocate == Resize
        //                         and Commit   == noop.
        // TODO: Exception safety a la TPushPop
        TVirtualCollectionProxy* proxy = GetCollectionProxy();
        TVirtualCollectionProxy::TPushPop helper(proxy,fObject);
        void* env = proxy->Allocate(fNdata,true);
        Int_t i, nbranches = fBranches.GetEntriesFast();
        switch(fSTLtype)  {
          case TClassEdit::kSet:
          case TClassEdit::kMultiSet:
          case TClassEdit::kMap:
          case TClassEdit::kMultiMap:
            for (i=0;i<nbranches;i++)  {
              TBranch *branch = (TBranch*)fBranches[i];
              Int_t    nb = branch->GetEntry(GetReadEntry(), 1);
              if (nb < 0) break;
            }
            break;
          default:
            break;
        }
        proxy->Commit(env);
      }
  } else if (fType == 41) {    // sub branch of an STL class
     //Error("ReadLeaves","STL split mode not yet implemented (error 2)\n");
     //char **ppointer = (char**)fAddress;
     fNdata = fBranchCount->GetNdata();
     if (!fObject) return;
     TVirtualCollectionProxy::TPushPop helper(GetCollectionProxy(),fObject);
     fInfo->ReadBufferSTL(b,fCollProxy,fNdata,fID,fOffset);
  } else if (fType == 3) {    //top level branch of a TClonesArray
     Int_t n;
     b >> n;
     if (n<0 || n>fMaximum) {
        if (IsMissingCollection()) {
           n = 0;
           b.SetBufferOffset( b.Length() - sizeof(n) );
        } else {
           Error("ReadLeaves",
                 "Incorrect size read for the container in %s\n\tThe size read is %d while the maximum is %d\n\tThe size is reset to 0 for this entry (%d)",
                 GetName(),n,fMaximum,GetReadEntry());
           n = 0;
        }
     }
     fNdata = n;
     TClonesArray *clones = (TClonesArray*)fObject;
     if (!clones) return;
     if (clones->IsZombie()) return;
     clones->Clear();
     clones->ExpandCreateFast(fNdata);
  } else if (fType == 31) {    // sub branch of a TClonesArray
     fNdata = fBranchCount->GetNdata();
     TClonesArray *clones = (TClonesArray*)fObject;
     if (!clones) return;
     if (clones->IsZombie()) return;
     fInfo->ReadBufferClones(b,clones,fNdata,fID,fOffset);
  } else if (fType <= 2) {     // branch in split mode
     if (fBranchCount) fNdata = (Int_t)fBranchCount->GetValue(0,0);
     else fNdata = 1;
     if (!fInfo) return;
     //char **arr = &fObject;
     fInfo->ReadBuffer(b,(char**)&fObject,fID);
     if (fStreamerType == 6) fNdata = (Int_t)GetValue(0,0);
  }
}

//______________________________________________________________________________
 void TBranchElement::Reset(Option_t *option)
{
//*-*-*-*-*-*-*-*Reset a Branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ====================
//
//    Existing buffers are deleted
//    Entries, max and min are reset
//

   TBranch::Reset(option);
   fInfo = fBranchClass->GetStreamerInfo(fClassVersion);
   Int_t nbranches = fBranches.GetEntriesFast();
   for (Int_t i=0;i<nbranches;i++)  {
      TBranch *branch = (TBranch*)fBranches[i];
      branch->Reset(option);
   }
}

//______________________________________________________________________________
 void TBranchElement::ResetAddress()
{
//*-*-*-*-*-*-*-*Reset the address of the branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ===============================
//

   fObject = 0;
   TBranch::ResetAddress();
}

//______________________________________________________________________________
namespace {
   void SwitchContainer(TObjArray *branches) {
      const Int_t nbranches = branches->GetEntriesFast();
      for(Int_t i = 0; i < nbranches; ++i) {
         TBranchElement *br = (TBranchElement*)branches->At(i);
         switch ( br->GetType() ) {
            case 31: br->SetType(41); break;
            case 41: br->SetType(31); break;
         };
         SwitchContainer( br->GetListOfBranches());
      }
   }
}

//______________________________________________________________________________
 TClass* TBranchElement::GetParentClass()   
{
   // Return a pointer to the current type of the data member corresponding to branch element

   if ( fParentName.Data()[0] == 0 ) return 0;
   return fParentClass;
}

//______________________________________________________________________________
 TClass* TBranchElement::GetCurrentClass()   
{
   // Return a pointer to the current type of the data member corresponding to branch element

   TClass* cl = fCurrentClass;
   if ( cl ) return cl;

   // Get the current type of this data member!
   TStreamerInfo *brInfo = GetInfo();
   if (brInfo==0) {
      cl = gROOT->GetClass(GetClassName());
      Assert(cl && cl->GetCollectionProxy());
      fCurrentClass = cl;
      return cl;
   }
   TClass *motherCl = brInfo->GetClass();
   if (motherCl->GetCollectionProxy())   {
      cl = motherCl->GetCollectionProxy()->GetCollectionClass();
      if ( cl ) fCurrentClass = cl;
      return cl;
   }
   TStreamerElement *currentStreamerElement = 
      ((TStreamerElement*)brInfo->GetElems()[GetID()]);
   TDataMember *dm = 
      (TDataMember*)motherCl->GetListOfDataMembers()->FindObject(currentStreamerElement->GetName());

   TString newType;
   if ( dm==0 ) {
      // Either the class is not loaded or the data member is gone
      if (! motherCl->IsLoaded() ) {
         TStreamerInfo *newInfo = motherCl->GetStreamerInfo();
         if (newInfo != brInfo) {
            TStreamerElement *newElems = (TStreamerElement*)
               newInfo->GetElements()->FindObject(currentStreamerElement->GetName());
            newType = newElems->GetClassPointer()->GetName();
         }
      }
   } else {
      newType = dm->GetTypeName();
   }
   cl = gROOT->GetClass(newType);
   if ( cl ) fCurrentClass = cl;
   return cl;
}

namespace {
   void CleanParentName(TString& parentName, const char* prefix)  {
      if (parentName.Index(prefix)==0) {
         parentName.Remove(0,strlen(prefix));
      }
   }
}

//______________________________________________________________________________
 Int_t TBranchElement::GetDataMemberOffsetEx(TClass* par_cl, TString& parentName, Int_t off)  
{
   // remove the current data member name

   Ssiz_t pos = parentName.Last('.');
   if (pos>0) {
      // We had a branch name of the style:
      //     [X.]Y.Z
      // and we are looking up 'Y'
      parentName.Remove(pos);
      return GetDataMemberOffset(par_cl,parentName);
   } else {
      // We had a branch name of the style:
      //     [X.]Z
      // and we are looking up 'Z'
      // Because we are missing 'Y' (or more exactly the name of the
      // thing that contains Z, we can only get the offset of Z and
      // then remove the offset Z inside 'Y' (i.e. lOffset)
      if (pos==0&&parentName[0]=='.') parentName.Remove(0,1);
      return GetDataMemberOffset(par_cl,parentName) - off;
   }
}

//______________________________________________________________________________
 void TBranchElement::InitializeOffsets()   
{
   Int_t nbranches = fBranches.GetEntriesFast();
   TClass *clparent = GetParentClass();
   TClass *clm      = fBranchClass;
   if (fType == 31 || fType == 41) {
       if ( fClassName != fParentName ) {
          // We are in the case where we have a missing link.
          // This information is realliable here (or so it seems)
          // (In other cases fParentName does not seems to be set correctly in all cases).

          if (clparent != clm) {
             if (!clparent || !clm)    {
                fInitOffsets = kTRUE;
                return;
             }
             const char *ename = fID<0 ? 0 : ((TStreamerElement*)fInfo->GetElems()[fID])->GetName();
             Int_t lOffset    = clm->GetStreamerInfo()->GetOffset(ename); // offset in the local streamerInfo.

             TBranchElement *parent = (TBranchElement*) GetMother()->GetSubBranch(this);
             TString parentDataName( GetName() );
             // remove the TClonesArray main name (if present)
             CleanParentName(parentDataName,fBranchCount->GetName());
             // remove the parent branch name (if present)
             CleanParentName(parentDataName,parent->GetName());
             fOffset = GetDataMemberOffsetEx(clparent, parentDataName, lOffset);
          }
       }
       if (gDebug > 0 ) {
         printf("fOffset=%d\n",fOffset);
       }
   }
   else if (nbranches == 0) {
      if (clparent && clparent != clm) {
         // We need to discover if 'this' represents a direct datamember of the class in parent or
         // if it is an indirect one (with a missing branch in the hierachy)

         TBranchElement *parent = (TBranchElement*) GetMother()->GetSubBranch(this);
         assert(parent!=this);

         Int_t parentID = parent->GetID();
         assert(parentID>=0);  // if the ID was negative, the branch would not have been split!

         TStreamerInfo *parentInfo = parent->GetInfo();
         assert(parentInfo != 0);

         TStreamerElement *parentElem = (TStreamerElement*)parentInfo->GetElems()[parentID];
         TClass *parentBranchClass = parentElem->GetClassPointer();

         if ( ! parentBranchClass->InheritsFrom(clm) ) {

            // We are in the case where there is a missing branch in the hiearchy
            TString parentDataName( GetName() );
            const char *ename = fID<0 ? 0 : ((TStreamerElement*)fInfo->GetElems()[fID])->GetName();
            Int_t lOffset    = clm->GetStreamerInfo()->GetOffset(ename); // offset in the local streamerInfo.
            // remove the parent branch name (if present)
            CleanParentName(parentDataName,parent->GetName());

            fParentOffset = GetDataMemberOffsetEx(parentBranchClass, parentDataName, lOffset);

            if (parent->fType==1) {
               const char *name = GetName();
               const char *pos = strchr( name, '.');
               if (pos && fParentOffset) {
                  size_t idx = (pos-name);
                  TClass *pbc = parentBranchClass;
                  if ( pbc && (parentInfo=pbc->GetStreamerInfo()) )  {
                     std::string enam( name, idx );
                     TObject *info = parentInfo->GetElements()->FindObject(enam.c_str());
                     if (info) {
                        // If all the condition above are fullfilled we have already
                        // compensated for the missing branch.
                        fParentOffset=0;
                     }
                  }
               }
            }
         } else {
            // Case where we have a proper branch hierachy
            // fObject is already correct!

            // nothing to do :)
            // fprintf(stderr,"section has nothing to do!\n");
         }
      }
   }
   if ( nbranches > 0 )  {
      Int_t parentID = 0;
      TClass* parentBranchClass = 0;
      TStreamerElement* elem = fID<0 ? 0 : ((TStreamerElement*)fInfo->GetElems()[fID]);
      const char *ename = elem ? elem->GetName() : 0;
      fBranchOffset = new Int_t[nbranches];
      fBranchTypes  = new Bool_t[nbranches];
      //for (Int_t j=0; j<nbranches; j++ )  {
      //   fBranchOffset[j] = 0;
      //   TBranch *abranch = (TBranch*)fBranches[j];
      //   fBranchTypes[j]  = abranch->InheritsFrom(TBranchElement::Class());
      //}
      for (Int_t i=0; i<nbranches;i++ )  {
         fBranchOffset[i] = 0;
         TBranch *abranch = (TBranch*)fBranches[i];
         fBranchTypes[i]  = abranch->InheritsFrom(TBranchElement::Class());

         //just in case a TBranch had been added to a TBranchElement!
         if ( !fBranchTypes[i] ) {
           continue;
         }
         TBranchElement *branch = (TBranchElement*)abranch;
         Int_t nb2 = branch->GetListOfBranches()->GetEntriesFast();
         Int_t lOffset = 0; // offset in the local streamerInfo.

         lOffset = clm->GetStreamerInfo()->GetOffset(ename);
         Int_t id = branch->GetID();

         if (!clparent) clparent = clm;
         // Test if we are in the case where the class described by 'clparent'
         // did not get its own branch in the tree.  In this case the immediate
         // parent branch will have a different type.

         // First get the immediate parent (i.e a branch which has 'branch' has
         // a direct sub-branch.

         TStreamerInfo *info = branch->GetInfo();
         TBranchElement *parent = this; // = (TBranchElement*) branch->GetMother()->GetSubBranch(branch);
         //assert(parent==this);

         parentID = parent->GetID();
         assert(parentID>=0 || parentID==-2 || parentID==-1);  
         // if the ID was negative, the branch would not have been split!
         // -2 = Base class; -1 = (STL-)Collection
         TStreamerInfo *parentInfo = fInfo; // since parent==this parent->GetInfo();
         assert(parentInfo != 0);

         switch(parentID) {
            case -2:
            case -1:
               parentBranchClass = parentInfo->GetClass();
               break;
            default: {
               TStreamerElement *parentElem = (TStreamerElement*)parentInfo->GetElems()[parentID];
               parentBranchClass = parentElem->GetClassPointer();
               break;
            }
         }
         if ( nb2 > 0 )   {
            // The branch has some sub-branches
            if (info) {
               Int_t *leafOffsets = info->GetOffsets();

               TClass *containingClass = info->GetClass();
               if ( ! parentBranchClass->InheritsFrom(containingClass) ) {
                 // We are in the case where there is a missing branch in the hiearchy

                 // Since we do not have a proper hierachy, fObject does NOT point
                 // to object of type 'clparent'.  Instead it points to an object
                 // which 'contains' an object of type 'clparent'.  So the first
                 // order of business is to find the address of the object of type
                 // 'clparent' and then just add 'leafOffsets[id]' (i.e. the offset
                 // of this branch inside the object of type 'clparent'

                 // We need to extract from branch->GetName() the qualified name
                 // of the data member which contains us

                 TString parentDataName = branch->GetName();
                 // remove the main branch name (if present)
                 CleanParentName(parentDataName,branch->GetMother()->GetName());
                 if (leafOffsets) {
                     Int_t offset = GetDataMemberOffsetEx(parentBranchClass, parentDataName, lOffset);
                     fBranchOffset[i] = offset + leafOffsets[id];
                 } else {
                     Error("SetAddress","info=%s, leafOffsets=0",info->GetName());
                 }
               } else {
                 // Case where we have a proper branch hierachy fObject is already correct!
                 if (leafOffsets) {
                     fBranchOffset[i] = leafOffsets[id];
                 } else {
                     Error("SetAddress","info=%s, leafOffsets=0",info->GetName());
                 }
               }
            } else {
               // fInfo==0
               Error("SetAddress","branch=%s, info=0",branch->GetName());
            }
         }
         else if ( fType == 1 ) {
            // Offset seems to need correction for TStreamerBases
            const char *name = branch->GetName();
            const char *pos = strchr( name, '.');
            if (pos) {
               size_t idx = (pos-name);
               // Broken branch hierarchy: need to look for offset 
               // in the parents StreamerInfo if the branch represents
               // a TStreamerBase
               TClass *pbc = parentBranchClass;
               if ( pbc && (parentInfo=pbc->GetStreamerInfo()) )  {
                  std::string enam( branch->GetName(), idx );
                  fBranchOffset[i] = parentInfo->GetOffset(enam.c_str());
               }
               else  {
                  Error("SetAddress","branch=%s, parentInfo==0",branch->GetName());
               }
            }
         }
      }
   }
   fInitOffsets = kTRUE;
}

//______________________________________________________________________________
 void TBranchElement::SetAddress(void *add)
{
//*-*-*-*-*-*-*-*Set address of this branch*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
//*-*            ====================
//

   if (TestBit(kDoNotProcess)) return;
   if (fType < 0) return;

   //special case when called from code generated by TTree::MakeClass
   if (Long_t(add) == -1) {
      SetBit(kWarn);
      fAddress = (char*)add;
      return;
   }
   fReadEntry = -1;

   //build the StreamerInfo if first time for the class
   TClass *cl = fBranchClass;
   if ( !fInfo ) GetInfo();
   Int_t nbranches = fBranches.GetEntriesFast();
   if (gDebug > 0) {
      printf("SetAddress, branch:%s, classname=%s, parent=%s, fID=%d, fType=%d, nbranches=%d, add=%p, fInfo=%s, version=%d => ",
             GetName(),fClassName.Data(),fParentName.Data(),fID,fType,nbranches,add,fInfo->GetName(),fClassVersion);
   }
   fAddress = (char*)add;
   if (fTree->GetMakeClass()) {
      if (fID >= 0) {
         if (!fInfo) {fObject=fAddress; return;}
         fObject = fAddress - fInfo->GetOffsets()[fID];
         return;
      }
   }
   if (fID < 0) {
      if (fAddress) {
         char **ppointer = (char**)fAddress;
         fObject = *ppointer;
         if (!fObject && cl) {
            //Remember if we build an object of an emulated class
            if (!cl->GetClassInfo()) SetBit(kDeleteObject);
            fObject = (char*)cl->New();
            *ppointer = fObject;
         }
      } else {
         //Remember if we build an object of a emulated class
         if (!cl->GetClassInfo()) SetBit(kDeleteObject);
         fObject = (char*)cl->New();
      }
      if (!fAddress) fAddress = (char*)&fObject;
   } else {
      fObject = fAddress;
   }

   // Check whether the container type is still the same
   if (fType ==3) {
      TClass *clm = gROOT->GetClass(fClonesName.Data());
      if (clm) {
         clm->BuildRealData(); //just in case clm derives from an abstract class
         clm->GetStreamerInfo();
      }  
      TClass *newType = GetCurrentClass();
      if ( newType && newType != TClonesArray::Class() ) {
         // The data type of the container was changed

         // Let's check if it is a compatible type:
         Bool_t matched = kFALSE;
         if (newType->GetCollectionProxy()) {
            TClass *content = newType->GetCollectionProxy()->GetValueClass();
            if (clm==content) {
               matched = kTRUE;
            } else {
               Warning("SetAddress",
                  "The type of %s was changed from TClonesArray to %s but the content do not match (was %s)!",
                  GetName(),newType->GetName(),fClonesName.Data());
            }
         } else {
            Warning("SetAddress",
               "The type of the %s was changed from TClonesArray to %s but we do not have a TVirtualCollectionProxy for that container type!",
               GetName(),newType->GetName());
         }
         if (matched) {
            // Change from 3/31 to 4/41 
            SetType(4);
            SwitchContainer(GetListOfBranches());
            // Set the proxy.
            fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(newType->GetName()));
            fCollProxy = newType->GetCollectionProxy()->Generate();
         } else {
            fAddress = 0;
         }
      }
   }

   //Special case for an STL container.
   if (fType==4) {
      TClass *newType = GetCurrentClass();
      if ( newType && newType != GetCollectionProxy()->GetCollectionClass() ) {

         // Let's check if it is a compatible type:
         TVirtualCollectionProxy *newProxy = newType->GetCollectionProxy();
         TVirtualCollectionProxy *oldProxy = GetCollectionProxy();
         if (newProxy && oldProxy->GetValueClass() == newProxy->GetValueClass()
            && ( (oldProxy->GetValueClass() ==0 && 
                  oldProxy->GetType() == newProxy->GetType()) || 
                 (oldProxy->GetValueClass() && 
                  oldProxy->HasPointers() == newProxy->HasPointers()) ) ) {

            if ( fSTLtype==TClassEdit::kNotSTL ) {
               fSTLtype = TMath::Abs(TClassEdit::IsSTLCont(newType->GetName()));
            }
            fCollProxy = newType->GetCollectionProxy()->Generate();           
         } else {
            // The new collection and the old collection are not compatible,
            // we can not use the new collection to read the data.
            // Actually if could check whether the new collection is a 
            // compatible ROOT collection.
            if (  newType == TClonesArray::Class() && 
                  ( oldProxy->GetValueClass() && !oldProxy->HasPointers()
                   && oldProxy->GetValueClass()->InheritsFrom(TObject::Class()))) {
               // We can not insure that the TClonesArray is set for the
               // proper class ( oldProxy->GetValueClass() ), so we assume that
               // the transformation was done properly by the class designer.

               // Change from 4/41 to 3/31 
               SetType(3);
               SwitchContainer(GetListOfBranches());
               // Reset the proxy.
               fSTLtype = kNone; 
               switch(fStreamerType) {
                  case TStreamerInfo::kAny:
                  case TStreamerInfo::kSTL: 
                     fStreamerType = TStreamerInfo::kObject; 
                     break;
                  case TStreamerInfo::kAnyp:
                  case TStreamerInfo::kSTLp: 
                     fStreamerType = TStreamerInfo::kObjectp;
                     break;
                  case TStreamerInfo::kAnyP: 
                     fStreamerType = TStreamerInfo::kObjectP;
                     break;
               }
               fClonesName = oldProxy->GetValueClass()->GetName();
               delete fCollProxy; fCollProxy = 0;
               TClass *clm = gROOT->GetClass(fClonesName);
               if (clm) {
                  clm->BuildRealData(); //just in case clm derives from an abstract class
                  clm->GetStreamerInfo();
               }
             } else {
               fAddress = 0;
            }
         }
      }
   }

   //special case for a TClonesArray when address is not yet set
   //we must create the clonesarray first
   if (fType==3) {
      if (fAddress) {
         if (fStreamerType==61) {
            // Case of an embedded ClonesArray
            fObject = fAddress;
            // Check if it has already been properly build.
            TClonesArray *clones = (TClonesArray*)fObject;
            if (clones->GetClass()==0) {
               new (fObject) TClonesArray(fClonesName.Data());
            }
         } else {
            TClonesArray **ppointer = (TClonesArray**)fAddress;
            if (!*ppointer) *ppointer = new TClonesArray(fClonesName.Data());
            fObject = (char*)*ppointer;
         }
         if (!fObject) fAddress = 0;
      }
      if (!fAddress) {
         //SetBit(kDeleteObject);
         fObject = (char*)new TClonesArray(fClonesName.Data());
         fAddress = (char*)&fObject;
      }

   } else if (fType==4) {
      TVirtualCollectionProxy* proxy = GetCollectionProxy(); // initialize fCollProxy
      if (fAddress) {
         if (fStreamerType==61 ||
             fStreamerType==TStreamerInfo::kAny ||
             fStreamerType==TStreamerInfo::kSTL) {
            // Case of an embedded container?
            fObject = fAddress;
         } else {
            void **ppointer = (void**)fAddress;
            if (!*ppointer) *ppointer = proxy->New();
            fObject = (char*)*ppointer;
         }
         if (!fObject) fAddress = 0;
      }
      if (!fAddress) {
         //SetBit(kDeleteObject);
         fObject  = (char*)proxy->New();
         fAddress = (char*)&fObject;
      }
   } else if (fType==41) {
      GetCollectionProxy(); // initialize fCollProxy
   }

   if (gDebug > 0 ) {
      printf("fAddress=%p, fObject=%p, \n",fAddress,fObject);
   }

   if ( !fInfo ) return;
   if ( !fInitOffsets ) InitializeOffsets();

   if (fType == 31 || fType == 41) {
     return;
   }
   if (nbranches == 0) {
      fObject += fParentOffset;
      return;
   }
   for (Int_t i=0;i<nbranches;i++)  {
      TBranch *abranch = (TBranch*)fBranches[i];
      abranch->SetAddress(fObject + fBranchOffset[i]);
   }
}

//______________________________________________________________________________
 void TBranchElement::SetAutoDelete(Bool_t autodel)
{
//*-*-*-*-*-*-*-*Set the AutoDelete bit
//*-*            ====================
//  This function can be used to instruct Root in TBranchElement::ReadBasket
//  to not delete the object referenced by a branchelement before reading a
//  new entry. By default, the object is deleted.
//  If autodel is kTRUE, this existing object will be deleted, a new object
//    created by the default constructor, then object->Streamer called.
//  If autodel is kFALSE, the existing object is not deleted. Root assumes
//    that the user is taking care of deleting any internal object or array
//    This can be done in Streamer itself.
//  If this branch has sub-branches, the function sets autodel for these
//  branches as well.
//  We STRONGLY suggest to activate this option by default when you create
//  the top level branch. This will make the read phase more efficient
//  because it minimizes the numbers of new/delete operations.
//  Once this option has been set and the Tree is written to a file, it is
//  not necessary to specify the option again when reading, unless you
//  want to set the opposite mode.
//

   TBranch::SetAutoDelete(autodel);
}

//______________________________________________________________________________
 void TBranchElement::SetBasketSize(Int_t buffsize)
{
// Reset basket size for all subbranches of this branchelement

   TBranch::SetBasketSize(buffsize);

   Int_t nbranches = fBranches.GetEntriesFast();
   for (Int_t i=0;i<nbranches;i++)  {
      TBranch *branch = (TBranch*)fBranches[i];
      branch->SetBasketSize(fBasketSize);
   }
}

//______________________________________________________________________________
 void TBranchElement::SetBranchCount(TBranchElement *bre)
{
// Set the branch count for this branch
   fBranchCount = bre;
   TLeafElement *lfc  = (TLeafElement *)bre->GetListOfLeaves()->At(0);
   TLeafElement *leaf = (TLeafElement *)GetListOfLeaves()->At(0);
   if (lfc && leaf) leaf->SetLeafCount(lfc);
}

//______________________________________________________________________________
 void TBranchElement::Streamer(TBuffer &R__b)
{
   // Stream an object of class TBranchElement.

   if (R__b.IsReading()) {
      TBranchElement::Class()->ReadBuffer(R__b, this);
      fParentClass.SetName(fParentName);
      fBranchClass.SetName(fClassName);
   } else {
      TDirectory *dirsav = fDirectory;
      fDirectory = 0;  // to avoid recursive calls

      TBranchElement::Class()->WriteBuffer(R__b, this);

      // make sure that all TStreamerInfo objects referenced by
      // this class are written to the file
      if (fInfo) fInfo->ForceWriteInfo((TFile *)R__b.GetParent(), kTRUE);

      // if branch is in a separate file save this branch
      // as an independent key
      if (!dirsav) return;
      if (!dirsav->IsWritable()) {fDirectory = dirsav; return;}
      TDirectory *pdirectory = fTree->GetDirectory();
      if (!pdirectory) {fDirectory = dirsav; return;}
      const char *treeFileName = pdirectory->GetFile()->GetName();
      TBranch *mother = GetMother();
      const char *motherFileName = treeFileName;
      if (mother && mother != this) {
         motherFileName = mother->GetFileName();
      }
      if (fFileName.Length() > 0 && strcmp(motherFileName,fFileName.Data())) {
         TDirectory *cursav = gDirectory;
         dirsav->cd();
         Write();
         cursav->cd();
      }
      fDirectory = dirsav;
   }
}

//______________________________________________________________________________
 Int_t TBranchElement::Unroll(const char *name, TClass *cltop, TClass *cl,Int_t basketsize, Int_t splitlevel, Int_t btype)
{
// unroll base classes and loop on all elements of class cl

   if (cl == TObject::Class() && cltop->CanIgnoreTObjectStreamer()) return 0;
   Bool_t optim = TStreamerInfo::CanOptimize();
   if (splitlevel > 0) TStreamerInfo::Optimize(kFALSE);
   TStreamerInfo *info = fTree->BuildStreamerInfo(cl);
   TStreamerInfo::Optimize(optim);
   if (!info) return 0;
   TClass *clbase;
   Int_t ndata = info->GetNdata();
   ULong_t *elems = info->GetElems();
   TStreamerElement *elem;
   TBranchElement *branch;
   char branchname[kMaxLen];
   Int_t jd = 0;
   Int_t unroll = 0;
   if (ndata==1 && cl->GetCollectionProxy() && 
      strcmp(((TStreamerElement*)elems[0])->GetName(),"This")==0) {
      // This streamerInfo only refers to the collection itself
      return 1;
   }
   for (Int_t i=0;i<ndata;i++) {
      elem = (TStreamerElement*)elems[i];
      Int_t offset = elem->GetOffset();
      char *oldPointer = fBranchPointer;
      if (gDebug > 0) printf("Unroll name=%s, cltop=%s, cl=%s, i=%d, elem=%s, offset=%d, splitlevel=%d, fBranchPointer=%lx, btype=%d \n",name,cltop->GetName(),cl->GetName(),i,elem->GetName(),elem->GetOffset(),splitlevel,(Long_t)fBranchPointer,btype);
      if (elem->IsA() == TStreamerBase::Class()) {
         clbase = gROOT->GetClass(elem->GetName());

         if (clbase->Property() & kIsAbstract) {
            if (cl->InheritsFrom("TCollection")) unroll = -1;
         }
         if (unroll < 0 && (btype != 31 || btype != 41)) return -1;

         if (gDebug > 0) printf("Unrolling base class, cltop=%s, clbase=%s\n",cltop->GetName(),clbase->GetName());
         if (btype==31 || btype==41) {
            fBranchPointer += offset;
            unroll = Unroll(name,cltop,clbase,basketsize,splitlevel-1,btype);
            fBranchPointer = oldPointer;
            if (unroll < 0) {
               if (strlen(name)) sprintf(branchname,"%s.%s",name,elem->GetFullName());
               else              sprintf(branchname,"%s",elem->GetFullName());
               branch = new TBranchElement(branchname,info,jd,0,basketsize,0,btype);
               branch->SetParentClass(cltop);
               fBranches.Add(branch);
            }
         } else if (clbase->GetListOfRealData()->GetSize()!=0) {

            // We do not create a branch for an empty base class:
            char *pointer = fBranchPointer + offset;
            if (strlen(name)) {
               sprintf(branchname,"%s.%s",name,elem->GetFullName());
               // First claim that we have the short name (to fool the children)
               branch = new TBranchElement(name,info,jd,pointer,basketsize,splitlevel,btype);
               // Then reset it to the proper name
               branch->SetName(branchname);
               branch->SetTitle(branchname);
            } else {
               sprintf(branchname,"%s",elem->GetFullName());
               branch = new TBranchElement(branchname,info,jd,pointer,basketsize,splitlevel,btype);
            }
            // branch = new TBranchElement(branchname,info,jd,pointer,basketsize,splitlevel-1,btype);
            branch->SetParentClass(cltop);
            fBranches.Add(branch);
            if (0 && unroll < 0) {
               branch = new TBranchElement(branchname,info,jd,0,basketsize,0,btype);
               branch->SetParentClass(cltop);
               fBranches.Add(branch);
            }
         }
      } else {
         if (strlen(name)) sprintf(branchname,"%s.%s",name,elem->GetFullName());
         else              sprintf(branchname,"%s",elem->GetFullName());
         if (  splitlevel > 1 &&
               ( elem->IsA() == TStreamerObject::Class() || elem->IsA() == TStreamerObjectAny::Class() ) ) {

            clbase = gROOT->GetClass(elem->GetTypeName());
            if (clbase->Property() & kIsAbstract) return -1;

            if (gDebug > 0) printf("Unrolling object class, cltop=%s, clbase=%s\n",cltop->GetName(),clbase->GetName());
            fBranchPointer += offset;
            if (elem->CannotSplit()) {

               unroll = -1;

            } else if  (clbase->InheritsFrom(TClonesArray::Class())) {

               branch = new TBranchElement(branchname,info,jd,fBranchPointer ,basketsize,splitlevel-1,btype);
               branch->SetParentClass(cltop);
               fBranches.Add(branch);
               unroll = 0;

            } else {

               unroll = Unroll(branchname,cltop,clbase,basketsize,splitlevel-1,btype);
            }
            fBranchPointer = oldPointer;
            if (unroll < 0) {
               char *pointer = fBranchPointer + offset;
               branch = new TBranchElement(branchname,info,jd,pointer,basketsize,0,btype);
               branch->SetParentClass(cltop);
               fBranches.Add(branch);
            }
         } else if (elem->IsA() == TStreamerSTL::Class() && !elem->IsaPointer()) {
            // here all STL classes are handled
            Int_t subSplitlevel = splitlevel-1;
            if (btype == 31 || btype == 41 || elem->CannotSplit()) {
               subSplitlevel = 0;
            }
            char* pointer = fBranchPointer + offset;
            branch = new TBranchElement(branchname,info,jd,/* 0 */ pointer ,basketsize,subSplitlevel,btype);
            branch->SetParentClass(cltop);
            fBranches.Add(branch);

         } else {
            //fBranchPointer may be null in case of a TClonesArray inside another TClonesArray
            if ((btype != 31 && btype != 41) && fBranchPointer &&
                ( elem->GetClassPointer() == TClonesArray::Class()
                  || (elem->IsA() == TStreamerSTL::Class() && !elem->CannotSplit())
                  )
                ) {
               //process case of a TClonesArray in a derived class
               char *pointer = fBranchPointer + offset;
               branch = new TBranchElement(branchname,info,jd,pointer,basketsize,splitlevel-1,btype);
            } else {
               branch = new TBranchElement(branchname,info,jd,0,basketsize,0,btype);
               branch->SetType(btype);
            }
            branch->SetParentClass(cltop);
            fBranches.Add(branch);
         }
      }
      jd++;
   }
   return 1;
}

//______________________________________________________________________________
 TVirtualCollectionProxy *TBranchElement::GetCollectionProxy()
{
   if (fCollProxy) return fCollProxy;

   TBranchElement *thiscast = const_cast<TBranchElement*>(this);
   if (fType==4 ) {

      const char *ty;
      if (fID>=0) ty = ((TStreamerElement*)thiscast->GetInfo()->GetElems()[fID])->GetTypeName();
      else ty = fClassName.Data();
      TClass *cl = gROOT->GetClass(ty);
      fCollProxy = cl->GetCollectionProxy()->Generate();
      fSTLtype   = TClassEdit::IsSTLCont(ty);
      if ( fSTLtype<0 ) fSTLtype = -fSTLtype;
   } else if(fType==41) {
      thiscast->fCollProxy = fBranchCount->fCollProxy;
   }
   return fCollProxy;
}


ROOT page - Class index - Class Hierarchy - Top of the page

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.