#include <string.h>
#include <typeinfo>
#include "TFile.h"
#include "TBufferFile.h"
#include "TExMap.h"
#include "TClass.h"
#include "TProcessID.h"
#include "TRefTable.h"
#include "TStorage.h"
#include "TError.h"
#include "TClonesArray.h"
#include "TStreamer.h"
#include "TStreamerInfo.h"
#include "TStreamerElement.h"
#include "TSchemaRuleSet.h"
#if (defined(__linux) || defined(__APPLE__)) && defined(__i386__) && \
defined(__GNUC__)
#define USE_BSWAPCPY
#endif
#ifdef USE_BSWAPCPY
#include "Bswapcpy.h"
#endif
const UInt_t kNullTag = 0;
const UInt_t kNewClassTag = 0xFFFFFFFF;
const UInt_t kClassMask = 0x80000000;
const UInt_t kByteCountMask = 0x40000000;
const UInt_t kMaxMapCount = 0x3FFFFFFE;
const Version_t kByteCountVMask = 0x4000;
const Version_t kMaxVersion = 0x3FFF;
const Int_t kMapOffset = 2;
Int_t TBufferFile::fgMapSize = kMapSize;
ClassImp(TBufferFile)
static inline ULong_t Void_Hash(const void *ptr)
{
return TString::Hash(&ptr, sizeof(void*));
}
TBufferFile::TBufferFile(TBuffer::EMode mode)
:TBuffer(mode),
fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
fInfo(0), fInfoStack()
{
fMapCount = 0;
fMapSize = fgMapSize;
fMap = 0;
fClassMap = 0;
fParent = 0;
fDisplacement = 0;
}
TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz)
:TBuffer(mode,bufsiz),
fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
fInfo(0), fInfoStack()
{
fMapCount = 0;
fMapSize = fgMapSize;
fMap = 0;
fClassMap = 0;
fDisplacement = 0;
}
TBufferFile::TBufferFile(TBuffer::EMode mode, Int_t bufsiz, void *buf, Bool_t adopt, ReAllocCharFun_t reallocfunc) :
TBuffer(mode,bufsiz,buf,adopt,reallocfunc),
fDisplacement(0),fPidOffset(0), fMap(0), fClassMap(0),
fInfo(0), fInfoStack()
{
fMapCount = 0;
fMapSize = fgMapSize;
fMap = 0;
fClassMap = 0;
fDisplacement = 0;
}
TBufferFile::~TBufferFile()
{
delete fMap;
delete fClassMap;
}
Int_t TBufferFile::GetVersionOwner() const
{
TFile *file = (TFile*)GetParent();
if (file) return file->GetVersion();
else return 0;
}
void TBufferFile::IncrementLevel(TVirtualStreamerInfo* info)
{
fInfoStack.push_back(fInfo);
fInfo = (TStreamerInfo*)info;
}
void TBufferFile::DecrementLevel(TVirtualStreamerInfo* )
{
fInfo = fInfoStack.back();
fInfoStack.pop_back();
}
void TBufferFile::PushDataCache(TVirtualArray *obj)
{
fCacheStack.push_back(obj);
}
TVirtualArray *TBufferFile::PeekDataCache() const
{
if (fCacheStack.empty()) return 0;
return fCacheStack.back();
}
TVirtualArray *TBufferFile::PopDataCache()
{
TVirtualArray *val = PeekDataCache();
fCacheStack.pop_back();
return val;
}
static void frombufOld(char *&buf, Long_t *x)
{
#ifdef R__BYTESWAP
#ifdef R__B64
char *sw = (char *)x;
sw[0] = buf[7];
sw[1] = buf[6];
sw[2] = buf[5];
sw[3] = buf[4];
sw[4] = buf[3];
sw[5] = buf[2];
sw[6] = buf[1];
sw[7] = buf[0];
#else
char *sw = (char *)x;
sw[0] = buf[3];
sw[1] = buf[2];
sw[2] = buf[1];
sw[3] = buf[0];
#endif
#else
memcpy(x, buf, sizeof(Long_t));
#endif
buf += sizeof(Long_t);
}
void TBufferFile::ReadLong(Long_t &l)
{
TFile *file = (TFile*)fParent;
if (file && file->GetVersion() < 30006) {
frombufOld(fBufCur, &l);
} else {
frombuf(fBufCur, &l);
}
}
void TBufferFile::ReadTString(TString &s)
{
s.Streamer(*this);
}
void TBufferFile::WriteTString(const TString &s)
{
((TString&)s).Streamer(*this);
}
void TBufferFile::SetByteCount(UInt_t cntpos, Bool_t packInVersion)
{
UInt_t cnt = UInt_t(fBufCur - fBuffer) - cntpos - sizeof(UInt_t);
char *buf = (char *)(fBuffer + cntpos);
if (packInVersion) {
union {
UInt_t cnt;
Version_t vers[2];
} v;
v.cnt = cnt;
#ifdef R__BYTESWAP
tobuf(buf, Version_t(v.vers[1] | kByteCountVMask));
tobuf(buf, v.vers[0]);
#else
tobuf(buf, Version_t(v.vers[0] | kByteCountVMask));
tobuf(buf, v.vers[1]);
#endif
} else
tobuf(buf, cnt | kByteCountMask);
if (cnt >= kMaxMapCount) {
Error("WriteByteCount", "bytecount too large (more than %d)", kMaxMapCount);
}
}
Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss, const char *classname)
{
if (!bcnt) return 0;
Int_t offset = 0;
Long_t endpos = Long_t(fBuffer) + startpos + bcnt + sizeof(UInt_t);
if (Long_t(fBufCur) != endpos) {
offset = Int_t(Long_t(fBufCur) - endpos);
const char *name = clss ? clss->GetName() : classname ? classname : 0;
if (name) {
if (offset < 0) {
Error("CheckByteCount", "object of class %s read too few bytes: %d instead of %d",
name,bcnt+offset,bcnt);
}
if (offset > 0) {
Error("CheckByteCount", "object of class %s read too many bytes: %d instead of %d",
name,bcnt+offset,bcnt);
if (fParent)
Warning("CheckByteCount","%s::Streamer() not in sync with data on file %s, fix Streamer()",
name, fParent->GetName());
else
Warning("CheckByteCount","%s::Streamer() not in sync with data, fix Streamer()",
name);
}
}
if ( ((char *)endpos) > fBufMax ) {
offset = fBufMax-fBufCur;
Error("CheckByteCount",
"Byte count probably corrupted around buffer position %d:\n\t%d for a possible maximum of %d",
startpos, bcnt, offset);
fBufCur = fBufMax;
} else {
fBufCur = (char *) endpos;
}
}
return offset;
}
Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const TClass *clss)
{
if (!bcnt) return 0;
return CheckByteCount( startpos, bcnt, clss, 0);
}
Int_t TBufferFile::CheckByteCount(UInt_t startpos, UInt_t bcnt, const char *classname)
{
if (!bcnt) return 0;
return CheckByteCount( startpos, bcnt, 0, classname);
}
void TBufferFile::ReadFloat16(Float_t *f, TStreamerElement *ele)
{
if (ele && ele->GetFactor() != 0) {
UInt_t aint; *this >> aint; f[0] = (Float_t)(aint/ele->GetFactor() + ele->GetXmin());
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) nbits = 12;
union {
Float_t xx;
Int_t ix;
};
UChar_t theExp;
UShort_t theMan;
*this >> theExp;
*this >> theMan;
ix = theExp;
ix <<= 23;
ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
if(1<<(nbits+1) & theMan) xx=-xx;
f[0] = xx;
}
}
void TBufferFile::ReadDouble32(Double_t *d, TStreamerElement *ele)
{
if (ele && ele->GetFactor() != 0) {
UInt_t aint; *this >> aint; d[0] = (Double_t)(aint/ele->GetFactor() + ele->GetXmin());
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) {
Float_t afloat;
*this >> afloat;
d[0] = (Double_t)afloat;
} else {
union {
Float_t xx;
Int_t ix;
};
UChar_t theExp;
UShort_t theMan;
*this >> theExp;
*this >> theMan;
ix = theExp;
ix <<= 23;
ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
if(1<<(nbits+1) & theMan) xx=-xx;
d[0] = (Double_t)xx;
}
}
}
void TBufferFile::WriteFloat16(Float_t *f, TStreamerElement *ele)
{
/*
<img src="gif/double32.gif">
*/
//End_Html
if (ele && ele->GetFactor() != 0) {
Double_t x = f[0];
Double_t xmin = ele->GetXmin();
Double_t xmax = ele->GetXmax();
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) nbits = 12;
union {
Float_t xx;
Int_t ix;
};
xx = f[0];
UChar_t theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
theMan++;
theMan = theMan>>1;
if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
if (xx < 0) theMan |= 1<<(nbits+1);
*this << theExp;
*this << theMan;
}
}
void TBufferFile::WriteDouble32(Double_t *d, TStreamerElement *ele)
{
/*
<img src="gif/double32.gif">
*/
//End_Html
if (ele && ele->GetFactor() != 0) {
Double_t x = d[0];
Double_t xmin = ele->GetXmin();
Double_t xmax = ele->GetXmax();
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
UInt_t aint = UInt_t(0.5+ele->GetFactor()*(x-xmin)); *this << aint;
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) {
Float_t afloat = (Float_t)d[0];
*this << afloat;
} else {
union {
Float_t xx;
Int_t ix;
};
xx = (Float_t)d[0];
UChar_t theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1)) ;
theMan++;
theMan = theMan>>1;
if (theMan&1<<nbits) theMan = (1<<nbits)-1 ;
if (xx < 0) theMan |= 1<<(nbits+1);
*this << theExp;
*this << theMan;
}
}
}
Int_t TBufferFile::ReadArray(Bool_t *&b)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || n > fBufSize) return 0;
if (!b) b = new Bool_t[n];
if (sizeof(Bool_t) > 1) {
for (int i = 0; i < n; i++)
frombuf(fBufCur, &b[i]);
} else {
Int_t l = sizeof(Bool_t)*n;
memcpy(b, fBufCur, l);
fBufCur += l;
}
return n;
}
Int_t TBufferFile::ReadArray(Char_t *&c)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Char_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!c) c = new Char_t[n];
memcpy(c, fBufCur, l);
fBufCur += l;
return n;
}
Int_t TBufferFile::ReadArray(Short_t *&h)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Short_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!h) h = new Short_t[n];
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy16(h, fBufCur, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &h[i]);
# endif
#else
memcpy(h, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadArray(Int_t *&ii)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Int_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ii) ii = new Int_t[n];
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(ii, fBufCur, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ii[i]);
# endif
#else
memcpy(ii, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadArray(Long_t *&ll)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Long_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ll) ll = new Long_t[n];
TFile *file = (TFile*)fParent;
if (file && file->GetVersion() < 30006) {
for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
} else {
for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
}
return n;
}
Int_t TBufferFile::ReadArray(Long64_t *&ll)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Long64_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ll) ll = new Long64_t[n];
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ll[i]);
#else
memcpy(ll, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadArray(Float_t *&f)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Float_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!f) f = new Float_t[n];
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(f, fBufCur, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &f[i]);
# endif
#else
memcpy(f, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadArray(Double_t *&d)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Double_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!d) d = new Double_t[n];
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &d[i]);
#else
memcpy(d, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadArrayFloat16(Float_t *&f, TStreamerElement *ele)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || 4*n > fBufSize) return 0;
if (!f) f = new Float_t[n];
ReadFastArrayFloat16(f,n,ele);
return n;
}
Int_t TBufferFile::ReadArrayDouble32(Double_t *&d, TStreamerElement *ele)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || 4*n > fBufSize) return 0;
if (!d) d = new Double_t[n];
ReadFastArrayDouble32(d,n,ele);
return n;
}
Int_t TBufferFile::ReadStaticArray(Bool_t *b)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || n > fBufSize) return 0;
if (!b) return 0;
if (sizeof(Bool_t) > 1) {
for (int i = 0; i < n; i++)
frombuf(fBufCur, &b[i]);
} else {
Int_t l = sizeof(Bool_t)*n;
memcpy(b, fBufCur, l);
fBufCur += l;
}
return n;
}
Int_t TBufferFile::ReadStaticArray(Char_t *c)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Char_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!c) return 0;
memcpy(c, fBufCur, l);
fBufCur += l;
return n;
}
Int_t TBufferFile::ReadStaticArray(Short_t *h)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Short_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!h) return 0;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy16(h, fBufCur, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &h[i]);
# endif
#else
memcpy(h, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadStaticArray(Int_t *ii)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Int_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ii) return 0;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(ii, fBufCur, n);
fBufCur += sizeof(Int_t)*n;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ii[i]);
# endif
#else
memcpy(ii, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadStaticArray(Long_t *ll)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Long_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ll) return 0;
TFile *file = (TFile*)fParent;
if (file && file->GetVersion() < 30006) {
for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
} else {
for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
}
return n;
}
Int_t TBufferFile::ReadStaticArray(Long64_t *ll)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Long64_t)*n;
if (l <= 0 || l > fBufSize) return 0;
if (!ll) return 0;
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ll[i]);
#else
memcpy(ll, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadStaticArray(Float_t *f)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Float_t)*n;
if (n <= 0 || l > fBufSize) return 0;
if (!f) return 0;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(f, fBufCur, n);
fBufCur += sizeof(Float_t)*n;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &f[i]);
# endif
#else
memcpy(f, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadStaticArray(Double_t *d)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
Int_t l = sizeof(Double_t)*n;
if (n <= 0 || l > fBufSize) return 0;
if (!d) return 0;
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &d[i]);
#else
memcpy(d, fBufCur, l);
fBufCur += l;
#endif
return n;
}
Int_t TBufferFile::ReadStaticArrayFloat16(Float_t *f, TStreamerElement *ele)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || 4*n > fBufSize) return 0;
if (!f) return 0;
ReadFastArrayFloat16(f,n,ele);
return n;
}
Int_t TBufferFile::ReadStaticArrayDouble32(Double_t *d, TStreamerElement *ele)
{
R__ASSERT(IsReading());
Int_t n;
*this >> n;
if (n <= 0 || 4*n > fBufSize) return 0;
if (!d) return 0;
ReadFastArrayDouble32(d,n,ele);
return n;
}
void TBufferFile::ReadFastArray(Bool_t *b, Int_t n)
{
if (n <= 0 || n > fBufSize) return;
if (sizeof(Bool_t) > 1) {
for (int i = 0; i < n; i++)
frombuf(fBufCur, &b[i]);
} else {
Int_t l = sizeof(Bool_t)*n;
memcpy(b, fBufCur, l);
fBufCur += l;
}
}
void TBufferFile::ReadFastArray(Char_t *c, Int_t n)
{
if (n <= 0 || n > fBufSize) return;
Int_t l = sizeof(Char_t)*n;
memcpy(c, fBufCur, l);
fBufCur += l;
}
void TBufferFile::ReadFastArrayString(Char_t *c, Int_t n)
{
Int_t len;
UChar_t lenchar;
*this >> lenchar;
if (lenchar < 255) {
len = lenchar;
} else {
*this >> len;
}
if (len) {
if (len <= 0 || len > fBufSize) return;
Int_t blen = len;
if (len >= n) len = n-1;
Int_t l = sizeof(Char_t)*len;
memcpy(c, fBufCur, l);
fBufCur += blen;
c[len] = 0;
} else {
c[0] = 0;
}
}
void TBufferFile::ReadFastArray(Short_t *h, Int_t n)
{
Int_t l = sizeof(Short_t)*n;
if (n <= 0 || l > fBufSize) return;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy16(h, fBufCur, n);
fBufCur += sizeof(Short_t)*n;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &h[i]);
# endif
#else
memcpy(h, fBufCur, l);
fBufCur += l;
#endif
}
void TBufferFile::ReadFastArray(Int_t *ii, Int_t n)
{
Int_t l = sizeof(Int_t)*n;
if (l <= 0 || l > fBufSize) return;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(ii, fBufCur, n);
fBufCur += sizeof(Int_t)*n;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ii[i]);
# endif
#else
memcpy(ii, fBufCur, l);
fBufCur += l;
#endif
}
void TBufferFile::ReadFastArray(Long_t *ll, Int_t n)
{
Int_t l = sizeof(Long_t)*n;
if (l <= 0 || l > fBufSize) return;
TFile *file = (TFile*)fParent;
if (file && file->GetVersion() < 30006) {
for (int i = 0; i < n; i++) frombufOld(fBufCur, &ll[i]);
} else {
for (int i = 0; i < n; i++) frombuf(fBufCur, &ll[i]);
}
}
void TBufferFile::ReadFastArray(Long64_t *ll, Int_t n)
{
Int_t l = sizeof(Long64_t)*n;
if (l <= 0 || l > fBufSize) return;
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &ll[i]);
#else
memcpy(ll, fBufCur, l);
fBufCur += l;
#endif
}
void TBufferFile::ReadFastArray(Float_t *f, Int_t n)
{
Int_t l = sizeof(Float_t)*n;
if (l <= 0 || l > fBufSize) return;
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(f, fBufCur, n);
fBufCur += sizeof(Float_t)*n;
# else
for (int i = 0; i < n; i++)
frombuf(fBufCur, &f[i]);
# endif
#else
memcpy(f, fBufCur, l);
fBufCur += l;
#endif
}
void TBufferFile::ReadFastArray(Double_t *d, Int_t n)
{
Int_t l = sizeof(Double_t)*n;
if (l <= 0 || l > fBufSize) return;
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
frombuf(fBufCur, &d[i]);
#else
memcpy(d, fBufCur, l);
fBufCur += l;
#endif
}
void TBufferFile::ReadFastArrayFloat16(Float_t *f, Int_t n, TStreamerElement *ele)
{
if (n <= 0 || 4*n > fBufSize) return;
if (ele && ele->GetFactor() != 0) {
Double_t xmin = ele->GetXmin();
Double_t factor = ele->GetFactor();
for (int j=0;j < n; j++) {
UInt_t aint; *this >> aint; f[j] = (Float_t)(aint/factor + xmin);
}
} else {
Int_t i;
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) nbits = 12;
union {
Float_t xx;
Int_t ix;
};
UChar_t theExp;
UShort_t theMan;
for (i = 0; i < n; i++) {
*this >> theExp;
*this >> theMan;
ix = theExp;
ix <<= 23;
ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
if(1<<(nbits+1) & theMan) xx=-xx;
f[i] = xx;
}
}
}
void TBufferFile::ReadFastArrayDouble32(Double_t *d, Int_t n, TStreamerElement *ele)
{
if (n <= 0 || 4*n > fBufSize) return;
if (ele && ele->GetFactor() != 0) {
Double_t xmin = ele->GetXmin();
Double_t factor = ele->GetFactor();
for (int j=0;j < n; j++) {
UInt_t aint; *this >> aint; d[j] = (Double_t)(aint/factor + xmin);
}
} else {
Int_t i;
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) {
Float_t afloat;
for (i = 0; i < n; i++) {
*this >> afloat;
d[i] = (Double_t)afloat;
}
} else {
union {
Float_t xx;
Int_t ix;
};
UChar_t theExp;
UShort_t theMan;
for (i = 0; i < n; i++) {
*this >> theExp;
*this >> theMan;
ix = theExp;
ix <<= 23;
ix |= (theMan & ((1<<(nbits+1))-1)) <<(23-nbits);
if (1<<(nbits+1) & theMan) xx=-xx;
d[i] = (Double_t)xx;
}
}
}
}
void TBufferFile::ReadFastArray(void *start, const TClass *cl, Int_t n,
TMemberStreamer *streamer, const TClass* onFileClass )
{
if (streamer) {
streamer->SetOnFileClass(onFileClass);
(*streamer)(*this,start,0);
return;
}
int objectSize = cl->Size();
char *obj = (char*)start;
char *end = obj + n*objectSize;
for(; obj<end; obj+=objectSize) ((TClass*)cl)->Streamer(obj,*this, onFileClass);
}
void TBufferFile::ReadFastArray(void **start, const TClass *cl, Int_t n,
Bool_t isPreAlloc, TMemberStreamer *streamer, const TClass* onFileClass)
{
if (streamer) {
if (isPreAlloc) {
for (Int_t j=0;j<n;j++) {
if (!start[j]) start[j] = cl->New();
}
}
streamer->SetOnFileClass(onFileClass);
(*streamer)(*this,(void*)start,0);
return;
}
if (!isPreAlloc) {
for (Int_t j=0; j<n; j++){
void *old = start[j];
start[j] = ReadObjectAny(cl);
if (old && old!=start[j] &&
TStreamerInfo::CanDelete()
) {
((TClass*)cl)->Destructor(old,kFALSE);
}
}
} else {
for (Int_t j=0; j<n; j++){
if (!start[j]) start[j] = ((TClass*)cl)->New();
((TClass*)cl)->Streamer(start[j],*this,onFileClass);
}
}
}
void TBufferFile::WriteArray(const Bool_t *b, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(b);
Int_t l = sizeof(UChar_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
if (sizeof(Bool_t) > 1) {
for (int i = 0; i < n; i++)
tobuf(fBufCur, b[i]);
} else {
memcpy(fBufCur, b, l);
fBufCur += l;
}
}
void TBufferFile::WriteArray(const Char_t *c, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(c);
Int_t l = sizeof(Char_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
memcpy(fBufCur, c, l);
fBufCur += l;
}
void TBufferFile::WriteArray(const Short_t *h, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(h);
Int_t l = sizeof(Short_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy16(fBufCur, h, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, h[i]);
# endif
#else
memcpy(fBufCur, h, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteArray(const Int_t *ii, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(ii);
Int_t l = sizeof(Int_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(fBufCur, ii, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, ii[i]);
# endif
#else
memcpy(fBufCur, ii, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteArray(const Long_t *ll, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(ll);
Int_t l = 8*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
}
void TBufferFile::WriteArray(const ULong_t *ll, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(ll);
Int_t l = 8*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
}
void TBufferFile::WriteArray(const Long64_t *ll, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(ll);
Int_t l = sizeof(Long64_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
tobuf(fBufCur, ll[i]);
#else
memcpy(fBufCur, ll, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteArray(const Float_t *f, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(f);
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(fBufCur, f, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, f[i]);
# endif
#else
memcpy(fBufCur, f, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteArray(const Double_t *d, Int_t n)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(d);
Int_t l = sizeof(Double_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
tobuf(fBufCur, d[i]);
#else
memcpy(fBufCur, d, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(f);
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
WriteFastArrayFloat16(f,n,ele);
}
void TBufferFile::WriteArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
{
R__ASSERT(IsWriting());
*this << n;
if (n <= 0) return;
R__ASSERT(d);
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
WriteFastArrayDouble32(d,n,ele);
}
void TBufferFile::WriteFastArray(const Bool_t *b, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(UChar_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
if (sizeof(Bool_t) > 1) {
for (int i = 0; i < n; i++)
tobuf(fBufCur, b[i]);
} else {
memcpy(fBufCur, b, l);
fBufCur += l;
}
}
void TBufferFile::WriteFastArray(const Char_t *c, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Char_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
memcpy(fBufCur, c, l);
fBufCur += l;
}
void TBufferFile::WriteFastArrayString(const Char_t *c, Int_t n)
{
if (n < 255) {
*this << (UChar_t)n;
} else {
*this << (UChar_t)255;
*this << n;
}
if (n <= 0) return;
Int_t l = sizeof(Char_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
memcpy(fBufCur, c, l);
fBufCur += l;
}
void TBufferFile::WriteFastArray(const Short_t *h, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Short_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy16(fBufCur, h, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, h[i]);
# endif
#else
memcpy(fBufCur, h, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteFastArray(const Int_t *ii, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Int_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(fBufCur, ii, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, ii[i]);
# endif
#else
memcpy(fBufCur, ii, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteFastArray(const Long_t *ll, Int_t n)
{
if (n <= 0) return;
Int_t l = 8*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
}
void TBufferFile::WriteFastArray(const ULong_t *ll, Int_t n)
{
if (n <= 0) return;
Int_t l = 8*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
for (int i = 0; i < n; i++) tobuf(fBufCur, ll[i]);
}
void TBufferFile::WriteFastArray(const Long64_t *ll, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Long64_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
tobuf(fBufCur, ll[i]);
#else
memcpy(fBufCur, ll, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteFastArray(const Float_t *f, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
# ifdef USE_BSWAPCPY
bswapcpy32(fBufCur, f, n);
fBufCur += l;
# else
for (int i = 0; i < n; i++)
tobuf(fBufCur, f[i]);
# endif
#else
memcpy(fBufCur, f, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteFastArray(const Double_t *d, Int_t n)
{
if (n <= 0) return;
Int_t l = sizeof(Double_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
#ifdef R__BYTESWAP
for (int i = 0; i < n; i++)
tobuf(fBufCur, d[i]);
#else
memcpy(fBufCur, d, l);
fBufCur += l;
#endif
}
void TBufferFile::WriteFastArrayFloat16(const Float_t *f, Int_t n, TStreamerElement *ele)
{
if (n <= 0) return;
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
if (ele && ele->GetFactor()) {
Double_t factor = ele->GetFactor();
Double_t xmin = ele->GetXmin();
Double_t xmax = ele->GetXmax();
for (int j = 0; j < n; j++) {
Float_t x = f[j];
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
}
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
if (!nbits) nbits = 12;
Int_t i;
union {
Float_t xx;
Int_t ix;
};
for (i = 0; i < n; i++) {
xx = f[i];
UChar_t theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
theMan++;
theMan = theMan>>1;
if (theMan&1<<nbits) theMan = (1<<nbits) - 1;
if (xx < 0) theMan |= 1<<(nbits+1);
*this << theExp;
*this << theMan;
}
}
}
void TBufferFile::WriteFastArrayDouble32(const Double_t *d, Int_t n, TStreamerElement *ele)
{
if (n <= 0) return;
Int_t l = sizeof(Float_t)*n;
if (fBufCur + l > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+l));
if (ele && ele->GetFactor()) {
Double_t factor = ele->GetFactor();
Double_t xmin = ele->GetXmin();
Double_t xmax = ele->GetXmax();
for (int j = 0; j < n; j++) {
Double_t x = d[j];
if (x < xmin) x = xmin;
if (x > xmax) x = xmax;
UInt_t aint = UInt_t(0.5+factor*(x-xmin)); *this << aint;
}
} else {
Int_t nbits = 0;
if (ele) nbits = (Int_t)ele->GetXmin();
Int_t i;
if (!nbits) {
for (i = 0; i < n; i++) {
Float_t afloat = (Float_t)d[i];
*this << afloat;
}
} else {
union {
Float_t xx;
Int_t ix;
};
for (i = 0; i < n; i++) {
xx = (Float_t)d[i];
UChar_t theExp = (UChar_t)(0x000000ff & ((ix<<1)>>24));
UShort_t theMan = ((1<<(nbits+1))-1) & (ix>>(23-nbits-1));
theMan++;
theMan = theMan>>1;
if(theMan&1<<nbits) theMan = (1<<nbits) - 1;
if (xx < 0) theMan |= 1<<(nbits+1);
*this << theExp;
*this << theMan;
}
}
}
}
void TBufferFile::WriteFastArray(void *start, const TClass *cl, Int_t n,
TMemberStreamer *streamer)
{
if (streamer) {
(*streamer)(*this, start, 0);
return;
}
char *obj = (char*)start;
if (!n) n=1;
int size = cl->Size();
for(Int_t j=0; j<n; j++,obj+=size) {
((TClass*)cl)->Streamer(obj,*this);
}
}
Int_t TBufferFile::WriteFastArray(void **start, const TClass *cl, Int_t n,
Bool_t isPreAlloc, TMemberStreamer *streamer)
{
if (streamer) {
(*streamer)(*this,(void*)start,0);
return 0;
}
int strInfo = 0;
Int_t res = 0;
if (!isPreAlloc) {
for (Int_t j=0;j<n;j++) {
if (!strInfo && !start[j] ) {
TStreamerInfo *info = (TStreamerInfo*)((TClass*)cl)->GetStreamerInfo();
ForceWriteInfo(info,kFALSE);
}
strInfo = 2003;
res |= WriteObjectAny(start[j],cl);
}
} else {
for (Int_t j=0;j<n;j++) {
if (!start[j]) start[j] = ((TClass*)cl)->New();
((TClass*)cl)->Streamer(start[j],*this);
}
}
return res;
}
TObject *TBufferFile::ReadObject(const TClass * )
{
return (TObject*) ReadObjectAny(0);
}
void TBufferFile::SkipObjectAny()
{
UInt_t start, count;
ReadVersion(&start, &count);
SetBufferOffset(start+count+sizeof(UInt_t));
}
void *TBufferFile::ReadObjectAny(const TClass *clCast)
{
R__ASSERT(IsReading());
InitMap();
UInt_t startpos = UInt_t(fBufCur-fBuffer);
UInt_t tag;
TClass *clRef = ReadClass(clCast, &tag);
TClass *clOnfile = 0;
Int_t baseOffset = 0;
if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
baseOffset = clRef->GetBaseClassOffset(clCast);
if (baseOffset == -1) {
if (!clCast->GetSchemaRules() ||
!clCast->GetSchemaRules()->HasRuleWithSourceClass(clRef->GetName()))
{
Error("ReadObject", "got object of wrong class! requested %s but got %s",
clCast->GetName(), clRef->GetName());
CheckByteCount(startpos, tag, (TClass*)0);
return 0;
}
baseOffset = 0;
Info("ReadObjectAny","Using Converter StreamerInfo from %s to %s",clRef->GetName(),clCast->GetName());
clRef = const_cast<TClass*>(clCast);
}
if (clCast->GetClassInfo() && !clRef->GetClassInfo()) {
Error("ReadObject", "trying to read an emulated class (%s) to store in a compiled pointer (%s)",
clRef->GetName(),clCast->GetName());
CheckByteCount(startpos, tag, (TClass*)0);
return 0;
}
}
char *obj;
if (fVersion > 0) {
obj = (char *) fMap->GetValue(startpos+kMapOffset);
if (obj == (void*) -1) obj = 0;
if (obj) {
CheckByteCount(startpos, tag, (TClass*)0);
return (obj+baseOffset);
}
}
if (clRef == (TClass*) -1) {
if (fBufCur >= fBufMax) return 0;
if (fVersion > 0)
MapObject((TObject*) -1, startpos+kMapOffset);
else
MapObject((void*)0, 0, fMapCount);
CheckByteCount(startpos, tag, (TClass*)0);
return 0;
}
if (!clRef) {
if (fVersion > 0) {
tag += fDisplacement;
tag = CheckObject(tag, clCast);
} else {
if (tag > (UInt_t)fMap->GetSize()) {
Error("ReadObject", "object tag too large, I/O buffer corrupted");
return 0;
}
}
obj = (char *) fMap->GetValue(tag);
clRef = (TClass*) fClassMap->GetValue(tag);
if (clRef && (clRef!=(TClass*)(-1)) && clCast) {
baseOffset = clRef->GetBaseClassOffset(clCast);
if (baseOffset == -1) {
Error("ReadObject", "Got object of wrong class (Got %s while expecting %s)",
clRef->GetName(),clCast->GetName());
baseOffset = 0;
}
}
} else {
obj = (char*)clRef->New();
if (!obj) {
Error("ReadObject", "could not create object of class %s",
clRef->GetName());
return 0;
}
if (fVersion > 0)
MapObject(obj, clRef, startpos+kMapOffset);
else
MapObject(obj, clRef, fMapCount);
clRef->Streamer( obj, *this, clOnfile );
CheckByteCount(startpos, tag, clRef);
}
return obj+baseOffset;
}
void TBufferFile::WriteObject(const TObject *obj)
{
WriteObjectAny(obj, TObject::Class());
}
void TBufferFile::WriteObjectClass(const void *actualObjectStart, const TClass *actualClass)
{
R__ASSERT(IsWriting());
if (!actualObjectStart) {
*this << kNullTag;
} else {
InitMap();
ULong_t idx;
UInt_t slot;
ULong_t hash = Void_Hash(actualObjectStart);
if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)actualObjectStart, slot)) != 0) {
UInt_t objIdx = UInt_t(idx);
*this << objIdx;
} else {
if (actualClass->HasDefaultConstructor() == 0) {
Warning("WriteObjectAny", "since %s has no public constructor\n"
"\twhich can be called without argument, objects of this class\n"
"\tcan not be read with the current library. You will need to\n"
"\tadd a default constructor before attempting to read it.",
actualClass->GetName());
}
UInt_t cntpos = UInt_t(fBufCur-fBuffer);
fBufCur += sizeof(UInt_t);
Int_t mapsize = fMap->Capacity();
WriteClass(actualClass);
UInt_t offset = cntpos+kMapOffset;
if (mapsize == fMap->Capacity()) {
fMap->AddAt(slot, hash, (Long_t)actualObjectStart, offset);
} else {
fMap->Add(hash, (Long_t)actualObjectStart, offset);
}
fMapCount++;
((TClass*)actualClass)->Streamer((void*)actualObjectStart,*this);
SetByteCount(cntpos);
}
}
}
namespace {
struct DynamicType {
virtual ~DynamicType() {}
};
}
Int_t TBufferFile::WriteObjectAny(const void *obj, const TClass *ptrClass)
{
if (!obj) {
WriteObjectClass(0, 0);
return 1;
}
if (!ptrClass) {
Error("WriteObjectAny", "ptrClass argument may not be 0");
return 0;
}
TClass *clActual = ptrClass->GetActualClass(obj);
if (clActual==0) {
DynamicType* d_ptr = (DynamicType*)obj;
Warning("WriteObjectAny",
"An object of type %s (from type_info) passed through a %s pointer was truncated (due a missing dictionary)!!!",
typeid(*d_ptr).name(),ptrClass->GetName());
WriteObjectClass(obj, ptrClass);
return 2;
} else if (clActual && (clActual != ptrClass)) {
const char *temp = (const char*) obj;
temp -= clActual->GetBaseClassOffset(ptrClass);
WriteObjectClass(temp, clActual);
return 1;
} else {
WriteObjectClass(obj, ptrClass);
return 1;
}
}
TClass *TBufferFile::ReadClass(const TClass *clReq, UInt_t *objTag)
{
R__ASSERT(IsReading());
TClass *cl;
if (fBufCur < fBuffer || fBufCur > fBufMax) {
fBufCur = fBufMax;
cl = (TClass*)-1;
return cl;
}
UInt_t bcnt, tag, startpos = 0;
*this >> bcnt;
if (!(bcnt & kByteCountMask) || bcnt == kNewClassTag) {
tag = bcnt;
bcnt = 0;
} else {
fVersion = 1;
startpos = UInt_t(fBufCur-fBuffer);
*this >> tag;
}
if (!(tag & kClassMask)) {
if (objTag) *objTag = tag;
return 0;
}
if (tag == kNewClassTag) {
cl = TClass::Load(*this);
if (fVersion > 0) {
TClass *cl1 = (TClass *)fMap->GetValue(startpos+kMapOffset);
if (cl1 != cl)
MapObject(cl ? cl : (TObject*) -1, startpos+kMapOffset);
} else
MapObject(cl, fMapCount);
} else {
UInt_t clTag = (tag & ~kClassMask);
if (fVersion > 0) {
clTag += fDisplacement;
clTag = CheckObject(clTag, clReq, kTRUE);
} else {
if (clTag == 0 || clTag > (UInt_t)fMap->GetSize()) {
Error("ReadClass", "illegal class tag=%d (0<tag<=%d), I/O buffer corrupted",
clTag, fMap->GetSize());
}
}
cl = (TClass *)fMap->GetValue(clTag);
}
if (cl && clReq &&
(!cl->InheritsFrom(clReq) &&
!(clReq->GetSchemaRules() &&
clReq->GetSchemaRules()->HasRuleWithSourceClass(cl->GetName()) )
) ) {
Error("ReadClass", "got wrong class: %s", cl->GetName());
}
if (objTag) *objTag = (bcnt & ~kByteCountMask);
if (!cl) cl = (TClass*)-1;
return cl;
}
void TBufferFile::WriteClass(const TClass *cl)
{
R__ASSERT(IsWriting());
ULong_t idx;
ULong_t hash = Void_Hash(cl);
UInt_t slot;
if ((idx = (ULong_t)fMap->GetValue(hash, (Long_t)cl,slot)) != 0) {
UInt_t clIdx = UInt_t(idx);
*this << (clIdx | kClassMask);
} else {
UInt_t offset = UInt_t(fBufCur-fBuffer);
*this << kNewClassTag;
cl->Store(*this);
CheckCount(offset+kMapOffset);
fMap->AddAt(slot, hash, (Long_t)cl, offset+kMapOffset);
fMapCount++;
}
}
Version_t TBufferFile::ReadVersion(UInt_t *startpos, UInt_t *bcnt, const TClass *cl)
{
Version_t version;
if (startpos && bcnt) {
*startpos = UInt_t(fBufCur-fBuffer);
union {
UInt_t cnt;
Version_t vers[2];
} v;
#ifdef R__BYTESWAP
*this >> v.vers[1];
*this >> v.vers[0];
#else
*this >> v.vers[0];
*this >> v.vers[1];
#endif
if (!(v.cnt & kByteCountMask)) {
fBufCur -= sizeof(UInt_t);
v.cnt = 0;
}
*bcnt = (v.cnt & ~kByteCountMask);
*this >> version;
} else {
*this >> version;
if (version & kByteCountVMask) {
*this >> version;
*this >> version;
}
}
if (cl && cl->GetClassVersion() != 0) {
if (version <= 0) {
UInt_t checksum = 0;
*this >> checksum;
TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
if (vinfo) {
version = vinfo->GetClassVersion();
} else {
if (checksum==cl->GetCheckSum() || checksum==cl->GetCheckSum(1)) {
version = cl->GetClassVersion();
} else {
if (fParent) {
Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
checksum, cl->GetName(), ((TFile*)fParent)->GetName());
} else {
Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\"( buffer with no parent)",
checksum, cl->GetName());
}
return 0;
}
}
} else if (version == 1 && fParent && ((TFile*)fParent)->GetVersion()<40000 ) {
if ((!cl->IsLoaded() || cl->IsForeign()) &&
cl->GetStreamerInfos()->GetLast()>1 ) {
const TList *list = ((TFile*)fParent)->GetStreamerInfoCache();
const TStreamerInfo *local = (TStreamerInfo*)list->FindObject(cl->GetName());
if ( local ) {
UInt_t checksum = local->GetCheckSum();
TStreamerInfo *vinfo = (TStreamerInfo*)cl->FindStreamerInfo(checksum);
if (vinfo) {
version = vinfo->GetClassVersion();
} else {
Error("ReadVersion", "Could not find the StreamerInfo with a checksum of %d for the class \"%s\" in %s.",
checksum, cl->GetName(), ((TFile*)fParent)->GetName());
return 0;
}
}
else {
Error("ReadVersion", "Class %s not known to file %s.",
cl->GetName(), ((TFile*)fParent)->GetName());
version = 0;
}
}
}
}
return version;
}
UInt_t TBufferFile::WriteVersion(const TClass *cl, Bool_t useBcnt)
{
UInt_t cntpos = 0;
if (useBcnt) {
cntpos = UInt_t(fBufCur-fBuffer);
fBufCur += sizeof(UInt_t);
}
Version_t version = cl->GetClassVersion();
if (version<=1 && cl->IsForeign()) {
*this << Version_t(0);
*this << cl->GetCheckSum();
} else {
if (version > kMaxVersion) {
Error("WriteVersion", "version number cannot be larger than %hd)",
kMaxVersion);
version = kMaxVersion;
}
*this <<version;
}
return cntpos;
}
UInt_t TBufferFile::WriteVersionMemberWise(const TClass *cl, Bool_t useBcnt)
{
UInt_t cntpos = 0;
if (useBcnt) {
cntpos = UInt_t(fBufCur-fBuffer);
fBufCur += sizeof(UInt_t);
}
Version_t version = cl->GetClassVersion();
if (version<=1 && cl->IsForeign()) {
Error("WriteVersionMemberWise", "Member-wise streaming of foreign collection not yet implemented!");
*this << Version_t(0);
*this << cl->GetCheckSum();
} else {
if (version > kMaxVersion) {
Error("WriteVersionMemberWise", "version number cannot be larger than %hd)",
kMaxVersion);
version = kMaxVersion;
}
version |= kStreamedMemberWise;
*this <<version;
}
return cntpos;
}
void TBufferFile::StreamObject(void *obj, const type_info &typeinfo, const TClass* onFileClass )
{
TClass *cl = TClass::GetClass(typeinfo);
cl->Streamer(obj, *this, (TClass*)onFileClass );
}
void TBufferFile::StreamObject(void *obj, const char *className, const TClass* onFileClass)
{
TClass *cl = TClass::GetClass(className);
cl->Streamer(obj, *this, (TClass*)onFileClass );
}
void TBufferFile::StreamObject(void *obj, const TClass *cl, const TClass* onFileClass )
{
((TClass*)cl)->Streamer(obj, *this, (TClass*)onFileClass );
}
void TBufferFile::StreamObject(TObject *obj)
{
obj->Streamer(*this);
}
void TBufferFile::CheckCount(UInt_t offset)
{
if (IsWriting()) {
if (offset >= kMaxMapCount) {
Error("CheckCount", "buffer offset too large (larger than %d)", kMaxMapCount);
}
}
}
UInt_t TBufferFile::CheckObject(UInt_t offset, const TClass *cl, Bool_t readClass)
{
if (!offset) return offset;
Long_t cli;
if (readClass) {
if ((cli = fMap->GetValue(offset)) == 0) {
char *bufsav = fBufCur;
fBufCur = (char *)(fBuffer + offset-kMapOffset-sizeof(UInt_t));
TClass *c = ReadClass(cl);
if (c == (TClass*) -1) {
fMap->Remove(offset);
fMap->Add(offset, -1);
offset = 0;
if (cl)
Warning("CheckObject", "reference to unavailable class %s,"
" pointers of this type will be 0", cl->GetName());
else
Warning("CheckObject", "reference to an unavailable class,"
" pointers of that type will be 0");
}
fBufCur = bufsav;
} else if (cli == -1) {
return 0;
}
} else {
if ((cli = fMap->GetValue(offset)) == 0) {
char *bufsav = fBufCur;
fBufCur = (char *)(fBuffer + offset-kMapOffset);
TObject *obj = ReadObject(cl);
if (!obj) {
fMap->Remove(offset);
fMap->Add(offset, -1);
Warning("CheckObject", "reference to object of unavailable class %s, offset=%d"
" pointer will be 0", cl ? cl->GetName() : "TObject",offset);
offset = 0;
}
fBufCur = bufsav;
} else if (cli == -1) {
return 0;
}
}
return offset;
}
Bool_t TBufferFile::CheckObject(const TObject *obj)
{
return CheckObject(obj, TObject::Class());
}
Bool_t TBufferFile::CheckObject(const void *obj, const TClass *ptrClass)
{
if (!obj || !fMap || !ptrClass) return kFALSE;
TClass *clActual = ptrClass->GetActualClass(obj);
ULong_t idx;
if (clActual && (ptrClass != clActual)) {
const char *temp = (const char*) obj;
temp -= clActual->GetBaseClassOffset(ptrClass);
idx = (ULong_t)fMap->GetValue(Void_Hash(temp), (Long_t)temp);
} else {
idx = (ULong_t)fMap->GetValue(Void_Hash(obj), (Long_t)obj);
}
return idx ? kTRUE : kFALSE;
}
void TBufferFile::SetPidOffset(UShort_t offset)
{
fPidOffset = offset;
}
void TBufferFile::GetMappedObject(UInt_t tag, void* &ptr, TClass* &ClassPtr) const
{
if (tag > (UInt_t)fMap->GetSize()) {
ptr = 0;
ClassPtr = 0;
} else {
ptr = (void*)fMap->GetValue(tag);
ClassPtr = (TClass*) fClassMap->GetValue(tag);
}
}
void TBufferFile::MapObject(const TObject *obj, UInt_t offset)
{
if (IsWriting()) {
if (!fMap) InitMap();
if (obj) {
CheckCount(offset);
ULong_t hash = Void_Hash(obj);
fMap->Add(hash, (Long_t)obj, offset);
fMapCount++;
}
} else {
if (!fMap || !fClassMap) InitMap();
fMap->Add(offset, (Long_t)obj);
fClassMap->Add(offset,
(obj && obj != (TObject*)-1) ? (Long_t)((TObject*)obj)->IsA() : 0);
fMapCount++;
}
}
void TBufferFile::MapObject(const void *obj, const TClass* cl, UInt_t offset)
{
if (IsWriting()) {
if (!fMap) InitMap();
if (obj) {
CheckCount(offset);
ULong_t hash = Void_Hash(obj);
fMap->Add(hash, (Long_t)obj, offset);
fMapCount++;
}
} else {
if (!fMap || !fClassMap) InitMap();
fMap->Add(offset, (Long_t)obj);
fClassMap->Add(offset, (Long_t)cl);
fMapCount++;
}
}
void TBufferFile::SetReadParam(Int_t mapsize)
{
R__ASSERT(IsReading());
R__ASSERT(fMap == 0);
fMapSize = mapsize;
}
void TBufferFile::SetWriteParam(Int_t mapsize)
{
R__ASSERT(IsWriting());
R__ASSERT(fMap == 0);
fMapSize = mapsize;
}
void TBufferFile::InitMap()
{
if (IsWriting()) {
if (!fMap) {
fMap = new TExMap(fMapSize);
fMapCount = 0;
}
} else {
if (!fMap) {
fMap = new TExMap(fMapSize);
fMap->Add(0, kNullTag);
fMapCount = 1;
} else if (fMapCount==0) {
fMap->Add(0, kNullTag);
fMapCount = 1;
}
if (!fClassMap) {
fClassMap = new TExMap(fMapSize);
fClassMap->Add(0, kNullTag);
}
}
}
void TBufferFile::ResetMap()
{
if (fMap) fMap->Delete();
if (fClassMap) fClassMap->Delete();
fMapCount = 0;
fDisplacement = 0;
ResetBit(kUser1);
ResetBit(kUser2);
ResetBit(kUser3);
}
Int_t TBufferFile::ReadBuf(void *buf, Int_t max)
{
R__ASSERT(IsReading());
if (max == 0) return 0;
Int_t n = TMath::Min(max, (Int_t)(fBufMax - fBufCur));
memcpy(buf, fBufCur, n);
fBufCur += n;
return n;
}
void TBufferFile::WriteBuf(const void *buf, Int_t max)
{
R__ASSERT(IsWriting());
if (max == 0) return;
if (fBufCur + max > fBufMax) Expand(TMath::Max(2*fBufSize, fBufSize+max));
memcpy(fBufCur, buf, max);
fBufCur += max;
}
char *TBufferFile::ReadString(char *s, Int_t max)
{
R__ASSERT(IsReading());
char ch;
Int_t nr = 0;
if (max == -1) max = kMaxInt;
while (nr < max-1) {
*this >> ch;
if (ch == 0) break;
s[nr++] = ch;
}
s[nr] = 0;
return s;
}
void TBufferFile::WriteString(const char *s)
{
WriteBuf(s, (strlen(s)+1)*sizeof(char));
}
TProcessID *TBufferFile::GetLastProcessID(TRefTable *reftable) const
{
TFile *file = (TFile*)GetParent();
if (file && !reftable->TestBit(TRefTable::kHaveWarnedReadingOld) && file->GetNProcessIDs()>1) {
Warning("ReadBuffer", "The file was written during several processes with an "
"older ROOT version; the TRefTable entries might be inconsistent.");
reftable->SetBit(TRefTable::kHaveWarnedReadingOld);
}
TProcessID *fileProcessID = TProcessID::GetProcessID(0);
if (file && file->GetNProcessIDs() > 0) {
fileProcessID = (TProcessID *) file->GetListOfProcessIDs()->Last();
}
return fileProcessID;
}
TProcessID *TBufferFile::ReadProcessID(UShort_t pidf)
{
TFile *file = (TFile*)GetParent();
if (!file) {
if (!pidf) return TProcessID::GetPID();
return 0;
}
return file->ReadProcessID(pidf);
}
UInt_t TBufferFile::GetTRefExecId()
{
return TStreamerInfo::GetCurrentElement()->GetUniqueID();
}
UShort_t TBufferFile::WriteProcessID(TProcessID *pid)
{
TFile *file = (TFile*)GetParent();
if (!file) return 0;
return file->WriteProcessID(pid);
}
void TBufferFile::ForceWriteInfo(TVirtualStreamerInfo *info, Bool_t force)
{
if (info) info->ForceWriteInfo((TFile*)GetParent(),force);
}
void TBufferFile::ForceWriteInfoClones(TClonesArray *a)
{
Bool_t optim = TStreamerInfo::CanOptimize();
if (optim) TStreamerInfo::Optimize(kFALSE);
TStreamerInfo *sinfo = (TStreamerInfo*)a->GetClass()->GetStreamerInfo();
ForceWriteInfo(sinfo,kFALSE);
if (optim) TStreamerInfo::Optimize(kTRUE);
if (sinfo->IsOptimized()) a->BypassStreamer(kFALSE);
}
Int_t TBufferFile::ReadClones(TClonesArray *a, Int_t nobjects, Version_t objvers)
{
char **arr = (char **)a->GetObjectRef(0);
TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo(objvers);
return info->ReadBuffer(*this,arr,-1,nobjects,0,1);
}
Int_t TBufferFile::WriteClones(TClonesArray *a, Int_t nobjects)
{
char **arr = reinterpret_cast<char**>(a->GetObjectRef(0));
TStreamerInfo *info = (TStreamerInfo*)a->GetClass()->GetStreamerInfo();
return info->WriteBufferAux(*this,arr,-1,nobjects,0,1);
}
Int_t TBufferFile::ReadClassEmulated(const TClass *cl, void *object, const TClass *onFileClass)
{
UInt_t start,count;
Version_t v = ReadVersion(&start,&count);
void *ptr = &object;
if (count) {
TStreamerInfo *sinfo = 0;
if( onFileClass ) {
sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, v );
if( !sinfo )
return 0;
}
sinfo = (TStreamerInfo*)cl->GetStreamerInfo(v);
sinfo->ReadBuffer(*this,(char**)ptr,-1);
if (sinfo->IsRecovered()) count=0;
CheckByteCount(start,count,cl);
} else {
SetBufferOffset(start);
((TStreamerInfo*)cl->GetStreamerInfo())->ReadBuffer(*this,(char**)ptr,-1);
}
return 0;
}
Int_t TBufferFile::ReadClassBuffer(const TClass *cl, void *pointer, Int_t version, UInt_t start, UInt_t count, const TClass *onFileClass)
{
TObjArray *infos = cl->GetStreamerInfos();
Int_t ninfos = infos->GetSize();
if (version < -1 || version >= ninfos) {
Error("ReadBuffer1", "class: %s, attempting to access a wrong version: %d",cl->GetName(),version);
CheckByteCount(start, count, cl);
return 0;
}
TStreamerInfo *sinfo = 0;
if( onFileClass ) {
sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, version );
if( !sinfo ) {
Error( "ReadClassBuffer", "Could not find the right streamer info" );
CheckByteCount(start, count, onFileClass);
return 0;
}
}
else {
sinfo = (TStreamerInfo*)infos->At(version);
if (sinfo == 0) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
infos->AddAtAndExpand(sinfo, version);
if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n", cl->GetName(), version);
sinfo->Build();
} else if (!sinfo->GetOffsets()) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo->BuildOld();
}
}
void *ptr = &pointer;
sinfo->ReadBuffer(*this, (char**)ptr,-1);
if (sinfo->IsRecovered()) count=0;
CheckByteCount(start, count, cl);
return 0;
}
Int_t TBufferFile::ReadClassBuffer(const TClass *cl, void *pointer, const TClass *onFileClass)
{
UInt_t R__s = 0;
UInt_t R__c = 0;
Version_t version;
if( onFileClass )
version = ReadVersion(&R__s, &R__c, onFileClass);
else
version = ReadVersion(&R__s, &R__c, cl);
Bool_t v2file = kFALSE;
TFile *file = (TFile*)GetParent();
if (file && file->GetVersion() < 30000) {
version = -1;
v2file = kTRUE;
}
TStreamerInfo *sinfo = 0;
if( onFileClass ) {
sinfo = (TStreamerInfo*)cl->GetConversionStreamerInfo( onFileClass, version );
if( !sinfo ) {
Error( "ReadClassBuffer", "Could not find the right streamer info" );
CheckByteCount(R__s, R__c, onFileClass);
return 0;
}
}
else {
TObjArray *infos = cl->GetStreamerInfos();
Int_t ninfos = infos->GetSize();
if (version < -1 || version >= ninfos) {
Error("ReadClassBuffer","class: %s, attempting to access a wrong version: %d, object skipped at offset %d",
cl->GetName(), version,Length());
CheckByteCount(R__s, R__c, cl);
return 0;
}
sinfo = (TStreamerInfo*) infos->At(version);
if (sinfo == 0) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
infos->AddAtAndExpand(sinfo,version);
if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n", cl->GetName(), version);
sinfo->Build();
if (v2file) sinfo->BuildEmulated(file);
} else if (!sinfo->GetOffsets()) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo->BuildOld();
}
}
void *ptr = &pointer;
sinfo->ReadBuffer(*this, (char**)ptr,-1);
if (sinfo->IsRecovered()) R__c=0;
CheckByteCount(R__s, R__c, cl);
if (gDebug > 2) printf(" ReadBuffer for class: %s has read %d bytes\n", cl->GetName(), R__c);
return 0;
}
Int_t TBufferFile::WriteClassBuffer(const TClass *cl, void *pointer)
{
TStreamerInfo *sinfo = (TStreamerInfo*)const_cast<TClass*>(cl)->GetCurrentStreamerInfo();
if (sinfo == 0) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo = new TStreamerInfo(const_cast<TClass*>(cl));
const_cast<TClass*>(cl)->SetCurrentStreamerInfo(sinfo);
cl->GetStreamerInfos()->AddAtAndExpand(sinfo,cl->GetClassVersion());
if (gDebug > 0) printf("Creating StreamerInfo for class: %s, version: %d\n",cl->GetName(),cl->GetClassVersion());
sinfo->Build();
} else if (!sinfo->GetOffsets()) {
const_cast<TClass*>(cl)->BuildRealData(pointer);
sinfo->BuildOld();
}
if (sinfo->IsOptimized() && !TVirtualStreamerInfo::CanOptimize()) sinfo->Compile();
UInt_t R__c = WriteVersion(cl, kTRUE);
void *ptr = &pointer;
sinfo->WriteBufferAux(*this,(char**)ptr,-1,1,0,0);
SetByteCount(R__c, kTRUE);
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));
return 0;
}
void TBufferFile::SetGlobalReadParam(Int_t mapsize)
{
fgMapSize = mapsize;
}
void TBufferFile::SetGlobalWriteParam(Int_t mapsize)
{
fgMapSize = mapsize;
}
Int_t TBufferFile::GetGlobalReadParam()
{
return fgMapSize;
}
Int_t TBufferFile::GetGlobalWriteParam()
{
return fgMapSize;
}