TStreamerInfoActions.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TStreamerInfoActions.cxx 38371 2011-03-10 20:16:53Z pcanal $
00002 // Author: Philippe Canal 05/2010
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 #include "TStreamerInfo.h"
00013 #include "TStreamerInfoActions.h"
00014 #include "TROOT.h"
00015 #include "TStreamerElement.h"
00016 #include "TVirtualMutex.h"
00017 #include "TInterpreter.h"
00018 #include "TError.h"
00019 #include "TVirtualArray.h"
00020 #include "TBufferFile.h"
00021 #include "TMemberStreamer.h"
00022 #include "TError.h"
00023 #include "TClassEdit.h"
00024 #include "TVirtualCollectionIterators.h"
00025 
00026 static const Int_t kRegrouped = TStreamerInfo::kOffsetL;
00027 
00028 // More possible optimizations:
00029 // Avoid call the virtual version of TBuffer::ReadInt and co.
00030 // Merge the Reading of the version and the looking up or the StreamerInfo
00031 // Avoid if (bytecnt) inside the CheckByteCount routines and avoid multiple (mostly useless nested calls)
00032 // Try to avoid if statement on onfile class being set (TBufferFile::ReadClassBuffer).
00033 
00034 using namespace TStreamerInfoActions;
00035 
00036 namespace TStreamerInfoActions 
00037 {
00038    void TConfiguration::AddToOffset(Int_t delta)
00039    {
00040       // Add the (potentially negative) delta to all the configuration's offset.  This is used by
00041       // TBranchElement in the case of split sub-object.
00042 
00043       fOffset += delta;
00044    }
00045 
00046    void TConfiguredAction::PrintDebug(TBuffer &buf, void *addr) const
00047    {
00048       // Inform the user what we are about to stream.
00049 
00050       // Idea, we should find a way to print the name of the function
00051       if (fConfiguration) fConfiguration->PrintDebug(buf,addr);
00052    }
00053 
00054    void TConfiguration::Print() const
00055    {
00056       // Inform the user what we are about to stream.
00057 
00058       // Idea: We should print the name of the action function.
00059       TStreamerInfo *info = (TStreamerInfo*)fInfo;
00060       TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
00061 
00062       printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
00063              " %s, offset=%d\n",
00064              info->GetClass()->GetName(), aElement->GetName(), fElemId, info->GetTypes()[fElemId],
00065              aElement->ClassName(), fOffset);
00066    }
00067 
00068    void TConfiguration::PrintDebug(TBuffer &buf, void *addr) const
00069    {
00070       // Inform the user what we are about to stream.
00071 
00072       if (gDebug > 1) {
00073          // Idea: We should print the name of the action function.
00074          TStreamerInfo *info = (TStreamerInfo*)fInfo;
00075          TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
00076 
00077          printf("StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
00078                 " %s, bufpos=%d, arr=%p, offset=%d\n",
00079                 info->GetClass()->GetName(), aElement->GetName(), fElemId, info->GetTypes()[fElemId],
00080                 aElement->ClassName(), buf.Length(), addr, fOffset);
00081       }
00082    }
00083 
00084    void TLoopConfiguration::Print() const
00085    {
00086       // Inform the user what we are about to stream.
00087 
00088       printf("TLoopConfiguration: unconfigured\n");
00089    }
00090    
00091 
00092    struct TGenericConfiguration : TConfiguration {
00093       // Configuration of action using the legacy code.
00094       // Mostly to cancel out the PrintDebug.
00095    public:
00096       TGenericConfiguration(TVirtualStreamerInfo *info, UInt_t id, Int_t offset = 0) : TConfiguration(info,id,offset) {};
00097       void PrintDebug(TBuffer &, void *) const {
00098          // Since we call the old code, it will print the debug statement.
00099       }
00100    };
00101 
00102 
00103    Int_t GenericAction(TBuffer &buf, void *addr, const TConfiguration *config) 
00104    {
00105       char *obj = (char*)addr;
00106       TGenericConfiguration *conf = (TGenericConfiguration*)config;
00107       return ((TStreamerInfo*)conf->fInfo)->ReadBuffer(buf, &obj, conf->fElemId, 1, config->fOffset, 2);
00108    }
00109 
00110    template <typename T> 
00111    inline Int_t ReadBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
00112    {
00113       T *x = (T*)( ((char*)addr) + config->fOffset );
00114       // Idea: Implement buf.ReadBasic/Primitive to avoid the return value
00115       buf >> *x;
00116       return 0;
00117    }
00118 
00119    class TConfWithFactor : public TConfiguration {
00120       // Configuration object for the Float16/Double32 where a factor has been specified.
00121    public:
00122       Double_t fFactor;
00123       Double_t fXmin;
00124       TConfWithFactor(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, Double_t factor, Double_t xmin) : TConfiguration(info,id,offset),fFactor(factor),fXmin(xmin) {};
00125       virtual TConfiguration *Copy() { return new TConfWithFactor(*this); }
00126    };
00127 
00128    template <typename T>
00129    inline Int_t ReadBasicType_WithFactor(TBuffer &buf, void *addr, const TConfiguration *config)
00130    {
00131       // Stream a Float16 or Double32 where a factor has been specified.
00132       //a range was specified. We read an integer and convert it back to a double.
00133 
00134       TConfWithFactor *conf = (TConfWithFactor *)config;
00135       buf.ReadWithFactor((T*)( ((char*)addr) + config->fOffset ), conf->fFactor, conf->fXmin);
00136       return 0;
00137    }
00138 
00139    class TConfNoFactor : public TConfiguration {
00140       // Configuration object for the Float16/Double32 where a factor has been specified.
00141    public:
00142       Int_t fNbits;
00143       TConfNoFactor(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, Int_t nbits) : TConfiguration(info,id,offset),fNbits(nbits) {};
00144       virtual TConfiguration *Copy() { return new TConfNoFactor(*this); }
00145    };
00146 
00147    template <typename T>
00148    inline Int_t ReadBasicType_NoFactor(TBuffer &buf, void *addr, const TConfiguration *config)
00149    {
00150       // Stream a Float16 or Double32 where a factor has not been specified.
00151 
00152       TConfNoFactor *conf = (TConfNoFactor *)config;
00153       Int_t nbits = conf->fNbits;
00154 
00155       buf.ReadWithNbits( (T*)( ((char*)addr) + config->fOffset ), nbits );
00156       return 0;
00157    }
00158 
00159    inline Int_t ReadTString(TBuffer &buf, void *addr, const TConfiguration *config) 
00160    {
00161       // Read in a TString object.
00162 
00163       // Idea: We could separate the TString Streamer in its two parts and 
00164       // avoid the if (buf.IsReading()) and try having it inlined.
00165       ((TString*)(((char*)addr)+config->fOffset))->TString::Streamer(buf);
00166       return 0;
00167    }
00168 
00169    inline Int_t ReadTObject(TBuffer &buf, void *addr, const TConfiguration *config) 
00170    {
00171       // Read in a TObject object part.
00172 
00173       // Idea: We could separate the TObject Streamer in its two parts and 
00174       // avoid the if (buf.IsReading()).
00175       ((TObject*)(((char*)addr)+config->fOffset))->TObject::Streamer(buf);
00176       return 0;
00177    }
00178 
00179    inline Int_t ReadTNamed(TBuffer &buf, void *addr, const TConfiguration *config) 
00180    {
00181       // Read in a TNamed object part.
00182       // Since the TNamed streamer is solely delegating back to the StreamerInfo we 
00183       // can skip the streamer.
00184 
00185       // Idea: We could extract the code from ReadClassBuffer and avoid one function
00186       // code.
00187       static const TClass *TNamed_cl = TNamed::Class();
00188       return buf.ReadClassBuffer(TNamed_cl,(((char*)addr)+config->fOffset));
00189    }
00190 
00191    class TConfigSTL : public TConfiguration {
00192       // Configuration object for the kSTL case
00193    private:
00194       void Init() {
00195          TVirtualCollectionProxy *proxy = fNewClass->GetCollectionProxy();
00196          if (proxy) {
00197             fCreateIterators = proxy->GetFunctionCreateIterators();
00198             fCopyIterator = proxy->GetFunctionCopyIterator();
00199             fDeleteIterator = proxy->GetFunctionDeleteIterator();
00200             fDeleteTwoIterators = proxy->GetFunctionDeleteTwoIterators();
00201          }
00202       }
00203 
00204    public:
00205       TClass          *fOldClass;   // Class of the content on file
00206       TClass          *fNewClass;   // Class of the content in memory.
00207       TMemberStreamer *fStreamer;
00208       const char      *fTypeName;   // Type name of the member as typed by ther user.
00209       bool             fIsSTLBase;  // aElement->IsBase() && aElement->IsA()!=TStreamerBase::Class()
00210 
00211       TVirtualCollectionProxy::CreateIterators_t    fCreateIterators;
00212       TVirtualCollectionProxy::CopyIterator_t       fCopyIterator;
00213       TVirtualCollectionProxy::DeleteIterator_t     fDeleteIterator;
00214       TVirtualCollectionProxy::DeleteTwoIterators_t fDeleteTwoIterators;
00215 
00216       TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, UInt_t length, TClass *oldClass, const char *type_name, Bool_t isbase) : 
00217          TConfiguration(info,id,offset,length), fOldClass(oldClass), fNewClass(oldClass), fTypeName(type_name), fIsSTLBase(isbase),
00218          fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
00219 
00220       TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, const char *type_name, Bool_t isbase) : 
00221          TConfiguration(info,id,offset,length), fOldClass(oldClass), fNewClass(newClass), fTypeName(type_name), fIsSTLBase(isbase),
00222          fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
00223 
00224       TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, UInt_t length, TClass *oldClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) : 
00225          TConfiguration(info,id,offset,length), fOldClass(oldClass), fNewClass(oldClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
00226          fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
00227 
00228       TConfigSTL(TVirtualStreamerInfo *info, UInt_t id, Int_t offset, UInt_t length, TClass *oldClass, TClass *newClass, TMemberStreamer* streamer, const char *type_name, Bool_t isbase) : 
00229          TConfiguration(info,id,offset,length), fOldClass(oldClass), fNewClass(newClass), fStreamer(streamer), fTypeName(type_name), fIsSTLBase(isbase),
00230          fCreateIterators(0), fCopyIterator(0), fDeleteIterator(0), fDeleteTwoIterators(0) { Init(); }
00231 
00232       virtual TConfiguration *Copy() { return new TConfigSTL(*this); }
00233    };
00234 
00235    class TVectorLoopConfig : public TLoopConfiguration {
00236       // Base class of the Configurations used in member wise streaming.
00237    protected:
00238    public:
00239       Long_t fIncrement; // Either a value to increase the cursor by and 
00240    public:
00241       TVectorLoopConfig(Long_t increment) : fIncrement(increment) {};
00242       //virtual void PrintDebug(TBuffer &buffer, void *);
00243       virtual ~TVectorLoopConfig() {};
00244       void Print() const
00245       {
00246          printf("TVectorLoopConfig: increment=%ld\n",fIncrement);
00247       }
00248 
00249       void* GetFirstAddress(void *start, const void * /* end */) const
00250       {
00251          // Return the address of the first element of the collection.
00252          
00253          return start;
00254       }
00255 
00256       virtual TLoopConfiguration* Copy() { return new TVectorLoopConfig(*this); }
00257    };
00258 
00259    class TAssocLoopConfig : public TLoopConfiguration {
00260       // Base class of the Configurations used in member wise streaming.
00261    protected:
00262    public:
00263       TVirtualCollectionProxy *fProxy;
00264    public:
00265       TAssocLoopConfig(TVirtualCollectionProxy *proxy) : fProxy(proxy) {};
00266       //virtual void PrintDebug(TBuffer &buffer, void *);
00267       virtual ~TAssocLoopConfig() {};
00268       void Print() const
00269       {
00270          printf("TAssocLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
00271       }
00272       virtual TLoopConfiguration* Copy() { return new TAssocLoopConfig(*this); }
00273 
00274       void* GetFirstAddress(void *start, const void * /* end */) const
00275       {
00276          // Return the address of the first element of the collection.
00277          
00278          R__ASSERT(0);
00279 //         char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
00280 //         void *iter = genloopconfig->fCopyIterator(&iterator,start_collection);
00281 //         arr0 = genloopconfig->fNext(iter,end_collection);
00282 //         if (iter != &iterator[0]) {
00283 //            genloopconfig->fDeleteIterator(iter);
00284 //         }
00285          return start;
00286       }
00287    };
00288 
00289    class TGenericLoopConfig : public TLoopConfiguration {
00290       // Configuration object for the generic case of member wise streaming looping.
00291    private:
00292       void Init() {
00293          if (fProxy) {
00294             if (fProxy->HasPointers()) {
00295                fNext = TVirtualCollectionPtrIterators::Next;
00296                fCopyIterator = TVirtualCollectionPtrIterators::CopyIterator;
00297                fDeleteIterator = TVirtualCollectionPtrIterators::DeleteIterator;               
00298             } else {
00299                fNext = fProxy->GetFunctionNext();
00300                fCopyIterator = fProxy->GetFunctionCopyIterator();
00301                fDeleteIterator = fProxy->GetFunctionDeleteIterator();
00302             }
00303          }
00304       }
00305    public:
00306       TVirtualCollectionProxy                      *fProxy;
00307       TVirtualCollectionProxy::Next_t               fNext;
00308       TVirtualCollectionProxy::CopyIterator_t       fCopyIterator;
00309       TVirtualCollectionProxy::DeleteIterator_t     fDeleteIterator;
00310       
00311       TGenericLoopConfig(TVirtualCollectionProxy *proxy) : fProxy(proxy), fNext(0), fCopyIterator(0), fDeleteIterator(0)
00312       { 
00313          Init(); 
00314       }
00315       virtual ~TGenericLoopConfig() {};
00316       void Print() const
00317       {
00318          printf("TGenericLoopConfig: proxy=%s\n",fProxy->GetCollectionClass()->GetName());
00319       }
00320       virtual TLoopConfiguration* Copy() { return new TGenericLoopConfig(*this); }
00321 
00322       void* GetFirstAddress(void *start_collection, const void *end_collection) const
00323       {
00324          // Return the address of the first element of the collection.
00325          
00326          char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
00327          void *iter = fCopyIterator(&iterator,start_collection);
00328          void *arr0 = fNext(iter,end_collection);
00329          if (iter != &iterator[0]) {
00330             fDeleteIterator(iter);
00331          }
00332          return arr0;
00333       }
00334    };
00335 
00336    inline void ReadSTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
00337    {
00338       // Collection was saved member-wise
00339 
00340       TConfigSTL *config = (TConfigSTL*)conf;
00341       vers &= ~( TBufferFile::kStreamedMemberWise );
00342 
00343       if( vers >= 8 ) {
00344 
00345          TClass *oldClass = config->fOldClass;   
00346 
00347          TClass *valueClass = oldClass->GetCollectionProxy()->GetValueClass();
00348          UInt_t startDummy, countDummy;
00349          Version_t vClVersion = buf.ReadVersion( &startDummy, &countDummy, valueClass );
00350 
00351          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00352          TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
00353          Int_t nobjects;
00354          buf.ReadInt(nobjects);
00355          void* alternative = oldProxy->Allocate(nobjects,true);
00356          if (nobjects) {
00357             TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
00358 
00359             char startbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00360             char endbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00361             void *begin = &(startbuf[0]);
00362             void *end = &(endbuf[0]);
00363             config->fCreateIterators(alternative, &begin, &end );
00364             // We can not get here with a split vector of pointer, so we can indeed assume
00365             // that actions->fConfiguration != null.
00366             buf.ReadSequence(*actions, begin, end);
00367             if (begin != &(startbuf[0])) {
00368                // assert(end != endbuf);
00369                config->fDeleteTwoIterators(begin,end);
00370             }
00371          }
00372          oldProxy->Commit(alternative);
00373 
00374       } else {
00375 
00376          TClass *oldClass = config->fOldClass;
00377 
00378          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00379 
00380          TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)addr );
00381          Int_t nobjects;
00382          buf.ReadInt(nobjects);
00383          void* env = oldProxy->Allocate(nobjects,true);
00384 
00385          if (nobjects || vers < 7 ) {
00386             // coverity[dereference] since this is a member streaming action by definition the collection contains objects. 
00387             TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
00388 
00389             if (subinfo->IsOptimized()) {
00390                subinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00391                subinfo->Compile();
00392             }
00393             subinfo->ReadBuffer(buf, *oldProxy, -1, nobjects, 0, 1);
00394          }
00395          oldProxy->Commit(env);
00396       }
00397    }
00398 
00399    inline void ReadArraySTLMemberWiseSameClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
00400    {
00401       // Collection was saved member-wise
00402 
00403       TConfigSTL *config = (TConfigSTL*)conf;
00404       vers &= ~( TBufferFile::kStreamedMemberWise );
00405 
00406       if( vers >= 8 ) {
00407 
00408          TClass *oldClass = config->fOldClass;   
00409 
00410          TClass *valueClass = oldClass->GetCollectionProxy()->GetValueClass();
00411          UInt_t startDummy, countDummy;
00412          Version_t vClVersion = buf.ReadVersion( &startDummy, &countDummy, valueClass );
00413 
00414          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00415          TActionSequence *actions = oldProxy->GetReadMemberWiseActions( vClVersion );
00416 
00417          int objectSize = oldClass->Size();
00418          char *obj = (char*)addr;
00419          char *endobj = obj + conf->fLength*objectSize;
00420 
00421          for(; obj<endobj; obj+=objectSize) {            
00422             Int_t nobjects;
00423             buf.ReadInt(nobjects);
00424             TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
00425             void* alternative = oldProxy->Allocate(nobjects,true);
00426             if (nobjects) {
00427                char startbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00428                char endbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00429                void *begin = &(startbuf[0]);
00430                void *end = &(endbuf[0]);
00431                config->fCreateIterators(alternative, &begin, &end );
00432                // We can not get here with a split vector of pointer, so we can indeed assume
00433                // that actions->fConfiguration != null.
00434                buf.ReadSequence(*actions, begin, end);
00435                if (begin != &(startbuf[0])) {
00436                   // assert(end != endbuf);
00437                   config->fDeleteTwoIterators(begin,end);
00438                }
00439             }
00440             oldProxy->Commit(alternative);
00441          }
00442 
00443       } else {
00444 
00445          TClass *oldClass = config->fOldClass;
00446 
00447          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00448 
00449          int objectSize = oldClass->Size();
00450          char *obj = (char*)addr;
00451          char *endobj = obj + conf->fLength*objectSize;
00452 
00453          for(; obj<endobj; obj+=objectSize) {            
00454             TVirtualCollectionProxy::TPushPop helper( oldProxy, (char*)obj );
00455             Int_t nobjects;
00456             buf.ReadInt(nobjects);
00457             void* env = oldProxy->Allocate(nobjects,true);
00458 
00459             if (nobjects || vers < 7 ) {
00460                // coverity[dereference] since this is a member streaming action by definition the collection contains objects. 
00461                TStreamerInfo *subinfo = (TStreamerInfo*)oldProxy->GetValueClass()->GetStreamerInfo( 0 );
00462 
00463                if (subinfo->IsOptimized()) {
00464                   subinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00465                   subinfo->Compile();
00466                }
00467                subinfo->ReadBuffer(buf, *oldProxy, -1, nobjects, 0, 1);
00468             }
00469             oldProxy->Commit(env);
00470          }
00471       }
00472    }
00473 
00474    inline void ReadSTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
00475    {
00476       // Collection was saved member-wise
00477 
00478       TConfigSTL *config = (TConfigSTL*)conf;
00479 
00480       vers &= ~( TBufferFile::kStreamedMemberWise );
00481 
00482       TClass *newClass = config->fNewClass;
00483       TClass *oldClass = config->fOldClass;
00484 
00485       if( vers < 8 ) {
00486          Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
00487                vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
00488       } else {
00489 
00490          UInt_t startDummy, countDummy;
00491 
00492          Version_t vClVersion = buf.ReadVersion( &startDummy, &countDummy, oldClass->GetCollectionProxy()->GetValueClass() );
00493 
00494          TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
00495          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00496 
00497          TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)addr );
00498          Int_t nobjects;
00499          buf.ReadInt(nobjects);
00500          void* alternative = newProxy->Allocate(nobjects,true);
00501          if (nobjects) {
00502             TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
00503             char startbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00504             char endbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00505             void *begin = &(startbuf[0]);
00506             void *end = &(endbuf[0]);
00507             config->fCreateIterators( alternative, &begin, &end );
00508             // We can not get here with a split vector of pointer, so we can indeed assume
00509             // that actions->fConfiguration != null.
00510             buf.ReadSequence(*actions, begin, end);
00511             if (begin != &(startbuf[0])) {
00512                // assert(end != endbuf);
00513                config->fDeleteTwoIterators(begin,end);
00514             }
00515          }
00516          newProxy->Commit(alternative);
00517       }
00518    }
00519 
00520    inline void ReadArraySTLMemberWiseChangedClass(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers)
00521    {
00522       // Collection was saved member-wise
00523 
00524       TConfigSTL *config = (TConfigSTL*)conf;
00525 
00526       vers &= ~( TBufferFile::kStreamedMemberWise );
00527 
00528       TClass *newClass = config->fNewClass;
00529       TClass *oldClass = config->fOldClass;
00530 
00531       if( vers < 8 ) {
00532          Error( "ReadSTLMemberWiseChangedClass", "Unfortunately, version %d of TStreamerInfo (used in %s) did not record enough information to convert a %s into a %s.",
00533                vers, buf.GetParent() ? buf.GetParent()->GetName() : "memory/socket", oldClass->GetName(), newClass->GetName() );
00534       } else {
00535 
00536          UInt_t startDummy, countDummy;
00537 
00538          Version_t vClVersion = buf.ReadVersion( &startDummy, &countDummy, oldClass->GetCollectionProxy()->GetValueClass() );
00539 
00540          TVirtualCollectionProxy *newProxy = newClass->GetCollectionProxy();
00541          TVirtualCollectionProxy *oldProxy = oldClass->GetCollectionProxy();
00542 
00543          int objectSize = newClass->Size();
00544          char *obj = (char*)addr;
00545          char *endobj = obj + conf->fLength*objectSize;
00546 
00547          for(; obj<endobj; obj+=objectSize) {            
00548             TVirtualCollectionProxy::TPushPop helper( newProxy, (char*)obj );
00549             Int_t nobjects;
00550             buf.ReadInt(nobjects);
00551             void* alternative = newProxy->Allocate(nobjects,true);
00552             if (nobjects) {
00553                TActionSequence *actions = newProxy->GetConversionReadMemberWiseActions( oldProxy->GetValueClass(), vClVersion );
00554                char startbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00555                char endbuf[TVirtualCollectionProxy::fgIteratorArenaSize];
00556                void *begin = &(startbuf[0]);
00557                void *end = &(endbuf[0]);
00558                config->fCreateIterators( alternative, &begin, &end );
00559                // We can not get here with a split vector of pointer, so we can indeed assume
00560                // that actions->fConfiguration != null.
00561                buf.ReadSequence(*actions, begin, end);
00562                if (begin != &(startbuf[0])) {
00563                   // assert(end != endbuf);
00564                   config->fDeleteTwoIterators(begin,end);
00565                }
00566             }
00567             newProxy->Commit(alternative);
00568          }
00569       }
00570    }
00571 
00572 
00573    inline void ReadSTLObjectWiseFastArray(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
00574    {
00575       TConfigSTL *config = (TConfigSTL*)conf;
00576       // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
00577       buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
00578    }
00579    inline void ReadSTLObjectWiseStreamer(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t /* vers */, UInt_t /* start */)
00580    {
00581       TConfigSTL *config = (TConfigSTL*)conf;
00582       (*config->fStreamer)(buf,addr,conf->fLength);
00583    }
00584    inline void ReadSTLObjectWiseFastArrayV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
00585    {
00586       // case of old TStreamerInfo
00587 
00588       TConfigSTL *config = (TConfigSTL*)conf;
00589       //  Backward compatibility. Some TStreamerElement's where without
00590       //  Streamer but were not removed from element list
00591       if (config->fIsSTLBase || vers == 0) {
00592          buf.SetBufferOffset(start);  //there is no byte count
00593       }
00594       // Idea: This needs to be unrolled, it currently calls the TGenCollectionStreamer ....
00595       buf.ReadFastArray(addr,config->fNewClass,conf->fLength,(TMemberStreamer*)0,config->fOldClass);
00596    }
00597    inline void ReadSTLObjectWiseStreamerV2(TBuffer &buf, void *addr, const TConfiguration *conf, Version_t vers, UInt_t start)
00598    {
00599       // case of old TStreamerInfo
00600 
00601       TConfigSTL *config = (TConfigSTL*)conf;
00602       //  Backward compatibility. Some TStreamerElement's where without
00603       //  Streamer but were not removed from element list
00604       if (config->fIsSTLBase || vers == 0) {
00605          buf.SetBufferOffset(start);  //there is no byte count
00606       }
00607       (*config->fStreamer)(buf,addr,conf->fLength);
00608    }
00609 
00610    template <void (*memberwise)(TBuffer&,void *,const TConfiguration*, Version_t), 
00611              void (*objectwise)(TBuffer&,void *,const TConfiguration*, Version_t, UInt_t)>
00612    inline Int_t ReadSTL(TBuffer &buf, void *addr, const TConfiguration *conf)
00613    {
00614       TConfigSTL *config = (TConfigSTL*)conf;
00615       UInt_t start, count;
00616       Version_t vers = buf.ReadVersion(&start, &count, config->fOldClass);
00617       if ( vers & TBufferFile::kStreamedMemberWise ) {
00618          memberwise(buf,((char*)addr)+config->fOffset,config, vers);
00619       } else {
00620          objectwise(buf,((char*)addr)+config->fOffset,config, vers, start);
00621       }
00622       buf.CheckByteCount(start,count,config->fTypeName);
00623       return 0;
00624    }
00625 
00626    template <typename From, typename To>
00627    inline Int_t ConvertBasicType(TBuffer &buf, void *addr, const TConfiguration *config)
00628    {
00629       // Simple conversion from a 'From' on disk to a 'To' in memory.
00630       From temp;
00631       buf >> temp;
00632       *(To*)( ((char*)addr) + config->fOffset ) = (To)temp;
00633       return 0;
00634    }
00635 
00636    class TConfigurationUseCache : public TConfiguration {
00637       // Configuration object for the UseCache case.
00638    public:
00639       TConfiguredAction fAction;
00640       Bool_t            fNeedRepeat;
00641       
00642       TConfigurationUseCache(TVirtualStreamerInfo *info, TConfiguredAction &action, Bool_t repeat) : 
00643               TConfiguration(info,action.fConfiguration->fElemId,action.fConfiguration->fOffset),fAction(action),fNeedRepeat(repeat) {};
00644       virtual void PrintDebug(TBuffer &b, void *addr) const
00645       {
00646          if (gDebug > 1) {
00647             // Idea: We should print the name of the action function.
00648             TStreamerInfo *info = (TStreamerInfo*)fInfo;
00649             TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[fElemId];
00650             fprintf(stdout,"StreamerInfoAction, class:%s, name=%s, fType[%d]=%d,"
00651                    " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
00652                    info->GetClass()->GetName(),aElement->GetName(),fElemId,info->GetTypes()[fElemId],
00653                    aElement->ClassName(),b.Length(),addr, 0,b.PeekDataCache()->GetObjectAt(0));
00654          }            
00655 
00656       }
00657       virtual ~TConfigurationUseCache() {};
00658       virtual TConfiguration *Copy() { 
00659          TConfigurationUseCache *copy = new TConfigurationUseCache(*this);
00660          fAction.fConfiguration = copy->fAction.fConfiguration->Copy(); // since the previous allocation did a 'move' of fAction we need to fix it.
00661          return copy;
00662       }
00663    };
00664 
00665 
00666    inline Int_t UseCache(TBuffer &b, void *addr, const TConfiguration *conf) 
00667    {
00668       TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
00669       
00670       Int_t bufpos = b.Length();
00671       TVirtualArray *cached = b.PeekDataCache();
00672       if (cached==0) {
00673          TStreamerElement *aElement = (TStreamerElement*)conf->fInfo->GetElems()[conf->fElemId];
00674          TStreamerInfo *info = (TStreamerInfo*)conf->fInfo;
00675          Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
00676          char *ptr = (char*)addr;
00677          info->ReadBufferSkip(b,&ptr,config->fElemId,info->GetTypes()[config->fElemId]+TStreamerInfo::kSkip,aElement,1,0);
00678       } else {
00679          config->fAction(b, (*cached)[0]);
00680       }
00681       // Idea: Factor out this 'if' to a UseCacheRepeat function
00682       if (config->fNeedRepeat) {
00683          b.SetBufferOffset(bufpos); 
00684       }
00685       return 0;
00686    }
00687 
00688    inline Int_t UseCacheVectorPtrLoop(TBuffer &b, void *start, const void *end, const TConfiguration *conf) 
00689    {
00690       TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
00691       Int_t bufpos = b.Length();
00692 
00693       TVirtualArray *cached = b.PeekDataCache();
00694       if (cached==0) {
00695          TStreamerElement *aElement = (TStreamerElement*)config->fInfo->GetElems()[config->fElemId];
00696          TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
00697          Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
00698          char *ptr = (char*)start;
00699          UInt_t n = (((void**)end)-((void**)start));
00700          info->ReadBufferSkip(b,&ptr,config->fElemId,info->GetTypes()[config->fElemId]+TStreamerInfo::kSkip,aElement,n,0);
00701       } else {
00702          TVectorLoopConfig cached_config( cached->fClass->Size() );
00703          void *cached_start = (*cached)[0];
00704          void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
00705          config->fAction(b,cached_start,cached_end,&cached_config);         
00706       }
00707       // Idea: Factor out this 'if' to a UseCacheRepeat function
00708       if (config->fNeedRepeat) {
00709          b.SetBufferOffset(bufpos); 
00710       }
00711       return 0;
00712    }
00713 
00714    inline Int_t UseCacheVectorLoop(TBuffer &b, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *conf) 
00715    {
00716       TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
00717 
00718       Int_t bufpos = b.Length();
00719       TVirtualArray *cached = b.PeekDataCache();
00720       if (cached==0) {
00721          TStreamerElement *aElement = (TStreamerElement*)config->fInfo->GetElems()[config->fElemId];
00722          TStreamerInfo *info = (TStreamerInfo*)config->fInfo;         
00723          Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
00724          char *ptr = (char*)start;
00725          UInt_t n = (((char*)end)-((char*)start))/((TVectorLoopConfig*)loopconf)->fIncrement;
00726          info->ReadBufferSkip(b,&ptr,config->fElemId,info->GetTypes()[config->fElemId]+TStreamerInfo::kSkip,aElement,n,0);
00727       } else {
00728          TVectorLoopConfig cached_config( cached->fClass->Size() );
00729          void *cached_start = (*cached)[0];
00730          void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
00731          config->fAction(b,cached_start,cached_end,&cached_config);
00732       }
00733       // Idea: Factor out this 'if' to a UseCacheRepeat function
00734       if (config->fNeedRepeat) {
00735          b.SetBufferOffset(bufpos); 
00736       }
00737       return 0;
00738    }
00739 
00740    inline Int_t UseCacheGenericCollection(TBuffer &b, void *, const void *, const TLoopConfiguration *loopconfig, const TConfiguration *conf) 
00741    {
00742       TConfigurationUseCache *config = (TConfigurationUseCache*)conf;
00743 
00744       Int_t bufpos = b.Length();
00745       TVirtualArray *cached = b.PeekDataCache();
00746       if (cached==0) {
00747          TStreamerElement *aElement = (TStreamerElement*)config->fInfo->GetElems()[config->fElemId];
00748          TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
00749          
00750          TVirtualCollectionProxy *proxy = ((TGenericLoopConfig*)loopconfig)->fProxy;
00751          Warning("ReadBuffer","Skipping %s::%s because the cache is missing.",info->GetName(),aElement->GetName());
00752          UInt_t n = proxy->Size();
00753          info->ReadBufferSkip(b, *proxy,config->fElemId,info->GetTypes()[config->fElemId]+TStreamerInfo::kSkip,aElement,n,0);
00754       } else {
00755          TVectorLoopConfig cached_config( cached->fClass->Size() );
00756          void *cached_start = (*cached)[0];
00757          void *cached_end = ((char*)cached_start) + cached->fSize * cached_config.fIncrement;
00758          config->fAction(b,cached_start,cached_end,&cached_config);
00759       }
00760       // Idea: Factor out this 'if' to a UseCacheRepeat function
00761       if (config->fNeedRepeat) {
00762          b.SetBufferOffset(bufpos); 
00763       }
00764       return 0;
00765    }
00766 
00767    // Support for collections.
00768 
00769    Int_t GenericVectorPtrAction(TBuffer &buf, void *iter, const void *end, const TConfiguration *config) 
00770    {
00771       Int_t n = ( ((void**)end) - ((void**)iter) );
00772       char **arr = (char**)iter;
00773       return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arr, config->fElemId, n, config->fOffset, 1|2 );
00774    }
00775 
00776    Int_t ReadVectorBase(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config) 
00777    {
00778       // Well the implementation is non trivial since we do not have a proxy for the container of _only_ the base class.  For now
00779       // punt.
00780 
00781       UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00782       UInt_t n = (((char*)end)-((char*)start))/incr;
00783       char **arrptr = new char*[n];
00784       UInt_t i = 0;
00785       for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
00786          arrptr[i] = (char*)iter;
00787       }
00788       ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, config->fElemId, n, config->fOffset, 1|2 );
00789       delete [] arrptr;
00790 
00791 //      // Idea: need to cache this result!
00792 //      TStreamerInfo *info = (TStreamerInfo*)config->fInfo;
00793 //      TStreamerElement *aElement = (TStreamerElement*)info->GetElems()[config->fElemId];
00794 //      Int_t clversion = ((TStreamerBase*)aElement)->GetBaseVersion();
00795 //      TClass *cle = aElement->GetNewBaseClass();
00796 //      TSequence *actions = CreateReadMemberWiseActions( cle->GetStreamerInfo(clversion), ???? );
00797 //      actions->ReadBuffer(b,start,end);
00798 //      delete actions;
00799 
00800 //      const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00801 //      for(void *iter = start; iter != end; iter = (char*)iter + incr ) 
00802 //      {
00803 //         Int_t clversion = ((TStreamerBase*)aElement)->GetBaseVersion();
00804 //         ((TStreamerInfo*)cle->GetStreamerInfo(clversion))->ReadBuffer(b,arr,-1,narr,ioffset,arrayMode);
00805 //
00806 //         ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)&iter, config->fElemId, 1, config->fOffset, 1|2 );
00807 //      }
00808       return 0;
00809    }
00810 
00811    Int_t ReadVectorWrapping(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config) 
00812    {
00813       // Well the implementation is non trivial. For now punt.
00814 
00815       UInt_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00816       UInt_t n = (((char*)end)-((char*)start))/incr;
00817       char **arrptr = new char*[n];
00818       UInt_t i = 0;
00819       for(void *iter = start; iter != end; iter = (char*)iter + incr, ++i ) {
00820          arrptr[i] = (char*)iter;
00821       }
00822       ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, arrptr, config->fElemId, n, config->fOffset, 1|2 );
00823       delete [] arrptr;
00824       return 0;
00825    }
00826 
00827    Int_t GenericVectorAction(TBuffer &buf, void *start, const void *end, const TLoopConfiguration * loopconfig, const TConfiguration *config) 
00828    {
00829       const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00830       for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
00831          void **iter_ptr = &iter;
00832          ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, (char**)iter_ptr, config->fElemId, 1, config->fOffset, 1|2 );
00833       }
00834       return 0;
00835    }
00836 
00837    Int_t GenericCollectionAction(TBuffer &buf, void *, const void *, const TLoopConfiguration * loopconf, const TConfiguration *config) 
00838    {
00839       TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
00840       TVirtualCollectionProxy *proxy = loopconfig->fProxy;
00841       return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, config->fElemId, proxy->Size(), config->fOffset, 1|2 );
00842    }
00843 
00844    Int_t GenericAssocCollectionAction(TBuffer &buf, void *, const void *, const TLoopConfiguration *loopconf, const TConfiguration *config) 
00845    {
00846       TAssocLoopConfig *loopconfig = (TAssocLoopConfig*)loopconf;
00847       TVirtualCollectionProxy *proxy = loopconfig->fProxy;
00848       return ((TStreamerInfo*)config->fInfo)->ReadBuffer(buf, *proxy, config->fElemId, proxy->Size(), config->fOffset, 1|2 );
00849    }
00850 
00851    template <typename T> 
00852    Int_t ReadBasicTypeVectorLoop(TBuffer &buf, void *iter, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config)
00853    {
00854       const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00855       iter = (char*)iter + config->fOffset;
00856       end = (char*)end + config->fOffset;
00857       for(; iter != end; iter = (char*)iter + incr ) {
00858          T *x = (T*) ((char*) iter);
00859          buf >> *x;
00860       }
00861       return 0;
00862    }
00863 
00864    template <typename T> 
00865    Int_t ReadBasicTypeGenericLoop(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config)
00866    {
00867       TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
00868 
00869       // const Int_t offset = config->fOffset;
00870       Next_t next = loopconfig->fNext;
00871       const Int_t offset = config->fOffset;
00872 
00873       char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
00874       void *iter = loopconfig->fCopyIterator(iterator,start);
00875       void *addr;
00876       while( (addr = next(iter,end)) ) {
00877          T *x =  (T*)( ((char*)addr) + offset );
00878          buf >> *x;
00879       }
00880       if (iter != &iterator[0]) {
00881          loopconfig->fDeleteIterator(iter);
00882       }
00883       return 0;
00884    }
00885 
00886    template <typename T> 
00887    Int_t ReadBasicTypeVectorPtrLoop(TBuffer &buf, void *iter, const void *end, const TConfiguration *config)
00888    {
00889       const Int_t offset = config->fOffset;
00890 
00891       for(; iter != end; iter = (char*)iter + sizeof(void*) ) {
00892          T *x = (T*)( ((char*) (*(void**)iter) ) + offset );
00893          buf >> *x;
00894       }
00895       return 0;
00896    }
00897 
00898    template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
00899    Int_t VectorPtrLooper(TBuffer &buf, void *start, const void *end, const TConfiguration *config) 
00900    {     
00901       for(void *iter = start; iter != end; iter = (char*)iter + sizeof(void*) ) {
00902          action(buf, *(void**)iter, config);
00903       }
00904       return 0;
00905    }
00906 
00907    template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
00908    Int_t VectorLooper(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconfig, const TConfiguration *config) 
00909    {     
00910       const Int_t incr = ((TVectorLoopConfig*)loopconfig)->fIncrement;
00911       //Idea: can we factor out the addition of fOffset
00912       //  iter = (char*)iter + config->fOffset;
00913       for(void *iter = start; iter != end; iter = (char*)iter + incr ) {
00914          action(buf, iter, config);
00915       }
00916       return 0;
00917    }
00918 
00919    template <Int_t (*action)(TBuffer&,void *,const TConfiguration*)>
00920    Int_t GenericLooper(TBuffer &buf, void *start, const void *end, const TLoopConfiguration *loopconf, const TConfiguration *config) 
00921    {
00922       TGenericLoopConfig *loopconfig = (TGenericLoopConfig*)loopconf;
00923 
00924       // const Int_t offset = config->fOffset;
00925       Next_t next = loopconfig->fNext;
00926 
00927       char iterator[TVirtualCollectionProxy::fgIteratorArenaSize];
00928       void *iter = loopconfig->fCopyIterator(&iterator,start);
00929       void *addr;
00930       while( (addr = next(iter,end)) ) {
00931          action(buf, addr, config);
00932       }
00933       if (iter != &iterator[0]) {
00934          loopconfig->fDeleteIterator(iter);
00935       }
00936       return 0;
00937    }
00938 
00939 }
00940 
00941 static TConfiguredAction GetVectorAction(TVirtualStreamerInfo *info, TStreamerElement *element, Int_t type, UInt_t i, Int_t offset)
00942 {
00943    switch (type) {
00944          // read basic types
00945       case TStreamerInfo::kBool:    return TConfiguredAction( ReadBasicTypeVectorLoop<Bool_t>, new TConfiguration(info,i,offset) );    break;
00946       case TStreamerInfo::kChar:    return TConfiguredAction( ReadBasicTypeVectorLoop<Char_t>, new TConfiguration(info,i,offset) );    break;
00947       case TStreamerInfo::kShort:   return TConfiguredAction( ReadBasicTypeVectorLoop<Short_t>, new TConfiguration(info,i,offset) );   break;
00948       case TStreamerInfo::kInt:     return TConfiguredAction( ReadBasicTypeVectorLoop<Int_t>, new TConfiguration(info,i,offset) );     break;
00949       case TStreamerInfo::kLong:    return TConfiguredAction( ReadBasicTypeVectorLoop<Long_t>, new TConfiguration(info,i,offset) );    break;
00950       case TStreamerInfo::kLong64:  return TConfiguredAction( ReadBasicTypeVectorLoop<Long64_t>, new TConfiguration(info,i,offset) );  break;
00951       case TStreamerInfo::kFloat:   return TConfiguredAction( ReadBasicTypeVectorLoop<Float_t>, new TConfiguration(info,i,offset) );   break;
00952       case TStreamerInfo::kDouble:  return TConfiguredAction( ReadBasicTypeVectorLoop<Double_t>, new TConfiguration(info,i,offset) );  break;
00953       case TStreamerInfo::kUChar:   return TConfiguredAction( ReadBasicTypeVectorLoop<UChar_t>, new TConfiguration(info,i,offset) );   break;
00954       case TStreamerInfo::kUShort:  return TConfiguredAction( ReadBasicTypeVectorLoop<UShort_t>, new TConfiguration(info,i,offset) );  break;
00955       case TStreamerInfo::kUInt:    return TConfiguredAction( ReadBasicTypeVectorLoop<UInt_t>, new TConfiguration(info,i,offset) );    break;
00956       case TStreamerInfo::kULong:   return TConfiguredAction( ReadBasicTypeVectorLoop<ULong_t>, new TConfiguration(info,i,offset) );   break;
00957       case TStreamerInfo::kULong64: return TConfiguredAction( ReadBasicTypeVectorLoop<ULong64_t>, new TConfiguration(info,i,offset) ); break;
00958       case TStreamerInfo::kFloat16: {
00959          if (element->GetFactor() != 0) {
00960             return TConfiguredAction( VectorLooper<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,offset,element->GetFactor(),element->GetXmin()) );
00961          } else {
00962             Int_t nbits = (Int_t)element->GetXmin();
00963             if (!nbits) nbits = 12;
00964             return TConfiguredAction( VectorLooper<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,offset,nbits) );               
00965          }
00966          break;
00967       }
00968       case TStreamerInfo::kDouble32: {
00969          if (element->GetFactor() != 0) {
00970             return TConfiguredAction( VectorLooper<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,offset,element->GetFactor(),element->GetXmin()) );
00971          } else {
00972             Int_t nbits = (Int_t)element->GetXmin();
00973             if (!nbits) {
00974                return TConfiguredAction( VectorLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,offset) );
00975             } else {
00976                return TConfiguredAction( VectorLooper<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,offset,nbits) );
00977             }
00978          }
00979          break;
00980       }
00981       case TStreamerInfo::kTNamed:  return TConfiguredAction( VectorLooper<ReadTNamed >, new TConfiguration(info,i,offset) );    break;
00982          // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
00983          // Streamer alltogether.
00984       case TStreamerInfo::kTObject: return TConfiguredAction( VectorLooper<ReadTObject >, new TConfiguration(info,i,offset) );    break;
00985       case TStreamerInfo::kTString: return TConfiguredAction( VectorLooper<ReadTString >, new TConfiguration(info,i,offset) );    break;
00986       case TStreamerInfo::kArtificial:
00987       case TStreamerInfo::kCacheNew:
00988       case TStreamerInfo::kCacheDelete:
00989       case TStreamerInfo::kSTL:  return TConfiguredAction( ReadVectorWrapping, new TConfiguration(info,i,0 /* 0 because we call the legacy code */) ); break;
00990       case TStreamerInfo::kBase: return TConfiguredAction( ReadVectorBase, new TConfiguration(info,i,0 /* 0 because we call the legacy code */) ); break;
00991       default:
00992          return TConfiguredAction( ReadVectorWrapping, new TConfiguration(info,i,0 /* 0 because we call the legacy code */) );
00993          // return TConfiguredAction( GenericVectorAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy->GetCollectionClass(),0,0) );
00994          break;
00995    }
00996    R__ASSERT(0); // We should never be here
00997    return TConfiguredAction();
00998 }
00999 
01000 //______________________________________________________________________________
01001 void TStreamerInfo::Compile()
01002 {
01003    // loop on the TStreamerElement list
01004    // regroup members with same type
01005    // Store predigested information into local arrays. This saves a huge amount
01006    // of time compared to an explicit iteration on all elements.
01007 
01008    R__LOCKGUARD(gCINTMutex);
01009 
01010    // fprintf(stderr,"Running Compile for %s %d %d req=%d,%d\n",GetName(),fClassVersion,fOptimized,CanOptimize(),TestBit(kCannotOptimize));
01011 
01012    // if (IsCompiled() && (!fOptimized || (CanOptimize() && !TestBit(kCannotOptimize)))) return;
01013 
01014    fOptimized = kFALSE;
01015    fNdata = 0;
01016 
01017    TObjArray* infos = (TObjArray*) gROOT->GetListOfStreamerInfo();
01018    if (fNumber >= infos->GetSize()) {
01019       infos->AddAtAndExpand(this, fNumber);
01020    } else {
01021       if (!infos->At(fNumber)) {
01022          infos->AddAt(this, fNumber);
01023       }
01024    }
01025 
01026    delete[] fType;
01027    fType = 0;
01028    delete[] fNewType;
01029    fNewType = 0;
01030    delete[] fOffset;
01031    fOffset = 0;
01032    delete[] fLength;
01033    fLength = 0;
01034    delete[] fElem;
01035    fElem = 0;
01036    delete[] fMethod;
01037    fMethod = 0;
01038    delete[] fComp;
01039    fComp = 0;
01040 
01041    if (fReadObjectWise) {
01042       fReadObjectWise->fActions.clear();
01043    }
01044    Int_t ndata = fElements->GetEntries();
01045 
01046    fOffset = new Int_t[ndata+1];
01047    fType   = new Int_t[ndata+1];
01048 
01049    SetBit(kIsCompiled);
01050    if (!fReadObjectWise) fReadObjectWise = new TStreamerInfoActions::TActionSequence(this,ndata);
01051 
01052    if (!ndata) {
01053       // This may be the case for empty classes (e.g., TAtt3D).
01054       // We still need to properly set the size of emulated classes (i.e. add the virtual table)
01055       if (fClass->TestBit(TClass::kIsEmulation) && fNVirtualInfoLoc!=0) {
01056          fSize = sizeof(TStreamerInfo*);
01057       }
01058       return;
01059    }
01060 
01061 
01062    fComp = new TCompInfo[ndata];
01063    fNewType = new Int_t[ndata];
01064    fLength = new Int_t[ndata];
01065    fElem = new ULong_t[ndata];
01066    fMethod = new ULong_t[ndata];
01067 
01068    TStreamerElement* element;
01069    TStreamerElement* previous = 0;
01070    Int_t keep = -1;
01071    Int_t i;
01072 
01073    if (!CanOptimize()) {
01074       SetBit(kCannotOptimize);
01075    }
01076 
01077    Bool_t isOptimized = kFALSE;
01078 
01079    for (i = 0; i < ndata; ++i) {
01080       element = (TStreamerElement*) fElements->At(i);
01081       if (!element) {
01082          break;
01083       }
01084       if (element->GetType() < 0) {
01085          // -- Skip an ignored TObject base class.
01086          // Note: The only allowed negative value here is -1,
01087          // and signifies that Build() has found a TObject
01088          // base class and TClass::IgnoreTObjectStreamer() was
01089          // called.  In this case the compiled version of the
01090          // elements omits the TObject base class element,
01091          // which has to be compensated for by TTree::Bronch()
01092          // when it is making branches for a split object.
01093          continue;
01094       }
01095       if (TestBit(kCannotOptimize) && element->IsBase()) 
01096       {
01097          // Make sure the StreamerInfo for the base class is also
01098          // not optimized.
01099          TClass *bclass = element->GetClassPointer();
01100          Int_t clversion = ((TStreamerBase*)element)->GetBaseVersion();
01101          TStreamerInfo *binfo = ((TStreamerInfo*)bclass->GetStreamerInfo(clversion));
01102          binfo->SetBit(kCannotOptimize);
01103          if (binfo->IsOptimized())
01104          {
01105             // Optimizing does not work with splitting.
01106             binfo->Compile();
01107          }      
01108       }
01109       Int_t asize = element->GetSize();
01110       if (element->GetArrayLength()) {
01111          asize /= element->GetArrayLength();
01112       }
01113       fType[fNdata] = element->GetType();
01114       fNewType[fNdata] = element->GetNewType();
01115       fOffset[fNdata] = element->GetOffset();
01116       fLength[fNdata] = element->GetArrayLength();
01117       fElem[fNdata] = (ULong_t) element;
01118       fMethod[fNdata] = element->GetMethod();
01119       // try to group consecutive members of the same type
01120       if (!TestBit(kCannotOptimize) 
01121           && (keep >= 0) 
01122           && (element->GetType() < 10) 
01123           && (fType[fNdata] == fNewType[fNdata]) 
01124           && (fMethod[keep] == 0) 
01125           && (element->GetType() > 0) 
01126           && (element->GetArrayDim() == 0) 
01127           && (fType[keep] < kObject) 
01128           && (fType[keep] != kCharStar) /* do not optimize char* */ 
01129           && (element->GetType() == (fType[keep]%kRegrouped)) 
01130           && ((element->GetOffset()-fOffset[keep]) == (fLength[keep])*asize)
01131           && ((fOldVersion<6) || !previous || /* In version of TStreamerInfo less than 6, the Double32_t were merged even if their annotation (aka factor) were different */
01132               ((element->GetFactor() == previous->GetFactor())
01133                && (element->GetXmin() == previous->GetXmin())
01134                && (element->GetXmax() == previous->GetXmax())
01135                )
01136               )
01137           && (element->TestBit(TStreamerElement::kCache) == previous->TestBit(TStreamerElement::kCache))
01138           ) 
01139       {
01140          if (fLength[keep] == 0) {
01141             fLength[keep]++;
01142          }
01143          fLength[keep]++;
01144          fType[keep] = element->GetType() + kRegrouped;
01145          isOptimized = kTRUE;
01146       } else {
01147          if (fNewType[fNdata] != fType[fNdata]) {
01148             if (fNewType[fNdata] > 0) {
01149                if (fType[fNdata] != kCounter) {
01150                   fType[fNdata] += kConv;
01151                }
01152             } else {
01153                if (fType[fNdata] == kCounter) {
01154                   Warning("Compile", "Counter %s should not be skipped from class %s", element->GetName(), GetName());
01155                }
01156                fType[fNdata] += kSkip;
01157             }
01158          }
01159          keep = fNdata;
01160          if (fLength[keep] == 0) {
01161             fLength[keep] = 1;
01162          }
01163          fNdata++;
01164       }
01165       previous = element;
01166    }
01167 
01168    if ( ! isOptimized ) {
01169       if (fReadMemberWise) fReadMemberWise->fActions.clear();
01170       else fReadMemberWise = new TStreamerInfoActions::TActionSequence(this,ndata);
01171    }
01172 
01173    for (i = 0; i < fNdata; ++i) {
01174       element = (TStreamerElement*) fElem[i];
01175       if (!element) {
01176          continue;
01177       }
01178       fComp[i].fClass = element->GetClassPointer();
01179       fComp[i].fNewClass = element->GetNewClass();
01180       fComp[i].fClassName = TString(element->GetTypeName()).Strip(TString::kTrailing, '*');
01181       fComp[i].fStreamer = element->GetStreamer();
01182 
01183       switch (fType[i]) {
01184             // read basic types
01185          case TStreamerInfo::kBool:    fReadObjectWise->AddAction( ReadBasicType<Bool_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01186          case TStreamerInfo::kChar:    fReadObjectWise->AddAction( ReadBasicType<Char_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01187          case TStreamerInfo::kShort:   fReadObjectWise->AddAction( ReadBasicType<Short_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01188          case TStreamerInfo::kInt:     fReadObjectWise->AddAction( ReadBasicType<Int_t>, new TConfiguration(this,i,fOffset[i]) );     break;
01189          case TStreamerInfo::kLong:    fReadObjectWise->AddAction( ReadBasicType<Long_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01190          case TStreamerInfo::kLong64:  fReadObjectWise->AddAction( ReadBasicType<Long64_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01191          case TStreamerInfo::kFloat:   fReadObjectWise->AddAction( ReadBasicType<Float_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01192          case TStreamerInfo::kDouble:  fReadObjectWise->AddAction( ReadBasicType<Double_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01193          case TStreamerInfo::kUChar:   fReadObjectWise->AddAction( ReadBasicType<UChar_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01194          case TStreamerInfo::kUShort:  fReadObjectWise->AddAction( ReadBasicType<UShort_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01195          case TStreamerInfo::kUInt:    fReadObjectWise->AddAction( ReadBasicType<UInt_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01196          case TStreamerInfo::kULong:   fReadObjectWise->AddAction( ReadBasicType<ULong_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01197          case TStreamerInfo::kULong64: fReadObjectWise->AddAction( ReadBasicType<ULong64_t>, new TConfiguration(this,i,fOffset[i]) ); break;
01198          case TStreamerInfo::kFloat16: {
01199             if (element->GetFactor() != 0) {
01200                fReadObjectWise->AddAction( ReadBasicType_WithFactor<float>, new TConfWithFactor(this,i,fOffset[i],element->GetFactor(),element->GetXmin()) );
01201             } else {
01202                Int_t nbits = (Int_t)element->GetXmin();
01203                if (!nbits) nbits = 12;
01204                fReadObjectWise->AddAction( ReadBasicType_NoFactor<float>, new TConfNoFactor(this,i,fOffset[i],nbits) );               
01205             }
01206             break;
01207          }
01208          case TStreamerInfo::kDouble32: {
01209             if (element->GetFactor() != 0) {
01210                fReadObjectWise->AddAction( ReadBasicType_WithFactor<double>, new TConfWithFactor(this,i,fOffset[i],element->GetFactor(),element->GetXmin()) );
01211             } else {
01212                Int_t nbits = (Int_t)element->GetXmin();
01213                if (!nbits) {
01214                   fReadObjectWise->AddAction( ConvertBasicType<float,double>, new TConfiguration(this,i,fOffset[i]) );
01215                } else {
01216                   fReadObjectWise->AddAction( ReadBasicType_NoFactor<double>, new TConfNoFactor(this,i,fOffset[i],nbits) );
01217                }
01218             }
01219             break;
01220          }
01221          case TStreamerInfo::kTNamed:  fReadObjectWise->AddAction( ReadTNamed, new TConfiguration(this,i,fOffset[i]) );    break;
01222             // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
01223             // Streamer alltogether.
01224          case TStreamerInfo::kTObject: fReadObjectWise->AddAction( ReadTObject, new TConfiguration(this,i,fOffset[i]) );    break;
01225          case TStreamerInfo::kTString: fReadObjectWise->AddAction( ReadTString, new TConfiguration(this,i,fOffset[i]) );    break;
01226          case TStreamerInfo::kSTL: {
01227             TClass *newClass = element->GetNewClass();
01228             TClass *oldClass = element->GetClassPointer();
01229             Bool_t isSTLbase = element->IsBase() && element->IsA()!=TStreamerBase::Class();
01230             
01231             if (element->GetArrayLength() <= 1) {
01232                if (fOldVersion<3){   // case of old TStreamerInfo
01233                   if (newClass && newClass != oldClass) {
01234                      if (element->GetStreamer()) {
01235                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,fOffset[i],1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01236                      } else {
01237                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,fOffset[i],1,oldClass,newClass,element->GetTypeName(),isSTLbase));                     
01238                      }
01239                   } else {
01240                      if (element->GetStreamer()) {
01241                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,fOffset[i],1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01242                      } else {
01243                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,fOffset[i],1,oldClass,element->GetTypeName(),isSTLbase));
01244                      }                  
01245                   }
01246                } else {
01247                   if (newClass && newClass != oldClass) {
01248                      if (element->GetStreamer()) {
01249                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,fOffset[i],1,oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01250                      } else {
01251                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,fOffset[i],1,oldClass,newClass,element->GetTypeName(),isSTLbase));                     
01252                      }
01253                   } else {
01254                      if (element->GetStreamer()) {
01255                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,fOffset[i],1,oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01256                      } else {
01257                         fReadObjectWise->AddAction(ReadSTL<ReadSTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,fOffset[i],1,oldClass,element->GetTypeName(),isSTLbase));
01258                      }                  
01259                   }                  
01260                }
01261             } else {
01262                if (fOldVersion<3){   // case of old TStreamerInfo
01263                   if (newClass && newClass != oldClass) {
01264                      if (element->GetStreamer()) {
01265                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01266                      } else {
01267                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));                     
01268                      }
01269                   } else {
01270                      if (element->GetStreamer()) {
01271                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamerV2>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01272                      } else {
01273                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArrayV2>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
01274                      }                  
01275                   }
01276                } else {
01277                   if (newClass && newClass != oldClass) {
01278                      if (element->GetStreamer()) {
01279                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,newClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01280                      } else {
01281                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseChangedClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,newClass,element->GetTypeName(),isSTLbase));                     
01282                      }
01283                   } else {
01284                      if (element->GetStreamer()) {
01285                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseStreamer>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,element->GetStreamer(),element->GetTypeName(),isSTLbase));
01286                      } else {
01287                         fReadObjectWise->AddAction(ReadSTL<ReadArraySTLMemberWiseSameClass,ReadSTLObjectWiseFastArray>, new TConfigSTL(this,i,fOffset[i],element->GetArrayLength(),oldClass,element->GetTypeName(),isSTLbase));
01288                      }                  
01289                   }                                    
01290                }
01291             }
01292             break;
01293          }
01294          default:
01295             fReadObjectWise->AddAction( GenericAction, new TGenericConfiguration(this,i) );
01296             break;
01297       }
01298       if (element->TestBit(TStreamerElement::kCache)) {
01299          TConfiguredAction action( fReadObjectWise->fActions.back() );  // Action is moved, we must pop it next.
01300          fReadObjectWise->fActions.pop_back();
01301          fReadObjectWise->AddAction( UseCache, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
01302       }            
01303       if (fReadMemberWise) {
01304          // This is for streaming via a TClonesArray.
01305 
01306          if (element->TestBit(TStreamerElement::kCache)) {
01307             TConfiguredAction action( GetVectorAction(this,element,fType[i],i,fOffset[i]) );
01308             fReadMemberWise->AddAction( UseCacheVectorPtrLoop, new TConfigurationUseCache(this,action,element->TestBit(TStreamerElement::kRepeat)) );
01309          } else {
01310             switch (fType[i]) {
01311                   // read basic types
01312                case TStreamerInfo::kBool:    fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Bool_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01313                case TStreamerInfo::kChar:    fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Char_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01314                case TStreamerInfo::kShort:   fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Short_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01315                case TStreamerInfo::kInt:     fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Int_t>, new TConfiguration(this,i,fOffset[i]) );     break;
01316                case TStreamerInfo::kLong:    fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Long_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01317                case TStreamerInfo::kLong64:  fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Long64_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01318                case TStreamerInfo::kFloat:   fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Float_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01319                case TStreamerInfo::kDouble:  fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<Double_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01320                case TStreamerInfo::kUChar:   fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<UChar_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01321                case TStreamerInfo::kUShort:  fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<UShort_t>, new TConfiguration(this,i,fOffset[i]) );  break;
01322                case TStreamerInfo::kUInt:    fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<UInt_t>, new TConfiguration(this,i,fOffset[i]) );    break;
01323                case TStreamerInfo::kULong:   fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<ULong_t>, new TConfiguration(this,i,fOffset[i]) );   break;
01324                case TStreamerInfo::kULong64: fReadMemberWise->AddAction( ReadBasicTypeVectorPtrLoop<ULong64_t>, new TConfiguration(this,i,fOffset[i]) ); break;
01325                case TStreamerInfo::kFloat16: {
01326                   if (element->GetFactor() != 0) {
01327                      fReadMemberWise->AddAction( VectorPtrLooper<ReadBasicType_WithFactor<float> >, new TConfWithFactor(this,i,fOffset[i],element->GetFactor(),element->GetXmin()) );
01328                   } else {
01329                      Int_t nbits = (Int_t)element->GetXmin();
01330                      if (!nbits) nbits = 12;
01331                      fReadMemberWise->AddAction( VectorPtrLooper<ReadBasicType_NoFactor<float> >, new TConfNoFactor(this,i,fOffset[i],nbits) );               
01332                   }
01333                   break;
01334                }
01335                case TStreamerInfo::kDouble32: {
01336                   if (element->GetFactor() != 0) {
01337                      fReadMemberWise->AddAction( VectorPtrLooper<ReadBasicType_WithFactor<double> >, new TConfWithFactor(this,i,fOffset[i],element->GetFactor(),element->GetXmin()) );
01338                   } else {
01339                      Int_t nbits = (Int_t)element->GetXmin();
01340                      if (!nbits) {
01341                         fReadMemberWise->AddAction( VectorPtrLooper<ConvertBasicType<float,double> >, new TConfiguration(this,i,fOffset[i]) );
01342                      } else {
01343                         fReadMemberWise->AddAction( VectorPtrLooper<ReadBasicType_NoFactor<double> >, new TConfNoFactor(this,i,fOffset[i],nbits) );
01344                      }
01345                   }
01346                   break;
01347                }
01348                case TStreamerInfo::kTNamed:  fReadMemberWise->AddAction( VectorPtrLooper<ReadTNamed >, new TConfiguration(this,i,fOffset[i]) );    break;
01349                   // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
01350                   // Streamer alltogether.
01351                case TStreamerInfo::kTObject: fReadMemberWise->AddAction( VectorPtrLooper<ReadTObject >, new TConfiguration(this,i,fOffset[i]) );    break;
01352                case TStreamerInfo::kTString: fReadMemberWise->AddAction( VectorPtrLooper<ReadTString >, new TConfiguration(this,i,fOffset[i]) );    break;
01353                default:
01354                   fReadMemberWise->AddAction( GenericVectorPtrAction, new TGenericConfiguration(this,i) );
01355                   break;
01356             }
01357          }
01358       }
01359    }
01360    ComputeSize();
01361 
01362    fOptimized = isOptimized;
01363 
01364    if (gDebug > 0) {
01365       ls();
01366    }
01367 }
01368 
01369 TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::CreateReadMemberWiseActions(TVirtualStreamerInfo *info, TVirtualCollectionProxy &proxy)
01370 {
01371    // Create the bundle of the actions necessary for the streaming memberwise of the content described by 'info' into the collection described by 'proxy'
01372 
01373    if (info == 0) {
01374       return new TStreamerInfoActions::TActionSequence(0,0);
01375    }
01376 
01377    if (info->IsOptimized()) {
01378       // For now insures that the StreamerInfo is not optimized
01379       info->SetBit(TVirtualStreamerInfo::kCannotOptimize);
01380       info->Compile();
01381    }
01382    UInt_t ndata = info->GetElements()->GetEntries();
01383    TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(info,ndata);
01384    if ( (proxy.GetCollectionType() == TClassEdit::kVector) || (proxy.GetProperties() & TVirtualCollectionProxy::kIsEmulated) ) 
01385    {
01386       if (proxy.HasPointers()) {
01387          // Instead of the creating a new one let's copy the one from the StreamerInfo.
01388          delete sequence;
01389          
01390          sequence = static_cast<TStreamerInfo*>(info)->GetReadMemberWiseActions(kTRUE)->CreateCopy();
01391          
01392          return sequence;
01393       }
01394       
01395       // We can speed up the iteration in case of vector.  We also know that all emulated collection are stored internally as a vector.
01396       Long_t increment = proxy.GetIncrement();
01397       sequence->fLoopConfig = new TVectorLoopConfig(increment);
01398    } else if (proxy.GetCollectionType() == TClassEdit::kSet || proxy.GetCollectionType() == TClassEdit::kMultiSet
01399               || proxy.GetCollectionType() == TClassEdit::kMap || proxy.GetCollectionType() == TClassEdit::kMultiMap) 
01400    {
01401       Long_t increment = proxy.GetIncrement();
01402       sequence->fLoopConfig = new TVectorLoopConfig(increment);
01403       // sequence->fLoopConfig = new TAssocLoopConfig(proxy);
01404    } else {
01405       sequence->fLoopConfig = new TGenericLoopConfig(&proxy);
01406    }
01407    for (UInt_t i = 0; i < ndata; ++i) {
01408       TStreamerElement *element = (TStreamerElement*) info->GetElements()->At(i);
01409       if (!element) {
01410          break;
01411       }
01412       if (element->GetType() < 0) {
01413          // -- Skip an ignored TObject base class.
01414          // Note: The only allowed negative value here is -1, and signifies that Build() has found a TObject
01415          // base class and TClass::IgnoreTObjectStreamer() was called.  In this case the compiled version of the
01416          // elements omits the TObject base class element, which has to be compensated for by TTree::Bronch()
01417          // when it is making branches for a split object.
01418          continue;
01419       }
01420       Int_t asize = element->GetSize();
01421       if (element->GetArrayLength()) {
01422          asize /= element->GetArrayLength();
01423       }
01424       Int_t oldType = element->GetType();
01425       Int_t newType = element->GetNewType();
01426 
01427       Int_t offset = element->GetOffset();
01428       if (newType != oldType) {
01429          if (newType > 0) {
01430             if (oldType != TVirtualStreamerInfo::kCounter) {
01431                oldType += TVirtualStreamerInfo::kConv;
01432             }
01433          } else {
01434             oldType += TVirtualStreamerInfo::kSkip;
01435          }
01436       }
01437       if ( (proxy.GetCollectionType() == TClassEdit::kVector) || (proxy.GetProperties() & TVirtualCollectionProxy::kIsEmulated)  
01438             || (proxy.GetCollectionType() == TClassEdit::kSet || proxy.GetCollectionType() == TClassEdit::kMultiSet
01439             || proxy.GetCollectionType() == TClassEdit::kMap || proxy.GetCollectionType() == TClassEdit::kMultiMap) )
01440       {
01441 
01442          // We can speed up the iteration in case of vector.  We also know that all emulated collection are stored internally as a vector.
01443          if (element->TestBit(TStreamerElement::kCache)) {
01444             TConfiguredAction action( GetVectorAction(info,element,oldType,i,offset) );
01445             sequence->AddAction( UseCacheVectorLoop,  new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
01446          } else {            
01447             sequence->AddAction(GetVectorAction(info,element,oldType,i,offset));
01448          }
01449          
01450 //         } else if (proxy.GetCollectionType() == TClassEdit::kSet || proxy.GetCollectionType() == TClassEdit::kMultiSet
01451 //                    || proxy.GetCollectionType() == TClassEdit::kMap || proxy.GetCollectionType() == TClassEdit::kMultiMap) {
01452 //            sequence->AddAction( GenericAssocCollectionAction, new TConfigSTL(info,i,offset,0,proxy.GetCollectionClass(),0,0) );
01453       } else {
01454          // The usual collection case.
01455          if (element->TestBit(TStreamerElement::kCache)) {
01456             TConfiguredAction action( GetVectorAction(info,element,oldType,i,offset) );
01457             sequence->AddAction( UseCacheGenericCollection, new TConfigurationUseCache(info,action,element->TestBit(TStreamerElement::kRepeat)) );
01458          } else {
01459             switch (oldType) {
01460                   // read basic types
01461                case TStreamerInfo::kBool:    sequence->AddAction( ReadBasicTypeGenericLoop<Bool_t>, new TConfiguration(info,i,offset) );    break;
01462                case TStreamerInfo::kChar:    sequence->AddAction( ReadBasicTypeGenericLoop<Char_t>, new TConfiguration(info,i,offset) );    break;
01463                case TStreamerInfo::kShort:   sequence->AddAction( ReadBasicTypeGenericLoop<Short_t>, new TConfiguration(info,i,offset) );   break;
01464                case TStreamerInfo::kInt:     sequence->AddAction( ReadBasicTypeGenericLoop<Int_t>, new TConfiguration(info,i,offset) );     break;
01465                case TStreamerInfo::kLong:    sequence->AddAction( ReadBasicTypeGenericLoop<Long_t>, new TConfiguration(info,i,offset) );    break;
01466                case TStreamerInfo::kLong64:  sequence->AddAction( ReadBasicTypeGenericLoop<Long64_t>, new TConfiguration(info,i,offset) );  break;
01467                case TStreamerInfo::kFloat:   sequence->AddAction( ReadBasicTypeGenericLoop<Float_t>, new TConfiguration(info,i,offset) );   break;
01468                case TStreamerInfo::kDouble:  sequence->AddAction( ReadBasicTypeGenericLoop<Double_t>, new TConfiguration(info,i,offset) );  break;
01469                case TStreamerInfo::kUChar:   sequence->AddAction( ReadBasicTypeGenericLoop<UChar_t>, new TConfiguration(info,i,offset) );   break;
01470                case TStreamerInfo::kUShort:  sequence->AddAction( ReadBasicTypeGenericLoop<UShort_t>, new TConfiguration(info,i,offset) );  break;
01471                case TStreamerInfo::kUInt:    sequence->AddAction( ReadBasicTypeGenericLoop<UInt_t>, new TConfiguration(info,i,offset) );    break;
01472                case TStreamerInfo::kULong:   sequence->AddAction( ReadBasicTypeGenericLoop<ULong_t>, new TConfiguration(info,i,offset) );   break;
01473                case TStreamerInfo::kULong64: sequence->AddAction( ReadBasicTypeGenericLoop<ULong64_t>, new TConfiguration(info,i,offset) ); break;
01474                case TStreamerInfo::kFloat16: {
01475                   if (element->GetFactor() != 0) {
01476                      sequence->AddAction( GenericLooper<ReadBasicType_WithFactor<float> >, new TConfWithFactor(info,i,offset,element->GetFactor(),element->GetXmin()) );
01477                   } else {
01478                      Int_t nbits = (Int_t)element->GetXmin();
01479                      if (!nbits) nbits = 12;
01480                      sequence->AddAction( GenericLooper<ReadBasicType_NoFactor<float> >, new TConfNoFactor(info,i,offset,nbits) );               
01481                   }
01482                   break;
01483                }
01484                case TStreamerInfo::kDouble32: {
01485                   if (element->GetFactor() != 0) {
01486                      sequence->AddAction( GenericLooper<ReadBasicType_WithFactor<double> >, new TConfWithFactor(info,i,offset,element->GetFactor(),element->GetXmin()) );
01487                   } else {
01488                      Int_t nbits = (Int_t)element->GetXmin();
01489                      if (!nbits) {
01490                         sequence->AddAction( GenericLooper<ConvertBasicType<float,double> >, new TConfiguration(info,i,offset) );
01491                      } else {
01492                         sequence->AddAction( GenericLooper<ReadBasicType_NoFactor<double> >, new TConfNoFactor(info,i,offset,nbits) );
01493                      }
01494                   }
01495                   break;
01496                }
01497                case TStreamerInfo::kTNamed:  sequence->AddAction( GenericLooper<ReadTNamed >, new TConfiguration(info,i,offset) );    break;
01498                   // Idea: We should calculate the CanIgnoreTObjectStreamer here and avoid calling the
01499                   // Streamer alltogether.
01500                case TStreamerInfo::kTObject: sequence->AddAction( GenericLooper<ReadTObject >, new TConfiguration(info,i,offset) );    break;
01501                case TStreamerInfo::kTString: sequence->AddAction( GenericLooper<ReadTString >, new TConfiguration(info,i,offset) );    break;
01502                default:
01503                   sequence->AddAction( GenericCollectionAction, new TConfigSTL(info,i,0 /* the offset will be used from TStreamerInfo */,0,proxy.GetCollectionClass(),0,0) );
01504                   break;
01505             }
01506          }
01507       }
01508    }
01509    return sequence;
01510 }
01511 
01512 void TStreamerInfoActions::TActionSequence::AddToOffset(Int_t delta)
01513 {
01514    // Add the (potentially negative) delta to all the configuration's offset.  This is used by
01515    // TTBranchElement in the case of split sub-object.
01516 
01517    TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
01518    for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
01519        iter != end;
01520        ++iter) 
01521    {
01522       iter->fConfiguration->AddToOffset(delta);
01523    }
01524 }
01525 
01526 TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::CreateCopy()
01527 {
01528    // Create a copy of this sequence.
01529    
01530    TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,fActions.size());
01531 
01532    sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
01533 
01534    TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
01535    for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
01536        iter != end;
01537        ++iter) 
01538    {
01539       TConfiguration *conf = iter->fConfiguration->Copy();
01540       sequence->AddAction( iter->fAction, conf );
01541    }
01542    return sequence;
01543 }
01544 
01545 TStreamerInfoActions::TActionSequence *TStreamerInfoActions::TActionSequence::CreateSubSequence(const std::vector<Int_t> &element_ids, size_t offset)
01546 {
01547    // Create a sequence containing the subset of the action corresponding to the SteamerElement whose ids is contained in the vector.
01548    // 'offset' is the location of this 'class' within the object (address) that will be pass to ReadBuffer when using this sequence.
01549    
01550    TStreamerInfoActions::TActionSequence *sequence = new TStreamerInfoActions::TActionSequence(fStreamerInfo,element_ids.size());
01551    
01552    sequence->fLoopConfig = fLoopConfig ? fLoopConfig->Copy() : 0;
01553    
01554    for(UInt_t id = 0; id < element_ids.size(); ++id) {
01555       if ( element_ids[id] < 0 ) {
01556          TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
01557          for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
01558              iter != end;
01559              ++iter) 
01560          {
01561             TConfiguration *conf = iter->fConfiguration->Copy();
01562             conf->AddToOffset(offset);
01563             sequence->AddAction( iter->fAction, conf );
01564          }
01565       } else {
01566          TStreamerInfoActions::ActionContainer_t::iterator end = fActions.end();
01567          for(TStreamerInfoActions::ActionContainer_t::iterator iter = fActions.begin();
01568              iter != end;
01569              ++iter) {
01570             if ( iter->fConfiguration->fElemId == (UInt_t)element_ids[id] ) {
01571                TConfiguration *conf = iter->fConfiguration->Copy();
01572                conf->AddToOffset(offset);
01573                sequence->AddAction( iter->fAction, conf );
01574             }
01575          }
01576       }
01577    }
01578    return sequence;
01579 }
01580 
01581 void TStreamerInfoActions::TActionSequence::Print(Option_t *) const
01582 {
01583    // Add the (potentially negative) delta to all the configuration's offset.  This is used by
01584    // TTBranchElement in the case of split sub-object.
01585 
01586    if (fLoopConfig) {
01587       fLoopConfig->Print();
01588    }
01589    TStreamerInfoActions::ActionContainer_t::const_iterator end = fActions.end();
01590    for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = fActions.begin();
01591        iter != end;
01592        ++iter) 
01593    {
01594       iter->fConfiguration->Print();
01595    }
01596 }
01597 
01598 

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