#include "TEmulatedCollectionProxy.h"
#include "TStreamerElement.h"
#include "TStreamerInfo.h"
#include "TClassEdit.h"
#include "TError.h"
#include "TROOT.h"
#include "Riostream.h"
#include "TVirtualMutex.h"
static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset);
static TStreamerInfo *R__GenerateTClassForPair(const string &f, const string &s);
TEmulatedCollectionProxy::TEmulatedCollectionProxy(const TEmulatedCollectionProxy& copy)
: TGenCollectionProxy(copy)
{
}
TEmulatedCollectionProxy::TEmulatedCollectionProxy(const char* cl_name)
: TGenCollectionProxy(typeid(std::vector<char>), sizeof(std::vector<char>::iterator))
{
fName = cl_name;
this->TEmulatedCollectionProxy::InitializeEx();
}
TEmulatedCollectionProxy::~TEmulatedCollectionProxy()
{
if ( fEnv && fEnv->object ) {
Clear();
}
}
TVirtualCollectionProxy* TEmulatedCollectionProxy::Generate() const
{
if ( !fClass ) Initialize();
return new TEmulatedCollectionProxy(*this);
}
void TEmulatedCollectionProxy::Destructor(void* p, Bool_t dtorOnly)
{
if (!p) return;
TVirtualCollectionProxy::TPushPop env(this, p);
Clear();
if (!dtorOnly) {
delete (Cont_t*) p;
}
}
void TEmulatedCollectionProxy::DeleteArray(void* p, Bool_t dtorOnly)
{
Warning("DeleteArray", "Cannot properly delete emulated array of %s at %p, I don't know how many elements it has!", fClass->GetName(), p);
if (!dtorOnly) {
delete[] (Cont_t*) p;
}
}
TGenCollectionProxy *TEmulatedCollectionProxy::InitializeEx()
{
R__LOCKGUARD2(gCollectionMutex);
if (fClass) return this;
TClass *cl = TClass::GetClass(fName.c_str());
fEnv = 0;
fKey = 0;
if ( cl ) {
int nested = 0;
std::vector<std::string> inside;
fPointers = false;
int num = TClassEdit::GetSplit(fName.c_str(),inside,nested);
if ( num > 1 ) {
std::string nam;
if ( inside[0].find("stdext::hash_") != std::string::npos ) {
inside[0].replace(3,10,"::");
}
if ( inside[0].find("__gnu_cxx::hash_") != std::string::npos ) {
inside[0].replace(0,16,"std::");
}
fSTL_type = TClassEdit::STLKind(inside[0].c_str());
int slong = sizeof(void*);
switch ( fSTL_type ) {
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
nam = "pair<"+inside[1]+","+inside[2];
nam += (nam[nam.length()-1]=='>') ? " >" : ">";
if (0==TClass::GetClass(nam.c_str())) {
R__GenerateTClassForPair(inside[1],inside[2]);
}
fValue = new Value(nam);
fKey = new Value(inside[1]);
fVal = new Value(inside[2]);
fPointers |= 0 != (fKey->fCase&G__BIT_ISPOINTER);
if ( 0 == fValDiff ) {
fValDiff = fKey->fSize + fVal->fSize;
fValDiff += (slong - fKey->fSize%slong)%slong;
fValDiff += (slong - fValDiff%slong)%slong;
}
if ( 0 == fValOffset ) {
fValOffset = fKey->fSize;
fValOffset += (slong - fKey->fSize%slong)%slong;
}
break;
default:
fValue = new Value(inside[1]);
fVal = new Value(*fValue);
if ( 0 == fValDiff ) {
fValDiff = fVal->fSize;
if (fVal->fCase != G__BIT_ISFUNDAMENTAL) {
fValDiff += (slong - fValDiff%slong)%slong;
}
}
break;
}
fPointers |= 0 != (fVal->fCase&G__BIT_ISPOINTER);
fClass = cl;
return this;
}
Fatal("TEmulatedCollectionProxy","Components of %s not analysed!",cl->GetName());
}
Fatal("TEmulatedCollectionProxy","Collection class %s not found!",fTypeinfo.name());
return 0;
}
UInt_t TEmulatedCollectionProxy::Size() const
{
if ( fEnv && fEnv->object ) {
return fEnv->size = PCont_t(fEnv->object)->size()/fValDiff;
}
Fatal("TEmulatedCollectionProxy","Size> Logic error - no proxy object set.");
return 0;
}
void TEmulatedCollectionProxy::Clear(const char* opt)
{
Resize(0, opt && *opt=='f');
}
void TEmulatedCollectionProxy::Shrink(UInt_t nCurr, UInt_t left, Bool_t )
{
typedef std::string String_t;
PCont_t c = PCont_t(fEnv->object);
char* addr = ((char*)fEnv->start) + fValDiff*left;
size_t i;
switch ( fSTL_type ) {
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
addr = ((char*)fEnv->start) + fValDiff*left;
switch(fKey->fCase) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
break;
case G__BIT_ISCLASS:
for( i= fKey->fType ? left : nCurr; i<nCurr; ++i, addr += fValDiff ) {
fKey->fType->Destructor(addr, kTRUE);
}
break;
case kBIT_ISSTRING:
for( i=left; i<nCurr; ++i, addr += fValDiff ) {
((std::string*)addr)->~String_t();
}
break;
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
for( i=left; i<nCurr; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
h->set(0);
}
case G__BIT_ISPOINTER|kBIT_ISSTRING:
for( i=nCurr; i<left; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
h->set(0);
}
break;
case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
for( i=nCurr; i<left; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
h->set(0);
}
break;
}
addr = ((char*)fEnv->start)+fValOffset+fValDiff*left;
default:
switch( fVal->fCase ) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
break;
case G__BIT_ISCLASS:
for( i=left; i<nCurr; ++i, addr += fValDiff ) {
fVal->fType->Destructor(addr,kTRUE);
}
break;
case kBIT_ISSTRING:
for( i=left; i<nCurr; ++i, addr += fValDiff )
((std::string*)addr)->~String_t();
break;
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
for( i=left; i<nCurr; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
void* p = h->ptr();
if ( p ) {
}
h->set(0);
}
case G__BIT_ISPOINTER|kBIT_ISSTRING:
for( i=nCurr; i<left; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
h->set(0);
}
break;
case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
for( i=nCurr; i<left; ++i, addr += fValDiff ) {
StreamHelper* h = (StreamHelper*)addr;
h->set(0);
}
break;
}
}
c->resize(left*fValDiff,0);
fEnv->start = left>0 ? &(*c->begin()) : 0;
return;
}
void TEmulatedCollectionProxy::Expand(UInt_t nCurr, UInt_t left)
{
size_t i;
PCont_t c = PCont_t(fEnv->object);
c->resize(left*fValDiff,0);
void *oldstart = fEnv->start;
fEnv->start = left>0 ? &(*c->begin()) : 0;
char* addr = ((char*)fEnv->start) + fValDiff*nCurr;
switch ( fSTL_type ) {
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
switch(fKey->fCase) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
break;
case G__BIT_ISCLASS:
if (oldstart && oldstart != fEnv->start) {
Long_t offset = 0;
for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
fKey->fType->Move(((char*)oldstart)+offset,((char*)fEnv->start)+offset);
}
}
for( i=nCurr; i<left; ++i, addr += fValDiff )
fKey->fType->New(addr);
break;
case kBIT_ISSTRING:
for( i=nCurr; i<left; ++i, addr += fValDiff )
::new(addr) std::string();
break;
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
case G__BIT_ISPOINTER|kBIT_ISSTRING:
case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
for( i=nCurr; i<left; ++i, addr += fValDiff )
*(void**)addr = 0;
break;
}
addr = ((char*)fEnv->start)+fValOffset+fValDiff*nCurr;
default:
switch(fVal->fCase) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
break;
case G__BIT_ISCLASS:
if (oldstart && oldstart != fEnv->start) {
Long_t offset = 0;
for( i=0; i<=nCurr; ++i, offset += fValDiff ) {
fVal->fType->Move(((char*)oldstart)+offset,((char*)fEnv->start)+offset);
}
}
for( i=nCurr; i<left; ++i, addr += fValDiff ) {
fVal->fType->New(addr);
}
break;
case kBIT_ISSTRING:
for( i=nCurr; i<left; ++i, addr += fValDiff )
::new(addr) std::string();
break;
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
case G__BIT_ISPOINTER|kBIT_ISSTRING:
case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
for( i=nCurr; i<left; ++i, addr += fValDiff )
*(void**)addr = 0;
break;
}
break;
}
}
void TEmulatedCollectionProxy::Resize(UInt_t left, Bool_t force)
{
if ( fEnv && fEnv->object ) {
size_t nCurr = Size();
PCont_t c = PCont_t(fEnv->object);
fEnv->start = nCurr>0 ? &(*c->begin()) : 0;
if ( left == nCurr ) {
return;
}
else if ( left < nCurr ) {
Shrink(nCurr, left, force);
return;
}
Expand(nCurr, left);
return;
}
Fatal("TEmulatedCollectionProxy","Resize> Logic error - no proxy object set.");
}
void* TEmulatedCollectionProxy::At(UInt_t idx)
{
if ( fEnv && fEnv->object ) {
PCont_t c = PCont_t(fEnv->object);
size_t s = c->size();
if ( idx >= (s/fValDiff) ) {
return 0;
}
return idx<(s/fValDiff) ? ((char*)&(*c->begin()))+idx*fValDiff : 0;
}
Fatal("TEmulatedCollectionProxy","At> Logic error - no proxy object set.");
return 0;
}
void* TEmulatedCollectionProxy::Allocate(UInt_t n, Bool_t forceDelete)
{
Resize(n, forceDelete);
return fEnv;
}
void TEmulatedCollectionProxy::Commit(void* )
{
}
void TEmulatedCollectionProxy::ReadItems(int nElements, TBuffer &b)
{
Bool_t vsn3 = b.GetInfo() && b.GetInfo()->GetOldVersion()<=3;
StreamHelper* itm = (StreamHelper*)At(0);
switch (fVal->fCase) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
switch( int(fVal->fKind) ) {
case kBool_t: b.ReadFastArray(&itm->boolean , nElements); break;
case kChar_t: b.ReadFastArray(&itm->s_char , nElements); break;
case kShort_t: b.ReadFastArray(&itm->s_short , nElements); break;
case kInt_t: b.ReadFastArray(&itm->s_int , nElements); break;
case kLong_t: b.ReadFastArray(&itm->s_long , nElements); break;
case kLong64_t: b.ReadFastArray(&itm->s_longlong, nElements); break;
case kFloat_t: b.ReadFastArray(&itm->flt , nElements); break;
case kFloat16_t: b.ReadFastArrayFloat16(&itm->flt, nElements); break;
case kDouble_t: b.ReadFastArray(&itm->dbl , nElements); break;
case kBOOL_t: b.ReadFastArray(&itm->boolean , nElements); break;
case kUChar_t: b.ReadFastArray(&itm->u_char , nElements); break;
case kUShort_t: b.ReadFastArray(&itm->u_short , nElements); break;
case kUInt_t: b.ReadFastArray(&itm->u_int , nElements); break;
case kULong_t: b.ReadFastArray(&itm->u_long , nElements); break;
case kULong64_t: b.ReadFastArray(&itm->u_longlong, nElements); break;
case kDouble32_t:b.ReadFastArrayDouble32(&itm->dbl,nElements); break;
case kchar:
case kNoType_t:
case kOther_t:
Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind);
}
break;
#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
case G__BIT_ISCLASS:
DOLOOP( b.StreamObject(i,fVal->fType) );
case kBIT_ISSTRING:
DOLOOP( i->read_std_string(b) );
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
DOLOOP( i->read_any_object(fVal,b) );
case G__BIT_ISPOINTER|kBIT_ISSTRING:
DOLOOP( i->read_std_string_pointer(b) );
case G__BIT_ISPOINTER|kBIT_ISTSTRING|G__BIT_ISCLASS:
DOLOOP( i->read_tstring_pointer(vsn3,b) );
}
#undef DOLOOP
}
void TEmulatedCollectionProxy::WriteItems(int nElements, TBuffer &b)
{
StreamHelper* itm = (StreamHelper*)At(0);
switch (fVal->fCase) {
case G__BIT_ISFUNDAMENTAL:
case G__BIT_ISENUM:
itm = (StreamHelper*)At(0);
switch( int(fVal->fKind) ) {
case kBool_t: b.WriteFastArray(&itm->boolean , nElements); break;
case kChar_t: b.WriteFastArray(&itm->s_char , nElements); break;
case kShort_t: b.WriteFastArray(&itm->s_short , nElements); break;
case kInt_t: b.WriteFastArray(&itm->s_int , nElements); break;
case kLong_t: b.WriteFastArray(&itm->s_long , nElements); break;
case kLong64_t: b.WriteFastArray(&itm->s_longlong, nElements); break;
case kFloat_t: b.WriteFastArray(&itm->flt , nElements); break;
case kFloat16_t: b.WriteFastArrayFloat16(&itm->flt, nElements); break;
case kDouble_t: b.WriteFastArray(&itm->dbl , nElements); break;
case kBOOL_t: b.WriteFastArray(&itm->boolean , nElements); break;
case kUChar_t: b.WriteFastArray(&itm->u_char , nElements); break;
case kUShort_t: b.WriteFastArray(&itm->u_short , nElements); break;
case kUInt_t: b.WriteFastArray(&itm->u_int , nElements); break;
case kULong_t: b.WriteFastArray(&itm->u_long , nElements); break;
case kULong64_t: b.WriteFastArray(&itm->u_longlong, nElements); break;
case kDouble32_t:b.WriteFastArrayDouble32(&itm->dbl,nElements); break;
case kchar:
case kNoType_t:
case kOther_t:
Error("TEmulatedCollectionProxy","fType %d is not supported yet!\n",fVal->fKind);
}
break;
#define DOLOOP(x) {int idx=0; while(idx<nElements) {StreamHelper* i=(StreamHelper*)(((char*)itm) + fValDiff*idx); { x ;} ++idx;} break;}
case G__BIT_ISCLASS:
DOLOOP( b.StreamObject(i,fVal->fType) );
case kBIT_ISSTRING:
DOLOOP( TString(i->c_str()).Streamer(b) );
case G__BIT_ISPOINTER|G__BIT_ISCLASS:
DOLOOP( b.WriteObjectAny(i->ptr(),fVal->fType) );
case kBIT_ISSTRING|G__BIT_ISPOINTER:
DOLOOP( i->write_std_string_pointer(b) );
case kBIT_ISTSTRING|G__BIT_ISCLASS|G__BIT_ISPOINTER:
DOLOOP( i->write_tstring_pointer(b) );
}
#undef DOLOOP
}
void TEmulatedCollectionProxy::Streamer(TBuffer &b)
{
if ( b.IsReading() ) {
int nElements = 0;
b >> nElements;
if ( fEnv->object ) {
Resize(nElements,true);
}
if ( nElements > 0 ) {
ReadItems(nElements, b);
}
}
else {
int nElements = fEnv->object ? Size() : 0;
b << nElements;
if ( nElements > 0 ) {
WriteItems(nElements, b);
}
}
}
static TStreamerElement* R__CreateEmulatedElement(const char *dmName, const char *dmFull, Int_t offset)
{
TString s1( TClassEdit::ShortType(dmFull,0) );
TString dmType( TClassEdit::ShortType(dmFull,1) );
bool dmIsPtr = (s1 != dmType);
const char *dmTitle = "Emulation";
TDataType *dt = gROOT->GetType(dmType);
if (dt && dt->GetType() > 0 ) {
Int_t dsize,dtype;
dtype = dt->GetType();
dsize = dt->Size();
if (dmIsPtr && dtype != kCharStar) {
Error("Pair Emulation Building","%s is not yet supported in pair emulation",
dmFull);
return 0;
} else {
TStreamerElement *el = new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
el->SetSize(dsize);
return el;
}
} else {
static const char *full_string_name = "basic_string<char,char_traits<char>,allocator<char> >";
if (strcmp(dmType,"string") == 0 || strcmp(dmType,full_string_name)==0 ) {
return new TStreamerSTLstring(dmName,dmTitle,offset,dmFull,dmIsPtr);
}
if (TClassEdit::IsSTLCont(dmType)) {
return new TStreamerSTL(dmName,dmTitle,offset,dmFull,dmFull,dmIsPtr);
}
TClass *clm = TClass::GetClass(dmType);
if (!clm) {
Int_t dtype = kInt_t;
return new TStreamerBasicType(dmName,dmTitle,offset,dtype,dmFull);
}
if ( dmIsPtr ) {
if (clm->InheritsFrom(TObject::Class())) {
return new TStreamerObjectPointer(dmName,dmTitle,offset,dmFull);
} else {
return new TStreamerObjectAnyPointer(dmName,dmTitle,offset,dmFull);
}
}
if (clm->InheritsFrom(TObject::Class())) {
return new TStreamerObject(dmName,dmTitle,offset,dmFull);
} else if(clm == TString::Class() && !dmIsPtr) {
return new TStreamerString(dmName,dmTitle,offset);
} else {
return new TStreamerObjectAny(dmName,dmTitle,offset,dmFull);
}
}
}
static TStreamerInfo *R__GenerateTClassForPair(const string &fname, const string &sname)
{
TStreamerInfo *i = (TStreamerInfo*)TClass::GetClass("pair<const int,int>")->GetStreamerInfo()->Clone();
std::string pname = "pair<"+fname+","+sname;
pname += (pname[pname.length()-1]=='>') ? " >" : ">";
i->SetName(pname.c_str());
i->SetClass(0);
i->GetElements()->Delete();
TStreamerElement *fel = R__CreateEmulatedElement("first", fname.c_str(), 0);
i->GetElements()->Add( fel );
Int_t size = 0;
if (fel) {
size = fel->GetSize();
Int_t sp = sizeof(void *);
#if defined(R__SGI64)
sp = 8;
#endif
if (size%sp != 0) size = size - size%sp + sp;
}
i->GetElements()->Add( R__CreateEmulatedElement("second", sname.c_str(), size) );
Int_t oldlevel = gErrorIgnoreLevel;
gErrorIgnoreLevel = kError;
i->BuildCheck();
gErrorIgnoreLevel = oldlevel;
i->BuildOld();
return i;
}
Last change: Wed Jun 25 08:36:22 2008
Last generated: 2008-06-25 08:36
This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.