#include "TGenCollectionProxy.h"
#include "TVirtualStreamerInfo.h"
#include "TStreamerElement.h"
#include "TClassEdit.h"
#include "TClass.h"
#include "TError.h"
#include "TROOT.h"
#include "TInterpreter.h"
#include "Riostream.h"
#include "TVirtualMutex.h"
#include <stdlib.h>
#define MESSAGE(which,text)
class TGenVectorProxy : public TGenCollectionProxy {
public:
TGenVectorProxy(const TGenCollectionProxy& c) : TGenCollectionProxy(c)
{
}
virtual ~TGenVectorProxy()
{
}
virtual void* At(UInt_t idx)
{
if ( fEnv && fEnv->object ) {
fEnv->idx = idx;
switch( idx ) {
case 0:
return fEnv->start = fFirst.invoke(fEnv);
default:
if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv);
return ((char*)fEnv->start) + fValDiff*idx;
}
}
Fatal("TGenVectorProxy","At> Logic error - no proxy object set.");
return 0;
}
virtual void DeleteItem(bool force, void* ptr) const
{
if ( force && ptr ) {
fVal->DeleteItem(ptr);
}
}
};
class TGenListProxy : public TGenVectorProxy {
public:
TGenListProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c)
{
}
virtual ~TGenListProxy()
{
}
void* At(UInt_t idx)
{
if ( fEnv && fEnv->object ) {
switch( idx ) {
case 0:
fEnv->idx = idx;
return fEnv->start = fFirst.invoke(fEnv);
default: {
fEnv->idx = idx - fEnv->idx;
if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv);
void* result = fNext.invoke(fEnv);
fEnv->idx = idx;
return result;
}
}
}
Fatal("TGenListProxy","At> Logic error - no proxy object set.");
return 0;
}
};
class TGenSetProxy : public TGenVectorProxy {
public:
TGenSetProxy(const TGenCollectionProxy& c) : TGenVectorProxy(c)
{
}
virtual ~TGenSetProxy()
{
}
void* At(UInt_t idx)
{
if ( fEnv && fEnv->object ) {
if ( fEnv->use_temp ) {
return (((char*)fEnv->temp)+idx*fValDiff);
}
switch( idx ) {
case 0:
fEnv->idx = idx;
return fEnv->start = fFirst.invoke(fEnv);
default: {
fEnv->idx = idx - fEnv->idx;
if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv);
void* result = fNext.invoke(fEnv);
fEnv->idx = idx;
return result;
}
}
}
Fatal("TGenSetProxy","At> Logic error - no proxy object set.");
return 0;
}
};
class TGenMapProxy : public TGenSetProxy {
public:
TGenMapProxy(const TGenCollectionProxy& c) : TGenSetProxy(c)
{
}
virtual ~TGenMapProxy()
{
}
virtual void DeleteItem(Bool_t , void* ptr) const
{
if ( fKey->fCase&G__BIT_ISPOINTER ) {
fKey->DeleteItem(*(void**)ptr);
}
if ( fVal->fCase&G__BIT_ISPOINTER ) {
char *addr = ((char*)ptr)+fValOffset;
fVal->DeleteItem(*(void**)addr);
}
}
};
TGenCollectionProxy::Value::Value(const Value& copy)
{
fType = copy.fType;
fCase = copy.fCase;
fKind = copy.fKind;
fSize = copy.fSize;
fCtor = copy.fCtor;
fDtor = copy.fDtor;
fDelete = copy.fDelete;
}
TGenCollectionProxy::Value::Value(const std::string& inside_type)
{
std::string inside = (inside_type.find("const ")==0) ? inside_type.substr(6) : inside_type;
fCase = 0;
fCtor = 0;
fDtor = 0;
fDelete = 0;
fSize = std::string::npos;
fKind = kNoType_t;
std::string intype = TClassEdit::ShortType(inside.c_str(),TClassEdit::kDropTrailStar );
if ( inside.substr(0,6) == "string" || inside.substr(0,11) == "std::string" ) {
fCase = kBIT_ISSTRING;
fType = TClass::GetClass("string");
fCtor = fType->GetNew();
fDtor = fType->GetDestructor();
fDelete = fType->GetDelete();
switch(inside[inside.length()-1]) {
case '*':
fCase |= G__BIT_ISPOINTER;
fSize = sizeof(void*);
break;
default:
fSize = sizeof(std::string);
break;
}
}
else {
fType = TClass::GetClass(intype.c_str());
if (fType && !fType->IsLoaded()) {
if (intype != inside) {
fCase |= G__BIT_ISPOINTER;
fSize = sizeof(void*);
}
fCase |= G__BIT_ISCLASS;
fCtor = fType->GetNew();
fDtor = fType->GetDestructor();
fDelete = fType->GetDelete();
} else {
#if defined(NOT_YET)
G__value gval = G__string2type_body(inside.c_str(),2);
G__TypeInfo ti(gval);
#else
TypeInfo_t *ti = gCint->TypeInfo_Factory();
gCint->TypeInfo_Init(ti,inside.c_str());
#endif
if ( !gCint->TypeInfo_IsValid(ti) ) {
if (intype != inside) {
fCase |= G__BIT_ISPOINTER;
fSize = sizeof(void*);
}
fType = TClass::GetClass(intype.c_str());
if (fType) {
fCase |= G__BIT_ISCLASS;
fCtor = fType->GetNew();
fDtor = fType->GetDestructor();
fDelete = fType->GetDelete();
}
else {
fCase = G__BIT_ISENUM;
fSize = sizeof(Int_t);
fKind = kInt_t;
}
}
else {
Long_t prop = gCint->TypeInfo_Property(ti);
if ( prop&G__BIT_ISPOINTER ) {
fSize = sizeof(void*);
}
if ( prop&G__BIT_ISSTRUCT ) {
prop |= G__BIT_ISCLASS;
}
if ( prop&G__BIT_ISCLASS ) {
fType = TClass::GetClass(intype.c_str());
R__ASSERT(fType);
fCtor = fType->GetNew();
fDtor = fType->GetDestructor();
fDelete = fType->GetDelete();
}
else if ( prop&G__BIT_ISFUNDAMENTAL ) {
TDataType *fundType = gROOT->GetType( intype.c_str() );
fKind = (EDataType)fundType->GetType();
if ( 0 == strcmp("bool",fundType->GetFullTypeName()) ) {
fKind = (EDataType)kBOOL_t;
}
fSize = gCint->TypeInfo_Size(ti);
R__ASSERT((fKind>0 && fKind<0x16) || (fKind==-1&&(prop&G__BIT_ISPOINTER)) );
}
else if ( prop&G__BIT_ISENUM ) {
fSize = sizeof(int);
fKind = kInt_t;
}
fCase = prop & (G__BIT_ISPOINTER|G__BIT_ISFUNDAMENTAL|G__BIT_ISENUM|G__BIT_ISCLASS);
if (fType == TString::Class() && (fCase&G__BIT_ISPOINTER)) {
fCase |= kBIT_ISTSTRING;
}
}
gCint->TypeInfo_Delete(ti);
}
}
if ( fSize == std::string::npos ) {
if ( fType == 0 ) {
Fatal("TGenCollectionProxy","Could not find %s!",inside.c_str());
}
fSize = fType->Size();
}
}
void TGenCollectionProxy::Value::DeleteItem(void* ptr)
{
if ( ptr && fCase&G__BIT_ISPOINTER ) {
if ( fDelete ) {
(*fDelete)(ptr);
}
else if ( fType ) {
fType->Destructor(ptr);
}
else {
::operator delete(ptr);
}
}
}
TGenCollectionProxy::TGenCollectionProxy(const TGenCollectionProxy& copy)
: TVirtualCollectionProxy(copy.fClass),
fTypeinfo(copy.fTypeinfo)
{
fEnv = 0;
fName = copy.fName;
fPointers = copy.fPointers;
fSTL_type = copy.fSTL_type;
fSize.call = copy.fSize.call;
fNext.call = copy.fNext.call;
fFirst.call = copy.fFirst.call;
fClear.call = copy.fClear.call;
fResize.call = copy.fResize.call;
fDestruct.call = copy.fDestruct.call;
fConstruct.call = copy.fConstruct.call;
fFeed.call = copy.fFeed.call;
fCollect.call = copy.fCollect.call;
fValOffset = copy.fValOffset;
fValDiff = copy.fValDiff;
fValue = copy.fValue ? new Value(*copy.fValue) : 0;
fVal = copy.fVal ? new Value(*copy.fVal) : 0;
fKey = copy.fKey ? new Value(*copy.fKey) : 0;
}
TGenCollectionProxy::TGenCollectionProxy(Info_t info, size_t iter_size)
: TVirtualCollectionProxy(0),
fTypeinfo(info)
{
fEnv = 0;
fSize.call = 0;
fFirst.call = 0;
fNext.call = 0;
fClear.call = 0;
fResize.call = 0;
fDestruct.call = 0;
fConstruct.call = 0;
fCollect.call = 0;
fFeed.call = 0;
fValue = 0;
fKey = 0;
fVal = 0;
fValOffset = 0;
fValDiff = 0;
fPointers = false;
Env_t e;
if ( iter_size > sizeof(e.buff) ) {
Fatal("TGenCollectionProxy",
"%s %s are too large:%d bytes. Maximum is:%d bytes",
"Iterators for collection",
fClass->GetName(),
iter_size,
sizeof(e.buff));
}
}
TGenCollectionProxy::TGenCollectionProxy(const ROOT::TCollectionProxyInfo &info, TClass *cl)
: TVirtualCollectionProxy(cl),
fTypeinfo(info.fInfo)
{
fEnv = 0;
fValDiff = info.fValueDiff;
fValOffset = info.fValueOffset;
fSize.call = info.fSizeFunc;
fResize.call = info.fResizeFunc;
fNext.call = info.fNextFunc;
fFirst.call = info.fFirstFunc;
fClear.call = info.fClearFunc;
fConstruct.call = info.fConstructFunc;
fDestruct.call = info.fDestructFunc;
fFeed.call = info.fFeedFunc;
fCollect.call = info.fCollectFunc;
CheckFunctions();
fValue = 0;
fKey = 0;
fVal = 0;
fPointers = false;
Env_t e;
if ( info.fIterSize > sizeof(e.buff) ) {
Fatal("TGenCollectionProxy",
"%s %s are too large:%d bytes. Maximum is:%d bytes",
"Iterators for collection",
fClass->GetName(),
info.fIterSize,
sizeof(e.buff));
}
}
namespace {
typedef std::vector<ROOT::TCollectionProxyInfo::Environ<char[64]>* > Proxies_t;
void clearProxies(Proxies_t& v)
{
for(Proxies_t::iterator i=v.begin(); i != v.end(); ++i) {
ROOT::TCollectionProxyInfo::Environ<char[64]> *e = *i;
if ( e ) {
if ( e->temp ) ::free(e->temp);
delete e;
}
}
v.clear();
}
}
TGenCollectionProxy::~TGenCollectionProxy()
{
clearProxies(fProxyList);
clearProxies(fProxyKept);
if ( fValue ) delete fValue;
if ( fVal ) delete fVal;
if ( fKey ) delete fKey;
}
TVirtualCollectionProxy* TGenCollectionProxy::Generate() const
{
if ( !fValue ) Initialize();
if( fPointers )
return new TGenCollectionProxy(*this);
switch(fSTL_type) {
case TClassEdit::kVector:
return new TGenVectorProxy(*this);
case TClassEdit::kList:
return new TGenListProxy(*this);
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
return new TGenMapProxy(*this);
case TClassEdit::kSet:
case TClassEdit::kMultiSet:
return new TGenSetProxy(*this);
default:
return new TGenCollectionProxy(*this);
}
}
TGenCollectionProxy *TGenCollectionProxy::Initialize() const
{
TGenCollectionProxy* p = const_cast<TGenCollectionProxy*>(this);
if ( fValue ) return p;
return p->InitializeEx();
}
void TGenCollectionProxy::CheckFunctions() const
{
if ( 0 == fSize.call ) {
Fatal("TGenCollectionProxy","No 'size' function pointer for class %s present.",fName.c_str());
}
if ( 0 == fResize.call ) {
Fatal("TGenCollectionProxy","No 'resize' function for class %s present.",fName.c_str());
}
if ( 0 == fNext.call ) {
Fatal("TGenCollectionProxy","No 'next' function for class %s present.",fName.c_str());
}
if ( 0 == fFirst.call ) {
Fatal("TGenCollectionProxy","No 'begin' function for class %s present.",fName.c_str());
}
if ( 0 == fClear.call ) {
Fatal("TGenCollectionProxy","No 'clear' function for class %s present.",fName.c_str());
}
if ( 0 == fConstruct.call ) {
Fatal("TGenCollectionProxy","No 'block constructor' function for class %s present.",fName.c_str());
}
if ( 0 == fDestruct.call ) {
Fatal("TGenCollectionProxy","No 'block destructor' function for class %s present.",fName.c_str());
}
if ( 0 == fFeed.call ) {
Fatal("TGenCollectionProxy","No 'data feed' function for class %s present.",fName.c_str());
}
if ( 0 == fCollect.call ) {
Fatal("TGenCollectionProxy","No 'data collect' function for class %s present.",fName.c_str());
}
}
TGenCollectionProxy *TGenCollectionProxy::InitializeEx()
{
R__LOCKGUARD2(gCollectionMutex);
if (fValue) return this;
TClass *cl = fClass ? fClass.GetClass() : TClass::GetClass(fTypeinfo);
if ( cl ) {
fEnv = 0;
fName = cl->GetName();
fPointers = false;
int nested = 0;
std::vector<std::string> inside;
int num = TClassEdit::GetSplit(cl->GetName(),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]=='>') ? " >" : ">";
fValue = new Value(nam);
fVal = new Value(inside[2]);
fKey = new Value(inside[1]);
fPointers = 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;
fValDiff += (slong - fValDiff%slong)%slong;
}
break;
}
if (TVirtualStreamerInfo::GetStreamMemberWise() && fValue->fType.GetClass()) {
Bool_t optim = TVirtualStreamerInfo::CanOptimize();
TVirtualStreamerInfo::Optimize(kFALSE);
fValue->fType.GetClass()->GetStreamerInfo()->Compile();
TVirtualStreamerInfo::Optimize(optim);
}
fPointers = fPointers || (0 != (fVal->fCase&G__BIT_ISPOINTER));
fClass = cl;
return this;
}
Fatal("TGenCollectionProxy","Components of %s not analysed!",cl->GetName());
}
Fatal("TGenCollectionProxy","Collection class %s not found!",fTypeinfo.name());
return 0;
}
TClass *TGenCollectionProxy::GetCollectionClass()
{
return fClass ? fClass : Initialize()->fClass;
}
UInt_t TGenCollectionProxy::Sizeof() const
{
return fClass->Size();
}
Bool_t TGenCollectionProxy::HasPointers() const
{
if( !fValue )
Initialize();
return fPointers && !(fSTL_type == TClassEdit::kMap || fSTL_type == TClassEdit::kMultiMap);
}
TClass *TGenCollectionProxy::GetValueClass()
{
if (!fValue) Initialize();
return fValue ? fValue->fType.GetClass() : 0;
}
void TGenCollectionProxy::SetValueClass(TClass *new_Value_type)
{
if (!fValue) Initialize();
fValue->fType = new_Value_type;
}
EDataType TGenCollectionProxy::GetType()
{
if ( !fValue ) Initialize();
return fValue->fKind;
}
void* TGenCollectionProxy::At(UInt_t idx)
{
if ( fEnv && fEnv->object ) {
switch (fSTL_type) {
case TClassEdit::kVector:
fEnv->idx = idx;
switch( idx ) {
case 0:
return fEnv->start = fFirst.invoke(fEnv);
default:
if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv);
return ((char*)fEnv->start) + fValDiff*idx;
}
case TClassEdit::kSet:
case TClassEdit::kMultiSet:
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
if ( fEnv->use_temp ) {
return (((char*)fEnv->temp)+idx*fValDiff);
}
default:
switch( idx ) {
case 0:
fEnv->idx = idx;
return fEnv->start = fFirst.invoke(fEnv);
default: {
fEnv->idx = idx - fEnv->idx;
if (! fEnv->start ) fEnv->start = fFirst.invoke(fEnv);
void* result = fNext.invoke(fEnv);
fEnv->idx = idx;
return result;
}
}
}
}
Fatal("TGenCollectionProxy","At> Logic error - no proxy object set.");
return 0;
}
void TGenCollectionProxy::Clear(const char* opt)
{
if ( fEnv && fEnv->object ) {
if ( fPointers && opt && *opt=='f' ) {
size_t i, n = *(size_t*)fSize.invoke(fEnv);
if ( n > 0 ) {
for (i=0; i<n; ++i)
DeleteItem(true, TGenCollectionProxy::At(i));
}
}
fClear.invoke(fEnv);
}
}
UInt_t TGenCollectionProxy::Size() const
{
if ( fEnv && fEnv->object ) {
return *(size_t*)fSize.invoke(fEnv);
}
Fatal("TGenCollectionProxy","Size> Logic error - no proxy object set.");
return 0;
}
void TGenCollectionProxy::Resize(UInt_t n, Bool_t force)
{
if ( fEnv && fEnv->object ) {
if ( force && fPointers ) {
size_t i, nold = *(size_t*)fSize.invoke(fEnv);
if ( n != nold ) {
for (i=n; i<nold; ++i)
DeleteItem(true, *(void**)TGenCollectionProxy::At(i));
}
}
MESSAGE(3, "Resize(n)" );
fEnv->size = n;
fResize.invoke(fEnv);
return;
}
Fatal("TGenCollectionProxy","Resize> Logic error - no proxy object set.");
}
void* TGenCollectionProxy::Allocate(UInt_t n, Bool_t )
{
if ( fEnv && fEnv->object ) {
switch ( fSTL_type ) {
case TClassEdit::kSet:
case TClassEdit::kMultiSet:
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
if ( fPointers )
Clear("force");
else
fClear.invoke(fEnv);
++fEnv->refCount;
fEnv->size = n;
if ( fEnv->space < fValDiff*n ) {
fEnv->temp = fEnv->temp ? ::realloc(fEnv->temp,fValDiff*n) : ::malloc(fValDiff*n);
fEnv->space = fValDiff*n;
}
fEnv->use_temp = kTRUE;
fEnv->start = fEnv->temp;
fConstruct.invoke(fEnv);
return fEnv;
case TClassEdit::kVector:
case TClassEdit::kList:
case TClassEdit::kDeque:
if( fPointers ) {
Clear("force");
}
fEnv->size = n;
fResize.invoke(fEnv);
return fEnv;
}
}
return 0;
}
void TGenCollectionProxy::Commit(void* env)
{
switch (fSTL_type) {
case TClassEdit::kVector:
case TClassEdit::kList:
case TClassEdit::kDeque:
return;
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
case TClassEdit::kSet:
case TClassEdit::kMultiSet:
if ( env ) {
Env_t* e = (Env_t*)env;
if ( e->object ) {
e->start = e->temp;
fFeed.invoke(e);
}
fDestruct.invoke(e);
e->start = 0;
--e->refCount;
}
return;
default:
return;
}
}
void TGenCollectionProxy::PushProxy(void *objstart)
{
if ( !fValue ) Initialize();
if ( !fProxyList.empty() ) {
Env_t* back = fProxyList.back();
if ( back->object == objstart ) {
back->refCount++;
fProxyList.push_back(back);
fEnv = back;
return;
}
}
Env_t* e = 0;
if ( fProxyKept.empty() ) {
e = new Env_t();
e->space = 0;
e->temp = 0;
e->use_temp = kFALSE;
}
else {
e = fProxyKept.back();
fProxyKept.pop_back();
}
e->size = 0;
e->refCount = 1;
e->object = objstart;
e->start = 0;
e->idx = 0;
::memset(e->buff,0,sizeof(e->buff));
fProxyList.push_back(e);
fEnv = e;
}
void TGenCollectionProxy::PopProxy()
{
if ( !fProxyList.empty() ) {
Env_t* e = fProxyList.back();
if ( --e->refCount <= 0 ) {
fProxyKept.push_back(e);
e->use_temp = kFALSE;
}
fProxyList.pop_back();
}
fEnv = fProxyList.empty() ? 0 : fProxyList.back();
}
void TGenCollectionProxy::DeleteItem(Bool_t force, void* ptr) const
{
if ( force && ptr ) {
switch (fSTL_type) {
case TClassEdit::kMap:
case TClassEdit::kMultiMap:
if ( fKey->fCase&G__BIT_ISPOINTER ) {
fKey->DeleteItem(*(void**)ptr);
}
if ( fVal->fCase&G__BIT_ISPOINTER ) {
char *addr = ((char*)ptr)+fValOffset;
fVal->DeleteItem(*(void**)addr);
}
break;
default:
if ( fVal->fCase&G__BIT_ISPOINTER ) {
fVal->DeleteItem(*(void**)ptr);
}
break;
}
}
}
void TGenCollectionProxy::Streamer(TBuffer &buff)
{
if ( fEnv ) {
GetCollectionClass()->Streamer( fEnv->object, buff );
return;
}
Fatal("TGenCollectionProxy","Streamer> Logic error - no proxy object set.");
}
void TGenCollectionProxy::Streamer(TBuffer &buff, void *objp, int )
{
TPushPop env(this, objp);
Streamer(buff);
}
void TGenCollectionProxy::operator()(TBuffer &b, void *objp)
{
Streamer(b, objp, 0);
}
Last change: Wed Jun 25 08:44:04 2008
Last generated: 2008-06-25 08:44
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.