1 /* 2 * Copyright (c) 2015, 2016, 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. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package com.sun.tools.jextract; 24 25 /** 26 * A Java Type descriptor 27 */ 28 public interface JType { 29 30 /** 31 * The descriptor of this type 32 * 33 * @return The type descriptor as defined in JVMS 4.3 34 */ 35 public String getDescriptor(); 36 37 default public String getSignature() { return getDescriptor(); } 38 39 public final static JType Void = () -> "V"; 40 public final static JType Byte = () -> "B"; 41 public final static JType Bool = () -> "Z"; 42 public final static JType Char = () -> "C"; 43 public final static JType Short = () -> "S"; 44 public final static JType Int = () -> "I"; 45 public final static JType Long = () -> "J"; 46 public final static JType Float = () -> "F"; 47 public final static JType Double = () -> "D"; 48 public final static JType Object = new ObjectRef(java.lang.Object.class); 49 50 public static JType of(final Class<?> cls) { 51 if (cls.isArray()) { 52 return ofArray(JType.of(cls.getComponentType())); 53 } 54 if (cls.isPrimitive()) { 55 switch (cls.getTypeName()) { 56 case "int": 57 return JType.Int; 58 case "long": 59 return JType.Long; 60 case "byte": 61 return JType.Byte; 62 case "char": 63 return JType.Char; 64 case "float": 65 return JType.Float; 66 case "double": 67 return JType.Double; 68 case "short": 69 return JType.Short; 70 case "boolean": 71 return JType.Bool; 72 case "void": 73 return JType.Void; 74 } 75 } 76 if (cls == Object.class) { 77 return JType.Object; 78 } 79 // assuming reference 80 return new ObjectRef(cls); 81 } 82 83 public static String boxing(JType t) { 84 if (t instanceof JType2) { 85 t = ((JType2) t).getDelegate(); 86 } 87 88 if (t == JType.Bool) { 89 return "Ljava/lang/Boolean;"; 90 } else if (t == JType.Char) { 91 return "Ljava/lang/Character;"; 92 } else if (t == JType.Int) { 93 return "Ljava/lang/Integer;"; 94 } else if (t == JType.Byte) { 95 return "Ljava/lang/Byte;"; 96 } else if (t == JType.Double) { 97 return "Ljava/lang/Double;"; 98 } else if (t == JType.Float) { 99 return "Ljava/lang/Float;"; 100 } else if (t == JType.Long) { 101 return "Ljava/lang/Long;"; 102 } else if (t == JType.Short) { 103 return "Ljava/lang/Short;"; 104 } else if (t == JType.Void) { 105 return "Ljava/lang/Void;"; 106 } else { 107 return t.getSignature(); 108 } 109 } 110 111 public static JType of(String clsName) { 112 return new ObjectRef(clsName); 113 } 114 public static JType ofArray(JType elementType) { return new ArrayType(elementType); } 115 116 /** 117 * Return Java type signature for JType. If JType is a Pointer<Void>, return as 118 * Pointer<?> 119 * @param jt The JType to get signature for 120 * @return The Java type signature 121 */ 122 static String getPointerVoidAsWildcard(JType jt) { 123 // Return Pointer<?> instead of Pointer<Void> 124 if (jt instanceof JType2) { 125 jt = ((JType2) jt).getDelegate(); 126 } 127 if (jt instanceof TypeAlias) { 128 JType tmp = ((TypeAlias) jt).baseType; 129 // Respect alias signature, like FnIf has its own rule about signature 130 if (tmp instanceof PointerType) { 131 jt = tmp; 132 } 133 } 134 if (jt instanceof PointerType) { 135 return ((PointerType) jt).getSignature(true); 136 } else { 137 return jt.getSignature(); 138 } 139 } 140 141 static class ObjectRef implements JType { 142 final String clsName; 143 144 ObjectRef(Class<?> cls) { 145 this.clsName = cls.getName().replace('.', '/'); 146 } 147 148 ObjectRef(String clsName) { 149 this.clsName = clsName; 150 } 151 152 @Override 153 public String getDescriptor() { 154 return "L" + clsName + ";"; 155 } 156 } 157 158 final static class InnerType implements JType { 159 final String outerName; 160 final String name; 161 162 InnerType(Class<?> outer, String name) { 163 outerName = outer.getName().replace('.', '/'); 164 this.name = name; 165 } 166 167 InnerType(String outerName, String name) { 168 this.outerName = outerName; 169 this.name = name; 170 } 171 172 public String getOuterClassName() { 173 return outerName; 174 } 175 176 public String getName() { 177 return name; 178 } 179 180 @Override 181 public String getDescriptor() { 182 return "L" + outerName + "$" + name + ";"; 183 } 184 } 185 186 final class ArrayType implements JType { 187 final JType elementType; 188 189 ArrayType(JType type) { 190 elementType = type; 191 } 192 193 @Override 194 public String getDescriptor() { 195 return JType.of(java.foreign.memory.Array.class).getDescriptor(); 196 } 197 198 @Override 199 public String getSignature() { 200 StringBuilder sb = new StringBuilder(); 201 sb.append("L"); 202 sb.append(java.foreign.memory.Array.class.getName().replace('.', '/')); 203 sb.append("<"); 204 JType pt = elementType; 205 if (pt instanceof JType2) { 206 pt = ((JType2) pt).getDelegate(); 207 } 208 if (pt instanceof TypeAlias) { 209 pt = ((TypeAlias) pt).canonicalType(); 210 } 211 sb.append(JType.boxing(pt)); 212 sb.append(">;"); 213 return sb.toString(); 214 } 215 216 public JType getElementType() { 217 return elementType; 218 } 219 } 220 221 final static class Function implements JType { 222 final JType returnType; 223 final JType[] args; 224 final boolean isVarArgs; 225 final java.foreign.layout.Function layout; 226 227 Function(java.foreign.layout.Function layout, boolean isVarArgs, JType returnType, JType... args) { 228 this.layout = layout; 229 this.returnType = returnType; 230 this.args = args; 231 this.isVarArgs = isVarArgs; 232 } 233 234 @Override 235 public String getDescriptor() { 236 StringBuilder sb = new StringBuilder(); 237 sb.append('('); 238 // ensure sequence 239 for (int i = 0; i < args.length; i++) { 240 sb.append(args[i].getDescriptor()); 241 } 242 if (isVarArgs) { 243 sb.append("[Ljava/lang/Object;"); 244 } 245 sb.append(')'); 246 sb.append(returnType.getDescriptor()); 247 return sb.toString(); 248 } 249 250 @Override 251 public String getSignature() { 252 StringBuilder sb = new StringBuilder(); 253 sb.append('('); 254 // ensure sequence 255 for (int i = 0; i < args.length; i++) { 256 sb.append(getPointerVoidAsWildcard(args[i])); 257 } 258 if (isVarArgs) { 259 sb.append("[Ljava/lang/Object;"); 260 } 261 sb.append(')'); 262 sb.append(returnType.getSignature()); 263 return sb.toString(); 264 } 265 266 public String getNativeDescriptor() { 267 return layout.toString(); 268 } 269 } 270 271 final static class FnIf implements JType { 272 final JType type; 273 final Function fn; 274 275 FnIf(JType type, Function fn) { 276 this.type = type; 277 this.fn = fn; 278 } 279 280 @Override 281 public String getDescriptor() { 282 return type.getDescriptor(); 283 } 284 285 @Override 286 public String getSignature() { 287 return type.getSignature(); 288 } 289 290 Function getFunction() { 291 return fn; 292 } 293 294 @Override 295 public String toString() { 296 return "FunctionalInterface: " + getDescriptor() + " for " + fn.getSignature(); 297 } 298 } 299 }