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 }