    // @(#)root/meta:$Name:  $:$Id: TStreamerInfo.cxx,v 1.226 2005/06/23 18:19:26 pcanal Exp $
    // Author: Rene Brun   12/10/2000

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

    //////////////////////////////////////////////////////////////////////////
    //                                                                      //
    //                                                                      //
    //////////////////////////////////////////////////////////////////////////

    #include "TROOT.h"
    #include "TStreamerInfo.h"
    #include "TStreamerElement.h"
    #include "TClass.h"
    #include "TClassEdit.h"
    #include "TDataMember.h"
    #include "TMethodCall.h"
    #include "TDataType.h"
    #include "TRealData.h"
    #include "TBaseClass.h"
    #include "TBuffer.h"
    #include "TArrayC.h"
    #include "TArrayI.h"
    #include "TArrayF.h"
    #include "TArrayD.h"
    #include "TArrayS.h"
    #include "TArrayL.h"
    #include "TError.h"
    #include "TRef.h"
    #include "TProcessID.h"
    #include "TVirtualCollectionProxy.h"
    #include "TStreamer.h"
    #include "TInterpreter.h"
    #include "TContainerConverters.h"

    Int_t   TStreamerInfo::fgCount = 0;
    Bool_t  TStreamerInfo::fgCanDelete        = kTRUE;
    Bool_t  TStreamerInfo::fgOptimize         = kTRUE;
    Bool_t  TStreamerInfo::fgStreamMemberWise = kFALSE;
    TStreamerElement *TStreamerInfo::fgElement = 0;

    const Int_t kRegrouped = TStreamerInfo::kOffsetL;

    const Int_t kMaxLen = 1024;

    ClassImp(TStreamerInfo)

    //______________________________________________________________________________
     TStreamerInfo::TStreamerInfo()
    {
       // Default ctor.

       fNumber   = fgCount;
       fClass    = 0;
       fElements = 0;
       fComp     = 0;
       fType     = 0;
       fNewType  = 0;
       fOffset   = 0;
       fLength   = 0;
       fElem     = 0;
       fMethod   = 0;
       fCheckSum = 0;
       fNdata    = 0;
       fSize     = 0;
       fClassVersion = 0;
       fOptimized = kFALSE;
       fOldVersion = Class()->GetClassVersion();
       fIsBuilt  = kFALSE;
    }

    //______________________________________________________________________________
     TStreamerInfo::TStreamerInfo(TClass *cl, const char *info)
       : TNamed(cl->GetName(),info)
    {
       // Create a TStreamerInfo object.

       fgCount++;
       fNumber   = fgCount;
       fClass    = cl;
       fElements = new TObjArray();
       fComp     = 0;
       fType     = 0;
       fNewType  = 0;
       fOffset   = 0;
       fLength   = 0;
       fElem     = 0;
       fMethod   = 0;
       fCheckSum = 0;
       fNdata    = 0;
       fSize     = 0;
       fOptimized = kFALSE;
       fIsBuilt  = kFALSE;
       fClassVersion = fClass->GetClassVersion();
       fOldVersion = Class()->GetClassVersion();

       if (info) BuildUserInfo(info);

    }

    //______________________________________________________________________________
     TStreamerInfo::~TStreamerInfo()
    {
       // TStreamerInfo dtor.

       delete [] fType;    fType   =0;
       delete [] fNewType; fNewType=0;
       delete [] fOffset;  fOffset =0;
       delete [] fLength;  fLength =0;
       delete [] fElem;    fElem   =0;
       delete [] fMethod;  fMethod =0;
       delete [] fComp;    fComp   =0;

       if (!fElements) return;
       fElements->Delete();
       delete fElements; fElements=0;
    }

    //______________________________________________________________________________
     void TStreamerInfo::Build()
    {
       // Build the I/O data structure for the current class version
       // A list of TStreamerElement derived classes is built by scanning
       // one by one the list of data members of the analyzed class.

       // This is used to avoid unwanted recursive call to Build
       fIsBuilt = kTRUE;

       if (fClass->GetCollectionProxy()) {
          TStreamerElement *element = new TStreamerSTL("This","Used to call the proper TStreamerInfo case",0,fClass->GetName(),fClass->GetName(),0);
          fElements->Add(element);
          Compile();
          return;
       }

       TStreamerElement::Class()->IgnoreTObjectStreamer();
       //if (!strcmp(fClass->GetName(),"TVector3"))       fClass->IgnoreTObjectStreamer();

       fClass->BuildRealData();

       fCheckSum = fClass->GetCheckSum();
       Int_t i, ndim, offset;
       TClass *clm;
       TDataType *dt;
       TDataMember *dm;
       TBaseClass *base;
       TStreamerElement *element;
       TIter nextb(fClass->GetListOfBases());
       TMemberStreamer *streamer = 0;

       //iterate on list of base classes
       while((base = (TBaseClass*)nextb())) {
          element  = 0;
          offset   = base->GetDelta();
          if (offset == kMissing) continue;
          streamer = 0; // base->GetStreamer();
          do { //do block in while
             const char* bname  = base->GetName();
             const char* btitle = base->GetTitle();
             // this case appears with STL collections as base class.
             if (strcmp(bname,"string") == 0) {
                element = new TStreamerSTLstring(bname,btitle,offset,bname,kFALSE);
                continue;
             }
             if (base->IsSTLContainer()) {
                element = new TStreamerSTL(bname,btitle,offset,bname,0,kFALSE);
    //             if (!streamer)  element->SetType(-1);
                continue;
             }
             element = new TStreamerBase(bname,btitle,offset);
             clm = element->GetClassPointer();
             if (!clm) {
                Error("Build","%s, unknown type: %s %s\n",GetName(),bname,btitle);
                delete element;
                element = 0;
                continue;
             }
             clm->GetStreamerInfo();
             if (clm == TObject::Class() && fClass->CanIgnoreTObjectStreamer()) {
                SetBit(TClass::kIgnoreTObjectStreamer);
                element->SetType(-1);
             }
             if (!clm->IsLoaded()) {
                Warning("Build:","%s: base class %s has no streamer or dictionary it will not be saved",
                         GetName(), clm->GetName());
             }
          } while(0); {
             // continue block in while

             if (!element) continue;
             fElements->Add(element);
    //          element->SetStreamer(streamer);
          }//end continue block
       }//end base class loop

       //iterate on list of data members
       TIter nextd(fClass->GetListOfDataMembers());

       Int_t dsize,dtype;
       while((dm=(TDataMember*)nextd()))  {
          if (fClass->GetClassVersion() == 0) continue;
          if (!dm->IsPersistent())            continue;
          streamer = 0;
          offset = GetDataMemberOffset(dm,streamer);
          if (offset == kMissing)             continue;
    //       streamer = dm->GetStreamer();
          element = 0;
          dsize   = 0;

          do { //do block in while
             const char* dmName = dm->GetName();
             const char* dmType = dm->GetTypeName();
             const char* dmFull = dm->GetFullTypeName();
             const char* dmTitle = dm->GetTitle();
             bool        dmIsPtr = dm->IsaPointer();

             //look for a data member with a counter in the comment string [n]
             TDataMember *dmref = 0;
             if (dmIsPtr) {
                const char *lbracket = ::strchr(dmTitle,'[');
                const char *rbracket = ::strchr(dmTitle,']');
                if (lbracket && rbracket) {
                   const char* index = dm->GetArrayIndex();
                   TRealData *refcount = (TRealData*)fClass->GetListOfRealData()->FindObject(index);
                   if (!refcount) {
                      Error("Build","%s, discarding: %s %s, illegal %s\n",GetName(),dmFull,dmName,dmTitle);
                      continue;
                   }
                   dmref = refcount->GetDataMember();
                   TDataType *reftype = dmref->GetDataType();
                   Bool_t isInteger = reftype->GetType() == 3 || reftype->GetType() == 13;
                   if (!reftype || !isInteger) {
                      Error("Build","%s, discarding: %s %s, illegal [%s] (must be Int_t)\n",GetName(),dmFull,dmName,index);
                      continue;
                   }
                   TStreamerBasicType *bt = TStreamerInfo::GetElementCounter(index,dmref->GetClass());
                   if (!bt) {
                      if (dmref->GetClass()->Property() & kIsAbstract) continue;
                      Error("Build","%s, discarding: %s %s, illegal [%s] must be placed before \n",GetName(),dmFull,dmName,index);
                      continue;
                   }
                }
             }

             dt=dm->GetDataType();

             if (dt) {  // found a basic type
                dtype = dt->GetType();
                dsize = dt->Size();
                if (!dmref && (strstr(dmFull,"char*") || strstr(dmFull,"Char_t*"))) {
                   dtype = kCharStar;
                   dsize = sizeof(char*);
                }
                if (dmIsPtr && dtype != kCharStar) {
                   if (dmref) {
                      // data member is pointer to an array of basic types
                      element = new TStreamerBasicPointer(dmName,dmTitle,offset,dtype,
                                                          dm->GetArrayIndex(),
                                                          dmref->GetClass()->GetName(),
                                                          dmref->GetClass()->GetClassVersion(),
                                                          dmFull);
                      continue;
                   } else {
                      if (fName == "TString" || fName == "TClass") continue;
                      Error("Build","%s, discarding: %s %s, no [dimension]\n",GetName(),dmFull,dmName);
                      continue;
                   }
                }
                // data member is a basic type
                if (fClass == TObject::Class() && !strcmp(dmName,"fBits")) {
                   //printf("found fBits, changing dtype from %d to 15\n",dtype);
                   dtype = kBits;
                }
                element = new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
                continue;

             }  else {
                // try STL container or string
                static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
                if (strcmp(dmType,"string") == 0 || strcmp(dmType,full_string_name)==0 ) {
                   element = new TStreamerSTLstring(dmName,dmTitle,offset,dmFull,dmIsPtr);
                   continue;
                }
                if (dm->IsSTLContainer()) {
                   element = new TStreamerSTL(dmName,dmTitle,offset,dmFull,dm->GetTrueTypeName(),dmIsPtr);
                   continue;
                }
                clm = gROOT->GetClass(dmType);
                if (!clm) {
                   Error("Build","%s, unknow type: %s %s\n",GetName(),dmFull,dmName);
                   continue;
                }
                // a pointer to a class
                if ( dmIsPtr ) {
                   if(dmref) {
                      element = new TStreamerLoop(dmName,
                                                  dmTitle,offset,
                                                  dm->GetArrayIndex(),
                                                  dmref->GetClass()->GetName(),
                                                  dmref->GetClass()->GetClassVersion(),
                                                  dmFull);
                      continue;
                   } else {
                      if (clm->InheritsFrom(TObject::Class())) {
                         element = new TStreamerObjectPointer(dmName,dmTitle,offset,dmFull);
                         continue;
                      } else {
                         element = new TStreamerObjectAnyPointer(dmName,dmTitle,offset,dmFull);
                         if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
                            Error("Build:","%s: %s has no streamer or dictionary, data member %s will not be saved",
                                  GetName(), dmFull,dmName);
                         }
                         continue;
                      }
                   }
                }
                // a class
                if (clm->InheritsFrom(TObject::Class())) {
                   element = new TStreamerObject(dmName,dmTitle,offset,dmFull);
                   continue;
                } else if(clm == TString::Class() && !dmIsPtr) {
                   element = new TStreamerString(dmName,dmTitle,offset);
                   continue;
                } else {
                   element = new TStreamerObjectAny(dmName,dmTitle,offset,dmFull);
                   if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
                      Warning("Build:","%s: %s has no streamer or dictionary, data member \"%s\" will not be saved",
                              GetName(), dmFull,dmName);
                   }
                   continue;
                }
             }
          } while(0); {//continue block

             if(!element)  continue;
             ndim = dm->GetArrayDim();
             if (!dsize) dsize = dm->GetUnitSize();
             for (i=0;i<ndim;i++) element->SetMaxIndex(i,dm->GetMaxIndex(i));
             element->SetArrayDim(ndim);
             int narr = element->GetArrayLength(); if (!narr) narr = 1;
             element->SetSize(dsize*narr);
             element->SetStreamer(streamer);
             fElements->Add(element);
             if (streamer) continue;
             int k = element->GetType();
    //          if (k!=kSTL && k!=kSTL+kOffsetL && k!=kStreamer && k!=kStreamLoop) continue;
             if (k!=kStreamer && k!=kStreamLoop) continue;
             element->SetType(-1);

          }//end continue block
       }//end member loop

       Compile();

    }

    //______________________________________________________________________________
     void TStreamerInfo::BuildCheck()
    {
       // check if the TStreamerInfo structure is already created
       // called by TFile::ReadStreamerInfo

       fClass = gROOT->GetClass(GetName());
       TObjArray *array;
       if (fClass) {

          if (TClassEdit::IsSTLCont(fClass->GetName())) return;

          array = fClass->GetStreamerInfos();
          TStreamerInfo *info = 0;

          // If we have a foreign class, we need to search for a StreamerInfo
          // with same checksum.
          Bool_t searchOnChecksum = kFALSE;
          if( !fClass->IsLoaded() ) {
             // When the class is not loaded
             // the result of IsForeign is not what we are looking
             // for (Technically IsForeign means IsLoaded and do not
             // have a Streamer method).

             // A foreign class would have the ClassVersion equal to 1
             // Also we only care if a StreamerInfo has already been loaded
             TStreamerInfo *v1;
             if ( fClassVersion==1 && (v1=(TStreamerInfo*)array->At(1)) != 0 ) {
                if (fCheckSum != v1->GetCheckSum()) {
                   searchOnChecksum = kTRUE;
                   fClassVersion = array->GetLast()+1;
                }
             }
          } else if (fClass->IsForeign()) {
             searchOnChecksum = kTRUE;
          }

          if (searchOnChecksum) {
             Int_t ninfos = array->GetEntriesFast();
             for (Int_t i=1;i<ninfos;i++) {
                info = (TStreamerInfo*)array->UncheckedAt(i);
                if (!info) continue;
                if (fCheckSum == info->GetCheckSum()) {
                   fClassVersion = i;
                   //printf("found class with checksum, version=%d\n",i);
                   break;
                } else {
                   info = 0;
                }
             }
          } else {
             info = (TStreamerInfo *)array->At(fClassVersion);
          }
          // NOTE: Should we check if the already existing info is the same as
          // the current one? Yes
          // In case a class (eg Event.h) has a TClonesArray of Tracks, it could be
          // that the old info does not have the class name (Track) in the data
          // member title. Set old title to new title
          if (info) {

             if (info->IsBuilt()) {
                SetBit(kCanDelete);
                fNumber = info->GetNumber();
                Int_t nel = fElements->GetEntriesFast();
                TObjArray *elems = info->GetElements();
                TStreamerElement *e1, *e2;
                for (Int_t i=0;i<nel;i++) {
                   e1 = (TStreamerElement *)fElements->UncheckedAt(i);
                   e2 = (TStreamerElement *)elems->At(i);
                   if (!e1 || !e2) continue;
                   if (strlen(e1->GetTitle()) != strlen(e2->GetTitle())) {
                      e2->SetTitle(e1->GetTitle());
                   }
                }
                return;
             } else {
                array->RemoveAt(fClassVersion);
                delete info; info = 0;
             }
          }
          if (fClass->GetListOfDataMembers()
              && (fClassVersion == fClass->GetClassVersion())
              && (fCheckSum != fClass->GetCheckSum())
              && (fClass->GetClassInfo()) ) {
             //give a last chance. Due to a new CINT behaviour with enums
             //verify the checksum ignoring members of type enum
             if (fCheckSum != fClass->GetCheckSum(1)) {
                if (fClass->IsForeign()) {
                   fClassVersion = fClass->GetClassVersion() + 1;
                   //printf("setting fClassVersion=%d\n",fClassVersion);
                } else {
                   int warn = 1;
                   if (fOldVersion<=2) {
                      // Names of STL base classes was modified in vers==3. Allocators removed
                      //
                      TIter nextBC(fClass->GetListOfBases());
                      TBaseClass *bc;
                      while ((bc=(TBaseClass*)nextBC()))
                      {if (TClassEdit::IsSTLCont(bc->GetName())) warn = 0;}
                   }

                   if (warn) Warning("BuildCheck","\n\
            The StreamerInfo of class %s read from file %s\n\
            has the same version (=%d) as the active class but a different checksum.\n\
            You should update the version to ClassDef(%s,%d).\n\
            Do not try to write objects with the current class definition,\n\
            the files will not be readable.\n",GetName(),gDirectory->GetFile()->GetName()
                                  ,fClassVersion,GetName(),fClassVersion+1);
                }
             }
          } else {
             if (info) {
                Error("BuildCheck","Wrong class info");
                SetBit(kCanDelete);
                return;
             }
          }
       } else {
          fClass = new TClass(GetName(),fClassVersion, 0, 0, -1, -1 );
          fClass->SetBit(TClass::kIsEmulation);
          array = fClass->GetStreamerInfos();
       }
       if (TestBit(TClass::kIgnoreTObjectStreamer)) fClass->IgnoreTObjectStreamer();
       if (fClassVersion < 0 || fClassVersion > 65000) {
          printf("ERROR reading TStreamerInfo: %s fClassVersion=%d\n",GetName(),fClassVersion);
          SetBit(kCanDelete);
          fNumber = -1;
          return;
       }
       array->AddAtAndExpand(this,fClassVersion);
       fgCount++;
       fNumber = fgCount;

       // Since we just read this streamerInfo from file, it has already been built.
       fIsBuilt = kTRUE;

       //add to the global list of StreamerInfo
       TObjArray *infos = (TObjArray*)gROOT->GetListOfStreamerInfo();
       infos->AddAtAndExpand(this,fNumber);
    }

    //______________________________________________________________________________
     void TStreamerInfo::BuildEmulated(TFile *file)
    {
       // Create an Emulation TStreamerInfo object.
       char duName[100];
       Assert(file);
       Int_t fv = file->GetVersion()%100000;
       Assert(fv < 30000);
       fClassVersion = -1;
       fCheckSum = 2001;
       TObjArray *elements = GetElements();
       if (!elements) return;
       Int_t ndata = elements->GetEntries();
       if (ndata == 0) return;
       TStreamerElement *element;
       Int_t i;
       for (i=0;i<ndata;i++) {
          element = (TStreamerElement*)elements->UncheckedAt(i);
          if (!element) break;
          int ty = element->GetType();
          if (ty < kChar || ty >kULong+kOffsetL)    continue;
          if (ty == kLong )                         element->SetType(kInt          );
          if (ty == kULong)                         element->SetType(kUInt         );
          if (ty == kLong +kOffsetL)                element->SetType(kInt +kOffsetL);
          if (ty == kULong+kOffsetL)                element->SetType(kUInt+kOffsetL);
          if (ty <= kULong)                         continue;
          strcpy(duName,element->GetName());
          strcat(duName,"QWERTY");
          TStreamerBasicType *bt = new TStreamerBasicType(duName, "", 0, kInt,"Int_t");
          {for (int j=ndata-1;j>=i;j--) {elements->AddAtAndExpand(elements->At(j),j+1);}}
          elements->AddAt(bt,i);
          ndata++;
          i++;
       }
       BuildOld();
    }

    //______________________________________________________________________________
    // Helper function for BuildOld
    namespace {
       Bool_t ClassWasMovedToNamespace(TClass *oldClass, TClass *newClass)
       {
          // Returns true if oldClass is the same as newClass but newClass is in a
          // namespace (and oldClass was not in a namespace).

          if (oldClass == 0 || newClass == 0) return kFALSE;

          UInt_t newlen = strlen(newClass->GetName());
          UInt_t oldlen = strlen(oldClass->GetName());

          const char *oldname = oldClass->GetName();
          for(UInt_t i = oldlen, done = false, nest = 0; (i>0) && !done ; --i) {
             switch ( oldClass->GetName()[i-1] ) {
                case '>' : ++nest; break;
                case '<' : --nest; break;
                case ':' : if (nest==0) oldname= &(oldClass->GetName()[i]); done = kTRUE; break;
             }
          }
          oldlen = strlen(oldname);
          if ( ! (strlen(newClass->GetName()) > strlen(oldClass->GetName()) ) ) return kFALSE;

          const char* newEnd = & ( newClass->GetName()[ newlen - oldlen ] );

          if (0 != strcmp( newEnd, oldname ) ) return kFALSE;

          Int_t oldv = oldClass->GetStreamerInfo()->GetClassVersion();

          if (   newClass->GetStreamerInfos()
              && oldv < newClass->GetStreamerInfos()->GetSize()
              && newClass->GetStreamerInfos()->At(oldv)
              && strcmp( newClass->GetStreamerInfos()->At(oldv)->GetName(),
                         oldClass->GetName() ) != 0 ) {
             // The new class has already a TStreamerInfo for the the same version as
             // the old class and this was not the result of an import.  So we do not
             // have a match
             return kFALSE;
          }
          return kTRUE;
       }

       Int_t ImportStreamerInfo(TClass *oldClass, TClass *newClass) {
          // Import the streamerInfo from oldClass to newClass
          // In case of conflict, returns the version number of the StreamerInfo
          // with the conflict.
          // Return 0 in case of success

          TIter next(oldClass->GetStreamerInfos());
          TStreamerInfo *info;
          while ((info = (TStreamerInfo*)next())) {
             info = (TStreamerInfo*)info->Clone();
             info->SetClass(newClass);
             Int_t oldv = info->GetClassVersion();
             if (   oldv > newClass->GetStreamerInfos()->GetSize()
                 || newClass->GetStreamerInfos()->At(oldv)==0 ) {
                // All is good.
                newClass->GetStreamerInfos()->AddAtAndExpand(info,oldv);
             } else {
                // We verify that we are consitent and that
                //   newcl->GetStreamerInfos()->UncheckedAt(info->GetClassVersion)
                // is already the same as info.
                if ( strcmp( newClass->GetStreamerInfos()->At(oldv)->GetName(),
                             oldClass->GetName() ) != 0 ) {
                   // The existing StreamerInfo does not already come from OldClass.
                   // This is a real problem!
                   return oldv;
                }
             }
          }
          return 0;
       }

       Bool_t ContainerMatchTClonesArray(TClass *newClass)
       {
          // Return true if newClass is a likely valid conversion from
          // a TClonesArray

          return newClass->GetCollectionProxy()
                 && newClass->GetCollectionProxy()->GetValueClass()
                 && !newClass->GetCollectionProxy()->HasPointers();
       }

       Bool_t CollectionMatch(const TClass *oldClass, const TClass* newClass)
       {
          // Return true if oldClass and newClass points to 2 compatible collection.
          // i.e. they contains the exact same type.

          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
          TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();

          if (oldProxy->GetValueClass() == newProxy->GetValueClass()) {
             if (  (oldProxy->GetValueClass() ==0 && oldProxy->GetType() == newProxy->GetType())
                 ||(oldProxy->GetValueClass() && oldProxy->HasPointers() == newProxy->HasPointers()) ) {
                // We have compatibles collections (they have the same content!
                return kTRUE;
             }
          }
          return kFALSE;
       }
    }

    //______________________________________________________________________________
     void TStreamerInfo::BuildOld()
    {
       // rebuild the TStreamerInfo structure

       if (gDebug > 0) printf("\n====>Rebuilding TStreamerInfo for class: %s, version: %d\n",GetName(),fClassVersion);

       // This is used to avoid unwanted recursive call to Build
       fIsBuilt = kTRUE;

       if (fClass->GetClassVersion()==fClassVersion)  {
          fClass->BuildRealData();
       }
       else {
          // This is to support the following case
          //  Shared library: Event v2
          //  calling cl->GetStreamerInfo(1)->BuildOld();  (or equivalent)
          //  which calls cl->BuildReadData()
          //  which set fRealData to some value
          //  then call Event()
          //  which call cl->GetStreamerInfo()
          //  which call cl->BuildRealData();
          //  which returns immediately (upon seeing fRealData!=0)
          //  then the main StreamerInfo build using the partial content of fRealData
          //  then BuildRealData returns
          //  then GetStreamerInfo() returns
          //  then Event() returns
          //  then fRealData is finished being populated
          //  then this function continue,
          //  then it uses the main streamerInfo
          //  .... which is incomplete.
          //
          //  Instead we force the creation of the main streamerInfo object
          //  before the creation of fRealData.
          fClass->GetStreamerInfo();
       }

       if (fClass->GetCollectionProxy() &&
          fElements->GetEntries()==1 &&
          strcmp(fElements->At(0)->GetName(),"This")==0) {
       }
       TIter next(fElements);
       TStreamerElement *element;
       Int_t offset = 0;
       TMemberStreamer *streamer = 0;
       Int_t sp = sizeof(void *);
    #if defined(R__SGI64)
       sp = 8;
    #endif
       int nBaze=0;
       if (fClass->GetCollectionProxy() &&
          fElements->GetEntries()==1 &&
          strcmp(fElements->At(0)->GetName(),"This")==0) {
          next();
       }
       while ((element = (TStreamerElement*)next())) {
          element->SetNewType(element->GetType());
          element->Init();

          if (element->IsBase()) {

             if (element->IsA()==TStreamerBase::Class()) {

                TStreamerBase *base = (TStreamerBase*)element;
                TClass *baseclass = base->GetClassPointer();
                if (!baseclass) {
                   Warning("BuildOld","Missing base class: %s skipped",base->GetName());
                   baseclass = new TClass(element->GetName(),1,0,0,-1,-1);
                   element->Update(0,baseclass);
                }
                baseclass->BuildRealData();
                Int_t version = base->GetBaseVersion();
                TStreamerInfo *infobase = baseclass->GetStreamerInfo(version);
                if (infobase->GetTypes() == 0) infobase->BuildOld();
                Int_t baseOffset = fClass->GetBaseClassOffset(baseclass);
                if (baseOffset < 0) baseOffset = 0;
                element->SetOffset(baseOffset);
                offset += baseclass->Size();
                continue;

             } else {

                // Not a base elem but still base, string or STL as a base
                nBaze++;
                TBaseClass *bc  = 0;
                TList *listOfBases = fClass->GetListOfBases();
                if (listOfBases) {
                   TIter nextBC(fClass->GetListOfBases());
                   while ((bc=(TBaseClass*)nextBC())) {

                      if (strchr(bc->GetName(),'<')!=0 ||
                          strcmp(bc->GetName(),"string")==0) {
                         TString bcName( TClassEdit::ShortType(bc->GetName()         ,TClassEdit::kDropStlDefault).c_str() );
                         TString elName( TClassEdit::ShortType(element->GetTypeName(),TClassEdit::kDropStlDefault).c_str() );
                         if (bcName==elName) break;

                      }
                   }

                }
                if (bc==0) {
                   Error("BuildOld","Could not find STL base class: %s for %s\n",
                         element->GetName(),GetName());
                   continue;
                }
                int baseOffset = bc->GetDelta();
                if (baseOffset==-1) {
                   TClass *cb = element->GetClassPointer();
                   if (!cb) { element->SetNewType(-1); continue;}
                   baseOffset = fClass->GetBaseClassOffset(cb);
                }
                //  we know how to read but do we know where to read?
                if (baseOffset<0) { element->SetNewType(-1); continue;}
                element->SetOffset(baseOffset);
                continue;
             }
          }

          TDataMember *dm = 0;

          // First set the offset and sizes.
          if (fClass->GetDeclFileLine() < 0) {

             // Note the initilization in this case are
             // delayed until __after__ the schema evolution
             // section, just in case the info has changed.

             // We are in the emulated case
             streamer = 0;
             element->Init(fClass);

          } else {
             // The class is loaded.

             // First look for the data member in the current class
             dm = (TDataMember*)fClass->GetListOfDataMembers()->FindObject(element->GetName());
             if (dm && dm->IsPersistent()) {
                fClass->BuildRealData();
                streamer = 0;
                offset = GetDataMemberOffset(dm,streamer);
                element->SetOffset(offset);
                element->Init(fClass);
                element->SetStreamer(streamer);
                int narr = element->GetArrayLength(); if (!narr) narr=1;
                int dsize = dm->GetUnitSize();
                element->SetSize(dsize*narr);

             } else {
                // We did not find it, let's look for it in the base classes via TRealData
                TRealData *rd = fClass->GetRealData(element->GetName());
                if (rd && rd->GetDataMember() ) {
                   element->SetOffset(rd->GetThisOffset());
                   element->Init(fClass);
                   dm = rd->GetDataMember();
                   int narr = element->GetArrayLength(); if (!narr) narr=1;
                   int dsize = dm->GetUnitSize();
                   element->SetSize(dsize*narr);
                }
             }
          }

          // Now let's deal with Schema evolution
          Int_t newType = kNoType_t;
          TClassRef newClass;
          if (dm && dm->IsPersistent()) {
             if (dm->GetDataType()) {
                Bool_t isPointer = dm->IsaPointer();
                bool   isArray   = element->GetArrayLength() > 1;
                bool   hasCount  = element->HasCounter();
                newType = dm->GetDataType()->GetType();
                if (newType == kChar && isPointer && !isArray && !hasCount ) {
                   newType = kCharStar;
                } else if (isPointer) {
                   newType += kOffsetP;
                } else if (isArray) {
                   newType += kOffsetL;
                }
             }
             if (newType==0) newClass = gROOT->GetClass( dm->GetTypeName() );
          } else {
             // Either the class is not loaded or the data member is gone
             if (! fClass->IsLoaded() ) {
                TStreamerInfo *newInfo = (TStreamerInfo*)fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
                if (newInfo && newInfo != this) {
                   TStreamerElement *newElems = (TStreamerElement*)
                      newInfo->GetElements()->FindObject(element->GetName());
                   newClass = newElems ?  newElems->GetClassPointer() : 0;
                   if (newClass==0) {
                      newType = newElems ? newElems->GetType() : kNoType_t;
                      if (! (newType<kObject) ) newType = kNoType_t; // sanity check.
                   }
                } else {
                   newClass = element->GetClassPointer();
                   if (newClass.GetClass()==0) {
                      newType = element->GetType();
                      if (! (newType<kObject) ) newType = kNoType_t; // sanity check.
                   }
                }
             }
          }

          if (newType) {
             // Case of a numerical type
             if (element->GetType() != newType ) {
                element->SetNewType(newType);
                if (gDebug > 0) Warning("BuildOld","element: %s::%s %s has new type: %s/%d",
                                        GetName(),element->GetTypeName(),element->GetName(),
                                        dm->GetFullTypeName(),newType);
             }
          } else if (newClass.GetClass()) {
             // Sometime BuildOld is called again.
             // In that case we migth already have fix up the streamer element.
             // So we need to go back to the original information!
             newClass.Reset();
             TClass *oldClass = gROOT->GetClass(
                TClassEdit::ShortType(element->GetTypeName(),TClassEdit::kDropTrailStar).c_str());
             if (oldClass == newClass.GetClass()) {
                // Nothing to do :)

             } else if ( ClassWasMovedToNamespace(oldClass,newClass.GetClass()) ) {
                Int_t oldv;
                if (0 != (oldv=ImportStreamerInfo(oldClass,newClass.GetClass()))) {
                    Warning("BuildOld","Can not properly load the TStreamerInfo from %s into %s due to a conflict for the class version %d",
                            oldClass->GetName(), newClass->GetName(), oldv);
                } else {
                   element->SetTypeName(dm->GetFullTypeName());

                   if (gDebug>0) Warning("BuildOld","element: %s::%s %s has new type %s",
                                         GetName(),element->GetTypeName(), element->GetName(),
                                         newClass->GetName());
                }

             } else if ( oldClass == TClonesArray::Class() ) {

                if ( ContainerMatchTClonesArray( newClass.GetClass() ) ) {

                   Int_t elemType = element->GetType();
                   Bool_t isPrealloc = elemType==kObjectp || elemType==kAnyp
                      || elemType==kObjectp+kOffsetL || elemType==kAnyp+kOffsetL;

                   element->Update( oldClass, newClass.GetClass() );
                   element->SetStreamer(
                      new TConvertClonesArrayToProxy(newClass->GetCollectionProxy(),
                                                     element->IsaPointer(),
                                                     isPrealloc) );
                   // When the type is kObject, the TObject::Streamer is used instead
                   // of the TStreamerElement's streamer.  So let force the usage
                   // of our streamer
                   if (element->GetType()==kObject) {
                      element->SetNewType(kAny);
                      element->SetType(kAny);
                   }
                   if (gDebug>0) Warning("BuildOld","element: %s::%s %s has new type %s",
                                         GetName(),element->GetTypeName(), element->GetName(),
                                         newClass->GetName());
                } else {
                   element->SetNewType(-2);
                }

             } else if ( oldClass->GetCollectionProxy() &&
                         newClass->GetCollectionProxy() ) {
                if ( CollectionMatch ( oldClass, newClass ) ) {

                   element->Update( oldClass, newClass.GetClass() );
                   // Is this needed ? : element->SetSTLtype(newelement->GetSTLtype());

                   if (gDebug>0) Warning("BuildOld","element: %s::%s %s has new type %s",
                                         GetName(),element->GetTypeName(), element->GetName(),
                                         newClass->GetName());
                } else {
                    element->SetNewType(-2);
                }
             } else {
                element->SetNewType(-2);
             }
          } else {
             element->SetNewType(-1);
             element->SetOffset(kMissing);
          }
          if (element->GetNewType()==-2) {
             Warning("BuildOld","Cannot convert %s::%s from type:%s to type:%s, skip element",
                     GetName(),element->GetName(),element->GetTypeName(),newClass->GetName());
          }

          if (fClass->GetDeclFileLine() < 0) {

             // Note the initilization in this case are
             // delayed until __after__ the schema evolution
             // section, just in case the info has changed.

             Int_t asize = element->GetSize();
             //align the non-basic data types (required on alpha and IRIX!!)
             if (offset%sp != 0) offset = offset - offset%sp + sp;
             element->SetOffset(offset);
             offset += asize;
          }

       }

       // change order , move "bazes" to the end. Workaround old bug
       if (fOldVersion<=2 && nBaze) {
          SetBit(kRecovered);
          TObjArray &arr = *fElements;
          TObjArray  tai(nBaze);
          int narr = arr.GetLast()+1;
          int iel,jel=0,kel=0;
          for (iel=0;iel<narr;iel++) {
             element = (TStreamerElement*)arr[iel];
             if (element->IsBase() && element->IsA()!=TStreamerBase::Class()) tai[kel++] = element;
             else                                        arr[jel++] = element;
          }
          for (kel=0;jel<narr;) arr[jel++]=tai[kel++];
       }

       Compile();
    }
    //______________________________________________________________________________
     void TStreamerInfo::BuildUserInfo(const char * /*info*/)
    {
       // Build the I/O data structure for the current class version

    #ifdef TOBEIMPLEMENTED

       Int_t nch = strlen(title);
       char *info = new char[nch+1];
       strcpy(info,title);
       char *pos = info;
       TDataType *dt;
       TDataMember *dm;
       TRealData *rdm, *rdm1;
       TIter nextrdm(rmembers);

       // search tokens separated by a semicolon
       //tokens can be of the following types
       // -baseclass
       // -class     membername
       // -basictype membername
       // -classpointer     membername
       // -basictypepointer membername
       while(1) {
          Bool_t isPointer = kFALSE;
          while (*pos == ' ') pos++;
          if (*pos == 0) break;
          char *colon = strchr(pos,';');
          char *col = colon;
          if (colon) {
             *col = 0; col--;
             while (*col == ' ') {*col = 0; col--;}
             if (pos > col) break;
             char *star = strchr(pos,'*');
             if (star) {*star = ' '; isPointer = kTRUE;}
             char *blank;
             while(1) {
                blank = strstr(pos,"  ");
                if (blank == 0) break;
                strcpy(blank,blank+1);
             }
             blank = strrchr(pos,' '); //start in reverse order (case like unsigned short xx)
             if (blank) {
                *blank = 0;
                //check that this is a known data member
                dm  = (TDataMember*)members->FindObject(blank+1);
                rdm1 = 0;
                nextrdm.Reset();
                while((rdm = (TRealData*)nextrdm())) {
                   if (rdm->GetDataMember() != dm) continue;
                   rdm1 = rdm;
                   break;
                }
                if (!dm || !rdm1) {
                   printf("Unknown data member:%s %s in class:%s\n",pos,blank+1,fClass->GetName());
                   pos = colon+1;
                   continue;
                }
                // Is type a class name?
                TClass *clt = gROOT->GetClass(pos);
                if (clt) {
                   //checks that the class matches with the data member declaration
                   if (strcmp(pos,dm->GetTypeName()) == 0) {
                      newtype[fNdata] = 20;
                      fNdata++;
                      printf("class: %s member=%s\n",pos,blank+1);
                   } else {
                      printf("Mismatch between class:%s %s and data member:%s %s in class:%s\n",
                             pos,blank+1,dm->GetTypeName(),blank+1,fClass->GetName());
                   }
                   // Is type a basic type?
                } else {
                   dt = (TDataType*)gROOT->GetListOfTypes()->FindObject(pos);
                   if (dt) {
                      Int_t dtype = dt->GetType();
                      //check that this is a valid data member and that the
                      //declared type matches with the data member type
                      if (dm->GetDataType()->GetType() == dtype) {
                         //store type and offset
                         newtype[fNdata]   = dtype;
                         newoffset[fNdata] = rdm->GetThisOffset();
                         fNdata++;
                         printf("type=%s, basic type=%s dtype=%d, member=%s\n",pos,dt->GetFullTypeName(),dtype,blank+1);
                      } else {
                         printf("Mismatch between type:%s %s and data member:%s %s in class:%s\n",
                                pos,blank+1,dm->GetTypeName(),blank+1,fClass->GetName());
                      }

                   } else {
                      printf("found unknown type:%s, member=%s\n",pos,blank+1);
                   }
                }
             } else {
                // very likely a base class
                TClass *base = gROOT->GetClass(pos);
                if (base && fClass->GetBaseClass(pos)) {
                   printf("base class:%s\n",pos);
                   //get pointer to method baseclass::Streamer
                   TMethodCall *methodcall = new TMethodCall(base,"Streamer","");
                   newtype[fNdata]   = 0;
                   newmethod[fNdata] = (ULong_t)methodcall;
                   fNdata++;
                }
             }
             pos = colon+1;
          }
       }
       fType     = new Int_t[fNdata+1];
       fOffset   = new Int_t[fNdata+1];
       fMethod   = new ULong_t[fNdata+1];
       for (Int_t i=0;i<fNdata;i++) {
          fType[i]   = newtype[i];
          fOffset[i] = newoffset[i];
          fMethod[i] = newmethod[i];
       }
       delete [] info;
       delete [] newtype;
       delete [] newoffset;
       delete [] newmethod;
    #endif
    }

    //______________________________________________________________________________
     Bool_t TStreamerInfo::CanDelete()
    {
       // static function returning true if ReadBuffer can delete object
       return fgCanDelete;
    }

    //______________________________________________________________________________
     Bool_t TStreamerInfo::CanOptimize()
    {
       // static function returning true if optimization can be on
       return fgOptimize;
    }

    //______________________________________________________________________________
     void TStreamerInfo::Compile()
    {
       // loop on the TStreamerElement list
       // regroup members with same type
       // Store predigested information into local arrays. This saves a huge amount
       // of time compared to an explicit iteration on all elements.

       TObjArray *infos = (TObjArray*)gROOT->GetListOfStreamerInfo();
       if (fNumber >= infos->GetSize()) {
          infos->AddAtAndExpand(this,fNumber);
       } else {
          if (!infos->At(fNumber)) {
             infos->AddAt(this,fNumber);
          }
       }

       delete [] fType;     fType    = 0;
       delete [] fNewType;  fNewType = 0;
       delete [] fOffset;   fOffset  = 0;
       delete [] fLength;   fLength  = 0;
       delete [] fElem;     fElem    = 0;
       delete [] fMethod;   fMethod  = 0;
       delete [] fComp;     fComp    = 0;

       fOptimized = kFALSE;
       fNdata = 0;
       Int_t ndata = fElements->GetEntries();
       fOffset = new Int_t[ndata+1];
       fType   = new Int_t[ndata+1];
       if (ndata == 0) return;  //this may be the case for empty classes(eg TAtt3D)
       fComp   = new CompInfo[ndata];
       fNewType= new Int_t[ndata];
       fLength = new Int_t[ndata];
       fElem   = new ULong_t[ndata];
       fMethod = new ULong_t[ndata];
       TStreamerElement *element;
       Int_t keep = -1;
       Int_t i;
       if (!fgOptimize) SetBit(kCannotOptimize);
       for (i=0;i<ndata;i++) {
          element = (TStreamerElement*)fElements->At(i);
          if (!element) break;
          if (element->GetType() < 0) continue;
          Int_t asize = element->GetSize();
          if (element->GetArrayLength()) asize /= element->GetArrayLength();
          fType[fNdata]   = element->GetType();
          fNewType[fNdata]= element->GetNewType();
          fOffset[fNdata] = element->GetOffset();
          fLength[fNdata] = element->GetArrayLength();
          fElem[fNdata]   = (ULong_t)element;
          fMethod[fNdata] = element->GetMethod();
          // try to group consecutive members of the same type
          if (!TestBit(kCannotOptimize)
              && (keep>=0)
              && (element->GetType() < 10)
              && (fType[fNdata] == fNewType[fNdata])
              && (fMethod[keep] == 0)
              && (element->GetType() > 0)
              && (element->GetArrayDim() == 0)
              && (fType[keep] < kObject)
              && (fType[keep] != kCharStar) /* do not optimize char* */
              && (element->GetType() == (fType[keep]%kRegrouped))
              && ((element->GetOffset()-fOffset[keep]) == (fLength[keep])*asize)) {
             if (fLength[keep] == 0) fLength[keep]++;
             fLength[keep]++;
             fType[keep] = element->GetType() + kRegrouped;
             fOptimized = kTRUE;
          } else {
             if (fNewType[fNdata] != fType[fNdata]) {
                if (fNewType[fNdata] > 0) {
                  if (fType[fNdata] != kCounter)
                     fType[fNdata] += kConv;
                } else {
                   if (fType[fNdata] == kCounter)
                      Warning("Compile","Counter %s should not be skipped from class %s", element->GetName(), GetName());
                   fType[fNdata] += kSkip;
                }
             }
             keep = fNdata;
             if (fLength[keep] == 0) fLength[keep] = 1;
             fNdata++;
          }
       }

       for (i=0;i<fNdata;i++) {
          element = (TStreamerElement*)fElem[i];
          if (!element)  continue;
          fComp[i].fClass    = element->GetClassPointer();
          fComp[i].fClassName= TString(element->GetTypeName()).Strip(TString::kTrailing, '*');
          fComp[i].fStreamer = element->GetStreamer();
       }
       ComputeSize();

       if (gDebug > 0) ls();
    }

    //______________________________________________________________________________
     void TStreamerInfo::ComputeSize()
    {
       // Compute total size of all persistent elements of the class

       TIter next(fElements);
       TStreamerElement *element = (TStreamerElement*)fElements->Last();
       //faster and more precise to use last element offset +size
       //on 64 bit machines, offset may be forced to be a multiple of 8 bytes
       fSize = element->GetOffset() + element->GetSize();
       //fSize = 0;
       //while ((element = (TStreamerElement*)next())) {
       //   fSize += element->GetSize();
       //}
    }

    //______________________________________________________________________________
     void TStreamerInfo::ForceWriteInfo(TFile *file, Bool_t force)
    {
       // will force this TStreamerInfo to the file and also
       // all the dependencies.
       // This function is called when streaming a class that contains
       // a null pointer. In this case, the TStreamerInfo for the class
       // with the null pointer must be written to the file and also all the
       // TStreamerInfo of all the classes referenced by the class.
       //
       // if argument force > 0 the loop on class dependencies is forced

       // flag this class
       if (!file) return;
       TArrayC *cindex = file->GetClassIndex();
       //the test below testing fArray[fNumber]>1 is to avoid a recursivity
       //problem in some cases like:
       //        class aProblemChild: public TNamed {
       //        aProblemChild *canBeNull;
       //        };
       if ((cindex->fArray[fNumber] && !force) || cindex->fArray[fNumber]>1) return;
       cindex->fArray[fNumber] = 2;
       cindex->fArray[0] = 1;

       // flag all its dependencies
       TIter next(fElements);
       TStreamerElement *element;
       while ((element = (TStreamerElement*)next())) {
          TClass *cl = element->GetClassPointer();
          if (cl) {
             const char *name = cl->GetName();
             static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
             if (!strcmp(name, "string")||!strcmp(name,full_string_name)) continue; //reject string
             if (strstr(name, "vector<")   || strstr(name, "list<") ||
                 strstr(name, "set<")      || strstr(name, "map<")  ||
                 strstr(name, "deque<")    || strstr(name, "multimap<") ||
                 strstr(name, "multiset<") || strstr(name, "::" ))
                continue; //reject STL containers

             cl->GetStreamerInfo()->ForceWriteInfo(file, force);
          }
       }
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::GenerateHeaderFile(const char *dirname)
    {
       // Generate header file for the class described by this TStreamerInfo
       // the function is called by TFile::MakeProject for each class in the file

       TClass *cl = gROOT->GetClass(GetName());
       if (cl) {
          if (cl->GetClassInfo()) return 0; // skip known classes
       }
       if (gDebug) printf("generating code for class %s\n",GetName());

       //open the file
       Int_t nch = strlen(dirname) + strlen(GetName()) + 4;
       char *filename = new char[nch];
       sprintf(filename,"%s/%s.h",dirname,GetName());
       FILE *fp = fopen(filename,"w");
       if (!fp) {
          printf("Cannot open output file:%s\n",filename);
          delete [] filename;
          return 0;
       }

       // generate class header
       TDatime td;
       fprintf(fp,"//////////////////////////////////////////////////////////\n");
       fprintf(fp,"//   This class has been generated by TFile::MakeProject\n");
       fprintf(fp,"//     (%s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
       fprintf(fp,"//      from the StreamerInfo in file %s\n",gDirectory->GetFile()->GetName());
       fprintf(fp,"//////////////////////////////////////////////////////////\n");
       fprintf(fp,"\n");
       fprintf(fp,"\n");
       fprintf(fp,"#ifndef %s_h\n",GetName());
       fprintf(fp,"#define %s_h\n",GetName());
       fprintf(fp,"\n");

       // compute longest typename and member name
       // in the same loop, generate list of include files
       Int_t ltype = 10;
       Int_t ldata = 10;
       Int_t i,lt,ld;

       char *line = new char[kMaxLen];
       char name[128];
       char cdim[8];
       char *inclist = new char[5000];
       inclist[0] = 0;

       TIter next(fElements);
       TStreamerElement *element;
       Int_t ninc = 0;
       Bool_t Riostream = kFALSE;
       while ((element = (TStreamerElement*)next())) {
          //if (element->IsA() == TStreamerBase::Class()) continue;
          sprintf(name,element->GetName());
          for (i=0;i<element->GetArrayDim();i++) {
             sprintf(cdim,"[%d]",element->GetMaxIndex(i));
             strcat(name,cdim);
          }
          ld = strlen(name);
          lt = strlen(element->GetTypeName());
          if (ltype < lt) ltype = lt;
          if (ldata < ld) ldata = ld;
          //must include Riostream.h in case of an STL container
          if (!Riostream && element->InheritsFrom(TStreamerSTL::Class())) {
             Riostream = kTRUE;
             fprintf(fp,"#include \"Riostream.h\"\n");
          }
          //get include file name if any
          const char *include = element->GetInclude();
          if (strlen(include) == 0) continue;
          const char *slash = strrchr(include,'/');
          if (slash) include = slash+1;
          // do not generate the include if already done
          if (strstr(inclist,include)) continue;
          ninc++;
          strcat(inclist,include);
          if (strstr(include,"include/") || strstr(include,"include\\"))
             fprintf(fp,"#include \"%s\n",include+9);
          else {
             if (slash) fprintf(fp,"#include \"%s\n",include);
             else       fprintf(fp,"#include %s\n",include);
          }
       }
       ltype += 2;
       ldata++; // to take into account the semi colon
       if (ninc == 0) fprintf(fp,"#include \"TNamed.h\"\n");

       // generate class statement with base classes
       fprintf(fp,"\nclass %s",GetName());
       next.Reset();
       Int_t nbase = 0;
       while ((element = (TStreamerElement*)next())) {
          if (element->IsA() != TStreamerBase::Class()) continue;
          nbase++;
          if (nbase == 1) fprintf(fp," : public %s",element->GetName());
          else            fprintf(fp," , public %s",element->GetName());
       }
       fprintf(fp," {\n");

       // generate data members
       fprintf(fp,"\npublic:\n");
       next.Reset();
       while ((element = (TStreamerElement*)next())) {
          for (i=0;i<kMaxLen;i++) line[i] = ' ';
          if (element->IsA() == TStreamerBase::Class()) continue;
          sprintf(name,element->GetName());
          for (Int_t i=0;i<element->GetArrayDim();i++) {
             sprintf(cdim,"[%d]",element->GetMaxIndex(i));
             strcat(name,cdim);
          }
          strcat(name,";");
          ld = strlen(name);
          lt = strlen(element->GetTypeNameBasic());
          strncpy(line+3,element->GetTypeNameBasic(),lt);
          strncpy(line+3+ltype,name,ld);
          if (element->IsaPointer() && !strchr(line,'*')) line[2+ltype] = '*';
          sprintf(line+3+ltype+ldata,"   //%s",element->GetTitle());
          fprintf(fp,"%s\n",line);
       }

       // generate default functions, ClassDef and trailer
       fprintf(fp,"\n   %s();\n",GetName());
       fprintf(fp,"   virtual ~%s();\n\n",GetName());
       fprintf(fp,"   ClassDef(%s,%d) //\n",GetName(),fClassVersion);
       fprintf(fp,"};\n");

       //generate constructor code
       fprintf(fp,"%s::%s() {\n",GetName(),GetName());
       next.Reset();
       while ((element = (TStreamerElement*)next())) {
          if (element->GetType() == kObjectp || element->GetType() == kObjectP ||
              element->GetType() == kAnyp || element->GetType() == kAnyP) {
             fprintf(fp,"   %s = 0;\n",element->GetName());
          }
       }
       fprintf(fp,"}\n\n");
       //generate destructor code
       fprintf(fp,"%s::~%s() {\n",GetName(),GetName());
       next.Reset();
       while ((element = (TStreamerElement*)next())) {
          if (element->GetType() == kObjectp || element->GetType() == kObjectP||
              element->GetType() == kAnyp || element->GetType() == kAnyP
              || element->GetType() == kAnyPnoVT) {
             fprintf(fp,"   delete %s;   %s = 0;\n",element->GetName(),element->GetName());
          }
       }
       fprintf(fp,"}\n\n");
       fprintf(fp,"#endif\n");

       fclose(fp);
       delete [] filename;
       delete [] inclist;
       delete [] line;
       return 1;
    }

    //______________________________________________________________________________
     TStreamerElement *TStreamerInfo::GetCurrentElement()
    {
       //static function returning a pointer to the current TStreamerElement
       //fgElement points to the current TStreamerElement being read in ReadBuffer
       return fgElement;
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::GetDataMemberOffset(TDataMember *dm, TMemberStreamer *&streamer) const
    {
       // Compute data member offset
       // return pointer to the Streamer function if one exists

       TIter nextr(fClass->GetListOfRealData());
       char dmbracket[256];
       sprintf(dmbracket,"%s[",dm->GetName());
       Int_t offset = kMissing;
       if (fClass->GetDeclFileLine() < 0) offset = dm->GetOffset();
       TRealData *rdm;
       while ((rdm = (TRealData*)nextr())) {
          char *rdmc = (char*)rdm->GetName();
          //next statement required in case a class and one of its parent class
          //have data members with the same name
          if (dm->IsaPointer() && rdmc[0] == '*') rdmc++;

          if (rdm->GetDataMember() != dm) continue;
          if (strcmp(rdmc,dm->GetName()) == 0) {
             offset   = rdm->GetThisOffset();
             streamer = rdm->GetStreamer();
             break;
          }
          if (strcmp(rdm->GetName(),dm->GetName()) == 0) {
             if (rdm->IsObject()) {
                offset = rdm->GetThisOffset();
                streamer = rdm->GetStreamer();
                break;
             }
          }
          if (strstr(rdm->GetName(),dmbracket)) {
             offset   = rdm->GetThisOffset();
             streamer = rdm->GetStreamer();
             break;
          }
       }
       return offset;
    }

    //______________________________________________________________________________
     TStreamerBasicType *TStreamerInfo::GetElementCounter(const char *countName, TClass *cl)
    {
       // Get pointer to a TStreamerBasicType in TClass *cl
       //static function

       TObjArray *sinfos = cl->GetStreamerInfos();
       TStreamerInfo *info = (TStreamerInfo *)sinfos->At(cl->GetClassVersion());

       if (!info || !info->IsBuilt()) {
          // Even if the streamerInfo exist, it could still need to be 'build'
          // It is important to figure this out, because
          //   a) if it is not build, we need to build
          //   b) if is build, we should not build it (or we could end up in an
          //      infinite loop, if the element and its counter are in the same
          //      class!

          info = cl->GetStreamerInfo();
       }
       if (!info) return 0;
       TStreamerElement *element = (TStreamerElement *)info->fElements->FindObject(countName);
       if (!element) return 0;
       if (element->IsA() == TStreamerBasicType::Class()) return (TStreamerBasicType*)element;
       return 0;
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::GetOffset(const char *elementName) const
    {
       // return the offset of the data member as indicated by this StreamerInfo

       if (elementName==0) return 0;

       Int_t offset = 0;
       TStreamerElement *elem = (TStreamerElement*)fElements->FindObject(elementName);
       if (elem) offset = elem->GetOffset();

       return offset;
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::GetSize() const
    {
       //  return total size of all persistent elements of the class (with offsets)

       return fSize;
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::GetSizeElements() const
    {
       //  return total size of all persistent elements of the class
       //  use GetSize if you want to get the real size in memory

       TIter next(fElements);
       TStreamerElement *element;
       Int_t asize = 0;
       while ((element = (TStreamerElement*)next())) {
          asize += element->GetSize();
       }
       return asize;
    }

    //______________________________________________________________________________
     TStreamerElement* TStreamerInfo::GetStreamerElement(const char* datamember, Int_t &offset) const
    {
       //  Return the StreamerElement of "datamember" inside this class of any of its
       //  base class.  The offset information contained in the StreamerElement is related
       //  to its immediate containing class, so we return in 'offset' the offset inside
       //  the class of this streamerInfo.

       if (!fElements) return 0;
       TStreamerElement *element = (TStreamerElement*)fElements->FindObject(datamember);
       if (element) {
          offset = element->GetOffset();
          return element;
       }

       if (fClass->GetClassInfo()) {
          // We have the class's shared library.

          TStreamerElement *base_element;
          TBaseClass *base;
          TClass *base_cl;
          Int_t base_offset = 0;
          Int_t local_offset = 0;
          TIter nextb(fClass->GetListOfBases());
          //iterate on list of base classes
          while((base = (TBaseClass*)nextb())) {
             base_cl = gROOT->GetClass(base->GetName());
             base_element = (TStreamerElement*)fElements->FindObject(base->GetName());
             if (!base_cl || !base_element) continue;
             base_offset = base_element->GetOffset();

             element = base_cl->GetStreamerInfo()->GetStreamerElement(datamember,local_offset);
             if (element) {
                offset = base_offset + local_offset;
                return element;
             }
          }
       } else {
          // We do not have the class's shared library

          TIter next( fElements );
          TStreamerElement * curelem;
          while ((curelem = (TStreamerElement*)next())) {

             if (curelem->InheritsFrom(TStreamerBase::Class())) {

                TClass *baseClass = curelem->GetClassPointer();
                if (!baseClass) continue;
                Int_t base_offset = curelem->GetOffset();

                Int_t local_offset = 0;
                element = baseClass->GetStreamerInfo()->GetStreamerElement(datamember,local_offset);
                if (element) {
                   offset = base_offset + local_offset;
                   return element;
                }
             }
          }
       }
       return 0;
    }

    //______________________________________________________________________________
     TStreamerElement* TStreamerInfo::GetStreamerElementReal(Int_t i, Int_t j) const
    {
       //  TStreamerInfo  holds two types of data structures
       //    -TObjArray* fElements; containing the list of all TStreamerElement
       //       objects for this class version.
       //    -ULong_t*  fElem;  containing the preprocessed information
       //       by TStreamerInfo::Compile In case consecutive data members
       //       are of the same type, the Compile function declares the consecutive
       //       elements as one single element in fElems.
       //
       //  example with the class TAttLine
       //   gROOT->GetClass("TAttLine")->GetStreamerInfo()->ls(); produces;
       //      StreamerInfo for class: TAttLine, version=1
       //       short        fLineColor      offset=  4 type= 2 line color
       //       short        fLineStyle      offset=  6 type= 2 line style
       //       short        fLineWidth      offset=  8 type= 2 line width
       //        i= 0, fLineColor      type= 22, offset=  4, len=3, method=0
       //  For I/O implementations (eg. XML) , one has to know the original name
       //  of the data member. This function can be used to return a pointer
       //  to the original TStreamerElement object corresponding to the j-th
       //  element of a compressed array in fElems.
       //
       //  parameters description:
       //    - i: the serial number in array fElem
       //    - j: the element number in the array of consecutive types
       //  In the above example the class TAttLine has 3 consecutive data members
       //  of the same type "short". Compile makes one single array of 3 elements.
       //  To access the TStreamerElement for the second element
       //  of this array, one can call:
       //     TStreamerElement *el = GetStreamerElementReal(0,1);
       //     const char* membername = el->GetName();
       //  This function is typically called from Tbuffer, TXmlBuffer

       if (i < 0 || i >= fNdata) return 0;
       if (j < 0) return 0;
       if (!fElements) return 0;
       TStreamerElement *se = (TStreamerElement*)fElem[i];
       if (!se) return 0;
       Int_t nelems = fElements->GetEntriesFast();
       for (Int_t ise=0;ise<nelems;ise++) {
          if (se != (TStreamerElement*)fElements->UncheckedAt(ise)) continue;
          if (ise+j >= nelems) return 0;
          return (TStreamerElement*)fElements->UncheckedAt(ise+j);
       }
       return 0;
    }

    //______________________________________________________________________________
     Bool_t TStreamerInfo::GetStreamMemberWise()
    {
       // Return whether the TStreamerInfos will save the collections in
       // "member-wise" order whenever possible.    The default is to store member-wise.
       // kTRUE indicates member-wise storing
       // kFALSE inddicates object-wise storing
       //
       // A collection can be saved member wise when it contain is guaranteed to be
       // homogeneous.  For example std::vector<THit> can be stored member wise,
       // while std::vector<THit*> can not (possible use of polymorphism).

       return fgStreamMemberWise;
    }

    //______________________________________________________________________________
     Double_t  TStreamerInfo::GetValueAux(Int_t type, void *ladd, Int_t k, Int_t len)
    {
       switch (type) {
          // basic types
          case kBool:              {Bool_t *val   = (Bool_t*)ladd;   return Double_t(*val);}
          case kChar:              {Char_t *val   = (Char_t*)ladd;   return Double_t(*val);}
          case kShort:             {Short_t *val  = (Short_t*)ladd;  return Double_t(*val);}
          case kInt:               {Int_t *val    = (Int_t*)ladd;    return Double_t(*val);}
          case kLong:              {Long_t *val   = (Long_t*)ladd;   return Double_t(*val);}
          case kLong64:            {Long64_t *val = (Long64_t*)ladd; return Double_t(*val);}
          case kFloat:             {Float_t *val  = (Float_t*)ladd;  return Double_t(*val);}
          case kDouble:            {Double_t *val = (Double_t*)ladd; return Double_t(*val);}
          case kDouble32:          {Double_t *val = (Double_t*)ladd; return Double_t(*val);}
          case kUChar:             {UChar_t *val  = (UChar_t*)ladd;  return Double_t(*val);}
          case kUShort:            {UShort_t *val = (UShort_t*)ladd; return Double_t(*val);}
          case kUInt:              {UInt_t *val   = (UInt_t*)ladd;   return Double_t(*val);}
          case kULong:             {ULong_t *val  = (ULong_t*)ladd;  return Double_t(*val);}
    #if defined(_MSC_VER) && (_MSC_VER <= 1200)
          case kULong64:           {Long64_t *val = (Long64_t*)ladd;  return Double_t(*val);}
    #else
          case kULong64:           {ULong64_t *val= (ULong64_t*)ladd; return Double_t(*val);}
    #endif
          case kBits:              {UInt_t *val   = (UInt_t*)ladd;   return Double_t(*val);}

             // array of basic types  array[8]
          case kOffsetL + kBool:    {Bool_t *val   = (Bool_t*)ladd;   return Double_t(val[k]);}
          case kOffsetL + kChar:    {Char_t *val   = (Char_t*)ladd;   return Double_t(val[k]);}
          case kOffsetL + kShort:   {Short_t *val  = (Short_t*)ladd;  return Double_t(val[k]);}
          case kOffsetL + kInt:     {Int_t *val    = (Int_t*)ladd;    return Double_t(val[k]);}
          case kOffsetL + kLong:    {Long_t *val   = (Long_t*)ladd;   return Double_t(val[k]);}
          case kOffsetL + kLong64:  {Long64_t *val = (Long64_t*)ladd; return Double_t(val[k]);}
          case kOffsetL + kFloat:   {Float_t *val  = (Float_t*)ladd;  return Double_t(val[k]);}
          case kOffsetL + kDouble:  {Double_t *val = (Double_t*)ladd; return Double_t(val[k]);}
          case kOffsetL + kDouble32:{Double_t *val = (Double_t*)ladd; return Double_t(val[k]);}
          case kOffsetL + kUChar:   {UChar_t *val  = (UChar_t*)ladd;  return Double_t(val[k]);}
          case kOffsetL + kUShort:  {UShort_t *val = (UShort_t*)ladd; return Double_t(val[k]);}
          case kOffsetL + kUInt:    {UInt_t *val   = (UInt_t*)ladd;   return Double_t(val[k]);}
          case kOffsetL + kULong:   {ULong_t *val  = (ULong_t*)ladd;  return Double_t(val[k]);}
    #if defined(_MSC_VER) && (_MSC_VER <= 1200)
          case kOffsetL + kULong64: {Long64_t *val = (Long64_t*)ladd;  return Double_t(val[k]);}
    #else
          case kOffsetL + kULong64:{ULong64_t *val= (ULong64_t*)ladd; return Double_t(val[k]);}
    #endif

    #define READ_ARRAY(TYPE_t)                               \
             {                                               \
                Int_t sub_instance, index;                   \
                Int_t instance = k;                          \
                if (len) {                                   \
                   index = instance / len;                   \
                   sub_instance = instance % len;            \
                } else {                                     \
                   index = instance;                         \
                   sub_instance = 0;                         \
                }                                            \
                TYPE_t **val =(TYPE_t**)(ladd);              \
                return Double_t((val[sub_instance])[index]); \
             }

             // pointer to an array of basic types  array[n]
          case kOffsetP + kBool_t:    READ_ARRAY(Bool_t)
          case kOffsetP + kChar_t:    READ_ARRAY(Char_t)
          case kOffsetP + kShort_t:   READ_ARRAY(Short_t)
          case kOffsetP + kInt_t:     READ_ARRAY(Int_t)
          case kOffsetP + kLong_t:    READ_ARRAY(Long_t)
          case kOffsetP + kLong64_t:  READ_ARRAY(Long64_t)
          case kOffsetP + kFloat_t:   READ_ARRAY(Float_t)
          case kOffsetP + kDouble32_t:
          case kOffsetP + kDouble_t:  READ_ARRAY(Double_t)
          case kOffsetP + kUChar_t:   READ_ARRAY(UChar_t)
          case kOffsetP + kUShort_t:  READ_ARRAY(UShort_t)
          case kOffsetP + kUInt_t:    READ_ARRAY(UInt_t)
          case kOffsetP + kULong_t:   READ_ARRAY(ULong_t)
    #if defined(_MSC_VER) && (_MSC_VER <= 1200)
          case kOffsetP + kULong64_t: READ_ARRAY(Long64_t)
    #else
          case kOffsetP + kULong64_t: READ_ARRAY(ULong64_t)
    #endif

              // array counter //[n]
          case kCounter:           {Int_t *val    = (Int_t*)ladd;    return Double_t(*val);}
       }
       return 0;
    }
    //______________________________________________________________________________
     Double_t TStreamerInfo::GetValue(char *pointer, Int_t i, Int_t j, Int_t len) const
    {
       //  return value of element i in object at pointer.
       //  The function may be called in two ways:
       //    -method1  len < 0
       //           i is assumed to be the TStreamerElement number i in StreamerInfo
       //    -method2  len >= 0
       //           i is the type
       //           address of variable is directly pointer.

       char *ladd;
       Int_t atype;
       if (len >= 0) {
          ladd  = pointer;
          atype = i;
       } else {
          if (i < 0) return 0;
          ladd  = pointer + fOffset[i];
          atype = fNewType[i];
          len = ((TStreamerElement*)fElem[i])->GetArrayLength();
       }
       return GetValueAux(atype,ladd,j,len);
    }

    //______________________________________________________________________________
     Double_t TStreamerInfo::GetValueClones(TClonesArray *clones, Int_t i, Int_t j, int k, Int_t eoffset) const
    {
       //  return value of element i in object number j in a TClonesArray and eventually
       // element k in a sub-array.

       Int_t nc = clones->GetEntriesFast();
       if (j >= nc) return 0;

       char *pointer = (char*)clones->UncheckedAt(j);
       char *ladd    = pointer + eoffset + fOffset[i];
       return GetValueAux(fType[i],ladd,k,((TStreamerElement*)fElem[i])->GetArrayLength());
    }

    //______________________________________________________________________________
     Double_t TStreamerInfo::GetValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const
    {
       //  return value of element i in object number j in a TClonesArray and eventually
       // element k in a sub-array.

       Int_t nc = cont->Size();
       if (j >= nc) return 0;

       char *pointer = (char*)cont->At(j);
       char *ladd    = pointer + eoffset + fOffset[i];
       return GetValueAux(fType[i],ladd,k,((TStreamerElement*)fElem[i])->GetArrayLength());
    }
    //______________________________________________________________________________
     void TStreamerInfo::ls(Option_t *option) const
    {
       //  List the TStreamerElement list and also the precomputed tables
       printf("\nStreamerInfo for class: %s, version=%d\n",GetName(),fClassVersion);

       if (fElements) fElements->ls(option);
       for (Int_t i=0;i<fNdata;i++) {
          TStreamerElement *element = (TStreamerElement*)fElem[i];
          printf("   i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld\n",i,element->GetName(),fType[i],fOffset[i],fLength[i],fMethod[i]);
       }
    }

    //______________________________________________________________________________
     Int_t TStreamerInfo::New(const char *p)
    {
       //  emulated constructor for this class.
       //  An emulated object is created at address p

       TIter next(fElements);
       TStreamerElement *element;
       while ((element = (TStreamerElement*)next())) {
          Int_t etype = element->GetType();
          if (element->GetOffset() == kMissing) continue;
          //cle->GetStreamerInfo(); //necessary in case "->" is not specified
          if (etype == kObjectp || etype == kAnyp) {
             // if the option "->" is given in the data member comment field
             // it is assumed that the object exist before reading data in.
             // In this case an object must be created
             if (strstr(element->GetTitle(),"->") == element->GetTitle()) {
                char line[200];
                char pname[100];
                char clonesClass[40];
                // in case of a TClonesArray, the class name of the contained objects
                // must be specified
                sprintf(clonesClass,"%s"," ");
                if (element->GetClassPointer() == TClonesArray::Class()) {
                   char *bracket1 = (char*)strrchr(element->GetTitle(),'(');
                   char *bracket2 = (char*)strrchr(element->GetTitle(),')');
                   if (bracket1 && bracket2) {
                      clonesClass[0] = '"';
                      strncat(clonesClass,bracket1+1,bracket2-bracket1-1);
                      strcat(clonesClass,"\"");
                   }
                }
                // object is created via the interpreter
                sprintf(pname,"R__%s_%s",GetName(),element->GetName());
                sprintf(line,"%s* %s = (%s*)0x%lx; *%s = new %s(%s);",
                        element->GetTypeName(),pname,element->GetTypeName(),
                        (Long_t)((char*)p + element->GetOffset()),pname,
                        element->GetClassPointer()->GetName(),clonesClass);
                gROOT->ProcessLine(line);
             }
          }
          if (etype == kObject || etype == kAny || etype == kBase ||
              etype == kTObject || etype == kTString || etype == kTNamed ||
              etype == kSTL
              ) {
             TClass *cle = element->GetClassPointer();
             if (!cle) continue;
             cle->New((char*)p + element->GetOffset());
          }
          if (etype == kObject +kOffsetL || etype == kAny+kOffsetL ||
              etype == kTObject+kOffsetL || etype == kTString+kOffsetL ||
              etype == kTNamed +kOffsetL || etype == kSTL+kOffsetL) {
             TClass *cle = element->GetClassPointer();
             if (!cle) continue;

             Int_t size = cle->Size();
             char *start= (char*)p + element->GetOffset();
             Int_t len = element->GetArrayLength();

             for (Int_t j=0;j<len;j++) {
                cle->New(start);
                start += size;
             }
          }
          if (etype == kAnyP || etype == kObjectP || etype == kAnyPnoVT || etype == kSTLp) {
             // Initialize to zero
             void **where = (void**)((char*)p + element->GetOffset());
             Int_t len = element->GetArrayLength();
             for (Int_t j=0;j<len;j++) {
                where[j] = 0;
             }
          }
       }
       return 0;
    }

    //______________________________________________________________________________
     void TStreamerInfo::Optimize(Bool_t opt)
    {
       //  This is a static function.
       //  Set optimization option.
       //  When this option is activated (default), consecutive data members
       //  of the same type are merged into an array (faster).
       //  Optimization must be off in TTree split mode.

       fgOptimize = opt;
    }

    //______________________________________________________________________________
     void TStreamerInfo::PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax) const
    {
       //  print value of element i in object at pointer
       //  The function may be called in two ways:
       //    -method1  len < 0
       //           i is assumed to be the TStreamerElement number i in StreamerInfo
       //    -method2  len >= 0
       //           i is the type
       //           address of variable is directly pointer.
       //           len is the number of elements to be printed starting at pointer.

       char *ladd;
       Int_t atype,aleng;
       printf(" %-15s = ",name);

       TStreamerElement * aElement  = 0;
       Int_t *count  = 0;
       if (len >= 0) {
          ladd  = pointer;
          atype = i;
          aleng = len;
       } else        {
          if (i < 0) {printf("NULL\n"); return;}
          ladd  = pointer + fOffset[i];
          atype = fNewType[i];
          aleng = fLength[i];
          aElement  = (TStreamerElement*)fElem[i];
          count = (Int_t*)(pointer+fMethod[i]);
       }
       if (aleng > lenmax) aleng = lenmax;

       PrintValueAux(ladd,atype,aElement,aleng,count);
       printf("\n");
    }

    //______________________________________________________________________________
     void TStreamerInfo::PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax) const
    {
       //  print value of element i in a TClonesArray

       if (!clones) {printf(" %-15s = \n",name); return;}
       printf(" %-15s = ",name);
       Int_t nc = clones->GetEntriesFast();
       if (nc > lenmax) nc = lenmax;

       Int_t offset = eoffset + fOffset[i];
       TStreamerElement *aElement  = (TStreamerElement*)fElem[i];
       int aleng = fLength[i];
       if (aleng > lenmax) aleng = lenmax;

       for (Int_t k=0;k<nc;k++) {
          char *pointer = (char*)clones->UncheckedAt(k);
          char *ladd = pointer+offset;
          Int_t *count = (Int_t*)(pointer+fMethod[i]);
          PrintValueAux(ladd,fNewType[i],aElement, aleng, count);
          if (k < nc-1) printf(", ");
       }
       printf("\n");

    }

    //______________________________________________________________________________
     void TStreamerInfo::PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax) const
    {
       //  print value of element i in a TClonesArray

       if (!cont) {printf(" %-15s = \n",name); return;}
       printf(" %-15s = ",name);
       Int_t nc = cont->Size();
       if (nc > lenmax) nc = lenmax;

       Int_t offset = eoffset + fOffset[i];
       TStreamerElement *aElement  = (TStreamerElement*)fElem[i];
       int aleng = fLength[i];
       if (aleng > lenmax) aleng = lenmax;

       for (Int_t k=0;k<nc;k++) {
          char *pointer = (char*)cont->At(k);
          char *ladd = pointer+offset;
          Int_t *count = (Int_t*)(pointer+fMethod[i]);
          PrintValueAux(ladd,fNewType[i],aElement, aleng, count);
          if (k < nc-1) printf(", ");
       }
       printf("\n");

    }

    //______________________________________________________________________________
     void TStreamerInfo::SetCanDelete(Bool_t opt)
    {
       //  This is a static function.
       //  Set object delete option.
       //  When this option is activated (default), ReadBuffer automatically
       //  delete objects when a data member is a pointer to an object.
       //  If your constructor is not presetting pointers to 0, you must
       //  call this static function TStreamerInfo::SetCanDelete(kFALSE);

       fgCanDelete = opt;
    }

    //______________________________________________________________________________
     Bool_t TStreamerInfo::SetStreamMemberWise(Bool_t enable)
    {
       // Set whether the TStreamerInfos will save the collections in
       // "member-wise" order whenever possible.  The default is to store member-wise.
       // kTRUE indicates member-wise storing
       // kFALSE inddicates object-wise storing
       // This function returns the previous value of fgStreamMemberWise.

       // A collection can be saved member wise when it contain is guaranteed to be
       // homogeneous.  For example std::vector<THit> can be stored member wise,
       // while std::vector<THit*> can not (possible use of polymorphism).

       Bool_t prev = fgStreamMemberWise;
       fgStreamMemberWise = enable;
       return prev;
    }

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

       UInt_t R__s, R__c;
       if (R__b.IsReading()) {
          Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
          fOldVersion = R__v;
          if (R__v > 1) {
             TStreamerInfo::Class()->ReadBuffer(R__b, this, R__v, R__s, R__c);
             return;
          }
          //====process old versions before automatic schema evolution
          TNamed::Streamer(R__b);
          R__b >> fCheckSum;
          R__b >> fClassVersion;
          R__b >> fElements;
          R__b.CheckByteCount(R__s, R__c, TStreamerInfo::IsA());
       } else {
          TStreamerInfo::Class()->WriteBuffer(R__b,this);
       }
    }

    //______________________________________________________________________________
     void TStreamerInfo::TagFile(TFile *file)
    {
       // Mark the classindex of the current file as using this TStreamerInfo

       if (file) {
          TArrayC *cindex = file->GetClassIndex();
          Int_t nindex = cindex->GetSize();
          if (fNumber < 0 || fNumber >= nindex) {
             Error("TagFile","StreamerInfo: %s number: %d out of range[0,%d] in file: %s",
                   GetName(),fNumber,nindex,file->GetName());
             return;
          }
          if (cindex->fArray[fNumber] == 0) {
             cindex->fArray[0]       = 1;
             cindex->fArray[fNumber] = 1;
          }
       }

    }

    //______________________________________________________________________________
    #ifdef DOLOOP
    #undef DOLOOP
    #endif
    #define DOLOOP for(k=0,pointer=arr[0]; k<narr; pointer=arr[++k])

    namespace {
       static void PrintCR(int j,Int_t aleng, UInt_t ltype)
       {
          if (j == aleng-1) printf("\n");
          else {
             printf(", ");
             if (j%ltype==ltype-1) printf("\n                    ");
          }
       }
    }

    //______________________________________________________________________________
     void TStreamerInfo::PrintValueAux(char *ladd, Int_t atype,
                                      TStreamerElement * aElement, Int_t aleng,
                                      Int_t *count)
    {
       //  print value of element  in object at pointer, type atype, leng aleng or *count
       //  The function may be called in two ways:
       //    -method1  len < 0
       //           i is assumed to be the TStreamerElement number i in StreamerInfo
       //    -method2  len >= 0
       //           i is the type
       //           address of variable is directly pointer.
       //           len is the number of elements to be printed starting at pointer.
       int j;

       //assert(  ! ((kOffsetP + kChar)<=atype && atype<=(kOffsetP + kBool) && count==0) );
       switch (atype) {
          // basic types
          case kBool:              {Bool_t    *val = (Bool_t*   )ladd; printf("%d" ,*val);  break;}
          case kChar:              {Char_t    *val = (Char_t*   )ladd; printf("%d" ,*val);  break;}
          case kShort:             {Short_t   *val = (Short_t*  )ladd; printf("%d" ,*val);  break;}
          case kInt:               {Int_t     *val = (Int_t*    )ladd; printf("%d" ,*val);  break;}
          case kLong:              {Long_t    *val = (Long_t*   )ladd; printf("%ld",*val);  break;}
          case kLong64:            {Long64_t  *val = (Long64_t* )ladd; printf("%lld",*val);  break;}
          case kFloat:             {Float_t   *val = (Float_t*  )ladd; printf("%f" ,*val);  break;}
          case kDouble:            {Double_t  *val = (Double_t* )ladd; printf("%g" ,*val);  break;}
          case kDouble32:          {Double_t  *val = (Double_t* )ladd; printf("%g" ,*val);  break;}
          case kUChar:             {UChar_t   *val = (UChar_t*  )ladd; printf("%u" ,*val);  break;}
          case kUShort:            {UShort_t  *val = (UShort_t* )ladd; printf("%u" ,*val);  break;}
          case kUInt:              {UInt_t    *val = (UInt_t*   )ladd; printf("%u" ,*val);  break;}
          case kULong:             {ULong_t   *val = (ULong_t*  )ladd; printf("%lu",*val);  break;}
          case kULong64:           {ULong64_t *val = (ULong64_t*)ladd; printf("%llu",*val);  break;}
          case kBits:              {UInt_t    *val = (UInt_t*   )ladd; printf("%d" ,*val);  break;}

             // array of basic types  array[8]
          case kOffsetL + kBool:    {Bool_t    *val = (Bool_t*   )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
          case kOffsetL + kChar:    {Char_t    *val = (Char_t*   )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
          case kOffsetL + kShort:   {Short_t   *val = (Short_t*  )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
          case kOffsetL + kInt:     {Int_t     *val = (Int_t*    )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
          case kOffsetL + kLong:    {Long_t    *val = (Long_t*   )ladd; for(j=0;j<aleng;j++) { printf("%ld ",val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kLong64:  {Long64_t  *val = (Long64_t* )ladd; for(j=0;j<aleng;j++) { printf("%lld ",val[j]);PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kFloat:   {Float_t   *val = (Float_t*  )ladd; for(j=0;j<aleng;j++) { printf("%f " ,val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kDouble:  {Double_t  *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kDouble32:{Double_t  *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kUChar:   {UChar_t   *val = (UChar_t*  )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,20); } break;}
          case kOffsetL + kUShort:  {UShort_t  *val = (UShort_t* )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,10); } break;}
          case kOffsetL + kUInt:    {UInt_t    *val = (UInt_t*   )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kULong:   {ULong_t   *val = (ULong_t*  )ladd; for(j=0;j<aleng;j++) { printf("%lu ",val[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kULong64: {ULong64_t *val = (ULong64_t*)ladd; for(j=0;j<aleng;j++) { printf("%llu ",val[j]);PrintCR(j,aleng, 5); } break;}
          case kOffsetL + kBits:    {UInt_t    *val = (UInt_t*   )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng, 5); } break;}

             // pointer to an array of basic types  array[n]
          case kOffsetP + kBool:    {Bool_t   **val = (Bool_t**  )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
          case kOffsetP + kChar:    {Char_t   **val = (Char_t**  )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
          case kOffsetP + kShort:   {Short_t  **val = (Short_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
          case kOffsetP + kInt:     {Int_t    **val = (Int_t**   )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
          case kOffsetP + kLong:    {Long_t   **val = (Long_t**  )ladd; for(j=0;j<*count;j++) { printf("%ld ",(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kLong64:  {Long64_t **val = (Long64_t**)ladd; for(j=0;j<*count;j++) { printf("%lld ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kFloat:   {Float_t  **val = (Float_t** )ladd; for(j=0;j<*count;j++) { printf("%f " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kDouble:  {Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kDouble32:{Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kUChar:   {UChar_t  **val = (UChar_t** )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
          case kOffsetP + kUShort:  {UShort_t **val = (UShort_t**)ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
          case kOffsetP + kUInt:    {UInt_t   **val = (UInt_t**  )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kULong:   {ULong_t  **val = (ULong_t** )ladd; for(j=0;j<*count;j++) { printf("%lu ",(*val)[j]);  PrintCR(j,aleng, 5); } break;}
          case kOffsetP + kULong64: {ULong64_t**val = (ULong64_t**)ladd; for(j=0;j<*count;j++){ printf("%llu ",(*val)[j]); PrintCR(j,aleng, 5); } break;}

             // array counter //[n]
          case kCounter:            {Int_t *val    = (Int_t*)ladd;    printf("%d",*val);  break;}
             // char *
          case kCharStar:{
             char **val = (char**)ladd;
             if (*val) printf("%s",*val);
             break;
          }
          // Class *  derived from TObject with comment field  //->
          case kObjectp: {
             TObject **obj = (TObject**)(ladd);
             TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
             printf("(%s*)%lx",el->GetClass()->GetName(),(Long_t)(*obj));
             break;
          }

          // Class*   derived from TObject
          case kObjectP: {
             TObject **obj = (TObject**)(ladd);
             TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
             printf("(%s*)%lx",el->GetClass()->GetName(),(Long_t)(*obj));
             break;
          }

          // Class    derived from TObject
          case kObject:  {
             TObject *obj = (TObject*)(ladd);
             printf("%s",obj->GetName());
             break;
          }

          // Special case for TString, TObject, TNamed
          case kTString: {
             TString *st = (TString*)(ladd);
             printf("%s",st->Data());
             break;
          }
          case kTObject: {
             TObject *obj = (TObject*)(ladd);
             printf("%s",obj->GetName());
             break;
          }
          case kTNamed:  {
             TNamed *named = (TNamed*) (ladd);
             printf("%s/%s",named->GetName(),named->GetTitle());
             break;
          }

          // Class *  not derived from TObject with comment field  //->
          case kAnyp:    {
             TObject **obj = (TObject**)(ladd);
             TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
             printf("(%s*)%lx",el->GetClass()->GetName(),(Long_t)(*obj));
             break;
          }

          // Class*   not derived from TObject
          case kAnyP:    {
             TObject **obj = (TObject**)(ladd);
             TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
             printf("(%s*)%lx",el->GetClass()->GetName(),(Long_t)(*obj));
             break;
          }
          // Any Class not derived from TObject
          case kOffsetL + kObjectp:
          case kOffsetL + kObjectP:
          case kAny:     {
             printf("printing kAny case (%d)",atype);
             TMemberStreamer *pstreamer = aElement->GetStreamer();
             if (pstreamer == 0) {
                //printf("ERROR, Streamer is null\n");
                //aElement->ls();
                break;
             }
             //(*pstreamer)(b,ladd,0);
             break;
          }
          // Base Class
          case kBase:    {
             printf("printing kBase case (%d)",atype);
             //aElement->ReadBuffer(b,pointer);
             break;
          }

          case kOffsetL + kObject:
          case kOffsetL + kTString:
          case kOffsetL + kTObject:
          case kOffsetL + kTNamed:
          case kStreamer: {
             printf("printing kStreamer case (%d)",atype);
             TMemberStreamer *pstreamer = aElement->GetStreamer();
             if (pstreamer == 0) {
                //printf("ERROR, Streamer is null\n");
                //aElement->ls();
                break;
             }
             //UInt_t start,count;
             //b.ReadVersion(&start, &count);
             //(*pstreamer)(b,ladd,0);
             //b.CheckByteCount(start,count,IsA());
             break;
          }

          case kStreamLoop: {
             printf("printing kStreamLoop case (%d)",atype);
             TMemberStreamer *pstreamer = aElement->GetStreamer();
             if (pstreamer == 0) {
                //printf("ERROR, Streamer is null\n");
                //aElement->ls();
                break;
             }
             //Int_t *counter = (Int_t*)(count);
             //UInt_t start,count;
             ///b.ReadVersion(&start, &count);
             //(*pstreamer)(b,ladd,*counter);
             //b.CheckByteCount(start,count,IsA());
             break;
          }
       }
    }

    //______________________________________________________________________________
     void TStreamerInfo::Update(const TClass *oldcl, TClass *newcl)
    {
       //function called by the TClass constructor when replacing an emulated class
       //by the real class

       TStreamerElement *element;
       TIter nextElement(GetElements());
       while ((element = (TStreamerElement*)nextElement())) {
          element->Update(oldcl,newcl);
       }
       for (Int_t i=0;i<fNdata;i++) {
          fComp[i].Update(oldcl,newcl);
       }

    }