#include "TInterpreter.h"
#include "TMethodCall.h"
#include "TMethod.h"
#include "TClass.h"
#include "TROOT.h"
#include "Strlen.h"
#include "TVirtualMutex.h"
#include "TError.h"
ClassImp(TMethodCall)
TMethodCall::TMethodCall():
fFunc(0), fOffset(0), fClass(0), fMetPtr(0), fDtorOnly(kFALSE), fRetType(kNone)
{
}
TMethodCall::TMethodCall(TClass *cl, CallFunc_t *callfunc, Long_t offset):
fFunc(0), fOffset(0), fClass(0), fMetPtr(0), fDtorOnly(kFALSE), fRetType(kNone)
{
Init(cl, callfunc, offset);
}
TMethodCall::TMethodCall(TClass *cl, const char *method, const char *params):
fFunc(0), fOffset(0), fClass(0), fMetPtr(0), fDtorOnly(kFALSE), fRetType(kNone)
{
Init(cl, method, params);
}
TMethodCall::TMethodCall(const char *function, const char *params):
fFunc(0), fOffset(0), fClass(0), fMetPtr(0), fDtorOnly(kFALSE), fRetType(kNone)
{
Init(function, params);
}
TMethodCall::TMethodCall(TFunction *func):
fFunc(0), fOffset(0), fClass(0), fMetPtr(0), fDtorOnly(kFALSE), fRetType(kNone)
{
Init(func);
}
TMethodCall::TMethodCall(const TMethodCall &orig) :
TObject(orig),
fFunc(orig.fFunc ? gCling->CallFunc_FactoryCopy(orig.fFunc) : 0),
fOffset(orig.fOffset), fClass(orig.fClass), fMetPtr(0 ),
fMethod(orig.fMethod), fParams(orig.fParams), fProto(orig.fProto),
fDtorOnly(orig.fDtorOnly), fRetType(orig.fRetType)
{
}
TMethodCall &TMethodCall::operator=(const TMethodCall &rhs)
{
if (this != &rhs) {
gCling->CallFunc_Delete(fFunc);
fFunc = rhs.fFunc ? gCling->CallFunc_FactoryCopy(rhs.fFunc) : 0;
fOffset = rhs.fOffset;
fClass = rhs.fClass;
fMethod = rhs.fMethod;
fParams = rhs.fParams;
fProto = rhs.fProto;
fDtorOnly = rhs.fDtorOnly;
fRetType = rhs.fRetType;
delete fMetPtr;
fMetPtr = 0;
}
return *this;
}
TMethodCall::~TMethodCall()
{
gCling->CallFunc_Delete(fFunc);
delete fMetPtr;
}
TObject *TMethodCall::Clone(const char *) const
{
TObject *newobj = new TMethodCall(*this);
return newobj;
}
static TClass *R__FindScope(const char *function, UInt_t &pos, ClassInfo_t *cinfo)
{
if (function) {
UInt_t nested = 0;
for(int i=strlen(function); i>=0; --i) {
switch(function[i]) {
case '<': ++nested; break;
case '>': if (nested==0) { Error("TMethodCall R__FindScope","%s is not well formed function name",function); return 0; }
--nested; break;
case ':':
if (nested==0) {
if (i>1 && function[i-1]==':') {
TString scope(function);
scope[i-1] = 0;
pos = i+1;
TClass *cl = TClass::GetClass(scope);
if (!cl) gCling->ClassInfo_Init(cinfo, scope);
return cl;
}
}
break;
}
}
}
return 0;
}
void TMethodCall::Init(TClass *cl, CallFunc_t *function, Long_t offset)
{
if (!function) {
fOffset = 0;
fDtorOnly = kFALSE;
fRetType = kNone;
return;
}
MethodInfo_t* info = gCling->CallFunc_FactoryMethod(function);
if (!fFunc)
fFunc = gCling->CallFunc_Factory();
else
gCling->CallFunc_Init(fFunc);
fClass = cl;
if (fClass) {
fMetPtr = new TMethod(info,cl);
} else {
fMetPtr = new TFunction(info);
}
fMethod = fMetPtr->GetName();
fParams = "";
fProto = fMetPtr->GetSignature()+1;
Ssiz_t s = fProto.Last(')');
fProto.Remove(s);
fOffset = offset;
fDtorOnly = kFALSE;
fRetType = kNone;
gCling->CallFunc_SetFunc(fFunc,info);
}
void TMethodCall::Init(TFunction *function)
{
if (!function) return;
if (!fFunc)
fFunc = gCling->CallFunc_Factory();
else
gCling->CallFunc_Init(fFunc);
TMethod *m = dynamic_cast<TMethod*>(function);
fClass = m ? m->GetClass() : 0;
fMetPtr = function;
fMethod = function->GetName();
fParams = "";
fProto = function->GetSignature()+1;
Ssiz_t s = fProto.Last(')');
fProto.Remove(s);
fDtorOnly = kFALSE;
fRetType = kNone;
gCling->CallFunc_SetFunc(fFunc,function->fInfo);
}
void TMethodCall::Init(TClass *cl, const char *method, const char *params, Bool_t objectIsConst )
{
ClassInfo_t *cinfo = gCling->ClassInfo_Factory();
if (!cl) {
UInt_t pos = 0;
cl = R__FindScope(method,pos,cinfo);
method = method+pos;
}
InitImplementation(method,params,0,objectIsConst,cl,cinfo);
gCling->ClassInfo_Delete(cinfo);
}
void TMethodCall::Init(const char *function, const char *params)
{
UInt_t pos = 0;
ClassInfo_t *cinfo = gCling->ClassInfo_Factory();
TClass *cl = R__FindScope(function,pos,cinfo);
InitImplementation(function+pos, params, 0, false, cl, cinfo);
gCling->ClassInfo_Delete(cinfo);
}
void TMethodCall::InitImplementation(const char *methodname, const char *params,
const char *proto,
Bool_t objectIsConst, TClass *cl,
const ClassInfo_t *cinfo,
ROOT::EFunctionMatchMode mode )
{
if (!fFunc)
fFunc = gCling->CallFunc_Factory();
else
gCling->CallFunc_Init(fFunc);
fClass = cl;
fMetPtr = 0;
fMethod = methodname;
fParams = params ? params : "";
fProto = proto ? proto : "";
fDtorOnly = kFALSE;
fRetType = kNone;
ClassInfo_t *scope = 0;
if (cl) scope = (ClassInfo_t*)cl->GetClassInfo();
else scope = (ClassInfo_t*)cinfo;
if (!scope) return;
R__LOCKGUARD2(gInterpreterMutex);
if (params && params[0]) {
gCling->CallFunc_SetFunc(fFunc, scope, (char *)methodname, (char *)params, objectIsConst, &fOffset);
} else if (proto && proto[0]) {
gCling->CallFunc_SetFuncProto(fFunc, scope, (char *)methodname, (char *)proto, objectIsConst, &fOffset, mode);
} else {
gCling->CallFunc_SetFuncProto(fFunc, scope, (char *)methodname, "", objectIsConst, &fOffset, mode);
}
}
void TMethodCall::InitWithPrototype(TClass *cl, const char *method, const char *proto, Bool_t objectIsConst , ROOT::EFunctionMatchMode mode )
{
ClassInfo_t *cinfo = gCling->ClassInfo_Factory();
if (!cl) {
UInt_t pos = 0;
cl = R__FindScope(method,pos,cinfo);
method = method+pos;
}
InitImplementation(method, 0, proto, objectIsConst, cl, cinfo, mode);
gCling->ClassInfo_Delete(cinfo);
}
void TMethodCall::InitWithPrototype(const char *function, const char *proto, ROOT::EFunctionMatchMode mode )
{
UInt_t pos = 0;
ClassInfo_t *cinfo = gCling->ClassInfo_Factory();
TClass *cl = R__FindScope(function,pos,cinfo);
InitImplementation(function+pos, 0, proto, false, cl, cinfo, mode);
gCling->ClassInfo_Delete(cinfo);
}
Bool_t TMethodCall::IsValid() const
{
return fFunc ? gCling->CallFunc_IsValid(fFunc) : kFALSE;
}
TFunction *TMethodCall::GetMethod()
{
if (!fMetPtr) {
if (fFunc && gCling->CallFunc_IsValid(fFunc)) {
if (fClass) {
fMetPtr = new TMethod( gCling->CallFunc_FactoryMethod(fFunc), fClass );
} else {
fMetPtr = new TFunction( gCling->CallFunc_FactoryMethod(fFunc) );
}
} else if (fClass) {
if (fProto == "") {
fMetPtr = fClass->GetMethod(fMethod.Data(), fParams.Data());
} else {
fMetPtr = fClass->GetMethodWithPrototype(fMethod.Data(), fProto.Data());
}
TMethod *met = dynamic_cast<TMethod*>(fMetPtr);
if (met) fMetPtr = new TMethod(*met);
} else {
if (fProto == "")
fMetPtr = gROOT->GetGlobalFunction(fMethod.Data(), fParams.Data(), kFALSE);
else
fMetPtr = gROOT->GetGlobalFunctionWithPrototype(fMethod.Data(), fProto.Data(), kFALSE);
if (fMetPtr) fMetPtr = new TFunction(*fMetPtr);
}
}
return fMetPtr;
}
void TMethodCall::Execute(void *object)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
if (!fDtorOnly && fMethod[0]=='~') {
Error("Execute","TMethodCall can no longer be use to call the operator delete and the destructor at the same time");
}
gCling->CallFunc_Exec(fFunc,address);
}
void TMethodCall::Execute(void *object, const char *params)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
gCling->CallFunc_SetArgs(fFunc, (char *)params);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
gCling->CallFunc_Exec(fFunc,address);
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, Long_t &retLong)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
retLong = gCling->CallFunc_ExecInt(fFunc,address);
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, const char *params, Long_t &retLong)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
gCling->CallFunc_SetArgs(fFunc, (char *)params);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
retLong = gCling->CallFunc_ExecInt(fFunc,address);
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, Double_t &retDouble)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
retDouble = gCling->CallFunc_ExecDouble(fFunc,address);
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, const char *params, Double_t &retDouble)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
gCling->CallFunc_SetArgs(fFunc, (char *)params);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
retDouble = gCling->CallFunc_ExecDouble(fFunc,address);
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, char **retText)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
*retText =(char*) (gCling->CallFunc_ExecInt(fFunc,address));
gCling->SetTempLevel(-1);
}
void TMethodCall::Execute(void *object, const char *params, char **retText)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
gCling->CallFunc_SetArgs(fFunc, (char *)params);
void *address = 0;
if (object) address = (void*)((Long_t)object + fOffset);
gCling->SetTempLevel(1);
*retText =(char*)(gCling->CallFunc_ExecInt(fFunc,address));
gCling->SetTempLevel(-1);
}
TMethodCall::EReturnType TMethodCall::ReturnType()
{
if ( fRetType == kNone) {
TFunction *func = GetMethod();
if (func == 0) {
fRetType = kOther;
Error("ReturnType","Unknown method");
return kOther;
}
fRetType = gCling->MethodCallReturnType(func);
}
return fRetType;
}
void TMethodCall::SetParamPtrs(void *paramArr, Int_t nparam)
{
if (!fFunc) return;
R__LOCKGUARD2(gInterpreterMutex);
gCling->CallFunc_SetArgArray(fFunc,(Long_t *)paramArr, nparam);
}
void TMethodCall::ResetParam()
{
if (!fFunc) return;
gCling->CallFunc_ResetArg(fFunc);
}
void TMethodCall::SetParam(Long_t l)
{
if (!fFunc) return;
gCling->CallFunc_SetArg(fFunc,l);
}
void TMethodCall::SetParam(Double_t d)
{
if (!fFunc) return;
gCling->CallFunc_SetArg(fFunc,d);
}
void TMethodCall::SetParam(Long64_t ll)
{
if (!fFunc) return;
gCling->CallFunc_SetArg(fFunc,ll);
}
void TMethodCall::SetParam(ULong64_t ull)
{
if (!fFunc) return;
gCling->CallFunc_SetArg(fFunc,ull);
}