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 }