001/* 002 * BridJ - Dynamic and blazing-fast native interop for Java. 003 * http://bridj.googlecode.com/ 004 * 005 * Copyright (c) 2010-2013, Olivier Chafik (http://ochafik.com/) 006 * All rights reserved. 007 * 008 * Redistribution and use in source and binary forms, with or without 009 * modification, are permitted provided that the following conditions are met: 010 * 011 * * Redistributions of source code must retain the above copyright 012 * notice, this list of conditions and the following disclaimer. 013 * * Redistributions in binary form must reproduce the above copyright 014 * notice, this list of conditions and the following disclaimer in the 015 * documentation and/or other materials provided with the distribution. 016 * * Neither the name of Olivier Chafik nor the 017 * names of its contributors may be used to endorse or promote products 018 * derived from this software without specific prior written permission. 019 * 020 * THIS SOFTWARE IS PROVIDED BY OLIVIER CHAFIK AND CONTRIBUTORS ``AS IS'' AND ANY 021 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 022 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 023 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY 024 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 025 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 026 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 027 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 029 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 030 */ 031package org.bridj; 032 033import java.lang.reflect.ParameterizedType; 034import java.lang.reflect.Type; 035import java.util.*; 036import java.nio.*; 037import java.util.concurrent.ConcurrentHashMap; 038import org.bridj.util.Utils; 039 040/** 041 * Helper class that knows how to read/write data from/to a {@link Pointer}.<br> 042 * End users don't need to use this class directly as ({@link Pointer} lets you work with {@link java.lang.reflect.Type} and {@link Class}). 043 * @author Olivier 044 */ 045public abstract class PointerIO<T> { 046 final Type targetType; 047 final Class<?> typedPointerClass; 048 final int targetSize, targetAlignment = -1; 049 050 public PointerIO(Type targetType, int targetSize, Class<?> typedPointerClass) { 051 this.targetType = targetType; 052 this.targetSize = targetSize; 053 this.typedPointerClass = typedPointerClass; 054 } 055 abstract T get(Pointer<T> pointer, long index); 056 abstract void set(Pointer<T> pointer, long index, T value); 057 public Object getArray(Pointer<T> pointer, long byteOffset, int length) { 058 return pointer.offset(byteOffset).toArray(length); 059 } 060 public <B extends Buffer> B getBuffer(Pointer<T> pointer, long byteOffset, int length) { 061 throw new UnsupportedOperationException("Cannot create a Buffer instance of elements of type " + getTargetType()); 062 } 063 public void setArray(Pointer<T> pointer, long byteOffset, Object array) { 064 Object[] a = (Object[])array; 065 for (int i = 0, n = a.length; i < n; i++) 066 set(pointer, i, (T)a[i]); 067 } 068 069 public T castTarget(long peer) { 070 throw new UnsupportedOperationException("Cannot cast pointer to " + targetType); 071 } 072 073 PointerIO<Pointer<T>> getReferenceIO() { 074 return new CommonPointerIOs.PointerPointerIO<T>(this); 075 } 076 public long getTargetSize() { 077 return targetSize; 078 } 079 public long getTargetAlignment() { 080 return targetAlignment < 0 ? getTargetSize() : targetAlignment; 081 } 082 public boolean isTypedPointer() { 083 return typedPointerClass != null; 084 } 085 public Class<?> getTypedPointerClass() { 086 return typedPointerClass; 087 } 088 public Type getTargetType() { 089 return targetType; 090 } 091 092 static Class<?> getClass(Type type) { 093 if (type instanceof Class<?>) 094 return (Class<?>)type; 095 if (type instanceof ParameterizedType) 096 return getClass(((ParameterizedType)type).getRawType()); 097 return null; 098 } 099 100 private static final PointerIO<Pointer> PointerIO = getPointerInstance((PointerIO)null); 101 102 public static <T> PointerIO<Pointer<T>> getPointerInstance(Type target) { 103 return getPointerInstance((PointerIO<T>)getInstance(target)); 104 } 105 public static <T> PointerIO<Pointer<T>> getPointerInstance(PointerIO<T> targetIO) { 106 return new CommonPointerIOs.PointerPointerIO<T>(targetIO); 107 } 108 public static <T> PointerIO<Pointer<T>> getArrayInstance(PointerIO<T> targetIO, long[] dimensions, int iDimension) { 109 return new CommonPointerIOs.PointerArrayIO<T>(targetIO, dimensions, iDimension); 110 } 111 112 static <T> PointerIO<T> getArrayIO(Object array) { 113 if (array instanceof int[]) 114 return (PointerIO)CommonPointerIOs.intIO; 115 if (array instanceof long[]) 116 return (PointerIO)CommonPointerIOs.longIO; 117 if (array instanceof short[]) 118 return (PointerIO)CommonPointerIOs.shortIO; 119 if (array instanceof byte[]) 120 return (PointerIO)CommonPointerIOs.byteIO; 121 if (array instanceof char[]) 122 return (PointerIO)CommonPointerIOs.charIO; 123 if (array instanceof float[]) 124 return (PointerIO)CommonPointerIOs.floatIO; 125 if (array instanceof double[]) 126 return (PointerIO)CommonPointerIOs.doubleIO; 127 if (array instanceof boolean[]) 128 return (PointerIO)CommonPointerIOs.booleanIO; 129 return PointerIO.getInstance(array.getClass().getComponentType()); 130 } 131 132 private static final ConcurrentHashMap<StructIO, PointerIO<?>> structIOs = new ConcurrentHashMap<StructIO, PointerIO<?>>(); 133 public static <S extends StructObject> PointerIO<S> getInstance(StructIO s) { 134 PointerIO io = structIOs.get(s); 135 if (io == null) { 136 io = new CommonPointerIOs.StructPointerIO(s); 137 PointerIO previousIO = structIOs.putIfAbsent(s, io); 138 if (previousIO != null) 139 io = previousIO; 140 } 141 return io; 142 } 143 private static final ConcurrentHashMap<Type, PointerIO<?>> ios = new ConcurrentHashMap<Type, PointerIO<?>>(); 144 static { 145 ios.put(Pointer.class, PointerIO); 146 ios.put(SizeT.class, CommonPointerIOs.SizeTIO); 147 ios.put(TimeT.class, CommonPointerIOs.TimeTIO); 148 ios.put(CLong.class, CommonPointerIOs.CLongIO); 149 150 { 151 PointerIO io = CommonPointerIOs.intIO; 152 ios.put(Integer.TYPE, io); 153 ios.put(Integer.class, io); 154 } 155 { 156 PointerIO io = CommonPointerIOs.longIO; 157 ios.put(Long.TYPE, io); 158 ios.put(Long.class, io); 159 } 160 { 161 PointerIO io = CommonPointerIOs.shortIO; 162 ios.put(Short.TYPE, io); 163 ios.put(Short.class, io); 164 } 165 { 166 PointerIO io = CommonPointerIOs.byteIO; 167 ios.put(Byte.TYPE, io); 168 ios.put(Byte.class, io); 169 } 170 { 171 PointerIO io = CommonPointerIOs.charIO; 172 ios.put(Character.TYPE, io); 173 ios.put(Character.class, io); 174 } 175 { 176 PointerIO io = CommonPointerIOs.floatIO; 177 ios.put(Float.TYPE, io); 178 ios.put(Float.class, io); 179 } 180 { 181 PointerIO io = CommonPointerIOs.doubleIO; 182 ios.put(Double.TYPE, io); 183 ios.put(Double.class, io); 184 } 185 { 186 PointerIO io = CommonPointerIOs.booleanIO; 187 ios.put(Boolean.TYPE, io); 188 ios.put(Boolean.class, io); 189 } 190 } 191 public static <P> PointerIO<P> getInstance(Type type) { 192 if (type == null) 193 return null; 194 195 PointerIO io = ios.get(type); 196 if (io == null) { 197 final Class<?> cl = Utils.getClass(type); 198 if (cl != null) { 199 if (cl == Pointer.class) 200 io = getPointerInstance(((ParameterizedType)type).getActualTypeArguments()[0]); 201 else if (StructObject.class.isAssignableFrom(cl)) 202 io = getInstance(StructIO.getInstance((Class)cl, type)); 203 else if (Callback.class.isAssignableFrom(cl)) 204 io = new CommonPointerIOs.CallbackPointerIO(cl); 205 else if (NativeObject.class.isAssignableFrom(cl)) 206 io = new CommonPointerIOs.NativeObjectPointerIO(type); 207 else if (IntValuedEnum.class.isAssignableFrom(cl)) { 208 if (type instanceof ParameterizedType) { 209 Type enumType = ((ParameterizedType)type).getActualTypeArguments()[0]; 210 if (enumType instanceof Class) 211 io = new CommonPointerIOs.IntValuedEnumPointerIO((Class)enumType); 212 } 213 } 214 else if (TypedPointer.class.isAssignableFrom(cl)) 215 io = new CommonPointerIOs.TypedPointerPointerIO((Class<? extends TypedPointer>)cl); 216 } 217 if (io != null) { 218 PointerIO previousIO = ios.putIfAbsent(type, io); 219 if (previousIO != null) 220 io = previousIO; // created io twice : not important in general (expecially not compared to cost of contention on non-concurrent map) 221 } 222 } 223 return io; 224 } 225 226 227 public static PointerIO<Integer> getIntInstance() { 228 return (PointerIO)CommonPointerIOs.intIO; 229 } 230 public static PointerIO<Long> getLongInstance() { 231 return (PointerIO)CommonPointerIOs.longIO; 232 } 233 public static PointerIO<Short> getShortInstance() { 234 return (PointerIO)CommonPointerIOs.shortIO; 235 } 236 public static PointerIO<Byte> getByteInstance() { 237 return (PointerIO)CommonPointerIOs.byteIO; 238 } 239 public static PointerIO<Character> getCharInstance() { 240 return (PointerIO)CommonPointerIOs.charIO; 241 } 242 public static PointerIO<Float> getFloatInstance() { 243 return (PointerIO)CommonPointerIOs.floatIO; 244 } 245 public static PointerIO<Double> getDoubleInstance() { 246 return (PointerIO)CommonPointerIOs.doubleIO; 247 } 248 public static PointerIO<Boolean> getBooleanInstance() { 249 return (PointerIO)CommonPointerIOs.booleanIO; 250 } 251 public static PointerIO<CLong> getCLongInstance() { 252 return (PointerIO)CommonPointerIOs.CLongIO; 253 } 254 public static PointerIO<SizeT> getSizeTInstance() { 255 return (PointerIO)CommonPointerIOs.SizeTIO; 256 } 257 258 public static PointerIO<Pointer> getPointerInstance() { 259 return PointerIO; 260 } 261 262 public static PointerIO<TimeT> getTimeTInstance() { 263 return (PointerIO)CommonPointerIOs.TimeTIO; 264 } 265 266 public static <P> PointerIO<P> getBufferPrimitiveInstance(Buffer buffer) { 267 if (buffer instanceof IntBuffer) 268 return (PointerIO)CommonPointerIOs.intIO; 269 if (buffer instanceof LongBuffer) 270 return (PointerIO)CommonPointerIOs.longIO; 271 if (buffer instanceof ShortBuffer) 272 return (PointerIO)CommonPointerIOs.shortIO; 273 if (buffer instanceof ByteBuffer) 274 return (PointerIO)CommonPointerIOs.byteIO; 275 if (buffer instanceof CharBuffer) 276 return (PointerIO)CommonPointerIOs.charIO; 277 if (buffer instanceof FloatBuffer) 278 return (PointerIO)CommonPointerIOs.floatIO; 279 if (buffer instanceof DoubleBuffer) 280 return (PointerIO)CommonPointerIOs.doubleIO; 281 throw new UnsupportedOperationException(); 282 } 283 284}