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( 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 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 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(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) { TypeInfo typeinfo = typeinfos.get(param); printParameterCheck( writer, method, param.getSimpleName().toString(), typeinfo.getType().getSimpleName(), check_value, can_be_null, param.getAnnotation(NullTerminated.class), 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()) { printArrayParameterCheck( writer, param.getSimpleName().toString(), check_value, can_be_null); } } } if (method.getAnnotation(CachedResult.class) != null) { printParameterCheck( writer, method, Utils.CACHED_BUFFER_NAME, null, null, true, null, generate_error_checks); } }
/** 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(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 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 generateParametersJava( 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; } 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; }