diff --git a/src/java/net/jpountz/lz4/LZ4JNI.java b/src/java/net/jpountz/lz4/LZ4JNI.java index 0b5c1617..5b8fc7a8 100644 --- a/src/java/net/jpountz/lz4/LZ4JNI.java +++ b/src/java/net/jpountz/lz4/LZ4JNI.java @@ -34,6 +34,7 @@ enum LZ4JNI { static native void init(); static native int LZ4_compress_limitedOutput(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen); + static native int LZ4_compress_fast_continue(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen, int acceleration); static native int LZ4_compressHC(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen, int compressionLevel); static native int LZ4_decompress_fast(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, byte[] destArray, ByteBuffer destBuffer, int destOff, int destLen); static native int LZ4_decompress_safe(byte[] srcArray, ByteBuffer srcBuffer, int srcOff, int srcLen, byte[] destArray, ByteBuffer destBuffer, int destOff, int maxDestLen); diff --git a/src/jni/net_jpountz_lz4_LZ4JNI.c b/src/jni/net_jpountz_lz4_LZ4JNI.c index c2f8c226..ed359cc9 100644 --- a/src/jni/net_jpountz_lz4_LZ4JNI.c +++ b/src/jni/net_jpountz_lz4_LZ4JNI.c @@ -85,6 +85,54 @@ JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compress_1limitedOutput } +/* + * Class: net_jpountz_lz4_LZ4JNI + * Method: LZ4_compress_fast_contine + * Signature: ([BLjava/nio/ByteBuffer;II[BLjava/nio/ByteBuffer;III)I + */ +JNIEXPORT jint JNICALL Java_net_jpountz_lz4_LZ4JNI_LZ4_1compress_1fast_1continue + (JNIEnv *env, jclass cls, jbyteArray srcArray, jobject srcBuffer, jint srcOff, jint srcLen, jbyteArray destArray, jobject destBuffer, jint destOff, jint maxDestLen, jint acceleration) { + + char* in; + char* out; + jint compressed; + + if (srcArray != NULL) { + in = (char*) (*env)->GetPrimitiveArrayCritical(env, srcArray, 0); + } else { + in = (char*) (*env)->GetDirectBufferAddress(env, srcBuffer); + } + + if (in == NULL) { + throw_OOM(env); + return 0; + } + + if (destArray != NULL) { + out = (char*) (*env)->GetPrimitiveArrayCritical(env, destArray, 0); + } else { + out = (char*) (*env)->GetDirectBufferAddress(env, destBuffer); + } + + if (out == NULL) { + throw_OOM(env); + return 0; + } + + LZ4_stream_t lz4_state; + LZ4_resetStream (&lz4_state); + compressed = LZ4_compress_fast_continue (&lz4_state, in + srcOff, out + destOff, srcLen, maxDestLen, acceleration); + + if (srcArray != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, srcArray, in, 0); + } + if (destArray != NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, destArray, out, 0); + } + + return compressed; +} + /* * Class: net_jpountz_lz4_LZ4JNI * Method: LZ4_compressHC diff --git a/src/resources/net/jpountz/util/darwin/x86_64/liblz4-java.dylib b/src/resources/net/jpountz/util/darwin/x86_64/liblz4-java.dylib index b065dc8d..65bd2719 100755 Binary files a/src/resources/net/jpountz/util/darwin/x86_64/liblz4-java.dylib and b/src/resources/net/jpountz/util/darwin/x86_64/liblz4-java.dylib differ diff --git a/src/resources/net/jpountz/util/linux/aarch64/liblz4-java.so b/src/resources/net/jpountz/util/linux/aarch64/liblz4-java.so index 2dc71561..20d27d49 100755 Binary files a/src/resources/net/jpountz/util/linux/aarch64/liblz4-java.so and b/src/resources/net/jpountz/util/linux/aarch64/liblz4-java.so differ diff --git a/src/resources/net/jpountz/util/linux/amd64/liblz4-java.so b/src/resources/net/jpountz/util/linux/amd64/liblz4-java.so index f1d8df5b..484632fa 100755 Binary files a/src/resources/net/jpountz/util/linux/amd64/liblz4-java.so and b/src/resources/net/jpountz/util/linux/amd64/liblz4-java.so differ diff --git a/src/resources/net/jpountz/util/linux/i386/liblz4-java.so b/src/resources/net/jpountz/util/linux/i386/liblz4-java.so index aa50fd15..5f6c6261 100755 Binary files a/src/resources/net/jpountz/util/linux/i386/liblz4-java.so and b/src/resources/net/jpountz/util/linux/i386/liblz4-java.so differ diff --git a/src/resources/net/jpountz/util/linux/ppc64le/liblz4-java.so b/src/resources/net/jpountz/util/linux/ppc64le/liblz4-java.so index 3efdf335..eaa99877 100755 Binary files a/src/resources/net/jpountz/util/linux/ppc64le/liblz4-java.so and b/src/resources/net/jpountz/util/linux/ppc64le/liblz4-java.so differ diff --git a/src/resources/net/jpountz/util/linux/s390x/liblz4-java.so b/src/resources/net/jpountz/util/linux/s390x/liblz4-java.so index f3f627a6..e1367ea0 100755 Binary files a/src/resources/net/jpountz/util/linux/s390x/liblz4-java.so and b/src/resources/net/jpountz/util/linux/s390x/liblz4-java.so differ diff --git a/src/resources/net/jpountz/util/win32/amd64/liblz4-java.so b/src/resources/net/jpountz/util/win32/amd64/liblz4-java.so index d100dd22..6d8860d6 100755 Binary files a/src/resources/net/jpountz/util/win32/amd64/liblz4-java.so and b/src/resources/net/jpountz/util/win32/amd64/liblz4-java.so differ diff --git a/src/test/net/jpountz/lz4/LZ4FrameIOStreamTest.java b/src/test/net/jpountz/lz4/LZ4FrameIOStreamTest.java index 37f9166d..2ccc33ea 100644 --- a/src/test/net/jpountz/lz4/LZ4FrameIOStreamTest.java +++ b/src/test/net/jpountz/lz4/LZ4FrameIOStreamTest.java @@ -51,6 +51,12 @@ */ @RunWith(Parameterized.class) public class LZ4FrameIOStreamTest { + private final static String LZ4_COMMAND; + + static { + LZ4_COMMAND = System.getProperty("os.name").contains("Windows") ? "lz4.exe" : "lz4"; + } + private static void copy(InputStream in, OutputStream out) throws IOException { final byte[] buffer = new byte[1 << 10]; int inSize = in.read(buffer);; @@ -428,7 +434,7 @@ private void nativeCompress(String... args) throws IOException, InterruptedExcep try { final ProcessBuilder builder = new ProcessBuilder(); final ArrayList cmd = new ArrayList<>(); - cmd.add("lz4"); + cmd.add(LZ4_COMMAND); if (args != null) { cmd.addAll(Arrays.asList(args)); } @@ -470,7 +476,7 @@ public void testUncompressableEnd() throws IOException { } private static boolean hasNativeLz4CLI() throws IOException, InterruptedException { - ProcessBuilder checkBuilder = new ProcessBuilder().command("lz4", "-V").inheritIO(); + ProcessBuilder checkBuilder = new ProcessBuilder().command(LZ4_COMMAND, "-V").inheritIO(); Process checkProcess = checkBuilder.start(); return checkProcess.waitFor() == 0; } @@ -498,7 +504,7 @@ public void testNativeDecompresIfAvailable() throws IOException, InterruptedExce } final ProcessBuilder builder = new ProcessBuilder(); - builder.command("lz4", "-d", "-vvvvvvv", lz4File.getAbsolutePath(), unCompressedFile.getAbsolutePath()).inheritIO(); + builder.command(LZ4_COMMAND, "-d", "-vvvvvvv", lz4File.getAbsolutePath(), unCompressedFile.getAbsolutePath()).inheritIO(); Process process = builder.start(); int retval = process.waitFor(); Assert.assertEquals(0, retval); diff --git a/src/test/net/jpountz/lz4/LZ4Test.java b/src/test/net/jpountz/lz4/LZ4Test.java index 92ad9433..bae3aac2 100644 --- a/src/test/net/jpountz/lz4/LZ4Test.java +++ b/src/test/net/jpountz/lz4/LZ4Test.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; +import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.io.File; import java.io.FilenameFilter; @@ -485,6 +486,19 @@ public void testRoundtripIssue12() { testRoundTrip(data, 9, data.length - 9); } + @Test + public void testNativeFastContinue() { + final byte[] src = "01234567890123456789".getBytes(StandardCharsets.US_ASCII); + final byte[] dest = new byte[LZ4JNI.LZ4_compressBound(src.length)]; + final int compressLen = LZ4JNI.LZ4_compress_fast_continue(src, null, 0, src.length, dest, null, 0, dest.length, 1); + final byte[] compressed = Arrays.copyOf(dest, compressLen); + + final byte[] decompressed = new byte[src.length]; + final int decompressedLen = LZ4JNI.LZ4_decompress_fast(compressed, null, 0, decompressed, null, 0, decompressed.length); + assertEquals(compressLen, decompressedLen); + assertArrayEquals(src, decompressed); + } + private static void assertCompressedArrayEquals(String message, byte[] expected, byte[] actual) { int off = 0; int decompressedOff = 0;