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.lang.reflect.Field; 024 import java.nio.Buffer; 025 026 import com.sun.jna.Native; 027 import com.sun.jna.Pointer; 028 import java.lang.reflect.Array; 029 030 public abstract class Structure<S extends Structure<S, V, R>, V extends S, R extends S> 031 extends com.sun.jna.Structure 032 implements 033 Comparable<Structure<S, V, R>>, 034 StructureType, 035 StructureTypeDependent 036 { 037 public interface ByReference extends com.sun.jna.Structure.ByReference, StructureTypeDependent {} 038 public interface ByValue extends com.sun.jna.Structure.ByValue, StructureTypeDependent {} 039 040 transient WeakReference<StructureType> dependency; 041 @Override 042 public void setDependency(StructureType type) { 043 this.dependency = type == null ? null : new WeakReference<StructureType>(type); 044 } 045 protected void readDependency() { 046 StructureType dep; 047 if (dependency == null || (dep = dependency.get()) == null) 048 return; 049 dep.read(); 050 } 051 052 @Override 053 public void read() { 054 super.read(); 055 readDependency(); 056 } 057 @Override 058 public void write() { 059 super.write(); 060 readDependency(); 061 } 062 063 protected <T extends Structure<S, V, R>> T setupClone(T clone, StructureType dependency) { 064 write(); 065 clone.useMemory(getPointer()); 066 clone.setDependency(this); 067 return clone; 068 } 069 070 //getFieldOffset(String fieldName); 071 072 protected abstract S newInstance(); 073 protected abstract V newByValue(); 074 protected abstract R newByReference(); 075 076 public R byReference() { return setupClone(newByReference(), this); } 077 public V byValue() { return setupClone(newByValue(), this); } 078 public S clone() { return setupClone(newInstance(), this); } 079 080 public static <S extends Structure> 081 S[] newArray(Class<S> structClass, int arrayLength) { 082 try { 083 S first = structClass.newInstance(); 084 int sz = first.size(); 085 Memory mem = new Memory(arrayLength * sz); 086 first.use(mem); 087 S[] array = (S[])first.castToArray(arrayLength); 088 for (int i = 1; i < arrayLength; i++) { 089 S s = structClass.newInstance(); 090 s.use(mem, i * sz); 091 array[i] = s; 092 } 093 return array; 094 } catch (Exception ex) { 095 throw new RuntimeException(ex); 096 } 097 } 098 /** 099 * @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 }