Skip to content
Permalink
 
 
Cannot retrieve contributors at this time
package se.krka.kahlua.vm;
import java.io.IOException;
import java.io.InputStream;
public class KahluaUtil {
/** @exclude */
private static final Object WORKER_THREAD_KEY = new Object();
/** @exclude */
private static final String TYPE_NIL = "nil";
/** @exclude */
private static final String TYPE_STRING = "string";
/** @exclude */
private static final String TYPE_NUMBER = "number";
/** @exclude */
private static final String TYPE_BOOLEAN = "boolean";
/** @exclude */
private static final String TYPE_FUNCTION = "function";
/** @exclude */
private static final String TYPE_TABLE = "table";
/** @exclude */
private static final String TYPE_COROUTINE = "coroutine";
/** @exclude */
private static final String TYPE_USERDATA = "userdata";
public static double fromDouble(Object o) {
return ((Double) o).doubleValue();
}
public static Double toDouble(double d) {
return new Double(d);
}
public static Double toDouble(long d) {
return toDouble((double) d);
}
public static Boolean toBoolean(boolean b) {
return b ? Boolean.TRUE : Boolean.FALSE;
}
public static boolean boolEval(Object o) {
return (o != null) && (o != Boolean.FALSE);
}
public static LuaClosure loadByteCodeFromResource(String name, KahluaTable environment) {
InputStream stream = environment.getClass().getResourceAsStream(name + ".lbc");
if (stream == null) {
return null;
}
try {
return Prototype.loadByteCode(stream, environment);
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
public static void luaAssert(boolean b, String msg) {
if (!b) {
fail(msg);
}
}
public static void fail(String msg) {
throw new RuntimeException(msg);
}
/**
* Rounds towards even numbers
* @param x
*/
public static double round(double x) {
if (x < 0) {
return -round(-x);
}
x += 0.5;
double x2 = Math.floor(x);
if (x2 == x) {
return x2 - ((long) x2 & 1);
}
return x2;
}
/* Thanks rici lake for ipow-implementation */
/**
* Calculates base^exponent, for non-negative exponents.
* 0^0 is defined to be 1
* @return 1 if exponent is zero or negative
*/
public static long ipow(long base, int exponent) {
if (exponent <= 0) {
return 1;
}
long b = 1;
for (b = (exponent & 1) != 0 ? base : 1, exponent >>= 1; exponent != 0; exponent >>= 1) {
base *= base;
if ((exponent & 1) != 0) {
b *= base;
}
}
return b;
}
public static boolean isNegative(double vDouble) {
return Double.doubleToLongBits(vDouble) < 0;
}
public static KahluaTable getClassMetatables(Platform platform, KahluaTable env) {
return getOrCreateTable(platform, env, "__classmetatables");
}
public static KahluaThread getWorkerThread(Platform platform, KahluaTable env) {
Object workerThread = env.rawget(WORKER_THREAD_KEY);
if (workerThread == null) {
workerThread = new KahluaThread(platform, env);
env.rawset(WORKER_THREAD_KEY, workerThread);
}
return (KahluaThread) workerThread;
}
public static void setWorkerThread(KahluaTable env, KahluaThread thread) {
env.rawset(WORKER_THREAD_KEY, thread);
}
public static KahluaTable getOrCreateTable(Platform platform, KahluaTable env, String name) {
Object t = env.rawget(name);
if (t == null || !(t instanceof KahluaTable)) {
t = platform.newTable();
env.rawset(name, t);
}
return (KahluaTable) t;
}
public static void setupLibrary(KahluaTable env, KahluaThread workerThread, String library) {
LuaClosure closure = loadByteCodeFromResource(library, env);
if (closure == null) {
fail("Could not load " + library + ".lbc");
}
workerThread.call(closure, null, null, null);
}
public static String numberToString(Double num) {
if (num.isNaN()) {
return "nan";
}
if (num.isInfinite()) {
if (isNegative(num.doubleValue())) {
return "-inf";
}
return "inf";
}
double n = num.doubleValue();
if (Math.floor(n) == n && Math.abs(n) < 1e14) {
return String.valueOf(num.longValue());
}
return num.toString();
}
public static String type(Object o) {
if (o == null) {
return TYPE_NIL;
}
if (o instanceof String) {
return TYPE_STRING;
}
if (o instanceof Double) {
return TYPE_NUMBER;
}
if (o instanceof Boolean) {
return TYPE_BOOLEAN;
}
if (o instanceof JavaFunction || o instanceof LuaClosure) {
return TYPE_FUNCTION;
}
if (o instanceof KahluaTable) {
return TYPE_TABLE;
}
if (o instanceof Coroutine) {
return TYPE_COROUTINE;
}
return TYPE_USERDATA;
}
public static String tostring(Object o, KahluaThread thread) {
if (o == null) {
return TYPE_NIL;
}
if (o instanceof String) {
return (String) o;
}
if (o instanceof Double) {
return rawTostring(o);
}
if (o instanceof Boolean) {
return o == Boolean.TRUE ? "true" : "false";
}
if (o instanceof LuaClosure) {
return "closure 0x" + System.identityHashCode(o);
}
if (o instanceof JavaFunction) {
return "function 0x" + System.identityHashCode(o);
}
if (thread != null) {
Object tostringFun = thread.getMetaOp(o, "__tostring");
if (tostringFun != null) {
String res = (String) thread.call(tostringFun, o, null, null);
return res;
}
}
return o.toString();
}
public static Double tonumber(String s) {
return tonumber(s, 10);
}
public static Double tonumber(String s, int radix) {
if (radix < 2 || radix > 36) {
throw new RuntimeException("base out of range");
}
try {
if (radix == 10) {
return Double.valueOf(s);
} else {
return toDouble(Integer.parseInt(s, radix));
}
} catch (NumberFormatException e) {
s = s.toLowerCase();
if (s.endsWith("nan")) {
return toDouble(Double.NaN);
}
if (s.endsWith("inf")) {
if (s.charAt(0) == '-') {
return toDouble(Double.NEGATIVE_INFINITY);
}
return toDouble(Double.POSITIVE_INFINITY);
}
return null;
}
}
public static String rawTostring(Object o) {
if (o instanceof String) {
return (String) o;
}
if (o instanceof Double) {
return numberToString((Double) o);
}
return null;
}
public static Double rawTonumber(Object o) {
if (o instanceof Double) {
return (Double) o;
}
if (o instanceof String) {
return tonumber((String) o);
}
return null;
}
public static String getStringArg(LuaCallFrame callFrame, int n, String function) {
Object o = getArg(callFrame, n, function);
String res = rawTostring(o);
if (res == null) {
fail(n, function, "string", type(res));
}
return res;
}
public static String getOptionalStringArg(LuaCallFrame callFrame, int n) {
Object o = getOptionalArg(callFrame, n);
return rawTostring(o);
}
public static Double getNumberArg(LuaCallFrame callFrame, int n, String function) {
Object o = getArg(callFrame, n, function);
Double res = rawTonumber(o);
if (res == null) {
fail(n, function, "double", type(res));
}
return res;
}
public static Double getOptionalNumberArg(LuaCallFrame callFrame, int n) {
Object o = getOptionalArg(callFrame, n);
return rawTonumber(o);
}
private static void fail(int n, String function, String wantedType, String gotten) {
throw new RuntimeException("bad argument #" + n + " to '" + function +
"' (" + wantedType + " expected, got " + gotten + ")");
}
public static void assertArgNotNull(Object o, int n, String type, String function) {
if (o == null) {
fail(n, function, type, "null");
}
}
public static Object getOptionalArg(LuaCallFrame callFrame, int n) {
int top = callFrame.getTop();
int index = n - 1;
if (index >= top) {
return null;
}
return callFrame.get(n - 1);
}
public static Object getArg(LuaCallFrame callFrame, int n, String function) {
Object res = getOptionalArg(callFrame, n);
if (res == null) {
throw new RuntimeException("missing argument #" + n + "to '" + function + "'");
}
return res;
}
public static int len(KahluaTable kahluaTable, int low, int high) {
while (low < high) {
int middle = (high + low + 1) >> 1;
Object value = kahluaTable.rawget(middle);
if (value == null) {
high = middle - 1;
} else {
low = middle;
}
}
while (kahluaTable.rawget(low + 1) != null) {
low++;
}
return low;
}
public static double getDoubleArg(LuaCallFrame callFrame, int i, String name) {
return getNumberArg(callFrame, i, name).doubleValue();
}
}