TBufferFile.cxx

Go to the documentation of this file.
00001 // @(#)root/io:$Id: TBufferFile.cxx 37930 2011-02-01 18:29:06Z pcanal $
00002 // Author: Rene Brun 17/01/2007
00003 
00004 /*************************************************************************
00005  * Copyright (C) 1995-2007, Rene Brun and Fons Rademakers.               *
00006  * All rights reserved.                                                  *
00007  *                                                                       *
00008  * For the licensing terms see $ROOTSYS/LICENSE.                         *
00009  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
00010  *************************************************************************/
00011 
00012 //////////////////////////////////////////////////////////////////////////
00013 //                                                                      //
00014 // TBufferFile                                                          //
00015 //                                                                      //
00016 // The concrete implementation of TBuffer for writing/reading to/from a //
00017 // ROOT file or socket.                                                 //
00018 //                                                                      //
00019 //////////////////////////////////////////////////////////////////////////
00020 
00021 #include <string.h>
00022 #include <typeinfo>
00023 
00024 #include "TFile.h"
00025 #include "TBufferFile.h"
00026 #include "TExMap.h"
00027 #include "TClass.h"
00028 #include "TProcessID.h"
00029 #include "TRefTable.h"
00030 #include "TStorage.h"
00031 #include "TError.h"
00032 #include "TClonesArray.h"
00033 #include "TStreamer.h"
00034 #include "TStreamerInfo.h"
00035 #include "TStreamerElement.h"
00036 #include "TSchemaRuleSet.h"
00037 #include "TStreamerInfoActions.h"
00038 #include "TArrayC.h"
00039 
00040 #if (defined(__linux) || defined(__APPLE__)) && defined(__i386__) && \
00041      defined(__GNUC__)
00042 #define USE_BSWAPCPY
00043 #endif
00044 
00045 #ifdef USE_BSWAPCPY
00046 #include "Bswapcpy.h"
00047 #endif
00048 
00049 
00050 const UInt_t kNullTag           = 0;
00051 const UInt_t kNewClassTag       = 0xFFFFFFFF;
00052 const UInt_t kClassMask         = 0x80000000;  // OR the class index with this
00053 const UInt_t kByteCountMask     = 0x40000000;  // OR the byte count with this
00054 const UInt_t kMaxMapCount       = 0x3FFFFFFE;  // last valid fMapCount and byte count
00055 const Version_t kByteCountVMask = 0x4000;      // OR the version byte count with this
00056 const Version_t kMaxVersion     = 0x3FFF;      // highest possible version number
00057 const Int_t  kMapOffset         = 2;   // first 2 map entries are taken by null obj and self obj
00058 
00059 Int_t TBufferFile::fgMapSize   = kMapSize;
00060 
00061 
00062 ClassImp(TBufferFile)
00063 
00064 //______________________________________________________________________________
00065 static inline ULong_t Void_Hash(const void *ptr)
00066 {
00067    // Return hash value for this object.
00068 
00069    return TString::Hash(&ptr, sizeof(void*));
00070 }
00071 
00072 //______________________________________________________________________________
00073 TBufferFile::TBufferFile(TBuffer::EMode mode)
00074             :TBuffer(mode),
00075              fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
00076              fInfo(0), fInfoStack()
00077 {
00078    // Create an I/O buffer object. Mode should be either TBuffer::kRead or
00079    // TBuffer::kWrite. By default the I/O buffer has a size of
00080    // TBuffer::kInitialSize (1024) bytes.
00081 
00082    fMapCount     = 0;
00083    fMapSize      = fgMapSize;
00084    fMap          = 0;
00085    fClassMap     = 0;
00086    fParent       = 0;
00087    fDisplacement = 0;
00088 }
00089 
00090 //______________________________________________________________________________
00091 TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz)
00092             :TBuffer(mode,bufsiz),
00093              fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
00094              fInfo(0), fInfoStack()
00095 {
00096    // Create an I/O buffer object. Mode should be either TBuffer::kRead or
00097    // TBuffer::kWrite.
00098 
00099    fMapCount = 0;
00100    fMapSize  = fgMapSize;
00101    fMap      = 0;
00102    fClassMap = 0;
00103    fDisplacement = 0;
00104 }
00105 
00106 //______________________________________________________________________________
00107 TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc) :
00108    TBuffer(mode,bufsiz,buf,adopt,reallocfunc),
00109    fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
00110    fInfo(0), fInfoStack()
00111 {
00112    // Create an I/O buffer object. Mode should be either TBuffer::kRead or
00113    // TBuffer::kWrite. By default the I/O buffer has a size of
00114    // TBuffer::kInitialSize (1024) bytes. An external buffer can be passed
00115    // to TBuffer via the buf argument. By default this buffer will be adopted
00116    // unless adopt is false.
00117    // If the new buffer is _not_ adopted and no memory allocation routine
00118    // is provided, a Fatal error will be issued if the Buffer attempts to
00119    // expand.
00120 
00121    fMapCount = 0;
00122    fMapSize  = fgMapSize;
00123    fMap      = 0;
00124    fClassMap = 0;
00125    fDisplacement = 0;
00126 }
00127 
00128 //______________________________________________________________________________
00129 TBufferFile::~TBufferFile()
00130 {
00131    // Delete an I/O buffer object.
00132 
00133    delete fMap;
00134    delete fClassMap;
00135 }
00136 
00137 //______________________________________________________________________________
00138 Int_t TBufferFile::GetVersionOwner() const
00139 {
00140    // Return the version number of the owner file.
00141 
00142    TFile *file = (TFile*)GetParent();
00143    if (file) return file->GetVersion();
00144    else return 0;
00145 }
00146 
00147 //______________________________________________________________________________
00148 void TBufferFile::TagStreamerInfo(TVirtualStreamerInfo* info)
00149 {
00150    // Mark the classindex of the current file as using this TStreamerInfo
00151 
00152    TFile *file = (TFile*)GetParent();
00153    if (file) {
00154       TArrayC *cindex = file->GetClassIndex();
00155       Int_t nindex = cindex->GetSize();
00156       Int_t number = info->GetNumber();
00157       if (number < 0 || number >= nindex) {
00158          Error("TagStreamerInfo","StreamerInfo: %s number: %d out of range[0,%d] in file: %s",
00159                info->GetName(),number,nindex,file->GetName());
00160          return;
00161       }
00162       if (cindex->fArray[number] == 0) {
00163          cindex->fArray[0]       = 1;
00164          cindex->fArray[number] = 1;
00165       }
00166    }
00167 }
00168 
00169 //______________________________________________________________________________
00170 void TBufferFile::IncrementLevel(TVirtualStreamerInfo* info)
00171 {
00172    // Increment level.
00173 
00174    fInfoStack.push_back(fInfo);
00175    fInfo = (TStreamerInfo*)info;
00176 }
00177 
00178 //______________________________________________________________________________
00179 void TBufferFile::DecrementLevel(TVirtualStreamerInfo* /*info*/)
00180 {
00181    // Decrement level.
00182 
00183    fInfo = fInfoStack.back();
00184    fInfoStack.pop_back();
00185 }
00186 
00187 //______________________________________________________________________________
00188 static void frombufOld(char *&buf, Long_t *x)
00189 {
00190    // Files written with versions older than 3.00/06 had a non-portable
00191    // implementation of Long_t/ULong_t. These types should not have been
00192    // used at all. However, because some users had already written many
00193    // files with these types we provide this dirty patch for "backward
00194    // compatibility"
00195 
00196 #ifdef R__BYTESWAP
00197 #ifdef R__B64
00198    char *sw = (char *)x;
00199    sw[0] = buf[7];
00200    sw[1] = buf[6];
00201    sw[2] = buf[5];
00202    sw[3] = buf[4];
00203    sw[4] = buf[3];
00204    sw[5] = buf[2];
00205    sw[6] = buf[1];
00206    sw[7] = buf[0];
00207 #else
00208    char *sw = (char *)x;
00209    sw[0] = buf[3];
00210    sw[1] = buf[2];
00211    sw[2] = buf[1];
00212    sw[3] = buf[0];
00213 #endif
00214 #else
00215    memcpy(x, buf, sizeof(Long_t));
00216 #endif
00217    buf += sizeof(Long_t);
00218 }
00219 
00220 //______________________________________________________________________________
00221 void TBufferFile::ReadLong(Long_t &l)
00222 {
00223    // Read Long from TBuffer.
00224 
00225    TFile *file = (TFile*)fParent;
00226    if (file && file->GetVersion() < 30006) {
00227       frombufOld(fBufCur, &l);
00228    } else {
00229       frombuf(fBufCur, &l);
00230    }
00231 }
00232 
00233 //_______________________________________________________________________
00234 void TBufferFile::ReadTString(TString &s)
00235 {
00236    // Read string from TBuffer.
00237 
00238    s.Streamer(*this);
00239 }
00240 
00241 //_______________________________________________________________________
00242 void TBufferFile::WriteTString(const TString &s)
00243 {
00244    // Write string to TBuffer.
00245 
00246    ((TString&)s).Streamer(*this);
00247 }
00248 
00249 //______________________________________________________________________________
00250 void TBufferFile::SetByteCount(UInt_t cntpos, Bool_t packInVersion)
00251 {
00252    // Set byte count at position cntpos in the buffer. Generate warning if
00253    // count larger than kMaxMapCount. The count is excluded its own size.
00254 
00255    UInt_t cnt = UInt_t(fBufCur - fBuffer) - cntpos - sizeof(UInt_t);
00256    char  *buf = (char *)(fBuffer + cntpos);
00257 
00258    // if true, pack byte count in two consecutive shorts, so it can
00259    // be read by ReadVersion()
00260    if (packInVersion) {
00261       union {
00262          UInt_t    cnt;
00263          Version_t vers[2];
00264       } v;
00265       v.cnt = cnt;
00266 #ifdef R__BYTESWAP
00267       tobuf(buf, Version_t(v.vers[1] | kByteCountVMask));
00268       tobuf(buf, v.vers[0]);
00269 #else
00270       tobuf(buf, Version_t(v.vers[0] | kByteCountVMask));
00271       tobuf(buf, v.vers[1]);
00272 #endif
00273    } else
00274       tobuf(buf, cnt | kByteCountMask);
00275 
00276    if (cnt >= kMaxMapCount) {
00277       Error("WriteByteCount", "bytecount too large (more than %d)", kMaxMapCount);
00278       // exception
00279    }
00280 }
00281 
00282 //______________________________________________________________________________
00283 Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss, const char *classname)
00284 {
00285    // Check byte count with current buffer position. They should
00286    // match. If not print warning and position buffer in correct
00287    // place determined by the byte count. Startpos is position of
00288    // first byte where the byte count is written in buffer.
00289    // Returns 0 if everything is ok, otherwise the bytecount offset
00290    // (< 0 when read too little, >0 when read too much).
00291 
00292    if (!bcnt) return 0;
00293 
00294    Int_t  offset = 0;
00295 
00296    Long_t endpos = Long_t(fBuffer) + startpos + bcnt + sizeof(UInt_t);
00297 
00298    if (Long_t(fBufCur) != endpos) {
00299       offset = Int_t(Long_t(fBufCur) - endpos);
00300 
00301       const char *name = clss ? clss->GetName() : classname ? classname : 0;
00302 
00303       if (name) {
00304          if (offset < 0) {
00305             Error("CheckByteCount", "object of class %s read too few bytes: %d instead of %d",
00306                   name,bcnt+offset,bcnt);
00307          }
00308          if (offset > 0) {
00309             Error("CheckByteCount", "object of class %s read too many bytes: %d instead of %d",
00310                   name,bcnt+offset,bcnt);
00311             if (fParent)
00312                Warning("CheckByteCount","%s::Streamer() not in sync with data on file %s, fix Streamer()",
00313                        name, fParent->GetName());
00314             else
00315                Warning("CheckByteCount","%s::Streamer() not in sync with data, fix Streamer()",
00316                        name);
00317          }
00318       }
00319       if ( ((char *)endpos) > fBufMax ) {
00320          offset = fBufMax-fBufCur;
00321          Error("CheckByteCount",
00322                "Byte count probably corrupted around buffer position %d:\n\t%d for a possible maximum of %d",
00323                startpos, bcnt, offset);
00324          fBufCur = fBufMax;
00325 
00326       } else {
00327 
00328          fBufCur = (char *) endpos;
00329 
00330       }
00331    }
00332    return offset;
00333 }
00334 
00335 //______________________________________________________________________________
00336 Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)
00337 {
00338    // Check byte count with current buffer position. They should
00339    // match. If not print warning and position buffer in correct
00340    // place determined by the byte count. Startpos is position of
00341    // first byte where the byte count is written in buffer.
00342    // Returns 0 if everything is ok, otherwise the bytecount offset
00343    // (< 0 when read too little, >0 when read too much).
00344 
00345    if (!bcnt) return 0;
00346    return CheckByteCount( startpos, bcnt, clss, 0);
00347 }
00348 
00349 //______________________________________________________________________________
00350 Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *classname)
00351 {
00352    // Check byte count with current buffer position. They should
00353    // match. If not print warning and position buffer in correct
00354    // place determined by the byte count. Startpos is position of
00355    // first byte where the byte count is written in buffer.
00356    // Returns 0 if everything is ok, otherwise the bytecount offset
00357    // (< 0 when read too little, >0 when read too much).
00358 
00359    if (!bcnt) return 0;
00360    return CheckByteCount( startpos, bcnt, 0, classname);
00361 }
00362 
00363 //______________________________________________________________________________
00364 void TBufferFile::ReadFloat16(Float_t *f, TStreamerElement *ele)
00365 {
00366    // Read a Float16_t from the buffer,
00367    // see comments about Float16_t encoding at TBufferFile::WriteFloat16().
00368 
00369    if (ele && ele->GetFactor() != 0) {
00370       ReadWithFactor(f, ele->GetFactor(), ele->GetXmin());
00371    } else {
00372       Int_t nbits = 0;
00373       if (ele) nbits = (Int_t)ele->GetXmin();
00374       if (!nbits) nbits = 12;
00375       ReadWithNbits(f, nbits);      
00376    }
00377 }
00378 
00379 //______________________________________________________________________________
00380 void TBufferFile::ReadDouble32(Double_t *d, TStreamerElement *ele)
00381 {
00382    // Read a Double32_t from the buffer,
00383    // see comments about Double32_t encoding at TBufferFile::WriteDouble32().
00384 
00385    if (ele && ele->GetFactor() != 0) {
00386       ReadWithFactor(d, ele->GetFactor(), ele->GetXmin());
00387    } else {
00388       Int_t nbits = 0;
00389       if (ele) nbits = (Int_t)ele->GetXmin();
00390       if (!nbits) {
00391          //we read a float and convert it to double
00392          Float_t afloat;
00393          *this >> afloat;
00394          d[0] = (Double_t)afloat;
00395       } else {
00396          ReadWithNbits(d, nbits);      
00397       }
00398    }
00399 }
00400 
00401 //______________________________________________________________________________
00402 void TBufferFile::ReadWithFactor(Float_t *ptr, Double_t factor, Double_t minvalue)
00403 {
00404    // Read a Double32_t from the buffer when the factor and minimun value have been specified
00405    // see comments about Double32_t encoding at TBufferFile::WriteDouble32().
00406 
00407    //a range was specified. We read an integer and convert it back to a double.
00408    UInt_t aint; 
00409    frombuf(this->fBufCur,&aint); 
00410    ptr[0] = (Float_t)(aint/factor + minvalue);
00411 }
00412 
00413 //______________________________________________________________________________
00414 void TBufferFile::ReadWithNbits(Float_t *ptr, Int_t nbits) 
00415 {
00416    // Read a Float16_t from the buffer when the number of bits is specified (explicitly or not)
00417    // see comments about Float16_t encoding at TBufferFile::WriteFloat16().
00418 
00419    //we read the exponent and the truncated mantissa of the float
00420    //and rebuild the float.
00421    union {
00422       Float_t xx;
00423       Int_t ix;
00424    } temp;
00425    UChar_t  theExp;
00426    UShort_t theMan;
00427    frombuf(this->fBufCur,&theExp);
00428    frombuf(this->fBufCur,&theMan);
00429    temp.ix = theExp;
00430    temp.ix <<= 23;
00431    temp.ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
00432    if(1<<(nbits+1) & theMan) temp.xx = -temp.xx;
00433    ptr[0] = temp.xx;
00434 }
00435 
00436 //______________________________________________________________________________
00437 void TBufferFile::ReadWithFactor(Double_t *ptr, Double_t factor, Double_t minvalue) 
00438 {
00439    // Read a Double32_t from the buffer when the factor and minimun value have been specified
00440    // see comments about Double32_t encoding at TBufferFile::WriteDouble32().
00441 
00442    //a range was specified. We read an integer and convert it back to a double.
00443    UInt_t aint; 
00444    frombuf(this->fBufCur,&aint); 
00445    ptr[0] = (Double_t)(aint/factor + minvalue);
00446 }
00447 
00448 //______________________________________________________________________________
00449 void TBufferFile::ReadWithNbits(Double_t *ptr, Int_t nbits) 
00450 {
00451    // Read a Double32_t from the buffer when the number of bits is specified (explicitly or not)
00452    // see comments about Double32_t encoding at TBufferFile::WriteDouble32().
00453 
00454    //we read the exponent and the truncated mantissa of the float
00455    //and rebuild the float.
00456    union {
00457       Float_t xx;
00458       Int_t ix;
00459    } temp;
00460    UChar_t  theExp;
00461    UShort_t theMan;
00462    frombuf(this->fBufCur,&theExp);
00463    frombuf(this->fBufCur,&theMan);
00464    temp.ix = theExp;
00465    temp.ix <<= 23;
00466    temp.ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
00467    if(1<<(nbits+1) & theMan) temp.xx = -temp.xx;
00468    ptr[0] = (Double_t)temp.xx;
00469 }
00470 
00471 //______________________________________________________________________________
00472 void TBufferFile::WriteFloat16(Float_t *f, TStreamerElement *ele)
00473 {
00474    // write a Float16_t to the buffer.
00475    // The following cases are supported for streaming a Float16_t type
00476    // depending on the range declaration in the comment field of the data member:
00477    //  A-    Float16_t     fNormal;
00478    //  B-    Float16_t     fTemperature; //[0,100]
00479    //  C-    Float16_t     fCharge;      //[-1,1,2]
00480    //  D-    Float16_t     fVertex[3];   //[-30,30,10]
00481    //  E-    Float16_t     fChi2;        //[0,0,6]
00482    //  F-    Int_t          fNsp;
00483    //        Float16_t*    fPointValue;   //[fNsp][0,3]
00484    //
00485    // In case A fNormal is converted from a Float_t to a Float_t with mantissa truncated to 12 bits
00486    // In case B fTemperature is converted to a 32 bit unsigned integer
00487    // In case C fCharge is converted to a 2 bits unsigned integer
00488    // In case D the array elements of fVertex are converted to an unsigned 10 bits integer
00489    // In case E fChi2 is converted to a Float_t with truncated precision at 6 bits
00490    // In case F the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer
00491    //           Note that the range specifier must follow the dimension specifier.
00492    // the case B has more precision (9 to 10 significative digits than case A (6 to 7 digits).
00493    //
00494    // The range specifier has the general format: [xmin,xmax] or [xmin,xmax,nbits]
00495    //  [0,1]
00496    //  [-10,100];
00497    //  [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi]
00498    //  [-10,100,16]
00499    //  [0,0,8]
00500    // if nbits is not specified, or nbits <2 or nbits>16 it is set to 16
00501    // if (xmin==0 and xmax==0 and nbits <=14) the float word will have
00502    // its mantissa truncated to nbits significative bits.
00503    //
00504    // IMPORTANT NOTE
00505    // --------------
00506    // --NOTE 1
00507    // Lets assume an original variable float x:
00508    // When using the format [0,0,8] (ie range not specified) you get the best
00509    // relative precision when storing and reading back the truncated x, say xt.
00510    // The variance of (x-xt)/x will be better than when specifying a range
00511    // for the same number of bits. However the precision relative to the
00512    // range (x-xt)/(xmax-xmin) will be worst, and vice-versa.
00513    // The format [0,0,8] is also interesting when the range of x is infinite
00514    // or unknown.
00515    //
00516    // --NOTE 2
00517    // It is important to understand the difference with the meaning of nbits
00518    //  -in case of [-1,1,nbits], nbits is the total number of bits used to make
00519    //    the conversion from a float to an integer
00520    //  -in case of [0,0,nbits], nbits is the number of bits used for the mantissa
00521    //
00522    //  see example of use of the Float16_t data type in tutorial double32.C
00523    //
00524    //Begin_Html
00525    /*
00526      <img src="gif/double32.gif">
00527    */
00528    //End_Html
00529 
00530    if (ele && ele->GetFactor() != 0) {
00531       //A range is specified. We normalize the double to the range and
00532       //convert it to an integer using a scaling factor that is a function of nbits.
00533       //see TStreamerElement::GetRange.
00534       Double_t x = f[0];
00535       Double_t xmin = ele->GetXmin();
00536       Double_t xmax = ele->GetXmax();
00537       if (x < xmin) x = xmin;
00538       if (x > xmax) x = xmax;
00539       UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
00540    } else {
00541       Int_t nbits = 0;
00542       //number of bits stored in fXmin (see TStreamerElement::GetRange)
00543       if (ele) nbits = (Int_t)ele->GetXmin();
00544       if (!nbits) nbits = 12;
00545       //a range is not specified, but nbits is.
00546       //In this case we truncate the mantissa to nbits and we stream
00547       //the exponent as a UChar_t and the mantissa as a UShort_t.
00548       union {
00549          Float_t xx;
00550          Int_t ix;
00551       };
00552       xx = f[0];
00553       UChar_t  theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
00554       UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
00555       theMan++;
00556       theMan = theMan>>1;
00557       if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
00558       if (xx < 0) theMan |= 1<<(nbits+1);
00559       *this << theExp;
00560       *this << theMan;
00561    }
00562 }
00563 
00564 //______________________________________________________________________________
00565 void TBufferFile::WriteDouble32(Double_t *d, TStreamerElement *ele)
00566 {
00567    // write a Double32_t to the buffer.
00568    // The following cases are supported for streaming a Double32_t type
00569    // depending on the range declaration in the comment field of the data member:
00570    //  A-    Double32_t     fNormal;
00571    //  B-    Double32_t     fTemperature; //[0,100]
00572    //  C-    Double32_t     fCharge;      //[-1,1,2]
00573    //  D-    Double32_t     fVertex[3];   //[-30,30,10]
00574    //  E-    Double32_t     fChi2;        //[0,0,6]
00575    //  F-    Int_t          fNsp;
00576    //        Double32_t*    fPointValue;   //[fNsp][0,3]
00577    //
00578    // In case A fNormal is converted from a Double_t to a Float_t
00579    // In case B fTemperature is converted to a 32 bit unsigned integer
00580    // In case C fCharge is converted to a 2 bits unsigned integer
00581    // In case D the array elements of fVertex are converted to an unsigned 10 bits integer
00582    // In case E fChi2 is converted to a Float_t with mantissa truncated precision at 6 bits
00583    // In case F the fNsp elements of array fPointvalue are converted to an unsigned 32 bit integer
00584    //           Note that the range specifier must follow the dimension specifier.
00585    // the case B has more precision (9 to 10 significative digits than case A (6 to 7 digits).
00586    //
00587    // The range specifier has the general format: [xmin,xmax] or [xmin,xmax,nbits]
00588    //  [0,1]
00589    //  [-10,100];
00590    //  [-pi,pi], [-pi/2,pi/4],[-2pi,2*pi]
00591    //  [-10,100,16]
00592    //  [0,0,8]
00593    // if nbits is not specified, or nbits <2 or nbits>32 it is set to 32
00594    // if (xmin==0 and xmax==0 and nbits <=14) the double word will be converted
00595    // to a float and its mantissa truncated to nbits significative bits.
00596    //
00597    // IMPORTANT NOTEs
00598    // --------------
00599    // --NOTE 1
00600    // Lets assume an original variable double x:
00601    // When using the format [0,0,8] (ie range not specified) you get the best
00602    // relative precision when storing and reading back the truncated x, say xt.
00603    // The variance of (x-xt)/x will be better than when specifying a range
00604    // for the same number of bits. However the precision relative to the
00605    // range (x-xt)/(xmax-xmin) will be worst, and vice-versa.
00606    // The format [0,0,8] is also interesting when the range of x is infinite
00607    // or unknown.
00608    //
00609    // --NOTE 2
00610    // It is important to understand the difference with the meaning of nbits
00611    //  -in case of [-1,1,nbits], nbits is the total number of bits used to make
00612    //    the conversion from a double to an integer
00613    //  -in case of [0,0,nbits], nbits is the number of bits used for the mantissa
00614    //
00615    //  see example of use of the Double32_t data type in tutorial double32.C
00616    //
00617    //Begin_Html
00618    /*
00619      <img src="gif/double32.gif">
00620    */
00621    //End_Html
00622 
00623    if (ele && ele->GetFactor() != 0) {
00624       //A range is specified. We normalize the double to the range and
00625       //convert it to an integer using a scaling factor that is a function of nbits.
00626       //see TStreamerElement::GetRange.
00627       Double_t x = d[0];
00628       Double_t xmin = ele->GetXmin();
00629       Double_t xmax = ele->GetXmax();
00630       if (x < xmin) x = xmin;
00631       if (x > xmax) x = xmax;
00632       UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
00633    } else {
00634       Int_t nbits = 0;
00635       //number of bits stored in fXmin (see TStreamerElement::GetRange)
00636       if (ele) nbits = (Int_t)ele->GetXmin();
00637       if (!nbits) {
00638          //if no range and no bits specified, we convert from double to float
00639          Float_t afloat = (Float_t)d[0];
00640          *this << afloat;
00641       } else {
00642          //a range is not specified, but nbits is.
00643          //In this case we truncate the mantissa to nbits and we stream
00644          //the exponent as a UChar_t and the mantissa as a UShort_t.
00645          union {
00646             Float_t xx;
00647             Int_t ix;
00648          };
00649          xx = (Float_t)d[0];
00650          UChar_t  theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
00651          UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1)) ;
00652          theMan++;
00653          theMan = theMan>>1;
00654          if (theMan&1<<nbits) theMan = (1<<nbits)-1 ;
00655          if (xx < 0) theMan |= 1<<(nbits+1);
00656          *this << theExp;
00657          *this << theMan;
00658       }
00659    }
00660 }
00661 
00662 //______________________________________________________________________________
00663 Int_t TBufferFile::ReadArray(Bool_t *&b)
00664 {
00665    // Read array of bools from the I/O buffer. Returns the number of
00666    // bools read. If argument is a 0 pointer then space will be
00667    // allocated for the array.
00668 
00669    R__ASSERT(IsReading());
00670 
00671    Int_t n;
00672    *this >> n;
00673 
00674    if (n <= 0 || n > fBufSize) return 0;
00675 
00676    if (!b) b = new Bool_t[n];
00677 
00678    if (sizeof(Bool_t) > 1) {
00679       for (int i = 0; i < n; i++)
00680          frombuf(fBufCur, &b[i]);
00681    } else {
00682       Int_t l = sizeof(Bool_t)*n;
00683       memcpy(b, fBufCur, l);
00684       fBufCur += l;
00685    }
00686 
00687    return n;
00688 }
00689 
00690 //______________________________________________________________________________
00691 Int_t TBufferFile::ReadArray(Char_t *&c)
00692 {
00693    // Read array of characters from the I/O buffer. Returns the number of
00694    // characters read. If argument is a 0 pointer then space will be
00695    // allocated for the array.
00696 
00697    R__ASSERT(IsReading());
00698 
00699    Int_t n;
00700    *this >> n;
00701    Int_t l = sizeof(Char_t)*n;
00702 
00703    if (l <= 0 || l > fBufSize) return 0;
00704 
00705    if (!c) c = new Char_t[n];
00706 
00707    memcpy(c, fBufCur, l);
00708    fBufCur += l;
00709 
00710    return n;
00711 }
00712 
00713 //______________________________________________________________________________
00714 Int_t TBufferFile::ReadArray(Short_t *&h)
00715 {
00716    // Read array of shorts from the I/O buffer. Returns the number of shorts
00717    // read. If argument is a 0 pointer then space will be allocated for the
00718    // array.
00719 
00720    R__ASSERT(IsReading());
00721 
00722    Int_t n;
00723    *this >> n;
00724    Int_t l = sizeof(Short_t)*n;
00725 
00726    if (l <= 0 || l > fBufSize) return 0;
00727 
00728    if (!h) h = new Short_t[n];
00729 
00730 #ifdef R__BYTESWAP
00731 # ifdef USE_BSWAPCPY
00732    bswapcpy16(h, fBufCur, n);
00733    fBufCur += l;
00734 # else
00735    for (int i = 0; i < n; i++)
00736       frombuf(fBufCur, &h[i]);
00737 # endif
00738 #else
00739    memcpy(h, fBufCur, l);
00740    fBufCur += l;
00741 #endif
00742 
00743    return n;
00744 }
00745 
00746 //______________________________________________________________________________
00747 Int_t TBufferFile::ReadArray(Int_t *&ii)
00748 {
00749    // Read array of ints from the I/O buffer. Returns the number of ints
00750    // read. If argument is a 0 pointer then space will be allocated for the
00751    // array.
00752 
00753    R__ASSERT(IsReading());
00754 
00755    Int_t n;
00756    *this >> n;
00757    Int_t l = sizeof(Int_t)*n;
00758 
00759    if (l <= 0 || l > fBufSize) return 0;
00760 
00761    if (!ii) ii = new Int_t[n];
00762 
00763 #ifdef R__BYTESWAP
00764 # ifdef USE_BSWAPCPY
00765    bswapcpy32(ii, fBufCur, n);
00766    fBufCur += l;
00767 # else
00768    for (int i = 0; i < n; i++)
00769       frombuf(fBufCur, &ii[i]);
00770 # endif
00771 #else
00772    memcpy(ii, fBufCur, l);
00773    fBufCur += l;
00774 #endif
00775 
00776    return n;
00777 }
00778 
00779 //______________________________________________________________________________
00780 Int_t TBufferFile::ReadArray(Long_t *&ll)
00781 {
00782    // Read array of longs from the I/O buffer. Returns the number of longs
00783    // read. If argument is a 0 pointer then space will be allocated for the
00784    // array.
00785 
00786    R__ASSERT(IsReading());
00787 
00788    Int_t n;
00789    *this >> n;
00790    Int_t l = sizeof(Long_t)*n;
00791 
00792    if (l <= 0 || l > fBufSize) return 0;
00793 
00794    if (!ll) ll = new Long_t[n];
00795 
00796    TFile *file = (TFile*)fParent;
00797    if (file && file->GetVersion() < 30006) {
00798       for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
00799    } else {
00800       for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
00801    }
00802    return n;
00803 }
00804 
00805 //______________________________________________________________________________
00806 Int_t TBufferFile::ReadArray(Long64_t *&ll)
00807 {
00808    // Read array of long longs from the I/O buffer. Returns the number of
00809    // long longs read. If argument is a 0 pointer then space will be
00810    // allocated for the array.
00811 
00812    R__ASSERT(IsReading());
00813 
00814    Int_t n;
00815    *this >> n;
00816    Int_t l = sizeof(Long64_t)*n;
00817 
00818    if (l <= 0 || l > fBufSize) return 0;
00819 
00820    if (!ll) ll = new Long64_t[n];
00821 
00822 #ifdef R__BYTESWAP
00823    for (int i = 0; i < n; i++)
00824       frombuf(fBufCur, &ll[i]);
00825 #else
00826    memcpy(ll, fBufCur, l);
00827    fBufCur += l;
00828 #endif
00829 
00830    return n;
00831 }
00832 
00833 //______________________________________________________________________________
00834 Int_t TBufferFile::ReadArray(Float_t *&f)
00835 {
00836    // Read array of floats from the I/O buffer. Returns the number of floats
00837    // read. If argument is a 0 pointer then space will be allocated for the
00838    // array.
00839 
00840    R__ASSERT(IsReading());
00841 
00842    Int_t n;
00843    *this >> n;
00844    Int_t l = sizeof(Float_t)*n;
00845 
00846    if (l <= 0 || l > fBufSize) return 0;
00847 
00848    if (!f) f = new Float_t[n];
00849 
00850 #ifdef R__BYTESWAP
00851 # ifdef USE_BSWAPCPY
00852    bswapcpy32(f, fBufCur, n);
00853    fBufCur += l;
00854 # else
00855    for (int i = 0; i < n; i++)
00856       frombuf(fBufCur, &f[i]);
00857 # endif
00858 #else
00859    memcpy(f, fBufCur, l);
00860    fBufCur += l;
00861 #endif
00862 
00863    return n;
00864 }
00865 
00866 //______________________________________________________________________________
00867 Int_t TBufferFile::ReadArray(Double_t *&d)
00868 {
00869    // Read array of doubles from the I/O buffer. Returns the number of doubles
00870    // read. If argument is a 0 pointer then space will be allocated for the
00871    // array.
00872 
00873    R__ASSERT(IsReading());
00874 
00875    Int_t n;
00876    *this >> n;
00877    Int_t l = sizeof(Double_t)*n;
00878 
00879    if (l <= 0 || l > fBufSize) return 0;
00880 
00881    if (!d) d = new Double_t[n];
00882 
00883 #ifdef R__BYTESWAP
00884    for (int i = 0; i < n; i++)
00885       frombuf(fBufCur, &d[i]);
00886 #else
00887    memcpy(d, fBufCur, l);
00888    fBufCur += l;
00889 #endif
00890 
00891    return n;
00892 }
00893 
00894 //______________________________________________________________________________
00895 Int_t TBufferFile::ReadArrayFloat16(Float_t *&f, TStreamerElement *ele)
00896 {
00897    // Read array of floats (written as truncated float) from the I/O buffer.
00898    // Returns the number of floats read.
00899    // If argument is a 0 pointer then space will be allocated for the array.
00900    // see comments about Float16_t encoding at TBufferFile::WriteFloat16
00901 
00902    R__ASSERT(IsReading());
00903 
00904    Int_t n;
00905    *this >> n;
00906 
00907    if (n <= 0 || 3*n > fBufSize) return 0;
00908 
00909    if (!f) f = new Float_t[n];
00910 
00911    ReadFastArrayFloat16(f,n,ele);
00912 
00913    return n;
00914 }
00915 
00916 //______________________________________________________________________________
00917 Int_t TBufferFile::ReadArrayDouble32(Double_t *&d, TStreamerElement *ele)
00918 {
00919    // Read array of doubles (written as float) from the I/O buffer.
00920    // Returns the number of doubles read.
00921    // If argument is a 0 pointer then space will be allocated for the array.
00922    // see comments about Double32_t encoding at TBufferFile::WriteDouble32
00923 
00924    R__ASSERT(IsReading());
00925 
00926    Int_t n;
00927    *this >> n;
00928 
00929    if (n <= 0 || 3*n > fBufSize) return 0;
00930 
00931    if (!d) d = new Double_t[n];
00932 
00933    ReadFastArrayDouble32(d,n,ele);
00934 
00935    return n;
00936 }
00937 
00938 //______________________________________________________________________________
00939 Int_t TBufferFile::ReadStaticArray(Bool_t *b)
00940 {
00941    // Read array of bools from the I/O buffer. Returns the number of bools
00942    // read.
00943 
00944    R__ASSERT(IsReading());
00945 
00946    Int_t n;
00947    *this >> n;
00948 
00949    if (n <= 0 || n > fBufSize) return 0;
00950 
00951    if (!b) return 0;
00952 
00953    if (sizeof(Bool_t) > 1) {
00954       for (int i = 0; i < n; i++)
00955          frombuf(fBufCur, &b[i]);
00956    } else {
00957       Int_t l = sizeof(Bool_t)*n;
00958       memcpy(b, fBufCur, l);
00959       fBufCur += l;
00960    }
00961 
00962    return n;
00963 }
00964 
00965 //______________________________________________________________________________
00966 Int_t TBufferFile::ReadStaticArray(Char_t *c)
00967 {
00968    // Read array of characters from the I/O buffer. Returns the number of
00969    // characters read.
00970 
00971    R__ASSERT(IsReading());
00972 
00973    Int_t n;
00974    *this >> n;
00975    Int_t l = sizeof(Char_t)*n;
00976 
00977    if (l <= 0 || l > fBufSize) return 0;
00978 
00979    if (!c) return 0;
00980 
00981    memcpy(c, fBufCur, l);
00982    fBufCur += l;
00983 
00984    return n;
00985 }
00986 
00987 //______________________________________________________________________________
00988 Int_t TBufferFile::ReadStaticArray(Short_t *h)
00989 {
00990    // Read array of shorts from the I/O buffer. Returns the number of shorts
00991    // read.
00992 
00993    R__ASSERT(IsReading());
00994 
00995    Int_t n;
00996    *this >> n;
00997    Int_t l = sizeof(Short_t)*n;
00998 
00999    if (l <= 0 || l > fBufSize) return 0;
01000 
01001    if (!h) return 0;
01002 
01003 #ifdef R__BYTESWAP
01004 # ifdef USE_BSWAPCPY
01005    bswapcpy16(h, fBufCur, n);
01006    fBufCur += l;
01007 # else
01008    for (int i = 0; i < n; i++)
01009       frombuf(fBufCur, &h[i]);
01010 # endif
01011 #else
01012    memcpy(h, fBufCur, l);
01013    fBufCur += l;
01014 #endif
01015 
01016    return n;
01017 }
01018 
01019 //______________________________________________________________________________
01020 Int_t TBufferFile::ReadStaticArray(Int_t *ii)
01021 {
01022    // Read array of ints from the I/O buffer. Returns the number of ints
01023    // read.
01024 
01025    R__ASSERT(IsReading());
01026 
01027    Int_t n;
01028    *this >> n;
01029    Int_t l = sizeof(Int_t)*n;
01030 
01031    if (l <= 0 || l > fBufSize) return 0;
01032 
01033    if (!ii) return 0;
01034 
01035 #ifdef R__BYTESWAP
01036 # ifdef USE_BSWAPCPY
01037    bswapcpy32(ii, fBufCur, n);
01038    fBufCur += sizeof(Int_t)*n;
01039 # else
01040    for (int i = 0; i < n; i++)
01041       frombuf(fBufCur, &ii[i]);
01042 # endif
01043 #else
01044    memcpy(ii, fBufCur, l);
01045    fBufCur += l;
01046 #endif
01047 
01048    return n;
01049 }
01050 
01051 //______________________________________________________________________________
01052 Int_t TBufferFile::ReadStaticArray(Long_t *ll)
01053 {
01054    // Read array of longs from the I/O buffer. Returns the number of longs
01055    // read.
01056 
01057    R__ASSERT(IsReading());
01058 
01059    Int_t n;
01060    *this >> n;
01061    Int_t l = sizeof(Long_t)*n;
01062 
01063    if (l <= 0 || l > fBufSize) return 0;
01064 
01065    if (!ll) return 0;
01066 
01067    TFile *file = (TFile*)fParent;
01068    if (file && file->GetVersion() < 30006) {
01069       for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
01070    } else {
01071       for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
01072    }
01073    return n;
01074 }
01075 
01076 //______________________________________________________________________________
01077 Int_t TBufferFile::ReadStaticArray(Long64_t *ll)
01078 {
01079    // Read array of long longs from the I/O buffer. Returns the number of
01080    // long longs read.
01081 
01082    R__ASSERT(IsReading());
01083 
01084    Int_t n;
01085    *this >> n;
01086    Int_t l = sizeof(Long64_t)*n;
01087 
01088    if (l <= 0 || l > fBufSize) return 0;
01089 
01090    if (!ll) return 0;
01091 
01092 #ifdef R__BYTESWAP
01093    for (int i = 0; i < n; i++)
01094       frombuf(fBufCur, &ll[i]);
01095 #else
01096    memcpy(ll, fBufCur, l);
01097    fBufCur += l;
01098 #endif
01099 
01100    return n;
01101 }
01102 
01103 //______________________________________________________________________________
01104 Int_t TBufferFile::ReadStaticArray(Float_t *f)
01105 {
01106    // Read array of floats from the I/O buffer. Returns the number of floats
01107    // read.
01108 
01109    R__ASSERT(IsReading());
01110 
01111    Int_t n;
01112    *this >> n;
01113    Int_t l = sizeof(Float_t)*n;
01114 
01115    if (n <= 0 || l > fBufSize) return 0;
01116 
01117    if (!f) return 0;
01118 
01119 #ifdef R__BYTESWAP
01120 # ifdef USE_BSWAPCPY
01121    bswapcpy32(f, fBufCur, n);
01122    fBufCur += sizeof(Float_t)*n;
01123 # else
01124    for (int i = 0; i < n; i++)
01125       frombuf(fBufCur, &f[i]);
01126 # endif
01127 #else
01128    memcpy(f, fBufCur, l);
01129    fBufCur += l;
01130 #endif
01131 
01132    return n;
01133 }
01134 
01135 //______________________________________________________________________________
01136 Int_t TBufferFile::ReadStaticArray(Double_t *d)
01137 {
01138    // Read array of doubles from the I/O buffer. Returns the number of doubles
01139    // read.
01140 
01141    R__ASSERT(IsReading());
01142 
01143    Int_t n;
01144    *this >> n;
01145    Int_t l = sizeof(Double_t)*n;
01146 
01147    if (n <= 0 || l > fBufSize) return 0;
01148 
01149    if (!d) return 0;
01150 
01151 #ifdef R__BYTESWAP
01152    for (int i = 0; i < n; i++)
01153       frombuf(fBufCur, &d[i]);
01154 #else
01155    memcpy(d, fBufCur, l);
01156    fBufCur += l;
01157 #endif
01158 
01159    return n;
01160 }
01161 
01162 //______________________________________________________________________________
01163 Int_t TBufferFile::ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele)
01164 {
01165    // Read array of floats (written as truncated float) from the I/O buffer.
01166    // Returns the number of floats read.
01167    // see comments about Float16_t encoding at TBufferFile::WriteFloat16
01168 
01169    R__ASSERT(IsReading());
01170 
01171    Int_t n;
01172    *this >> n;
01173 
01174    if (n <= 0 || 3*n > fBufSize) return 0;
01175 
01176    if (!f) return 0;
01177 
01178    ReadFastArrayFloat16(f,n,ele);
01179 
01180    return n;
01181 }
01182 
01183 //______________________________________________________________________________
01184 Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele)
01185 {
01186    // Read array of doubles (written as float) from the I/O buffer.
01187    // Returns the number of doubles read.
01188    // see comments about Double32_t encoding at TBufferFile::WriteDouble32
01189 
01190    R__ASSERT(IsReading());
01191 
01192    Int_t n;
01193    *this >> n;
01194 
01195    if (n <= 0 || 3*n > fBufSize) return 0;
01196 
01197    if (!d) return 0;
01198 
01199    ReadFastArrayDouble32(d,n,ele);
01200 
01201    return n;
01202 }
01203 
01204 //______________________________________________________________________________
01205 void TBufferFile::ReadFastArray(Bool_t *b, Int_t n)
01206 {
01207    // Read array of n bools from the I/O buffer.
01208 
01209    if (n <= 0 || n > fBufSize) return;
01210 
01211    if (sizeof(Bool_t) > 1) {
01212       for (int i = 0; i < n; i++)
01213          frombuf(fBufCur, &b[i]);
01214    } else {
01215       Int_t l = sizeof(Bool_t)*n;
01216       memcpy(b, fBufCur, l);
01217       fBufCur += l;
01218    }
01219 }
01220 
01221 //______________________________________________________________________________
01222 void TBufferFile::ReadFastArray(Char_t *c, Int_t n)
01223 {
01224    // Read array of n characters from the I/O buffer.
01225 
01226    if (n <= 0 || n > fBufSize) return;
01227 
01228    Int_t l = sizeof(Char_t)*n;
01229    memcpy(c, fBufCur, l);
01230    fBufCur += l;
01231 }
01232 
01233 //______________________________________________________________________________
01234 void TBufferFile::ReadFastArrayString(Char_t *c, Int_t n)
01235 {
01236    // Read array of n characters from the I/O buffer.
01237 
01238    Int_t len;
01239    UChar_t lenchar;
01240    *this >> lenchar;
01241    if (lenchar < 255) {
01242       len = lenchar;
01243    } else {
01244       *this >> len;
01245    }
01246    if (len) {
01247       if (len <= 0 || len > fBufSize) return;
01248       Int_t blen = len;
01249       if (len >= n) len = n-1;
01250 
01251       Int_t l = sizeof(Char_t)*len;
01252       memcpy(c, fBufCur, l);
01253       fBufCur += blen;
01254 
01255       c[len] = 0;
01256    } else {
01257       c[0] = 0;
01258    }
01259 }
01260 
01261 //______________________________________________________________________________
01262 void TBufferFile::ReadFastArray(Short_t *h, Int_t n)
01263 {
01264    // Read array of n shorts from the I/O buffer.
01265 
01266    Int_t l = sizeof(Short_t)*n;
01267    if (n <= 0 || l > fBufSize) return;
01268 
01269 #ifdef R__BYTESWAP
01270 # ifdef USE_BSWAPCPY
01271    bswapcpy16(h, fBufCur, n);
01272    fBufCur += sizeof(Short_t)*n;
01273 # else
01274    for (int i = 0; i < n; i++)
01275       frombuf(fBufCur, &h[i]);
01276 # endif
01277 #else
01278    memcpy(h, fBufCur, l);
01279    fBufCur += l;
01280 #endif
01281 }
01282 
01283 //______________________________________________________________________________
01284 void TBufferFile::ReadFastArray(Int_t *ii, Int_t n)
01285 {
01286    // Read array of n ints from the I/O buffer.
01287 
01288    Int_t l = sizeof(Int_t)*n;
01289    if (l <= 0 || l > fBufSize) return;
01290 
01291 #ifdef R__BYTESWAP
01292 # ifdef USE_BSWAPCPY
01293    bswapcpy32(ii, fBufCur, n);
01294    fBufCur += sizeof(Int_t)*n;
01295 # else
01296    for (int i = 0; i < n; i++)
01297       frombuf(fBufCur, &ii[i]);
01298 # endif
01299 #else
01300    memcpy(ii, fBufCur, l);
01301    fBufCur += l;
01302 #endif
01303 }
01304 
01305 //______________________________________________________________________________
01306 void TBufferFile::ReadFastArray(Long_t *ll, Int_t n)
01307 {
01308    // Read array of n longs from the I/O buffer.
01309 
01310    Int_t l = sizeof(Long_t)*n;
01311    if (l <= 0 || l > fBufSize) return;
01312 
01313    TFile *file = (TFile*)fParent;
01314    if (file && file->GetVersion() < 30006) {
01315       for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
01316    } else {
01317       for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
01318    }
01319 }
01320 
01321 //______________________________________________________________________________
01322 void TBufferFile::ReadFastArray(Long64_t *ll, Int_t n)
01323 {
01324    // Read array of n long longs from the I/O buffer.
01325 
01326    Int_t l = sizeof(Long64_t)*n;
01327    if (l <= 0 || l > fBufSize) return;
01328 
01329 #ifdef R__BYTESWAP
01330    for (int i = 0; i < n; i++)
01331       frombuf(fBufCur, &ll[i]);
01332 #else
01333    memcpy(ll, fBufCur, l);
01334    fBufCur += l;
01335 #endif
01336 }
01337 
01338 //______________________________________________________________________________
01339 void TBufferFile::ReadFastArray(Float_t *f, Int_t n)
01340 {
01341    // Read array of n floats from the I/O buffer.
01342 
01343    Int_t l = sizeof(Float_t)*n;
01344    if (l <= 0 || l > fBufSize) return;
01345 
01346 #ifdef R__BYTESWAP
01347 # ifdef USE_BSWAPCPY
01348    bswapcpy32(f, fBufCur, n);
01349    fBufCur += sizeof(Float_t)*n;
01350 # else
01351    for (int i = 0; i < n; i++)
01352       frombuf(fBufCur, &f[i]);
01353 # endif
01354 #else
01355    memcpy(f, fBufCur, l);
01356    fBufCur += l;
01357 #endif
01358 }
01359 
01360 //______________________________________________________________________________
01361 void TBufferFile::ReadFastArray(Double_t *d, Int_t n)
01362 {
01363    // Read array of n doubles from the I/O buffer.
01364 
01365    Int_t l = sizeof(Double_t)*n;
01366    if (l <= 0 || l > fBufSize) return;
01367 
01368 #ifdef R__BYTESWAP
01369    for (int i = 0; i < n; i++)
01370       frombuf(fBufCur, &d[i]);
01371 #else
01372    memcpy(d, fBufCur, l);
01373    fBufCur += l;
01374 #endif
01375 }
01376 
01377 //______________________________________________________________________________
01378 void TBufferFile::ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele)
01379 {
01380    // Read array of n floats (written as truncated float) from the I/O buffer.
01381    // see comments about Float16_t encoding at TBufferFile::WriteFloat16
01382 
01383    if (n <= 0 || 3*n > fBufSize) return;
01384 
01385    if (ele && ele->GetFactor() != 0) {
01386       //a range was specified. We read an integer and convert it back to a float
01387       Double_t xmin = ele->GetXmin();
01388       Double_t factor = ele->GetFactor();
01389       for (int j=0;j < n; j++) {
01390          UInt_t aint; *this >> aint; f[j] = (Float_t)(aint/factor + xmin);
01391       }
01392    } else {
01393       Int_t i;
01394       Int_t nbits = 0;
01395       if (ele) nbits = (Int_t)ele->GetXmin();
01396       if (!nbits) nbits = 12;
01397       //we read the exponent and the truncated mantissa of the float
01398       //and rebuild the new float.
01399       union {
01400          Float_t xx;
01401          Int_t ix;
01402       };
01403       UChar_t  theExp;
01404       UShort_t theMan;
01405       for (i = 0; i < n; i++) {
01406          *this >> theExp;
01407          *this >> theMan;
01408          ix = theExp;
01409          ix <<= 23;
01410          ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
01411          if(1<<(nbits+1) & theMan) xx = -xx;
01412          f[i] = xx;
01413       }
01414    }
01415 }
01416 
01417 //______________________________________________________________________________
01418 void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele)
01419 {
01420    // Read array of n doubles (written as float) from the I/O buffer.
01421    // see comments about Double32_t encoding at TBufferFile::WriteDouble32
01422 
01423    if (n <= 0 || 3*n > fBufSize) return;
01424 
01425    if (ele && ele->GetFactor() != 0) {
01426       //a range was specified. We read an integer and convert it back to a double.
01427       Double_t xmin = ele->GetXmin();
01428       Double_t factor = ele->GetFactor();
01429       for (int j=0;j < n; j++) {
01430          UInt_t aint; *this >> aint; d[j] = (Double_t)(aint/factor + xmin);
01431       }
01432    } else {
01433       Int_t i;
01434       Int_t nbits = 0;
01435       if (ele) nbits = (Int_t)ele->GetXmin();
01436       if (!nbits) {
01437          //we read a float and convert it to double
01438          Float_t afloat;
01439          for (i = 0; i < n; i++) {
01440             *this >> afloat;
01441             d[i] = (Double_t)afloat;
01442          }
01443       } else {
01444          //we read the exponent and the truncated mantissa of the float
01445          //and rebuild the double.
01446          union {
01447             Float_t xx;
01448             Int_t ix;
01449          };
01450          UChar_t  theExp;
01451          UShort_t theMan;
01452          for (i = 0; i < n; i++) {
01453             *this >> theExp;
01454             *this >> theMan;
01455             ix = theExp;
01456             ix <<= 23;
01457             ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
01458             if (1<<(nbits+1) & theMan) xx = -xx;
01459             d[i] = (Double_t)xx;
01460          }
01461       }
01462    }
01463 }
01464 
01465 //______________________________________________________________________________
01466 void TBufferFile::ReadFastArray(void  *start, const TClass *cl, Int_t n,
01467                                 TMemberStreamer *streamer, const TClass* onFileClass )
01468 {
01469    // Read an array of 'n' objects from the I/O buffer.
01470    // Stores the objects read starting at the address 'start'.
01471    // The objects in the array are assume to be of class 'cl'.
01472 
01473    if (streamer) {
01474       streamer->SetOnFileClass(onFileClass);
01475       (*streamer)(*this,start,0);
01476       return;
01477    }
01478 
01479    int objectSize = cl->Size();
01480    char *obj = (char*)start;
01481    char *end = obj + n*objectSize;
01482 
01483    for(; obj<end; obj+=objectSize) ((TClass*)cl)->Streamer(obj,*this, onFileClass);
01484 }
01485 
01486 //______________________________________________________________________________
01487 void TBufferFile::ReadFastArray(void **start, const TClass *cl, Int_t n,
01488                                 Bool_t isPreAlloc, TMemberStreamer *streamer, const TClass* onFileClass)
01489 {
01490    // Read an array of 'n' objects from the I/O buffer.
01491    // The objects read are stored starting at the address '*start'
01492    // The objects in the array are assumed to be of class 'cl' or a derived class.
01493    // 'mode' indicates whether the data member is marked with '->'
01494 
01495    // if isPreAlloc is true (data member has a ->) we can assume that the pointer (*start)
01496    // is never 0.
01497 
01498    if (streamer) {
01499       if (isPreAlloc) {
01500          for (Int_t j=0;j<n;j++) {
01501             if (!start[j]) start[j] = cl->New();
01502          }
01503       }
01504       streamer->SetOnFileClass(onFileClass);
01505       (*streamer)(*this,(void*)start,0);
01506       return;
01507    }
01508 
01509    if (!isPreAlloc) {
01510 
01511       for (Int_t j=0; j<n; j++){
01512          //delete the object or collection
01513          void *old = start[j];
01514          start[j] = ReadObjectAny(cl);
01515          if (old && old!=start[j] &&
01516              TStreamerInfo::CanDelete()
01517              // There are some cases where the user may set up a pointer in the (default)
01518              // constructor but not mark this pointer as transient.  Sometime the value
01519              // of this pointer is the address of one of the object with just created
01520              // and the following delete would result in the deletion (possibly of the
01521              // top level object we are goint to return!).
01522              // Eventhough this is a user error, we could prevent the crash by simply
01523              // adding:
01524              // && !CheckObject(start[j],cl)
01525              // However this can increase the read time significantly (10% in the case
01526              // of one TLine pointer in the test/Track and run ./Event 200 0 0 20 30000
01527              //
01528              // If ReadObjectAny returned the same value as we previous had, this means
01529              // that when writing this object (start[j] had already been written and
01530              // is indeed pointing to the same object as the object the user set up
01531              // in the default constructor).
01532              ) {
01533             ((TClass*)cl)->Destructor(old,kFALSE); // call delete and desctructor
01534          }
01535       }
01536 
01537    } else {     //case //-> in comment
01538 
01539       for (Int_t j=0; j<n; j++){
01540          if (!start[j]) start[j] = ((TClass*)cl)->New();
01541          ((TClass*)cl)->Streamer(start[j],*this,onFileClass);
01542       }
01543 
01544    }
01545 }
01546 
01547 //______________________________________________________________________________
01548 void TBufferFile::WriteArray(const Bool_t *b, Int_t n)
01549 {
01550    // Write array of n bools into the I/O buffer.
01551 
01552    R__ASSERT(IsWriting());
01553 
01554    *this << n;
01555 
01556    if (n <= 0) return;
01557 
01558    R__ASSERT(b);
01559 
01560    Int_t l = sizeof(UChar_t)*n;
01561    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01562 
01563    if (sizeof(Bool_t) > 1) {
01564       for (int i = 0; i < n; i++)
01565          tobuf(fBufCur, b[i]);
01566    } else {
01567       memcpy(fBufCur, b, l);
01568       fBufCur += l;
01569    }
01570 }
01571 
01572 //______________________________________________________________________________
01573 void TBufferFile::WriteArray(const Char_t *c, Int_t n)
01574 {
01575    // Write array of n characters into the I/O buffer.
01576 
01577    R__ASSERT(IsWriting());
01578 
01579    *this << n;
01580 
01581    if (n <= 0) return;
01582 
01583    R__ASSERT(c);
01584 
01585    Int_t l = sizeof(Char_t)*n;
01586    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01587 
01588    memcpy(fBufCur, c, l);
01589    fBufCur += l;
01590 }
01591 
01592 //______________________________________________________________________________
01593 void TBufferFile::WriteArray(const Short_t *h, Int_t n)
01594 {
01595    // Write array of n shorts into the I/O buffer.
01596 
01597    R__ASSERT(IsWriting());
01598 
01599    *this << n;
01600 
01601    if (n <= 0) return;
01602 
01603    R__ASSERT(h);
01604 
01605    Int_t l = sizeof(Short_t)*n;
01606    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01607 
01608 #ifdef R__BYTESWAP
01609 # ifdef USE_BSWAPCPY
01610    bswapcpy16(fBufCur, h, n);
01611    fBufCur += l;
01612 # else
01613    for (int i = 0; i < n; i++)
01614       tobuf(fBufCur, h[i]);
01615 # endif
01616 #else
01617    memcpy(fBufCur, h, l);
01618    fBufCur += l;
01619 #endif
01620 }
01621 
01622 //______________________________________________________________________________
01623 void TBufferFile::WriteArray(const Int_t *ii, Int_t n)
01624 {
01625    // Write array of n ints into the I/O buffer.
01626 
01627    R__ASSERT(IsWriting());
01628 
01629    *this << n;
01630 
01631    if (n <= 0) return;
01632 
01633    R__ASSERT(ii);
01634 
01635    Int_t l = sizeof(Int_t)*n;
01636    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01637 
01638 #ifdef R__BYTESWAP
01639 # ifdef USE_BSWAPCPY
01640    bswapcpy32(fBufCur, ii, n);
01641    fBufCur += l;
01642 # else
01643    for (int i = 0; i < n; i++)
01644       tobuf(fBufCur, ii[i]);
01645 # endif
01646 #else
01647    memcpy(fBufCur, ii, l);
01648    fBufCur += l;
01649 #endif
01650 }
01651 
01652 //______________________________________________________________________________
01653 void TBufferFile::WriteArray(const Long_t *ll, Int_t n)
01654 {
01655    // Write array of n longs into the I/O buffer.
01656 
01657    R__ASSERT(IsWriting());
01658 
01659    *this << n;
01660 
01661    if (n <= 0) return;
01662 
01663    R__ASSERT(ll);
01664 
01665    Int_t l = 8*n;
01666    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01667    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
01668 }
01669 
01670 //______________________________________________________________________________
01671 void TBufferFile::WriteArray(const ULong_t *ll, Int_t n)
01672 {
01673    // Write array of n unsigned longs into the I/O buffer.
01674    // This is an explicit case for unsigned longs since signed longs
01675    // have a special tobuf().
01676 
01677    R__ASSERT(IsWriting());
01678 
01679    *this << n;
01680 
01681    if (n <= 0) return;
01682 
01683    R__ASSERT(ll);
01684 
01685    Int_t l = 8*n;
01686    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01687    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
01688 }
01689 
01690 //______________________________________________________________________________
01691 void TBufferFile::WriteArray(const Long64_t *ll, Int_t n)
01692 {
01693    // Write array of n long longs into the I/O buffer.
01694 
01695    R__ASSERT(IsWriting());
01696 
01697    *this << n;
01698 
01699    if (n <= 0) return;
01700 
01701    R__ASSERT(ll);
01702 
01703    Int_t l = sizeof(Long64_t)*n;
01704    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01705 
01706 #ifdef R__BYTESWAP
01707    for (int i = 0; i < n; i++)
01708       tobuf(fBufCur, ll[i]);
01709 #else
01710    memcpy(fBufCur, ll, l);
01711    fBufCur += l;
01712 #endif
01713 }
01714 
01715 //______________________________________________________________________________
01716 void TBufferFile::WriteArray(const Float_t *f, Int_t n)
01717 {
01718    // Write array of n floats into the I/O buffer.
01719 
01720    R__ASSERT(IsWriting());
01721 
01722    *this << n;
01723 
01724    if (n <= 0) return;
01725 
01726    R__ASSERT(f);
01727 
01728    Int_t l = sizeof(Float_t)*n;
01729    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01730 
01731 #ifdef R__BYTESWAP
01732 # ifdef USE_BSWAPCPY
01733    bswapcpy32(fBufCur, f, n);
01734    fBufCur += l;
01735 # else
01736    for (int i = 0; i < n; i++)
01737       tobuf(fBufCur, f[i]);
01738 # endif
01739 #else
01740    memcpy(fBufCur, f, l);
01741    fBufCur += l;
01742 #endif
01743 }
01744 
01745 //______________________________________________________________________________
01746 void TBufferFile::WriteArray(const Double_t *d, Int_t n)
01747 {
01748    // Write array of n doubles into the I/O buffer.
01749 
01750    R__ASSERT(IsWriting());
01751 
01752    *this << n;
01753 
01754    if (n <= 0) return;
01755 
01756    R__ASSERT(d);
01757 
01758    Int_t l = sizeof(Double_t)*n;
01759    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01760 
01761 #ifdef R__BYTESWAP
01762    for (int i = 0; i < n; i++)
01763       tobuf(fBufCur, d[i]);
01764 #else
01765    memcpy(fBufCur, d, l);
01766    fBufCur += l;
01767 #endif
01768 }
01769 
01770 //______________________________________________________________________________
01771 void TBufferFile::WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
01772 {
01773    // Write array of n floats (as truncated float) into the I/O buffer.
01774    // see comments about Float16_t encoding at TBufferFile::WriteFloat16
01775 
01776    R__ASSERT(IsWriting());
01777 
01778    *this << n;
01779 
01780    if (n <= 0) return;
01781 
01782    R__ASSERT(f);
01783 
01784    Int_t l = sizeof(Float_t)*n;
01785    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01786 
01787    WriteFastArrayFloat16(f,n,ele);
01788 }
01789 
01790 //______________________________________________________________________________
01791 void TBufferFile::WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
01792 {
01793    // Write array of n doubles (as float) into the I/O buffer.
01794    // see comments about Double32_t encoding at TBufferFile::WriteDouble32
01795 
01796    R__ASSERT(IsWriting());
01797 
01798    *this << n;
01799 
01800    if (n <= 0) return;
01801 
01802    R__ASSERT(d);
01803 
01804    Int_t l = sizeof(Float_t)*n;
01805    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01806 
01807    WriteFastArrayDouble32(d,n,ele);
01808 }
01809 
01810 //______________________________________________________________________________
01811 void TBufferFile::WriteFastArray(const Bool_t *b, Int_t n)
01812 {
01813    // Write array of n bools into the I/O buffer.
01814 
01815    if (n <= 0) return;
01816 
01817    Int_t l = sizeof(UChar_t)*n;
01818    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01819 
01820    if (sizeof(Bool_t) > 1) {
01821       for (int i = 0; i < n; i++)
01822          tobuf(fBufCur, b[i]);
01823    } else {
01824       memcpy(fBufCur, b, l);
01825       fBufCur += l;
01826    }
01827 }
01828 
01829 //______________________________________________________________________________
01830 void TBufferFile::WriteFastArray(const Char_t *c, Int_t n)
01831 {
01832    // Write array of n characters into the I/O buffer.
01833 
01834    if (n <= 0) return;
01835 
01836    Int_t l = sizeof(Char_t)*n;
01837    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01838 
01839    memcpy(fBufCur, c, l);
01840    fBufCur += l;
01841 }
01842 
01843 //______________________________________________________________________________
01844 void TBufferFile::WriteFastArrayString(const Char_t *c, Int_t n)
01845 {
01846    // Write array of n characters into the I/O buffer.
01847 
01848    if (n < 255) {
01849       *this << (UChar_t)n;
01850    } else {
01851       *this << (UChar_t)255;
01852       *this << n;
01853    }
01854 
01855    if (n <= 0) return;
01856 
01857    Int_t l = sizeof(Char_t)*n;
01858    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01859 
01860    memcpy(fBufCur, c, l);
01861    fBufCur += l;
01862 }
01863 
01864 //______________________________________________________________________________
01865 void TBufferFile::WriteFastArray(const Short_t *h, Int_t n)
01866 {
01867    // Write array of n shorts into the I/O buffer.
01868 
01869    if (n <= 0) return;
01870 
01871    Int_t l = sizeof(Short_t)*n;
01872    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01873 
01874 #ifdef R__BYTESWAP
01875 # ifdef USE_BSWAPCPY
01876    bswapcpy16(fBufCur, h, n);
01877    fBufCur += l;
01878 # else
01879    for (int i = 0; i < n; i++)
01880       tobuf(fBufCur, h[i]);
01881 # endif
01882 #else
01883    memcpy(fBufCur, h, l);
01884    fBufCur += l;
01885 #endif
01886 }
01887 
01888 //______________________________________________________________________________
01889 void TBufferFile::WriteFastArray(const Int_t *ii, Int_t n)
01890 {
01891    // Write array of n ints into the I/O buffer.
01892 
01893    if (n <= 0) return;
01894 
01895    Int_t l = sizeof(Int_t)*n;
01896    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01897 
01898 #ifdef R__BYTESWAP
01899 # ifdef USE_BSWAPCPY
01900    bswapcpy32(fBufCur, ii, n);
01901    fBufCur += l;
01902 # else
01903    for (int i = 0; i < n; i++)
01904       tobuf(fBufCur, ii[i]);
01905 # endif
01906 #else
01907    memcpy(fBufCur, ii, l);
01908    fBufCur += l;
01909 #endif
01910 }
01911 
01912 //______________________________________________________________________________
01913 void TBufferFile::WriteFastArray(const Long_t *ll, Int_t n)
01914 {
01915    // Write array of n longs into the I/O buffer.
01916 
01917    if (n <= 0) return;
01918 
01919    Int_t l = 8*n;
01920    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01921 
01922    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
01923 }
01924 
01925 //______________________________________________________________________________
01926 void TBufferFile::WriteFastArray(const ULong_t *ll, Int_t n)
01927 {
01928    // Write array of n unsigned longs into the I/O buffer.
01929    // This is an explicit case for unsigned longs since signed longs
01930    // have a special tobuf().
01931 
01932    if (n <= 0) return;
01933 
01934    Int_t l = 8*n;
01935    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01936 
01937    for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
01938 }
01939 
01940 //______________________________________________________________________________
01941 void TBufferFile::WriteFastArray(const Long64_t *ll, Int_t n)
01942 {
01943    // Write array of n long longs into the I/O buffer.
01944 
01945    if (n <= 0) return;
01946 
01947    Int_t l = sizeof(Long64_t)*n;
01948    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01949 
01950 #ifdef R__BYTESWAP
01951    for (int i = 0; i < n; i++)
01952       tobuf(fBufCur, ll[i]);
01953 #else
01954    memcpy(fBufCur, ll, l);
01955    fBufCur += l;
01956 #endif
01957 }
01958 
01959 //______________________________________________________________________________
01960 void TBufferFile::WriteFastArray(const Float_t *f, Int_t n)
01961 {
01962    // Write array of n floats into the I/O buffer.
01963 
01964    if (n <= 0) return;
01965 
01966    Int_t l = sizeof(Float_t)*n;
01967    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01968 
01969 #ifdef R__BYTESWAP
01970 # ifdef USE_BSWAPCPY
01971    bswapcpy32(fBufCur, f, n);
01972    fBufCur += l;
01973 # else
01974    for (int i = 0; i < n; i++)
01975       tobuf(fBufCur, f[i]);
01976 # endif
01977 #else
01978    memcpy(fBufCur, f, l);
01979    fBufCur += l;
01980 #endif
01981 }
01982 
01983 //______________________________________________________________________________
01984 void TBufferFile::WriteFastArray(const Double_t *d, Int_t n)
01985 {
01986    // Write array of n doubles into the I/O buffer.
01987 
01988    if (n <= 0) return;
01989 
01990    Int_t l = sizeof(Double_t)*n;
01991    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
01992 
01993 #ifdef R__BYTESWAP
01994    for (int i = 0; i < n; i++)
01995       tobuf(fBufCur, d[i]);
01996 #else
01997    memcpy(fBufCur, d, l);
01998    fBufCur += l;
01999 #endif
02000 }
02001 
02002 //______________________________________________________________________________
02003 void TBufferFile::WriteFastArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
02004 {
02005    // Write array of n floats (as truncated float) into the I/O buffer.
02006    // see comments about Float16_t encoding at TBufferFile::WriteFloat16
02007 
02008    if (n <= 0) return;
02009 
02010    Int_t l = sizeof(Float_t)*n;
02011    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
02012 
02013    if (ele && ele->GetFactor()) {
02014       //A range is specified. We normalize the float to the range and
02015       //convert it to an integer using a scaling factor that is a function of nbits.
02016       //see TStreamerElement::GetRange.
02017       Double_t factor = ele->GetFactor();
02018       Double_t xmin = ele->GetXmin();
02019       Double_t xmax = ele->GetXmax();
02020       for (int j = 0; j < n; j++) {
02021          Float_t x = f[j];
02022          if (x < xmin) x = xmin;
02023          if (x > xmax) x = xmax;
02024          UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
02025       }
02026    } else {
02027       Int_t nbits = 0;
02028       //number of bits stored in fXmin (see TStreamerElement::GetRange)
02029       if (ele) nbits = (Int_t)ele->GetXmin();
02030       if (!nbits) nbits = 12;
02031       Int_t i;
02032       //a range is not specified, but nbits is.
02033       //In this case we truncate the mantissa to nbits and we stream
02034       //the exponent as a UChar_t and the mantissa as a UShort_t.
02035       union {
02036          Float_t xx;
02037          Int_t ix;
02038       };
02039       for (i = 0; i < n; i++) {
02040          xx = f[i];
02041          UChar_t  theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
02042          UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
02043          theMan++;
02044          theMan = theMan>>1;
02045          if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
02046          if (xx < 0) theMan |= 1<<(nbits+1);
02047          *this << theExp;
02048          *this << theMan;
02049       }
02050    }
02051 }
02052 
02053 //______________________________________________________________________________
02054 void TBufferFile::WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
02055 {
02056    // Write array of n doubles (as float) into the I/O buffer.
02057    // see comments about Double32_t encoding at TBufferFile::WriteDouble32
02058 
02059    if (n <= 0) return;
02060 
02061    Int_t l = sizeof(Float_t)*n;
02062    if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
02063 
02064    if (ele && ele->GetFactor()) {
02065       //A range is specified. We normalize the double to the range and
02066       //convert it to an integer using a scaling factor that is a function of nbits.
02067       //see TStreamerElement::GetRange.
02068       Double_t factor = ele->GetFactor();
02069       Double_t xmin = ele->GetXmin();
02070       Double_t xmax = ele->GetXmax();
02071       for (int j = 0; j < n; j++) {
02072          Double_t x = d[j];
02073          if (x < xmin) x = xmin;
02074          if (x > xmax) x = xmax;
02075          UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
02076       }
02077    } else {
02078       Int_t nbits = 0;
02079       //number of bits stored in fXmin (see TStreamerElement::GetRange)
02080       if (ele) nbits = (Int_t)ele->GetXmin();
02081       Int_t i;
02082       if (!nbits) {
02083          //if no range and no bits specified, we convert from double to float
02084          for (i = 0; i < n; i++) {
02085             Float_t afloat = (Float_t)d[i];
02086             *this << afloat;
02087          }
02088       } else {
02089          //a range is not specified, but nbits is.
02090          //In this case we truncate the mantissa to nbits and we stream
02091          //the exponent as a UChar_t and the mantissa as a UShort_t.
02092          union {
02093             Float_t xx;
02094             Int_t ix;
02095          };
02096          for (i = 0; i < n; i++) {
02097             xx = (Float_t)d[i];
02098             UChar_t  theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
02099             UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
02100             theMan++;
02101             theMan = theMan>>1;
02102             if(theMan&1<<nbits) theMan = (1<<nbits) - 1;
02103             if (xx < 0) theMan |= 1<<(nbits+1);
02104             *this << theExp;
02105             *this << theMan;
02106          }
02107       }
02108    }
02109 }
02110 
02111 //______________________________________________________________________________
02112 void TBufferFile::WriteFastArray(void  *start, const TClass *cl, Int_t n,
02113                                  TMemberStreamer *streamer)
02114 {
02115    // Write an array of object starting at the address 'start' and of length 'n'
02116    // the objects in the array are assumed to be of class 'cl'
02117 
02118    if (streamer) {
02119       (*streamer)(*this, start, 0);
02120       return;
02121    }
02122 
02123    char *obj = (char*)start;
02124    if (!n) n=1;
02125    int size = cl->Size();
02126 
02127    for(Int_t j=0; j<n; j++,obj+=size) {
02128       ((TClass*)cl)->Streamer(obj,*this);
02129    }
02130 }
02131 
02132 //______________________________________________________________________________
02133 Int_t TBufferFile::WriteFastArray(void **start, const TClass *cl, Int_t n,
02134                                   Bool_t isPreAlloc, TMemberStreamer *streamer)
02135 {
02136    // Write an array of object starting at the address '*start' and of length 'n'
02137    // the objects in the array are of class 'cl'
02138    // 'isPreAlloc' indicates whether the data member is marked with '->'
02139    // Return:
02140    //  0: success
02141    //  2: truncated success (i.e actual class is missing. Only ptrClass saved.)
02142 
02143    // if isPreAlloc is true (data member has a ->) we can assume that the pointer
02144    // is never 0.
02145 
02146    if (streamer) {
02147       (*streamer)(*this,(void*)start,0);
02148       return 0;
02149    }
02150 
02151    int strInfo = 0;
02152 
02153    Int_t res = 0;
02154 
02155    if (!isPreAlloc) {
02156 
02157       for (Int_t j=0;j<n;j++) {
02158          //must write StreamerInfo if pointer is null
02159          if (!strInfo && !start[j] ) {
02160             TStreamerInfo *info = (TStreamerInfo*)((TClass*)cl)->GetStreamerInfo();
02161             ForceWriteInfo(info,kFALSE);
02162          }
02163          strInfo = 2003;
02164          res |= WriteObjectAny(start[j],cl);
02165       }
02166 
02167    } else {     //case //-> in comment
02168 
02169       for (Int_t j=0;j<n;j++) {
02170          if (!start[j]) start[j] = ((TClass*)cl)->New();
02171          ((TClass*)cl)->Streamer(start[j],*this);
02172       }
02173 
02174    }
02175    return res;
02176 }
02177 
02178 //______________________________________________________________________________
02179 TObject *TBufferFile::ReadObject(const TClass * /*clReq*/)
02180 {
02181    // Read object from I/O buffer. clReq is NOT used.
02182    // The value returned is the address of the actual start in memory of
02183    // the object. Note that if the actual class of the object does not
02184    // inherit first from TObject, the type of the pointer is NOT 'TObject*'.
02185    // [More accurately, the class needs to start with the TObject part, for
02186    // the pointer to be a real TObject*].
02187    // We recommend using ReadObjectAny instead of ReadObject
02188 
02189    return (TObject*) ReadObjectAny(0);
02190 }
02191 
02192 //______________________________________________________________________________
02193 void TBufferFile::SkipObjectAny()
02194 {
02195    // Skip any kind of object from buffer
02196 
02197    UInt_t start, count;
02198    ReadVersion(&start, &count);
02199    SetBufferOffset(start+count+sizeof(UInt_t));
02200 }
02201 
02202 //______________________________________________________________________________
02203 void *TBufferFile::ReadObjectAny(const TClass *clCast)
02204 {
02205    // Read object from I/O buffer.
02206    // A typical use for this function is:
02207    //    MyClass *ptr = (MyClass*)b.ReadObjectAny(MyClass::Class());
02208    // I.e. clCast should point to a TClass object describing the class pointed
02209    // to by your pointer.
02210    // In case of multiple inheritance, the return value might not be the
02211    // real beginning of the object in memory.  You will need to use a
02212    // dynamic_cast later if you need to retrieve it.
02213 
02214    R__ASSERT(IsReading());
02215 
02216    // make sure fMap is initialized
02217    InitMap();
02218 
02219    // before reading object save start position
02220    UInt_t startpos = UInt_t(fBufCur-fBuffer);
02221 
02222    // attempt to load next object as TClass clCast
02223    UInt_t tag;       // either tag or byte count
02224    TClass *clRef = ReadClass(clCast, &tag);
02225    TClass *clOnfile = 0;
02226    Int_t baseOffset = 0;
02227    if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
02228       //baseOffset will be -1 if clRef does not inherit from clCast.
02229       baseOffset = clRef->GetBaseClassOffset(clCast);
02230       if (baseOffset == -1) {
02231          // The 2 classes are unrelated, maybe there is a converter between the 2.
02232 
02233          if (!clCast->GetSchemaRules() ||
02234              !clCast->GetSchemaRules()->HasRuleWithSourceClass(clRef->GetName()))
02235          {
02236             // There is no converter
02237             Error("ReadObject", "got object of wrong class! requested %s but got %s",
02238                   clCast->GetName(), clRef->GetName());
02239 
02240             CheckByteCount(startpos, tag, (TClass*)0); // avoid mis-leading byte count error message
02241             return 0; // We better return at this point
02242          }
02243          baseOffset = 0; // For now we do not support requesting from a class that is the base of one of the class for which there is transformation to ....
02244 
02245          Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clRef->GetName(),clCast->GetName());
02246          clRef = const_cast<TClass*>(clCast);
02247 
02248       }
02249       if (clCast->GetClassInfo() && !clRef->GetClassInfo()) {
02250          //we cannot mix a compiled class with an emulated class in the inheritance
02251          Error("ReadObject", "trying to read an emulated class (%s) to store in a compiled pointer (%s)",
02252                clRef->GetName(),clCast->GetName());
02253          CheckByteCount(startpos, tag, (TClass*)0); // avoid mis-leading byte count error message
02254          return 0;
02255       }
02256    }
02257 
02258    // check if object has not already been read
02259    // (this can only happen when called via CheckObject())
02260    char *obj;
02261    if (fVersion > 0) {
02262       obj = (char *) (Long_t)fMap->GetValue(startpos+kMapOffset);
02263       if (obj == (void*) -1) obj = 0;
02264       if (obj) {
02265          CheckByteCount(startpos, tag, (TClass*)0);
02266          return (obj+baseOffset);
02267       }
02268    }
02269 
02270    // unknown class, skip to next object and return 0 obj
02271    if (clRef == (TClass*) -1) {
02272       if (fBufCur >= fBufMax) return 0;
02273       if (fVersion > 0)
02274          MapObject((TObject*) -1, startpos+kMapOffset);
02275       else
02276          MapObject((void*)0, 0, fMapCount);
02277       CheckByteCount(startpos, tag, (TClass*)0);
02278       return 0;
02279    }
02280 
02281    if (!clRef) {
02282 
02283       // got a reference to an already read object
02284       if (fVersion > 0) {
02285          tag += fDisplacement;
02286          tag = CheckObject(tag, clCast);
02287       } else {
02288          if (tag > (UInt_t)fMap->GetSize()) {
02289             Error("ReadObject", "object tag too large, I/O buffer corrupted");
02290             return 0;
02291             // exception
02292          }
02293       }
02294       obj = (char *) (Long_t)fMap->GetValue(tag);
02295       clRef = (TClass*) (Long_t)fClassMap->GetValue(tag);
02296 
02297       if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
02298          //baseOffset will be -1 if clRef does not inherit from clCast.
02299          baseOffset = clRef->GetBaseClassOffset(clCast);
02300          if (baseOffset == -1) {
02301             Error("ReadObject", "Got object of wrong class (Got %s while expecting %s)",
02302                   clRef->GetName(),clCast->GetName());
02303             // exception
02304             baseOffset = 0;
02305          }
02306       }
02307 
02308       // There used to be a warning printed here when:
02309       //   obj && isTObject && !((TObject*)obj)->IsA()->InheritsFrom(clReq)
02310       // however isTObject was based on clReq (now clCast).
02311       // If the test was to fail, then it is as likely that the object is not a TObject
02312       // and then we have a potential core dump.
02313       // At this point (missing clRef), we do NOT have enough information to really
02314       // answer the question: is the object read of the type I requested.
02315 
02316    } else {
02317 
02318       // allocate a new object based on the class found
02319       obj = (char*)clRef->New();
02320       if (!obj) {
02321          Error("ReadObject", "could not create object of class %s",
02322                clRef->GetName());
02323          // exception
02324          return 0;
02325       }
02326 
02327       // add to fMap before reading rest of object
02328       if (fVersion > 0)
02329          MapObject(obj, clRef, startpos+kMapOffset);
02330       else
02331          MapObject(obj, clRef, fMapCount);
02332 
02333       // let the object read itself
02334       clRef->Streamer( obj, *this, clOnfile );
02335 
02336       CheckByteCount(startpos, tag, clRef);
02337    }
02338 
02339    return obj+baseOffset;
02340 }
02341 
02342 //______________________________________________________________________________
02343 void TBufferFile::WriteObject(const TObject *obj)
02344 {
02345    // Write object to I/O buffer.
02346 
02347    WriteObjectAny(obj, TObject::Class());
02348 }
02349 
02350 //______________________________________________________________________________
02351 void TBufferFile::WriteObjectClass(const void *actualObjectStart, const TClass *actualClass)
02352 {
02353    // Write object to I/O buffer.
02354    // This function assumes that the value of 'actualObjectStart' is the actual start of
02355    // the object of class 'actualClass'
02356 
02357    R__ASSERT(IsWriting());
02358 
02359    if (!actualObjectStart) {
02360 
02361       // save kNullTag to represent NULL pointer
02362       *this << kNullTag;
02363 
02364    } else {
02365 
02366       // make sure fMap is initialized
02367       InitMap();
02368 
02369       ULong_t idx;
02370       UInt_t slot;
02371       ULong_t hash = Void_Hash(actualObjectStart);
02372 
02373       if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)actualObjectStart, slot)) != 0) {
02374 
02375          // truncation is OK the value we did put in the map is an 30-bit offset
02376          // and not a pointer
02377          UInt_t objIdx = UInt_t(idx);
02378 
02379          // save index of already stored object
02380          *this << objIdx;
02381 
02382       } else {
02383 
02384          // A warning to let the user know it will need to change the class code
02385          // to  be able to read this back.
02386          if (actualClass->HasDefaultConstructor() == 0) {
02387             Warning("WriteObjectAny", "since %s has no public constructor\n"
02388                "\twhich can be called without argument, objects of this class\n"
02389                "\tcan not be read with the current library. You will need to\n"
02390                "\tadd a default constructor before attempting to read it.",
02391                actualClass->GetName());
02392          }
02393 
02394          // reserve space for leading byte count
02395          UInt_t cntpos = UInt_t(fBufCur-fBuffer);
02396          fBufCur += sizeof(UInt_t);
02397 
02398          // write class of object first
02399          Int_t mapsize = fMap->Capacity(); // The slot depends on the capacity and WriteClass might induce an increase.
02400          WriteClass(actualClass);
02401 
02402          // add to map before writing rest of object (to handle self reference)
02403          // (+kMapOffset so it's != kNullTag)
02404          //MapObject(actualObjectStart, actualClass, cntpos+kMapOffset);
02405          UInt_t offset = cntpos+kMapOffset;
02406          if (mapsize == fMap->Capacity()) {
02407             fMap->AddAt(slot, hash, (Long_t)actualObjectStart, offset);
02408          } else {
02409             // The slot depends on the capacity and WriteClass has induced an increase.
02410             fMap->Add(hash, (Long_t)actualObjectStart, offset);
02411          }
02412          // No need to keep track of the class in write mode
02413          // fClassMap->Add(hash, (Long_t)obj, (Long_t)((TObject*)obj)->IsA());
02414          fMapCount++;
02415 
02416          ((TClass*)actualClass)->Streamer((void*)actualObjectStart,*this);
02417 
02418          // write byte count
02419          SetByteCount(cntpos);
02420       }
02421    }
02422 }
02423 
02424 namespace {
02425    struct DynamicType {
02426       // Helper class to enable typeid on any address
02427       // Used in code similar to:
02428       //    typeid( * (DynamicType*) void_ptr );
02429       virtual ~DynamicType() {}
02430    };
02431 }
02432 
02433 //______________________________________________________________________________
02434 Int_t TBufferFile::WriteObjectAny(const void *obj, const TClass *ptrClass)
02435 {
02436    // Write object to I/O buffer.
02437    // This function assumes that the value in 'obj' is the value stored in
02438    // a pointer to a "ptrClass". The actual type of the object pointed to
02439    // can be any class derived from "ptrClass".
02440    // Return:
02441    //  0: failure
02442    //  1: success
02443    //  2: truncated success (i.e actual class is missing. Only ptrClass saved.)
02444 
02445    if (!obj) {
02446       WriteObjectClass(0, 0);
02447       return 1;
02448    }
02449 
02450    if (!ptrClass) {
02451       Error("WriteObjectAny", "ptrClass argument may not be 0");
02452       return 0;
02453    }
02454 
02455    TClass *clActual = ptrClass->GetActualClass(obj);
02456 
02457    if (clActual==0) {
02458       // The ptrClass is a class with a virtual table and we have no
02459       // TClass with the actual type_info in memory.
02460 
02461       DynamicType* d_ptr = (DynamicType*)obj;
02462       Warning("WriteObjectAny",
02463               "An object of type %s (from type_info) passed through a %s pointer was truncated (due a missing dictionary)!!!",
02464               typeid(*d_ptr).name(),ptrClass->GetName());
02465       WriteObjectClass(obj, ptrClass);
02466       return 2;
02467    } else if (clActual && (clActual != ptrClass)) {
02468       const char *temp = (const char*) obj;
02469       temp -= clActual->GetBaseClassOffset(ptrClass);
02470       WriteObjectClass(temp, clActual);
02471       return 1;
02472    } else {
02473       WriteObjectClass(obj, ptrClass);
02474       return 1;
02475    }
02476 }
02477 
02478 //______________________________________________________________________________
02479 TClass *TBufferFile::ReadClass(const TClass *clReq, UInt_t *objTag)
02480 {
02481    // Read class definition from I/O buffer. clReq can be used to cross check
02482    // if the actually read object is of the requested class. objTag is
02483    // set in case the object is a reference to an already read object.
02484 
02485    R__ASSERT(IsReading());
02486 
02487    // read byte count and/or tag (older files don't have byte count)
02488    TClass *cl;
02489    if (fBufCur < fBuffer || fBufCur > fBufMax) {
02490       fBufCur = fBufMax;
02491       cl = (TClass*)-1;
02492       return cl;
02493    }
02494    UInt_t bcnt, tag, startpos = 0;
02495    *this >> bcnt;
02496    if (!(bcnt & kByteCountMask) || bcnt == kNewClassTag) {
02497       tag  = bcnt;
02498       bcnt = 0;
02499    } else {
02500       fVersion = 1;
02501       startpos = UInt_t(fBufCur-fBuffer);
02502       *this >> tag;
02503    }
02504 
02505    // in case tag is object tag return tag
02506    if (!(tag & kClassMask)) {
02507       if (objTag) *objTag = tag;
02508       return 0;
02509    }
02510 
02511    if (tag == kNewClassTag) {
02512 
02513       // got a new class description followed by a new object
02514       // (class can be 0 if class dictionary is not found, in that
02515       // case object of this class must be skipped)
02516       cl = TClass::Load(*this);
02517 
02518       // add class to fMap for later reference
02519       if (fVersion > 0) {
02520          // check if class was already read
02521          TClass *cl1 = (TClass *)(Long_t)fMap->GetValue(startpos+kMapOffset);
02522          if (cl1 != cl)
02523             MapObject(cl ? cl : (TObject*) -1, startpos+kMapOffset);
02524       } else
02525          MapObject(cl, fMapCount);
02526 
02527    } else {
02528 
02529       // got a tag to an already seen class
02530       UInt_t clTag = (tag & ~kClassMask);
02531 
02532       if (fVersion > 0) {
02533          clTag += fDisplacement;
02534          clTag = CheckObject(clTag, clReq, kTRUE);
02535       } else {
02536          if (clTag == 0 || clTag > (UInt_t)fMap->GetSize()) {
02537             Error("ReadClass", "illegal class tag=%d (0<tag<=%d), I/O buffer corrupted",
02538                   clTag, fMap->GetSize());
02539             // exception
02540          }
02541       }
02542 
02543       // class can be 0 if dictionary was not found
02544       cl = (TClass *)(Long_t)fMap->GetValue(clTag);
02545    }
02546 
02547    if (cl && clReq &&
02548        (!cl->InheritsFrom(clReq) &&
02549         !(clReq->GetSchemaRules() &&
02550           clReq->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()) )
02551         ) ) {
02552       Error("ReadClass", "got wrong class: %s", cl->GetName());
02553       // exception
02554    }
02555 
02556    // return bytecount in objTag
02557    if (objTag) *objTag = (bcnt & ~kByteCountMask);
02558 
02559    // case of unknown class
02560    if (!cl) cl = (TClass*)-1;
02561 
02562    return cl;
02563 }
02564 
02565 //______________________________________________________________________________
02566 void TBufferFile::WriteClass(const TClass *cl)
02567 {
02568    // Write class description to I/O buffer.
02569 
02570    R__ASSERT(IsWriting());
02571 
02572    ULong_t idx;
02573    ULong_t hash = Void_Hash(cl);
02574    UInt_t slot;
02575 
02576    if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)cl,slot)) != 0) {
02577 
02578       // truncation is OK the value we did put in the map is an 30-bit offset
02579       // and not a pointer
02580       UInt_t clIdx = UInt_t(idx);
02581 
02582       // save index of already stored class
02583       *this << (clIdx | kClassMask);
02584 
02585    } else {
02586 
02587       // offset in buffer where class info is written
02588       UInt_t offset = UInt_t(fBufCur-fBuffer);
02589 
02590       // save new class tag
02591       *this << kNewClassTag;
02592 
02593       // write class name
02594       cl->Store(*this);
02595 
02596       // store new class reference in fMap (+kMapOffset so it's != kNullTag)
02597       CheckCount(offset+kMapOffset);
02598       fMap->AddAt(slot, hash, (Long_t)cl, offset+kMapOffset);
02599       fMapCount++;
02600    }
02601 }
02602 
02603 //______________________________________________________________________________
02604 void TBufferFile::SkipVersion(const TClass *cl)
02605 {
02606    // Skip class version from I/O buffer.
02607    
02608    Version_t version;
02609    
02610    // not interested in byte count
02611    frombuf(this->fBufCur,&version);
02612       
02613    // if this is a byte count, then skip next short and read version
02614    if (version & kByteCountVMask) {
02615       frombuf(this->fBufCur,&version);
02616       frombuf(this->fBufCur,&version);
02617    }
02618 
02619    if (cl && cl->GetClassVersion() != 0  && version<=1) {
02620       if (version <= 0)  {
02621          UInt_t checksum = 0;
02622          //*this >> checksum;
02623          frombuf(this->fBufCur,&checksum);
02624          TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
02625          if (vinfo) {
02626             return;
02627          } else {
02628             // There are some cases (for example when the buffer was stored outside of
02629             // a ROOT file) where we do not have a TStreamerInfo.  If the checksum is
02630             // the one from the current class, we can still assume that we can read
02631             // the data so let use it.
02632             if (checksum==cl->GetCheckSum() || checksum==cl->GetCheckSum(1)) {
02633                version = cl->GetClassVersion();
02634             } else {
02635                if (fParent) {
02636                   Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
02637                         checksum, cl->GetName(), ((TFile*)fParent)->GetName());
02638                } else {
02639                   Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\"( buffer with no parent)",
02640                         checksum, cl->GetName());
02641                }
02642                return;
02643             }
02644          }
02645       }  else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 ) {
02646          // We could have a file created using a Foreign class before
02647          // the introduction of the CheckSum.  We need to check
02648          if ((!cl->IsLoaded() || cl->IsForeign()) &&
02649              cl->GetStreamerInfos()->GetLast()>1 ) {
02650             
02651             const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
02652             const TStreamerInfo *local = (TStreamerInfo*)list->FindObject(cl->GetName());
02653             if ( local )  {
02654                UInt_t checksum = local->GetCheckSum();
02655                TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
02656                if (vinfo) {
02657                   version = vinfo->GetClassVersion();
02658                } else {
02659                   Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
02660                         checksum, cl->GetName(), ((TFile*)fParent)->GetName());
02661                   return;
02662                }
02663             }
02664             else  {
02665                Error("ReadVersion", "Class %s not known to file %s.",
02666                      cl->GetName(), ((TFile*)fParent)->GetName());
02667                version = 0;
02668             }
02669          }
02670       }
02671    }
02672 }
02673 
02674 //______________________________________________________________________________
02675 Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass *cl)
02676 {
02677    // Read class version from I/O buffer.
02678 
02679    Version_t version;
02680 
02681    if (startpos && bcnt) {
02682       // before reading object save start position
02683       *startpos = UInt_t(fBufCur-fBuffer);
02684 
02685       // read byte count (older files don't have byte count)
02686       // byte count is packed in two individual shorts, this to be
02687       // backward compatible with old files that have at this location
02688       // only a single short (i.e. the version)
02689       union {
02690          UInt_t     cnt;
02691          Version_t  vers[2];
02692       } v;
02693 #ifdef R__BYTESWAP
02694       frombuf(this->fBufCur,&v.vers[1]);
02695       frombuf(this->fBufCur,&v.vers[0]);
02696 #else
02697       frombuf(this->fBufCur,&v.vers[0]);
02698       frombuf(this->fBufCur,&v.vers[1]);
02699 #endif      
02700 
02701       // no bytecount, backup and read version
02702       if (!(v.cnt & kByteCountMask)) {
02703          fBufCur -= sizeof(UInt_t);
02704          v.cnt = 0;
02705       }
02706       *bcnt = (v.cnt & ~kByteCountMask);
02707       frombuf(this->fBufCur,&version);
02708 
02709    } else {
02710 
02711       // not interested in byte count
02712       frombuf(this->fBufCur,&version);
02713 
02714       // if this is a byte count, then skip next short and read version
02715       if (version & kByteCountVMask) {
02716          frombuf(this->fBufCur,&version);
02717          frombuf(this->fBufCur,&version);
02718       }
02719    }
02720    if (version<=1) {
02721       if (version <= 0)  {
02722          if (cl) {
02723             if (cl->GetClassVersion() != 0) {
02724                UInt_t checksum = 0;
02725                //*this >> checksum;
02726                frombuf(this->fBufCur,&checksum);
02727                TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
02728                if (vinfo) {
02729                   return vinfo->TStreamerInfo::GetClassVersion(); // Try to get inlining.
02730                } else {
02731                   // There are some cases (for example when the buffer was stored outside of
02732                   // a ROOT file) where we do not have a TStreamerInfo.  If the checksum is
02733                   // the one from the current class, we can still assume that we can read
02734                   // the data so let use it.
02735                   if (checksum==cl->GetCheckSum() || checksum==cl->GetCheckSum(1)) {
02736                      version = cl->GetClassVersion();
02737                   } else {
02738                      if (fParent) {
02739                         Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
02740                               checksum, cl->GetName(), ((TFile*)fParent)->GetName());
02741                      } else {
02742                         Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\"( buffer with no parent)",
02743                               checksum, cl->GetName());
02744                      }
02745                      return 0;
02746                   }
02747                }
02748             }
02749          } else { // of if (cl) {
02750             UInt_t checksum = 0;
02751             //*this >> checksum;
02752             frombuf(this->fBufCur,&checksum);            
02753          }
02754       }  else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 && cl && cl->GetClassVersion() != 0) {
02755          // We could have a file created using a Foreign class before
02756          // the introduction of the CheckSum.  We need to check
02757          if ((!cl->IsLoaded() || cl->IsForeign()) &&
02758             cl->GetStreamerInfos()->GetLast()>1 ) {
02759 
02760             const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
02761             const TStreamerInfo *local = (TStreamerInfo*)list->FindObject(cl->GetName());
02762             if ( local )  {
02763                UInt_t checksum = local->GetCheckSum();
02764                TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
02765                if (vinfo) {
02766                   version = vinfo->GetClassVersion();
02767                } else {
02768                   Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
02769                         checksum, cl->GetName(), ((TFile*)fParent)->GetName());
02770                   return 0;
02771                }
02772             }
02773             else  {
02774                Error("ReadVersion", "Class %s not known to file %s.",
02775                  cl->GetName(), ((TFile*)fParent)->GetName());
02776                version = 0;
02777             }
02778          }
02779       }
02780    }
02781    return version;
02782 }
02783 
02784 //______________________________________________________________________________
02785 UInt_t TBufferFile::WriteVersion(const TClass *cl, Bool_t useBcnt)
02786 {
02787    // Write class version to I/O buffer.
02788 
02789    UInt_t cntpos = 0;
02790    if (useBcnt) {
02791       // reserve space for leading byte count
02792       cntpos   = UInt_t(fBufCur-fBuffer);
02793       fBufCur += sizeof(UInt_t);
02794    }
02795 
02796    Version_t version = cl->GetClassVersion();
02797    if (version<=1 && cl->IsForeign()) {
02798       *this << Version_t(0);
02799       *this << cl->GetCheckSum();
02800    } else {
02801       if (version > kMaxVersion) {
02802          Error("WriteVersion", "version number cannot be larger than %hd)",
02803                kMaxVersion);
02804          version = kMaxVersion;
02805       }
02806       *this <<version;
02807    }
02808 
02809    // return position where to store possible byte count
02810    return cntpos;
02811 }
02812 
02813 //______________________________________________________________________________
02814 UInt_t TBufferFile::WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt)
02815 {
02816    // Write class version to I/O buffer after setting the kStreamedMemberWise
02817    // bit in the version number.
02818 
02819    UInt_t cntpos = 0;
02820    if (useBcnt) {
02821       // reserve space for leading byte count
02822       cntpos   = UInt_t(fBufCur-fBuffer);
02823       fBufCur += sizeof(UInt_t);
02824    }
02825 
02826    Version_t version = cl->GetClassVersion();
02827    if (version<=1 && cl->IsForeign()) {
02828       Error("WriteVersionMemberWise", "Member-wise streaming of foreign collection not yet implemented!");
02829       *this << Version_t(0);
02830       *this << cl->GetCheckSum();
02831    } else {
02832       if (version > kMaxVersion) {
02833          Error("WriteVersionMemberWise", "version number cannot be larger than %hd)",
02834                kMaxVersion);
02835          version = kMaxVersion;
02836       }
02837       version |= kStreamedMemberWise;
02838       *this <<version;
02839    }
02840 
02841    // return position where to store possible byte count
02842    return cntpos;
02843 }
02844 
02845 //______________________________________________________________________________
02846 void TBufferFile::StreamObject(void *obj, const type_info &typeinfo, const TClass* onFileClass )
02847 {
02848    // Stream an object given its C++ typeinfo information.
02849 
02850    TClass *cl = TClass::GetClass(typeinfo);
02851    cl->Streamer(obj, *this, (TClass*)onFileClass );
02852 }
02853 
02854 //______________________________________________________________________________
02855 void TBufferFile::StreamObject(void *obj, const char *className, const TClass* onFileClass)
02856 {
02857    // Stream an object given the name of its actual class.
02858 
02859    TClass *cl = TClass::GetClass(className);
02860    cl->Streamer(obj, *this, (TClass*)onFileClass );
02861 }
02862 
02863 //______________________________________________________________________________
02864 void TBufferFile::StreamObject(void *obj, const TClass *cl, const TClass* onFileClass )
02865 {
02866    // Stream an object given a pointer to its actual class.
02867 
02868    ((TClass*)cl)->Streamer(obj, *this, (TClass*)onFileClass );
02869 }
02870 
02871 //______________________________________________________________________________
02872 void TBufferFile::StreamObject(TObject *obj)
02873 {
02874    // Stream an object inheriting from TObject using its streamer.
02875 
02876    obj->Streamer(*this);
02877 }
02878 
02879 //______________________________________________________________________________
02880 void TBufferFile::CheckCount(UInt_t offset)
02881 {
02882    // Check if offset is not too large (< kMaxMapCount) when writing.
02883 
02884    if (IsWriting()) {
02885       if (offset >= kMaxMapCount) {
02886          Error("CheckCount", "buffer offset too large (larger than %d)", kMaxMapCount);
02887          // exception
02888       }
02889    }
02890 }
02891 
02892 //______________________________________________________________________________
02893 UInt_t TBufferFile::CheckObject(UInt_t offset, const TClass *cl, Bool_t readClass)
02894 {
02895    // Check for object in the read map. If the object is 0 it still has to be
02896    // read. Try to read it from the buffer starting at location offset. If the
02897    // object is -1 then it really does not exist and we return 0. If the object
02898    // exists just return the offset.
02899 
02900    // in position 0 we always have the reference to the null object
02901    if (!offset) return offset;
02902 
02903    Long_t cli;
02904 
02905    if (readClass) {
02906       if ((cli = fMap->GetValue(offset)) == 0) {
02907          // No class found at this location in map. It might have been skipped
02908          // as part of a skipped object. Try to explicitely read the class.
02909 
02910          // save fBufCur and set to place specified by offset (-kMapOffset-sizeof(bytecount))
02911          char *bufsav = fBufCur;
02912          fBufCur = (char *)(fBuffer + offset-kMapOffset-sizeof(UInt_t));
02913 
02914          TClass *c = ReadClass(cl);
02915          if (c == (TClass*) -1) {
02916             // mark class as really not available
02917             fMap->Remove(offset);
02918             fMap->Add(offset, -1);
02919             offset = 0;
02920             if (cl)
02921                Warning("CheckObject", "reference to unavailable class %s,"
02922                        " pointers of this type will be 0", cl->GetName());
02923             else
02924                Warning("CheckObject", "reference to an unavailable class,"
02925                        " pointers of that type will be 0");
02926          }
02927 
02928          fBufCur = bufsav;
02929 
02930       } else if (cli == -1) {
02931 
02932          // class really does not exist
02933          return 0;
02934       }
02935 
02936    } else {
02937 
02938       if ((cli = fMap->GetValue(offset)) == 0) {
02939          // No object found at this location in map. It might have been skipped
02940          // as part of a skipped object. Try to explicitely read the object.
02941 
02942          // save fBufCur and set to place specified by offset (-kMapOffset)
02943          char *bufsav = fBufCur;
02944          fBufCur = (char *)(fBuffer + offset-kMapOffset);
02945 
02946          TObject *obj = ReadObject(cl);
02947          if (!obj) {
02948             // mark object as really not available
02949             fMap->Remove(offset);
02950             fMap->Add(offset, -1);
02951             Warning("CheckObject", "reference to object of unavailable class %s, offset=%d"
02952                     " pointer will be 0", cl ? cl->GetName() : "TObject",offset);
02953             offset = 0;
02954          }
02955 
02956          fBufCur = bufsav;
02957 
02958       } else if (cli == -1) {
02959 
02960          // object really does not exist
02961          return 0;
02962       }
02963 
02964    }
02965 
02966    return offset;
02967 }
02968 
02969 //______________________________________________________________________________
02970 Bool_t TBufferFile::CheckObject(const TObject *obj)
02971 {
02972    // Check if the specified object is already in the buffer.
02973    // Returns kTRUE if object already in the buffer, kFALSE otherwise
02974    // (also if obj is 0 or TBuffer not in writing mode).
02975 
02976    return CheckObject(obj, TObject::Class());
02977 }
02978 
02979 //______________________________________________________________________________
02980 Bool_t TBufferFile::CheckObject(const void *obj, const TClass *ptrClass)
02981 {
02982    // Check if the specified object of the specified class is already in
02983    // the buffer. Returns kTRUE if object already in the buffer,
02984    // kFALSE otherwise (also if obj is 0 ).
02985 
02986    if (!obj || !fMap || !ptrClass) return kFALSE;
02987 
02988    TClass *clActual = ptrClass->GetActualClass(obj);
02989 
02990    ULong_t idx;
02991 
02992    if (clActual && (ptrClass != clActual)) {
02993       const char *temp = (const char*) obj;
02994       temp -= clActual->GetBaseClassOffset(ptrClass);
02995       idx = (ULong_t)fMap->GetValue(Void_Hash(temp), (Long_t)temp);
02996    } else {
02997       idx = (ULong_t)fMap->GetValue(Void_Hash(obj), (Long_t)obj);
02998    }
02999 
03000    return idx ? kTRUE : kFALSE;
03001 }
03002 
03003 //______________________________________________________________________________
03004 void TBufferFile::SetPidOffset(UShort_t offset)
03005 {
03006    // This offset is used when a key (or basket) is transfered from one
03007    // file to the other.  In this case the TRef and TObject might have stored a
03008    // pid index (to retrieve TProcessIDs) which refered to their order on the original
03009    // file, the fPidOffset is to be added to those values to correctly find the
03010    // TProcessID.  This fPidOffset needs to be increment if the key/basket is copied
03011    // and need to be zero for new key/basket.
03012 
03013    fPidOffset = offset;
03014 }
03015 
03016 //______________________________________________________________________________
03017 void TBufferFile::GetMappedObject(UInt_t tag, void* &ptr, TClass* &ClassPtr) const
03018 {
03019    // Retrieve the object stored in the buffer's object map at 'tag'
03020    // Set ptr and ClassPtr respectively to the address of the object and
03021    // a pointer to its TClass.
03022 
03023    if (tag > (UInt_t)fMap->GetSize()) {
03024       ptr = 0;
03025       ClassPtr = 0;
03026    } else {
03027       ptr = (void*)(Long_t)fMap->GetValue(tag);
03028       ClassPtr = (TClass*) (Long_t)fClassMap->GetValue(tag);
03029    }
03030 }
03031 
03032 //______________________________________________________________________________
03033 void TBufferFile::MapObject(const TObject *obj, UInt_t offset)
03034 {
03035    // Add object to the fMap container.
03036    // If obj is not 0 add object to the map (in read mode also add 0 objects to
03037    // the map). This method may only be called outside this class just before
03038    // calling obj->Streamer() to prevent self reference of obj, in case obj
03039    // contains (via via) a pointer to itself. In that case offset must be 1
03040    // (default value for offset).
03041 
03042    if (IsWriting()) {
03043       if (!fMap) InitMap();
03044 
03045       if (obj) {
03046          CheckCount(offset);
03047          ULong_t hash = Void_Hash(obj);
03048          fMap->Add(hash, (Long_t)obj, offset);
03049          // No need to keep track of the class in write mode
03050          // fClassMap->Add(hash, (Long_t)obj, (Long_t)((TObject*)obj)->IsA());
03051          fMapCount++;
03052       }
03053    } else {
03054       if (!fMap || !fClassMap) InitMap();
03055 
03056       fMap->Add(offset, (Long_t)obj);
03057       fClassMap->Add(offset,
03058              (obj && obj != (TObject*)-1) ? (Long_t)((TObject*)obj)->IsA() : 0);
03059       fMapCount++;
03060    }
03061 }
03062 
03063 //______________________________________________________________________________
03064 void TBufferFile::MapObject(const void *obj, const TClass* cl, UInt_t offset)
03065 {
03066    // Add object to the fMap container.
03067    // If obj is not 0 add object to the map (in read mode also add 0 objects to
03068    // the map). This method may only be called outside this class just before
03069    // calling obj->Streamer() to prevent self reference of obj, in case obj
03070    // contains (via via) a pointer to itself. In that case offset must be 1
03071    // (default value for offset).
03072 
03073    if (IsWriting()) {
03074       if (!fMap) InitMap();
03075 
03076       if (obj) {
03077          CheckCount(offset);
03078          ULong_t hash = Void_Hash(obj);
03079          fMap->Add(hash, (Long_t)obj, offset);
03080          // No need to keep track of the class in write mode
03081          // fClassMap->Add(hash, (Long_t)obj, (Long_t)cl);
03082          fMapCount++;
03083       }
03084    } else {
03085       if (!fMap || !fClassMap) InitMap();
03086 
03087       fMap->Add(offset, (Long_t)obj);
03088       fClassMap->Add(offset, (Long_t)cl);
03089       fMapCount++;
03090    }
03091 }
03092 
03093 //______________________________________________________________________________
03094 void TBufferFile::SetReadParam(Int_t mapsize)
03095 {
03096    // Set the initial size of the map used to store object and class
03097    // references during reading. The default size is kMapSize=503.
03098    // Increasing the default has the benefit that when reading many
03099    // small objects the map does not need to be resized too often
03100    // (the system is always dynamic, even with the default everything
03101    // will work, only the initial resizing will cost some time).
03102    // This method can only be called directly after the creation of
03103    // the TBuffer, before any reading is done. Globally this option
03104    // can be changed using SetGlobalReadParam().
03105 
03106    R__ASSERT(IsReading());
03107    R__ASSERT(fMap == 0);
03108 
03109    fMapSize = mapsize;
03110 }
03111 
03112 //______________________________________________________________________________
03113 void TBufferFile::SetWriteParam(Int_t mapsize)
03114 {
03115    // Set the initial size of the hashtable used to store object and class
03116    // references during writing. The default size is kMapSize=503.
03117    // Increasing the default has the benefit that when writing many
03118    // small objects the hashtable does not get too many collisions
03119    // (the system is always dynamic, even with the default everything
03120    // will work, only a large number of collisions will cost performance).
03121    // For optimal performance hashsize should always be a prime.
03122    // This method can only be called directly after the creation of
03123    // the TBuffer, before any writing is done. Globally this option
03124    // can be changed using SetGlobalWriteParam().
03125 
03126    R__ASSERT(IsWriting());
03127    R__ASSERT(fMap == 0);
03128 
03129    fMapSize = mapsize;
03130 }
03131 
03132 //______________________________________________________________________________
03133 void TBufferFile::InitMap()
03134 {
03135    // Create the fMap container and initialize them
03136    // with the null object.
03137 
03138    if (IsWriting()) {
03139       if (!fMap) {
03140          fMap = new TExMap(fMapSize);
03141          // No need to keep track of the class in write mode
03142          // fClassMap = new TExMap(fMapSize);
03143          fMapCount = 0;
03144       }
03145    } else {
03146       if (!fMap) {
03147          fMap = new TExMap(fMapSize);
03148          fMap->Add(0, kNullTag);      // put kNullTag in slot 0
03149          fMapCount = 1;
03150       } else if (fMapCount==0) {
03151          fMap->Add(0, kNullTag);      // put kNullTag in slot 0
03152          fMapCount = 1;
03153       }
03154       if (!fClassMap) {
03155          fClassMap = new TExMap(fMapSize);
03156          fClassMap->Add(0, kNullTag);      // put kNullTag in slot 0
03157       }
03158    }
03159 }
03160 
03161 //______________________________________________________________________________
03162 void TBufferFile::ResetMap()
03163 {
03164    // Delete existing fMap and reset map counter.
03165 
03166    if (fMap) fMap->Delete();
03167    if (fClassMap) fClassMap->Delete();
03168    fMapCount     = 0;
03169    fDisplacement = 0;
03170 
03171    // reset user bits
03172    ResetBit(kUser1);
03173    ResetBit(kUser2);
03174    ResetBit(kUser3);
03175 }
03176 
03177 //______________________________________________________________________________
03178 Int_t TBufferFile::ReadBuf(void *buf, Int_t max)
03179 {
03180    // Read max bytes from the I/O buffer into buf. The function returns
03181    // the actual number of bytes read.
03182 
03183    R__ASSERT(IsReading());
03184 
03185    if (max == 0) return 0;
03186 
03187    Int_t n = TMath::Min(max, (Int_t)(fBufMax - fBufCur));
03188 
03189    memcpy(buf, fBufCur, n);
03190    fBufCur += n;
03191 
03192    return n;
03193 }
03194 
03195 //______________________________________________________________________________
03196 void TBufferFile::WriteBuf(const void *buf, Int_t max)
03197 {
03198    // Write max bytes from buf into the I/O buffer.
03199 
03200    R__ASSERT(IsWriting());
03201 
03202    if (max == 0) return;
03203 
03204    if (fBufCur + max > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+max));
03205 
03206    memcpy(fBufCur, buf, max);
03207    fBufCur += max;
03208 }
03209 
03210 //______________________________________________________________________________
03211 char *TBufferFile::ReadString(char *s, Int_t max)
03212 {
03213    // Read string from I/O buffer. String is read till 0 character is
03214    // found or till max-1 characters are read (i.e. string s has max
03215    // bytes allocated). If max = -1 no check on number of character is
03216    // made, reading continues till 0 character is found.
03217 
03218    R__ASSERT(IsReading());
03219 
03220    char  ch;
03221    Int_t nr = 0;
03222 
03223    if (max == -1) max = kMaxInt;
03224 
03225    while (nr < max-1) {
03226 
03227       *this >> ch;
03228 
03229       // stop when 0 read
03230       if (ch == 0) break;
03231 
03232       s[nr++] = ch;
03233    }
03234 
03235    s[nr] = 0;
03236    return s;
03237 }
03238 
03239 //______________________________________________________________________________
03240 void TBufferFile::WriteString(const char *s)
03241 {
03242    // Write string to I/O buffer. Writes string upto and including the
03243    // terminating 0.
03244 
03245    WriteBuf(s, (strlen(s)+1)*sizeof(char));
03246 }
03247 
03248 //______________________________________________________________________________
03249 TProcessID *TBufferFile::GetLastProcessID(TRefTable *reftable) const
03250 {
03251    // Return the last TProcessID in the file.
03252 
03253    TFile *file = (TFile*)GetParent();
03254    // warn if the file contains > 1 PID (i.e. if we might have ambiguity)
03255    if (file && !reftable->TestBit(TRefTable::kHaveWarnedReadingOld) && file->GetNProcessIDs()>1) {
03256       Warning("ReadBuffer", "The file was written during several processes with an "
03257          "older ROOT version; the TRefTable entries might be inconsistent.");
03258       reftable->SetBit(TRefTable::kHaveWarnedReadingOld);
03259    }
03260 
03261    // the file's last PID is the relevant one, all others might have their tables overwritten
03262    TProcessID *fileProcessID = TProcessID::GetProcessID(0);
03263    if (file && file->GetNProcessIDs() > 0) {
03264       // take the last loaded PID
03265       fileProcessID = (TProcessID *) file->GetListOfProcessIDs()->Last();
03266    }
03267    return fileProcessID;
03268 }
03269 
03270 //______________________________________________________________________________
03271 TProcessID *TBufferFile::ReadProcessID(UShort_t pidf)
03272 {
03273    // The TProcessID with number pidf is read from file.
03274    // If the object is not already entered in the gROOT list, it is added.
03275 
03276    TFile *file = (TFile*)GetParent();
03277    if (!file) {
03278       if (!pidf) return TProcessID::GetPID(); //may happen when cloning an object
03279       return 0;
03280    }
03281    return file->ReadProcessID(pidf);
03282 }
03283 
03284 //______________________________________________________________________________
03285 UInt_t TBufferFile::GetTRefExecId()
03286 {
03287    // Return the exec id stored in the current TStreamerInfo element.
03288    // The execid has been saved in the unique id of the TStreamerElement
03289    // being read by TStreamerElement::Streamer.
03290    // The current element (fgElement) is set as a static global
03291    // by TStreamerInfo::ReadBuffer (Clones) when reading this TRef.
03292 
03293    return TStreamerInfo::GetCurrentElement()->GetUniqueID();
03294 }
03295 
03296 //______________________________________________________________________________
03297 UShort_t TBufferFile::WriteProcessID(TProcessID *pid)
03298 {
03299    // Check if the ProcessID pid is already in the file.
03300    // If not, add it and return the index number in the local file list.
03301 
03302    TFile *file = (TFile*)GetParent();
03303    if (!file) return 0;
03304    return file->WriteProcessID(pid);
03305 }
03306 
03307 //---- Utilities for TStreamerInfo ----------------------------------------------
03308 
03309 //______________________________________________________________________________
03310 void TBufferFile::ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t force)
03311 {
03312    // force writing the TStreamerInfo to the file
03313 
03314    if (info) info->ForceWriteInfo((TFile*)GetParent(),force);
03315 }
03316 
03317 
03318 //______________________________________________________________________________
03319 void TBufferFile::ForceWriteInfoClones(TClonesArray *a)
03320 {
03321    // Make sure TStreamerInfo is not optimized, otherwise it will not be
03322    // possible to support schema evolution in read mode.
03323    // In case the StreamerInfo has already been computed and optimized,
03324    // one must disable the option BypassStreamer.
03325 
03326    TStreamerInfo *sinfo = (TStreamerInfo*)a->GetClass()->GetStreamerInfo();
03327    if (sinfo->IsOptimized()) {
03328       sinfo->SetBit(TVirtualStreamerInfo::kCannotOptimize);
03329       sinfo->Compile();
03330    }
03331    ForceWriteInfo(sinfo,kFALSE);
03332 }
03333 
03334 //______________________________________________________________________________
03335 Int_t TBufferFile::ReadClones(TClonesArray *a, Int_t nobjects, Version_t objvers)
03336 {
03337    // Interface to TStreamerInfo::ReadBufferClones.
03338 
03339    char **arr = (char **)a->GetObjectRef(0);
03340    char **end = arr + nobjects;
03341    //a->GetClass()->GetStreamerInfo()->ReadBufferClones(*this,a,nobjects,-1,0);
03342    TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo(objvers);
03343    //return info->ReadBuffer(*this,arr,-1,nobjects,0,1);
03344    return ReadSequenceVecPtr(*(info->GetReadMemberWiseActions(kTRUE)),arr,end);
03345 }
03346 
03347 //______________________________________________________________________________
03348 Int_t TBufferFile::WriteClones(TClonesArray *a, Int_t nobjects)
03349 {
03350    // Interface to TStreamerInfo::WriteBufferClones.
03351 
03352    char **arr = reinterpret_cast<char**>(a->GetObjectRef(0));
03353    //a->GetClass()->GetStreamerInfo()->WriteBufferClones(*this,(TClonesArray*)a,nobjects,-1,0);
03354    TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo();
03355    return info->WriteBufferAux(*this,arr,-1,nobjects,0,1);
03356 }
03357 
03358 //______________________________________________________________________________
03359 Int_t TBufferFile::ReadClassEmulated(const TClass *cl, void *object, const TClass *onFileClass)
03360 {
03361    // Read emulated class.
03362 
03363    UInt_t start,count;
03364    //We assume that the class was written with a standard streamer
03365    //We attempt to recover if a version count was not written
03366    Version_t v = ReadVersion(&start,&count);
03367    void *ptr = &object;
03368    if (count) {
03369       TStreamerInfo *sinfo = 0;
03370       if( onFileClass ) {
03371          sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, v );
03372          if( !sinfo )
03373             return 0;
03374       }
03375 
03376       sinfo = (TStreamerInfo*)cl->GetStreamerInfo(v);
03377       sinfo->ReadBuffer(*this,(char**)ptr,-1);
03378       if (sinfo->IsRecovered()) count=0;
03379       CheckByteCount(start,count,cl);
03380    } else {
03381       SetBufferOffset(start);
03382       ((TStreamerInfo*)cl->GetStreamerInfo())->ReadBuffer(*this,(char**)ptr,-1);
03383    }
03384    return 0;
03385 }
03386 
03387 //______________________________________________________________________________
03388 Int_t TBufferFile::ReadClassBuffer(const TClass *cl, void *pointer, Int_t version, UInt_t start, UInt_t count, const TClass *onFileClass)
03389 {
03390    // Deserialize information from a buffer into an object.
03391    //
03392    // Note: This function is called by the xxx::Streamer()
03393    //       functions in rootcint-generated dictionaries.
03394    //   // This function assumes that the class version and the byte count
03395    // information have been read.
03396    //
03397    //   version  is the version number of the class
03398    //   start    is the starting position in the buffer b
03399    //   count    is the number of bytes for this object in the buffer
03400    //
03401 
03402    TObjArray *infos = cl->GetStreamerInfos();
03403    Int_t ninfos = infos->GetSize();
03404    if (version < -1 || version >= ninfos) {
03405       Error("ReadBuffer1", "class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
03406             cl->GetName(), version, Length() );
03407       CheckByteCount(start, count, cl);
03408       return 0;
03409    }
03410    //---------------------------------------------------------------------------
03411    // The ondisk class has been specified so get foreign streamer info
03412    //---------------------------------------------------------------------------
03413    TStreamerInfo *sinfo = 0;
03414    if( onFileClass ) {
03415       sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, version );
03416       if( !sinfo ) {
03417          Error("ReadClassBuffer",
03418                "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d", 
03419                onFileClass->GetName(), version, cl->GetName(), Length() );
03420          CheckByteCount(start, count, onFileClass);
03421          return 0;
03422       }
03423    }
03424    //---------------------------------------------------------------------------
03425    // Get local streamer info
03426    //---------------------------------------------------------------------------
03427    else {
03428       // The StreamerInfo should exist at this point.
03429       sinfo = (TStreamerInfo*)infos->At(version);
03430       if (sinfo == 0) {
03431          // Unless the data is coming via a socket connection from with schema evolution
03432          // (tracking) was not enabled.  So let's create the StreamerInfo if it is the
03433          // one for the current version, otherwise let's complain ...
03434          // We could also get here if there old class version was '1' and the new class version is higher than 1
03435          // AND the checksum is the same.
03436          if ( version == cl->GetClassVersion() || version == 1 ) {
03437             const_cast<TClass*>(cl)->BuildRealData(pointer);
03438             sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
03439             infos->AddAtAndExpand(sinfo, version);
03440             if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n", cl->GetName(), version);
03441             sinfo->Build();
03442          } else {
03443             Error("ReadClassBuffer", "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
03444                   version, cl->GetName(), Length() );
03445             CheckByteCount(start, count, cl);
03446             return 0;            
03447          }
03448       } else if (!sinfo->IsCompiled()) {
03449          // Streamer info has not been compiled, but exists.
03450          // Therefore it was read in from a file and we have to do schema evolution.
03451          const_cast<TClass*>(cl)->BuildRealData(pointer);
03452          sinfo->BuildOld();
03453       }
03454    }
03455 
03456    // Deserialize the object.
03457    ReadSequence(*(sinfo->GetReadObjectWiseActions()), (char*)pointer);
03458    if (sinfo->IsRecovered()) count=0;
03459 
03460    // Check that the buffer position corresponds to the byte count.
03461    CheckByteCount(start, count, cl);
03462    return 0;
03463 }
03464 
03465 //______________________________________________________________________________
03466 Int_t TBufferFile::ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onFileClass)
03467 {
03468    // Deserialize information from a buffer into an object.
03469    //
03470    // Note: This function is called by the xxx::Streamer()
03471    //       functions in rootcint-generated dictionaries.
03472    //
03473 
03474    // Read the class version from the buffer.
03475    UInt_t R__s = 0; // Start of object.
03476    UInt_t R__c = 0; // Count of bytes.
03477    Version_t version;
03478 
03479    if( onFileClass )
03480       version = ReadVersion(&R__s, &R__c, onFileClass);
03481    else
03482       version = ReadVersion(&R__s, &R__c, cl);
03483 
03484    Bool_t v2file = kFALSE;
03485    TFile *file = (TFile*)GetParent();
03486    if (file && file->GetVersion() < 30000) {
03487       version = -1; //This is old file
03488       v2file = kTRUE;
03489    }
03490 
03491    //---------------------------------------------------------------------------
03492    // The ondisk class has been specified so get foreign streamer info
03493    //---------------------------------------------------------------------------
03494    TStreamerInfo *sinfo = 0;
03495    if( onFileClass ) {
03496       sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, version );
03497       if( !sinfo ) {
03498          Error("ReadClassBuffer",
03499                "Could not find the right streamer info to convert %s version %d into a %s, object skipped at offset %d",
03500                onFileClass->GetName(), version, cl->GetName(), Length() );
03501          CheckByteCount(R__s, R__c, onFileClass);
03502          return 0;
03503       }
03504    }
03505    //---------------------------------------------------------------------------
03506    // Get local streamer info
03507    //---------------------------------------------------------------------------
03508    else {
03509       // The StreamerInfo should exist at this point.
03510       TObjArray *infos = cl->GetStreamerInfos();
03511       Int_t infocapacity = infos->Capacity();
03512       if (infocapacity) {
03513          if (version < -1 || version >= infocapacity) {
03514             Error("ReadClassBuffer","class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
03515                   cl->GetName(), version, Length());
03516             CheckByteCount(R__s, R__c, cl);
03517             return 0;
03518          }
03519          sinfo = (TStreamerInfo*) infos->UncheckedAt(version);
03520       }
03521       if (sinfo == 0) {
03522          // Unless the data is coming via a socket connection from with schema evolution
03523          // (tracking) was not enabled.  So let's create the StreamerInfo if it is the
03524          // one for the current version, otherwise let's complain ...
03525          // We could also get here when reading a file prior to the introduction of StreamerInfo.
03526          // We could also get here if there old class version was '1' and the new class version is higher than 1
03527          // AND the checksum is the same.
03528          if (v2file || version == cl->GetClassVersion() || version == 1 ) {
03529             const_cast<TClass*>(cl)->BuildRealData(pointer);
03530             sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
03531             infos->AddAtAndExpand(sinfo,version);
03532             if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n", cl->GetName(), version);
03533             sinfo->Build();
03534 
03535             if (v2file) sinfo->BuildEmulated(file);
03536          } else {
03537             Error( "ReadClassBuffer", "Could not find the StreamerInfo for version %d of the class %s, object skipped at offset %d",
03538                   version, cl->GetName(), Length() );
03539             CheckByteCount(R__s, R__c, cl);
03540             return 0;            
03541          }
03542       } 
03543       else if (!sinfo->IsCompiled())
03544       { 
03545          // Streamer info has not been compiled, but exists.
03546          // Therefore it was read in from a file and we have to do schema evolution?
03547          const_cast<TClass*>(cl)->BuildRealData(pointer);
03548          sinfo->BuildOld();
03549       }
03550    }
03551 
03552    //deserialize the object
03553    ReadSequence(*(sinfo->GetReadObjectWiseActions()), (char*)pointer );
03554    if (sinfo->TStreamerInfo::IsRecovered()) R__c=0; // 'TStreamerInfo::' avoids going via a virtual function.
03555 
03556    // Check that the buffer position corresponds to the byte count.
03557    CheckByteCount(R__s, R__c, cl);
03558 
03559    if (gDebug > 2) printf(" ReadBuffer for class: %s has read %d bytes\n", cl->GetName(), R__c);
03560 
03561    return 0;
03562 }
03563 
03564 //______________________________________________________________________________
03565 Int_t TBufferFile::WriteClassBuffer(const TClass *cl, void *pointer)
03566 {
03567    // Function called by the Streamer functions to serialize object at p
03568    // to buffer b. The optional argument info may be specified to give an
03569    // alternative StreamerInfo instead of using the default StreamerInfo
03570    // automatically built from the class definition.
03571    // For more information, see class TStreamerInfo.
03572 
03573    //build the StreamerInfo if first time for the class
03574    TStreamerInfo *sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetCurrentStreamerInfo();
03575    if (sinfo == 0) {
03576       const_cast<TClass*>(cl)->BuildRealData(pointer);
03577       sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
03578       const_cast<TClass*>(cl)->SetCurrentStreamerInfo(sinfo);
03579       cl->GetStreamerInfos()->AddAtAndExpand(sinfo,cl->GetClassVersion());
03580       if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n",cl->GetName(),cl->GetClassVersion());
03581       sinfo->Build();
03582    } else if (!sinfo->IsCompiled()) {
03583       const_cast<TClass*>(cl)->BuildRealData(pointer);
03584       sinfo->BuildOld();
03585    }
03586 
03587    //write the class version number and reserve space for the byte count
03588    UInt_t R__c = WriteVersion(cl, kTRUE);
03589 
03590    //serialize the object
03591    void *ptr = &pointer;
03592    sinfo->WriteBufferAux(*this,(char**)ptr,-1,1,0,0); // NOTE: expanded
03593 
03594    //write the byte count at the start of the buffer
03595    SetByteCount(R__c, kTRUE);
03596 
03597    if (gDebug > 2) printf(" WriteBuffer for class: %s version %d has written %d bytes\n",cl->GetName(),cl->GetClassVersion(),UInt_t(fBufCur - fBuffer) - R__c - (UInt_t)sizeof(UInt_t));
03598    return 0;
03599 }
03600 
03601 //______________________________________________________________________________
03602 Int_t TBufferFile::ReadSequence(const TStreamerInfoActions::TActionSequence &sequence, void *obj) 
03603 {
03604    // Read one collection of objects from the buffer using the StreamerInfoLoopAction.
03605    // The collection needs to be a split TClonesArray or a split vector of pointers.
03606    
03607    if (gDebug) {
03608       //loop on all active members
03609       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03610       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03611           iter != end;
03612           ++iter) {      
03613          (*iter).PrintDebug(*this,obj);
03614          (*iter)(*this,obj);
03615       }
03616       
03617    } else {
03618       //loop on all active members
03619       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03620       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03621           iter != end;
03622           ++iter) {      
03623          (*iter)(*this,obj);
03624       }
03625    }
03626    
03627    return 0;
03628 }
03629 
03630 //______________________________________________________________________________
03631 Int_t TBufferFile::ReadSequenceVecPtr(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection) 
03632 {
03633    // Read one collection of objects from the buffer using the StreamerInfoLoopAction.
03634    // The collection needs to be a split TClonesArray or a split vector of pointers.
03635    
03636    if (gDebug) {
03637       //loop on all active members
03638       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03639       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03640           iter != end;
03641           ++iter) {      
03642          (*iter).PrintDebug(*this,*(char**)start_collection);  // Warning: This limits us to TClonesArray and vector of pointers.
03643          (*iter)(*this,start_collection,end_collection);
03644       }
03645       
03646    } else {
03647       //loop on all active members
03648       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03649       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03650           iter != end;
03651           ++iter) {      
03652          (*iter)(*this,start_collection,end_collection);
03653       }
03654    }
03655    
03656    return 0;
03657 }
03658 
03659 //______________________________________________________________________________
03660 Int_t TBufferFile::ReadSequence(const TStreamerInfoActions::TActionSequence &sequence, void *start_collection, void *end_collection) 
03661 {
03662    // Read one collection of objects from the buffer using the StreamerInfoLoopAction.
03663    
03664    TStreamerInfoActions::TLoopConfiguration *loopconfig = sequence.fLoopConfig;
03665    if (gDebug) {
03666       
03667       // Get the address of the first item for the PrintDebug.
03668       // (Performance is not essential here since we are going to print to
03669       // the screen anyway).
03670       void *arr0 = loopconfig->GetFirstAddress(start_collection,end_collection);
03671       // loop on all active members
03672       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03673       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03674           iter != end;
03675           ++iter) {      
03676          (*iter).PrintDebug(*this,arr0);
03677          (*iter)(*this,start_collection,end_collection,loopconfig);
03678       }
03679       
03680    } else {
03681       //loop on all active members
03682       TStreamerInfoActions::ActionContainer_t::const_iterator end = sequence.fActions.end();
03683       for(TStreamerInfoActions::ActionContainer_t::const_iterator iter = sequence.fActions.begin();
03684           iter != end;
03685           ++iter) {      
03686          (*iter)(*this,start_collection,end_collection,loopconfig);
03687       }
03688    }
03689    
03690    return 0;
03691 }
03692 
03693 //---- Static functions --------------------------------------------------------
03694 
03695 //______________________________________________________________________________
03696 void TBufferFile::SetGlobalReadParam(Int_t mapsize)
03697 {
03698    // Set the initial size of the map used to store object and class
03699    // references during reading. The default size is kMapSize=503.
03700    // Increasing the default has the benefit that when reading many
03701    // small objects the array does not need to be resized too often
03702    // (the system is always dynamic, even with the default everything
03703    // will work, only the initial resizing will cost some time).
03704    // Per TBuffer object this option can be changed using SetReadParam().
03705 
03706    fgMapSize = mapsize;
03707 }
03708 
03709 //______________________________________________________________________________
03710 void TBufferFile::SetGlobalWriteParam(Int_t mapsize)
03711 {
03712    // Set the initial size of the hashtable used to store object and class
03713    // references during writing. The default size is kMapSize=503.
03714    // Increasing the default has the benefit that when writing many
03715    // small objects the hashtable does not get too many collisions
03716    // (the system is always dynamic, even with the default everything
03717    // will work, only a large number of collisions will cost performance).
03718    // For optimal performance hashsize should always be a prime.
03719    // Per TBuffer object this option can be changed using SetWriteParam().
03720 
03721    fgMapSize = mapsize;
03722 }
03723 
03724 //______________________________________________________________________________
03725 Int_t TBufferFile::GetGlobalReadParam()
03726 {
03727    // Get default read map size.
03728 
03729    return fgMapSize;
03730 }
03731 
03732 //______________________________________________________________________________
03733 Int_t TBufferFile::GetGlobalWriteParam()
03734 {
03735    // Get default write map size.
03736 
03737    return fgMapSize;
03738 }

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