/* * This file is a part of Alchemy OS project. * Copyright (C) 2011-2014, Sergey Basalaev <sbasalaev@gmail.com> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package alchemy.system; import alchemy.io.UTFReader; import alchemy.types.Float32; import alchemy.types.Float64; import alchemy.types.Int32; import alchemy.types.Int64; import java.io.IOException; /** * Library implemented as Java code. * Function names for native library should be provided * in a resource file available on classpath. These names * are loaded using {@link #load(String) load} method. * The order of names implies indexation of functions starting * with zero. The invokeNative method should be implemented using * switch on index: * <pre> * protected Object invokeNative(int index, Context c, Object[] args) throws Exception { * switch (index) { * case 0: { * // implement function with index 0 * } * case 1: { * // implement function with index 1 * } * ... * default: * return null * } * } * </pre> * Native libraries are loaded through the reflection * (using Class.forName()) so they must have public * constructor with no arguments. * * @author Sergey Basalaev */ public abstract class NativeLibrary extends Library { protected NativeLibrary() { } /** Loads native function names from named resource. */ public final void load(String symbols) throws IOException { UTFReader r = new UTFReader(getClass().getResourceAsStream(symbols)); int index = size(); String funcname; while ((funcname = r.readLine()) != null) { if (funcname.length() > 0) { putFunction(new NativeFunction(this, funcname, index)); index++; } } r.close(); } /** Invokes native function. */ protected abstract Object invokeNative(int index, Process p, Object[] args) throws Exception; /** Boxing method for integer values. */ protected static Int32 Ival(int value) { return Int32.toInt32(value); } /** Boxing method for boolean values. * Method converts <code>true</code> to <code>Int(1)</code> * and <code>false</code> to <code>Int(0)</code>. */ protected static Int32 Ival(boolean value) { return value ? Int32.ONE : Int32.ZERO; } /** Boxing method for long values. */ protected static Int64 Lval(long value) { return new Int64(value); } /** Boxing method for float values. */ protected static Float32 Fval(float value) { return new Float32(value); } /** Boxing method for double values. */ protected static Float64 Dval(double value) { return new Float64(value); } /** Unboxing method for Int values. */ protected static int ival(Object obj) { return ((Int32)obj).value; } /** Unboxing method for Int values. * Method returns <code>false</code> iff <code>obj</code> * is <code>Int(0)</code>. */ protected static boolean bval(Object obj) { return obj != Int32.ZERO; } /** Unboxing method for Long values. */ protected static long lval(Object obj) { return ((Int64)obj).value; } /** Unboxing method for Float values. */ protected static float fval(Object obj) { return ((Float32)obj).value; } /** Unboxing method for Double values. */ protected static double dval(Object obj) { return ((Float64)obj).value; } }