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&lt;Void&gt;, return as
 118      * Pointer&lt;?&gt;
 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         PointerType asPointer() {
 194             return new PointerType(elementType);
 195         }
 196 
 197         @Override
 198         public String getDescriptor() {
 199             return JType.of(java.foreign.memory.Array.class).getDescriptor();
 200         }
 201 
 202         @Override
 203         public String getSignature() {
 204             StringBuilder sb = new StringBuilder();
 205             sb.append("L");
 206             sb.append(java.foreign.memory.Array.class.getName().replace('.', '/'));
 207             sb.append("<");
 208             JType pt = elementType;
 209             if (pt instanceof JType2) {
 210                 pt = ((JType2) pt).getDelegate();
 211             }
 212             if (pt instanceof TypeAlias) {
 213                 pt = ((TypeAlias) pt).canonicalType();
 214             }
 215             sb.append(JType.boxing(pt));
 216             sb.append(">;");
 217             return sb.toString();
 218         }
 219 
 220         public JType getElementType() {
 221             return elementType;
 222         }
 223     }
 224 
 225     final static class Function implements JType {
 226         final JType returnType;
 227         final JType[] args;
 228         final boolean isVarArgs;
 229         final java.foreign.layout.Function layout;
 230 
 231         Function(java.foreign.layout.Function layout, boolean isVarArgs, JType returnType, JType... args) {
 232             this.layout = layout;
 233             this.returnType = returnType;
 234             this.args = args;
 235             for (int i = 0; i < args.length; i++) {
 236                 args[i] = arrayAsPointer(args[i]);
 237             }
 238             this.isVarArgs = isVarArgs;
 239         }
 240 
 241         private static JType arrayAsPointer(JType t) {
 242             if (t instanceof JType2) {
 243                 t = ((JType2)t).getDelegate();
 244             }
 245             if (t instanceof TypeAlias) {
 246                 t = ((TypeAlias)t).canonicalType();
 247             }
 248             return t instanceof ArrayType? ((ArrayType)t).asPointer() : t;
 249         }
 250 
 251         @Override
 252         public String getDescriptor() {
 253             StringBuilder sb = new StringBuilder();
 254             sb.append('(');
 255             // ensure sequence
 256             for (int i = 0; i < args.length; i++) {
 257                 sb.append(args[i].getDescriptor());
 258             }
 259             if (isVarArgs) {
 260                 sb.append("[Ljava/lang/Object;");
 261             }
 262             sb.append(')');
 263             sb.append(returnType.getDescriptor());
 264             return sb.toString();
 265         }
 266 
 267         @Override
 268         public String getSignature() {
 269             StringBuilder sb = new StringBuilder();
 270             sb.append('(');
 271             // ensure sequence
 272             for (int i = 0; i < args.length; i++) {
 273                 sb.append(getPointerVoidAsWildcard(args[i]));
 274             }
 275             if (isVarArgs) {
 276                 sb.append("[Ljava/lang/Object;");
 277             }
 278             sb.append(')');
 279             sb.append(returnType.getSignature());
 280             return sb.toString();
 281         }
 282 
 283         public String getNativeDescriptor() {
 284             return layout.toString();
 285         }
 286     }
 287 
 288     final static class FnIf implements JType {
 289         final JType type;
 290         final Function fn;
 291 
 292         FnIf(JType type, Function fn) {
 293             this.type = type;
 294             this.fn = fn;
 295         }
 296 
 297         @Override
 298         public String getDescriptor() {
 299             return type.getDescriptor();
 300         }
 301 
 302         @Override
 303         public String getSignature() {
 304             return type.getSignature();
 305         }
 306 
 307         Function getFunction() {
 308             return fn;
 309         }
 310 
 311         @Override
 312         public String toString() {
 313             return "FunctionalInterface: " + getDescriptor() + " for " + fn.getSignature();
 314         }
 315     }
 316 }
--- EOF ---