// -*- mode:C++; tab-width:2; c-basic-offset:2; indent-tabs-mode:nil -*-
//
// Copyright (C) 2000-2005 by Roger Rene Kommer / artefaktur, Kassel, Germany.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public License (LGPL).
//
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// License ACDK-FreeLicense document enclosed in the distribution
// for more for more details.
// This file is part of the Artefaktur Component Development Kit:
// ACDK
//
// Please refer to
// - http://www.acdk.de
// - http://www.artefaktur.com
// - http://acdk.sourceforge.net
// for more information.
//
// $Header: /cvsroot/acdk/acdk/acdk_core/src/acdk/lang/dmi/StdDispatch.cpp,v 1.98 2005/04/18 15:14:27 kommer Exp $
#include <acdk.h>
#include <acdk/lang/NoSuchDmiElementException.h>
#include <acdk/lang/ParamsMismatchException.h>
#include <acdk/lang/ClassNotFoundException.h>
#include <acdk/lang/NoSuchFieldException.h>
#include <acdk/lang/NoSuchMethodException.h>
#include <acdk/lang/Number.h>
#include <acdk/lang/Integer.h>
#include <acdk/lang/Character.h>
#include <acdk/lang/DmiTypeConversionException.h>
#include "DmiNamedArg.h"
#include "ClazzInfo.h"
#include "ClazzAttributesRes.h"
namespace acdk {
namespace lang {
namespace dmi {
//virtual
DmiClient&
StdDispatch::getDmiClient()
{
return AcdkDmiClient::getDmiClient();
}
//inline
::acdk::lang::Object*
StdDispatch::getDmiTarget(const ::acdk::lang::dmi::ClazzInfo*& ci)
{
bool bret = false;
::acdk::lang::Object* o = (::acdk::lang::Object*)this;
while ((o = o->getDmiTarget(bret, ci)) && bret == true)
;
return o;
}
//static
const ClazzMethodInfo*
StdDispatch::_invoke_notexistant( ::acdk::lang::Object* This,
IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
THROW1(UnsupportedOperationException, "No DMI function available for call");
return 0;
}
//static
const ClazzMethodInfo*
StdDispatch::_invoke_dynamic( ::acdk::lang::Object* This,
IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
if (clazzinfo == 0)
clazzinfo = This->getClazzInfo();
if ((flags & MiIvNoWeakBind) == 0 && This != 0)
{
bool __forward = false;
::acdk::lang::Object* __forwardPtr = This->_getObjectPtr()->getDmiTarget(__forward, clazzinfo);
if (__forward == true)
return __forwardPtr->standardDispatch(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
}
DmiClient::setCurInvokeFlags(flags); // because on circumstance the flags are not deleted
if (methinf == 0 || flags & MiIvViaHash)
{
const ClazzInfo* clazzsic = clazzinfo;
methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags, methinf);
flags &= ~MiIvViaHash;
}
return methinf->dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
//return clazzinfo->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
}
//static
const ClazzMethodInfo*
StdDispatch::_invoke_dynamic_super( ::acdk::lang::Object* This,
IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
/*
if (methinf == 0)
{
const ClazzInfo* clazzsic = clazzinfo;
methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags);
if (clazzsic != clazzinfo)
return clazzinfo->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
}
int i;
for (i = 0; i < clazzinfo->getInterfacesCount(); ++i)
{
const ClazzInfo* ci = clazzinfo->interfaces[i]->type;
methinf = ci->dynamic_dispatch(This, fname, ret, args, dc, namedArgs, flags, ci, methinf);
if (methinf != 0)
break;
}*/
return methinf;
}
//static
const ClazzMethodInfo*
StdDispatch::_invoke_static( IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
const ClazzInfo* clazzSic = clazzinfo;
if (methinf == 0 || flags & MiIvViaHash)
{
methinf = ::acdk::lang::dmi::StdDispatch::lookupMethod(clazzinfo, fname, args, namedArgs, dc, flags, methinf);
flags &= ~MiIvViaHash;
}
if (clazzSic->isArray() == true)
{
clazzinfo = clazzSic;
ASCLITERAL(GetClass);
if (fname->equals(lit_GetClass) == true)
{
ret = inOf(Class::getSingeltonClass(clazzinfo));
return methinf;
}
}
if (methinf->dispatch == 0)
THROW1(NoSuchMethodException, "Method has no DMI implementation (probably abstract class): " + clazzinfo->toTypeString() + "::" + methinf->name);
// ### check if methinf is this
methinf = methinf->dispatch(0, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
return methinf;
}
//static
const ClazzMethodInfo*
StdDispatch::_invoke_static_super( IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
/*
int i;
for (i = 0; i < clazzinfo->getInterfacesCount(); ++i)
{
const ClazzInfo* ci = clazzinfo->interfaces[i]->type;
methinf = ci->static_dispatch(fname, ret, args, dc, namedArgs, flags, ci, methinf);
if (methinf != 0)
break;
}*/
return methinf;
}
//virtual
const ClazzMethodInfo*
StdDispatch::standardDispatch( IN(acdk::lang::RString) fname, ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs/* = Nil*/,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf/* = 0*/)
{
if (clazzinfo == 0)
clazzinfo = getClazzInfo();
clazzinfo = clazzinfo->loadFullClazzInfo();
DmiClient::setCurInvokeFlags(flags);
return clazzinfo->dynamic_dispatch((acdk::lang::Object*)this, fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
/*
not correct, because __dmi_proxy_target should not be static
::acdk::lang::dmi::ClazzInfo* ci = getClazzInfo();
KeyValue<StringRes, ClazzAttributeResValue> kv = ClazzAttributesRes::getAttribute((MetaInfo*)ci, "__dmi_proxy_target");
if (kv.value.data != 0)
{
acdk::lang::Object fw = (acdk::lang::Object*)kv.value.data;
return fw->standardDispatch(fname, ret, args, dc, namedArgs, flags, methinf);
}
*/
THROW1(UnsupportedOperationException, "StdDispatch::standardDispatch");
return 0;
}
/**
This version of StandardDispatch is used in the generated stub */
//static
const ClazzMethodInfo*
StdDispatch::StandardDispatch(IN(acdk::lang::RString) fname,
ScriptVar& ret,
ScriptVarArray& args,
DmiClient& dc,
IN(::acdk::lang::RStringArray) namedArgs,
int flags,
const ClazzInfo* clazzinfo,
const ClazzMethodInfo* methinf)
{
/*
if (clazzinfo == 0)
clazzinfo = getClazzInfo();
*/
clazzinfo = clazzinfo->loadFullClazzInfo();
return clazzinfo->static_dispatch(fname, ret, args, dc, namedArgs, flags, clazzinfo, methinf);
THROW1(UnsupportedOperationException, "StdDispatch::standardDispatch: This method is reserved for the generated stub");
return 0;
}
//static
const ClazzMethodInfo*
StdDispatch::StandardDispatch( IN(acdk::lang::RString) classname, IN(acdk::lang::RString) fname
, ScriptVar& ret
, ScriptVarArray& args
, DmiClient& dc
, IN(::acdk::lang::RStringArray) namedArgs
, int flags
, const ClazzInfo* clazzinfo
, const ClazzMethodInfo* methinf/* = 0*/)
{
RClass cls;
cls = Class::forName(&classname);// method with use cstr instead of RString
const ClazzInfo* ci = cls->objectClazzInfo();
if (clazzinfo == 0)
clazzinfo = ci;
ci = ci->loadFullClazzInfo();
if (ci->static_dispatch != 0/* && namedArgs == Nil*/)
return ci->static_dispatch(fname, ret, args, dc, namedArgs, flags, ci, methinf);
const ClazzMethodInfo* mi = lookupMethod(ci, fname, args, namedArgs, dc, flags, methinf);
if (mi->dispatch != 0)
return mi->dispatch(0, fname, ret, args, dc, namedArgs, flags, ci, mi);
return _invoke_notexistant(0, fname, ret, args, dc, namedArgs, flags, ci, mi);
}
void throwFieldNotFount(IN(RString) msg, const ClazzInfo* ci, const ClazzFieldInfo* fi, int formatFlags)
{
StringBuffer sb;
sb.append(msg);
sb.append(MetaInfo::flagsToString(MetaInfo::accessMask(fi->flags) | MetaInfo::staticMask(fi->flags), FieldInfoExtFlags(0)));
sb.append(" ");
ci->toTypeString(sb, formatFlags);
sb.append("::");
sb.append(fi->name);
THROW1(NoSuchFieldException, sb.toString());
}
//static
ScriptVar
StdDispatch::_getMember(::acdk::lang::Object* This, const ClazzInfo* clazz, const ClazzFieldInfo* field,
IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags)
{
if (field->accessor != 0)
{
ScriptVar erg;
field->accessor(This, fieldname, erg, dc, flags | MiReadOnly, clazz, field);
return erg;
}
if ((flags & MiIvNoThrowIfNotFound) == 0)
throwFieldNotFount("Field has no accessor function", clazz, field, dc._formatFlags);
return ScriptVar();
}
//static
void
StdDispatch::_setMember(::acdk::lang::Object* This, const ScriptVar& val, const ClazzInfo* clazz, const ClazzFieldInfo* field,
IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags)
{
if (field->accessor != 0)
{
field->accessor(This, fieldname, const_cast<ScriptVar&>(val), dc, flags & ~MiReadOnly, clazz, field);
return;
}
if ((flags & MiIvNoThrowIfNotFound) == 0)
throwFieldNotFount("Field has no accessor function", clazz, field, dc._formatFlags);
}
//static
dmi::ScriptVar
StdDispatch::getStaticMember(const ClazzInfo* clazz, IN(acdk::lang::RString) fieldname, DmiClient& dc, int flags
, const ClazzInfo* type_requested)
{
//int mflags = Modifier_accessMask(flags) | Modifier_accessMask(flags);
if (clazz->flags & MiCiWeakBind && (flags & MiIvNoWeakBind) == 0)
{
ScriptVar ret;
ScriptVarArray args(1);
args[0] = &fieldname;
clazz->static_dispatch("peek_static", ret, args, dc, Nil, flags, clazz, 0);
return ret;
}
const ClazzFieldInfo* field = ClazzInfo::findField(clazz, fieldname, flags);
ScriptVar sv = _getMember(0, clazz, field, fieldname, dc, flags);
dc.castTo(sv, type_requested);
return sv;
//return ScriptVar_dynConvert(sv, type_requested);
}
dmi::ScriptVar
StdDispatch::getMember(IN(RString) fieldname, DmiClient& dc, int flags, const ClazzInfo* type_requested)
{
//acdk::lang::Object* This = this; //dynamic_cast<ObjectBase*>(this)->_cast(Object::clazzInfo());
bool forwarded = false;
const ClazzInfo* clazz = 0;
acdk::lang::Object* This = this->getDmiTarget(forwarded, clazz);
if (clazz == 0)
clazz = This->getClazzInfo();
const ClazzInfo* tclazz = clazz;
clazz = clazz->loadFullClazzInfo();
if ((clazz->flags & MiCiWeakBind) && (flags & MiIvNoWeakBind) == 0)
{
ScriptVar ret;
ScriptVarArray args(1);
args[0] = &fieldname;
/*
if (flags & MiPublic)
mflags |= MiPublic;
*/
This->standardDispatch("peek", ret, args, dc, Nil, flags, clazz, 0);
return ret;
}
const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags);
ScriptVar sv = _getMember(This, clazz, fi, fieldname, dc, flags);
if (type_requested == 0)
return sv;
if (dc.typeDistance(sv, type_requested) == -1)
{
StringBuffer sb("Cannot convert variable: ");
sb.append(sv.toString());
sb.append(" to type ");
type_requested->toTypeString(sb, dc._formatFlags);
sb.append(" in accessing ");
fi->toTypeString(sb, dc._formatFlags);
if ((flags & MiIvNoThrowIfNotFound) == 0)
THROW1(DmiTypeConversionException, sb.toString());
return ScriptVar();
}
dc.castTo(sv, type_requested);
return sv;
}
void
StdDispatch::setMember(IN(RString) fieldname, const ScriptVar& newval, DmiClient& dc, int flags)
{
bool forwarded = false;
//const ClazzInfo* clazz = This->getClazzInfo();
acdk::lang::Object* This = dmi_cast<acdk::lang::Object>((acdk::lang::Object*)this);
const ClazzInfo* clazz = 0;
This = This->getDmiTarget(forwarded, clazz);
if (clazz == 0)
clazz = This->getClazzInfo();
clazz = clazz->loadFullClazzInfo();
if (getClazzInfo()->flags & MiCiWeakBind)
{
ScriptVar ret;
ScriptVarArray args(2);
args[0] = &fieldname;
args[1] = newval;
/*
if (flags & MiPublic)
mflags |= MiPublic;
*/
This->standardDispatch("poke", ret, args, dc, Nil, flags, getClazzInfo(), 0);
return;
}
const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags);
ScriptVar sv = newval;
dc.castTo(sv, fi->type);
_setMember(This, sv, clazz, fi, fieldname, dc, flags);
}
SysFields
StdDispatch::getInternalFields(int flags, const ClazzInfo* clazz)
{
// #### TODO handle basic/ObjectArray
if (clazz == 0)
clazz = getClazzInfo();
clazz = clazz->loadFullClazzInfo(true, false);
if (clazz == 0)
return SysFields(0);
ClazzFieldInfoVec fds;
clazz->getFields(fds, flags);
SysFields sf(fds.size());
acdk::lang::Object* This = dynamic_cast<acdk::lang::Object*>(this);
DmiClient& dc = AcdkDmiClient::getDmiClient();
for (int i = 0; i < fds.size(); ++i)
{
ScriptVar sv;
const ClazzFieldInfo* fi = fds[i];
if (fi->accessor != 0)
{
fi->accessor(This, fi->name, sv, dc, MiReadOnly | MiAiOut,
(const ClazzInfo*)fi->_scopeParent, fi);
// ### TODO missing here an else?
sf[i] = SysField::getField(fi, sv);
}
}
return sf;
}
SysField
StdDispatch::getInternalField(IN(RString) name, int flags, const ClazzInfo* ci)
{
if (ci == 0)
ci = getClazzInfo();
ci = ci->loadFullClazzInfo(true, false);
if (ci != 0)
{
const ClazzFieldInfo* fi = ci->findField(ci, name, flags);
if (fi != 0 && fi->accessor != 0)
{
DmiClient& dc = AcdkDmiClient::getDmiClient();
ScriptVar sv;
fi->accessor(dynamic_cast<acdk::lang::Object*>(this), name, sv, dc, MiReadOnly | MiAiOut, ci, fi);
return SysField::getField(fi, sv);
}
}
{
SysFields sysfields = getInternalFields(flags);
SysFields::iterator it = sysfields.begin();
SysFields::iterator end = sysfields.end();
for (; it != end; ++it)
{
if ((*it).fieldInfo->getMetaInfo()->equalsName(name) == true)
return *it;
}
// ### THROW
return SysField();
}
}
/*
//static
const ClazzFieldInfo*
StdDispatch::lookupMember( const ClazzInfo*& clazz, IN(RString) membername, int flags)
{
if (clazz == 0)
{
acdk::lang::Object* o = dynamic_cast<acdk::lang::Object*>(this);
clazz = o->getClazzInfo();
}
clazz = clazz->loadFullClazzInfo();
for (int i = 0; i < clazz->getFieldsCount(); ++i)
{
if (membername.equals(clazz->fields[i]->name) == true && Modifier::checkMemberAccess(flags, clazz->fields[i]->flags)
return clazz->fields[i];
}
if ((MiIvDeclared & flags) == 0)
{
if (flags & MiIvTransientCall)
flags |= MiProtected;
const ClazzInfo* tclazz = clazz;
for (int i = 0; i < tclazz->getInterfacesCount(); i++)
{
clazz = tclazz->interfaces[i]->type;
const ClazzFieldInfo* cfi = lookupMember(clazz, *fname, flags, vec);
if (cfi != 0)
return cfi;
}
}
StringBuffer sb("Field not found: ");
sb.append(Modifier::toString(Modifier::accessMask(flags) | Modifier::staticMask(flags)));
sb.append(" ");
clazz->toTypeString(sb, false);
sb.append("::");
sb.append(&membername);
THROW1(NoSuchMethodException, sb.toString());
return SysField();
}
//static
const ClazzFieldInfo*
StdDispatch::lookupStaticMember( const ClazzInfo*& clazz, IN(RString) membername, int flags)
{
int i;
if (clazz->fields != 0)
{
for (i = 0; clazz->fields[i] != 0; i++)
{
const ClazzFieldInfo* cfi = clazz->fields[i];
if (membername.equals(cfi->name) == true)
{
if (cfi->address != 0 && cfi->address != (void*)-1) // otherwise doesn't work with DClazzInfo
{
if (Modifier::checkMemberAccess(flags, cfi->flags) == true)
{
return cfi;
}
}
}
}
}
const ClazzInfo* tclazz = clazz;
if (tclazz->interfaces != 0 && (MiIvDeclared & flags) == 0)
{
if (flags & MiIvTransientCall)
flags |= MiProtected;
const ClazzFieldInfo* cfi;
for (i = 0; tclazz->interfaces[i]; i++)
{
clazz = tclazz->interfaces[i]->type;
cfi = lookupStaticMember(clazz, membername, flags);
if (cfi != 0)
return cfi;
}
}
clazz = tclazz;
return 0;
}
*/
//static
ScriptVar
StdDispatch::getStaticMember(const ClazzInfo* clazz, const ClazzFieldInfo* field, int flags)
{
if (field->accessor != 0)
{
return _getMember(0, clazz, field, field->name, AcdkDmiClient::getDmiClient(), MiStatic);
}
void* address = field->address;
const ClazzInfo* clazzInfo = field->type;
if (clazzInfo == ClazzInfo::getBoolClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((bool*)address));
else
return outOf(*((bool*)address));
}
else
return inOf(*((bool*)address));
}
if (clazzInfo == ClazzInfo::getCharClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((char*)address));
else
return outOf(*((char*)address));
}
else
return inOf(*((char*)address));
}
if (clazzInfo == ClazzInfo::getByteClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((byte*)address));
else
return outOf(*((byte*)address));
}
else
return inOf(*((byte*)address));
}
if (clazzInfo == ClazzInfo::getShortClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((short*)address));
else
return outOf(*((short*)address));
}
else
return inOf(*((short*)address));
}
if (clazzInfo == ClazzInfo::getIntClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((int*)address));
else
return outOf(*((int*)address));
}
else
return inOf(*((int*)address));
}
if (clazzInfo == ClazzInfo::getLongClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((jlong*)address));
else
return outOf(*((jlong*)address));
}
else
return inOf(*((jlong*)address));
}
if (clazzInfo == ClazzInfo::getFloatClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((float*)address));
else
return outOf(*((float*)address));
}
else
return inOf(*((float*)address));
}
if (clazzInfo == ClazzInfo::getDoubleClazz())
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((double*)address));
else
return outOf(*((double*)address));
}
else
return inOf(*((double*)address));
}
// otherwise
{
if (flags & MiAiOut)
{
if (flags & MiAiIn)
return inoutOf(*((acdk::lang::Object*)address));
else
return outOf(*((acdk::lang::Object*)address));
}
else
return inOf(*((acdk::lang::Object*)address));
}
}
//static
void
StdDispatch::setStaticMember(const ClazzInfo* clazz, IN(RString) fieldname, const ScriptVar& newval, DmiClient& dc, int flags)
{
clazz = clazz->loadFullClazzInfo();
if (clazz->flags & MiCiWeakBind)
{
ScriptVar ret;
ScriptVarArray args(2);
args[0] = &fieldname;
args[1] = newval;
clazz->static_dispatch("poke_static", ret, args, dc, Nil, flags, clazz, 0);
return;
}
const ClazzFieldInfo* fi = ClazzInfo::findField(clazz, fieldname, flags | MiStatic);
ScriptVar sv = newval;
dc.castTo(sv, fi->type);
_setMember(0, sv, clazz, fi, fieldname, dc, flags);
}
//static
void
StdDispatch::setStaticMember(const ClazzInfo* clazz, const ClazzFieldInfo* field, const ScriptVar& value, DmiClient& dc, int flags)
{
if (flags & MiCiWeakBind)
{
setStaticMember(clazz, ACDK_STACK_STR(field->name), value, dc, flags);
return;
}
// ### todo check flags for protecttion
if (field->accessor != 0)
{
_setMember(0, value, clazz, field, field->name, AcdkDmiClient::getDmiClient(), MiStatic);
return;
}
const ClazzInfo* clazzInfo = field->type;
void* address = field->address;
if (clazzInfo == ClazzInfo::getBoolClazz()) {
*((bool*)address) = value.getBoolVar();
return;
}
if (clazzInfo == ClazzInfo::getCharClazz()) {
*((char*)address) = value.getCharVar();
return;
}
if (clazzInfo == ClazzInfo::getByteClazz()) {
*((byte*)address) = value.getByteVar();
return;
}
if (clazzInfo == ClazzInfo::getShortClazz()) {
*((short*)address) = value.getShortVar();
return;
}
if (clazzInfo == ClazzInfo::getIntClazz()) {
*((int*)address) = value.getIntVar();
return;
}
if (clazzInfo == ClazzInfo::getLongClazz()) {
*((jlong*)address) = value.getLongVar();
return;
}
if (clazzInfo == ClazzInfo::getFloatClazz()) {
*((float*)address) = value.getFloatVar();
return;
}
if (clazzInfo == ClazzInfo::getDoubleClazz()) {
*((double*)address) = value.getDoubleVar();
return;
}
*((acdk::lang::Object*)address) = value.getObjectVar();
}
//static
void
StdDispatch::poke_static(IN(RString) clsname, IN(RString) member, IN(ScriptVar) val, int flags)
{
RClass cls = Class::forName(clsname);
if (cls == Nil)
THROW1(ClassNotFoundException, "Class cannot be found: " + clsname->getName());
StdDispatch::setStaticMember(cls->objectClazzInfo(), member, val, AcdkDmiClient::getDmiClient(), flags);
}
//static
ScriptVar
StdDispatch::peek_static(IN(RString) clsname, IN(RString) member, int flags)
{
RClass cls = Class::forName(clsname);
if (cls == Nil)
THROW1(ClassNotFoundException, "Class cannot be found: " + clsname->getName());
return StdDispatch::getStaticMember(cls->objectClazzInfo(), member, AcdkDmiClient::getDmiClient(), flags) ;
}
ScriptVar
StdDispatch::New(IN(RString) classname, ScriptVarArray& args, DmiClient& dc)
{
return New(classname, args, Nil, dc);
}
ScriptVar
StdDispatch::New(IN(RString) classname, ScriptVarArray& args, IN(RStringArray) nargs, DmiClient& dc)
{
RString constructorname = classname->replace('.', '/');
if (constructorname->indexOf('/') != -1)
constructorname = constructorname->substr(constructorname->lastIndexOf('/') + 1);
ScriptVar ret;
StandardDispatch(classname, constructorname
, ret
, args
, dc
, nargs
, MiPublic | MiIvConstructor //| MiStatic
, 0);
return ret;
}
//static
ScriptVar
StdDispatch::New(IN(RString) classname, ScriptVarArray& args, IN(NamedArgs) nargs, DmiClient& dc)
{
StringArray namedArgs(nargs.size());
args.reserve(args.size() + nargs.size());
for (int i = 0; i < nargs.size(); ++i)
{
namedArgs[i] = new String(nargs[i]._name);
args.push_back(*nargs[i]._val);
}
RString constructorname = classname->replace('.', '/');
if (constructorname->indexOf('/') != -1)
constructorname = constructorname->substr(constructorname->lastIndexOf('/') + 1);
ScriptVar ret;
StandardDispatch(classname, constructorname
, ret
, args
, dc
, &namedArgs
, MiPublic | MiMiConstructor //| MiStatic
, 0);
return ret;
}
//foreign static
ScriptVar
StdDispatch::invokeStaticMethod(IN(RString) classname, IN(RString) funcname , ScriptVarArray& args, int flags)
{
ScriptVar ret;
StandardDispatch(classname, funcname, ret, args, ::acdk::lang::dmi::AcdkDmiClient::getDmiClient(), Nil,
flags, 0);
return ret;
}
//foreign static
ScriptVar
StdDispatch::invokeStaticMethod( IN(RString) classname, IN(RString) funcname
, ScriptVarArray& args
, IN(NamedArgs) nargs
, int flags
)
{
StringArray namedArgs(nargs.size());
args.reserve(args.size() + nargs.size());
for (int i = 0; i < nargs.size(); ++i)
{
namedArgs[i] = new String(nargs[i]._name);
args.push_back(*nargs[i]._val);
}
return invokeStaticMethod(classname, funcname, args, ::acdk::lang::dmi::AcdkDmiClient::getDmiClient(), &namedArgs, flags);
}
//foreign static
ScriptVar
StdDispatch::invokeStaticMethod( IN(RString) classname, IN(RString) funcname
, ScriptVarArray& args
, DmiClient& dc
, IN(::acdk::lang::RStringArray) namedArgs// = Nil
, int flags
)
{
ScriptVar ret;
StandardDispatch(classname, funcname, ret, args, dc, namedArgs, flags, 0, 0);
return ret;
}
//foreign
ScriptVar
StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args, int flags)
{
ScriptVar erg;
standardDispatch(funcname, erg, args, getDmiClient(), Nil, flags, getClazzInfo(), 0);
return erg;
}
//foreign
ScriptVar
StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args, IN(NamedArgs) nargs, int flags)
{
StringArray namedArgs(nargs.size());
args.reserve(args.size() + nargs.size());
for (int i = 0; i < nargs.size(); ++i)
{
namedArgs[i] = new String(nargs[i]._name);
args.push_back(*nargs[i]._val);
}
return invokeMethod(funcname, args, &namedArgs, flags);
}
//foreign
ScriptVar
StdDispatch::invokeMethod(IN(RString) funcname, ScriptVarArray& args
, DmiClient& dc
, IN(::acdk::lang::RStringArray) namedArgs
, int flags
)
{
ScriptVar erg;
standardDispatch(funcname, erg, args, dc, namedArgs, flags, getClazzInfo(), 0);
return erg;
}
//foreign
ScriptVar
StdDispatch::invokeMethod( IN(RString) funcname, ScriptVarArray& args
, IN(::acdk::lang::RStringArray) namedArgs, int flags)
{
ScriptVar erg;
standardDispatch(funcname, erg, args, getDmiClient(), namedArgs, flags, getClazzInfo(), 0);
return erg;
}
//foreign
ScriptVar
StdDispatch::peek(IN(RString) fieldname, int flags)
{
return getMember(fieldname, getDmiClient(), flags, 0);
}
//foreign
void
StdDispatch::poke(IN(RString) fieldname, const ScriptVar& arg, int flags)
{
setMember(fieldname, arg, getDmiClient(), flags);
}
inline ::acdk::lang::RString isOperator(IN(RString) fname)
{
RString strOperator = ACDK_STACK_STR("operator");
if (fname->startsWith(strOperator) == true)
{
if (acdk::lang::Character::isJavaIdentifierPart(fname->charAt(strOperator->length())) == false)
return fname->substr(strOperator->length());
}
return Nil;
}
class FunctionDescriptor
{
public:
int getParamCount() const { return 0; }
const ClazzInfo* getParamType(int i) const { return 0; }
int getParamFlags(int i) const { return 0; }
bool equalsParamName(int i, IN(RString) pname) const { return false; }
bool hasDefaultValue(int i) const { return false; }
ScriptVar getDefaultValue(int i) const { return ScriptVar(); }
};
class ClazzMethodInfoDescriptor
: public FunctionDescriptor
{
public:
const ClazzMethodInfo* _mi;
ClazzMethodInfoDescriptor(const ClazzMethodInfo* mi) : _mi(mi) {}
int getParamCount() const { return _mi->getArgumentCount(); }
const ClazzInfo* getParamType(int i) const { return _mi->methodArgs[i]->type; }
int getParamFlags(int i) const { return _mi->methodArgs[i]->flags; }
bool equalsParamName(int i, IN(RString) pname) const
{
return _mi->methodArgs[i]->equalsName(pname);
}
bool hasDefaultValue(int i) const
{
return _mi->methodArgs[i]->getDefaultArgValueFunc != 0;
}
ScriptVar getDefaultValue(int i) const
{
return _mi->methodArgs[i]->getDefaultArgValueFunc(_mi->methodArgs[i]);
}
};
class NamedArgDescription
{
protected:
RStringArray namedargs;
public:
NamedArgDescription(IN(RStringArray) n) : namedargs(n) {}
bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; }
int getNamedCount() const
{
return namedargs == Nil ? 0 : namedargs->length();
}
RString getNameArgName(int argCount, int idx)
{
/*
a, b, c: C, d: D
idx = 2 (c)
argCount = 4;
namedArg = 2
realidx = 0
idx = (c)
argCount = 4;
namedArg = 2
realidx = 0
*/
int realIdx = idx - (argCount - namedargs->length());
return namedargs[realIdx];
}
};
class ScriptVarArgDescription
: public NamedArgDescription
{
ScriptVarArray& args;
public:
typedef ScriptVar ElementType;
typedef ScriptVarArray ElementContainer;
ScriptVarArgDescription(ScriptVarArray& a, IN(RStringArray) nargs) : NamedArgDescription(nargs), args(a) {}
int getCount() const { return args.size(); }
bool hasValues() const { return true; }
ScriptVar& getValue(int idx) { return args[idx]; }
const ClazzInfo* getType(int idx) const { return args[idx].getValueClazzInfo(); }
int getUnnamedCount() const
{
if (hasNamed() == false)
return getCount();
return getCount() - namedargs->length();
}
RString getName(int idx)
{
return getNameArgName(getCount(), idx);
}
const ElementContainer& elementContainer() const { return args; }
const ElementType& get(int idx) const { return args[idx]; }
void set(int idx, const ElementType& et) { args[idx] = et; }
void resetElement(int idx) { args[idx].reset(); }
void resize(int newSize) { args.resize(newSize); }
void setValue(int idx, const ScriptVar& sv) { args[idx] = sv; }
};
class MethodArgInfoArgDesc
: public NamedArgDescription
{
::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& args;
public:
typedef ClazzMethodArgInfo ElementType;
typedef ::acdk::lang::sys::core_vector<ClazzMethodArgInfo> ElementContainer;
MethodArgInfoArgDesc(::acdk::lang::sys::core_vector<ClazzMethodArgInfo>& a, IN(RStringArray) nargs)
: NamedArgDescription(nargs)
, args(a)
{}
int getCount() const { return args.size(); }
bool hasValues() const { return false; }
ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; }
const ClazzInfo* getType(int idx) const { return args[idx].type; }
bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; }
int getUnnamedCount() const
{
if (hasNamed() == false)
return getCount();
return getCount() - namedargs->length();
}
int getNamedCount() const
{
return namedargs == Nil ? 0 : namedargs->length();
}
RString getName(int idx)
{
return getNameArgName(getCount(), idx);
}
const ElementContainer& elementContainer() const { return args; }
const ElementType& get(int idx) const { return args[idx]; }
void set(int idx, const ElementType& et) { args[idx] = et; }
void resetElement(int idx) { }
void resize(int newSize) { args.resize(newSize); }
// not supported, hasValues() == false
void setValue(int idx, const ScriptVar& sv) { }
};
class MethodArgInfoPtrArgDesc
: public NamedArgDescription
{
ClazzMethodArgInfo** args;
int count;
public:
typedef ClazzMethodArgInfo ElementType;
typedef ClazzMethodArgInfo** ElementContainer;
MethodArgInfoPtrArgDesc(acdk::lang::dmi::ClazzMethodArgInfo** a, IN(RStringArray) nargs)
: NamedArgDescription(nargs)
, args(a)
, count(0)
{
if (args != 0)
{
for (int i = 0; args[i] != 0; ++i)
++count;
}
}
int getCount() const { return count; }
bool hasValues() const { return false; }
ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; }
const ClazzInfo* getType(int idx) const { return args[idx]->type; }
bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; }
int getUnnamedCount() const
{
if (hasNamed() == false)
return getCount();
return getCount() - namedargs->length();
}
int getNamedCount() const
{
return namedargs == Nil ? 0 : namedargs->length();
}
RString getName(int idx)
{
return getNameArgName(getCount(), idx);
}
const ElementContainer& elementContainer() const { return args; }
const ElementType& get(int idx) const { return *args[idx]; }
void set(int idx, const ElementType& et) { }
void resetElement(int idx) { }
void resize(int newSize) { }
// not supported, hasValues() == false
void setValue(int idx, const ScriptVar& sv) { }
};
class FunctionSignatureArgDesc
: public NamedArgDescription
{
FunctionSignature& args;
public:
typedef const ClazzInfo* ElementType;
typedef const ClazzInfo** ElementContainer;
FunctionSignatureArgDesc(FunctionSignature& a, IN(RStringArray) nargs)
: NamedArgDescription(nargs)
, args(a)
{
}
int getCount() const { return args.size; }
bool hasValues() const { return false; }
ScriptVar& getValue(int idx) { static ScriptVar voidSv; return voidSv; }
const ClazzInfo* getType(int idx) const { return args.args[idx]; }
bool hasNamed() const { return namedargs != Nil && namedargs->length() > 0; }
int getUnnamedCount() const
{
if (hasNamed() == false)
return getCount();
return getCount() - namedargs->length();
}
int getNamedCount() const
{
return namedargs == Nil ? 0 : namedargs->length();
}
RString getName(int idx)
{
return getNameArgName(getCount(), idx);
}
ElementContainer& elementContainer() { return args.args; }
ElementType& get(int idx) { return args.args[idx]; }
void set(int idx, const ElementType& et) { }
void resetElement(int idx) { }
void resize(int newSize) { }
// not supported, hasValues() == false
void setValue(int idx, const ScriptVar& sv) { }
};
template <class CMD, class ARGS>
bool
hasRestParam(const CMD& mi, ARGS& args)
{
bool hasRest = (mi.getParamCount() > 0) &&
ClazzInfo::isRestArg(mi.getParamType(mi.getParamCount() - 1));
if (hasRest == false)
return false;
int argCount = args.getCount();
if (argCount == 0)
return true;
int paramCount = mi.getParamCount();
if (args.getType(argCount - 1) == DmiObjectArray::clazzInfo() &&
argCount == paramCount)
return false;
return true;
}
template <class CMD, class ARGS>
bool
hasNamedRestParam(const CMD& mi, ARGS& args)
{
bool hasRest = (mi.getParamCount() > 0) &&
ClazzInfo::isNamedRestArg(mi.getParamType(mi.getParamCount() - 1));
if (hasRest == false)
return false;
int argCount = args.getCount();
if (argCount == 0)
return true;
if (args.getType(argCount - 1) == DmiNamedArgArray::clazzInfo())
return false;
return true;
}
//static
void
StdDispatch::findFunctions(const ClazzInfo* clazz, IN(RString) funcname, int flags, ClazzMethodInfoVec& vec)
{
if (clazz == 0)
return;
clazz = clazz->loadFullClazzInfo();
int i;
RString opmethod;
RString opChar;
RString fname = funcname;
if ((opChar = isOperator(funcname)) != Nil)
{
opmethod = acdk::lang::reflect::Method::encodeOperatorToFuncName(opChar);
fname = opmethod;
}
if (clazz->methods != 0)
{
for (i = 0; clazz->methods[i]; i++)
{
const ClazzMethodInfo* cmi = clazz->methods[i];
if (MetaInfo::checkMemberAccess(flags, cmi->flags) == false)
continue;
// ## TODO check MiIvViaAltName flag
if (cmi->equalsName(fname) == false && cmi->equalsAltName(fname) == false)
continue;
vec.push_back(cmi);
}
}
if (clazz->interfaces != 0 && (MiIvDeclared & flags) == 0 && (MiMiConstructor & flags) == 0)
{
if (flags & MiIvTransientCall)
flags |= MiProtected;
for (i = 0; clazz->interfaces[i]; i++)
{
findFunctions(clazz->interfaces[i]->type, fname, flags, vec);
}
}
}
void asSignature(StringBuffer& sb, ScriptVarArray& args)
{
for (int i = 0; i < args.size(); ++i)
{
if (i > 0)
sb.append(", ");
sb.append(args[i].getTypeInfo());
}
}
/*
bool
MethodInfo_hasRestParam(const ClazzMethodInfo* mi)
{
return (mi->getArgumentCount() > 0 &&
ClazzInfo::isRestArg(mi->methodArgs[mi->getArgumentCount() - 1]->type));
}
bool
MethodInfo_hasNamedRestParam(const ClazzMethodInfo* mi)
{
return (mi->getArgumentCount() > 0 &&
ClazzInfo::isNamedRestArg(mi->methodArgs[mi->getArgumentCount() - 1]->type));
}*/
//static
const ClazzMethodInfo*
StdDispatch::_lookupMethod(const ClazzInfo*& clazz, IN(RString) fname,
ScriptVarArray& args, DmiClient& dc, int flags, const ClazzMethodInfo* methinf)
{
return _lookupMethod(clazz, fname, args, Nil, dc, flags, methinf);
/*
dead method
const ClazzInfo* tclazz = clazz;
if (flags & MiIvViaHash)
{
int methhash = ACDK_CAST_PTR2INT(methinf);
const ClazzMethodInfo* cmi = lookupMethod(clazz, methhash, flags);
if (cmi == 0 && (flags & MiIvNoThrowIfNotFound) == 0)
ClazzMethodInfo::throwMethodNotFound(tclazz, Integer::toString(methhash), flags, dc._formatFlags);
return cmi;
}
if (fname->length() == 0 || clazz == 0)
{
if ((flags & MiIvNoThrowIfNotFound) == 0)
THROW1(NoSuchDmiElementException, "Class or method not not defined");
return 0;
}
// ## TODO check MiIvViaAltName
RString rfname = fname;
if ((flags & MiIvConstructor) == MiIvConstructor && clazz->isArray() == true)
{
const ClazzInfo* eltype = clazz->userInfo; //clazz->getArrayElementType();
if (rfname->startsWith(eltype->name) == true)
{
if (eltype->isBasicClazz() == true)
rfname = "ObjectArrayBaseImpl"; // ###typo??
else
rfname = "ObjectArrayBaseImpl";
}
else if (*eltype->name == '[')
{
rfname = "ObjectArrayBaseImpl";
}
}
ClazzMethodInfoVec methods;
findFunctions(clazz, rfname, flags, methods);
if (methods.size() == 0)
{
if ((flags & MiIvNoThrowIfNotFound) == 0)
ClazzMethodInfo::throwMethodNotFound(tclazz, &fname, flags, dc._formatFlags);
return 0;
}
int lastmatch = 0;
//ClazzMethodInfoVec lastBestMatch;
const ClazzMethodInfo* lastBestMatch = 0;
ClazzMethodInfoVec::iterator it = methods.begin();
ClazzMethodInfoVec::iterator end = methods.end();
for (; it != end; ++it)
{
const ClazzMethodInfo* cmi = *it;
int mcount = cmi->getArgumentCount();
bool hasRestParam = MethodInfo_hasRestParam(cmi);
bool hasNamedRestParam = MethodInfo_hasNamedRestParam(cmi);
if (mcount != args.size())
{
if (hasRestParam == false && hasNamedRestParam == false)
continue;
}
bool canasign = true;
int total = 0;
bool wasViaNamedRest = false;
for (int j = 0; j < mcount; j++)
{
if (j == mcount - 1 && (hasRestParam == true || hasNamedRestParam == true))
{
wasViaNamedRest = true;
break;
}
int match;
if (cmi->methodArgs[j]->flags & MiAiOut)
match = dc.typeDistance(cmi->methodArgs[j]->type, args[j].getClazzInfo());
else
match = dc.typeDistance(args[j], cmi->methodArgs[j]->type);
if (match == -1)
{
canasign = false;
break;
}
total += match;
}
if (canasign == true)
{
if (total == 0)
{
if (wasViaNamedRest == false)
{
clazz = reinterpret_cast<const ClazzInfo*>(cmi->_scopeParent);
return cmi;
}
else
total = 1024;
}
if ((total < lastmatch) || (lastBestMatch == 0)) {
lastmatch = total;
lastBestMatch = *it;
}
}
}
if (lastBestMatch != 0)
{
clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent);
return lastBestMatch;
}
StringBuffer sb(1024);
sb.append("No matching function found: ");
clazz->toTypeString(sb, dc._formatFlags);
if (dc._formatFlags & TpFtAcdkType)
sb.append("::");
else
sb.append(".");
sb.append(fname);
sb.append("(");
asSignature(sb, args);
sb.append(")\n Following functions are defined:\n");
for (int i = 0; i < methods.size(); ++i)
{
sb.append("\t");
const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent;
if (clazz->isArray() == true)
parent = clazz;
methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags);
sb.append("\n");
}
if ((flags & MiIvNoThrowIfNotFound) == 0)
THROW3(ParamsMismatchException, sb.toString(), clazz, methods);
return 0;
*/
}
int matchParameter(const ClazzInfo* paramType, int paramFlag, ScriptVar& sv, DmiClient& dc)
{
if (paramFlag & MiAiOut)
return dc.typeDistance(paramType, sv.getClazzInfo());
else
return dc.typeDistance(sv, paramType);
}
int matchParameter(const ClazzInfo* paramType, int paramFlag, const ClazzInfo* argType, DmiClient& dc)
{
if (paramFlag & MiAiOut)
return dc.typeDistance(paramType, argType);
else
return dc.typeDistance(argType, paramType);
}
template <class CMD, class ARGS>
int
matchParameters(const ClazzInfo* clazz, const CMD& cmi, ARGS& args, int argCount
, DmiClient& dc, int flags)
{
int matchSum = 0;
for (int i = 0; i < argCount; ++i)
{
int match = -1;
if (args.hasValues() == true)
match = matchParameter(cmi.getParamType(i), cmi.getParamFlags(i), args.getValue(i), dc);
else
match = matchParameter(cmi.getParamType(i), cmi.getParamFlags(i), args.getType(i), dc);
if (match == -1)
return -1;
matchSum += match;
}
return matchSum;
}
/**
return weight of this matching method
does not check if method has
*/
template <class CMD, class ARGS>
int
matchSimpleMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args
, DmiClient& dc
, int flags
, OUT(RbyteArray) order
)
{
bool hasRest = hasRestParam(cmi, args);
bool hasNamedRest = hasNamedRestParam(cmi, args);
int argCount = args.getCount();
int paramCount = cmi.getParamCount();
if (hasNamedRest == true)
{
--paramCount;
}
if (argCount != paramCount && hasRest == false)
return -1;
if (hasRest == false)
return matchParameters(clazz, cmi, args, argCount, dc, flags);
int c = matchParameters(clazz, cmi, args, paramCount - 1, dc, flags);
if (c == -1)
return -1;
c += (argCount - (paramCount - 1)) * 1024;
order = new byteArray(argCount);
int i;
for (i = 0; i < paramCount - 1; ++i)
order[i] = i;
for (i = paramCount - 1; i < argCount; ++i)
order[i] = -1;
return c;
}
template <class CMD, class ARGS>
int
matchNamedArgsMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args
, DmiClient& dc
, int flags, OUT(RbyteArray) order)
{
bool hasNamedRest = hasNamedRestParam(cmi, args);
int argCount = args.getCount();
int paramCount = cmi.getParamCount();
int namedArgCount = args.getNamedCount();
int unnamedArgCount = args.getUnnamedCount();
int mc = matchParameters(clazz, cmi, args, unnamedArgCount, dc, flags);
if (mc == -1)
return -1;
if (argCount != paramCount && hasNamedRest == false)
return -1;
order = new byteArray(argCount, 0xfe);
int i;
for (i = 0; i < unnamedArgCount; ++i)
order[i] = i;
for (i = unnamedArgCount; i < argCount; ++i)
{
int namedIdx = i - unnamedArgCount;
bool foundNamed = false;
RString narg = args.getName(i);
for (int j = unnamedArgCount; j < paramCount; ++j)
{
if (cmi.equalsParamName(j, narg) == true)
{
int m = -1;
if (args.hasValues() == true)
m = matchParameter(cmi.getParamType(j), cmi.getParamFlags(j), args.getValue(i), dc);
else
m = matchParameter(cmi.getParamType(j), cmi.getParamFlags(j), args.getType(i), dc);
if (m == -1)
return -1;
order[i] = j;
mc += m;
foundNamed = true;
break;
}
}
if (foundNamed == false)
{
if (hasNamedRest == false)
return -1;
break;
}
}
/** try to match default parameter doesn't work currently
for (i = 0; i < paramCount; ++i)
{
int fidx = order->findFirst(byte(i));
if (fidx == -1)
{
if (cmi.hasDefaultValue(i) == false)
return -1;
}
}
*/
mc += (argCount - (i - 1)) * 1024;
for (; i < argCount; ++i)
order[i] = -1;
return mc;
}
template <class CMD, class ARGS>
int
matchMethod(const ClazzInfo* clazz, const CMD& cmi, ARGS& args
, DmiClient& dc
, int flags
, OUT(RbyteArray) order)
{
if (args.hasNamed() == false)
{
return matchSimpleMethod(clazz, cmi, args, dc, flags, order);
}
return matchNamedArgsMethod(clazz, cmi, args, dc, flags, order);
}
template <class CMD, class ARGS>
void
mapArguments(const ClazzInfo*& clazz, const CMD& cmd, ARGS& args, IN(RbyteArray) lastnewargpos)
{
bool hasNamedRest = hasNamedRestParam(cmd, args);
bool hasRest = hasRestParam(cmd, args);
bool restAdded = false;
int argsCount = args.getCount();
if (lastnewargpos != Nil)
{
typename ARGS::ElementContainer argssic = args.elementContainer();
int i;
for (i = 0; i < argsCount; ++i)
{
int newpos = lastnewargpos[i];
if (newpos == 0xff)
break;
else if (newpos == 0xfe)
{
/*### not working if (lastBestMatch->methodArgs[i]->getDefaultArgValueFunc != 0)
args[i] = lastBestMatch->methodArgs[i]->getDefaultArgValueFunc(lastBestMatch->methodArgs[i]);
else
; //Ooops
*/
}
else if (newpos != i)
{
args.resetElement(newpos);
args.set(newpos, argssic[i]);
}
}
if (i != argsCount)
{
int fixed = i;
int calcUnmappedsize = 0;
for (int ti = lastnewargpos->length() - 1; ti >= 0; --ti)
{
if (lastnewargpos[ti] != 0xff)
break;
++calcUnmappedsize;
}
if (args.hasValues() == true)
{
if (hasNamedRest = true && args.hasNamed() == true)
{
int unmapped = argsCount - fixed;
RDmiNamedArgArray rest = new DmiNamedArgArray(unmapped);
int mc = 0;
for (int naidx = 0; i < argsCount; ++i, ++naidx)
{
RString narg = args.getName(i);
rest[naidx] = new DmiNamedArg(narg, new DmiObject(args.getValue(i)));
}
args.resize(fixed + 1);
args.setValue(fixed, inOf(rest));
restAdded = true;
}
else if (hasRest == true)
{
int unmapped = argsCount - fixed;
RDmiObjectArray rest = new DmiObjectArray(unmapped);
for (; i < argsCount; ++i)
{
rest[i - fixed] = new DmiObject(args.getValue(i));
}
args.resize(fixed + 1);
args.setValue(fixed, inOf(rest));
restAdded = true;
}
}
}
}
if (hasNamedRest == true && restAdded == false)
{
RDmiNamedArgArray rest = new DmiNamedArgArray(0);
args.resize(argsCount + 1);
args.setValue(argsCount, inOf(rest));
}
if (hasRest == true && restAdded == false)
{
RDmiObjectArray rest = new DmiObjectArray(0);
args.resize(argsCount + 1);
args.setValue(argsCount, inOf(rest));
}
}
/*
standard lookup used by dmi
*/
//static
const ClazzMethodInfo*
StdDispatch::_lookupMethod( const ClazzInfo*& clazz
, IN(RString) fname
, ScriptVarArray& args
, IN(RStringArray) namedargs
, DmiClient& dc
, int flags
, const ClazzMethodInfo* methinf
)
{
const ClazzInfo* tclazz = clazz;
if (flags & MiIvViaHash)
{
int methhash = ACDK_CAST_PTR2INT(methinf);
const ClazzMethodInfo* cmi = lookupMethod(clazz, methhash, flags);
if (cmi == 0 && (flags & MiIvNoThrowIfNotFound) == 0)
ClazzMethodInfo::throwMethodNotFound(tclazz, Integer::toString(methhash), flags, dc._formatFlags);
return cmi;
}
if (fname->length() == 0 || clazz == 0)
{
if ((flags & MiIvNoThrowIfNotFound) == 0)
THROW1(NoSuchDmiElementException, "Class or method not defined");
return 0;
}
RString rfname = fname;
if ((flags & MiIvConstructor) == MiIvConstructor && clazz->isArray() == true)
{
const ClazzInfo* eltype = clazz->userInfo; //clazz->getArrayElementType();
if (rfname->startsWith(eltype->name) == true)
{
if (eltype->isBasicClazz() == true)
rfname = "ObjectArrayBaseImpl"; // ###typo??
else
rfname = "ObjectArrayBaseImpl";
}
else if (*eltype->name == '[')
{
rfname = "ObjectArrayBaseImpl";
}
}
ClazzMethodInfoVec methods;
findFunctions(clazz, rfname, flags, methods);
if (methods.size() == 0)
{
if ((flags & MiIvNoThrowIfNotFound) == MiIvNoThrowIfNotFound)
return 0;
StringBuffer sb;
sb.append("Method not found: ");
MetaInfo::flagsToTypeDecl(sb, flags, dc._formatFlags);
sb.append(" ");
tclazz->toTypeString(sb, dc._formatFlags);
sb.append("::");
sb.append(fname);
sb.append("(...)");
THROW1(NoSuchMethodException, sb.toString());
}
int lastmatch = 0;
const ClazzMethodInfo* lastBestMatch = 0;
/*
idx is original position
newargpos[i] is new position
if position is -1 the argument belongs to Named or unnamed rest
*/
RbyteArray newargpos;
RbyteArray lastnewargpos = Nil;
ClazzMethodInfoVec::iterator it = methods.begin();
ClazzMethodInfoVec::iterator end = methods.end();
for (; it != end; ++it)
{
const ClazzMethodInfo* cmi = *it;
ClazzMethodInfoDescriptor cmd(cmi);
ScriptVarArgDescription argdesc(args, namedargs);
int m = matchMethod(clazz, cmd, argdesc, dc,flags, newargpos);
if (m == -1)
continue;
if (m == 0 || lastmatch == 0 || lastmatch > m)
{
lastBestMatch = cmi;
lastmatch = m;
lastnewargpos = newargpos;
if (m == 0)
break;
}
}
if (lastBestMatch == 0)
{
if ((flags & MiIvNoThrowIfNotFound) == MiIvNoThrowIfNotFound)
return 0;
StringBuffer sb(1024);
sb.append("No matching function found: ");
tclazz->toTypeString(sb, dc._formatFlags);
sb.append("::");
sb.append(fname);
sb.append("(");
asSignature(sb, args);
sb.append(")\n Following functions are defined:\n");
for (int i = 0; i < methods.size(); ++i)
{
sb.append("\t");
const ClazzInfo* parent = (const ClazzInfo*)methods[i]->_scopeParent;
if (tclazz->isArray() == true)
parent = tclazz;
methods[i]->toTypeString(sb, reinterpret_cast<const ClazzInfo*>(parent), dc._formatFlags);
sb.append("\n");
}
THROW3(ParamsMismatchException, sb.toString(), tclazz, methods);
}
ClazzMethodInfoDescriptor cmd(lastBestMatch);
ScriptVarArgDescription argdesc(args, namedargs);
mapArguments(clazz, cmd, argdesc, lastnewargpos);
/*
bool hasNamedRest = hasNamedRestParam(cmd);
bool hasRest = hasRestParam(cmd);
bool restAdded = false;
if (lastmatch == 0 && hasNamedRest == false && hasRest == false)
return lastBestMatch;
if (lastnewargpos != Nil)
{
ScriptVarArray argssic = args;
int i;
for (i = 0; i < args.size(); ++i)
{
int newpos = lastnewargpos[i];
int argsCount = args.size();
if (newpos == 0xff)
break;
else if (newpos == 0xfe)
{
if (lastBestMatch->methodArgs[i]->getDefaultArgValueFunc != 0)
args[i] = lastBestMatch->methodArgs[i]->getDefaultArgValueFunc(lastBestMatch->methodArgs[i]);
else
; //Ooops
}
else if (newpos != i)
{
args[newpos].reset();
args[newpos] = argssic[i];
}
}
if (i != args.size())
{
int fixed = i;
int calcUnmappedsize = 0;
for (int ti = lastnewargpos->length() - 1; ti >= 0; --ti)
{
if (lastnewargpos[ti] != 0xff)
break;
++calcUnmappedsize;
}
ClazzMethodInfoDescriptor cmd(lastBestMatch);
if (hasNamedRestParam(cmd) == true)
{
int unmapped = args.size() - fixed;
RDmiNamedArgArray rest = new DmiNamedArgArray(unmapped);
int mc = 0;
int unMappedOffset = namedargs->length() - calcUnmappedsize;
for (int naidx = 0; i < args.size(); ++i, ++naidx)
{
RString narg = namedargs[unMappedOffset + naidx];
rest[naidx] = new DmiNamedArg(narg, new DmiObject(args[i]));
}
args.resize(fixed + 1);
args[fixed] = &rest;
restAdded = true;
}
else if (hasRestParam(cmd) == true)
{
int unmapped = args.size() - fixed;
RDmiObjectArray rest = new DmiObjectArray(unmapped);
for (; i < args.size(); ++i)
{
rest[i - fixed] = new DmiObject(args[i]);
}
args.resize(fixed + 1);
args[fixed] = &rest;
restAdded = true;
}
}
}
if (hasNamedRest == true && restAdded == false)
{
RDmiNamedArgArray rest = new DmiNamedArgArray(0);
args.resize(args.size() + 1);
args[args.size() - 1] = &rest;
}
if (hasRest == true && restAdded == false)
{
RDmiObjectArray rest = new DmiObjectArray(0);
args.resize(args.size() + 1);
args[args.size() - 1] = &rest;
}
*/
clazz = reinterpret_cast<const ClazzInfo*>(lastBestMatch->_scopeParent);
return lastBestMatch;
/*
int mcount = 0;
int nargsc = namedargs->length();
int unamedargsc = 0;
newargpos = new byteArray(args.size(), (byte)-1);
const ClazzMethodInfo* cmi = *it;
mcount = cmi->getArgumentCount();
bool hasNamedRest = MethodInfo_hasNamedRestParam(cmi);
if (hasNamedRest == true)
mcount -= 1;
else if (mcount != args.size())
continue;
if (hasNamedRest == true)
unamedargsc = mcount;
else
unamedargsc = mcount - nargsc;
bool canasign = true;
int total = 0;
for (int j = 0; j < unamedargsc; j++)
{
int match;
if (cmi->methodArgs[j]->flags & MiAiOut)
match = dc.typeDistance(cmi->methodArgs[j]->type, args[j].getClazzInfo());
else
match = dc.typeDistance(args[j], cmi->methodArgs[j]->type);
if (match == -1) {
canasign = false;
break;
}
total += match;
}
if (canasign == true)
{
for (int j = unamedargsc; j < mcount; j++) // checke named values
{
bool foundp = false;
int mapped = 0;
//for (mapped = 0; mapped < nargsc && mapped + j < mcount; ++mapped) // seek positinal
for (mapped = 0; mapped < nargsc && mapped + unamedargsc < mcount; ++mapped) // seek positinal
{
RString narg = namedargs[mapped];
if (cmi->methodArgs[j]->equ |