TStreamerInfo.cxx

Go to the documentation of this file.
00001 // @(#)Root/io:$Id: TStreamerInfo.cxx 38211 2011-02-24 21:51:24Z pcanal $
00002 // Author: Rene Brun   12/10/2000
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 
00013 //////////////////////////////////////////////////////////////////////////
00014 //                                                                      //
00015 // A TStreamerInfo object describes a persistent version of a class.    //
00016 // A ROOT file contains the list of TStreamerInfo objects for all the   //
00017 // class versions written to this file.                                 //
00018 // When reading a file, all the TStreamerInfo objects are read back in  //
00019 // memory and registered to the TClass list of TStreamerInfo.           //
00020 //                                                                      //
00021 // One can see the list and contents of the TStreamerInfo on a file     //
00022 // with, eg,                                                            //
00023 //    TFile f("myfile.root");                                           //
00024 //    f.ShowStreamerInfo();                                             //
00025 //                                                                      //
00026 // A TStreamerInfo is a list of TStreamerElement objects (one per data  //
00027 // member or base class).                                               //
00028 // When streaming an object, the system (TClass) loops on all the       //
00029 // TStreamerElement objects and calls teh appropriate function for each //
00030 // element type.                                                        //
00031 //                                                                      //
00032 //////////////////////////////////////////////////////////////////////////
00033 
00034 #include "TStreamerInfo.h"
00035 #include "TFile.h"
00036 #include "TROOT.h"
00037 #include "TClonesArray.h"
00038 #include "TStreamerElement.h"
00039 #include "TClass.h"
00040 #include "TClassEdit.h"
00041 #include "TDataMember.h"
00042 #include "TMethodCall.h"
00043 #include "TDataType.h"
00044 #include "TRealData.h"
00045 #include "TBaseClass.h"
00046 #include "TBuffer.h"
00047 #include "TArrayC.h"
00048 #include "TArrayI.h"
00049 #include "TArrayF.h"
00050 #include "TArrayD.h"
00051 #include "TArrayS.h"
00052 #include "TArrayL.h"
00053 #include "TError.h"
00054 #include "TRef.h"
00055 #include "TProcessID.h"
00056 
00057 #include "TStreamer.h"
00058 #include "TContainerConverters.h"
00059 #include "TCollectionProxyFactory.h"
00060 #include "TVirtualCollectionProxy.h"
00061 #include "TInterpreter.h"
00062 
00063 #include "TMemberInspector.h"
00064 
00065 #include "TMakeProject.h"
00066 
00067 #include "TSchemaRuleSet.h"
00068 #include "TSchemaRule.h"
00069 
00070 #include "TVirtualMutex.h"
00071 
00072 #include "TStreamerInfoActions.h"
00073 
00074 TStreamerElement *TStreamerInfo::fgElement = 0;
00075 Int_t   TStreamerInfo::fgCount = 0;
00076 
00077 const Int_t kRegrouped = TStreamerInfo::kOffsetL;
00078 
00079 const Int_t kMaxLen = 1024;
00080 
00081 ClassImp(TStreamerInfo)
00082 
00083 static void R__TObjArray_InsertAt(TObjArray *arr, TObject *obj, Int_t at)
00084 {
00085    // Slide by one.
00086    Int_t last = arr->GetLast();
00087    arr->AddAtAndExpand(arr->At(last),last+1);
00088    for(Int_t ind = last-1; ind >= at; --ind) {
00089       arr->AddAt( arr->At(ind), ind+1);
00090    };
00091    arr->AddAt( obj, at);
00092 }
00093 
00094 #if 0
00095 static void R__TObjArray_InsertAfter(TObjArray *arr, TObject *newobj, TObject *oldobj)
00096 {
00097    // Slide by one.
00098    Int_t last = arr->GetLast();
00099    Int_t at = 0;
00100    while (at<last && arr->At(at) != oldobj) {
00101       ++at;
00102    }
00103    if (at!=0) { 
00104       ++at; // we found the object, insert after it 
00105    }
00106    R__TObjArray_InsertAt(arr, newobj, at);
00107 }
00108 #endif
00109 
00110 static void R__TObjArray_InsertBefore(TObjArray *arr, TObject *newobj, TObject *oldobj)
00111 {
00112    // Slide by one.
00113    Int_t last = arr->GetLast();
00114    Int_t at = 0;
00115    while (at<last && arr->At(at) != oldobj) {
00116       ++at;
00117    }
00118    R__TObjArray_InsertAt(arr, newobj, at);
00119 }
00120 
00121 //______________________________________________________________________________
00122 TStreamerInfo::TStreamerInfo()
00123 {
00124    // Default ctor.
00125 
00126    fNumber   = fgCount;
00127    fClass    = 0;
00128    fElements = 0;
00129    fComp     = 0;
00130    fType     = 0;
00131    fNewType  = 0;
00132    fOffset   = 0;
00133    fLength   = 0;
00134    fElem     = 0;
00135    fMethod   = 0;
00136    fCheckSum = 0;
00137    fNdata    = 0;
00138    fSize     = 0;
00139    fClassVersion = 0;
00140    fOnFileClassVersion = 0;
00141    fOldVersion = Class()->GetClassVersion();
00142    fNVirtualInfoLoc = 0;
00143    fVirtualInfoLoc = 0;
00144    fLiveCount = 0;
00145    
00146    fReadObjectWise = 0;
00147    fReadMemberWise = 0;
00148 }
00149 
00150 //______________________________________________________________________________
00151 TStreamerInfo::TStreamerInfo(TClass *cl)
00152 : TVirtualStreamerInfo(cl)
00153 {
00154    // Create a TStreamerInfo object.
00155 
00156    fgCount++;
00157    fNumber   = fgCount;
00158    fClass    = cl;
00159    fElements = new TObjArray();
00160    fComp     = 0;
00161    fType     = 0;
00162    fNewType  = 0;
00163    fOffset   = 0;
00164    fLength   = 0;
00165    fElem     = 0;
00166    fMethod   = 0;
00167    fCheckSum = 0;
00168    fNdata    = 0;
00169    fSize     = 0;
00170    fClassVersion = fClass->GetClassVersion();
00171    fOnFileClassVersion = 0;
00172    fOldVersion = Class()->GetClassVersion();
00173    fNVirtualInfoLoc = 0;
00174    fVirtualInfoLoc = 0;
00175    fLiveCount = 0;
00176    
00177    fReadObjectWise = 0;
00178    fReadMemberWise = 0;
00179 }
00180 
00181 //______________________________________________________________________________
00182 TStreamerInfo::~TStreamerInfo()
00183 {
00184    // TStreamerInfo dtor.
00185 
00186    delete [] fType;    fType   =0;
00187    delete [] fNewType; fNewType=0;
00188    delete [] fOffset;  fOffset =0;
00189    delete [] fLength;  fLength =0;
00190    delete [] fElem;    fElem   =0;
00191    delete [] fMethod;  fMethod =0;
00192    delete [] fComp;    fComp   =0;
00193    delete [] fVirtualInfoLoc; fVirtualInfoLoc =0;
00194 
00195    delete fReadObjectWise;
00196    delete fReadMemberWise;
00197 
00198    if (!fElements) return;
00199    fElements->Delete();
00200    delete fElements; fElements=0;
00201 }
00202 
00203 //______________________________________________________________________________
00204 void TStreamerInfo::Build()
00205 {
00206    // Build the I/O data structure for the current class version.
00207    // A list of TStreamerElement derived classes is built by scanning
00208    // one by one the list of data members of the analyzed class.
00209 
00210    R__LOCKGUARD(gCINTMutex);
00211 
00212    // This is used to avoid unwanted recursive call to Build
00213    fIsBuilt = kTRUE;
00214 
00215    if (fClass->GetCollectionProxy()) {
00216       //FIXME: What about arrays of STL containers?
00217       TStreamerElement* element = new TStreamerSTL("This", "Used to call the proper TStreamerInfo case", 0, fClass->GetName(), fClass->GetName(), 0);
00218       fElements->Add(element);
00219       Compile();
00220       return;
00221    }
00222 
00223    TStreamerElement::Class()->IgnoreTObjectStreamer();
00224 
00225    fClass->BuildRealData();
00226 
00227    fCheckSum = fClass->GetCheckSum();
00228 
00229    Bool_t needAllocClass = kFALSE;
00230    Bool_t wasCompiled = fOffset != 0;
00231    const ROOT::TSchemaMatch* rules = 0;
00232    if (fClass->GetSchemaRules()) {
00233        rules = fClass->GetSchemaRules()->FindRules(fClass->GetName(), fClassVersion);
00234    }
00235 
00236    //
00237    // Iterate over base classes.
00238    //
00239 
00240    TBaseClass* base = 0;
00241    TIter nextb(fClass->GetListOfBases());
00242    while ((base = (TBaseClass*)nextb())) {
00243       TStreamerElement* element = 0;
00244       Int_t offset = base->GetDelta();
00245       if (offset == kMissing) {
00246          continue;
00247       }
00248       const char* bname  = base->GetName();
00249       const char* btitle = base->GetTitle();
00250       // this case appears with STL collections as base class.
00251       if (!strcmp(bname, "string")) {
00252          element = new TStreamerSTLstring(bname, btitle, offset, bname, kFALSE);
00253       } else if (base->IsSTLContainer()) {
00254          element = new TStreamerSTL(bname, btitle, offset, bname, 0, kFALSE);
00255       } else {
00256          element = new TStreamerBase(bname, btitle, offset);
00257          TClass* clm = element->GetClassPointer();
00258          if (!clm) {
00259             Error("Build", "%s, unknown type: %s %s\n", GetName(), bname, btitle);
00260             delete element;
00261             element = 0;
00262          } else {
00263             clm->GetStreamerInfo();
00264             if ((clm == TObject::Class()) && fClass->CanIgnoreTObjectStreamer()) {
00265                // -- An ignored TObject base class.
00266                // Note: The TClass kIgnoreTObjectStreamer == BIT(15), but
00267                // the TStreamerInfo kIgnoreTobjectStreamer == BIT(13) which
00268                // is confusing.
00269                SetBit(kIgnoreTObjectStreamer);
00270                // Flag the element to be ignored by setting its type to -1.
00271                // This flag will be used later by Compile() to prevent this
00272                // element from being inserted into the compiled info.
00273                element->SetType(-1);
00274             }
00275             if (!clm->IsLoaded()) {
00276                Warning("Build:", "%s: base class %s has no streamer or dictionary it will not be saved", GetName(), clm->GetName());
00277             }
00278          }
00279       }
00280       if (element) {
00281          fElements->Add(element);
00282       }
00283    } // end of base class loop
00284 
00285    //
00286    // Iterate over data members.
00287    //
00288 
00289    Int_t dsize;
00290    TDataMember* dm = 0;
00291    TIter nextd(fClass->GetListOfDataMembers());
00292    while ((dm = (TDataMember*) nextd())) {
00293       if (fClass->GetClassVersion() == 0) {
00294          continue;
00295       }
00296       if (!dm->IsPersistent()) {
00297          continue;
00298       }
00299       TMemberStreamer* streamer = 0;
00300       Int_t offset = GetDataMemberOffset(dm, streamer);
00301       if (offset == kMissing) {
00302          continue;
00303       }
00304       TStreamerElement* element = 0;
00305       dsize = 0;
00306       const char* dmName = dm->GetName();
00307       const char* dmTitle = dm->GetTitle();
00308       const char* dmType = dm->GetTypeName();
00309       const char* dmFull = dm->GetFullTypeName();
00310       Bool_t dmIsPtr = dm->IsaPointer();
00311       TDataMember* dmCounter = 0;
00312       if (dmIsPtr) {
00313          //
00314          // look for a pointer data member with a counter
00315          // in the comment string, like so:
00316          //
00317          //      int n;
00318          //      double* MyArray; //[n]
00319          //
00320          const char* lbracket = ::strchr(dmTitle, '[');
00321          const char* rbracket = ::strchr(dmTitle, ']');
00322          if (lbracket && rbracket) {
00323             const char* counterName = dm->GetArrayIndex();
00324             TRealData* rdCounter = (TRealData*) fClass->GetListOfRealData()->FindObject(counterName);
00325             if (!rdCounter || rdCounter->TestBit(TRealData::kTransient)) {
00326                Error("Build", "%s, discarding: %s %s, illegal %s\n", GetName(), dmFull, dmName, dmTitle);
00327                continue;
00328             }
00329             dmCounter = rdCounter->GetDataMember();
00330             TDataType* dtCounter = dmCounter->GetDataType();
00331             Bool_t isInteger = dtCounter && ((dtCounter->GetType() == 3) || (dtCounter->GetType() == 13));
00332             if (!dtCounter || !isInteger) {
00333                Error("Build", "%s, discarding: %s %s, illegal [%s] (must be Int_t)\n", GetName(), dmFull, dmName, counterName);
00334                continue;
00335             }
00336             TStreamerBasicType* bt = TStreamerInfo::GetElementCounter(counterName, dmCounter->GetClass());
00337             if (!bt) {
00338                if (dmCounter->GetClass()->Property() & kIsAbstract) {
00339                   continue;
00340                }
00341                Error("Build", "%s, discarding: %s %s, illegal [%s] must be placed before \n", GetName(), dmFull, dmName, counterName);
00342                continue;
00343             }
00344          }
00345       }
00346       TDataType* dt = dm->GetDataType();
00347       if (dt) {
00348          // found a basic type
00349          Int_t dtype = dt->GetType();
00350          dsize = dt->Size();
00351          if (!dmCounter && (strstr(dmFull, "char*") || strstr(dmFull, "Char_t*"))) {
00352             dtype = kCharStar;
00353             dsize = sizeof(char*);
00354          }
00355          if (dmIsPtr && (dtype != kCharStar)) {
00356             if (dmCounter) {
00357                // data member is pointer to an array of basic types
00358                element = new TStreamerBasicPointer(dmName, dmTitle, offset, dtype, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
00359             } else {
00360                if ((fName == "TString") || (fName == "TClass")) {
00361                   continue;
00362                }
00363                Error("Build", "%s, discarding: %s %s, no [dimension]\n", GetName(), dmFull, dmName);
00364                continue;
00365             }
00366          } else {
00367             // data member is a basic type
00368             if ((fClass == TObject::Class()) && !strcmp(dmName, "fBits")) {
00369                //printf("found fBits, changing dtype from %d to 15\n", dtype);
00370                dtype = kBits;
00371             }
00372             element = new TStreamerBasicType(dmName, dmTitle, offset, dtype, dmFull);
00373          }
00374       } else {
00375          // try STL container or string
00376          static const char* full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
00377          if (!strcmp(dmType, "string") || !strcmp(dmType, full_string_name)) {
00378             element = new TStreamerSTLstring(dmName, dmTitle, offset, dmFull, dmIsPtr);
00379          } else if (dm->IsSTLContainer()) {
00380             element = new TStreamerSTL(dmName, dmTitle, offset, dmFull, dm->GetTrueTypeName(), dmIsPtr);
00381          } else {
00382             TClass* clm = TClass::GetClass(dmType);
00383             if (!clm) {
00384                Error("Build", "%s, unknown type: %s %s\n", GetName(), dmFull, dmName);
00385                continue;
00386             }
00387             if (dmIsPtr) {
00388                // a pointer to a class
00389                if (dmCounter) {
00390                   element = new TStreamerLoop(dmName, dmTitle, offset, dm->GetArrayIndex(), dmCounter->GetClass()->GetName(), dmCounter->GetClass()->GetClassVersion(), dmFull);
00391                } else {
00392                   if (clm->InheritsFrom(TObject::Class())) {
00393                      element = new TStreamerObjectPointer(dmName, dmTitle, offset, dmFull);
00394                   } else {
00395                      element = new TStreamerObjectAnyPointer(dmName, dmTitle, offset, dmFull);
00396                      if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
00397                         Error("Build:", "%s: %s has no streamer or dictionary, data member %s will not be saved", GetName(), dmFull, dmName);
00398                      }
00399                   }
00400                }
00401             } else if (clm->InheritsFrom(TObject::Class())) {
00402                element = new TStreamerObject(dmName, dmTitle, offset, dmFull);
00403             } else if ((clm == TString::Class()) && !dmIsPtr) {
00404                element = new TStreamerString(dmName, dmTitle, offset);
00405             } else {
00406                element = new TStreamerObjectAny(dmName, dmTitle, offset, dmFull);
00407                if (!streamer && !clm->GetStreamer() && !clm->IsLoaded()) {
00408                   Warning("Build:", "%s: %s has no streamer or dictionary, data member \"%s\" will not be saved", GetName(), dmFull, dmName);
00409                }
00410             }
00411          }
00412       }
00413       if (!element) {
00414          // If we didn't make an element, there is nothing to do.
00415          continue;
00416       }
00417       Int_t ndim = dm->GetArrayDim();
00418       if (!dsize) {
00419          dsize = dm->GetUnitSize();
00420       }
00421       for (Int_t i = 0; i < ndim; ++i) {
00422          element->SetMaxIndex(i, dm->GetMaxIndex(i));
00423       }
00424       element->SetArrayDim(ndim);
00425       Int_t narr = element->GetArrayLength();
00426       if (!narr) {
00427          narr = 1;
00428       }
00429       element->SetSize(dsize*narr);
00430       element->SetStreamer(streamer);
00431       if (!streamer) {
00432          Int_t k = element->GetType();
00433          if (k == kStreamer) {
00434             //if ((k == kSTL) || (k == kSTL + kOffsetL) || (k == kStreamer) || (k == kStreamLoop))
00435             element->SetType(-1);
00436          }
00437       }
00438 
00439       if ( !wasCompiled && (rules && rules->HasRuleWithSource( element->GetName(), kTRUE )) ) {
00440          needAllocClass = kTRUE;
00441 
00442          // If this is optimized to re-use TStreamerElement(s) in case of variable renaming,
00443          // then we must revisit the code in TBranchElement::InitInfo that recalculate the
00444          // fID (i.e. the index of the TStreamerElement to be used for streaming).
00445 
00446          TStreamerElement *cached = element;
00447          // Now that we are caching the unconverted element, we do not assign it to the real type even if we could have!
00448          if (element->GetNewType()>0 /* intentionally not including base class for now */ 
00449              && rules && !rules->HasRuleWithTarget( element->GetName(), kTRUE ) ) 
00450          {
00451             TStreamerElement *copy = (TStreamerElement*)element->Clone();
00452             fElements->Add(copy);
00453             copy->SetBit(TStreamerElement::kRepeat);
00454             cached = copy;
00455 
00456             // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
00457          }
00458          cached->SetBit(TStreamerElement::kCache);
00459          cached->SetNewType( cached->GetType() );
00460       }
00461 
00462       fElements->Add(element);
00463    } // end of member loop
00464 
00465    // Now add artificial TStreamerElement (i.e. rules that creates new members or set transient members).
00466    InsertArtificialElements(rules);
00467 
00468    if (needAllocClass) {
00469       TStreamerInfo *infoalloc  = (TStreamerInfo *)Clone(TString::Format("%s@@%d",GetName(),GetClassVersion()));
00470       infoalloc->BuildCheck();
00471       infoalloc->BuildOld();
00472       TClass *allocClass = infoalloc->GetClass();
00473 
00474       {
00475          TIter next(fElements);
00476          TStreamerElement* element;
00477          while ((element = (TStreamerElement*) next())) {
00478             if (element->TestBit(TStreamerElement::kRepeat) && element->IsaPointer()) {
00479                TStreamerElement *other = (TStreamerElement*) infoalloc->GetElements()->FindObject(element->GetName());
00480                if (other) {
00481                   other->SetBit(TStreamerElement::kDoNotDelete);
00482                }
00483             }
00484          }
00485          infoalloc->GetElements()->Compress();
00486       }
00487       {
00488          TIter next(fElements);
00489          TStreamerElement* element;
00490          while ((element = (TStreamerElement*) next())) {
00491             if (element->TestBit(TStreamerElement::kCache)) {
00492                element->SetOffset(infoalloc->GetOffset(element->GetName()));            
00493             }
00494          }
00495       }
00496 
00497       TStreamerElement *el = new TStreamerArtificial("@@alloc","", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
00498       R__TObjArray_InsertAt( fElements, el, 0 );
00499 
00500       el = new TStreamerArtificial("@@dealloc","", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
00501       fElements->Add( el );
00502    }
00503 
00504    //
00505    // Make a more compact version.
00506    //
00507    Compile();
00508 }
00509 
00510 //______________________________________________________________________________
00511 void TStreamerInfo::BuildCheck()
00512 {
00513    // Check if built and consistent with the class dictionary.
00514    // This method is called by TFile::ReadStreamerInfo.
00515 
00516    R__LOCKGUARD(gCINTMutex);
00517 
00518    TObjArray* array = 0;
00519    fClass = TClass::GetClass(GetName());
00520    if (!fClass) {
00521       fClass = new TClass(GetName(), fClassVersion, 0, 0, -1, -1);
00522       fClass->SetBit(TClass::kIsEmulation);
00523       array = fClass->GetStreamerInfos();
00524    } else {
00525       if (TClassEdit::IsSTLCont(fClass->GetName())) {
00526          SetBit(kCanDelete);
00527          return;
00528       }
00529       array = fClass->GetStreamerInfos();
00530       TStreamerInfo* info = 0;
00531 
00532       if (fClass->TestBit(TClass::kIsEmulation) && array->GetEntries()==0) {
00533          // We have an emulated class that has no TStreamerInfo, this 
00534          // means it was created to insert a (default) rule.  Consequently
00535          // the error message about the missing dictionary was not printed.
00536          // For consistency, let's print it now!
00537          
00538          ::Warning("TClass::TClass", "no dictionary for class %s is available", GetName());
00539       }
00540 
00541       // If the user has not specified a class version (this _used to_
00542       // always be the case when the class is Foreign) or if the user
00543       // has specified a version to be explicitly 1. [We can not
00544       // distringuish the two cases using the information in the "on
00545       // file" StreamerInfo.]
00546 
00547       Bool_t searchOnChecksum = kFALSE;
00548       if (fClass->IsLoaded() && fClass->GetClassVersion() >= 2) {
00549          // We know for sure that the user specified the version.
00550 
00551          if (fOnFileClassVersion >= 2) {
00552             // The class version was specified when the object was
00553             // written
00554 
00555             searchOnChecksum = kFALSE;
00556 
00557          } else {
00558             // The class version was not specified when the object was
00559             // written OR it was specified to be 1.
00560 
00561             searchOnChecksum = kTRUE;            
00562          }
00563       } else if (fClass->IsLoaded() && !fClass->IsForeign()) {
00564          // We are in the case where the class has a Streamer function.
00565          // and fClass->GetClassVersion is 1, we still assume that the
00566          // Class Version is specified (to be one).
00567 
00568          searchOnChecksum = kFALSE;
00569 
00570       } else if (fClass->IsLoaded() /* implied: && fClass->IsForeign() */ ) {
00571          // We are in the case of a Foreign class with no specified
00572          // class version.
00573 
00574          searchOnChecksum = kTRUE;
00575 
00576       }
00577       else {
00578          // We are in the case of an 'emulated' class.
00579 
00580          if (fOnFileClassVersion >= 2) {
00581             // The class version was specified when the object was
00582             // written
00583 
00584             searchOnChecksum = kFALSE;
00585 
00586          } else {
00587             // The class version was not specified when the object was
00588             // written OR it was specified to be 1.
00589 
00590             searchOnChecksum = kTRUE;
00591 
00592             TStreamerInfo* v1 = (TStreamerInfo*) array->At(1);
00593             if (v1) {
00594                if (fCheckSum != v1->GetCheckSum()) {
00595                   fClassVersion = array->GetLast() + 1;
00596                }
00597             }
00598          }
00599       }
00600 
00601       if (!searchOnChecksum) {
00602          if (fClassVersion < array->GetEntriesFast()) {
00603             info = (TStreamerInfo*) array->At(fClassVersion);
00604          }
00605       } else {
00606          Int_t ninfos = array->GetEntriesFast() - 1;
00607          for (Int_t i = -1; i < ninfos; ++i) {
00608             info = (TStreamerInfo*) array->UncheckedAt(i);
00609             if (!info) {
00610                continue;
00611             }
00612             if (fCheckSum == info->GetCheckSum() && (info->GetOnFileClassVersion()==1 || info->GetOnFileClassVersion()==0)) {
00613                // We must match on the same checksum, an existing TStreamerInfo
00614                // for one of the 'unversioned' class layout (i.e. version was 1).
00615                fClassVersion = i;
00616                break;
00617             }
00618             info = 0;
00619          }
00620          if (info==0) {
00621             // Find an empty slot.
00622             ninfos = array->GetEntriesFast() - 1;
00623             Int_t slot = 1; // Start of Class version 1.
00624             while ((slot < ninfos) && (array->UncheckedAt(slot) != 0)) {
00625                ++slot;
00626             }
00627             fClassVersion = slot;
00628          }
00629       }
00630 
00631       // NOTE: Should we check if the already existing info is the same as
00632       // the current one? Yes
00633       // In case a class (eg Event.h) has a TClonesArray of Tracks, it could be
00634       // that the old info does not have the class name (Track) in the data
00635       // member title. Set old title to new title
00636       if (info) {
00637          // We found an existing TStreamerInfo for our ClassVersion
00638          Bool_t match = kTRUE;
00639          Bool_t done = kFALSE;
00640          Bool_t oldIsNonVersioned = kFALSE;
00641          if (fClassVersion!=0 && !fClass->TestBit(TClass::kWarned) && (fClassVersion == info->GetClassVersion()) && (fCheckSum != info->GetCheckSum())) {
00642             // The TStreamerInfo's checksum is different from the checksum for the compile class.
00643 
00644             match = kFALSE;
00645             oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
00646 
00647             if (fClass->IsLoaded() && (fClassVersion == fClass->GetClassVersion()) && fClass->GetListOfDataMembers() && (fClass->GetClassInfo())) {
00648                // In the case where the read-in TStreamerInfo does not
00649                // match in the 'current' in memory TStreamerInfo for
00650                // a non foreign class (we can not get here if this is
00651                // a foreign class so we do not need to test it),
00652                // we need to add this one more test since the CINT behaviour
00653                // with enums changed over time, so verify the checksum ignoring
00654                // members of type enum. We also used to not count the //[xyz] comment
00655                // in the checksum, so test for that too.
00656                if (  (fCheckSum == fClass->GetCheckSum() || fCheckSum == fClass->GetCheckSum(1) || fCheckSum == fClass->GetCheckSum(2))
00657                      &&(info->GetCheckSum() == fClass->GetCheckSum() || info->GetCheckSum() == fClass->GetCheckSum(1) || info->GetCheckSum() == fClass->GetCheckSum(2))
00658                      )
00659                   {
00660                      match = kTRUE;
00661                   }
00662                if (fOldVersion <= 2) {
00663                   // Names of STL base classes was modified in vers==3. Allocators removed
00664                   // (We could be more specific (see test for the same case below)
00665                   match = kTRUE;
00666                }
00667                if (!match && CompareContent(0,info,kFALSE,kFALSE)) {
00668                   match = kTRUE;
00669                }
00670             } else {
00671                // The on-file TStreamerInfo's checksum differs from the checksum of a TStreamerInfo on another file.
00672 
00673                match = kFALSE;
00674                oldIsNonVersioned = info->fOnFileClassVersion==1 && info->fClassVersion != 1;
00675 
00676                // In the case where the read-in TStreamerInfo does not
00677                // match in the 'current' in memory TStreamerInfo for
00678                // a non foreign class (we can not get here if this is
00679                // a foreign class so we do not need to test it),
00680                // we need to add this one more test since the CINT behaviour
00681                // with enums changed over time, so verify the checksum ignoring
00682                // members of type enum. We also used to not count the //[xyz] comment
00683                // in the checksum, so test for that too.
00684                if (fCheckSum == info->GetCheckSum(0) || fCheckSum == info->GetCheckSum(1) || fCheckSum == info->GetCheckSum(2)
00685                    || GetCheckSum(0) == info->GetCheckSum() || GetCheckSum(1) == info->GetCheckSum() || GetCheckSum(2) == info->GetCheckSum() 
00686                    || GetCheckSum(0) == info->GetCheckSum(0))
00687                   {
00688                      match = kTRUE;
00689                   }
00690                if (fOldVersion <= 2) {
00691                   // Names of STL base classes was modified in vers==3. Allocators removed
00692                   // (We could be more specific (see test for the same case below)
00693                   match = kTRUE;
00694                }
00695                if (!match && CompareContent(0,info,kFALSE,kFALSE)) {
00696                   match = kTRUE;
00697                }
00698             }
00699          }
00700          if (info->IsBuilt()) {
00701             SetBit(kCanDelete);
00702             fNumber = info->GetNumber();
00703             Int_t nel = fElements->GetEntriesFast();
00704             TObjArray* elems = info->GetElements();
00705             TStreamerElement* e1 = 0;
00706             TStreamerElement* e2 = 0;
00707             for (Int_t i = 0; i < nel; ++i) {
00708                e1 = (TStreamerElement*) fElements->UncheckedAt(i);
00709                e2 = (TStreamerElement*) elems->At(i);
00710                if (!e1 || !e2) {
00711                   continue;
00712                }
00713                if (strlen(e1->GetTitle()) != strlen(e2->GetTitle())) {
00714                   e2->SetTitle(e1->GetTitle());
00715                }
00716             }
00717             
00718             if (TestBit(kCannotOptimize)) {
00719                info->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00720                if (info->IsOptimized()) 
00721                {
00722                   // Optimizing does not work with splitting.
00723                   info->Compile();
00724                }
00725             } 
00726             done = kTRUE;
00727          } else {
00728             array->RemoveAt(fClassVersion);
00729             delete info;
00730             info = 0;
00731          }
00732          TString origin;
00733          if (!match && !fClass->TestBit(TClass::kWarned)) {
00734             if (oldIsNonVersioned) {
00735                if (gDirectory && gDirectory->GetFile()) {
00736                   Warning("BuildCheck", "\n\
00737    The class %s transitioned from not having a specified class version\n\
00738    to having a specified class version (the current class version is %d).\n\
00739    However too many different non-versioned layouts of the class have been\n\
00740    loaded so far.  This prevent the proper reading of objects written with\n\
00741    the class layout version %d, in particular from the file:\n\
00742    %s.\n\
00743    To work around this issue, load fewer 'old' files in the same ROOT session.",
00744                           GetName(),fClass->GetClassVersion(),fClassVersion,gDirectory->GetFile()->GetName());
00745                } else {
00746                   Warning("BuildCheck", "\n\
00747    The class %s transitioned from not having a specified class version\n\
00748    to having a specified class version (the current class version is %d).\n\
00749    However too many different non-versioned layouts of the class have been\n\
00750    loaded so far.  This prevent the proper reading of objects written with\n\
00751    the class layout version %d.\n\
00752    To work around this issue, load fewer 'old' files in the same ROOT session.",
00753                           GetName(),fClass->GetClassVersion(),fClassVersion);
00754                }
00755             } else {
00756                if (gDirectory && gDirectory->GetFile()) {
00757                   if (done) {
00758                      Warning("BuildCheck", "\n\
00759    The StreamerInfo for version %d of class %s read from the file %s\n\
00760    has a different checksum than the previously loaded StreamerInfo.\n\
00761    Reading objects of type %s from the file %s \n\
00762    (and potentially other files) might not work correctly.\n\
00763    Most likely the version number of the class was not properly\n\
00764    updated [See ClassDef(%s,%d)].", 
00765                              fClassVersion, GetName(), gDirectory->GetFile()->GetName(), GetName(), gDirectory->GetFile()->GetName(), GetName(), fClassVersion);
00766                   } else {
00767                      Warning("BuildCheck", "\n\
00768    The StreamerInfo from %s does not match existing one (%s:%d)\n\
00769    The existing one has not been used yet and will be discarded.\n\
00770    Reading the file %s will work properly, however writing object of\n\
00771    type %s will not work properly.  Most likely the version number\n\
00772    of the class was not properly updated [See ClassDef(%s,%d)].", 
00773                              gDirectory->GetFile()->GetName(), GetName(), fClassVersion,gDirectory->GetFile()->GetName(),GetName(), GetName(), fClassVersion);
00774                   }
00775                } else {
00776                   if (done) {
00777                      Warning("BuildCheck", "\n\
00778    The StreamerInfo for version %d of class %s\n\
00779    has a different checksum than the previously loaded StreamerInfo.\n\
00780    Reading objects of type %s\n\
00781    (and potentially other files) might not work correctly.\n\
00782    Most likely the version number of the class was not properly\n\
00783    updated [See ClassDef(%s,%d)].", 
00784                              fClassVersion, GetName(), GetName(), GetName(), fClassVersion);
00785                   } else {
00786                      Warning("BuildCheck", "\n\
00787    The StreamerInfo from %s does not match existing one (%s:%d)\n\
00788    The existing one has not been used yet and will be discarded.\n\
00789    Reading should work properly, however writing object of\n\
00790    type %s will not work properly.  Most likely the version number\n\
00791    of the class was not properly updated [See ClassDef(%s,%d)].", 
00792                              gDirectory->GetFile()->GetName(), GetName(), fClassVersion, GetName(), GetName(), fClassVersion);
00793                   }
00794                }
00795             }
00796             CompareContent(0,info,kTRUE,kTRUE);
00797             fClass->SetBit(TClass::kWarned);
00798          }
00799          if (done) {
00800             return;
00801          }
00802       }
00803       // The slot was free, however it might still be reserved for the current 
00804       // loaded version of the class
00805       if (fClass->IsLoaded() 
00806           && fClass->GetListOfDataMembers() 
00807           && (fClassVersion != 0) // We don't care about transient classes
00808           && (fClassVersion == fClass->GetClassVersion()) 
00809           && (fCheckSum != fClass->GetCheckSum()) 
00810           && (fClass->GetClassInfo())) {
00811 
00812          // If the old TStreamerInfo matches the in-memory one when we either
00813          //   - ignore the members of type enum
00814          // or
00815          //   - ignore the comments annotation (//[xyz])
00816          // we can accept the old TStreamerInfo.
00817 
00818          if (fCheckSum != fClass->GetCheckSum(1) && fCheckSum != fClass->GetCheckSum(2)) {
00819 
00820             Bool_t warn = !fClass->TestBit(TClass::kWarned);
00821             if (warn && (fOldVersion <= 2)) {
00822                // Names of STL base classes was modified in vers==3. Allocators removed
00823                //
00824                TIter nextBC(fClass->GetListOfBases());
00825                TBaseClass* bc = 0;
00826                while ((bc = (TBaseClass*) nextBC())) {
00827                   if (TClassEdit::IsSTLCont(bc->GetName())) {
00828                      warn = kFALSE;
00829                   }
00830                }
00831             }
00832             if (warn) {
00833                if (gDirectory && gDirectory->GetFile()) {
00834                   Warning("BuildCheck", "\n\
00835    The StreamerInfo of class %s read from file %s\n\
00836    has the same version (=%d) as the active class but a different checksum.\n\
00837    You should update the version to ClassDef(%s,%d).\n\
00838    Do not try to write objects with the current class definition,\n\
00839    the files will not be readable.\n", GetName(), gDirectory->GetFile()->GetName(), fClassVersion, GetName(), fClassVersion + 1);
00840                } else {
00841                   Warning("BuildCheck", "\n\
00842    The StreamerInfo of class %s \n\
00843    has the same version (=%d) as the active class but a different checksum.\n\
00844    You should update the version to ClassDef(%s,%d).\n\
00845    Do not try to write objects with the current class definition,\n\
00846    the files will not be readable.\n", GetName(), fClassVersion, GetName(), fClassVersion + 1);
00847                }
00848                fClass->SetBit(TClass::kWarned);
00849             }
00850          } else {
00851             if (fClass->IsForeign()) {
00852                R__ASSERT(0);
00853             }
00854          }
00855       }
00856       if (!fClass->IsLoaded() &&  this->fOnFileClassVersion>1)
00857       {
00858          ROOT::ResetClassVersion(fClass,(const char*)-1, this->fClassVersion);
00859       }
00860    }
00861    // FIXME: This code can never execute because Build() calls
00862    // TStreamerElement::Class()->IgnoreTObjectStreamer()
00863    // so our bits are never saved to the file.
00864    if (TestBit(kIgnoreTObjectStreamer)) {
00865       fClass->IgnoreTObjectStreamer();
00866    }
00867    if ((fClassVersion < -1) || (fClassVersion > 65000)) {
00868       printf("ERROR reading TStreamerInfo: %s fClassVersion=%d\n", GetName(), fClassVersion);
00869       SetBit(kCanDelete);
00870       fNumber = -1;
00871       return;
00872    }
00873 
00874    array->AddAtAndExpand(this, fClassVersion);
00875    ++fgCount;
00876    fNumber = fgCount;
00877 
00878    // Since we just read this streamerInfo from file, it has already been built.
00879    fIsBuilt = kTRUE;
00880 
00881    //add to the global list of StreamerInfo
00882    TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
00883    infos->AddAtAndExpand(this, fNumber);
00884 }
00885 
00886 //______________________________________________________________________________
00887 void TStreamerInfo::BuildEmulated(TFile *file)
00888 {
00889    // Create an Emulation TStreamerInfo object.
00890 
00891    R__LOCKGUARD(gCINTMutex);
00892 
00893    TString duName;
00894    R__ASSERT(file);
00895    Int_t fv = file->GetVersion()%100000;
00896    R__ASSERT(fv < 30000);
00897    fClassVersion = -1;
00898    fCheckSum = 2001;
00899    TObjArray *elements = GetElements();
00900    if (!elements) return;
00901    Int_t ndata = elements->GetEntries();
00902    if (ndata == 0) return;
00903    TStreamerElement *element;
00904    Int_t i;
00905    for (i=0;i < ndata;i++) {
00906       element = (TStreamerElement*)elements->UncheckedAt(i);
00907       if (!element) break;
00908       int ty = element->GetType();
00909       if (ty < kChar || ty >kULong+kOffsetL)    continue;
00910       if (ty == kLong)                         element->SetType(kInt);
00911       if (ty == kULong)                         element->SetType(kUInt);
00912       if (ty == kLong + kOffsetL)                element->SetType(kInt + kOffsetL);
00913       if (ty == kULong + kOffsetL)                element->SetType(kUInt + kOffsetL);
00914       if (ty <= kULong)                         continue;
00915       duName = element->GetName();
00916       duName.Append("QWERTY");
00917       TStreamerBasicType *bt = new TStreamerBasicType(duName, "", 0, kInt,"Int_t");
00918       {for (int j=ndata-1;j>=i;j--) {elements->AddAtAndExpand(elements->At(j),j+1);}}
00919       elements->AddAt(bt,i);
00920       ndata++;
00921       i++;
00922    }
00923    BuildOld();
00924 }
00925 
00926 //______________________________________________________________________________
00927 Bool_t TStreamerInfo::BuildFor( const TClass *in_memory_cl )
00928 {
00929    //---------------------------------------------------------------------------
00930    // Check if we can build this for foreign class - do we have some rules
00931    // to do that
00932    //---------------------------------------------------------------------------
00933    R__LOCKGUARD(gCINTMutex);
00934 
00935    if( !in_memory_cl || !in_memory_cl->GetSchemaRules() )
00936       return kFALSE;
00937 
00938    const TObjArray* rules;
00939 
00940    rules = in_memory_cl->GetSchemaRules()->FindRules( GetName(), fOnFileClassVersion, fCheckSum );
00941 
00942    if( !rules && !TClassEdit::IsSTLCont( in_memory_cl->GetName() ) ) {
00943       Warning( "BuildFor", "The build of %s streamer info for %s has been requested, but no matching conversion rules were specified", GetName(), in_memory_cl->GetName() );
00944       return kFALSE;
00945    }
00946 
00947    fClass = const_cast<TClass*>(in_memory_cl);
00948 
00949    return kTRUE;
00950 }
00951 
00952 //______________________________________________________________________________
00953 // Helper function for BuildOld
00954 namespace {
00955    Bool_t ClassWasMovedToNamespace(TClass *oldClass, TClass *newClass)
00956    {
00957       // Returns true if oldClass is the same as newClass but newClass is in a
00958       // namespace (and oldClass was not in a namespace).
00959 
00960       if (oldClass == 0 || newClass == 0) return kFALSE;
00961 
00962       UInt_t newlen = strlen(newClass->GetName());
00963       UInt_t oldlen = strlen(oldClass->GetName());
00964 
00965       const char *oldname = oldClass->GetName();
00966       for (UInt_t i = oldlen, done = false, nest = 0; (i>0) && !done ; --i) {
00967          switch (oldClass->GetName()[i-1]) {
00968             case '>' : ++nest; break;
00969             case '<' : --nest; break;
00970             case ':' : if (nest == 0) oldname= &(oldClass->GetName()[i]); done = kTRUE; break;
00971          }
00972       }
00973       oldlen = strlen(oldname);
00974       if (!(strlen(newClass->GetName()) > strlen(oldClass->GetName()))) {
00975          return kFALSE;
00976       }
00977 
00978       const char* newEnd = & (newClass->GetName()[newlen-oldlen]);
00979 
00980       if (0 != strcmp(newEnd, oldname)) {
00981          return kFALSE;
00982       }
00983 
00984       Int_t oldv = oldClass->GetStreamerInfo()->GetClassVersion();
00985 
00986       if (newClass->GetStreamerInfos() && oldv < newClass->GetStreamerInfos()->GetSize() && newClass->GetStreamerInfos()->At(oldv) && strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(), oldClass->GetName()) != 0) {
00987          // The new class has already a TStreamerInfo for the the same version as
00988          // the old class and this was not the result of an import.  So we do not
00989          // have a match
00990          return kFALSE;
00991       }
00992       return kTRUE;
00993    }
00994 
00995    Int_t ImportStreamerInfo(TClass *oldClass, TClass *newClass) {
00996       // Import the streamerInfo from oldClass to newClass
00997       // In case of conflict, returns the version number of the StreamerInfo
00998       // with the conflict.
00999       // Return 0 in case of success
01000 
01001       TIter next(oldClass->GetStreamerInfos());
01002       TStreamerInfo *info;
01003       while ((info = (TStreamerInfo*)next())) {
01004          info = (TStreamerInfo*)info->Clone();
01005          info->SetClass(newClass);
01006          Int_t oldv = info->GetClassVersion();
01007          if (oldv > newClass->GetStreamerInfos()->GetSize() || newClass->GetStreamerInfos()->At(oldv) == 0) {
01008             // All is good.
01009             newClass->GetStreamerInfos()->AddAtAndExpand(info,oldv);
01010          } else {
01011             // We verify that we are consistent and that
01012             //   newcl->GetStreamerInfos()->UncheckedAt(info->GetClassVersion)
01013             // is already the same as info.
01014             if (strcmp(newClass->GetStreamerInfos()->At(oldv)->GetName(),
01015                          oldClass->GetName()) != 0) {
01016                // The existing StreamerInfo does not already come from OldClass.
01017                // This is a real problem!
01018                return oldv;
01019             }
01020          }
01021       }
01022       return 0;
01023    }
01024 
01025    Bool_t ContainerMatchTClonesArray(TClass *newClass)
01026    {
01027       // Return true if newClass is a likely valid conversion from
01028       // a TClonesArray
01029 
01030       return newClass->GetCollectionProxy()
01031              && newClass->GetCollectionProxy()->GetValueClass()
01032              && !newClass->GetCollectionProxy()->HasPointers();
01033    }
01034 
01035    Bool_t CollectionMatch(const TClass *oldClass, const TClass* newClass)
01036    {
01037       // Return true if oldClass and newClass points to 2 compatible collection.
01038       // i.e. they contains the exact same type.
01039 
01040       TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
01041       TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
01042       
01043       TClass *oldContent = oldProxy->GetValueClass();
01044       TClass *newContent = newProxy->GetValueClass();
01045 
01046       Bool_t contentMatch = kFALSE;
01047       if (oldContent) {
01048          if (oldContent == newContent) {
01049             contentMatch = kTRUE;
01050          } else if (newContent) {
01051             TString oldFlatContent( TMakeProject::UpdateAssociativeToVector(oldContent->GetName()) );
01052             TString newFlatContent( TMakeProject::UpdateAssociativeToVector(newContent->GetName()) );
01053             contentMatch = kTRUE;
01054          } else {
01055             contentMatch = kFALSE;
01056          }
01057       } else {
01058          contentMatch = (newContent==0);
01059       }
01060 
01061       if (contentMatch) {
01062          if ((oldContent==0 && oldProxy->GetType() == newProxy->GetType())
01063              ||(oldContent && oldProxy->HasPointers() == newProxy->HasPointers())) {
01064             // We have compatibles collections (they have the same content)!
01065             return kTRUE;
01066          }
01067       }
01068       return kFALSE;
01069    }
01070 
01071    Bool_t CollectionMatchFloat16(const TClass *oldClass, const TClass* newClass)
01072    {
01073       // Return true if oldClass and newClass points to 2 compatible collection.
01074       // i.e. they contains the exact same type.
01075 
01076       TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
01077       TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
01078 
01079       if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
01080           && (oldProxy->GetType() == kFloat_t || oldProxy->GetType() == kFloat16_t)
01081           && (newProxy->GetType() == kFloat_t || newProxy->GetType() == kFloat16_t )) {
01082             // We have compatibles collections (they have the same content)!
01083          return (TClassEdit::IsSTLCont(oldClass->GetName()) == TClassEdit::IsSTLCont(newClass->GetName()));
01084       }
01085       return kFALSE;
01086    }
01087 
01088    Bool_t CollectionMatchDouble32(const TClass *oldClass, const TClass* newClass)
01089    {
01090       // Return true if oldClass and newClass points to 2 compatible collection.
01091       // i.e. they contains the exact same type.
01092 
01093       TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
01094       TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
01095 
01096       if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
01097           && (oldProxy->GetType() == kDouble_t || oldProxy->GetType() == kDouble32_t)
01098           && (newProxy->GetType() == kDouble_t || newProxy->GetType() == kDouble32_t )) {
01099             // We have compatibles collections (they have the same content)!
01100          return (TClassEdit::IsSTLCont(oldClass->GetName()) == TClassEdit::IsSTLCont(newClass->GetName()));
01101       }
01102       return kFALSE;
01103    }
01104 
01105    Bool_t CollectionMatchLong64(const TClass *oldClass, const TClass* newClass)
01106    {
01107       // Return true if oldClass and newClass points to 2 compatible collection.
01108       // i.e. they contains the exact same type.
01109 
01110       TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
01111       TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
01112 
01113       if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
01114           && (oldProxy->GetType() == kLong_t || oldProxy->GetType() == kLong64_t)
01115           && (newProxy->GetType() == kLong_t || newProxy->GetType() == kLong64_t )) {
01116          // We have compatibles collections (they have the same content)!
01117          return (TClassEdit::IsSTLCont(oldClass->GetName()) == TClassEdit::IsSTLCont(newClass->GetName()));
01118       }
01119       return kFALSE;
01120    }
01121 
01122    Bool_t CollectionMatchULong64(const TClass *oldClass, const TClass* newClass)
01123    {
01124       // Return true if oldClass and newClass points to 2 compatible collection.
01125       // i.e. they contains the exact same type.
01126 
01127       TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
01128       TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
01129 
01130       if (oldProxy->GetValueClass() == 0 && newProxy->GetValueClass() == 0
01131           && (oldProxy->GetType() == kULong_t || oldProxy->GetType() == kULong64_t)
01132           && (newProxy->GetType() == kULong_t || newProxy->GetType() == kULong64_t )) {
01133          // We have compatibles collections (they have the same content)!
01134          return (TClassEdit::IsSTLCont(oldClass->GetName()) == TClassEdit::IsSTLCont(newClass->GetName()));
01135       }
01136       return kFALSE;
01137    }
01138 }
01139 
01140 //______________________________________________________________________________
01141 void TStreamerInfo::BuildOld()
01142 {
01143    // rebuild the TStreamerInfo structure
01144 
01145    R__LOCKGUARD(gCINTMutex);
01146 
01147    if (gDebug > 0) {
01148       printf("\n====>Rebuilding TStreamerInfo for class: %s, version: %d\n", GetName(), fClassVersion);
01149    }
01150 
01151    Bool_t wasCompiled = IsCompiled();
01152 
01153    // This is used to avoid unwanted recursive call to Build
01154    fIsBuilt = kTRUE;
01155 
01156    if (fClass->GetClassVersion() == fClassVersion) {
01157       fClass->BuildRealData();
01158    }
01159    else {
01160       // This is to support the following case
01161       //  Shared library: Event v2
01162       //  calling cl->GetStreamerInfo(1)->BuildOld();  (or equivalent)
01163       //  which calls cl->BuildReadData()
01164       //  which set fRealData to some value
01165       //  then call Event()
01166       //  which call cl->GetStreamerInfo()
01167       //  which call cl->BuildRealData();
01168       //  which returns immediately (upon seeing fRealData!=0)
01169       //  then the main StreamerInfo build using the partial content of fRealData
01170       //  then BuildRealData returns
01171       //  then GetStreamerInfo() returns
01172       //  then Event() returns
01173       //  then fRealData is finished being populated
01174       //  then this function continue,
01175       //  then it uses the main streamerInfo
01176       //  .... which is incomplete.
01177       //
01178       //  Instead we force the creation of the main streamerInfo object
01179       //  before the creation of fRealData.
01180       fClass->GetStreamerInfo();
01181    }
01182 
01183    TIter next(fElements);
01184    TStreamerElement* element;
01185    Int_t offset = 0;
01186    TMemberStreamer* streamer = 0;
01187 
01188    Int_t sp = sizeof(void*);
01189 #if defined(R__SGI64)
01190    sp = 8;
01191 #endif
01192 
01193    int nBaze = 0;
01194 
01195    if (fClass->GetCollectionProxy() && (fElements->GetEntries() == 1) && !strcmp(fElements->At(0)->GetName(), "This")) {
01196       element = (TStreamerElement*)next();
01197       element->SetNewType( element->GetType() );
01198       element->SetNewClass( fClass );
01199    }
01200 
01201    TClass *allocClass = 0;
01202    TStreamerInfo *infoalloc = 0;
01203 
01204    //---------------------------------------------------------------------------
01205    // Get schema rules for this class
01206    //---------------------------------------------------------------------------
01207    const ROOT::TSchemaMatch*   rules   = 0;
01208    const ROOT::TSchemaRuleSet* ruleSet = fClass->GetSchemaRules();
01209 
01210    rules = (ruleSet ? ruleSet->FindRules( GetName(), fOnFileClassVersion, fCheckSum ) : 0);
01211 
01212    Bool_t shouldHaveInfoLoc = fClass->TestBit(TClass::kIsEmulation) && !TClassEdit::IsStdClass(fClass->GetName());
01213    Int_t virtualInfoLocAlloc = 0;
01214    fNVirtualInfoLoc = 0;
01215    delete [] fVirtualInfoLoc;
01216    fVirtualInfoLoc = 0;
01217 
01218    while ((element = (TStreamerElement*) next())) {
01219       if (element->IsA()==TStreamerArtificial::Class() 
01220           || element->TestBit(TStreamerElement::kCache) ) 
01221       {
01222          // Prevent BuildOld from modifying existing ArtificialElement (We need to review when and why BuildOld 
01223          // needs to be re-run; it might be needed if the 'current' class change (for example from being an onfile 
01224          // version to being a version loaded from a shared library) and we thus may have to remove the artifical 
01225          // element at the beginning of BuildOld)
01226 
01227          continue;
01228       };
01229 
01230       element->SetNewType(element->GetType());
01231       element->Init();
01232       if (element->IsBase()) {
01233          //---------------------------------------------------------------------
01234          // Dealing with nonSTL bases
01235          //---------------------------------------------------------------------
01236          if (element->IsA() == TStreamerBase::Class()) {
01237             TStreamerBase* base = (TStreamerBase*) element;
01238 #if defined(PROPER_IMPLEMEMANTION_OF_BASE_CLASS_RENAMING)
01239             TClass* baseclass =  fClass->GetBaseClass( base->GetName() );
01240 #else
01241             // Currently the base class renaming does not work, so we use the old
01242             // version of the code which essentially disable the next if(!baseclass ..
01243             // statement.
01244             TClass* baseclass =  base->GetClassPointer();
01245 #endif
01246 
01247             //------------------------------------------------------------------
01248             // We do not have this base class - check if we're renaming
01249             //------------------------------------------------------------------
01250             if( !baseclass && !fClass->TestBit( TClass::kIsEmulation ) ) {
01251                const ROOT::TSchemaRule* rule = (rules ? rules->GetRuleWithSource( base->GetName() ) : 0);
01252 
01253                //---------------------------------------------------------------
01254                // No renaming, sorry
01255                //---------------------------------------------------------------
01256                if( !rule ) {
01257                   Error("BuildOld", "Could not find base class: %s for %s and could not find any matching rename rule\n", base->GetName(), GetName());
01258                   continue;
01259                }
01260 
01261                //----------------------------------------------------------------
01262                // Find a new target class
01263                //----------------------------------------------------------------
01264                const TObjArray* targets = rule->GetTarget();
01265                if( !targets ) {
01266                   Error("BuildOld", "Could not find base class: %s for %s, renaming rule was found but is malformed\n", base->GetName(), GetName());
01267                }
01268                TString newBaseClass = ((TObjString*)targets->At(0))->GetString();
01269                baseclass = TClass::GetClass( newBaseClass );
01270                base->SetNewBaseClass( baseclass );
01271             }
01272             //-------------------------------------------------------------------
01273             // No base class in emulated mode
01274             //-------------------------------------------------------------------
01275             else if( !baseclass ) {
01276                baseclass = base->GetClassPointer();
01277                if (!baseclass) {
01278                   Warning("BuildOld", "Missing base class: %s skipped", base->GetName());
01279                   // FIXME: Why is the version number 1 here? Answer: because we don't know any better at this point
01280                   baseclass = new TClass(element->GetName(), 1, 0, 0, -1, -1);
01281                   element->Update(0, baseclass);
01282                }
01283             }
01284             baseclass->BuildRealData();
01285 
01286             // Force the StreamerInfo "Compilation" of the base classes first. This is necessary in 
01287             // case the base class contains a member used as an array dimension in the derived classes.
01288             Int_t version = base->GetBaseVersion();
01289             TStreamerInfo* infobase = (TStreamerInfo*)baseclass->GetStreamerInfo(version);
01290             if (infobase->GetTypes() == 0) {
01291                infobase->BuildOld();
01292             }
01293             Int_t baseOffset = fClass->GetBaseClassOffset(baseclass);
01294 
01295             if (shouldHaveInfoLoc && baseclass->TestBit(TClass::kIsEmulation) ) {
01296                if ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) > virtualInfoLocAlloc ) {
01297                   ULong_t *store = fVirtualInfoLoc;
01298                   virtualInfoLocAlloc = 16 * ( (fNVirtualInfoLoc + infobase->fNVirtualInfoLoc) / 16 + 1);
01299                   fVirtualInfoLoc = new ULong_t[virtualInfoLocAlloc];
01300                   if (store) {
01301                      memcpy(fVirtualInfoLoc, store, sizeof(ULong_t)*fNVirtualInfoLoc);
01302                      delete [] store;
01303                   }
01304                }
01305                for (int nloc = 0; nloc < infobase->fNVirtualInfoLoc; ++nloc) {
01306                   fVirtualInfoLoc[ fNVirtualInfoLoc + nloc ] = baseOffset + infobase->fVirtualInfoLoc[nloc];
01307                }
01308                fNVirtualInfoLoc += infobase->fNVirtualInfoLoc;
01309             }
01310             // FIXME: Presumably we're in emulated mode, but is still does not make any sense
01311             // shouldn't it be element->SetNewType(-1) ?
01312             if (baseOffset < 0) {
01313                baseOffset = 0;
01314             }
01315             element->SetOffset(baseOffset);
01316             offset += baseclass->Size();
01317 
01318             continue;
01319          } else {
01320             // Not a base elem but still base, string or STL as a base
01321             nBaze++;
01322             TList* listOfBases = fClass->GetListOfBases();
01323             Int_t baseOffset = -1;
01324             Int_t asize = 0;
01325             if (listOfBases) {
01326                // Do a search for the classname and some of its alternatives spelling.
01327 
01328                TBaseClass* bc = 0;
01329                TIter nextBC(fClass->GetListOfBases());
01330                while ((bc = (TBaseClass*) nextBC())) {
01331                   if (strchr(bc->GetName(), '<') || !strcmp(bc->GetName(),"string")) {
01332                      TString bcName(TClassEdit::ShortType(bc->GetName(), TClassEdit::kDropStlDefault).c_str());
01333                      TString elName(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropStlDefault).c_str());
01334                      if (bcName == elName) {
01335                         break;
01336                      }
01337                   }
01338                }
01339 
01340                if (!bc) {
01341                   Error("BuildOld", "Could not find STL base class: %s for %s\n", element->GetName(), GetName());
01342                   continue;
01343                }
01344                baseOffset = bc->GetDelta();
01345                asize = bc->GetClassPointer()->Size();
01346 
01347             } else if (fClass->TestBit( TClass::kIsEmulation )) {
01348                // Do a search for the classname and some of its alternatives spelling.
01349 
01350                TStreamerInfo* newInfo = (TStreamerInfo*) fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
01351                if (newInfo == this) {
01352                   baseOffset = offset;
01353                   asize = element->GetSize();
01354                } else if (newInfo) {
01355                   TIter newElems( newInfo->GetElements() );
01356                   TStreamerElement *newElement;
01357                   while( (newElement = (TStreamerElement*)newElems()) ) {
01358                      const char *newElName = newElement->GetName();
01359                      if (newElement->IsBase() && (strchr(newElName,'<') || !strcmp(newElName,"string")) ) {
01360                         TString bcName(TClassEdit::ShortType(newElName, TClassEdit::kDropStlDefault).c_str());
01361                         TString elName(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropStlDefault).c_str());
01362                         if (bcName == elName) {
01363                            break;
01364                         }
01365                      }
01366                   }
01367                   if (!newElement) {
01368                      Error("BuildOld", "Could not find STL base class: %s for %s\n", element->GetName(), GetName());
01369                      continue;
01370                   }
01371                   baseOffset = newElement->GetOffset();
01372                   asize = newElement->GetSize();
01373                }
01374             }
01375             if (baseOffset == -1) {
01376                TClass* cb = element->GetClassPointer();
01377                if (!cb) {
01378                   element->SetNewType(-1);
01379                   continue;
01380                }
01381                asize = cb->Size();
01382                baseOffset = fClass->GetBaseClassOffset(cb);
01383             }
01384 
01385             //  we know how to read but do we know where to read?
01386             if (baseOffset < 0) {
01387                element->SetNewType(-1);
01388                continue;
01389             }
01390             element->SetOffset(baseOffset);
01391             offset += asize;
01392             continue;
01393          }
01394       }
01395 
01396       // If we get here, this means that we looked at all the base classes.
01397       if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
01398          fNVirtualInfoLoc = 1;
01399          fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement.
01400          fVirtualInfoLoc[0] = offset;
01401          offset += sizeof(TStreamerInfo*);
01402       }
01403 
01404       TDataMember* dm = 0;
01405 
01406       // First set the offset and sizes.
01407       if (fClass->GetDeclFileLine() < 0) {
01408          // Note the initilization in this case are
01409          // delayed until __after__ the schema evolution
01410          // section, just in case the info has changed.
01411 
01412          // We are in the emulated case
01413          streamer = 0;
01414          element->Init(this);
01415       } else {
01416          // The class is loaded.
01417 
01418          // First look for the data member in the current class
01419          dm = (TDataMember*) fClass->GetListOfDataMembers()->FindObject(element->GetName());
01420          if (dm && dm->IsPersistent()) {
01421             fClass->BuildRealData();
01422             streamer = 0;
01423             offset = GetDataMemberOffset(dm, streamer);
01424             element->SetOffset(offset);
01425             element->Init(this);
01426             element->SetStreamer(streamer);
01427             int narr = element->GetArrayLength();
01428             if (!narr) {
01429                narr = 1;
01430             }
01431             int dsize = dm->GetUnitSize();
01432             element->SetSize(dsize*narr);
01433          } else {
01434             // We did not find it, let's look for it in the base classes via TRealData
01435             TRealData* rd = fClass->GetRealData(element->GetName());
01436             if (rd && rd->GetDataMember()) {
01437                element->SetOffset(rd->GetThisOffset());
01438                element->Init(this);
01439                dm = rd->GetDataMember();
01440                int narr = element->GetArrayLength();
01441                if (!narr) {
01442                   narr = 1;
01443                }
01444                int dsize = dm->GetUnitSize();
01445                element->SetSize(dsize*narr);
01446             }
01447          }
01448       }
01449 
01450       // Now let's deal with Schema evolution
01451       Int_t newType = kNoType_t;
01452       TClassRef newClass;
01453 
01454       if (dm && dm->IsPersistent()) {
01455          if (dm->GetDataType()) {
01456             Bool_t isPointer = dm->IsaPointer();
01457             Bool_t isArray = element->GetArrayLength() >= 1;
01458             Bool_t hasCount = element->HasCounter();
01459             newType = dm->GetDataType()->GetType();
01460             if ((newType == kChar) && isPointer && !isArray && !hasCount) {
01461                newType = kCharStar;
01462             } else if (isPointer) {
01463                newType += kOffsetP;
01464             } else if (isArray) {
01465                newType += kOffsetL;
01466             }
01467          }
01468          if (newType == 0) {
01469             newClass = TClass::GetClass(dm->GetTypeName());
01470          }
01471       } else {
01472          // Either the class is not loaded or the data member is gone
01473          if (!fClass->IsLoaded()) {
01474             TStreamerInfo* newInfo = (TStreamerInfo*) fClass->GetStreamerInfos()->At(fClass->GetClassVersion());
01475             if (newInfo && (newInfo != this)) {
01476                TStreamerElement* newElems = (TStreamerElement*) newInfo->GetElements()->FindObject(element->GetName());
01477                newClass = newElems ?  newElems->GetClassPointer() : 0;
01478                if (newClass == 0) {
01479                   newType = newElems ? newElems->GetType() : kNoType_t;
01480                   if (!(newType < kObject)) {
01481                      // sanity check.
01482                      newType = kNoType_t;
01483                   }
01484                }
01485             } else {
01486                newClass = element->GetClassPointer();
01487                if (newClass.GetClass() == 0) {
01488                   newType = element->GetType();
01489                   if (!(newType < kObject)) {
01490                      // sanity check.
01491                      newType = kNoType_t;
01492                   }
01493                }
01494             }
01495          }
01496       }
01497 
01498       if (newType) {
01499          // Case of a numerical type
01500          if (element->GetType() != newType) {
01501             element->SetNewType(newType);
01502             if (gDebug > 0) {
01503                Info("BuildOld", "element: %s %s::%s has new type: %s/%d", element->GetTypeName(), GetName(), element->GetName(), dm ? dm->GetFullTypeName() : TDataType::GetTypeName((EDataType)newType), newType);
01504             }
01505          }
01506       } else if (newClass.GetClass()) {
01507          // Sometime BuildOld is called again.
01508          // In that case we migth already have fix up the streamer element.
01509          // So we need to go back to the original information!
01510          newClass.Reset();
01511          TClass* oldClass = TClass::GetClass(TClassEdit::ShortType(element->GetTypeName(), TClassEdit::kDropTrailStar).c_str());
01512          if (oldClass == newClass.GetClass()) {
01513             // Nothing to do :)
01514          } else if (ClassWasMovedToNamespace(oldClass, newClass.GetClass())) {
01515             Int_t oldv;
01516             if (0 != (oldv = ImportStreamerInfo(oldClass, newClass.GetClass()))) {
01517                 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);
01518             } else {
01519                element->SetTypeName(newClass->GetName());
01520                if (gDebug > 0) {
01521                   Warning("BuildOld", "element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
01522                }
01523             }
01524          } else if (oldClass == TClonesArray::Class()) {
01525             if (ContainerMatchTClonesArray(newClass.GetClass())) {
01526                Int_t elemType = element->GetType();
01527                Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
01528                element->Update(oldClass, newClass.GetClass());
01529                TVirtualCollectionProxy *cp = newClass->GetCollectionProxy();
01530                TConvertClonesArrayToProxy *ms = new TConvertClonesArrayToProxy(cp, element->IsaPointer(), isPrealloc);
01531                element->SetStreamer(ms);
01532 
01533                // When the type is kObject, the TObject::Streamer is used instead
01534                // of the TStreamerElement's streamer.  So let force the usage
01535                // of our streamer
01536                if (element->GetType() == kObject) {
01537                   element->SetNewType(kAny);
01538                   element->SetType(kAny);
01539                }
01540                if (gDebug > 0) {
01541                   Warning("BuildOld","element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
01542                }
01543             } else {
01544                element->SetNewType(-2);
01545             }
01546          } else if (oldClass  && oldClass->GetCollectionProxy() && newClass->GetCollectionProxy()) {
01547             if (CollectionMatch(oldClass, newClass)) {
01548                Int_t oldkind = TMath::Abs(TClassEdit::IsSTLCont( oldClass->GetName() ));
01549                Int_t newkind = TMath::Abs(TClassEdit::IsSTLCont( newClass->GetName() ));
01550 
01551                if ( (oldkind==TClassEdit::kMap || oldkind==TClassEdit::kMultiMap) &&
01552                     (newkind!=TClassEdit::kMap && newkind!=TClassEdit::kMultiMap) ) {
01553 
01554                   Int_t elemType = element->GetType();
01555                   Bool_t isPrealloc = (elemType == kObjectp) || (elemType == kAnyp) || (elemType == (kObjectp + kOffsetL)) || (elemType == (kAnyp + kOffsetL));
01556 
01557                   TClassStreamer *streamer2 = newClass->GetStreamer();
01558                   if (streamer2) {
01559                      TConvertMapToProxy *ms = new TConvertMapToProxy(streamer2, element->IsaPointer(), isPrealloc);
01560                      if (ms && ms->IsValid()) {
01561                         element->SetStreamer(ms);
01562                         switch( element->GetType() ) {
01563                            //case TStreamerInfo::kSTLvarp:           // Variable size array of STL containers.
01564                         case TStreamerInfo::kSTLp:                // Pointer to container with no virtual table (stl) and no comment
01565                         case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL:     // array of pointers to container with no virtual table (stl) and no comment
01566                            element->SetNewType(-2);                       
01567                            break;
01568                         case TStreamerInfo::kSTL:             // container with no virtual table (stl) and no comment
01569                         case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL:  // array of containers with no virtual table (stl) and no comment
01570                            break;
01571                         }
01572                      } else {
01573                         delete ms;
01574                      }
01575                   }
01576                   element->Update(oldClass, newClass.GetClass());
01577 
01578                } else if ( (newkind==TClassEdit::kMap || newkind==TClassEdit::kMultiMap) &&
01579                            (oldkind!=TClassEdit::kMap && oldkind!=TClassEdit::kMultiMap) ) {
01580                   element->SetNewType(-2); 
01581                } else {                                    
01582                   element->Update(oldClass, newClass.GetClass());
01583                }
01584                // Is this needed ? : element->SetSTLtype(newelement->GetSTLtype());
01585                if (gDebug > 0) {
01586                   Warning("BuildOld","element: %s::%s %s has new type %s", GetName(), element->GetTypeName(), element->GetName(), newClass->GetName());
01587                }
01588             } else if (CollectionMatchFloat16(oldClass,newClass)) {
01589                // Actually nothing to do, since both are the same collection of double in memory.
01590             } else if (CollectionMatchDouble32(oldClass,newClass)) {
01591                // Actually nothing to do, since both are the same collection of double in memory.              
01592             } else if (CollectionMatchLong64(oldClass,newClass)) {
01593                // Not much to do since both are the same collection of 8 bits entities on file.
01594                element->Update(oldClass, newClass.GetClass());
01595             } else if (CollectionMatchULong64(oldClass,newClass)) {
01596                // Not much to do since both are the same collection of 8 bits unsigned entities on file              
01597                element->Update(oldClass, newClass.GetClass());
01598             } else {
01599                element->SetNewType(-2);
01600             }
01601 
01602          } else if(oldClass && 
01603                    newClass.GetClass() && 
01604                    newClass->GetSchemaRules() && 
01605                    newClass->GetSchemaRules()->HasRuleWithSourceClass( oldClass->GetName() ) ) {
01606             //-----------------------------------------------------------------------
01607             // We can convert one type to another (at least for some of the versions.
01608             //-----------------------------------------------------------------------
01609             element->SetNewClass( newClass );               
01610          } else {
01611             element->SetNewType(-2);
01612          }
01613       } else {
01614          element->SetNewType(-1);
01615          offset = kMissing;
01616          element->SetOffset(kMissing);
01617       }
01618 
01619       if (offset != kMissing && fClass->GetDeclFileLine() < 0) {
01620          // Note the initilization in this case are
01621          // delayed until __after__ the schema evolution
01622          // section, just in case the info has changed.
01623          Int_t asize = element->GetSize();
01624          // align the non-basic data types (required on alpha and IRIX!!)
01625          if ((offset % sp) != 0) {
01626             offset = offset - (offset % sp) + sp;
01627          }
01628          element->SetOffset(offset);
01629          offset += asize;
01630       }
01631 
01632       if ( !wasCompiled && rules && rules->HasRuleWithSource( element->GetName(), kTRUE ) ) {
01633          
01634          if (allocClass == 0) {
01635             infoalloc  = (TStreamerInfo *)Clone(TString::Format("%s@@%d",GetName(),GetOnFileClassVersion()));
01636             infoalloc->BuildCheck();
01637             infoalloc->BuildOld();
01638             allocClass = infoalloc->GetClass();
01639          }
01640 
01641          // Now that we are caching the unconverted element, we do not assign it to the real type even if we could have!
01642          if (element->GetNewType()>0 /* intentionally not including base class for now */ 
01643              && !rules->HasRuleWithTarget( element->GetName(), kTRUE ) ) 
01644          {
01645             TStreamerElement *copy = (TStreamerElement*)element->Clone();
01646             R__TObjArray_InsertBefore( fElements, copy, element );
01647             next(); // move the cursor passed the insert object.
01648             copy->SetBit(TStreamerElement::kRepeat);
01649             element = copy;
01650 
01651             // Warning("BuildOld","%s::%s is not set from the version %d of %s (You must add a rule for it)\n",GetName(), element->GetName(), GetClassVersion(), GetName() );
01652          }
01653          element->SetBit(TStreamerElement::kCache);
01654          element->SetNewType( element->GetType() );
01655          element->SetOffset(infoalloc->GetOffset(element->GetName()));
01656       }
01657 
01658       if (element->GetNewType() == -2) {
01659          Warning("BuildOld", "Cannot convert %s::%s from type:%s to type:%s, skip element", GetName(), element->GetName(), element->GetTypeName(), newClass->GetName());
01660       }
01661    }
01662 
01663    // If we get here, this means that there no data member after the last base class
01664    // (or no base class at all).
01665    if (shouldHaveInfoLoc && fNVirtualInfoLoc==0) {
01666       fNVirtualInfoLoc = 1;
01667       fVirtualInfoLoc = new ULong_t[1]; // To allow for a single delete statement.
01668       fVirtualInfoLoc[0] = offset;
01669       offset += sizeof(TStreamerInfo*);
01670    }
01671 
01672    // change order , move "bazes" to the end. Workaround old bug
01673    if ((fOldVersion <= 2) && nBaze) {
01674       SetBit(kRecovered);
01675       TObjArray& arr = *fElements;
01676       TObjArray tai(nBaze);
01677       int narr = arr.GetLast() + 1;
01678       int iel;
01679       int jel = 0;
01680       int kel = 0;
01681       for (iel = 0; iel < narr; ++iel) {
01682          element = (TStreamerElement*) arr[iel];
01683          if (element->IsBase() && (element->IsA() != TStreamerBase::Class())) {
01684             tai[kel++] = element;
01685          } else {
01686             arr[jel++] = element;
01687          }
01688       }
01689       for (kel = 0; jel < narr;) {
01690          arr[jel++] = tai[kel++];
01691       }
01692    }
01693 
01694    // Now add artificial TStreamerElement (i.e. rules that creates new members or set transient members).
01695    if (!wasCompiled) InsertArtificialElements(rules);
01696 
01697    if (!wasCompiled && allocClass) {
01698 
01699       TStreamerElement *el = new TStreamerArtificial("@@alloc","", 0, TStreamerInfo::kCacheNew, allocClass->GetName());
01700       R__TObjArray_InsertAt( fElements, el, 0 );
01701 
01702       el = new TStreamerArtificial("@@dealloc","", 0, TStreamerInfo::kCacheDelete, allocClass->GetName());
01703       fElements->Add( el );
01704    }
01705 
01706    Compile();
01707    delete rules;
01708 }
01709 
01710 //______________________________________________________________________________
01711 void TStreamerInfo::Clear(Option_t *option)
01712 {
01713    // If opt cointains 'built', reset this StreamerInfo as if Build or BuildOld
01714    // was never called on it (usefull to force their re-running).
01715 
01716    TString opt = option;
01717    opt.ToLower();
01718 
01719    if (opt.Contains("build")) {
01720       delete [] fType;     fType    = 0;
01721       delete [] fNewType;  fNewType = 0;
01722       delete [] fOffset;   fOffset  = 0;
01723       delete [] fLength;   fLength  = 0;
01724       delete [] fElem;     fElem    = 0;
01725       delete [] fMethod;   fMethod  = 0;
01726       delete [] fComp;     fComp    = 0;
01727       fNdata = 0;
01728       fSize = 0;
01729       ResetBit(kIsCompiled);
01730       
01731       if (fReadObjectWise) fReadObjectWise->fActions.clear();
01732       if (fReadMemberWise) fReadMemberWise->fActions.clear();
01733    }
01734 }
01735 
01736 namespace {
01737    // TMemberInfo
01738    // Local helper class to be able to compare data member represened by
01739    // 2 distinct TStreamerInfos
01740    class TMemberInfo {
01741    public:
01742       TString fName;
01743       TString fClassName;
01744       TString fComment;
01745       void SetName(const char *name) {
01746          fName = name;
01747       }
01748       void SetClassName(const char *name) {
01749          fClassName = TClassEdit::ShortType( name, TClassEdit::kDropStlDefault );
01750       }
01751       void SetComment(const char *title) {
01752          const char *left = strstr(title,"[");
01753          if (left) {
01754             const char *right = strstr(left,"]");
01755             if (right) {
01756                ++left;
01757                fComment.Append(left,right-left);
01758             }
01759          }
01760       }
01761       void Clear() {
01762          fName.Clear();
01763          fClassName.Clear();
01764          fComment.Clear();
01765       }
01766       /* Hide this not yet used implementation to suppress warnings message
01767        from icc 11 
01768       Bool_t operator==(const TMemberInfo &other) {
01769          return fName==other.fName
01770             && fClassName == other.fClassName
01771             && fComment == other.fComment;
01772       }
01773        */
01774       Bool_t operator!=(const TMemberInfo &other) {
01775          if (fName != other.fName) return kTRUE;
01776          if (fClassName != other.fClassName) {
01777             if ( (fClassName == "long" && (other.fClassName == "long long" || other.fClassName == "Long64_t"))
01778                   || ( (fClassName == "long long" || fClassName == "Long64_t") && other.fClassName == "long") ) {
01779                // This is okay both have the same on file format.
01780             } else if ( (fClassName == "unsigned long" && (other.fClassName == "unsigned long long" || other.fClassName == "ULong64_t"))
01781                        || ( (fClassName == "unsigned long long" || fClassName == "ULong64_t") && other.fClassName == "unsigned long") ) {
01782                // This is okay both have the same on file format.
01783             } else {
01784                return kTRUE;
01785             }
01786          }
01787          return fComment != other.fComment;
01788       }
01789    };
01790 }
01791 
01792 //______________________________________________________________________________
01793 void TStreamerInfo::CallShowMembers(void* obj, TMemberInspector &insp) const
01794 {
01795    // Emulated a call ShowMembers() on the obj of this class type, passing insp and parent.
01796 
01797    TIter next(fElements);
01798    TStreamerElement* element = (TStreamerElement*) next();
01799 
01800    TString elementName;
01801 
01802    for (; element; element = (TStreamerElement*) next()) {
01803 
01804       // Skip elements which have not been allocated memory.
01805       if (element->GetOffset() == kMissing) {
01806          continue;
01807       }
01808 
01809       char* eaddr = ((char*)obj) + element->GetOffset();
01810 
01811       if (element->IsBase()) {
01812          // Nothing to do this round.
01813       } else if (element->IsaPointer()) {
01814          elementName.Form("*%s",element->GetFullName());
01815          insp.Inspect(fClass, insp.GetParent(), elementName.Data(), eaddr);
01816       } else {
01817          insp.Inspect(fClass, insp.GetParent(), element->GetFullName(), eaddr);         
01818          Int_t etype = element->GetType();
01819          switch(etype) {
01820             case kObject:
01821             case kAny:
01822             case kTObject:
01823             case kTString:
01824             case kTNamed:
01825             case kSTL:
01826             {
01827                TClass *ecl = element->GetClassPointer();
01828                if (ecl && (fClass!=ecl /* This happens 'artificially for stl container see the use of "This" */)) { 
01829                   insp.InspectMember(ecl, eaddr, TString(element->GetName()) + ".");
01830                }
01831                break;
01832             }
01833          } // switch(etype)
01834       } // if IsaPointer()
01835    } // Loop over elements
01836 
01837    // And now do the base classes
01838    next.Reset();
01839    element = (TStreamerElement*) next();
01840    for (; element; element = (TStreamerElement*) next()) {
01841       if (element->IsBase()) {
01842          // Skip elements which have not been allocated memory.
01843          if (element->GetOffset() == kMissing) {
01844             continue;
01845          }
01846 
01847          char* eaddr = ((char*)obj) + element->GetOffset();
01848 
01849          TClass *ecl = element->GetClassPointer();
01850          if (ecl) {
01851             ecl->CallShowMembers(eaddr, insp);
01852          }
01853       } // If is a abse
01854    } // Loop over elements
01855 }
01856 
01857 //______________________________________________________________________________
01858 TObject *TStreamerInfo::Clone(const char *newname) const
01859 {
01860    // Make a clone of an object using the Streamer facility.
01861    // If newname is specified, this will be the name of the new object.
01862 
01863    TStreamerInfo *newinfo = (TStreamerInfo*)TNamed::Clone(newname);
01864    if (newname && newname[0] && fName != newname) {
01865       TObjArray *newelems = newinfo->GetElements(); 
01866       Int_t ndata = newelems->GetEntries();
01867       for(Int_t i = 0; i < ndata; ++i) {
01868          TObject *element = newelems->UncheckedAt(i);
01869          if (element->IsA() == TStreamerLoop::Class()) {
01870             TStreamerLoop *eloop = (TStreamerLoop*)element;
01871             if (fName == eloop->GetCountClass()) {
01872                eloop->SetCountClass(newname);
01873                eloop->Init();
01874             }
01875          } else if (element->IsA() == TStreamerBasicPointer::Class()) {
01876             TStreamerBasicPointer *eptr = (TStreamerBasicPointer*)element;
01877             if (fName == eptr->GetCountClass()) {
01878                eptr->SetCountClass(newname);
01879                eptr->Init();
01880             }
01881          }
01882       }
01883    }
01884    return newinfo;
01885 }
01886 
01887 //______________________________________________________________________________
01888 Bool_t TStreamerInfo::CompareContent(TClass *cl, TVirtualStreamerInfo *info, Bool_t warn, Bool_t complete)
01889 {
01890    // Return True if the current StreamerInfo in cl or info is equivalent to this TStreamerInfo.
01891    // 'Equivalent' means the same number of persistent data member which the same actual C++ type and
01892    // the same name.
01893    // if 'warn' is true, Warning message are printed to explicit the differences.
01894    // if 'complete' is false, stop at the first error, otherwise continue until all members have been checked.
01895 
01896    Bool_t result = kTRUE;
01897    R__ASSERT( (cl==0 || info==0) && (cl!=0 || info!=0) /* must compare to only one thhing! */);
01898 
01899    TString name;
01900    TString type;
01901    TStreamerElement *el;
01902    TStreamerElement *infoel;
01903 
01904    TIter next(GetElements());
01905    TIter infonext((TList*)0);
01906    TIter basenext((TList*)0);
01907    TIter membernext((TList*)0);
01908    if (info) {
01909       infonext = info->GetElements();
01910    }
01911    if (cl) {
01912       TList *tlb = cl->GetListOfBases();
01913       if (tlb) {   // Loop over bases
01914          basenext = tlb;
01915       }
01916       tlb = cl->GetListOfDataMembers();
01917       if (tlb) {
01918          membernext = tlb;
01919       }
01920    }
01921 
01922    // First let's compare base classes
01923    Bool_t done = kFALSE;
01924    TString localClass;
01925    TString otherClass;
01926    while(!done) {
01927       localClass.Clear();
01928       otherClass.Clear();
01929       el = (TStreamerElement*)next();
01930       if (el && el->IsBase()) {
01931          localClass = el->GetName();
01932       } else {
01933          el = 0;
01934       }
01935       if (cl) {
01936          TBaseClass *tbc = (TBaseClass*)basenext();
01937          if (tbc) {
01938             otherClass = tbc->GetName();
01939          } else if (el==0) {
01940             done = kTRUE;
01941             break;
01942          }
01943       } else {
01944          infoel = (TStreamerElement*)infonext();
01945          if (infoel && infoel->IsBase()) {
01946             otherClass = infoel->GetName();
01947          } else if (el==0) {
01948             done = kTRUE;
01949             break;
01950          }
01951       }
01952       // Need to normalized the name
01953       if (localClass != otherClass) {
01954          if (warn) {
01955             if (el==0) {
01956                Warning("CompareContent",
01957                        "The in-memory layout version %d for class '%s' has a base class (%s) that the on-file layout version %d does not have.",
01958                        GetClassVersion(), GetName(), otherClass.Data(), GetClassVersion());
01959             } else if (otherClass.Length()==0) {
01960                Warning("CompareContent",
01961                        "The on-file layout version %d for class '%s'  has a base class (%s) that the in-memory layout version %d does not have",
01962                        GetClassVersion(), GetName(), localClass.Data(), GetClassVersion());
01963             } else {
01964                Warning("CompareContent",
01965                        "One base class of the on-file layout version %d and of the in memory layout version %d for '%s' is different: '%s' vs '%s'",
01966                        GetClassVersion(), GetClassVersion(), GetName(), localClass.Data(), otherClass.Data());
01967             }
01968          }
01969          if (!complete) return kFALSE;
01970          result = result && kFALSE;
01971       }
01972    }
01973    if (!result && !complete) {
01974       return result;
01975    }
01976    // Next the datamembers
01977    done = kFALSE;
01978    next.Reset();
01979    infonext.Reset();
01980 
01981    TMemberInfo local;
01982    TMemberInfo other;
01983    UInt_t idx = 0;
01984    while(!done) {
01985       local.Clear();
01986       other.Clear();
01987       el = (TStreamerElement*)next();
01988       while (el && (el->IsBase() || el->IsA() == TStreamerArtificial::Class())) {
01989          el = (TStreamerElement*)next();
01990          ++idx;
01991       }
01992       if (el) {
01993          local.SetName( el->GetName() );
01994          local.SetClassName( el->GetTypeName() );
01995          local.SetComment( el->GetTitle() );
01996       }
01997       if (cl) {
01998          TDataMember *tdm = (TDataMember*)membernext();
01999          while(tdm && ( (!tdm->IsPersistent()) || (tdm->Property()&kIsStatic) || (el && local.fName != tdm->GetName()) )) {
02000             tdm = (TDataMember*)membernext();
02001          }
02002          if (tdm) {
02003             other.SetName( tdm->GetName() );
02004             other.SetClassName( tdm->GetFullTypeName() );
02005             other.SetComment( tdm->GetTitle() );
02006          } else if (el==0) {
02007             done = kTRUE;
02008             break;
02009          }
02010       } else {
02011          infoel = (TStreamerElement*)infonext();
02012          while (infoel && (infoel->IsBase() || infoel->IsA() == TStreamerArtificial::Class())) {
02013             infoel = (TStreamerElement*)infonext();
02014          }
02015          if (infoel) {
02016             other.SetName( infoel->GetName() );
02017             other.SetClassName( infoel->GetTypeName() );
02018             other.SetComment( infoel->GetTitle() );
02019          } else if (el==0) {
02020             done = kTRUE;
02021             break;
02022          }
02023       }
02024       if (local!=other) {
02025          if (warn) {
02026             if (!el) {
02027                Warning("CompareContent","The following data member of\nthe on-file layout version %d of class '%s' is missing from \nthe in-memory layout version %d:\n"
02028                        "   %s %s; //%s"
02029                        ,GetClassVersion(), GetName(), GetClassVersion()
02030                        ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
02031 
02032             } else if (other.fName.Length()==0) {
02033                Warning("CompareContent","The following data member of\nthe in-memory layout version %d of class '%s' is missing from \nthe on-file layout version %d:\n"
02034                        "   %s %s; //%s"
02035                        ,GetClassVersion(), GetName(), GetClassVersion()
02036                        ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data());
02037             } else {
02038                Warning("CompareContent","The following data member of\nthe on-file layout version %d of class '%s' differs from \nthe in-memory layout version %d:\n"
02039                        "   %s %s; //%s\n"
02040                        "vs\n"
02041                        "   %s %s; //%s"
02042                        ,GetClassVersion(), GetName(), GetClassVersion()
02043                        ,local.fClassName.Data(),local.fName.Data(),local.fComment.Data()
02044                        ,other.fClassName.Data(),other.fName.Data(),other.fComment.Data());
02045             }
02046          }
02047          result = result && kFALSE;
02048          if (!complete) return result;
02049       }
02050       ++idx;
02051    }
02052    return result;
02053 }
02054 
02055 
02056 //______________________________________________________________________________
02057 void TStreamerInfo::ComputeSize()
02058 {
02059    // Compute total size of all persistent elements of the class
02060 
02061    TStreamerElement *element = (TStreamerElement*)fElements->Last();
02062    //faster and more precise to use last element offset +size
02063    //on 64 bit machines, offset may be forced to be a multiple of 8 bytes
02064    fSize = element->GetOffset() + element->GetSize();
02065    if (fNVirtualInfoLoc > 0 && (fVirtualInfoLoc[0]+sizeof(TStreamerInfo*)) >= (ULong_t)fSize) {
02066       fSize = fVirtualInfoLoc[0] + sizeof(TStreamerInfo*);
02067    }
02068 }
02069 
02070 //______________________________________________________________________________
02071 void TStreamerInfo::ForceWriteInfo(TFile* file, Bool_t force)
02072 {
02073    // -- Recursively mark streamer infos for writing to a file.
02074    //
02075    // Will force this TStreamerInfo to the file and also
02076    // all the dependencies.
02077    //
02078    // If argument force > 0 the loop on class dependencies is forced.
02079    //
02080    // This function is called when streaming a class that contains
02081    // a null pointer. In this case, the TStreamerInfo for the class
02082    // with the null pointer must be written to the file and also all
02083    // the TStreamerInfo of all the classes referenced by the class.
02084    //
02085    //--
02086    // We must be given a file to write to.
02087    if (!file) {
02088       return;
02089    }
02090    // Get the given file's list of streamer infos marked for writing.
02091    TArrayC* cindex = file->GetClassIndex();
02092    //the test below testing fArray[fNumber]>1 is to avoid a recursivity
02093    //problem in some cases like:
02094    //        class aProblemChild: public TNamed {
02095    //        aProblemChild *canBeNull;
02096    //        };
02097    if ( // -- Done if already marked, and we are not forcing, or forcing is blocked.
02098       (cindex->fArray[fNumber] && !force) || // Streamer info is already marked, and not forcing, or
02099       (cindex->fArray[fNumber] > 1) // == 2 means ignore forcing to prevent infinite recursion.
02100    ) {
02101       return;
02102    }
02103    // We do not want to write streamer info to the file
02104    // for std::string.
02105    static TClassRef string_classref("string");
02106    if (fClass == string_classref) { // We are std::string.
02107       return;
02108    }
02109    // We do not want to write streamer info to the file
02110    // for STL containers.
02111    if (fClass==0) {
02112       // Build or BuildCheck has not been called yet.
02113       // Let's use another means of checking.
02114       if (fElements && fElements->GetEntries()==1 && strcmp("This",fElements->UncheckedAt(0)->GetName())==0) {
02115          // We are an STL collection.
02116          return;
02117       }
02118    } else if (fClass->GetCollectionProxy()) { // We are an STL collection.
02119       return;
02120    }
02121    // Mark ourselves for output, and block
02122    // forcing to prevent infinite recursion.
02123    cindex->fArray[fNumber] = 2;
02124    // Signal the file that the marked streamer info list has changed.
02125    cindex->fArray[0] = 1;
02126    // Recursively mark the streamer infos for
02127    // all of our elements.
02128    TIter next(fElements);
02129    TStreamerElement* element = (TStreamerElement*) next();
02130    for (; element; element = (TStreamerElement*) next()) {
02131       TClass* cl = element->GetClassPointer();
02132       if (cl) {
02133          TVirtualStreamerInfo* si = 0;
02134          if (cl->Property() & kIsAbstract) {
02135             // If the class of the element is abstract, register the
02136             // TStreamerInfo only if it has already been built.
02137             // Otherwise call cl->GetStreamerInfo() would generate an
02138             // incorrect StreamerInfo.
02139             si = cl->GetCurrentStreamerInfo();
02140          } else {
02141             si = cl->GetStreamerInfo();
02142          }
02143          if (si) {
02144             si->ForceWriteInfo(file, force);
02145          }
02146       }
02147    }
02148 }
02149 
02150 //______________________________________________________________________________
02151 TClass *TStreamerInfo::GetActualClass(const void *obj) const 
02152 {
02153    // Assuming that obj points to (the part of) an object that is of the
02154    // type described by this streamerInfo, return the actual type of the
02155    // object (i.e. the type described by this streamerInfo is a base class
02156    // of the actual type of the object.
02157    // This routine should only be called if the class decribed by this
02158    // StreamerInfo is 'emulated'.
02159    
02160    R__ASSERT(!fClass->IsLoaded());
02161    
02162    if (fNVirtualInfoLoc != 0) {
02163       TStreamerInfo *allocator = *(TStreamerInfo**)( (const char*)obj + fVirtualInfoLoc[0] );
02164       if (allocator) return allocator->GetClass();
02165    }
02166    return (TClass*)fClass;
02167 }
02168    
02169 //______________________________________________________________________________
02170 UInt_t TStreamerInfo::GetCheckSum(UInt_t code) const 
02171 {
02172    // Recalculate the checksum of this TStreamerInfo based on its code.
02173    // 
02174    // The class ckecksum is used by the automatic schema evolution algorithm
02175    // to uniquely identify a class version.
02176    // The check sum is built from the names/types of base classes and
02177    // data members.
02178    // Algorithm from Victor Perevovchikov (perev@bnl.gov).
02179    //
02180    // if code==1 data members of type enum are not counted in the checksum
02181    // if code==2 return the checksum of data members and base classes, not including the ranges and array size found in comments.  
02182    //            This is needed for backward compatibility.
02183    //
02184    // WARNING: this function must be kept in sync with TClass::GetCheckSum.
02185    // They are both used to handle backward compatibility and should both return the same values.
02186    // TStreamerInfo uses the information in TStreamerElement while TClass uses the information
02187    // from TClass::GetListOfBases and TClass::GetListOfDataMembers.
02188 
02189    UInt_t id = 0;
02190 
02191    int il;
02192    TString name = GetName();
02193    TString type;
02194    il = name.Length();
02195    for (int i=0; i<il; i++) id = id*3+name[i];
02196 
02197    TIter next(GetElements());
02198    TStreamerElement *el;
02199    while ( (el=(TStreamerElement*)next()) ) {
02200       if (el->IsBase()) {
02201          name = el->GetName();
02202          il = name.Length();
02203          for (int i=0; i<il; i++) id = id*3+name[i];
02204       }
02205    } /* End of Base Loop */
02206 
02207    next.Reset();
02208    while ( (el=(TStreamerElement*)next()) ) {
02209       if (el->IsBase()) continue;
02210 
02211       // humm can we tell if a TStreamerElement is an enum?
02212       // Maybe something like:
02213       Bool_t isenum = kFALSE;
02214       if ( el->GetType()==3 && gROOT->GetType(el->GetTypeName())==0) {
02215          // If the type is not an enum but a typedef to int then 
02216          // el->GetTypeName() should be return 'int'
02217          isenum = kTRUE;
02218       }
02219       if ( (code != 1) && isenum) id = id*3 + 1;
02220 
02221       name = el->GetName();  il = name.Length();
02222 
02223       int i;
02224       for (i=0; i<il; i++) id = id*3+name[i];
02225 
02226       type = el->GetTypeName();
02227       if (TClassEdit::IsSTLCont(type)) {
02228          type = TClassEdit::ShortType( type, TClassEdit::kDropStlDefault | TClassEdit::kLong64 );
02229       }
02230 
02231       il = type.Length();
02232       for (i=0; i<il; i++) id = id*3+type[i];
02233 
02234       int dim = el->GetArrayDim();
02235       if (dim) {
02236          for (i=0;i<dim;i++) id = id*3+el->GetMaxIndex(i);
02237       }
02238 
02239 
02240       if (code != 2) {
02241          const char *left = strstr(el->GetTitle(),"[");
02242          if (left) {
02243             const char *right = strstr(left,"]");
02244             if (right) {
02245                ++left;
02246                while (left != right) {
02247                   id = id*3 + *left;
02248                   ++left;
02249                }
02250             }
02251          }
02252       }
02253    }
02254    return id;
02255 }
02256 
02257 //______________________________________________________________________________
02258 static void R__WriteConstructorBody(FILE *file, TIter &next)
02259 {
02260    TStreamerElement *element = 0;
02261    next.Reset();
02262    while ((element = (TStreamerElement*)next())) {
02263       if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP ||
02264           element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP || 
02265           element->GetType() == TVirtualStreamerInfo::kCharStar || element->GetType() == TVirtualStreamerInfo::kSTLp) {
02266          if(element->GetArrayLength() <= 1) {
02267             fprintf(file,"   %s = 0;\n",element->GetName());
02268          } else {
02269             fprintf(file,"   memset(%s,0,%d);\n",element->GetName(),element->GetSize());
02270          }
02271       }
02272       if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) {
02273          fprintf(file,"   %s = 0;\n",element->GetName());
02274       }
02275    }
02276 }
02277 
02278 //______________________________________________________________________________
02279 static void R__WriteMoveConstructorBody(FILE *file, const TString &protoname, TIter &next)
02280 {
02281    // Write down the body of the 'move' constructor.
02282 
02283    TStreamerElement *element = 0;
02284    next.Reset();
02285    Bool_t atstart = kTRUE;
02286    while ((element = (TStreamerElement*)next())) {
02287       if (element->IsBase()) {
02288          if (atstart) { fprintf(file,"   : "); atstart = kFALSE; }
02289          else fprintf(file,"   , ");
02290          fprintf(file, "%s(const_cast<%s &>( rhs ))\n", element->GetName(),protoname.Data());
02291       } else {
02292          if (element->GetArrayLength() <= 1) {
02293             if (atstart) { fprintf(file,"   : "); atstart = kFALSE; }
02294             else fprintf(file,"   , ");
02295             fprintf(file, "%s(const_cast<%s &>( rhs ).%s)\n",element->GetName(),protoname.Data(),element->GetName());
02296          }
02297       }
02298    }
02299    fprintf(file,"{\n");
02300    fprintf(file,"   // This is NOT a copy constructor. This is actually a move constructor (for stl container's sake).\n");
02301    fprintf(file,"   // Use at your own risk!\n");
02302    fprintf(file,"   if (&rhs) {} // avoid warning about unused parameter\n");
02303    next.Reset();
02304    Bool_t defMod = kFALSE;
02305    while ((element = (TStreamerElement*)next())) {
02306       if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP||
02307           element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP
02308           || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT) 
02309       {
02310          if (!defMod) { fprintf(file,"   %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
02311          const char *ename = element->GetName();
02312          const char *colon2 = strstr(ename,"::");
02313          if (colon2) ename = colon2+2;
02314          if(element->GetArrayLength() <= 1) {
02315             fprintf(file,"   modrhs.%s = 0;\n",ename);
02316          } else {
02317             fprintf(file,"   memset(modrhs.%s,0,%d);\n",ename,element->GetSize());
02318          }
02319       } else {
02320          const char *ename = element->GetName();
02321          if (element->GetType() == kCharStar) {
02322             if (!defMod) { 
02323                fprintf(file,"   %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; 
02324             };
02325             fprintf(file,"   modrhs.%s = 0;\n",ename);
02326          } else if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) { 
02327             if (!defMod) { 
02328                fprintf(file,"   %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; 
02329             };
02330             fprintf(file,"   modrhs.%s = 0;\n",ename);
02331          } else if (element->GetArrayLength() > 1) {
02332             // FIXME: Need to add support for variable length array.
02333             if (element->GetArrayDim() == 1) {
02334                fprintf(file,"   for (Int_t i=0;i<%d;i++) %s[i] = rhs.%s[i];\n",element->GetArrayLength(),ename,ename);            
02335             } else if (element->GetArrayDim() >= 2) {
02336                fprintf(file,"   for (Int_t i=0;i<%d;i++) (&(%s",element->GetArrayLength(),ename);
02337                for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
02338                   fprintf(file,"[0]");
02339                }
02340                fprintf(file,"))[i] = (&(rhs.%s",ename);
02341                for (Int_t d = 0; d < element->GetArrayDim(); ++d) {
02342                   fprintf(file,"[0]");
02343                }
02344                fprintf(file,"))[i];\n");
02345             }
02346          } else if (element->GetType() == TVirtualStreamerInfo::kSTLp) {
02347             if (!defMod) { fprintf(file,"   %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; };
02348             fprintf(file,"   modrhs.%s = 0;\n",ename);
02349          } else if (element->GetType() == TVirtualStreamerInfo::kSTL) {
02350             if (!defMod) { 
02351                fprintf(file,"   %s &modrhs = const_cast<%s &>( rhs );\n",protoname.Data(),protoname.Data()); defMod = kTRUE; 
02352             }
02353             if (element->IsBase()) {
02354                fprintf(file,"   modrhs.clear();\n");
02355             } else {
02356                fprintf(file,"   modrhs.%s.clear();\n",ename);
02357             }
02358          }
02359       }
02360    }
02361 }
02362 
02363 //______________________________________________________________________________
02364 static void R__WriteDestructorBody(FILE *file, TIter &next)
02365 {
02366    TStreamerElement *element = 0;
02367    next.Reset();
02368    while ((element = (TStreamerElement*)next())) {
02369       if (element->GetType() == TVirtualStreamerInfo::kObjectp || element->GetType() == TVirtualStreamerInfo::kObjectP||
02370           element->GetType() == TVirtualStreamerInfo::kAnyp || element->GetType() == TVirtualStreamerInfo::kAnyP
02371           || element->GetType() == TVirtualStreamerInfo::kAnyPnoVT) 
02372       {
02373          const char *ename = element->GetName();
02374          const char *colon2 = strstr(ename,"::");
02375          if (colon2) ename = colon2+2;
02376          if (element->TestBit(TStreamerElement::kDoNotDelete)) {
02377             if(element->GetArrayLength() <= 1) {
02378                fprintf(file,"   %s = 0;\n",ename);
02379             } else {
02380                fprintf(file,"   memset(%s,0,%d);\n",ename,element->GetSize());
02381             }
02382          } else {
02383             if(element->GetArrayLength() <= 1) {
02384                fprintf(file,"   delete %s;   %s = 0;\n",ename,ename);
02385             } else {
02386                fprintf(file,"   for (Int_t i=0;i<%d;i++) delete %s[i];   memset(%s,0,%d);\n",element->GetArrayLength(),ename,ename,element->GetSize());
02387             }
02388          }
02389       }
02390       if (element->GetType() == TVirtualStreamerInfo::kCharStar) {
02391          const char *ename = element->GetName();
02392          if (element->TestBit(TStreamerElement::kDoNotDelete)) {
02393             fprintf(file,"   %s = 0;\n",ename);
02394          } else {
02395             fprintf(file,"   delete [] %s;   %s = 0;\n",ename,ename);
02396          }
02397       }
02398       if (TVirtualStreamerInfo::kOffsetP <= element->GetType() && element->GetType() < TVirtualStreamerInfo::kObject ) { 
02399          const char *ename = element->GetName();
02400          if (element->TestBit(TStreamerElement::kDoNotDelete)) {
02401             fprintf(file,"   %s = 0;\n",ename);
02402          } else if (element->HasCounter()) {
02403             fprintf(file,"   delete %s;   %s = 0;\n",ename,ename);
02404          } else {
02405             fprintf(file,"   delete [] %s;   %s = 0;\n",ename,ename);
02406          }
02407       }
02408       if (element->GetType() == TVirtualStreamerInfo::kSTL || element->GetType() == TVirtualStreamerInfo::kSTLp) {
02409          const char *ename = element->GetName();
02410          const char *prefix = "";
02411          if ( element->GetType() == TVirtualStreamerInfo::kSTLp ) {
02412             prefix = "*";
02413          } else if ( element->IsBase() ) {
02414             ename = "this";
02415          }
02416          TVirtualCollectionProxy *proxy = element->GetClassPointer()->GetCollectionProxy();
02417          if (!element->TestBit(TStreamerElement::kDoNotDelete) && element->GetClassPointer() && proxy) {
02418             Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
02419             
02420             if (proxy->HasPointers()) {
02421                fprintf(file,"   std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
02422                //fprintf(file,"      %s::iterator iter;\n");
02423                //fprintf(file,"      %s::iterator begin = (%s %s).begin();\n");
02424                //fprintf(file,"      %s::iterator end (%s %s).end();\n");
02425                //fprintf(file,"      for( iter = begin; iter != end; ++iter) { delete *iter; }\n");
02426             } else {
02427                if (stltype == TStreamerElement::kSTLmap || stltype == TStreamerElement::kSTLmultimap) {
02428                   TString enamebasic = TMakeProject::UpdateAssociativeToVector(element->GetTypeNameBasic());
02429                   std::vector<std::string> inside;
02430                   int nestedLoc;
02431                   TClassEdit::GetSplit(enamebasic, inside, nestedLoc, TClassEdit::kLong64);
02432                   if (inside[1][inside[1].size()-1]=='*' || inside[2][inside[2].size()-1]=='*') {
02433                      fprintf(file,"   std::for_each( (%s %s).rbegin(), (%s %s).rend(), DeleteObjectFunctor() );\n",prefix,ename,prefix,ename);
02434                   }
02435                }
02436                }
02437          }
02438          if ( prefix[0] ) {
02439             fprintf(file,"   delete %s;   %s = 0;\n",ename,ename);
02440          }
02441       }
02442    }
02443 }
02444 
02445 //______________________________________________________________________________
02446 void TStreamerInfo::GenerateDeclaration(FILE *fp, FILE *sfp, const TList *subClasses, Bool_t top)
02447 {
02448    // Write the Declaration of class.
02449 
02450    if (fClassVersion == -3) {
02451       return;
02452    }
02453 
02454    bool needGenericTemplate = fElements==0 || fElements->GetEntries() == 0;
02455    Bool_t isTemplate = kFALSE;
02456    const char *clname = GetName();
02457    TString template_protoname;
02458    if (strchr(clname, ':')) {
02459       // We might have a namespace in front of the classname.
02460       Int_t len = strlen(clname);
02461       const char *name = clname;
02462       UInt_t nest = 0;
02463       UInt_t pr_pos = 0;
02464       for (Int_t cur = 0; cur < len; ++cur) {
02465          switch (clname[cur]) {
02466             case '<':
02467                ++nest;
02468                pr_pos = cur;
02469                isTemplate = kTRUE;
02470                break;
02471             case '>':
02472                --nest;
02473                break;
02474             case ':': {
02475                if (nest == 0 && clname[cur+1] == ':') {
02476                   // We have a scope
02477                   isTemplate = kFALSE;
02478                   name = clname + cur + 2;
02479                }
02480                break;
02481             }
02482          }
02483       }
02484       if (isTemplate) {
02485          template_protoname.Append(clname,pr_pos);
02486       }
02487       clname = name;
02488    } else {
02489       const char *where = strstr(clname, "<");
02490       isTemplate = where != 0;
02491       if (isTemplate) {
02492          template_protoname.Append(clname,where-clname);
02493       }
02494    }
02495 
02496    if (needGenericTemplate && isTemplate) {
02497       TString templateName(TMakeProject::GetHeaderName("template "+template_protoname,0));
02498       fprintf(fp, "#ifndef %s_h\n", templateName.Data());
02499       fprintf(fp, "#define %s_h\n", templateName.Data());
02500    }
02501 
02502    TString protoname;
02503    UInt_t numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, GetName(), top, protoname, 0, kFALSE, needGenericTemplate);
02504 
02505    // Generate class statement with base classes.
02506    TStreamerElement *element;
02507    TIter next(fElements);
02508    Int_t nbase = 0;
02509    while ((element = (TStreamerElement*)next())) {
02510       if (!element->IsBase()) continue;
02511       nbase++;
02512       const char *ename = element->GetName();
02513       if (nbase == 1) fprintf(fp," : public %s",ename);
02514       else            fprintf(fp," , public %s",ename);
02515    }
02516    fprintf(fp," {\n");
02517 
02518    // Generate forward declaration nested classes.
02519    if (subClasses && subClasses->GetEntries()) {
02520       bool needheader = true;
02521 
02522       TIter subnext(subClasses);
02523       TStreamerInfo *subinfo;
02524       Int_t len = strlen(GetName());
02525       while ((subinfo = (TStreamerInfo*)subnext())) {
02526          if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==':') ) {
02527             if (subinfo->GetName()[len+1]==':' && strstr(subinfo->GetName()+len+2,":")==0) {
02528                if (needheader) {
02529                   fprintf(fp,"\npublic:\n");
02530                   fprintf(fp,"// Nested classes forward declaration.\n");
02531                   needheader = false;
02532                }
02533                TString sub_protoname;
02534                UInt_t sub_numberOfClasses = 0;
02535                UInt_t sub_numberOfNamespaces;
02536                if (subinfo->GetClassVersion() == -3) {
02537                   sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, 3);                  
02538                } else {
02539                   sub_numberOfNamespaces = TMakeProject::GenerateClassPrefix(fp, subinfo->GetName() + len+2, kFALSE, sub_protoname, &sub_numberOfClasses, kFALSE);
02540                   fprintf(fp, ";\n");
02541                }
02542 
02543                for (UInt_t i = 0;i < sub_numberOfClasses;++i) {
02544                   fprintf(fp, "}; // end of class.\n");
02545                }
02546                if (sub_numberOfNamespaces > 0) {
02547                   Error("GenerateDeclaration","Nested classes %s thought to be inside a namespace inside the class %s",subinfo->GetName(),GetName());
02548                }
02549             }
02550          }
02551       }
02552    }
02553 
02554    fprintf(fp,"\npublic:\n");
02555    fprintf(fp,"// Nested classes declaration.\n");
02556 
02557    // Generate nested classes.
02558    if (subClasses && subClasses->GetEntries()) {
02559       TIter subnext(subClasses,kIterBackward);
02560       TStreamerInfo *subinfo;
02561       Int_t len = strlen(GetName());
02562       while ((subinfo = (TStreamerInfo*)subnext())) {
02563          if (strncmp(GetName(),subinfo->GetName(),len)==0 && (subinfo->GetName()[len]==':')) {
02564             if (subinfo->GetName()[len+1]==':' && strstr(subinfo->GetName()+len+2,":")==0) {
02565                subinfo->GenerateDeclaration(fp, sfp, subClasses, kFALSE);
02566             }
02567          }
02568       }
02569    }
02570 
02571    fprintf(fp,"\npublic:\n");
02572    fprintf(fp,"// Data Members.\n");
02573 
02574    {
02575       // Generate data members.
02576       TString name(128);
02577       Int_t ltype = 12;
02578       Int_t ldata = 10;
02579       Int_t lt,ld,is;
02580       TString line;
02581       line.Resize(kMaxLen);      
02582       next.Reset();
02583       while ((element = (TStreamerElement*)next())) {
02584 
02585          if (element->IsBase()) continue;
02586          const char *ename = element->GetName();
02587          
02588          name = ename;
02589          for (Int_t i=0;i < element->GetArrayDim();i++) {
02590             name += TString::Format("[%d]",element->GetMaxIndex(i));
02591          }
02592          name += ";";
02593          ld = name.Length();
02594          
02595          TString enamebasic = element->GetTypeNameBasic();
02596          if (element->IsA() == TStreamerSTL::Class()) {
02597             // If we have a map, multimap, set or multiset,
02598             // and the key is a class, we need to replace the
02599             // container by a vector since we don't have the
02600             // comparator function.
02601             Int_t stltype = ((TStreamerSTL*)element)->GetSTLtype();
02602             switch (stltype) {
02603                case TStreamerElement::kSTLmap: 
02604                case TStreamerElement::kSTLmultimap:
02605                case TStreamerElement::kSTLset:
02606                case TStreamerElement::kSTLmultiset:
02607                {
02608                   enamebasic = TMakeProject::UpdateAssociativeToVector(enamebasic);
02609                }
02610                default:
02611                   // nothing to do.
02612                   break;
02613             }
02614          } 
02615          
02616          lt = enamebasic.Length();
02617          
02618          line = "   ";
02619          line += enamebasic;
02620          if (lt>=ltype) ltype = lt+1;
02621          
02622          for (is = 3+lt; is < (3+ltype); ++is) line += ' ';
02623 
02624          line += name;
02625          if (element->IsaPointer() && !strchr(line,'*')) line[2+ltype] = '*';
02626          
02627          if (ld>=ldata) ldata = ld+1;
02628          for (is = 3+ltype+ld; is < (3+ltype+ldata); ++is) line += ' ';
02629 
02630          line += "   //";
02631          line += element->GetTitle();
02632          fprintf(fp,"%s\n",line.Data());
02633       }
02634    }
02635    if (needGenericTemplate && isTemplate) {
02636       // Generate default functions, ClassDef and trailer.
02637       fprintf(fp,"\n   %s() {\n",protoname.Data());
02638       R__WriteConstructorBody(fp,next);      
02639       fprintf(fp,"   }\n");
02640       fprintf(fp,"   %s(const %s & rhs )\n",protoname.Data(),protoname.Data());
02641       R__WriteMoveConstructorBody(fp,protoname,next);
02642       fprintf(fp,"   }\n");
02643       fprintf(fp,"   virtual ~%s() {\n",protoname.Data());
02644       R__WriteDestructorBody(fp,next);
02645       fprintf(fp,"   }\n\n");
02646 
02647    } else {
02648       // Generate default functions, ClassDef and trailer.
02649       fprintf(fp,"\n   %s();\n",protoname.Data());
02650       fprintf(fp,"   %s(const %s & );\n",protoname.Data(),protoname.Data());
02651       fprintf(fp,"   virtual ~%s();\n\n",protoname.Data());
02652 
02653       // Add the implementations to the source.cxx file.
02654       TString guard( TMakeProject::GetHeaderName( GetName(), 0, kTRUE ) );
02655       fprintf(sfp,"#ifndef %s_cxx\n",guard.Data());
02656       fprintf(sfp,"#define %s_cxx\n",guard.Data());
02657       fprintf(sfp,"%s::%s() {\n",GetName(),protoname.Data());
02658       R__WriteConstructorBody(sfp,next);
02659       fprintf(sfp,"}\n");
02660 
02661       fprintf(sfp,"%s::%s(const %s & rhs)\n",GetName(),protoname.Data(),protoname.Data());
02662       R__WriteMoveConstructorBody(sfp,protoname,next);
02663       fprintf(sfp,"}\n");
02664 
02665       fprintf(sfp,"%s::~%s() {\n",GetName(),protoname.Data());
02666       R__WriteDestructorBody(sfp,next);
02667       fprintf(sfp,"}\n");
02668       fprintf(sfp,"#endif // %s_cxx\n\n",guard.Data());
02669    }
02670 
02671    TClass *cl = gROOT->GetClass(GetName());
02672    if (fClassVersion > 1 || (cl && cl->InheritsFrom(TObject::Class())) ) {
02673       // add 1 to class version in case we didn't manage reproduce the class layout to 100%.
02674       fprintf(fp,"   ClassDef(%s,%d); // Generated by MakeProject.\n",protoname.Data(),fClassVersion + 1);
02675    }
02676    fprintf(fp,"};\n");
02677 
02678    for(UInt_t i=0;i<numberOfNamespaces;++i) {
02679       fprintf(fp,"} // namespace\n");
02680    }
02681 
02682    if (needGenericTemplate && isTemplate) {
02683       fprintf(fp,"#endif // generic template declaration\n");
02684    }
02685 }
02686 
02687 //______________________________________________________________________________
02688 UInt_t TStreamerInfo::GenerateIncludes(FILE *fp, char *inclist, const TList *extrainfos)
02689 {
02690    // Add to the header file, the #include need for this class
02691 
02692    UInt_t ninc = 0;
02693 
02694    const char *clname = GetName();
02695    if (strchr(clname,'<')) {
02696       // This is a template, we need to check the template parameter.
02697       ninc += TMakeProject::GenerateIncludeForTemplate(fp, clname, inclist, kFALSE, extrainfos);
02698    }
02699 
02700    TString name(1024);
02701    Int_t ltype = 10;
02702    Int_t ldata = 10;
02703    Int_t lt;
02704    Int_t ld;
02705    TIter next(fElements);
02706    TStreamerElement *element;
02707    Bool_t incRiostream = kFALSE;
02708    while ((element = (TStreamerElement*)next())) {
02709       //if (element->IsA() == TStreamerBase::Class()) continue;
02710       const char *ename = element->GetName();
02711       const char *colon2 = strstr(ename,"::");
02712       if (colon2) ename = colon2+2;
02713       name = ename;
02714       for (Int_t i=0;i < element->GetArrayDim();i++) {
02715          name += TString::Format("[%d]",element->GetMaxIndex(i));
02716       }
02717       ld = name.Length();
02718       lt = strlen(element->GetTypeName());
02719       if (ltype < lt) ltype = lt;
02720       if (ldata < ld) ldata = ld;
02721 
02722       //must include Riostream.h in case of an STL container
02723       if (!incRiostream && element->InheritsFrom(TStreamerSTL::Class())) {
02724          incRiostream = kTRUE;
02725          TMakeProject::AddInclude( fp, "Riostream.h", kFALSE, inclist);
02726       }
02727 
02728       //get include file name if any
02729       const char *include = element->GetInclude();
02730       if (strlen(include) == 0) continue;
02731 
02732       Bool_t greater = (include[0]=='<');
02733       include++;
02734 
02735       if (strncmp(include,"include/",8)==0) {
02736          include += 8;
02737       } 
02738       if (strncmp(include,"include\\",9)==0) {
02739          include += 9;
02740       }
02741       if (strncmp(element->GetTypeName(),"pair<",strlen("pair<"))==0) {
02742          TMakeProject::AddInclude( fp, "utility", kTRUE, inclist);
02743       } else if (strncmp(element->GetTypeName(),"auto_ptr<",strlen("auto_ptr<"))==0) {
02744          TMakeProject::AddInclude( fp, "memory", kTRUE, inclist);
02745       } else {
02746          TString incName( include, strlen(include)-1 );
02747          incName = TMakeProject::GetHeaderName(incName,extrainfos);
02748          TMakeProject::AddInclude( fp, incName.Data(), greater, inclist);
02749       }
02750 
02751       if (strchr(element->GetTypeName(),'<')) {
02752          // This is a template, we need to check the template parameter.
02753          ninc += TMakeProject::GenerateIncludeForTemplate(fp, element->GetTypeName(), inclist, kFALSE, extrainfos);
02754       }
02755    }
02756    if (inclist[0]==0) {
02757       TMakeProject::AddInclude( fp, "TNamed.h", kFALSE, inclist);
02758    }
02759    return ninc;
02760 }
02761 
02762 //______________________________________________________________________________
02763 Int_t TStreamerInfo::GenerateHeaderFile(const char *dirname, const TList *subClasses, const TList *extrainfos)
02764 {
02765    // Generate header file for the class described by this TStreamerInfo
02766    // the function is called by TFile::MakeProject for each class in the file
02767 
02768    // if (fClassVersion == -4) return 0;
02769    if (TClassEdit::IsSTLCont(GetName())) return 0;
02770    if (strncmp(GetName(),"pair<",strlen("pair<"))==0) return 0;
02771    if (strncmp(GetName(),"auto_ptr<",strlen("auto_ptr<"))==0) return 0;
02772 
02773    TClass *cl = TClass::GetClass(GetName());
02774    if (cl) {
02775       if (cl->GetClassInfo()) return 0; // skip known classes
02776    }
02777    Bool_t isTemplate = kFALSE;
02778    if (strchr(GetName(),':')) {
02779       UInt_t len = strlen(GetName());
02780       UInt_t nest = 0;
02781       UInt_t scope = 0;
02782       for(UInt_t i=len; i>0; --i) {
02783          switch(GetName()[i]) {
02784             case '>': ++nest; if (scope==0) { isTemplate = kTRUE; } break;
02785             case '<': --nest; break;
02786             case ':': 
02787                if (nest==0 && GetName()[i-1]==':') {
02788                   // We have a scope
02789                   TString nsname(GetName(), i-1);
02790                   cl = gROOT->GetClass(nsname);
02791                   if (cl && (cl->Size()!=0 || (cl->Size()==0 && cl->GetClassInfo()==0 /*empty 'base' class on file*/))) {
02792                      // This class is actually nested.
02793                      return 0;
02794                   } else if (cl == 0 && extrainfos != 0) {
02795                      TStreamerInfo *clinfo = (TStreamerInfo*)extrainfos->FindObject(nsname);
02796                      if (clinfo && clinfo->GetClassVersion() == -5) {
02797                         // This class is actually nested.
02798                         return 0;
02799                      }
02800                   }
02801                   ++scope;
02802                }
02803                break;
02804          }
02805       }
02806    }
02807    Bool_t needGenericTemplate = isTemplate && (fElements==0 || fElements->GetEntries()==0); 
02808 
02809    if (gDebug) printf("generating code for class %s\n",GetName());
02810 
02811    // Open the file
02812 
02813    TString headername( TMakeProject::GetHeaderName( GetName(), extrainfos ) );
02814    TString filename;
02815    filename.Form("%s/%s.h",dirname,headername.Data());
02816 
02817    FILE *fp = fopen(filename.Data(),"w");
02818    if (!fp) {
02819       Error("MakeProject","Cannot open output file:%s\n",filename.Data());
02820       return 0;
02821    }
02822 
02823    filename.Form("%s/%sProjectHeaders.h",dirname,dirname);
02824    FILE *allfp = fopen(filename.Data(),"a");
02825    if (!allfp) {
02826       Error("MakeProject","Cannot open output file:%s\n",filename.Data());
02827       fclose(fp);
02828       return 0;
02829    }
02830    fprintf(allfp,"#include \"%s.h\"\n", headername.Data());
02831    fclose(allfp);
02832 
02833    char *inclist = new char[50000];
02834    inclist[0] = 0;
02835 
02836    // Generate class header.
02837    TDatime td;
02838    fprintf(fp,"//////////////////////////////////////////////////////////\n");
02839    fprintf(fp,"//   This class has been generated by TFile::MakeProject\n");
02840    fprintf(fp,"//     (%s by ROOT version %s)\n",td.AsString(),gROOT->GetVersion());
02841    fprintf(fp,"//      from the StreamerInfo in file %s\n",gDirectory->GetFile()->GetName());
02842    fprintf(fp,"//////////////////////////////////////////////////////////\n");
02843    fprintf(fp,"\n");
02844    fprintf(fp,"\n");
02845    fprintf(fp,"#ifndef %s_h\n",headername.Data());
02846    fprintf(fp,"#define %s_h\n",headername.Data());
02847    TMakeProject::GenerateForwardDeclaration(fp, GetName(), inclist, kFALSE, needGenericTemplate, extrainfos);
02848    fprintf(fp,"\n");
02849 
02850    UInt_t ninc = 0;
02851    ninc += GenerateIncludes(fp, inclist, extrainfos);
02852    if (subClasses) {
02853       TIter subnext(subClasses);
02854       TStreamerInfo *subinfo;
02855       while ((subinfo = (TStreamerInfo*)subnext())) {
02856          ninc = subinfo->GenerateIncludes(fp, inclist, extrainfos);
02857       }
02858    }   
02859    fprintf(fp,"\n");
02860 
02861    TString sourcename; sourcename.Form( "%s/%sProjectSource.cxx", dirname, dirname );
02862    FILE *sfp = fopen( sourcename.Data(), "a" );
02863    GenerateDeclaration(fp, sfp, subClasses);
02864    
02865    TMakeProject::GeneratePostDeclaration(fp, this, inclist);
02866 
02867    fprintf(fp,"#endif\n");
02868 
02869    delete [] inclist;
02870    fclose(fp);
02871    fclose(sfp);
02872    return 1;
02873 }
02874 
02875 //______________________________________________________________________________
02876 TStreamerElement *TStreamerInfo::GetCurrentElement()
02877 {
02878    //static function returning a pointer to the current TStreamerElement
02879    //fgElement points to the current TStreamerElement being read in ReadBuffer
02880    return fgElement;
02881 }
02882 
02883 //______________________________________________________________________________
02884 Int_t TStreamerInfo::GetDataMemberOffset(TDataMember *dm, TMemberStreamer *&streamer) const
02885 {
02886    // Compute data member offset
02887    // return pointer to the Streamer function if one exists
02888 
02889    TIter nextr(fClass->GetListOfRealData());
02890    char dmbracket[256];
02891    snprintf(dmbracket,255,"%s[",dm->GetName());
02892    Int_t offset = kMissing;
02893    if (fClass->GetDeclFileLine() < 0) offset = dm->GetOffset();
02894    TRealData *rdm;
02895    while ((rdm = (TRealData*)nextr())) {
02896       char *rdmc = (char*)rdm->GetName();
02897       //next statement required in case a class and one of its parent class
02898       //have data members with the same name
02899       if (dm->IsaPointer() && rdmc[0] == '*') rdmc++;
02900 
02901       if (rdm->GetDataMember() != dm) continue;
02902       if (strcmp(rdmc,dm->GetName()) == 0) {
02903          offset   = rdm->GetThisOffset();
02904          streamer = rdm->GetStreamer();
02905          break;
02906       }
02907       if (strcmp(rdm->GetName(),dm->GetName()) == 0) {
02908          if (rdm->IsObject()) {
02909             offset = rdm->GetThisOffset();
02910             streamer = rdm->GetStreamer();
02911             break;
02912          }
02913       }
02914       if (strstr(rdm->GetName(),dmbracket)) {
02915          offset   = rdm->GetThisOffset();
02916          streamer = rdm->GetStreamer();
02917          break;
02918       }
02919    }
02920    return offset;
02921 }
02922 
02923 //______________________________________________________________________________
02924 Int_t TStreamerInfo::GetOffset(const char *elementName) const
02925 {
02926    // return the offset of the data member as indicated by this StreamerInfo
02927 
02928    if (elementName == 0) return 0;
02929 
02930    Int_t offset = 0;
02931    TStreamerElement *elem = (TStreamerElement*)fElements->FindObject(elementName);
02932    if (elem) offset = elem->GetOffset();
02933 
02934    return offset;
02935 }
02936 
02937 //______________________________________________________________________________
02938 Int_t TStreamerInfo::GetSize() const
02939 {
02940    //  return total size of all persistent elements of the class (with offsets)
02941 
02942    return fSize;
02943 }
02944 
02945 //______________________________________________________________________________
02946 Int_t TStreamerInfo::GetSizeElements() const
02947 {
02948    //  return total size of all persistent elements of the class
02949    //  use GetSize if you want to get the real size in memory
02950 
02951    TIter next(fElements);
02952    TStreamerElement *element;
02953    Int_t asize = 0;
02954    while ((element = (TStreamerElement*)next())) {
02955       asize += element->GetSize();
02956    }
02957    return asize;
02958 }
02959 
02960 //______________________________________________________________________________
02961 TStreamerElement* TStreamerInfo::GetStreamerElement(const char* datamember, Int_t& offset) const
02962 {
02963    // Return the StreamerElement of "datamember" inside our
02964    // class or any of its base classes.  The offset information
02965    // contained in the StreamerElement is related to its immediately
02966    // containing class, so we return in 'offset' the offset inside
02967    // our class.
02968 
02969    if (!fElements) {
02970       return 0;
02971    }
02972 
02973    // Look first at the data members and base classes
02974    // of our class.
02975    TStreamerElement* element = (TStreamerElement*) fElements->FindObject(datamember);
02976    if (element) {
02977       offset = element->GetOffset();
02978       return element;
02979    }
02980 
02981    // Not found, so now try the data members and base classes
02982    // of the base classes of our class.
02983    if (fClass->GetClassInfo()) {
02984       // Our class has a dictionary loaded, use it to search the base classes.
02985       TStreamerElement* base_element = 0;
02986       TBaseClass* base = 0;
02987       TClass* base_cl = 0;
02988       Int_t base_offset = 0;
02989       Int_t local_offset = 0;
02990       TIter nextb(fClass->GetListOfBases());
02991       // Iterate on list of base classes.
02992       while ((base = (TBaseClass*) nextb())) {
02993          base_cl = TClass::GetClass(base->GetName());
02994          base_element = (TStreamerElement*) fElements->FindObject(base->GetName());
02995          if (!base_cl || !base_element) {
02996             continue;
02997          }
02998          base_offset = base_element->GetOffset();
02999          element = ((TStreamerInfo*)base_cl->GetStreamerInfo())->GetStreamerElement(datamember, local_offset);
03000          if (element) {
03001             offset = base_offset + local_offset;
03002             return element;
03003          }
03004       }
03005    } else {
03006       // Our class's dictionary is not loaded. Search through the base class streamer elements.
03007       TIter next(fElements);
03008       TStreamerElement* curelem = 0;
03009       while ((curelem = (TStreamerElement*) next())) {
03010          if (curelem->InheritsFrom(TStreamerBase::Class())) {
03011             TClass* baseClass = curelem->GetClassPointer();
03012             if (!baseClass) {
03013                continue;
03014             }
03015             Int_t base_offset = curelem->GetOffset();
03016             Int_t local_offset = 0;
03017             element = ((TStreamerInfo*)baseClass->GetStreamerInfo())->GetStreamerElement(datamember, local_offset);
03018             if (element) {
03019                offset = base_offset + local_offset;
03020                return element;
03021             }
03022          }
03023       }
03024    }
03025    return 0;
03026 }
03027 
03028 //______________________________________________________________________________
03029 TStreamerElement* TStreamerInfo::GetStreamerElementReal(Int_t i, Int_t j) const
03030 {
03031    //  TStreamerInfo  holds two types of data structures
03032    //    -TObjArray* fElements; containing the list of all TStreamerElement
03033    //       objects for this class version.
03034    //    -ULong_t*  fElem;  containing the preprocessed information
03035    //       by TStreamerInfo::Compile In case consecutive data members
03036    //       are of the same type, the Compile function declares the consecutive
03037    //       elements as one single element in fElems.
03038    //
03039    //  example with the class TAttLine
03040    //   TClass::GetClass("TAttLine")->GetStreamerInfo()->ls(); produces;
03041    //      StreamerInfo for class: TAttLine, version=1
03042    //       short        fLineColor      offset=  4 type= 2 line color
03043    //       short        fLineStyle      offset=  6 type= 2 line style
03044    //       short        fLineWidth      offset=  8 type= 2 line width
03045    //        i= 0, fLineColor      type= 22, offset=  4, len=3, method=0
03046    //  For I/O implementations (eg. XML) , one has to know the original name
03047    //  of the data member. This function can be used to return a pointer
03048    //  to the original TStreamerElement object corresponding to the j-th
03049    //  element of a compressed array in fElems.
03050    //
03051    //  parameters description:
03052    //    - i: the serial number in array fElem
03053    //    - j: the element number in the array of consecutive types
03054    //  In the above example the class TAttLine has 3 consecutive data members
03055    //  of the same type "short". Compile makes one single array of 3 elements.
03056    //  To access the TStreamerElement for the second element
03057    //  of this array, one can call:
03058    //     TStreamerElement *el = GetStreamerElementReal(0,1);
03059    //     const char* membername = el->GetName();
03060    //  This function is typically called from Tbuffer, TXmlBuffer
03061 
03062    if (i < 0 || i >= fNdata) return 0;
03063    if (j < 0) return 0;
03064    if (!fElements) return 0;
03065    TStreamerElement *se = (TStreamerElement*)fElem[i];
03066    if (!se) return 0;
03067    Int_t nelems = fElements->GetEntriesFast();
03068    for (Int_t ise=0;ise < nelems;ise++) {
03069       if (se != (TStreamerElement*)fElements->UncheckedAt(ise)) continue;
03070       if (ise+j >= nelems) return 0;
03071       return (TStreamerElement*)fElements->UncheckedAt(ise+j);
03072    }
03073    return 0;
03074 }
03075 
03076 //______________________________________________________________________________
03077 Double_t  TStreamerInfo::GetValueAux(Int_t type, void *ladd, Int_t k, Int_t len)
03078 {
03079    // Get the value from inside a collection.
03080 
03081    if (type>=kConv && type<kSTL) {
03082       type -= kConv;
03083    }
03084    switch (type) {
03085       // basic types
03086       case kBool:              {Bool_t *val   = (Bool_t*)ladd;   return Double_t(*val);}
03087       case kChar:              {Char_t *val   = (Char_t*)ladd;   return Double_t(*val);}
03088       case kShort:             {Short_t *val  = (Short_t*)ladd;  return Double_t(*val);}
03089       case kInt:               {Int_t *val    = (Int_t*)ladd;    return Double_t(*val);}
03090       case kLong:              {Long_t *val   = (Long_t*)ladd;   return Double_t(*val);}
03091       case kLong64:            {Long64_t *val = (Long64_t*)ladd; return Double_t(*val);}
03092       case kFloat:             {Float_t *val  = (Float_t*)ladd;  return Double_t(*val);}
03093       case kFloat16:           {Float_t *val  = (Float_t*)ladd;  return Double_t(*val);}
03094       case kDouble:            {Double_t *val = (Double_t*)ladd; return Double_t(*val);}
03095       case kDouble32:          {Double_t *val = (Double_t*)ladd; return Double_t(*val);}
03096       case kUChar:             {UChar_t *val  = (UChar_t*)ladd;  return Double_t(*val);}
03097       case kUShort:            {UShort_t *val = (UShort_t*)ladd; return Double_t(*val);}
03098       case kUInt:              {UInt_t *val   = (UInt_t*)ladd;   return Double_t(*val);}
03099       case kULong:             {ULong_t *val  = (ULong_t*)ladd;  return Double_t(*val);}
03100 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
03101       case kULong64:           {Long64_t *val = (Long64_t*)ladd;  return Double_t(*val);}
03102 #else
03103       case kULong64:           {ULong64_t *val= (ULong64_t*)ladd; return Double_t(*val);}
03104 #endif
03105       case kBits:              {UInt_t *val   = (UInt_t*)ladd;   return Double_t(*val);}
03106 
03107          // array of basic types  array[8]
03108       case kOffsetL + kBool:    {Bool_t *val   = (Bool_t*)ladd;   return Double_t(val[k]);}
03109       case kOffsetL + kChar:    {Char_t *val   = (Char_t*)ladd;   return Double_t(val[k]);}
03110       case kOffsetL + kShort:   {Short_t *val  = (Short_t*)ladd;  return Double_t(val[k]);}
03111       case kOffsetL + kInt:     {Int_t *val    = (Int_t*)ladd;    return Double_t(val[k]);}
03112       case kOffsetL + kLong:    {Long_t *val   = (Long_t*)ladd;   return Double_t(val[k]);}
03113       case kOffsetL + kLong64:  {Long64_t *val = (Long64_t*)ladd; return Double_t(val[k]);}
03114       case kOffsetL + kFloat:   {Float_t *val  = (Float_t*)ladd;  return Double_t(val[k]);}
03115       case kOffsetL + kFloat16: {Float_t *val  = (Float_t*)ladd;  return Double_t(val[k]);}
03116       case kOffsetL + kDouble:  {Double_t *val = (Double_t*)ladd; return Double_t(val[k]);}
03117       case kOffsetL + kDouble32:{Double_t *val = (Double_t*)ladd; return Double_t(val[k]);}
03118       case kOffsetL + kUChar:   {UChar_t *val  = (UChar_t*)ladd;  return Double_t(val[k]);}
03119       case kOffsetL + kUShort:  {UShort_t *val = (UShort_t*)ladd; return Double_t(val[k]);}
03120       case kOffsetL + kUInt:    {UInt_t *val   = (UInt_t*)ladd;   return Double_t(val[k]);}
03121       case kOffsetL + kULong:   {ULong_t *val  = (ULong_t*)ladd;  return Double_t(val[k]);}
03122 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
03123       case kOffsetL + kULong64: {Long64_t *val = (Long64_t*)ladd;  return Double_t(val[k]);}
03124 #else
03125       case kOffsetL + kULong64:{ULong64_t *val= (ULong64_t*)ladd; return Double_t(val[k]);}
03126 #endif
03127 
03128 #define READ_ARRAY(TYPE_t)                               \
03129          {                                               \
03130             Int_t sub_instance, index;                   \
03131             Int_t instance = k;                          \
03132             if (len) {                                   \
03133                index = instance / len;                   \
03134                sub_instance = instance % len;            \
03135             } else {                                     \
03136                index = instance;                         \
03137                sub_instance = 0;                         \
03138             }                                            \
03139             TYPE_t **val =(TYPE_t**)(ladd);              \
03140             return Double_t((val[sub_instance])[index]); \
03141          }
03142 
03143          // pointer to an array of basic types  array[n]
03144       case kOffsetP + kBool_t:    READ_ARRAY(Bool_t)
03145       case kOffsetP + kChar_t:    READ_ARRAY(Char_t)
03146       case kOffsetP + kShort_t:   READ_ARRAY(Short_t)
03147       case kOffsetP + kInt_t:     READ_ARRAY(Int_t)
03148       case kOffsetP + kLong_t:    READ_ARRAY(Long_t)
03149       case kOffsetP + kLong64_t:  READ_ARRAY(Long64_t)
03150       case kOffsetP + kFloat16_t:
03151       case kOffsetP + kFloat_t:   READ_ARRAY(Float_t)
03152       case kOffsetP + kDouble32_t:
03153       case kOffsetP + kDouble_t:  READ_ARRAY(Double_t)
03154       case kOffsetP + kUChar_t:   READ_ARRAY(UChar_t)
03155       case kOffsetP + kUShort_t:  READ_ARRAY(UShort_t)
03156       case kOffsetP + kUInt_t:    READ_ARRAY(UInt_t)
03157       case kOffsetP + kULong_t:   READ_ARRAY(ULong_t)
03158 #if defined(_MSC_VER) && (_MSC_VER <= 1200)
03159       case kOffsetP + kULong64_t: READ_ARRAY(Long64_t)
03160 #else
03161       case kOffsetP + kULong64_t: READ_ARRAY(ULong64_t)
03162 #endif
03163 
03164           // array counter //[n]
03165       case kCounter:           {Int_t *val    = (Int_t*)ladd;    return Double_t(*val);}
03166    }
03167    return 0;
03168 }
03169 
03170 //______________________________________________________________________________
03171 Double_t TStreamerInfo::GetValue(char *pointer, Int_t i, Int_t j, Int_t len) const
03172 {
03173    //  return value of element i in object at pointer.
03174    //  The function may be called in two ways:
03175    //    -method1  len < 0
03176    //           i is assumed to be the TStreamerElement number i in StreamerInfo
03177    //    -method2  len >= 0
03178    //           i is the type
03179    //           address of variable is directly pointer.
03180 
03181    char *ladd;
03182    Int_t atype;
03183    if (len >= 0) {
03184       ladd  = pointer;
03185       atype = i;
03186    } else {
03187       if (i < 0) return 0;
03188       ladd  = pointer + fOffset[i];
03189       atype = fNewType[i];
03190       len = ((TStreamerElement*)fElem[i])->GetArrayLength();
03191       if (atype == kSTL) {
03192          TClass *newClass = ((TStreamerElement*)fElem[i])->GetNewClass();
03193          if (newClass == 0) {
03194             newClass = ((TStreamerElement*)fElem[i])->GetClassPointer();
03195          }
03196          TClass *innerClass = newClass->GetCollectionProxy()->GetValueClass();
03197          if (innerClass) {
03198             return 0; // We don't know which member of the class we would want.
03199          } else {
03200             TVirtualCollectionProxy *proxy = newClass->GetCollectionProxy();
03201             atype = proxy->GetType();
03202             TVirtualCollectionProxy::TPushPop pop(proxy,ladd);
03203             Int_t nc = proxy->Size();
03204             if (j >= nc) return 0;
03205             char *element_ptr = (char*)proxy->At(j);
03206             return GetValueAux(atype,element_ptr,0,1);
03207          }
03208       }
03209    }
03210    return GetValueAux(atype,ladd,j,len);
03211 }
03212 
03213 //______________________________________________________________________________
03214 Double_t TStreamerInfo::GetValueClones(TClonesArray *clones, Int_t i, Int_t j, int k, Int_t eoffset) const
03215 {
03216    //  return value of element i in object number j in a TClonesArray and eventually
03217    // element k in a sub-array.
03218 
03219    Int_t nc = clones->GetEntriesFast();
03220    if (j >= nc) return 0;
03221 
03222    char *pointer = (char*)clones->UncheckedAt(j);
03223    char *ladd    = pointer + eoffset + fOffset[i];
03224    return GetValueAux(fType[i],ladd,k,((TStreamerElement*)fElem[i])->GetArrayLength());
03225 }
03226 
03227 //______________________________________________________________________________
03228 Double_t TStreamerInfo::GetValueSTL(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const
03229 {
03230    //  return value of element i in object number j in a TClonesArray and eventually
03231    // element k in a sub-array.
03232 
03233    Int_t nc = cont->Size();
03234    if (j >= nc) return 0;
03235 
03236    char *pointer = (char*)cont->At(j);
03237    char *ladd    = pointer + eoffset + fOffset[i];
03238    return GetValueAux(fType[i],ladd,k,((TStreamerElement*)fElem[i])->GetArrayLength());
03239 }
03240 
03241 //______________________________________________________________________________
03242 Double_t TStreamerInfo::GetValueSTLP(TVirtualCollectionProxy *cont, Int_t i, Int_t j, int k, Int_t eoffset) const
03243 {
03244    //  return value of element i in object number j in a TClonesArray and eventually
03245    // element k in a sub-array.
03246    Int_t nc = cont->Size();
03247 
03248    if (j >= nc) return 0;
03249 
03250    char **ptr = (char**)cont->At(j);
03251    char *pointer = *ptr;
03252 
03253    char *ladd    = pointer + eoffset + fOffset[i];
03254    return GetValueAux(fType[i],ladd,k,((TStreamerElement*)fElem[i])->GetArrayLength());
03255 }
03256 
03257 //______________________________________________________________________________
03258 void TStreamerInfo::InsertArtificialElements(const TObjArray *rules) 
03259 {
03260    // Insert new members as expressed in the array of TSchemaRule(s).
03261 
03262    if (!rules) return;
03263 
03264    TIter next(fElements);
03265    UInt_t count = 0;
03266 
03267    for(Int_t art = 0; art < rules->GetEntries(); ++art) {
03268       ROOT::TSchemaRule *rule = (ROOT::TSchemaRule*)rules->At(art);
03269       if( rule->IsRenameRule() || rule->IsAliasRule() )
03270          continue;
03271       next.Reset();
03272       Bool_t match = kFALSE;
03273       TStreamerElement *element;
03274       while ((element = (TStreamerElement*) next())) {
03275          if ( rule->HasTarget( element->GetName() ) ) {            
03276             // If the rule targets an existing member but it is also a source,
03277             // we still need to insert the rule.
03278             match = ! ((ROOT::TSchemaMatch*)rules)->HasRuleWithSource( element->GetName(), kTRUE );
03279             
03280             // Check whether this is an 'attribute' rule.
03281             if ( rule->GetAttributes()[0] != 0 ) {
03282                TString attr( rule->GetAttributes() );
03283                attr.ToLower();
03284                if (attr.Contains("owner")) {
03285                   if (attr.Contains("notowner")) {
03286                      element->SetBit(TStreamerElement::kDoNotDelete);
03287                   } else {
03288                      element->ResetBit(TStreamerElement::kDoNotDelete);
03289                   }
03290                }
03291             
03292             }
03293             break;
03294          }
03295       }
03296       if (!match) {
03297          TStreamerArtificial *newel;
03298          if (rule->GetTarget()==0) {
03299             TString newName;
03300             newName.Form("%s_rule%d",fClass->GetName(),count);
03301             newel = new TStreamerArtificial(newName,"", 
03302                                             fClass->GetDataMemberOffset(newName), 
03303                                             TStreamerInfo::kArtificial, 
03304                                             "void");
03305             newel->SetReadFunc( rule->GetReadFunctionPointer() );
03306             newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
03307             fElements->Add(newel);
03308          } else {
03309             TObjString * objstr = (TObjString*)(rule->GetTarget()->At(0));
03310             if (objstr) {
03311                TString newName = objstr->String();
03312                if ( fClass->GetDataMember( newName ) ) {
03313                   newel = new TStreamerArtificial(newName,"", 
03314                                                   fClass->GetDataMemberOffset(newName),
03315                                                   TStreamerInfo::kArtificial, 
03316                                                   fClass->GetDataMember( newName )->GetTypeName());
03317                   newel->SetReadFunc( rule->GetReadFunctionPointer() );
03318                   newel->SetReadRawFunc( rule->GetReadRawFunctionPointer() );
03319                   fElements->Add(newel);
03320                } else {
03321                   // This would be a completely new member (so it would need to be cached)
03322                   // TOBEDONE
03323                }
03324                for(Int_t other = 1; other < rule->GetTarget()->GetEntries(); ++other) {
03325                   objstr = (TObjString*)(rule->GetTarget()->At(other));
03326                   if (objstr) {
03327                      newName = objstr->String();
03328                      if ( fClass->GetDataMember( newName ) ) {
03329                         newel = new TStreamerArtificial(newName,"", 
03330                                                         fClass->GetDataMemberOffset(newName),
03331                                                         TStreamerInfo::kArtificial, 
03332                                                         fClass->GetDataMember( newName )->GetTypeName());
03333                         fElements->Add(newel);
03334                      }
03335                   }
03336                }
03337             } // For each target of the rule
03338          }
03339       } // None of the target of the rule are on file.
03340    }
03341 }
03342 
03343 //______________________________________________________________________________
03344 void TStreamerInfo::ls(Option_t *option) const
03345 {
03346    //  List the TStreamerElement list and also the precomputed tables
03347    if (fClass && fClass->IsForeign() && fClass->GetClassVersion()<2) {
03348       Printf("\nStreamerInfo for class: %s, checksum=0x%x",GetName(),GetCheckSum());
03349    } else {
03350       Printf("\nStreamerInfo for class: %s, version=%d, checksum=0x%x",GetName(),fClassVersion,GetCheckSum());
03351    }
03352 
03353    if (fElements) {
03354       TIter    next(fElements);
03355       TObject *obj;
03356       while ((obj = next()))
03357          obj->ls(option);
03358    }
03359    for (Int_t i=0;i < fNdata;i++) {
03360       TStreamerElement *element = (TStreamerElement*)fElem[i];
03361       TString sequenceType = " [";
03362       Bool_t first = kTRUE;
03363       if (element->TestBit(TStreamerElement::kCache)) {
03364          first = kFALSE;
03365          sequenceType += "cached";
03366       }
03367       if (element->TestBit(TStreamerElement::kRepeat)) {
03368          if (!first) sequenceType += ",";
03369          first = kFALSE;
03370          sequenceType += "repeat";
03371       }
03372       if (element->TestBit(TStreamerElement::kDoNotDelete)) {
03373          if (!first) sequenceType += ",";
03374          first = kFALSE;
03375          sequenceType += "nodelete";
03376       }
03377       if (first) sequenceType.Clear();
03378       else sequenceType += "]";
03379 
03380       Printf("   i=%2d, %-15s type=%3d, offset=%3d, len=%d, method=%ld%s",i,element->GetName(),fType[i],fOffset[i],fLength[i],fMethod[i],sequenceType.Data());
03381    }
03382 }
03383 
03384 //______________________________________________________________________________
03385 void* TStreamerInfo::New(void *obj)
03386 {
03387    // An emulated object is created at address obj, if obj is null we
03388    // allocate memory for the object.
03389 
03390    //???FIX ME: What about varying length array elements?
03391 
03392    char* p = (char*) obj;
03393 
03394    TIter next(fElements);
03395 
03396    if (!p) {
03397       // Allocate and initialize the memory block.
03398       p = new char[fSize];
03399       memset(p, 0, fSize);
03400    }
03401 
03402    next.Reset();
03403    TStreamerElement* element = (TStreamerElement*) next();
03404 
03405    for (; element; element = (TStreamerElement*) next()) {
03406 
03407       // Skip elements which have not been allocated memory.
03408       if (element->GetOffset() == kMissing) {
03409          continue;
03410       }
03411 
03412       // Skip elements for which we do not have any class
03413       // information.  FIXME: Document how this could happen.
03414       TClass* cle = element->GetClassPointer();
03415       if (!cle) {
03416          continue;
03417       }
03418 
03419       char* eaddr = p + element->GetOffset();
03420       Int_t etype = element->GetType();
03421 
03422       //cle->GetStreamerInfo(); //necessary in case "->" is not specified
03423 
03424       switch (etype) {
03425 
03426          case kAnyP:
03427          case kObjectP:
03428          case kSTLp:
03429          {
03430             // Initialize array of pointers with null pointers.
03431             char** r = (char**) eaddr;
03432             Int_t len = element->GetArrayLength();
03433             for (Int_t i = 0; i < len; ++i) {
03434                r[i] = 0;
03435             }
03436          }
03437          break;
03438 
03439          case kObjectp:
03440          case kAnyp:
03441          {
03442             // If the option "->" is given in the data member comment field
03443             // it is assumed that the object exists before reading data in,
03444             // so we create an object.
03445             if (cle != TClonesArray::Class()) {
03446                void** r = (void**) eaddr;
03447                *r = cle->New();
03448             } else {
03449                // In the case of a TClonesArray, the class name of
03450                // the contained objects must be specified in the
03451                // data member comment in this format:
03452                //    TClonesArray* myVar; //->(className)
03453                const char* title = element->GetTitle();
03454                const char* bracket1 = strrchr(title, '(');
03455                const char* bracket2 = strrchr(title, ')');
03456                if (bracket1 && bracket2 && (bracket2 != (bracket1 + 1))) {
03457                   Int_t len = bracket2 - (bracket1 + 1);
03458                   char* clonesClass = new char[len+1];
03459                   clonesClass[0] = '\0';
03460                   strncat(clonesClass, bracket1 + 1, len);
03461                   void** r = (void**) eaddr;
03462                   *r = (void*) new TClonesArray(clonesClass);
03463                   delete[] clonesClass;
03464                } else {
03465                   //Warning("New", "No class name found for TClonesArray initializer in data member comment (expected \"//->(className)\"");
03466                   void** r = (void**) eaddr;
03467                   *r = (void*) new TClonesArray();
03468                }
03469             }
03470          }
03471          break;
03472 
03473          case kBase:
03474          case kObject:
03475          case kAny:
03476          case kTObject:
03477          case kTString:
03478          case kTNamed:
03479          case kSTL:
03480          {
03481             cle->New(eaddr);
03482          }
03483          break;
03484 
03485          case kObject + kOffsetL:
03486          case kAny + kOffsetL:
03487          case kTObject + kOffsetL:
03488          case kTString + kOffsetL:
03489          case kTNamed + kOffsetL:
03490          case kSTL + kOffsetL:
03491          {
03492             Int_t size = cle->Size();
03493             char* r = eaddr;
03494             Int_t len = element->GetArrayLength();
03495             for (Int_t i = 0; i < len; ++i, r += size) {
03496                cle->New(r);
03497             }
03498          }
03499          break;
03500 
03501       } // switch etype
03502    } // for TIter next(fElements)
03503 
03504    for(int nbase = 0; nbase < fNVirtualInfoLoc; ++nbase) {
03505       *(TStreamerInfo**)(p + fVirtualInfoLoc[nbase]) = this;
03506    }
03507    ++fLiveCount;
03508    return p;
03509 }
03510 
03511 //______________________________________________________________________________
03512 void* TStreamerInfo::NewArray(Long_t nElements, void *ary)
03513 {
03514    // An array of emulated objects is created at address ary, if ary is null,
03515    // we allocate memory for the array.
03516 
03517    if (fClass == 0) {
03518       Error("NewArray", "TClass pointer is null!");
03519       return 0;
03520    }
03521 
03522    Int_t size = fClass->Size();
03523 
03524    char* p = (char*) ary;
03525 
03526    if (!p) {
03527       Long_t len = nElements * size + sizeof(Long_t)*2;
03528       p = new char[len];
03529       memset(p, 0, len);
03530    }
03531 
03532    // Store the array cookie
03533    Long_t* r = (Long_t*) p;
03534    r[0] = size;
03535    r[1] = nElements;
03536    char* dataBegin = (char*) &r[2];
03537 
03538    // Do a placement new for each element.
03539    p = dataBegin;
03540    for (Long_t cnt = 0; cnt < nElements; ++cnt) {
03541       New(p);
03542       p += size;
03543    } // for nElements
03544 
03545    return dataBegin;
03546 }
03547 
03548 
03549 #define DeleteBasicPointer(addr,element,name)                           \
03550    {                                                                    \
03551       name **f = (name**)(addr);                                        \
03552       int n = element->GetArrayLength() ? element->GetArrayLength() : 1;\
03553       for(int j=0;j<n;j++) {                                            \
03554          delete [] f[j];                                                \
03555          f[j] = 0;                                                      \
03556       }                                                                 \
03557    }
03558 
03559 //______________________________________________________________________________
03560 void TStreamerInfo::DestructorImpl(void* obj, Bool_t dtorOnly)
03561 {
03562    // Internal part of the destructor.
03563    // Destruct each of the datamembers in the same order
03564    // as the implicit destructor would.
03565 
03566    R__ASSERT(obj != 0);
03567 
03568    char *p = (char*)obj;
03569 
03570    Int_t nelements = fElements->GetEntriesFast();
03571    //for (; ele; ele = (TStreamerElement*) next())
03572    for (Int_t elenum = nelements - 1; elenum >= 0; --elenum) {
03573       TStreamerElement* ele = (TStreamerElement*) fElements->UncheckedAt(elenum);
03574       if (ele->GetOffset() == kMissing) continue;
03575       char* eaddr = p + ele->GetOffset();
03576 
03577 
03578       Int_t etype = ele->GetType();
03579 
03580       switch(etype) {
03581          case TStreamerInfo::kOffsetP + TStreamerInfo::kBool:   DeleteBasicPointer(eaddr,ele,Bool_t);  continue;
03582          case TStreamerInfo::kOffsetP + TStreamerInfo::kChar:   DeleteBasicPointer(eaddr,ele,Char_t);  continue;
03583          case TStreamerInfo::kOffsetP + TStreamerInfo::kShort:  DeleteBasicPointer(eaddr,ele,Short_t);  continue;
03584          case TStreamerInfo::kOffsetP + TStreamerInfo::kInt:    DeleteBasicPointer(eaddr,ele,Int_t);  continue;
03585          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong:   DeleteBasicPointer(eaddr,ele,Long_t);  continue;
03586          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong64: DeleteBasicPointer(eaddr,ele,Long64_t);  continue;
03587          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat16:
03588          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat:  DeleteBasicPointer(eaddr,ele,Float_t);  continue;
03589          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble32:
03590          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble: DeleteBasicPointer(eaddr,ele,Double_t);  continue;
03591          case TStreamerInfo::kOffsetP + TStreamerInfo::kUChar:  DeleteBasicPointer(eaddr,ele,UChar_t);  continue;
03592          case TStreamerInfo::kOffsetP + TStreamerInfo::kUShort: DeleteBasicPointer(eaddr,ele,UShort_t);  continue;
03593          case TStreamerInfo::kOffsetP + TStreamerInfo::kUInt:   DeleteBasicPointer(eaddr,ele,UInt_t);  continue;
03594          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong:  DeleteBasicPointer(eaddr,ele,ULong_t);  continue;
03595          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong64:DeleteBasicPointer(eaddr,ele,ULong64_t);  continue;
03596       }
03597 
03598 
03599 
03600       TClass* cle = ele->GetClassPointer();
03601       if (!cle) continue;
03602 
03603 
03604       if (etype == kObjectp || etype == kAnyp) {
03605          // Destroy an array of pre-allocated objects.
03606          Int_t len = ele->GetArrayLength();
03607          if (!len) {
03608             len = 1;
03609          }
03610          void** r = (void**) eaddr;
03611          for (Int_t j = len - 1; j >= 0; --j) {
03612             if (r[j]) {
03613                cle->Destructor(r[j]);
03614                r[j] = 0;
03615             }
03616          }
03617       }
03618 
03619       if ((etype == kObjectP || etype == kAnyP || etype == kSTLp) && !ele->TestBit(TStreamerElement::kDoNotDelete)) {
03620          // Destroy an array of pointers to not-pre-allocated objects.
03621          Int_t len = ele->GetArrayLength();
03622          if (!len) {
03623             len = 1;
03624          }
03625          void** r = (void**) eaddr;
03626          for (Int_t j = len - 1; j >= 0; --j) {
03627             if (r[j]) {
03628                cle->Destructor(r[j]);
03629                r[j] = 0;
03630             }
03631          }
03632       }
03633 
03634       if (etype == kObject || etype == kAny || etype == kBase ||
03635           etype == kTObject || etype == kTString || etype == kTNamed) {
03636          // A data member is destroyed, but not deleted.
03637          cle->Destructor(eaddr, kTRUE);
03638       }
03639 
03640       if (etype == kSTL) {
03641          // A data member is destroyed, but not deleted.
03642          TVirtualCollectionProxy *pr = cle->GetCollectionProxy();
03643          if (!pr) {
03644             cle->Destructor(eaddr, kTRUE);
03645          } else {
03646             if (ele->TestBit(TStreamerElement::kDoNotDelete)) {
03647                TVirtualCollectionProxy::TPushPop env(cle->GetCollectionProxy(), eaddr); // used for both this 'clear' and the 'clear' inside destructor.
03648                cle->GetCollectionProxy()->Clear(); // empty the collection without deleting the pointer
03649                pr->Destructor(eaddr, kTRUE);
03650             } else {
03651                pr->Destructor(eaddr, kTRUE);
03652             }
03653          }
03654       }
03655 
03656       if (etype == kObject  + kOffsetL || etype == kAny     + kOffsetL ||
03657           etype == kTObject + kOffsetL || etype == kTString + kOffsetL ||
03658           etype == kTNamed  + kOffsetL || etype == kSTL     + kOffsetL) {
03659          // For a data member which is an array of objects, we
03660          // destroy the objects, but do not delete them.
03661          Int_t len = ele->GetArrayLength();
03662          Int_t size = cle->Size();
03663          char* r = eaddr + (size * (len - 1));
03664          for (Int_t j = len - 1; j >= 0; --j, r -= size) {
03665             cle->Destructor(r, kTRUE);
03666          }
03667       }
03668    } // iter over elements
03669 
03670    if (!dtorOnly) {
03671       delete[] p;
03672    }
03673    --fLiveCount;
03674 }   
03675 
03676 //______________________________________________________________________________
03677 void TStreamerInfo::Destructor(void* obj, Bool_t dtorOnly)
03678 {
03679    // Emulated destructor for this class.
03680    // An emulated object is destroyed at address p.
03681    // Destruct each of the datamembers in the same order
03682    // as the implicit destructor would.
03683 
03684    // Do nothing if passed a null pointer.
03685    if (obj == 0) return;
03686 
03687    char* p = (char*) obj;
03688 
03689    if (!dtorOnly && fNVirtualInfoLoc) {
03690       // !dtorOnly is used to filter out the case where this is called for
03691       // a base class or embeded object of the outer most class.
03692       TStreamerInfo *allocator = *(TStreamerInfo**)(p + fVirtualInfoLoc[0]);
03693       if (allocator != this) {
03694 
03695          Int_t baseoffset = allocator->GetClass()->GetBaseClassOffset(GetClass());
03696 
03697          p -= baseoffset;
03698          allocator->DestructorImpl(p, kFALSE);
03699          return;
03700       }
03701    }
03702    DestructorImpl(p, dtorOnly);
03703 }
03704 
03705 //______________________________________________________________________________
03706 void TStreamerInfo::DeleteArray(void* ary, Bool_t dtorOnly)
03707 {
03708    // Destroy an array of emulated objects, with optional delete.
03709 
03710    // Do nothing if passed a null pointer.
03711    if (ary == 0) return;
03712 
03713    //???FIX ME: What about varying length arrays?
03714 
03715    Long_t* r = (Long_t*) ary;
03716    Long_t arrayLen = r[-1];
03717    Long_t size = r[-2];
03718    char* memBegin = (char*) &r[-2];
03719 
03720    char* p = ((char*) ary) + ((arrayLen - 1) * size);
03721    for (Long_t cnt = 0; cnt < arrayLen; ++cnt, p -= size) {
03722       // Destroy each element, but do not delete it.
03723       Destructor(p, kTRUE);
03724    } // for arrayItemSize
03725 
03726    if (!dtorOnly) {
03727       delete[] memBegin;
03728    }
03729 }
03730 
03731 //______________________________________________________________________________
03732 void TStreamerInfo::PrintValue(const char *name, char *pointer, Int_t i, Int_t len, Int_t lenmax) const
03733 {
03734    //  print value of element i in object at pointer
03735    //  The function may be called in two ways:
03736    //    -method1  len < 0
03737    //           i is assumed to be the TStreamerElement number i in StreamerInfo
03738    //    -method2  len >= 0
03739    //           i is the type
03740    //           address of variable is directly pointer.
03741    //           len is the number of elements to be printed starting at pointer.
03742 
03743    char *ladd;
03744    Int_t atype,aleng;
03745    printf(" %-15s = ",name);
03746 
03747    TStreamerElement * aElement  = 0;
03748    Int_t *count  = 0;
03749    if (len >= 0) {
03750       ladd  = pointer;
03751       atype = i;
03752       aleng = len;
03753    } else        {
03754       if (i < 0) {
03755          if (pointer==0) {
03756             printf("NULL\n");
03757          } else {
03758             static TClassRef stringClass("string");
03759             if (fClass == stringClass) {
03760                std::string *st = (std::string*)(pointer);
03761                printf("%s\n",st->c_str());               
03762             } else if (fClass == TString::Class()) {
03763                TString *st = (TString*)(pointer);
03764                printf("%s\n",st->Data());               
03765             } else {
03766                printf("(%s*)0x%lx\n",GetName(),(ULong_t)pointer);
03767             }
03768          }
03769          return;
03770       }
03771       ladd  = pointer + fOffset[i];
03772       atype = fNewType[i];
03773       aleng = fLength[i];
03774       aElement  = (TStreamerElement*)fElem[i];
03775       count = (Int_t*)(pointer+fMethod[i]);
03776    }
03777    if (aleng > lenmax) aleng = lenmax;
03778 
03779    PrintValueAux(ladd,atype,aElement,aleng,count);
03780    printf("\n");
03781 }
03782 
03783 //______________________________________________________________________________
03784 void TStreamerInfo::PrintValueClones(const char *name, TClonesArray *clones, Int_t i, Int_t eoffset, Int_t lenmax) const
03785 {
03786    //  print value of element i in a TClonesArray
03787 
03788    if (!clones) {printf(" %-15s = \n",name); return;}
03789    printf(" %-15s = ",name);
03790    Int_t nc = clones->GetEntriesFast();
03791    if (nc > lenmax) nc = lenmax;
03792 
03793    Int_t offset = eoffset + fOffset[i];
03794    TStreamerElement *aElement  = (TStreamerElement*)fElem[i];
03795    int aleng = fLength[i];
03796    if (aleng > lenmax) aleng = lenmax;
03797 
03798    for (Int_t k=0;k < nc;k++) {
03799       char *pointer = (char*)clones->UncheckedAt(k);
03800       char *ladd = pointer+offset;
03801       Int_t *count = (Int_t*)(pointer+fMethod[i]);
03802       PrintValueAux(ladd,fNewType[i],aElement, aleng, count);
03803       if (k < nc-1) printf(", ");
03804    }
03805    printf("\n");
03806 }
03807 
03808 //______________________________________________________________________________
03809 void TStreamerInfo::PrintValueSTL(const char *name, TVirtualCollectionProxy *cont, Int_t i, Int_t eoffset, Int_t lenmax) const
03810 {
03811    //  print value of element i in a TClonesArray
03812 
03813    if (!cont) {printf(" %-15s = \n",name); return;}
03814    printf(" %-15s = ",name);
03815    Int_t nc = cont->Size();
03816    if (nc > lenmax) nc = lenmax;
03817 
03818    Int_t offset = eoffset + fOffset[i];
03819    TStreamerElement *aElement  = (TStreamerElement*)fElem[i];
03820    int aleng = fLength[i];
03821    if (aleng > lenmax) aleng = lenmax;
03822 
03823    for (Int_t k=0;k < nc;k++) {
03824       char *pointer = (char*)cont->At(k);
03825       char *ladd = pointer+offset;
03826       Int_t *count = (Int_t*)(pointer+fMethod[i]);
03827       PrintValueAux(ladd,fNewType[i],aElement, aleng, count);
03828       if (k < nc-1) printf(", ");
03829    }
03830    printf("\n");
03831 }
03832 
03833 //______________________________________________________________________________
03834 void TStreamerInfo::Streamer(TBuffer &R__b)
03835 {
03836    // Stream an object of class TStreamerInfo.
03837 
03838    UInt_t R__s, R__c;
03839    if (R__b.IsReading()) {
03840       Version_t R__v = R__b.ReadVersion(&R__s, &R__c);
03841       fOldVersion = R__v;
03842       if (R__v > 1) {
03843          //R__b.ReadClassBuffer(TStreamerInfo::Class(), this, R__v, R__s, R__c);
03844          R__b.ClassBegin(TStreamerInfo::Class(), R__v);
03845          R__b.ClassMember("TNamed");
03846          TNamed::Streamer(R__b);
03847          fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
03848          R__b.ClassMember("fCheckSum","UInt_t");
03849          R__b >> fCheckSum;
03850          R__b.ClassMember("fClassVersion","Int_t");
03851          R__b >> fClassVersion;
03852          fOnFileClassVersion = fClassVersion;
03853          R__b.ClassMember("fElements","TObjArray*");     
03854          R__b >> fElements;
03855          R__b.ClassEnd(TStreamerInfo::Class());
03856          R__b.SetBufferOffset(R__s+R__c+sizeof(UInt_t));
03857          ResetBit(kIsCompiled);
03858          return;
03859       }
03860       //====process old versions before automatic schema evolution
03861       TNamed::Streamer(R__b);
03862       fName = TClassEdit::GetLong64_Name( fName.Data() ).c_str();
03863       R__b >> fCheckSum;
03864       R__b >> fClassVersion;
03865       fOnFileClassVersion = fClassVersion;
03866       R__b >> fElements;
03867       R__b.CheckByteCount(R__s, R__c, TStreamerInfo::IsA());
03868    } else {
03869       R__c = R__b.WriteVersion(TStreamerInfo::IsA(), kTRUE);
03870       R__b.ClassBegin(TStreamerInfo::Class());
03871       R__b.ClassMember("TNamed");
03872       TNamed::Streamer(R__b);
03873       R__b.ClassMember("fCheckSum","UInt_t");
03874       R__b << fCheckSum;
03875       R__b.ClassMember("fClassVersion","Int_t");
03876       R__b << ((fClassVersion > 0) ? fClassVersion : -fClassVersion);
03877 
03878       //------------------------------------------------------------------------
03879       // Stream only non-artificial streamer elements
03880       //------------------------------------------------------------------------
03881       R__b.ClassMember("fElements","TObjArray*");
03882 #if NOTYET
03883       if (has_no_artificial_member) {
03884          R__b << fElements;
03885       } else 
03886 #endif
03887       { 
03888          R__LOCKGUARD(gCINTMutex);
03889          Int_t nobjects = fElements->GetEntriesFast();
03890          TObjArray store( *fElements );
03891          TStreamerElement *el;
03892          for (Int_t i = 0; i < nobjects; i++) {
03893             el = (TStreamerElement*)fElements->UncheckedAt(i);
03894             if( el != 0 && (el->IsA() == TStreamerArtificial::Class() || el->TestBit(TStreamerElement::kRepeat))) {
03895                fElements->RemoveAt( i );
03896             }
03897          }
03898          fElements->Compress();
03899          R__b << fElements;
03900          R__ASSERT(!fElements->IsOwner());
03901          *fElements = store;
03902       }
03903       R__b.ClassEnd(TStreamerInfo::Class());
03904       R__b.SetByteCount(R__c, kTRUE);
03905    }
03906 }
03907 
03908 //______________________________________________________________________________
03909 void TStreamerInfo::TagFile(TFile *file)
03910 {
03911    // Mark the classindex of the current file as using this TStreamerInfo
03912    // This function is deprecated and its functionality is now done by
03913    // the overloads of TBuffer::TagStreamerInfo.
03914 
03915    if (file) {
03916       static Bool_t onlyonce = kFALSE;
03917       if (!onlyonce) {
03918          Warning("TagFile","This function is deprecated, use TBuffer::TagStreamerInfo instead");
03919          onlyonce = kTRUE;
03920       }
03921       TArrayC *cindex = file->GetClassIndex();
03922       Int_t nindex = cindex->GetSize();
03923       if (fNumber < 0 || fNumber >= nindex) {
03924          Error("TagFile","StreamerInfo: %s number: %d out of range[0,%d] in file: %s",
03925                GetName(),fNumber,nindex,file->GetName());
03926          return;
03927       }
03928       if (cindex->fArray[fNumber] == 0) {
03929          cindex->fArray[0]       = 1;
03930          cindex->fArray[fNumber] = 1;
03931       }
03932    }
03933 }
03934 
03935 //______________________________________________________________________________
03936 #ifdef DOLOOP
03937 #undef DOLOOP
03938 #endif
03939 #define DOLOOP for (k = 0, pointer = arr[0]; k < narr; pointer = arr[++k])
03940 
03941 namespace {
03942    static void PrintCR(int j,Int_t aleng, UInt_t ltype)
03943    {
03944       if (j == aleng-1) printf("\n");
03945       else {
03946          printf(", ");
03947          if (j%ltype == ltype-1) printf("\n                    ");
03948       }
03949    }
03950 }
03951 
03952 //______________________________________________________________________________
03953 void TStreamerInfo::PrintValueAux(char *ladd, Int_t atype, TStreamerElement *aElement, Int_t aleng, Int_t *count)
03954 {
03955    //  print value of element  in object at pointer, type atype, leng aleng or *count
03956    //  The function may be called in two ways:
03957    //    -method1  len < 0
03958    //           i is assumed to be the TStreamerElement number i in StreamerInfo
03959    //    -method2  len >= 0
03960    //           i is the type
03961    //           address of variable is directly pointer.
03962    //           len is the number of elements to be printed starting at pointer.
03963    int j;
03964 
03965    //assert(!((kOffsetP + kChar) <= atype && atype <= (kOffsetP + kBool) && count == 0));
03966    switch (atype) {
03967       // basic types
03968       case kBool:              {Bool_t    *val = (Bool_t*   )ladd; printf("%d" ,*val);  break;}
03969       case kChar:              {Char_t    *val = (Char_t*   )ladd; printf("%d" ,*val);  break;}
03970       case kShort:             {Short_t   *val = (Short_t*  )ladd; printf("%d" ,*val);  break;}
03971       case kInt:               {Int_t     *val = (Int_t*    )ladd; printf("%d" ,*val);  break;}
03972       case kLong:              {Long_t    *val = (Long_t*   )ladd; printf("%ld",*val);  break;}
03973       case kLong64:            {Long64_t  *val = (Long64_t* )ladd; printf("%lld",*val);  break;}
03974       case kFloat:             {Float_t   *val = (Float_t*  )ladd; printf("%f" ,*val);  break;}
03975       case kFloat16:           {Float_t   *val = (Float_t*  )ladd; printf("%f" ,*val);  break;}
03976       case kDouble:            {Double_t  *val = (Double_t* )ladd; printf("%g" ,*val);  break;}
03977       case kDouble32:          {Double_t  *val = (Double_t* )ladd; printf("%g" ,*val);  break;}
03978       case kUChar:             {UChar_t   *val = (UChar_t*  )ladd; printf("%u" ,*val);  break;}
03979       case kUShort:            {UShort_t  *val = (UShort_t* )ladd; printf("%u" ,*val);  break;}
03980       case kUInt:              {UInt_t    *val = (UInt_t*   )ladd; printf("%u" ,*val);  break;}
03981       case kULong:             {ULong_t   *val = (ULong_t*  )ladd; printf("%lu",*val);  break;}
03982       case kULong64:           {ULong64_t *val = (ULong64_t*)ladd; printf("%llu",*val);  break;}
03983       case kBits:              {UInt_t    *val = (UInt_t*   )ladd; printf("%d" ,*val);  break;}
03984 
03985          // array of basic types  array[8]
03986       case kOffsetL + kBool:    {Bool_t    *val = (Bool_t*   )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
03987       case kOffsetL + kChar:    {Char_t    *val = (Char_t*   )ladd; for(j=0;j<aleng;j++) { printf("%c " ,val[j]); PrintCR(j,aleng,20); } break;}
03988       case kOffsetL + kShort:   {Short_t   *val = (Short_t*  )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
03989       case kOffsetL + kInt:     {Int_t     *val = (Int_t*    )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng,10); } break;}
03990       case kOffsetL + kLong:    {Long_t    *val = (Long_t*   )ladd; for(j=0;j<aleng;j++) { printf("%ld ",val[j]); PrintCR(j,aleng, 5); } break;}
03991       case kOffsetL + kLong64:  {Long64_t  *val = (Long64_t* )ladd; for(j=0;j<aleng;j++) { printf("%lld ",val[j]);PrintCR(j,aleng, 5); } break;}
03992       case kOffsetL + kFloat:   {Float_t   *val = (Float_t*  )ladd; for(j=0;j<aleng;j++) { printf("%f " ,val[j]); PrintCR(j,aleng, 5); } break;}
03993       case kOffsetL + kFloat16: {Float_t   *val = (Float_t*  )ladd; for(j=0;j<aleng;j++) { printf("%f " ,val[j]); PrintCR(j,aleng, 5); } break;}
03994       case kOffsetL + kDouble:  {Double_t  *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
03995       case kOffsetL + kDouble32:{Double_t  *val = (Double_t* )ladd; for(j=0;j<aleng;j++) { printf("%g " ,val[j]); PrintCR(j,aleng, 5); } break;}
03996       case kOffsetL + kUChar:   {UChar_t   *val = (UChar_t*  )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,20); } break;}
03997       case kOffsetL + kUShort:  {UShort_t  *val = (UShort_t* )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng,10); } break;}
03998       case kOffsetL + kUInt:    {UInt_t    *val = (UInt_t*   )ladd; for(j=0;j<aleng;j++) { printf("%u " ,val[j]); PrintCR(j,aleng, 5); } break;}
03999       case kOffsetL + kULong:   {ULong_t   *val = (ULong_t*  )ladd; for(j=0;j<aleng;j++) { printf("%lu ",val[j]); PrintCR(j,aleng, 5); } break;}
04000       case kOffsetL + kULong64: {ULong64_t *val = (ULong64_t*)ladd; for(j=0;j<aleng;j++) { printf("%llu ",val[j]);PrintCR(j,aleng, 5); } break;}
04001       case kOffsetL + kBits:    {UInt_t    *val = (UInt_t*   )ladd; for(j=0;j<aleng;j++) { printf("%d " ,val[j]); PrintCR(j,aleng, 5); } break;}
04002 
04003          // pointer to an array of basic types  array[n]
04004       case kOffsetP + kBool:    {Bool_t   **val = (Bool_t**  )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
04005       case kOffsetP + kChar:    {Char_t   **val = (Char_t**  )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
04006       case kOffsetP + kShort:   {Short_t  **val = (Short_t** )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
04007       case kOffsetP + kInt:     {Int_t    **val = (Int_t**   )ladd; for(j=0;j<*count;j++) { printf("%d " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
04008       case kOffsetP + kLong:    {Long_t   **val = (Long_t**  )ladd; for(j=0;j<*count;j++) { printf("%ld ",(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04009       case kOffsetP + kLong64:  {Long64_t **val = (Long64_t**)ladd; for(j=0;j<*count;j++) { printf("%lld ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
04010       case kOffsetP + kFloat:   {Float_t  **val = (Float_t** )ladd; for(j=0;j<*count;j++) { printf("%f " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04011       case kOffsetP + kFloat16: {Float_t  **val = (Float_t** )ladd; for(j=0;j<*count;j++) { printf("%f " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04012       case kOffsetP + kDouble:  {Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04013       case kOffsetP + kDouble32:{Double_t **val = (Double_t**)ladd; for(j=0;j<*count;j++) { printf("%g " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04014       case kOffsetP + kUChar:   {UChar_t  **val = (UChar_t** )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng,20); } break;}
04015       case kOffsetP + kUShort:  {UShort_t **val = (UShort_t**)ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng,10); } break;}
04016       case kOffsetP + kUInt:    {UInt_t   **val = (UInt_t**  )ladd; for(j=0;j<*count;j++) { printf("%u " ,(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04017       case kOffsetP + kULong:   {ULong_t  **val = (ULong_t** )ladd; for(j=0;j<*count;j++) { printf("%lu ",(*val)[j]);  PrintCR(j,aleng, 5); } break;}
04018       case kOffsetP + kULong64: {ULong64_t**val = (ULong64_t**)ladd; for(j=0;j<*count;j++){ printf("%llu ",(*val)[j]); PrintCR(j,aleng, 5); } break;}
04019 
04020          // array counter //[n]
04021       case kCounter:            {Int_t *val    = (Int_t*)ladd;    printf("%d",*val);  break;}
04022          // char *
04023       case kCharStar:{
04024          char **val = (char**)ladd;
04025          if (*val) printf("%s",*val);
04026          break;
04027       }
04028       // Class *  derived from TObject with comment field  //->
04029       case kObjectp: {
04030          TObject **obj = (TObject**)(ladd);
04031          TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
04032          printf("(%s*)%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
04033          break;
04034       }
04035 
04036       // Class*   derived from TObject
04037       case kObjectP: {
04038          TObject **obj = (TObject**)(ladd);
04039          TStreamerObjectPointer *el = (TStreamerObjectPointer*)aElement;
04040          printf("(%s*)%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
04041          break;
04042       }
04043 
04044       // Class    derived from TObject
04045       case kObject:  {
04046          TObject *obj = (TObject*)(ladd);
04047          printf("%s",obj->GetName());
04048          break;
04049       }
04050 
04051       // Special case for TString, TObject, TNamed
04052       case kTString: {
04053          TString *st = (TString*)(ladd);
04054          printf("%s",st->Data());
04055          break;
04056       }
04057       case kTObject: {
04058          TObject *obj = (TObject*)(ladd);
04059          printf("%s",obj->GetName());
04060          break;
04061       }
04062       case kTNamed:  {
04063          TNamed *named = (TNamed*) (ladd);
04064          printf("%s/%s",named->GetName(),named->GetTitle());
04065          break;
04066       }
04067 
04068       // Class *  not derived from TObject with comment field  //->
04069       case kAnyp:    {
04070          TObject **obj = (TObject**)(ladd);
04071          TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
04072          printf("(%s*)0x%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
04073          break;
04074       }
04075 
04076       // Class*   not derived from TObject
04077       case kAnyP:    {
04078          TObject **obj = (TObject**)(ladd);
04079          TStreamerObjectAnyPointer *el = (TStreamerObjectAnyPointer*)aElement;
04080          printf("(%s*)0x%lx",el ? el->GetClass()->GetName() : "unknown_type",(Long_t)(*obj));
04081          break;
04082       }
04083       // Any Class not derived from TObject
04084       case kOffsetL + kObjectp:
04085       case kOffsetL + kObjectP:
04086       case kAny:     {
04087          printf("printing kAny case (%d)",atype);
04088 //         if (aElement) {
04089 //            TMemberStreamer *pstreamer = aElement->GetStreamer();
04090 //            if (pstreamer == 0) {
04091 //               //printf("ERROR, Streamer is null\n");
04092 //               //aElement->ls();
04093 //               break;
04094 //            }
04095 //            //(*pstreamer)(b,ladd,0);
04096 //         }
04097          break;
04098       }
04099       // Base Class
04100       case kBase:    {
04101          printf("printing kBase case (%d)",atype);
04102          //aElement->ReadBuffer(b,pointer);
04103          break;
04104       }
04105 
04106       case kOffsetL + kObject:
04107       case kOffsetL + kTString:
04108       case kOffsetL + kTObject:
04109       case kOffsetL + kTNamed:
04110       case kStreamer: {
04111          printf("printing kStreamer case (%d)",atype);
04112 //         TMemberStreamer *pstreamer = aElement->GetStreamer();
04113 //         if (pstreamer == 0) {
04114 //            //printf("ERROR, Streamer is null\n");
04115 //            //aElement->ls();
04116 //            break;
04117 //         }
04118 //         //UInt_t start,count;
04119 //         //b.ReadVersion(&start, &count);
04120 //         //(*pstreamer)(b,ladd,0);
04121 //         //b.CheckByteCount(start,count,IsA());
04122          break;
04123       }
04124 
04125       case kStreamLoop: {
04126          printf("printing kStreamLoop case (%d)",atype);
04127 //         TMemberStreamer *pstreamer = aElement->GetStreamer();
04128 //         if (pstreamer == 0) {
04129 //            //printf("ERROR, Streamer is null\n");
04130 //            //aElement->ls();
04131 //            break;
04132 //         }
04133          //Int_t *counter = (Int_t*)(count);
04134          //UInt_t start,count;
04135          ///b.ReadVersion(&start, &count);
04136          //(*pstreamer)(b,ladd,*counter);
04137          //b.CheckByteCount(start,count,IsA());
04138          break;
04139       }
04140       case kSTL: {
04141          if (aElement) {
04142             static TClassRef stringClass("string");
04143             if (ladd && aElement->GetClass() == stringClass) {
04144                std::string *st = (std::string*)(ladd);
04145                printf("%s",st->c_str());
04146             } else {
04147                printf("(%s*)0x%lx",aElement->GetClass()->GetName(),(Long_t)(ladd));
04148             }
04149          } else {
04150             printf("(unknown_type*)0x%lx",(Long_t)(ladd));
04151          }
04152          break;
04153       }   
04154    }
04155 }
04156 
04157 //______________________________________________________________________________
04158 void TStreamerInfo::Update(const TClass *oldcl, TClass *newcl)
04159 {
04160    //function called by the TClass constructor when replacing an emulated class
04161    //by the real class
04162 
04163    TStreamerElement *element;
04164    TIter nextElement(GetElements());
04165    while ((element = (TStreamerElement*)nextElement())) {
04166       element->Update(oldcl,newcl);
04167    }
04168    for (Int_t i=0;i < fNdata;i++) {
04169       fComp[i].Update(oldcl,newcl);
04170    }
04171 }
04172 
04173 //______________________________________________________________________________
04174 void TStreamerInfo::TCompInfo::Update(const TClass *oldcl, TClass *newcl)
04175 {
04176    // Update the TClass pointer cached in this object.
04177 
04178    if (fClass == oldcl)
04179       fClass = newcl;
04180    else if (fClass == 0)
04181       fClass =TClass::GetClass(fClassName);
04182 }
04183 
04184 
04185 //______________________________________________________________________________
04186 //______________________________________________________________________________
04187 
04188 //______________________________________________________________________________
04189 TVirtualCollectionProxy*
04190 TStreamerInfo::GenEmulatedProxy(const char* class_name)
04191 {
04192    // Generate emulated collection proxy for a given class.
04193 
04194    return TCollectionProxyFactory::GenEmulatedProxy(class_name);
04195 }
04196 
04197 //______________________________________________________________________________
04198 TClassStreamer*
04199 TStreamerInfo::GenEmulatedClassStreamer(const char* class_name)
04200 {
04201    // Generate emulated class streamer for a given collection class.
04202 
04203    return TCollectionProxyFactory::GenEmulatedClassStreamer(class_name);
04204 }
04205 
04206 //______________________________________________________________________________
04207 TVirtualCollectionProxy*
04208 TStreamerInfo::GenExplicitProxy( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
04209 {
04210    // Generate proxy from static functions.
04211 
04212    return TCollectionProxyFactory::GenExplicitProxy(info, cl);
04213 }
04214 
04215 //______________________________________________________________________________
04216 TClassStreamer*
04217 TStreamerInfo::GenExplicitClassStreamer( const ::ROOT::TCollectionProxyInfo &info, TClass *cl )
04218 {
04219    // Generate class streamer from static functions.
04220 
04221    return TCollectionProxyFactory::GenExplicitClassStreamer(info, cl);
04222 }

Generated on Tue Jul 5 14:30:19 2011 for ROOT_528-00b_version by  doxygen 1.5.1