All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.luaj.vm2.lib.jse.CoerceLuaToJava Maven / Gradle / Ivy

There is a newer version: 3.0.1
Show newest version
/*******************************************************************************
* Copyright (c) 2009-2011 Luaj.org. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
* 
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
******************************************************************************/
package org.luaj.vm2.lib.jse;

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import org.luaj.vm2.LuaError;
import org.luaj.vm2.LuaString;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.Varargs;

/**
 * Helper class to coerce values from lua to Java within the luajava library. 
 * 

* This class is primarily used by the {@link LuajavaLib}, * but can also be used directly when working with Java/lua bindings. *

* To coerce to specific Java values, generally the {@code toType()} methods * on {@link LuaValue} may be used: *

    *
  • {@link LuaValue#toboolean()}
  • *
  • {@link LuaValue#tobyte()}
  • *
  • {@link LuaValue#tochar()}
  • *
  • {@link LuaValue#toshort()}
  • *
  • {@link LuaValue#toint()}
  • *
  • {@link LuaValue#tofloat()}
  • *
  • {@link LuaValue#todouble()}
  • *
  • {@link LuaValue#tojstring()}
  • *
  • {@link LuaValue#touserdata()}
  • *
  • {@link LuaValue#touserdata(Class)}
  • *
*

* For data in lua tables, the various methods on {@link LuaTable} can be used directly * to convert data to something more useful. * * @see LuajavaLib * @see CoerceJavaToLua */ public class CoerceLuaToJava { static int SCORE_NULL_VALUE = 0x10; static int SCORE_WRONG_TYPE = 0x100; static int SCORE_UNCOERCIBLE = 0x10000; static interface Coercion { public int score( LuaValue value ); public Object coerce( LuaValue value ); }; /** * Coerce a LuaValue value to a specified java class * @param value LuaValue to coerce * @param clazz Class to coerce into * @return Object of type clazz (or a subclass) with the corresponding value. */ public static Object coerce(LuaValue value, Class clazz) { return getCoercion(clazz).coerce(value); } static final Map COERCIONS = Collections.synchronizedMap(new HashMap()); static final class BoolCoercion implements Coercion { public String toString() { return "BoolCoercion()"; } public int score( LuaValue value ) { switch ( value.type() ) { case LuaValue.TBOOLEAN: return 0; } return 1; } public Object coerce(LuaValue value) { return value.toboolean()? Boolean.TRUE: Boolean.FALSE; } } static final class NumericCoercion implements Coercion { static final int TARGET_TYPE_BYTE = 0; static final int TARGET_TYPE_CHAR = 1; static final int TARGET_TYPE_SHORT = 2; static final int TARGET_TYPE_INT = 3; static final int TARGET_TYPE_LONG = 4; static final int TARGET_TYPE_FLOAT = 5; static final int TARGET_TYPE_DOUBLE = 6; static final String[] TYPE_NAMES = { "byte", "char", "short", "int", "long", "float", "double" }; final int targetType; public String toString() { return "NumericCoercion("+TYPE_NAMES[targetType]+")"; } NumericCoercion(int targetType) { this.targetType = targetType; } public int score( LuaValue value ) { int fromStringPenalty = 0; if ( value.type() == LuaValue.TSTRING ) { value = value.tonumber(); if ( value.isnil() ) { return SCORE_UNCOERCIBLE; } fromStringPenalty = 4; } if ( value.isint() ) { switch ( targetType ) { case TARGET_TYPE_BYTE: { int i = value.toint(); return fromStringPenalty + ((i==(byte)i)? 0: SCORE_WRONG_TYPE); } case TARGET_TYPE_CHAR: { int i = value.toint(); return fromStringPenalty + ((i==(byte)i)? 1: (i==(char)i)? 0: SCORE_WRONG_TYPE); } case TARGET_TYPE_SHORT: { int i = value.toint(); return fromStringPenalty + ((i==(byte)i)? 1: (i==(short)i)? 0: SCORE_WRONG_TYPE); } case TARGET_TYPE_INT: { int i = value.toint(); return fromStringPenalty + ((i==(byte)i)? 2: ((i==(char)i) || (i==(short)i))? 1: 0); } case TARGET_TYPE_FLOAT: return fromStringPenalty + 1; case TARGET_TYPE_LONG: return fromStringPenalty + 1; case TARGET_TYPE_DOUBLE: return fromStringPenalty + 2; default: return SCORE_WRONG_TYPE; } } else if ( value.isnumber() ) { switch ( targetType ) { case TARGET_TYPE_BYTE: return SCORE_WRONG_TYPE; case TARGET_TYPE_CHAR: return SCORE_WRONG_TYPE; case TARGET_TYPE_SHORT: return SCORE_WRONG_TYPE; case TARGET_TYPE_INT: return SCORE_WRONG_TYPE; case TARGET_TYPE_LONG: { double d = value.todouble(); return fromStringPenalty + ((d==(long)d)? 0: SCORE_WRONG_TYPE); } case TARGET_TYPE_FLOAT: { double d = value.todouble(); return fromStringPenalty + ((d==(float)d)? 0: SCORE_WRONG_TYPE); } case TARGET_TYPE_DOUBLE: { double d = value.todouble(); return fromStringPenalty + (((d==(long)d) || (d==(float)d))? 1: 0); } default: return SCORE_WRONG_TYPE; } } else { return SCORE_UNCOERCIBLE; } } public Object coerce(LuaValue value) { switch ( targetType ) { case TARGET_TYPE_BYTE: return new Byte( (byte) value.toint() ); case TARGET_TYPE_CHAR: return new Character( (char) value.toint() ); case TARGET_TYPE_SHORT: return new Short( (short) value.toint() ); case TARGET_TYPE_INT: return new Integer( (int) value.toint() ); case TARGET_TYPE_LONG: return new Long( (long) value.todouble() ); case TARGET_TYPE_FLOAT: return new Float( (float) value.todouble() ); case TARGET_TYPE_DOUBLE: return new Double( (double) value.todouble() ); default: return null; } } } static final class StringCoercion implements Coercion { public static final int TARGET_TYPE_STRING = 0; public static final int TARGET_TYPE_BYTES = 1; final int targetType; public StringCoercion(int targetType) { this.targetType = targetType; } public String toString() { return "StringCoercion("+(targetType==TARGET_TYPE_STRING? "String": "byte[]")+")"; } public int score(LuaValue value) { switch ( value.type() ) { case LuaValue.TSTRING: return value.checkstring().isValidUtf8()? (targetType==TARGET_TYPE_STRING? 0: 1): (targetType==TARGET_TYPE_BYTES? 0: SCORE_WRONG_TYPE); case LuaValue.TNIL: return SCORE_NULL_VALUE; default: return targetType == TARGET_TYPE_STRING? SCORE_WRONG_TYPE: SCORE_UNCOERCIBLE; } } public Object coerce(LuaValue value) { if ( value.isnil() ) return null; if ( targetType == TARGET_TYPE_STRING ) return value.tojstring(); LuaString s = value.checkstring(); byte[] b = new byte[s.m_length]; s.copyInto(0, b, 0, b.length); return b; } } static final class ArrayCoercion implements Coercion { final Class componentType; final Coercion componentCoercion; public ArrayCoercion(Class componentType) { this.componentType = componentType; this.componentCoercion = getCoercion(componentType); } public String toString() { return "ArrayCoercion("+componentType.getName()+")"; } public int score(LuaValue value) { switch ( value.type() ) { case LuaValue.TTABLE: return value.length()==0? 0: componentCoercion.score( value.get(1) ); case LuaValue.TUSERDATA: return inheritanceLevels( componentType, value.touserdata().getClass().getComponentType() ); case LuaValue.TNIL: return SCORE_NULL_VALUE; default: return SCORE_UNCOERCIBLE; } } public Object coerce(LuaValue value) { switch ( value.type() ) { case LuaValue.TTABLE: { int n = value.length(); Object a = Array.newInstance(componentType, n); for ( int i=0; i





© 2015 - 2024 Weber Informatics LLC | Privacy Policy