pax_global_header00006660000000000000000000000064120174754360014523gustar00rootroot0000000000000052 comment=b70b5d8319d841c941baff9422153584171a2808 jaffl-0.5.9/000077500000000000000000000000001201747543600126205ustar00rootroot00000000000000jaffl-0.5.9/.gitignore000066400000000000000000000001421201747543600146050ustar00rootroot00000000000000*.orig$ *.rej$ *.class$ *~ nbproject/private build dist target lib/nblibraries-private.properties jaffl-0.5.9/.hgignore000066400000000000000000000001741201747543600144250ustar00rootroot00000000000000\.orig$ \.orig\..*$ \.chg\..*$ \.rej$ \.conflict\~$ ^target/.*$ ^build/.*$ ^nbproject/private/.*$ ^lib/.*private.* ^dist/.* jaffl-0.5.9/LICENSE000066400000000000000000000022531201747543600136270ustar00rootroot00000000000000 Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Alternatively, you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This code 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 Lesser General Public License version 3 for more details. You should have received a copy of the GNU Lesser General Public License version 3 along with this work. If not, see . jaffl-0.5.9/build.xml000066400000000000000000000140401201747543600144400ustar00rootroot00000000000000 Builds, tests, and runs the project jaffl. jaffl-0.5.9/lib/000077500000000000000000000000001201747543600133665ustar00rootroot00000000000000jaffl-0.5.9/lib/nblibraries.properties000066400000000000000000000004251201747543600200010ustar00rootroot00000000000000libs.junit.classpath=\ ${base}/junit/junit-3.8.2.jar libs.junit.javadoc=\ ${base}/junit/junit-3.8.2-api.zip libs.junit_4.classpath=\ ${base}/junit_4/junit-4.1.jar libs.CopyLibs.classpath=\ ${base}/CopyLibs/org-netbeans-modules-java-j2seproject-copylibstask.jar jaffl-0.5.9/libtest/000077500000000000000000000000001201747543600142665ustar00rootroot00000000000000jaffl-0.5.9/libtest/Benchmark.c000066400000000000000000000002201201747543600163160ustar00rootroot00000000000000 void returnVoid() { } void returnVoidI(int arg) { } int returnInt() { return 0; } int returnIntI(int arg) { return arg; } jaffl-0.5.9/libtest/BufferTest.c000066400000000000000000000012271201747543600165050ustar00rootroot00000000000000 #define MEMSET(buf, value, size) do { \ int i; for (i = 0; i < size; ++i) buf[i] = value; \ } while(0) #define MEMCPY(dst, src, size) do { \ int i; for (i = 0; i < size; ++i) dst[i] = src[i]; \ } while(0) #define FILL(JTYPE, CTYPE) \ void fill##JTYPE##Buffer(CTYPE* buf, CTYPE value, int size) { MEMSET(buf, value, size); } #define COPY(JTYPE, CTYPE) \ void copy##JTYPE##Buffer(CTYPE* dst, CTYPE* src, int size) { MEMCPY(dst, src, size); } #define FUNC(JTYPE, CTYPE) \ FILL(JTYPE, CTYPE); \ COPY(JTYPE, CTYPE) FUNC(Byte, char); FUNC(Short, short); FUNC(Int, int); FUNC(Long, long long); FUNC(Float, float); FUNC(Double, double); jaffl-0.5.9/libtest/ClosureTest.c000066400000000000000000000041341201747543600167100ustar00rootroot00000000000000 void testClosureVrV(void (*closure)(void)) { (*closure)(); } char testClosureVrB(char (*closure)(void)) { return (*closure)(); } short testClosureVrS(short (*closure)(void)) { return (*closure)(); } int testClosureVrI(int (*closure)(void)) { return (*closure)(); } long long testClosureVrL(long long (*closure)(void)) { return (*closure)(); } float testClosureVrF(float (*closure)(void)) { return (*closure)(); } double testClosureVrD(double (*closure)(void)) { return (*closure)(); } void testClosureBrV(void (*closure)(char), char a1) { (*closure)(a1); } void testClosureSrV(void (*closure)(short), short a1) { (*closure)(a1); } void testClosureIrV(void (*closure)(int), int a1) { (*closure)(a1); } void testClosureLrV(void (*closure)(long long), long long a1) { (*closure)(a1); } void testClosureFrV(void (*closure)(float), float a1) { (*closure)(a1); } void testClosureDrV(void (*closure)(double), double a1) { (*closure)(a1); } // // These macros produce functions of the form: // testClosureBIrV(void (*closure)(char, int), char a1, int a2) {} // #define C2_(J1, J2, N1, N2) \ void testClosure##J1##J2##rV(void (*closure)(N1, N2), N1 a1, N2 a2) \ { \ (*closure)(a1, a2); \ } #define C2(J, N) \ C2_(B, J, char, N) \ C2_(S, J, short, N) \ C2_(I, J, int, N) \ C2_(L, J, long long, N) \ C2_(F, J, float, N) \ C2_(D, J, double, N) \ C2(B, char); C2(S, short); C2(I, int); C2(L, long long); C2(F, float); C2(D, double); #define C3_(J1, J2, J3, N1, N2, N3) \ void testClosure##J1##J2##J3##rV(void (*closure)(N1, N2, N3), N1 a1, N2 a2, N3 a3) \ { \ (*closure)(a1, a2, a3); \ } #define C3(J, N) \ C3_(B, J, B, char, N, char) \ C3_(S, J, S, short, N, short) \ C3_(I, J, I, int, N, int) \ C3_(L, J, L, long long, N, long long) \ C3_(F, J, F, float, N, float) \ C3_(D, J, D, double, N, double) \ C3(B, char); C3(S, short); C3(I, int); C3(L, long long); C3(F, float); C3(D, double); C3_(B, S, I, char, short, int); C3_(B, S, L, char, short, long long); C3_(L, S, B, long long, short, char); C3_(L, B, S, long long, char, short); jaffl-0.5.9/libtest/GNUmakefile000066400000000000000000000064141201747543600163450ustar00rootroot00000000000000# -*- makefile -*- BUILD_OS := $(strip $(shell uname -s | tr '[:upper:]' '[:lower:]')) OS ?= $(BUILD_OS) CPU = $(shell uname -m | sed -e 's/i[345678]86/i386/') MODEL = 32 # Default to 32bit compiles PLATFORM = $(CPU)-$(OS) ifeq ($(OS), sunos) OS = solaris endif # Default value of $OS on Windows is Windows_NT ifeq ($(OS), Windows_NT) # that's how we detect x64... ifneq ($(findstring 64, $(BUILD_OS)),) OS = win64 else OS = win32 endif endif SRC_DIR = libtest BUILD_DIR ?= build TEST_BUILD_DIR = $(BUILD_DIR)/libtest # Set defaults to unix (linux/solaris/bsd) PREFIX = lib LIBEXT = so LIBNAME = $(PREFIX)test.$(LIBEXT) export MACOSX_DEPLOYMENT_TARGET=10.5 ifeq ($(OS),linux) CCACHE := $(shell /usr/bin/which ccache) endif TEST_SRCS = $(wildcard $(SRC_DIR)/*.c) TEST_OBJS := $(patsubst $(SRC_DIR)/%.c, $(TEST_BUILD_DIR)/%.o, $(TEST_SRCS)) # # Compiler/linker flags from: # http://weblogs.java.net/blog/kellyohair/archive/2006/01/compilation_of_1.html JFLAGS = -fno-omit-frame-pointer -fno-strict-aliasing OFLAGS = -O2 $(JFLAGS) WFLAGS = -W -Werror -Wall -Wno-unused -Wno-parentheses PICFLAGS = -fPIC SOFLAGS = -shared -mimpure-text -Wl,-O1 LDFLAGS += $(SOFLAGS) IFLAGS = -I"$(BUILD_DIR)" CFLAGS = $(OFLAGS) $(WFLAGS) $(IFLAGS) $(PICFLAGS) -D_REENTRANT ifeq ($(OS), win32) CC += -mno-cygwin LDFLAGS += -mno-cygwin -Wl,--add-stdcall-alias PREFIX = LIBEXT = dll PICFLAGS = endif ifeq ($(OS),win64) CC += -mno-cygwin LDFLAGS += -mno-cygwin -Wl,--add-stdcall-alias PREFIX = LIBEXT = dll PICFLAGS = endif ifeq ($(OS), darwin) ARCHFLAGS = -arch ppc ifneq ($(findstring $(CPU), i386 x86_64),) ARCHFLAGS += -arch i386 -arch x86_64 endif MACSDK = /Developer/SDKs/MacOSX10.5.sdk CFLAGS += $(ARCHFLAGS) -isysroot $(MACSDK) -DTARGET_RT_MAC_CFM=0 CFLAGS += -fno-common LDFLAGS = $(ARCHFLAGS) -dynamiclib -Wl,-syslibroot,$(MACSDK) -mmacosx-version-min=10.5 # link against the universal libraries on ppc machines LDFLAGS += -L$(MACSDK)/usr/lib LIBEXT = dylib FFI_CFLAGS += -isysroot $(MACSDK) PICFLAGS = SOFLAGS = endif ifeq ($(OS), linux) SOFLAGS += -Wl,-soname,$(LIBNAME) endif ifeq ($(OS), solaris) CC = /usr/sfw/bin/gcc -std=c99 LD = /usr/ccs/bin/ld SOFLAGS = -shared -static-libgcc endif ifeq ($(OS), aix) LIBEXT = a SOFLAGS = -shared -static-libgcc PICFLAGS += -pthread endif ifneq ($(findstring cygwin, $(OS)),) CFLAGS += -mno-cygwin -mwin32 LIBEXT = dll # PREFIX = PICFLAGS= endif ifneq ($(findstring mingw, $(OS)),) LIBEXT = dll PICFLAGS= endif ifeq ($(CPU), sparcv9) MODEL = 64 endif ifeq ($(CPU), amd64) MODEL = 64 endif ifeq ($(CPU), x86_64) MODEL = 64 endif # On platforms (linux, solaris) that support both 32bit and 64bit, force building for one or the other ifneq ($(or $(findstring linux, $(OS)), $(findstring solaris, $(OS))),) # Change the CC/LD instead of CFLAGS/LDFLAGS, incase other things in the flags # makes the libffi build choke CC += -m$(MODEL) LD += -m$(MODEL) endif LIBTEST = $(BUILD_DIR)/$(LIBNAME) all: $(LIBTEST) $(TEST_BUILD_DIR)/%.o : $(SRC_DIR)/%.c @mkdir -p $(@D) $(CCACHE) $(CC) $(CFLAGS) -c $< -o $@ $(LIBTEST): $(TEST_OBJS) $(CC) -o $@ $(LDFLAGS) $(TEST_OBJS) -lm clean:: # nothing to do - ant will delete the build dir debug:: @echo "SRCS=$(TEST_SRCS)" jaffl-0.5.9/libtest/LastErrorTest.c000066400000000000000000000001271201747543600172070ustar00rootroot00000000000000 #include int setLastError(int error) { errno = error; return -1; } jaffl-0.5.9/libtest/NumberTest.c000066400000000000000000000010071201747543600165200ustar00rootroot00000000000000 #include #include #define ADD(T) T add_##T(T arg1, T arg2) { return arg1 + arg2; } #define SUB(T) T sub_##T(T arg1, T arg2) { return arg1 - arg2; } #define MUL(T) T mul_##T(T arg1, T arg2) { return arg1 * arg2; } #define DIV(T) T div_##T(T arg1, T arg2) { return arg1 / arg2; } #define RET(T) T ret_##T(T arg1) { return arg1; } typedef char* ptr; #define TEST(T) ADD(T) SUB(T) MUL(T) DIV(T) RET(T) TEST(int8_t); TEST(int16_t); TEST(int32_t); TEST(int64_t); TEST(float); TEST(double); TEST(long); jaffl-0.5.9/libtest/PointerTest.c000066400000000000000000000017371201747543600167220ustar00rootroot00000000000000 #include #include #include #include #include #include typedef void* ptr; typedef void* pointer; #ifdef _WIN32 typedef char* caddr_t; #endif #define RET(T) T ptr_ret_##T(void* arg1, int offset) { \ T tmp; memcpy(&tmp, (caddr_t) arg1 + offset, sizeof(tmp)); return tmp; \ } #define SET(T) void ptr_set_##T(void* arg1, int offset, T value) { \ memcpy((caddr_t) arg1 + offset, &value, sizeof(value)); \ } #define TEST(T) SET(T) RET(T) TEST(int8_t); TEST(int16_t); TEST(int32_t); TEST(int64_t); TEST(float); TEST(double); TEST(pointer); void* ptr_return_array_element(void **ptrArray, int arrayIndex) { return ptrArray[arrayIndex]; } void ptr_set_array_element(void **ptrArray, int arrayIndex, void *value) { ptrArray[arrayIndex] = value; } void* ptr_from_buffer(void* ptr) { return ptr; } void* ptr_malloc(int size) { return calloc(1, size); } void ptr_free(void* ptr) { free(ptr); } jaffl-0.5.9/libtest/ReferenceTest.c000066400000000000000000000010731201747543600171710ustar00rootroot00000000000000 #include #define REF(T) void ref_##T(T arg, T* result) { *result = arg; } #define ADD(T) void ref_add_##T(T arg1, T arg2, T* result) { *result = arg1 + arg2; } #define SUB(T) void ref_sub_##T(T arg1, T arg2, T* result) { *result = arg1 - arg2; } #define MUL(T) void ref_mul_##T(T arg1, T arg2, T* result) { *result = arg1 * arg2; } #define DIV(T) void ref_div_##T(T arg1, T arg2, T* result) { *result = arg1 / arg2; } #define TEST(T) ADD(T) SUB(T) MUL(T) DIV(T) REF(T) TEST(int8_t); TEST(int16_t); TEST(int32_t); TEST(int64_t); TEST(float); TEST(double); jaffl-0.5.9/libtest/StringTest.c000066400000000000000000000003721201747543600165420ustar00rootroot00000000000000 #include int string_equals(const char* s1, const char* s2) { return strcmp(s1, s2) == 0; } void string_set(char* s1, const char* s2) { strcpy(s1, s2); } void string_concat(char* dst, const char* src) { strcat(dst, src); } jaffl-0.5.9/libtest/StructTest.c000066400000000000000000000023211201747543600165540ustar00rootroot00000000000000 #include #include #include #include typedef char Signed8; typedef short Signed16; typedef int Signed32; typedef long long Signed64; typedef float Float32; typedef double Float64; typedef long SignedLong; struct test1 { char b; short s; int i; long long j; SignedLong l; float f; double d; char string[32]; }; #define T(x, type) \ type struct_field_##type(struct test1* t) { return t->x; } \ struct type##Align { char first; type value; }; \ type struct_align_##type(struct type##Align* a) { return a->value; } T(b, Signed8); T(s, Signed16); T(i, Signed32); T(j, Signed64); T(f, Float32); T(d, Float64); Signed64 struct_field_SignedLong(struct test1* t) { return t->l; } struct SignedLongAlign { char first; SignedLong value; }; Signed64 struct_align_SignedLong(struct SignedLongAlign* a) { return a->value; } void struct_set_string(struct test1* t, char* s) { strcpy(t->string, s); } struct test1* struct_make_struct(char b, short s, int i, long long ll, float f, double d) { static struct test1 t; memset(&t, 0, sizeof(t)); t.b = b; t.s = s; t.i = i; t.j = ll; t.f = f; t.d = d; return &t; } jaffl-0.5.9/nbproject/000077500000000000000000000000001201747543600146065ustar00rootroot00000000000000jaffl-0.5.9/nbproject/build-impl.xml000066400000000000000000001311311201747543600173660ustar00rootroot00000000000000 Must set src.dir Must set test.src.dir Must set build.dir Must set dist.dir Must set build.classes.dir Must set dist.javadoc.dir Must set build.test.classes.dir Must set build.test.results.dir Must set build.classes.excludes Must set dist.jar Must set javac.includes Must select some files in the IDE or set javac.includes To run this application from the command line without Ant, try: java -cp "${run.classpath.with.dist.jar}" ${main.class} To run this application from the command line without Ant, try: java -jar "${dist.jar.resolved}" Must select one file in the IDE or set run.class Must select one file in the IDE or set run.class Must select one file in the IDE or set debug.class Must select one file in the IDE or set debug.class Must set fix.includes Must select some files in the IDE or set javac.includes Some tests failed; see details above. Must select some files in the IDE or set test.includes Some tests failed; see details above. Must select one file in the IDE or set test.class Must select one file in the IDE or set applet.url Must select one file in the IDE or set applet.url jaffl-0.5.9/nbproject/genfiles.properties000066400000000000000000000011711201747543600205200ustar00rootroot00000000000000build.xml.data.CRC32=862bdb0a build.xml.script.CRC32=e8c19673 build.xml.stylesheet.CRC32=958a1d3e # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=00e566fd nbproject/build-impl.xml.script.CRC32=fe26ad8d nbproject/build-impl.xml.stylesheet.CRC32=576378a2@1.32.1.45 nbproject/profiler-build-impl.xml.data.CRC32=429aaa4a nbproject/profiler-build-impl.xml.script.CRC32=abda56ed nbproject/profiler-build-impl.xml.stylesheet.CRC32=42cb6bcf@1.6.1 jaffl-0.5.9/nbproject/project.properties000066400000000000000000000057211201747543600203770ustar00rootroot00000000000000application.title=jafl application.vendor=wayne build.classes.dir=${build.dir}/classes build.classes.excludes=**/*.java,**/*.form # This directory is removed when the project is cleaned: build.dir=build build.generated.dir=${build.dir}/generated build.generated.sources.dir=${build.dir}/generated-sources # Only compile against the classpath explicitly listed here: build.sysclasspath=ignore build.test.classes.dir=${build.dir}/test/classes build.test.results.dir=${build.dir}/test/results debug.classpath=\ ${run.classpath} debug.test.classpath=\ ${run.test.classpath} # This directory is removed when the project is cleaned: dist.dir=dist dist.jar=${dist.dir}/jaffl-0.5.jar dist.javadoc.dir=${dist.dir}/javadoc endorsed.classpath= excludes= file.reference.asm-3.2.jar=lib/asm-3.2.jar file.reference.asm-analysis-3.2.jar=lib/asm-analysis-3.2.jar file.reference.asm-commons-3.2.jar=lib/asm-commons-3.2.jar file.reference.asm-tree-3.2.jar=lib/asm-tree-3.2.jar file.reference.asm-util-3.2.jar=lib/asm-util-3.2.jar file.reference.asm-xml-3.2.jar=lib/asm-xml-3.2.jar file.reference.jffi-complete.jar-1=../jffi/dist/jffi-complete.jar includes=** jar.compress=true javac.classpath=\ ${file.reference.asm-3.2.jar}:\ ${reference.jffi.jar}:\ ${file.reference.asm-analysis-3.2.jar}:\ ${file.reference.asm-commons-3.2.jar}:\ ${file.reference.asm-tree-3.2.jar}:\ ${file.reference.asm-util-3.2.jar}:\ ${file.reference.asm-xml-3.2.jar}:\ ${reference.jnr-x86asm.jar} # Space-separated list of extra javac options javac.compilerargs= javac.deprecation=true javac.source=1.5 javac.target=1.5 javac.test.classpath=\ ${javac.classpath}:\ ${build.classes.dir}:\ ${libs.junit_4.classpath} javadoc.additionalparam= javadoc.author=false javadoc.encoding=${source.encoding} javadoc.noindex=false javadoc.nonavbar=false javadoc.notree=false javadoc.private=false javadoc.splitindex=true javadoc.use=true javadoc.version=false javadoc.windowtitle= jaxbwiz.endorsed.dirs="${netbeans.home}/../ide12/modules/ext/jaxb/api" jnlp.codebase.type=local jnlp.codebase.url=file:/home/wayne/src/jaffl/dist/ jnlp.descriptor=application jnlp.enabled=false jnlp.offline-allowed=false jnlp.signed=false main.class=com.kenai.jaffl.provider.ffi.AsmLibraryLoader meta.inf.dir=${src.dir}/META-INF platform.active=default_platform project.jffi=../jffi project.jnr-x86asm=../jnr-x86asm reference.jffi.jar=${project.jffi}/dist/jffi.jar reference.jnr-x86asm.jar=${project.jnr-x86asm}/dist/jnr-x86asm.jar run.classpath=\ ${javac.classpath}:\ ${build.classes.dir} # Space-separated list of JVM arguments used when running the project # (you may also define separate properties like run-sys-prop.name=value instead of -Dname=value # or test-sys-prop.name=value to set system properties for unit tests): run.jvmargs=-Djffi.library.path=build run.test.classpath=\ ${javac.test.classpath}:\ ${build.test.classes.dir}:\ ${file.reference.jffi-complete.jar-1} source.encoding=UTF-8 src.dir=src test.src.dir=test jaffl-0.5.9/nbproject/project.xml000066400000000000000000000027001201747543600167750ustar00rootroot00000000000000 org.netbeans.modules.java.j2seproject jaffl-0.5 1.6.5 ./lib/nblibraries.properties jffi jar jar clean jar jnr-x86asm jar jar clean jar jaffl-0.5.9/pom.xml000066400000000000000000000123221201747543600141350ustar00rootroot00000000000000 4.0.0 org.jruby.extras jaffl jar 0.5.9 jaffl An abstracted interface to invoking native functions from java http://github.com/wmeissner/jaffl The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt repo scm:git:http://github.com/wmeissner/jaffl.git http://github.com/wmeissner/jaffl codehaus-jruby-repository JRuby Central Repository dav:https://dav.codehaus.org/repository/jruby codehaus-jruby-snapshot-repository JRuby Central Development Repository dav:https://dav.codehaus.org/snapshots.repository/jruby maven2-repository.dev.java.net Java.net Repository for Maven http://download.java.net/maven/2/ codehaus Codehaus Repository true true http://repository.codehaus.org maven2-repository.dev.java.net Java.net Repository for Maven http://download.java.net/maven/2/ wmeissner Wayne Meissner wmeissner@gmail.com true junit junit 4.5 test org.jruby.extras jffi 1.0.6 compile org.jruby.extras jffi 1.0.6 runtime native asm asm 3.2 compile asm asm-commons 3.2 compile org.jruby.extras jnr-x86asm 1.0.0 compile src test org.apache.maven.plugins maven-compiler-plugin 2.0.2 1.5 1.5 maven-antrun-plugin 1.1 test-compile run org.apache.maven.plugins maven-surefire-plugin 2.4.2 jna.library.path ${build.directory} org.jvnet.wagon-svn wagon-svn 1.8 org.apache.maven.wagon wagon-webdav build/report jaffl-0.5.9/src/000077500000000000000000000000001201747543600134075ustar00rootroot00000000000000jaffl-0.5.9/src/com/000077500000000000000000000000001201747543600141655ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/000077500000000000000000000000001201747543600152545ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/000077500000000000000000000000001201747543600163365ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/Address.java000066400000000000000000000071241201747543600205720ustar00rootroot00000000000000 package com.kenai.jaffl; /** * Represents a native memory address. */ public class Address extends Number implements Comparable
{ public static final int SIZE = Platform.getPlatform().addressSize(); public static final int SHIFT = SIZE == 32 ? 2 : 3; public static final long MASK = SIZE == 32 ? 0xffffffffL : 0xffffffffffffffffL; protected final long address; public static final Address valueOf(long address) { return new Address(address); } /** * Creates a new address representation. * * @param address the native address. */ public Address(long address) { this.address = address & MASK; } /** * Creates a new address representation. * * @param address the native address. */ public Address(final Address address) { this.address = address.address; } /** * Returns an integer representation of this address. * * @return an integer value for this address. */ @Override public final int intValue() { return (int) address; } /** * Returns an {@code long} representation of this address. * * @return an {@code long} value for this address. */ @Override public final long longValue() { return address; } /** * Returns an {@code float} representation of this address. * * @return an {@code float} value for this address. */ @Override public final float floatValue() { return (float) address; } /** * Returns an {@code double} representation of this address. * * @return an {@code double} value for this address. */ @Override public final double doubleValue() { return (double) address; } /** * Returns the native value of this address. * * @return an {@code long} value representing the native value of this address. */ public final long nativeAddress() { return address; } /** * Gets a hash code for this {@code Address}. * * @return a hash code for this {@code Address}. */ @Override public final int hashCode() { return (int)(address ^ (address >>> 32)); } /** * Compares this address to another address. * * @param obj the other address to compare to. * @return {@code true} if this Address is equal to the other address, else false. */ @Override public final boolean equals(Object obj) { return ((obj instanceof Address) && address == ((Address) obj).address) || (obj == null && address == 0); } /** * Returns a string representation of this Address. * * @return a string representation of this Address. */ @Override public String toString() { return getClass().getName() + String.format("[address=%x]", address); } /** * Compares two {@code Address} instances numerically. * * @param other the other Address to compare to. * @return {@code 0} if {@code other} is equal to this instance, -1 if this * instance is numerically less than {@code other} or 1 if this instance is * numerically greater than {@code other}. */ public final int compareTo(Address other) { return address < other.address ? -1 : address > other.address ? 1 : 0; } /** * Tests if this Address is equivalent to C NULL * * @return true if the address is 0 */ public final boolean isNull() { return address == 0; } } jaffl-0.5.9/src/com/kenai/jaffl/CallingConvention.java000066400000000000000000000003761201747543600226230ustar00rootroot00000000000000 package com.kenai.jaffl; /** * Defines the function calling conventions. */ public enum CallingConvention { /** * The default C calling convention */ DEFAULT, /** * Windows stdcall calling convention */ STDCALL; } jaffl-0.5.9/src/com/kenai/jaffl/FFIProvider.java000066400000000000000000000062221201747543600213220ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.provider.MemoryManager; import com.kenai.jaffl.provider.NativeType; import java.util.Map; /** * This class defines the facilities a jaffl FFI provider must provide. */ public abstract class FFIProvider { /** * Gets an instance of FFIProvider * * @return an instance of FFIProvider */ public static final FFIProvider getProvider() { return SingletonHolder.INSTANCE; } /** * Gets the native memory manager for this provider. * * @return a {@link MemoryManager} */ public abstract MemoryManager getMemoryManager(); /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param libraryName the name of the library to load * @param interfaceClass the interface that describes the native library interface * @param libraryOptions options * @return an instance of {@code interfaceclass} that will call the native methods. */ public abstract T loadLibrary(String libraryName, Class interfaceClass, Map libraryOptions); /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param interfaceClass the interface that describes the native library interface * @param libraryOptions options * @param libraryNames the list of libraries to load * @return an instance of {@code interfaceclass} that will call the native methods. */ public abstract T loadLibrary(Class interfaceClass, Map libraryOptions, String... libraryNames); /** * Gets the last native error code. *

* This returns the errno value that was set at the time of the last native * function call. * * @return The errno value. */ public abstract int getLastError(); /** * Sets the native error code. * * @param error The value to set errno to. */ public abstract void setLastError(int error); public abstract Type getType(NativeType type); private static final class SingletonHolder { private static final FFIProvider INSTANCE = getInstance(); private static final FFIProvider getInstance() { final boolean useJNA = Boolean.getBoolean("jaffl.usejna"); FFIProvider provider = null; String prefix = FFIProvider.class.getPackage().getName() + ".provider"; if (!useJNA) { try { provider = (FFIProvider) Class.forName(prefix + ".jffi.Provider").newInstance(); } catch (Throwable ex) { } } if (provider == null) { try { provider = (FFIProvider) Class.forName(prefix + ".jna.JNAProvider").newInstance(); } catch (Throwable ex) { throw new RuntimeException("Could not load FFI provider", ex); } } return provider; } } protected FFIProvider() {} } jaffl-0.5.9/src/com/kenai/jaffl/LastError.java000066400000000000000000000012001201747543600211070ustar00rootroot00000000000000 package com.kenai.jaffl; /** * Enables getting/setting of the unix errno and windows GetLastError() value */ public final class LastError { private LastError() {} /** * Gets the value of errno from the last native call. * * @return An integer containing the errno value. */ public static final int getLastError() { return FFIProvider.getProvider().getLastError(); } /** * Sets the native errno value. * * @param error The value to set errno to. */ public static final void setLastError(int error) { FFIProvider.getProvider().setLastError(error); } } jaffl-0.5.9/src/com/kenai/jaffl/Library.java000066400000000000000000000111761201747543600206130ustar00rootroot00000000000000 package com.kenai.jaffl; import java.io.File; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; /** * */ public final class Library { private static final Map> customSearchPaths = new ConcurrentHashMap>(); /** The name of this library */ private final String name; private Library(String libraryName) { name = libraryName; } /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param libraryName the name of the library to load * @param interfaceClass the interface that describes the native library interface * @return an instance of {@code interfaceclass} that will call the native methods. */ public static T loadLibrary(String libraryName, Class interfaceClass) { final Map options = Collections.emptyMap(); return loadLibrary(libraryName, interfaceClass, options); } /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param libraryName the name of the library to load * @param interfaceClass the interface that describes the native library interface * @return an instance of {@code interfaceclass} that will call the native methods. */ public static T loadLibrary(Class interfaceClass, String... libraryNames) { final Map options = Collections.emptyMap(); return loadLibrary(interfaceClass, options, libraryNames); } /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param libraryName the name of the library to load * @param interfaceClass the interface that describes the native library interface * @param libraryOptions options * @return an instance of {@code interfaceclass} that will call the native methods. */ public static T loadLibrary(String libraryName, Class interfaceClass, Map libraryOptions) { return FFIProvider.getProvider().loadLibrary(libraryName, interfaceClass, libraryOptions); } /** * Loads a native library and links the methods defined in {@code interfaceClass} * to native methods in the library. * * @param libraryName the name of the library to load * @param interfaceClass the interface that describes the native library interface * @param libraryOptions options * @return an instance of {@code interfaceclass} that will call the native methods. */ public static T loadLibrary(Class interfaceClass, Map libraryOptions, String... libraryNames) { return FFIProvider.getProvider().loadLibrary(interfaceClass, libraryOptions, libraryNames); } /** * Adds a custom search path for a library * * @param libraryName the name of the library to search for * @param path the path to search for the library in */ public static synchronized final void addLibraryPath(String libraryName, File path) { List customPaths = customSearchPaths.get(libraryName); if (customPaths == null) { customPaths = new CopyOnWriteArrayList(); customSearchPaths.put(libraryName, customPaths); } customPaths.add(path.getAbsolutePath()); } /** * Gets the custom search path for a library. * * @param libraryName The library to retrieve the path for. * * @return A List of String instances. */ public static List getLibraryPath(String libraryName) { List customPaths = customSearchPaths.get(libraryName); if (customPaths != null) { return customPaths; } return Collections.emptyList(); } public static final Library getInstance(String libraryName) { return new Library(libraryName); } /** * Checks if a specific function exists in the library. * * @param function The function * @return true if the function exists * @deprecated this method is no longer supported. */ public boolean hasFunction(String function) { return false; } /** * Gets the name of this library * * @return The name of this library as a String */ public String getName() { return name; } } jaffl-0.5.9/src/com/kenai/jaffl/LibraryOption.java000066400000000000000000000020331201747543600217740ustar00rootroot00000000000000 package com.kenai.jaffl; /** * Options that apply to a library */ public enum LibraryOption { /** * Function calls should save the errno/last error after the call. * This option can be overridden on individual methods by use of the * {@link com.googlecode.jffi.annotations.IgnoreError} annotation. */ SaveError, /** * Function calls should NOT save the errno/last error after the call. * This option can be overridden on individual methods by use of the * {@link com.googlecode.jffi.annotations.SaveError} annotation. */ IgnoreError, /** * A type mapper which maps java types to native types is present. */ TypeMapper, /** * A function mapper which maps from java function names to native function names. */ FunctionMapper, /** * The type of calling convention. * @see CallingConvention */ CallingConvention, /** * Load the library into memory immediately, instead of lazily loading it */ LoadNow; } jaffl-0.5.9/src/com/kenai/jaffl/MemoryIO.java000066400000000000000000000316751201747543600207150ustar00rootroot00000000000000 package com.kenai.jaffl; import java.nio.ByteBuffer; import java.nio.charset.Charset; /** * Interface to reading/writing various types of memory */ public abstract class MemoryIO implements Pointer { /** * Allocates a new block of java heap memory and wraps it in a {@link MemoryIO} * accessor. * * @param size The size in bytes of memory to allocate. * * @return A new MemoryIO instance that can access the memory. */ public static final MemoryIO allocate(int size) { return FFIProvider.getProvider().getMemoryManager().allocate(size); } /** * Allocates a new block of native memory and wraps it in a {@link MemoryIO} * accessor. * * @param size The size in bytes of memory to allocate. * * @return A new MemoryIO instance that can access the memory. */ public static final MemoryIO allocateDirect(int size) { return FFIProvider.getProvider().getMemoryManager().allocateDirect(size); } /** * Allocates a new block of native memory and wraps it in a {@link MemoryIO} * accessor. * * @param size The size in bytes of memory to allocate. * @param clear Whether the memory contents should be cleared, or left as * random data. * * @return A new MemoryIO instance that can access the memory. */ public static final MemoryIO allocateDirect(int size, boolean clear) { return FFIProvider.getProvider().getMemoryManager().allocateDirect(size, clear); } public static final MemoryIO wrap(Pointer ptr) { return FFIProvider.getProvider().getMemoryManager().wrap(ptr); } public static final MemoryIO wrap(Pointer ptr, int size) { return FFIProvider.getProvider().getMemoryManager().wrap(ptr, size); } public static final MemoryIO wrap(ByteBuffer buffer) { return FFIProvider.getProvider().getMemoryManager().wrap(buffer); } /** * Reads a 8 bit integer at the given offset. * * @param offset The offset from which the integer will be read. * @return The byte value at the offset. */ abstract public byte getByte(long offset); /** * Reads a 16 bit integer at the given offset. * * @param offset The offset from which the integer will be read. * @return The short value at the offset. */ abstract public short getShort(long offset); /** * Reads a 32 bit integer at the given offset. * * @param offset The offset from which the integer will be read. * @return The int value at the offset. */ abstract public int getInt(long offset); /** * Reads a 64 bit integer at the given offset. * * @param offset The offset from which the integer will be read. * @return The long value at the offset. */ abstract public long getLong(long offset); /** * Reads a 32 bit floating point value at the given offset. * * @param offset The offset from which the integer will be read. * @return The float value at the offset. */ abstract public float getFloat(long offset); /** * Reads a 64 bit floating point value at the given offset. * * @param offset The offset from which the integer will be read. * @return The double value at the offset. */ abstract public double getDouble(long offset); /** * Writes an 8 bit integer value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putByte(long offset, byte value); /** * Writes a 16 bit integer value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putShort(long offset, short value); /** * Writes a 32 bit integer value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putInt(long offset, int value); /** * Writes a 64 bit integer value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putLong(long offset, long value); /** * Writes a 32 bit floating point value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putFloat(long offset, float value); /** * Writes a 64 bit floating point value at the given offset. * * @param offset The offset at which the value will be written. * @param value The value to be written. */ abstract public void putDouble(long offset, double value); /** * Bulk byte get method. * * This method reads an array of bytes at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, byte[] dst, int idx, int len); /** * Bulk byte put method. * * This method writes an array of bytes at the given offset from the given * source array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, byte[] src, int idx, int len); /** * Bulk short get method. * * This method reads an array of 16 bit integers at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, short[] dst, int idx, int len); /** * Bulk short put method. * * This method writes an array of 16 bit integers at the given offset from * the given array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, short[] src, int idx, int len); /** * Bulk int get method. * * This method reads an array of 32 bit integers at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, int[] dst, int idx, int len); /** * Bulk int put method. * * This method writes an array of 32 bit integers at the given offset from * the given array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, int[] src, int idx, int len); /** * Bulk long get method. * * This method reads an array of 64 bit integers at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, long[] dst, int idx, int len); /** * Bulk long put method. * * This method writes an array of 64 bit integers at the given offset from * the given array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, long[] src, int idx, int len); /** * Bulk float get method. * * This method reads an array of 32 bit floats at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, float[] dst, int idx, int len); /** * Bulk float put method. * * This method writes an array of 32 bit floats at the given offset from * the given array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, float[] src, int idx, int len); /** * Bulk double get method. * * This method reads an array of 64 bit floats at the given offset into the given * destination array. * * @param offset The offset at which the values will be read. * @param dst The array into which values are to be written. * @param idx The index within the destination array of the first value to be written. * @param len The number of values to be written to the destination array. */ abstract public void get(long offset, double[] dst, int idx, int len); /** * Bulk double put method. * * This method writes an array of 64 bit floats at the given offset from * the given array. * * @param offset The offset at which the values will be written. * @param src The source array from which values are to be read. * @param idx The index within the destination array of the first value to be read. * @param len The number of values to be read from the source array. */ abstract public void put(long offset, double[] src, int idx, int len); abstract public MemoryIO getMemoryIO(long offset); abstract public MemoryIO getMemoryIO(long offset, long size); abstract public Pointer getPointer(long offset); abstract public void putPointer(long offset, Pointer value); abstract public int indexOf(long offset, byte value); abstract public int indexOf(long offset, byte value, int maxlen); abstract public long getAddress(long offset); abstract public void putAddress(long offset, long value); abstract public void putAddress(long offset, Address value); abstract public long getNativeLong(long offset); abstract public void putNativeLong(long offset, long value); abstract public String getString(long offset, int maxLength, Charset cs); abstract public String getString(long offset); abstract public void putString(long offset, String string, int maxLength, Charset cs); abstract public MemoryIO slice(long offset); abstract public MemoryIO slice(long offset, long size); abstract public void transferTo(long offset, MemoryIO other, long otherOffset, long count); abstract public void setMemory(long offset, long size, byte value); /** * Tells whether or not this memory object is direct. * * Memory objects can be either direct (representing native memory), or * non-direct (representing java heap memory). * * @return true if, and only if, this memory object is direct */ abstract public boolean isDirect(); /** * Gets the native address of this memory object (optional operation). * * @return The native address of this memory object. * @throws UnsupportedOperationException If this memory object is not backed by native memory. */ abstract public long address(); } jaffl-0.5.9/src/com/kenai/jaffl/NativeLong.java000066400000000000000000000112371201747543600212530ustar00rootroot00000000000000 package com.kenai.jaffl; /** * Represents a C long. *

* In C, a long can be either 32 bits or 64bits, depending on the platform. *

* Replace any function parameters which are long in the C definition with * a NativeLong. *

*/ public final class NativeLong extends Number implements Comparable { public static final int SIZE = Platform.getPlatform().longSize(); public static final int SHIFT = SIZE == 32 ? 2 : 3; public static final long MASK = SIZE == 32 ? 0xffffffffL : 0xffffffffffffffffL; private static final NativeLong ZERO = new NativeLong(0); private static final NativeLong ONE = new NativeLong(1); private static final NativeLong MINUS_ONE = new NativeLong(-1); private final long value; /** * Creates a new NativeLong instance with the supplied value. * * @param value a long or integer. */ public NativeLong(long value) { this.value = value; } /** * Returns an integer representation of this NativeLong. * * @return an integer value for this NativeLong. */ @Override public final int intValue() { return (int) value; } /** * Returns an {@code long} representation of this NativeLong. * * @return an {@code long} value for this NativeLong. */ @Override public final long longValue() { return value; } /** * Returns an {@code float} representation of this NativeLong. * * @return an {@code float} value for this NativeLong. */ @Override public final float floatValue() { return (float) value; } /** * Returns an {@code double} representation of this NativeLong. * * @return an {@code double} value for this NativeLong. */ @Override public final double doubleValue() { return (double) value; } /** * Gets a hash code for this {@code NativeLong}. * * @return a hash code for this {@code NativeLong}. */ @Override public final int hashCode() { return (int)(value ^ (value >>> 32)); } /** * Compares this NativeLong to another NativeLong. * * @param obj the other NativeLong to compare to. * @return {@code true} if this NativeLong is equal to the other * NativeLong, else false. */ @Override public final boolean equals(Object obj) { return ((obj instanceof NativeLong) && value == ((NativeLong) obj).value); } /** * Returns a string representation of this NativeLong. * * @return a string representation of this NativeLong. */ @Override public String toString() { return String.valueOf(value); } /** * Compares two {@code NativeLong} instances numerically. * * @param other the other NativeLong to compare to. * * @return {@code 0} if {@code other} is equal to this instance, -1 if this * instance is numerically less than {@code other} or 1 if this instance is * numerically greater than {@code other}. */ public final int compareTo(NativeLong other) { return value < other.value ? -1 : value > other.value ? 1 : 0; } /** * Internal cache of common native long values */ private static final class Cache { private Cache() {} static final NativeLong[] cache = new NativeLong[256]; static { for (int i = 0; i < cache.length; ++i) { cache[i] = new NativeLong(i - 128); } cache[128 + 0] = ZERO; cache[128 + 1] = ONE; cache[128 - 1] = MINUS_ONE; } } private static final NativeLong _valueOf(final long value) { return value >= -128 && value <= 127 ? Cache.cache[128 + (int) value] : new NativeLong(value); } /** * Returns a NativeLong instance representing the specified long value * * @param value a long value * @return a NativeLong instance representing value */ public static final NativeLong valueOf(final long value) { return value == 0 ? ZERO : value == 1 ? ONE : value == -1 ? MINUS_ONE : _valueOf(value); } /** * Returns a NativeLong instance representing the specified int value * * @param value a 32bit integer value * @return a NativeLong instance representing value */ public static final NativeLong valueOf(final int value) { return valueOf((long) value); } } jaffl-0.5.9/src/com/kenai/jaffl/ParameterFlags.java000066400000000000000000000044711201747543600221040ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.annotations.Direct; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.NulTerminate; import com.kenai.jaffl.annotations.Out; import com.kenai.jaffl.annotations.Pinned; import com.kenai.jaffl.annotations.Transient; import java.lang.annotation.Annotation; /** * * @author wayne */ public final class ParameterFlags { private ParameterFlags() {} public static final int OUT = 0x01; public static final int IN = 0x02; public static final int PINNED = 0x04; public static final int NULTERMINATE = 0x08; public static final int TRANSIENT = 0x10; public static final int DIRECT = 0x20; public static final int parse(Annotation[] annotations) { int flags = 0; for (Annotation a : annotations) { flags |= a instanceof Out ? OUT : 0; flags |= a instanceof In ? IN : 0; flags |= a instanceof Transient ? TRANSIENT : 0; flags |= a instanceof Direct ? DIRECT : 0; flags |= a instanceof Pinned ? PINNED : 0; flags |= a instanceof NulTerminate ? NULTERMINATE : 0; } return flags; } /** * Checks if the annotation is a recognised parameter flag. * * @param annotation the annotation to check. * @return true if the annotation is a parameter flag */ public static final boolean isFlag(Annotation annotation) { return annotation instanceof Pinned || annotation instanceof Transient || annotation instanceof Direct || annotation instanceof NulTerminate || annotation instanceof Out || annotation instanceof In; } public static final boolean isPinned(int flags) { return (flags & PINNED) != 0; } public static final boolean isTransient(int flags) { return (flags & TRANSIENT) != 0; } public static final boolean isDirect(int flags) { return (flags & DIRECT) != 0; } public static final boolean isNulTerminate(int flags) { return (flags & NULTERMINATE) != 0; } public static final boolean isOut(int flags) { return (flags & (OUT | IN)) != IN; } public static final boolean isIn(int flags) { return (flags & (OUT | IN)) != OUT; } } jaffl-0.5.9/src/com/kenai/jaffl/Platform.java000066400000000000000000000305531201747543600207730ustar00rootroot00000000000000 package com.kenai.jaffl; import java.io.File; import java.io.FilenameFilter; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.regex.Pattern; public abstract class Platform { private final OS os; private final CPU cpu; private final int longSize; private final int addressSize; private final long addressMask; private final int javaVersionMajor; protected final Pattern libPattern; /** * The common names of operating systems. * * Note The names of the enum values are used in other parts of the * code to determine where to find the native stub library. Do not rename. */ public enum OS { /** MacOSX */ DARWIN, /** FreeBSD */ FREEBSD, /** NetBSD */ NETBSD, /** OpenBSD */ OPENBSD, /** Linux */ LINUX, /** Solaris (and OpenSolaris) */ SOLARIS, /** The evil borg operating system */ WINDOWS, /** IBM AIX */ AIX, /** IBM zOS **/ ZLINUX, /** No idea what the operating system is */ UNKNOWN; @Override public String toString() { return name().toLowerCase(); } } /** * The common names of cpu architectures. * * Note The names of the enum values are used in other parts of the * code to determine where to find the native stub library. Do not rename. */ public enum CPU { /** Intel ia32 */ I386, /** AMD 64 bit (aka EM64T/X64) */ X86_64, /** Power PC 32 bit */ PPC, /** Power PC 64 bit */ PPC64, /** Sun sparc 32 bit */ SPARC, /** Sun sparc 64 bit */ SPARCV9, /** IBM zSeries S/390 64 bit */ S390X, /** Unknown CPU */ UNKNOWN; @Override public String toString() { return name().toLowerCase(); } } private static final class SingletonHolder { static final Platform PLATFORM = determinePlatform(determineOS()); } /** * Determines the operating system jffi is running on * * @return An member of the OS enum. */ private static final OS determineOS() { String osName = System.getProperty("os.name").split(" ")[0].toLowerCase(); if (osName.startsWith("mac") || osName.startsWith("darwin")) { return OS.DARWIN; } else if (osName.startsWith("linux")) { return OS.LINUX; } else if (osName.startsWith("sunos") || osName.startsWith("solaris")) { return OS.SOLARIS; } else if (osName.startsWith("aix")) { return OS.AIX; } else if (osName.startsWith("openbsd")) { return OS.OPENBSD; } else if (osName.startsWith("freebsd")) { return OS.FREEBSD; } else if (osName.startsWith("windows")) { return OS.WINDOWS; } else { return OS.UNKNOWN; } } /** * Determines the Platform that best describes the OS * * @param os The operating system. * @return An instance of Platform */ private static final Platform determinePlatform(OS os) { switch (os) { case DARWIN: return new Darwin(); case LINUX: return new Linux(); case WINDOWS: return new Windows(); case UNKNOWN: return new Unsupported(os); default: return new Default(os); } } private static final CPU determineCPU() { String archString = System.getProperty("os.arch").toLowerCase(); if ("x86".equals(archString) || "i386".equals(archString) || "i86pc".equals(archString)) { return CPU.I386; } else if ("x86_64".equals(archString) || "amd64".equals(archString)) { return CPU.X86_64; } else if ("ppc".equals(archString) || "powerpc".equals(archString)) { return CPU.PPC; } // Try to find by lookup up in the CPU list try { return CPU.valueOf(archString.toUpperCase()); } catch (IllegalArgumentException ex) { return CPU.UNKNOWN; } } private Platform(OS os) { this.os = os; this.cpu = determineCPU(); int dataModel = Integer.getInteger("sun.arch.data.model"); if (dataModel != 32 && dataModel != 64) { switch (cpu) { case I386: case PPC: case SPARC: dataModel = 32; break; case X86_64: case PPC64: case SPARCV9: case S390X: dataModel = 64; break; default: throw new ExceptionInInitializerError("Cannot determine cpu address size"); } } addressSize = dataModel; addressMask = addressSize == 32 ? 0xffffffffL : 0xffffffffffffffffL; longSize = os == OS.WINDOWS ? 32 : addressSize; int version = 5; try { String versionString = System.getProperty("java.version"); if (versionString != null) { String[] v = versionString.split("\\."); version = Integer.valueOf(v[1]); } } catch (Exception ex) { throw new ExceptionInInitializerError("Could not determine java version"); } javaVersionMajor = version; String libpattern = null; switch (os) { case WINDOWS: libpattern = ".*\\.dll$"; break; case DARWIN: libpattern = "lib.*\\.(dylib|jnilib)$"; break; default: libpattern = "lib.*\\.so.*$"; break; } libPattern = Pattern.compile(libpattern); } /** * Gets the current Platform * * @return The current platform. */ public static final Platform getPlatform() { return SingletonHolder.PLATFORM; } /** * Gets the current Operating System. * * @return A OS value representing the current Operating System. */ public final OS getOS() { return os; } /** * Gets the current processor architecture the JVM is running on. * * @return A CPU value representing the current processor architecture. */ public final CPU getCPU() { return cpu; } /** * Gets the version of the Java Virtual Machine (JVM) jffi is running on. * * @return A number representing the java version. e.g. 5 for java 1.5, 6 for java 1.6 */ public final int getJavaMajorVersion() { return javaVersionMajor; } public final boolean isBSD() { return os == OS.FREEBSD || os == os.OPENBSD || os == OS.NETBSD || os == OS.DARWIN; } public final boolean isUnix() { return os != OS.WINDOWS; } /** * Gets the size of a C 'long' on the native platform. * * @return the size of a long in bits */ public final int longSize() { return longSize; } /** * Gets the size of a C address/pointer on the native platform. * * @return the size of a pointer in bits */ public final int addressSize() { return addressSize; } /** * Gets the 32/64bit mask of a C address/pointer on the native platform. * * @return the size of a pointer in bits */ public final long addressMask() { return addressMask; } /** * Gets the name of this Platform. * * @return The name of this platform. */ public String getName() { return cpu + "-" + os; } /** * Maps from a generic library name (e.g. "c") to the platform specific library name. * * @param libName The library name to map * @return The mapped library name. */ public String mapLibraryName(String libName) { // // A specific version was requested - use as is for search // if (libPattern.matcher(libName).find()) { return libName; } return System.mapLibraryName(libName); } /** * Searches through a list of directories for a native library. * * @param libName the base name (e.g. "c") of the library to locate * @param libraryPath the list of directories to search * @return the path of the library */ public String locateLibrary(String libName, List libraryPath) { String mappedName = mapLibraryName(libName); for (String path : libraryPath) { File libFile = new File(path, mappedName); if (libFile.exists()) { return libFile.getAbsolutePath(); } } // Default to letting the system search for it return mappedName; } private static class Supported extends Platform { public Supported(OS os) { super(os); } } private static class Unsupported extends Platform { public Unsupported(OS os) { super(os); } } private static final class Default extends Supported { public Default(OS os) { super(os); } } /** * A {@link Platform} subclass representing the MacOS system. */ private static final class Darwin extends Supported { public Darwin() { super(OS.DARWIN); } @Override public String mapLibraryName(String libName) { // // A specific version was requested - use as is for search // if (libPattern.matcher(libName).find()) { return libName; } return "lib" + libName + ".dylib"; } @Override public String getName() { return "Darwin"; } } /** * A {@link Platform} subclass representing the Linux operating system. */ private static final class Linux extends Supported { public Linux() { super(OS.LINUX); } @Override public String locateLibrary(final String libName, List libraryPath) { FilenameFilter filter = new FilenameFilter() { Pattern p = Pattern.compile("lib" + libName + "\\.so\\.[0-9]+$"); String exact = "lib" + libName + ".so"; public boolean accept(File dir, String name) { return p.matcher(name).matches() || exact.equals(name); } }; List matches = new LinkedList(); for (String path : libraryPath) { File[] files = new File(path).listFiles(filter); if (files != null && files.length > 0) { matches.addAll(Arrays.asList(files)); } } // // Search through the results and return the highest numbered version // i.e. libc.so.6 is preferred over libc.so.5 // int version = 0; String bestMatch = null; for (File file : matches) { String path = file.getAbsolutePath(); if (bestMatch == null && path.endsWith(".so")) { bestMatch = path; version = 0; } else { String num = path.substring(path.lastIndexOf(".so.") + 4); try { if (Integer.parseInt(num) >= version) { bestMatch = path; } } catch (NumberFormatException e) { } // Just skip if not a number } } return bestMatch != null ? bestMatch : mapLibraryName(libName); } @Override public String mapLibraryName(String libName) { // Older JDK on linux map 'c' to 'libc.so' which doesn't work return "c".equals(libName) || "libc.so".equals(libName) ? "libc.so.6" : super.mapLibraryName(libName); } } /** * A {@link Platform} subclass representing the Windows system. */ private static class Windows extends Supported { public Windows() { super(OS.WINDOWS); } } } jaffl-0.5.9/src/com/kenai/jaffl/Pointer.java000066400000000000000000000035611201747543600206260ustar00rootroot00000000000000 package com.kenai.jaffl; public interface Pointer { public static final int SIZE = Platform.getPlatform().addressSize(); abstract public byte getByte(long offset); abstract public short getShort(long offset); abstract public int getInt(long offset); abstract public long getLong(long offset); abstract public float getFloat(long offset); abstract public double getDouble(long offset); abstract public void putByte(long offset, byte value); abstract public void putShort(long offset, short value); abstract public void putInt(long offset, int value); abstract public void putLong(long offset, long value); abstract public void putFloat(long offset, float value); abstract public void putDouble(long offset, double value); abstract public void get(long offset, byte[] dst, int off, int len); abstract public void put(long offset, byte[] dst, int off, int len); abstract public void get(long offset, short[] dst, int off, int len); abstract public void put(long offset, short[] dst, int off, int len); abstract public void get(long offset, int[] dst, int off, int len); abstract public void put(long offset, int[] dst, int off, int len); abstract public void get(long offset, long[] dst, int off, int len); abstract public void put(long offset, long[] dst, int off, int len); abstract public void get(long offset, float[] dst, int off, int len); abstract public void put(long offset, float[] dst, int off, int len); abstract public void get(long offset, double[] dst, int off, int len); abstract public void put(long offset, double[] dst, int off, int len); abstract public Pointer getPointer(long offset); abstract public void putPointer(long offset, Pointer value); abstract public String getString(long offset); abstract public long address(); abstract public boolean isDirect(); } jaffl-0.5.9/src/com/kenai/jaffl/Type.java000066400000000000000000000027551201747543600201330ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.provider.NativeType; public interface Type { /** * The size in bytes of this type. * * @return An integer */ int size(); /** * The native alignment of this type, in bytes * * @return An integer */ int alignment(); public static final Type SCHAR = FFIProvider.getProvider().getType(NativeType.SCHAR); public static final Type UCHAR = FFIProvider.getProvider().getType(NativeType.UCHAR); public static final Type SSHORT = FFIProvider.getProvider().getType(NativeType.SSHORT); public static final Type USHORT = FFIProvider.getProvider().getType(NativeType.USHORT); public static final Type SINT = FFIProvider.getProvider().getType(NativeType.SINT); public static final Type UINT = FFIProvider.getProvider().getType(NativeType.UINT); public static final Type SLONG = FFIProvider.getProvider().getType(NativeType.SLONG); public static final Type ULONG = FFIProvider.getProvider().getType(NativeType.ULONG); public static final Type SLONGLONG = FFIProvider.getProvider().getType(NativeType.SLONGLONG); public static final Type ULONGLONG = FFIProvider.getProvider().getType(NativeType.ULONGLONG); public static final Type FLOAT = FFIProvider.getProvider().getType(NativeType.FLOAT); public static final Type DOUBLE = FFIProvider.getProvider().getType(NativeType.DOUBLE); public static final Type ADDRESS = FFIProvider.getProvider().getType(NativeType.ADDRESS); } jaffl-0.5.9/src/com/kenai/jaffl/annotations/000077500000000000000000000000001201747543600206735ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/annotations/Clear.java000066400000000000000000000006751201747543600225740ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that the temporary native memory allocated for an @Out paramneter * should be cleared before passing to the native function. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Clear { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/Direct.java000066400000000000000000000007551201747543600227570ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that the parameter requires native memory. * * This means it can be backed by allocated native memory, that is freed only * after the Struct instance goes out of scope. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Direct { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/IgnoreError.java000066400000000000000000000005111201747543600237700ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Tags a library method as not needing any error codes as returned * by errno on unix, or GetLastError on windows be saved. */ @Retention(RetentionPolicy.RUNTIME) public @interface IgnoreError { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/In.java000066400000000000000000000012361201747543600221060ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that the parameter is an IN parameter. *

* If a parameter is tagged only as In, and a temporary native memory * area needs to be allocated before passing the data to native memory, then * the java data is copied from java memory to native memory, but it is not * copied back to java from the native memory area after the call. *

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface In { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/NulTerminate.java000066400000000000000000000006041201747543600241450ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that a byte array or ByteBuffer should be passed as a C string */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface NulTerminate { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/Out.java000066400000000000000000000012401201747543600223020ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that the parameter is an OUT parameter. * *

* If a parameter is tagged only as Out, and a temporary native memory * area needs to be allocated before passing the data to native memory, then * the java data is not copied to native memory before the call, but is copied * back to java from the native memory area after the call. *

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Out { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/Pinned.java000066400000000000000000000012601201747543600227520ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Marks a method parameter as being pinnable. *

* This means the data for the parameter is not copied to/from native memory. * Instead, the JVM memory is locked and passed directly to the native code. *

*

* IMPORTANT: This should not be used for functions that may block on * network or filesystem access such as read(2), write(2), stat(2), etc. *

*/ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Pinned { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/SaveError.java000066400000000000000000000005051201747543600234460ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Tags a library method as requiring any error codes as returned * by errno on unix, or GetLastError on windows be saved. */ @Retention(RetentionPolicy.RUNTIME) public @interface SaveError { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/StdCall.java000066400000000000000000000004501201747543600230630ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface StdCall { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/Synchronized.java000066400000000000000000000006241201747543600242170ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; /** * Indicates that a library or a library method requires all calls to be * synchronized. * * i.e. calls from multiple threads will synchronize on a monitor object, * then call the native method. */ @Retention(RetentionPolicy.RUNTIME) public @interface Synchronized { } jaffl-0.5.9/src/com/kenai/jaffl/annotations/Transient.java000066400000000000000000000007731201747543600235140ustar00rootroot00000000000000 package com.kenai.jaffl.annotations; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Indicates that the parameter is transient. * * This means it can be backed by a temporarily allocated native memory block, * and after the method call, the native memory can be freed again. */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.PARAMETER) public @interface Transient { } jaffl-0.5.9/src/com/kenai/jaffl/byref/000077500000000000000000000000001201747543600174455ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/byref/AbstractPrimitiveReference.java000066400000000000000000000013231201747543600255620ustar00rootroot00000000000000 package com.kenai.jaffl.byref; /** * An abstract class for common PrimitiveReference functionality */ abstract public class AbstractPrimitiveReference implements ByReference { protected T value; public AbstractPrimitiveReference(T value) { if (value == null) { throw new NullPointerException("Reference value cannot be null"); } this.value = value; } public Class nativeType() { return value.getClass(); } public void setValue(T value) { if (value == null) { throw new NullPointerException("Reference value cannot be null"); } this.value = value; } public T getValue() { return value; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/AddressByReference.java000066400000000000000000000020621201747543600240070ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import com.kenai.jaffl.Address; import com.kenai.jaffl.util.BufferUtil; import java.nio.ByteBuffer; /** * */ public class AddressByReference extends AbstractPrimitiveReference
{ /** * Creates a new reference to an address value * * @param value the initial native value */ public AddressByReference(Address value) { super(value); } /** * Copies the address value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { BufferUtil.putAddress(buffer, 0, value.nativeAddress()); } /** * Copies the address value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = new Address(BufferUtil.getAddress(buffer, 0)); } /** * Gets the native size of type of reference * * @return Integer.SIZE */ public int nativeSize() { return Address.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/ByReference.java000066400000000000000000000011361201747543600225020ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; public interface ByReference { /** * Gets the size of the native buffer required to store the value * * @return the size in bytes of the native type */ int nativeSize(); /** * Copies the java value to native memory * * @param buffer the native memory buffer. */ void marshal(ByteBuffer buffer); /** * Copies the java value from native memory * * @param buffer the native memory buffer. */ void unmarshal(ByteBuffer buffer); T getValue(); } jaffl-0.5.9/src/com/kenai/jaffl/byref/ByteByReference.java000066400000000000000000000016621201747543600233320ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * */ public class ByteByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a byte value * * @param value the initial native value */ public ByteByReference(Byte value) { super(value); } /** * Copies the Byte value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.put(0, value); } /** * Copies the Byte value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.get(0); } /** * Gets the native size of type of reference in bytes. * * @return the size of a byte in bytes */ public final int nativeSize() { return Byte.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/DoubleByReference.java000066400000000000000000000017161201747543600236410ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * */ public class DoubleByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a double value * * @param value the initial native value */ public DoubleByReference(Double value) { super(value); } /** * Copies the double value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.putDouble(0, value); } /** * Copies the double value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.getDouble(0); } /** * Gets the native size of type of reference in bytes. * * @return the size of a byte in bytes */ public final int nativeSize() { return Double.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/FloatByReference.java000066400000000000000000000017041201747543600234710ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * */ public class FloatByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a float value * * @param value the initial native value */ public FloatByReference(Float value) { super(value); } /** * Copies the float value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.putFloat(0, value); } /** * Copies the float value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.getFloat(0); } /** * Gets the native size of type of reference in bytes. * * @return the size of a byte in bytes */ public final int nativeSize() { return Float.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/IntByReference.java000066400000000000000000000022471201747543600231610ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * A class to pass a reference (or address of) an Integer to a method. */ public final class IntByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a integer value * * @param value the initial native value */ public IntByReference(Integer value) { super(value); } /** * Copies the integer value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.putInt(0, value); } /** * Copies the integer value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.getInt(0); } /** * Gets the native size of type of reference * * @return Integer.SIZE */ public int nativeSize() { return Integer.SIZE / 8; } /** * Gets the native type of the reference * * @return Integer.class */ @Override public Class nativeType() { return Integer.class; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/LongLongByReference.java000066400000000000000000000017151201747543600241450ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * */ public class LongLongByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a native longlong value * * @param value the initial native value */ public LongLongByReference(Long value) { super(value); } /** * Copies the Byte value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.putLong(0, value); } /** * Copies the Byte value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.getLong(0); } /** * Gets the native size of type of reference in bytes. * * @return the size of a byte in bytes */ public final int nativeSize() { return Long.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/byref/ShortByReference.java000066400000000000000000000017041201747543600235230ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import java.nio.ByteBuffer; /** * */ public class ShortByReference extends AbstractPrimitiveReference { /** * Creates a new reference to a short value * * @param value the initial native value */ public ShortByReference(Short value) { super(value); } /** * Copies the short value to native memory * * @param buffer the native memory buffer */ public void marshal(ByteBuffer buffer) { buffer.putShort(0, value); } /** * Copies the short value from native memory * * @param buffer the native memory buffer. */ public void unmarshal(ByteBuffer buffer) { value = buffer.getShort(0); } /** * Gets the native size of type of reference in bytes. * * @return the size of a byte in bytes */ public final int nativeSize() { return Short.SIZE / 8; } } jaffl-0.5.9/src/com/kenai/jaffl/mapper/000077500000000000000000000000001201747543600176225ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/mapper/FromNativeContext.java000066400000000000000000000002501201747543600241010ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; /** * Context for a native->java type conversion. */ public interface FromNativeContext { // Nothing here, just a placeholder } jaffl-0.5.9/src/com/kenai/jaffl/mapper/FromNativeConverter.java000066400000000000000000000003611201747543600244270ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; /** * Converts data from a native type to a java type */ public interface FromNativeConverter { public J fromNative(N nativeValue, FromNativeContext context); public Class nativeType(); } jaffl-0.5.9/src/com/kenai/jaffl/mapper/FunctionMapper.java000066400000000000000000000003641201747543600234220ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; import com.kenai.jaffl.Library; public interface FunctionMapper { static interface Context { Library getLibrary(); } public String mapFunctionName(String functionName, Context context); } jaffl-0.5.9/src/com/kenai/jaffl/mapper/MethodParameterContext.java000066400000000000000000000013361201747543600251160ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; import java.lang.annotation.Annotation; import java.lang.reflect.Method; /** * Holds context for a method parameter java->native conversion. */ public final class MethodParameterContext implements ToNativeContext { private final Method method; private final int parameterIndex; private final Annotation[] annotations; public MethodParameterContext(Method method, int parameterIndex) { this.method = method; this.parameterIndex = parameterIndex; this.annotations = method.getParameterAnnotations()[parameterIndex]; } public Method getMethod() { return method; } public int getParameterIndex() { return parameterIndex; } } jaffl-0.5.9/src/com/kenai/jaffl/mapper/MethodResultContext.java000066400000000000000000000005031201747543600244470ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; import java.lang.reflect.Method; /** * */ public class MethodResultContext implements FromNativeContext { private final Method method; public MethodResultContext(Method method) { this.method = method; } public Method getMethod() { return method; } } jaffl-0.5.9/src/com/kenai/jaffl/mapper/ToNativeContext.java000066400000000000000000000001101201747543600235530ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; public interface ToNativeContext { } jaffl-0.5.9/src/com/kenai/jaffl/mapper/ToNativeConverter.java000066400000000000000000000002521201747543600241050ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; public interface ToNativeConverter { public N toNative(J value, ToNativeContext context); public Class nativeType(); } jaffl-0.5.9/src/com/kenai/jaffl/mapper/TypeMapper.java000066400000000000000000000003041201747543600225500ustar00rootroot00000000000000 package com.kenai.jaffl.mapper; public interface TypeMapper { public FromNativeConverter getFromNativeConverter(Class type); public ToNativeConverter getToNativeConverter(Class type); } jaffl-0.5.9/src/com/kenai/jaffl/provider/000077500000000000000000000000001201747543600201705ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/provider/AbstractArrayMemoryIO.java000066400000000000000000000347001201747543600252220ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.Platform; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.Charset; import java.util.Arrays; public abstract class AbstractArrayMemoryIO extends AbstractMemoryIO { protected static final ArrayIO IO = getArrayIO(); protected static final int LONG_SIZE = Platform.getPlatform().longSize(); protected final byte[] buffer; protected final int offset, length; public AbstractArrayMemoryIO(byte[] buffer, int offset, int length) { this.buffer = buffer; this.offset = offset; this.length = length; } public AbstractArrayMemoryIO(byte[] buffer) { this(buffer, 0, buffer.length); } public AbstractArrayMemoryIO(int size) { this(new byte[size], 0, size); } public final byte[] array() { return buffer; } public final int offset() { return offset; } public final int length() { return length; } @Override public final boolean isDirect() { return false; } @Override public long address() { throw new UnsupportedOperationException("Not a direct memory object"); } private static final ArrayIO getArrayIO() { if (ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN)) { return Platform.getPlatform().addressSize() == 64 ? newBE64ArrayIO() : newBE32ArrayIO(); } else { return Platform.getPlatform().addressSize() == 64 ? newLE64ArrayIO() : newLE32ArrayIO(); } } private static final ArrayIO newBE64ArrayIO() { return new BE64ArrayIO(); } private static final ArrayIO newBE32ArrayIO() { return new BE32ArrayIO(); } private static final ArrayIO newLE64ArrayIO() { return new LE64ArrayIO(); } private static final ArrayIO newLE32ArrayIO() { return new LE32ArrayIO(); } protected final int index(long off) { return this.offset + (int) off; } public final boolean isNull() { return false; } @Override public String getString(long offset) { ByteBuffer tmp = ByteBuffer.wrap(buffer, index(offset), length - (int) offset); return StringIO.getStringIO().fromNative(tmp, length - (int) offset).toString(); } @Override public String getString(long offset, int maxLength, Charset cs) { ByteBuffer tmp = ByteBuffer.wrap(buffer, index(offset), length - (int) offset); return StringIO.getStringIO().fromNative(tmp, Math.min(maxLength, length - (int) offset)).toString(); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { StringIO.getStringIO().toNative(string, ByteBuffer.wrap(buffer, index(offset), Math.min(maxLength, length - (int) offset))); } public final byte getByte(long offset) { return (byte) (buffer[index(offset)] & 0xff); } public final short getShort(long offset) { return IO.getInt16(buffer, index(offset)); } public final int getInt(long offset) { return IO.getInt32(buffer, index(offset)); } public final long getLong(long offset) { return IO.getInt64(buffer, index(offset)); } @Override public final long getAddress(long offset) { return IO.getAddress(buffer, index(offset)); } public final float getFloat(long offset) { return IO.getFloat32(buffer, index(offset)); } public final double getDouble(long offset) { return IO.getFloat64(buffer, index(offset)); } public final void putByte(long offset, byte value) { buffer[index(offset)] = value; } public final void putShort(long offset, short value) { IO.putInt16(buffer, index(offset), value); } public final void putInt(long offset, int value) { IO.putInt32(buffer, index(offset), value); } public final void putLong(long offset, long value) { IO.putInt64(buffer, index(offset), value); } @Override public final void putAddress(long offset, long value) { IO.putAddress(buffer, index(offset), value); } public final void putFloat(long offset, float value) { IO.putFloat32(buffer, index(offset), value); } public final void putDouble(long offset, double value) { IO.putFloat64(buffer, index(offset), value); } public final void get(long offset, byte[] dst, int off, int len) { System.arraycopy(buffer, index(offset), dst, off, len); } public final void put(long offset, byte[] src, int off, int len) { System.arraycopy(src, off, buffer, index(offset), len); } public final void get(long offset, short[] dst, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { dst[off + i] = IO.getInt16(buffer, begin + (i << 1)); } } public final void put(long offset, short[] src, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { IO.putInt16(buffer, begin + (i << 1), src[off + i]); } } public final void get(long offset, int[] dst, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { dst[off + i] = IO.getInt32(buffer, begin + (i << 2)); } } public final void put(long offset, int[] src, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { IO.putInt32(buffer, begin + (i << 2), src[off + i]); } } public final void get(long offset, long[] dst, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { dst[off + i] = IO.getInt64(buffer, begin + (i << 3)); } } public final void put(long offset, long[] src, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { IO.putInt64(buffer, begin + (i << 3), src[off + i]); } } public final void get(long offset, float[] dst, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { dst[off + i] = IO.getFloat32(buffer, begin + (i << 2)); } } public final void put(long offset, float[] src, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { IO.putFloat32(buffer, begin + (i << 2), src[off + i]); } } public final void get(long offset, double[] dst, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { dst[off + i] = IO.getFloat64(buffer, begin + (i << 3)); } } public final void put(long offset, double[] src, int off, int len) { int begin = index(offset); for (int i = 0; i < len; ++i) { IO.putFloat64(buffer, begin + (i << 3), src[off + i]); } } @Override public final int indexOf(long offset, byte value) { int off = index(offset); for (int i = 0; i < length; ++i) { if (buffer[off + i] == value) { return i; } } return -1; } public final int indexOf(long offset, byte value, int maxlen) { int off = index(offset); for (int i = 0; i < Math.min(length, maxlen); ++i) { if (buffer[off + i] == value) { return i; } } return -1; } public final void setMemory(long offset, long size, byte value) { Arrays.fill(buffer, index(offset), (int) size, value); } public final void clear() { Arrays.fill(buffer, offset, length, (byte) 0); } protected static abstract class ArrayIO { public abstract short getInt16(byte[] buffer, int offset); public abstract int getInt32(byte[] buffer, int offset); public abstract long getInt64(byte[] buffer, int offset); public abstract long getAddress(byte[] buffer, int offset); public abstract void putInt16(byte[] buffer, int offset, int value); public abstract void putInt32(byte[] buffer, int offset, int value); public abstract void putInt64(byte[] buffer, int offset, long value); public abstract void putAddress(byte[] buffer, int offset, long value); public final float getFloat32(byte[] buffer, int offset) { return Float.intBitsToFloat(getInt32(buffer, offset)); } public final void putFloat32(byte[] buffer, int offset, float value) { putInt32(buffer, offset, Float.floatToRawIntBits(value)); } public final double getFloat64(byte[] buffer, int offset) { return Double.longBitsToDouble(getInt64(buffer, offset)); } public final void putFloat64(byte[] buffer, int offset, double value) { putInt64(buffer, offset, Double.doubleToRawLongBits(value)); } } private static abstract class LittleEndianArrayIO extends ArrayIO { public final short getInt16(byte[] array, int offset) { return (short) ((array[offset] & 0xff) | ((array[offset + 1] & 0xff) << 8)); } public final int getInt32(byte[] array, int offset) { return ((array[offset + 0] & 0xff) << 0) | ((array[offset + 1] & 0xff) << 8) | ((array[offset + 2] & 0xff) << 16) | ((array[offset + 3] & 0xff) << 24); } public final long getInt64(byte[] array, int offset) { return (((long)array[offset + 0] & 0xff) << 0) | (((long)array[offset + 1] & 0xff) << 8) | (((long)array[offset + 2] & 0xff) << 16) | (((long)array[offset + 3] & 0xff) << 24) | (((long)array[offset + 4] & 0xff) << 32) | (((long)array[offset + 5] & 0xff) << 40) | (((long)array[offset + 6] & 0xff) << 48) | (((long)array[offset + 7] & 0xff) << 56); } public final void putInt16(byte[] buffer, int offset, int value) { buffer[offset + 0] = (byte) (value >> 0); buffer[offset + 1] = (byte) (value >> 8); } public final void putInt32(byte[] buffer, int offset, int value) { buffer[offset + 0] = (byte) (value >> 0); buffer[offset + 1] = (byte) (value >> 8); buffer[offset + 2] = (byte) (value >> 16); buffer[offset + 3] = (byte) (value >> 24); } public final void putInt64(byte[] buffer, int offset, long value) { buffer[offset + 0] = (byte) (value >> 0); buffer[offset + 1] = (byte) (value >> 8); buffer[offset + 2] = (byte) (value >> 16); buffer[offset + 3] = (byte) (value >> 24); buffer[offset + 4] = (byte) (value >> 32); buffer[offset + 5] = (byte) (value >> 40); buffer[offset + 6] = (byte) (value >> 48); buffer[offset + 7] = (byte) (value >> 56); } } private static abstract class BigEndianArrayIO extends ArrayIO { public short getInt16(byte[] array, int offset) { return (short) (((array[offset + 0] & 0xff) << 8) | (array[offset + 1] & 0xff)); } public int getInt32(byte[] array, int offset) { return ((array[offset + 0] & 0xff) << 24) | ((array[offset + 1] & 0xff) << 16) | ((array[offset + 2] & 0xff) << 8) | ((array[offset + 3] & 0xff) << 0); } public long getInt64(byte[] array, int offset) { return (((long)array[offset + 0] & 0xff) << 56) | (((long)array[offset + 1] & 0xff) << 48) | (((long)array[offset + 2] & 0xff) << 40) | (((long)array[offset + 3] & 0xff) << 32) | (((long)array[offset + 4] & 0xff) << 24) | (((long)array[offset + 5] & 0xff) << 16) | (((long)array[offset + 6] & 0xff) << 8) | (((long)array[offset + 7] & 0xff) << 0); } public final void putInt16(byte[] buffer, int offset, int value) { buffer[offset + 0] = (byte) (value >> 8); buffer[offset + 1] = (byte) (value >> 0); } public final void putInt32(byte[] buffer, int offset, int value) { buffer[offset + 0] = (byte) (value >> 24); buffer[offset + 1] = (byte) (value >> 16); buffer[offset + 2] = (byte) (value >> 8); buffer[offset + 3] = (byte) (value >> 0); } public final void putInt64(byte[] buffer, int offset, long value) { buffer[offset + 0] = (byte) (value >> 56); buffer[offset + 1] = (byte) (value >> 48); buffer[offset + 2] = (byte) (value >> 40); buffer[offset + 3] = (byte) (value >> 32); buffer[offset + 4] = (byte) (value >> 24); buffer[offset + 5] = (byte) (value >> 16); buffer[offset + 6] = (byte) (value >> 8); buffer[offset + 7] = (byte) (value >> 0); } } private static final class LE32ArrayIO extends LittleEndianArrayIO { public final long getAddress(byte[] buffer, int offset) { return ((long) getInt32(buffer, offset)) & 0xffffffffL; } public final void putAddress(byte[] buffer, int offset, long value) { putInt32(buffer, offset, (int) value); } } private static final class LE64ArrayIO extends LittleEndianArrayIO { public final long getAddress(byte[] buffer, int offset) { return getInt64(buffer, offset); } public final void putAddress(byte[] buffer, int offset, long value) { putInt64(buffer, offset, value); } } private static final class BE32ArrayIO extends BigEndianArrayIO { public final long getAddress(byte[] buffer, int offset) { return ((long) getInt32(buffer, offset)) & 0xffffffffL; } public final void putAddress(byte[] buffer, int offset, long value) { putInt32(buffer, offset, (int) value); } } private static final class BE64ArrayIO extends BigEndianArrayIO { public final long getAddress(byte[] buffer, int offset) { return getInt64(buffer, offset); } public final void putAddress(byte[] buffer, int offset, long value) { putInt64(buffer, offset, value); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/AbstractBufferMemoryIO.java000066400000000000000000000124111201747543600253500ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.util.BufferUtil; import java.nio.ByteBuffer; import java.nio.charset.Charset; /** * */ abstract public class AbstractBufferMemoryIO extends AbstractMemoryIO { protected final ByteBuffer buffer; public AbstractBufferMemoryIO(ByteBuffer buffer) { this.buffer = buffer; } public final boolean isDirect() { return buffer.isDirect(); } @Override public long address() { throw new UnsupportedOperationException("Not a direct memory object."); } public final ByteBuffer getByteBuffer() { return buffer; } public byte getByte(long offset) { return buffer.get((int) offset); } public short getShort(long offset) { return buffer.getShort((int) offset); } public int getInt(long offset) { return buffer.getInt((int) offset); } public long getLong(long offset) { return buffer.getLong((int) offset); } public float getFloat(long offset) { return buffer.getFloat((int) offset); } public double getDouble(long offset) { return buffer.getDouble((int) offset); } public void putByte(long offset, byte value) { buffer.put((int) offset, value); } public void putShort(long offset, short value) { buffer.putShort((int) offset, value); } public void putInt(long offset, int value) { buffer.putInt((int) offset, value); } public void putLong(long offset, long value) { buffer.putLong((int) offset, value); } public void putFloat(long offset, float value) { buffer.putFloat((int) offset, value); } public void putDouble(long offset, double value) { buffer.putDouble((int) offset, value); } public String getString(long offset, int size) { return BufferUtil.getString(BufferUtil.slice(buffer, (int) offset), Charset.defaultCharset()); } public void putString(long offset, String string) { BufferUtil.putString(BufferUtil.slice(buffer, (int) offset), Charset.defaultCharset(), string); } @Override public void get(long offset, byte[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len).get(dst, off, len); } @Override public void get(long offset, short[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Short.SIZE / 8).asShortBuffer().get(dst, off, len); } @Override public void get(long offset, int[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Integer.SIZE / 8).asIntBuffer().get(dst, off, len); } @Override public void get(long offset, long[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Long.SIZE / 8).asLongBuffer().get(dst, off, len); } @Override public void get(long offset, float[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Float.SIZE / 8).asFloatBuffer().get(dst, off, len); } @Override public void get(long offset, double[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Double.SIZE / 8).asDoubleBuffer().get(dst, off, len); } @Override public void put(long offset, byte[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len).put(dst, off, len); } @Override public void put(long offset, short[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Short.SIZE / 8).asShortBuffer().put(dst, off, len); } @Override public void put(long offset, int[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Integer.SIZE / 8).asIntBuffer().put(dst, off, len); } @Override public void put(long offset, long[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Long.SIZE / 8).asLongBuffer().put(dst, off, len); } @Override public void put(long offset, float[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Float.SIZE / 8).asFloatBuffer().put(dst, off, len); } @Override public void put(long offset, double[] dst, int off, int len) { BufferUtil.slice(buffer, (int) offset, len * Double.SIZE / 8).asDoubleBuffer().put(dst, off, len); } @Override public String getString(long offset) { return BufferUtil.getString(BufferUtil.slice(buffer, (int) offset), Charset.defaultCharset()); } @Override public String getString(long offset, int maxLength, Charset cs) { return BufferUtil.getString(BufferUtil.slice(buffer, (int) offset, maxLength), cs); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { BufferUtil.putString(BufferUtil.slice(buffer, (int) offset, maxLength), cs, string); } @Override public int indexOf(long offset, byte value, int maxlen) { for (; offset > -1; ++offset) { if (buffer.get((int) offset) == value) { return (int) offset; } } return -1; } @Override public void setMemory(long offset, long size, byte value) { for (int i = 0; i < size; ++i) { buffer.put((int) offset + i, value); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/AbstractMemoryIO.java000066400000000000000000000100401201747543600242120ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.*; /** * Base implementations of some MemoryIO operations. */ abstract public class AbstractMemoryIO extends MemoryIO { protected static final void checkBounds(long size, long off, long len) { if ((off | len | (off + len) | (size - (off + len))) < 0) { throw new IndexOutOfBoundsException(); } } public int indexOf(long offset, byte value) { return indexOf(offset, value, Integer.MAX_VALUE); } public long getAddress(long offset) { return AddressIO.INSTANCE.getAddress(this, offset); } public void putAddress(long offset, long value) { AddressIO.INSTANCE.putAddress(this, offset, value); } public void putAddress(long offset, Address value) { AddressIO.INSTANCE.putAddress(this, offset, value.longValue()); } public final long getNativeLong(long offset) { return NativeLongIO.INSTANCE.getLong(this, offset); } public MemoryIO slice(long offset) { return new ShareMemoryIO(this, offset); } public MemoryIO slice(long offset, long size) { return new BoundedMemoryIO(this, offset, size); } public void putNativeLong(long offset, long value) { NativeLongIO.INSTANCE.putLong(this, offset, value); } public void transferTo(long offset, MemoryIO other, long otherOffset, long count) { for (long i = 0; i < count; ++i) { other.putByte(otherOffset + i, getByte(offset + i)); } } public void transferFrom(long offset, MemoryIO other, long otherOffset, long count) { for (long i = 0; i < count; ++i) { putByte(offset + i, other.getByte(otherOffset + i)); } } // // Optimize reading/writing pointers. // private static interface AddressIO { public long getAddress(MemoryIO io, long offset); public void putAddress(MemoryIO io, long offset, long address); public static class AddressIO32 implements AddressIO { public static final AddressIO _INSTANCE = new AddressIO32(); public long getAddress(MemoryIO io, long offset) { return io.getInt(offset); } public void putAddress(MemoryIO io, long offset, long address) { io.putInt(offset, (int) address); } } public static class AddressIO64 implements AddressIO { public static final AddressIO _INSTANCE = new AddressIO64(); public long getAddress(MemoryIO io, long offset) { return io.getLong(offset); } public void putAddress(MemoryIO io, long offset, long address) { io.putLong(offset, address); } } public static final AddressIO INSTANCE = Platform.getPlatform().addressSize() == 32 ? AddressIO32._INSTANCE : AddressIO64._INSTANCE; } // // Optimize reading/writing native long values. // private static interface NativeLongIO { public long getLong(MemoryIO io, long offset); public void putLong(MemoryIO io, long offset, long value); public static class LongIO32 implements NativeLongIO { public static final NativeLongIO _INSTANCE = new LongIO32(); public long getLong(MemoryIO io, long offset) { return io.getInt(offset); } public void putLong(MemoryIO io, long offset, long value) { io.putInt(offset, (int) value); } } public static class LongIO64 implements NativeLongIO { public static final NativeLongIO _INSTANCE = new LongIO64(); public long getLong(MemoryIO io, long offset) { return io.getLong(offset); } public void putLong(MemoryIO io, long offset, long value) { io.putLong(offset, value); } } public static final NativeLongIO INSTANCE = Platform.getPlatform().longSize() == 32 ? LongIO32._INSTANCE : LongIO64._INSTANCE; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/BoundedMemoryIO.java000066400000000000000000000154661201747543600240500ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.Address; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import java.nio.charset.Charset; public class BoundedMemoryIO extends AbstractMemoryIO implements DelegatingMemoryIO { private final long base, size; private final MemoryIO io; public BoundedMemoryIO(MemoryIO parent, long offset, long size) { this.io = parent; this.base = offset; this.size = size; } public boolean isDirect() { return getDelegatedMemoryIO().isDirect(); } public long address() { return getDelegatedMemoryIO().address(); } public MemoryIO getDelegatedMemoryIO() { return io; } @Override public byte getByte(long offset) { checkBounds(size, offset, 1); return io.getByte(base + offset); } @Override public short getShort(long offset) { checkBounds(size, offset, 2); return io.getShort(base + offset); } @Override public int getInt(long offset) { checkBounds(size, offset, 4); return io.getInt(base + offset); } @Override public long getLong(long offset) { checkBounds(size, offset, 8); return io.getLong(base + offset); } @Override public float getFloat(long offset) { checkBounds(size, offset, 4); return io.getFloat(base + offset); } @Override public double getDouble(long offset) { checkBounds(size, offset, 8); return io.getDouble(base + offset); } public Pointer getPointer(long offset) { checkBounds(size, offset, Address.SIZE / 8); return io.getPointer(base + offset); } public MemoryIO getMemoryIO(long offset) { checkBounds(this.size, base + offset, Address.SIZE / 8); return io.getMemoryIO(base + offset); } public MemoryIO getMemoryIO(long offset, long size) { checkBounds(this.size, base + offset, Address.SIZE / 8); return io.getMemoryIO(base + offset, size); } @Override public void putByte(long offset, byte value) { checkBounds(size, offset, 1); io.putByte(base + offset, value); } @Override public void putShort(long offset, short value) { checkBounds(size, offset, 2); io.putShort(base + offset, value); } @Override public void putInt(long offset, int value) { checkBounds(size, offset, 4); io.putInt(base + offset, value); } @Override public void putLong(long offset, long value) { checkBounds(size, offset, 8); io.putLong(base + offset, value); } @Override public void putFloat(long offset, float value) { checkBounds(size, offset, 4); io.putFloat(base + offset, value); } @Override public void putDouble(long offset, double value) { checkBounds(size, offset, 8); io.putDouble(base + offset, value); } public void putPointer(long offset, Pointer value) { checkBounds(size, offset, Address.SIZE / 8); io.putPointer(base + offset, value); } @Override public void get(long offset, byte[] dst, int off, int len) { checkBounds(size, offset, len); io.get(base + offset, dst, off, len); } @Override public void put(long offset, byte[] dst, int off, int len) { checkBounds(size, offset, len); io.put(base + offset, dst, off, len); } @Override public void get(long offset, short[] dst, int off, int len) { checkBounds(size, offset, len * Short.SIZE / 8); io.get(base + offset, dst, off, len); } @Override public void put(long offset, short[] dst, int off, int len) { checkBounds(size, offset, len * Short.SIZE / 8); io.put(base + offset, dst, off, len); } @Override public void get(long offset, int[] dst, int off, int len) { checkBounds(size, offset, len * Integer.SIZE / 8); io.get(base + offset, dst, off, len); } @Override public void put(long offset, int[] dst, int off, int len) { checkBounds(size, offset, len * Integer.SIZE / 8); io.put(base + offset, dst, off, len); } @Override public void get(long offset, long[] dst, int off, int len) { checkBounds(size, offset, len * Long.SIZE / 8); io.get(base + offset, dst, off, len); } @Override public void put(long offset, long[] dst, int off, int len) { checkBounds(size, offset, len * Long.SIZE / 8); io.put(base + offset, dst, off, len); } @Override public void get(long offset, float[] dst, int off, int len) { checkBounds(size, offset, len * Float.SIZE / 8); io.get(base + offset, dst, off, len); } @Override public void put(long offset, float[] dst, int off, int len) { checkBounds(size, offset, len * Float.SIZE / 8); io.put(base + offset, dst, off, len); } @Override public void get(long offset, double[] dst, int off, int len) { checkBounds(size, offset, len * Double.SIZE / 8); io.get(base + offset, dst, off, len); } @Override public void put(long offset, double[] dst, int off, int len) { checkBounds(size, offset, len * Double.SIZE / 8); io.put(base + offset, dst, off, len); } @Override public long getAddress(long offset) { checkBounds(size, offset, Address.SIZE >> 3); return io.getAddress(base + offset); } @Override public String getString(long offset, int maxLength, Charset cs) { checkBounds(size, offset, maxLength); return io.getString(base + offset, maxLength, cs); } @Override public String getString(long offset) { return io.getString(base + offset, (int) size, Charset.defaultCharset()); } @Override public void putAddress(long offset, long value) { checkBounds(size, offset, Address.SIZE >> 3); io.putAddress(base + offset, value); } @Override public void putAddress(long offset, Address value) { checkBounds(size, offset, Address.SIZE >> 3); io.putAddress(base + offset, value); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { checkBounds(size, offset, maxLength); io.putString(base + offset, string, maxLength, cs); } @Override public int indexOf(long offset, byte value) { return io.indexOf(base + offset, value, (int) size); } @Override public int indexOf(long offset, byte value, int maxlen) { checkBounds(size, offset, maxlen); return io.indexOf(base + offset, value, maxlen); } @Override public void setMemory(long offset, long size, byte value) { checkBounds(this.size, base + offset, size); io.setMemory(base + offset, size, value); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/DelegatingMemoryIO.java000066400000000000000000000002321201747543600245140ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.MemoryIO; public interface DelegatingMemoryIO { public MemoryIO getDelegatedMemoryIO(); } jaffl-0.5.9/src/com/kenai/jaffl/provider/InvocationSession.java000066400000000000000000000011721201747543600245110ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import java.util.ArrayList; /** * Holds information for each invocation of a native function */ public class InvocationSession { private ArrayList list; public InvocationSession() { } public static interface PostInvoke { void postInvoke(); } public void finish() { if (list != null) for (PostInvoke p : list) { p.postInvoke(); } } public void addPostInvoke(PostInvoke postInvoke) { if (list == null) { list = new ArrayList(); } list.add(postInvoke); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/Invoker.java000066400000000000000000000002311201747543600224440ustar00rootroot00000000000000 package com.kenai.jaffl.provider; /** * Interface for any invocable function */ public interface Invoker { Object invoke(Object[] parameters); } jaffl-0.5.9/src/com/kenai/jaffl/provider/Library.java000066400000000000000000000035121201747543600224400ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.Platform; import java.io.File; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; /** * */ public abstract class Library { private static final class StaticDataHolder { private static final List userLibraryPath = new CopyOnWriteArrayList(); static { userLibraryPath.addAll(getPropertyPaths("jaffl.library.path")); // Add JNA paths for compatibility userLibraryPath.addAll(getPropertyPaths("jna.library.path")); } }; public abstract Invoker getInvoker(Method method, Map options); public abstract Object libraryLock(); public static String locateLibrary(String libraryName) { if (new File(libraryName).isAbsolute()) { return libraryName; } List searchPath = new LinkedList(); // // Prepend any custom search paths specifically for this library // searchPath.addAll(0, com.kenai.jaffl.Library.getLibraryPath(libraryName)); searchPath.addAll(StaticDataHolder.userLibraryPath); String path = Platform.getPlatform().locateLibrary(libraryName, searchPath); return path != null ? path : null; } private static final List getPropertyPaths(String propName) { String value = System.getProperty(propName); if (value != null) { String[] paths = value.split(File.pathSeparator); return new ArrayList(Arrays.asList(paths)); } return Collections.emptyList(); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/MemoryManager.java000066400000000000000000000012261201747543600235770ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import java.nio.Buffer; import java.nio.ByteBuffer; /** * Manages access to various types of java and native memory. */ public interface MemoryManager { public abstract MemoryIO allocate(int size); public abstract MemoryIO allocateDirect(int size); public abstract MemoryIO allocateDirect(int size, boolean clear); public abstract MemoryIO wrap(Pointer address); public abstract MemoryIO wrap(Pointer address, int size); public abstract MemoryIO wrap(ByteBuffer buffer); public abstract Pointer getBufferPointer(Buffer buffer); } jaffl-0.5.9/src/com/kenai/jaffl/provider/NativeInvocationHandler.java000066400000000000000000000247671201747543600256310ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.CallingConvention; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.Platform; import com.kenai.jaffl.annotations.StdCall; import com.kenai.jaffl.annotations.Synchronized; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.HashMap; import java.util.Map; /** * InvocationHandler used to map invocations on a java interface to the * correct native function. */ public class NativeInvocationHandler implements InvocationHandler { private final InvokerMap invokers; private final Library library; private final Map optionsMap; private final Class interfaceClass; /** * Creates a new InvocationHandler instance. * * @param library the native library to call * @param interfaceClass the interface that defines the methods in the * native library that will be accessed via this handler. * @param optionsMap a dictionary of options to apply to this library. */ public NativeInvocationHandler(Library library, Class interfaceClass, Map optionsMap) { this.library = library; this.interfaceClass = interfaceClass; this.optionsMap = new HashMap(optionsMap); if (interfaceClass.getAnnotation(StdCall.class) != null) { this.optionsMap.put(LibraryOption.CallingConvention, CallingConvention.STDCALL); } invokers = new InvokerMap(interfaceClass.getDeclaredMethods().length); } /** * Creates a new InvocationHandler mapping methods in the interfaceClass * to functions in the native library. * @param the type of interfaceClass * @param libraryName the native library to load * @param interfaceClass the interface that contains the native method description * @param optionsMap a dictionary of options to apply to this library. * @return a new instance of interfaceClass that can be used to call * functions in the native library. */ public static T wrapInterface(Library library, Class interfaceClass, Map optionsMap) { return interfaceClass.cast(Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{ interfaceClass }, new NativeInvocationHandler(library, interfaceClass, optionsMap))); } /** * Gets the {@link Invoker} for a method. * * @param method the method defined in the interface class * @return the Invoker to use to invoke the native function */ private Invoker getInvoker(Method method) { Invoker invoker = invokers.get(method); if (invoker != null) { return invoker; } return createInvoker(method); } /** * Creates a new Invoker to invoke method in the native library * @param method the method to invoke * @return a new Invoker */ private synchronized Invoker createInvoker(Method method) { // // Recheck in case another thread already created the same mapping // Invoker invoker = invokers.get(method); if (invoker != null) { return invoker; } invoker = library.getInvoker(method, optionsMap); // // If either the method or the library is specified as requiring // synchronization, then wrap the raw invoker in a synchronized proxy // if (method.getAnnotation(Synchronized.class) != null || interfaceClass.getAnnotation(Synchronized.class) != null) { // // Synchronize on the library, so multiple different interface // definitions for the same library synchronize on the same object. // invoker = new SynchronizedInvoker(invoker, library.libraryLock()); } invokers.put(method, invoker); return invoker; } public Object invoke(Object self, Method method, Object[] argArray) throws Throwable { return getInvoker(method).invoke(argArray); } private static final class SynchronizedInvoker implements Invoker { private final Object lock; private final Invoker invoker; public SynchronizedInvoker(Invoker invoker, Object lock) { this.invoker = invoker; this.lock = lock; } public Object invoke(Object[] parameters) { synchronized (lock) { return invoker.invoke(parameters); } } } /** * A custom map-like class for fast mapping between a Method and * an Invoker. *

* This is not a standard Map - it does not support removing or * replacing of elements, just gets and insertions. *

*

* It is optimized for many-reads, minimal writes. *

*/ private static final class InvokerMap { // // According to the new JMM: // In effect, because the new memory model places stricter constraints // on reordering of volatile field accesses with other field accesses, // volatile or not, anything that was visible to thread A when it writes // to volatile field f becomes visible to thread B when it reads f. // // Ergo, by doing copy-on-write of the entire array to a temp variable, // then inserting into the temp array, and assigning that temp array // to 'entries' after all writes are done, will ensure that everything // is fully visible to readers. // private volatile Object[] entries; private static final float loadFactor = 0.5f; /** * Creates a new Method->Invoker map * * @param maxEntries the maximum size of the map. No more entries than * this can be added. */ public InvokerMap(final int maxEntries) { final int capacity = (int) ((float) maxEntries / loadFactor) + 1; int size = 1; // Make the table power-of-2 sized so indexFor() is faster while (size < capacity) { size <<= 1; } entries = new Object[size * 2]; // write volatile } /** * Creates a new mapping between a Method and an Invoker * * @param method the Method to create the mapping for * @param invoker the Invoker to associate with the method. */ public final synchronized void put(Method method, Invoker invoker) { Object[] tmp = new Object[entries.length]; System.arraycopy(entries, 0, tmp, 0, tmp.length); int start = indexFor(method, tmp.length); Loop: for (int loop = 0; loop < 2; ++loop) { for (int i = start; i < tmp.length - 1; i += 2) { if (tmp[i] == null) { tmp[i] = method; tmp[i + 1] = invoker; break Loop; } } start = 0; // wrap around } entries = tmp; // write volatile } /** * Gets an Invoker from the map for method * * @param method the method to get an Invoker for * @return an Invoker if the method is in the table, else null */ public final Invoker get(Method method) { Object[] tmp = entries; // read volatile int start = indexFor(method, tmp.length); Loop: for (int loop = 0; loop < 2; ++loop) { for (int i = start; i < tmp.length - 1; i += 2) { if (tmp[i] == method) { return (Invoker) tmp[i + 1]; } if (tmp[i] == null) { break Loop; } } start = 0; // wrap around } return null; } /** * Abstracts different hashing methods, depending on the underlying jvm */ private static interface Hasher { public int hash(Method key); } /** * Uses System.identityHashCode() to generate a hash for the method. *

* This is fastest on JDK6+ where System.identityHashCode() is an intrinsic * and is inlined. *

*/ private static final class IdentityHasherSingleton { private static final class IdentityHasher implements Hasher { public final int hash(Method key) { final int h = System.identityHashCode(key); return (h << 1) - (h << 8); } } public static final Hasher getInstance() { return new IdentityHasher(); } } /** * Uses Method#hashCode to generate a hash for the method. *

* This is faster than using System.identityHashCode() on JDK5, since * System.identityHashCode() is not inlined. *

*/ private static final class NameHasherSingleton { private static final class NameHasher implements Hasher { public final int hash(Method key) { int h = key.hashCode(); h += (h << 15) ^ 0xffffcd7d; h ^= (h >>> 10); h += (h << 3); h ^= (h >>> 6); h += (h << 2) + (h << 14); return h ^ (h >>> 16); } } public static final Hasher getInstance() { return new NameHasher(); } } // // On JVM6 and above, System.identityHashCode is inlined so very fast // private static final Hasher hasher = Platform.getPlatform().getJavaMajorVersion() >= 6 ? IdentityHasherSingleton.getInstance() : NameHasherSingleton.getInstance(); /** * Gets the index in the hash table of the method. * * @param key the method to locate * @param length the length of the entries array * @return */ private static final int indexFor(Method key, int length) { return hasher.hash(key) & (length - 1); } } }jaffl-0.5.9/src/com/kenai/jaffl/provider/NativeType.java000066400000000000000000000003431201747543600231230ustar00rootroot00000000000000 package com.kenai.jaffl.provider; public enum NativeType { VOID, SCHAR, UCHAR, SSHORT, USHORT, SINT, UINT, SLONG, ULONG, SLONGLONG, ULONGLONG, FLOAT, DOUBLE, ADDRESS; } jaffl-0.5.9/src/com/kenai/jaffl/provider/NullMemoryIO.java000066400000000000000000000070171201747543600233730ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import java.nio.charset.Charset; public final class NullMemoryIO extends AbstractMemoryIO { private static final String msg = "Attempted access to a NULL memory address"; public static final MemoryIO INSTANCE = new NullMemoryIO(); private static final NullPointerException npe() { return new NullPointerException(msg); } public final byte getByte(long offset) { throw npe(); } public final short getShort(long offset) { throw npe(); } public final int getInt(long offset) { throw npe(); } public final long getLong(long offset) { throw npe(); } public final float getFloat(long offset) { throw npe(); } public final double getDouble(long offset) { throw npe(); } public final void putByte(long offset, byte value) { throw npe(); } public final void putShort(long offset, short value) { throw npe(); } public final void putInt(long offset, int value) { throw npe(); } public final void putLong(long offset, long value) { throw npe(); } public final void putFloat(long offset, float value) { throw npe(); } public final void putDouble(long offset, double value) { throw npe(); } public final void get(long offset, byte[] dst, int off, int len) { throw npe(); } public final void put(long offset, byte[] dst, int off, int len) { throw npe(); } public final void get(long offset, short[] dst, int off, int len) { throw npe(); } public final void put(long offset, short[] dst, int off, int len) { throw npe(); } public final void get(long offset, int[] dst, int off, int len) { throw npe(); } public final void put(long offset, int[] dst, int off, int len) { throw npe(); } public final void get(long offset, long[] dst, int off, int len) { throw npe(); } public final void put(long offset, long[] dst, int off, int len) { throw npe(); } public final void get(long offset, float[] dst, int off, int len) { throw npe(); } public final void put(long offset, float[] dst, int off, int len) { throw npe(); } public final void get(long offset, double[] dst, int off, int len) { throw npe(); } public final void put(long offset, double[] dst, int off, int len) { throw npe(); } public final MemoryIO getMemoryIO(long offset) { throw npe(); } public final MemoryIO getMemoryIO(long offset, long size) { throw npe(); } public final Pointer getPointer(long offset) { throw npe(); } public final void putPointer(long offset, Pointer value) { throw npe(); } public String getString(long offset) { throw npe(); } @Override public String getString(long offset, int maxLength, Charset cs) { throw npe(); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { throw npe(); } public final int indexOf(long offset, byte value, int maxlen) { throw npe(); } public final boolean isDirect() { return true; } @Override public long address() { return 0; } @Override public final void setMemory(long offset, long size, byte value) { throw npe(); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/ShareMemoryIO.java000066400000000000000000000111021201747543600235110ustar00rootroot00000000000000package com.kenai.jaffl.provider; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import java.nio.charset.Charset; /** * */ public class ShareMemoryIO extends AbstractMemoryIO implements DelegatingMemoryIO { private final MemoryIO io; private final long base; public ShareMemoryIO(MemoryIO parent, long offset) { this.io = parent; this.base = offset; } public final boolean isDirect() { return io.isDirect(); } @Override public long address() { return io.address() + base; } public final MemoryIO getDelegatedMemoryIO() { return io; } @Override public byte getByte(long offset) { return io.getByte(base + offset); } @Override public short getShort(long offset) { return io.getShort(base + offset); } @Override public int getInt(long offset) { return io.getInt(base + offset); } @Override public long getLong(long offset) { return io.getLong(base + offset); } @Override public float getFloat(long offset) { return io.getFloat(base + offset); } @Override public double getDouble(long offset) { return io.getDouble(base + offset); } public MemoryIO getMemoryIO(long offset) { return io.getMemoryIO(base + offset); } public MemoryIO getMemoryIO(long offset, long size) { return io.getMemoryIO(base + offset, size); } public Pointer getPointer(long offset) { return io.getPointer(base + offset); } @Override public String getString(long offset) { return io.getString(base + offset); } @Override public String getString(long offset, int maxLength, Charset cs) { return io.getString(base + offset, maxLength, cs); } @Override public void putByte(long offset, byte value) { io.putByte(base + offset, value); } @Override public void putShort(long offset, short value) { io.putShort(base + offset, value); } @Override public void putInt(long offset, int value) { io.putInt(base + offset, value); } @Override public void putLong(long offset, long value) { io.putLong(base + offset, value); } @Override public void putFloat(long offset, float value) { io.putFloat(base + offset, value); } @Override public void putDouble(long offset, double value) { io.putDouble(base + offset, value); } public void putPointer(long offset, Pointer value) { io.putPointer(base + offset, value); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { io.putString(base + offset, string, maxLength, cs); } @Override public void get(long offset, byte[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, byte[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public void get(long offset, short[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, short[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public void get(long offset, int[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, int[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public void get(long offset, long[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, long[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public void get(long offset, float[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, float[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public void get(long offset, double[] dst, int off, int len) { io.get(base + offset, dst, off, len); } @Override public void put(long offset, double[] dst, int off, int len) { io.put(base + offset, dst, off, len); } @Override public int indexOf(long offset, byte value, int maxlen) { return io.indexOf(base + offset, value, maxlen); } @Override public void setMemory(long offset, long size, byte value) { io.setMemory(base + offset, size, value); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/StringIO.java000066400000000000000000000122651201747543600225370ustar00rootroot00000000000000 package com.kenai.jaffl.provider; import com.kenai.jaffl.util.BufferUtil; import java.lang.ref.SoftReference; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CodingErrorAction; /** * */ public final class StringIO { private static final class StaticDataHolder { static final StringIO INSTANCE = new StringIO(Charset.defaultCharset()); static final ThreadLocal> ENCODER = new ThreadLocal>(); static final ThreadLocal> DECODER = new ThreadLocal>(); } private final Charset charset; public static StringIO getStringIO() { return StaticDataHolder.INSTANCE; } public static StringIO getStringIO(Charset charset) { return new StringIO(charset); } private StringIO(Charset charset) { this.charset = charset; } private static CharsetEncoder getEncoder(Charset charset) { SoftReference ref = StaticDataHolder.ENCODER.get(); CharsetEncoder encoder; if (ref != null && (encoder = ref.get()) != null && encoder.charset() == charset) { return encoder; } return initEncoder(charset); } private static CharsetDecoder getDecoder(Charset charset) { SoftReference ref = StaticDataHolder.DECODER.get(); CharsetDecoder decoder; if (ref != null && (decoder = ref.get()) != null && decoder.charset() == charset) { return decoder; } return initDecoder(charset); } private static CharsetEncoder initEncoder(Charset charset) { CharsetEncoder encoder = charset.newEncoder(); encoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); StaticDataHolder.ENCODER.set(new SoftReference(encoder)); return encoder; } private static CharsetDecoder initDecoder(Charset charset) { CharsetDecoder decoder = charset.newDecoder(); decoder.onMalformedInput(CodingErrorAction.REPLACE).onUnmappableCharacter(CodingErrorAction.REPLACE); StaticDataHolder.DECODER.set(new SoftReference(decoder)); return decoder; } public final ByteBuffer toNative(final CharSequence value, final int minSize, boolean copyIn) { return toNative(getEncoder(charset), value, minSize, copyIn); } public final ByteBuffer toNative(final CharSequence value, final ByteBuffer buf) { return toNative(getEncoder(charset), value, buf); } private static ByteBuffer toNative(CharsetEncoder encoder, final CharSequence value, final int minSize, boolean copyIn) { // Calculate the raw byte size required (with allowance for NUL termination) final int len = (int) (((float)Math.max(minSize, value.length()) + 1) * encoder.maxBytesPerChar()); final ByteBuffer buf = ByteBuffer.allocate(len); if (copyIn) { toNative(encoder, value, buf); } return buf; } private static ByteBuffer toNative(CharsetEncoder encoder, final CharSequence value, final ByteBuffer buf) { // // Copy the string to native memory // buf.mark(); try { encoder.reset(); encoder.encode(CharBuffer.wrap(value), buf, true); encoder.flush(buf); nulTerminate(encoder, buf); } finally { buf.reset(); } return buf; } public final CharSequence fromNative(final ByteBuffer buf, final int maxSize) { // Find the NUL terminator and limit to that, so the // StringBuffer/StringBuilder does not have superfluous NUL chars int end = BufferUtil.positionOf(buf, (byte) 0); if (end < 0 || end > maxSize) { end = maxSize; } final int limit = buf.limit(); buf.limit(end); try { return getDecoder(charset).reset().decode(buf); } catch (CharacterCodingException ex) { throw new Error("Illegal character data in native string", ex); } finally { buf.limit(limit); } } public final CharSequence fromNative(final ByteBuffer buf) { try { return getDecoder(charset).reset().decode(buf); } catch (CharacterCodingException ex) { throw new Error("Illegal character data in native string", ex); } } public final void nulTerminate(ByteBuffer buf) { nulTerminate(getEncoder(charset), buf); } private static void nulTerminate(CharsetEncoder encoder, ByteBuffer buf) { // NUL terminate the string int nulSize = Math.round(encoder.maxBytesPerChar()); while (nulSize >= 4) { buf.putInt(0); nulSize -= 4; } if (nulSize >= 2) { buf.putShort((short) 0); nulSize -= 2; } if (nulSize >= 1) { buf.put((byte) 0); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/000077500000000000000000000000001201747543600211065ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AbstractX86StubCompiler.java000066400000000000000000000073741201747543600263660ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jffi.MemoryIO; import com.kenai.jffi.NativeMethod; import com.kenai.jffi.NativeMethods; import com.kenai.jffi.PageManager; import com.kenai.jnr.x86asm.Assembler; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; import java.util.logging.Level; import java.util.logging.Logger; /** * Base class for most X86_32/X86_64 stub compilers */ abstract class AbstractX86StubCompiler extends StubCompiler { private static final class StaticDataHolder { // Keep a reference from the loaded class to the pages holding the code for that class. static final Map PAGES = Collections.synchronizedMap(new WeakHashMap()); } final List stubs = new LinkedList(); final class Stub { final String name; final String signature; final Assembler assembler; public Stub(String name, String signature, Assembler assembler) { this.name = name; this.signature = signature; this.assembler = assembler; } } static final class PageHolder { final PageManager pm; final long memory; final long pageCount; public PageHolder(PageManager pm, long memory, long pageCount) { this.pm = pm; this.memory = memory; this.pageCount = pageCount; } @Override protected void finalize() throws Throwable { try { pm.freePages(memory, (int) pageCount); } catch (Throwable t) { Logger.getLogger(getClass().getName()).log(Level.WARNING, "Exception when freeing native pages: %s", t.getLocalizedMessage()); } finally { super.finalize(); } } } @Override void attach(Class clazz) { if (stubs.isEmpty()) { return; } long codeSize = 0; for (Stub stub : stubs) { // add 8 bytes for alignment codeSize += stub.assembler.codeSize() + 8; } PageManager pm = PageManager.getInstance(); long npages = (codeSize + pm.pageSize() - 1) / pm.pageSize(); // Allocate some native memory for it long code = pm.allocatePages((int) npages, PageManager.PROT_READ | PageManager.PROT_WRITE); if (code == 0) { throw new OutOfMemoryError("allocatePages failed for codeSize=" + codeSize); } PageHolder page = new PageHolder(pm, code, npages); // Now relocate/copy all the assembler stubs into the real code area List methods = new ArrayList(stubs.size()); long fn = code; for (Stub stub : stubs) { Assembler asm = stub.assembler; // align the start of all functions on a 8 byte boundary fn = align(fn, 8); ByteBuffer buf = MemoryIO.getInstance().newDirectByteBuffer(fn, asm.codeSize()).order(ByteOrder.LITTLE_ENDIAN); stub.assembler.relocCode(buf, fn); methods.add(new NativeMethod(fn, stub.name, stub.signature)); fn += asm.codeSize(); } pm.protectPages(code, (int) npages, PageManager.PROT_READ | PageManager.PROT_EXEC); NativeMethods.register(clazz, methods); StaticDataHolder.PAGES.put(clazz, page); } static final int align(int offset, int align) { return align + ((offset - 1) & ~(align - 1)); } static final long align(long offset, long align) { return align + ((offset - 1) & ~(align - 1)); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AllocatedDirectMemoryIO.java000066400000000000000000000012061201747543600264140ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; class AllocatedDirectMemoryIO extends DirectMemoryIO { private volatile boolean allocated = true; public AllocatedDirectMemoryIO(int size, boolean clear) { super(IO.allocateMemory(size, clear)); if (address == 0L) { throw new OutOfMemoryError("Failed to allocate " + size + " bytes"); } } @Override protected void finalize() throws Throwable { try { if (allocated) { IO.freeMemory(address); allocated = false; } } finally { super.finalize(); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/ArrayMemoryIO.java000066400000000000000000000014551201747543600244550ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.provider.AbstractArrayMemoryIO; public final class ArrayMemoryIO extends AbstractArrayMemoryIO { public ArrayMemoryIO(int size) { super(size); } @Override public MemoryIO getMemoryIO(long offset) { return MemoryUtil.newMemoryIO(getAddress(offset)); } @Override public MemoryIO getMemoryIO(long offset, long size) { return MemoryUtil.newMemoryIO(getAddress(offset), size); } @Override public Pointer getPointer(long offset) { return MemoryUtil.newPointer(getAddress(offset)); } @Override public void putPointer(long offset, Pointer value) { putAddress(offset, value.address()); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AsmClassLoader.java000066400000000000000000000006001201747543600246020ustar00rootroot00000000000000package com.kenai.jaffl.provider.jffi; final class AsmClassLoader extends ClassLoader { static final AsmClassLoader INSTANCE = new AsmClassLoader(); public AsmClassLoader() { } public AsmClassLoader(ClassLoader parent) { super(parent); } public Class defineClass(String name, byte[] b) { return defineClass(name, b, 0, b.length); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AsmLibraryLoader.java000066400000000000000000001543271201747543600251610ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.Address; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.NativeLong; import com.kenai.jaffl.ParameterFlags; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.annotations.StdCall; import com.kenai.jaffl.byref.ByReference; import com.kenai.jaffl.mapper.FromNativeContext; import com.kenai.jaffl.mapper.FromNativeConverter; import com.kenai.jaffl.mapper.FunctionMapper; import com.kenai.jaffl.mapper.MethodParameterContext; import com.kenai.jaffl.mapper.MethodResultContext; import com.kenai.jaffl.mapper.ToNativeContext; import com.kenai.jaffl.mapper.ToNativeConverter; import com.kenai.jaffl.mapper.TypeMapper; import com.kenai.jaffl.provider.InvocationSession; import com.kenai.jaffl.struct.Struct; import com.kenai.jffi.ArrayFlags; import com.kenai.jffi.CallingConvention; import com.kenai.jffi.Function; import com.kenai.jffi.HeapInvocationBuffer; import com.kenai.jffi.InvocationBuffer; import com.kenai.jffi.Platform; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; import java.lang.reflect.Method; import java.nio.Buffer; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicLong; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.ClassWriter; import org.objectweb.asm.Label; import org.objectweb.asm.Opcodes; import static com.kenai.jaffl.provider.jffi.CodegenUtils.*; import static com.kenai.jaffl.provider.jffi.NumberUtil.*; import static com.kenai.jaffl.provider.jffi.AsmUtil.*; public class AsmLibraryLoader extends LibraryLoader implements Opcodes { public final static boolean DEBUG = false || Boolean.getBoolean("jaffl.compile.dump"); private static final class SingletonHolder { static final LibraryLoader INSTANCE = new AsmLibraryLoader(); } private static final boolean FAST_NUMERIC_AVAILABLE = isFastNumericAvailable(); private static final boolean FAST_LONG_AVAILABLE = isFastLongAvailable(); private final AtomicLong nextClassID = new AtomicLong(0); private final AtomicLong nextIvarID = new AtomicLong(0); private final AtomicLong nextMethodID = new AtomicLong(0); static final LibraryLoader getInstance() { return SingletonHolder.INSTANCE; } boolean isInterfaceSupported(Class interfaceClass, Map options) { TypeMapper typeMapper = options.containsKey(LibraryOption.TypeMapper) ? (TypeMapper) options.get(LibraryOption.TypeMapper) : NullTypeMapper.INSTANCE; for (Method m : interfaceClass.getDeclaredMethods()) { if (!isReturnTypeSupported(m.getReturnType()) && getResultConverter(m, typeMapper) == null) { System.err.println("Unsupported return type: " + m.getReturnType()); return false; } for (Class c: m.getParameterTypes()) { if (!isParameterTypeSupported(c) && typeMapper.getToNativeConverter(c) == null) { System.err.println("Unsupported parameter type: " + c); return false; } } } return true; } private boolean isReturnTypeSupported(Class type) { return type.isPrimitive() || Byte.class == type || Short.class == type || Integer.class == type || Long.class == type || Float.class == type || Double.class == type || NativeLong.class == type || Pointer.class == type || Address.class == type || String.class == type || Struct.class.isAssignableFrom(type); } private boolean isParameterTypeSupported(Class type) { return type.isPrimitive() || Byte.class == type || Short.class == type || Integer.class == type || Long.class == type || Float.class == type || Double.class == type || NativeLong.class == type || Pointer.class.isAssignableFrom(type) || Address.class.isAssignableFrom(type) || Enum.class.isAssignableFrom(type) || Buffer.class.isAssignableFrom(type) || (type.isArray() && type.getComponentType().isPrimitive()) || Struct.class.isAssignableFrom(type) || (type.isArray() && Struct.class.isAssignableFrom(type.getComponentType())) || (type.isArray() && Pointer.class.isAssignableFrom(type.getComponentType())) || CharSequence.class.isAssignableFrom(type) || ByReference.class.isAssignableFrom(type) || StringBuilder.class.isAssignableFrom(type) || StringBuffer.class.isAssignableFrom(type); } @Override T loadLibrary(Library library, Class interfaceClass, Map libraryOptions) { return generateInterfaceImpl(library, interfaceClass, libraryOptions); } private final T generateInterfaceImpl(final Library library, Class interfaceClass, Map libraryOptions) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); ClassVisitor cv = DEBUG ? AsmUtil.newCheckClassAdapter(AsmUtil.newTraceClassVisitor(cw, System.err)) : cw; String className = p(interfaceClass) + "$jaffl$" + nextClassID.getAndIncrement(); cv.visit(V1_5, ACC_PUBLIC | ACC_FINAL, className, null, p(AbstractNativeInterface.class), new String[] { p(interfaceClass) }); // Create the constructor to set the 'library' & functions fields SkinnyMethodAdapter init = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC, "", sig(void.class, Library.class, Function[].class, FromNativeConverter[].class, ToNativeConverter[][].class), null, null)); init.start(); // Invokes the super class constructor as super(Library) init.aload(0); init.aload(1); init.invokespecial(p(AbstractNativeInterface.class), "", sig(void.class, Library.class)); final Method[] methods = interfaceClass.getMethods(); Function[] functions = new Function[methods.length]; FromNativeConverter[] resultConverters = new FromNativeConverter[methods.length]; ToNativeConverter[][] parameterConverters = new ToNativeConverter[methods.length][0]; FunctionMapper functionMapper = libraryOptions.containsKey(LibraryOption.FunctionMapper) ? (FunctionMapper) libraryOptions.get(LibraryOption.FunctionMapper) : IdentityFunctionMapper.getInstance(); TypeMapper typeMapper = libraryOptions.containsKey(LibraryOption.TypeMapper) ? (TypeMapper) libraryOptions.get(LibraryOption.TypeMapper) : NullTypeMapper.INSTANCE; com.kenai.jffi.CallingConvention libraryCallingConvention = getCallingConvention(interfaceClass, libraryOptions); StubCompiler compiler = StubCompiler.newCompiler(); for (int i = 0; i < methods.length; ++i) { Method m = methods[i]; final Class returnType = m.getReturnType(); final Class[] parameterTypes = m.getParameterTypes(); Class nativeReturnType = returnType; Class[] nativeParameterTypes = new Class[parameterTypes.length]; boolean conversionRequired = false; resultConverters[i] = getResultConverter(m, typeMapper); if (resultConverters[i] != null) { cv.visitField(ACC_PRIVATE | ACC_FINAL, getResultConverterFieldName(i), ci(FromNativeConverter.class), null, null); nativeReturnType = resultConverters[i].nativeType(); conversionRequired = true; } parameterConverters[i] = new ToNativeConverter[parameterTypes.length]; for (int pidx = 0; pidx < parameterTypes.length; ++pidx) { ToNativeConverter converter = typeMapper.getToNativeConverter(parameterTypes[pidx]); if (converter != null) { cv.visitField(ACC_PRIVATE | ACC_FINAL, getParameterConverterFieldName(i, pidx), ci(ToNativeConverter.class), null, null); nativeParameterTypes[pidx] = converter.nativeType(); parameterConverters[i][pidx] = new ToNativeProxy(converter, new MethodParameterContext(m, pidx)); conversionRequired = true; } else { nativeParameterTypes[pidx] = parameterTypes[pidx]; } } // Stash the name of the function in a static field String functionName = functionMapper.mapFunctionName(m.getName(), null); cv.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, "name_" + i, ci(String.class), null, functionName); // Allow individual methods to set the calling convention to stdcall CallingConvention callingConvention = m.getAnnotation(StdCall.class) != null ? CallingConvention.STDCALL : libraryCallingConvention; try { functions[i] = getFunction(library.findSymbolAddress(functionName), nativeReturnType, nativeParameterTypes, InvokerUtil.requiresErrno(m), callingConvention); } catch (SymbolNotFoundError ex) { cv.visitField(ACC_PRIVATE | ACC_FINAL | ACC_STATIC, "error_" + i, ci(String.class), null, ex.getMessage()); generateFunctionNotFound(cv, className, i, functionName, returnType, parameterTypes); continue; } String functionFieldName = "function_" + i; cv.visitField(ACC_PRIVATE | ACC_FINAL, functionFieldName, ci(Function.class), null, null); final boolean ignoreErrno = !InvokerUtil.requiresErrno(m); if (canCompile(compiler, nativeReturnType, nativeParameterTypes, callingConvention)) { // The method can be generated via a direct java -> jni mapping compile(compiler, functions[i], cv, className, m.getName() + (conversionRequired ? "$raw" : ""), functionFieldName, nativeReturnType, nativeParameterTypes, m.getParameterAnnotations(), callingConvention, ignoreErrno); } else { generateMethod(cv, className, m.getName() + (conversionRequired ? "$raw" : ""), functionFieldName, nativeReturnType, nativeParameterTypes, m.getParameterAnnotations(), callingConvention, ignoreErrno); } if (conversionRequired) { generateConversionMethod(cv, className, m.getName(), i, returnType, parameterTypes, nativeReturnType, nativeParameterTypes); } // The Function[] array is passed in as the second param, so generate // the constructor code to store each function in a field init.aload(0); init.aload(2); init.pushInt(i); init.aaload(); init.putfield(className, functionFieldName, ci(Function.class)); // If there is a result converter for this function, put it in a field too if (resultConverters[i] != null) { init.aload(0); init.aload(3); init.pushInt(i); init.aaload(); init.putfield(className, getResultConverterFieldName(i), ci(FromNativeConverter.class)); } for (int pidx = 0; pidx < parameterTypes.length; ++pidx) { if (parameterConverters[i][pidx] != null) { init.aload(0); init.aload(4); init.pushInt(i); init.aaload(); init.pushInt(pidx); init.aaload(); init.putfield(className, getParameterConverterFieldName(i, pidx), ci(ToNativeConverter.class)); } } } init.voidreturn(); init.visitMaxs(10, 10); init.visitEnd(); cv.visitEnd(); try { Class implClass = new AsmClassLoader(interfaceClass.getClassLoader()).defineClass(className.replace("/", "."), cw.toByteArray()); Constructor cons = implClass.getDeclaredConstructor(Library.class, Function[].class, FromNativeConverter[].class, ToNativeConverter[][].class); T result = cons.newInstance(library, functions, resultConverters, parameterConverters); // Attach any native method stubs - we have to delay this until the // implementation class is loaded for it to work. compiler.attach(implClass); return result; } catch (Throwable ex) { throw new RuntimeException(ex); } } private final FromNativeConverter getResultConverter(Method m, TypeMapper typeMapper) { Class returnType = m.getReturnType(); FromNativeConverter conv = typeMapper.getFromNativeConverter(returnType); if (conv != null) { return new FromNativeProxy(conv, new MethodResultContext(m)); } else if (Enum.class.isAssignableFrom(returnType)) { return new EnumResultConverter(returnType); } else { return null; } } private static final com.kenai.jffi.CallingConvention getCallingConvention(Class interfaceClass, Map options) { if (interfaceClass.getAnnotation(StdCall.class) != null) { return com.kenai.jffi.CallingConvention.STDCALL; } return InvokerUtil.getCallingConvention(options); } private final String getFunctionFieldName(int idx) { return "function_" + idx; } private final String getResultConverterFieldName(int idx) { return "resultConverter_" + idx; } private final String getParameterConverterFieldName(int idx, int paramIndex) { return "parameterConverter_" + idx + "_" + paramIndex; } private final void generateFunctionNotFound(ClassVisitor cv, String className, int idx, String functionName, Class returnType, Class[] parameterTypes) { SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC | ACC_FINAL, functionName, sig(returnType, parameterTypes), null, null)); mv.start(); mv.getstatic(className, "error_" + idx, ci(String.class)); mv.invokestatic(AsmRuntime.class, "newUnsatisifiedLinkError", UnsatisfiedLinkError.class, String.class); mv.athrow(); mv.visitMaxs(10, 10); mv.visitEnd(); } private final void generateConversionMethod(ClassVisitor cv, String className, String functionName, int idx, Class returnType, Class[] parameterTypes, Class nativeReturnType, Class[] nativeParameterTypes) { SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC | ACC_FINAL, functionName, sig(returnType, parameterTypes), null, null)); mv.start(); // If there is a result converter, retrieve it and put on the stack if (!returnType.equals(nativeReturnType)) { mv.aload(0); mv.getfield(className, getResultConverterFieldName(idx), ci(FromNativeConverter.class)); } mv.aload(0); // Load and convert the parameters int lvar = 1; for (int pidx = 0; pidx < parameterTypes.length; ++pidx) { final boolean convertParameter = !parameterTypes[pidx].equals(nativeParameterTypes[pidx]); if (convertParameter) { mv.aload(0); mv.getfield(className, getParameterConverterFieldName(idx, pidx), ci(ToNativeConverter.class)); } lvar = loadParameter(mv, parameterTypes[pidx], lvar); if (convertParameter) { if (parameterTypes[pidx].isPrimitive()) { boxPrimitive(mv, parameterTypes[pidx]); } mv.aconst_null(); mv.invokeinterface(ToNativeConverter.class, "toNative", Object.class, Object.class, ToNativeContext.class); mv.checkcast(p(nativeParameterTypes[pidx])); } } // Invoke the real native method mv.invokevirtual(className, functionName + "$raw", sig(nativeReturnType, nativeParameterTypes)); if (!returnType.equals(nativeReturnType)) { if (nativeReturnType.isPrimitive()) { boxPrimitive(mv, nativeReturnType); } mv.aconst_null(); mv.invokeinterface(FromNativeConverter.class, "fromNative", Object.class, Object.class, FromNativeContext.class); mv.checkcast(p(returnType)); } emitReturnOp(mv, returnType); mv.visitMaxs(10, 10); mv.visitEnd(); } private final boolean canCompile(StubCompiler compiler, Class returnType, Class[] parameterTypes, CallingConvention convention) { Class[] nativeParameterTypes = new Class[parameterTypes.length]; for (int i = 0; i < nativeParameterTypes.length; ++i) { nativeParameterTypes[i] = AsmUtil.unboxedType(parameterTypes[i]); } return compiler.canCompile(AsmUtil.unboxedReturnType(returnType), nativeParameterTypes, convention); } private final void compile(StubCompiler compiler, Function function, ClassVisitor cv, String className, String functionName, String functionFieldName, Class returnType, Class[] parameterTypes, Annotation[][] annotations, CallingConvention convention, boolean ignoreErrno) { Class[] nativeParameterTypes = new Class[parameterTypes.length]; boolean unboxing = false; boolean ptrCheck = false; for (int i = 0; i < nativeParameterTypes.length; ++i) { nativeParameterTypes[i] = AsmUtil.unboxedType(parameterTypes[i]); unboxing |= nativeParameterTypes[i] != parameterTypes[i]; ptrCheck |= Pointer.class.isAssignableFrom(parameterTypes[i]) || Struct.class.isAssignableFrom(parameterTypes[i]); } Class nativeReturnType = AsmUtil.unboxedReturnType(returnType); unboxing |= nativeReturnType != returnType; String stubName = functionName + (unboxing || ptrCheck ? "$jni$" + nextMethodID.getAndIncrement() : ""); // If unboxing of parameters is required, generate a wrapper if (unboxing || ptrCheck) { SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC | ACC_FINAL, functionName, sig(returnType, parameterTypes), null, null)); mv.start(); mv.aload(0); Label bufferInvocationLabel = emitDirectCheck(mv, parameterTypes); // Emit the unboxing wrapper for (int i = 0, lvar = 1; i < parameterTypes.length; ++i) { lvar = loadParameter(mv, parameterTypes[i], lvar); if (parameterTypes[i] != nativeParameterTypes[i]) { if (Number.class.isAssignableFrom(parameterTypes[i])) { unboxNumber(mv, parameterTypes[i], nativeParameterTypes[i]); } else if (Pointer.class.isAssignableFrom(parameterTypes[i])) { unboxPointer(mv, nativeParameterTypes[i]); } else if (Struct.class.isAssignableFrom(parameterTypes[i])) { unboxStruct(mv, nativeParameterTypes[i]); } } } // invoke the compiled stub mv.invokevirtual(className, stubName, sig(nativeReturnType, nativeParameterTypes)); // emitReturn will box the return value if needed emitReturn(mv, returnType, nativeReturnType); String bufInvoke = null; if (bufferInvocationLabel != null) { // If there was a non-direct pointer in the parameters, need to // handle it via a call to the slow buffer invocation mv.label(bufferInvocationLabel); bufInvoke = functionName + "$buf$" + nextMethodID.getAndIncrement(); // reload all the parameters for (int i = 0, lvar = 1; i < parameterTypes.length; ++i) { lvar = loadParameter(mv, parameterTypes[i], lvar); } mv.invokevirtual(className, bufInvoke, sig(returnType, parameterTypes)); emitReturnOp(mv, returnType); } mv.visitMaxs(100, calculateLocalVariableSpace(parameterTypes) + 10); mv.visitEnd(); if (bufInvoke != null) { SkinnyMethodAdapter bi = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC | ACC_FINAL, bufInvoke, sig(returnType, parameterTypes), null, null)); bi.start(); // Retrieve the static 'ffi' Invoker instance bi.getstatic(p(AbstractNativeInterface.class), "ffi", ci(com.kenai.jffi.Invoker.class)); // retrieve this.function bi.aload(0); bi.getfield(className, functionFieldName, ci(Function.class)); generateBufferInvocation(bi, returnType, parameterTypes, annotations); bi.visitMaxs(100, calculateLocalVariableSpace(parameterTypes) + 10); bi.visitEnd(); } } cv.visitMethod(ACC_PUBLIC | ACC_FINAL | ACC_NATIVE, stubName, sig(nativeReturnType, nativeParameterTypes), null, null); compiler.compile(function, stubName, nativeReturnType, nativeParameterTypes, convention, !ignoreErrno); } private final void generateMethod(ClassVisitor cv, String className, String functionName, String functionFieldName, Class returnType, Class[] parameterTypes, Annotation[][] parameterAnnotations, CallingConvention convention, boolean ignoreErrno) { SkinnyMethodAdapter mv = new SkinnyMethodAdapter(cv.visitMethod(ACC_PUBLIC | ACC_FINAL, functionName, sig(returnType, parameterTypes), null, null)); mv.start(); // Retrieve the static 'ffi' Invoker instance mv.getstatic(p(AbstractNativeInterface.class), "ffi", ci(com.kenai.jffi.Invoker.class)); // retrieve this.function mv.aload(0); mv.getfield(className, functionFieldName, ci(Function.class)); if (convention == CallingConvention.DEFAULT && isFastIntegerMethod(returnType, parameterTypes)) { generateFastIntegerInvocation(mv, returnType, parameterTypes, parameterAnnotations, ignoreErrno); } else if (convention == CallingConvention.DEFAULT && FAST_NUMERIC_AVAILABLE && isFastNumericMethod(returnType, parameterTypes)) { generateFastNumericInvocation(mv, returnType, parameterTypes, parameterAnnotations); } else { generateBufferInvocation(mv, returnType, parameterTypes, parameterAnnotations); } mv.visitMaxs(100, calculateLocalVariableSpace(parameterTypes) + 10); mv.visitEnd(); } private final void generateBufferInvocation(SkinnyMethodAdapter mv, Class returnType, Class[] parameterTypes, Annotation[][] annotations) { // [ stack contains: Invoker, Function ] final boolean sessionRequired = isSessionRequired(parameterTypes); final int lvarSession = sessionRequired ? calculateLocalVariableSpace(parameterTypes) + 1 : -1; if (sessionRequired) { mv.newobj(p(InvocationSession.class)); mv.dup(); mv.invokespecial(InvocationSession.class, "", void.class); mv.astore(lvarSession); } // [ stack contains: Invoker, Function, Function ] mv.dup(); mv.invokestatic(AsmRuntime.class, "newHeapInvocationBuffer", HeapInvocationBuffer.class, Function.class); // [ stack contains: Invoker, Function, HeapInvocationBuffer ] int lvar = 1; for (int i = 0; i < parameterTypes.length; ++i) { mv.dup(); // dup ref to HeapInvocationBuffer if (isSessionRequired(parameterTypes[i])) { mv.aload(lvarSession); mv.swap(); } lvar = loadParameter(mv, parameterTypes[i], lvar); final int parameterFlags = DefaultInvokerFactory.getParameterFlags(annotations[i]); final int nativeArrayFlags = DefaultInvokerFactory.getNativeArrayFlags(parameterFlags) | ((parameterFlags & ParameterFlags.IN) != 0 ? ArrayFlags.NULTERMINATE : 0); if (parameterTypes[i].isArray() && parameterTypes[i].getComponentType().isPrimitive()) { mv.pushInt(nativeArrayFlags); marshal(mv, parameterTypes[i], int.class); } else if (Pointer.class.isAssignableFrom(parameterTypes[i])) { mv.pushInt(nativeArrayFlags); marshal(mv, Pointer.class, int.class); } else if (Address.class.isAssignableFrom(parameterTypes[i])) { marshal(mv, Pointer.class); } else if (Enum.class.isAssignableFrom(parameterTypes[i])) { marshal(mv, Enum.class); } else if (Buffer.class.isAssignableFrom(parameterTypes[i])) { mv.pushInt(nativeArrayFlags); marshal(mv, parameterTypes[i], int.class); } else if (ByReference.class.isAssignableFrom(parameterTypes[i])) { mv.pushInt(nativeArrayFlags); // stack should be: [ session, buffer, ref, flags ] sessionmarshal(mv, ByReference.class, int.class); } else if (StringBuilder.class.isAssignableFrom(parameterTypes[i]) || StringBuffer.class.isAssignableFrom(parameterTypes[i])) { mv.pushInt(parameterFlags); mv.pushInt(nativeArrayFlags); // stack should be: [ session, buffer, ref, flags ] sessionmarshal(mv, parameterTypes[i], int.class, int.class); } else if (CharSequence.class.isAssignableFrom(parameterTypes[i])) { // stack should be: [ Buffer, array, flags ] marshal(mv, CharSequence.class); } else if (Struct.class.isAssignableFrom(parameterTypes[i])) { mv.pushInt(parameterFlags); mv.pushInt(nativeArrayFlags); marshal(mv, Struct.class, int.class, int.class); } else if (parameterTypes[i].isArray() && Struct.class.isAssignableFrom(parameterTypes[i].getComponentType())) { mv.pushInt(parameterFlags); mv.pushInt(nativeArrayFlags); marshal(mv, Struct[].class, int.class, int.class); } else if (parameterTypes[i].isArray() && Pointer.class.isAssignableFrom(parameterTypes[i].getComponentType())) { mv.pushInt(parameterFlags); mv.pushInt(nativeArrayFlags); sessionmarshal(mv, Pointer[].class, int.class, int.class); } else if (parameterTypes[i].isPrimitive() || Number.class.isAssignableFrom(parameterTypes[i])) { emitInvocationBufferIntParameter(mv, parameterTypes[i]); } else { throw new IllegalArgumentException("unsupported parameter type " + parameterTypes[i]); } } String invokeMethod = null; Class nativeReturnType = null; if (isPrimitiveInt(returnType) || void.class == returnType || Byte.class == returnType || Short.class == returnType || Integer.class == returnType) { invokeMethod = "invokeInt"; nativeReturnType = int.class; } else if (Long.class == returnType || long.class == returnType) { invokeMethod = "invokeLong"; nativeReturnType = long.class; } else if (NativeLong.class == returnType) { invokeMethod = NativeLong.SIZE == 32 ? "invokeInt" : "invokeLong"; nativeReturnType = NativeLong.SIZE == 32 ? int.class : long.class; } else if (Pointer.class == returnType || Address.class == returnType || Struct.class.isAssignableFrom(returnType) || String.class.isAssignableFrom(returnType)) { invokeMethod = "invokeAddress"; nativeReturnType = long.class; } else if (Float.class == returnType || float.class == returnType) { invokeMethod = "invokeFloat"; nativeReturnType = float.class; } else if (Double.class == returnType || double.class == returnType) { invokeMethod = "invokeDouble"; nativeReturnType = double.class; } else { throw new IllegalArgumentException("unsupported return type " + returnType); } mv.invokevirtual(com.kenai.jffi.Invoker.class, invokeMethod, nativeReturnType, Function.class, HeapInvocationBuffer.class); if (sessionRequired) { mv.aload(lvarSession); mv.invokevirtual(p(InvocationSession.class), "finish", "()V"); } emitReturn(mv, returnType, nativeReturnType); } private final void generateFastIntegerInvocation(SkinnyMethodAdapter mv, Class returnType, Class[] parameterTypes, Annotation[][] annotations, boolean ignoreErrno) { // [ stack contains: Invoker, Function ] Label bufferInvocationLabel = emitDirectCheck(mv, parameterTypes); Class nativeIntType = getNativeIntType(returnType, parameterTypes); // Emit fast-int invocation for (int i = 0, lvar = 1; i < parameterTypes.length; ++i) { lvar = loadParameter(mv, parameterTypes[i], lvar); if (parameterTypes[i].isPrimitive()) { // widen to long if needed widen(mv, parameterTypes[i], nativeIntType); } else if (Number.class.isAssignableFrom(parameterTypes[i])) { unboxNumber(mv, parameterTypes[i], nativeIntType); } else if (Pointer.class.isAssignableFrom(parameterTypes[i])) { unboxPointer(mv, nativeIntType); } else if (Struct.class.isAssignableFrom(parameterTypes[i])) { unboxStruct(mv, nativeIntType); } } // stack now contains [ IntInvoker, Function, int args ] mv.invokevirtual(p(com.kenai.jffi.Invoker.class), getFastIntInvokerMethodName(parameterTypes.length, ignoreErrno, nativeIntType), getFastIntInvokerSignature(parameterTypes.length, nativeIntType)); emitReturn(mv, returnType, nativeIntType); // Now emit the fall back code to handle heap-based memory if (bufferInvocationLabel != null) { mv.label(bufferInvocationLabel); generateBufferInvocation(mv, returnType, parameterTypes, annotations); } } private final void generateFastNumericInvocation(SkinnyMethodAdapter mv, Class returnType, Class[] parameterTypes, Annotation[][] annotations) { // [ stack contains: Invoker, Function ] Label bufferInvocationLabel = emitDirectCheck(mv, parameterTypes); // Emit fast-numeric invocation for (int i = 0, lvar = 1; i < parameterTypes.length; ++i) { lvar = loadParameter(mv, parameterTypes[i], lvar); if (Pointer.class.isAssignableFrom(parameterTypes[i])) { unboxPointer(mv, long.class); } else if (Struct.class.isAssignableFrom(parameterTypes[i])) { unboxStruct(mv, long.class); } else { if (!parameterTypes[i].isPrimitive() && Number.class.isAssignableFrom(parameterTypes[i])) { unboxNumber(mv, parameterTypes[i], long.class); } if (Float.class == parameterTypes[i] || float.class == parameterTypes[i]) { mv.invokestatic(Float.class, "floatToRawIntBits", int.class, float.class); mv.i2l(); } else if (Double.class == parameterTypes[i] || double.class == parameterTypes[i]) { mv.invokestatic(Double.class, "doubleToRawLongBits", long.class, double.class); } else { // widen to long if needed widen(mv, parameterTypes[i], long.class); } } } // stack now contains [ IntInvoker, Function, int args ] mv.invokevirtual(p(com.kenai.jffi.Invoker.class), getFastNumericInvokerMethodName(parameterTypes.length, returnType), getFastNumericInvokerSignature(parameterTypes.length)); // Convert the result from long to the correct return type if (Float.class == returnType || float.class == returnType) { mv.l2i(); mv.invokestatic(Float.class, "intBitsToFloat", float.class, int.class); } else if (Double.class == returnType || double.class == returnType) { mv.invokestatic(Double.class, "longBitsToDouble", double.class, long.class); } emitReturn(mv, returnType, long.class); if (bufferInvocationLabel != null) { // Now emit the alternate path for any parameters that might require it mv.label(bufferInvocationLabel); generateBufferInvocation(mv, returnType, parameterTypes, annotations); } } private static final Label emitDirectCheck(SkinnyMethodAdapter mv, Class[] parameterTypes) { // Iterate through any parameters that might require a HeapInvocationBuffer Label notFastInt = new Label(); boolean needBufferInvocation = false; for (int i = 0, lvar = 1; i < parameterTypes.length; ++i) { if (Pointer.class.isAssignableFrom(parameterTypes[i])) { mv.aload(lvar++); mv.invokestatic(AsmRuntime.class, "isDirect", boolean.class, Pointer.class); mv.iffalse(notFastInt); needBufferInvocation = true; } else if (Struct.class.isAssignableFrom(parameterTypes[i])) { mv.aload(lvar++); mv.invokestatic(AsmRuntime.class, "isDirect", boolean.class, Struct.class); mv.iffalse(notFastInt); needBufferInvocation = true; } else { lvar += calculateLocalVariableSpace(parameterTypes[i]); } } return needBufferInvocation ? notFastInt : null; } private final void emitReturn(SkinnyMethodAdapter mv, Class returnType, Class nativeIntType) { if (returnType.isPrimitive()) { if (long.class == returnType) { widen(mv, nativeIntType, returnType); mv.lreturn(); } else if (float.class == returnType) { mv.freturn(); } else if (double.class == returnType) { mv.dreturn(); } else if (void.class == returnType) { mv.voidreturn(); } else { narrow(mv, nativeIntType, returnType); mv.ireturn(); } } else { boxValue(mv, returnType, nativeIntType); mv.areturn(); } } private final int loadParameter(SkinnyMethodAdapter mv, Class parameterType, int lvar) { if (!parameterType.isPrimitive()) { mv.aload(lvar++); } else if (long.class == parameterType) { mv.lload(lvar); lvar += 2; } else if (float.class == parameterType) { mv.fload(lvar++); } else if (double.class == parameterType) { mv.dload(lvar); lvar += 2; } else { mv.iload(lvar++); } return lvar; } private static final Class getNativeIntType(Class returnType, Class[] parameterTypes) { for (int i = 0; i < parameterTypes.length; ++i) { if (requiresLong(parameterTypes[i])) { return long.class; } } return requiresLong(returnType) ? long.class : int.class; } static final String getFastIntInvokerMethodName(int parameterCount, boolean ignoreErrno, Class nativeParamType) { StringBuilder sb = new StringBuilder("invoke"); if (ignoreErrno && int.class == nativeParamType) { sb.append("NoErrno"); } String t = int.class == nativeParamType ? "I" : "L"; if (parameterCount < 1) { sb.append("V"); } else for (int i = 0; i < parameterCount; ++i) { sb.append(t); } return sb.append("r").append(t).toString(); } static final String getFastIntInvokerSignature(int parameterCount, Class nativeIntType) { final String t = int.class == nativeIntType ? "I" : "J"; StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(ci(Function.class)); for (int i = 0; i < parameterCount; ++i) { sb.append(t); } sb.append(")").append(t); return sb.toString(); } static final String getFastNumericInvokerMethodName(int parameterCount, Class nativeParamType) { StringBuilder sb = new StringBuilder("invoke"); if (parameterCount < 1) { sb.append("V"); } else for (int i = 0; i < parameterCount; ++i) { sb.append("N"); } return sb.append("r").append("N").toString(); } static final String getFastNumericInvokerSignature(int parameterCount) { StringBuilder sb = new StringBuilder(); sb.append("("); sb.append(ci(Function.class)); for (int i = 0; i < parameterCount; ++i) { sb.append("J"); } sb.append(")").append("J"); return sb.toString(); } private final void boxStruct(SkinnyMethodAdapter mv, Class returnType) { mv.dup2(); Label nonnull = new Label(); Label end = new Label(); mv.lconst_0(); mv.lcmp(); mv.ifne(nonnull); mv.pop2(); mv.aconst_null(); mv.go_to(end); mv.label(nonnull); // Create an instance of the struct subclass mv.newobj(p(returnType)); mv.dup(); mv.invokespecial(returnType, "", void.class); mv.dup_x2(); // associate the memory with the struct and return the struct mv.invokestatic(AsmRuntime.class, "useMemory", void.class, long.class, Struct.class); mv.label(end); } private final void boxPrimitive(SkinnyMethodAdapter mv, Class primitiveType) { Class objClass = getBoxedClass(primitiveType); mv.invokestatic(objClass, "valueOf", objClass, primitiveType); } private final void boxNumber(SkinnyMethodAdapter mv, Class type, Class nativeType) { Class primitiveClass = getPrimitiveClass(type); if (Byte.class.isAssignableFrom(type)) { narrow(mv, nativeType, byte.class); } else if (Character.class.isAssignableFrom(type)) { narrow(mv, nativeType, char.class); } else if (Short.class.isAssignableFrom(type)) { narrow(mv, nativeType, short.class); } else if (Integer.class.isAssignableFrom(type)) { narrow(mv, nativeType, int.class); } else if (Long.class.isAssignableFrom(type)) { widen(mv, nativeType, long.class); } else if (NativeLong.class.isAssignableFrom(type)) { widen(mv, nativeType, long.class); primitiveClass = long.class; } else if (Boolean.class.isAssignableFrom(type)) { narrow(mv, nativeType, boolean.class); } else if (Float.class == type || Double.class == type) { // nothing to do } else { throw new IllegalArgumentException("invalid Number subclass"); } mv.invokestatic(type, "valueOf", type, primitiveClass); } private final void boxValue(SkinnyMethodAdapter mv, Class returnType, Class nativeReturnType) { if (returnType == nativeReturnType) { return; } else if (Boolean.class.isAssignableFrom(returnType)) { narrow(mv, nativeReturnType, boolean.class); mv.invokestatic(Boolean.class, "valueOf", Boolean.class, boolean.class); } else if (Pointer.class.isAssignableFrom(returnType)) { mv.invokestatic(AsmRuntime.class, "pointerValue", Pointer.class, nativeReturnType); } else if (Address.class == returnType) { widen(mv, nativeReturnType, long.class); mv.invokestatic(returnType, "valueOf", returnType, long.class); } else if (Struct.class.isAssignableFrom(returnType)) { widen(mv, nativeReturnType, long.class); boxStruct(mv, returnType); } else if (Number.class.isAssignableFrom(returnType)) { boxNumber(mv, returnType, nativeReturnType); } else if (String.class == returnType) { widen(mv, nativeReturnType, long.class); mv.invokestatic(AsmRuntime.class, "returnString", String.class, long.class); } else { throw new IllegalArgumentException("cannot box value of type " + nativeReturnType + " to " + returnType); } } private final void emitInvocationBufferIntParameter(final SkinnyMethodAdapter mv, final Class parameterType) { String paramMethod = null; Class paramClass = int.class; if (!parameterType.isPrimitive()) { unboxNumber(mv, parameterType, null); } if (byte.class == parameterType || Byte.class == parameterType) { paramMethod = "putByte"; } else if (short.class == parameterType || Short.class == parameterType) { paramMethod = "putShort"; } else if (int.class == parameterType || Integer.class == parameterType || boolean.class == parameterType) { paramMethod = "putInt"; } else if (long.class == parameterType || Long.class == parameterType) { paramMethod = "putLong"; paramClass = long.class; } else if (float.class == parameterType || Float.class == parameterType) { paramMethod = "putFloat"; paramClass = float.class; } else if (double.class == parameterType || Double.class == parameterType) { paramMethod = "putDouble"; paramClass = double.class; } else if (NativeLong.class.isAssignableFrom(parameterType) && Platform.getPlatform().longSize() == 32) { paramMethod = "putInt"; paramClass = int.class; } else if (NativeLong.class.isAssignableFrom(parameterType) && Platform.getPlatform().longSize() == 64) { paramMethod = "putLong"; paramClass = long.class; } else { throw new IllegalArgumentException("unsupported parameter type " + parameterType); } mv.invokevirtual(HeapInvocationBuffer.class, paramMethod, void.class, paramClass); } private final void marshal(SkinnyMethodAdapter mv, Class... parameterTypes) { mv.invokestatic(p(AsmRuntime.class), "marshal", sig(void.class, ci(InvocationBuffer.class), parameterTypes)); } private final void sessionmarshal(SkinnyMethodAdapter mv, Class... parameterTypes) { mv.invokestatic(p(AsmRuntime.class), "marshal", sig(void.class, ci(InvocationSession.class) + ci(InvocationBuffer.class), parameterTypes)); } private static final Function getFunction(long address, Class returnType, Class[] paramTypes, boolean requiresErrno, CallingConvention convention) { com.kenai.jffi.Type[] nativeParamTypes = new com.kenai.jffi.Type[paramTypes.length]; for (int i = 0; i < nativeParamTypes.length; ++i) { nativeParamTypes[i] = InvokerUtil.getNativeParameterType(paramTypes[i]); } return new Function(address, InvokerUtil.getNativeReturnType(returnType), nativeParamTypes, convention, requiresErrno); } private static boolean isSessionRequired(Class parameterType) { return StringBuilder.class.isAssignableFrom(parameterType) || StringBuffer.class.isAssignableFrom(parameterType) || ByReference.class.isAssignableFrom(parameterType) || (parameterType.isArray() && Pointer.class.isAssignableFrom(parameterType.getComponentType())); } private static boolean isSessionRequired(Class[] parameterTypes) { for (int i = 0; i < parameterTypes.length; ++i) { if (isSessionRequired(parameterTypes[i])) { return true; } } return false; } final static boolean isFastNumericMethod(Class returnType, Class[] parameterTypes) { if (!FAST_NUMERIC_AVAILABLE || parameterTypes.length > 6) { return false; } if (!isFastNumericResult(returnType)) { return false; } for (int i = 0; i < parameterTypes.length; ++i) { if (!isFastNumericParam(parameterTypes[i])) { return false; } } return com.kenai.jffi.Platform.getPlatform().getCPU() == com.kenai.jffi.Platform.CPU.I386 || com.kenai.jffi.Platform.getPlatform().getCPU() == com.kenai.jffi.Platform.CPU.X86_64; } final static boolean isFastIntegerMethod(Class returnType, Class[] parameterTypes) { if (parameterTypes.length > 3) { return false; } if (!isFastIntegerResult(returnType)) { return false; } for (int i = 0; i < parameterTypes.length; ++i) { if (!isFastIntegerParam(parameterTypes[i])) { return false; } } return com.kenai.jffi.Platform.getPlatform().getCPU() == com.kenai.jffi.Platform.CPU.I386 || com.kenai.jffi.Platform.getPlatform().getCPU() == com.kenai.jffi.Platform.CPU.X86_64; } final static boolean isInt32(Class type) { return Boolean.class.isAssignableFrom(type) || boolean.class == type || Byte.class.isAssignableFrom(type) || byte.class == type || Short.class.isAssignableFrom(type) || short.class == type || Integer.class.isAssignableFrom(type) || int.class == type; } final static boolean isInt32Result(Class type) { return isInt32(type) || Void.class.isAssignableFrom(type) || void.class == type; } final static boolean isPointerResult(Class type) { return Pointer.class.isAssignableFrom(type) || Struct.class.isAssignableFrom(type) || String.class.isAssignableFrom(type); } final static boolean isPointerParam(Class type) { return Pointer.class.isAssignableFrom(type) || Struct.class.isAssignableFrom(type); } private final static boolean isFastIntegerResult(Class type) { if (isInt32Result(type)) { return true; } final boolean isPointer = isPointerResult(type); if (isPointer && Platform.getPlatform().addressSize() == 32) { return true; } if (NativeLong.class.isAssignableFrom(type) && Platform.getPlatform().longSize() == 32) { return true; } // For x86_64, any args that promote up to 64bit can be accepted. final boolean isLong = Long.class == type || long.class == type; return Platform.getPlatform().addressSize() == 64 && FAST_LONG_AVAILABLE && (isPointer || NativeLong.class.isAssignableFrom(type) || isLong); } private final static boolean isFastIntegerParam(Class type) { if (isInt32(type)) { return true; } final boolean isPointer = isPointerParam(type); if (isPointer && Platform.getPlatform().addressSize() == 32) { return true; } if (NativeLong.class.isAssignableFrom(type) && Platform.getPlatform().longSize() == 32) { return true; } // For x86_64, any args that promote up to 64bit can be accepted. final boolean isLong = Long.class == type || long.class == type; return Platform.getPlatform().addressSize() == 64 && FAST_LONG_AVAILABLE && (isPointer || NativeLong.class.isAssignableFrom(type) || isLong); } final static boolean isFastNumericResult(Class type) { return isFastIntegerResult(type) || Long.class.isAssignableFrom(type) || long.class == type || NativeLong.class.isAssignableFrom(type) || Pointer.class.isAssignableFrom(type) || Struct.class.isAssignableFrom(type) || String.class.isAssignableFrom(type) || float.class == type || Float.class == type || double.class == type || Double.class == type; } final static boolean isFastNumericParam(Class type) { return isFastIntegerParam(type) || Long.class.isAssignableFrom(type) || long.class == type || NativeLong.class.isAssignableFrom(type) || Pointer.class.isAssignableFrom(type) || Struct.class.isAssignableFrom(type) || float.class == type || Float.class == type || double.class == type || Double.class == type; } final static boolean isFastNumericAvailable() { try { com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeNNNNNNrN", Function.class, long.class, long.class, long.class, long.class, long.class, long.class); return true; } catch (Throwable t) { return false; } } final static boolean isFastLongAvailable() { try { com.kenai.jffi.Invoker.class.getDeclaredMethod("invokeLLLLLLrL", Function.class, long.class, long.class, long.class, long.class, long.class, long.class); return true; } catch (Throwable t) { return false; } } private final static boolean requiresLong(Class type) { return Long.class.isAssignableFrom(type) || long.class == type || (NativeLong.class.isAssignableFrom(type) && Platform.getPlatform().longSize() == 64) || (Pointer.class.isAssignableFrom(type) && Platform.getPlatform().addressSize() == 64) || (Struct.class.isAssignableFrom(type) && Platform.getPlatform().addressSize() == 64) || (String.class.isAssignableFrom(type) && Platform.getPlatform().addressSize() == 64) ; } public static abstract class AbstractNativeInterface { public static final com.kenai.jffi.Invoker ffi = com.kenai.jffi.Invoker.getInstance(); // Strong ref to keep the library alive protected final Library library; public AbstractNativeInterface(Library library) { this.library = library; } protected static final HeapInvocationBuffer newInvocationBuffer(Function f) { return new HeapInvocationBuffer(f); } } public static final class ToNativeProxy implements ToNativeConverter { private final ToNativeConverter converter; private final ToNativeContext ctx; public ToNativeProxy(ToNativeConverter converter, ToNativeContext ctx) { this.converter = converter; this.ctx = ctx; } public Object toNative(Object value, ToNativeContext unused) { return converter.toNative(value, ctx); } public Class nativeType() { return converter.nativeType(); } } public static final class FromNativeProxy implements FromNativeConverter { private final FromNativeConverter converter; private final FromNativeContext ctx; public FromNativeProxy(FromNativeConverter converter, FromNativeContext ctx) { this.converter = converter; this.ctx = ctx; } public Object fromNative(Object value, FromNativeContext unused) { return converter.fromNative(value, ctx); } public Class nativeType() { return converter.nativeType(); } } public static final class IntToLong implements FromNativeConverter, ToNativeConverter { public Object fromNative(Object nativeValue, FromNativeContext context) { return ((Number) nativeValue).longValue(); } public Object toNative(Object value, ToNativeContext context) { return Integer.valueOf(((Number) value).intValue()); } public Class nativeType() { return Integer.class; } }; public static interface TestLib { static final class s8 extends Struct { public final Signed8 s8 = new Signed8(); } public Integer add_int32_t(Integer i1, int i2); public Float add_float(float f1, float f2); public Double add_double(Double f1, double f2); // public byte add_int8_t(byte i1, byte i2); byte ptr_ret_int8_t(s8[] s, int index); Byte ptr_ret_int8_t(Pointer p, int index); byte ptr_ret_int8_t(s8 s, int index); void not_found_function(); } public static void main(String[] args) { System.setProperty("jaffl.compile.dump", "true"); System.out.println("cpu=" + Platform.getPlatform().getCPU()); final Map options = new HashMap(); // options.put(LibraryOption.TypeMapper, new TypeMapper() { // // public FromNativeConverter getFromNativeConverter(Class type) { // if (Long.class.isAssignableFrom(type)) { // return new IntToLong(); // } // return null; // } // // public ToNativeConverter getToNativeConverter(Class type) { // if (Long.class.isAssignableFrom(type) || long.class == type) { // return new IntToLong(); // } // return null; // } // }); TestLib lib = AsmLibraryLoader.getInstance().loadLibrary(new Library("test"), TestLib.class, options); Number result = lib.add_int32_t(1, 2); System.err.println("result=" + result); // System.err.println("adding bytes =" + lib.add_int8_t((byte) 1, (byte) 3)); System.err.println("adding floats=" + lib.add_float(1.0f, 2.0f)); System.err.println("adding doubles=" + lib.add_double(1.0, 2.0)); Pointer p = MemoryIO.allocateDirect(1024); lib.ptr_ret_int8_t(p, 0); lib.ptr_ret_int8_t(MemoryIO.allocate(1024), 0); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AsmRuntime.java000066400000000000000000000345731201747543600240510ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.Address; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.ParameterFlags; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.byref.ByReference; import com.kenai.jaffl.provider.AbstractArrayMemoryIO; import com.kenai.jaffl.provider.DelegatingMemoryIO; import com.kenai.jaffl.provider.InvocationSession; import com.kenai.jaffl.provider.StringIO; import com.kenai.jaffl.struct.Struct; import com.kenai.jaffl.struct.StructUtil; import com.kenai.jaffl.util.EnumMapper; import com.kenai.jffi.Function; import com.kenai.jffi.HeapInvocationBuffer; import com.kenai.jffi.InvocationBuffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; /** * Utility methods that are used at runtime by generated code. */ public final class AsmRuntime { public static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); private AsmRuntime() {} public static final void marshal(InvocationBuffer buffer, byte[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, short[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, int[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, long[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, float[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, double[] array, int flags) { if (array == null) { buffer.putAddress(0L); } else { buffer.putArray(array, 0, array.length, flags); } } public static final void marshal(InvocationBuffer buffer, Pointer ptr, int nativeArrayFlags) { if (ptr == null) { buffer.putAddress(0L); } else if (ptr.isDirect()) { buffer.putAddress(ptr.address()); } else if (ptr instanceof AbstractArrayMemoryIO) { AbstractArrayMemoryIO aio = (AbstractArrayMemoryIO) ptr; buffer.putArray(aio.array(), aio.offset(), aio.length(), nativeArrayFlags); } else { throw new IllegalArgumentException("unsupported argument type" + ptr.getClass()); } } public static final void marshal(InvocationBuffer buffer, Address ptr) { if (ptr == null) { buffer.putAddress(0L); } else { buffer.putAddress(ptr.nativeAddress()); } } public static final void marshal(InvocationBuffer buffer, ByteBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position(), buf.remaining()); } } public static final void marshal(InvocationBuffer buffer, ShortBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position() << 1, buf.remaining() << 1); } } public static final void marshal(InvocationBuffer buffer, IntBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position() << 2, buf.remaining() << 2); } } public static final void marshal(InvocationBuffer buffer, LongBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position() << 3, buf.remaining() << 3); } } public static final void marshal(InvocationBuffer buffer, FloatBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position() << 2, buf.remaining() << 2); } } public static final void marshal(InvocationBuffer buffer, DoubleBuffer buf, int flags) { if (buf == null) { buffer.putAddress(0L); } else if (buf.hasArray()) { buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); } else { buffer.putDirectBuffer(buf, buf.position() << 3, buf.remaining() << 3); } } public static final void marshal(InvocationBuffer buffer, CharSequence cs) { if (cs == null) { buffer.putAddress(0L); } else { ByteBuffer buf = StringIO.getStringIO().toNative(cs, cs.length(), true); buffer.putArray(buf.array(), buf.arrayOffset(), buf.remaining(), com.kenai.jffi.ArrayFlags.IN | com.kenai.jffi.ArrayFlags.NULTERMINATE); } } public static final void marshal(InvocationBuffer buffer, Struct parameter, int parameterFlags, int nativeArrayFlags) { if (parameter == null) { buffer.putAddress(0L); } else { Struct s = parameter; MemoryIO io = StructUtil.getMemoryIO(s, parameterFlags); if (io instanceof AbstractArrayMemoryIO) { AbstractArrayMemoryIO aio = (AbstractArrayMemoryIO) io; buffer.putArray(aio.array(), aio.offset(), aio.length(), nativeArrayFlags); } else if (io.isDirect()) { buffer.putAddress(io.address()); } } } public static final void marshal(InvocationBuffer buffer, Struct[] parameter, int parameterFlags, int nativeArrayFlags) { if (parameter == null) { buffer.putAddress(0L); } else { Struct[] array = parameter; MemoryIO io = StructUtil.getMemoryIO(array[0], parameterFlags); if (!(io instanceof DelegatingMemoryIO)) { throw new RuntimeException("Struct array must be backed by contiguous array"); } io = ((DelegatingMemoryIO) io).getDelegatedMemoryIO(); if (io instanceof AbstractArrayMemoryIO) { AbstractArrayMemoryIO aio = (AbstractArrayMemoryIO) io; buffer.putArray(aio.array(), aio.offset(), aio.length(), nativeArrayFlags); } else if (io.isDirect()) { buffer.putAddress(io.address()); } } } public static final void marshal(InvocationSession session, InvocationBuffer buffer, ByReference parameter, int flags) { if (parameter == null) { buffer.putAddress(0L); } else { final ByReference ref = (ByReference) parameter; final ByteBuffer buf = ByteBuffer.allocate(ref.nativeSize()).order(ByteOrder.nativeOrder()); buf.clear(); if (com.kenai.jffi.ArrayFlags.isIn(flags)) { ref.marshal(buf); } buffer.putArray(buf.array(), buf.arrayOffset() + buf.position(), buf.remaining(), flags); if (com.kenai.jffi.ArrayFlags.isOut(flags)) { session.addPostInvoke(new InvocationSession.PostInvoke() { public void postInvoke() { ref.unmarshal(buf); } }); } } } public static final void marshal(InvocationSession session, InvocationBuffer buffer, StringBuilder parameter, int inout, int nflags) { if (parameter == null) { buffer.putAddress(0L); } else { final StringBuilder sb = parameter; final StringIO io = StringIO.getStringIO(); final ByteBuffer buf = io.toNative(sb, sb.capacity(), ParameterFlags.isIn(inout)); buffer.putArray(buf.array(), buf.arrayOffset(), buf.remaining(), nflags); // // Copy the string back out if its an OUT parameter // if (ParameterFlags.isOut(inout)) { session.addPostInvoke(new InvocationSession.PostInvoke() { public void postInvoke() { sb.delete(0, sb.length()).append(io.fromNative(buf, sb.capacity())); } }); } } } public static final void marshal(InvocationSession session, InvocationBuffer buffer, final StringBuffer parameter, int inout, int nflags) { if (parameter == null) { buffer.putAddress(0L); } else { final StringBuffer sb = parameter; final StringIO io = StringIO.getStringIO(); final ByteBuffer buf = io.toNative(sb, sb.capacity(), ParameterFlags.isIn(inout)); buffer.putArray(buf.array(), buf.arrayOffset(), buf.remaining(), nflags); // // Copy the string back out if its an OUT parameter // if (ParameterFlags.isOut(inout)) { session.addPostInvoke(new InvocationSession.PostInvoke() { public void postInvoke() { sb.delete(0, sb.length()).append(io.fromNative(buf, sb.capacity())); } }); } } } public static final void marshal(InvocationBuffer buffer, final Enum parameter) { buffer.putInt(EnumMapper.getInstance().intValue(parameter)); } public static final void marshal(InvocationSession session, InvocationBuffer buffer, Pointer[] parameter, int inout, int nativeArrayFlags) { if (parameter == null) { buffer.putAddress(0L); } else { final Pointer[] array = parameter; if (Pointer.SIZE == 32) { final int[] raw = new int[array.length]; for (int i = 0; i < raw.length; ++i) { if (!array[i].isDirect()) { throw new IllegalArgumentException("invalid pointer in array at index " + i); } raw[i] = (int) array[i].address(); } buffer.putArray(raw, 0, raw.length, nativeArrayFlags); if (ParameterFlags.isOut(inout)) { session.addPostInvoke(new InvocationSession.PostInvoke() { public void postInvoke() { for (int i = 0; i < raw.length; ++i) { array[i] = MemoryUtil.newPointer(raw[i]); } } }); } } else { final long[] raw = new long[array.length]; for (int i = 0; i < raw.length; ++i) { if (!array[i].isDirect()) { throw new IllegalArgumentException("invalid pointer in array at index " + i); } raw[i] = array[i].address(); } buffer.putArray(raw, 0, raw.length, nativeArrayFlags); if (ParameterFlags.isOut(inout)) { session.addPostInvoke(new InvocationSession.PostInvoke() { public void postInvoke() { for (int i = 0; i < raw.length; ++i) { array[i] = MemoryUtil.newPointer(raw[i]); } } }); } } } } public static final UnsatisfiedLinkError newUnsatisifiedLinkError(String msg) { return new UnsatisfiedLinkError(msg); } public static final HeapInvocationBuffer newHeapInvocationBuffer(Function function) { return new HeapInvocationBuffer(function); } public static final String returnString(long ptr) { if (ptr == 0) { return null; } final ByteBuffer buf = ByteBuffer.wrap(IO.getZeroTerminatedByteArray(ptr)); return StringIO.getStringIO().fromNative(buf).toString(); } public static final Pointer pointerValue(long ptr) { return ptr != 0 ? new DirectMemoryIO(ptr) : null; } public static final Pointer pointerValue(int ptr) { return ptr != 0 ? new DirectMemoryIO((long) ptr & 0xffffffffL) : null; } public static final MemoryIO newMemoryIO(long ptr) { return ptr == 0 ? null : new DirectMemoryIO(ptr); } public static final void useMemory(long ptr, Struct s) { s.useMemory(new DirectMemoryIO(ptr)); } public static final boolean isDirect(Pointer ptr) { return ptr == null || ptr.isDirect(); } public static final int intValue(Pointer ptr) { return ptr != null ? (int) ptr.address() : 0; } public static final long longValue(Pointer ptr) { return ptr != null ? ptr.address() : 0L; } public static final boolean isDirect(Struct s) { return s == null || StructUtil.isDirect(s); } public static final boolean isDirect(Struct s, int flags) { return s == null || StructUtil.getMemoryIO(s, flags).isDirect(); } public static final int intValue(Struct s) { return s != null ? (int) StructUtil.getMemoryIO(s).address() : 0; } public static final long longValue(Struct s) { return s != null ? StructUtil.getMemoryIO(s).address() : 0L; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/AsmUtil.java000066400000000000000000000154361201747543600233400ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.NativeLong; import com.kenai.jaffl.Platform; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.struct.Struct; import java.io.OutputStream; import java.io.PrintWriter; import java.lang.reflect.Constructor; import org.objectweb.asm.ClassVisitor; import org.objectweb.asm.MethodVisitor; import static com.kenai.jaffl.provider.jffi.NumberUtil.*; import static com.kenai.jaffl.provider.jffi.CodegenUtils.*; class AsmUtil { private AsmUtil() {} public static final MethodVisitor newTraceMethodVisitor(MethodVisitor mv) { try { Class tmvClass = Class.forName("org.objectweb.asm.util.TraceMethodVisitor"); Constructor c = tmvClass.getDeclaredConstructor(MethodVisitor.class); return (MethodVisitor) c.newInstance(mv); } catch (Throwable t) { return mv; } } public static final ClassVisitor newTraceClassVisitor(ClassVisitor cv, OutputStream out) { return newTraceClassVisitor(cv, new PrintWriter(out, true)); } public static final ClassVisitor newTraceClassVisitor(ClassVisitor cv, PrintWriter out) { try { Class tmvClass = Class.forName("org.objectweb.asm.util.TraceClassVisitor"); Constructor c = tmvClass.getDeclaredConstructor(ClassVisitor.class, PrintWriter.class); return (ClassVisitor) c.newInstance(cv, out); } catch (Throwable t) { return cv; } } public static final ClassVisitor newCheckClassAdapter(ClassVisitor cv) { try { Class tmvClass = Class.forName("org.objectweb.asm.util.CheckClassAdapter"); Constructor c = tmvClass.getDeclaredConstructor(ClassVisitor.class); return (ClassVisitor) c.newInstance(cv); } catch (Throwable t) { return cv; } } public static final Class unboxedReturnType(Class type) { if (Pointer.class.isAssignableFrom(type) || Struct.class.isAssignableFrom(type) || String.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? int.class : long.class; } return unboxedType(type); } public static final Class unboxedType(Class boxedType) { if (boxedType == Byte.class) { return byte.class; } else if (boxedType == Short.class) { return short.class; } else if (boxedType == Integer.class) { return int.class; } else if (boxedType == Long.class) { return long.class; } else if (boxedType == Float.class) { return float.class; } else if (boxedType == Double.class) { return double.class; } else if (boxedType == Boolean.class) { return boolean.class; } else if (boxedType == NativeLong.class) { return Platform.getPlatform().longSize() == 32 ? int.class : long.class; } else if (Pointer.class.isAssignableFrom(boxedType) || Struct.class.isAssignableFrom(boxedType)) { return Platform.getPlatform().addressSize() == 32 ? int.class : long.class; } else { return boxedType; } } public static final Class boxedType(Class type) { if (type == byte.class) { return Byte.class; } else if (type == short.class) { return Short.class; } else if (type == int.class) { return Integer.class; } else if (type == long.class) { return Long.class; } else if (type == float.class) { return Float.class; } else if (type == double.class) { return Double.class; } else if (type == boolean.class) { return Boolean.class; } else { return type; } } static final void emitReturnOp(SkinnyMethodAdapter mv, Class returnType) { if (!returnType.isPrimitive()) { mv.areturn(); } else if (long.class == returnType) { mv.lreturn(); } else if (float.class == returnType) { mv.freturn(); } else if (double.class == returnType) { mv.dreturn(); } else if (void.class == returnType) { mv.voidreturn(); } else { mv.ireturn(); } } /** * Calculates the size of a local variable * * @param type The type of parameter * @return The size in parameter units */ static final int calculateLocalVariableSpace(Class type) { return long.class == type || double.class == type ? 2 : 1; } /** * Calculates the size of a list of types in the local variable area. * * @param type The type of parameter * @return The size in parameter units */ static final int calculateLocalVariableSpace(Class... types) { int size = 0; for (int i = 0; i < types.length; ++i) { size += calculateLocalVariableSpace(types[i]); } return size; } private static final void unboxPointerOrStruct(final SkinnyMethodAdapter mv, final Class type, final Class nativeType) { mv.invokestatic(p(AsmRuntime.class), long.class == nativeType ? "longValue" : "intValue", sig(nativeType, type)); } static final void unboxPointer(final SkinnyMethodAdapter mv, final Class nativeType) { unboxPointerOrStruct(mv, Pointer.class, nativeType); } static final void unboxStruct(final SkinnyMethodAdapter mv, final Class nativeType) { unboxPointerOrStruct(mv, Struct.class, nativeType); } static final void unboxNumber(final SkinnyMethodAdapter mv, final Class boxedType, final Class nativeType) { String intValueMethod = long.class == nativeType ? "longValue" : "intValue"; String intValueSignature = long.class == nativeType ? "()J" : "()I"; if (Byte.class == boxedType || Short.class == boxedType || Integer.class == boxedType) { mv.invokevirtual(p(boxedType), intValueMethod, intValueSignature); } else if (Long.class == boxedType) { mv.invokevirtual(p(boxedType), "longValue", "()J"); } else if (Float.class == boxedType) { mv.invokevirtual(p(boxedType), "floatValue", "()F"); } else if (Double.class == boxedType) { mv.invokevirtual(p(boxedType), "doubleValue", "()D"); } else if (NativeLong.class.isAssignableFrom(boxedType)) { mv.invokevirtual(p(boxedType), intValueMethod, intValueSignature); } else if (Boolean.class.isAssignableFrom(boxedType)) { mv.invokevirtual(p(boxedType), "booleanValue", "()Z"); widen(mv, boolean.class, nativeType); } else { throw new IllegalArgumentException("unsupported Number subclass: " + boxedType); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/BoundedDirectMemoryIO.java000066400000000000000000000005541201747543600261110ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.provider.BoundedMemoryIO; class BoundedDirectMemoryIO extends BoundedMemoryIO { BoundedDirectMemoryIO(DirectMemoryIO parent, long offset, long size) { super(parent, offset, size); } @Override public long address() { return getDelegatedMemoryIO().address(); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/ByteBufferMemoryIO.java000066400000000000000000000014401201747543600254260ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.provider.AbstractBufferMemoryIO; import java.nio.ByteBuffer; public class ByteBufferMemoryIO extends AbstractBufferMemoryIO { public ByteBufferMemoryIO(ByteBuffer buffer) { super(buffer); } public MemoryIO getMemoryIO(long offset) { return MemoryUtil.newMemoryIO(getAddress(offset)); } public MemoryIO getMemoryIO(long offset, long size) { return MemoryUtil.newMemoryIO(getAddress(offset), size); } public Pointer getPointer(long offset) { return MemoryUtil.newPointer(getAddress(offset)); } public void putPointer(long offset, Pointer value) { putAddress(offset, value.address()); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/CodegenUtils.java000066400000000000000000000142751201747543600243470ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import java.util.Arrays; import java.util.Map; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Type; public class CodegenUtils { /** * Creates a dotted class name from a path/package name */ public static String c(String p) { return p.replace('/', '.'); } /** * Creates a class path name, from a Class. */ public static String p(Class n) { return n.getName().replace('.','/'); } /** * Creates a class identifier of form Labc/abc;, from a Class. */ public static String ci(Class n) { if (n.isArray()) { n = n.getComponentType(); if (n.isPrimitive()) { if (n == Byte.TYPE) { return "[B"; } else if (n == Boolean.TYPE) { return "[Z"; } else if (n == Short.TYPE) { return "[S"; } else if (n == Character.TYPE) { return "[C"; } else if (n == Integer.TYPE) { return "[I"; } else if (n == Float.TYPE) { return "[F"; } else if (n == Double.TYPE) { return "[D"; } else if (n == Long.TYPE) { return "[J"; } else { throw new RuntimeException("Unrecognized type in compiler: " + n.getName()); } } else { return "[" + ci(n); } } else { if (n.isPrimitive()) { if (n == Byte.TYPE) { return "B"; } else if (n == Boolean.TYPE) { return "Z"; } else if (n == Short.TYPE) { return "S"; } else if (n == Character.TYPE) { return "C"; } else if (n == Integer.TYPE) { return "I"; } else if (n == Float.TYPE) { return "F"; } else if (n == Double.TYPE) { return "D"; } else if (n == Long.TYPE) { return "J"; } else if (n == Void.TYPE) { return "V"; } else { throw new RuntimeException("Unrecognized type in compiler: " + n.getName()); } } else { return "L" + p(n) + ";"; } } } /** * Creates a human-readable representation, from a Class. */ public static String human(Class n) { return n.getCanonicalName(); } /** * Create a method signature from the given param types and return values */ public static String sig(Class retval, Class... params) { return sigParams(params) + ci(retval); } public static String sig(Class retval, String descriptor, Class... params) { return sigParams(descriptor, params) + ci(retval); } public static String sigParams(Class... params) { StringBuilder signature = new StringBuilder("("); for (int i = 0; i < params.length; i++) { signature.append(ci(params[i])); } signature.append(")"); return signature.toString(); } public static String sigParams(String descriptor, Class... params) { StringBuilder signature = new StringBuilder("("); signature.append(descriptor); for (int i = 0; i < params.length; i++) { signature.append(ci(params[i])); } signature.append(")"); return signature.toString(); } public static String pretty(Class retval, Class... params) { return prettyParams(params) + human(retval); } public static String prettyParams(Class... params) { StringBuilder signature = new StringBuilder("("); for (int i = 0; i < params.length; i++) { signature.append(human(params[i])); if (i < params.length - 1) signature.append(','); } signature.append(")"); return signature.toString(); } public static Class[] params(Class... classes) { return classes; } public static Class[] params(Class cls, int times) { Class[] classes = new Class[times]; Arrays.fill(classes, cls); return classes; } public static Class[] params(Class cls1, Class clsFill, int times) { Class[] classes = new Class[times + 1]; Arrays.fill(classes, clsFill); classes[0] = cls1; return classes; } public static String getAnnotatedBindingClassName(String javaMethodName, String typeName, boolean isStatic, int required, int optional, boolean multi, boolean framed) { String commonClassSuffix; String marker = framed ? "$RUBYFRAMEDINVOKER$" : "$RUBYINVOKER$"; if (multi) { commonClassSuffix = (isStatic ? "$s" : "$i" ) + "_method_multi" + marker + javaMethodName; } else { commonClassSuffix = (isStatic ? "$s" : "$i" ) + "_method_" + required + "_" + optional + marker + javaMethodName; } return typeName + commonClassSuffix; } public static void visitAnnotationFields(AnnotationVisitor visitor, Map fields) { for (Map.Entry fieldEntry : fields.entrySet()) { Object value = fieldEntry.getValue(); if (value.getClass().isArray()) { Object[] values = (Object[]) value; AnnotationVisitor arrayV = visitor.visitArray(fieldEntry.getKey()); for (int i = 0; i < values.length; i++) { arrayV.visit(null, values[i]); } arrayV.visitEnd(); } else if (value.getClass().isEnum()) { visitor.visitEnum(fieldEntry.getKey(), ci(value.getClass()), value.toString()); } else if (value instanceof Class) { visitor.visit(fieldEntry.getKey(), Type.getType((Class)value)); } else { visitor.visit(fieldEntry.getKey(), value); } } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/DefaultInvokerFactory.java000066400000000000000000001052251201747543600262300ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.NativeLong; import com.kenai.jaffl.ParameterFlags; import com.kenai.jaffl.Platform; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.annotations.StdCall; import com.kenai.jaffl.byref.ByReference; import com.kenai.jaffl.mapper.FromNativeContext; import com.kenai.jaffl.mapper.FromNativeConverter; import com.kenai.jaffl.mapper.FunctionMapper; import com.kenai.jaffl.mapper.MethodResultContext; import com.kenai.jaffl.mapper.ToNativeContext; import com.kenai.jaffl.mapper.ToNativeConverter; import com.kenai.jaffl.mapper.TypeMapper; import com.kenai.jaffl.provider.InvocationSession; import com.kenai.jaffl.provider.Invoker; import com.kenai.jaffl.provider.StringIO; import com.kenai.jaffl.struct.Struct; import com.kenai.jaffl.util.EnumMapper; import com.kenai.jffi.Function; import com.kenai.jffi.HeapInvocationBuffer; import com.kenai.jffi.InvocationBuffer; import com.kenai.jffi.Type; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import java.util.Map; final class DefaultInvokerFactory implements InvokerFactory { private final static class SingletonHolder { static InvokerFactory INSTANCE = new DefaultInvokerFactory(); } public static final InvokerFactory getInstance() { return SingletonHolder.INSTANCE; } public final boolean isMethodSupported(Method method) { return true; // The default factory supports everything } public final Invoker createInvoker(Method method, com.kenai.jaffl.provider.Library library, Map options) { FunctionMapper functionMapper = options.containsKey(LibraryOption.FunctionMapper) ? (FunctionMapper) options.get(LibraryOption.FunctionMapper) : IdentityFunctionMapper.getInstance(); final long address = ((Library) library).findSymbolAddress(functionMapper.mapFunctionName(method.getName(), null)); TypeMapper typeMapper = options.containsKey(LibraryOption.TypeMapper) ? (TypeMapper) options.get(LibraryOption.TypeMapper) : NullTypeMapper.INSTANCE; com.kenai.jffi.CallingConvention convention = method.getAnnotation(StdCall.class) != null ? com.kenai.jffi.CallingConvention.STDCALL : InvokerUtil.getCallingConvention(options); Marshaller[] marshallers = new Marshaller[method.getParameterTypes().length]; Type[] paramTypes = new Type[marshallers.length]; for (int i = 0; i < marshallers.length; ++i) { marshallers[i] = getMarshaller(method, i, typeMapper); paramTypes[i] = getNativeParameterType(method, i, typeMapper); } Class returnType = method.getReturnType(); FromNativeConverter resultConverter = typeMapper.getFromNativeConverter(returnType); if (resultConverter != null) { returnType = resultConverter.nativeType(); } Function function = new Function(address, getNativeReturnType(returnType), paramTypes, convention, InvokerUtil.requiresErrno(method)); FunctionInvoker invoker = getFunctionInvoker(returnType); if (resultConverter != null) { MethodResultContext context = new MethodResultContext(method); invoker = new ConvertingInvoker(resultConverter, context, invoker); } return isSessionRequired(marshallers) ? new SessionInvoker(function, invoker, marshallers) : new DefaultInvoker(function, invoker, marshallers); } private static final boolean isSessionRequired(Marshaller[] marshallers) { for (Marshaller m : marshallers) { if (m.isSessionRequired()) { return true; } } return false; } private static final FunctionInvoker getFunctionInvoker(Class returnType) { if (Void.class.isAssignableFrom(returnType) || void.class == returnType) { return VoidInvoker.INSTANCE; } else if (Boolean.class.isAssignableFrom(returnType) || boolean.class == returnType) { return BooleanInvoker.INSTANCE; } else if (Enum.class.isAssignableFrom(returnType)) { return new EnumInvoker(returnType); } else if (Byte.class.isAssignableFrom(returnType) || byte.class == returnType) { return Int8Invoker.INSTANCE; } else if (Short.class.isAssignableFrom(returnType) || short.class == returnType) { return Int16Invoker.INSTANCE; } else if (Integer.class.isAssignableFrom(returnType) || int.class == returnType) { return Int32Invoker.INSTANCE; } else if (Long.class.isAssignableFrom(returnType) || long.class == returnType) { return Int64Invoker.INSTANCE; } else if (NativeLong.class.isAssignableFrom(returnType)) { return Platform.getPlatform().longSize() == 32 ? NativeLong32Invoker.INSTANCE : NativeLong64Invoker.INSTANCE; } else if (Float.class.isAssignableFrom(returnType) || float.class == returnType) { return Float32Invoker.INSTANCE; } else if (Double.class.isAssignableFrom(returnType) || double.class == returnType) { return Float64Invoker.INSTANCE; } else if (Pointer.class.isAssignableFrom(returnType)) { return PointerInvoker.INSTANCE; } else if (Struct.class.isAssignableFrom(returnType)) { return new StructInvoker(returnType); } else if (String.class.isAssignableFrom(returnType)) { return StringInvoker.INSTANCE; } else { throw new IllegalArgumentException("Unknown return type: " + returnType); } } private static final Type getNativeReturnType(Class type) { if (Void.class.isAssignableFrom(type) || void.class == type) { return Type.VOID; } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) { return Type.SINT32; } else if (Byte.class.isAssignableFrom(type) || byte.class == type) { return Type.SINT8; } else if (Short.class.isAssignableFrom(type) || short.class == type) { return Type.SINT16; } else if (Integer.class.isAssignableFrom(type) || int.class == type) { return Type.SINT32; } else if (Long.class.isAssignableFrom(type) || long.class == type) { return Type.SINT64; } else if (NativeLong.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? Type.SINT32: Type.SINT64; } else if (Float.class.isAssignableFrom(type) || float.class == type) { return Type.FLOAT; } else if (Double.class.isAssignableFrom(type) || double.class == type) { return Type.DOUBLE; } else if (Enum.class.isAssignableFrom(type)) { return Type.SINT32; } else if (Pointer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Struct.class.isAssignableFrom(type)) { return Type.POINTER; } else if (String.class.isAssignableFrom(type)) { return Type.POINTER; } else { throw new IllegalArgumentException("Unsupported return type: " + type); } } private static final Type getNativeParameterType(Method method, int paramIndex, TypeMapper mapper) { Class type = method.getParameterTypes()[paramIndex]; ToNativeConverter converter = mapper.getToNativeConverter(type); return getNativeParameterType(converter != null ? converter.nativeType() : type); } private static final Type getNativeParameterType(Class type) { if (Byte.class.isAssignableFrom(type) || byte.class == type) { return Type.SINT8; } else if (Short.class.isAssignableFrom(type) || short.class == type) { return Type.SINT16; } else if (Integer.class.isAssignableFrom(type) || int.class == type) { return Type.SINT32; } else if (Long.class.isAssignableFrom(type) || long.class == type) { return Type.SINT64; } else if (NativeLong.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? Type.SINT32: Type.SINT64; } else if (Float.class.isAssignableFrom(type) || float.class == type) { return Type.FLOAT; } else if (Double.class.isAssignableFrom(type) || double.class == type) { return Type.DOUBLE; } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) { return Type.SINT32; } else if (Enum.class.isAssignableFrom(type)) { return Type.SINT32; } else if (Pointer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Struct.class.isAssignableFrom(type) || type.isArray() && Struct.class.isAssignableFrom(type.getComponentType())) { return Type.POINTER; } else if (Buffer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (CharSequence.class.isAssignableFrom(type)) { return Type.POINTER; } else if (ByReference.class.isAssignableFrom(type)) { return Type.POINTER; } else if (type.isArray()) { return Type.POINTER; } else { throw new IllegalArgumentException("Unsupported parameter type: " + type); } } static final int getParameterFlags(Method method, int paramIndex) { return getParameterFlags(method.getParameterAnnotations()[paramIndex]); } static final int getParameterFlags(Annotation[] annotations) { return ParameterFlags.parse(annotations); } static final int getNativeArrayFlags(int flags) { int nflags = 0; nflags |= ParameterFlags.isIn(flags) ? com.kenai.jffi.ArrayFlags.IN : 0; nflags |= ParameterFlags.isOut(flags) ? com.kenai.jffi.ArrayFlags.OUT : 0; nflags |= ParameterFlags.isNulTerminate(flags) ? com.kenai.jffi.ArrayFlags.NULTERMINATE : 0; return nflags; } static final int getNativeArrayFlags(Annotation[] annotations) { return getNativeArrayFlags(getParameterFlags(annotations)); } static final Marshaller getMarshaller(Method method, int paramIndex, TypeMapper mapper) { Class type = method.getParameterTypes()[paramIndex]; ToNativeConverter converter = mapper != null ? mapper.getToNativeConverter(type) : null; if (converter != null) { return new ToNativeConverterMarshaller(converter, getMarshaller(converter.nativeType(), method.getParameterAnnotations()[paramIndex])); } else { return getMarshaller(method, paramIndex); } } static final Marshaller getMarshaller(Method method, int paramIndex) { return getMarshaller(method.getParameterTypes()[paramIndex], method.getParameterAnnotations()[paramIndex]); } static final Marshaller getMarshaller(Class type, Annotation[] annotations) { if (Byte.class.isAssignableFrom(type) || byte.class == type) { return Int8Marshaller.INSTANCE; } else if (Short.class.isAssignableFrom(type) || short.class == type) { return Int16Marshaller.INSTANCE; } else if (Integer.class.isAssignableFrom(type) || int.class == type) { return Int32Marshaller.INSTANCE; } else if (Long.class.isAssignableFrom(type) || long.class == type) { return Int64Marshaller.INSTANCE; } else if (NativeLong.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? Int32Marshaller.INSTANCE : Int64Marshaller.INSTANCE; } else if (Float.class.isAssignableFrom(type) || float.class == type) { return Float32Marshaller.INSTANCE; } else if (Double.class.isAssignableFrom(type) || double.class == type) { return Float64Marshaller.INSTANCE; } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) { return BooleanMarshaller.INSTANCE; } else if (Enum.class.isAssignableFrom(type)) { return EnumMarshaller.INSTANCE; } else if (Pointer.class.isAssignableFrom(type)) { return PointerMarshaller.INSTANCE; } else if (StringBuffer.class.isAssignableFrom(type)) { return new StringBufferMarshaller(getParameterFlags(annotations)); } else if (StringBuilder.class.isAssignableFrom(type)) { return new StringBuilderMarshaller(getParameterFlags(annotations)); } else if (CharSequence.class.isAssignableFrom(type)) { return CharSequenceMarshaller.INSTANCE; } else if (ByReference.class.isAssignableFrom(type)) { return new ByReferenceMarshaller(getParameterFlags(annotations)); } else if (Struct.class.isAssignableFrom(type)) { return new StructMarshaller(getParameterFlags(annotations)); } else if (ByteBuffer.class.isAssignableFrom(type)) { return new ByteBufferMarshaller(getParameterFlags(annotations)); } else if (ShortBuffer.class.isAssignableFrom(type)) { return new ShortBufferMarshaller(getParameterFlags(annotations)); } else if (IntBuffer.class.isAssignableFrom(type)) { return new IntBufferMarshaller(getParameterFlags(annotations)); } else if (LongBuffer.class.isAssignableFrom(type)) { return new LongBufferMarshaller(getParameterFlags(annotations)); } else if (FloatBuffer.class.isAssignableFrom(type)) { return new FloatBufferMarshaller(getParameterFlags(annotations)); } else if (DoubleBuffer.class.isAssignableFrom(type)) { return new DoubleBufferMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == byte.class) { return new ByteArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == short.class) { return new ShortArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == int.class) { return new IntArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == long.class) { return new LongArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == float.class) { return new FloatArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && type.getComponentType() == double.class) { return new DoubleArrayMarshaller(getParameterFlags(annotations)); } else if (type.isArray() && Struct.class.isAssignableFrom(type.getComponentType())) { return new StructArrayMarshaller(getParameterFlags(annotations)); } else { throw new IllegalArgumentException("Unsupported parameter type: " + type); } } static final class SessionInvoker implements com.kenai.jaffl.provider.Invoker { static final com.kenai.jffi.Invoker invoker = com.kenai.jffi.Invoker.getInstance(); final Function function; final FunctionInvoker functionInvoker; final Marshaller[] marshallers; SessionInvoker(Function function, FunctionInvoker invoker, Marshaller[] marshallers) { this.function = function; this.functionInvoker = invoker; this.marshallers = marshallers; } final HeapInvocationBuffer marshal(InvocationSession session, Object[] parameters) { HeapInvocationBuffer buffer = new HeapInvocationBuffer(function); for (int i = 0; i < parameters.length; ++i) { marshallers[i].marshal(session, buffer, parameters[i]); } return buffer; } public final Object invoke(Object[] parameters) { InvocationSession session = new InvocationSession(); Object retVal = functionInvoker.invoke(function, marshal(session, parameters)); session.finish(); return retVal; } } static final class DefaultInvoker implements com.kenai.jaffl.provider.Invoker { final Function function; final FunctionInvoker functionInvoker; final Marshaller[] marshallers; DefaultInvoker(Function function, FunctionInvoker invoker, Marshaller[] marshallers) { this.function = function; this.functionInvoker = invoker; this.marshallers = marshallers; } final HeapInvocationBuffer marshal(Object[] parameters) { HeapInvocationBuffer buffer = new HeapInvocationBuffer(function); for (int i = 0; i < parameters.length; ++i) { marshallers[i].marshal(buffer, parameters[i]); } return buffer; } public final Object invoke(Object[] parameters) { return functionInvoker.invoke(function, marshal(parameters)); } } static interface Marshaller { abstract boolean isSessionRequired(); abstract void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter); abstract void marshal(InvocationBuffer buffer, Object parameter); } static interface FunctionInvoker { Object invoke(Function function, HeapInvocationBuffer buffer); } static abstract class BaseMarshaller implements Marshaller { public boolean isSessionRequired() { return false; } public void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter) { marshal(buffer, parameter); } } static abstract class BaseInvoker implements FunctionInvoker { static final com.kenai.jffi.Invoker invoker = com.kenai.jffi.Invoker.getInstance(); } static final class ConvertingInvoker extends BaseInvoker { private final FromNativeConverter converter; private final FromNativeContext context; private final FunctionInvoker nativeInvoker; public ConvertingInvoker(FromNativeConverter converter, FromNativeContext context, FunctionInvoker nativeInvoker) { this.converter = converter; this.context = context; this.nativeInvoker = nativeInvoker; } public final Object invoke(Function function, HeapInvocationBuffer buffer) { return converter.fromNative(nativeInvoker.invoke(function, buffer), context); } } static final class VoidInvoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new VoidInvoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { invoker.invokeInt(function, buffer); return null; } } static final class BooleanInvoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new BooleanInvoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return Boolean.valueOf(invoker.invokeInt(function, buffer) != 0); } } static final class EnumInvoker extends BaseInvoker { private final Class enumClass; private EnumInvoker(Class enumClass) { this.enumClass = enumClass; } @SuppressWarnings("unchecked") public final Object invoke(Function function, HeapInvocationBuffer buffer) { return EnumMapper.getInstance().valueOf(invoker.invokeInt(function, buffer), enumClass); } } static final class Int8Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Int8Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return Byte.valueOf((byte) invoker.invokeInt(function, buffer)); } } static final class Int16Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Int16Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return Short.valueOf((short) invoker.invokeInt(function, buffer)); } } static final class Int32Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Int32Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return Integer.valueOf(invoker.invokeInt(function, buffer)); } } static final class Int64Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Int64Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return Long.valueOf(invoker.invokeLong(function, buffer)); } } static final class NativeLong32Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new NativeLong32Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return NativeLong.valueOf(invoker.invokeInt(function, buffer)); } } static final class NativeLong64Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new NativeLong64Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return NativeLong.valueOf(invoker.invokeLong(function, buffer)); } } static final class Float32Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Float32Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return invoker.invokeFloat(function, buffer); } } static final class Float64Invoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new Float64Invoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return invoker.invokeDouble(function, buffer); } } static final class PointerInvoker extends BaseInvoker { static final FunctionInvoker INSTANCE = new PointerInvoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { return MemoryUtil.newPointer(invoker.invokeAddress(function, buffer)); } } static final class StructInvoker extends BaseInvoker { private final Class structClass; public StructInvoker(Class structClass) { this.structClass = structClass; } public final Object invoke(Function function, HeapInvocationBuffer buffer) { final long ptr = invoker.invokeAddress(function, buffer); if (ptr == 0L) { return null; } try { Struct s = (Struct) structClass.newInstance(); s.useMemory(new DirectMemoryIO(ptr)); return s; } catch (Throwable t) { throw new RuntimeException(t); } } } static final class StringInvoker extends BaseInvoker { com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); static final FunctionInvoker INSTANCE = new StringInvoker(); public final Object invoke(Function function, HeapInvocationBuffer buffer) { final long ptr = invoker.invokeAddress(function, buffer); if (ptr == 0) { return null; } final ByteBuffer buf = ByteBuffer.wrap(IO.getZeroTerminatedByteArray(ptr)); return StringIO.getStringIO().fromNative(buf).toString(); } } /* ---------------------------------------------------------------------- */ static final class BooleanMarshaller extends BaseMarshaller { static final Marshaller INSTANCE = new BooleanMarshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putInt(((Boolean) parameter).booleanValue() ? 1 : 0); } } static final class EnumMarshaller extends BaseMarshaller { static final Marshaller INSTANCE = new EnumMarshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putInt(EnumMapper.getInstance().intValue((Enum) parameter)); } } static final class Int8Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Int8Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putByte(((Number) parameter).intValue()); } } static final class Int16Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Int16Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putShort(((Number) parameter).intValue()); } } static final class Int32Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Int32Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putInt(((Number) parameter).intValue()); } } static final class Int64Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Int64Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putLong(((Number) parameter).longValue()); } } static final class Float32Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Float32Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putFloat(((Number) parameter).floatValue()); } } static final class Float64Marshaller extends BaseMarshaller { static final Marshaller INSTANCE = new Float64Marshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putDouble(((Number) parameter).doubleValue()); } } static final class PointerMarshaller extends BaseMarshaller { static final Marshaller INSTANCE = new PointerMarshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { buffer.putAddress(((Pointer) parameter).address()); } } static final class CharSequenceMarshaller extends BaseMarshaller { static final Marshaller INSTANCE = new CharSequenceMarshaller(); public void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (CharSequence) parameter); } } static abstract class SessionRequiredMarshaller extends BaseMarshaller { @Override public final boolean isSessionRequired() { return true; } public void marshal(InvocationBuffer buffer, Object parameter) { throw new UnsupportedOperationException("Cannot marshal this type without session"); } } static final class StringBuilderMarshaller extends SessionRequiredMarshaller { private final int nflags, inout; public StringBuilderMarshaller(int inout) { this.inout = inout; this.nflags = getNativeArrayFlags(inout | (ParameterFlags.isIn(inout) ? ParameterFlags.NULTERMINATE : 0)); } @Override public void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(session, buffer, (StringBuilder) parameter, inout, nflags); } } static final class StringBufferMarshaller extends SessionRequiredMarshaller { private final int nflags, inout; public StringBufferMarshaller(int inout) { this.inout = inout; this.nflags = getNativeArrayFlags(inout | (ParameterFlags.isIn(inout) ? ParameterFlags.NULTERMINATE : 0)); } @Override public void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(session, buffer, (StringBuffer) parameter, inout, nflags); } } static final class ByteArrayMarshaller extends BaseMarshaller { private final int flags; public ByteArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags | (ParameterFlags.isIn(flags) ? ParameterFlags.NULTERMINATE : 0)); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, byte[].class.cast(parameter), flags); } } static final class ShortArrayMarshaller extends BaseMarshaller { private final int flags; public ShortArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, short[].class.cast(parameter), flags); } } static final class IntArrayMarshaller extends BaseMarshaller { private final int flags; public IntArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, int[].class.cast(parameter), flags); } } static final class LongArrayMarshaller extends BaseMarshaller { private final int flags; public LongArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, long[].class.cast(parameter), flags); } } static final class FloatArrayMarshaller extends BaseMarshaller { private final int flags; public FloatArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, float[].class.cast(parameter), flags); } } static final class DoubleArrayMarshaller extends BaseMarshaller { private final int flags; public DoubleArrayMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, double[].class.cast(parameter), flags); } } static final class ByteBufferMarshaller extends BaseMarshaller { private final int flags; public ByteBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags | (ParameterFlags.isIn(flags) ? ParameterFlags.NULTERMINATE : 0)); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (ByteBuffer) parameter, flags); } } static final class ShortBufferMarshaller extends BaseMarshaller { private final int flags; public ShortBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (ShortBuffer) parameter, flags); } } static final class IntBufferMarshaller extends BaseMarshaller { private final int flags; public IntBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (IntBuffer) parameter, flags); } } static final class LongBufferMarshaller extends BaseMarshaller { private final int flags; public LongBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (LongBuffer) parameter, flags); } } static final class FloatBufferMarshaller extends BaseMarshaller { private final int flags; public FloatBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (FloatBuffer) parameter, flags); } } static final class DoubleBufferMarshaller extends BaseMarshaller { private final int flags; public DoubleBufferMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (DoubleBuffer) parameter, flags); } } static final class ByReferenceMarshaller extends SessionRequiredMarshaller { private final int flags; public ByReferenceMarshaller(int flags) { this.flags = getNativeArrayFlags(flags); } @Override public final void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(session, buffer, (ByReference) parameter, flags); } } static final class StructMarshaller extends BaseMarshaller { private final int nflags, flags; public StructMarshaller(int flags) { this.flags = flags; this.nflags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, (Struct) parameter, flags, nflags); } } static final class StructArrayMarshaller extends BaseMarshaller { private final int nflags, flags; public StructArrayMarshaller(int flags) { this.flags = flags; this.nflags = getNativeArrayFlags(flags); } public final void marshal(InvocationBuffer buffer, Object parameter) { AsmRuntime.marshal(buffer, Struct[].class.cast(parameter), flags, nflags); } } static final class ToNativeConverterMarshaller extends BaseMarshaller { private final ToNativeConverter converter; private final ToNativeContext context = null; private final Marshaller marshaller; public ToNativeConverterMarshaller(ToNativeConverter converter, Marshaller marshaller) { this.converter = converter; this.marshaller = marshaller; } public void marshal(InvocationBuffer buffer, Object parameter) { marshaller.marshal(buffer, converter.toNative(parameter, context)); } @Override public boolean isSessionRequired() { return marshaller.isSessionRequired(); } @Override public void marshal(InvocationSession session, InvocationBuffer buffer, Object parameter) { marshaller.marshal(session, buffer, converter.toNative(parameter, context)); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/DirectMemoryIO.java000066400000000000000000000123471201747543600246130ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.Address; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.provider.AbstractMemoryIO; import com.kenai.jaffl.provider.NullMemoryIO; import com.kenai.jaffl.provider.StringIO; import java.nio.ByteBuffer; import java.nio.charset.Charset; class DirectMemoryIO extends AbstractMemoryIO { static final com.kenai.jffi.MemoryIO IO = com.kenai.jffi.MemoryIO.getInstance(); protected final long address; DirectMemoryIO(long address) { this.address = address & Address.MASK; } public final long address() { return address; } public final byte getByte(long offset) { return IO.getByte(address + offset); } public final short getShort(long offset) { return IO.getShort(address + offset); } public final int getInt(long offset) { return IO.getInt(address + offset); } public final long getLong(long offset) { return IO.getLong(address + offset); } public final float getFloat(long offset) { return IO.getFloat(address + offset); } public final double getDouble(long offset) { return IO.getDouble(address + offset); } public final void putByte(long offset, byte value) { IO.putByte(address + offset, value); } public final void putShort(long offset, short value) { IO.putShort(address + offset, value); } public final void putInt(long offset, int value) { IO.putInt(address + offset, value); } public final void putLong(long offset, long value) { IO.putLong(address + offset, value); } public final void putFloat(long offset, float value) { IO.putFloat(address + offset, value); } public final void putDouble(long offset, double value) { IO.putDouble(address + offset, value); } public final void get(long offset, byte[] dst, int off, int len) { IO.getByteArray(address + offset, dst, off, len); } public final void put(long offset, byte[] src, int off, int len) { IO.putByteArray(address + offset, src, off, len); } public final void get(long offset, short[] dst, int off, int len) { IO.getShortArray(address + offset, dst, off, len); } public final void put(long offset, short[] src, int off, int len) { IO.putShortArray(address + offset, src, off, len); } public final void get(long offset, int[] dst, int off, int len) { IO.getIntArray(address + offset, dst, off, len); } public final void put(long offset, int[] src, int off, int len) { IO.putIntArray(address + offset, src, off, len); } public final void get(long offset, long[] dst, int off, int len) { IO.getLongArray(address + offset, dst, off, len); } public final void put(long offset, long[] src, int off, int len) { IO.putLongArray(address + offset, src, off, len); } public final void get(long offset, float[] dst, int off, int len) { IO.getFloatArray(address + offset, dst, off, len); } public final void put(long offset, float[] src, int off, int len) { IO.putFloatArray(address + offset, src, off, len); } public final void get(long offset, double[] dst, int off, int len) { IO.getDoubleArray(address + offset, dst, off, len); } public final void put(long offset, double[] src, int off, int len) { IO.putDoubleArray(address + offset, src, off, len); } public MemoryIO getMemoryIO(long offset) { return MemoryUtil.newMemoryIO(IO.getAddress(address + offset)); } public MemoryIO getMemoryIO(long offset, long size) { final long ptr = IO.getAddress(this.address + offset); return ptr != 0 ? new BoundedDirectMemoryIO(new DirectMemoryIO(ptr), 0, size) : new NullMemoryIO(); } @Override public Pointer getPointer(long offset) { return MemoryUtil.newPointer(IO.getAddress(address + offset)); } @Override public void putPointer(long offset, Pointer value) { IO.putAddress(address + offset, value.address()); } @Override public String getString(long offset) { final byte[] bytes = IO.getZeroTerminatedByteArray(address + offset); return StringIO.getStringIO().fromNative(ByteBuffer.wrap(bytes)).toString(); } @Override public String getString(long offset, int maxLength, Charset cs) { byte[] bytes = IO.getZeroTerminatedByteArray(address + offset, maxLength); final ByteBuffer buf = ByteBuffer.wrap(bytes); return StringIO.getStringIO().fromNative(buf).toString(); } @Override public void putString(long offset, String string, int maxLength, Charset cs) { ByteBuffer buf = StringIO.getStringIO().toNative(string, 0, true); IO.putByteArray(address + offset, buf.array(), buf.arrayOffset() + buf.position(), buf.remaining()); } public int indexOf(long offset, byte value, int maxlen) { return (int) IO.indexOf(address + offset, value, maxlen); } public final boolean isDirect() { return true; } public final void setMemory(long offset, long size, byte value) { IO.setMemory(this.address + offset, size, value); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/EnumResultConverter.java000066400000000000000000000012061201747543600257430ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.mapper.FromNativeContext; import com.kenai.jaffl.mapper.FromNativeConverter; import com.kenai.jaffl.util.EnumMapper; public class EnumResultConverter implements FromNativeConverter { private final Class enumClass; EnumResultConverter(Class enumClass) { this.enumClass = enumClass; } @SuppressWarnings("unchecked") public Object fromNative(Object nativeValue, FromNativeContext context) { return EnumMapper.getInstance().valueOf(((Integer) nativeValue), enumClass); } public Class nativeType() { return Integer.class; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/IdentityFunctionMapper.java000066400000000000000000000011231201747543600264120ustar00rootroot00000000000000package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.mapper.FunctionMapper; /** * An implementation of {@link FunctionMapper} that just returns the same name as input */ public class IdentityFunctionMapper implements FunctionMapper { private static final class SingletonHolder { public static final FunctionMapper INSTANCE = new IdentityFunctionMapper(); } public static FunctionMapper getInstance() { return SingletonHolder.INSTANCE; } public String mapFunctionName(String functionName, Context context) { return functionName; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/InvokerFactory.java000066400000000000000000000005651201747543600247240ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.provider.Invoker; import java.lang.reflect.Method; import java.util.Map; public interface InvokerFactory { Invoker createInvoker(Method method, com.kenai.jaffl.provider.Library library, Map options); boolean isMethodSupported(Method method); } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/InvokerUtil.java000066400000000000000000000126311201747543600242270ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.Address; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.NativeLong; import com.kenai.jaffl.Platform; import com.kenai.jaffl.Pointer; import com.kenai.jaffl.annotations.IgnoreError; import com.kenai.jaffl.annotations.SaveError; import com.kenai.jaffl.byref.ByReference; import com.kenai.jaffl.struct.Struct; import com.kenai.jffi.Type; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.nio.Buffer; import java.util.Map; final class InvokerUtil { static final Type getNativeReturnType(Method method) { return getNativeReturnType(method.getReturnType()); } static final Type getNativeReturnType(Class type) { if (Void.class.isAssignableFrom(type) || void.class == type) { return Type.VOID; } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) { return Type.SINT32; } else if (Byte.class.isAssignableFrom(type) || byte.class == type) { return Type.SINT8; } else if (Short.class.isAssignableFrom(type) || short.class == type) { return Type.SINT16; } else if (Integer.class.isAssignableFrom(type) || int.class == type) { return Type.SINT32; } else if (Long.class.isAssignableFrom(type) || long.class == type) { return Type.SINT64; } else if (NativeLong.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? Type.SINT32: Type.SINT64; } else if (Float.class.isAssignableFrom(type) || float.class == type) { return Type.FLOAT; } else if (Double.class.isAssignableFrom(type) || double.class == type) { return Type.DOUBLE; } else if (Enum.class.isAssignableFrom(type)) { return Type.SINT32; } else if (Pointer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Address.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Struct.class.isAssignableFrom(type)) { return Type.POINTER; } else if (String.class.isAssignableFrom(type)) { return Type.POINTER; } else { throw new IllegalArgumentException("Unsupported return type: " + type); } } static final Type getNativeParameterType(Class type) { if (Byte.class.isAssignableFrom(type) || byte.class == type) { return Type.SINT8; } else if (Short.class.isAssignableFrom(type) || short.class == type) { return Type.SINT16; } else if (Integer.class.isAssignableFrom(type) || int.class == type) { return Type.SINT32; } else if (Long.class.isAssignableFrom(type) || long.class == type) { return Type.SINT64; } else if (NativeLong.class.isAssignableFrom(type)) { return Platform.getPlatform().longSize() == 32 ? Type.SINT32: Type.SINT64; } else if (Float.class.isAssignableFrom(type) || float.class == type) { return Type.FLOAT; } else if (Double.class.isAssignableFrom(type) || double.class == type) { return Type.DOUBLE; } else if (Boolean.class.isAssignableFrom(type) || boolean.class == type) { return Type.SINT32; } else if (Enum.class.isAssignableFrom(type)) { return Type.SINT32; } else if (Pointer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Address.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Struct.class.isAssignableFrom(type)) { return Type.POINTER; } else if (Buffer.class.isAssignableFrom(type)) { return Type.POINTER; } else if (CharSequence.class.isAssignableFrom(type)) { return Type.POINTER; } else if (ByReference.class.isAssignableFrom(type)) { return Type.POINTER; } else if (type.isArray()) { return Type.POINTER; } else { throw new IllegalArgumentException("Unsupported parameter type: " + type); } } public static final boolean requiresErrno(Method method) { boolean saveError = true; for (Annotation a : method.getAnnotations()) { if (a instanceof IgnoreError) { saveError = false; } else if (a instanceof SaveError) { saveError = true; } } return saveError; } public static final com.kenai.jffi.CallingConvention getCallingConvention(Map libraryOptions) { Object convention = (com.kenai.jaffl.CallingConvention) libraryOptions.get(LibraryOption.CallingConvention); // If someone passed in the jffi calling convention, just use it. if (convention instanceof com.kenai.jffi.CallingConvention) { return (com.kenai.jffi.CallingConvention) convention; } if (convention instanceof com.kenai.jaffl.CallingConvention) switch ((com.kenai.jaffl.CallingConvention) convention) { case DEFAULT: return com.kenai.jffi.CallingConvention.DEFAULT; case STDCALL: return com.kenai.jffi.CallingConvention.STDCALL; } else if (convention != null) { throw new IllegalArgumentException("unknown calling convention: " + convention); } return com.kenai.jffi.CallingConvention.DEFAULT; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/JFFIPointer.java000066400000000000000000000012241201747543600240270ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; final class JFFIPointer extends DirectMemoryIO { JFFIPointer(long address) { super(address); } public int intValue() { return (int) address; } public long longValue() { return address; } public float floatValue() { return (float) address; } public double doubleValue() { return (double) address; } public static final JFFIPointer valueOf(long address) { return new JFFIPointer(address); } public static final JFFIPointer valueOf(int address) { return new JFFIPointer(address & 0xffffffffL); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/JNIInvokeInterface.java000066400000000000000000000005611201747543600253700ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; /** * Indexes of JavaVM methods */ public class JNIInvokeInterface { public static final int DestroyJavaVM = 3; public static final int AttachCurrentThread = 4; public static final int DetachCurrentThread = 5; public static final int GetEnv = 6; public static final int AttachCurrentThreadAsDaemon = 7; } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/JNINativeInterface.java000066400000000000000000000311161201747543600253630ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; /** * * WARNING: Highly experimental!!! * * This class contains constants that are the indexes withing the JNINativeInterface_ * struct of each of the JNIEnv functions. To invoke one of the functions, the * index _must_ be multiplied by sizeof(void *), then used as an index into the table. * * These indexes are valid on both 32bit and 64bit linux and macos. Win32 also * seems to be the same. Other platforms may be completely different. */ public final class JNINativeInterface { private JNINativeInterface() { } public static final int GetVersion = 4; public static final int DefineClass = 5; public static final int FindClass = 6; public static final int FromReflectedMethod = 7; public static final int FromReflectedField = 8; public static final int ToReflectedMethod = 9; public static final int GetSuperclass = 10; public static final int IsAssignableFrom = 11; public static final int ToReflectedField = 12; public static final int Throw = 13; public static final int ThrowNew = 14; public static final int ExceptionOccurred = 15; public static final int ExceptionDescribe = 16; public static final int ExceptionClear = 17; public static final int FatalError = 18; public static final int PushLocalFrame = 19; public static final int PopLocalFrame = 20; public static final int NewGlobalRef = 21; public static final int DeleteGlobalRef = 22; public static final int DeleteLocalRef = 23; public static final int IsSameObject = 24; public static final int NewLocalRef = 25; public static final int EnsureLocalCapacity = 26; public static final int AllocObject = 27; public static final int NewObject = 28; public static final int NewObjectV = 29; public static final int NewObjectA = 30; public static final int GetObjectClass = 31; public static final int IsInstanceOf = 32; public static final int GetMethodID = 33; public static final int CallObjectMethod = 34; public static final int CallObjectMethodV = 35; public static final int CallObjectMethodA = 36; public static final int CallBooleanMethod = 37; public static final int CallBooleanMethodV = 38; public static final int CallBooleanMethodA = 39; public static final int CallByteMethod = 40; public static final int CallByteMethodV = 41; public static final int CallByteMethodA = 42; public static final int CallCharMethod = 43; public static final int CallCharMethodV = 44; public static final int CallCharMethodA = 45; public static final int CallShortMethod = 46; public static final int CallShortMethodV = 47; public static final int CallShortMethodA = 48; public static final int CallIntMethod = 49; public static final int CallIntMethodV = 50; public static final int CallIntMethodA = 51; public static final int CallLongMethod = 52; public static final int CallLongMethodV = 53; public static final int CallLongMethodA = 54; public static final int CallFloatMethod = 55; public static final int CallFloatMethodV = 56; public static final int CallFloatMethodA = 57; public static final int CallDoubleMethod = 58; public static final int CallDoubleMethodV = 59; public static final int CallDoubleMethodA = 60; public static final int CallVoidMethod = 61; public static final int CallVoidMethodV = 62; public static final int CallVoidMethodA = 63; public static final int CallNonvirtualObjectMethod = 64; public static final int CallNonvirtualObjectMethodV = 65; public static final int CallNonvirtualObjectMethodA = 66; public static final int CallNonvirtualBooleanMethod = 67; public static final int CallNonvirtualBooleanMethodV = 68; public static final int CallNonvirtualBooleanMethodA = 69; public static final int CallNonvirtualByteMethod = 70; public static final int CallNonvirtualByteMethodV = 71; public static final int CallNonvirtualByteMethodA = 72; public static final int CallNonvirtualCharMethod = 73; public static final int CallNonvirtualCharMethodV = 74; public static final int CallNonvirtualCharMethodA = 75; public static final int CallNonvirtualShortMethod = 76; public static final int CallNonvirtualShortMethodV = 77; public static final int CallNonvirtualShortMethodA = 78; public static final int CallNonvirtualIntMethod = 79; public static final int CallNonvirtualIntMethodV = 80; public static final int CallNonvirtualIntMethodA = 81; public static final int CallNonvirtualLongMethod = 82; public static final int CallNonvirtualLongMethodV = 83; public static final int CallNonvirtualLongMethodA = 84; public static final int CallNonvirtualFloatMethod = 85; public static final int CallNonvirtualFloatMethodV = 86; public static final int CallNonvirtualFloatMethodA = 87; public static final int CallNonvirtualDoubleMethod = 88; public static final int CallNonvirtualDoubleMethodV = 89; public static final int CallNonvirtualDoubleMethodA = 90; public static final int CallNonvirtualVoidMethod = 91; public static final int CallNonvirtualVoidMethodV = 92; public static final int CallNonvirtualVoidMethodA = 93; public static final int GetFieldID = 94; public static final int GetObjectField = 95; public static final int GetBooleanField = 96; public static final int GetByteField = 97; public static final int GetCharField = 98; public static final int GetShortField = 99; public static final int GetIntField = 100; public static final int GetLongField = 101; public static final int GetFloatField = 102; public static final int GetDoubleField = 103; public static final int SetObjectField = 104; public static final int SetBooleanField = 105; public static final int SetByteField = 106; public static final int SetCharField = 107; public static final int SetShortField = 108; public static final int SetIntField = 109; public static final int SetLongField = 110; public static final int SetFloatField = 111; public static final int SetDoubleField = 112; public static final int GetStaticMethodID = 113; public static final int CallStaticObjectMethod = 114; public static final int CallStaticObjectMethodV = 115; public static final int CallStaticObjectMethodA = 116; public static final int CallStaticBooleanMethod = 117; public static final int CallStaticBooleanMethodV = 118; public static final int CallStaticBooleanMethodA = 119; public static final int CallStaticByteMethod = 120; public static final int CallStaticByteMethodV = 121; public static final int CallStaticByteMethodA = 122; public static final int CallStaticCharMethod = 123; public static final int CallStaticCharMethodV = 124; public static final int CallStaticCharMethodA = 125; public static final int CallStaticShortMethod = 126; public static final int CallStaticShortMethodV = 127; public static final int CallStaticShortMethodA = 128; public static final int CallStaticIntMethod = 129; public static final int CallStaticIntMethodV = 130; public static final int CallStaticIntMethodA = 131; public static final int CallStaticLongMethod = 132; public static final int CallStaticLongMethodV = 133; public static final int CallStaticLongMethodA = 134; public static final int CallStaticFloatMethod = 135; public static final int CallStaticFloatMethodV = 136; public static final int CallStaticFloatMethodA = 137; public static final int CallStaticDoubleMethod = 138; public static final int CallStaticDoubleMethodV = 139; public static final int CallStaticDoubleMethodA = 140; public static final int CallStaticVoidMethod = 141; public static final int CallStaticVoidMethodV = 142; public static final int CallStaticVoidMethodA = 143; public static final int GetStaticFieldID = 144; public static final int GetStaticObjectField = 145; public static final int GetStaticBooleanField = 146; public static final int GetStaticByteField = 147; public static final int GetStaticCharField = 148; public static final int GetStaticShortField = 149; public static final int GetStaticIntField = 150; public static final int GetStaticLongField = 151; public static final int GetStaticFloatField = 152; public static final int GetStaticDoubleField = 153; public static final int SetStaticObjectField = 154; public static final int SetStaticBooleanField = 155; public static final int SetStaticByteField = 156; public static final int SetStaticCharField = 157; public static final int SetStaticShortField = 158; public static final int SetStaticIntField = 159; public static final int SetStaticLongField = 160; public static final int SetStaticFloatField = 161; public static final int SetStaticDoubleField = 162; public static final int NewString = 163; public static final int GetStringLength = 164; public static final int GetStringChars = 165; public static final int ReleaseStringChars = 166; public static final int NewStringUTF = 167; public static final int GetStringUTFLength = 168; public static final int GetStringUTFChars = 169; public static final int ReleaseStringUTFChars = 170; public static final int GetArrayLength = 171; public static final int NewObjectArray = 172; public static final int GetObjectArrayElement = 173; public static final int SetObjectArrayElement = 174; public static final int NewBooleanArray = 175; public static final int NewByteArray = 176; public static final int NewCharArray = 177; public static final int NewShortArray = 178; public static final int NewIntArray = 179; public static final int NewLongArray = 180; public static final int NewFloatArray = 181; public static final int NewDoubleArray = 182; public static final int GetBooleanArrayElements = 183; public static final int GetByteArrayElements = 184; public static final int GetCharArrayElements = 185; public static final int GetShortArrayElements = 186; public static final int GetIntArrayElements = 187; public static final int GetLongArrayElements = 188; public static final int GetFloatArrayElements = 189; public static final int GetDoubleArrayElements = 190; public static final int ReleaseBooleanArrayElements = 191; public static final int ReleaseByteArrayElements = 192; public static final int ReleaseCharArrayElements = 193; public static final int ReleaseShortArrayElements = 194; public static final int ReleaseIntArrayElements = 195; public static final int ReleaseLongArrayElements = 196; public static final int ReleaseFloatArrayElements = 197; public static final int ReleaseDoubleArrayElements = 198; public static final int GetBooleanArrayRegion = 199; public static final int GetByteArrayRegion = 200; public static final int GetCharArrayRegion = 201; public static final int GetShortArrayRegion = 202; public static final int GetIntArrayRegion = 203; public static final int GetLongArrayRegion = 204; public static final int GetFloatArrayRegion = 205; public static final int GetDoubleArrayRegion = 206; public static final int SetBooleanArrayRegion = 207; public static final int SetByteArrayRegion = 208; public static final int SetCharArrayRegion = 209; public static final int SetShortArrayRegion = 210; public static final int SetIntArrayRegion = 211; public static final int SetLongArrayRegion = 212; public static final int SetFloatArrayRegion = 213; public static final int SetDoubleArrayRegion = 214; public static final int RegisterNatives = 215; public static final int UnregisterNatives = 216; public static final int MonitorEnter = 217; public static final int MonitorExit = 218; public static final int GetJavaVM = 219; public static final int GetStringRegion = 220; public static final int GetStringUTFRegion = 221; public static final int GetPrimitiveArrayCritical = 222; public static final int ReleasePrimitiveArrayCritical = 223; public static final int GetStringCritical = 224; public static final int ReleaseStringCritical = 225; public static final int NewWeakGlobalRef = 226; public static final int DeleteWeakGlobalRef = 227; public static final int ExceptionCheck = 228; public static final int NewDirectByteBuffer = 229; public static final int GetDirectBufferAddress = 230; public static final int GetDirectBufferCapacity = 231; public static final int GetObjectRefType = 232; }; jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/Library.java000066400000000000000000000050361201747543600233610ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.provider.Invoker; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; public class Library extends com.kenai.jaffl.provider.Library { private final String[] libraryNames; private volatile List nativeLibraries = Collections.EMPTY_LIST; Library(String name) { this.libraryNames = new String[] { name }; } Library(String... names) { this.libraryNames = (String[]) names.clone(); } public Invoker getInvoker(Method method, Map options) { return DefaultInvokerFactory.getInstance().createInvoker(method, this, options); } public Object libraryLock() { return this; } long getSymbolAddress(String name) { for (com.kenai.jffi.Library l : getNativeLibraries()) { long address = l.getSymbolAddress(name); if (address != 0) { return address; } } return 0; } long findSymbolAddress(String name) { long address = getSymbolAddress(name); if (address == 0) { throw new SymbolNotFoundError(com.kenai.jffi.Library.getLastError()); } return address; } private synchronized List getNativeLibraries() { if (!this.nativeLibraries.isEmpty()) { return nativeLibraries; } return nativeLibraries = loadNativeLibraries(); } private synchronized List loadNativeLibraries() { List libs = new ArrayList(); List errors = new ArrayList(0); for (String libraryName : libraryNames) { com.kenai.jffi.Library lib; lib = com.kenai.jffi.Library.getCachedInstance(libraryName, com.kenai.jffi.Library.LAZY); if (lib == null) { String path; if (libraryName != null && (path = locateLibrary(libraryName)) != null && !libraryName.equals(path)) { lib = com.kenai.jffi.Library.getCachedInstance(path, com.kenai.jffi.Library.LAZY); } } if (lib == null) { throw new UnsatisfiedLinkError(com.kenai.jffi.Library.getLastError()); } libs.add(lib); } return Collections.unmodifiableList(libs); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/LibraryLoader.java000066400000000000000000000005451201747543600245100ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import java.util.Map; public abstract class LibraryLoader { abstract T loadLibrary(Library library, Class interfaceClass, Map libraryOptions); abstract boolean isInterfaceSupported(Class interfaceClass, Map libraryOptions); } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/MemoryManager.java000066400000000000000000000026531201747543600245220ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.Pointer; import java.nio.Buffer; import java.nio.ByteBuffer; public class MemoryManager implements com.kenai.jaffl.provider.MemoryManager { public MemoryIO allocate(int size) { return new ArrayMemoryIO(size); } public MemoryIO allocateDirect(int size) { return new BoundedDirectMemoryIO(new AllocatedDirectMemoryIO(size, false), 0, size); } public MemoryIO allocateDirect(int size, boolean clear) { return new BoundedDirectMemoryIO(new AllocatedDirectMemoryIO(size, clear), 0, size); } public MemoryIO wrap(Pointer ptr) { if (ptr instanceof MemoryIO) { return (MemoryIO) ptr; } else if (ptr.isDirect()) { return MemoryUtil.newMemoryIO(ptr.address()); } throw new UnsupportedOperationException("Unsupported Pointer type: " + ptr.getClass()); } public MemoryIO wrap(Pointer ptr, int size) { if (ptr.isDirect()) { return MemoryUtil.newMemoryIO(ptr.address(), size); } throw new UnsupportedOperationException("Unsupported Pointer type: " + ptr.getClass()); } public MemoryIO wrap(ByteBuffer buffer) { return new ByteBufferMemoryIO(buffer); } public Pointer getBufferPointer(Buffer buffer) { throw new UnsupportedOperationException("Not supported yet."); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/MemoryUtil.java000066400000000000000000000020751201747543600240630ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.provider.NullMemoryIO; public final class MemoryUtil { private MemoryUtil() {} static final com.kenai.jaffl.Pointer newPointer(long ptr) { return ptr != 0 ? new DirectMemoryIO(ptr) : null; } static final com.kenai.jaffl.MemoryIO newMemoryIO(long ptr) { return ptr != 0 ? new DirectMemoryIO(ptr) : NullMemoryIO.INSTANCE; } static final com.kenai.jaffl.MemoryIO newMemoryIO(long ptr, long size) { return ptr != 0 ? new BoundedDirectMemoryIO(new DirectMemoryIO(ptr), 0, size) : NullMemoryIO.INSTANCE; } static final long getAddress(MemoryIO ptr) { if (ptr == null) { return 0L; } else if (ptr instanceof JFFIPointer) { return ((JFFIPointer) ptr).address; } else if (ptr instanceof DirectMemoryIO) { return ((DirectMemoryIO) ptr).address; } throw new IllegalArgumentException("attempted to get address of non-direct memory. " + ptr.getClass()); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/NullTypeMapper.java000066400000000000000000000010721201747543600246720ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.mapper.FromNativeConverter; import com.kenai.jaffl.mapper.ToNativeConverter; import com.kenai.jaffl.mapper.TypeMapper; /** * An instance of {@link TypeMapper} which always returns null */ public class NullTypeMapper implements TypeMapper { public static final TypeMapper INSTANCE = new NullTypeMapper(); public FromNativeConverter getFromNativeConverter(Class type) { return null; } public ToNativeConverter getToNativeConverter(Class type) { return null; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/NumberUtil.java000066400000000000000000000060461201747543600240450ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.NativeLong; public final class NumberUtil { private NumberUtil() {} static final Class getBoxedClass(Class c) { if (!c.isPrimitive()) { return c; } if (void.class == c) { return Void.class; } else if (byte.class == c) { return Byte.class; } else if (char.class == c) { return Character.class; } else if (short.class == c) { return Short.class; } else if (int.class == c) { return Integer.class; } else if (long.class == c) { return Long.class; } else if (float.class == c) { return Float.class; } else if (double.class == c) { return Double.class; } else if (boolean.class == c) { return Boolean.class; } else { throw new IllegalArgumentException("unknown primitive class"); } } static final Class getPrimitiveClass(Class c) { if (Void.class == c) { return void.class; } else if (Boolean.class == c) { return boolean.class; } else if (Byte.class == c) { return byte.class; } else if (Character.class == c) { return char.class; } else if (Short.class == c) { return short.class; } else if (Integer.class == c) { return int.class; } else if (Long.class == c) { return long.class; } else if (Float.class == c) { return float.class; } else if (Double.class == c) { return double.class; } else if (NativeLong.class == c) { return long.class; } else if (c.isPrimitive()) { return c; } else { throw new IllegalArgumentException("unsupported number class"); } } public static boolean isPrimitiveInt(Class c) { return byte.class == c || short.class == c || int.class == c || boolean.class == c; } public static final void widen(SkinnyMethodAdapter mv, Class from, Class to) { if (long.class == to && long.class != from && isPrimitiveInt(from)) { mv.i2l(); } } public static final void narrow(SkinnyMethodAdapter mv, Class from, Class to) { if (!from.equals(to)) { if (byte.class == to || short.class == to || char.class == to || int.class == to || boolean.class == to) { if (long.class == from) { mv.l2i(); } if (byte.class == to) { mv.i2b(); } else if (short.class == to) { mv.i2s(); } else if (char.class == to) { mv.i2c(); } else if (boolean.class == to) { // Ensure only 0x0 and 0x1 values are used for boolean mv.iconst_1(); mv.iand(); } } } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/Provider.java000066400000000000000000000076121201747543600235510ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.provider.MemoryManager; import com.kenai.jaffl.provider.NativeType; import com.kenai.jffi.LastError; import java.util.Map; public class Provider extends com.kenai.jaffl.FFIProvider { private final MemoryManager memoryManager = new com.kenai.jaffl.provider.jffi.MemoryManager(); @Override public MemoryManager getMemoryManager() { return memoryManager; } @Override public T loadLibrary(String libraryName, Class interfaceClass, Map libraryOptions) { return loadLibrary(new Library(libraryName), interfaceClass, libraryOptions); } @Override public T loadLibrary(Class interfaceClass, Map libraryOptions, String... libraryNames) { return loadLibrary(new Library(libraryNames), interfaceClass, libraryOptions); } private T loadLibrary(Library library, Class interfaceClass, Map libraryOptions) { try { if (AsmLibraryLoader.getInstance().isInterfaceSupported(interfaceClass, libraryOptions)) { return AsmLibraryLoader.getInstance().loadLibrary(library, interfaceClass, libraryOptions); } } catch (Exception ex) { ex.printStackTrace(System.err); } return ProxyLibraryLoader.getInstance().loadLibrary(library, interfaceClass, libraryOptions); } @Override public int getLastError() { return LastError.getInstance().get(); } @Override public void setLastError(int error) { LastError.getInstance().set(error); } private static final class TypeDelegate implements com.kenai.jaffl.Type { private final com.kenai.jffi.Type type; public TypeDelegate(com.kenai.jffi.Type type) { this.type = type; } public int alignment() { return type.alignment(); } public int size() { return type.size(); } } private static final class BadType implements com.kenai.jaffl.Type { private final NativeType type; public BadType(NativeType type) { this.type = type; } public int alignment() { throw new RuntimeException("invalid type: " + type); } public int size() { throw new RuntimeException("invalid type: " + type); } } @Override public com.kenai.jaffl.Type getType(NativeType type) { switch (type) { case VOID: return new TypeDelegate(com.kenai.jffi.Type.VOID); case SCHAR: return new TypeDelegate(com.kenai.jffi.Type.SCHAR); case UCHAR: return new TypeDelegate(com.kenai.jffi.Type.UCHAR); case SSHORT: return new TypeDelegate(com.kenai.jffi.Type.SSHORT); case USHORT: return new TypeDelegate(com.kenai.jffi.Type.USHORT); case SINT: return new TypeDelegate(com.kenai.jffi.Type.SINT); case UINT: return new TypeDelegate(com.kenai.jffi.Type.UINT); case SLONG: return new TypeDelegate(com.kenai.jffi.Type.SLONG); case ULONG: return new TypeDelegate(com.kenai.jffi.Type.ULONG); case SLONGLONG: return new TypeDelegate(com.kenai.jffi.Type.SINT64); case ULONGLONG: return new TypeDelegate(com.kenai.jffi.Type.UINT64); case FLOAT: return new TypeDelegate(com.kenai.jffi.Type.FLOAT); case DOUBLE: return new TypeDelegate(com.kenai.jffi.Type.DOUBLE); case ADDRESS: return new TypeDelegate(com.kenai.jffi.Type.POINTER); default: return new BadType(type); } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/ProxyLibraryLoader.java000066400000000000000000000013121201747543600255430ustar00rootroot00000000000000package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.LibraryOption; import com.kenai.jaffl.provider.NativeInvocationHandler; import java.util.Map; class ProxyLibraryLoader extends LibraryLoader { private static final LibraryLoader INSTANCE = new ProxyLibraryLoader(); static final LibraryLoader getInstance() { return INSTANCE; } T loadLibrary(Library library, Class interfaceClass, Map libraryOptions) { return interfaceClass.cast(NativeInvocationHandler.wrapInterface(library, interfaceClass, libraryOptions)); } boolean isInterfaceSupported(Class interfaceClass, Map libraryOptions) { return true; } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/SkinnyMethodAdapter.java000066400000000000000000000567001201747543600256760ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import java.io.PrintStream; import java.io.PrintWriter; import java.lang.reflect.Method; import java.util.Map; import static com.kenai.jaffl.provider.jffi.CodegenUtils.*; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.Attribute; import org.objectweb.asm.Label; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; /** * * @author headius */ public class SkinnyMethodAdapter implements MethodVisitor, Opcodes { private final static boolean DEBUG = Boolean.getBoolean("jaffl.compile.dump"); private MethodVisitor method; /** Creates a new instance of SkinnyMethodAdapter */ public SkinnyMethodAdapter(MethodVisitor method) { setMethodVisitor(method); } public SkinnyMethodAdapter() { } public MethodVisitor getMethodVisitor() { return method; } public void setMethodVisitor(MethodVisitor mv) { this.method = DEBUG ? AsmUtil.newTraceMethodVisitor(mv) : mv; } public void aload(int arg0) { getMethodVisitor().visitVarInsn(ALOAD, arg0); } public void aload(int... args) { for (int arg : args) { getMethodVisitor().visitVarInsn(ALOAD, arg); } } public void iload(int arg0) { getMethodVisitor().visitVarInsn(ILOAD, arg0); } public void iload(int... args) { for (int arg : args) { getMethodVisitor().visitVarInsn(ILOAD, arg); } } public void lload(int arg0) { getMethodVisitor().visitVarInsn(LLOAD, arg0); } public void lload(int... args) { for (int arg : args) { getMethodVisitor().visitVarInsn(LLOAD, arg); } } public void fload(int arg0) { getMethodVisitor().visitVarInsn(FLOAD, arg0); } public void fload(int... args) { for (int arg : args) { getMethodVisitor().visitVarInsn(FLOAD, arg); } } public void dload(int arg0) { getMethodVisitor().visitVarInsn(DLOAD, arg0); } public void dload(int... args) { for (int arg : args) { getMethodVisitor().visitVarInsn(DLOAD, arg); } } public void astore(int arg0) { getMethodVisitor().visitVarInsn(ASTORE, arg0); } public void istore(int arg0) { getMethodVisitor().visitVarInsn(ISTORE, arg0); } public void lstore(int arg0) { getMethodVisitor().visitVarInsn(LSTORE, arg0); } public void fstore(int arg0) { getMethodVisitor().visitVarInsn(FSTORE, arg0); } public void dstore(int arg0) { getMethodVisitor().visitVarInsn(DSTORE, arg0); } public void ldc(Object arg0) { getMethodVisitor().visitLdcInsn(arg0); } public void bipush(int arg) { getMethodVisitor().visitIntInsn(BIPUSH, arg); } public void sipush(int arg) { getMethodVisitor().visitIntInsn(SIPUSH, arg); } public void pushInt(int value) { if (value <= Byte.MAX_VALUE && value >= Byte.MIN_VALUE) { switch (value) { case -1: iconst_m1(); break; case 0: iconst_0(); break; case 1: iconst_1(); break; case 2: iconst_2(); break; case 3: iconst_3(); break; case 4: iconst_4(); break; case 5: iconst_5(); break; default: bipush(value); break; } } else if (value <= Short.MAX_VALUE && value >= Short.MIN_VALUE) { sipush(value); } else { ldc(value); } } public void pushBoolean(boolean bool) { if (bool) iconst_1(); else iconst_0(); } public void invokestatic(String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(INVOKESTATIC, arg1, arg2, arg3); } public void invokestatic(Class recv, String methodName, Class returnType, Class... parameterTypes) { getMethodVisitor().visitMethodInsn(INVOKESTATIC, p(recv), methodName, sig(returnType, parameterTypes)); } public void invokespecial(String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(INVOKESPECIAL, arg1, arg2, arg3); } public void invokespecial(Class recv, String methodName, Class returnType, Class... parameterTypes) { getMethodVisitor().visitMethodInsn(INVOKESPECIAL, p(recv), methodName, sig(returnType, parameterTypes)); } public void invokevirtual(String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(INVOKEVIRTUAL, arg1, arg2, arg3); } public void invokevirtual(Class recv, String methodName, Class returnType, Class... parameterTypes) { getMethodVisitor().visitMethodInsn(INVOKEVIRTUAL, p(recv), methodName, sig(returnType, parameterTypes)); } public void invokeinterface(String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(INVOKEINTERFACE, arg1, arg2, arg3); } public void invokeinterface(Class recv, String methodName, Class returnType, Class... parameterTypes) { getMethodVisitor().visitMethodInsn(INVOKEINTERFACE, p(recv), methodName, sig(returnType, parameterTypes)); } public void invokedynamic(String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(INVOKEDYNAMIC, arg1, arg2, arg3); } public void aprintln() { dup(); getstatic(p(System.class), "out", ci(PrintStream.class)); swap(); invokevirtual(p(PrintStream.class), "println", sig(void.class, params(Object.class))); } public void areturn() { getMethodVisitor().visitInsn(ARETURN); } public void ireturn() { getMethodVisitor().visitInsn(IRETURN); } public void freturn() { getMethodVisitor().visitInsn(FRETURN); } public void lreturn() { getMethodVisitor().visitInsn(LRETURN); } public void dreturn() { getMethodVisitor().visitInsn(DRETURN); } public void newobj(String arg0) { getMethodVisitor().visitTypeInsn(NEW, arg0); } public void dup() { getMethodVisitor().visitInsn(DUP); } public void swap() { getMethodVisitor().visitInsn(SWAP); } public void swap2() { dup2_x2(); pop2(); } public void getstatic(String arg1, String arg2, String arg3) { getMethodVisitor().visitFieldInsn(GETSTATIC, arg1, arg2, arg3); } public void putstatic(String arg1, String arg2, String arg3) { getMethodVisitor().visitFieldInsn(PUTSTATIC, arg1, arg2, arg3); } public void getfield(String arg1, String arg2, String arg3) { getMethodVisitor().visitFieldInsn(GETFIELD, arg1, arg2, arg3); } public void putfield(String arg1, String arg2, String arg3) { getMethodVisitor().visitFieldInsn(PUTFIELD, arg1, arg2, arg3); } public void voidreturn() { getMethodVisitor().visitInsn(RETURN); } public void anewarray(String arg0) { getMethodVisitor().visitTypeInsn(ANEWARRAY, arg0); } public void multianewarray(String arg0, int dims) { getMethodVisitor().visitMultiANewArrayInsn(arg0, dims); } public void newarray(int arg0) { getMethodVisitor().visitIntInsn(NEWARRAY, arg0); } public void iconst_m1() { getMethodVisitor().visitInsn(ICONST_M1); } public void iconst_0() { getMethodVisitor().visitInsn(ICONST_0); } public void iconst_1() { getMethodVisitor().visitInsn(ICONST_1); } public void iconst_2() { getMethodVisitor().visitInsn(ICONST_2); } public void iconst_3() { getMethodVisitor().visitInsn(ICONST_3); } public void iconst_4() { getMethodVisitor().visitInsn(ICONST_4); } public void iconst_5() { getMethodVisitor().visitInsn(ICONST_5); } public void lconst_0() { getMethodVisitor().visitInsn(LCONST_0); } public void aconst_null() { getMethodVisitor().visitInsn(ACONST_NULL); } public void label(Label label) { getMethodVisitor().visitLabel(label); } public void nop() { getMethodVisitor().visitInsn(NOP); } public void pop() { getMethodVisitor().visitInsn(POP); } public void pop2() { getMethodVisitor().visitInsn(POP2); } public void arrayload() { getMethodVisitor().visitInsn(AALOAD); } public void arraystore() { getMethodVisitor().visitInsn(AASTORE); } public void iarrayload() { getMethodVisitor().visitInsn(IALOAD); } public void barrayload() { getMethodVisitor().visitInsn(BALOAD); } public void barraystore() { getMethodVisitor().visitInsn(BASTORE); } public void aaload() { getMethodVisitor().visitInsn(AALOAD); } public void aastore() { getMethodVisitor().visitInsn(AASTORE); } public void iaload() { getMethodVisitor().visitInsn(IALOAD); } public void iastore() { getMethodVisitor().visitInsn(IASTORE); } public void laload() { getMethodVisitor().visitInsn(LALOAD); } public void lastore() { getMethodVisitor().visitInsn(LASTORE); } public void baload() { getMethodVisitor().visitInsn(BALOAD); } public void bastore() { getMethodVisitor().visitInsn(BASTORE); } public void saload() { getMethodVisitor().visitInsn(SALOAD); } public void sastore() { getMethodVisitor().visitInsn(SASTORE); } public void caload() { getMethodVisitor().visitInsn(CALOAD); } public void castore() { getMethodVisitor().visitInsn(CASTORE); } public void faload() { getMethodVisitor().visitInsn(FALOAD); } public void fastore() { getMethodVisitor().visitInsn(FASTORE); } public void daload() { getMethodVisitor().visitInsn(DALOAD); } public void dastore() { getMethodVisitor().visitInsn(DASTORE); } public void fcmpl() { getMethodVisitor().visitInsn(FCMPL); } public void fcmpg() { getMethodVisitor().visitInsn(FCMPG); } public void dcmpl() { getMethodVisitor().visitInsn(DCMPL); } public void dcmpg() { getMethodVisitor().visitInsn(DCMPG); } public void dup_x2() { getMethodVisitor().visitInsn(DUP_X2); } public void dup_x1() { getMethodVisitor().visitInsn(DUP_X1); } public void dup2_x2() { getMethodVisitor().visitInsn(DUP2_X2); } public void dup2_x1() { getMethodVisitor().visitInsn(DUP2_X1); } public void dup2() { getMethodVisitor().visitInsn(DUP2); } public void trycatch(Label arg0, Label arg1, Label arg2, String arg3) { getMethodVisitor().visitTryCatchBlock(arg0, arg1, arg2, arg3); } public void trycatch(String type, Runnable body, Runnable catchBody) { Label before = new Label(); Label after = new Label(); Label catchStart = new Label(); Label done = new Label(); trycatch(before, after, catchStart, type); label(before); body.run(); label(after); go_to(done); if (catchBody != null) { label(catchStart); catchBody.run(); } label(done); } public void go_to(Label arg0) { getMethodVisitor().visitJumpInsn(GOTO, arg0); } public void lookupswitch(Label arg0, int[] arg1, Label[] arg2) { getMethodVisitor().visitLookupSwitchInsn(arg0, arg1, arg2); } public void athrow() { getMethodVisitor().visitInsn(ATHROW); } public void instance_of(String arg0) { getMethodVisitor().visitTypeInsn(INSTANCEOF, arg0); } public void ifeq(Label arg0) { getMethodVisitor().visitJumpInsn(IFEQ, arg0); } public void iffalse(Label arg0) { ifeq(arg0); } public void ifne(Label arg0) { getMethodVisitor().visitJumpInsn(IFNE, arg0); } public void iftrue(Label arg0) { ifne(arg0); } public void if_acmpne(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ACMPNE, arg0); } public void if_acmpeq(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ACMPEQ, arg0); } public void if_icmple(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ICMPLE, arg0); } public void if_icmpgt(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ICMPGT, arg0); } public void if_icmplt(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ICMPLT, arg0); } public void if_icmpne(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ICMPNE, arg0); } public void if_icmpeq(Label arg0) { getMethodVisitor().visitJumpInsn(IF_ICMPEQ, arg0); } public void checkcast(String arg0) { getMethodVisitor().visitTypeInsn(CHECKCAST, arg0); } public void start() { getMethodVisitor().visitCode(); } private final void dump() { PrintWriter pw = new PrintWriter(System.out); Class tmvClass = getMethodVisitor().getClass(); try { Method print = tmvClass.getDeclaredMethod("print", PrintWriter.class); pw.write("*** Dumping ***\n"); print.invoke(getMethodVisitor(), pw); } catch (Exception ex) { } finally { pw.flush(); } } public void end() { if (DEBUG) { dump(); } getMethodVisitor().visitMaxs(1, 1); getMethodVisitor().visitEnd(); } public void line(int line) { Label label = new Label(); label(label); visitLineNumber(line, label); } public void line(int line, Label label) { visitLineNumber(line, label); } public void ifnonnull(Label arg0) { getMethodVisitor().visitJumpInsn(IFNONNULL, arg0); } public void ifnull(Label arg0) { getMethodVisitor().visitJumpInsn(IFNULL, arg0); } public void iflt(Label arg0) { getMethodVisitor().visitJumpInsn(IFLT, arg0); } public void ifle(Label arg0) { getMethodVisitor().visitJumpInsn(IFLE, arg0); } public void ifgt(Label arg0) { getMethodVisitor().visitJumpInsn(IFGT, arg0); } public void ifge(Label arg0) { getMethodVisitor().visitJumpInsn(IFGE, arg0); } public void arraylength() { getMethodVisitor().visitInsn(ARRAYLENGTH); } public void ishr() { getMethodVisitor().visitInsn(ISHR); } public void ishl() { getMethodVisitor().visitInsn(ISHL); } public void iushr() { getMethodVisitor().visitInsn(IUSHR); } public void lshr() { getMethodVisitor().visitInsn(LSHR); } public void lshl() { getMethodVisitor().visitInsn(LSHL); } public void lushr() { getMethodVisitor().visitInsn(LUSHR); } public void lcmp() { getMethodVisitor().visitInsn(LCMP); } public void iand() { getMethodVisitor().visitInsn(IAND); } public void ior() { getMethodVisitor().visitInsn(IOR); } public void ixor() { getMethodVisitor().visitInsn(IXOR); } public void land() { getMethodVisitor().visitInsn(LAND); } public void lor() { getMethodVisitor().visitInsn(LOR); } public void lxor() { getMethodVisitor().visitInsn(LXOR); } public void iadd() { getMethodVisitor().visitInsn(IADD); } public void ladd() { getMethodVisitor().visitInsn(LADD); } public void fadd() { getMethodVisitor().visitInsn(FADD); } public void dadd() { getMethodVisitor().visitInsn(DADD); } public void isub() { getMethodVisitor().visitInsn(ISUB); } public void lsub() { getMethodVisitor().visitInsn(LSUB); } public void fsub() { getMethodVisitor().visitInsn(FSUB); } public void dsub() { getMethodVisitor().visitInsn(DSUB); } public void idiv() { getMethodVisitor().visitInsn(IDIV); } public void irem() { getMethodVisitor().visitInsn(IREM); } public void ineg() { getMethodVisitor().visitInsn(INEG); } public void i2d() { getMethodVisitor().visitInsn(I2D); } public void i2l() { getMethodVisitor().visitInsn(I2L); } public void i2f() { getMethodVisitor().visitInsn(I2F); } public void i2s() { getMethodVisitor().visitInsn(I2S); } public void i2c() { getMethodVisitor().visitInsn(I2C); } public void i2b() { getMethodVisitor().visitInsn(I2B); } public void ldiv() { getMethodVisitor().visitInsn(LDIV); } public void lrem() { getMethodVisitor().visitInsn(LREM); } public void lneg() { getMethodVisitor().visitInsn(LNEG); } public void l2d() { getMethodVisitor().visitInsn(L2D); } public void l2i() { getMethodVisitor().visitInsn(L2I); } public void l2f() { getMethodVisitor().visitInsn(L2F); } public void fdiv() { getMethodVisitor().visitInsn(FDIV); } public void frem() { getMethodVisitor().visitInsn(FREM); } public void fneg() { getMethodVisitor().visitInsn(FNEG); } public void f2d() { getMethodVisitor().visitInsn(F2D); } public void f2i() { getMethodVisitor().visitInsn(F2D); } public void f2l() { getMethodVisitor().visitInsn(F2L); } public void ddiv() { getMethodVisitor().visitInsn(DDIV); } public void drem() { getMethodVisitor().visitInsn(DREM); } public void dneg() { getMethodVisitor().visitInsn(DNEG); } public void d2f() { getMethodVisitor().visitInsn(D2F); } public void d2i() { getMethodVisitor().visitInsn(D2I); } public void d2l() { getMethodVisitor().visitInsn(D2L); } public void imul() { getMethodVisitor().visitInsn(IMUL); } public void lmul() { getMethodVisitor().visitInsn(LMUL); } public void fmul() { getMethodVisitor().visitInsn(FMUL); } public void dmul() { getMethodVisitor().visitInsn(DMUL); } public void iinc(int arg0, int arg1) { getMethodVisitor().visitIincInsn(arg0, arg1); } public void monitorenter() { getMethodVisitor().visitInsn(MONITORENTER); } public void monitorexit() { getMethodVisitor().visitInsn(MONITOREXIT); } public void jsr(Label branch) { getMethodVisitor().visitJumpInsn(JSR, branch); } public void ret(int arg0) { getMethodVisitor().visitVarInsn(RET, arg0); } public AnnotationVisitor visitAnnotationDefault() { return getMethodVisitor().visitAnnotationDefault(); } public AnnotationVisitor visitAnnotation(String arg0, boolean arg1) { return getMethodVisitor().visitAnnotation(arg0, arg1); } public AnnotationVisitor visitParameterAnnotation(int arg0, String arg1, boolean arg2) { return getMethodVisitor().visitParameterAnnotation(arg0, arg1, arg2); } public void visitAnnotationWithFields(String name, boolean visible, Map fields) { AnnotationVisitor visitor = visitAnnotation(name, visible); visitAnnotationFields(visitor, fields); visitor.visitEnd(); } public void visitParameterAnnotationWithFields(int param, String name, boolean visible, Map fields) { AnnotationVisitor visitor = visitParameterAnnotation(param, name, visible); visitAnnotationFields(visitor, fields); visitor.visitEnd(); } public void visitAttribute(Attribute arg0) { getMethodVisitor().visitAttribute(arg0); } public void visitCode() { getMethodVisitor().visitCode(); } public void visitInsn(int arg0) { getMethodVisitor().visitInsn(arg0); } public void visitIntInsn(int arg0, int arg1) { getMethodVisitor().visitIntInsn(arg0, arg1); } public void visitVarInsn(int arg0, int arg1) { getMethodVisitor().visitVarInsn(arg0, arg1); } public void visitTypeInsn(int arg0, String arg1) { getMethodVisitor().visitTypeInsn(arg0, arg1); } public void visitFieldInsn(int arg0, String arg1, String arg2, String arg3) { getMethodVisitor().visitFieldInsn(arg0, arg1, arg2, arg3); } public void visitMethodInsn(int arg0, String arg1, String arg2, String arg3) { getMethodVisitor().visitMethodInsn(arg0, arg1, arg2, arg3); } public void visitJumpInsn(int arg0, Label arg1) { getMethodVisitor().visitJumpInsn(arg0, arg1); } public void visitLabel(Label arg0) { getMethodVisitor().visitLabel(arg0); } public void visitLdcInsn(Object arg0) { getMethodVisitor().visitLdcInsn(arg0); } public void visitIincInsn(int arg0, int arg1) { getMethodVisitor().visitIincInsn(arg0, arg1); } public void visitTableSwitchInsn(int arg0, int arg1, Label arg2, Label[] arg3) { getMethodVisitor().visitTableSwitchInsn(arg0, arg1, arg2, arg3); } public void visitLookupSwitchInsn(Label arg0, int[] arg1, Label[] arg2) { getMethodVisitor().visitLookupSwitchInsn(arg0, arg1, arg2); } public void visitMultiANewArrayInsn(String arg0, int arg1) { getMethodVisitor().visitMultiANewArrayInsn(arg0, arg1); } public void visitTryCatchBlock(Label arg0, Label arg1, Label arg2, String arg3) { getMethodVisitor().visitTryCatchBlock(arg0, arg1, arg2, arg3); } public void visitLocalVariable(String arg0, String arg1, String arg2, Label arg3, Label arg4, int arg5) { getMethodVisitor().visitLocalVariable(arg0, arg1, arg2, arg3, arg4, arg5); } public void visitLineNumber(int arg0, Label arg1) { getMethodVisitor().visitLineNumber(arg0, arg1); } public void visitMaxs(int arg0, int arg1) { if (DEBUG) { dump(); } getMethodVisitor().visitMaxs(arg0, arg1); } public void visitEnd() { getMethodVisitor().visitEnd(); } public void tableswitch(int min, int max, Label defaultLabel, Label[] cases) { getMethodVisitor().visitTableSwitchInsn(min, max, defaultLabel, cases); } public void visitFrame(int arg0, int arg1, Object[] arg2, int arg3, Object[] arg4) { getMethodVisitor().visitFrame(arg0, arg1, arg2, arg3, arg4); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/StubCompiler.java000066400000000000000000000065071201747543600243710ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jaffl.Platform; import com.kenai.jffi.CallingConvention; import com.kenai.jffi.Function; import com.kenai.jffi.Internals; import com.kenai.jffi.PageManager; import com.kenai.jnr.x86asm.Assembler; import com.kenai.jnr.x86asm.CPU; /** * Compiles asm trampoline stubs for java class methods */ abstract class StubCompiler { // If the version of jffi exports the jffi_save_errno function address, // then it is recent enough to support PageManager and NativeMethods as well. static final long errnoFunctionAddress = getErrnoSaveFunction(); static final boolean hasPageManager = hasPageManager(); static final boolean hasAssembler = hasAssembler(); public static final StubCompiler newCompiler() { if (errnoFunctionAddress != 0 && hasPageManager && hasAssembler) { switch (Platform.getPlatform().getCPU()) { case I386: if (Platform.getPlatform().getOS() != Platform.OS.WINDOWS) { return new X86_32StubCompiler(); } break; case X86_64: if (Platform.getPlatform().getOS() != Platform.OS.WINDOWS) { return new X86_64StubCompiler(); } break; } } return new DummyStubCompiler(); } abstract boolean canCompile(Class returnType, Class[] parameterTypes, CallingConvention convention); abstract void compile(Function function, String name, Class returnType, Class[] parameterTypes, CallingConvention convention, boolean saveErrno); abstract void attach(Class clazz); static final class DummyStubCompiler extends StubCompiler { @Override boolean canCompile(Class returnType, Class[] parameterTypes, CallingConvention convention) { return false; } @Override void compile(Function function, String name, Class returnType, Class[] parameterTypes, CallingConvention convention, boolean saveErrno) { throw new UnsupportedOperationException("Not supported yet."); } @Override void attach(Class clazz) { // do nothing } } private static final long getErrnoSaveFunction() { try { return Internals.getErrnoSaveFunction(); } catch (Throwable t) { return 0; } } private static final boolean hasPageManager() { try { // Just try and allocate/free a page to check the PageManager is working long page = PageManager.getInstance().allocatePages(1, PageManager.PROT_READ | PageManager.PROT_WRITE); PageManager.getInstance().freePages(page, 1); return true; } catch (Throwable t) { return false; } } private static final boolean hasAssembler() { try { switch (Platform.getPlatform().getCPU()) { case I386: new Assembler(CPU.X86_32); return true; case X86_64: new Assembler(CPU.X86_64); return true; default: return false; } } catch (Throwable t) { return false; } } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/SymbolNotFoundError.java000066400000000000000000000002751201747543600257110ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; public class SymbolNotFoundError extends java.lang.UnsatisfiedLinkError { public SymbolNotFoundError(String msg) { super(msg); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/X86_32StubCompiler.java000066400000000000000000000114071201747543600251760ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jffi.CallingConvention; import com.kenai.jffi.Function; import com.kenai.jffi.Internals; import static com.kenai.jnr.x86asm.Asm.*; import com.kenai.jnr.x86asm.Assembler; import static com.kenai.jaffl.provider.jffi.CodegenUtils.*; /** * Stub compiler for i386 unix */ final class X86_32StubCompiler extends AbstractX86StubCompiler { @Override boolean canCompile(Class returnType, Class[] parameterTypes, CallingConvention convention) { if (returnType != byte.class && returnType != short.class && returnType != int.class && returnType != long.class && returnType != float.class && returnType != double.class && returnType != void.class) { return false; } // There is only one calling convention; SYSV, so abort if someone tries to use stdcall if (convention != CallingConvention.DEFAULT) { return false; } int fCount = 0; int iCount = 0; for (Class t : parameterTypes) { if (t == byte.class || t == short.class || t == int.class || t == long.class) { ++iCount; } else if (t == float.class || t == double.class) { ++fCount; } else { // Fail on anything else return false; } } return true; } @Override void compile(Function function, String name, Class returnType, Class[] parameterTypes, CallingConvention convention, boolean saveErrno) { int psize = 0; for (Class t : parameterTypes) { if (t == byte.class || t == short.class || t == int.class || t == float.class) { psize += 4; } else if (t == long.class || t == double.class) { psize += 8; } else { throw new IllegalArgumentException("invalid parameter type" + t); } } int rsize = 0; if (double.class == returnType || float.class == returnType) { rsize = 16; } else if (long.class == returnType) { rsize = 8; } else if (byte.class == returnType || short.class == returnType || int.class == returnType) { rsize = 4; } else if (void.class == returnType) { rsize = 0; } else { throw new IllegalArgumentException("invalid return type " + returnType); } // // JNI functions all look like: // foo(JNIEnv* env, jobject self, arg...) // We need to align the stack to 16 bytes, then copy all the old args // into the new parameter space. // It already has 4 bytes pushed (the return address) so we need to account for that. // final int stackadj = align(Math.max(psize, rsize) + 4, 16) - 4; Assembler a = new Assembler(X86_32); a.sub(esp, imm(stackadj)); // memcpy the parameters from the orig stack to the new location for (int i = 0; i < psize; i += 4) { a.mov(eax, dword_ptr(esp, stackadj + 4 + 8 + i)); a.mov(dword_ptr(esp, i), eax); } // Call to the actual native function a.mov(eax, imm(function.getFunctionAddress())); a.call(eax); if (saveErrno) { int save = 0; if (float.class == returnType) { a.fstp(dword_ptr(esp, save)); } else if (double.class == returnType) { a.fstp(qword_ptr(esp, save)); } else if (long.class == returnType) { a.mov(dword_ptr(esp, save), eax); a.mov(dword_ptr(esp, save + 4), edx); } else if (void.class == returnType) { // Do nothing for void values } else { a.mov(dword_ptr(esp, save), eax); } // Save the errno in a thread-local variable a.mov(eax, imm(errnoFunctionAddress)); a.call(eax); // Retrieve return value and put it back in the appropriate return register if (float.class == returnType) { a.fld(dword_ptr(esp, save)); } else if (double.class == returnType) { a.fld(qword_ptr(esp, save)); } else if (long.class == returnType) { a.mov(eax, dword_ptr(esp, save)); a.mov(edx, dword_ptr(esp, save + 4)); } else if (void.class == returnType) { // Do nothing for void values } else { a.mov(eax, dword_ptr(esp, save)); } } // Restore esp to the original position and return a.add(esp, imm(stackadj)); a.ret(); stubs.add(new Stub(name, sig(returnType, parameterTypes), a)); } } jaffl-0.5.9/src/com/kenai/jaffl/provider/jffi/X86_64StubCompiler.java000066400000000000000000000124721201747543600252060ustar00rootroot00000000000000 package com.kenai.jaffl.provider.jffi; import com.kenai.jffi.CallingConvention; import com.kenai.jffi.Function; import com.kenai.jffi.Internals; import static com.kenai.jnr.x86asm.Asm.*; import com.kenai.jnr.x86asm.Assembler; import static com.kenai.jaffl.provider.jffi.CodegenUtils.*; /** * Compilers method trampoline stubs for x86_64 */ final class X86_64StubCompiler extends AbstractX86StubCompiler { @Override final boolean canCompile(Class returnType, Class[] parameterTypes, CallingConvention convention) { if (returnType != byte.class && returnType != short.class && returnType != int.class && returnType != long.class && returnType != float.class && returnType != double.class && returnType != void.class) { return false; } // There is only one calling convention; SYSV, so abort if someone tries to use stdcall if (convention != CallingConvention.DEFAULT) { return false; } int fCount = 0; int iCount = 0; for (Class t : parameterTypes) { if (t == byte.class || t == short.class || t == int.class || t == long.class) { ++iCount; } else if (t == float.class || t == double.class) { ++fCount; } else { // Fail on anything else return false; } } // We can only safely compile methods with up to 6 integer and 8 floating point parameters if (iCount > 6 || fCount > 8) { return false; } return true; } @Override final void compile(Function function, String name, Class returnType, Class[] parameterTypes, CallingConvention convention, boolean saveErrno) { int fCount = 0; int iCount = 0; for (Class t : parameterTypes) { if (t == byte.class || t == short.class || t == int.class || t == long.class) { ++iCount; } else if (t == float.class || t == double.class) { ++fCount; } else { throw new IllegalArgumentException("invalid parameter type"); } } Assembler a = new Assembler(X86_64); // // JNI functions all look like: // foo(JNIEnv* env, jobject self, arg...) // on AMD64, those sit in %rdi, %rsi, %rdx, %rcx, %r8 and %r9 // So we need to shuffle all the integer args up to over-write the // env and self arguments // if (iCount > 0) { a.mov(rdi, rdx); } if (iCount > 1) { a.mov(rsi, rcx); } if (iCount > 2) { a.mov(rdx, r8); } if (iCount > 3) { a.mov(rcx, r9); } // For args 5 & 6 of the function, they would have been pushed on the stack if (iCount > 4) { a.mov(r8, qword_ptr(rsp, 8)); } if (iCount > 5) { a.mov(r9, qword_ptr(rsp, 16)); } if (iCount > 6) { throw new IllegalArgumentException("integer argument count > 6"); } // All the integer registers are loaded; there nothing to do for the floating // registers, as the first 8 args are already in xmm0..xmm7, so just sanity check if (fCount > 8) { throw new IllegalArgumentException("float argument count > 8"); } if (saveErrno) { // Need to align the stack to 16 bytes for function call. // It already has 8 bytes pushed (the return address), so making space // to save the return value from the function neatly aligns it to 16 bytes int space = returnType == float.class || returnType == double.class ? 24 : 8; a.sub(rsp, imm(space)); // Call to the actual native function a.mov(rax, imm(function.getFunctionAddress())); a.call(rax); // Save the return on the stack if (returnType == float.class) { a.movss(dword_ptr(rsp, 0), xmm0); } else if (returnType == double.class) { a.movsd(qword_ptr(rsp, 0), xmm0); } else { a.mov(qword_ptr(rsp, 0), rax); } // Save the errno in a thread-local variable a.mov(rax, imm(errnoFunctionAddress)); a.call(rax); // Retrieve return value and put it back in the appropriate return register if (returnType == float.class) { a.movss(xmm0, dword_ptr(rsp, 0)); } else if (returnType == double.class) { a.movsd(xmm0, qword_ptr(rsp, 0)); } else { a.mov(rax, dword_ptr(rsp, 0)); } // Restore rsp to original position a.add(rsp, imm(space)); a.ret(); } else { // Since there is no need to return here to save the errno, and the // stack was not modified, we can just do a jmpq directly to the // native function, and let it return back to the caller. a.mov(rax, imm(function.getFunctionAddress())); a.jmp(rax); } stubs.add(new Stub(name, sig(returnType, parameterTypes), a)); } } jaffl-0.5.9/src/com/kenai/jaffl/struct/000077500000000000000000000000001201747543600176625ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/struct/Struct.java000066400000000000000000001525211201747543600220170ustar00rootroot00000000000000/* * This file is covered by the license described in the LICENSE file in the root of * the project, however, it incorporates some code from the javolution project, * and that copyright is reproduced here. * * Copyright (C) 2006 - Javolution (http://javolution.org/) * All rights reserved. * * Permission to use, copy, modify, and distribute this software is * freely granted, provided that this notice is preserved. */ package com.kenai.jaffl.struct; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.ParameterFlags; import com.kenai.jaffl.Type; import com.kenai.jaffl.util.EnumMapper; import java.lang.reflect.Constructor; import java.nio.charset.Charset; /** * Representation of C structures in java. * * Note: This class is not threadsafe. */ public abstract class Struct /*implements Marshallable */{ /** * Various platform-dependent constants needed for Struct construction */ protected static final class Constants { static final int LONG_SIZE = Type.SLONG.size() * 8; static final int ADDRESS_SIZE = Type.ADDRESS.size() * 8; static final long LONG_MASK = LONG_SIZE == 32 ? 0x7FFFFFFFL : 0x7FFFFFFFFFFFFFFFL; static final int LONG_ALIGN = Type.SLONG.alignment() * 8; static final int INT64_ALIGN = Type.SLONGLONG.alignment() * 8; static final int DOUBLE_ALIGN = Type.DOUBLE.alignment() * 8; static final int FLOAT_ALIGN = Type.FLOAT.alignment() * 8;; } static final class Info { Struct enclosing = null; int offset = 0; // offset within enclosing Struct MemoryIO io; int size = 0; int minAlign = 1; boolean isUnion = false; boolean resetIndex = false; public final MemoryIO getMemoryIO(int flags) { return enclosing != null ? enclosing.__info.getMemoryIO(flags) : io != null ? io : (io = allocateMemory(flags)); } public final MemoryIO getMemoryIO() { return getMemoryIO(ParameterFlags.TRANSIENT); } final boolean isDirect() { return (enclosing != null && enclosing.__info.isDirect()) || (io != null && io.isDirect()); } final int size() { return size; } final int getMinimumAlignment() { return minAlign; } private final MemoryIO allocateMemory(int flags) { if (ParameterFlags.isDirect(flags)) { return MemoryIO.allocateDirect(size(), true); } else { return MemoryIO.allocate(size()); } } /* public final Marshaller.Session marshal(Marshaller marshaller, MarshalContext context) { final int flags = context.getFlags(); if (io == null) { allocateMemory(flags); } else if (!ParameterFlags.isTransient(flags) && !io.isDirect()) { // Switching from heap memory to native memory final ByteBuffer old = buffer; allocateMemory(flags); if (ParameterFlags.isIn(flags)) { io.put(0, old.array(), old.arrayOffset(), old.capacity()); } } if (memory != null) { marshaller.add(memory); } else { marshaller.add(buffer, context); } return Marshaller.EMPTY_SESSION; } */ public final void useMemory(com.kenai.jaffl.MemoryIO io) { this.io = io; } protected final int addField(int sizeBits, int alignBits, Offset offset) { this.size = Math.max(this.size, offset.intValue() + (sizeBits >> 3)); this.minAlign = Math.max(this.minAlign, alignBits >> 3); return offset.intValue(); } protected final int addField(int sizeBits, int alignBits) { final int mask = (alignBits >> 3) - 1; int off = resetIndex ? 0 : this.size; if ((off & mask) != 0) { off = (off & ~mask) + (alignBits >> 3); } this.size = Math.max(this.size, off + (sizeBits >> 3)); this.minAlign = Math.max(this.minAlign, alignBits >> 3); return off; } } final Info __info = new Info(); /** * Creates a new Struct. */ protected Struct() {} /** * Creates a new Struct. * * @param isUnion if this Struct is a Union */ Struct(final boolean isUnion) { __info.resetIndex = isUnion; } /** * Uses the specified memory address as the backing store for this structure. * * @param address the native memory area. */ public void useMemory(com.kenai.jaffl.MemoryIO address) { __info.useMemory(address); } /** * Uses the specified memory address as the backing store for this structure. * * @param address the native memory area. */ public void useMemory(com.kenai.jaffl.Pointer address) { __info.useMemory(MemoryIO.wrap(address)); } /** * Returns a human readable {@link java.lang.String} representation of the structure. * * @return a String representation of this structure. */ @Override public java.lang.String toString() { StringBuilder sb = new StringBuilder(); java.lang.reflect.Field[] fields = getClass().getDeclaredFields(); sb.append(getClass().getSimpleName() + " { \n"); final java.lang.String fieldPrefix = " "; for (java.lang.reflect.Field field : fields) { try { sb.append(fieldPrefix); sb.append(field.getName()).append(" = "); sb.append(field.get(this).toString()); sb.append("\n"); } catch (Throwable ex) { throw new RuntimeException(ex); } } sb.append("}\n"); return sb.toString(); } public static final class Offset extends java.lang.Number { private final int offset; public Offset(int offset) { this.offset = offset; } @Override public int intValue() { return offset; } @Override public long longValue() { return offset; } @Override public float floatValue() { return offset; } @Override public double doubleValue() { return offset; } } /** * Interface all Struct members must implement. */ protected interface Member { /** * Gets the Struct this Member is a member of. * * @return a Struct. */ Struct struct(); /** * Gets the MemoryIO used to read/write this Member. * * @return a MemoryIO. */ MemoryIO getMemoryIO(); /** * Gets the offset within the structure for this field. */ long offset(); } /** * Starts an array construction session */ protected final void arrayBegin() { __info.resetIndex = false; } /** * Ends an array construction session */ protected final void arrayEnd() { __info.resetIndex = __info.isUnion; } /** * Creates an array of Member instances. * * @param The type of the Member subclass to create. * @param array the array to store the instances in * @return the array that was passed in */ @SuppressWarnings("unchecked") protected T[] array(T[] array) { arrayBegin(); try { Class arrayClass = array.getClass().getComponentType(); Constructor ctor = arrayClass.getDeclaredConstructor(new Class[] { arrayClass.getEnclosingClass() }); Object[] parameters = { Struct.this }; for (int i = 0; i < array.length; ++i) { array[i] = (T) ctor.newInstance(parameters); } } catch (Exception ex) { throw new RuntimeException(ex); } arrayEnd(); return array; } /** * Creates an array of Signed8 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Signed8[] array(Signed8[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Signed8(); } arrayEnd(); return array; } /** * Creates an array of Unsigned8 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Unsigned8[] array(Unsigned8[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Unsigned8(); } arrayEnd(); return array; } /** * Creates an array of Signed16 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Signed16[] array(Signed16[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Signed16(); } arrayEnd(); return array; } /** * Creates an array of Unsigned16 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Unsigned16[] array(Unsigned16[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Unsigned16(); } arrayEnd(); return array; } /** * Creates an array of Signed32 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Signed32[] array(Signed32[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Signed32(); } arrayEnd(); return array; } /** * Creates an array of Unsigned32 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Unsigned32[] array(Unsigned32[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Unsigned32(); } arrayEnd(); return array; } /** * Creates an array of Signed64 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Signed64[] array(Signed64[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Signed64(); } arrayEnd(); return array; } /** * Creates an array of Unsigned64 instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Unsigned64[] array(Unsigned64[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Unsigned64(); } arrayEnd(); return array; } /** * Creates an array of SignedLong instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final SignedLong[] array(SignedLong[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new SignedLong(); } arrayEnd(); return array; } /** * Creates an array of UnsignedLong instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final UnsignedLong[] array(UnsignedLong[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new UnsignedLong(); } arrayEnd(); return array; } /** * Creates an array of Float instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Float[] array(Float[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Float(); } arrayEnd(); return array; } /** * Creates an array of Double instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Double[] array(Double[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Double(); } arrayEnd(); return array; } /** * Creates an array of Address instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Address[] array(Address[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Address(); } arrayEnd(); return array; } /** * Creates an array of Pointer instances. * * @param array the array to store the instances in * @return the array that was passed in */ protected final Pointer[] array(Pointer[] array) { arrayBegin(); for (int i = 0; i < array.length; ++i) { array[i] = new Pointer(); } arrayEnd(); return array; } protected final T inner(Struct struct) { int salign = struct.__info.getMinimumAlignment(); int off = salign + ((__info.size - 1) & ~(salign - 1)); struct.__info.enclosing = this; struct.__info.offset = off; __info.size = off + struct.__info.size; return (T) struct; } /** * Base implementation of Member */ public abstract class AbstractMember implements Member { private final int offset; protected AbstractMember(int size) { this(size, size); } protected AbstractMember(int size, int align, Offset offset) { this.offset = __info.addField(size, align, offset); } protected AbstractMember(int size, int align) { this.offset = __info.addField(size, align); } protected AbstractMember(Type type) { this.offset = __info.addField(type.size() * 8, type.alignment() * 8); } protected AbstractMember(Type type, Offset offset) { this.offset = __info.addField(type.size() * 8, type.alignment() * 8, offset); } /** * Gets the MemoryIO used to read/write this Member. * * @return a MemoryIO. */ public final MemoryIO getMemoryIO() { return __info.getMemoryIO(); } /** * Gets the Struct this Member is a member of. * * @return a Struct. */ public final Struct struct() { return Struct.this; } /** * Gets the offset within the structure for this field. */ public final long offset() { return offset + __info.offset; } } /** * Base class for Boolean fields */ public abstract class AbstractBoolean extends AbstractMember { public AbstractBoolean(Type type) { super(type); } protected AbstractBoolean(Type type, Offset offset) { super(type, offset); } /** * Gets the value for this field. * * @return a boolean. */ public abstract boolean get(); /** * Sets the field to a new value. * * @param value The new value. */ public abstract void set(boolean value); /** * Returns a string representation of this Address. * * @return a string representation of this Address. */ @Override public java.lang.String toString() { return java.lang.Boolean.toString(get()); } } /** * A normal C boolean - 1 byte in size */ public final class Boolean extends AbstractBoolean { public Boolean() { super(Type.SCHAR); } public final boolean get() { return (getMemoryIO().getByte(offset()) & 0x1) != 0; } public final void set(boolean value) { getMemoryIO().putByte(offset(), (byte) (value ? 1 : 0)); } } /** * A Windows BOOL - 4 bytes */ public final class WBOOL extends AbstractBoolean { public WBOOL() { super(Type.SINT); } public final boolean get() { return (getMemoryIO().getInt(offset()) & 0x1) != 0; } public final void set(boolean value) { getMemoryIO().putInt(offset(), value ? 1 : 0); } } /** * Base class for all Number structure fields. */ protected abstract class NumberField extends java.lang.Number implements Member { /** * Offset from the start of the Struct memory this field is located at. */ private final int offset; protected NumberField(int size) { this(size, size); } protected NumberField(int size, Offset offset) { this(size, size, offset); } protected NumberField(int size, int align, Offset offset) { this.offset = __info.addField(size, align, offset); } protected NumberField(int size, int align) { this.offset = __info.addField(size, align); } /** * Gets the MemoryIO used to read/write this Member. * * @return a MemoryIO. */ public final MemoryIO getMemoryIO() { return __info.getMemoryIO(); } /** * Gets the Struct this Member is in. * * @return a Struct. */ public final Struct struct() { return Struct.this; } /** * Gets the offset within the structure for this field. */ public final long offset() { return offset + __info.offset; } /** * Sets the field to a new value. * * @param value The new value. */ public abstract void set(java.lang.Number value); /** * Returns an {@code float} representation of this Number. * * @return an {@code float} value for this Number. */ @Override public double doubleValue() { return (double) longValue(); } /** * Returns an {@code float} representation of this Number. * * @return an {@code float} value for this Number. */ @Override public float floatValue() { return (float) intValue(); } /** * Returns an {@code long} representation of this Number. * * @return an {@code long} value for this Number. */ @Override public long longValue() { return intValue(); } /** * Returns a string representation of this Address. * * @return a string representation of this Address. */ @Override public java.lang.String toString() { return java.lang.Integer.toString(intValue(), 10); } } /** * An 8 bit signed integer */ public class Signed8 extends NumberField { /** * Creates a new 8 bit integer field. */ public Signed8() { super(8); } /** * Creates a new 8 bit integer field at a specific offset * * @param offset The offset within the memory area */ public Signed8(Offset offset) { super(8, offset); } /** * Gets the value for this field. * * @return a byte. */ public final byte get() { return getMemoryIO().getByte(offset()); } /** * Sets the value for this field. * * @param value the 8 bit value to set. */ public final void set(byte value) { getMemoryIO().putByte(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putByte(offset(), value.byteValue()); } /** * Returns a java byte representation of this field. * * @return a java byte value for this field. */ @Override public final byte byteValue() { return get(); } /** * Returns a java short representation of this field. * * @return a java short value for this field. */ @Override public final short shortValue() { return get(); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return get(); } } /** * An 8 bit unsigned integer */ public class Unsigned8 extends NumberField { /** * Creates a new 8 bit unsigned integer field. */ public Unsigned8() { super(8); } /** * Creates a new 8 bit unsigned integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Unsigned8(Offset offset) { super(8, offset); } /** * Gets the value for this field. * * @return a byte. */ public final short get() { short value = getMemoryIO().getByte(offset()); return value < 0 ? (short) ((value & 0x7F) + 0x80) : value; } /** * Sets the value for this field. * * @param value the 8 bit value to set. */ public final void set(short value) { getMemoryIO().putByte(offset(), (byte) value); } public void set(java.lang.Number value) { getMemoryIO().putByte(offset(), value.byteValue()); } /** * Returns a java short representation of this field. * * @return a java short value for this field. */ @Override public final short shortValue() { return get(); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return get(); } } /** * A 16 bit signed integer field. */ public class Signed16 extends NumberField { /** * Creates a new 16 bit integer field. */ public Signed16() { super(16); } /** * Creates a new 16 bit signed integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Signed16(Offset offset) { super(16, offset); } /** * Gets the value for this field. * * @return a short. */ public final short get() { return getMemoryIO().getShort(offset()); } /** * Sets the value for this field. * * @param value the 16 bit value to set. */ public final void set(short value) { getMemoryIO().putShort(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putShort(offset(), value.shortValue()); } /** * Returns a java short representation of this field. * * @return a java short value for this field. */ @Override public final short shortValue() { return get(); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return get(); } } /** * A 16 bit signed integer field. */ public class Unsigned16 extends NumberField { /** * Creates a new 16 bit integer field. */ public Unsigned16() { super(16); } /** * Creates a new 16 bit unsigned integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Unsigned16(Offset offset) { super(16, offset); } /** * Gets the value for this field. * * @return a short. */ public final int get() { int value = getMemoryIO().getShort(offset()); return value < 0 ? (int)((value & 0x7FFF) + 0x8000) : value; } /** * Sets the value for this field. * * @param value the 16 bit unsigned value to set. */ public final void set(int value) { getMemoryIO().putShort(offset(), (short) value); } public void set(Number value) { getMemoryIO().putShort(offset(), value.shortValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return get(); } } /** * A 32 bit signed integer field. */ public class Signed32 extends NumberField { /** * Creates a new 32 bit integer field. */ public Signed32() { super(32); } /** * Creates a new 32 bit signed integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Signed32(Offset offset) { super(32, offset); } /** * Gets the value for this field. * * @return a int. */ public final int get() { return getMemoryIO().getInt(offset()); } /** * Sets the value for this field. * * @param value the 32 bit value to set. */ public final void set(int value) { getMemoryIO().putInt(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putInt(offset(), value.intValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return get(); } } /** * A 32 bit signed integer field. */ public class Unsigned32 extends NumberField { /** * Creates a new 32 bit integer field. */ public Unsigned32() { super(32); } /** * Creates a new 32 bit unsigned integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Unsigned32(Offset offset) { super(32, offset); } /** * Gets the value for this field. * * @return a long. */ public final long get() { long value = getMemoryIO().getInt(offset()); return value < 0 ? (long)((value & 0x7FFFFFFFL) + 0x80000000L) : value; } /** * Sets the value for this field. * * @param value the 32 bit unsigned value to set. */ public final void set(long value) { getMemoryIO().putInt(offset(), (int) value); } public void set(java.lang.Number value) { getMemoryIO().putInt(offset(), value.intValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return (int) get(); } /** * Returns a java long representation of this field. * * @return a java long value for this field. */ @Override public final long longValue() { return get(); } } /** * A 64 bit signed integer field. */ public class Signed64 extends NumberField { /** * Creates a new 64 bit integer field. */ public Signed64() { super(64, Constants.INT64_ALIGN); } /** * Creates a new 64 bit signed integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Signed64(Offset offset) { super(64, Constants.INT64_ALIGN, offset); } /** * Gets the value for this field. * * @return a long. */ public final long get() { return getMemoryIO().getLong(offset()); } /** * Sets the value for this field. * * @param value the 64 bit value to set. */ public final void set(long value) { getMemoryIO().putLong(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putLong(offset(), value.longValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return (int) get(); } /** * Returns a java long representation of this field. * * @return a java long value for this field. */ @Override public final long longValue() { return get(); } /** * Returns a string representation of this field. * * @return a string representation of this field. */ @Override public final java.lang.String toString() { return java.lang.Long.toString(get()); } } /** * A 64 bit unsigned integer field. */ public class Unsigned64 extends NumberField { /** * Creates a new 64 bit integer field. */ public Unsigned64() { super(64, Constants.INT64_ALIGN); } /** * Creates a new 64 bit unsigned integer field at a specific offset * * @param offset The offset within the memory area for this field. */ public Unsigned64(Offset offset) { super(64, Constants.INT64_ALIGN, offset); } /** * Gets the value for this field. * * @return a long. */ public final long get() { return getMemoryIO().getLong(offset()); } /** * Sets the value for this field. * * @param value the 64 bit value to set. */ public final void set(long value) { getMemoryIO().putLong(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putLong(offset(), value.longValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return (int) get(); } /** * Returns a java long representation of this field. * * @return a java long value for this field. */ @Override public final long longValue() { return get(); } /** * Returns a string representation of this field. * * @return a string representation of this field. */ @Override public final java.lang.String toString() { return java.lang.Long.toString(get()); } } /** * A native long integer field. */ public class SignedLong extends NumberField { /** * Creates a new native long field. */ public SignedLong() { super(Constants.LONG_SIZE, Constants.LONG_ALIGN); } /** * Creates a new signed native long field at a specific offset * * @param offset The offset within the memory area for this field. */ public SignedLong(Offset offset) { super(Constants.LONG_SIZE, Constants.LONG_ALIGN, offset); } /** * Gets the value for this field. * * @return a long. */ public final long get() { return getMemoryIO().getNativeLong(offset()); } /** * Sets the value for this field. * * @param value the 32/64 bit value to set. */ public final void set(long value) { getMemoryIO().putNativeLong(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putNativeLong(offset(), value.longValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return (int) get(); } /** * Returns a java long representation of this field. * * @return a java long value for this field. */ @Override public final long longValue() { return get(); } /** * Returns a string representation of this field. * * @return a string representation of this field. */ @Override public final java.lang.String toString() { return java.lang.Long.toString(get()); } } /** * A native long integer field. */ public class UnsignedLong extends NumberField { /** * Creates a new native long field. */ public UnsignedLong() { super(Constants.LONG_SIZE, Constants.LONG_ALIGN); } /** * Creates a new unsigned native long field at a specific offset * * @param offset The offset within the memory area for this field. */ public UnsignedLong(Offset offset) { super(Constants.LONG_SIZE, Constants.LONG_ALIGN, offset); } /** * Gets the value for this field. * * @return a int. */ public final long get() { long value = getMemoryIO().getNativeLong(offset()); return value < 0 ? (long) ((value & Constants.LONG_MASK) + Constants.LONG_MASK + 1) : value; } /** * Sets the value for this field. * * @param value the 32/64 bit value to set. */ public final void set(long value) { getMemoryIO().putNativeLong(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putNativeLong(offset(), value.longValue()); } /** * Returns a java int representation of this field. * * @return a java int value for this field. */ @Override public final int intValue() { return (int) get(); } /** * Returns a java long representation of this field. * * @return a java long value for this field. */ @Override public final long longValue() { return get(); } /** * Returns a string representation of this field. * * @return a string representation of this field. */ @Override public final java.lang.String toString() { return java.lang.Long.toString(get()); } } public class Float extends NumberField { public Float() { super(java.lang.Float.SIZE, Constants.FLOAT_ALIGN); } /** * Creates a new float field at a specific offset * * @param offset The offset within the memory area for this field. */ public Float(Offset offset) { super(java.lang.Float.SIZE, Constants.FLOAT_ALIGN, offset); } public final float get() { return getMemoryIO().getFloat(offset()); } public final void set(float value) { getMemoryIO().putFloat(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putFloat(offset(), value.floatValue()); } @Override public final int intValue() { return (int) get(); } @Override public final double doubleValue() { return get(); } @Override public final float floatValue() { return get(); } @Override public final long longValue() { return (long) get(); } @Override public final java.lang.String toString() { return java.lang.String.valueOf(get()); } } public final class Double extends NumberField { public Double() { super(java.lang.Double.SIZE, Constants.DOUBLE_ALIGN); } public Double(Offset offset) { super(java.lang.Double.SIZE, Constants.DOUBLE_ALIGN, offset); } public final double get() { return getMemoryIO().getDouble(offset()); } public final void set(double value) { getMemoryIO().putDouble(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putDouble(offset(), value.doubleValue()); } @Override public final int intValue() { return (int) get(); } @Override public final long longValue() { return (long) get(); } @Override public final float floatValue() { return (float) get(); } @Override public final double doubleValue() { return get(); } @Override public final java.lang.String toString() { return java.lang.String.valueOf(get()); } } /** * Represents a native memory address. */ public class Address extends NumberField { /** * Creates a new Address field. */ public Address() { super(Constants.ADDRESS_SIZE); } public Address(Offset offset) { super(Constants.ADDRESS_SIZE, offset); } /** * Gets the {@link com.googlecode.jffi.Address} value from the native memory. * * @return a {@link com.googlecode.jffi.Address}. */ public final com.kenai.jaffl.Address get() { long value = getMemoryIO().getAddress(offset()); return value != 0 ? new com.kenai.jaffl.Address(value) : null; } /** * Puts a {@link jafl.Address} value into the native memory. */ public final void set(com.kenai.jaffl.Address value) { getMemoryIO().putAddress(offset(), value != null ? value.nativeAddress() : 0); } public void set(java.lang.Number value) { getMemoryIO().putAddress(offset(), value.longValue()); } /** * Returns an integer representation of this address. * * @return an integer value for this address. */ @Override public final int intValue() { return get().intValue(); } /** * Returns an {@code long} representation of this address. * * @return an {@code long} value for this address. */ @Override public final long longValue() { return get().longValue(); } /** * Returns a string representation of this Address. * * @return a string representation of this Address. */ @Override public final java.lang.String toString() { return get().toString(); } } /** * Represents a native memory address. */ public class Pointer extends NumberField { /** * Creates a new Address field. */ public Pointer() { super(Constants.ADDRESS_SIZE); } public Pointer(Offset offset) { super(Constants.ADDRESS_SIZE, offset); } /** * Gets the {@link com.googlecode.jffi.Address} value from the native memory. * * @return a {@link com.googlecode.jffi.Address}. */ public final com.kenai.jaffl.Pointer get() { return getMemoryIO().getPointer(offset()); } /** * Gets the size of a Pointer in bits * * @return the size of the Pointer */ public final int size() { return com.kenai.jaffl.Address.SIZE; } /** * Puts a {@link com.googlecode.jffi.Address} value into the native memory. */ public final void set(com.kenai.jaffl.Pointer value) { getMemoryIO().putPointer(offset(), value); } public void set(java.lang.Number value) { getMemoryIO().putAddress(offset(), value.longValue()); } /** * Returns an integer representation of this Pointer. * * @return an integer value for this Pointer. */ @Override public final int intValue() { return (int) getMemoryIO().getAddress(offset()); } /** * Returns an {@code long} representation of this Pointer. * * @return an {@code long} value for this Pointer. */ @Override public final long longValue() { return getMemoryIO().getAddress(offset()); } /** * Returns a string representation of this Pointer. * * @return a string representation of this Pointer. */ @Override public final java.lang.String toString() { return get().toString(); } } /** * Base for all the Enum fields. * * @param the type of {@link java.lang.Enum} */ protected abstract class EnumField extends NumberField { protected final Class enumClass; /** * Constructs a new Enum field. * * @param size the size of the native integer. * @param enumClass the Enum class. */ public EnumField(int size, Class enumClass) { this(size, size, enumClass); } /** * Constructs a new Enum field. * * @param size the size of the native integer. * * @param offset the offset from the start of the struct memory area. * @param enumClass the Enum class. */ public EnumField(int size, Offset offset, Class enumClass) { this(size, size, offset, enumClass); } /** * Constructs a new Enum field. * @param size the size of the native integer. * @param align the minimum alignment of the native integer * @param enumClass the Enum class. */ public EnumField(int size, int align, Class enumClass) { super(size, align); this.enumClass = enumClass; } /** * Constructs a new Enum field. * @param size the size of the native integer. * @param align the minimum alignment of the native integer * @param offset the offset from the start of the struct memory area * @param enumClass the Enum class. */ public EnumField(int size, int align, Offset offset, Class enumClass) { super(size, align, offset); this.enumClass = enumClass; } /** * Gets a java Enum value representing the native integer value. * * @return a java Enum value. */ public abstract E get(); /** * Returns a string representation of this field. * * @return a string representation of this field. */ @Override public final java.lang.String toString() { return get().toString(); } } /** * An 8 bit enum field. * * @param the {@link java.lang.Enum} to translate to/from. */ public class Enum8> extends EnumField { /** * Creates a new 8 bit enum field. * * @param enumClass the class of the {@link java.lang.Enum}. */ public Enum8(Class enumClass) { super(8, enumClass); } /** * Gets a java Enum value representing the native integer value. * * @return a java Enum value. */ public final E get() { return EnumMapper.getInstance().valueOf(intValue(), enumClass); } /** * Sets the native integer value using a java Enum value. * * @param value the java Enum value. */ public final void set(E value) { getMemoryIO().putByte(offset(), (byte) EnumMapper.getInstance().intValue(value)); } public void set(java.lang.Number value) { getMemoryIO().putByte(offset(), value.byteValue()); } /** * Returns an integer representation of this enum field. * * @return an integer value for this enum field. */ @Override public final int intValue() { return getMemoryIO().getByte(offset()); } } public class Enum16> extends EnumField { public Enum16(Class enumClass) { super(16, enumClass); } public final E get() { return EnumMapper.getInstance().valueOf(intValue(), enumClass); } public final void set(E value) { getMemoryIO().putShort(offset(), (short) EnumMapper.getInstance().intValue(value)); } public void set(java.lang.Number value) { getMemoryIO().putShort(offset(), value.shortValue()); } @Override public final int intValue() { return getMemoryIO().getShort(offset()); } } public class Enum32> extends EnumField { public Enum32(Class enumClass) { super(32, enumClass); } public final E get() { return EnumMapper.getInstance().valueOf(intValue(), enumClass); } public final void set(E value) { getMemoryIO().putInt(offset(), EnumMapper.getInstance().intValue(value)); } public void set(java.lang.Number value) { getMemoryIO().putInt(offset(), value.intValue()); } @Override public final int intValue() { return getMemoryIO().getInt(offset()); } } public class Enum64> extends EnumField { public Enum64(Class enumClass) { super(64, Constants.INT64_ALIGN, enumClass); } public final E get() { return EnumMapper.getInstance().valueOf(intValue(), enumClass); } public final void set(E value) { getMemoryIO().putLong(offset(), EnumMapper.getInstance().intValue(value)); } public void set(java.lang.Number value) { getMemoryIO().putLong(offset(), value.longValue()); } @Override public final int intValue() { return (int) longValue(); } @Override public final long longValue() { return getMemoryIO().getLong(offset()); } } public class EnumLong> extends EnumField { public EnumLong(Class enumClass) { super(Constants.LONG_SIZE, Constants.LONG_ALIGN, enumClass); } public final E get() { return EnumMapper.getInstance().valueOf(intValue(), enumClass); } public final void set(E value) { getMemoryIO().putNativeLong(offset(), EnumMapper.getInstance().intValue(value)); } public void set(java.lang.Number value) { getMemoryIO().putNativeLong(offset(), value.longValue()); } @Override public final int intValue() { return (int) longValue(); } @Override public final long longValue() { return getMemoryIO().getNativeLong(offset()); } } public class Enum> extends Enum32 { public Enum(Class enumClass) { super(enumClass); } } abstract public class String extends AbstractMember { private final Charset charset; private final int length; protected String(int size, int align, int length, Charset cs) { super(size, align); this.length = length; this.charset = cs; } protected String(int size, int align, Offset offset, int length, Charset cs) { super(size, align, offset); this.length = length; this.charset = cs; } public final int length() { return length; } protected abstract MemoryIO getStringMemory(); public final java.lang.String get() { return getStringMemory().getString(0, length, charset); } public final void set(java.lang.String value) { getStringMemory().putString(0, value, length, charset); } @Override public final java.lang.String toString() { return get(); } } public class UTFString extends String { public UTFString(int length, Charset cs) { super(length * 8, 8, length, cs); // FIXME: This won't work for non-ASCII } protected MemoryIO getStringMemory() { return getMemoryIO().slice(offset(), length()); } } public class UTF8String extends UTFString { public UTF8String(int size) { super(size, Charset.forName("UTF-8")); } } public class AsciiString extends UTFString { public AsciiString(int size) { super(size, Charset.forName("ASCII")); } } public class UTFStringRef extends String { public UTFStringRef(int length, Charset cs) { super(Constants.ADDRESS_SIZE, Constants.ADDRESS_SIZE, length, cs); } public UTFStringRef(Charset cs) { this(Integer.MAX_VALUE, cs); } protected MemoryIO getStringMemory() { return getMemoryIO().getMemoryIO(offset(), length()); } } public class UTF8StringRef extends UTFStringRef { public UTF8StringRef(int size) { super(size, Charset.forName("UTF-8")); } public UTF8StringRef() { super(Integer.MAX_VALUE, Charset.forName("UTF-8")); } } public class AsciiStringRef extends UTFStringRef { public AsciiStringRef(int size) { super(size, Charset.forName("ASCII")); } public AsciiStringRef() { super(Integer.MAX_VALUE, Charset.forName("ASCII")); } } /** * Specialized padding fields for structs. Use this instead of arrays of other * members for more efficient struct construction. */ public final class Padding extends AbstractMember { public Padding(Type type, int length) { super(type.size() * 8 * length, type.alignment() * 8); } } /* public final Marshaller.Session marshal(Marshaller marshaller, MarshalContext context) { return __info.marshal(marshaller, context); } */ } jaffl-0.5.9/src/com/kenai/jaffl/struct/StructUtil.java000066400000000000000000000036151201747543600226540ustar00rootroot00000000000000 package com.kenai.jaffl.struct; import com.kenai.jaffl.MemoryIO; import java.lang.reflect.Array; /** * */ public final class StructUtil { private StructUtil() {} public final static MemoryIO getMemoryIO(Struct struct) { return struct.__info.getMemoryIO(0); } public final static MemoryIO getMemoryIO(Struct struct, int flags) { return struct.__info.getMemoryIO(flags); } public final static int getSize(Struct struct) { return struct.__info.size(); } public final static int getMinimumAlignment(Struct struct) { return struct.__info.getMinimumAlignment(); } public final static boolean isDirect(Struct struct) { return struct.__info.isDirect(); } @SuppressWarnings("unchecked") public static final T[] newArray(Class type, int length) { try { T[] array = (T[]) Array.newInstance(type, length); for (int i = 0; i < length; ++i) { array[i] = type.newInstance(); } if (array.length > 0) { final int align = getMinimumAlignment(array[0]); final int mask = align - 1; int structSize = getSize(array[0]); if ((structSize & mask) != 0) { structSize = (structSize & ~mask) + align; } MemoryIO memory = MemoryIO.allocateDirect(structSize * length); for (int i = 0; i < array.length; ++i) { array[i].useMemory(memory.slice(structSize * i, structSize)); } } return array; } catch (SecurityException ex) { throw new RuntimeException(ex); } catch (InstantiationException ex) { throw new RuntimeException(ex); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } } } jaffl-0.5.9/src/com/kenai/jaffl/struct/Union.java000066400000000000000000000011231201747543600216120ustar00rootroot00000000000000/* * This file is covered by the license described in the LICENSE file in the root of * the project, however, it incorporates some code from the javolution project, * and that copyright is reproduced here. * * Copyright (C) 2006 - Javolution (http://javolution.org/) * All rights reserved. * * Permission to use, copy, modify, and distribute this software is * freely granted, provided that this notice is preserved. */ package com.kenai.jaffl.struct; /** * Represents a C union */ public abstract class Union extends Struct { protected Union() { super(true); } } jaffl-0.5.9/src/com/kenai/jaffl/util/000077500000000000000000000000001201747543600173135ustar00rootroot00000000000000jaffl-0.5.9/src/com/kenai/jaffl/util/BufferPool.java000066400000000000000000000003601201747543600222200ustar00rootroot00000000000000 package com.kenai.jaffl.util; import java.nio.ByteBuffer; import java.util.List; public interface BufferPool { public ByteBuffer get(int size); public void put(ByteBuffer buffer); public void putAll(List list); } jaffl-0.5.9/src/com/kenai/jaffl/util/BufferUtil.java000066400000000000000000000143771201747543600222410ustar00rootroot00000000000000 package com.kenai.jaffl.util; import com.kenai.jaffl.Platform; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharacterCodingException; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; import java.nio.charset.CodingErrorAction; /** * */ public final class BufferUtil { private BufferUtil() {} public final static void putString(ByteBuffer buf, Charset charset, String value) { putCharSequence(buf, charset, value); } public final static String getString(ByteBuffer buf, Charset charset) { return getCharSequence(buf, charset).toString(); } public final static void putCharSequence(ByteBuffer buf, Charset charset, CharSequence value) { putCharSequence(buf, charset.newEncoder(), value); } public final static void putCharSequence(ByteBuffer buf, CharsetEncoder encoder, CharSequence value) { // // Convert any CharSequence implementor (String, etc) into a native // C string. // encoder.reset().onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE) .encode(CharBuffer.wrap(value), buf, true); encoder.flush(buf); final int nulSize = Math.round(encoder.maxBytesPerChar()); // NUL terminate the string if (nulSize == 4) { buf.putInt(0); } else if (nulSize == 2) { buf.putShort((short) 0); } else if (nulSize == 1) { buf.put((byte) 0); } } public final static CharSequence getCharSequence(ByteBuffer buf, Charset charset) { return getCharSequence(buf, charset.newDecoder()); } public final static CharSequence getCharSequence(final ByteBuffer buf, final CharsetDecoder decoder) { final ByteBuffer buffer = buf.slice(); // Find the NUL terminator and limit to that, so the // StringBuffer/StringBuilder does not have superfluous NUL chars int end = indexOf(buffer, (byte) 0); if (end < 0) { end = buffer.limit(); } buffer.position(0).limit(end); try { return decoder.reset().onMalformedInput(CodingErrorAction.REPLACE) .onUnmappableCharacter(CodingErrorAction.REPLACE).decode(buffer); } catch (CharacterCodingException ex) { throw new Error("Illegal character data in native string", ex); } } /** * Finds the position of a byte relative to the start of the buffer. * * @param buf The ByteBuffer to find the value in * @param value The value to locate * @return The position within the buffer that value is found, or -1 if not * found. */ public final static int positionOf(ByteBuffer buf, byte value) { if (buf.hasArray()) { final byte[] array = buf.array(); final int offset = buf.arrayOffset(); final int limit = buf.limit(); for (int pos = buf.position(); pos < limit; ++pos) { if (array[offset + pos] == value) { return pos; } } } else { final int limit = buf.limit(); for (int pos = buf.position(); pos < limit; ++pos) { if (buf.get(pos) == value) { return pos; } } } return -1; } public final static int indexOf(ByteBuffer buf, byte value) { if (buf.hasArray()) { byte[] array = buf.array(); int begin = buf.arrayOffset() + buf.position(); int end = begin + buf.limit(); for (int offset = 0; offset < end && offset > -1; ++offset) { if (array[begin + offset] == value) { return offset; } } } else { int begin = buf.position(); for (int offset = 0; offset < buf.limit(); ++offset) { if (buf.get(begin + offset) == value) { return offset; } } } return -1; } private static interface AddressIO { public long getAddress(ByteBuffer io, int offset); public void putAddress(ByteBuffer io, int offset, long address); public static class AddressIO32 implements AddressIO { public static final AddressIO IMPL = new AddressIO32(); public long getAddress(ByteBuffer io, int offset) { return io.getInt(offset); } public void putAddress(ByteBuffer io, int offset, long address) { io.putInt(offset, (int) address); } } public static class AddressIO64 implements AddressIO { public static final AddressIO IMPL = new AddressIO64(); public long getAddress(ByteBuffer io, int offset) { return io.getLong(offset); } public void putAddress(ByteBuffer io, int offset, long address) { io.putLong(offset, address); } } public static final AddressIO INSTANCE = Platform.getPlatform().addressSize() == 32 ? AddressIO32.IMPL : AddressIO64.IMPL; } public final static long getAddress(ByteBuffer buf, int position) { return AddressIO.INSTANCE.getAddress(buf, position); } public final static void putAddress(ByteBuffer buf, int position, long address) { AddressIO.INSTANCE.putAddress(buf, position, address); } /* public final static Pointer getPointer(ByteBuffer buf, int position) { return new Pointer(getAddress(buf, position)); } public final static void putPointer(ByteBuffer buf, int position, Pointer value) { putAddress(buf, position, value.nativeAddress()); } */ public static ByteBuffer slice(final ByteBuffer buffer, final int position) { final ByteBuffer tmp = buffer.duplicate(); tmp.position(position); return tmp.slice(); } public static ByteBuffer slice(final ByteBuffer buffer, final int position, final int size) { final ByteBuffer tmp = buffer.duplicate(); tmp.position(position).limit(position + size); return tmp.slice(); } }jaffl-0.5.9/src/com/kenai/jaffl/util/EnumMapper.java000066400000000000000000000061311201747543600222300ustar00rootroot00000000000000 package com.kenai.jaffl.util; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Provides mapping from Enum values to native integers and vice-versa */ public class EnumMapper { public static interface IntegerEnum { public int intValue(); } private static final class Entry { Map enumMap = new HashMap(); Map valueMap = new HashMap(); } private static final class SingletonHolder { private static final EnumMapper INSTANCE = new EnumMapper(); } public static EnumMapper getInstance() { return SingletonHolder.INSTANCE; } private static final int getIntegerValue(Enum e) { if (e instanceof IntegerEnum) { return ((IntegerEnum) e).intValue(); } else { return e.ordinal(); } } private Entry createEntry(Class enumClass) { Entry entry = new Entry(); for (Enum e : enumClass.getEnumConstants()) { int intValue = getIntegerValue(e); entry.enumMap.put(intValue, e); entry.valueMap.put(e, intValue); } return entry; } private Entry getEntry(Class enumClass) { Entry entry = enums.get(enumClass); if (entry == null) { // // When building the entry, lock on the class so other lookups can proceed // without waiting for the build. // synchronized (enumClass) { // // Re-check in case two threads tried at the same time and fell through // to here. // if (!enums.containsKey(enumClass)) { enums.put(enumClass, entry = createEntry(enumClass)); } else { entry = enums.get(enumClass); } } } return entry; } public int intValue(Enum value) { //return getEntry(value.getClass()).valueMap.get(value); return getIntegerValue(value); } public > E valueOf(int value, Class enumClass) { Enum e = getEntry(enumClass).enumMap.get(value); if (e == null) { // // No value found - try to find the default value for unknown values. // This is useful for enums that aren't fixed in stone and/or where you // don't want to throw an Exception for an unknown value. // try { return Enum.valueOf(enumClass, "__UNKNOWN_NATIVE_VALUE"); } catch (IllegalArgumentException ex) { // // No default, so just give up and throw an exception // throw new IllegalArgumentException("No known Enum mapping for value " + value + " of type " + enumClass.getName()); } } return enumClass.cast(e); } private final Map, Entry> enums = new ConcurrentHashMap, Entry>(); } jaffl-0.5.9/src/com/kenai/jaffl/util/MultiBufferPool.java000066400000000000000000000052101201747543600232320ustar00rootroot00000000000000 package com.kenai.jaffl.util; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.List; public class MultiBufferPool implements BufferPool { /** * Creates a new instance of MultiBufferPool */ public MultiBufferPool(int maxBufferSize, int maxItemsPerSize, boolean threadSafe) { this.maxBufferSize = maxBufferSize; this.maxItemsPerSize = maxItemsPerSize; maxPoolIndex = getSizeIndex(maxBufferSize); pools = new SimpleBufferPool[maxPoolIndex + 1]; // Now create each of the buckets for (int i = 0; i <= maxPoolIndex; ++i) { if (threadSafe) { pools[i] = new SynchronizedPool(1 << i, maxItemsPerSize); } else { pools[i] = new SimpleBufferPool(1 << i, maxItemsPerSize); } } } public MultiBufferPool(int maxBufferSize, int maxItemsPerSize) { this(maxBufferSize, maxItemsPerSize, false); } private final int maxBufferSize, maxItemsPerSize, maxPoolIndex; private SimpleBufferPool[] pools; private static final int getSizeIndex(int size) { int start = 0; int ssize = size; // // Cut down the loop size by dividing up the address space // if (ssize > 0xffff) { start += 16; ssize >>= 16; } if (ssize > 0xff) { start += 8; ssize >>= 8; } if (ssize > 0xf) { start += 4; } for (int i = start; i < 32; ++i) { if ((1 << i) >= size) { //System.out.println("size " + size + " maps to pool index " + i); return i; } } return 32; } public ByteBuffer get(int size) { int index = getSizeIndex(size); if (index <= maxPoolIndex) { return pools[index].get(size); } return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()); } public void put(ByteBuffer buf) { int index = getSizeIndex(buf.capacity()); if (index <= maxPoolIndex) { pools[index].put(buf); } } public void putAll(List list) { for (ByteBuffer buf : list) { put(buf); } } static class SynchronizedPool extends SimpleBufferPool { public SynchronizedPool(int bufferSize, int poolSize) { super(bufferSize, poolSize); } public synchronized ByteBuffer get(int size) { return super.get(size); } public synchronized void put(ByteBuffer buf) { super.put(buf); } } } jaffl-0.5.9/src/com/kenai/jaffl/util/SimpleBufferPool.java000066400000000000000000000055271201747543600234040ustar00rootroot00000000000000 package com.kenai.jaffl.util; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; public class SimpleBufferPool implements BufferPool { private final int bufferSize, poolSize; private final BufferPool parent; private final ArrayList list; /** * Creates a new instance of SimpleBufferPool * @param bufferSize The Size of ByteBuffer this pool should return * @param poolSize The maximum number of ByteBuffers to cache */ public SimpleBufferPool(int bufferSize, int poolSize) { this(new DefaultPool(), bufferSize, poolSize); } /** Creates a new instance of SimpleBufferPool * @param parent The parent pool from which to to fetch/return extra buffers. * @param bufferSize The Size of ByteBuffer this pool should return. * @param poolSize The maximum number of ByteBuffers to cache. */ public SimpleBufferPool(BufferPool parent, int bufferSize, int poolSize) { this.parent = parent; this.bufferSize = bufferSize; this.poolSize = poolSize; this.list = new ArrayList(poolSize); } public ByteBuffer get(int size) { if (size <= bufferSize && !list.isEmpty()) { //System.out.println("Returning cached buffer for size=" + size); // Removing from the end of the ArrayList is O(1) ByteBuffer buf = list.remove(list.size() - 1); buf.rewind().limit(size); return buf; } // Fetch a new buffer from the parent pool //System.out.println("Allocating new direct ByteBuffer"); // Default to allocating a new buffer - make it at least bufferSize so it // can be added back to the pool later // This also handles buffers that are larger than the pool bufferSize. // System.out.println("Requested buffer size of " + size + " is larger than " + bufferSize); ByteBuffer buf = parent.get(Math.max(size, bufferSize)); buf.rewind().limit(size); return buf; } public void put(ByteBuffer buf) { if (list.size() < poolSize && buf.capacity() == bufferSize) { //System.out.println("Storing ByteBuffer in pool size=" + bufferSize); // Adding at the end of the ArrayList is O(1) list.add(buf); } else { parent.put(buf); } } public void putAll(List list) { for (ByteBuffer buf : list) { put(buf); } } static class DefaultPool implements BufferPool { public ByteBuffer get(int size) { return ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder()); } // Just let the GC collect the buffers public void put(ByteBuffer buffer) { } public void putAll(List list) { } } } jaffl-0.5.9/test/000077500000000000000000000000001201747543600135775ustar00rootroot00000000000000jaffl-0.5.9/test/com/000077500000000000000000000000001201747543600143555ustar00rootroot00000000000000jaffl-0.5.9/test/com/kenai/000077500000000000000000000000001201747543600154445ustar00rootroot00000000000000jaffl-0.5.9/test/com/kenai/jaffl/000077500000000000000000000000001201747543600165265ustar00rootroot00000000000000jaffl-0.5.9/test/com/kenai/jaffl/ArrayTest.java000066400000000000000000000167701201747543600213220ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class ArrayTest { public static interface TestLib { // Pointer ptr_return_array_element(Pointer[] array, int index); // void ptr_set_array_element(Pointer[] array, int index, Pointer value); byte ptr_ret_int8_t(byte[] p, int offset); short ptr_ret_int16_t(short[] p, int offset); int ptr_ret_int32_t(int[] p, int offset); long ptr_ret_int64_t(long[] p, int offset); float ptr_ret_float(float[] p, int offset); // Pointer ptr_ret_pointer(Pointer[] p, int offset); double ptr_ret_double(double[] p, int offset); void ptr_set_int8_t(byte[] p, int offset, byte value); void ptr_set_int16_t(short[] p, int offset, short value); void ptr_set_int32_t(int[] p, int offset, int value); void ptr_set_int64_t(long[] p, int offset, long value); void ptr_set_float(float[] p, int offset, float value); void ptr_set_double(double[] p, int offset, double value); // void ptr_set_pointer(Pointer[] p, int offset, Pointer value); Pointer ptr_malloc(int size); void ptr_free(Pointer ptr); } public static interface TestLibInOnly { byte ptr_ret_int8_t(@In byte[] p, int offset); short ptr_ret_int16_t(@In short[] p, int offset); int ptr_ret_int32_t(@In int[] p, int offset); long ptr_ret_int64_t(@In long[] p, int offset); float ptr_ret_float(@In float[] p, int offset); void ptr_set_int8_t(@In byte[] p, int offset, byte value); void ptr_set_int16_t(@In short[] p, int offset, short value); void ptr_set_int32_t(@In int[] p, int offset, int value); void ptr_set_int64_t(@In long[] p, int offset, long value); void ptr_set_float(@In float[] p, int offset, float value); void ptr_set_double(@In double[] p, int offset, double value); // void ptr_set_pointer(@In Pointer[] p, int offset, Pointer value); } public static interface TestLibOutOnly { byte ptr_ret_int8_t(@Out byte[] p, int offset); short ptr_ret_int16_t(@Out short[] p, int offset); int ptr_ret_int32_t(@Out int[] p, int offset); long ptr_ret_int64_t(@Out long[] p, int offset); float ptr_ret_float(@Out float[] p, int offset); void ptr_set_int8_t(@Out byte[] p, int offset, byte value); void ptr_set_int16_t(@Out short[] p, int offset, short value); void ptr_set_int32_t(@Out int[] p, int offset, int value); void ptr_set_int64_t(@Out long[] p, int offset, long value); void ptr_set_float(@Out float[] p, int offset, float value); void ptr_set_double(@Out double[] p, int offset, double value); // void ptr_set_pointer(@Out Pointer[] p, int offset, Pointer value); } static TestLib testlib; public ArrayTest() { } @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void byteByReference() { final byte MAGIC = (byte) 0xfe; byte[] ref = { MAGIC }; assertEquals("byte reference not read correctly", MAGIC, testlib.ptr_ret_int8_t(ref, 0)); final byte MAGIC2 = (byte) 0xca; testlib.ptr_set_int8_t(ref, 0, MAGIC2); assertEquals("byte reference not written correctly", MAGIC2, ref[0]); } @Test public void shortByReference() { final short MAGIC = (short) 0xfee1; short[] ref = { MAGIC }; assertEquals("short reference not read correctly", MAGIC, testlib.ptr_ret_int16_t(ref, 0)); final short MAGIC2 = (short) 0xcafe; testlib.ptr_set_int16_t(ref, 0, MAGIC2); assertEquals("short reference not written correctly", MAGIC2, ref[0]); } @Test public void intByReference() { final int MAGIC = (int) 0xfee1dead; int[] ref = { MAGIC }; assertEquals("int reference not read correctly", MAGIC, testlib.ptr_ret_int32_t(ref, 0)); final int MAGIC2 = (int) 0xcafebabe; testlib.ptr_set_int32_t(ref, 0, MAGIC2); assertEquals("int reference not written correctly", MAGIC2, ref[0]); } @Test public void longByReference() { final long MAGIC = 0x1234fee1dead6789L; long[] ref = { MAGIC }; assertEquals("long reference not read correctly", MAGIC, testlib.ptr_ret_int64_t(ref, 0)); final long MAGIC2 = 0xcafebabe12345678L; testlib.ptr_set_int64_t(ref, 0, MAGIC2); assertEquals("long reference not written correctly", MAGIC2, ref[0]); } // @Test // public void pointerByReference() { // final Pointer MAGIC = new Pointer(0xfee1dead); // Pointer[] ref = { MAGIC }; // assertEquals("Pointer reference not read correctly", MAGIC, testlib.ptr_ret_pointer(ref, 0)); // final Pointer MAGIC2 = new Pointer(0xcafebabe); // testlib.ptr_set_pointer(ref, 0, MAGIC2); // assertEquals("Pointer reference not written correctly", MAGIC2, ref[0]); // } @Test public void floatByReference() { final float MAGIC = (float) 0xfee1dead; float[] ref = { MAGIC }; assertEquals("float reference not read correctly", MAGIC, testlib.ptr_ret_float(ref, 0), 0.0f); final float MAGIC2 = (float) 0xcafebabe; testlib.ptr_set_float(ref, 0, MAGIC2); assertEquals("float reference not written correctly", MAGIC2, ref[0], 0f); } @Test public void doubleByReference() { final double MAGIC = 0x1234fee1dead6789L; double[] ref = { MAGIC }; assertEquals("double reference not read correctly", MAGIC, testlib.ptr_ret_double(ref, 0), 0d); final double MAGIC2 = (double) 0xcafebabe12345678L; testlib.ptr_set_double(ref, 0, MAGIC2); assertEquals("double reference not written correctly", MAGIC2, ref[0], 0d); } //@Test public void inOnlyByteByReference() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final byte MAGIC = (byte) 0xfe; byte[] ref = { MAGIC }; assertEquals("byte reference not read correctly", MAGIC, lib.ptr_ret_int8_t(ref, 0)); final byte MAGIC2 = (byte) 0xca; lib.ptr_set_int8_t(ref, 0, MAGIC2); assertEquals("byte array read from native memory when it should not be", MAGIC, ref[0]); } //@Test public void inOnlyByteArray() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final byte MAGIC = (byte) 0xfe; byte[] ref = new byte[1024]; ref[0] = MAGIC; assertEquals("byte array not read correctly", MAGIC, lib.ptr_ret_int8_t(ref, 0)); final byte MAGIC2 = (byte) 0xca; lib.ptr_set_int8_t(ref, 0, MAGIC2); assertEquals("byte array read from native memory when it should not be", MAGIC, ref[0]); } //@Test public void outOnlyByteByReference() { TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); final byte MAGIC = (byte) 0xfe; byte[] ref = { MAGIC }; final byte MAGIC2 = (byte) 0xca; lib.ptr_set_int8_t(ref, 0, MAGIC2); assertEquals("byte reference not copied from native memory", MAGIC2, ref[0]); } }jaffl-0.5.9/test/com/kenai/jaffl/BufferTest.java000066400000000000000000000332611201747543600214470ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.CharBuffer; import java.nio.DoubleBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.LongBuffer; import java.nio.ShortBuffer; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class BufferTest { public BufferTest() { } public static interface TestLib { void fillByteBuffer(@Out ByteBuffer buf, byte value, int size); // void fillCharBuffer(@Out CharBuffer buf, char value, int size); void fillShortBuffer(@Out ShortBuffer buf, short value, int size); void fillIntBuffer(@Out IntBuffer buf, int value, int size); void fillLongBuffer(@Out LongBuffer buf, long value, int size); void fillFloatBuffer(@Out FloatBuffer buf, float value, int size); void fillDoubleBuffer(@Out DoubleBuffer buf, double value, int size); void fillByteBuffer(@Out byte[] buf, byte value, int size); // void fillCharBuffer(@Out char[] buf, char value, int size); void fillShortBuffer(@Out short[] buf, short value, int size); void fillIntBuffer(@Out int[] buf, int value, int size); void fillLongBuffer(@Out long[] buf, long value, int size); void fillFloatBuffer(@Out float[] buf, float value, int size); void fillDoubleBuffer(@Out double[] buf, double value, int size); void copyByteBuffer(@Out ByteBuffer dst, @In ByteBuffer src, int size); void copyByteBuffer(@Out ByteBuffer dst, @In byte[] src, int size); void copyByteBuffer(@Out byte[] dst, @In ByteBuffer src, int size); void copyByteBuffer(@Out byte[] dst, @In byte[] src, int size); void copyShortBuffer(@Out ShortBuffer dst, @In ShortBuffer src, int size); void copyShortBuffer(@Out ShortBuffer dst, @In short[] src, int size); void copyShortBuffer(@Out short[] dst, @In ShortBuffer src, int size); void copyShortBuffer(@Out short[] dst, @In short[] src, int size); void copyIntBuffer(@Out IntBuffer dst, @In IntBuffer src, int size); void copyIntBuffer(@Out IntBuffer dst, @In int[] src, int size); void copyIntBuffer(@Out int[] dst, @In IntBuffer src, int size); void copyIntBuffer(@Out int[] dst, @In int[] src, int size); } static TestLib lib; @BeforeClass public static void setUpClass() throws Exception { lib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { lib = null; } @Before public void setUp() { } @After public void tearDown() { } // SMALL sized heap buffers can be done using direct buffers private static final int SMALL = 64; // LARGE sized heap buffers are handled via the native code private static final int LARGE = 2048; public void testByteBufferArgument(int size) { ByteBuffer buf = ByteBuffer.allocate(size).order(ByteOrder.nativeOrder()); final byte MAGIC = (byte)0xED; lib.fillByteBuffer(buf, MAGIC, buf.remaining()); for (int i=0;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillSmallByteBufferArgument() { testByteBufferArgument(SMALL); } @Test public void fillLargeByteBufferArgument() { testByteBufferArgument(LARGE); } @Test public void fillByteBufferWithOffsetArgument() { ByteBuffer buf = ByteBuffer.allocate(SMALL).order(ByteOrder.nativeOrder()); final byte MAGIC = (byte)0xED; buf.put((byte)0xDE); lib.fillByteBuffer(buf.slice(), MAGIC, SMALL - 1); assertEquals("Value at position 0 overwritten", (byte)0xde, buf.get(0)); for (int i=buf.position();i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillByteBufferSlice() { final int SIZE = SMALL; ByteBuffer buf = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); final byte MAGIC = (byte)0xED; buf.put(0, (byte)0xDE); buf.put(buf.limit() - 1, (byte) 0xDE); ByteBuffer dup = buf.duplicate(); dup.position(1).limit(buf.limit() - 1); ByteBuffer slice = dup.slice(); lib.fillByteBuffer(slice, MAGIC, slice.capacity()); assertEquals("Value at position 0 overwritten", (byte)0xde, buf.get(0)); assertEquals("Value at position " + (SIZE - 1) + " overwritten", (byte)0xde, buf.get(SIZE - 1)); for (int i = 1; i < buf.capacity() - 1; i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } public void testShortBufferArgument(int size) { ShortBuffer buf = ShortBuffer.allocate(size); final short MAGIC = (short)0xABED; lib.fillShortBuffer(buf, MAGIC, size); for (int i=0;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillSmallShortBufferArgument() { testShortBufferArgument(SMALL); } @Test public void fillLargeShortBufferArgument() { testShortBufferArgument(LARGE); } @Test public void fillShortBufferWithOffsetArgument() { ShortBuffer buf = ShortBuffer.allocate(SMALL); final short MAGIC = (short)0xABED; buf.put((short)0xDEAD); lib.fillShortBuffer(buf.slice(), MAGIC, SMALL - 1); assertEquals("Value at position 0 overwritten", (short)0xdead, buf.get(0)); for (int i=1;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillShortBufferSlice() { ShortBuffer buf = ShortBuffer.allocate(SMALL); final short FILL = (short) 0x1234; final short GUARD = (short) 0xdead; buf.put(0, GUARD).put(buf.limit() - 1, GUARD); ShortBuffer dup = buf.duplicate(); dup.position(1).limit(buf.limit() - 1); ShortBuffer slice = dup.slice(); lib.fillShortBuffer(slice, FILL, slice.capacity()); assertEquals("Value at position 0 overwritten", GUARD, buf.get(0)); assertEquals("Value at position " + (buf.limit() - 1) + " overwritten", GUARD, buf.get(buf.limit() - 1)); for (int i = 1; i < buf.limit() - 1; i++) { assertEquals("Bad value at index " + i, FILL, buf.get(i)); } } public void testIntBufferArgument(int size) { IntBuffer buf = IntBuffer.allocate(size); final int MAGIC = 0xABEDCF23; lib.fillIntBuffer(buf, MAGIC, size); for (int i=0;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillSmallIntBufferArgument() { testIntBufferArgument(SMALL); } @Test public void fillLargeIntBufferArgument() { testIntBufferArgument(SMALL); } @Test public void fillIntBufferWithOffsetArgument() { IntBuffer buf = IntBuffer.allocate(SMALL); final int MAGIC = 0xABEDCF23; buf.put(0xdeadbeef); lib.fillIntBuffer(buf.slice(), MAGIC, SMALL - 1); assertEquals("Value at position 0 overwritten", 0xdeadbeef, buf.get(0)); for (int i=1;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillIntBufferSlice() { IntBuffer buf = IntBuffer.allocate(SMALL); final int FILL = 0x12345678; final int GUARD = 0xdeadbeef; buf.put(0, GUARD).put(buf.limit() - 1, GUARD); IntBuffer dup = buf.duplicate(); dup.position(1).limit(buf.limit() - 1); IntBuffer slice = dup.slice(); lib.fillIntBuffer(slice, FILL, slice.capacity()); assertEquals("Value at position 0 overwritten", GUARD, buf.get(0)); assertEquals("Value at position " + (buf.limit() - 1) + " overwritten", GUARD, buf.get(buf.limit() - 1)); for (int i = 1; i < buf.limit() - 1; i++) { assertEquals("Bad value at index " + i, FILL, buf.get(i)); } } @Test public void fillLongBufferArgument() { LongBuffer buf = LongBuffer.allocate(SMALL); final long MAGIC = 0x1234567887654321L; lib.fillLongBuffer(buf, MAGIC, SMALL); for (int i=0;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillLongBufferWithOffsetArgument() { LongBuffer buf = LongBuffer.allocate(SMALL); final long MAGIC = 0x1234567887654321L; buf.put(0xdeadbeefL); lib.fillLongBuffer(buf.slice(), MAGIC, SMALL - 1); assertEquals("Value at position 0 overwritten", 0xdeadbeefL, buf.get(0)); for (int i=1;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillLongBufferSlice() { LongBuffer buf = LongBuffer.allocate(SMALL); final long GUARD = 0xdeadbeefL; final long FILL = 0x1234567887654321L; buf.put(0, GUARD).put(buf.limit() - 1, GUARD); LongBuffer dup = buf.duplicate(); dup.position(1).limit(buf.limit() - 1); LongBuffer slice = dup.slice(); lib.fillLongBuffer(dup.slice(), FILL, slice.capacity()); assertEquals("Value at position 0 overwritten", GUARD, buf.get(0)); assertEquals("Value at position " + (buf.limit() - 1) + " overwritten", GUARD, buf.get(buf.limit() - 1)); for (int i = 1; i < buf.limit() - 1; i++) { assertEquals("Bad value at index " + i, FILL, buf.get(i)); } } @Test public void fillDirectByteBufferArgument() { ByteBuffer buf = ByteBuffer.allocateDirect(SMALL).order(ByteOrder.nativeOrder()); final byte MAGIC = (byte)0xED; lib.fillByteBuffer(buf, MAGIC, SMALL); for (int i=0;i < buf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); } } @Test public void fillDirectShortBufferArgument() { ByteBuffer buf = ByteBuffer.allocateDirect(SMALL*2).order(ByteOrder.nativeOrder()); ShortBuffer shortBuf = buf.asShortBuffer(); final short MAGIC = (short)0xABED; lib.fillShortBuffer(shortBuf, MAGIC, SMALL); for (int i=0;i < shortBuf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, shortBuf.get(i)); } } @Test public void fillDirectIntBufferArgument() { ByteBuffer buf = ByteBuffer.allocateDirect(SMALL*4).order(ByteOrder.nativeOrder()); IntBuffer intBuf = buf.asIntBuffer(); final int MAGIC = 0xABEDCF23; lib.fillIntBuffer(intBuf, MAGIC, SMALL); for (int i=0;i < intBuf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, intBuf.get(i)); } } @Test public void fillDirectLongBufferArgument() { ByteBuffer buf = ByteBuffer.allocateDirect(SMALL*8).order(ByteOrder.nativeOrder()); LongBuffer longBuf = buf.asLongBuffer(); final long MAGIC = 0x1234567887654321L; lib.fillLongBuffer(longBuf, MAGIC, SMALL); for (int i=0;i < longBuf.capacity();i++) { assertEquals("Bad value at index " + i, MAGIC, longBuf.get(i)); } } @Test public void copySmallDirectByteBufferToArray() { testCopyByteBufferToArray(ByteBuffer.allocateDirect(SMALL)); } @Test public void copyLargeDirectByteBufferToArray() { testCopyByteBufferToArray(ByteBuffer.allocateDirect(LARGE)); } @Test public void copySmallHeapByteBufferToArray() { testCopyByteBufferToArray(ByteBuffer.allocate(SMALL)); } @Test public void copyLargeHeapByteBufferToArray() { testCopyByteBufferToArray(ByteBuffer.allocate(LARGE)); } public void testCopyByteBufferToArray(ByteBuffer src) { final int size = src.capacity(); for (int i = 0; i < size; ++i) { src.put(i, (byte) i); } byte[] dst = new byte[size]; lib.copyByteBuffer(dst, src, size); for (int i = 0; i < size; ++i) { assertEquals("Bad value at index " + i, (byte) i, dst[i]); } } // FIXME: re-enable when read-only buffers are supported // @Test public void copyReadOnlyHeapByteBufferToArray() { final int size = SMALL; ByteBuffer src = ByteBuffer.allocate(size); for (int i = 0; i < size; ++i) { src.put(i, (byte) i); } byte[] dst = new byte[size]; lib.copyByteBuffer(dst, src.asReadOnlyBuffer(), size); for (int i = 0; i < size; ++i) { assertEquals("Bad value at index " + i, (byte) i, dst[i]); } } // @Test // public void pinnedByteBuffer() { // ByteBuffer buf = ByteBuffer.allocate(LARGE); // Function fillByteBuffer = NativeLibrary.getInstance("jffitest").getFunction("fillByteBuffer"); // NativeInvoker nativeInvoker = FFINativeInvoker.getInvoker(fillByteBuffer, NativeInvoker.VOID); // CallBuilder cb = CallBuilder.create(nativeInvoker); // final byte MAGIC = (byte)0xED; // cb.addPinned(buf).addInt8(MAGIC).addInt32(buf.remaining()).invokeVoid(); // for (int i=0;i < buf.capacity();i++) { // assertEquals("Bad value at index " + i, MAGIC, buf.get(i)); // } // } }jaffl-0.5.9/test/com/kenai/jaffl/ClosureTest.java000066400000000000000000000506161201747543600216550ustar00rootroot00000000000000 package com.kenai.jaffl; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class ClosureTest { public ClosureTest() { } private static TestLib lib; @BeforeClass public static void setUpClass() throws Exception { lib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // FIXME: re-enable when closure/callbacks are working @Test public void nop() {} public static interface TestLib { // public static interface ClosureVrV extends Closure { // public void invoke(); // } // void testClosureVrV(Closure closure); // public static interface ClosureVrB extends Closure { // public byte invoke(); // } // byte testClosureVrB(Closure closure); // public static interface ClosureVrS extends Closure { // public short invoke(); // } // short testClosureVrS(Closure closure); // int testClosureVrI(Closure closure); // long testClosureVrL(Closure closure); // float testClosureVrF(Closure closure); // public interface ClosureVrD extends Closure { // public double invoke(); // } // double testClosureVrD(Closure closure); // // public interface ClosureIrV extends Closure { // public void invoke(int a1); // } // void testClosureBrV(Closure closure, byte a1); // void testClosureSrV(Closure closure, short a1); // void testClosureIrV(Closure closure, int a1); // void testClosureLrV(Closure closure, long a1); // void testClosureFrV(Closure closure, float a1); // void testClosureDrV(Closure closure, double a1); // // // closures with small-big-small arguments // void testClosureBSBrV(Closure closure, byte a1, short a2, byte a3); // void testClosureBIBrV(Closure closure, byte a1, int a2, byte a3); // void testClosureBLBrV(Closure closure, byte a1, long a2, byte a3); // void testClosureBFBrV(Closure closure, byte a1, float a2, byte a3); // void testClosureBDBrV(Closure closure, byte a1, double a2, byte a3); // // void testClosureSBSrV(Closure closure, short a1, byte a2, short a3); // void testClosureSISrV(Closure closure, short a1, int a2, short a3); // void testClosureSLSrV(Closure closure, short a1, long a2, short a3); // void testClosureSFSrV(Closure closure, short a1, float a2, short a3); // void testClosureSDSrV(Closure closure, short a1, double a2, short a3); // // // Now big-smaller-smaller // void testClosureLSBrV(Closure closure, long a1, short a2, byte a3); // // big-smaller-small // void testClosureLBSrV(Closure closure, long a1, byte a2, short a3); } // @Test // public void closureVrV() { // final boolean[] called = { false }; // final TestLib.ClosureVrV closure = new TestLib.ClosureVrV() { // // public void invoke() { // called[0] = true; // } // }; // lib.testClosureVrV(closure); // assertTrue("Closure not called", called[0]); // } // @Test // public void closureVrB() { // final boolean[] called = { false }; // final byte MAGIC = (byte) 0xfe; // TestLib.ClosureVrB closure = new TestLib.ClosureVrB() { // // public byte invoke() { // called[0] = true; // return MAGIC; // } // }; // byte retVal = lib.testClosureVrB(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal); // } // @Test // public void closureVrS() { // final boolean[] called = { false }; // final short MAGIC = (short) 0xfee1; // TestLib.ClosureVrS closure = new TestLib.ClosureVrS() { // // public short invoke() { // called[0] = true; // return MAGIC; // } // }; // short retVal = lib.testClosureVrS(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal); // } // @Test // public void closureVrI() { // final boolean[] called = { false }; // final int MAGIC = (int) 0xfee1dead; // Closure closure = new Closure() { // // public int invoke() { // called[0] = true; // return MAGIC; // } // }; // int retVal = lib.testClosureVrI(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal); // } // @Test // public void closureVrL() { // final boolean[] called = { false }; // final long MAGIC = 0xfee1deadcafebabeL; // Closure closure = new Closure() { // // public long invoke() { // called[0] = true; // return MAGIC; // } // }; // long retVal = lib.testClosureVrL(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal); // } // @Test // public void closureVrF() { // final boolean[] called = { false }; // final float MAGIC = (float) 0xfee1dead; // Closure closure = new Closure() { // // public float invoke() { // called[0] = true; // return MAGIC; // } // }; // float retVal = lib.testClosureVrF(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal, 0f); // } // @Test // public void closureVrD() { // final boolean[] called = { false }; // final double MAGIC = (double) 0xfee1dead; // TestLib.ClosureVrD closure = new TestLib.ClosureVrD() { // // public double invoke() { // called[0] = true; // return MAGIC; // } // }; // double retVal = lib.testClosureVrD(closure); // assertTrue("Closure not called", called[0]); // assertEquals("Incorrect return value from closure", MAGIC, retVal, 0d); // } // @Test // public void closureBrV() { // final boolean[] called = { false }; // final byte[] val = { 0 }; // final byte MAGIC = (byte) 0xde; // Closure closure = new Closure() { // // public void invoke(byte a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureBrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0]); // } // @Test // public void closureSrV() { // final boolean[] called = { false }; // final short[] val = { 0 }; // final short MAGIC = (short) 0xdead; // Closure closure = new Closure() { // // public void invoke(short a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureSrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0]); // } // @Test // public void closureIrV() { // final boolean[] called = { false }; // final int[] val = { 0 }; // final int MAGIC = 0xdeadbeef; // Closure closure = new Closure() { // // public void invoke(int a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureIrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0]); // } // @Test // public void closureLrV() { // final boolean[] called = { false }; // final long[] val = { 0 }; // final long MAGIC = 0xfee1deadcafebabeL; // Closure closure = new Closure() { // // public void invoke(long a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureLrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0]); // } // @Test // public void closureFrV() { // final boolean[] called = { false }; // final float[] val = { 0 }; // final float MAGIC = (float) 0xdeadbeef; // Closure closure = new Closure() { // // public void invoke(float a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureFrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0], 0f); // } // @Test // public void closureDrV() { // final boolean[] called = { false }; // final double[] val = { 0 }; // final double MAGIC = (double) 0xfee1deadcafebabeL; // Closure closure = new Closure() { // // public void invoke(double a1) { // called[0] = true; // val[0] = a1; // } // }; // lib.testClosureDrV(closure, MAGIC); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", MAGIC, val[0], 0d); // } // @Test // public void closureBSBrV() { // final boolean[] called = { false }; // final byte[] v1 = { 0 }; // final short[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final byte A1 = (byte) 0x11; // final short A2 = (short) 0xfee1; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(byte a1, short a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureBSBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureBIBrV() { // final boolean[] called = { false }; // final byte[] v1 = { 0 }; // final int[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final byte A1 = (byte) 0x11; // final int A2 = (int) 0xfee1dead; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(byte a1, int a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureBIBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureBLBrV() { // final boolean[] called = { false }; // final byte[] v1 = { 0 }; // final long[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final byte A1 = (byte) 0x11; // final long A2 = (long) 0xfee1deadcafebabeL; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(byte a1, long a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureBLBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureBFBrV() { // final boolean[] called = { false }; // final byte[] v1 = { 0 }; // final float[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final byte A1 = (byte) 0x11; // final float A2 = (float) 0xfee1dead; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(byte a1, float a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureBFBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0], 0f); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureBDBrV() { // final boolean[] called = { false }; // final byte[] v1 = { 0 }; // final double[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final byte A1 = (byte) 0x11; // final double A2 = (double) 0xfee1deadcafebabeL; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(byte a1, double a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureBDBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0], 0d); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureSBSrV() { // final boolean[] called = { false }; // final short[] v1 = { 0 }; // final byte[] v2 = { 0 }; // final short[] v3 = { 0 }; // final short A1 = (short) 0x1111; // final byte A2 = (byte) 0xfe; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(short a1, byte a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureSBSrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureSISrV() { // final boolean[] called = { false }; // final short[] v1 = { 0 }; // final int[] v2 = { 0 }; // final short[] v3 = { 0 }; // final short A1 = (short) 0x1111; // final int A2 = (int) 0xfee1dead; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(short a1, int a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureSISrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // // @Test // public void closureSLSrV() { // final boolean[] called = { false }; // final short[] v1 = { 0 }; // final long[] v2 = { 0 }; // final short[] v3 = { 0 }; // final short A1 = (short) 0x1111; // final long A2 = (long) 0xfee1deadcafebabeL; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(short a1, long a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureSLSrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureSFSrV() { // final boolean[] called = { false }; // final short[] v1 = { 0 }; // final float[] v2 = { 0 }; // final short[] v3 = { 0 }; // final short A1 = (short) 0x1111; // final float A2 = (float) 0xfee1dead; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(short a1, float a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureSFSrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0], 0f); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureSDSrV() { // final boolean[] called = { false }; // final short[] v1 = { 0 }; // final double[] v2 = { 0 }; // final short[] v3 = { 0 }; // final short A1 = (short) 0x1111; // final double A2 = (double) 0xfee1deadcafebabeL; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(short a1, double a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureSDSrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0], 0d); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureLSBrV() { // final boolean[] called = { false }; // final long[] v1 = { 0 }; // final short[] v2 = { 0 }; // final byte[] v3 = { 0 }; // final long A1 = (long) 0xfee1deadcafebabeL; // final short A2 = (short) 0x1111; // final byte A3 = (byte) 0x22; // Closure closure = new Closure() { // // public void invoke(long a1, short a2, byte a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureLSBrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } // @Test // public void closureLBSrV() { // final boolean[] called = { false }; // final long[] v1 = { 0 }; // final byte[] v2 = { 0 }; // final short[] v3 = { 0 }; // final long A1 = (long) 0xfee1deadcafebabeL; // final byte A2 = (byte) 0x11; // final short A3 = (short) 0x2222; // Closure closure = new Closure() { // // public void invoke(long a1, byte a2, short a3) { // called[0] = true; // v1[0] = a1; // v2[0] = a2; // v3[0] = a3; // } // }; // lib.testClosureLBSrV(closure, A1, A2, A3); // assertTrue("Closure not called", called[0]); // assertEquals("Wrong value passed to closure", A1, v1[0]); // assertEquals("Wrong value passed to closure", A2, v2[0]); // assertEquals("Wrong value passed to closure", A3, v3[0]); // } }jaffl-0.5.9/test/com/kenai/jaffl/EnumTest.java000066400000000000000000000041431201747543600211370ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.util.EnumMapper; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class EnumTest { public EnumTest() { } public static enum TestEnum implements EnumMapper.IntegerEnum { A(1), B(2), C(3), Z(100); TestEnum(int value) { this.value = value; } public int intValue() { return value; } private final int value; } public static interface TestLib { public int ret_int32_t(TestEnum e); public int add_int32_t(TestEnum i1, TestEnum i2); } public static interface ReturnEnumLib { public TestEnum ret_int32_t(int e); public TestEnum ret_int32_t(TestEnum e); public TestEnum add_int32_t(int i1, int i2); public TestEnum add_int32_t(TestEnum i1, TestEnum i2); } static TestLib testlib; static ReturnEnumLib retenum; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); retenum = TstUtil.loadTestLib(ReturnEnumLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} @Test public void enumArgument() { assertEquals("Wrong value returned for enum", TestEnum.Z.intValue(), testlib.ret_int32_t(TestEnum.Z)); assertEquals("Wrong value returned for enum", TestEnum.C.intValue(), testlib.add_int32_t(TestEnum.A, TestEnum.B)); } @Test public void returnEnum() { assertEquals("Wrong value returned for enum", TestEnum.Z, retenum.ret_int32_t(TestEnum.Z.intValue())); assertEquals("Wrong value returned for enum", TestEnum.C, retenum.add_int32_t(1, 2)); } }jaffl-0.5.9/test/com/kenai/jaffl/LastErrorTest.java000066400000000000000000000016401201747543600221470ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.annotations.SaveError; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class LastErrorTest { public static interface TestLib { @SaveError int setLastError(int error); } public LastErrorTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testLastError() { TestLib lib = TstUtil.loadTestLib(TestLib.class); final int MAGIC = 0xdeadbeef; lib.setLastError(MAGIC); assertEquals("Wrong errno value", MAGIC, LastError.getLastError()); } }jaffl-0.5.9/test/com/kenai/jaffl/LibraryTest.java000066400000000000000000000020301201747543600216300ustar00rootroot00000000000000 package com.kenai.jaffl; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * Test library locating/loading */ public class LibraryTest { public LibraryTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} public static interface TestLib { int setLastError(int error); } @Test public void loadTestLib() { TestLib lib = TstUtil.loadTestLib(TestLib.class); assertNotNull("Could not load libtest", lib); // This just forces the library to really load and call a function lib.setLastError(0); } }jaffl-0.5.9/test/com/kenai/jaffl/MemoryIOTest.java000066400000000000000000000360651201747543600217430ustar00rootroot00000000000000 package com.kenai.jaffl; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class MemoryIOTest { public MemoryIOTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } private static final Pointer getBufferPointer(ByteBuffer buffer) { return TstUtil.getDirectBufferPointer(buffer); } private static final MemoryIO wrapPointer(Pointer ptr, int size) { return MemoryIO.wrap(ptr, size); } private static final MemoryIO wrapPointer(Pointer ptr) { return MemoryIO.wrap(ptr); } private static final MemoryIO wrap(ByteBuffer buffer) { return MemoryIO.wrap(buffer); } private static final MemoryIO allocateDirect(int size) { return MemoryIO.allocateDirect(size); } private final void testPutByte(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i < size; ++i) { io.putByte(i, (byte) (i + 5)); assertEquals("Incorrect value at offset " + i, (byte) (i + 5), buffer.get(i)); } } private final void testGetByte(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i < size; ++i) { buffer.put(i, (byte) (i + 5)); assertEquals("Incorrect value at offset " + i, (byte) (i + 5), io.getByte(i)); } } private final void testPutShort(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 2; ++i) { io.putShort(i, (short) i); assertEquals("Incorrect value at offset " + i, (short) i, buffer.getShort(i)); } } private final void testGetShort(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 2; ++i) { buffer.putShort(i, (short) i); assertEquals("Incorrect value at offset " + i, (short) i, io.getShort(i)); } } private final void testPutInt(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 4; ++i) { io.putInt(i, i); assertEquals("Incorrect value at offset " + i, i, buffer.getInt(i)); } } private final void testGetInt(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 4; ++i) { buffer.putInt(i, i); assertEquals("Incorrect value at offset " + i, i, io.getInt(i)); } } private final void testPutLong(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 8; ++i) { io.putLong(i, i); assertEquals("Incorrect value at offset " + i, (long) i, buffer.getLong(i)); } } private final void testGetLong(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - 8; ++i) { buffer.putLong(i, i); assertEquals("Incorrect value at offset " + i, (long) i, io.getLong(i)); } } private final void testPutFloat(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - (Float.SIZE / 8); ++i) { io.putFloat(i, i); assertEquals("Incorrect value at offset " + i, (float) i, buffer.getFloat(i), 0f); } } private final void testGetFloat(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - (Float.SIZE / 8); ++i) { buffer.putFloat(i, i); assertEquals("Incorrect value at offset " + i, (float) i, io.getFloat(i), 0f); } } private final void testPutDouble(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - (Double.SIZE / 8); ++i) { io.putDouble(i, (double) i); assertEquals("Incorrect value at offset " + i, (double) i, buffer.getDouble(i), 0d); } } private final void testGetDouble(MemoryIO io, ByteBuffer buffer, int size) { for (int i = 0; i <= size - (Double.SIZE / 8); ++i) { buffer.putDouble(i, (double) i); assertEquals("Incorrect value at offset " + i, (double) i, io.getDouble(i), 0d); } } @Test public void testBoundedIOPutByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE); testPutByte(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE); testGetByte(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOPutShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutShort(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetShort(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOPutInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutInt(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetInt(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOPutLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutLong(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetLong(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOPutFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutFloat(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetFloat(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOPutDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutDouble(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testBoundedIOGetDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetDouble(wrapPointer(getBufferPointer(buffer), SIZE), buffer, SIZE); } @Test public void testNegativeBoundedIO() { final int SIZE = 16; MemoryIO memio = allocateDirect(SIZE); try { memio.putByte(-1, (byte) 0); fail("Should have thrown IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ex) { } } @Test public void testOverflowBoundedIO() { final int SIZE = 16; MemoryIO memio = allocateDirect(SIZE); try { memio.putByte(16, (byte) 0); fail("Should have thrown IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ex) { } } @Test public void testNativeIOPutByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE); testPutByte(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE); testGetByte(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOPutShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutShort(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetShort(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOPutInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutInt(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetInt(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOPutLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutLong(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetLong(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOPutFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutFloat(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetFloat(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOPutDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testPutDouble(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testNativeIOGetDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocateDirect(SIZE).order(ByteOrder.nativeOrder()); testGetDouble(wrapPointer(getBufferPointer(buffer)), buffer, SIZE); } @Test public void testBufferIOPutByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE); testPutByte(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetByte() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE); testGetByte(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOPutShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testPutShort(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetShort() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testGetShort(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOPutInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testPutInt(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetInt() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testGetInt(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOPutLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testPutLong(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetLong() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testGetLong(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOPutFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testPutFloat(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetFloat() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testGetFloat(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOPutDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testPutDouble(wrap(buffer), buffer, SIZE); } @Test public void testBufferIOGetDouble() { final int SIZE = 16; ByteBuffer buffer = ByteBuffer.allocate(SIZE).order(ByteOrder.nativeOrder()); testGetDouble(wrap(buffer), buffer, SIZE); } @Test public void testNegativeBufferIO() { final int SIZE = 16; MemoryIO memio = wrap(ByteBuffer.allocate(SIZE)); try { memio.putByte(-1, (byte) 0); fail("Should have thrown IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ex) { } } @Test public void testOverflowBufferIO() { final int SIZE = 16; MemoryIO memio = wrap(ByteBuffer.allocate(SIZE)); try { memio.putByte(16, (byte) 0); fail("Should have thrown IndexOutOfBoundsException"); } catch (IndexOutOfBoundsException ex) { } } @Test public void transferDirectToHeap() throws Exception { ByteBuffer buf = ByteBuffer.allocate(1024); MemoryIO dst = MemoryIO.wrap(buf); MemoryIO src = MemoryIO.allocateDirect(1024); byte[] MAGIC = "MAGIC".getBytes(); src.put(0, MAGIC, 0, MAGIC.length); src.transferTo(0, dst, 0, MAGIC.length); for (int i = 0; i < MAGIC.length; ++i) { assertEquals("Wrong byte at index " + i, MAGIC[i], dst.getByte(i)); } for (int i = 0; i < MAGIC.length; ++i) { assertEquals("Wrong byte at index " + i, MAGIC[i], buf.get(i)); } } @Test public void transferDirectToDirect() throws Exception { MemoryIO dst = MemoryIO.allocateDirect(1024); MemoryIO src = MemoryIO.allocateDirect(1024); final byte[] MAGIC = "MAGIC".getBytes(); final int SRCOFF = 100; final int DSTOFF = 123; src.put(SRCOFF, MAGIC, 0, MAGIC.length); src.transferTo(SRCOFF, dst, DSTOFF, MAGIC.length); for (int i = 0; i < MAGIC.length; ++i) { assertEquals("Wrong byte at index " + i, MAGIC[i], dst.getByte(DSTOFF + i)); } } }jaffl-0.5.9/test/com/kenai/jaffl/NumberTest.java000066400000000000000000000210371201747543600214640ustar00rootroot00000000000000 package com.kenai.jaffl; import java.util.Random; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class NumberTest { public NumberTest() { } public static interface TestLib { public byte add_int8_t(byte i1, byte i2); public short add_int16_t(short i1, short i2); public int add_int32_t(int i1, int i2); public long add_int64_t(long i1, long i2); public NativeLong add_long(NativeLong i1, NativeLong i2); public NativeLong sub_long(NativeLong i1, NativeLong i2); public NativeLong mul_long(NativeLong i1, NativeLong i2); public NativeLong div_long(NativeLong i1, NativeLong i2); public float add_float(float f1, float f2); public float sub_float(float f1, float f2); public float mul_float(float f1, float f2); public float div_float(float f1, float f2); public double add_double(double f1, double f2); public double sub_double(double f1, double f2); public double mul_double(double f1, double f2); public double div_double(double f1, double f2); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() throws Exception { } @After public void tearDown() throws Exception { } @Test public void testByteAddition() throws Exception { for (int i = 0; i <= 255; ++i) { byte i1 = (byte) i; byte i2 = (byte) 0xde; assertEquals("byte addition failed", (byte) (i1 + i2), testlib.add_int8_t(i1, i2)); } } @Test public void testShortAddition() throws Exception { for (int i = 0; i <= 0xffff; ++i) { short i1 = (short) i; short i2 = (short) 0xdead; assertEquals("byte addition failed", (short) (i1 + i2), testlib.add_int16_t(i1, i2)); } } static interface FloatOp { public float j(float f1, float f2); public float n(float f1, float f2); } private void testFloat(FloatOp op) throws Exception { float f1 = 1.0f; float f2 = (float) 0xdeadbeef; assertEquals("float " + op + " failed", op.j(f1, f2), op.n(f1, f2), 0f); for (int i = 0; i < 0xffff; ++i) { f1 = (float) i; assertEquals("float + " + op + " failed", op.j(f1, f2), op.n(f1, f2), 0f); } Random random = new Random(); for (int i = 0; i < 0xffff; ++i) { f1 = random.nextFloat(); f2 = random.nextFloat(); float expected = op.j(f1, f2); float result = op.n(f1, f2); if (expected != result) { fail(String.format("float " + op + "(%f, %f) failed - expected: %f, received: %f", f1, f2, expected, result)); } } } @Test public void testFloatAddition() throws Exception { testFloat(new FloatOp() { public float j(float f1, float f2) { return f1 + f2; } public float n(float f1, float f2) { return testlib.add_float(f1, f2); } @Override public String toString() { return "add"; } }); } @Test public void testFloatSubtraction() throws Exception { testFloat(new FloatOp() { public float j(float f1, float f2) { return f1 - f2; } public float n(float f1, float f2) { return testlib.sub_float(f1, f2); } @Override public String toString() { return "subtract"; } }); } @Test public void testFloatMultiplication() throws Exception { testFloat(new FloatOp() { public float j(float f1, float f2) { return f1 * f2; } public float n(float f1, float f2) { return testlib.mul_float(f1, f2); } public String toString() { return "multiply"; } }); } @Test public void testFloatDivision() throws Exception { testFloat(new FloatOp() { public float j(float f1, float f2) { return f1 / f2; } public float n(float f1, float f2) { return testlib.div_float(f1, f2); } @Override public String toString() { return "divide"; } }); } static interface DoubleOp { public double j(double f1, double f2); public double n(double f1, double f2); } private void testDouble(DoubleOp op) throws Exception { double f1 = 1.0f; double f2 = (double) 0xdeadbeef; assertEquals("double " + op + " failed", op.j(f1, f2), op.n(f1, f2), 0d); for (int i = 0; i < 0xffff; ++i) { f1 = (float) i; assertEquals("double + " + op + " failed", op.j(f1, f2), op.n(f1, f2), 0d); } Random random = new Random(); for (int i = 0; i < 0xffff; ++i) { f1 = random.nextFloat(); f2 = random.nextFloat(); double expected = op.j(f1, f2); double result = op.n(f1, f2); if (expected != result) { fail(String.format("double " + op + "(%f, %f) failed - expected: %f, received: %f", f1, f2, expected, result)); } } } @Test public void testDoubleAddition() throws Exception { testDouble(new DoubleOp() { public double j(double f1, double f2) { return f1 + f2; } public double n(double f1, double f2) { return testlib.add_double(f1, f2); } @Override public String toString() { return "add"; } }); } @Test public void testDoubleSubtraction() throws Exception { testDouble(new DoubleOp() { public double j(double f1, double f2) { return f1 - f2; } public double n(double f1, double f2) { return testlib.sub_double(f1, f2); } @Override public String toString() { return "subtract"; } }); } @Test public void testDoubleMultiplication() throws Exception { testDouble(new DoubleOp() { public double j(double f1, double f2) { return f1 * f2; } public double n(double f1, double f2) { return testlib.mul_double(f1, f2); } @Override public String toString() { return "multiply"; } }); } @Test public void testDoubleDivision() throws Exception { testDouble(new DoubleOp() { public double j(double f1, double f2) { return f1 / f2; } public double n(double f1, double f2) { return testlib.div_double(f1, f2); } @Override public String toString() { return "divide"; } }); } static interface NativeLongOp { public long j(long f1, long f2); public long n(long f1, long f2); } private void testNativeLong(NativeLongOp op) throws Exception { long i1 = 1; long i2 = 2; assertEquals("NativeLong " + op + " failed", op.j(i1, i2), op.n(i1, i2)); for (int i = 0; i < 0xffff; ++i) { assertEquals("NativeLong + " + op + " failed", op.j(i, i2), op.n(i, i2)); } } @Test public void NativeLong_valueOf() { for (int i = -1000; i < 1000; ++i) { assertEquals("Incorrect value from valueOf(" + i+ ")", i, NativeLong.valueOf(i).intValue()); } for (long i = -1000; i < 1000; ++i) { assertEquals("Incorrect value from valueOf(" + i+ ")", i, NativeLong.valueOf(i).longValue()); } } @Test public void testNativeLongAddition() throws Exception { testNativeLong(new NativeLongOp() { public long j(long i1, long i2) { return i1 + i2; } public long n(long i1, long i2) { return testlib.add_long(NativeLong.valueOf(i1), NativeLong.valueOf(i2)).longValue(); } }); } }jaffl-0.5.9/test/com/kenai/jaffl/PointerTest.java000066400000000000000000000171411201747543600216550ustar00rootroot00000000000000 package com.kenai.jaffl; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class PointerTest { public PointerTest() { } public static interface TestLib { Pointer ptr_return_array_element(Pointer[] array, int index); void ptr_set_array_element(Pointer[] array, int index, Pointer value); byte ptr_ret_int8_t(Pointer p, int offset); short ptr_ret_int16_t(Pointer p, int offset); int ptr_ret_int32_t(Pointer p, int offset); long ptr_ret_int64_t(Pointer p, int offset); float ptr_ret_float(Pointer p, int offset); double ptr_ret_double(Pointer p, int offset); void ptr_set_int8_t(Pointer p, int offset, byte value); void ptr_set_int16_t(Pointer p, int offset, short value); void ptr_set_int32_t(Pointer p, int offset, int value); void ptr_set_int64_t(Pointer p, int offset, long value); void ptr_set_float(Pointer p, int offset, float value); void ptr_set_double(Pointer p, int offset, double value); Pointer ptr_malloc(int size); void ptr_free(Pointer ptr); } static TestLib testlib; public static interface Libc { Pointer calloc(int nmemb, int size); Pointer malloc(int size); void free(Pointer ptr); void cfree(Pointer ptr); } static Libc libc; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); libc = Library.loadLibrary("c", Libc.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // @Test // public void testGetPointerArrayArgument() throws Exception { // // Pointer MAGIC0 = new Pointer(0xdeadbeef); // Pointer MAGIC1 = new Pointer(0xcafebabe); // Pointer[] array = { MAGIC0, MAGIC1 }; // // assertEquals("Incorrect Pointer at index 0", MAGIC0, // testlib.ptr_return_array_element(array, 0)); // assertEquals("Incorrect Pointer at index 1", MAGIC1, // testlib.ptr_return_array_element(array, 1)); // } // @Test // public void testSetPointerArrayArgument() throws Exception { // // Pointer MAGIC0 = new Pointer(0xdeadbeef); // Pointer MAGIC1 = new Pointer(0xcafebabe); // Pointer[] array = { MAGIC0, MAGIC1 }; // // testlib.ptr_set_array_element(array, 0, MAGIC1); // testlib.ptr_set_array_element(array, 1, MAGIC0); // assertEquals("Pointer at index 0 not set", MAGIC1, array[0]); // assertEquals("Pointer at index 1 not set", MAGIC0, array[1]); // } // // @Test // public void testLongPointerValue() throws Exception { // long MAGIC0 = 0xdeadbeefL | (Address.SIZE == 64 ? (0xfee1deadL << 32) : 0L); // assertEquals("Pointer value not equal", MAGIC0, new Pointer(MAGIC0).nativeAddress()); // } static final int SIZE = 128; @Test public void testPointerSetByte() { Pointer p = testlib.ptr_malloc(SIZE); byte MAGIC = (byte) 0xFE; for (int i = 0; i < SIZE; ++i) { p.putByte(i, MAGIC); assertEquals("Byte not set at offset " + i, MAGIC, testlib.ptr_ret_int8_t(p, i)); } } @Test public void testPointerSetShort() { Pointer p = testlib.ptr_malloc(SIZE); short MAGIC = (short) 0xFEE1; for (int i = 0; i < (SIZE - 1); ++i) { p.putShort(i, MAGIC); assertEquals("Short not set at offset " + i, MAGIC, testlib.ptr_ret_int16_t(p, i)); } } @Test public void testPointerSetInt() { Pointer p = testlib.ptr_malloc(SIZE); int MAGIC = (int) 0xFEE1DEAD; for (int i = 0; i < (SIZE - 3); ++i) { p.putInt(i, MAGIC); assertEquals("Integer not set at offset " + i, MAGIC, testlib.ptr_ret_int32_t(p, i)); } } @Test public void testPointerSetLong() { Pointer p = testlib.ptr_malloc(SIZE); long MAGIC = 0xFEE1DEADABCDEF12L; for (int i = 0; i < (SIZE - 7); ++i) { p.putLong(i, MAGIC); assertEquals("Long not set at offset " + i, MAGIC, testlib.ptr_ret_int64_t(p, i)); } } @Test public void testPointerSetFloat() { Pointer p = testlib.ptr_malloc(SIZE); float MAGIC = (float) 0xFEE1DEADABCDEF12L; for (int i = 0; i < (SIZE - 7); ++i) { p.putFloat(i, MAGIC); assertEquals("Float not set at offset " + i, MAGIC, testlib.ptr_ret_float(p, i), 0f); } } @Test public void testPointerSetDouble() { Pointer p = testlib.ptr_malloc(SIZE); double MAGIC = (double) 0xFEE1DEADABCDEF12L; for (int i = 0; i < (SIZE - 7); ++i) { p.putDouble(i, MAGIC); assertEquals("Double not set at offset " + i, MAGIC, testlib.ptr_ret_double(p, i), 0d); } } @Test public void testPointerGetByte() { Pointer p = testlib.ptr_malloc(SIZE); byte MAGIC = (byte) 0xFE; for (int i = 0; i < SIZE; ++i) { testlib.ptr_set_int8_t(p, i, MAGIC); assertEquals("Byte not set at offset " + i, MAGIC, p.getByte(i)); } } @Test public void testPointerGetShort() { Pointer p = testlib.ptr_malloc(SIZE); short MAGIC = (short) 0xFEE1; for (int i = 0; i < SIZE - 1; ++i) { testlib.ptr_set_int16_t(p, i, MAGIC); assertEquals("Short not set at offset " + i, MAGIC, p.getShort(i)); } } @Test public void testPointerGetInt() { Pointer p = testlib.ptr_malloc(SIZE); int MAGIC = (int) 0xFEE1DEAD; for (int i = 0; i < SIZE - 3; ++i) { testlib.ptr_set_int32_t(p, i, MAGIC); assertEquals("Integer not set at offset " + i, MAGIC, p.getInt(i)); } } @Test public void testPointerGetLong() { Pointer p = testlib.ptr_malloc(SIZE); long MAGIC = 0xFEE1DEADABCDEF12L; for (int i = 0; i < SIZE - 7; ++i) { testlib.ptr_set_int64_t(p, i, MAGIC); assertEquals("Long not set at offset " + i, MAGIC, p.getLong(i)); } } @Test public void testPointerGetFloat() { Pointer p = testlib.ptr_malloc(SIZE); float MAGIC = (float) 0xFEE1DEADABCDEF12L; for (int i = 0; i < (SIZE - 7); ++i) { testlib.ptr_set_float(p, i, MAGIC); assertEquals("Float not set at offset " + i, MAGIC, p.getFloat(i), 0f); } } @Test public void testPointerGetDouble() { Pointer p = testlib.ptr_malloc(SIZE); double MAGIC = (double) 0xFEE1DEADABCDEF12L; for (int i = 0; i < (SIZE - 7); ++i) { testlib.ptr_set_double(p, i, MAGIC); assertEquals("Double not set at offset " + i, MAGIC, p.getDouble(i), 0d); } } @Test public void testMalloc() { Pointer[] pointers = new Pointer[1024]; for (int i = 0; i < pointers.length; ++i) { pointers[i] = testlib.ptr_malloc(SIZE); } for (int i = 0; i < pointers.length; ++i) { testlib.ptr_free(pointers[i]); } } @Test public void testLibcMalloc() { if (Platform.getPlatform().getOS() != Platform.OS.LINUX) { Pointer p = libc.malloc(SIZE); libc.free(p); } } }jaffl-0.5.9/test/com/kenai/jaffl/ResultConverterTest.java000066400000000000000000000051471201747543600234060ustar00rootroot00000000000000 package com.kenai.jaffl; import com.kenai.jaffl.mapper.FromNativeContext; import com.kenai.jaffl.mapper.FromNativeConverter; import com.kenai.jaffl.mapper.ToNativeConverter; import com.kenai.jaffl.mapper.TypeMapper; import java.util.HashMap; import java.util.Map; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class ResultConverterTest { public static final class TestType { public final String str; public TestType(String str) { this.str = str; } } public static interface TestLib { TestType strdup(CharSequence cs); void cfree(Pointer ptr); } public static interface Libc { Pointer calloc(int nmemb, int size); Pointer malloc(int size); void free(Pointer ptr); void cfree(Pointer ptr); } public static final class TestTypeResultConverter implements FromNativeConverter { public Class nativeType() { return Pointer.class; } public TestType fromNative(Pointer nativeValue, FromNativeContext context) { return new TestType(nativeValue.getString(0)); } } static final TypeMapper mapper = new TypeMapper() { public FromNativeConverter getFromNativeConverter(Class type) { if (TestType.class == type) { return new TestTypeResultConverter(); } return null; } public ToNativeConverter getToNativeConverter(Class type) { return null; } }; static TestLib testlib; public ResultConverterTest() { } @BeforeClass public static void setUpClass() throws Exception { Map options = new HashMap(); options.put(LibraryOption.TypeMapper, mapper); System.setProperty("jaffl.compiler.dump", "true"); testlib = Library.loadLibrary("c", TestLib.class, options); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} @Test public void testCustomResult() { final String MAGIC = "test"; TestType t = testlib.strdup(MAGIC); assertNotNull(t); assertEquals("contents not set", MAGIC, t.str); } } jaffl-0.5.9/test/com/kenai/jaffl/StringTest.java000066400000000000000000000052111201747543600214760ustar00rootroot00000000000000 package com.kenai.jaffl; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class StringTest { public StringTest() { } public static interface TestLib { boolean string_equals(CharSequence s1, byte[] s2); void string_set(StringBuffer dst, CharSequence src); void string_set(StringBuilder dst, CharSequence src); void string_concat(StringBuilder dst, CharSequence src); void string_concat(StringBuffer dst, CharSequence src); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void testReadOnlyString() { String MAGIC = "deadbeef\u0000"; assertTrue("String did not equal byte array", testlib.string_equals(MAGIC, MAGIC.getBytes())); assertTrue("StringBuffer did not equal byte array", testlib.string_equals(new StringBuffer(MAGIC), MAGIC.getBytes())); assertTrue("StringBuilder did not equal byte array", testlib.string_equals(new StringBuilder(MAGIC), MAGIC.getBytes())); } @Test public void testSetStringBuffer() { String MAGIC = "deadbeef"; StringBuffer buffer = new StringBuffer(1024); testlib.string_set(buffer, MAGIC); assertEquals("StringBuffer was not set", MAGIC, buffer.toString()); } @Test public void testSetStringBuilder() { String MAGIC = "deadbeef"; StringBuilder buffer = new StringBuilder(1024); testlib.string_set(buffer, MAGIC); assertEquals("StringBuilder was not set", MAGIC, buffer.toString()); } @Test public void testStringBufferAppend() { String ORIG = "test "; String MAGIC = "deadbeef"; StringBuffer buffer = new StringBuffer(1024); buffer.append(ORIG); testlib.string_concat(buffer, MAGIC); assertEquals("StringBuilder was not set", ORIG + MAGIC, buffer.toString()); } @Test public void testStringBuilderAppend() { String ORIG = "test "; String MAGIC = "deadbeef"; StringBuilder buffer = new StringBuilder(1024); buffer.append(ORIG); testlib.string_concat(buffer, MAGIC); assertEquals("StringBuilder was not set", ORIG + MAGIC, buffer.toString()); } }jaffl-0.5.9/test/com/kenai/jaffl/TstUtil.java000066400000000000000000000015411201747543600210020ustar00rootroot00000000000000 package com.kenai.jaffl; import java.nio.ByteBuffer; import java.util.Collections; import java.util.Map; public final class TstUtil { private TstUtil() {} public static final String getTestLibraryName() { return "test"; } public static interface HelperLib { Pointer ptr_from_buffer(ByteBuffer buf); } public static T loadTestLib(Class interfaceClass) { final Map options = Collections.emptyMap(); return loadTestLib(interfaceClass, options); } public static T loadTestLib(Class interfaceClass, Map options) { return Library.loadLibrary(getTestLibraryName(), interfaceClass, options); } public static Pointer getDirectBufferPointer(ByteBuffer buf) { return TstUtil.loadTestLib(HelperLib.class).ptr_from_buffer(buf); } } jaffl-0.5.9/test/com/kenai/jaffl/byref/000077500000000000000000000000001201747543600176355ustar00rootroot00000000000000jaffl-0.5.9/test/com/kenai/jaffl/byref/AddressByReferenceTest.java000066400000000000000000000056631201747543600250510ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import com.kenai.jaffl.Address; import com.kenai.jaffl.TstUtil; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class AddressByReferenceTest { public AddressByReferenceTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static interface TestLib { Address ptr_ret_pointer(AddressByReference p, int offset); void ptr_set_pointer(AddressByReference p, int offset, Address value); } public static interface TestLibInOnly { Address ptr_ret_pointer(@In AddressByReference p, int offset); void ptr_set_pointer(@In AddressByReference p, int offset, Address value); } public static interface TestLibOutOnly { Address ptr_ret_pointer(@Out AddressByReference p, int offset); void ptr_set_pointer(@Out AddressByReference p, int offset, Address value); } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} @Test public void dummy() {} @Test public void inOnlyReferenceSet() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final Address MAGIC = new Address(0xdeadbeef); AddressByReference ref = new AddressByReference(MAGIC); assertEquals("Wrong value passed", MAGIC, lib.ptr_ret_pointer(ref, 0)); } // @Test public void inOnlyIntReferenceNotWritten() { // TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); // final Address MAGIC = new Address(0xdeadbeef); // AddressByReference ref = new AddressByReference(MAGIC); // lib.ptr_set_pointer(ref, 0, new Address(0)); // assertEquals("Int reference written when it should not be", MAGIC, ref.getValue()); // } // @Test public void outOnlyIntReferenceNotRead() { // TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); // final Address MAGIC = new Address(0xdeadbeef); // AddressByReference ref = new AddressByReference(MAGIC); // assertTrue("Reference value passed to native code when it should not be", MAGIC != lib.ptr_ret_pointer(ref, 0)); // } // @Test public void outOnlyIntReferenceGet() { // TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); // final Address MAGIC = new Address(0xdeadbeef); // AddressByReference ref = new AddressByReference(new Address(0)); // lib.ptr_set_pointer(ref, 0, MAGIC); // assertEquals("Reference value not set", MAGIC, ref.getValue()); // } }jaffl-0.5.9/test/com/kenai/jaffl/byref/ByteByReferenceTest.java000066400000000000000000000050641201747543600243620ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import com.kenai.jaffl.TstUtil; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class ByteByReferenceTest { public ByteByReferenceTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static interface TestLib { byte ptr_ret_int8_t(ByteByReference p, int offset); void ptr_set_int_t(ByteByReference p, int offset, byte value); } public static interface TestLibInOnly { byte ptr_ret_int8_t(@In ByteByReference p, int offset); void ptr_set_int8_t(@In ByteByReference p, int offset, byte value); } public static interface TestLibOutOnly { byte ptr_ret_int8_t(@Out ByteByReference p, int offset); void ptr_set_int8_t(@Out ByteByReference p, int offset, byte value); } @Test public void inOnlyReferenceSet() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final byte MAGIC = (byte) 0xef; ByteByReference ref = new ByteByReference(MAGIC); assertEquals("Wrong value passed", MAGIC, lib.ptr_ret_int8_t(ref, 0)); } @Test public void inOnlyByteReferenceNotWritten() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final byte MAGIC = (byte) 0xef; ByteByReference ref = new ByteByReference(MAGIC); lib.ptr_set_int8_t(ref, 0, (byte) 0); assertEquals("Int reference written when it should not be", Byte.valueOf(MAGIC), ref.getValue()); } @Test public void outOnlyByteReferenceNotRead() { TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); final byte MAGIC = (byte) 0xef; ByteByReference ref = new ByteByReference(MAGIC); assertTrue("Reference value passed to native code when it should not be", MAGIC != lib.ptr_ret_int8_t(ref, 0)); } @Test public void outOnlyByteReferenceGet() { TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); final byte MAGIC = (byte) 0xef; ByteByReference ref = new ByteByReference((byte) 0); lib.ptr_set_int8_t(ref, 0, MAGIC); assertEquals("Reference value not set", Byte.valueOf(MAGIC), ref.getValue()); } }jaffl-0.5.9/test/com/kenai/jaffl/byref/IntByReferenceTest.java000066400000000000000000000050161201747543600242060ustar00rootroot00000000000000 package com.kenai.jaffl.byref; import com.kenai.jaffl.TstUtil; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class IntByReferenceTest { public IntByReferenceTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static interface TestLib { int ptr_ret_int32_t(IntByReference p, int offset); void ptr_set_int32_t(IntByReference p, int offset, int value); } public static interface TestLibInOnly { int ptr_ret_int32_t(@In IntByReference p, int offset); void ptr_set_int32_t(@In IntByReference p, int offset, int value); } public static interface TestLibOutOnly { int ptr_ret_int32_t(@Out IntByReference p, int offset); void ptr_set_int32_t(@Out IntByReference p, int offset, int value); } @Test public void inOnlyIntReferenceSet() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final int MAGIC = 0xdeadbeef; IntByReference ref = new IntByReference(MAGIC); assertEquals("Wrong value passed", MAGIC, lib.ptr_ret_int32_t(ref, 0)); } @Test public void inOnlyIntReferenceNotWritten() { TestLibInOnly lib = TstUtil.loadTestLib(TestLibInOnly.class); final int MAGIC = 0xdeadbeef; IntByReference ref = new IntByReference(MAGIC); lib.ptr_set_int32_t(ref, 0, 0); assertEquals("Int reference written when it should not be", Integer.valueOf(MAGIC), ref.getValue()); } @Test public void outOnlyIntReferenceNotRead() { TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); final int MAGIC = 0xdeadbeef; IntByReference ref = new IntByReference(MAGIC); assertTrue("Reference value passed to native code when it should not be", MAGIC != lib.ptr_ret_int32_t(ref, 0)); } @Test public void outOnlyIntReferenceGet() { TestLibOutOnly lib = TstUtil.loadTestLib(TestLibOutOnly.class); final int MAGIC = 0xdeadbeef; IntByReference ref = new IntByReference(0); lib.ptr_set_int32_t(ref, 0, MAGIC); assertEquals("Reference value not set", Integer.valueOf(MAGIC), ref.getValue()); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/000077500000000000000000000000001201747543600200525ustar00rootroot00000000000000jaffl-0.5.9/test/com/kenai/jaffl/struct/AlignmentTest.java000066400000000000000000000023531201747543600234760ustar00rootroot00000000000000/* * To change this template, choose Tools | Templates * and open the template in the editor. */ package com.kenai.jaffl.struct; import com.kenai.jaffl.Platform; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class AlignmentTest { public AlignmentTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} class PointerStruct extends Struct { public final Signed8 s8 = new Signed8(); public final Pointer p = new Pointer(); } @Test public void alignPointer() throws Throwable { PointerStruct s = new PointerStruct(); final int SIZE = Platform.getPlatform().addressSize() == 32 ? 8 : 16; assertEquals("Incorrect pointer field alignment", SIZE, StructUtil.getSize(s)); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/ArrayTest.java000066400000000000000000000043601201747543600226360ustar00rootroot00000000000000 package com.kenai.jaffl.struct; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.TstUtil; import com.kenai.jaffl.provider.AbstractArrayMemoryIO; import com.kenai.jaffl.provider.DelegatingMemoryIO; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class ArrayTest { public ArrayTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static final class s8 extends Struct { public final Signed8 s8 = new Signed8(); } public static final class s32 extends Struct { public final Signed8 s8 = new Signed8(); } public static interface TestLib { byte ptr_ret_int8_t(s8[] s, int index); } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} @Test public void s8Array() { TestLib testlib = TstUtil.loadTestLib(TestLib.class); s8[] array = StructUtil.newArray(s8.class, 10); assertEquals("Array length incorrect", 10, array.length); for (int i = 0; i < array.length; ++i) { assertNotNull("Memory not allocated for array member", StructUtil.getMemoryIO(array[i])); } MemoryIO io = ((DelegatingMemoryIO) StructUtil.getMemoryIO(array[0])).getDelegatedMemoryIO(); for (int i = 0; i < array.length; ++i) { assertSame("Different backing memory", io, ((DelegatingMemoryIO) StructUtil.getMemoryIO(array[i])).getDelegatedMemoryIO()); } if (io instanceof AbstractArrayMemoryIO) { assertEquals("Incorrect size", array.length, ((AbstractArrayMemoryIO)io).length()); } for (int i = 0; i < array.length; ++i) { array[i].s8.set((byte) i); } for (int i = 0; i < array.length; ++i) { assertEquals("Incorrect value written to native memory at index " + i, (byte) i, testlib.ptr_ret_int8_t(array, i)); } } }jaffl-0.5.9/test/com/kenai/jaffl/struct/AsciiStringFieldTest.java000066400000000000000000000050111201747543600247350ustar00rootroot00000000000000/* * Copyright (C) 2008 Wayne Meissner * * This file is part of jffi. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see . */ package com.kenai.jaffl.struct; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import com.kenai.jaffl.annotations.Pinned; import com.kenai.jaffl.annotations.Transient; import com.kenai.jaffl.TstUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class AsciiStringFieldTest { public AsciiStringFieldTest() { } public class StringFieldStruct extends Struct { public final String string = new AsciiString(32); } public static interface TestLib { // This makes use of the string being the first field in the struct int string_equals(@Pinned @In @Transient StringFieldStruct s1, String s2); int copyByteBuffer(@Pinned @Out StringFieldStruct dst, @In byte[] src, int len); int copyByteBuffer(@Pinned @Out byte[] dst, @Pinned @In @Transient StringFieldStruct src, int len); int copyByteBuffer(@Pinned @Out StringBuilder dst, @Pinned @In @Transient StringFieldStruct src, int len); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void stringFieldFirstInStruct() { StringFieldStruct s = new StringFieldStruct(); final String MAGIC = "test"; s.string.set(MAGIC); StringBuilder tmp = new StringBuilder(s.string.length()); testlib.copyByteBuffer(tmp, s, s.string.length()); assertEquals("String not put into struct correctly", MAGIC, tmp.toString()); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/EnumTest.java000066400000000000000000000154331201747543600224670ustar00rootroot00000000000000/* * Copyright (C) 2008 Wayne Meissner * * This file is part of jffi. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see . */ package com.kenai.jaffl.struct; import com.kenai.jaffl.util.EnumMapper; import com.kenai.jaffl.TstUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class EnumTest { public EnumTest() { } public enum TestEnum { ZERO, B, MAGIC; } public class struct1 extends Struct { public final Enum8 b = new Enum8(TestEnum.class); public final Enum16 s = new Enum16(TestEnum.class); public final Enum32 i = new Enum32(TestEnum.class); public final Enum64 i64 = new Enum64(TestEnum.class); public final EnumLong l = new EnumLong(TestEnum.class); } public static interface TestLib { byte struct_field_Signed8(struct1 s); short struct_field_Signed16(struct1 s); int struct_field_Signed32(struct1 s); long struct_field_Signed64(struct1 s); float struct_field_Float32(struct1 s); double struct_field_Float64(struct1 s); short struct_align_Signed16(Int16Align s); int struct_align_Signed32(Int32Align s); long struct_align_Signed64(Int64Align s); long struct_align_SignedLong(LongAlign s); // float struct_align_Float32(Float32Align s); // double struct_align_Float64(Float64Align s); // void struct_set_string(struct1 s, String string); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } // TODO add test methods here. // The methods must be annotated with annotation @Test. For example: // // @Test // public void hello() {} public static class Int16Align extends Struct { public final Enum8 first = new Enum8(TestEnum.class); public final Enum16 s = new Enum16(TestEnum.class); } public static class Int32Align extends Struct { public final Enum8 first = new Enum8(TestEnum.class); public final Enum32 i = new Enum32(TestEnum.class); } public static class Int64Align extends Struct { public final Enum8 first = new Enum8(TestEnum.class); public final Enum64 l = new Enum64(TestEnum.class); } public static class LongAlign extends Struct { public final Enum8 first = new Enum8(TestEnum.class); public final EnumLong l = new EnumLong(TestEnum.class); } @Test public void testInt8InitialValue() { struct1 s = new struct1(); assertEquals("default value not zero", TestEnum.ZERO, s.b.get()); } @Test public void testInt8Set() { struct1 s = new struct1(); final TestEnum MAGIC = TestEnum.MAGIC; s.b.set(MAGIC); assertEquals("Byte value not set correctly", MAGIC, s.b.get()); } @Test public void byteField() { final byte MAGIC = (byte) EnumMapper.getInstance().intValue(TestEnum.MAGIC); struct1 s = new struct1(); s.b.set(TestEnum.MAGIC); assertEquals("byte field not set", MAGIC, testlib.struct_field_Signed8(s)); s.b.set(TestEnum.ZERO); assertEquals("byte field not cleared", (byte) 0, testlib.struct_field_Signed8(s)); } @Test public void shortField() { final short MAGIC = (short) EnumMapper.getInstance().intValue(TestEnum.MAGIC); struct1 s = new struct1(); s.s.set(TestEnum.MAGIC); assertEquals("short field not set", MAGIC, testlib.struct_field_Signed16(s)); s.s.set(TestEnum.ZERO); assertEquals("short field not cleared", (short) 0, testlib.struct_field_Signed16(s)); } @Test public void intField() { final int MAGIC = EnumMapper.getInstance().intValue(TestEnum.MAGIC); struct1 s = new struct1(); s.i.set(TestEnum.MAGIC); assertEquals("int field not set", MAGIC, testlib.struct_field_Signed32(s)); s.i.set(TestEnum.ZERO); assertEquals("int field not cleared", 0, testlib.struct_field_Signed32(s)); } @Test public void longField() { final long MAGIC = EnumMapper.getInstance().intValue(TestEnum.MAGIC); struct1 s = new struct1(); s.i64.set(TestEnum.MAGIC); assertEquals("long field not set", MAGIC, testlib.struct_field_Signed64(s)); s.i64.set(TestEnum.ZERO); assertEquals("long field not cleared", 0L, testlib.struct_field_Signed64(s)); } @Test public void alignInt16Field() { final short MAGIC = (short) EnumMapper.getInstance().intValue(TestEnum.MAGIC); Int16Align s = new Int16Align(); s.s.set(TestEnum.MAGIC); assertEquals("short field not aligned", MAGIC, testlib.struct_align_Signed16(s)); } @Test public void alignSigned32Field() { final int MAGIC = (int) EnumMapper.getInstance().intValue(TestEnum.MAGIC); Int32Align s = new Int32Align(); s.i.set(TestEnum.MAGIC); assertEquals("int field not aligned", MAGIC, testlib.struct_align_Signed32(s)); } @Test public void alignSigned64Field() { final long MAGIC = EnumMapper.getInstance().intValue(TestEnum.MAGIC); Int64Align s = new Int64Align(); s.l.set(TestEnum.MAGIC); assertEquals("long field not aligned", MAGIC, testlib.struct_align_Signed64(s)); } @Test public void alignSignedLongField() { final long MAGIC = EnumMapper.getInstance().intValue(TestEnum.MAGIC); LongAlign s = new LongAlign(); s.l.set(TestEnum.MAGIC); assertEquals("native long field not aligned", MAGIC, testlib.struct_align_SignedLong(s)); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/PaddingTest.java000066400000000000000000000016511201747543600231260ustar00rootroot00000000000000 package com.kenai.jaffl.struct; import com.kenai.jaffl.Type; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; public class PaddingTest { public PaddingTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } static final class LongPadding extends Struct { public final Signed8 s8 = new Signed8(); public final Padding pad = new Padding(Type.SLONG, 3); } @Test public void longPadding() throws Throwable { final int SIZE = Type.SLONG.alignment() + (Type.SLONG.size() * 3); assertEquals("incorrect size", SIZE, StructUtil.getSize(new LongPadding())); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/StructureTest.java000066400000000000000000000235271201747543600235660ustar00rootroot00000000000000/* * Copyright (C) 2008 Wayne Meissner * * This file is part of jffi. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see . */ package com.kenai.jaffl.struct; import com.kenai.jaffl.MemoryIO; import com.kenai.jaffl.TstUtil; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class StructureTest { public StructureTest() { } public static interface TestLib { byte struct_field_Signed8(struct1 s); short struct_field_Signed16(struct1 s); int struct_field_Signed32(struct1 s); long struct_field_Signed64(struct1 s); float struct_field_Float32(struct1 s); double struct_field_Float64(struct1 s); short struct_align_Signed16(Int16Align s); int struct_align_Signed32(Int32Align s); long struct_align_Signed64(Int64Align s); long struct_align_SignedLong(LongAlign s); struct1 struct_make_struct(byte b, short s, int i, long ll, float f, double d); // float struct_align_Float32(Float32Align s); // double struct_align_Float64(Float64Align s); // void struct_set_string(struct1 s, String string); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static class struct1 extends Struct { public final Signed8 b = new Signed8(); public final Signed16 s = new Signed16(); public final Signed32 i = new Signed32(); public final Signed64 i64 = new Signed64(); public final SignedLong l = new SignedLong(); public final Float f = new Float(); public final Double d = new Double(); } public static class Int16Align extends Struct { public final Signed8 first = new Signed8(); public final Signed16 s = new Signed16(); } public static class Int32Align extends Struct { public final Signed8 first = new Signed8(); public final Signed32 i = new Signed32(); } public static class Int64Align extends Struct { public final Signed8 first = new Signed8(); public final Signed64 l = new Signed64(); } public static class LongAlign extends Struct { public final Signed8 first = new Signed8(); public final SignedLong l = new SignedLong(); } @Test public void testInt8InitialValue() { struct1 s = new struct1(); assertEquals("default value not zero", (byte) 0, s.b.get()); } @Test public void testInt8Set() { struct1 s = new struct1(); final byte MAGIC = (byte) 0xfe; s.b.set(MAGIC); assertEquals("Byte value not set correctly", MAGIC, s.b.get()); } @Test public void byteField() { final byte MAGIC = (byte) 0xbe; struct1 s = new struct1(); s.b.set(MAGIC); assertEquals("byte field not set", MAGIC, testlib.struct_field_Signed8(s)); s.b.set((byte) 0); assertEquals("byte field not cleared", (byte) 0, testlib.struct_field_Signed8(s)); } @Test public void shortField() { final short MAGIC = (short) 0xbeef; struct1 s = new struct1(); s.s.set(MAGIC); assertEquals("short field not set", MAGIC, testlib.struct_field_Signed16(s)); s.s.set((short) 0); assertEquals("short field not cleared", (short) 0, testlib.struct_field_Signed16(s)); } @Test public void intField() { final int MAGIC = 0xdeadbeef; struct1 s = new struct1(); s.i.set(MAGIC); assertEquals("int field not set", MAGIC, testlib.struct_field_Signed32(s)); s.i.set(0); assertEquals("int field not cleared", 0, testlib.struct_field_Signed32(s)); } @Test public void longField() { final long MAGIC = 0x1234deadbeef5678L; struct1 s = new struct1(); s.i64.set(MAGIC); assertEquals("long field not set", MAGIC, testlib.struct_field_Signed64(s)); s.i64.set(0); assertEquals("long field not cleared", 0L, testlib.struct_field_Signed64(s)); } @Test public void alignInt16Field() { final short MAGIC = (short) 0xbeef; Int16Align s = new Int16Align(); s.s.set(MAGIC); assertEquals("short field not aligned", MAGIC, testlib.struct_align_Signed16(s)); } @Test public void alignSigned32Field() { final int MAGIC = (int) 0xdeadbeef; Int32Align s = new Int32Align(); s.i.set(MAGIC); assertEquals("int field not aligned", MAGIC, testlib.struct_align_Signed32(s)); } @Test public void alignSigned64Field() { final long MAGIC = 0x1234deadbeef5678L; Int64Align s = new Int64Align(); s.l.set(MAGIC); assertEquals("long field not aligned", MAGIC, testlib.struct_align_Signed64(s)); } @Test public void alignSignedLongField() { final long MAGIC = 0xdeadbeef; LongAlign s = new LongAlign(); s.l.set(MAGIC); assertEquals("native long field not aligned", MAGIC, testlib.struct_align_SignedLong(s)); } @Test public void returnStructAddress() throws Throwable { final byte B = 0x11; final short S = 0x2222; final int I = 0x33333333; final long L = 0x4444444444444444L; final float F = (float) 0x55555555; final double D = (double) 0x6666666666666666L; struct1 s = testlib.struct_make_struct(B, S, I, L, F, D); assertEquals("Incorrect byte value in struct", B, s.b.get()); assertEquals("Incorrect short value in struct", S, s.s.get()); assertEquals("Incorrect int value in struct", I, s.i.get()); assertEquals("Incorrect int64 value in struct", L, s.i64.get()); assertEquals("Incorrect float value in struct", F, s.f.get(), 0f); assertEquals("Incorrect double value in struct", D, s.d.get(), 0d); } private static final class ArrayTest extends Struct { public final Signed8[] byteArray = array(new Signed8[8]); } @Test public void arrayMember() { ArrayTest s = new ArrayTest(); assertEquals("First element not at correct offset", 0L, s.byteArray[0].offset()); assertEquals("Second element not at correct offset", 1L, s.byteArray[1].offset()); assertEquals("Last element not at correct offset", 7L, s.byteArray[7].offset()); } private static final class Unsigned8Test extends Struct { public final Unsigned8 u8 = new Unsigned8(); } @Test public void unsigned8() { Unsigned8Test s = new Unsigned8Test(); final short MAGIC = (short) Byte.MAX_VALUE + 1; s.u8.set(MAGIC); assertEquals("Incorrect unsigned byte value", MAGIC, s.u8.shortValue()); } private static final class Unsigned16Test extends Struct { public final Unsigned16 u16 = new Unsigned16(); } @Test public void unsigned16() { Unsigned16Test s = new Unsigned16Test(); final int MAGIC = (int) Short.MAX_VALUE + 1; s.u16.set(MAGIC); assertEquals("Incorrect unsigned short value", MAGIC, s.u16.intValue()); } private static final class Unsigned32Test extends Struct { public final Unsigned32 u32 = new Unsigned32(); } @Test public void unsigned32() { Unsigned32Test s = new Unsigned32Test(); final long MAGIC = (long) Integer.MAX_VALUE + 1; s.u32.set(MAGIC); assertEquals("Incorrect unsigned int value", MAGIC, s.u32.longValue()); } private static final class Unsigned64Test extends Struct { public final Unsigned64 u64 = new Unsigned64(); } @Test public void unsigned64() { Unsigned64Test s = new Unsigned64Test(); final long MAGIC = Long.MAX_VALUE; s.u64.set(MAGIC); assertEquals("Incorrect unsigned long long value", MAGIC, s.u64.longValue()); // Just make sure that an Unsigned64 doesn't do anything weird with negative values s.u64.set(Long.MIN_VALUE); assertEquals("Incorrect unsigned long long value", Long.MIN_VALUE, s.u64.longValue()); } private static final class UnsignedLongTest extends Struct { public final UnsignedLong ul = new UnsignedLong(); } @Test public void unsignedLong() { UnsignedLongTest s = new UnsignedLongTest(); final long MAGIC = (long) Integer.MAX_VALUE + 1; s.ul.set(MAGIC); assertEquals("Incorrect unsigned long value", MAGIC, s.ul.longValue()); } private class InnerStruct extends Struct { public final Signed8 s8 = new Signed8(); } private class InnerTest extends Struct { public final Signed32 i32 = new Signed32(); public final InnerStruct s = inner(new InnerStruct()); } @Test public void innerStruct() { InnerTest t = new InnerTest(); MemoryIO io = StructUtil.getMemoryIO(t); io.putInt(0, 0xdeadbeef); io.putByte(4, (byte) 0x12); assertEquals("incorrect inner struct field value", (byte) 0x12, t.s.s8.get()); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/UTF8StringFieldTest.java000066400000000000000000000064171201747543600244460ustar00rootroot00000000000000/* * Copyright (C) 2008 Wayne Meissner * * This file is part of jffi. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see . */ package com.kenai.jaffl.struct; import com.kenai.jaffl.TstUtil; import com.kenai.jaffl.annotations.In; import com.kenai.jaffl.annotations.Out; import com.kenai.jaffl.annotations.Pinned; import com.kenai.jaffl.annotations.Transient; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * * @author wayne */ public class UTF8StringFieldTest { public UTF8StringFieldTest() { } public class StringFieldStruct extends Struct { public final UTF8String string = new UTF8String(32); } public static interface TestLib { // This makes use of the string being the first field in the struct int string_equals(@Pinned @In @Transient StringFieldStruct s1, String s2); int copyByteBuffer(@Pinned @Out StringFieldStruct dst, @In byte[] src, int len); int copyByteBuffer(@Pinned @Out byte[] dst, @Pinned @In @Transient StringFieldStruct src, int len); int copyByteBuffer(@Pinned @Out StringBuilder dst, @Pinned @In @Transient StringFieldStruct src, int len); } static TestLib testlib; @BeforeClass public static void setUpClass() throws Exception { testlib = TstUtil.loadTestLib(TestLib.class); } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } @Test public void stringFieldFirstInStruct() { StringFieldStruct s = new StringFieldStruct(); final String MAGIC = "test"; s.string.set(MAGIC); StringBuilder tmp = new StringBuilder(s.string.length()); testlib.copyByteBuffer(tmp, s, s.string.length()); assertEquals("String not put into struct correctly", MAGIC, tmp.toString()); } private final class SockaddrUnix extends Struct { private final Signed8 sun_len = new Signed8(); private final Signed8 sun_family = new Signed8(); private final UTF8String sun_path = new UTF8String(100); } @Test public void SockaddrUnix() { final int SUN_LEN = 1; final int SUN_FAM = 2; final String SUN_PATH = "test"; SockaddrUnix s = new SockaddrUnix(); s.sun_len.set(SUN_LEN); s.sun_family.set(SUN_FAM); s.sun_path.set(SUN_PATH); assertEquals("Incorrect sun_len value", SUN_LEN, s.sun_len.intValue()); assertEquals("Incorrect sun_fam value", SUN_FAM, s.sun_family.intValue()); assertEquals("Incorrect sun_path value", SUN_PATH, s.sun_path.toString()); } }jaffl-0.5.9/test/com/kenai/jaffl/struct/UnionTest.java000066400000000000000000000076771201747543600226660ustar00rootroot00000000000000/* * Copyright (C) 2008 Wayne Meissner * * This file is part of jffi. * * This code is free software: you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License version 3 only, as * published by the Free Software Foundation. * * This code 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 Lesser General Public License * version 3 for more details. * * You should have received a copy of the GNU Lesser General Public License * version 3 along with this work. If not, see . */ package com.kenai.jaffl.struct; import java.nio.ByteOrder; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import static org.junit.Assert.*; /** * */ public class UnionTest { public UnionTest() { } @BeforeClass public static void setUpClass() throws Exception { } @AfterClass public static void tearDownClass() throws Exception { } @Before public void setUp() { } @After public void tearDown() { } public static final class union extends Union { public final Signed8 s8 = new Signed8(); public final Unsigned8 u8 = new Unsigned8(); public final Signed16 s16 = new Signed16(); public final Unsigned16 u16 = new Unsigned16(); public final Signed32 s32 = new Signed32(); public final Unsigned32 u32 = new Unsigned32(); public final Signed64 s64 = new Signed64(); public final Unsigned64 u64 = new Unsigned64(); } @Test public void offsetTest() { union u = new union(); assertEquals("Not at offset 0", 0L, u.s8.offset()); assertEquals("Not at offset 0", 0L, u.u8.offset()); assertEquals("Not at offset 0", 0L, u.s16.offset()); assertEquals("Not at offset 0", 0L, u.u16.offset()); assertEquals("Not at offset 0", 0L, u.s32.offset()); assertEquals("Not at offset 0", 0L, u.s32.offset()); assertEquals("Not at offset 0", 0L, u.s64.offset()); assertEquals("Not at offset 0", 0L, u.u64.offset()); } @Test public void s8s16() { union u = new union(); final int MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xef00 : 0x00ef; u.s16.set((short) MAGIC); assertEquals("Wrong value", (byte) 0xef, u.s8.get()); } @Test public void s8s32() { union u = new union(); final int MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xef000000 : 0x000000ef; u.s32.set(MAGIC); assertEquals("Wrong value", (byte) 0xef, u.s8.get()); } @Test public void s16s32() { union u = new union(); final int MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xdead0000 : 0x0000dead; u.s32.set(MAGIC); assertEquals("Wrong value", (short) 0xdead, u.s16.get()); } @Test public void s8s64() { union u = new union(); final long MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xef00000000000000L : 0xefL; u.s64.set(MAGIC); assertEquals("Wrong value", (byte) 0xef, u.s8.get()); } @Test public void s16s64() { union u = new union(); final long MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xbeef000000000000L : 0xbeefL; u.s64.set(MAGIC); assertEquals("Wrong value", (short) 0xbeef, u.s16.get()); } @Test public void s32s64() { union u = new union(); final long MAGIC = ByteOrder.nativeOrder().equals(ByteOrder.BIG_ENDIAN) ? 0xdeadbeef00000000L : 0xdeadbeefL; u.s64.set(MAGIC); assertEquals("Wrong value", 0xdeadbeef, u.s32.get()); } }