summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/classes/com/sun/gluegen/JavaConfiguration.java53
-rw-r--r--src/classes/com/sun/gluegen/JavaEmitter.java6
-rw-r--r--src/classes/com/sun/gluegen/JavaMethodBindingEmitter.java68
-rw-r--r--src/classes/com/sun/gluegen/runtime/BufferFactory.java77
4 files changed, 198 insertions, 6 deletions
diff --git a/src/classes/com/sun/gluegen/JavaConfiguration.java b/src/classes/com/sun/gluegen/JavaConfiguration.java
index 152d9cf80..ae8c46eaa 100644
--- a/src/classes/com/sun/gluegen/JavaConfiguration.java
+++ b/src/classes/com/sun/gluegen/JavaConfiguration.java
@@ -116,6 +116,8 @@ public class JavaConfiguration {
private Map/*<String,String>*/ javaMethodRenames = new HashMap();
private Map/*<String,List<String>>*/ javaPrologues = new HashMap();
private Map/*<String,List<String>>*/ javaEpilogues = new HashMap();
+ private Map/*<String,Map<Integer,String>>*/ rangeChecks = new HashMap();
+ private Map/*<String,Map<Integer,String>>*/ byteRangeChecks = new HashMap();
/** Reads the configuration file.
@param filename path to file that should be read
@@ -569,6 +571,22 @@ public class JavaConfiguration {
return res;
}
+ /** Returns a map of Integer argument numbers to expressions to be
+ used to range check the given arguments to the given function.
+ Returns null if there were no range check expressions supplied
+ for this function. */
+ public Map/*<Integer, String>*/ rangeCheckExpressions(String functionName) {
+ return (Map/*<Integer, String>*/) rangeChecks.get(functionName);
+ }
+
+ /** Returns a map of Integer argument numbers to expressions to be
+ used to range check (in size of bytes) the given arguments to
+ the given function. Returns null if there were no range check
+ expressions supplied for this function. */
+ public Map/*<Integer, String>*/ byteRangeCheckExpressions(String functionName) {
+ return (Map/*<Integer, String>*/) byteRangeChecks.get(functionName);
+ }
+
//----------------------------------------------------------------------
// Internals only below this point
//
@@ -686,6 +704,14 @@ public class JavaConfiguration {
readJavaPrologueOrEpilogue(tok, filename, lineNo, false);
// Warning: make sure delimiters are reset at the top of this loop
// because readJavaPrologueOrEpilogue changes them.
+ } else if (cmd.equalsIgnoreCase("RangeCheck")) {
+ readRangeCheck(tok, filename, lineNo, false);
+ // Warning: make sure delimiters are reset at the top of this loop
+ // because RangeCheck changes them.
+ } else if (cmd.equalsIgnoreCase("RangeCheckBytes")) {
+ readRangeCheck(tok, filename, lineNo, true);
+ // Warning: make sure delimiters are reset at the top of this loop
+ // because RangeCheckBytes changes them.
} else {
throw new RuntimeException("Unknown command \"" + cmd +
"\" in command file " + filename +
@@ -1131,6 +1157,33 @@ public class JavaConfiguration {
}
}
+ protected void readRangeCheck(StringTokenizer tok, String filename, int lineNo, boolean inBytes) {
+ try {
+ String functionName = tok.nextToken();
+ int argNum = Integer.parseInt(tok.nextToken());
+ String restOfLine = tok.nextToken("\n\r\f");
+ restOfLine = restOfLine.trim();
+ Map/*<Integer, String>*/ checksForFunction = null;
+ if (inBytes) {
+ checksForFunction = (Map/*<Integer, String>*/) byteRangeChecks.get(functionName);
+ } else {
+ checksForFunction = (Map/*<Integer, String>*/) rangeChecks.get(functionName);
+ }
+ if (checksForFunction == null) {
+ checksForFunction = new HashMap/*<Integer, String>*/();
+ if (inBytes) {
+ byteRangeChecks.put(functionName, checksForFunction);
+ } else {
+ rangeChecks.put(functionName, checksForFunction);
+ }
+ }
+ checksForFunction.put(new Integer(argNum), restOfLine);
+ } catch (Exception e) {
+ throw new RuntimeException("Error parsing \"RangeCheck" + (inBytes ? "Bytes" : "") + "\" command at line " + lineNo +
+ " in file \"" + filename + "\"", e);
+ }
+ }
+
protected static TypeInfo parseTypeInfo(String cType, JavaType javaType) {
String typeName = null;
int pointerDepth = 0;
diff --git a/src/classes/com/sun/gluegen/JavaEmitter.java b/src/classes/com/sun/gluegen/JavaEmitter.java
index d4bafb7a8..f0799067e 100644
--- a/src/classes/com/sun/gluegen/JavaEmitter.java
+++ b/src/classes/com/sun/gluegen/JavaEmitter.java
@@ -377,6 +377,8 @@ public class JavaEmitter implements GlueEmitter {
emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
emitter.setPrologue(prologue);
emitter.setEpilogue(epilogue);
+ emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName()));
+ emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName()));
allEmitters.add(emitter);
}
@@ -430,6 +432,8 @@ public class JavaEmitter implements GlueEmitter {
}
emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
+ emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName()));
+ emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName()));
allEmitters.add(emitter);
// Optionally emit the entry point taking arrays which handles
@@ -455,6 +459,8 @@ public class JavaEmitter implements GlueEmitter {
}
emitter.addModifier(JavaMethodBindingEmitter.NATIVE);
emitter.setReturnedArrayLengthExpression(cfg.returnedArrayLength(binding.getName()));
+ emitter.setRangeCheckExpressions(cfg.rangeCheckExpressions(binding.getName()));
+ emitter.setByteRangeCheckExpressions(cfg.byteRangeCheckExpressions(binding.getName()));
allEmitters.add(emitter);
}
}
diff --git a/src/classes/com/sun/gluegen/JavaMethodBindingEmitter.java b/src/classes/com/sun/gluegen/JavaMethodBindingEmitter.java
index 5a7e065f7..7e08977a6 100644
--- a/src/classes/com/sun/gluegen/JavaMethodBindingEmitter.java
+++ b/src/classes/com/sun/gluegen/JavaMethodBindingEmitter.java
@@ -87,6 +87,10 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
// number of elements of the returned array.
private String returnedArrayLengthExpression;
+ // Range-check expressions for various Buffer arguments
+ private Map/*<Integer, String>*/ rangeCheckExpressions;
+ private Map/*<Integer, String>*/ byteRangeCheckExpressions;
+
public JavaMethodBindingEmitter(MethodBinding binding,
PrintWriter output,
String runtimeExceptionType,
@@ -126,9 +130,11 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
forDirectBufferImplementation = arg.forDirectBufferImplementation;
forIndirectBufferAndArrayImplementation = arg.forIndirectBufferAndArrayImplementation;
isUnimplemented = arg.isUnimplemented;
- returnedArrayLengthExpression = arg.returnedArrayLengthExpression;
prologue = arg.prologue;
epilogue = arg.epilogue;
+ returnedArrayLengthExpression = arg.returnedArrayLengthExpression;
+ rangeCheckExpressions = arg.rangeCheckExpressions;
+ byteRangeCheckExpressions = arg.byteRangeCheckExpressions;
}
public final MethodBinding getBinding() { return binding; }
@@ -193,6 +199,14 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
this.forImplementingMethodCall = impl;
}
+ public void setRangeCheckExpressions(Map/*<Integer, String>*/ rangeChecks) {
+ this.rangeCheckExpressions = rangeChecks;
+ }
+
+ public void setByteRangeCheckExpressions(Map/*<Integer, String>*/ rangeChecks) {
+ this.byteRangeCheckExpressions = rangeChecks;
+ }
+
protected void emitReturnType(PrintWriter writer)
{
writer.print(getReturnTypeString(false));
@@ -424,6 +438,44 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
}
}
}
+
+ emitManuallySpecifiedRangeChecks(rangeCheckExpressions, false, writer);
+ emitManuallySpecifiedRangeChecks(byteRangeCheckExpressions, true, writer);
+ }
+
+ protected void emitManuallySpecifiedRangeChecks(Map/*<Integer, String>*/ rangeChecks,
+ boolean inBytes,
+ PrintWriter writer) {
+ if (rangeChecks == null) {
+ return;
+ }
+
+ // Check lengths of arrays and buffers with user-specified checks
+ for (Iterator iter = rangeChecks.keySet().iterator(); iter.hasNext(); ) {
+ Integer argNumBox = (Integer) iter.next();
+ int argNum = argNumBox.intValue();
+ JavaType type = binding.getJavaArgumentType(argNum);
+ String argName = getArgumentName(argNum);
+ if (type.isPrimitiveArray()) {
+ String offsetArg = offsetArgName(argNum);
+ if (inBytes) {
+ throw new RuntimeException("Can not specify RangeCheckBytes for primitive array arguments (failed on function " +
+ binding.getName() + ", argument " + argName + ")");
+ }
+ writer.println(" BufferFactory.rangeCheck(" + argName + ", " + offsetArg + ", " +
+ new MessageFormat((String) rangeChecks.get(argNumBox)).format(argumentNameArray()) +
+ ");");
+ } else if (!type.isPrimitive()) {
+ // Assume it's a Buffer
+ writer.print(" BufferFactory.rangeCheck");
+ if (inBytes) {
+ writer.print("Bytes");
+ }
+ writer.println("(" + argName + ", " +
+ new MessageFormat((String) rangeChecks.get(argNumBox)).format(argumentNameArray()) +
+ ");");
+ }
+ }
}
protected void emitCall(MethodBinding binding, PrintWriter writer, boolean direct) {
@@ -601,11 +653,7 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
writer.print(" return " + returnType.getName() + ".create(_res.order(ByteOrder.nativeOrder()))");
} else {
writer.println(" _res.order(ByteOrder.nativeOrder());");
- String[] argumentNames = new String[binding.getNumArguments()];
- for (int i = 0; i < binding.getNumArguments(); i++) {
- argumentNames[i] = getArgumentName(i);
- }
- String expr = new MessageFormat(fmt).format(argumentNames);
+ String expr = new MessageFormat(fmt).format(argumentNameArray());
PointerType cReturnTypePointer = binding.getCReturnType().asPointer();
CompoundType cReturnType = null;
if (cReturnTypePointer != null) {
@@ -648,6 +696,14 @@ public class JavaMethodBindingEmitter extends FunctionEmitter
}
}
+ protected String[] argumentNameArray() {
+ String[] argumentNames = new String[binding.getNumArguments()];
+ for (int i = 0; i < binding.getNumArguments(); i++) {
+ argumentNames[i] = getArgumentName(i);
+ }
+ return argumentNames;
+ }
+
public static String javaThisArgumentName() {
return "jthis0";
}
diff --git a/src/classes/com/sun/gluegen/runtime/BufferFactory.java b/src/classes/com/sun/gluegen/runtime/BufferFactory.java
index ca66e6915..dd8856a43 100644
--- a/src/classes/com/sun/gluegen/runtime/BufferFactory.java
+++ b/src/classes/com/sun/gluegen/runtime/BufferFactory.java
@@ -161,4 +161,81 @@ public class BufferFactory {
throw new RuntimeException("Unknown buffer type " + buf.getClass().getName());
}
+
+ public static void rangeCheck(byte[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(char[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(short[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(int[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(long[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(float[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(double[] array, int offset, int minElementsRemaining) {
+ if (array.length < offset + minElementsRemaining) {
+ throw new ArrayIndexOutOfBoundsException("Required " + minElementsRemaining + " elements in array, only had " + (array.length - offset));
+ }
+ }
+
+ public static void rangeCheck(Buffer buffer, int minElementsRemaining) {
+ if (buffer == null) {
+ return;
+ }
+
+ if (buffer.remaining() < minElementsRemaining) {
+ throw new IndexOutOfBoundsException("Required " + minElementsRemaining + " remaining elements in buffer, only had " + buffer.remaining());
+ }
+ }
+
+ public static void rangeCheckBytes(Buffer buffer, int minBytesRemaining) {
+ if (buffer == null) {
+ return;
+ }
+
+ int elementsRemaining = buffer.remaining();
+ int bytesRemaining = 0;
+ if (buffer instanceof ByteBuffer) {
+ bytesRemaining = elementsRemaining;
+ } else if (buffer instanceof FloatBuffer) {
+ bytesRemaining = elementsRemaining * SIZEOF_FLOAT;
+ } else if (buffer instanceof IntBuffer) {
+ bytesRemaining = elementsRemaining * SIZEOF_INT;
+ } else if (buffer instanceof ShortBuffer) {
+ bytesRemaining = elementsRemaining * SIZEOF_SHORT;
+ } else if (buffer instanceof DoubleBuffer) {
+ bytesRemaining = elementsRemaining * SIZEOF_DOUBLE;
+ } else if (buffer instanceof LongBuffer) {
+ bytesRemaining = elementsRemaining * SIZEOF_LONG;
+ }
+ if (bytesRemaining < minBytesRemaining) {
+ throw new IndexOutOfBoundsException("Required " + minBytesRemaining + " remaining bytes in buffer, only had " + bytesRemaining);
+ }
+ }
}