2005-02-15 06:05:36 -05:00
/ *
2008-04-07 14:36:09 -04:00
* Copyright ( c ) 2002 - 2008 LWJGL Project
2005-02-15 06:05:36 -05:00
* 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 ;
2005-02-15 06:05:36 -05:00
/ * *
*
* This class generates the methods in the generated java source files .
*
* @author elias_naur < elias_naur @users.sourceforge.net >
2014-09-14 10:07:56 -04:00
* @version $Revision$ $Id$
2005-02-15 06:05:36 -05:00
* /
2014-09-14 10:16:51 -04:00
import org.lwjgl.PointerBuffer ;
import org.lwjgl.util.generator.opengl.GLreturn ;
import java.io.PrintWriter ;
2005-02-15 06:05:36 -05:00
import java.nio.* ;
2014-08-16 08:39:04 -04:00
import java.util.* ;
2014-09-14 10:07:56 -04:00
import java.util.regex.Matcher ;
import java.util.regex.Pattern ;
import javax.annotation.processing.ProcessingEnvironment ;
import javax.lang.model.element.AnnotationMirror ;
import javax.lang.model.element.ExecutableElement ;
import javax.lang.model.element.TypeElement ;
import javax.lang.model.element.VariableElement ;
import javax.lang.model.type.TypeKind ;
import javax.lang.model.type.TypeMirror ;
2005-02-15 06:05:36 -05:00
public class JavaMethodsGenerator {
2014-09-14 10:07:56 -04:00
2014-09-14 10:16:51 -04:00
private static final String SAVED_PARAMETER_POSTFIX = " _saved " ;
public static void generateMethodsJava ( ProcessingEnvironment env , TypeMap type_map , PrintWriter writer , TypeElement interface_decl , boolean generate_error_checks , boolean context_specific ) {
for ( ExecutableElement method : Utils . getMethods ( interface_decl ) ) {
generateMethodJava ( env , type_map , writer , interface_decl , method , generate_error_checks , context_specific ) ;
}
}
/ * *
* TODO : fix info multi - type methods print .
* /
private static void generateMethodJava ( ProcessingEnvironment env , TypeMap type_map , PrintWriter writer , TypeElement interface_decl , ExecutableElement 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 < VariableElement , TypeInfo > > cross_product = TypeInfo . getTypeInfoCrossProduct ( env , type_map , method ) ;
for ( Map < VariableElement , 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 ( ) ) ) {
if ( alt_annotation ! = null & & method . getSimpleName ( ) . toString ( ) . 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 ( env , 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 ( env , writer , method , Mode . BUFFEROBJECT , generate_error_checks , context_specific ) ;
}
}
}
}
private static void printJavaNativeStub ( ProcessingEnvironment env , PrintWriter writer , ExecutableElement 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 , env ) ;
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 ( env , 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 ( ProcessingEnvironment env , PrintWriter writer , ExecutableElement method , Map < VariableElement , TypeInfo > typeinfos_instance , boolean native_stub , final boolean printTypes , Mode mode ) {
boolean first_parameter = true ;
for ( VariableElement 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 ;
}
/ * env . getMessager ( ) . printMessage ( Diagnostic . Kind . NOTE , param . getAnnotationMirrors ( )
2014-09-14 10:07:56 -04:00
+ " ( " + typeinfos_instance . get ( param ) . getType ( ) + " ) " , param ) ; * /
2014-09-14 10:16:51 -04:00
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 ) {
VariableElement 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 " ) ;
}
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 , VariableElement param , TypeInfo type_info , boolean native_stub , final boolean printTypes , boolean first_parameter , Mode mode ) {
Class buffer_type = Utils . getNIOBufferType ( param . asType ( ) ) ;
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 . 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 ;
}
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 " ) ;
}
if ( context_specific ) {
writer . println ( " (caps); " ) ;
} else {
writer . println ( " (); " ) ;
}
}
private static void printBufferObjectChecks ( PrintWriter writer , ExecutableElement method , Mode mode , boolean context_specific ) {
EnumSet < BufferKind > check_set = EnumSet . noneOf ( BufferKind . class ) ;
for ( VariableElement 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 ) {
printBufferObjectCheck ( writer , kind , mode , context_specific ) ;
}
}
private static void printMethodWithMultiType ( ProcessingEnvironment env , TypeMap type_map , PrintWriter writer , TypeElement interface_decl , ExecutableElement method , Map < VariableElement , TypeInfo > typeinfos_instance , Mode mode , boolean generate_error_checks , boolean context_specific ) {
Utils . printDocComment ( writer , method , env ) ;
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 ( ) . toString ( ) : alt_annotation . value ( ) ;
if ( strip_annotation ! = null & & mode = = Mode . NORMAL ) {
method_name = getPostfixStrippedName ( type_map , interface_decl , method ) ;
}
writer . print ( " " + method_name + " ( " ) ;
generateParametersJava ( env , writer , method , typeinfos_instance , false , true , mode ) ;
writer . println ( " ) { " ) ;
final TypeMirror result_type = Utils . getMethodReturnType ( method ) ;
boolean has_result = ! result_type . equals ( env . getTypeUtils ( ) . getNoType ( TypeKind . VOID ) ) ;
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 ( env , 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 ( ) ) ;
}
printBufferObjectChecks ( writer , method , mode , context_specific ) ;
printParameterChecks ( writer , method , typeinfos_instance , mode , generate_error_checks ) ;
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 ) ;
}
2010-01-31 11:40:51 -05:00
// DISABLED: indirect buffer support
2014-09-14 10:16:51 -04:00
//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 ( TypeElement interface_decl ) {
String interface_simple_name = interface_decl . getSimpleName ( ) . toString ( ) ;
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 VariableElement getAutoTypeParameter ( ExecutableElement method , VariableElement target_parameter ) {
for ( VariableElement 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 ( ) . toString ( ) . equals ( parameter_name ) ) {
return param ;
}
}
}
return null ;
}
private static boolean hasAnyParameterAutoTypeAnnotation ( ExecutableElement method , VariableElement target_param ) {
for ( VariableElement param : method . getParameters ( ) ) {
AutoType auto_type_annotation = param . getAnnotation ( AutoType . class ) ;
if ( auto_type_annotation ! = null ) {
VariableElement 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 < > ( ) ;
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 , TypeElement interface_decl , ExecutableElement method ) {
StripPostfix strip_annotation = method . getAnnotation ( StripPostfix . class ) ;
VariableElement 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 . asType ( ) . accept ( translator , null ) ;
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 ( ) . toString ( ) : 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 , ExecutableElement method , VariableElement param , Map < VariableElement , 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 VariableElement 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 VariableElement 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 . asType ( ) ) ;
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 , ExecutableElement method , Map < VariableElement , TypeInfo > typeinfos_instance , Mode mode , TypeMap type_map ) {
boolean first_parameter = true ;
for ( VariableElement 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 ;
}
private static void printParameterCaching ( PrintWriter writer , TypeElement interface_decl , ExecutableElement method , Mode mode , boolean context_specific ) {
for ( VariableElement param : method . getParameters ( ) ) {
Class java_type = Utils . getJavaType ( param . asType ( ) ) ;
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 ) {
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 , ExecutableElement method , Map < VariableElement , 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 VariableElement param : method . getParameters ( ) ) {
if ( Arrays . binarySearch ( gen_autos_annotation . sizeVariables ( ) , param . getSimpleName ( ) . toString ( ) ) > = 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 ( VariableElement param : method . getParameters ( ) ) {
Class java_type = Utils . getJavaType ( param . asType ( ) ) ;
if ( java_type . isArray ( ) | | ( Utils . isAddressableType ( ( Class ) 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 ( ) . toString ( ) , 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 ( ) . toString ( ) , 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 , ExecutableElement 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 ( ExecutableElement 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 ( ExecutableElement 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 " ;
}
}
}
2010-09-26 19:43:24 -04:00
2005-02-15 06:05:36 -05:00
}