Mercurial Hosting > luan
changeset 47:659c7139e903
better conversion
git-svn-id: https://luan-java.googlecode.com/svn/trunk@48 21e917c8-12df-6dd8-5cb6-c86387c605b9
author | fschmidt@gmail.com <fschmidt@gmail.com@21e917c8-12df-6dd8-5cb6-c86387c605b9> |
---|---|
date | Thu, 27 Dec 2012 04:36:44 +0000 |
parents | a443637829c1 |
children | 64ecb7a3aad7 |
files | src/luan/LuaJavaFunction.java src/luan/LuaTable.java |
diffstat | 2 files changed, 352 insertions(+), 24 deletions(-) [+] |
line wrap: on
line diff
--- a/src/luan/LuaJavaFunction.java Thu Dec 27 01:48:36 2012 +0000 +++ b/src/luan/LuaJavaFunction.java Thu Dec 27 04:36:44 2012 +0000 @@ -4,6 +4,9 @@ import java.lang.reflect.Method; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.List; +import java.util.Map; +import java.util.Set; public final class LuaJavaFunction extends LuaFunction { @@ -45,6 +48,9 @@ Object rtn; try { rtn = method.invoke(obj,args); + } catch(IllegalArgumentException e) { + checkArgs(lua,args); + throw e; } catch(IllegalAccessException e) { throw new RuntimeException(e); } catch(InvocationTargetException e) { @@ -62,6 +68,19 @@ return rtnConverter.convert(rtn); } + private void checkArgs(LuaState lua,Object[] args) throws LuaException { + Class<?>[] a = getParameterTypes(); + for( int i=0; i<a.length; i++ ) { + if( !a[i].isInstance(args[i]) ) { + String got = args[i].getClass().getName(); + String expected = a[i].getName(); + if( !takesLuaState ) + i++; + throw new LuaException(lua,LuaElement.JAVA,"bad argument #"+i+" ("+expected+" expected, got "+got+")"); + } + } + } + private Object[] fixArgs(LuaState lua,Object[] args) { int n = argConverters.length; Object[] rtn; @@ -125,16 +144,40 @@ private static final Object[] NULL_RTN = new Object[1]; + private static final RtnConverter RTN_NUMBER_ARRAY = new RtnConverter() { + public Object[] convert(Object obj) { + if( obj == null ) + return NULL_RTN; + Object[] rtn = new Object[Array.getLength(obj)]; + for( int i=0; i<rtn.length; i++ ) { + rtn[i] = Array.get(obj,i); + } + return rtn; + } + }; + private static RtnConverter getRtnConverter(JavaMethod m) { Class<?> rtnType = m.getReturnType(); if( rtnType == Void.TYPE ) return RTN_EMPTY; if( rtnType.isArray() ) { + rtnType = rtnType.getComponentType(); + if( isNumber(rtnType) ) + return RTN_NUMBER_ARRAY; return RTN_ARRAY; } return RTN_ONE; } + private static boolean isNumber(Class<?> rtnType) { + return rtnType == Byte.TYPE + || rtnType == Short.TYPE + || rtnType == Integer.TYPE + || rtnType == Long.TYPE + || rtnType == Float.TYPE + || rtnType == Double.TYPE + ; + } private interface ArgConverter { public Object convert(Object obj); @@ -146,6 +189,177 @@ } }; + private static final ArgConverter ARG_DOUBLE = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Double ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + return n.doubleValue(); + } + if( obj instanceof String ) { + String s = (String)obj; + try { + return Double.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_FLOAT = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Float ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + float r = n.floatValue(); + if( r==n.doubleValue() ) + return r; + } + if( obj instanceof String ) { + String s = (String)obj; + try { + return Float.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_LONG = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Long ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + long r = n.longValue(); + if( r==n.doubleValue() ) + return r; + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Long.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_INTEGER = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Integer ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + int r = n.intValue(); + if( r==n.doubleValue() ) + return r; + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Integer.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_SHORT = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Short ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + short r = n.shortValue(); + if( r==n.doubleValue() ) + return r; + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Short.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_BYTE = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof Byte ) + return obj; + if( obj instanceof Number ) { + Number n = (Number)obj; + byte r = n.byteValue(); + if( r==n.doubleValue() ) + return r; + } + else if( obj instanceof String ) { + String s = (String)obj; + try { + return Byte.valueOf(s); + } catch(NumberFormatException e) {} + } + return obj; + } + }; + + private static final ArgConverter ARG_TABLE = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof List ) { + @SuppressWarnings("unchecked") + List<Object> list = (List<Object>)obj; + return new LuaTable(list); + } + if( obj instanceof Map ) { + @SuppressWarnings("unchecked") + Map<Object,Object> map = (Map<Object,Object>)obj; + return new LuaTable(map); + } + if( obj instanceof Set ) { + @SuppressWarnings("unchecked") + Set<Object> set = (Set<Object>)obj; + return new LuaTable(set); + } + return obj; + } + }; + + private static final ArgConverter ARG_MAP = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaTable ) { + LuaTable t = (LuaTable)obj; + return t.asMap(); + } + return obj; + } + }; + + private static final ArgConverter ARG_LIST = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaTable ) { + LuaTable t = (LuaTable)obj; + if( t.isList() ) + return t.asList(); + } + return obj; + } + }; + + private static final ArgConverter ARG_SET = new ArgConverter() { + public Object convert(Object obj) { + if( obj instanceof LuaTable ) { + LuaTable t = (LuaTable)obj; + if( t.isSet() ) + return t.asSet(); + } + return obj; + } + }; + private static boolean takesLuaState(JavaMethod m) { Class<?>[] paramTypes = m.getParameterTypes(); return paramTypes.length > 0 && paramTypes[0].equals(LuaState.class); @@ -170,6 +384,26 @@ } private static ArgConverter getArgConverter(Class<?> cls) { + if( cls == Double.TYPE || cls.equals(Double.class) ) + return ARG_DOUBLE; + if( cls == Float.TYPE || cls.equals(Float.class) ) + return ARG_FLOAT; + if( cls == Long.TYPE || cls.equals(Long.class) ) + return ARG_LONG; + if( cls == Integer.TYPE || cls.equals(Integer.class) ) + return ARG_INTEGER; + if( cls == Short.TYPE || cls.equals(Short.class) ) + return ARG_SHORT; + if( cls == Byte.TYPE || cls.equals(Byte.class) ) + return ARG_BYTE; + if( cls.equals(LuaTable.class) ) + return ARG_TABLE; + if( cls.equals(Map.class) ) + return ARG_MAP; + if( cls.equals(List.class) ) + return ARG_LIST; + if( cls.equals(Set.class) ) + return ARG_SET; return ARG_SAME; }
--- a/src/luan/LuaTable.java Thu Dec 27 01:48:36 2012 +0000 +++ b/src/luan/LuaTable.java Thu Dec 27 04:36:44 2012 +0000 @@ -8,6 +8,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; +import java.util.Set; +import java.util.HashSet; public class LuaTable { @@ -21,8 +23,97 @@ this.list = list; } + public LuaTable(Map<Object,Object> map) { + this.map = map; + } + + public LuaTable(Set<Object> set) { + map = new HashMap<Object,Object>(); + for( Object obj : set ) { + map.put(obj,Boolean.TRUE); + } + } + + boolean isList() { + return map==null || map.isEmpty(); + } + + List<Object> asList() { + return list!=null ? list : Collections.emptyList(); + } + + Map<Object,Object> asMap() { + if( list == null || list.isEmpty() ) + return map!=null ? map : Collections.emptyMap(); + Map<Object,Object> rtn = map!=null ? new HashMap<Object,Object>(map) : new HashMap<Object,Object>(); + for( ListIterator iter = list.listIterator(); iter.hasNext(); ) { + int i = iter.nextIndex(); + rtn.put(i+1,iter.next()); + } + return rtn; + } + + boolean isSet() { + if( list != null ) { + for( Object obj : list ) { + if( obj!=null && !obj.equals(Boolean.TRUE) ) + return false; + } + } + if( map != null ) { + for( Object obj : map.values() ) { + if( !obj.equals(Boolean.TRUE) ) + return false; + } + } + return true; + } + + Set<Object> asSet() { + if( list == null || list.isEmpty() ) + return map!=null ? map.keySet() : Collections.emptySet(); + Set<Object> rtn = map!=null ? new HashSet<Object>(map.keySet()) : new HashSet<Object>(); + for( int i=1; i<=list.size(); i++ ) { + rtn.add(i); + } + return rtn; + } + @Override public String toString() { - return "table: " + Integer.toHexString(hashCode()); +// return "table: " + Integer.toHexString(hashCode()); + StringBuilder sb = new StringBuilder(); + sb.append('{'); + boolean isFirst = true; + if( list != null ) { + boolean gotNull = false; + for( int i=0; i<list.size(); i++ ) { + Object obj = list.get(i); + if( obj==null ) { + gotNull = true; + } else { + if( isFirst ) { + isFirst = false; + } else { + sb.append(", "); + } + if( gotNull ) + sb.append(i+1).append('='); + sb.append(obj); + } + } + } + if( map != null ) { + for( Map.Entry<Object,Object> entry : map.entrySet() ) { + if( isFirst ) { + isFirst = false; + } else { + sb.append(", "); + } + sb.append(entry.getKey()).append('=').append(entry.getValue()); + } + } + sb.append('}'); + return sb.toString(); } public Object get(Object key) { @@ -43,20 +134,11 @@ Integer iT = Lua.asInteger(key); if( iT != null ) { int i = iT - 1; - if( list == null && i == 0 ) - list = new ArrayList<Object>(); - if( list != null ) { - if( i == list.size() ) { + if( list != null || i == 0 ) { + if( i == list().size() ) { if( val != null ) { list.add(val); - if( map != null ) { - while(true) { - Object v = map.remove(Double.valueOf(list.size()+1)); - if( v == null ) - break; - list.add(v); - } - } + mapToList(); } return null; } else if( i>=0 && i<list.size() ) { @@ -85,21 +167,35 @@ } } + private void mapToList() { + if( map != null ) { + while(true) { + Object v = map.remove(Double.valueOf(list.size()+1)); + if( v == null ) + break; + list.add(v); + } + } + } + + private List<Object> list() { + if( list == null ) { + list = new ArrayList<Object>(); + mapToList(); + } + return list; + } + public void insert(int pos,Object value) { - if( list == null ) - list = new ArrayList<Object>(); - list.add(pos-1,value); + list().add(pos-1,value); } public Object remove(int pos) { - if( list == null ) - list = new ArrayList<Object>(); - return list.remove(pos-1); + return list().remove(pos-1); } public void sort(Comparator<Object> cmp) { - if( list != null ) - Collections.sort(list,cmp); + Collections.sort(list(),cmp); } public int length() { @@ -158,9 +254,7 @@ } public LuaTable subList(int from,int to) { - if( list == null ) - list = new ArrayList<Object>(); - return new LuaTable(new ArrayList<Object>(list.subList(from-1,to-1))); + return new LuaTable(new ArrayList<Object>(list().subList(from-1,to-1))); } public LuaTable getMetatable() {