initial commit
This commit is contained in:
5
src/main/java/net/woggioni/jzstd/ZSTD_CCtx.java
Normal file
5
src/main/java/net/woggioni/jzstd/ZSTD_CCtx.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import com.sun.jna.PointerType;
|
||||
|
||||
public class ZSTD_CCtx extends PointerType { }
|
5
src/main/java/net/woggioni/jzstd/ZSTD_CDict.java
Normal file
5
src/main/java/net/woggioni/jzstd/ZSTD_CDict.java
Normal file
@@ -0,0 +1,5 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import com.sun.jna.PointerType;
|
||||
|
||||
public class ZSTD_CDict extends PointerType { }
|
12
src/main/java/net/woggioni/jzstd/ZSTD_EndDirective.java
Normal file
12
src/main/java/net/woggioni/jzstd/ZSTD_EndDirective.java
Normal file
@@ -0,0 +1,12 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum ZSTD_EndDirective {
|
||||
ZSTD_e_continue(0),
|
||||
ZSTD_e_flush(1),
|
||||
ZSTD_e_end(2);
|
||||
|
||||
public final int value;
|
||||
}
|
13
src/main/java/net/woggioni/jzstd/ZSTD_ResetDirective.java
Normal file
13
src/main/java/net/woggioni/jzstd/ZSTD_ResetDirective.java
Normal file
@@ -0,0 +1,13 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum ZSTD_ResetDirective {
|
||||
ZSTD_reset_session_only(1),
|
||||
ZSTD_reset_parameters(2),
|
||||
ZSTD_reset_session_and_parameters(3);
|
||||
|
||||
public final int value;
|
||||
}
|
14
src/main/java/net/woggioni/jzstd/ZSTD_bounds.java
Normal file
14
src/main/java/net/woggioni/jzstd/ZSTD_bounds.java
Normal file
@@ -0,0 +1,14 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
import net.woggioni.jzstd.internal.size_t;
|
||||
|
||||
@Structure.FieldOrder({"error", "lowerBound", "upperBound"})
|
||||
public class ZSTD_bounds extends Structure {
|
||||
|
||||
public size_t error;
|
||||
public int lowerBound;
|
||||
public int upperBound;
|
||||
|
||||
public static class ByValue extends ZSTD_bounds implements Structure.ByValue {}
|
||||
}
|
28
src/main/java/net/woggioni/jzstd/ZSTD_cParameter.java
Normal file
28
src/main/java/net/woggioni/jzstd/ZSTD_cParameter.java
Normal file
@@ -0,0 +1,28 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum ZSTD_cParameter {
|
||||
compressionLevel(100),
|
||||
windowLog(101),
|
||||
hashLog(102),
|
||||
chainLog(103),
|
||||
searchLog(104),
|
||||
minMatch(105),
|
||||
targetLength(106),
|
||||
strategy(107),
|
||||
enableLongDistanceMatching(160),
|
||||
ldmHashLog(161),
|
||||
ldmMinMatch(162),
|
||||
ldmBucketSizeLog(163),
|
||||
ldmHashRateLog(164),
|
||||
contentSizeFlag(200),
|
||||
checksumFlag(201),
|
||||
dictIDFlag(202),
|
||||
nbWorkers(400),
|
||||
jobSize(401),
|
||||
overlapLog(402);
|
||||
|
||||
public final int value;
|
||||
}
|
124
src/main/java/net/woggioni/jzstd/ZstdOutputStream.java
Normal file
124
src/main/java/net/woggioni/jzstd/ZstdOutputStream.java
Normal file
@@ -0,0 +1,124 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import net.woggioni.jzstd.internal.ZSTD_inBuffer;
|
||||
import net.woggioni.jzstd.internal.ZSTD_outBuffer;
|
||||
import net.woggioni.jzstd.internal.ZstdLibrary;
|
||||
import net.woggioni.jzstd.internal.size_t;
|
||||
|
||||
import java.io.OutputStream;
|
||||
|
||||
public class ZstdOutputStream extends OutputStream {
|
||||
private final OutputStream sink;
|
||||
private final ZSTD_CCtx ctx;
|
||||
private final boolean ctx_owner;
|
||||
|
||||
private final byte[] buffer;
|
||||
private final ZSTD_inBuffer input;
|
||||
private final ZSTD_outBuffer output;
|
||||
private int pos;
|
||||
private ZSTD_EndDirective flag;
|
||||
|
||||
private ZstdOutputStream(OutputStream sink,
|
||||
ZSTD_CCtx ctx,
|
||||
boolean ctx_owner,
|
||||
int bufferSize) {
|
||||
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 = ZSTD_EndDirective.ZSTD_e_continue;
|
||||
}
|
||||
|
||||
public static ZstdOutputStream from(OutputStream sink,
|
||||
ZSTD_CCtx ctx) {
|
||||
return from(sink, ctx, 0x10000);
|
||||
}
|
||||
|
||||
public static ZstdOutputStream from(
|
||||
OutputStream sink,
|
||||
ZSTD_CCtx ctx,
|
||||
int bufferSize) {
|
||||
ZstdLibrary.CCtx_reset(ctx, ZSTD_ResetDirective.ZSTD_reset_session_only);
|
||||
ZstdLibrary.CCtx_refCDict(ctx, null);
|
||||
return new ZstdOutputStream(sink, ctx, false, bufferSize);
|
||||
}
|
||||
|
||||
public static ZstdOutputStream from(OutputStream sink) {
|
||||
return from(sink, 3);
|
||||
}
|
||||
|
||||
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(ZSTD_cParameter.compressionLevel);
|
||||
if (compressionLevel < range.lowerBound || compressionLevel > range.upperBound) {
|
||||
throw new IllegalArgumentException("Compression level must be between " +
|
||||
range.lowerBound + " and " + range.upperBound);
|
||||
}
|
||||
ZSTD_CCtx ctx = ZstdLibrary.ZSTD_createCCtx();
|
||||
ZstdLibrary.CCtx_setParameter(ctx,
|
||||
ZSTD_cParameter.compressionLevel, compressionLevel);
|
||||
return new ZstdOutputStream(sink, ctx, true, bufferSize);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void flush() {
|
||||
input.src.put(buffer, 0, pos);
|
||||
input.src.position(0);
|
||||
input.pos = new size_t(0);
|
||||
input.size = new size_t(pos);
|
||||
pos = 0;
|
||||
while (true) {
|
||||
size_t rc = ZstdLibrary.compressStream2(ctx, output, input, flag);
|
||||
if (output.pos.longValue() > 0) {
|
||||
output.dst.get(buffer);
|
||||
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 == ZSTD_EndDirective.ZSTD_e_continue) {
|
||||
break;
|
||||
} else if (flag == ZSTD_EndDirective.ZSTD_e_end && rc.intValue() == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) {
|
||||
if (pos == buffer.length) flush();
|
||||
buffer[pos++] = (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();
|
||||
written += writeSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SneakyThrows
|
||||
public void close() {
|
||||
flag = ZSTD_EndDirective.ZSTD_e_end;
|
||||
flush();
|
||||
sink.close();
|
||||
if (ctx_owner) ZstdLibrary.ZSTD_freeCCtx(ctx);
|
||||
}
|
||||
}
|
@@ -0,0 +1,32 @@
|
||||
package net.woggioni.jzstd.internal;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public enum ZSTD_ErrorCode {
|
||||
ZSTD_error_no_error(0),
|
||||
ZSTD_error_GENERIC(1),
|
||||
ZSTD_error_prefix_unknown(10),
|
||||
ZSTD_error_version_unsupported(12),
|
||||
ZSTD_error_frameParameter_unsupported(14),
|
||||
ZSTD_error_frameParameter_windowTooLarge(16),
|
||||
ZSTD_error_corruption_detected(20),
|
||||
ZSTD_error_checksum_wrong(22),
|
||||
ZSTD_error_dictionary_corrupted(30),
|
||||
ZSTD_error_dictionary_wrong(32),
|
||||
ZSTD_error_dictionaryCreation_failed(34),
|
||||
ZSTD_error_parameter_unsupported(40),
|
||||
ZSTD_error_parameter_outOfBound(42),
|
||||
ZSTD_error_tableLog_tooLarge(44),
|
||||
ZSTD_error_maxSymbolValue_tooLarge(46),
|
||||
ZSTD_error_maxSymbolValue_tooSmall(48),
|
||||
ZSTD_error_stage_wrong(60),
|
||||
ZSTD_error_init_missing(62),
|
||||
ZSTD_error_memory_allocation(64),
|
||||
ZSTD_error_workSpace_tooSmall(66),
|
||||
ZSTD_error_dstSize_tooSmall(70),
|
||||
ZSTD_error_srcSize_wrong(72),
|
||||
ZSTD_error_dstBuffer_null(74);
|
||||
|
||||
public final int value;
|
||||
}
|
19
src/main/java/net/woggioni/jzstd/internal/ZSTD_inBuffer.java
Normal file
19
src/main/java/net/woggioni/jzstd/internal/ZSTD_inBuffer.java
Normal file
@@ -0,0 +1,19 @@
|
||||
package net.woggioni.jzstd.internal;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
@Structure.FieldOrder(value = {"src", "size", "pos"})
|
||||
public class ZSTD_inBuffer extends Structure {
|
||||
public ByteBuffer src;
|
||||
public size_t size;
|
||||
public size_t pos;
|
||||
|
||||
public ZSTD_inBuffer(int size) {
|
||||
this.src = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
|
||||
this.size = new size_t(this.src.capacity());
|
||||
this.pos = new size_t(this.src.capacity());
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package net.woggioni.jzstd.internal;
|
||||
|
||||
import com.sun.jna.Structure;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
@Structure.FieldOrder({"dst", "size", "pos"})
|
||||
public class ZSTD_outBuffer extends Structure {
|
||||
public ByteBuffer dst;
|
||||
public size_t size;
|
||||
public size_t pos;
|
||||
|
||||
public ZSTD_outBuffer(int size) {
|
||||
this.dst = ByteBuffer.allocateDirect(size).order(ByteOrder.nativeOrder());
|
||||
this.size = new size_t(dst.capacity());
|
||||
this.pos = new size_t(0);
|
||||
}
|
||||
}
|
82
src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java
Normal file
82
src/main/java/net/woggioni/jzstd/internal/ZstdLibrary.java
Normal file
@@ -0,0 +1,82 @@
|
||||
package net.woggioni.jzstd.internal;
|
||||
|
||||
import com.sun.jna.Native;
|
||||
import net.woggioni.jzstd.*;
|
||||
|
||||
public class ZstdLibrary {
|
||||
|
||||
public static void checkReturnCode(size_t rc) {
|
||||
if (ZSTD_isError(rc)) {
|
||||
String error = getErrorString(rc);
|
||||
throw new RuntimeException(error);
|
||||
}
|
||||
}
|
||||
|
||||
public static size_t compressStream2(
|
||||
ZSTD_CCtx cctx,
|
||||
ZSTD_outBuffer output,
|
||||
ZSTD_inBuffer input,
|
||||
ZSTD_EndDirective endOp) {
|
||||
size_t rc = ZSTD_compressStream2(cctx, output, input, endOp.value);
|
||||
checkReturnCode(rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
public static ZSTD_bounds cParam_getBounds(ZSTD_cParameter cParam) {
|
||||
ZSTD_bounds bounds = ZSTD_cParam_getBounds(cParam.value);
|
||||
checkReturnCode(bounds.error);
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public static void CCtx_setParameter(ZSTD_CCtx cctx, ZSTD_cParameter param, int value) {
|
||||
size_t rc = ZSTD_CCtx_setParameter(cctx, param.value, value);
|
||||
if (ZSTD_isError(rc)) {
|
||||
throw new RuntimeException(getErrorString(rc));
|
||||
}
|
||||
}
|
||||
|
||||
public static ZSTD_ErrorCode getErrorCode(size_t functionResult) {
|
||||
int code = ZSTD_getErrorCode(functionResult);
|
||||
for (ZSTD_ErrorCode result : ZSTD_ErrorCode.values()) {
|
||||
if (code == result.value) return result;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown error code " + code);
|
||||
}
|
||||
|
||||
public static String getErrorString(size_t functionResult) {
|
||||
return ZSTD_getErrorString(getErrorCode(functionResult).value);
|
||||
}
|
||||
|
||||
public static void CCtx_reset(ZSTD_CCtx ctx, ZSTD_ResetDirective resetDirective) {
|
||||
checkReturnCode(ZSTD_CCtx_reset(ctx, resetDirective.value));
|
||||
}
|
||||
|
||||
public static void CCtx_refCDict(ZSTD_CCtx ctx, ZSTD_CDict cdict) {
|
||||
checkReturnCode(ZSTD_CCtx_refCDict(ctx, cdict));
|
||||
}
|
||||
|
||||
public 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);
|
||||
public static native size_t ZSTD_initCStream(ZSTD_CCtx ctx, int compressionLevel);
|
||||
|
||||
public static native ZSTD_CCtx ZSTD_createCStream();
|
||||
public static native void ZSTD_freeCStream(ZSTD_CCtx ctx);
|
||||
public static native size_t ZSTD_compressStream2(
|
||||
ZSTD_CCtx cctx,
|
||||
ZSTD_outBuffer output,
|
||||
ZSTD_inBuffer input,
|
||||
int endOp);
|
||||
|
||||
public static native ZSTD_bounds.ByValue ZSTD_cParam_getBounds(int cParam);
|
||||
public static native boolean ZSTD_isError(size_t code);
|
||||
public static native int ZSTD_getErrorCode(size_t functionResult);
|
||||
public static native String ZSTD_getErrorString(int code);
|
||||
|
||||
public static native size_t ZSTD_CCtx_reset(ZSTD_CCtx ctx, int reset_directive);
|
||||
public static native size_t ZSTD_CCtx_refCDict(ZSTD_CCtx ctx, ZSTD_CDict cdict);
|
||||
|
||||
static {
|
||||
Native.register("zstd");
|
||||
}
|
||||
}
|
11
src/main/java/net/woggioni/jzstd/internal/size_t.java
Normal file
11
src/main/java/net/woggioni/jzstd/internal/size_t.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package net.woggioni.jzstd.internal;
|
||||
|
||||
import com.sun.jna.IntegerType;
|
||||
import com.sun.jna.Native;
|
||||
|
||||
public class size_t extends IntegerType {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
public size_t() { this(0); }
|
||||
public size_t(long value) { super(Native.SIZE_T_SIZE, value); }
|
||||
}
|
336
src/main/kotlin/net/woggioni/kzstd/Library.kt
Normal file
336
src/main/kotlin/net/woggioni/kzstd/Library.kt
Normal file
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* This Kotlin source file was generated by the Gradle 'init' task.
|
||||
*/
|
||||
package net.woggioni.kzstd
|
||||
|
||||
import com.sun.jna.*
|
||||
import java.io.BufferedInputStream
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.lang.IllegalArgumentException
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
import kotlin.math.min
|
||||
|
||||
import net.woggioni.jzstd.internal.ZSTD_inBuffer as jZSTD_inBuffer
|
||||
import net.woggioni.jzstd.internal.ZSTD_outBuffer as jZSTD_outBuffer
|
||||
import net.woggioni.jzstd.ZSTD_CCtx as jZSTD_CCtx
|
||||
|
||||
class ZstdInputStream private constructor(
|
||||
private val source: InputStream,
|
||||
private val ctx: ZstdLibrary.ZSTD_CCtx,
|
||||
private val ctx_owner: Boolean,
|
||||
bufferSize: Int) : InputStream() {
|
||||
|
||||
override fun read(): Int {
|
||||
TODO("Not yet implemented")
|
||||
}
|
||||
|
||||
override fun read(b: ByteArray, off: Int, len: Int): Int {
|
||||
return super.read(b, off, len)
|
||||
}
|
||||
}
|
||||
|
||||
class ZstdOutputStream private constructor(
|
||||
private val sink: OutputStream,
|
||||
private val ctx: ZstdLibrary.ZSTD_CCtx,
|
||||
private val ctx_owner: Boolean,
|
||||
bufferSize: Int) : OutputStream() {
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun from(sink: OutputStream,
|
||||
ctx: ZstdLibrary.ZSTD_CCtx,
|
||||
bufferSize: Int = 0x10000) = let {
|
||||
ZstdLibrary.CCtx_reset(ctx, ZstdLibrary.ZSTD_ResetDirective.ZSTD_reset_session_only)
|
||||
ZstdLibrary.CCtx_refCDict(ctx, null)
|
||||
ZstdOutputStream(sink, ctx, false, bufferSize)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@JvmOverloads
|
||||
fun from(sink: OutputStream,
|
||||
compressionLevel: Int = 3,
|
||||
bufferSize: Int = 0x10000) = let {
|
||||
val range = ZstdLibrary.ZSTD_cParam_getBounds(
|
||||
ZstdLibrary.ZSTD_cParameter.compressionLevel.value)
|
||||
if (compressionLevel < range.lowerBound || compressionLevel > range.upperBound) {
|
||||
throw IllegalArgumentException("Compression level must be between " +
|
||||
"${range.lowerBound} and ${range.upperBound}")
|
||||
}
|
||||
val ctx = ZstdLibrary.ZSTD_createCCtx()
|
||||
ZstdLibrary.CCtx_setParameter(ctx,
|
||||
ZstdLibrary.ZSTD_cParameter.compressionLevel, compressionLevel)
|
||||
ZstdOutputStream(sink, ctx, true, bufferSize)
|
||||
}
|
||||
}
|
||||
|
||||
private val buffer = ByteArray(bufferSize)
|
||||
private val input = ZstdLibrary.ZSTD_inBuffer(bufferSize)
|
||||
private val output = ZstdLibrary.ZSTD_outBuffer(bufferSize)
|
||||
private var pos = 0
|
||||
private var flag = ZstdLibrary.ZSTD_EndDirective.ZSTD_e_continue
|
||||
|
||||
|
||||
override fun flush() {
|
||||
input.src.put(buffer, 0, pos)
|
||||
input.src.position(0)
|
||||
input.pos = 0
|
||||
input.size = pos.toLong()
|
||||
pos = 0
|
||||
while (true) {
|
||||
val rc = ZstdLibrary.compressStream2(ctx, output, input, flag)
|
||||
if (output.pos > 0) {
|
||||
output.dst.get(buffer)
|
||||
output.dst.position(0)
|
||||
sink.write(buffer, 0, output.pos.toInt())
|
||||
output.pos = 0
|
||||
}
|
||||
if (input.pos == input.size && flag == ZstdLibrary.ZSTD_EndDirective.ZSTD_e_continue) {
|
||||
break
|
||||
} else if (flag == ZstdLibrary.ZSTD_EndDirective.ZSTD_e_end && rc == 0L) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun write(b: Int) {
|
||||
if (pos == buffer.size) flush()
|
||||
buffer[pos++] = b.toByte()
|
||||
}
|
||||
|
||||
override fun write(b: ByteArray, off: Int, len: Int) {
|
||||
var written = 0
|
||||
while (written < len - off) {
|
||||
val writeSize = min(len, buffer.size - pos)
|
||||
System.arraycopy(b, off, buffer, pos, writeSize)
|
||||
pos += writeSize
|
||||
if (pos == buffer.size) flush()
|
||||
written += writeSize
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
flag = ZstdLibrary.ZSTD_EndDirective.ZSTD_e_end
|
||||
flush()
|
||||
sink.close()
|
||||
if (ctx_owner) ZstdLibrary.ZSTD_freeCCtx(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
class HelloWorld {
|
||||
|
||||
inline fun <reified T : AutoCloseable, R> withResource(closeable: T, body: (resource: T) -> R): R {
|
||||
return closeable.use {
|
||||
body(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkReturnCode(rc: Long) {
|
||||
if (ZstdLibrary.ZSTD_isError(rc)) {
|
||||
val error = ZstdLibrary.getErrorString(rc)
|
||||
throw RuntimeException(error)
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
BufferedInputStream(HelloWorld::class.java.getResourceAsStream("/Richard_Dawkins_The_Selfish_Gene.pdf")).use { inputStream ->
|
||||
Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf.zst").let {
|
||||
ZstdOutputStream.from(Files.newOutputStream(it))
|
||||
}.use { outputStream ->
|
||||
val buffer = ByteArray(0x1000)
|
||||
while (true) {
|
||||
val read = inputStream.read(buffer)
|
||||
if (read < 0) break
|
||||
outputStream.write(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object ZstdLibrary {
|
||||
|
||||
fun checkReturnCode(rc: Long) {
|
||||
if (ZSTD_isError(rc)) {
|
||||
val error = getErrorString(rc)
|
||||
throw RuntimeException(error)
|
||||
}
|
||||
}
|
||||
|
||||
class ZSTD_CCtx : PointerType()
|
||||
|
||||
class ZSTD_CDict : PointerType()
|
||||
|
||||
|
||||
@Structure.FieldOrder(value = ["src", "size", "pos"])
|
||||
class ZSTD_inBuffer(size: Int = 0) : Structure() {
|
||||
@JvmField
|
||||
var src = ByteBuffer.allocateDirect(size)
|
||||
|
||||
@JvmField
|
||||
var size: Long = src.capacity().toLong()
|
||||
|
||||
@JvmField
|
||||
var pos: Long = src.capacity().toLong()
|
||||
}
|
||||
|
||||
@Structure.FieldOrder(value = ["dst", "size", "pos"])
|
||||
class ZSTD_outBuffer(size: Int = 0) : Structure() {
|
||||
@JvmField
|
||||
var dst = ByteBuffer.allocateDirect(size)
|
||||
|
||||
@JvmField
|
||||
var size: Long = dst.capacity().toLong()
|
||||
|
||||
@JvmField
|
||||
var pos: Long = 0
|
||||
}
|
||||
|
||||
@Structure.FieldOrder(value = ["error", "lowerBound", "upperBound"])
|
||||
open class ZSTD_bounds(
|
||||
@JvmField
|
||||
var error: Long = 0,
|
||||
@JvmField
|
||||
var lowerBound: Int = 0,
|
||||
@JvmField
|
||||
var upperBound: Int = 0
|
||||
) : Structure() {
|
||||
class ByValue : ZSTD_bounds(), Structure.ByValue
|
||||
}
|
||||
|
||||
enum class ZSTD_ResetDirective(@JvmField val value: Int) {
|
||||
ZSTD_reset_session_only(1),
|
||||
ZSTD_reset_parameters(2),
|
||||
ZSTD_reset_session_and_parameters(3)
|
||||
}
|
||||
|
||||
enum class ZSTD_EndDirective(@JvmField val value: Int) {
|
||||
ZSTD_e_continue(0),
|
||||
ZSTD_e_flush(1),
|
||||
ZSTD_e_end(2)
|
||||
}
|
||||
|
||||
enum class ZSTD_cParameter(@JvmField val value: Int) {
|
||||
compressionLevel(100),
|
||||
windowLog(101),
|
||||
hashLog(102),
|
||||
chainLog(103),
|
||||
searchLog(104),
|
||||
minMatch(105),
|
||||
targetLength(106),
|
||||
strategy(107),
|
||||
enableLongDistanceMatching(160),
|
||||
ldmHashLog(161),
|
||||
ldmMinMatch(162),
|
||||
ldmBucketSizeLog(163),
|
||||
ldmHashRateLog(164),
|
||||
contentSizeFlag(200),
|
||||
checksumFlag(201),
|
||||
dictIDFlag(202),
|
||||
nbWorkers(400),
|
||||
jobSize(401),
|
||||
overlapLog(402)
|
||||
}
|
||||
|
||||
enum class ZSTD_ErrorCode(@JvmField val value: Int) {
|
||||
ZSTD_error_no_error(0),
|
||||
ZSTD_error_GENERIC(1),
|
||||
ZSTD_error_prefix_unknown(10),
|
||||
ZSTD_error_version_unsupported(12),
|
||||
ZSTD_error_frameParameter_unsupported(14),
|
||||
ZSTD_error_frameParameter_windowTooLarge(16),
|
||||
ZSTD_error_corruption_detected(20),
|
||||
ZSTD_error_checksum_wrong(22),
|
||||
ZSTD_error_dictionary_corrupted(30),
|
||||
ZSTD_error_dictionary_wrong(32),
|
||||
ZSTD_error_dictionaryCreation_failed(34),
|
||||
ZSTD_error_parameter_unsupported(40),
|
||||
ZSTD_error_parameter_outOfBound(42),
|
||||
ZSTD_error_tableLog_tooLarge(44),
|
||||
ZSTD_error_maxSymbolValue_tooLarge(46),
|
||||
ZSTD_error_maxSymbolValue_tooSmall(48),
|
||||
ZSTD_error_stage_wrong(60),
|
||||
ZSTD_error_init_missing(62),
|
||||
ZSTD_error_memory_allocation(64),
|
||||
ZSTD_error_workSpace_tooSmall(66),
|
||||
ZSTD_error_dstSize_tooSmall(70),
|
||||
ZSTD_error_srcSize_wrong(72),
|
||||
ZSTD_error_dstBuffer_null(74),
|
||||
}
|
||||
|
||||
fun compressStream2(
|
||||
cctx: ZSTD_CCtx,
|
||||
output: ZSTD_outBuffer,
|
||||
input: ZSTD_inBuffer,
|
||||
endOp: ZSTD_EndDirective): Long {
|
||||
val rc = ZSTD_compressStream2(cctx, output, input, endOp.value)
|
||||
checkReturnCode(rc)
|
||||
return rc
|
||||
}
|
||||
|
||||
fun cParam_getBounds(cParam: ZSTD_cParameter): ZSTD_bounds = let {
|
||||
val bounds = ZSTD_cParam_getBounds(cParam.value)
|
||||
if (ZSTD_isError(bounds.error)) throw RuntimeException()
|
||||
bounds
|
||||
}
|
||||
|
||||
fun CCtx_setParameter(cctx: ZSTD_CCtx, param: ZSTD_cParameter, value: Int) {
|
||||
val rc = ZSTD_CCtx_setParameter(cctx, param.value, value)
|
||||
if (ZSTD_isError(rc)) {
|
||||
throw RuntimeException(getErrorString(rc))
|
||||
}
|
||||
}
|
||||
|
||||
fun getErrorCode(functionResult: Long): ZSTD_ErrorCode {
|
||||
val code = ZSTD_getErrorCode(functionResult)
|
||||
for (result in ZSTD_ErrorCode.values()) {
|
||||
if (code == result.value) return result
|
||||
}
|
||||
throw IllegalArgumentException("Unknown error code $code")
|
||||
}
|
||||
|
||||
fun getErrorString(functionResult: Long): String {
|
||||
return ZSTD_getErrorString(getErrorCode(functionResult).value)
|
||||
}
|
||||
|
||||
fun CCtx_reset(ctx: ZSTD_CCtx, resetDirective: ZSTD_ResetDirective) {
|
||||
checkReturnCode(ZSTD_CCtx_reset(ctx, resetDirective.value))
|
||||
}
|
||||
|
||||
fun CCtx_refCDict(ctx: ZSTD_CCtx, cdict: ZSTD_CDict?) {
|
||||
checkReturnCode(ZSTD_CCtx_refCDict(ctx, cdict))
|
||||
}
|
||||
|
||||
external fun ZSTD_CCtx_setParameter(cctx: ZSTD_CCtx, param: Int, value: Int): Long
|
||||
external fun ZSTD_createCCtx(): ZSTD_CCtx
|
||||
external fun ZSTD_freeCCtx(cctx: ZSTD_CCtx): Long
|
||||
external fun ZSTD_initCStream(ctx: ZSTD_CCtx, compressionLevel: Int): Long
|
||||
|
||||
external fun ZSTD_createCStream(): ZSTD_CCtx
|
||||
external fun ZSTD_freeCStream(p: ZSTD_CCtx)
|
||||
external fun ZSTD_compressStream2(
|
||||
cctx: ZSTD_CCtx,
|
||||
output: ZSTD_outBuffer,
|
||||
input: ZSTD_inBuffer,
|
||||
endOp: Int): Long
|
||||
|
||||
external fun ZSTD_cParam_getBounds(cParam: Int): ZSTD_bounds.ByValue
|
||||
external fun ZSTD_isError(code: Long): Boolean
|
||||
external fun ZSTD_getErrorCode(functionResult: Long): Int
|
||||
external fun ZSTD_getErrorString(code: Int): String
|
||||
|
||||
external fun ZSTD_CCtx_reset(ctx: ZSTD_CCtx, reset_directive: Int): Long
|
||||
external fun ZSTD_CCtx_refCDict(ctx: ZSTD_CCtx, cdict: ZSTD_CDict?): Long
|
||||
|
||||
init {
|
||||
Native.register("zstd")
|
||||
}
|
||||
}
|
61
src/test/java/net/woggioni/jzstd/SillyTest.java
Normal file
61
src/test/java/net/woggioni/jzstd/SillyTest.java
Normal file
@@ -0,0 +1,61 @@
|
||||
package net.woggioni.jzstd;
|
||||
|
||||
import lombok.SneakyThrows;
|
||||
import net.woggioni.jwo.Chronometer;
|
||||
import net.woggioni.jzstd.internal.ZstdLibrary;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
|
||||
public class SillyTest {
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void test() {
|
||||
var ctx = ZstdLibrary.ZSTD_createCCtx();
|
||||
ZstdLibrary.CCtx_setParameter(ctx, ZSTD_cParameter.compressionLevel, 3);
|
||||
try (InputStream is = new BufferedInputStream(
|
||||
getClass().getResourceAsStream("/Richard_Dawkins_The_Selfish_Gene.pdf"))) {
|
||||
try (OutputStream os =
|
||||
ZstdOutputStream.from(
|
||||
Files.newOutputStream(
|
||||
Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf.zst")))) {
|
||||
byte[] buffer = new byte[0x1000];
|
||||
while (true) {
|
||||
int read = is.read(buffer);
|
||||
if (read < 0) break;
|
||||
os.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@SneakyThrows
|
||||
public void test4() {
|
||||
Chronometer chronometer = new Chronometer();
|
||||
Path file = Paths.get("/tmp/citylots.json");
|
||||
Path destination = file.getParent().resolve(file.getFileName().toString() + ".zst");
|
||||
try (InputStream is = new BufferedInputStream(Files.newInputStream(file))) {
|
||||
try (OutputStream os =
|
||||
ZstdOutputStream.from(
|
||||
Files.newOutputStream(destination), 11)) {
|
||||
chronometer.reset();
|
||||
byte[] buffer = new byte[0x1000];
|
||||
while (true) {
|
||||
int read = is.read(buffer);
|
||||
if (read < 0) break;
|
||||
os.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println(
|
||||
String.format("Elapsed time: %.3f s", chronometer.elapsed(Chronometer.UnitOfMeasure.SECONDS)));
|
||||
}
|
||||
}
|
58
src/test/kotlin/net/woggioni/kstd/SillyTest.kt
Normal file
58
src/test/kotlin/net/woggioni/kstd/SillyTest.kt
Normal file
@@ -0,0 +1,58 @@
|
||||
package net.woggioni.kstd
|
||||
|
||||
import lombok.SneakyThrows
|
||||
import net.woggioni.kzstd.ZstdLibrary
|
||||
import net.woggioni.kzstd.ZstdOutputStream
|
||||
import org.junit.jupiter.api.Test
|
||||
import java.io.BufferedInputStream
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Paths
|
||||
|
||||
import net.woggioni.jzstd.internal.ZstdLibrary as jZstdLibrary
|
||||
import net.woggioni.jzstd.ZSTD_CCtx
|
||||
import net.woggioni.jzstd.internal.size_t
|
||||
import net.woggioni.jzstd.internal.ZSTD_outBuffer as jZSTD_outBuffer
|
||||
import net.woggioni.jzstd.internal.ZSTD_inBuffer as jZSTD_inBuffer
|
||||
|
||||
class SillyTest {
|
||||
@Test
|
||||
@SneakyThrows
|
||||
fun test() {
|
||||
BufferedInputStream(
|
||||
javaClass.getResourceAsStream("/Richard_Dawkins_The_Selfish_Gene.pdf")).use { inputstream ->
|
||||
ZstdOutputStream.from(
|
||||
Files.newOutputStream(
|
||||
Paths.get("/tmp/Richard_Dawkins_The_Selfish_Gene.pdf.zst"))).use { outputStream ->
|
||||
val buffer = ByteArray(0x1000)
|
||||
while (true) {
|
||||
val read: Int = inputstream.read(buffer)
|
||||
if (read < 0) break
|
||||
outputStream.write(buffer, 0, read)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
fun test2() {
|
||||
val ctx = ZstdLibrary.ZSTD_createCCtx()
|
||||
ZstdLibrary.CCtx_setParameter(ctx, ZstdLibrary.ZSTD_cParameter.compressionLevel, 3)
|
||||
val input = ZstdLibrary.ZSTD_inBuffer(0x1000)
|
||||
input.pos = 0
|
||||
val output = ZstdLibrary.ZSTD_outBuffer(0x1000)
|
||||
ZstdLibrary.compressStream2(ctx, output, input, ZstdLibrary.ZSTD_EndDirective.ZSTD_e_continue)
|
||||
ZstdLibrary.ZSTD_freeCCtx(ctx)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test3() {
|
||||
val ctx = jZstdLibrary.ZSTD_createCCtx()
|
||||
// jZstdLibrary.CCtx_setParameter(ctx, ZstdLibrary.ZSTD_cParameter.compressionLevel, 3)
|
||||
val input = jZSTD_inBuffer(0x1000)
|
||||
input.pos = size_t(0)
|
||||
val output = jZSTD_outBuffer(0x1000)
|
||||
// ZstdLibrary.ZSTD_compressStream2(ctx, output, input, ZstdLibrary.ZSTD_EndDirective.ZSTD_e_continue.value)
|
||||
jZstdLibrary.ZSTD_freeCCtx(ctx)
|
||||
}
|
||||
}
|
0
src/test/resources/index.html
Normal file
0
src/test/resources/index.html
Normal file
Reference in New Issue
Block a user