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;
032import java.lang.reflect.TypeVariable;
033import java.lang.reflect.WildcardType;
034import org.bridj.CallIO.NativeObjectHandler;
035import org.bridj.util.*;
036import java.lang.reflect.ParameterizedType;
037import java.lang.reflect.Method;
038import java.lang.reflect.Modifier;
039import java.lang.reflect.Member;
040import java.lang.reflect.AnnotatedElement;
041import java.lang.reflect.Type;
042import java.nio.*;
043import java.util.ArrayList;
044import java.util.Collections;
045import java.util.Comparator;
046import java.util.HashMap;
047import java.util.LinkedHashMap;
048import java.util.HashSet;
049import java.util.List;
050import java.util.Map;
051import java.util.TreeMap;
052import java.util.Set;
053import java.util.concurrent.*;
054import org.bridj.ann.Virtual;
055import org.bridj.ann.Array;
056import org.bridj.ann.Union;
057import org.bridj.ann.Bits;
058import org.bridj.ann.Field;
059import org.bridj.ann.Struct;
060import org.bridj.ann.Alignment;
061import static org.bridj.Pointer.*;
062import static org.bridj.StructUtils.*;
063
064/**
065 * Object responsible for reading and writing of a C struct's fields.<br>
066 * End-users should not use this class, it's used by runtimes.<br>
067 * See {@link org.bridj.StructDescription}.
068 * @author ochafik
069 */
070public class StructIO {
071
072    static Map<Type, StructIO> structIOs = new HashMap<Type, StructIO>();
073
074    public static StructIO getInstance(Type structType) {
075        return getInstance(Utils.getClass(structType), structType);
076    }
077    public static StructIO getInstance(Class structClass, Type structType) {
078        synchronized (structIOs) {
079            StructIO io = structIOs.get(structType == null ? structClass : structType);
080            if (io == null) {
081                io = new StructIO(structClass, structType);
082                if (io != null)
083                        registerStructIO(structClass, structType, io);
084            }
085            return (StructIO)io;
086        }
087    }
088
089    public static synchronized StructIO registerStructIO(Class structClass, Type structType, StructIO io) {
090        structIOs.put(structType, io);
091        return io;
092    }
093
094    protected PointerIO<?> pointerIO;
095    public final StructDescription desc;
096    
097        public StructIO(Class<?> structClass, Type structType) {
098                this.desc = new StructDescription(structClass, structType, StructCustomizer.getInstance(structClass));
099        // Don't call build here, for recursive initialization cases (TODO test this)
100        }
101        
102        @Override
103        public String toString() {
104                return "StructIO(" + desc + ")";
105        }
106        
107        public boolean equal(StructObject a, StructObject b) {
108                return compare(a, b) == 0;      
109        }
110        public int compare(StructObject a, StructObject b) {
111                return StructUtils.compare(a, b, desc.getSolidRanges());
112        }
113        
114        public final String describe(StructObject struct) {
115                return desc.describe(struct);
116        }
117        
118        /**
119         * Write struct fields implemented as Java fields to the corresponding native memory (Java fields are written to native memory).<br>
120         * This does not concern normal structs as generated by JNAerator (which use getters and setters methods that read and write the fields directly from / to the native memory), but rather structs that are in the JNA style.
121         */
122        public final void writeFieldsToNative(StructObject struct) {
123                desc.build();
124                if (!desc.hasFieldFields)
125                        return;
126                try {
127                        for (StructFieldDescription fd : desc.fields) {
128                                if (fd.field == null)
129                                        continue;
130                        
131                                if (fd.isArray)
132                                        continue;
133
134                                Object value = fd.field.get(struct);
135                                if (value instanceof NativeObject) {//fd.isNativeObject) {
136                                                if (value != null) 
137                                                        BridJ.writeToNative((NativeObject)value);
138                                                continue;
139                                }
140                                Pointer ptr = struct.peer.offset(fd.byteOffset);
141                                Type tpe = fd.isNativeObject || fd.isArray ? fd.nativeTypeOrPointerTargetType : fd.field.getGenericType();
142                                ptr = ptr.as(tpe);
143                                ptr = fixIntegralTypeIOToMatchLength(ptr, fd.byteLength, fd.arrayLength);
144                                
145                                if (fd.isCLong && CLong.SIZE == 4 || fd.isSizeT && SizeT.SIZE == 4)
146                                        value = (int)(long)(Long)value;
147                                
148                                ptr.set(value);
149                        }
150                } catch (Throwable th) {
151                        throw new RuntimeException("Unexpected error while writing fields from struct " + Utils.toString(desc.structType) + " (" + getPointer(struct) + ")", th);
152                }
153        }
154        
155        /**
156         * Read struct fields implemented as Java fields from the corresponding native memory (Java fields are read from native memory).<br>
157         * This does not concern normal structs as generated by JNAerator (which use getters and setters methods that read and write the fields directly from / to the native memory), but rather structs that are in the JNA style.
158         */
159        public final void readFieldsFromNative(StructObject struct) {
160                desc.build();
161                if (!desc.hasFieldFields)
162                        return;
163                try {
164                        for (StructFieldDescription fd : desc.fields) {
165                                if (fd.field == null)
166                                        continue;
167
168                                Pointer ptr = struct.peer.offset(fd.byteOffset);
169                                Type tpe = fd.isNativeObject || fd.isArray ? fd.nativeTypeOrPointerTargetType : fd.field.getGenericType();
170                                ptr = ptr.as(tpe);
171                                ptr = fixIntegralTypeIOToMatchLength(ptr, fd.byteLength, fd.arrayLength);
172                                Object value;
173                                if (fd.isArray) {
174                                        ptr = ptr.validElements(fd.arrayLength);
175                                        value = ptr;
176                                } else {
177                                        value = ptr.get();
178                                }
179                                fd.field.set(struct, value);
180                                
181                                if (value instanceof NativeObject) {//if (fd.isNativeObject) {
182                                                if (value != null)
183                                                        BridJ.readFromNative((NativeObject)value);
184                                }
185                        }
186                } catch (Throwable th) {
187                        throw new RuntimeException("Unexpected error while reading fields from struct " + Utils.toString(desc.structType) + " (" + getPointer(struct) + ") : " + th, th);
188                }
189        }
190        public final <T> Pointer<T> getPointerField(StructObject struct, int fieldIndex) {
191        StructFieldDescription fd = desc.fields[fieldIndex];
192        Pointer<T> p;
193        if (fd.isArray) {
194                        p = struct.peer.offset(fd.byteOffset).as(fd.nativeTypeOrPointerTargetType);
195                        p = p.validElements(fd.arrayLength);
196        } else {
197                        p = struct.peer.getPointerAtOffset(fd.byteOffset, fd.nativeTypeOrPointerTargetType);
198        }
199                return p;
200        }
201        
202        public final <T> void setPointerField(StructObject struct, int fieldIndex, Pointer<T> value) {
203                StructFieldDescription fd = desc.fields[fieldIndex];
204                struct.peer.setPointerAtOffset(fd.byteOffset, value);
205        }
206        
207        public final <T extends TypedPointer> T getTypedPointerField(StructObject struct, int fieldIndex) {
208                StructFieldDescription fd = desc.fields[fieldIndex];
209                PointerIO<T> pio = PointerIO.getInstance(fd.nativeTypeOrPointerTargetType);
210                return pio.castTarget(struct.peer.getSizeTAtOffset(fd.byteOffset));
211        }
212        public final <O extends NativeObject> O getNativeObjectField(StructObject struct, int fieldIndex) {
213                StructFieldDescription fd = desc.fields[fieldIndex];
214                return (O)struct.peer.offset(fd.byteOffset).getNativeObject(fd.nativeTypeOrPointerTargetType);
215        }
216
217        public final <O extends NativeObject> void setNativeObjectField(StructObject struct, int fieldIndex, O value) {
218                StructFieldDescription fd = desc.fields[fieldIndex];
219                struct.peer.offset(fd.byteOffset).setNativeObject(value, fd.nativeTypeOrPointerTargetType);
220        }
221        
222        public final <E extends Enum<E>> IntValuedEnum<E> getEnumField(StructObject struct, int fieldIndex) {
223        StructFieldDescription fd = desc.fields[fieldIndex];
224                return FlagSet.fromValue(struct.peer.getIntAtOffset(fd.byteOffset), (Class<E>)fd.nativeTypeOrPointerTargetType);
225        }
226        
227        public final void setEnumField(StructObject struct, int fieldIndex, ValuedEnum<?> value) {
228                StructFieldDescription fd = desc.fields[fieldIndex];
229                struct.peer.setIntAtOffset(fd.byteOffset, (int)value.value());
230        }
231        
232    private void setSignedIntegral(Pointer<?> ptr, long byteOffset, long byteLength, long bitMask, long bitOffset, long value) {
233        if (bitMask != -1) {
234            long previous = ptr.getSignedIntegralAtOffset(byteOffset, byteLength);
235            value = value << bitOffset;
236            value = previous & ~bitMask | value & bitMask;
237        }
238        ptr.setSignedIntegralAtOffset(byteOffset, value, byteLength);
239    }
240
241    public final void setIntField(StructObject struct, int fieldIndex, int value) {
242                StructFieldDescription fd = desc.fields[fieldIndex];
243                        if (4 != fd.byteLength || fd.bitMask != -1)
244            setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value);
245        else
246                    struct.peer.setIntAtOffset(fd.byteOffset, value);
247        }
248        public final int getIntField(StructObject struct, int fieldIndex) {
249                StructFieldDescription fd = desc.fields[fieldIndex];
250        int value;
251                if (4 != fd.byteLength)
252                        value = (int)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength);
253        else
254                            value = struct.peer.getIntAtOffset(fd.byteOffset);
255        
256                return (int) ((value & fd.bitMask) >> fd.bitOffset);
257            }
258    public final void setLongField(StructObject struct, int fieldIndex, long value) {
259                StructFieldDescription fd = desc.fields[fieldIndex];
260                        if (8 != fd.byteLength || fd.bitMask != -1)
261            setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value);
262        else
263                    struct.peer.setLongAtOffset(fd.byteOffset, value);
264        }
265        public final long getLongField(StructObject struct, int fieldIndex) {
266                StructFieldDescription fd = desc.fields[fieldIndex];
267        long value;
268                if (8 != fd.byteLength)
269                        value = (long)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength);
270        else
271                            value = struct.peer.getLongAtOffset(fd.byteOffset);
272        
273                return (long) ((value & fd.bitMask) >> fd.bitOffset);
274            }
275    public final void setShortField(StructObject struct, int fieldIndex, short value) {
276                StructFieldDescription fd = desc.fields[fieldIndex];
277                        if (2 != fd.byteLength || fd.bitMask != -1)
278            setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value);
279        else
280                    struct.peer.setShortAtOffset(fd.byteOffset, value);
281        }
282        public final short getShortField(StructObject struct, int fieldIndex) {
283                StructFieldDescription fd = desc.fields[fieldIndex];
284        short value;
285                if (2 != fd.byteLength)
286                        value = (short)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength);
287        else
288                            value = struct.peer.getShortAtOffset(fd.byteOffset);
289        
290                return (short) ((value & fd.bitMask) >> fd.bitOffset);
291            }
292    public final void setByteField(StructObject struct, int fieldIndex, byte value) {
293                StructFieldDescription fd = desc.fields[fieldIndex];
294                        if (1 != fd.byteLength || fd.bitMask != -1)
295            setSignedIntegral(struct.peer, fd.byteOffset, fd.byteLength, fd.bitMask, fd.bitOffset, value);
296        else
297                    struct.peer.setByteAtOffset(fd.byteOffset, value);
298        }
299        public final byte getByteField(StructObject struct, int fieldIndex) {
300                StructFieldDescription fd = desc.fields[fieldIndex];
301        byte value;
302                if (1 != fd.byteLength)
303                        value = (byte)struct.peer.getSignedIntegralAtOffset(fd.byteOffset, fd.byteLength);
304        else
305                            value = struct.peer.getByteAtOffset(fd.byteOffset);
306        
307                return (byte) ((value & fd.bitMask) >> fd.bitOffset);
308            }
309    public final void setCharField(StructObject struct, int fieldIndex, char value) {
310                StructFieldDescription fd = desc.fields[fieldIndex];
311                            struct.peer.setCharAtOffset(fd.byteOffset, value);
312        }
313        public final char getCharField(StructObject struct, int fieldIndex) {
314                StructFieldDescription fd = desc.fields[fieldIndex];
315        char value;
316                    value = struct.peer.getCharAtOffset(fd.byteOffset);
317        
318                //assert fd.bitMask == -1;
319        return value;
320            }
321    public final void setFloatField(StructObject struct, int fieldIndex, float value) {
322                StructFieldDescription fd = desc.fields[fieldIndex];
323                            struct.peer.setFloatAtOffset(fd.byteOffset, value);
324        }
325        public final float getFloatField(StructObject struct, int fieldIndex) {
326                StructFieldDescription fd = desc.fields[fieldIndex];
327        float value;
328                    value = struct.peer.getFloatAtOffset(fd.byteOffset);
329        
330                //assert fd.bitMask == -1;
331        return value;
332            }
333    public final void setDoubleField(StructObject struct, int fieldIndex, double value) {
334                StructFieldDescription fd = desc.fields[fieldIndex];
335                            struct.peer.setDoubleAtOffset(fd.byteOffset, value);
336        }
337        public final double getDoubleField(StructObject struct, int fieldIndex) {
338                StructFieldDescription fd = desc.fields[fieldIndex];
339        double value;
340                    value = struct.peer.getDoubleAtOffset(fd.byteOffset);
341        
342                //assert fd.bitMask == -1;
343        return value;
344            }
345    public final void setBooleanField(StructObject struct, int fieldIndex, boolean value) {
346                StructFieldDescription fd = desc.fields[fieldIndex];
347                            struct.peer.setBooleanAtOffset(fd.byteOffset, value);
348        }
349        public final boolean getBooleanField(StructObject struct, int fieldIndex) {
350                StructFieldDescription fd = desc.fields[fieldIndex];
351        boolean value;
352                    value = struct.peer.getBooleanAtOffset(fd.byteOffset);
353        
354                //assert fd.bitMask == -1;
355        return value;
356            }
357
358    public final void setSizeTField(StructObject struct, int fieldIndex, long value) {
359                StructFieldDescription fd = desc.fields[fieldIndex];
360                struct.peer.setSizeTAtOffset(fd.byteOffset, value);
361        }
362        public final long getSizeTField(StructObject struct, int fieldIndex) {
363                StructFieldDescription fd = desc.fields[fieldIndex];
364                return struct.peer.getSizeTAtOffset(fd.byteOffset);
365        }
366    public final void setCLongField(StructObject struct, int fieldIndex, long value) {
367                StructFieldDescription fd = desc.fields[fieldIndex];
368                struct.peer.setCLongAtOffset(fd.byteOffset, value);
369        }
370        public final long getCLongField(StructObject struct, int fieldIndex) {
371                StructFieldDescription fd = desc.fields[fieldIndex];
372                return struct.peer.getCLongAtOffset(fd.byteOffset);
373        }
374
375  public final void setTimeTField(StructObject struct, int fieldIndex, TimeT value) {
376                StructFieldDescription fd = desc.fields[fieldIndex];
377                struct.peer.setIntegralAtOffset(fd.byteOffset, value);
378        }
379        public final TimeT getTimeTField(StructObject struct, int fieldIndex) {
380                StructFieldDescription fd = desc.fields[fieldIndex];
381                return new TimeT(struct.peer.getIntegralAtOffset(fd.byteOffset, TimeT.SIZE));
382        }
383}