/* * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.apple.internal.jobjc.generator.model.types; import com.apple.internal.jobjc.generator.classes.RootJObjCClass; import com.apple.internal.jobjc.generator.model.CFType; import com.apple.internal.jobjc.generator.model.Clazz; import com.apple.internal.jobjc.generator.model.Opaque; import com.apple.internal.jobjc.generator.model.Struct; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.ComplexCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.IDCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.NSClassCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.PointerCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.SELCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.StructCoderDescriptor; import com.apple.internal.jobjc.generator.model.coders.CoderDescriptor.UnknownCoderDescriptor; import com.apple.internal.jobjc.generator.model.types.NType.NPrimitive; import com.apple.jobjc.ID; import com.apple.jobjc.NSClass; import com.apple.jobjc.NativeArgumentBuffer; import com.apple.jobjc.Pointer; import com.apple.jobjc.SEL; public abstract class JType { public abstract String getJavaTypeName(); public String getJavaClassName() { return getJavaTypeName().substring(getJavaTypeName().lastIndexOf('.') + 1); } public String getJavaReturnTypeName() { return getJavaTypeName(); } public String getReturnTypeCast() { return null; } public String getTypeNameAsParam() { return getJavaTypeName(); } public abstract CoderDescriptor getCoderDescriptor(); public String getDefaultReturnValue() { return "null"; } public String getAppendableDescription() { return getJavaTypeName().substring(getJavaTypeName().lastIndexOf('.') + 1); } /** * Used for primitive types (like int) that can't be used as generic arguments. This returns an appropriate Java class (like Integer). */ public JType getParameterizableType() { return this; } // // Writer ops // public String createDeclareBuffer(String contextName) { return "final " + NativeArgumentBuffer.class.getName() + " " + contextName + " = getRuntime().getThreadLocalState();"; } public String createInit(final String contextName, final String functionIdentifier, final String initWithObj) { return functionIdentifier + ".init(" + contextName + (initWithObj != null ? ", " + initWithObj : "") + ");"; } public String createInvoke(final String contextName, final String functionIdentifier) { return functionIdentifier + ".invoke(" + contextName + ");"; } public String createPop(final String contextName) { return getCoderDescriptor().getPopStatementFor(contextName, getJavaTypeName(), "returnValue", null); } public String createPopAddr(final String runtime, final String addr) { return getCoderDescriptor().getPopAddrStatementFor(runtime, addr, getJavaTypeName(), "returnValue", null); } public String createReturn() { final String preCast = getReturnTypeCast(); return "return " + (preCast == null ? "" : "(" + preCast + ")") + "returnValue;"; } // // Specialized // static public class JUnknown extends JType { final Type type; protected JUnknown(final Type type) { this.type = type; TypeCache.inst().getUnknownTypes().add(type); } @Override public String getJavaTypeName() { return "Object /* " + type + " */"; } @Override public String getAppendableDescription() { return "Unknown"; } @Override public CoderDescriptor getCoderDescriptor() { return UnknownCoderDescriptor.UNKNOWN_DESC; } } static class JVoid extends JType { public static JVoid INST = new JVoid(); @Override public String getJavaTypeName() { return "Void"; } @Override public String getJavaReturnTypeName() { return "void"; } @Override public CoderDescriptor getCoderDescriptor(){ return CoderDescriptor.VOID_DESC; } @Override public String createPop(final String contextName){ return ""; } @Override public String createReturn(){ return ""; } }; static class JSelector extends JType { public static JSelector INST = new JSelector(); @Override public String getJavaTypeName() { return SEL.class.getName(); } @Override public CoderDescriptor getCoderDescriptor() { return SELCoderDescriptor.INST; } }; static class JCFType extends JType{ final CFType cfType; public JCFType(final CFType cfType){ this.cfType = cfType; } @Override public String getJavaTypeName() { return cfType.parent.pkg + "." + cfType.name + "CFType"; } @Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; } @Override public String createPop(final String contextName) { return "\t\t" + getCoderDescriptor().getPopStatementFor(contextName, getJavaReturnTypeName(), "returnValue", "new " + getJavaTypeName()); } } static class JOpaque extends JType{ final Opaque opaque; public JOpaque(final Opaque opaque){ this.opaque = opaque; } @Override public String getJavaTypeName() { return opaque.parent.pkg + "." + opaque.name + "Opaque"; } @Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; } @Override public String createPop(final String contextName) { return "\t\t" + getCoderDescriptor().getPopStatementFor(contextName, getJavaReturnTypeName(), "returnValue", "new " + getJavaTypeName()); } } static class JPointer extends JType { static JType VOID_PTR = new JPointer(JVoid.INST); final JType subject; protected JPointer(final JType javaType) { this.subject = javaType; } @Override public String getJavaTypeName() { return Pointer.class.getName() + "<" + subject.getParameterizableType().getJavaTypeName() + ">"; } @Override public String getAppendableDescription() { return "PointerTo" + subject.getAppendableDescription(); } @Override public CoderDescriptor getCoderDescriptor() { return PointerCoderDescriptor.INST; } } static class JObject extends JType { public static JType ID_TYPE = new JType() { @Override public String getJavaTypeName() { return ID.class.getName(); } @Override public String getJavaReturnTypeName() { return "<T extends " + getJavaTypeName() + "> T"; } @Override public String getReturnTypeCast() { return "T"; } @Override public CoderDescriptor getCoderDescriptor() { return IDCoderDescriptor.INST; } }; final Type type; final Clazz clazz; public JObject(final Type type, final Clazz clazz) { this.type = type; this.clazz = clazz; } @Override public String getJavaTypeName() { return clazz.getFullPath();} @Override public CoderDescriptor getCoderDescriptor() { return IDCoderDescriptor.INST; } } static class JClass extends JType { public static JClass INST = new JClass(); @Override public String getJavaTypeName() { return NSClass.class.getName(); } @Override public String getJavaReturnTypeName() { return "<T extends " + super.getJavaReturnTypeName() + "> T"; } @Override public String getTypeNameAsParam() { return super.getTypeNameAsParam(); } @Override public String getReturnTypeCast() { return "T"; } @Override public CoderDescriptor getCoderDescriptor() { return NSClassCoderDescriptor.INST; } }; public static class JStruct extends JType { public final Struct struct; public JStruct(final Struct struct) { this.struct = struct; } @Override public String getJavaTypeName() { return struct.parent.pkg + "." + struct.name; } @Override public String getJavaReturnTypeName() { return getJavaTypeName(); } StructCoderDescriptor coderDescriptor = new StructCoderDescriptor(this); @Override public CoderDescriptor getCoderDescriptor() { return coderDescriptor; } public String createReturnValue() { return "\t\t" + getJavaReturnTypeName() + " returnValue = " + RootJObjCClass.runtimeFrameworkInstR(struct.parent.name) + ".make" + struct.name + "();"; } @Override public String createInvoke(final String contextName, final String functionIdentifier) { return createReturnValue() + "\n\t\t" + functionIdentifier + ".invoke(" + contextName + ", returnValue);"; } @Override public String createPop(final String contextName){ return ""; } } public static class JPrimitive extends JType { final Type type; final ComplexCoderDescriptor coderDescriptor; final JType parameterizable; public JPrimitive(final Type type, final ComplexCoderDescriptor coderDesc) { this.type = type; this.coderDescriptor = coderDesc; this.parameterizable = new JType() { @Override public String getJavaTypeName() { return coderDescriptor.getJavaObjectClass(); } @Override public CoderDescriptor getCoderDescriptor() { throw new RuntimeException(); } }; } @Override public String getJavaTypeName() { return coderDescriptor.getName(); } @Override public String getDefaultReturnValue() { return coderDescriptor.getDefaultReturnValue(); } @Override public JType getParameterizableType() { return parameterizable; } @Override public CoderDescriptor getCoderDescriptor() { return coderDescriptor; } /** * Return the suffix placed on java literals to indicate the type. If none applies, return ' '. */ public char getLiteralSuffix() { char t = ((NPrimitive)type.type64).type; switch(t){ case 'l': case 'L': case 'f': case 'd': return t; case 'q': case 'Q': return 'L'; } return ' '; } } }