View Javadoc

1   /*
2   	Copyright (c) 2009 Olivier Chafik, All Rights Reserved
3   	
4   	This file is part of JNAerator (http://jnaerator.googlecode.com/).
5   	
6   	JNAerator is free software: you can redistribute it and/or modify
7   	it under the terms of the GNU Lesser General Public License as published by
8   	the Free Software Foundation, either version 3 of the License, or
9   	(at your option) any later version.
10  	
11  	JNAerator is distributed in the hope that it will be useful,
12  	but WITHOUT ANY WARRANTY; without even the implied warranty of
13  	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  	GNU Lesser General Public License for more details.
15  	
16  	You should have received a copy of the GNU Lesser General Public License
17  	along with JNAerator.  If not, see <http://www.gnu.org/licenses/>.
18  */
19  package com.ochafik.lang.jnaerator.runtime;
20  
21  import com.sun.jna.Memory;
22  import java.lang.ref.WeakReference;
23  import java.lang.reflect.Field;
24  import java.nio.Buffer;
25  
26  import com.sun.jna.Native;
27  import com.sun.jna.Pointer;
28  import java.lang.reflect.Array;
29  
30  public abstract class Structure<S extends Structure<S, V, R>, V extends S, R extends S> 
31  	extends com.sun.jna.Structure
32  	implements 
33  		Comparable<Structure<S, V, R>>,
34  		StructureType,
35  		StructureTypeDependent
36  {	
37  	public interface ByReference extends com.sun.jna.Structure.ByReference, StructureTypeDependent {}
38  	public interface ByValue extends com.sun.jna.Structure.ByValue, StructureTypeDependent {}
39  	
40  	transient WeakReference<StructureType> dependency;
41  	@Override
42  	public void setDependency(StructureType type) {
43  		this.dependency = type == null ? null : new WeakReference<StructureType>(type);
44  	}
45  	protected void readDependency() {
46  		StructureType dep;
47  		if (dependency == null || (dep = dependency.get()) == null)
48  			return;
49  		dep.read();
50  	}
51  	
52  	@Override
53  	public void read() {
54  		super.read();
55  		readDependency();
56  	}
57  	@Override
58  	public void write() {
59  		super.write();
60  		readDependency();
61  	}
62  	
63  	protected <T extends Structure<S, V, R>> T setupClone(T clone, StructureType dependency) {
64  		write();
65  		clone.useMemory(getPointer());
66  		clone.setDependency(this);
67  		return clone;
68  	}
69  	
70  	//getFieldOffset(String fieldName);
71  	
72  	protected abstract S newInstance();
73  	protected abstract V newByValue();
74  	protected abstract R newByReference();
75  	
76  	public R byReference() { return setupClone(newByReference(), this); }
77  	public V byValue() { return setupClone(newByValue(), this); }
78  	public S clone() { return setupClone(newInstance(), this); }
79  
80  	public static <S extends Structure>
81  			S[] newArray(Class<S> structClass, int arrayLength) {
82  		try {
83  			S first = structClass.newInstance();
84  			int sz = first.size();
85  			Memory mem = new Memory(arrayLength * sz);
86  			first.use(mem);
87  			S[] array = (S[])first.castToArray(arrayLength);
88  			for (int i = 1; i < arrayLength; i++) {
89  				S s = structClass.newInstance();
90  				s.use(mem, i * sz);
91  				array[i] = s;
92  			}
93  			return array;
94  		} catch (Exception ex) {
95  			throw new RuntimeException(ex);
96  		}
97  	}
98  	/**
99  	 * @deprecated use castToArray instead
100 	 */
101 	@Deprecated
102 	@SuppressWarnings("unchecked")
103 	@Override
104 	public S[] toArray(int size) {
105 		return (S[])super.toArray(size);
106 	}
107 	/**
108 	 * @deprecated use castToArray instead
109 	 */
110 	@Deprecated
111 	public S[] toArray() {
112 		return toArray(1);
113 	}
114 	/**
115 	 * @deprecated use castToArray instead
116 	 */
117 	@Deprecated
118 	@SuppressWarnings("unchecked")
119 	public R[] toReferenceArray(int size) {
120 		return (R[])byReference().toArray(size);
121 	}
122 	/**
123 	 * @deprecated use castToArray instead
124 	 */
125 	@Deprecated
126 	@SuppressWarnings("unchecked")
127 	public V[] toValueArray(int size) {
128 		return (V[])byValue().toArray(size);
129 	}
130 	/**
131 	 * @deprecated use castToArray instead
132 	 */
133 	@Deprecated
134 	public R[] toReferenceArray() {
135 		return toReferenceArray(1);
136 	}
137 	/**
138 	 * @deprecated use castToArray instead
139 	 */
140 	@Deprecated
141 	public V[] toValueArray() {
142 		return toValueArray(1);
143 	}
144 
145 	/**
146 	 * @deprecated use castToArray instead
147 	 */
148 	@Deprecated
149 	@SuppressWarnings("unchecked")
150 	@Override
151 	public S[] toArray(com.sun.jna.Structure[] array) {
152 		return (S[])super.toArray(array);
153 	}
154 	
155 	@SuppressWarnings("unchecked")
156 	public S[] castToArray(int size) {
157 		return (S[])super.toArray(size);
158 	}
159 	public S[] castToArray() {
160 		return castToArray(1);
161 	}
162 	@SuppressWarnings("unchecked")
163 	public R[] castToReferenceArray(int size) {
164 		return (R[])byReference().toArray(size);
165 	}
166 	@SuppressWarnings("unchecked")
167 	public V[] castToValueArray(int size) {
168 		return (V[])byValue().toArray(size);
169 	}
170 	public R[] castToReferenceArray() {
171 		return castToReferenceArray(1);
172 	}
173 	public V[] castToValueArray() {
174 		return castToValueArray(1);
175 	}
176 	@SuppressWarnings("unchecked")
177 	public S[] castToArray(com.sun.jna.Structure[] array) {
178 		return (S[])super.toArray(array);
179 	}
180 
181 
182 	@Override
183 	protected Integer getBitsAnnotation(Field field) {
184 		Bits bits = field.getAnnotation(Bits.class);
185 		return bits == null ? null : bits.value();
186 	}
187 	/** Simply does a memcmp between the two memory blocks of the two structures
188      */
189 	@Override
190 	public int compareTo(Structure<S, V, R> o) {
191         if (o == this)
192             return 0;
193         if (!(o instanceof Structure<?, ?, ?>))
194         	return 1;
195         
196         int size = size();
197         int d = size - ((Structure<?, ?, ?>)o).size();
198         if (d != 0)
199         	return d;
200         
201         Structure<?, ?, ?> s = (Structure<?, ?, ?>)o;
202         if (getPointer().equals(s.getPointer()))
203         	return 0;
204         
205         write();
206         s.write();
207         
208         byte[] bytes1 = getPointer().getByteArray(0, size);
209         byte[] bytes2 = s.getPointer().getByteArray(0, size);
210         
211         for (int i = 0; i < size; i++) {
212         	byte b1 = bytes1[i], b2 = bytes2[i];
213         	if (b1 != b2)
214         		return b1 < b2 ? -1 : 1;
215         }
216         return 0;
217     }
218 	
219 	protected <T extends Union<?, ?, ?>> T setupClone(T clone) {
220 		write();
221 		clone.use(getPointer());
222 		return clone;
223 	}
224 	
225 	public S use(Pointer m) {
226 		return use(m, 0);
227 	}
228 	public S use(Pointer m, long byteOffset) {
229 		useMemory(m, (int)byteOffset);
230 		return (S)this;
231 	}
232 	public S use(Buffer m) {
233 		return use(m, 0);
234 	}
235 	public S use(Buffer b, long byteOffset) {
236 		useMemory(Native.getDirectBufferPointer(b), (int)byteOffset);
237 		return (S)this;
238 	}
239 	
240 }