001    /*
002            Copyright (c) 2009 Olivier Chafik, All Rights Reserved
003            
004            This file is part of JNAerator (http://jnaerator.googlecode.com/).
005            
006            JNAerator is free software: you can redistribute it and/or modify
007            it under the terms of the GNU Lesser General Public License as published by
008            the Free Software Foundation, either version 3 of the License, or
009            (at your option) any later version.
010            
011            JNAerator is distributed in the hope that it will be useful,
012            but WITHOUT ANY WARRANTY; without even the implied warranty of
013            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
014            GNU Lesser General Public License for more details.
015            
016            You should have received a copy of the GNU Lesser General Public License
017            along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
018    */
019    package com.ochafik.lang.jnaerator.runtime;
020    
021    import com.sun.jna.Memory;
022    import java.lang.ref.WeakReference;
023    import java.nio.Buffer;
024    
025    import com.sun.jna.Native;
026    import com.sun.jna.Pointer;
027    
028    public abstract class Union<S extends Union<S, V, R>, V extends S, R extends S> 
029            extends com.sun.jna.Union
030            implements
031                    StructureType,
032                    StructureTypeDependent
033    {       
034            public interface ByReference extends com.sun.jna.Union.ByReference, StructureTypeDependent {}
035            public interface ByValue extends com.sun.jna.Union.ByValue, StructureTypeDependent {}
036    
037            transient WeakReference<StructureType> dependency;
038            @Override
039            public void setDependency(StructureType type) {
040                    this.dependency = type == null ? null : new WeakReference<StructureType>(type);
041            }
042            protected void readDependency() {
043                    StructureType dep;
044                    if (dependency == null || (dep = dependency.get()) == null)
045                            return;
046                    dep.read();
047            }
048            @Override
049            public void read() {
050                    super.read();
051                    readDependency();
052            }
053            @Override
054            public void write() {
055                    super.write();
056                    readDependency();
057            }
058            /**
059             * @deprecated use castToArray instead
060             */
061            @Deprecated
062            @SuppressWarnings("unchecked")
063            @Override
064            public S[] toArray(int size) {
065                    return (S[])super.toArray(size);
066            }
067            /**
068             * @deprecated use castToArray instead
069             */
070            @Deprecated
071            public S[] toArray() {
072                    return toArray(1);
073            }
074    
075            /**
076             * @deprecated use castToArray instead
077             */
078            @Deprecated
079            @SuppressWarnings("unchecked")
080            @Override
081            public S[] toArray(com.sun.jna.Structure[] array) {
082                    return (S[])super.toArray(array);
083            }
084    
085            @SuppressWarnings("unchecked")
086            public S[] castToArray(int size) {
087                    return (S[])super.toArray(size);
088            }
089            public S[] castToArray() {
090                    return castToArray(1);
091            }
092            @SuppressWarnings("unchecked")
093            public S[] castToArray(com.sun.jna.Structure[] array) {
094                    return (S[])super.toArray(array);
095            }
096    
097    
098            public static <S extends Union>
099                            S[] newArray(Class<S> structClass, int arrayLength) {
100                    try {
101                            S first = structClass.newInstance();
102                            int sz = first.size();
103                            Memory mem = new Memory(arrayLength * sz);
104                            first.use(mem);
105                            S[] array = (S[])first.castToArray(arrayLength);
106                            for (int i = 1; i < arrayLength; i++) {
107                                    S s = structClass.newInstance();
108                                    s.use(mem, i * sz);
109                                    array[i] = s;
110                            }
111                            return array;
112                    } catch (Exception ex) {
113                            throw new RuntimeException(ex);
114                    }
115            }
116            
117            protected abstract S newInstance();
118            protected abstract V newByValue();
119            protected abstract R newByReference();
120            
121            public R byReference() { return setupClone(newByReference()); }
122            public V byValue() { return setupClone(newByValue()); }
123            public S clone() { return setupClone(newInstance()); }
124            
125            protected <T extends Union<?, ?, ?>> T setupClone(T clone) {
126                    write();
127                    clone.use(getPointer());
128                    return clone;
129            }
130            
131            public S use(Pointer m) {
132                    return use(m, 0);
133            }
134            public S use(Pointer m, long byteOffset) {
135                    useMemory(m, (int)byteOffset);
136                    return (S)this;
137            }
138            public S use(Buffer m) {
139                    return use(m, 0);
140            }
141            public S use(Buffer b, long byteOffset) {
142                    useMemory(Native.getDirectBufferPointer(b), (int)byteOffset);
143                    return (S)this;
144            }
145            
146    }