001 package org.bridj;
002
003 import java.lang.reflect.ParameterizedType;
004 import java.lang.reflect.Type;
005 import java.util.*;
006 import java.nio.*;
007 import java.util.concurrent.ConcurrentHashMap;
008 import java.util.concurrent.atomic.AtomicReference;
009 import org.bridj.util.Utils;
010
011 /**
012 * Helper class that knows how to read/write data from/to a {@link Pointer}.<br>
013 * 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}).
014 * @author Olivier
015 */
016 public abstract class PointerIO<T> {
017 final Type targetType;
018 final Class<?> typedPointerClass;
019 final int targetSize, targetAlignment = -1;
020
021 public PointerIO(Type targetType, int targetSize, Class<?> typedPointerClass) {
022 this.targetType = targetType;
023 this.targetSize = targetSize;
024 this.typedPointerClass = typedPointerClass;
025 }
026 abstract T get(Pointer<T> pointer, long index);
027 abstract void set(Pointer<T> pointer, long index, T value);
028 public Object getArray(Pointer<T> pointer, long byteOffset, int length) {
029 return pointer.offset(byteOffset).toArray(length);
030 }
031 public <B extends Buffer> B getBuffer(Pointer<T> pointer, long byteOffset, int length) {
032 throw new UnsupportedOperationException("Cannot create a Buffer instance of elements of type " + getTargetType());
033 }
034 public void setArray(Pointer<T> pointer, long byteOffset, Object array) {
035 Object[] a = (Object[])array;
036 for (int i = 0, n = a.length; i < n; i++)
037 set(pointer, i, (T)a[i]);
038 }
039
040 public T castTarget(long peer) {
041 throw new UnsupportedOperationException("Cannot cast pointer to " + targetType);
042 }
043
044 PointerIO<Pointer<T>> getReferenceIO() {
045 return new CommonPointerIOs.PointerPointerIO<T>(this);
046 }
047 public long getTargetSize() {
048 return targetSize;
049 }
050 public long getTargetAlignment() {
051 return targetAlignment < 0 ? getTargetSize() : targetAlignment;
052 }
053 public boolean isTypedPointer() {
054 return typedPointerClass != null;
055 }
056 public Class<?> getTypedPointerClass() {
057 return typedPointerClass;
058 }
059 public Type getTargetType() {
060 return targetType;
061 }
062
063 static Class<?> getClass(Type type) {
064 if (type instanceof Class<?>)
065 return (Class<?>)type;
066 if (type instanceof ParameterizedType)
067 return getClass(((ParameterizedType)type).getRawType());
068 return null;
069 }
070
071 public static <T> PointerIO<Pointer<T>> getPointerInstance(Type target) {
072 return getPointerInstance((PointerIO<T>)getInstance(target));
073 }
074 public static <T> PointerIO<Pointer<T>> getPointerInstance(PointerIO<T> targetIO) {
075 return new CommonPointerIOs.PointerPointerIO<T>(targetIO);
076 }
077 public static <T> PointerIO<Pointer<T>> getArrayInstance(PointerIO<T> targetIO, long[] dimensions, int iDimension) {
078 return new CommonPointerIOs.PointerArrayIO<T>(targetIO, dimensions, iDimension);
079 }
080
081 static <T> PointerIO<T> getArrayIO(Object array) {
082 if (array instanceof int[])
083 return (PointerIO)PointerIO.getIntInstance();
084 if (array instanceof long[])
085 return (PointerIO)PointerIO.getLongInstance();
086 if (array instanceof short[])
087 return (PointerIO)PointerIO.getShortInstance();
088 if (array instanceof byte[])
089 return (PointerIO)PointerIO.getByteInstance();
090 if (array instanceof char[])
091 return (PointerIO)PointerIO.getCharInstance();
092 if (array instanceof float[])
093 return (PointerIO)PointerIO.getFloatInstance();
094 if (array instanceof double[])
095 return (PointerIO)PointerIO.getDoubleInstance();
096 if (array instanceof boolean[])
097 return (PointerIO)PointerIO.getBooleanInstance();
098 return PointerIO.getInstance(array.getClass().getComponentType());
099 }
100
101 private static final ConcurrentHashMap<StructIO, PointerIO<?>> structIOs = new ConcurrentHashMap<StructIO, PointerIO<?>>();
102 public static <S extends StructObject> PointerIO<S> getInstance(StructIO s) {
103 PointerIO io = structIOs.get(s);
104 if (io == null) {
105 io = new CommonPointerIOs.StructPointerIO(s);
106 PointerIO previousIO = structIOs.putIfAbsent(s, io);
107 if (previousIO != null)
108 io = previousIO;
109 }
110 return io;
111 }
112 private static final ConcurrentHashMap<Type, PointerIO<?>> ios = new ConcurrentHashMap<Type, PointerIO<?>>();
113 public static <P> PointerIO<P> getInstance(Type type) {
114 if (type == null)
115 return null;
116
117 PointerIO io = ios.get(type);
118 if (io == null) {
119 final Class<?> cl = Utils.getClass(type);
120
121 if (type == Integer.TYPE || type == Integer.class)
122 io = CommonPointerIOs.intIO;
123 else if (type == Long.TYPE || type == Long.class)
124 io = CommonPointerIOs.longIO;
125 else if (type == Short.TYPE || type == Short.class)
126 io = CommonPointerIOs.shortIO;
127 else if (type == Byte.TYPE || type == Byte.class)
128 io = CommonPointerIOs.byteIO;
129 else if (type == Character.TYPE || type == Character.class)
130 io = CommonPointerIOs.charIO;
131 else if (type == Float.TYPE || type == Float.class)
132 io = CommonPointerIOs.floatIO;
133 else if (type == Double.TYPE || type == Double.class)
134 io = CommonPointerIOs.doubleIO;
135 else if (type == Boolean.TYPE || type == Boolean.class)
136 io = CommonPointerIOs.booleanIO;
137 else if (cl != null) {
138 if (TypedPointer.class.isAssignableFrom(cl))
139 io = new CommonPointerIOs.TypedPointerPointerIO((Class<? extends TypedPointer>)cl);
140 else if (Pointer.class.isAssignableFrom(cl)) {
141 if (Pointer.class.equals(type) || !(type instanceof ParameterizedType))
142 io = getPointerInstance((PointerIO<?>)null);
143 else
144 io = getPointerInstance(((ParameterizedType)type).getActualTypeArguments()[0]);
145 }
146 else if (SizeT.class.isAssignableFrom(cl))
147 io = CommonPointerIOs.sizeTIO;
148 else if (TimeT.class.isAssignableFrom(cl))
149 io = CommonPointerIOs.timeTIO;
150 else if (CLong.class.isAssignableFrom(cl))
151 io = CommonPointerIOs.clongIO;
152 else if (StructObject.class.isAssignableFrom(cl))
153 io = getInstance(StructIO.getInstance((Class)cl, type));
154 else if (Callback.class.isAssignableFrom(cl))
155 io = new CommonPointerIOs.CallbackPointerIO(cl);
156 else if (NativeObject.class.isAssignableFrom(cl))
157 io = new CommonPointerIOs.NativeObjectPointerIO(type);
158 else if (IntValuedEnum.class.isAssignableFrom(cl)) {
159 if (type instanceof ParameterizedType) {
160 Type enumType = ((ParameterizedType)type).getActualTypeArguments()[0];
161 if (enumType instanceof Class)
162 io = new CommonPointerIOs.IntValuedEnumPointerIO((Class)enumType);
163 }
164 }
165 }
166 //else
167 //throw new UnsupportedOperationException("Cannot create pointer io to type " + type + ((type instanceof Class) && ((Class)type).getSuperclass() != null ? " (parent type : " + ((Class)type).getSuperclass().getName() + ")" : ""));
168 //return null; // TODO throw here ?
169
170 //if (io == null)
171 // throw new RuntimeException("Failed to create pointer io to type " + type);
172 if (io != null) {
173 PointerIO previousIO = ios.putIfAbsent(type, io);
174 if (previousIO != null)
175 io = previousIO; // created io twice : not important in general (expecially not compared to cost of contention on non-concurrent map)
176 }
177 }
178 return io;
179 }
180
181 private static PointerIO atomicInstance(AtomicReference ref, Type type) {
182 PointerIO io = (PointerIO)ref.get();
183 if (io != null)
184 return io;
185
186 if (ref.compareAndSet(null, io = getInstance(type)))
187 return io;
188
189 return (PointerIO)ref.get();
190 }
191
192 private static final AtomicReference<PointerIO<Integer>> intInstance = new AtomicReference<PointerIO<Integer>>();
193 public static PointerIO<Integer> getIntInstance() {
194 return atomicInstance(intInstance, Integer.class);
195 }
196 /* PointerIO<Integer> io = intInstance.get();
197 if (io != null)
198 return io;
199
200 if (intInstance.compareAndSet(null, io = getInstance(Integer.class)))
201 return io;
202
203 return intInstance.get();
204 }*/
205 private static final AtomicReference<PointerIO<Long>> longInstance = new AtomicReference<PointerIO<Long>>();
206 public static PointerIO<Long> getLongInstance() {
207 return atomicInstance(longInstance, Long.class);
208 }
209 /* PointerIO<Long> io = longInstance.get();
210 if (io != null)
211 return io;
212
213 if (longInstance.compareAndSet(null, io = getInstance(Long.class)))
214 return io;
215
216 return longInstance.get();
217 }*/
218 private static final AtomicReference<PointerIO<Short>> shortInstance = new AtomicReference<PointerIO<Short>>();
219 public static PointerIO<Short> getShortInstance() {
220 return atomicInstance(shortInstance, Short.class);
221 }
222 /* PointerIO<Short> io = shortInstance.get();
223 if (io != null)
224 return io;
225
226 if (shortInstance.compareAndSet(null, io = getInstance(Short.class)))
227 return io;
228
229 return shortInstance.get();
230 }*/
231 private static final AtomicReference<PointerIO<Byte>> byteInstance = new AtomicReference<PointerIO<Byte>>();
232 public static PointerIO<Byte> getByteInstance() {
233 return atomicInstance(byteInstance, Byte.class);
234 }
235 /* PointerIO<Byte> io = byteInstance.get();
236 if (io != null)
237 return io;
238
239 if (byteInstance.compareAndSet(null, io = getInstance(Byte.class)))
240 return io;
241
242 return byteInstance.get();
243 }*/
244 private static final AtomicReference<PointerIO<Character>> charInstance = new AtomicReference<PointerIO<Character>>();
245 public static PointerIO<Character> getCharInstance() {
246 return atomicInstance(charInstance, Character.class);
247 }
248 /* PointerIO<Character> io = charInstance.get();
249 if (io != null)
250 return io;
251
252 if (charInstance.compareAndSet(null, io = getInstance(Character.class)))
253 return io;
254
255 return charInstance.get();
256 }*/
257 private static final AtomicReference<PointerIO<Float>> floatInstance = new AtomicReference<PointerIO<Float>>();
258 public static PointerIO<Float> getFloatInstance() {
259 return atomicInstance(floatInstance, Float.class);
260 }
261 /* PointerIO<Float> io = floatInstance.get();
262 if (io != null)
263 return io;
264
265 if (floatInstance.compareAndSet(null, io = getInstance(Float.class)))
266 return io;
267
268 return floatInstance.get();
269 }*/
270 private static final AtomicReference<PointerIO<Double>> doubleInstance = new AtomicReference<PointerIO<Double>>();
271 public static PointerIO<Double> getDoubleInstance() {
272 return atomicInstance(doubleInstance, Double.class);
273 }
274 /* PointerIO<Double> io = doubleInstance.get();
275 if (io != null)
276 return io;
277
278 if (doubleInstance.compareAndSet(null, io = getInstance(Double.class)))
279 return io;
280
281 return doubleInstance.get();
282 }*/
283 private static final AtomicReference<PointerIO<Boolean>> booleanInstance = new AtomicReference<PointerIO<Boolean>>();
284 public static PointerIO<Boolean> getBooleanInstance() {
285 return atomicInstance(booleanInstance, Boolean.class);
286 }
287 /* PointerIO<Boolean> io = booleanInstance.get();
288 if (io != null)
289 return io;
290
291 if (booleanInstance.compareAndSet(null, io = getInstance(Boolean.class)))
292 return io;
293
294 return booleanInstance.get();
295 }*/
296 private static final AtomicReference<PointerIO<CLong>> CLongInstance = new AtomicReference<PointerIO<CLong>>();
297 public static PointerIO<CLong> getCLongInstance() {
298 return atomicInstance(CLongInstance, CLong.class);
299 }
300 /* PointerIO<CLong> io = CLongInstance.get();
301 if (io != null)
302 return io;
303
304 if (CLongInstance.compareAndSet(null, io = getInstance(CLong.class)))
305 return io;
306
307 return CLongInstance.get();
308 }*/
309 private static final AtomicReference<PointerIO<SizeT>> SizeTInstance = new AtomicReference<PointerIO<SizeT>>();
310 public static PointerIO<SizeT> getSizeTInstance() {
311 return atomicInstance(SizeTInstance, SizeT.class);
312 }
313 /* PointerIO<SizeT> io = SizeTInstance.get();
314 if (io != null)
315 return io;
316
317 if (SizeTInstance.compareAndSet(null, io = getInstance(SizeT.class)))
318 return io;
319
320 return SizeTInstance.get();
321 }*/
322 private static final AtomicReference<PointerIO<Pointer>> PointerInstance = new AtomicReference<PointerIO<Pointer>>();
323 public static PointerIO<Pointer> getPointerInstance() {
324 return atomicInstance(PointerInstance, Pointer.class);
325 }
326 /* PointerIO<Pointer> io = PointerInstance.get();
327 if (io != null)
328 return io;
329
330 if (PointerInstance.compareAndSet(null, io = getInstance(Pointer.class)))
331 return io;
332
333 return PointerInstance.get();
334 }*/
335
336 public static <P> PointerIO<P> getBufferPrimitiveInstance(Buffer buffer) {
337 if (buffer instanceof IntBuffer)
338 return (PointerIO<P>)getIntInstance();
339 if (buffer instanceof LongBuffer)
340 return (PointerIO<P>)getLongInstance();
341 if (buffer instanceof ShortBuffer)
342 return (PointerIO<P>)getShortInstance();
343 if (buffer instanceof ByteBuffer)
344 return (PointerIO<P>)getByteInstance();
345 if (buffer instanceof CharBuffer)
346 return (PointerIO<P>)getCharInstance();
347 if (buffer instanceof FloatBuffer)
348 return (PointerIO<P>)getFloatInstance();
349 if (buffer instanceof DoubleBuffer)
350 return (PointerIO<P>)getDoubleInstance();
351 throw new UnsupportedOperationException();
352 }
353
354 private static final AtomicReference<PointerIO> stringInstance = new AtomicReference<PointerIO>();
355 public static PointerIO<String> getStringInstance() {
356 return atomicInstance(stringInstance, String.class);/*
357 PointerIO io = stringInstance.get();
358 if (io != null)
359 return io;
360
361 if (stringInstance.compareAndSet(null, io = getInstance(String.class)))
362 return io;
363
364 return stringInstance.get();*/
365 }
366
367 }