338 lines
12 KiB
C#
338 lines
12 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Drawing;
|
|
using System.Reflection;
|
|
using Lua511;
|
|
|
|
namespace LuaInterface
|
|
{
|
|
/*
|
|
* Type checking and conversion functions.
|
|
*
|
|
* Author: Fabio Mascarenhas
|
|
* Version: 1.0
|
|
*/
|
|
class CheckType
|
|
{
|
|
private ObjectTranslator translator;
|
|
|
|
ExtractValue extractNetObject;
|
|
Dictionary<long, ExtractValue> extractValues = new Dictionary<long, ExtractValue>();
|
|
|
|
public CheckType(ObjectTranslator translator)
|
|
{
|
|
this.translator = translator;
|
|
|
|
extractValues.Add(typeof(object).TypeHandle.Value.ToInt64(), new ExtractValue(getAsObject));
|
|
extractValues.Add(typeof(sbyte).TypeHandle.Value.ToInt64(), new ExtractValue(getAsSbyte));
|
|
extractValues.Add(typeof(byte).TypeHandle.Value.ToInt64(), new ExtractValue(getAsByte));
|
|
extractValues.Add(typeof(short).TypeHandle.Value.ToInt64(), new ExtractValue(getAsShort));
|
|
extractValues.Add(typeof(ushort).TypeHandle.Value.ToInt64(), new ExtractValue(getAsUshort));
|
|
extractValues.Add(typeof(int).TypeHandle.Value.ToInt64(), new ExtractValue(getAsInt));
|
|
extractValues.Add(typeof(uint).TypeHandle.Value.ToInt64(), new ExtractValue(getAsUint));
|
|
extractValues.Add(typeof(long).TypeHandle.Value.ToInt64(), new ExtractValue(getAsLong));
|
|
extractValues.Add(typeof(ulong).TypeHandle.Value.ToInt64(), new ExtractValue(getAsUlong));
|
|
extractValues.Add(typeof(double).TypeHandle.Value.ToInt64(), new ExtractValue(getAsDouble));
|
|
extractValues.Add(typeof(char).TypeHandle.Value.ToInt64(), new ExtractValue(getAsChar));
|
|
extractValues.Add(typeof(float).TypeHandle.Value.ToInt64(), new ExtractValue(getAsFloat));
|
|
extractValues.Add(typeof(decimal).TypeHandle.Value.ToInt64(), new ExtractValue(getAsDecimal));
|
|
extractValues.Add(typeof(bool).TypeHandle.Value.ToInt64(), new ExtractValue(getAsBoolean));
|
|
extractValues.Add(typeof(string).TypeHandle.Value.ToInt64(), new ExtractValue(getAsString));
|
|
extractValues.Add(typeof(LuaFunction).TypeHandle.Value.ToInt64(), new ExtractValue(getAsFunction));
|
|
extractValues.Add(typeof(LuaTable).TypeHandle.Value.ToInt64(), new ExtractValue(getAsTable));
|
|
extractValues.Add(typeof(LuaUserData).TypeHandle.Value.ToInt64(), new ExtractValue(getAsUserdata));
|
|
extractValues.Add(typeof(Color).TypeHandle.Value.ToInt64(), new ExtractValue(getAsColor));
|
|
extractNetObject = new ExtractValue(getAsNetObject);
|
|
}
|
|
|
|
/*
|
|
* Checks if the value at Lua stack index stackPos matches paramType,
|
|
* returning a conversion function if it does and null otherwise.
|
|
*/
|
|
internal ExtractValue getExtractor(IReflect paramType)
|
|
{
|
|
return getExtractor(paramType.UnderlyingSystemType);
|
|
}
|
|
internal ExtractValue getExtractor(Type paramType)
|
|
{
|
|
if(paramType.IsByRef) paramType=paramType.GetElementType();
|
|
|
|
long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64();
|
|
|
|
if(extractValues.ContainsKey(runtimeHandleValue))
|
|
return extractValues[runtimeHandleValue];
|
|
else
|
|
return extractNetObject;
|
|
}
|
|
|
|
internal ExtractValue checkType(IntPtr luaState,int stackPos,Type paramType)
|
|
{
|
|
LuaTypes luatype = LuaDLL.lua_type(luaState, stackPos);
|
|
|
|
if(paramType.IsByRef) paramType=paramType.GetElementType();
|
|
|
|
Type underlyingType = Nullable.GetUnderlyingType(paramType);
|
|
if (underlyingType != null)
|
|
{
|
|
paramType = underlyingType; // Silently convert nullable types to their non null requics
|
|
}
|
|
|
|
long runtimeHandleValue = paramType.TypeHandle.Value.ToInt64();
|
|
|
|
if (paramType.Equals(typeof(object)))
|
|
return extractValues[runtimeHandleValue];
|
|
|
|
//CP: Added support for generic parameters
|
|
if (paramType.IsGenericParameter)
|
|
{
|
|
if (luatype == LuaTypes.LUA_TBOOLEAN)
|
|
return extractValues[typeof(bool).TypeHandle.Value.ToInt64()];
|
|
else if (luatype == LuaTypes.LUA_TSTRING)
|
|
return extractValues[typeof(string).TypeHandle.Value.ToInt64()];
|
|
else if (luatype == LuaTypes.LUA_TTABLE)
|
|
return extractValues[typeof(LuaTable).TypeHandle.Value.ToInt64()];
|
|
else if (luatype == LuaTypes.LUA_TUSERDATA)
|
|
return extractValues[typeof(object).TypeHandle.Value.ToInt64()];
|
|
else if (luatype == LuaTypes.LUA_TFUNCTION)
|
|
return extractValues[typeof(LuaFunction).TypeHandle.Value.ToInt64()];
|
|
else if (luatype == LuaTypes.LUA_TNUMBER)
|
|
return extractValues[typeof(double).TypeHandle.Value.ToInt64()];
|
|
else
|
|
;//an unsupported type was encountered
|
|
}
|
|
|
|
if (LuaDLL.lua_isnumber(luaState, stackPos))
|
|
return extractValues[runtimeHandleValue];
|
|
|
|
if (paramType == typeof(bool))
|
|
{
|
|
if (LuaDLL.lua_isboolean(luaState, stackPos))
|
|
return extractValues[runtimeHandleValue];
|
|
}
|
|
else if (paramType == typeof(Color))
|
|
{
|
|
return extractValues[runtimeHandleValue];
|
|
}
|
|
else if (paramType == typeof(string) || paramType == typeof(char[]))
|
|
{
|
|
if (LuaDLL.lua_isstring(luaState, stackPos))
|
|
return extractValues[runtimeHandleValue];
|
|
else if (luatype == LuaTypes.LUA_TNIL)
|
|
return extractNetObject; // kevinh - silently convert nil to a null string pointer
|
|
}
|
|
else if (paramType == typeof(LuaTable))
|
|
{
|
|
if (luatype == LuaTypes.LUA_TTABLE)
|
|
return extractValues[runtimeHandleValue];
|
|
}
|
|
else if (paramType == typeof(LuaUserData))
|
|
{
|
|
if (luatype == LuaTypes.LUA_TUSERDATA)
|
|
return extractValues[runtimeHandleValue];
|
|
}
|
|
else if (paramType == typeof(LuaFunction))
|
|
{
|
|
if (luatype == LuaTypes.LUA_TFUNCTION)
|
|
return extractValues[runtimeHandleValue];
|
|
}
|
|
else if (typeof(Delegate).IsAssignableFrom(paramType) && luatype == LuaTypes.LUA_TFUNCTION)
|
|
{
|
|
return new ExtractValue(new DelegateGenerator(translator, paramType).extractGenerated);
|
|
}
|
|
else if (paramType.IsInterface && luatype == LuaTypes.LUA_TTABLE)
|
|
{
|
|
return new ExtractValue(new ClassGenerator(translator, paramType).extractGenerated);
|
|
}
|
|
else if ((paramType.IsInterface || paramType.IsClass) && luatype == LuaTypes.LUA_TNIL)
|
|
{
|
|
// kevinh - allow nil to be silently converted to null - extractNetObject will return null when the item ain't found
|
|
return extractNetObject;
|
|
}
|
|
else if (LuaDLL.lua_type(luaState, stackPos) == LuaTypes.LUA_TTABLE)
|
|
{
|
|
if (LuaDLL.luaL_getmetafield(luaState, stackPos, "__index"))
|
|
{
|
|
object obj = translator.getNetObject(luaState, -1);
|
|
LuaDLL.lua_settop(luaState, -2);
|
|
if (obj != null && paramType.IsAssignableFrom(obj.GetType()))
|
|
return extractNetObject;
|
|
}
|
|
else
|
|
return null;
|
|
}
|
|
else
|
|
{
|
|
object obj = translator.getNetObject(luaState, stackPos);
|
|
if (obj != null && paramType.IsAssignableFrom(obj.GetType()))
|
|
return extractNetObject;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
/*
|
|
* The following functions return the value in the Lua stack
|
|
* index stackPos as the desired type if it can, or null
|
|
* otherwise.
|
|
*/
|
|
private object getAsSbyte(IntPtr luaState,int stackPos)
|
|
{
|
|
sbyte retVal=(sbyte)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsByte(IntPtr luaState,int stackPos)
|
|
{
|
|
byte retVal=(byte)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsShort(IntPtr luaState,int stackPos)
|
|
{
|
|
short retVal=(short)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsUshort(IntPtr luaState,int stackPos)
|
|
{
|
|
ushort retVal=(ushort)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsInt(IntPtr luaState,int stackPos)
|
|
{
|
|
int retVal=(int)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsUint(IntPtr luaState,int stackPos)
|
|
{
|
|
uint retVal=(uint)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsLong(IntPtr luaState,int stackPos)
|
|
{
|
|
long retVal=(long)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsUlong(IntPtr luaState,int stackPos)
|
|
{
|
|
ulong retVal=(ulong)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsDouble(IntPtr luaState,int stackPos)
|
|
{
|
|
double retVal=LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsChar(IntPtr luaState,int stackPos)
|
|
{
|
|
char retVal=(char)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsFloat(IntPtr luaState,int stackPos)
|
|
{
|
|
float retVal=(float)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsDecimal(IntPtr luaState,int stackPos)
|
|
{
|
|
decimal retVal=(decimal)LuaDLL.lua_tonumber(luaState,stackPos);
|
|
if(retVal==0 && !LuaDLL.lua_isnumber(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsBoolean(IntPtr luaState,int stackPos)
|
|
{
|
|
return LuaDLL.lua_toboolean(luaState,stackPos);
|
|
}
|
|
private object getAsString(IntPtr luaState,int stackPos)
|
|
{
|
|
string retVal=LuaDLL.lua_tostring(luaState,stackPos);
|
|
if(retVal=="" && !LuaDLL.lua_isstring(luaState,stackPos)) return null;
|
|
return retVal;
|
|
}
|
|
private object getAsColor(IntPtr luaState, int stackPos)
|
|
{
|
|
try
|
|
{
|
|
if (LuaDLL.lua_isnumber(luaState, stackPos))
|
|
{
|
|
Color retVal = Color.FromArgb((int)(long)LuaDLL.lua_tonumber(luaState, stackPos));
|
|
return retVal;
|
|
}
|
|
else if (LuaDLL.lua_isstring(luaState, stackPos))
|
|
{
|
|
|
|
Color retVal = Color.FromName(LuaDLL.lua_tostring(luaState, stackPos));
|
|
return retVal;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
private object getAsTable(IntPtr luaState,int stackPos)
|
|
{
|
|
return translator.getTable(luaState,stackPos);
|
|
}
|
|
private object getAsFunction(IntPtr luaState,int stackPos)
|
|
{
|
|
return translator.getFunction(luaState,stackPos);
|
|
}
|
|
private object getAsUserdata(IntPtr luaState,int stackPos)
|
|
{
|
|
return translator.getUserData(luaState,stackPos);
|
|
}
|
|
public object getAsObject(IntPtr luaState,int stackPos)
|
|
{
|
|
if(LuaDLL.lua_type(luaState,stackPos)==LuaTypes.LUA_TTABLE)
|
|
{
|
|
if(LuaDLL.luaL_getmetafield(luaState,stackPos,"__index"))
|
|
{
|
|
if(LuaDLL.luaL_checkmetatable(luaState,-1))
|
|
{
|
|
LuaDLL.lua_insert(luaState,stackPos);
|
|
LuaDLL.lua_remove(luaState,stackPos+1);
|
|
}
|
|
else
|
|
{
|
|
LuaDLL.lua_settop(luaState,-2);
|
|
}
|
|
}
|
|
}
|
|
object obj=translator.getObject(luaState,stackPos);
|
|
return obj;
|
|
}
|
|
public object getAsNetObject(IntPtr luaState,int stackPos)
|
|
{
|
|
object obj=translator.getNetObject(luaState,stackPos);
|
|
if(obj==null && LuaDLL.lua_type(luaState,stackPos)==LuaTypes.LUA_TTABLE)
|
|
{
|
|
if(LuaDLL.luaL_getmetafield(luaState,stackPos,"__index"))
|
|
{
|
|
if(LuaDLL.luaL_checkmetatable(luaState,-1))
|
|
{
|
|
LuaDLL.lua_insert(luaState,stackPos);
|
|
LuaDLL.lua_remove(luaState,stackPos+1);
|
|
obj=translator.getNetObject(luaState,stackPos);
|
|
}
|
|
else
|
|
{
|
|
LuaDLL.lua_settop(luaState,-2);
|
|
}
|
|
}
|
|
}
|
|
return obj;
|
|
}
|
|
}
|
|
}
|