diff --git a/src/main/java/net/woggioni/jzstd/EndDirective.java b/src/main/java/net/woggioni/jzstd/EndDirective.java deleted file mode 100644 index f27d304..0000000 --- a/src/main/java/net/woggioni/jzstd/EndDirective.java +++ /dev/null @@ -1,12 +0,0 @@ -package net.woggioni.jzstd; - -import lombok.RequiredArgsConstructor; - -@RequiredArgsConstructor -public enum EndDirective { - Continue(0), - Flush(1), - End(2); - - public final int value; -} diff --git a/src/main/java/net/woggioni/jzstd/ParameterBoundaries.java b/src/main/java/net/woggioni/jzstd/ParameterBoundaries.java new file mode 100644 index 0000000..63f0e6a --- /dev/null +++ b/src/main/java/net/woggioni/jzstd/ParameterBoundaries.java @@ -0,0 +1,9 @@ +package net.woggioni.jzstd; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class ParameterBoundaries { + public final int min; + public final int max; +} diff --git a/src/main/java/net/woggioni/jzstd/ZstdCompressionCtx.java b/src/main/java/net/woggioni/jzstd/ZstdCompressionCtx.java index 97bcd75..7bc81b2 100644 --- a/src/main/java/net/woggioni/jzstd/ZstdCompressionCtx.java +++ b/src/main/java/net/woggioni/jzstd/ZstdCompressionCtx.java @@ -1,6 +1,7 @@ package net.woggioni.jzstd; import net.woggioni.jzstd.internal.ZSTD_CCtx; +import net.woggioni.jzstd.internal.ZSTD_bounds; import net.woggioni.jzstd.internal.ZstdLibrary; public class ZstdCompressionCtx implements AutoCloseable { @@ -19,4 +20,9 @@ public class ZstdCompressionCtx implements AutoCloseable { public void close() { ZstdLibrary.freeCStream(ctx); } + + public ParameterBoundaries getParameterBoundaries(CompressionParameter param) { + ZSTD_bounds bounds = ZstdLibrary.cParam_getBounds(param); + return new ParameterBoundaries(bounds.lowerBound, bounds.upperBound); + } } diff --git a/src/main/java/net/woggioni/jzstd/ZstdOutputStream.java b/src/main/java/net/woggioni/jzstd/ZstdOutputStream.java index b93a13e..fb9d45f 100644 --- a/src/main/java/net/woggioni/jzstd/ZstdOutputStream.java +++ b/src/main/java/net/woggioni/jzstd/ZstdOutputStream.java @@ -10,37 +10,30 @@ public class ZstdOutputStream extends OutputStream { private final ZstdCompressionCtx ctx; private final boolean ctx_owner; - private final byte[] buffer; private final ZSTD_inBuffer input; private final ZSTD_outBuffer output; - private int pos; - private EndDirective flag; + private ZSTD_EndDirective flag; + + private static final int inputBufferSize = ZstdLibrary.CStreamInSize(); + private static final int outputBufferSize = ZstdLibrary.CStreamOutSize(); + private ZstdOutputStream(OutputStream sink, ZstdCompressionCtx ctx, - boolean ctx_owner, - int bufferSize) { + boolean ctx_owner) { this.sink = sink; this.ctx = ctx; this.ctx_owner = ctx_owner; - this.buffer = new byte[bufferSize]; - this.input = new ZSTD_inBuffer(bufferSize); - this.output = new ZSTD_outBuffer(bufferSize); - this.pos = 0; - this.flag = EndDirective.Continue; - } - - public static ZstdOutputStream from(OutputStream sink, - ZstdCompressionCtx ctx) { - return from(sink, ctx, 0x10000); + this.input = new ZSTD_inBuffer(inputBufferSize); + this.output = new ZSTD_outBuffer(outputBufferSize); + this.flag = ZSTD_EndDirective.ZSTD_e_continue; } public static ZstdOutputStream from( OutputStream sink, - ZstdCompressionCtx ctx, - int bufferSize) { + ZstdCompressionCtx ctx) { ctx.init(); - return new ZstdOutputStream(sink, ctx, false, bufferSize); + return new ZstdOutputStream(sink, ctx, false); } public static ZstdOutputStream from(OutputStream sink) { @@ -49,12 +42,6 @@ public class ZstdOutputStream extends OutputStream { public static ZstdOutputStream from(OutputStream sink, int compressionLevel) { - return from(sink, compressionLevel, 0x1000); - } - - public static ZstdOutputStream from(OutputStream sink, - int compressionLevel, - int bufferSize) { ZSTD_bounds range = ZstdLibrary.cParam_getBounds(CompressionParameter.compressionLevel); if (compressionLevel < range.lowerBound || compressionLevel > range.upperBound) { throw new IllegalArgumentException("Compression level must be between " + @@ -62,29 +49,31 @@ public class ZstdOutputStream extends OutputStream { } ZstdCompressionCtx ctx = new ZstdCompressionCtx(); ctx.setParameter(CompressionParameter.compressionLevel, compressionLevel); - return new ZstdOutputStream(sink, ctx, true, bufferSize); + return new ZstdOutputStream(sink, ctx, true); } @Override @SneakyThrows public void flush() { - input.src.put(buffer, 0, pos); + size_t zero = new size_t(0); + input.size = new size_t(input.src.position()); input.src.position(0); - input.pos = new size_t(0); - input.size = new size_t(pos); - pos = 0; + input.pos = zero; while (true) { size_t rc = ZstdLibrary.compressStream2(ctx.ctx, output, input, flag); if (output.pos.longValue() > 0) { - output.dst.get(buffer); + int limit = output.pos.intValue(); + while(output.dst.position() < limit) { + byte b = output.dst.get(); + sink.write(b); + } + output.pos = zero; output.dst.position(0); - sink.write(buffer, 0, output.pos.intValue()); - output.pos = new size_t(0); } - if (input.pos.longValue() == input.size.longValue() && flag == EndDirective.Continue) { + if (input.pos.longValue() == input.size.longValue() && flag == ZSTD_EndDirective.ZSTD_e_continue) { break; - } else if (flag == EndDirective.End && rc.intValue() == 0) { + } else if (flag == ZSTD_EndDirective.ZSTD_e_end && rc.intValue() == 0) { break; } } @@ -92,18 +81,17 @@ public class ZstdOutputStream extends OutputStream { @Override public void write(int b) { - if (pos == buffer.length) flush(); - buffer[pos++] = (byte) b; + if (input.src.position() == input.src.capacity()) flush(); + input.src.put((byte) b); } @Override public void write(byte[] arr, int off, int len) { var written = 0; while (written < len - off) { - int writeSize = Math.min(len, buffer.length - pos); - System.arraycopy(arr, off, buffer, pos, writeSize); - pos += writeSize; - if (pos == buffer.length) flush(); + int writeSize = Math.min(len, input.src.capacity() - input.src.position()); + input.src.put(arr, off, writeSize); + if (input.src.position() == input.src.capacity()) flush(); written += writeSize; } } @@ -111,7 +99,7 @@ public class ZstdOutputStream extends OutputStream { @Override @SneakyThrows public void close() { - flag = EndDirective.End; + flag = ZSTD_EndDirective.ZSTD_e_end; flush(); sink.close(); if (ctx_owner) ctx.close(); diff --git a/src/main/java/net/woggioni/jzstd/internal/ZSTD_EndDirective.java b/src/main/java/net/woggioni/jzstd/internal/ZSTD_EndDirective.java new file mode 100644 index 0000000..cd16eb8 --- /dev/null +++ b/src/main/java/net/woggioni/jzstd/internal/ZSTD_EndDirective.java @@ -0,0 +1,11 @@ +package net.woggioni.jzstd.internal; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public enum ZSTD_EndDirective { + ZSTD_e_continue(0), + ZSTD_e_flush(1), + ZSTD_e_end(2); + public final int value; +} diff --git a/src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java b/src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java index 82ddbb2..7470fd6 100644 --- a/src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java +++ b/src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java @@ -16,7 +16,7 @@ public class ZstdLibrary { ZSTD_CCtx cctx, ZSTD_outBuffer output, ZSTD_inBuffer input, - EndDirective endOp) { + ZSTD_EndDirective endOp) { size_t rc = ZSTD_compressStream2(cctx, output, input, endOp.value); checkReturnCode(rc); return rc; @@ -55,6 +55,15 @@ public class ZstdLibrary { checkReturnCode(ZSTD_CCtx_refCDict(ctx, cdict)); } + public static int CStreamInSize() { + return ZSTD_CStreamInSize().intValue(); + } + + public static int CStreamOutSize() { + return ZSTD_CStreamOutSize().intValue(); + } + + public static void freeCStream(ZSTD_CCtx ctx) { freeCCtx(ctx); } @@ -62,6 +71,9 @@ public class ZstdLibrary { checkReturnCode(ZSTD_freeCStream(ctx)); } + private static native size_t ZSTD_CStreamInSize(); + private static native size_t ZSTD_CStreamOutSize(); + private static native size_t ZSTD_CCtx_setParameter(ZSTD_CCtx cctx, int param, int value); public static native ZSTD_CCtx ZSTD_createCCtx(); public static native size_t ZSTD_freeCCtx(ZSTD_CCtx cctx);