TStreamerInfoWriteBuffer.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TStreamerInfoWriteBuffer.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 #include "TBuffer.h"
00013 #include "TClass.h"
00014 #include "TClonesArray.h"
00015 #include "TError.h"
00016 #include "TProcessID.h"
00017 #include "TStreamer.h"
00018 #include "TStreamerElement.h"
00019 #include "TStreamerInfo.h"
00020 #include "TVirtualCollectionProxy.h"
00021 #include "TRefTable.h"
00022 #include "TFile.h"
00023 
00024 #include "TVirtualArray.h"
00025 #include "TBufferFile.h"
00026 #include "TInterpreter.h"
00027 
00028 //==========CPP macros
00029 
00030 #define DOLOOP for(int k=0; k<narr; ++k)
00031 
00032 #define WriteBasicTypeElem(name,index)          \
00033    {                                            \
00034       name *x=(name*)(arr[index]+ioffset);      \
00035       b << *x;                                  \
00036    }
00037 
00038 #define WriteBasicType(name)                    \
00039    {                                            \
00040       WriteBasicTypeElem(name,0);               \
00041    }
00042 
00043 #define WriteBasicTypeLoop(name)                            \
00044    {                                                        \
00045       for(int k=0; k<narr; ++k) WriteBasicTypeElem(name,k); \
00046    }
00047 
00048 #define WriteBasicArrayElem(name,index)         \
00049    {                                            \
00050       name *x=(name*)(arr[index]+ioffset);      \
00051       b.WriteFastArray(x,fLength[i]);           \
00052    }
00053 
00054 #define WriteBasicArray(name)                   \
00055    {                                            \
00056       WriteBasicArrayElem(name,0);              \
00057    }
00058 
00059 #define WriteBasicArrayLoop(name)                              \
00060    {                                                           \
00061       for(int k=0; k<narr; ++k) WriteBasicArrayElem(name,k);   \
00062    }
00063 
00064 #define WriteBasicPointerElem(name,index)       \
00065    {                                            \
00066       Int_t *l = (Int_t*)(arr[index]+imethod);  \
00067       name **f = (name**)(arr[index]+ioffset);  \
00068       name *af = *f;                            \
00069       if (af && *l)  b << Char_t(1);            \
00070       else          {b << Char_t(0); continue;} \
00071       int j;                                    \
00072       for(j=0;j<fLength[i];j++) {               \
00073          b.WriteFastArray(f[j],*l);             \
00074       }                                         \
00075    }
00076 
00077 #define WriteBasicPointer(name)                 \
00078    {                                            \
00079       int imethod = fMethod[i]+eoffset;         \
00080       WriteBasicPointerElem(name,0);            \
00081    }
00082 
00083 #define WriteBasicPointerLoop(name)             \
00084    {                                            \
00085       int imethod = fMethod[i]+eoffset;         \
00086       for(int k=0; k<narr; ++k) {               \
00087          WriteBasicPointerElem(name,k);         \
00088       }                                         \
00089    }
00090 
00091 // Helper function for TStreamerInfo::WriteBuffer
00092 namespace {
00093    template <class T> Bool_t R__TestUseCache(TStreamerElement *element) 
00094    {
00095       return element->TestBit(TStreamerElement::kCache);
00096    }
00097 
00098    template <> Bool_t R__TestUseCache<TVirtualArray>(TStreamerElement*)
00099    {
00100       // We are already using the cache, no need to recurse one more time.
00101       return kFALSE;
00102    }
00103 }
00104 
00105 //______________________________________________________________________________
00106 #ifdef R__BROKEN_FUNCTION_TEMPLATES
00107 template <class T>
00108 Int_t TStreamerInfo__WriteBufferAuxImp(TStreamerInfo *thisVar,
00109                                        TBuffer &b, const T &arr, Int_t first,
00110                                        Int_t narr, Int_t eoffset, Int_t arrayMode,
00111                                        ULong_t *fMethod, ULong_t *fElem,Int_t *fLength,
00112                                        TClass *fClass, Int_t *fOffset, Int_t * /*fNewType*/,
00113                                        Int_t fNdata, Int_t *fType, TStreamerElement *& /*fgElement*/,
00114                                        TStreamerInfo::TCompInfo *fComp)
00115 {
00116    //  The object at pointer is serialized to the buffer b
00117    //  if (arrayMode & 1) ptr is a pointer to array of pointers to the objects
00118    //  otherwise it is a pointer to a pointer to a single object.
00119    //  This also means that T is of a type such that arr[i] is a pointer to an
00120    //  object.  Currently the only anticipated instantiation are for T==char**
00121    //  and T==TVirtualCollectionProxy
00122 #else
00123 template <class T>
00124 Int_t TStreamerInfo::WriteBufferAux(TBuffer &b, const T &arr, Int_t first,
00125                                     Int_t narr, Int_t eoffset, Int_t arrayMode)
00126 {
00127    //  The object at pointer is serialized to the buffer b
00128    //  if (arrayMode & 1) ptr is a pointer to array of pointers to the objects
00129    //  otherwise it is a pointer to a pointer to a single object.
00130    //  This also means that T is of a type such that arr[i] is a pointer to an
00131    //  object.  Currently the only anticipated instantiation are for T==char**
00132    //  and T==TVirtualCollectionProxy
00133 
00134    TStreamerInfo *thisVar = this;
00135 #endif
00136 
00137    b.IncrementLevel(thisVar);
00138 
00139    //mark this class as being used in the current file
00140    b.TagStreamerInfo(thisVar);
00141 
00142    //============
00143 
00144    //loop on all active members
00145    Int_t last;
00146    if (first < 0) {first = 0; last = fNdata;}
00147    else            last = first+1;
00148 
00149    // In order to speed up the case where the object being written is
00150    // not in a collection (i.e. arrayMode is false), we actually
00151    // duplicate the elementary types using this typeOffset.
00152    static const int kHaveLoop = 1024;
00153    const Int_t typeOffset = arrayMode ? kHaveLoop : 0;
00154 
00155    for (Int_t i=first;i<last;i++) {
00156 
00157       b.SetStreamerElementNumber(i);
00158       TStreamerElement *aElement = (TStreamerElement*)fElem[i];
00159 
00160       Int_t ioffset = eoffset+fOffset[i];
00161 
00162       if (R__TestUseCache<T>(aElement)) {
00163          if (aElement->TestBit(TStreamerElement::kWrite)) {
00164             if (((TBufferFile&)b).PeekDataCache()==0) {
00165                Warning("WriteBuffer","Skipping %s::%s because the cache is missing.",thisVar->GetName(),aElement->GetName());
00166             } else {
00167                if (gDebug > 1) {
00168                   printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d,"
00169                          " %s, bufpos=%d, arr=%p, eoffset=%d, Redirect=%p\n",
00170                          fClass->GetName(),aElement->GetName(),i,fType[i],
00171                          aElement->ClassName(),b.Length(),arr[0], eoffset,((TBufferFile&)b).PeekDataCache()->GetObjectAt(0));
00172                }
00173                thisVar->WriteBufferAux(b,*((TBufferFile&)b).PeekDataCache(),i,narr,eoffset, arrayMode);
00174             }
00175             continue;
00176          } else {
00177             if (gDebug > 1) {
00178                printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d,"
00179                       " %s, bufpos=%d, arr=%p, eoffset=%d, not a write rule, skipping.\n",
00180                       fClass->GetName(),aElement->GetName(),i,fType[i],
00181                       aElement->ClassName(),b.Length(),arr[0], eoffset);
00182             }
00183             // The rule was a cached element for a read, rule, the real offset is in the
00184             // next element (the one for the rule itself).
00185             if (aElement->TestBit(TStreamerElement::kRepeat)) continue;
00186             ioffset = eoffset+fOffset[i];
00187          }
00188       }
00189 
00190 
00191       if (gDebug > 1) {
00192          printf("WriteBuffer, class:%s, name=%s, fType[%d]=%d, %s, "
00193                "bufpos=%d, arr=%p, offset=%d\n",
00194                 fClass->GetName(),aElement->GetName(),i,fType[i],aElement->ClassName(),
00195                 b.Length(),arr[0],ioffset);
00196       }
00197 
00198       switch (fType[i]+typeOffset) {
00199          // In this switch we intentionally use 'continue' instead of
00200          // 'break' to avoid running the 2nd switch (see later in this
00201          // function).
00202 
00203          case TStreamerInfo::kBool:                WriteBasicType(Bool_t);    continue;
00204          case TStreamerInfo::kChar:                WriteBasicType(Char_t);    continue;
00205          case TStreamerInfo::kShort:               WriteBasicType(Short_t);   continue;
00206          case TStreamerInfo::kInt:                 WriteBasicType(Int_t);     continue;
00207          case TStreamerInfo::kLong:                WriteBasicType(Long_t);    continue;
00208          case TStreamerInfo::kLong64:              WriteBasicType(Long64_t);  continue;
00209          case TStreamerInfo::kFloat:               WriteBasicType(Float_t);   continue;
00210          case TStreamerInfo::kDouble:              WriteBasicType(Double_t);  continue;
00211          case TStreamerInfo::kUChar:               WriteBasicType(UChar_t);   continue;
00212          case TStreamerInfo::kUShort:              WriteBasicType(UShort_t);  continue;
00213          case TStreamerInfo::kUInt:                WriteBasicType(UInt_t);    continue;
00214          case TStreamerInfo::kULong:               WriteBasicType(ULong_t);   continue;
00215          case TStreamerInfo::kULong64:             WriteBasicType(ULong64_t); continue;
00216          case TStreamerInfo::kFloat16: {
00217             Float_t *x=(Float_t*)(arr[0]+ioffset);
00218             b.WriteFloat16(x,aElement);
00219             continue;
00220          }
00221          case TStreamerInfo::kDouble32: {
00222             Double_t *x=(Double_t*)(arr[0]+ioffset);
00223             b.WriteDouble32(x,aElement);
00224             continue;
00225          }
00226 
00227          case TStreamerInfo::kBool    + kHaveLoop: WriteBasicTypeLoop(Bool_t);    continue;
00228          case TStreamerInfo::kChar    + kHaveLoop: WriteBasicTypeLoop(Char_t);    continue;
00229          case TStreamerInfo::kShort   + kHaveLoop: WriteBasicTypeLoop(Short_t);   continue;
00230          case TStreamerInfo::kInt     + kHaveLoop: WriteBasicTypeLoop(Int_t);     continue;
00231          case TStreamerInfo::kLong    + kHaveLoop: WriteBasicTypeLoop(Long_t);    continue;
00232          case TStreamerInfo::kLong64  + kHaveLoop: WriteBasicTypeLoop(Long64_t);  continue;
00233          case TStreamerInfo::kFloat   + kHaveLoop: WriteBasicTypeLoop(Float_t);   continue;
00234          case TStreamerInfo::kDouble  + kHaveLoop: WriteBasicTypeLoop(Double_t);  continue;
00235          case TStreamerInfo::kUChar   + kHaveLoop: WriteBasicTypeLoop(UChar_t);   continue;
00236          case TStreamerInfo::kUShort  + kHaveLoop: WriteBasicTypeLoop(UShort_t);  continue;
00237          case TStreamerInfo::kUInt    + kHaveLoop: WriteBasicTypeLoop(UInt_t);    continue;
00238          case TStreamerInfo::kULong   + kHaveLoop: WriteBasicTypeLoop(ULong_t);   continue;
00239          case TStreamerInfo::kULong64 + kHaveLoop: WriteBasicTypeLoop(ULong64_t); continue;
00240          case TStreamerInfo::kFloat16+ kHaveLoop: {
00241             for(int k=0; k<narr; ++k) {
00242                Float_t *x=(Float_t*)(arr[k]+ioffset);
00243                b.WriteFloat16(x,aElement);
00244             }
00245             continue;
00246          }
00247          case TStreamerInfo::kDouble32+ kHaveLoop: {
00248             for(int k=0; k<narr; ++k) {
00249                Double_t *x=(Double_t*)(arr[k]+ioffset);
00250                b.WriteDouble32(x,aElement);
00251             }
00252             continue;
00253          }
00254 
00255          // write array of basic types  array[8]
00256          case TStreamerInfo::kOffsetL + TStreamerInfo::kBool:   WriteBasicArray(Bool_t);    continue;
00257          case TStreamerInfo::kOffsetL + TStreamerInfo::kChar:   WriteBasicArray(Char_t);    continue;
00258          case TStreamerInfo::kOffsetL + TStreamerInfo::kShort:  WriteBasicArray(Short_t);   continue;
00259          case TStreamerInfo::kOffsetL + TStreamerInfo::kInt:    WriteBasicArray(Int_t);     continue;
00260          case TStreamerInfo::kOffsetL + TStreamerInfo::kLong:   WriteBasicArray(Long_t);    continue;
00261          case TStreamerInfo::kOffsetL + TStreamerInfo::kLong64: WriteBasicArray(Long64_t);  continue;
00262          case TStreamerInfo::kOffsetL + TStreamerInfo::kFloat:  WriteBasicArray(Float_t);   continue;
00263          case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble: WriteBasicArray(Double_t);  continue;
00264          case TStreamerInfo::kOffsetL + TStreamerInfo::kUChar:  WriteBasicArray(UChar_t);   continue;
00265          case TStreamerInfo::kOffsetL + TStreamerInfo::kUShort: WriteBasicArray(UShort_t);  continue;
00266          case TStreamerInfo::kOffsetL + TStreamerInfo::kUInt:   WriteBasicArray(UInt_t);    continue;
00267          case TStreamerInfo::kOffsetL + TStreamerInfo::kULong:  WriteBasicArray(ULong_t);   continue;
00268          case TStreamerInfo::kOffsetL + TStreamerInfo::kULong64:WriteBasicArray(ULong64_t); continue;
00269          case TStreamerInfo::kOffsetL + TStreamerInfo::kFloat16: {
00270             b.WriteFastArrayFloat16((Float_t*)(arr[0]+ioffset),fLength[i],aElement);
00271             continue;
00272          }
00273          case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble32: {
00274             b.WriteFastArrayDouble32((Double_t*)(arr[0]+ioffset),fLength[i],aElement);
00275             continue;
00276          }
00277 
00278          case TStreamerInfo::kOffsetL + TStreamerInfo::kBool    + kHaveLoop: WriteBasicArrayLoop(Bool_t);    continue;
00279          case TStreamerInfo::kOffsetL + TStreamerInfo::kChar    + kHaveLoop: WriteBasicArrayLoop(Char_t);    continue;
00280          case TStreamerInfo::kOffsetL + TStreamerInfo::kShort   + kHaveLoop: WriteBasicArrayLoop(Short_t);   continue;
00281          case TStreamerInfo::kOffsetL + TStreamerInfo::kInt     + kHaveLoop: WriteBasicArrayLoop(Int_t);     continue;
00282          case TStreamerInfo::kOffsetL + TStreamerInfo::kLong    + kHaveLoop: WriteBasicArrayLoop(Long_t);    continue;
00283          case TStreamerInfo::kOffsetL + TStreamerInfo::kLong64  + kHaveLoop: WriteBasicArrayLoop(Long64_t);  continue;
00284          case TStreamerInfo::kOffsetL + TStreamerInfo::kFloat   + kHaveLoop: WriteBasicArrayLoop(Float_t);   continue;
00285          case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble  + kHaveLoop: WriteBasicArrayLoop(Double_t);  continue;
00286          case TStreamerInfo::kOffsetL + TStreamerInfo::kUChar   + kHaveLoop: WriteBasicArrayLoop(UChar_t);   continue;
00287          case TStreamerInfo::kOffsetL + TStreamerInfo::kUShort  + kHaveLoop: WriteBasicArrayLoop(UShort_t);  continue;
00288          case TStreamerInfo::kOffsetL + TStreamerInfo::kUInt    + kHaveLoop: WriteBasicArrayLoop(UInt_t);    continue;
00289          case TStreamerInfo::kOffsetL + TStreamerInfo::kULong   + kHaveLoop: WriteBasicArrayLoop(ULong_t);   continue;
00290          case TStreamerInfo::kOffsetL + TStreamerInfo::kULong64 + kHaveLoop: WriteBasicArrayLoop(ULong64_t); continue;
00291          case TStreamerInfo::kOffsetL + TStreamerInfo::kFloat16+ kHaveLoop: {
00292             for(int k=0; k<narr; ++k) {
00293                b.WriteFastArrayFloat16((Float_t*)(arr[k]+ioffset),fLength[i],aElement);
00294             }
00295             continue;
00296          }
00297          case TStreamerInfo::kOffsetL + TStreamerInfo::kDouble32+ kHaveLoop: {
00298             for(int k=0; k<narr; ++k) {
00299                b.WriteFastArrayDouble32((Double_t*)(arr[k]+ioffset),fLength[i],aElement);
00300             }
00301             continue;
00302          }
00303 
00304          // write pointer to an array of basic types  array[n]
00305          case TStreamerInfo::kOffsetP + TStreamerInfo::kBool:   WriteBasicPointer(Bool_t);    continue;
00306          case TStreamerInfo::kOffsetP + TStreamerInfo::kChar:   WriteBasicPointer(Char_t);    continue;
00307          case TStreamerInfo::kOffsetP + TStreamerInfo::kShort:  WriteBasicPointer(Short_t);   continue;
00308          case TStreamerInfo::kOffsetP + TStreamerInfo::kInt:    WriteBasicPointer(Int_t);     continue;
00309          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong:   WriteBasicPointer(Long_t);    continue;
00310          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong64: WriteBasicPointer(Long64_t);  continue;
00311          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat:  WriteBasicPointer(Float_t);   continue;
00312          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble: WriteBasicPointer(Double_t);  continue;
00313          case TStreamerInfo::kOffsetP + TStreamerInfo::kUChar:  WriteBasicPointer(UChar_t);   continue;
00314          case TStreamerInfo::kOffsetP + TStreamerInfo::kUShort: WriteBasicPointer(UShort_t);  continue;
00315          case TStreamerInfo::kOffsetP + TStreamerInfo::kUInt:   WriteBasicPointer(UInt_t);    continue;
00316          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong:  WriteBasicPointer(ULong_t);   continue;
00317          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong64:WriteBasicPointer(ULong64_t); continue;
00318          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat16: {
00319             int imethod = fMethod[i]+eoffset;
00320             Int_t *l = (Int_t*)(arr[0]+imethod);
00321             Float_t **f = (Float_t**)(arr[0]+ioffset);
00322             Float_t *af = *f;
00323             if (af && *l)  b << Char_t(1);
00324             else          {b << Char_t(0); continue;}
00325             int j;
00326             for(j=0;j<fLength[i];j++) {
00327                b.WriteFastArrayFloat16(f[j],*l,aElement);
00328             }
00329             continue;
00330          }
00331          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble32: {
00332             int imethod = fMethod[i]+eoffset;
00333             Int_t *l = (Int_t*)(arr[0]+imethod);
00334             Double_t **f = (Double_t**)(arr[0]+ioffset);
00335             Double_t *af = *f;
00336             if (af && *l)  b << Char_t(1);
00337             else          {b << Char_t(0); continue;}
00338             int j;
00339             for(j=0;j<fLength[i];j++) {
00340                b.WriteFastArrayDouble32(f[j],*l,aElement);
00341             }
00342             continue;
00343          }
00344 
00345          case TStreamerInfo::kOffsetP + TStreamerInfo::kBool    + kHaveLoop: WriteBasicPointerLoop(Bool_t);    continue;
00346          case TStreamerInfo::kOffsetP + TStreamerInfo::kChar    + kHaveLoop: WriteBasicPointerLoop(Char_t);    continue;
00347          case TStreamerInfo::kOffsetP + TStreamerInfo::kShort   + kHaveLoop: WriteBasicPointerLoop(Short_t);   continue;
00348          case TStreamerInfo::kOffsetP + TStreamerInfo::kInt     + kHaveLoop: WriteBasicPointerLoop(Int_t);     continue;
00349          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong    + kHaveLoop: WriteBasicPointerLoop(Long_t);    continue;
00350          case TStreamerInfo::kOffsetP + TStreamerInfo::kLong64  + kHaveLoop: WriteBasicPointerLoop(Long64_t);  continue;
00351          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat   + kHaveLoop: WriteBasicPointerLoop(Float_t);   continue;
00352          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble  + kHaveLoop: WriteBasicPointerLoop(Double_t);  continue;
00353          case TStreamerInfo::kOffsetP + TStreamerInfo::kUChar   + kHaveLoop: WriteBasicPointerLoop(UChar_t);   continue;
00354          case TStreamerInfo::kOffsetP + TStreamerInfo::kUShort  + kHaveLoop: WriteBasicPointerLoop(UShort_t);  continue;
00355          case TStreamerInfo::kOffsetP + TStreamerInfo::kUInt    + kHaveLoop: WriteBasicPointerLoop(UInt_t);    continue;
00356          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong   + kHaveLoop: WriteBasicPointerLoop(ULong_t);   continue;
00357          case TStreamerInfo::kOffsetP + TStreamerInfo::kULong64 + kHaveLoop: WriteBasicPointerLoop(ULong64_t); continue;
00358          case TStreamerInfo::kOffsetP + TStreamerInfo::kFloat16+ kHaveLoop: {
00359             int imethod = fMethod[i]+eoffset;
00360             for(int k=0; k<narr; ++k) {
00361                Int_t *l = (Int_t*)(arr[k]+imethod);
00362                Float_t **f = (Float_t**)(arr[k]+ioffset);
00363                Float_t *af = *f;
00364                if (af && *l)  b << Char_t(1);
00365                else          {b << Char_t(0); continue;}
00366                int j;
00367                for(j=0;j<fLength[i];j++) {
00368                   b.WriteFastArrayFloat16(f[j],*l,aElement);
00369                }
00370             }
00371             continue;
00372          }
00373          case TStreamerInfo::kOffsetP + TStreamerInfo::kDouble32+ kHaveLoop: {
00374             int imethod = fMethod[i]+eoffset;
00375             for(int k=0; k<narr; ++k) {
00376                Int_t *l = (Int_t*)(arr[k]+imethod);
00377                Double_t **f = (Double_t**)(arr[k]+ioffset);
00378                Double_t *af = *f;
00379                if (af && *l)  b << Char_t(1);
00380                else          {b << Char_t(0); continue;}
00381                int j;
00382                for(j=0;j<fLength[i];j++) {
00383                   b.WriteFastArrayDouble32(f[j],*l,aElement);
00384                }
00385             }
00386             continue;
00387          }
00388 
00389          case TStreamerInfo::kCounter: {
00390             Int_t *x=(Int_t*)(arr[0]+ioffset);
00391             b << *x;
00392             if (i == last-1) {
00393                b.DecrementLevel(thisVar);
00394                return x[0]; // info used by TBranchElement::FillLeaves
00395             }
00396             continue;
00397          }
00398 
00399          case TStreamerInfo::kCounter + kHaveLoop : {
00400             DOLOOP {
00401                Int_t *x=(Int_t*)(arr[k]+ioffset);
00402                b << x[0];
00403             }
00404             continue;
00405          }
00406 
00407 
00408       };
00409       Bool_t isPreAlloc = 0;
00410 
00411       switch (fType[i]) {
00412 
00413          // char*
00414          case TStreamerInfo::kCharStar: { DOLOOP {
00415             Int_t nch = 0;
00416             char **f = (char**)(arr[k]+ioffset);
00417             char *af = *f;
00418             if (af) {
00419                nch = strlen(af);
00420                b  << nch;
00421                b.WriteFastArray(af,nch);
00422             } else {
00423                b << nch;
00424             }
00425          }
00426          continue; }
00427 
00428          // special case for TObject::fBits in case of a referenced object
00429          case TStreamerInfo::kBits: { DOLOOP {
00430             UInt_t *x=(UInt_t*)(arr[k]+ioffset); b << *x;
00431             if ((*x & kIsReferenced) != 0) {
00432                TObject *obj = (TObject*)(arr[k]+eoffset);
00433                TProcessID *pid = TProcessID::GetProcessWithUID(obj->GetUniqueID(),obj);
00434                TRefTable *table = TRefTable::GetRefTable();
00435                if(table) table->Add(obj->GetUniqueID(),pid);
00436                UShort_t pidf = b.WriteProcessID(pid);
00437                b << pidf;
00438             }
00439          }
00440          continue; }
00441 
00442          // Special case for TString, TObject, TNamed
00443          case TStreamerInfo::kTString: { DOLOOP{ ((TString*)(arr[k]+ioffset))->Streamer(b);         }; continue; }
00444          case TStreamerInfo::kTObject: { DOLOOP{ ((TObject*)(arr[k]+ioffset))->TObject::Streamer(b);}; continue; }
00445          case TStreamerInfo::kTNamed:  { DOLOOP{ ((TNamed *)(arr[k]+ioffset))->TNamed::Streamer(b); }; continue; }
00446 
00447          case TStreamerInfo::kAnyp:     // Class*   Class not derived from TObject and with comment field //->
00448          case TStreamerInfo::kAnyp    + TStreamerInfo::kOffsetL:
00449 
00450          case TStreamerInfo::kObjectp:  // Class *  Class     derived from TObject and with comment field //->
00451          case TStreamerInfo::kObjectp + TStreamerInfo::kOffsetL:
00452 
00453             isPreAlloc = kTRUE;
00454 
00455             // Intentional fallthrough now that isPreAlloc is set.
00456          case TStreamerInfo::kAnyP:         // Class*   Class not derived from TObject and no comment
00457          case TStreamerInfo::kAnyP    + TStreamerInfo::kOffsetL:
00458 
00459          case TStreamerInfo::kObjectP:  // Class*   Class derived from TObject
00460          case TStreamerInfo::kObjectP + TStreamerInfo::kOffsetL: {
00461             TClass *cl                 = fComp[i].fClass;
00462             TMemberStreamer *pstreamer = fComp[i].fStreamer;
00463             DOLOOP {
00464                Int_t res = b.WriteFastArray((void**)(arr[k]+ioffset),cl,fLength[i],isPreAlloc,pstreamer);
00465                if (res==2) {
00466                   Warning("WriteBuffer",
00467                           "The actual class of %s::%s is not available. Only the \"%s\" part will be written\n",
00468                           thisVar->GetName(),aElement->GetName(),cl->GetName());
00469                }
00470             }
00471             continue;
00472          }
00473 
00474          case TStreamerInfo::kAnyPnoVT:     // Class*   Class not derived from TObject and no virtual table and no comment
00475          case TStreamerInfo::kAnyPnoVT    + TStreamerInfo::kOffsetL: {
00476             TClass *cl                 = fComp[i].fClass;
00477             TMemberStreamer *pstreamer = fComp[i].fStreamer;
00478             DOLOOP {
00479                void **f = (void**)(arr[k]+ioffset);
00480                int j;
00481                for(j=0;j<fLength[i];j++) {
00482                   void *af = f[j];
00483                   if (af)  b << Char_t(1);
00484                   else    {b << Char_t(0); continue;}
00485                   if (pstreamer) (*pstreamer)(b, af, 0);
00486                   else cl->Streamer( af, b );
00487                }
00488             }
00489             continue;
00490          }
00491 
00492 //          case TStreamerInfo::kSTLvarp:           // Variable size array of STL containers.
00493 //             {
00494 //                TMemberStreamer *pstreamer = fComp[i].fStreamer;
00495 //                TClass *cl                 = fComp[i].fClass;
00496 //                UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00497 //                if (pstreamer == 0) {
00498 //                   Int_t size = cl->Size();
00499 //                   Int_t imethod = fMethod[i]+eoffset;
00500 //                   DOLOOP {
00501 //                      char **contp = (char**)(arr[k]+ioffset);
00502 //                      const Int_t *counter = (Int_t*)(arr[k]+imethod);
00503 //                      const Int_t sublen = (*counter);
00504 
00505 //                      for(int j=0;j<fLength[i];++j) {
00506 //                         char *cont = contp[j];
00507 //                         for(int k=0;k<sublen;++k) {
00508 //                            cl->Streamer( cont, b );
00509 //                            cont += size;
00510 //                         }
00511 //                      }
00512 //                   }
00513 //                } else {
00514 //                   DOLOOP{(*pstreamer)(b,arr[k]+ioffset,fLength[i]);}
00515 //                }
00516 //                b.SetByteCount(pos,kTRUE);
00517 //             }
00518 //             continue;
00519 
00520 
00521          case TStreamerInfo::kSTLp:                // Pointer to container with no virtual table (stl) and no comment
00522          case TStreamerInfo::kSTLp + TStreamerInfo::kOffsetL:     // array of pointers to container with no virtual table (stl) and no comment
00523             {
00524                TClass *cl                 = fComp[i].fClass;
00525                TMemberStreamer *pstreamer = fComp[i].fStreamer;
00526                TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
00527                TClass* vClass = proxy ? proxy->GetValueClass() : 0;
00528 
00529                if (!b.TestBit(TBuffer::kCannotHandleMemberWiseStreaming) 
00530                    && proxy && vClass
00531                    && thisVar->GetStreamMemberWise() 
00532                    && cl->CanSplit()
00533                    && !(strspn(aElement->GetTitle(),"||") == 2)
00534                    && !(gInterpreter->ClassInfo_RootFlag(vClass->GetClassInfo()) & 1) ) {
00535                   // Let's save the collection member-wise.
00536 
00537                   UInt_t pos = b.WriteVersionMemberWise(thisVar->IsA(),kTRUE);
00538                   b.WriteVersion( vClass, kFALSE );
00539                   TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
00540                   if (subinfo->IsOptimized()) {
00541                      subinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00542                      subinfo->Compile();
00543                   }
00544                   DOLOOP {
00545                      char **contp = (char**)(arr[k]+ioffset);
00546                      for(int j=0;j<fLength[i];++j) {
00547                         char *cont = contp[j];
00548                         TVirtualCollectionProxy::TPushPop helper( proxy, cont );
00549                         Int_t nobjects = cont ? proxy->Size() : 0;
00550                         b << nobjects;
00551                         subinfo->WriteBufferSTL(b,proxy,nobjects,-1,0);
00552                      }
00553                   }
00554                   b.SetByteCount(pos,kTRUE);
00555                   continue;
00556                }
00557                UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00558                if (pstreamer == 0) {
00559                   DOLOOP {
00560                      char **contp = (char**)(arr[k]+ioffset);
00561                      for(int j=0;j<fLength[i];++j) {
00562                         char *cont = contp[j];
00563                         cl->Streamer( cont, b );
00564                      }
00565                   }
00566                } else {
00567                   DOLOOP{(*pstreamer)(b,arr[k]+ioffset,fLength[i]);}
00568                }
00569                b.SetByteCount(pos,kTRUE);
00570             }
00571             continue;
00572 
00573          case TStreamerInfo::kSTL:             // container with no virtual table (stl) and no comment
00574          case TStreamerInfo::kSTL + TStreamerInfo::kOffsetL:  // array of containers with no virtual table (stl) and no comment
00575             {
00576                TClass *cl                 = fComp[i].fClass;
00577                TMemberStreamer *pstreamer = fComp[i].fStreamer;
00578                TVirtualCollectionProxy *proxy = cl->GetCollectionProxy();
00579                TClass* vClass = proxy ? proxy->GetValueClass() : 0;
00580                if (!b.TestBit(TBuffer::kCannotHandleMemberWiseStreaming)
00581                    && proxy && vClass
00582                    && thisVar->GetStreamMemberWise() && cl->CanSplit()
00583                    && !(strspn(aElement->GetTitle(),"||") == 2)
00584                    && !(vClass->GetClassInfo() && (gInterpreter->ClassInfo_RootFlag(vClass->GetClassInfo()) & 1) ) ) {
00585                   // Let's save the collection in member-wise order.
00586 
00587                   UInt_t pos = b.WriteVersionMemberWise(thisVar->IsA(),kTRUE);
00588                   b.WriteVersion( vClass, kFALSE );
00589                   TStreamerInfo *subinfo = (TStreamerInfo*)vClass->GetStreamerInfo();
00590                   if (subinfo->IsOptimized()) {
00591                      subinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
00592                      subinfo->Compile();
00593                   }
00594                   DOLOOP {
00595                      char *obj = (char*)(arr[k]+ioffset);
00596                      Int_t n = fLength[i];
00597                      if (!n) n=1;
00598                      int size = cl->Size();
00599 
00600                      for(Int_t j=0; j<n; j++,obj+=size) {
00601                         TVirtualCollectionProxy::TPushPop helper( proxy, obj );
00602                         Int_t nobjects = proxy->Size();
00603                         b << nobjects;
00604                         subinfo->WriteBufferSTL(b,proxy,nobjects,-1,0);
00605                      }
00606                   }
00607                   b.SetByteCount(pos,kTRUE);
00608                   continue;
00609                }
00610                UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00611                if (pstreamer == 0) {
00612                   DOLOOP {
00613                      b.WriteFastArray((void*)(arr[k]+ioffset),cl,fLength[i],0);
00614                   }
00615                } else {
00616                   DOLOOP{(*pstreamer)(b,arr[k]+ioffset,fLength[i]);}
00617                }
00618                b.SetByteCount(pos,kTRUE);
00619 
00620                continue;
00621             }
00622 
00623          case TStreamerInfo::kObject:   // Class      derived from TObject
00624          case TStreamerInfo::kAny:   // Class  NOT derived from TObject
00625          case TStreamerInfo::kOffsetL + TStreamerInfo::kObject:
00626          case TStreamerInfo::kAny     + TStreamerInfo::kOffsetL: {
00627             TClass *cl                 = fComp[i].fClass;
00628             TMemberStreamer *pstreamer = fComp[i].fStreamer;
00629             DOLOOP
00630                {b.WriteFastArray((void*)(arr[k]+ioffset),cl,fLength[i],pstreamer);}
00631             continue;
00632          }
00633 
00634          case TStreamerInfo::kOffsetL + TStreamerInfo::kTString:
00635          case TStreamerInfo::kOffsetL + TStreamerInfo::kTObject:
00636          case TStreamerInfo::kOffsetL + TStreamerInfo::kTNamed:
00637          {
00638             TMemberStreamer *pstreamer = fComp[i].fStreamer;
00639             TClass *cl                 = fComp[i].fClass;
00640 
00641             UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00642             DOLOOP {b.WriteFastArray((void*)(arr[k]+ioffset),cl,fLength[i],pstreamer);}
00643             b.SetByteCount(pos,kTRUE);
00644             continue;
00645          }
00646 
00647             // Base Class
00648          case TStreamerInfo::kBase:
00649             if (!(arrayMode&1)) {
00650                TMemberStreamer *pstreamer = fComp[i].fStreamer;
00651                if(pstreamer) {
00652                   // See kStreamer case (similar code)
00653                   UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00654                   DOLOOP{(*pstreamer)(b,arr[k]+ioffset,fLength[i]);}
00655                   b.SetByteCount(pos,kTRUE);
00656                } else {
00657                   DOLOOP { ((TStreamerBase*)aElement)->WriteBuffer(b,arr[k]);}
00658                }
00659             } else {
00660                TClass *cl                 = fComp[i].fClass;
00661                TStreamerInfo *binfo = ((TStreamerInfo*)cl->GetStreamerInfo());
00662                if (!binfo->TestBit(kCannotOptimize) && binfo->IsCompiled()) { 
00663                   binfo->SetBit(kCannotOptimize);
00664                   binfo->Compile();
00665                }
00666                binfo->WriteBufferAux(b,arr,-1,narr,ioffset,arrayMode);
00667             }
00668             continue;
00669 
00670          case TStreamerInfo::kStreamer:
00671          {
00672             TMemberStreamer *pstreamer = fComp[i].fStreamer;
00673 
00674             UInt_t pos = b.WriteVersion(thisVar->IsA(),kTRUE);
00675             if (pstreamer == 0) {
00676                printf("ERROR, Streamer is null\n");
00677                aElement->ls();continue;
00678             } else {
00679                DOLOOP{(*pstreamer)(b,arr[k]+ioffset,fLength[i]);}
00680             }
00681             b.SetByteCount(pos,kTRUE);
00682          }
00683          continue;
00684 
00685          case TStreamerInfo::kStreamLoop:
00686             // -- A pointer to a varying-length array of objects.
00687             // MyClass* ary; //[n]
00688             // -- Or a pointer to a varying-length array of pointers to objects.
00689             // MyClass** ary; //[n]
00690          case TStreamerInfo::kOffsetL + TStreamerInfo::kStreamLoop:
00691             // -- An array of pointers to a varying-length array of objects.
00692             // MyClass* ary[d]; //[n]
00693             // -- Or an array of pointers to a varying-length array of pointers to objects.
00694             // MyClass** ary[d]; //[n]
00695          {
00696             // Get the class of the data member.
00697             TClass* cl = fComp[i].fClass;
00698             // Get any private streamer which was set for the data member.
00699             TMemberStreamer* pstreamer = fComp[i].fStreamer;
00700             // Which are we, an array of objects or an array of pointers to objects?
00701             Bool_t isPtrPtr = (strstr(aElement->GetTypeName(), "**") != 0);
00702             if (pstreamer) {
00703                // -- We have a private streamer.
00704                UInt_t pos = b.WriteVersion(thisVar->IsA(), kTRUE); 
00705                // Loop over the entries in the clones array or the STL container.
00706                for (int k = 0; k < narr; ++k) {
00707                   // Get a pointer to the counter for the varying length array.
00708                   Int_t* counter = (Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + fMethod[i] /*counter offset*/);
00709                   // And call the private streamer, passing it the buffer, the object, and the counter.
00710                   (*pstreamer)(b, arr[k] /*entry pointer*/ + ioffset /*object offset*/, *counter);
00711                }
00712                b.SetByteCount(pos, kTRUE);
00713                // We are done, next streamer element.
00714                continue;
00715             }
00716             // At this point we do *not* have a private streamer.
00717             // Get the version of the file we are writing to.
00718             TFile* file = (TFile*) b.GetParent();
00719             // By default assume the file version is the newest.
00720             Int_t fileVersion = kMaxInt;
00721             if (file) {
00722                fileVersion = file->GetVersion();
00723             }
00724             // Write the class version to the buffer.
00725             UInt_t pos = b.WriteVersion(thisVar->IsA(), kTRUE);
00726             if (fileVersion > 51508) {
00727                // -- Newer versions allow polymorphic pointers to objects.
00728                // Loop over the entries in the clones array or the STL container.
00729                for (int k = 0; k < narr; ++k) {
00730                   // Get the counter for the varying length array.
00731                   Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + fMethod[i] /*counter offset*/));
00732                   //b << vlen;
00733                   if (vlen) {
00734                      // Get a pointer to the array of pointers.
00735                      char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
00736                      // Loop over each element of the array of pointers to varying-length arrays.
00737                      for (Int_t ndx = 0; ndx < fLength[i]; ++ndx) {
00738                         if (!pp[ndx]) {
00739                            // -- We do not have a pointer to a varying-length array.
00740                            Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(), aElement->GetFullName(), fType[i], aElement->GetTypeName());
00741                            continue;
00742                         }
00743                         if (!isPtrPtr) {
00744                            // -- We are a varying-length array of objects.
00745                            // Write the entire array of objects to the buffer.
00746                            // Note: Polymorphism is not allowed here.
00747                            b.WriteFastArray(pp[ndx], cl, vlen, 0);
00748                         }
00749                         else {
00750                            // -- We are a varying-length array of pointers to objects.
00751                            // Write the entire array of object pointers to the buffer.
00752                            // Note: The object pointers are allowed to be polymorphic.
00753                            b.WriteFastArray((void**) pp[ndx], cl, vlen, kFALSE, 0);
00754                         } // isPtrPtr
00755                      } // ndx
00756                   } // vlen
00757                } // k
00758             }
00759             else {
00760                // -- Older versions do *not* allow polymorphic pointers to objects.
00761                // Loop over the entries in the clones array or the STL container.
00762                for (int k = 0; k < narr; ++k) {
00763                   // Get the counter for the varying length array.
00764                   Int_t vlen = *((Int_t*) (arr[k] /*entry pointer*/ + eoffset /*entry offset*/ + fMethod[i] /*counter offset*/));
00765                   //b << vlen;
00766                   if (vlen) {
00767                      // Get a pointer to the array of pointers.
00768                      char** pp = (char**) (arr[k] /*entry pointer*/ + ioffset /*object offset*/);
00769                      // -- Older versions do *not* allow polymorphic pointers to objects.
00770                      // Loop over each element of the array of pointers to varying-length arrays.
00771                      for (Int_t ndx = 0; ndx < fLength[i]; ++ndx) {
00772                         if (!pp[ndx]) {
00773                            // -- We do not have a pointer to a varying-length array.
00774                            Error("WriteBufferAux", "The pointer to element %s::%s type %d (%s) is null\n", thisVar->GetName(), aElement->GetFullName(), fType[i], aElement->GetTypeName());
00775                            continue;
00776                         }
00777                         if (!isPtrPtr) {
00778                            // -- We are a varying-length array of objects.
00779                            // Loop over the elements of the varying length array.
00780                            for (Int_t v = 0; v < vlen; ++v) {
00781                               // Write the object to the buffer.
00782                               cl->Streamer(pp[ndx] + (v * cl->Size()), b);
00783                            } // v
00784                         }
00785                         else {
00786                            // -- We are a varying-length array of pointers to objects.
00787                            // Loop over the elements of the varying length array.
00788                            for (Int_t v = 0; v < vlen; ++v) {
00789                               // Get a pointer to the object pointer.
00790                               char** r = (char**) pp[ndx];
00791                               // Write the object to the buffer.
00792                               cl->Streamer(r[v], b);
00793                            } // v
00794                         } // isPtrPtr
00795                      } // ndx
00796                   } // vlen
00797                } // k
00798             } // fileVersion
00799             // Backpatch the byte count into the buffer.
00800             b.SetByteCount(pos, kTRUE);
00801             continue;
00802          }
00803 
00804          case TStreamerInfo::kCacheNew:
00805             ((TBufferFile&)b).PushDataCache( new TVirtualArray( aElement->GetClassPointer(), narr ) );
00806             continue;
00807          case TStreamerInfo::kCacheDelete:
00808             delete ((TBufferFile&)b).PopDataCache();
00809             continue;
00810          case TStreamerInfo::kArtificial:
00811 #if 0
00812             ROOT::TSchemaRule::WriteFuncPtr_t writefunc = ((TStreamerArtificialElement*)aElement)->GetWriteFunc();
00813             if (writefunc) { 
00814                DOLOOP( writefunc(arr[k]+eoffset, b) );
00815             }
00816 #endif
00817             continue;
00818          default:
00819             Error("WriteBuffer","The element %s::%s type %d (%s) is not supported yet\n",thisVar->GetName(),aElement->GetFullName(),fType[i],aElement->GetTypeName());
00820             continue;
00821       }
00822    }
00823 
00824    b.DecrementLevel(thisVar);
00825 
00826    return 0;
00827 }
00828 
00829 #ifdef R__BROKEN_FUNCTION_TEMPLATES
00830 // Support for non standard compilers
00831 
00832 Int_t TStreamerInfo::WriteBufferAux(TBuffer &b, char ** const &arr, Int_t first,Int_t narr,Int_t eoffset,Int_t mode)
00833 {
00834   return TStreamerInfo__WriteBufferAuxImp(this,b,arr,first,narr,eoffset,mode,
00835                                           fMethod,fElem,fLength,fClass,fOffset,fNewType,
00836                                           fNdata,fType,fgElement,fComp);
00837 }
00838 
00839 Int_t TStreamerInfo::WriteBufferAux(TBuffer &b, const TVirtualCollectionProxy &arr, Int_t first,Int_t narr,Int_t eoffset,Int_t mode)
00840 {
00841   return TStreamerInfo__WriteBufferAuxImp(this,b,arr,first,narr,eoffset,mode,
00842                                           fMethod,fElem,fLength,fClass,fOffset,fNewType,
00843                                           fNdata,fType,fgElement,fComp);
00844 }
00845 
00846 Int_t TStreamerInfo::WriteBufferAux(TBuffer &b, const TPointerCollectionAdapter &arr, Int_t first,Int_t narr,Int_t eoffset,Int_t mode)
00847 {
00848   return TStreamerInfo__WriteBufferAuxImp(this,b,arr,first,narr,eoffset,mode,
00849                                           fMethod,fElem,fLength,fClass,fOffset,fNewType,
00850                                           fNdata,fType,fgElement,fComp);
00851 }
00852 
00853 Int_t TStreamerInfo::WriteBufferAux(TBuffer &b, const TVirtualArray &arr, Int_t first,Int_t narr,Int_t eoffset,Int_t mode)
00854 {
00855    return TStreamerInfo__WriteBufferAuxImp(this,b,arr,first,narr,eoffset,mode,
00856                                            fMethod,fElem,fLength,fClass,fOffset,fNewType,
00857                                            fNdata,fType,fgElement,fComp);
00858 }
00859 
00860 #endif
00861 
00862 //______________________________________________________________________________
00863 Int_t TStreamerInfo::WriteBufferSTL(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t first, Int_t eoffset)
00864 {
00865    // Write for STL container.
00866 
00867    if (!nc) return 0;
00868    R__ASSERT((unsigned int)nc==cont->Size());
00869 
00870    int ret = WriteBufferAux(b, *cont,first,nc,eoffset,1);
00871    return ret;
00872 }
00873 
00874 //______________________________________________________________________________
00875 Int_t TStreamerInfo::WriteBufferSTLPtrs(TBuffer &b, TVirtualCollectionProxy *cont, Int_t nc, Int_t first, Int_t eoffset )
00876 {
00877    // Write for STL container.
00878    if (!nc) return 0;
00879    R__ASSERT((unsigned int)nc==cont->Size());
00880    int ret = WriteBufferAux(b, TPointerCollectionAdapter(cont),first,nc,eoffset,1);
00881    return ret;
00882 }
00883 
00884 
00885 //______________________________________________________________________________
00886 Int_t TStreamerInfo::WriteBuffer(TBuffer &b, char *ipointer, Int_t first)
00887 {
00888    // General Write.
00889 
00890    return WriteBufferAux(b,&ipointer,first,1,0,0);
00891 }
00892 
00893 //______________________________________________________________________________
00894 Int_t TStreamerInfo::WriteBufferClones(TBuffer &b, TClonesArray *clones,
00895                                        Int_t nc, Int_t first, Int_t eoffset)
00896 {
00897    // Write for ClonesArray.
00898 
00899    char **arr = reinterpret_cast<char**>(clones->GetObjectRef(0));
00900    return WriteBufferAux(b,arr,first,nc,eoffset,1);
00901 }
00902 
00903 

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