1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.nicl.types; 27 28 import jdk.internal.nicl.types.DescriptorParser; 29 import jdk.internal.nicl.types.Reference; 30 import jdk.internal.nicl.types.References; 31 32 import java.nicl.layout.Address; 33 import java.nicl.layout.Group; 34 import java.nicl.layout.Layout; 35 import java.nicl.layout.Sequence; 36 37 import java.lang.invoke.MethodHandle; 38 import java.nicl.metadata.NativeType; 39 40 /** 41 * This class describes the relationship between a memory layout (usually described in bits) and a Java carrier 42 * (e.g. {@code int}, {@code long}, or any Java reference type. A {@code LayoutType} defines operation for getting/setting 43 * the layout contents using a given Java carrier (see {@link LayoutType#getter()} and {@link LayoutType#setter()}). 44 * Moreover, a {@code LayoutType} defines operation for creating array and pointer derived {@code LayoutType} instances 45 * (see {@link LayoutType#array()}, {@link LayoutType#array(int)} and {@link LayoutType#pointer()}). 46 */ 47 public class LayoutType<X> { 48 49 private final Reference reference; 50 private final Layout layout; 51 52 /* package */ LayoutType(Layout layout, Reference reference) { 53 this.reference = reference; 54 this.layout = layout; 55 } 56 57 public long bytesSize() { 58 return layout().bitsSize() / 8; 59 } 60 61 /** 62 * Retrieves the memory layout associated with this {@code LayoutType}. 63 * @return the layout. 64 */ 65 public Layout layout() { 66 return layout; 67 } 68 69 /** 70 * A {@link MethodHandle} which can be used to retrieve the contents of memory layout associated 71 * with this {@code LayoutType}. Note: the pointer passed as argument must be compatible with said layout. 72 * <p> 73 * A getter method handle is of the form: 74 * {@code (Pointer) -> T} 75 * Where {@code T} is the Java type to which the layout will be converted. 76 * </p> 77 * @return a 'getter' method handle. 78 */ 79 public MethodHandle getter() { 80 return reference.getter(); 81 } 82 83 /** 84 * A {@link MethodHandle} which can be used to store a value into the memory layout associated 85 * with this {@code LayoutType}. Note: the pointer passed as argument must be compatible with said layout. 86 * <p> 87 * A setter method handle is of the form: 88 * {@code (Pointer, T) -> V} 89 * Where {@code T} is the Java type to which the layout will be converted. 90 * </p> 91 * the pointer passed as argument. 92 * @return a 'setter' method handle. 93 */ 94 public MethodHandle setter() { 95 return reference.setter(); 96 } 97 98 /** 99 * Create an array {@code LayoutType} from this instance. 100 * @return the array {@code LayoutType}. 101 */ 102 @SuppressWarnings("unchecked") 103 public LayoutType<Array<X>> array() { 104 return array(0); 105 } 106 107 /** 108 * Create an array {@code LayoutType} from this instance with given size. 109 * @param size the array size. 110 * @return the array {@code LayoutType}. 111 */ 112 @SuppressWarnings("unchecked") 113 public LayoutType<Array<X>> array(int size) { 114 return new LayoutType<>(Sequence.of(size, layout), References.ofArray(this)); 115 } 116 117 /** 118 * Create a pointer {@code LayoutType} from this instance. 119 * @return the pointer {@code LayoutType}. 120 */ 121 @SuppressWarnings("unchecked") 122 public LayoutType<Pointer<X>> pointer() { 123 return new LayoutType<>(Address.ofLayout(64, layout), References.ofPointer(this)); 124 } 125 126 /** 127 * Create a {@code LayoutType} from the {@code boolean} Java primitive carrier and given layout. 128 * @param layout the layout. 129 * @return the {@code LayoutType}. 130 */ 131 public static LayoutType<Boolean> ofBoolean(Layout layout) { 132 return new LayoutType<>(layout, References.ofBoolean); 133 } 134 135 /** 136 * Create a {@code LayoutType} from the {@code char} Java primitive carrier and given layout. 137 * @param layout the layout. 138 * @return the {@code LayoutType}. 139 */ 140 public static LayoutType<Character> ofChar(Layout layout) { 141 return new LayoutType<>(layout, References.ofChar); 142 } 143 144 /** 145 * Create a {@code LayoutType} from the {@code byte} Java primitive carrier and given layout. 146 * @param layout the layout. 147 * @return the {@code LayoutType}. 148 */ 149 public static LayoutType<Byte> ofByte(Layout layout) { 150 return new LayoutType<>(layout, References.ofByte); 151 } 152 153 /** 154 * Create a {@code LayoutType} from the {@code short} Java primitive carrier and given layout. 155 * @param layout the layout. 156 * @return the {@code LayoutType}. 157 */ 158 public static LayoutType<Short> ofShort(Layout layout) { 159 return new LayoutType<>(layout, References.ofShort); 160 } 161 162 /** 163 * Create a {@code LayoutType} from the {@code int} Java primitive carrier and given layout. 164 * @param layout the layout. 165 * @return the {@code LayoutType}. 166 */ 167 public static LayoutType<Integer> ofInt(Layout layout) { 168 return new LayoutType<>(layout, References.ofInt); 169 } 170 171 /** 172 * Create a {@code LayoutType} from the {@code float} Java primitive carrier and given layout. 173 * @param layout the layout. 174 * @return the {@code LayoutType}. 175 */ 176 public static LayoutType<Float> ofFloat(Layout layout) { 177 return new LayoutType<>(layout, References.ofFloat); 178 } 179 180 /** 181 * Create a {@code LayoutType} from the {@code long} Java primitive carrier and given layout. 182 * @param layout the layout. 183 * @return the {@code LayoutType}. 184 */ 185 public static LayoutType<Long> ofLong(Layout layout) { 186 return new LayoutType<>(layout, References.ofLong); 187 } 188 189 /** 190 * Create a {@code LayoutType} from the {@code double} Java primitive carrier and given layout. 191 * @param layout the layout. 192 * @return the {@code LayoutType}. 193 */ 194 public static LayoutType<Double> ofDouble(Layout layout) { 195 return new LayoutType<>(layout, References.ofDouble); 196 } 197 198 /** 199 * Create a carrier-less {@code LayoutType} from given layout. 200 * @param layout the layout. 201 * @return the {@code LayoutType}. 202 */ 203 public static LayoutType<?> ofVoid(Layout layout) { 204 return new LayoutType<>(layout, null) { 205 @Override 206 public MethodHandle getter() throws UnsupportedOperationException { 207 throw new UnsupportedOperationException(); 208 } 209 210 @Override 211 public MethodHandle setter() throws UnsupportedOperationException { 212 throw new UnsupportedOperationException(); 213 } 214 }; 215 } 216 217 /** 218 * Create a {@code LayoutType} from a {@link Struct} interface carrier. 219 * @param <T> the struct type. 220 * @param carrier the struct carrier. 221 * @return the {@code LayoutType}. 222 * @throws IllegalArgumentException if the given carrier is not annotated with the {@link java.nicl.metadata.NativeType} annotation. 223 */ 224 public static <T extends Struct<T>> LayoutType<T> ofStruct(Class<T> carrier) throws IllegalArgumentException { 225 NativeType nativeStruct = carrier.getAnnotation(NativeType.class); 226 if (nativeStruct == null) { 227 throw new IllegalArgumentException("Not a struct type!"); 228 } 229 Group type = (Group) new DescriptorParser(nativeStruct.layout()).parseLayout().findFirst().get(); 230 return new LayoutType<>(type, References.ofStruct(carrier)); 231 } 232 }