added input stream and basic unit test, removed kotlin code

This commit is contained in:
2020-04-26 21:37:29 +01:00
parent ba704f18e5
commit 33aed799c0
14 changed files with 6083 additions and 477 deletions

6
.gitattributes vendored Normal file
View File

@@ -0,0 +1,6 @@
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
# Ignore Gradle project-specific cache directory
.gradle
# Ignore Gradle build output directory
build
.idea

View File

@@ -1,11 +1,3 @@
/*
* This file was generated by the Gradle 'init' task.
*
* This generated file contains a sample Kotlin library project to get you started.
*/
fun property(name : String) = project.property(name).toString()
plugins {
// Apply the Kotlin JVM plugin to add support for Kotlin.
id("org.jetbrains.kotlin.jvm") version "1.3.70"
@@ -15,6 +7,9 @@ plugins {
application
}
group = "net.woggioni"
version = "0.1"
repositories {
// Use jcenter for resolving dependencies.
// You can declare any Maven/Ivy/file repository here.
@@ -23,6 +18,8 @@ repositories {
mavenCentral()
}
fun property(name : String) = project.property(name).toString()
dependencies {
// Align versions of all Kotlin components
compileOnly(platform("org.jetbrains.kotlin:kotlin-bom"))
@@ -32,7 +29,7 @@ dependencies {
compileOnly("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
testImplementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("net.java.dev.jna", "jna", "5.5.0")
implementation("net.java.dev.jna", "jna", property("jna.version"))
// https://mvnrepository.com/artifact/org.projectlombok/lombok
compileOnly("org.projectlombok", "lombok", property("lombok.version"))
@@ -42,6 +39,7 @@ dependencies {
testAnnotationProcessor("org.projectlombok", "lombok", property("lombok.version"))
testRuntimeOnly("org.junit.jupiter", "junit-jupiter-engine", property("junit.version"))
testImplementation("org.junit.jupiter","junit-jupiter-api", property("junit.version"))
testImplementation("org.junit.jupiter","junit-jupiter-params", property("junit.version"))
testImplementation("net.woggioni", "jwo", "1.0")
}

View File

@@ -1,2 +1,4 @@
junit.version=5.6.2
lombok.version=1.18.12
jna.version=5.5.0
kotlin.version=1.3.70

View File

@@ -1,10 +1 @@
/*
* This file was generated by the Gradle 'init' task.
*
* The settings file is used to specify which projects to include in your build.
*
* Detailed information about configuring a multi-project build in Gradle can be found
* in the user manual at https://docs.gradle.org/6.3/userguide/multi_project_builds.html
*/
rootProject.name = "kzstd"
rootProject.name = "jzstd"

View File

@@ -0,0 +1,5 @@
package net.woggioni.jzstd;
import com.sun.jna.PointerType;
public class ZSTD_DCtx extends PointerType { }

View File

@@ -0,0 +1,5 @@
package net.woggioni.jzstd;
import com.sun.jna.PointerType;
public class ZSTD_DDict extends PointerType { }

View File

@@ -0,0 +1,110 @@
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.InputStream;
public class ZstdInputStream extends InputStream {
private final InputStream source;
private final ZSTD_DCtx ctx;
private final boolean ctx_owner;
private final ZSTD_inBuffer input;
private final ZSTD_outBuffer output;
private enum State {
AVAILABLE_INPUT, SOURCE_DEPLETED, CTX_FLUSHED
}
private State state = State.AVAILABLE_INPUT;
private static final int inputBufferSize = ZstdLibrary.DStreamInSize();
private static final int outputBufferSize = ZstdLibrary.DStreamOutSize();
private ZstdInputStream(InputStream source,
ZSTD_DCtx ctx,
boolean ctx_owner) {
this.source = source;
this.ctx = ctx;
this.ctx_owner = ctx_owner;
this.input = new ZSTD_inBuffer(inputBufferSize);
this.output = new ZSTD_outBuffer(outputBufferSize);
}
public static ZstdInputStream from(InputStream source) {
ZSTD_DCtx ctx = ZstdLibrary.ZSTD_createDStream();
return new ZstdInputStream(source, ctx, true);
}
public static ZstdInputStream from(InputStream source, ZSTD_DCtx ctx) {
return new ZstdInputStream(source, ctx, false);
}
@SneakyThrows
void fill() {
size_t zero = new size_t(0);
output.pos = zero;
do {
if (input.pos.intValue() == input.size.intValue()) {
if (state == State.SOURCE_DEPLETED) {
return;
} else if(input.src.position() == input.src.capacity()) {
input.src.position(0);
}
while (input.src.position() < input.src.capacity()) {
int b = source.read();
if (b < 0) {
state = State.SOURCE_DEPLETED;
break;
}
input.src.put((byte) b);
}
input.pos = zero;
input.size = new size_t(input.src.position());
output.pos = zero;
}
int rc = ZstdLibrary.decompressStream(ctx, output, input);
if(rc == 0) {
state = State.CTX_FLUSHED;
break;
}
} while (output.pos.intValue() < output.size.intValue());
output.dst.position(0);
}
@Override
public int read() {
if (output.dst.position() == output.pos.intValue()) {
if (state == State.CTX_FLUSHED) return -1;
else fill();
}
return output.dst.get();
}
@Override
public int read(byte[] arr, int off, int len) {
int totalRead = 0;
while (totalRead < len) {
if(output.pos.intValue() == output.dst.position()) {
if(state == State.CTX_FLUSHED) {
if(totalRead == 0) --totalRead;
break;
}
else fill();
}
int toBeRead = Math.min(len, output.pos.intValue() - output.dst.position());
output.dst.get(arr, off, toBeRead);
totalRead += toBeRead;
}
return totalRead;
}
@Override
public void close() {
if (ctx_owner) ZstdLibrary.freeDStream(ctx);
}
}

View File

@@ -61,7 +61,7 @@ public class ZstdLibrary {
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_freeCStream(ZSTD_CCtx ctx);
public static native size_t ZSTD_compressStream2(
ZSTD_CCtx cctx,
ZSTD_outBuffer output,
@@ -76,6 +76,44 @@ public class ZstdLibrary {
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);
public static native ZSTD_DCtx ZSTD_createDStream();
public static native size_t ZSTD_freeDStream(ZSTD_DCtx ctx);
public static native size_t ZSTD_initDStream(ZSTD_DCtx ctx);
public static native size_t ZSTD_DCtx_reset(ZSTD_DCtx ctx, int reset_directive);
public static native size_t ZSTD_DCtx_refDDict(ZSTD_CCtx ctx, ZSTD_DDict ddict);
public static native size_t ZSTD_decompressStream(ZSTD_DCtx ctx, ZSTD_outBuffer output, ZSTD_inBuffer input);
public static native size_t ZSTD_DStreamInSize();
public static native size_t ZSTD_DStreamOutSize();
public static void freeDStream(ZSTD_DCtx ctx) {
checkReturnCode(ZSTD_freeDStream(ctx));
}
public static void ZSTD_DCtx_reset(ZSTD_DCtx ctx, ZSTD_ResetDirective reset_directive) {
checkReturnCode(ZSTD_DCtx_reset(ctx, reset_directive.value));
}
public static void refDDict(ZSTD_CCtx ctx, ZSTD_DDict ddict) {
checkReturnCode(ZSTD_DCtx_refDDict(ctx, ddict));
}
public static int decompressStream(ZSTD_DCtx ctx, ZSTD_outBuffer output, ZSTD_inBuffer input) {
size_t rc = ZSTD_decompressStream(ctx, output, input);
checkReturnCode(rc);
return rc.intValue();
}
public static int DStreamInSize() {
return ZSTD_DStreamInSize().intValue();
}
public static int DStreamOutSize() {
return ZSTD_DStreamOutSize().intValue();
}
static {
Native.register("zstd");
}

View File

@@ -1,336 +0,0 @@
/*
* 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")
}
}

View File

@@ -0,0 +1,66 @@
package net.woggioni.jzstd;
import lombok.SneakyThrows;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.ArgumentsProvider;
import org.junit.jupiter.params.provider.ArgumentsSource;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.DigestInputStream;
import java.security.DigestOutputStream;
import java.security.MessageDigest;
import java.util.stream.Stream;
class InputStreamProvider implements ArgumentsProvider {
@Override
@SneakyThrows
public Stream<? extends Arguments> provideArguments(ExtensionContext context) {
return Stream.of(
Arguments.of(getClass().getResourceAsStream("/index.html")),
Arguments.of(Files.newInputStream(Paths.get("/tmp/citylots.json")))
);
}
}
public class BasicTest {
@SneakyThrows
@ParameterizedTest
@ArgumentsSource(InputStreamProvider.class)
public void test(InputStream testStream) {
MessageDigest md5 = MessageDigest.getInstance("MD5");
ByteArrayInputStream compressedStream;
try (InputStream is = new BufferedInputStream(testStream)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (OutputStream os = new DigestOutputStream(ZstdOutputStream.from(baos), md5)) {
byte[] buffer = new byte[0x1000];
while (true) {
int read = is.read(buffer);
if (read < 0) break;
os.write(buffer, 0, read);
}
}
compressedStream = new ByteArrayInputStream(baos.toByteArray());
}
final byte[] originalDigest = md5.digest();
md5.reset();
try (InputStream is = new DigestInputStream(
ZstdInputStream.from(compressedStream), md5)) {
byte [] buffer = new byte[0x10000];
while(true) {
int read = is.read(buffer);
if(read < 0) break;
}
}
Assertions.assertArrayEquals(originalDigest, md5.digest());
}
}

View File

@@ -1,61 +0,0 @@
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)));
}
}

View File

@@ -1,58 +0,0 @@
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)
}
}

File diff suppressed because it is too large Load Diff