lwjgl/src/java/org/lwjgl/util/generator/JavaMethodsGenerator.java

747 lines
34 KiB
Java
Raw Normal View History

/*
2008-04-07 14:36:09 -04:00
* Copyright (c) 2002-2008 LWJGL Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of 'LWJGL' nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
2005-02-20 14:28:34 -05:00
package org.lwjgl.util.generator;
/**
*
* This class generates the methods in the generated java source files.
*
* @author elias_naur <elias_naur@users.sourceforge.net>
* @version $Revision$
2006-03-23 14:32:21 -05:00
* $Id$
*/
import org.lwjgl.PointerBuffer;
import org.lwjgl.util.generator.opengl.GLreturn;
import com.sun.mirror.apt.*;
import com.sun.mirror.declaration.*;
import com.sun.mirror.type.*;
import java.io.*;
import java.nio.*;
import java.util.*;
import java.util.regex.*;
public class JavaMethodsGenerator {
private static final String SAVED_PARAMETER_POSTFIX = "_saved";
public static void generateMethodsJava(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration interface_decl, boolean generate_error_checks, boolean context_specific) {
for (MethodDeclaration method : interface_decl.getMethods())
generateMethodJava(env, type_map, writer, interface_decl, method, generate_error_checks, context_specific);
}
private static void generateMethodJava(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration interface_decl, MethodDeclaration method, boolean generate_error_checks, boolean context_specific) {
writer.println();
if (Utils.isMethodIndirect(generate_error_checks, context_specific, method)) {
if (method.getAnnotation(GenerateAutos.class) != null) {
printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.AUTOS, generate_error_checks, context_specific);
}
Collection<Map<ParameterDeclaration, TypeInfo>> cross_product = TypeInfo.getTypeInfoCrossProduct(type_map, method);
for (Map<ParameterDeclaration, TypeInfo> typeinfos_instance : cross_product) {
printMethodWithMultiType(env, type_map, writer, interface_decl, method, typeinfos_instance, Mode.NORMAL, generate_error_checks, context_specific);
}
}
if ( method.getAnnotation(CachedResult.class) != null && !method.getAnnotation(CachedResult.class).isRange() ) {
printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.CACHEDRESULT, generate_error_checks, context_specific);
}
Reuse reuse_annotation = method.getAnnotation(Reuse.class);
Alternate alt_annotation = method.getAnnotation(Alternate.class);
if ( alt_annotation == null || (alt_annotation.nativeAlt() && !alt_annotation.skipNative()) ) {
2010-03-16 13:58:48 -04:00
if ( alt_annotation != null && method.getSimpleName().equals(alt_annotation.value()) )
throw new RuntimeException("An alternate function with native code should have a different name than the main function.");
if ( reuse_annotation == null )
printJavaNativeStub(writer, method, Mode.NORMAL, generate_error_checks, context_specific);
if (Utils.hasMethodBufferObjectParameter(method)) {
printMethodWithMultiType(env, type_map, writer, interface_decl, method, TypeInfo.getDefaultTypeInfoMap(method), Mode.BUFFEROBJECT, generate_error_checks, context_specific);
if ( reuse_annotation == null )
printJavaNativeStub(writer, method, Mode.BUFFEROBJECT, generate_error_checks, context_specific);
}
}
}
private static void printJavaNativeStub(PrintWriter writer, MethodDeclaration method, Mode mode, boolean generate_error_checks, boolean context_specific) {
if (Utils.isMethodIndirect(generate_error_checks, context_specific, method)) {
writer.print("\tstatic native ");
} else {
Utils.printDocComment(writer, method);
writer.print("\tpublic static native ");
}
writer.print(getResultType(method, true));
writer.print(" " + Utils.getSimpleNativeMethodName(method, generate_error_checks, context_specific));
if (mode == Mode.BUFFEROBJECT)
writer.print(Utils.BUFFER_OBJECT_METHOD_POSTFIX);
writer.print("(");
boolean first_parameter = generateParametersJava(writer, method, TypeInfo.getDefaultTypeInfoMap(method), true, true, mode);
if (context_specific) {
if (!first_parameter)
writer.print(", ");
writer.print("long " + Utils.FUNCTION_POINTER_VAR_NAME);
}
writer.println(");");
}
private static boolean generateParametersJava(PrintWriter writer, MethodDeclaration method, Map<ParameterDeclaration, TypeInfo> typeinfos_instance, boolean native_stub, final boolean printTypes, Mode mode) {
boolean first_parameter = true;
for (ParameterDeclaration param : method.getParameters()) {
if ( native_stub && (param.getAnnotation(Helper.class) != null && !param.getAnnotation(Helper.class).passToNative()) )
continue;
final Constant constant_annotation = param.getAnnotation(Constant.class);
if ( constant_annotation != null && constant_annotation.isNative() )
continue;
AnnotationMirror auto_annotation_mirror = Utils.getParameterAutoAnnotation(param);
boolean hide_auto_parameter = mode == Mode.NORMAL && !native_stub && auto_annotation_mirror != null;
if (hide_auto_parameter) {
AutoType auto_type_annotation = param.getAnnotation(AutoType.class);
if (auto_type_annotation != null) {
ParameterDeclaration auto_parameter = Utils.findParameter(method, auto_type_annotation.value());
TypeInfo auto_param_type_info = typeinfos_instance.get(auto_parameter);
if (auto_param_type_info.getSignedness() == Signedness.BOTH) {
if (!first_parameter)
writer.print(", ");
first_parameter = false;
if ( printTypes )
writer.print("boolean ");
2010-10-04 13:04:46 -04:00
writer.print(TypeInfo.UNSIGNED_PARAMETER_NAME);
}
}
} else if (
param.getAnnotation(Result.class) == null
&& (native_stub || ((param.getAnnotation(Constant.class) == null || param.getAnnotation(Constant.class).keepParam()) && !Utils.isReturnParameter(method, param)))
&& (mode != Mode.AUTOS || getAutoTypeParameter(method, param) == null)
) {
first_parameter = generateParameterJava(writer, param, typeinfos_instance.get(param), native_stub, printTypes, first_parameter, mode);
}
}
CachedResult cached_result_annotation = method.getAnnotation(CachedResult.class);
TypeMirror result_type = Utils.getMethodReturnType(method);
if ((native_stub && Utils.getNIOBufferType(result_type) != null) || Utils.needResultSize(method)) {
AutoSize auto_size_annotation = method.getAnnotation(AutoSize.class);
if ( auto_size_annotation == null || !auto_size_annotation.isNative() ) {
if (cached_result_annotation == null || !cached_result_annotation.isRange()) {
if (!first_parameter)
writer.print(", ");
first_parameter = false;
if ( printTypes )
writer.print("long ");
writer.print(Utils.RESULT_SIZE_NAME);
}
}
}
if (cached_result_annotation != null) {
if (!first_parameter)
writer.print(", ");
if ( mode == Mode.CACHEDRESULT ) {
if ( printTypes )
writer.print("long ");
writer.print(Utils.CACHED_BUFFER_LENGTH_NAME + ", ");
}
first_parameter = false;
if ( printTypes )
writer.print(getResultType(method, native_stub));
writer.print(" " + Utils.CACHED_BUFFER_NAME);
}
return first_parameter;
}
private static boolean generateParameterJava(PrintWriter writer, ParameterDeclaration param, TypeInfo type_info, boolean native_stub, final boolean printTypes, boolean first_parameter, Mode mode) {
Class buffer_type = Utils.getNIOBufferType(param.getType());
if (!first_parameter)
writer.print(", ");
BufferObject bo_annotation = param.getAnnotation(BufferObject.class);
if (bo_annotation != null && mode == Mode.BUFFEROBJECT) {
if (buffer_type == null)
throw new RuntimeException("type of " + param + " is not a nio Buffer parameter but is annotated as buffer object");
if ( printTypes )
writer.print("long ");
writer.print(param.getSimpleName() + Utils.BUFFER_OBJECT_PARAMETER_POSTFIX);
} else {
if ( native_stub && param.getAnnotation(PointerWrapper.class) != null )
writer.print("long ");
else {
Class type = type_info.getType();
if ( native_stub && (type == CharSequence.class || type == CharSequence[].class || type == PointerBuffer.class || Buffer.class.isAssignableFrom(type) ) )
writer.print("long ");
else if ( printTypes )
writer.print(type_info.getType().getSimpleName() + " ");
}
AutoSize auto_size_annotation = param.getAnnotation(AutoSize.class);
if ( auto_size_annotation != null )
writer.print(auto_size_annotation.value() + "_");
writer.print(param.getSimpleName());
}
return false;
}
2011-05-17 12:53:57 -04:00
private static void printBufferObjectCheck(PrintWriter writer, BufferKind kind, Mode mode, boolean context_specific) {
String bo_check_method_name = kind.toString();
writer.print("\t\t" + Utils.CHECKS_CLASS_NAME + ".ensure" + bo_check_method_name);
if (mode == Mode.BUFFEROBJECT)
writer.print("enabled");
else
writer.print("disabled");
2011-05-17 12:53:57 -04:00
if ( context_specific )
writer.println("(caps);");
else
writer.println("();");
}
2011-05-17 12:53:57 -04:00
private static void printBufferObjectChecks(PrintWriter writer, MethodDeclaration method, Mode mode, boolean context_specific) {
EnumSet<BufferKind> check_set = EnumSet.noneOf(BufferKind.class);
for (ParameterDeclaration param : method.getParameters()) {
BufferObject bo_annotation = param.getAnnotation(BufferObject.class);
if (bo_annotation != null)
check_set.add(bo_annotation.value());
}
for (BufferKind kind : check_set)
2011-05-17 12:53:57 -04:00
printBufferObjectCheck(writer, kind, mode, context_specific);
}
private static void printMethodWithMultiType(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration interface_decl, MethodDeclaration method, Map<ParameterDeclaration, TypeInfo> typeinfos_instance, Mode mode, boolean generate_error_checks, boolean context_specific) {
Utils.printDocComment(writer, method);
if ( method.getAnnotation(Deprecated.class) != null )
writer.println("\t@Deprecated");
if ( interface_decl.getAnnotation(Private.class) == null && method.getAnnotation(Private.class) == null )
writer.print("\tpublic static ");
else
writer.print("\tstatic ");
writer.print(getResultType(method, false));
StripPostfix strip_annotation = method.getAnnotation(StripPostfix.class);
String method_name;
Alternate alt_annotation = method.getAnnotation(Alternate.class);
method_name = alt_annotation == null || alt_annotation.javaAlt() ? method.getSimpleName() : alt_annotation.value();
if (strip_annotation != null && mode == Mode.NORMAL)
method_name = getPostfixStrippedName(type_map, interface_decl, method);
writer.print(" " + method_name + "(");
generateParametersJava(writer, method, typeinfos_instance, false, true, mode);
writer.println(") {");
final TypeMirror result_type = Utils.getMethodReturnType(method);
boolean has_result = !result_type.equals(env.getTypeUtils().getVoidType());
final Reuse reuse_annotation = method.getAnnotation(Reuse.class);
if ( reuse_annotation != null ) {
writer.print("\t\t");
if ( has_result || method.getAnnotation(GLreturn.class) != null )
writer.print("return ");
writer.print(reuse_annotation.value() + "." + (reuse_annotation.method().length() > 0 ? reuse_annotation.method() : method_name) + "(");
generateParametersJava(writer, method, typeinfos_instance, false, false, mode);
writer.println(");\n\t}");
return;
}
if (context_specific) {
type_map.printCapabilitiesInit(writer);
writer.print("\t\tlong " + Utils.FUNCTION_POINTER_VAR_NAME + " = " + type_map.getCapabilities() + ".");
writer.println(Utils.getFunctionAddressName(interface_decl, method, true) + ";");
writer.print("\t\tBufferChecks.checkFunctionAddress(");
writer.println(Utils.FUNCTION_POINTER_VAR_NAME + ");");
}
final Code code_annotation = method.getAnnotation(Code.class);
if (code_annotation != null && code_annotation.value().length() > 0)
writer.println(code_annotation.value());
2011-05-17 12:53:57 -04:00
printBufferObjectChecks(writer, method, mode, context_specific);
printParameterChecks(writer, method, typeinfos_instance, mode, generate_error_checks);
2011-05-17 12:53:57 -04:00
printParameterCaching(writer, interface_decl, method, mode, context_specific);
if ( code_annotation != null && code_annotation.javaBeforeNative().length() > 0 )
writer.println(code_annotation.javaBeforeNative());
writer.print("\t\t");
final PointerWrapper pointer_wrapper_annotation = method.getAnnotation(PointerWrapper.class);
if (has_result) {
writer.print(getResultType(method, false) + " " + Utils.RESULT_VAR_NAME);
if ( code_annotation != null && code_annotation.tryBlock() ) {
writer.print(" = " + getDefaultResultValue(method));
writer.println(";\n\t\ttry {");
writer.print("\t\t\t" + Utils.RESULT_VAR_NAME);
}
writer.print(" = ");
if ( pointer_wrapper_annotation != null ) {
if ( pointer_wrapper_annotation.factory().length() > 0 )
writer.print(pointer_wrapper_annotation.factory() + "(");
else
writer.print("new " + getResultType(method, false) + "(");
}
} else if ( method.getAnnotation(GLreturn.class) != null ) {
has_result = true;
Utils.printGLReturnPre(writer, method, method.getAnnotation(GLreturn.class), type_map);
}
writer.print(Utils.getSimpleNativeMethodName(method, generate_error_checks, context_specific));
if (mode == Mode.BUFFEROBJECT)
writer.print(Utils.BUFFER_OBJECT_METHOD_POSTFIX);
writer.print("(");
boolean first_parameter = printMethodCallArguments(writer, method, typeinfos_instance, mode, type_map);
if (context_specific) {
if (!first_parameter)
writer.print(", ");
writer.print(Utils.FUNCTION_POINTER_VAR_NAME);
}
if ( has_result && pointer_wrapper_annotation != null ) {
writer.print(")");
if ( pointer_wrapper_annotation.params().length() > 0 )
writer.print(", " + pointer_wrapper_annotation.params());
}
writer.println(");");
if ( code_annotation != null && code_annotation.javaAfterNative().length() > 0 )
writer.println(code_annotation.javaAfterNative());
final String tabs = code_annotation != null && code_annotation.tryBlock() ? "\t\t\t" : "\t\t";
if (generate_error_checks && method.getAnnotation(NoErrorCheck.class) == null)
type_map.printErrorCheckMethod(writer, method, tabs);
// DISABLED: indirect buffer support
//printNondirectParameterCopies(writer, method, mode);
if (has_result) {
if ( method.getAnnotation(GLreturn.class) == null ) {
if ( ByteBuffer.class.equals(Utils.getJavaType(result_type)) )
writer.println(tabs + "return LWJGLUtil.CHECKS && " + Utils.RESULT_VAR_NAME + " == null ? null : " + Utils.RESULT_VAR_NAME + ".order(ByteOrder.nativeOrder());"); // safeNewBuffer returns a direct ByteBuffer with BIG_ENDIAN order.
else
writer.println(tabs + "return " + Utils.RESULT_VAR_NAME + ";");
} else
Utils.printGLReturnPost(writer, method, method.getAnnotation(GLreturn.class), type_map);
}
if ( code_annotation != null && code_annotation.tryBlock() ) {
writer.println("\t\t} finally {");
writer.println(code_annotation.javaFinally());
writer.println("\t\t}");
}
writer.println("\t}");
}
private static String getExtensionPostfix(InterfaceDeclaration interface_decl) {
String interface_simple_name = interface_decl.getSimpleName();
Extension extension_annotation = interface_decl.getAnnotation(Extension.class);
if (extension_annotation == null) {
int underscore_index = interface_simple_name.indexOf("_");
if (underscore_index != -1)
return interface_simple_name.substring(0, underscore_index);
else
return "";
} else
return extension_annotation.postfix();
}
private static ParameterDeclaration getAutoTypeParameter(MethodDeclaration method, ParameterDeclaration target_parameter) {
for (ParameterDeclaration param : method.getParameters()) {
AnnotationMirror auto_annotation = Utils.getParameterAutoAnnotation(param);
if (auto_annotation != null) {
Class annotation_type = NativeTypeTranslator.getClassFromType(auto_annotation.getAnnotationType());
String parameter_name;
if (annotation_type.equals(AutoType.class))
parameter_name = param.getAnnotation(AutoType.class).value();
else if (annotation_type.equals(AutoSize.class))
parameter_name = param.getAnnotation(AutoSize.class).value();
else
throw new RuntimeException("Unknown annotation type " + annotation_type);
if (target_parameter.getSimpleName().equals(parameter_name))
return param;
}
}
return null;
}
2005-02-15 12:13:05 -05:00
private static boolean hasAnyParameterAutoTypeAnnotation(MethodDeclaration method, ParameterDeclaration target_param) {
for (ParameterDeclaration param : method.getParameters()) {
AutoType auto_type_annotation = param.getAnnotation(AutoType.class);
if (auto_type_annotation != null) {
ParameterDeclaration type_target_param = Utils.findParameter(method, auto_type_annotation.value());
if (target_param.equals(type_target_param))
return true;
}
}
return false;
}
private static final Map<String, Pattern> postfixPatterns = new HashMap<String, Pattern>();
private static Pattern getPostfixPattern(String regex) {
Pattern pattern = postfixPatterns.get(regex);
if ( pattern == null )
postfixPatterns.put(regex, pattern = Pattern.compile(regex));
return pattern;
}
private static String getPostfixStrippedName(TypeMap type_map, InterfaceDeclaration interface_decl, MethodDeclaration method) {
StripPostfix strip_annotation = method.getAnnotation(StripPostfix.class);
ParameterDeclaration postfix_parameter = Utils.findParameter(method, strip_annotation.value());
String postfix = strip_annotation.postfix();
boolean postfixOverride = !("NULL".equals(postfix) && strip_annotation.hasPostfix());
if ( !postfixOverride ) {
PostfixTranslator translator = new PostfixTranslator(type_map, postfix_parameter);
postfix_parameter.getType().accept(translator);
postfix = translator.getSignature();
} else if ( !strip_annotation.hasPostfix() )
postfix = "";
String method_name;
Alternate alt_annotation = method.getAnnotation(Alternate.class);
method_name = alt_annotation == null || alt_annotation.javaAlt() ? method.getSimpleName() : alt_annotation.value();
String extension_postfix = "NULL".equals(strip_annotation.extension()) ? getExtensionPostfix(interface_decl) : strip_annotation.extension();
Matcher matcher = getPostfixPattern(
postfixOverride
? (postfix + "(?:v)?" + extension_postfix + "$")
: ("(?:" + postfix + "(?:v)?|i(?:64)?_v|v)" + extension_postfix + "$")
).matcher(method_name);
if ( !matcher.find() )
throw new RuntimeException(method_name + " is specified as being postfix stripped on parameter " + postfix_parameter + ", but it's postfix is neither '" + postfix + "' nor 'v'");
return method_name.substring(0, matcher.start()) + extension_postfix;
}
private static int getBufferElementSizeExponent(Class c) {
if (IntBuffer.class.equals(c))
return 2;
else if (LongBuffer.class.equals(c))
return 3;
else if (DoubleBuffer.class.equals(c))
return 3;
else if (ShortBuffer.class.equals(c))
return 1;
else if (ByteBuffer.class.equals(c))
return 0;
else if (FloatBuffer.class.equals(c))
return 2;
else
throw new RuntimeException(c + " is not allowed");
}
private static boolean printMethodCallArgument(PrintWriter writer, MethodDeclaration method, ParameterDeclaration param, Map<ParameterDeclaration, TypeInfo> typeinfos_instance, Mode mode, boolean first_parameter, TypeMap type_map) {
if (!first_parameter)
writer.print(", ");
AnnotationMirror auto_annotation = Utils.getParameterAutoAnnotation(param);
Constant constant_annotation = param.getAnnotation(Constant.class);
if (constant_annotation != null) {
writer.print(constant_annotation.value());
} else if (auto_annotation != null && mode == Mode.NORMAL) {
Class param_type = NativeTypeTranslator.getClassFromType(auto_annotation.getAnnotationType());
if (AutoType.class.equals(param_type)) {
final AutoType auto_type_annotation = param.getAnnotation(AutoType.class);
final ParameterDeclaration auto_parameter = Utils.findParameter(method, auto_type_annotation.value());
final String auto_type = typeinfos_instance.get(auto_parameter).getAutoType();
if ( auto_type == null )
throw new RuntimeException("No auto type for parameter " + param.getSimpleName() + " in method " + method);
writer.print(auto_type);
} else if (AutoSize.class.equals(param_type)) {
final AutoSize auto_size_annotation = param.getAnnotation(AutoSize.class);
if ( !auto_size_annotation.useExpression() ) {
final String auto_parameter_name = auto_size_annotation.value();
final ParameterDeclaration auto_target_param = Utils.findParameter(method, auto_parameter_name);
final TypeInfo auto_target_type_info = typeinfos_instance.get(auto_target_param);
final boolean shift_remaining = !hasAnyParameterAutoTypeAnnotation(method, auto_target_param) && Utils.isParameterMultiTyped(auto_target_param);
int shifting = 0;
if ( shift_remaining ) {
shifting = getBufferElementSizeExponent(auto_target_type_info.getType());
if ( shifting > 0 )
writer.print("(");
}
if ( auto_size_annotation.canBeNull() )
writer.print("(" + auto_parameter_name + " == null ? 0 : " + auto_parameter_name + ".remaining())");
else
writer.print(auto_parameter_name + ".remaining()");
// Shift the remaining if the target parameter is multityped and there's no AutoType to track type
if (shift_remaining && shifting > 0) {
writer.print(" << " + shifting);
writer.print(")");
}
}
writer.print(auto_size_annotation.expression());
} else
throw new RuntimeException("Unknown auto annotation " + param_type);
} else {
if (mode == Mode.BUFFEROBJECT && param.getAnnotation(BufferObject.class) != null) {
writer.print(param.getSimpleName() + Utils.BUFFER_OBJECT_PARAMETER_POSTFIX);
} else {
Class type = typeinfos_instance.get(param).getType();
Check check_annotation = param.getAnnotation(Check.class);
boolean hide_buffer = mode == Mode.AUTOS && getAutoTypeParameter(method, param) != null;
if (hide_buffer) {
writer.print("0L");
} else {
if ( type == CharSequence.class || type == CharSequence[].class ) {
final String offset = Utils.getStringOffset(method, param);
writer.print("APIUtil.getBuffer");
if ( param.getAnnotation(NullTerminated.class) != null )
writer.print("NT");
writer.print('(');
writer.print(type_map.getAPIUtilParam(true));
writer.print(param.getSimpleName());
if ( offset != null )
writer.print(", " + offset);
writer.print(")");
} else {
final AutoSize auto_size_annotation = param.getAnnotation(AutoSize.class);
if ( auto_size_annotation != null )
writer.print(auto_size_annotation.value() + "_");
final Class buffer_type = Utils.getNIOBufferType(param.getType());
if ( buffer_type == null )
writer.print(param.getSimpleName());
else {
writer.print("MemoryUtil.getAddress");
if ( check_annotation != null && check_annotation.canBeNull() )
writer.print("Safe");
writer.print("(");
writer.print(param.getSimpleName());
writer.print(")");
}
}
}
if ( type != long.class ) {
PointerWrapper pointer_annotation = param.getAnnotation(PointerWrapper.class);
if ( pointer_annotation != null ) {
if ( pointer_annotation.canBeNull() )
writer.print(" == null ? 0 : " + param.getSimpleName());
writer.print(".getPointer()");
}
}
}
}
return false;
}
private static boolean printMethodCallArguments(PrintWriter writer, MethodDeclaration method, Map<ParameterDeclaration, TypeInfo> typeinfos_instance, Mode mode, TypeMap type_map) {
boolean first_parameter = true;
for ( ParameterDeclaration param : method.getParameters() ) {
if ( param.getAnnotation(Result.class) != null || (param.getAnnotation(Helper.class) != null && !param.getAnnotation(Helper.class).passToNative()) )
continue;
final Constant constant_annotation = param.getAnnotation(Constant.class);
if ( constant_annotation== null || !constant_annotation.isNative() )
first_parameter = printMethodCallArgument(writer, method, param, typeinfos_instance, mode, first_parameter, type_map);
}
if (Utils.getNIOBufferType(Utils.getMethodReturnType(method)) != null) {
if (method.getAnnotation(CachedResult.class) != null && method.getAnnotation(CachedResult.class).isRange()) {
first_parameter = false;
Utils.printExtraCallArguments(writer, method, "");
} else {
AutoSize auto_size_annotation = method.getAnnotation(AutoSize.class);
if ( auto_size_annotation == null || !auto_size_annotation.isNative() ) {
if (!first_parameter)
writer.print(", ");
first_parameter = false;
String result_size_expression;
if ( mode == Mode.CACHEDRESULT )
result_size_expression = Utils.CACHED_BUFFER_LENGTH_NAME;
else if ( auto_size_annotation == null )
result_size_expression = Utils.RESULT_SIZE_NAME;
else
result_size_expression = auto_size_annotation.value();
Utils.printExtraCallArguments(writer, method, result_size_expression);
}
}
}
return first_parameter;
}
2011-05-17 12:53:57 -04:00
private static void printParameterCaching(PrintWriter writer, InterfaceDeclaration interface_decl, MethodDeclaration method, Mode mode, boolean context_specific) {
for (ParameterDeclaration param : method.getParameters()) {
Class java_type = Utils.getJavaType(param.getType());
CachedReference cachedReference = param.getAnnotation(CachedReference.class);
if (Buffer.class.isAssignableFrom(java_type) &&
cachedReference != null &&
(mode != Mode.BUFFEROBJECT || param.getAnnotation(BufferObject.class) == null) &&
param.getAnnotation(Result.class) == null) {
2011-05-17 12:53:57 -04:00
writer.print("\t\tif ( LWJGLUtil.CHECKS ) StateTracker.");
if ( context_specific )
writer.print("getReferences(caps).");
else
writer.print("getTracker().");
if(cachedReference.name().length() > 0) {
writer.print(cachedReference.name());
} else {
writer.print(Utils.getReferenceName(interface_decl, method, param));
}
if(cachedReference.index().length() > 0) {
writer.print("[" + cachedReference.index() + "]");
}
writer.println(" = " + param.getSimpleName() + ";");
}
}
}
private static void printParameterChecks(PrintWriter writer, MethodDeclaration method, Map<ParameterDeclaration, TypeInfo> typeinfos, Mode mode, final boolean generate_error_checks) {
if ( mode == Mode.NORMAL ) {
final GenerateAutos gen_autos_annotation = method.getAnnotation(GenerateAutos.class);
if ( gen_autos_annotation != null && gen_autos_annotation.sizeVariables().length > 0 ) {
// For the auto-generated parameters, declare and init a size variable (that can be reused by @Code)
for ( final ParameterDeclaration param : method.getParameters() ) {
if ( Arrays.binarySearch(gen_autos_annotation.sizeVariables(), param.getSimpleName()) >= 0 ) {
final int shifting = getBufferElementSizeExponent(typeinfos.get(param).getType());
final Check check_annotation = param.getAnnotation(Check.class);
writer.print("\t\tlong " + param.getSimpleName() + "_size = ");
if ( check_annotation == null || !check_annotation.canBeNull() )
writer.println(param.getSimpleName() + ".remaining() << " + shifting + ";");
else
writer.println(param.getSimpleName() + " == null ? 0 : " + param.getSimpleName() + ".remaining() << " + shifting + ";");
}
}
}
}
for (ParameterDeclaration param : method.getParameters()) {
Class java_type = Utils.getJavaType(param.getType());
if ( java_type.isArray() || (Utils.isAddressableType(java_type) &&
(mode != Mode.BUFFEROBJECT || param.getAnnotation(BufferObject.class) == null) &&
(mode != Mode.AUTOS || getAutoTypeParameter(method, param) == null) &&
param.getAnnotation(Result.class) == null &&
!Utils.isReturnParameter(method, param)) ) {
String check_value = null;
boolean can_be_null = false;
Check check_annotation = param.getAnnotation(Check.class);
if (check_annotation != null) {
check_value = check_annotation.value();
can_be_null = check_annotation.canBeNull();
}
if ((Buffer.class.isAssignableFrom(java_type) || PointerBuffer.class.isAssignableFrom(java_type)) && param.getAnnotation(Constant.class) == null) {
boolean out_parameter = param.getAnnotation(OutParameter.class) != null;
TypeInfo typeinfo = typeinfos.get(param);
printParameterCheck(writer, method, param.getSimpleName(), typeinfo.getType().getSimpleName(), check_value, can_be_null, param.getAnnotation(NullTerminated.class), out_parameter, generate_error_checks);
} else if ( String.class.equals(java_type)) {
if (!can_be_null)
writer.println("\t\tBufferChecks.checkNotNull(" + param.getSimpleName() + ");");
} else if ( java_type.isArray() ) {
final TypeInfo typeinfo = typeinfos.get(param);
printArrayParameterCheck(writer, param.getSimpleName(), typeinfo.getType().getSimpleName(), check_value, can_be_null);
}
}
}
if (method.getAnnotation(CachedResult.class) != null)
printParameterCheck(writer, method, Utils.CACHED_BUFFER_NAME, null, null, true, null, false, generate_error_checks);
}
private static void printParameterCheck(PrintWriter writer, MethodDeclaration method, String name, String type, String check_value, boolean can_be_null, NullTerminated null_terminated, boolean out_parameter, boolean generate_error_checks) {
String tabs;
if (can_be_null) {
writer.print("\t\tif (" + name + " != null)");
if ( null_terminated != null )
writer.println(" {");
else
writer.println();
tabs = "\t\t\t";
} else
tabs = "\t\t";
writer.print(tabs + "BufferChecks.check");
if (check_value != null && check_value.length() > 0) {
writer.print("Buffer");
if ( "Buffer".equals(type) )
writer.print("Size"); // Check size only, Buffer.isDirect() was added in 1.6, cannot use yet. TODO: Remove?
writer.print("(" + name + ", " + check_value);
} else {
writer.print("Direct(" + name);
}
writer.println(");");
if ( can_be_null && generate_error_checks ) {
final Check check_annotation = method.getAnnotation(Check.class);
if ( check_annotation != null && check_annotation.value().equals(name) ) {
writer.println("\t\telse");
writer.println("\t\t\t" + name + " = APIUtil.getBufferIntDebug();"); // Use an exclusive buffer here
}
}
if (null_terminated != null) {
writer.print(tabs + "BufferChecks.checkNullTerminated(");
writer.print(name);
if ( null_terminated.value().length() > 0 ) {
writer.print(", ");
writer.print(null_terminated.value());
}
writer.println(");");
if ( can_be_null )
writer.println("\t\t}");
}
}
private static void printArrayParameterCheck(PrintWriter writer, String name, String type, String check_value, boolean can_be_null) {
String tabs;
if ( can_be_null ) {
writer.println("\t\tif (" + name + " != null)");
tabs = "\t\t\t";
} else
tabs = "\t\t";
writer.print(tabs + "BufferChecks.checkArray(" + name);
if ( check_value != null && check_value.length() > 0)
writer.print(", " + check_value);
writer.println(");");
}
private static String getResultType(MethodDeclaration method, boolean native_stub) {
if ( native_stub && method.getAnnotation(PointerWrapper.class) != null )
return "long";
else if ( !native_stub && method.getAnnotation(GLreturn.class) != null )
return Utils.getMethodReturnType(method, method.getAnnotation(GLreturn.class), false);
else
return Utils.getJavaType(Utils.getMethodReturnType(method)).getSimpleName();
}
private static String getDefaultResultValue(MethodDeclaration method) {
if ( method.getAnnotation(GLreturn.class) != null ) {
final String type = Utils.getMethodReturnType(method, method.getAnnotation(GLreturn.class), false);
if ( "boolean".equals(type) )
return "false";
else if ( Character.isLowerCase(type.charAt(0)) )
return "0";
else
return "null";
} else {
final Class type = Utils.getJavaType(Utils.getMethodReturnType(method));
if ( type.isPrimitive() ) {
if ( type == boolean.class )
return "false";
else
return "0";
} else
return "null";
}
}
}