diff options
Diffstat (limited to 'core/src/main/native/spark_compress_lzf_LZF.c')
-rw-r--r-- | core/src/main/native/spark_compress_lzf_LZF.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/core/src/main/native/spark_compress_lzf_LZF.c b/core/src/main/native/spark_compress_lzf_LZF.c new file mode 100644 index 0000000000..c2a59def3e --- /dev/null +++ b/core/src/main/native/spark_compress_lzf_LZF.c @@ -0,0 +1,90 @@ +#include "spark_compress_lzf_LZF.h" +#include <lzf.h> + + +/* Helper function to throw an exception */ +static void throwException(JNIEnv *env, const char* className) { + jclass cls = (*env)->FindClass(env, className); + if (cls != 0) /* If cls is null, an exception was already thrown */ + (*env)->ThrowNew(env, cls, ""); +} + + +/* + * Since LZF.compress() and LZF.decompress() have the same signatures + * and differ only in which lzf_ function they call, implement both in a + * single function and pass it a pointer to the correct lzf_ function. + */ +static jint callCompressionFunction + (unsigned int (*func)(const void *const, unsigned int, void *, unsigned int), + JNIEnv *env, jclass cls, jbyteArray inArray, jint inOff, jint inLen, + jbyteArray outArray, jint outOff, jint outLen) +{ + jint inCap; + jint outCap; + jbyte *inData = 0; + jbyte *outData = 0; + jint ret; + jint s; + + if (!inArray || !outArray) { + throwException(env, "java/lang/NullPointerException"); + goto cleanup; + } + + inCap = (*env)->GetArrayLength(env, inArray); + outCap = (*env)->GetArrayLength(env, outArray); + + // Check if any of the offset/length pairs is invalid; we do this by OR'ing + // things we don't want to be negative and seeing if the result is negative + s = inOff | inLen | (inOff + inLen) | (inCap - (inOff + inLen)) | + outOff | outLen | (outOff + outLen) | (outCap - (outOff + outLen)); + if (s < 0) { + throwException(env, "java/lang/IndexOutOfBoundsException"); + goto cleanup; + } + + inData = (*env)->GetPrimitiveArrayCritical(env, inArray, 0); + outData = (*env)->GetPrimitiveArrayCritical(env, outArray, 0); + + if (!inData || !outData) { + // Out of memory - JVM will throw OutOfMemoryError + goto cleanup; + } + + ret = func(inData + inOff, inLen, outData + outOff, outLen); + +cleanup: + if (inData) + (*env)->ReleasePrimitiveArrayCritical(env, inArray, inData, 0); + if (outData) + (*env)->ReleasePrimitiveArrayCritical(env, outArray, outData, 0); + + return ret; +} + +/* + * Class: spark_compress_lzf_LZF + * Method: compress + * Signature: ([B[B)I + */ +JNIEXPORT jint JNICALL Java_spark_compress_lzf_LZF_compress + (JNIEnv *env, jclass cls, jbyteArray inArray, jint inOff, jint inLen, + jbyteArray outArray, jint outOff, jint outLen) +{ + return callCompressionFunction(lzf_compress, env, cls, + inArray, inOff, inLen, outArray,outOff, outLen); +} + +/* + * Class: spark_compress_lzf_LZF + * Method: decompress + * Signature: ([B[B)I + */ +JNIEXPORT jint JNICALL Java_spark_compress_lzf_LZF_decompress + (JNIEnv *env, jclass cls, jbyteArray inArray, jint inOff, jint inLen, + jbyteArray outArray, jint outOff, jint outLen) +{ + return callCompressionFunction(lzf_decompress, env, cls, + inArray, inOff, inLen, outArray,outOff, outLen); +} |