mirror of
https://github.com/shadowfacts/lwjgl2-arm64.git
synced 2026-04-08 16:04:39 +00:00
Added support for Strings! (WIP, needs more testing)
This commit is contained in:
parent
cb925a91e9
commit
6ac8e327f2
29 changed files with 889 additions and 231 deletions
268
src/java/org/lwjgl/opengl/StringUtils.java
Normal file
268
src/java/org/lwjgl/opengl/StringUtils.java
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lwjgl.opengl;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
/** @author spasi */
|
||||
final class StringUtils {
|
||||
|
||||
private static final int INITIAL_BUFFER_SIZE = 256;
|
||||
private static final int INITIAL_LENGTHS_SIZE = 4;
|
||||
|
||||
private static final ThreadLocal arrayTL = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
return new char[INITIAL_BUFFER_SIZE];
|
||||
}
|
||||
};
|
||||
|
||||
private static final ThreadLocal bufferTL = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
return BufferUtils.createByteBuffer(INITIAL_BUFFER_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
private static final ThreadLocal lengthsTL = new ThreadLocal() {
|
||||
protected Object initialValue() {
|
||||
return BufferUtils.createIntBuffer(INITIAL_LENGTHS_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
private StringUtils() {
|
||||
}
|
||||
|
||||
private static char[] getArray(final int size) {
|
||||
char[] array = (char[])arrayTL.get();
|
||||
|
||||
if ( array.length < size ) {
|
||||
int sizeNew = array.length << 1;
|
||||
while ( sizeNew < size )
|
||||
sizeNew <<= 1;
|
||||
|
||||
array = new char[size];
|
||||
arrayTL.set(array);
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
static ByteBuffer getBuffer(final int size) {
|
||||
ByteBuffer buffer = (ByteBuffer)bufferTL.get();
|
||||
|
||||
if ( buffer.capacity() < size ) {
|
||||
int sizeNew = buffer.capacity() << 1;
|
||||
while ( sizeNew < size )
|
||||
sizeNew <<= 1;
|
||||
|
||||
buffer = BufferUtils.createByteBuffer(size);
|
||||
bufferTL.set(buffer);
|
||||
}
|
||||
|
||||
buffer.clear();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private static ByteBuffer getBufferOffset(final int size) {
|
||||
ByteBuffer buffer = (ByteBuffer)bufferTL.get();
|
||||
|
||||
if ( buffer.capacity() < size ) {
|
||||
int sizeNew = buffer.capacity() << 1;
|
||||
while ( sizeNew < size )
|
||||
sizeNew <<= 1;
|
||||
|
||||
final ByteBuffer bufferNew = BufferUtils.createByteBuffer(size);
|
||||
bufferNew.put(buffer);
|
||||
bufferTL.set(buffer = bufferNew);
|
||||
} else {
|
||||
buffer.position(buffer.limit());
|
||||
buffer.limit(buffer.capacity());
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static IntBuffer getLengths(final int size) {
|
||||
IntBuffer lengths = (IntBuffer)lengthsTL.get();
|
||||
|
||||
if ( lengths.capacity() < size ) {
|
||||
int sizeNew = lengths.capacity();
|
||||
while ( sizeNew < size )
|
||||
sizeNew <<= 1;
|
||||
|
||||
lengths = BufferUtils.createIntBuffer(size);
|
||||
lengthsTL.set(lengths);
|
||||
}
|
||||
|
||||
lengths.clear();
|
||||
return lengths;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads a byte string from the specified buffer.
|
||||
*
|
||||
* @param buffer
|
||||
*
|
||||
* @return the buffer as a String.
|
||||
*/
|
||||
|
||||
static String getString(final ByteBuffer buffer) {
|
||||
final int length = buffer.remaining();
|
||||
final char[] charArray = getArray(length);
|
||||
|
||||
for ( int i = buffer.position(); i < buffer.limit(); i++ )
|
||||
charArray[i - buffer.position()] = (char)buffer.get(i);
|
||||
|
||||
return new String(charArray, 0, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the specified string as bytes.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return the String as a ByteBuffer
|
||||
*/
|
||||
static ByteBuffer getBuffer(final CharSequence string) {
|
||||
final ByteBuffer buffer = getBuffer(string.length());
|
||||
|
||||
for ( int i = 0; i < string.length(); i++ )
|
||||
buffer.put((byte)string.charAt(i));
|
||||
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the specified string as bytes, starting at the specified offset.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return the String as a ByteBuffer
|
||||
*/
|
||||
static ByteBuffer getBufferOffset(final CharSequence string, final int offset) {
|
||||
final ByteBuffer buffer = getBufferOffset(offset + string.length());
|
||||
|
||||
for ( int i = 0; i < string.length(); i++ )
|
||||
buffer.put((byte)string.charAt(i));
|
||||
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the specified string as bytes, including null-termination.
|
||||
*
|
||||
* @param string
|
||||
*
|
||||
* @return the String as a ByteBuffer
|
||||
*/
|
||||
static ByteBuffer getBufferNT(final CharSequence string) {
|
||||
final ByteBuffer buffer = getBuffer(string.length() + 1);
|
||||
|
||||
for ( int i = 0; i < string.length(); i++ )
|
||||
buffer.put((byte)string.charAt(i));
|
||||
|
||||
buffer.put((byte)0);
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the specified strings as bytes.
|
||||
*
|
||||
* @param strings
|
||||
*
|
||||
* @return the Strings as a ByteBuffer
|
||||
*/
|
||||
static ByteBuffer getBuffer(final CharSequence[] strings) {
|
||||
int length = 0;
|
||||
for ( int i = 0; i < strings.length; i++ )
|
||||
length += strings[i].length();
|
||||
|
||||
final ByteBuffer buffer = getBuffer(length);
|
||||
|
||||
for ( int i = 0; i < strings.length; i++ ) {
|
||||
final CharSequence string = strings[i];
|
||||
for ( int j = 0; j < string.length(); j++ )
|
||||
buffer.put((byte)string.charAt(i));
|
||||
}
|
||||
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the specified strings as bytes, including null-termination.
|
||||
*
|
||||
* @param strings
|
||||
*
|
||||
* @return the Strings as a ByteBuffer
|
||||
*/
|
||||
static ByteBuffer getBufferNT(final CharSequence[] strings) {
|
||||
int length = 0;
|
||||
for ( int i = 0; i < strings.length; i++ )
|
||||
length += strings[i].length() + 1;
|
||||
|
||||
final ByteBuffer buffer = getBuffer(length);
|
||||
|
||||
for ( int i = 0; i < strings.length; i++ ) {
|
||||
final CharSequence string = strings[i];
|
||||
for ( int j = 0; j < string.length(); j++ )
|
||||
buffer.put((byte)string.charAt(i));
|
||||
buffer.put((byte)0);
|
||||
}
|
||||
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a buffer containing the lengths of the specified strings.
|
||||
*
|
||||
* @param strings
|
||||
*
|
||||
* @return the String lengths in an IntBuffer
|
||||
*/
|
||||
static IntBuffer getLengths(final CharSequence[] strings) {
|
||||
IntBuffer buffer = getLengths(strings.length);
|
||||
|
||||
for ( int i = 0; i < strings.length; i++ )
|
||||
buffer.put(strings[i].length());
|
||||
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -42,6 +42,10 @@ import java.lang.annotation.Target;
|
|||
*/
|
||||
@Target({ ElementType.METHOD })
|
||||
public @interface Alternate {
|
||||
|
||||
/** This must match an existing GL method name. */
|
||||
String value();
|
||||
|
||||
/** If true, an alternate Java->native call will be created. Useful when the alternate implementation uses different types. */
|
||||
boolean nativeAlt() default false;
|
||||
}
|
||||
|
|
@ -210,8 +210,18 @@ public class ContextCapabilitiesGenerator {
|
|||
|
||||
writer.println(") {");
|
||||
writer.println("\t\treturn ");
|
||||
|
||||
boolean first = true;
|
||||
while ( methods.hasNext() ) {
|
||||
MethodDeclaration method = methods.next();
|
||||
if ( method.getAnnotation(Alternate.class) != null )
|
||||
continue;
|
||||
|
||||
if ( !first )
|
||||
writer.println(" &&");
|
||||
else
|
||||
first = false;
|
||||
|
||||
optional = method.getAnnotation(Optional.class) != null;
|
||||
deprecated = method.getAnnotation(DeprecatedGL.class) != null;
|
||||
dependent = method.getAnnotation(Dependent.class);
|
||||
|
|
@ -261,8 +271,6 @@ public class ContextCapabilitiesGenerator {
|
|||
writer.print(')');
|
||||
if ( optional )
|
||||
writer.print(" || true)");
|
||||
if ( methods.hasNext() )
|
||||
writer.println(" &&");
|
||||
}
|
||||
writer.println(";");
|
||||
writer.println("\t}");
|
||||
|
|
@ -271,7 +279,8 @@ public class ContextCapabilitiesGenerator {
|
|||
|
||||
public static void generateSymbolAddresses(PrintWriter writer, InterfaceDeclaration d) {
|
||||
for ( MethodDeclaration method : d.getMethods() ) {
|
||||
writer.println("\tlong " + Utils.getFunctionAddressName(d, method) + ";");
|
||||
if ( method.getAnnotation(Alternate.class) == null )
|
||||
writer.println("\tlong " + Utils.getFunctionAddressName(d, method) + ";");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@ public class GLTypeMap implements TypeMap {
|
|||
else if ( type.equals(boolean.class) )
|
||||
return new Class[] { GLboolean.class };
|
||||
else if ( type.equals(void.class) )
|
||||
return new Class[] { GLvoid.class };
|
||||
return new Class[] { GLvoid.class, GLstring.class };
|
||||
else
|
||||
return new Class[] { };
|
||||
}
|
||||
|
|
@ -243,6 +243,8 @@ public class GLTypeMap implements TypeMap {
|
|||
valid_types = new Class[] { GLubyte.class };
|
||||
else if ( PointerWrapper.class.isAssignableFrom(type) )
|
||||
valid_types = new Class[] { GLpointer.class };
|
||||
else if (void.class.equals(type) )
|
||||
valid_types = new Class[] { GLstring.class };
|
||||
else
|
||||
valid_types = new Class[] { };
|
||||
return valid_types;
|
||||
|
|
|
|||
50
src/java/org/lwjgl/util/generator/GLstring.java
Normal file
50
src/java/org/lwjgl/util/generator/GLstring.java
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lwjgl.util.generator;
|
||||
|
||||
/**
|
||||
* Methods annotated with @GLstring will return a String instead of void.
|
||||
*
|
||||
* @author spasi
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@NativeType
|
||||
@Target({ ElementType.METHOD })
|
||||
public @interface GLstring {
|
||||
/** The ByteBuffer argument that will be used to retrieve the String bytes. */
|
||||
String string();
|
||||
/** The argument that specifies the maximum number of bytes that may be read. */
|
||||
String maxLength();
|
||||
}
|
||||
48
src/java/org/lwjgl/util/generator/GLstringOffset.java
Normal file
48
src/java/org/lwjgl/util/generator/GLstringOffset.java
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
package org.lwjgl.util.generator;
|
||||
|
||||
/**
|
||||
* This annotation must be used when there are more than one CharSequence arguments in a method.
|
||||
* TODO: Add support for CharSequence[] if/when we need it.
|
||||
*
|
||||
* @author spasi
|
||||
*/
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ ElementType.PARAMETER })
|
||||
public @interface GLstringOffset {
|
||||
/** An expression that will specify the offset from which this String will be written to the ByteBuffer. */
|
||||
String value();
|
||||
}
|
||||
|
|
@ -125,7 +125,8 @@ public class GeneratorVisitor extends SimpleDeclarationVisitor {
|
|||
private void validateParameters(MethodDeclaration method) {
|
||||
for (ParameterDeclaration param : method.getParameters()) {
|
||||
validateTypes(method, param.getAnnotationMirrors(), param.getType());
|
||||
if (Utils.getNIOBufferType(param.getType()) != null) {
|
||||
Class<?> param_type = Utils.getJavaType(param.getType());
|
||||
if (Utils.getNIOBufferType(param.getType()) != null && param_type != CharSequence.class && param_type != CharSequence[].class) {
|
||||
Check parameter_check_annotation = param.getAnnotation(Check.class);
|
||||
NullTerminated null_terminated_annotation = param.getAnnotation(NullTerminated.class);
|
||||
if (parameter_check_annotation == null && null_terminated_annotation == null) {
|
||||
|
|
@ -138,7 +139,11 @@ public class GeneratorVisitor extends SimpleDeclarationVisitor {
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (!found_auto_size_param && param.getAnnotation(Result.class) == null && param.getAnnotation(Constant.class) == null)
|
||||
if (!found_auto_size_param
|
||||
&& param.getAnnotation(Result.class) == null
|
||||
&& param.getAnnotation(Constant.class) == null
|
||||
&& !Utils.isReturnString(method, param)
|
||||
)
|
||||
throw new RuntimeException(param + " has no Check, Result nor Constant annotation and no other parameters has" +
|
||||
" an @AutoSize annotation on it in method " + method);
|
||||
}
|
||||
|
|
@ -158,8 +163,10 @@ public class GeneratorVisitor extends SimpleDeclarationVisitor {
|
|||
}
|
||||
|
||||
private static void generateMethodsNativePointers(PrintWriter writer, Collection<? extends MethodDeclaration> methods) {
|
||||
for (MethodDeclaration method : methods)
|
||||
generateMethodNativePointers(writer, method);
|
||||
for (MethodDeclaration method : methods) {
|
||||
if ( method.getAnnotation(Alternate.class) == null )
|
||||
generateMethodNativePointers(writer, method);
|
||||
}
|
||||
}
|
||||
|
||||
private static void generateMethodNativePointers(PrintWriter writer, MethodDeclaration method) {
|
||||
|
|
|
|||
|
|
@ -56,7 +56,10 @@ public class JNITypeTranslator implements TypeVisitor {
|
|||
}
|
||||
|
||||
public void visitArrayType(ArrayType t) {
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
if ( "java.lang.CharSequence".equals(t.getComponentType().toString()) )
|
||||
signature.append("jobject");
|
||||
else
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
}
|
||||
|
||||
public void visitClassType(ClassType t) {
|
||||
|
|
|
|||
|
|
@ -71,7 +71,8 @@ public class JavaMethodsGenerator {
|
|||
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);
|
||||
}
|
||||
if ( method.getAnnotation(Alternate.class) == null ) {
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
if ( alt_annotation == null || alt_annotation.nativeAlt() ) {
|
||||
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);
|
||||
|
|
@ -119,8 +120,12 @@ public class JavaMethodsGenerator {
|
|||
writer.print("boolean " + TypeInfo.UNSIGNED_PARAMETER_NAME);
|
||||
}
|
||||
}
|
||||
} else if (param.getAnnotation(Result.class) == null && (native_stub || param.getAnnotation(Constant.class) == null) &&
|
||||
(getAutoTypeParameter(method, param) == null || mode != Mode.AUTOS)) {
|
||||
} else if (
|
||||
param.getAnnotation(Result.class) == null
|
||||
&& (native_stub || (param.getAnnotation(Constant.class) == null && !Utils.isReturnString(method, param)))
|
||||
&& (getAutoTypeParameter(method, param) == null || mode != Mode.AUTOS)
|
||||
)
|
||||
{
|
||||
TypeInfo type_info = typeinfos_instance.get(param);
|
||||
first_parameter = generateParameterJava(writer, param, type_info, native_stub, first_parameter, mode);
|
||||
}
|
||||
|
|
@ -161,10 +166,15 @@ public class JavaMethodsGenerator {
|
|||
} else {
|
||||
if ( native_stub && param.getAnnotation(GLpointer.class) != null )
|
||||
writer.print("long");
|
||||
else
|
||||
writer.print(type_info.getType().getSimpleName());
|
||||
else {
|
||||
Class type = type_info.getType();
|
||||
if ( native_stub && (type == CharSequence.class || type == CharSequence[].class) )
|
||||
writer.print("ByteBuffer");
|
||||
else
|
||||
writer.print(type_info.getType().getSimpleName());
|
||||
}
|
||||
writer.print(" " + param.getSimpleName());
|
||||
if (buffer_type != null && native_stub)
|
||||
if ( native_stub && buffer_type != null )
|
||||
writer.print(", int " + param.getSimpleName() + NativeMethodStubsGenerator.BUFFER_POSITION_POSTFIX);
|
||||
}
|
||||
return false;
|
||||
|
|
@ -208,7 +218,7 @@ public class JavaMethodsGenerator {
|
|||
if (context_specific) {
|
||||
writer.println("\t\tContextCapabilities caps = GLContext.getCapabilities();");
|
||||
writer.print("\t\tlong " + Utils.FUNCTION_POINTER_VAR_NAME + " = caps.");
|
||||
writer.println(Utils.getFunctionAddressName(interface_decl, method) + ";");
|
||||
writer.println(Utils.getFunctionAddressName(interface_decl, method, true) + ";");
|
||||
writer.print("\t\tBufferChecks.checkFunctionAddress(");
|
||||
writer.println(Utils.FUNCTION_POINTER_VAR_NAME + ");");
|
||||
}
|
||||
|
|
@ -227,6 +237,13 @@ public class JavaMethodsGenerator {
|
|||
if ( method.getAnnotation(GLpointer.class) != null )
|
||||
writer.print("new " + method.getReturnType() + "(");
|
||||
}
|
||||
GLstring string_annotation = method.getAnnotation(GLstring.class);
|
||||
if ( string_annotation != null ) {
|
||||
has_result = true;
|
||||
writer.println("IntBuffer " + string_annotation.string() + "_length = StringUtils.getLengths(1);");
|
||||
writer.println("\t\tByteBuffer " + string_annotation.string() + " = StringUtils.getBuffer(" + string_annotation.maxLength() + ");");
|
||||
writer.print("\t\t");
|
||||
}
|
||||
writer.print(Utils.getSimpleNativeMethodName(method, generate_error_checks, context_specific));
|
||||
if (mode == Mode.BUFFEROBJECT)
|
||||
writer.print(Utils.BUFFER_OBJECT_METHOD_POSTFIX);
|
||||
|
|
@ -244,8 +261,14 @@ public class JavaMethodsGenerator {
|
|||
writer.println("\t\t" + type_map.getErrorCheckMethodName() + ";");
|
||||
// DISABLED: indirect buffer support
|
||||
//printNondirectParameterCopies(writer, method, mode);
|
||||
if (has_result)
|
||||
writer.println("\t\treturn " + Utils.RESULT_VAR_NAME + ";");
|
||||
if (has_result) {
|
||||
if ( string_annotation == null )
|
||||
writer.println("\t\treturn " + Utils.RESULT_VAR_NAME + ";");
|
||||
else {
|
||||
writer.println("\t\t" + string_annotation.string() + ".limit(" + string_annotation.string() + "_length.get(0));");
|
||||
writer.println("\t\treturn StringUtils.getString(" + string_annotation.string() + ");");
|
||||
}
|
||||
}
|
||||
writer.println("\t}");
|
||||
}
|
||||
|
||||
|
|
@ -383,8 +406,24 @@ public class JavaMethodsGenerator {
|
|||
boolean hide_buffer = mode == Mode.AUTOS && getAutoTypeParameter(method, param) != null;
|
||||
if (hide_buffer)
|
||||
writer.print("null");
|
||||
else
|
||||
writer.print(param.getSimpleName());
|
||||
else {
|
||||
Class type = typeinfos_instance.get(param).getType();
|
||||
if ( type == CharSequence.class || type == CharSequence[].class ) {
|
||||
GLstringOffset offset_annotation = param.getAnnotation(GLstringOffset.class);
|
||||
|
||||
writer.print("StringUtils.getBuffer");
|
||||
if ( offset_annotation != null )
|
||||
writer.print("Offset");
|
||||
if ( param.getAnnotation(NullTerminated.class) != null )
|
||||
writer.print("NT");
|
||||
writer.print("(" + param.getSimpleName());
|
||||
if ( offset_annotation != null )
|
||||
writer.print(", " + offset_annotation.value());
|
||||
writer.print(")");
|
||||
hide_buffer = true;
|
||||
} else
|
||||
writer.print(param.getSimpleName());
|
||||
}
|
||||
Class buffer_type = Utils.getNIOBufferType(param.getType());
|
||||
if (buffer_type != null) {
|
||||
writer.print(", ");
|
||||
|
|
@ -404,7 +443,9 @@ public class JavaMethodsGenerator {
|
|||
writer.print(" << " + shifting);
|
||||
if (check_annotation != null && check_annotation.canBeNull())
|
||||
writer.print(" : 0");
|
||||
} else
|
||||
} else if ( param.getAnnotation(GLstringOffset.class) != null )
|
||||
writer.print(param.getAnnotation(GLstringOffset.class).value());
|
||||
else
|
||||
writer.print("0");
|
||||
} else if ( param.getAnnotation(GLpointer.class) != null ) {
|
||||
writer.print(".getPointer()");
|
||||
|
|
@ -489,7 +530,8 @@ public class JavaMethodsGenerator {
|
|||
if (Utils.isAddressableType(java_type) &&
|
||||
(mode != Mode.BUFFEROBJECT || param.getAnnotation(BufferObject.class) == null) &&
|
||||
(mode != Mode.AUTOS || getAutoTypeParameter(method, param) == null) &&
|
||||
param.getAnnotation(Result.class) == null) {
|
||||
param.getAnnotation(Result.class) == null &&
|
||||
!Utils.isReturnString(method, param) ) {
|
||||
String check_value = null;
|
||||
boolean can_be_null = false;
|
||||
Check check_annotation = param.getAnnotation(Check.class);
|
||||
|
|
@ -547,6 +589,8 @@ public class JavaMethodsGenerator {
|
|||
private static void printResultType(PrintWriter writer, MethodDeclaration method, boolean native_stub) {
|
||||
if ( native_stub && method.getAnnotation(GLpointer.class) != null )
|
||||
writer.print("long");
|
||||
else if ( !native_stub && method.getAnnotation(GLstring.class) != null )
|
||||
writer.print("String");
|
||||
else
|
||||
writer.print(Utils.getMethodReturnType(method).toString());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,10 @@ public class JavaTypeTranslator implements TypeVisitor {
|
|||
}
|
||||
|
||||
public void visitArrayType(ArrayType t) {
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
if ( "java.lang.CharSequence".equals(t.getComponentType().toString()) )
|
||||
type = CharSequence[].class;
|
||||
else
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
}
|
||||
|
||||
public void visitPrimitiveType(PrimitiveType t) {
|
||||
|
|
|
|||
|
|
@ -56,6 +56,9 @@ public class NativeMethodStubsGenerator {
|
|||
|
||||
public static void generateNativeMethodStubs(AnnotationProcessorEnvironment env, TypeMap type_map, PrintWriter writer, InterfaceDeclaration d, boolean generate_error_checks, boolean context_specific) {
|
||||
for (MethodDeclaration method : d.getMethods()) {
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
if ( alt_annotation != null && !alt_annotation.nativeAlt() )
|
||||
continue;
|
||||
generateMethodStub(env, type_map, writer, Utils.getQualifiedClassName(d), method, Mode.NORMAL, generate_error_checks, context_specific);
|
||||
if (Utils.hasMethodBufferObjectParameter(method))
|
||||
generateMethodStub(env, type_map, writer, Utils.getQualifiedClassName(d), method, Mode.BUFFEROBJECT, generate_error_checks, context_specific);
|
||||
|
|
@ -117,9 +120,10 @@ public class NativeMethodStubsGenerator {
|
|||
}
|
||||
writer.println(") {");
|
||||
generateBufferParameterAddresses(type_map, writer, method, mode);
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
if (context_specific) {
|
||||
String typedef_name = Utils.getTypedefName(method);
|
||||
writer.print("\t" + typedef_name + " " + method.getSimpleName());
|
||||
writer.print("\t" + typedef_name + " " + (alt_annotation == null ? method.getSimpleName() : alt_annotation.value()));
|
||||
writer.print(" = (" + typedef_name + ")((intptr_t)");
|
||||
writer.println(Utils.FUNCTION_POINTER_VAR_NAME + ");");
|
||||
}
|
||||
|
|
@ -141,7 +145,7 @@ public class NativeMethodStubsGenerator {
|
|||
} else
|
||||
writer.print(" = ");
|
||||
}
|
||||
writer.print(method.getSimpleName() + "(");
|
||||
writer.print((alt_annotation == null ? method.getSimpleName() : alt_annotation.value()) + "(");
|
||||
generateCallParameters(writer, type_map, method.getParameters());
|
||||
writer.print(")");
|
||||
writer.println(";");
|
||||
|
|
@ -222,13 +226,13 @@ public class NativeMethodStubsGenerator {
|
|||
}
|
||||
|
||||
private static void generateBufferParameterAddresses(TypeMap type_map, PrintWriter writer, MethodDeclaration method, Mode mode) {
|
||||
boolean loopDeclared = false;
|
||||
for (ParameterDeclaration param : method.getParameters())
|
||||
if (Utils.isAddressableType(param.getType()) &&
|
||||
param.getAnnotation(Result.class) == null)
|
||||
generateBufferParameterAddress(type_map, writer, method, param, mode);
|
||||
if (Utils.isAddressableType(param.getType()) && param.getAnnotation(Result.class) == null)
|
||||
loopDeclared = generateBufferParameterAddress(type_map, writer, method, param, mode, loopDeclared);
|
||||
}
|
||||
|
||||
private static void generateBufferParameterAddress(TypeMap type_map, PrintWriter writer, MethodDeclaration method, ParameterDeclaration param, Mode mode) {
|
||||
private static boolean generateBufferParameterAddress(TypeMap type_map, PrintWriter writer, MethodDeclaration method, ParameterDeclaration param, Mode mode, boolean loopDeclared) {
|
||||
NativeTypeTranslator translator = new NativeTypeTranslator(type_map, param);
|
||||
param.getType().accept(translator);
|
||||
writer.print("\t" + translator.getSignature() + param.getSimpleName());
|
||||
|
|
@ -240,7 +244,7 @@ public class NativeMethodStubsGenerator {
|
|||
writer.print("offsetToPointer(" + param.getSimpleName() + Utils.BUFFER_OBJECT_PARAMETER_POSTFIX + "))");
|
||||
} else {
|
||||
Class java_type = Utils.getJavaType(param.getType());
|
||||
if (Buffer.class.isAssignableFrom(java_type)) {
|
||||
if (Buffer.class.isAssignableFrom(java_type) || java_type.equals(CharSequence.class) || java_type.equals(CharSequence[].class)) {
|
||||
boolean explicitly_byte_sized = java_type.equals(Buffer.class) ||
|
||||
translator.getAnnotationType().equals(type_map.getVoidType());
|
||||
if (explicitly_byte_sized)
|
||||
|
|
@ -262,30 +266,47 @@ public class NativeMethodStubsGenerator {
|
|||
writer.println(";");
|
||||
|
||||
if ( param.getAnnotation(StringList.class) != null ) {
|
||||
if ( param.getAnnotation(GLchar.class) == null ||
|
||||
param.getAnnotation(NullTerminated.class) == null ||
|
||||
param.getAnnotation(NullTerminated.class).value().length() == 0
|
||||
if ( Utils.getJavaType(param.getType()) != CharSequence[].class && (
|
||||
param.getAnnotation(GLchar.class) == null ||
|
||||
param.getAnnotation(NullTerminated.class) == null ||
|
||||
param.getAnnotation(NullTerminated.class).value().length() == 0
|
||||
)
|
||||
)
|
||||
throw new RuntimeException("StringList annotation can only be applied on null-terminated GLchar buffers.");
|
||||
|
||||
// Declare string array and loop counters
|
||||
writer.print("\tGLchar **" + param.getSimpleName() + STRING_LIST_POSTFIX + "; ");
|
||||
writer.println("\tunsigned int " + param.getSimpleName() + "_i = 0;");
|
||||
writer.println("\tGLchar *" + param.getSimpleName() + "_next = (GLchar *)" + param.getSimpleName() + BUFFER_ADDRESS_POSTFIX + ";");
|
||||
if ( "_str".equals(param.getSimpleName()) )
|
||||
throw new RuntimeException("The name '_str' is not valid for arguments annotated with StringList");
|
||||
|
||||
// Declare loop counters and allocate string array
|
||||
if ( !loopDeclared ) {
|
||||
writer.println("\tunsigned int _str_i;");
|
||||
writer.println("\tGLchar *_str_address;");
|
||||
loopDeclared = true;
|
||||
}
|
||||
writer.println("\tGLchar **" + param.getSimpleName() + STRING_LIST_POSTFIX + " = (GLchar **) malloc(" + param.getAnnotation(StringList.class).value() + "*sizeof(GLchar*));");
|
||||
}
|
||||
return loopDeclared;
|
||||
}
|
||||
|
||||
private static void generateStringListInits(PrintWriter writer, Collection<ParameterDeclaration> params) {
|
||||
for ( ParameterDeclaration param : params ) {
|
||||
StringList stringList_annotation = param.getAnnotation(StringList.class);
|
||||
if ( stringList_annotation != null ) {
|
||||
// Allocate the string array
|
||||
writer.println("\t" + param.getSimpleName() + STRING_LIST_POSTFIX + " = (GLchar **) malloc(" + stringList_annotation.value() + "*sizeof(GLchar*));");
|
||||
String lengths = stringList_annotation.lengths();
|
||||
|
||||
// Init vars
|
||||
writer.println("\t_str_i = 0;");
|
||||
writer.println("\t_str_address = (GLchar *)" + param.getSimpleName() + BUFFER_ADDRESS_POSTFIX + ";");
|
||||
// Fill string array with the string pointers
|
||||
writer.println("\tdo {");
|
||||
writer.println("\t\t" + param.getSimpleName() + STRING_LIST_POSTFIX + "[" + param.getSimpleName() + "_i++] = " + param.getSimpleName() + "_next;");
|
||||
writer.println("\t\t" + param.getSimpleName() + "_next += strlen(" + param.getSimpleName() + "_next) + 1;");
|
||||
writer.println("\t} while ( " + param.getSimpleName() + "_i < " + stringList_annotation.value() + " );");
|
||||
writer.println("\twhile ( _str_i < " + stringList_annotation.value() + " ) {");
|
||||
if ( lengths.length() == 0 ) {
|
||||
writer.println("\t\t" + param.getSimpleName() + STRING_LIST_POSTFIX + "[_str_i++] = _str_address;");
|
||||
writer.println("\t\t_str_address += strlen(_str_address_next) + 1;");
|
||||
} else {
|
||||
writer.println("\t\t" + param.getSimpleName() + STRING_LIST_POSTFIX + "[_str_i] = _str_address;");
|
||||
writer.println("\t\t_str_address += " + lengths + BUFFER_ADDRESS_POSTFIX + "[_str_i++];");
|
||||
}
|
||||
writer.println("\t}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -104,7 +104,12 @@ public class NativeTypeTranslator implements TypeVisitor {
|
|||
}
|
||||
|
||||
public void visitArrayType(ArrayType t) {
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
if ( "java.lang.CharSequence".equals(t.getComponentType().toString()) ) {
|
||||
is_indirect = true;
|
||||
native_types = new ArrayList<Class>();
|
||||
native_types.add(GLchar.class);
|
||||
} else
|
||||
throw new RuntimeException(t + " is not allowed");
|
||||
}
|
||||
|
||||
public static PrimitiveType.Kind getPrimitiveKindFromBufferClass(Class c) {
|
||||
|
|
|
|||
|
|
@ -41,5 +41,8 @@ import java.lang.annotation.Target;
|
|||
|
||||
@Target({ElementType.PARAMETER, ElementType.METHOD})
|
||||
public @interface StringList {
|
||||
/** Number of values in the string list (name of native-side parameter) */
|
||||
String value();
|
||||
/** List of string lengths (name of native-side parameter) */
|
||||
String lengths() default "";
|
||||
}
|
||||
|
|
@ -82,8 +82,10 @@ public class TypedefsGenerator {
|
|||
}
|
||||
|
||||
public static void generateNativeTypedefs(TypeMap type_map, PrintWriter writer, Collection<? extends MethodDeclaration> methods) {
|
||||
for (MethodDeclaration method : methods)
|
||||
generateNativeTypedefs(type_map, writer, method);
|
||||
for (MethodDeclaration method : methods) {
|
||||
if ( method.getAnnotation(Alternate.class) == null )
|
||||
generateNativeTypedefs(type_map, writer, method);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,9 +43,16 @@ package org.lwjgl.util.generator;
|
|||
import com.sun.mirror.type.*;
|
||||
import java.nio.Buffer;
|
||||
import java.io.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
import javax.lang.model.util.SimpleTypeVisitor6;
|
||||
|
||||
import com.sun.mirror.declaration.*;
|
||||
import com.sun.mirror.type.PrimitiveType.Kind;
|
||||
import com.sun.mirror.util.SimpleTypeVisitor;
|
||||
import com.sun.mirror.util.TypeVisitor;
|
||||
import com.sun.mirror.util.Types;
|
||||
|
||||
public class Utils {
|
||||
public static final String TYPEDEF_POSTFIX = "PROC";
|
||||
|
|
@ -63,11 +70,20 @@ public class Utils {
|
|||
private static final String OVERLOADED_METHOD_PREFIX = "n";
|
||||
|
||||
public static String getTypedefName(MethodDeclaration method) {
|
||||
return method.getSimpleName() + TYPEDEF_POSTFIX;
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
return (alt_annotation == null ? method.getSimpleName() : alt_annotation.value()) + TYPEDEF_POSTFIX;
|
||||
}
|
||||
|
||||
public static String getFunctionAddressName(InterfaceDeclaration interface_decl, MethodDeclaration method) {
|
||||
return interface_decl.getSimpleName() + "_" + method.getSimpleName() + FUNCTION_POINTER_POSTFIX;
|
||||
return getFunctionAddressName(interface_decl, method, false);
|
||||
}
|
||||
|
||||
public static String getFunctionAddressName(InterfaceDeclaration interface_decl, MethodDeclaration method, boolean forceAlt) {
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
if ( alt_annotation == null || (alt_annotation.nativeAlt() && !forceAlt) )
|
||||
return interface_decl.getSimpleName() + "_" + method.getSimpleName() + FUNCTION_POINTER_POSTFIX;
|
||||
else
|
||||
return interface_decl.getSimpleName() + "_" + alt_annotation.value() + FUNCTION_POINTER_POSTFIX;
|
||||
}
|
||||
|
||||
public static boolean isFinal(InterfaceDeclaration d) {
|
||||
|
|
@ -103,7 +119,7 @@ public class Utils {
|
|||
}
|
||||
|
||||
public static boolean isAddressableType(Class type) {
|
||||
return Buffer.class.isAssignableFrom(type) || String.class.equals(type);
|
||||
return Buffer.class.isAssignableFrom(type) || String.class.equals(type) || CharSequence.class.equals(type) || CharSequence[].class.equals(type);
|
||||
}
|
||||
|
||||
public static Class getJavaType(TypeMirror type_mirror) {
|
||||
|
|
@ -248,6 +264,8 @@ public class Utils {
|
|||
Class<?> param_type = getJavaType(t);
|
||||
if (Buffer.class.isAssignableFrom(param_type))
|
||||
return param_type;
|
||||
else if ( param_type == CharSequence.class || param_type == CharSequence[].class )
|
||||
return ByteBuffer.class;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
|
@ -255,10 +273,15 @@ public class Utils {
|
|||
public static String getSimpleNativeMethodName(MethodDeclaration method, boolean generate_error_checks, boolean context_specific) {
|
||||
String method_name;
|
||||
Alternate alt_annotation = method.getAnnotation(Alternate.class);
|
||||
method_name = alt_annotation == null ? method.getSimpleName() : alt_annotation.value();
|
||||
method_name = alt_annotation == null || alt_annotation.nativeAlt() ? method.getSimpleName() : alt_annotation.value();
|
||||
if (isMethodIndirect(generate_error_checks, context_specific, method))
|
||||
method_name = OVERLOADED_METHOD_PREFIX + method_name;
|
||||
return method_name;
|
||||
}
|
||||
|
||||
static boolean isReturnString(MethodDeclaration method, ParameterDeclaration param) {
|
||||
GLstring string_annotation = method.getAnnotation(GLstring.class);
|
||||
return string_annotation != null && string_annotation.string().equals(param.getSimpleName());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue