From f1a15f3c754202e04b251cad24d2bc248a7f1298 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Mon, 20 Jan 2020 20:49:17 +0100 Subject: [PATCH 01/36] migrate to zlib-ng this is much better, it runs a fair bit faster and the resulting libzlib.so is only 14 KiB! (down from like 100 KiB) --- .gitignore | 7 ---- natives/.gitignore | 6 +++ natives/Makefile | 17 +++++++-- natives/compile.sh | 3 +- natives/src/example/java/NativeTests.java | 38 +++++++++++-------- natives/src/main/native/zlib/Makefile | 24 ++++++------ .../src/main/native/zlib/source/deflater.cpp | 6 +-- .../src/main/native/zlib/source/inflater.cpp | 8 ++-- natives/toolchain/x86-linux-gnu | 9 ----- 9 files changed, 64 insertions(+), 54 deletions(-) create mode 100644 natives/.gitignore delete mode 100644 natives/toolchain/x86-linux-gnu diff --git a/.gitignore b/.gitignore index ad190d2ae..8f08f9a92 100644 --- a/.gitignore +++ b/.gitignore @@ -29,10 +29,3 @@ test_out/ # project root /src/ - -#native libraries -/natives/**/*.so -/natives/**/*.dll -/natives/**/*.o -/natives/src/main/native/*/lib-*/ -/natives/src/main/native/*/build*/ diff --git a/natives/.gitignore b/natives/.gitignore new file mode 100644 index 000000000..b44691fbf --- /dev/null +++ b/natives/.gitignore @@ -0,0 +1,6 @@ +/**/*.so +/**/*.dll +/**/*.o +/*.tar.gz +/src/main/native/*/build*/ +/tmp/ diff --git a/natives/Makefile b/natives/Makefile index 0550fe4f4..3375c9edd 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -6,30 +6,35 @@ export TOPDIR := $(CURDIR) export SRCDIR := $(TOPDIR)/src/main/native export OUTDIR := $(TOPDIR)/src/main/resources -export CFLAGS := -shared -Ofast -ffast-math -fPIC -ffunction-sections -fdata-sections -fvisibility=hidden -flto +export CFLAGS := -shared -Ofast -ffast-math -fPIC -ffunction-sections -fdata-sections -fvisibility=hidden export CXXFLAGS := $(CFLAGS) export LDFLAGS := $(CFLAGS) -Wl,--gc-sections export SOURCES := $(SRCDIR)/common/source export INCLUDES := $(SRCDIR)/common/include $(JAVA_HOME)include $(JAVA_HOME)include/linux -export ARCHS := x86_64-linux-gnu x86-linux-gnu x86_64-w64-mingw32 +export ARCHS := x86_64-linux-gnu +#export ARCHS := x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-gcc),$(arch))) #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) export ARCH_TASKS := $(foreach arch,$(ARCHS),build.$(arch)) export MODULES := zlib +export LIBDIR := $(TOPDIR)/src/main/native/lib +export LIB_URL_BASE := https://cloud.daporkchop.net/programs/source/ +export LIBS := zlib-ng-1.2.11.tar.gz + #.PHONY: build clean .FORCE $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach module,$(MODULES),$(arch)/$(module).lib)) .PHONY: build clean .FORCE #build: $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach mod,$(MODULES),$(OUTDIR)/$(arch)/lib$(mod).so)) -build: $(ARCH_TASKS) +build: $(ARCH_TASKS) $(LIBS) build.%: .FORCE $(foreach module,$(MODULES),%/$(module).lib) @echo Built libraries for $(shell echo '$@' | perl -n -e '/build\.(.+)/ && print $$1')! -%.lib: .FORCE +%.lib: .FORCE $(LIBS) @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/\/([^.]+)\.lib$$/ && print $$1') && \ _ARCH=$(shell echo "$@" | perl -n -e '/^([^\/]*?)\/[^.]+\.lib$$/ && print $$1') && \ $(MAKE) -C $(SRCDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(SRCDIR)/$$_PRJ_NAME $$_ARCH && \ @@ -41,4 +46,8 @@ clean: $(foreach mod,$(MODULES),clean.$(mod)) clean.%: @$(MAKE) -C $(SRCDIR)/$(subst clean.,,$@) clean +%.tar.gz: + @echo "Downloading source for $@" + @curl -o $@ $(LIB_URL_BASE)$@ + .FORCE: diff --git a/natives/compile.sh b/natives/compile.sh index 17203fb4c..35b30a329 100644 --- a/natives/compile.sh +++ b/natives/compile.sh @@ -2,4 +2,5 @@ #i use this script simply so that i can add the natives compilation as a run configuration in intellij -make -j$( nproc ) +#make -j$( nproc ) +make diff --git a/natives/src/example/java/NativeTests.java b/natives/src/example/java/NativeTests.java index 9ff71683b..956766140 100644 --- a/natives/src/example/java/NativeTests.java +++ b/natives/src/example/java/NativeTests.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -36,25 +36,33 @@ public static void main(String... args) throws IOException { orig.setByte(i, ThreadLocalRandom.current().nextInt(8)); } ByteBuf compressed = Unpooled.directBuffer(SIZE >>> 3, SIZE).clear(); + ByteBuf decompressed = Unpooled.directBuffer(SIZE, SIZE); - try (PDeflater deflater = PNatives.ZLIB.get().deflater(Zlib.ZLIB_LEVEL_BEST)) { - System.out.printf("Deflating with %s...\nFinished: %b\n", PorkUtil.className(deflater), deflater.finished()); - deflater.deflate(orig, compressed); - System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", deflater.readBytes(), deflater.writtenBytes(), deflater.finished()); - } + long startTime = System.currentTimeMillis(); + for (int pass = 0; pass < 3; pass++) { + orig.resetReaderIndex(); + compressed.clear(); + decompressed.clear(); - ByteBuf decompressed = Unpooled.directBuffer(SIZE, SIZE).clear(); + try (PDeflater deflater = PNatives.ZLIB.get().deflater(Zlib.ZLIB_LEVEL_BEST)) { + System.out.printf("Deflating with %s...\nFinished: %b\n", PorkUtil.className(deflater), deflater.finished()); + deflater.deflate(orig, compressed); + System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", deflater.readBytes(), deflater.writtenBytes(), deflater.finished()); + } - try (PInflater inflater = PNatives.ZLIB.get().inflater()) { - System.out.printf("Inflating with %s...\nFinished: %b\n", PorkUtil.className(inflater), inflater.finished()); - inflater.inflate(compressed, decompressed); - System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", inflater.readBytes(), inflater.writtenBytes(), inflater.finished()); - } + try (PInflater inflater = PNatives.ZLIB.get().inflater()) { + System.out.printf("Inflating with %s...\nFinished: %b\n", PorkUtil.className(inflater), inflater.finished()); + inflater.inflate(compressed, decompressed); + System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", inflater.readBytes(), inflater.writtenBytes(), inflater.finished()); + } - for (int i = 0; i < SIZE; i++) { - if (orig.getByte(i) != decompressed.getByte(i)) { - throw new IllegalStateException(); + for (int i = 0; i < SIZE; i++) { + if (orig.getByte(i) != decompressed.getByte(i)) { + throw new IllegalStateException(); + } } } + + System.out.printf("Took %.2fs!\n", (System.currentTimeMillis() - startTime) / 1000.0d); } } diff --git a/natives/src/main/native/zlib/Makefile b/natives/src/main/native/zlib/Makefile index f8886ed25..3f332ec0b 100644 --- a/natives/src/main/native/zlib/Makefile +++ b/natives/src/main/native/zlib/Makefile @@ -6,28 +6,23 @@ ifneq ($(BUILD),$(notdir $(CURDIR))) clean: @rm -rf build/ tmp/ -$(BUILD): $(CURDIR)/lib-zlib/zlib.h +$(BUILD): @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zlib-$(BUILD) -$(CURDIR)/lib-zlib/zlib.h: - @echo "Downloading zlib sources..." - @curl -o - https://cloud.daporkchop.net/programs/source/zlib-1.2.11.tar.gz | tar zxf - - @mv zlib-1.2.11/ lib-zlib/ - else -.PHONY: zlib-$(BUILD) +.PHONY: zlib-$(BUILD) lib-zlib include $(TOPDIR)/toolchain/$(BUILD) -SOURCES := $(SOURCES) $(PROJDIR)/source $(PROJDIR)/lib-zlib +SOURCES := $(SOURCES) $(PROJDIR)/source CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) CFLAGS := $(CFLAGS) -D__LARGEFILE64__SOURCE=1 -DHAVE__HIDDEN -DPIC -INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include +INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR) zlib-$(BUILD): $(OUTDIR)/$(BUILD)/libzlib.$(EXT) @@ -38,12 +33,19 @@ $(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Mak @echo "Stripping $@..." @strip $@ -%.c.o: $(CFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile +%.c.o: $(CFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile lib-zlib @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ -%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile +%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile lib-zlib @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ +lib-zlib: $(TOPDIR)/zlib-ng-1.2.11.tar.gz + @[ ! -d lib-zlib ] || rm -rf lib-zlib/ + @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz + @mv zlib-ng-1.2.11/ lib-zlib/ + @cd lib-zlib/ && CFLAGS="-Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. + @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile static + endif diff --git a/natives/src/main/native/zlib/source/deflater.cpp b/natives/src/main/native/zlib/source/deflater.cpp index 1874ef2e7..e8655654c 100644 --- a/natives/src/main/native/zlib/source/deflater.cpp +++ b/natives/src/main/native/zlib/source/deflater.cpp @@ -1,7 +1,7 @@ #include #include "net_daporkchop_lib_natives_zlib_NativeDeflater.h" -#include "../lib-zlib/zlib.h" +#include #include #include @@ -44,7 +44,7 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat int ret = deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); if (ret != Z_OK) { - char* msg = stream->msg; + const char* msg = stream->msg; free(stream); throwException(env, msg == nullptr ? "Couldn't init deflater!" : msg, ret); } @@ -61,7 +61,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } ret = deflateEnd(stream); - char* msg = stream->msg; + const char* msg = stream->msg; free(stream); if (ret != Z_OK) { diff --git a/natives/src/main/native/zlib/source/inflater.cpp b/natives/src/main/native/zlib/source/inflater.cpp index 9ac00f89e..27dfe23eb 100644 --- a/natives/src/main/native/zlib/source/inflater.cpp +++ b/natives/src/main/native/zlib/source/inflater.cpp @@ -1,7 +1,7 @@ #include #include "net_daporkchop_lib_natives_zlib_NativeInflater.h" -#include "../lib-zlib/zlib.h" +#include #include #include @@ -39,7 +39,7 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat int ret = inflateInit2(stream, windowBits); if (ret != Z_OK) { - char* msg = stream->msg; + const char* msg = stream->msg; free(stream); throwException(env, msg == nullptr ? "Couldn't init inflater!" : msg, ret); } @@ -51,14 +51,14 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati z_stream* stream = (z_stream*) ctx; int ret = inflateReset(stream); if (ret != Z_OK) { - char* msg = stream->msg; + const char* msg = stream->msg; free(stream); throwException(env, msg == nullptr ? "Couldn't reset inflater!" : msg, ret); return; } ret = inflateEnd(stream); - char* msg = stream->msg; + const char* msg = stream->msg; free(stream); if (ret != Z_OK) { diff --git a/natives/toolchain/x86-linux-gnu b/natives/toolchain/x86-linux-gnu deleted file mode 100644 index 0980fea81..000000000 --- a/natives/toolchain/x86-linux-gnu +++ /dev/null @@ -1,9 +0,0 @@ -export CFLAGS := $(CFLAGS) -m32 -flto=auto -fno-fat-lto-objects -export CXXFLAGS := $(CXXFLAGS) -m32 -flto=auto -fno-fat-lto-objects -export LDFLAGS := $(LDFLAGS) -m32 -flto=auto -fno-fat-lto-objects - -export CC := x86_64-linux-gnu-gcc -export CXX := x86_64-linux-gnu-g++ -export LD := x86_64-linux-gnu-g++ - -export EXT := so From bc12f24a2f3af6f23fe64b53d03a7d139caf7f9d Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Mon, 20 Jan 2020 21:03:31 +0100 Subject: [PATCH 02/36] actually use zlib-ng i am too autistic and was not actually building against it --- natives/Makefile | 3 +-- natives/compile.sh | 3 +-- natives/src/main/native/zlib/Makefile | 14 +++++----- .../src/main/native/zlib/source/deflater.cpp | 26 +++++++++---------- .../src/main/native/zlib/source/inflater.cpp | 26 +++++++++---------- 5 files changed, 35 insertions(+), 37 deletions(-) diff --git a/natives/Makefile b/natives/Makefile index 3375c9edd..db7ea8191 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -13,8 +13,7 @@ export LDFLAGS := $(CFLAGS) -Wl,--gc-sections export SOURCES := $(SRCDIR)/common/source export INCLUDES := $(SRCDIR)/common/include $(JAVA_HOME)include $(JAVA_HOME)include/linux -export ARCHS := x86_64-linux-gnu -#export ARCHS := x86_64-linux-gnu x86_64-w64-mingw32 +export ARCHS := x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-gcc),$(arch))) #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) export ARCH_TASKS := $(foreach arch,$(ARCHS),build.$(arch)) diff --git a/natives/compile.sh b/natives/compile.sh index 35b30a329..17203fb4c 100644 --- a/natives/compile.sh +++ b/natives/compile.sh @@ -2,5 +2,4 @@ #i use this script simply so that i can add the natives compilation as a run configuration in intellij -#make -j$( nproc ) -make +make -j$( nproc ) diff --git a/natives/src/main/native/zlib/Makefile b/natives/src/main/native/zlib/Makefile index 3f332ec0b..2af2126b0 100644 --- a/natives/src/main/native/zlib/Makefile +++ b/natives/src/main/native/zlib/Makefile @@ -26,26 +26,26 @@ INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR zlib-$(BUILD): $(OUTDIR)/$(BUILD)/libzlib.$(EXT) -$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile +$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) @echo "Linking $@..." - @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) + @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Stripping $@..." @strip $@ -%.c.o: $(CFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile lib-zlib +%.c.o: $(CFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ -%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile lib-zlib +%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ -lib-zlib: $(TOPDIR)/zlib-ng-1.2.11.tar.gz +$(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz @[ ! -d lib-zlib ] || rm -rf lib-zlib/ @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz @mv zlib-ng-1.2.11/ lib-zlib/ - @cd lib-zlib/ && CFLAGS="-Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. - @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile static + @cd lib-zlib/ && CFLAGS="-fPIC -Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. + @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a endif diff --git a/natives/src/main/native/zlib/source/deflater.cpp b/natives/src/main/native/zlib/source/deflater.cpp index e8655654c..52c56be97 100644 --- a/natives/src/main/native/zlib/source/deflater.cpp +++ b/natives/src/main/native/zlib/source/deflater.cpp @@ -1,7 +1,7 @@ #include #include "net_daporkchop_lib_natives_zlib_NativeDeflater.h" -#include +#include #include #include @@ -38,10 +38,10 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat return 0; } - z_stream* stream = (z_stream*) malloc(sizeof(z_stream)); - memset(stream, 0, sizeof(z_stream)); + zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); + memset(stream, 0, sizeof(zng_stream)); - int ret = deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); + int ret = zng_deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); if (ret != Z_OK) { const char* msg = stream->msg; @@ -53,14 +53,14 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_end(JNIEnv* env, jclass cla, jlong ctx) { - z_stream* stream = (z_stream*) ctx; - int ret = deflateReset(stream); + zng_stream* stream = (zng_stream*) ctx; + int ret = zng_deflateReset(stream); if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); return; } - ret = deflateEnd(stream); + ret = zng_deflateEnd(stream); const char* msg = stream->msg; free(stream); @@ -70,27 +70,27 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_input(JNIEnv* env, jobject obj, jlong srcAddr, jint srcLen) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); stream->next_in = (unsigned char*) srcAddr; stream->avail_in = srcLen; } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_output(JNIEnv* env, jobject obj, jlong dstAddr, jint dstLen) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); stream->next_out = (unsigned char*) dstAddr; stream->avail_out = dstLen; } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_deflate(JNIEnv* env, jobject obj, jboolean finish) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); jint avail_in = stream->avail_in; jint avail_out = stream->avail_out; //even if finish is set to true, don't actually run deflate with the finish flag if the entire data isn't going to be able to be read this invocation - int ret = deflate(stream, finish ? Z_FINISH : Z_NO_FLUSH); + int ret = zng_deflate(stream, finish ? Z_FINISH : Z_NO_FLUSH); if (ret == Z_STREAM_END) { env->SetBooleanField(obj, finishedID, (jboolean) 1); } else if (ret != Z_OK) { @@ -103,8 +103,8 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_reset(JNIEnv* env, jobject obj) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); - int ret = deflateReset(stream); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + int ret = zng_deflateReset(stream); if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); diff --git a/natives/src/main/native/zlib/source/inflater.cpp b/natives/src/main/native/zlib/source/inflater.cpp index 27dfe23eb..d92aa0cbc 100644 --- a/natives/src/main/native/zlib/source/inflater.cpp +++ b/natives/src/main/native/zlib/source/inflater.cpp @@ -1,7 +1,7 @@ #include #include "net_daporkchop_lib_natives_zlib_NativeInflater.h" -#include +#include #include #include @@ -33,10 +33,10 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat return 0; } - z_stream* stream = (z_stream*) malloc(sizeof(z_stream)); - memset(stream, 0, sizeof(z_stream)); + zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); + memset(stream, 0, sizeof(zng_stream)); - int ret = inflateInit2(stream, windowBits); + int ret = zng_inflateInit2(stream, windowBits); if (ret != Z_OK) { const char* msg = stream->msg; @@ -48,8 +48,8 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_end(JNIEnv* env, jclass cla, jlong ctx) { - z_stream* stream = (z_stream*) ctx; - int ret = inflateReset(stream); + zng_stream* stream = (zng_stream*) ctx; + int ret = zng_inflateReset(stream); if (ret != Z_OK) { const char* msg = stream->msg; free(stream); @@ -57,7 +57,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati return; } - ret = inflateEnd(stream); + ret = zng_inflateEnd(stream); const char* msg = stream->msg; free(stream); @@ -67,28 +67,28 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_input(JNIEnv* env, jobject obj, jlong srcAddr, jint srcLen) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); stream->next_in = (unsigned char*) srcAddr; stream->avail_in = srcLen; } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_output(JNIEnv* env, jobject obj, jlong dstAddr, jint dstLen) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); stream->next_out = (unsigned char*) dstAddr; stream->avail_out = dstLen; } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_inflate(JNIEnv* env, jobject obj) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); jint avail_in = stream->avail_in; jint avail_out = stream->avail_out; //don't actually run inflate with the flush flag if the entire data isn't going to be able to be read this invocation //of course this doesn't mean it'll be buffering 4GB of data, it just means that it won't begin flushing the data until it decides to - int ret = inflate(stream, Z_SYNC_FLUSH); + int ret = zng_inflate(stream, Z_SYNC_FLUSH); if (ret == Z_STREAM_END) { env->SetBooleanField(obj, finishedID, (jboolean) 1); } else if (ret != Z_OK) { @@ -101,9 +101,9 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_reset(JNIEnv* env, jobject obj) { - z_stream* stream = (z_stream*) env->GetLongField(obj, ctxID); + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - int ret = inflateReset(stream); + int ret = zng_inflateReset(stream); if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Couldn't reset inflater!" : stream->msg, ret); From f7470d25690e3eac119f654c8473ef4c0f72cb72 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Mon, 20 Jan 2020 21:33:51 +0100 Subject: [PATCH 03/36] make zlib mode be an interface --- .../lib/natives/zlib/JavaDeflater.java | 15 +++--- .../lib/natives/zlib/JavaInflater.java | 15 +++--- .../daporkchop/lib/natives/zlib/JavaZlib.java | 7 +-- .../lib/natives/zlib/NativeDeflater.java | 7 +-- .../lib/natives/zlib/NativeInflater.java | 7 +-- .../lib/natives/zlib/NativeZlib.java | 7 +-- .../net/daporkchop/lib/natives/zlib/Zlib.java | 48 +++++-------------- .../daporkchop/lib/natives/zlib/ZlibMode.java | 44 +++++++++++++++++ 8 files changed, 89 insertions(+), 61 deletions(-) create mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java index 2c59bab51..3cc76170c 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -16,6 +16,7 @@ package net.daporkchop.lib.natives.zlib; import lombok.Getter; +import lombok.NonNull; import lombok.experimental.Accessors; import net.daporkchop.lib.unsafe.PUnsafe; import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; @@ -44,19 +45,19 @@ public final class JavaDeflater implements PDeflater { private int inputSize; private int outputSize; - public JavaDeflater(int level, int mode) { + public JavaDeflater(int level, @NonNull ZlibMode mode) { switch (mode) { - case Zlib.ZLIB_MODE_ZLIB: + case ZLIB: this.deflater = new Deflater(level, false); break; - case Zlib.ZLIB_MODE_RAW: + case RAW: this.deflater = new Deflater(level, true); break; - case Zlib.ZLIB_MODE_AUTO: - case Zlib.ZLIB_MODE_GZIP: + case AUTO: + case GZIP: throw new IllegalArgumentException("Pure Java deflater doesn't support Gzip!"); default: - throw new IllegalArgumentException(String.format("Invalid mode: %d", mode)); + throw new IllegalArgumentException("Invalid mode: " + mode); } } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java index da2958fbb..99d5c04f9 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -16,6 +16,7 @@ package net.daporkchop.lib.natives.zlib; import lombok.Getter; +import lombok.NonNull; import lombok.experimental.Accessors; import net.daporkchop.lib.unsafe.PUnsafe; import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; @@ -45,19 +46,19 @@ public final class JavaInflater implements PInflater { private int inputSize; private int outputSize; - public JavaInflater(int mode) { + public JavaInflater(@NonNull ZlibMode mode) { switch (mode) { - case Zlib.ZLIB_MODE_ZLIB: + case ZLIB: this.inflater = new Inflater(false); break; - case Zlib.ZLIB_MODE_RAW: + case RAW: this.inflater = new Inflater(true); break; - case Zlib.ZLIB_MODE_AUTO: - case Zlib.ZLIB_MODE_GZIP: + case AUTO: + case GZIP: throw new IllegalArgumentException("Pure Java inflater doesn't support Gzip!"); default: - throw new IllegalArgumentException(String.format("Invalid mode: %d", mode)); + throw new IllegalArgumentException("Invalid mode: " + mode); } } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java index 39bc12357..4cbe83810 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -15,6 +15,7 @@ package net.daporkchop.lib.natives.zlib; +import lombok.NonNull; import net.daporkchop.lib.natives.NativeCode; /** @@ -34,12 +35,12 @@ protected boolean _available() { } @Override - public PDeflater deflater(int level, int mode) { + public PDeflater deflater(int level, @NonNull ZlibMode mode) { return new JavaDeflater(level, mode); } @Override - public PInflater inflater(int mode) { + public PInflater inflater(@NonNull ZlibMode mode) { return new JavaInflater(mode); } } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java index a23bd59b8..0252dacec 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -17,6 +17,7 @@ import lombok.AccessLevel; import lombok.Getter; +import lombok.NonNull; import lombok.experimental.Accessors; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; @@ -46,8 +47,8 @@ public final class NativeDeflater implements PDeflater { private boolean finished; - NativeDeflater(int level, int mode) { - long ctx = this.ctx = init(level, mode); + NativeDeflater(int level, @NonNull ZlibMode mode) { + long ctx = this.ctx = init(level, mode.ordinal()); this.cleaner = PCleaner.cleaner(this, () -> end(ctx)); } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java index b46054a81..2eb8b9fcc 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -17,6 +17,7 @@ import lombok.AccessLevel; import lombok.Getter; +import lombok.NonNull; import lombok.experimental.Accessors; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; @@ -46,8 +47,8 @@ public final class NativeInflater implements PInflater { private boolean finished; - NativeInflater(int mode) { - long ctx = this.ctx = init(mode); + NativeInflater(@NonNull ZlibMode mode) { + long ctx = this.ctx = init(mode.ordinal()); this.cleaner = PCleaner.cleaner(this, () -> end(ctx)); } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java index ebf0cc03b..c0ee20af8 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -15,6 +15,7 @@ package net.daporkchop.lib.natives.zlib; +import lombok.NonNull; import net.daporkchop.lib.natives.NativeCode; /** @@ -38,12 +39,12 @@ protected Zlib _get() { } @Override - public PDeflater deflater(int level, int mode) { + public PDeflater deflater(int level, @NonNull ZlibMode mode) { return new NativeDeflater(level, mode); } @Override - public PInflater inflater(int mode) { + public PInflater inflater(@NonNull ZlibMode mode) { return new NativeInflater(mode); } } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java index ee4feaa69..8ce408554 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -15,6 +15,8 @@ package net.daporkchop.lib.natives.zlib; +import lombok.NonNull; + /** * Base representation of the Zlib algorithm. * @@ -41,69 +43,45 @@ public interface Zlib { */ int ZLIB_LEVEL_DEFAULT = -1; - /** - * Zlib wrapping mode, uses a 6-byte header with an Adler32 checksum. - *

- * This is the default mode. - */ - int ZLIB_MODE_ZLIB = 0; - - /** - * Gzip wrapping mode, uses an (at least) 18-byte header with a CRC32 checksum. - */ - int ZLIB_MODE_GZIP = 1; - - /** - * Only for use by {@link PInflater}, automatically detects whether the input data is in the Zlib or Gzip format. - *

- * Note that this doesn't work for data encoded in the {@link #ZLIB_MODE_RAW} format. - */ - int ZLIB_MODE_AUTO = 2; - - /** - * "Raw" Deflate mode, no wrapping is applied to the compressed data. - */ - int ZLIB_MODE_RAW = 3; - /** * Creates a new {@link PDeflater}. *

- * The returned {@link PDeflater} will use {@link #ZLIB_MODE_ZLIB}. + * The returned {@link PDeflater} will use {@link ZlibMode#ZLIB}. * * @param level the Deflate compression level to use. Must be in range 0-9 (inclusive), or {@link #ZLIB_LEVEL_DEFAULT} to use the library default * @return a new {@link PDeflater} instance - * @see #deflater(int, int) + * @see #deflater(int, ZlibMode) */ default PDeflater deflater(int level) { - return this.deflater(level, ZLIB_MODE_ZLIB); + return this.deflater(level, ZlibMode.ZLIB); } /** * Creates a new {@link PDeflater}. * * @param level the Deflate compression level to use. Must be in range 0-9 (inclusive), or {@link #ZLIB_LEVEL_DEFAULT} to use the library default - * @param mode the zlib wrapping mode to use. Must be one of {@link #ZLIB_MODE_ZLIB}, {@link #ZLIB_MODE_RAW} or {@link #ZLIB_MODE_GZIP} + * @param mode the zlib wrapping mode to use * @return a new {@link PDeflater} instance */ - PDeflater deflater(int level, int mode); + PDeflater deflater(int level, @NonNull ZlibMode mode); /** * Creates a new {@link PInflater}. *

- * The returned {@link PInflater} will use {@link #ZLIB_MODE_ZLIB}. + * The returned {@link PInflater} will use {@link ZlibMode#ZLIB}. * * @return a new {@link PInflater} instance - * @see #inflater(int) + * @see #inflater(ZlibMode) */ default PInflater inflater() { - return this.inflater(ZLIB_MODE_ZLIB); + return this.inflater(ZlibMode.ZLIB); } /** * Creates a new {@link PDeflater}. * - * @param mode the zlib wrapping mode to use. Must be one of {@link #ZLIB_MODE_ZLIB}, {@link #ZLIB_MODE_GZIP}, {@link #ZLIB_MODE_AUTO} or {@link #ZLIB_MODE_RAW} + * @param mode the zlib wrapping mode to use * @return a new {@link PInflater} instance */ - PInflater inflater(int mode); + PInflater inflater(@NonNull ZlibMode mode); } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java new file mode 100644 index 000000000..e276bf131 --- /dev/null +++ b/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java @@ -0,0 +1,44 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.natives.zlib; + +/** + * The different modes supported by Zlib. + * + * @author DaPorkchop_ + */ +public enum ZlibMode { + /** + * Zlib wrapping mode, uses a 6-byte header with an Adler32 checksum. + *

+ * This is the default mode. + */ + ZLIB, + /** + * Gzip wrapping mode, uses an (at least) 18-byte header with a CRC32 checksum. + */ + GZIP, + /** + * Only for use by {@link PInflater}, automatically detects whether the input data is in the Zlib or Gzip format. + *

+ * Note that this doesn't work for data encoded in the {@link #ZLIB_MODE_RAW} format. + */ + AUTO, + /** + * "Raw" Deflate mode, no wrapping is applied to the compressed data. + */ + RAW; +} From 38c7044dc72ddafb459c81c20de81fd6830f0da6 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Mon, 20 Jan 2020 21:57:14 +0100 Subject: [PATCH 04/36] add base for implementing zstd compression --- natives/Makefile | 6 ++-- natives/src/main/native/zlib/Makefile | 7 ++-- natives/src/main/native/zstd/Makefile | 49 +++++++++++++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 natives/src/main/native/zstd/Makefile diff --git a/natives/Makefile b/natives/Makefile index db7ea8191..04ab8cfda 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -13,16 +13,18 @@ export LDFLAGS := $(CFLAGS) -Wl,--gc-sections export SOURCES := $(SRCDIR)/common/source export INCLUDES := $(SRCDIR)/common/include $(JAVA_HOME)include $(JAVA_HOME)include/linux +#export ARCHS := x86_64-linux-gnu +#export ARCHS := x86_64-w64-mingw32 export ARCHS := x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-gcc),$(arch))) #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) export ARCH_TASKS := $(foreach arch,$(ARCHS),build.$(arch)) -export MODULES := zlib +export MODULES := zlib zstd export LIBDIR := $(TOPDIR)/src/main/native/lib export LIB_URL_BASE := https://cloud.daporkchop.net/programs/source/ -export LIBS := zlib-ng-1.2.11.tar.gz +export LIBS := zlib-ng-1.2.11.tar.gz zstd-1.4.4.tar.gz #.PHONY: build clean .FORCE $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach module,$(MODULES),$(arch)/$(module).lib)) .PHONY: build clean .FORCE diff --git a/natives/src/main/native/zlib/Makefile b/natives/src/main/native/zlib/Makefile index 2af2126b0..8a493cfd5 100644 --- a/natives/src/main/native/zlib/Makefile +++ b/natives/src/main/native/zlib/Makefile @@ -21,23 +21,22 @@ CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) -CFLAGS := $(CFLAGS) -D__LARGEFILE64__SOURCE=1 -DHAVE__HIDDEN -DPIC INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR) zlib-$(BUILD): $(OUTDIR)/$(BUILD)/libzlib.$(EXT) -$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a +$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) @echo "Linking $@..." @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Stripping $@..." @strip $@ -%.c.o: $(CFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a +%.c.o: $(CFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ -%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(TOPDIR)/src/main/native/zlib/Makefile $(CURDIR)/lib-zlib/libz-ng.a +%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ diff --git a/natives/src/main/native/zstd/Makefile b/natives/src/main/native/zstd/Makefile new file mode 100644 index 000000000..d7d1e461d --- /dev/null +++ b/natives/src/main/native/zstd/Makefile @@ -0,0 +1,49 @@ +BUILDDIR := build/$(BUILD) + +ifneq ($(BUILD),$(notdir $(CURDIR))) +.PHONY: $(BUILD) clean + +clean: + @rm -rf build/ tmp/ + +$(BUILD): + @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) + @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zstd-$(BUILD) + +else +.PHONY: zstd-$(BUILD) lib-zstd + +include $(TOPDIR)/toolchain/$(BUILD) + +SOURCES := $(SOURCES) $(PROJDIR)/source + +CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) +CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) +OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) + +INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR) + +zstd-$(BUILD): $(OUTDIR)/$(BUILD)/libzstd.$(EXT) + +$(OUTDIR)/$(BUILD)/libzstd.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a + @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) + @echo "Linking $@..." + @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a + @echo "Stripping $@..." + @strip $@ + +%.c.o: $(CFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a + @echo "Building $(subst .o,,$(subst __,/,$@))..." + @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + +%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a + @echo "Building $(subst .o,,$(subst __,/,$@))..." + @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + +$(CURDIR)/lib-zstd/lib/libzstd.a: $(TOPDIR)/zstd-1.4.4.tar.gz + @[ ! -d lib-zstd ] || rm -rf lib-zstd/ + @tar zxf $(TOPDIR)/zstd-1.4.4.tar.gz + @mv zstd-1.4.4/ lib-zstd/ + @$(MAKE) -C $(CURDIR)/lib-zstd/ -f $(CURDIR)/lib-zstd/Makefile lib-release + +endif From fcb02a0208e7104a74c36589018691e9876465b1 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Wed, 22 Jan 2020 17:24:58 +0100 Subject: [PATCH 05/36] add a separate compression module (base) --- compression/build.gradle | 18 ++++++++++++++ .../daporkchop/lib/compression/Context.java | 24 +++++++++++++++++++ .../daporkchop/lib/natives/NativeCode.java | 21 ++++++++++++++-- settings.gradle | 5 ++-- 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 compression/build.gradle create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/Context.java diff --git a/compression/build.gradle b/compression/build.gradle new file mode 100644 index 000000000..d3f046138 --- /dev/null +++ b/compression/build.gradle @@ -0,0 +1,18 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +dependencies { + compile project(":binary") +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java new file mode 100644 index 000000000..7cc5f6493 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -0,0 +1,24 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +/** + * Base interface for deflaters and inflaters. + * + * @author DaPorkchop_ + */ +interface Context { +} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java b/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java index 5f96c8ca9..51bd524c0 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -21,6 +21,7 @@ import net.daporkchop.lib.common.system.Architecture; import net.daporkchop.lib.common.system.OperatingSystem; import net.daporkchop.lib.common.system.PlatformInfo; +import net.daporkchop.lib.common.util.PorkUtil; import net.daporkchop.lib.unsafe.PUnsafe; import java.io.File; @@ -70,10 +71,26 @@ public static void loadNativeLibrary(@NonNull String name) { } } } + + StackTraceElement[] elements = Thread.getAllStackTraces().get(Thread.currentThread()); + Class clazz; + if (elements == null) { + //cannot get stack trace? + clazz = NativeCode.class; + } else { + //get class that called this method + int i = 0; + while ((clazz = PorkUtil.classForName(elements[i++].getClassName())) != NativeCode.class && i < elements.length); + if (clazz != NativeCode.class) { + throw new IllegalStateException(); + } + clazz = PorkUtil.classForName(elements[i].getClassName()); + } + try { File file = File.createTempFile(String.format("%s-%s-", name, LIB_ARCH), String.format(".%s", LIB_EXT)); file.deleteOnExit(); - try (InputStream is = NativeCode.class.getResourceAsStream(String.format("/%s/lib%s.%s", LIB_ARCH, name, LIB_EXT)); + try (InputStream is = clazz.getResourceAsStream(String.format("/%s/lib%s.%s", LIB_ARCH, name, LIB_EXT)); OutputStream os = new FileOutputStream(file)) { byte[] arr = new byte[PUnsafe.pageSize()]; for (int b; (b = is.read(arr)) >= 0; os.write(arr, 0, b)); diff --git a/settings.gradle b/settings.gradle index d2d6dd213..6e68f6431 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -18,10 +18,11 @@ rootProject.name = 'PorkLib' include 'ai' include 'binary' include 'collections' -include 'crypto' include 'common' +include 'compression' include 'concurrent' include 'concurrent:parallel' +include 'crypto' include 'db' include 'db:db-core' include 'db:db-extensions-leveldb' From da54afd033626cf2519304f2961889a15a0b89e9 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Wed, 29 Jan 2020 18:35:53 +0100 Subject: [PATCH 06/36] add some basic interfaces for compression --- compression/build.gradle | 2 +- .../daporkchop/lib/compression/Context.java | 42 ++++++++++++++++++- .../daporkchop/lib/compression/PDeflater.java | 41 ++++++++++++++++++ .../daporkchop/lib/compression/PInflater.java | 41 ++++++++++++++++++ .../util/InvalidBufferTypeException.java | 28 +++++++++++++ 5 files changed, 152 insertions(+), 2 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/PInflater.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java diff --git a/compression/build.gradle b/compression/build.gradle index d3f046138..3788af6ff 100644 --- a/compression/build.gradle +++ b/compression/build.gradle @@ -14,5 +14,5 @@ */ dependencies { - compile project(":binary") + compile "io.netty:netty-buffer:$nettyVersion" } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index 7cc5f6493..974f5f628 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -15,10 +15,50 @@ package net.daporkchop.lib.compression; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.capability.Releasable; + /** * Base interface for deflaters and inflaters. + *

+ * Unless explicitly specified, implementations of this class are not safe for use on multiple threads. * * @author DaPorkchop_ */ -interface Context { +interface Context> extends Releasable { + /** + * Checks whether this context uses direct or heap memory. + *

+ * {@link io.netty.buffer.ByteBuf}s of the wrong type will not be accepted by any methods, and will cause an {@link InvalidBufferTypeException} to be thrown. + * + * @return whether this context uses direct or heap memory + */ + boolean direct(); + + /** + * Sets the context's current source buffer when processing data in streaming mode. + * + * @param src the {@link ByteBuf} to read data from + * @return this + */ + I src(@NonNull ByteBuf src) throws InvalidBufferTypeException; + + /** + * Sets the context's current destination buffer when processing data in streaming mode. + * + * @param dst the {@link ByteBuf} to write data to + * @return this + */ + I dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException; + + /** + * Resets this context. + *

+ * This will erase any internal buffers and reset the source and destination buffers to {@code null}. + * + * @return this + */ + I reset(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java new file mode 100644 index 000000000..54ea73314 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -0,0 +1,41 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.InvalidBufferTypeException; + +/** + * Deflates (compresses) data. + * + * @author DaPorkchop_ + */ +public interface PDeflater extends Context { + /** + * Deflates the given source data into the given destination buffer. + *

+ * Rather than expanding the destination buffer if needed, this method will simply abort compression if not enough space is available. In such a case the + * reader/writer indices of both buffers will remain unaffected, however the contents of the destination buffer may be modified. + *

+ * This method will implicitly reset the context before the actual compression. Any previous state will be ignored. + * + * @param src the {@link ByteBuf} to read data from + * @param dst the {@link ByteBuf} to write data to + * @return whether or not there was enough space in the destination buffer for the compressed data + */ + boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java new file mode 100644 index 000000000..6fac84d88 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -0,0 +1,41 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.InvalidBufferTypeException; + +/** + * Inflates (decompresses) data. + * + * @author DaPorkchop_ + */ +public interface PInflater extends Context { + /** + * Inflates the given source data into the given destination buffer. + *

+ * Rather than expanding the destination buffer if needed, this method will simply abort decompression if not enough space is available. In such a case the + * reader/writer indices of both buffers will remain unaffected, however the contents of the destination buffer may be modified. + *

+ * This method will implicitly reset the context before the actual decompression. Any previous state will be ignored. + * + * @param src the {@link ByteBuf} to read data from + * @param dst the {@link ByteBuf} to write data to + * @return whether or not there was enough space in the destination buffer for the decompressed data + */ + boolean inflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java new file mode 100644 index 000000000..2e634fd82 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java @@ -0,0 +1,28 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util; + +/** + * Thrown when a {@link io.netty.buffer.ByteBuf} argument to a {@link net.daporkchop.lib.compression.PInflater} or {@link net.daporkchop.lib.compression.PDeflater} + * is of the wrong type. + * + * @author DaPorkchop_ + */ +public class InvalidBufferTypeException extends IllegalArgumentException { + public InvalidBufferTypeException(boolean direct) { + super(direct ? "direct buffer expected!" : "heap buffer expected!"); + } +} From 61f045a84c4fc33033eadf6cf2e3c84b121c0022 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Wed, 29 Jan 2020 20:33:57 +0100 Subject: [PATCH 07/36] begin moving makefiles around --- .gitignore | 5 ++ compression/zlib/Makefile | 52 +++++++++++++++++++ compression/zlib/build.gradle | 19 +++++++ .../zlib/src/main/native/common}/deflater.cpp | 0 .../zlib/src/main/native/common}/inflater.cpp | 0 ...porkchop_lib_natives_zlib_NativeDeflater.h | 0 ...porkchop_lib_natives_zlib_NativeInflater.h | 0 compression/zstd/build.gradle | 19 +++++++ natives/.gitignore | 3 -- natives/Makefile | 16 +++--- natives/build.gradle | 4 +- natives/toolchain/aarch64-linux-gnu | 9 ++++ settings.gradle | 4 ++ 13 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 compression/zlib/Makefile create mode 100644 compression/zlib/build.gradle rename {natives/src/main/native/zlib/source => compression/zlib/src/main/native/common}/deflater.cpp (100%) rename {natives/src/main/native/zlib/source => compression/zlib/src/main/native/common}/inflater.cpp (100%) rename {natives/src/main/native/zlib/source => compression/zlib/src/main/native/common}/net_daporkchop_lib_natives_zlib_NativeDeflater.h (100%) rename {natives/src/main/native/zlib/source => compression/zlib/src/main/native/common}/net_daporkchop_lib_natives_zlib_NativeInflater.h (100%) create mode 100644 compression/zstd/build.gradle create mode 100644 natives/toolchain/aarch64-linux-gnu diff --git a/.gitignore b/.gitignore index 8f08f9a92..6c2e94e65 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,8 @@ test_out/ # project root /src/ + +# native libraries +/**/*.so +/**/*.dll +/**/*.o diff --git a/compression/zlib/Makefile b/compression/zlib/Makefile new file mode 100644 index 000000000..557a0ed18 --- /dev/null +++ b/compression/zlib/Makefile @@ -0,0 +1,52 @@ +OUTDIR := $(PROJDIR)/src/main/resources + +ifneq ($(BUILD),$(notdir $(CURDIR))) +.PHONY: $(BUILD) clean + +BUILDDIR := build/$(BUILD) + +clean: + @rm -rf build/ $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) + +$(BUILD): + @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) + @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zlib-$(BUILD) + +else +.PHONY: build .FORCE + +include $(TOOLCHAINS)/$(BUILD) + +SOURCES := $(PROJDIR)/common $(PROJDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) +CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) +OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) + +build: $(OUTDIR)/$(BUILD)/libzlib.$(EXT) + +$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a + @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) + @echo "Linking $@..." + @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a + @echo "Stripping $@..." + @strip $@ + +%.c.o: $(CFILES) $(CURDIR)/lib-zlib/libz-ng.a + @echo "Building $(subst .o,,$(subst __,/,$@))..." + @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + +%.cpp.o: $(CPPFILES) $(CURDIR)/lib-zlib/libz-ng.a + @echo "Building $(subst .o,,$(subst __,/,$@))..." + @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + +$(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz + @[ ! -d lib-zlib ] || rm -rf lib-zlib/ + @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz + @mv zlib-ng-1.2.11/ lib-zlib/ + @cd lib-zlib/ && CFLAGS="-fPIC -Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. + @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a + +FORCE: + +endif \ No newline at end of file diff --git a/compression/zlib/build.gradle b/compression/zlib/build.gradle new file mode 100644 index 000000000..5f38939a3 --- /dev/null +++ b/compression/zlib/build.gradle @@ -0,0 +1,19 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +dependencies { + compile project(":compression") + compile project(":natives") +} diff --git a/natives/src/main/native/zlib/source/deflater.cpp b/compression/zlib/src/main/native/common/deflater.cpp similarity index 100% rename from natives/src/main/native/zlib/source/deflater.cpp rename to compression/zlib/src/main/native/common/deflater.cpp diff --git a/natives/src/main/native/zlib/source/inflater.cpp b/compression/zlib/src/main/native/common/inflater.cpp similarity index 100% rename from natives/src/main/native/zlib/source/inflater.cpp rename to compression/zlib/src/main/native/common/inflater.cpp diff --git a/natives/src/main/native/zlib/source/net_daporkchop_lib_natives_zlib_NativeDeflater.h b/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h similarity index 100% rename from natives/src/main/native/zlib/source/net_daporkchop_lib_natives_zlib_NativeDeflater.h rename to compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h diff --git a/natives/src/main/native/zlib/source/net_daporkchop_lib_natives_zlib_NativeInflater.h b/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h similarity index 100% rename from natives/src/main/native/zlib/source/net_daporkchop_lib_natives_zlib_NativeInflater.h rename to compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h diff --git a/compression/zstd/build.gradle b/compression/zstd/build.gradle new file mode 100644 index 000000000..5f38939a3 --- /dev/null +++ b/compression/zstd/build.gradle @@ -0,0 +1,19 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +dependencies { + compile project(":compression") + compile project(":natives") +} diff --git a/natives/.gitignore b/natives/.gitignore index b44691fbf..36e665b17 100644 --- a/natives/.gitignore +++ b/natives/.gitignore @@ -1,6 +1,3 @@ -/**/*.so -/**/*.dll -/**/*.o /*.tar.gz /src/main/native/*/build*/ /tmp/ diff --git a/natives/Makefile b/natives/Makefile index 04ab8cfda..aebdf7e66 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -3,8 +3,7 @@ export GCC_VERSION := 8.1.0 export TARGET := $(shell basename $(CURDIR)) export TOPDIR := $(CURDIR) -export SRCDIR := $(TOPDIR)/src/main/native -export OUTDIR := $(TOPDIR)/src/main/resources +export TOOLCHAINS := $(CURDIR)/toolchain export CFLAGS := -shared -Ofast -ffast-math -fPIC -ffunction-sections -fdata-sections -fvisibility=hidden export CXXFLAGS := $(CFLAGS) @@ -15,12 +14,13 @@ export INCLUDES := $(SRCDIR)/common/include $(JAVA_HOME)include $(JAVA_HOME)inc #export ARCHS := x86_64-linux-gnu #export ARCHS := x86_64-w64-mingw32 -export ARCHS := x86_64-linux-gnu x86_64-w64-mingw32 +export ARCHS := aarch64-linux-gnu x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-gcc),$(arch))) #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) export ARCH_TASKS := $(foreach arch,$(ARCHS),build.$(arch)) -export MODULES := zlib zstd +export MODULES := ../compression/zlib +#export MODULES := ../compression/zlib ../compression/zstd export LIBDIR := $(TOPDIR)/src/main/native/lib export LIB_URL_BASE := https://cloud.daporkchop.net/programs/source/ @@ -32,13 +32,13 @@ export LIBS := zlib-ng-1.2.11.tar.gz zstd-1.4.4.tar.gz #build: $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach mod,$(MODULES),$(OUTDIR)/$(arch)/lib$(mod).so)) build: $(ARCH_TASKS) $(LIBS) -build.%: .FORCE $(foreach module,$(MODULES),%/$(module).lib) +build.%: .FORCE $(foreach module,$(MODULES),%_$(module).lib) @echo Built libraries for $(shell echo '$@' | perl -n -e '/build\.(.+)/ && print $$1')! %.lib: .FORCE $(LIBS) - @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/\/([^.]+)\.lib$$/ && print $$1') && \ - _ARCH=$(shell echo "$@" | perl -n -e '/^([^\/]*?)\/[^.]+\.lib$$/ && print $$1') && \ - $(MAKE) -C $(SRCDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(SRCDIR)/$$_PRJ_NAME $$_ARCH && \ + @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/\/(.*?)\.lib$$/ && print $$1') && \ + _ARCH=$(shell echo "$@" | perl -n -e '/^([^_]*?)_.*?\.lib$$/ && print $$1') && \ + $(MAKE) -C $(SRCDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(TOPDIR)/$$_PRJ_NAME $$_ARCH && \ echo Built $$_PRJ_NAME for target $$_ARCH! clean: $(foreach mod,$(MODULES),clean.$(mod)) diff --git a/natives/build.gradle b/natives/build.gradle index 30b4f2ace..07b04257c 100644 --- a/natives/build.gradle +++ b/natives/build.gradle @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -18,7 +18,7 @@ dependencies { } if (System.getProperty("os.name", "").toLowerCase().replaceAll("[^a-z0-9]+", "").startsWith("windows")) { - System.out.println("You are running Windows, which is bad and you should feel bad.") + System.out.println("You are running Windows, which is bad and you should feel bad.\nThis means that native libraries will not be built.") } else { task compileNatives(type: Exec) { workingDir "$projectDir" diff --git a/natives/toolchain/aarch64-linux-gnu b/natives/toolchain/aarch64-linux-gnu new file mode 100644 index 000000000..27da91bac --- /dev/null +++ b/natives/toolchain/aarch64-linux-gnu @@ -0,0 +1,9 @@ +export CFLAGS := $(CFLAGS) -flto=auto -fno-fat-lto-objects +export CXXFLAGS := $(CXXFLAGS) -flto=auto -fno-fat-lto-objects +export LDFLAGS := $(LDFLAGS) -flto=auto -fno-fat-lto-objects + +export CC := aarch64-linux-gnu-gcc +export CXX := aarch64-linux-gnu-g++ +export LD := aarch64-linux-gnu-g++ + +export EXT := so diff --git a/settings.gradle b/settings.gradle index 6e68f6431..02b423063 100644 --- a/settings.gradle +++ b/settings.gradle @@ -20,6 +20,8 @@ include 'binary' include 'collections' include 'common' include 'compression' +include 'compression:zlib' +include 'compression:zstd' include 'concurrent' include 'concurrent:parallel' include 'crypto' @@ -52,6 +54,8 @@ include 'primitive:generator' include 'reflection' include 'unsafe' +findProject(':compression:zlib')?.name = 'compression-zlib' +findProject(':compression:zstd')?.name = 'compression-zstd' findProject(':concurrent:parallel')?.name = 'parallel' findProject(':db:db-core')?.name = 'db-core' findProject(':db:db-extensions-leveldb')?.name = 'db-extensions-leveldb' From b444c0cf390189bb22176a7d58ebb498d77891f6 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Thu, 30 Jan 2020 16:44:50 +0100 Subject: [PATCH 08/36] make zlib source build again --- compression/zlib/Makefile | 21 +++++--- natives/Makefile | 25 ++++------ .../native/common/{source => }/common.cpp | 0 .../main/native/{common => }/include/common.h | 0 natives/src/main/native/zlib/Makefile | 50 ------------------- natives/toolchain/aarch64-linux-gnu | 7 +-- natives/toolchain/x86_64-linux-gnu | 7 +-- natives/toolchain/x86_64-w64-mingw32 | 7 +-- 8 files changed, 35 insertions(+), 82 deletions(-) rename natives/src/main/native/common/{source => }/common.cpp (100%) rename natives/src/main/native/{common => }/include/common.h (100%) delete mode 100644 natives/src/main/native/zlib/Makefile diff --git a/compression/zlib/Makefile b/compression/zlib/Makefile index 557a0ed18..5065dfe16 100644 --- a/compression/zlib/Makefile +++ b/compression/zlib/Makefile @@ -10,19 +10,24 @@ clean: $(BUILD): @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) - @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zlib-$(BUILD) + @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) build else .PHONY: build .FORCE include $(TOOLCHAINS)/$(BUILD) -SOURCES := $(PROJDIR)/common $(PROJDIR)/$(BUILD) +SOURCES := $(PROJDIR)/src/main/native/common $(PROJDIR)/src/main/native/$(BUILD) $(COMMONSRC)/common $(COMMONSRC)/$(BUILD) +SOURCES := $(abspath $(SOURCES)) -CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) -CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) +#CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) +#CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) +CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c)) +CPPFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.cpp)) OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) +INCLUDE := $(addprefix -I,$(INCLUDES) $(CURDIR)) + build: $(OUTDIR)/$(BUILD)/libzlib.$(EXT) $(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @@ -30,7 +35,7 @@ $(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib @echo "Linking $@..." @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Stripping $@..." - @strip $@ + @$(STRIP) $@ %.c.o: $(CFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @@ -38,15 +43,15 @@ $(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib %.cpp.o: $(CPPFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Building $(subst .o,,$(subst __,/,$@))..." - @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + $(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ $(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz @[ ! -d lib-zlib ] || rm -rf lib-zlib/ @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz @mv zlib-ng-1.2.11/ lib-zlib/ - @cd lib-zlib/ && CFLAGS="-fPIC -Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. + @cd lib-zlib/ && CFLAGS="-fPIC -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --with-gzfileops && cd .. @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a FORCE: -endif \ No newline at end of file +endif diff --git a/natives/Makefile b/natives/Makefile index aebdf7e66..2d7c66697 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -1,19 +1,17 @@ export SHELL := /bin/bash -export GCC_VERSION := 8.1.0 export TARGET := $(shell basename $(CURDIR)) export TOPDIR := $(CURDIR) export TOOLCHAINS := $(CURDIR)/toolchain +export COMMONSRC := $(CURDIR)/src/main/native export CFLAGS := -shared -Ofast -ffast-math -fPIC -ffunction-sections -fdata-sections -fvisibility=hidden export CXXFLAGS := $(CFLAGS) export LDFLAGS := $(CFLAGS) -Wl,--gc-sections -export SOURCES := $(SRCDIR)/common/source -export INCLUDES := $(SRCDIR)/common/include $(JAVA_HOME)include $(JAVA_HOME)include/linux +export SOURCES := +export INCLUDES := $(COMMONSRC)/include $(JAVA_HOME)include $(JAVA_HOME)include/linux -#export ARCHS := x86_64-linux-gnu -#export ARCHS := x86_64-w64-mingw32 export ARCHS := aarch64-linux-gnu x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-gcc),$(arch))) #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) @@ -26,26 +24,23 @@ export LIBDIR := $(TOPDIR)/src/main/native/lib export LIB_URL_BASE := https://cloud.daporkchop.net/programs/source/ export LIBS := zlib-ng-1.2.11.tar.gz zstd-1.4.4.tar.gz -#.PHONY: build clean .FORCE $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach module,$(MODULES),$(arch)/$(module).lib)) .PHONY: build clean .FORCE -#build: $(ARCH_TASKS) $(foreach arch,$(ARCHS),$(foreach mod,$(MODULES),$(OUTDIR)/$(arch)/lib$(mod).so)) build: $(ARCH_TASKS) $(LIBS) -build.%: .FORCE $(foreach module,$(MODULES),%_$(module).lib) +build.%: .FORCE $(foreach module,$(MODULES),%,$(module).lib) @echo Built libraries for $(shell echo '$@' | perl -n -e '/build\.(.+)/ && print $$1')! %.lib: .FORCE $(LIBS) - @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/\/(.*?)\.lib$$/ && print $$1') && \ - _ARCH=$(shell echo "$@" | perl -n -e '/^([^_]*?)_.*?\.lib$$/ && print $$1') && \ - $(MAKE) -C $(SRCDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(TOPDIR)/$$_PRJ_NAME $$_ARCH && \ + @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/,(.*?)\.lib$$/ && print $$1') && \ + _ARCH=$(shell echo "$@" | perl -n -e '/^([^,]*?),.*?\.lib$$/ && print $$1') && \ + $(MAKE) -C $(TOPDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(TOPDIR)/$$_PRJ_NAME $$_ARCH && \ echo Built $$_PRJ_NAME for target $$_ARCH! -clean: $(foreach mod,$(MODULES),clean.$(mod)) - @rm -rf $(OUTDIR)/*/ +#echo "arg = $@" && echo "prj_name = $$_PRJ_NAME" && echo "arch = $$_ARCH" && \ -clean.%: - @$(MAKE) -C $(SRCDIR)/$(subst clean.,,$@) clean +clean: + @for f in $(MODULES); do $(MAKE) -C $(TOPDIR)/$$f clean; done %.tar.gz: @echo "Downloading source for $@" diff --git a/natives/src/main/native/common/source/common.cpp b/natives/src/main/native/common/common.cpp similarity index 100% rename from natives/src/main/native/common/source/common.cpp rename to natives/src/main/native/common/common.cpp diff --git a/natives/src/main/native/common/include/common.h b/natives/src/main/native/include/common.h similarity index 100% rename from natives/src/main/native/common/include/common.h rename to natives/src/main/native/include/common.h diff --git a/natives/src/main/native/zlib/Makefile b/natives/src/main/native/zlib/Makefile deleted file mode 100644 index 8a493cfd5..000000000 --- a/natives/src/main/native/zlib/Makefile +++ /dev/null @@ -1,50 +0,0 @@ -BUILDDIR := build/$(BUILD) - -ifneq ($(BUILD),$(notdir $(CURDIR))) -.PHONY: $(BUILD) clean - -clean: - @rm -rf build/ tmp/ - -$(BUILD): - @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) - @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zlib-$(BUILD) - -else -.PHONY: zlib-$(BUILD) lib-zlib - -include $(TOPDIR)/toolchain/$(BUILD) - -SOURCES := $(SOURCES) $(PROJDIR)/source - -CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) -CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) -OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) - -INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR) - -zlib-$(BUILD): $(OUTDIR)/$(BUILD)/libzlib.$(EXT) - -$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a - @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) - @echo "Linking $@..." - @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a - @echo "Stripping $@..." - @strip $@ - -%.c.o: $(CFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a - @echo "Building $(subst .o,,$(subst __,/,$@))..." - @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ - -%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zlib/libz-ng.a - @echo "Building $(subst .o,,$(subst __,/,$@))..." - @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ - -$(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz - @[ ! -d lib-zlib ] || rm -rf lib-zlib/ - @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz - @mv zlib-ng-1.2.11/ lib-zlib/ - @cd lib-zlib/ && CFLAGS="-fPIC -Ofast -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --64 --with-gzfileops && cd .. - @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a - -endif diff --git a/natives/toolchain/aarch64-linux-gnu b/natives/toolchain/aarch64-linux-gnu index 27da91bac..dac4e21a5 100644 --- a/natives/toolchain/aarch64-linux-gnu +++ b/natives/toolchain/aarch64-linux-gnu @@ -2,8 +2,9 @@ export CFLAGS := $(CFLAGS) -flto=auto -fno-fat-lto-objects export CXXFLAGS := $(CXXFLAGS) -flto=auto -fno-fat-lto-objects export LDFLAGS := $(LDFLAGS) -flto=auto -fno-fat-lto-objects -export CC := aarch64-linux-gnu-gcc -export CXX := aarch64-linux-gnu-g++ -export LD := aarch64-linux-gnu-g++ +export CC := aarch64-linux-gnu-gcc +export CXX := aarch64-linux-gnu-g++ +export LD := aarch64-linux-gnu-g++ +export STRIP := aarch64-linux-gnu-strip export EXT := so diff --git a/natives/toolchain/x86_64-linux-gnu b/natives/toolchain/x86_64-linux-gnu index 02f01d63d..c5dee7ce7 100644 --- a/natives/toolchain/x86_64-linux-gnu +++ b/natives/toolchain/x86_64-linux-gnu @@ -2,8 +2,9 @@ export CFLAGS := $(CFLAGS) -flto=auto -fno-fat-lto-objects export CXXFLAGS := $(CXXFLAGS) -flto=auto -fno-fat-lto-objects export LDFLAGS := $(LDFLAGS) -flto=auto -fno-fat-lto-objects -export CC := x86_64-linux-gnu-gcc -export CXX := x86_64-linux-gnu-g++ -export LD := x86_64-linux-gnu-g++ +export CC := x86_64-linux-gnu-gcc +export CXX := x86_64-linux-gnu-g++ +export LD := x86_64-linux-gnu-g++ +export STRIP := x86_64-linux-gnu-strip export EXT := so diff --git a/natives/toolchain/x86_64-w64-mingw32 b/natives/toolchain/x86_64-w64-mingw32 index e8e19b49e..9da701d24 100644 --- a/natives/toolchain/x86_64-w64-mingw32 +++ b/natives/toolchain/x86_64-w64-mingw32 @@ -5,8 +5,9 @@ export CFLAGS := $(CFLAGS) export CXXFLAGS := $(CXXFLAGS) export LDFLAGS := $(LDFLAGS) -export CC := x86_64-w64-mingw32-gcc -export CXX := x86_64-w64-mingw32-g++ -export LD := x86_64-w64-mingw32-g++ +export CC := x86_64-w64-mingw32-gcc +export CXX := x86_64-w64-mingw32-g++ +export LD := x86_64-w64-mingw32-g++ +export STRIP := x86_64-w64-mingw32-strip export EXT := dll From c95e03dce40da9b411aa7095cf152719d5951eba Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Thu, 30 Jan 2020 19:45:36 +0100 Subject: [PATCH 09/36] get to work on actually implementing zlib again --- .../daporkchop/lib/compression/zlib/Zlib.java | 40 ++++++ .../lib/compression/zlib/ZlibProvider.java | 34 ++++++ .../compression/zlib/natives/NativeZlib.java | 44 +++++++ .../zlib/natives/NativeZlibDeflater.java | 110 +++++++++++++++++ .../main/native/common/NativeZlibDeflater.h | 79 ++++++++++++ .../zlib/src/main/native/common/deflater.cpp | 98 +++++++++------ .../zlib/src/main/native/common/inflater.cpp | 115 ------------------ ...porkchop_lib_natives_zlib_NativeDeflater.h | 69 ----------- ...porkchop_lib_natives_zlib_NativeInflater.h | 69 ----------- .../daporkchop/lib/natives/NativeCode.java | 5 +- .../lib/unsafe/util/AbstractReleasable.java | 47 +++++++ 11 files changed, 418 insertions(+), 292 deletions(-) create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java create mode 100644 compression/zlib/src/main/native/common/NativeZlibDeflater.h delete mode 100644 compression/zlib/src/main/native/common/inflater.cpp delete mode 100644 compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h delete mode 100644 compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h create mode 100644 unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java new file mode 100644 index 000000000..dccc28273 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java @@ -0,0 +1,40 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import lombok.experimental.UtilityClass; + +/** + * @author DaPorkchop_ + */ +@UtilityClass +public class Zlib { + public final int LEVEL_NONE = 0; //no compression at all + public final int LEVEL_FASTEST = 1; //fastest compression, worst ratio + public final int LEVEL_BEST = 9; //best ratio, slowest compression + public final int LEVEL_DEFAULT = -1; //uses the library default level + + public final int STRATEGY_FILTERED = 1; + public final int STRATEGY_HUFFMAN = 2; + public final int STRATEGY_RLE = 3; + public final int STRATEGY_FIXED = 4; + public final int STRATEGY_DEFAULT = 0; + + public final int MODE_ZLIB = 0; //DEFLATE with zlib headers + public final int MODE_GZIP = 1; //DEFLATE with gzip headers + public final int MODE_RAW = 2; //raw DEFLATE output + public final int MODE_AUTO = 3; //automatically detects zlib or gzip (inflater only) +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java new file mode 100644 index 000000000..2f367bb9a --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -0,0 +1,34 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import net.daporkchop.lib.compression.PDeflater; + +/** + * A wrapper around a Zlib implementation. + * + * @author DaPorkchop_ + */ +public interface ZlibProvider { + /** + * Creates a new {@link PDeflater}. + * + * @param level the {@link Zlib} level to use + * @param strategy the {@link Zlib} strategy to use + * @return a new {@link PDeflater} with the given level and strategy + */ + PDeflater deflater(int level, int strategy); +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java new file mode 100644 index 000000000..3bc6e19e5 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -0,0 +1,44 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib.natives; + +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.zlib.ZlibProvider; +import net.daporkchop.lib.natives.NativeCode; + +/** + * @author DaPorkchop_ + */ +public final class NativeZlib extends NativeCode.NativeImpl implements ZlibProvider { + static { + if (NativeCode.NativeImpl.AVAILABLE) { + NativeCode.loadNativeLibrary("zlib"); + + //NativeZlibDeflater.load(); + //NativeZlibInflater.load(); + } + } + + @Override + protected ZlibProvider _get() { + return this; + } + + @Override + public PDeflater deflater(int level, int strategy) { + return null; + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java new file mode 100644 index 000000000..cf76e4787 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -0,0 +1,110 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib.natives; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * @author DaPorkchop_ + */ +public final class NativeZlibDeflater extends AbstractReleasable implements PDeflater { + static native void load(); + + private static native long allocateCtx(int level, int strategy, int mode); + + private static native void resetCtx(long ctx); + + private static native void releaseCtx(long ctx); + + private final long ctx; + + private final PCleaner cleaner; + + private ByteBuf src; + private ByteBuf dst; + + private int readBytes; + private int writtenBytes; + + public NativeZlibDeflater(int level, int strategy, int mode) { + this.ctx = allocateCtx(level, strategy, mode); + this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + } + + @Override + public boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return false; + } + + private native boolean doDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public PDeflater reset() { + this.src = null; + this.dst = null; + + this.readBytes = 0; + this.writtenBytes = 0; + + resetCtx(this.ctx); + return this; + } + + @Override + public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { + if (!src.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + this.src = src; + return this; + } + + @Override + public PDeflater dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException { + if (!dst.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + this.dst = dst; + return this; + } + + @Override + public boolean direct() { + return true; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long ctx; + + @Override + public void run() { + releaseCtx(this.ctx); + } + } +} diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h new file mode 100644 index 000000000..609ab16bb --- /dev/null +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -0,0 +1,79 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include +/* Header for class net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater */ + +#ifndef _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater +#define _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: load + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_load + (JNIEnv *, jclass); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: allocateCtx + * Signature: (III)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_allocateCtx + (JNIEnv *, jclass, jint, jint, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: resetCtx + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_resetCtx + (JNIEnv *, jclass, jlong); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: releaseCtx + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_releaseCtx + (JNIEnv *, jclass, jlong); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: doDeflate + * Signature: (JIJI)Z + */ +JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDeflate + (JNIEnv *, jobject, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: output + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_output + (JNIEnv *, jobject, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: deflate + * Signature: (Z)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_deflate + (JNIEnv *, jobject, jboolean); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: reset + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_reset + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/compression/zlib/src/main/native/common/deflater.cpp b/compression/zlib/src/main/native/common/deflater.cpp index 52c56be97..7ba5a9d7b 100644 --- a/compression/zlib/src/main/native/common/deflater.cpp +++ b/compression/zlib/src/main/native/common/deflater.cpp @@ -1,5 +1,5 @@ #include -#include "net_daporkchop_lib_natives_zlib_NativeDeflater.h" +#include "NativeZlibDeflater.h" #include @@ -11,37 +11,44 @@ static jfieldID ctxID; static jfieldID readBytesID; static jfieldID writtenBytesID; -static jfieldID finishedID; -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_load(JNIEnv* env, jclass cla) { +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_load + (JNIEnv* env, jclass cla) { ctxID = env->GetFieldID(cla, "ctx", "J"); readBytesID = env->GetFieldID(cla, "readBytes", "I"); writtenBytesID = env->GetFieldID(cla, "writtenBytes", "I"); - finishedID = env->GetFieldID(cla, "finished", "Z"); } -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_init(JNIEnv* env, jclass cla, jint level, jint mode) { - if (level < 0 || level > 9) { +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_allocateCtx + (JNIEnv* env, jclass cla, jint level, jint strategy, jint mode) { + if (level < -1 || level > 9) { throwException(env, "Invalid level!", level); return 0; + } else if (strategy < 0 || strategy > 4) { + throwException(env, "Invalid strategy!", strategy); + return 0; } int windowBits; - if (mode == 0) { //zlib - windowBits = 15; - } else if (mode == 1) { //gzip - windowBits = 15 + 16; - } else if (mode == 3) { //raw deflate - windowBits = -15; - } else { - throwException(env, "Invalid deflater mode!", mode); - return 0; + switch (mode) { + case 0: //zlib + windowBits = 15; + break; + case 1: //gzip + windowBits = 15 + 16; + break; + case 2: //raw + windowBits = -15; + break; + default: + throwException(env, "Invalid deflater mode!", mode); + return 0; } zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); memset(stream, 0, sizeof(zng_stream)); - int ret = zng_deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, Z_DEFAULT_STRATEGY); + int ret = zng_deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, strategy); if (ret != Z_OK) { const char* msg = stream->msg; @@ -52,7 +59,18 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_nat return (jlong) stream; } -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_end(JNIEnv* env, jclass cla, jlong ctx) { +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_resetCtx + (JNIEnv* env, jclass cla, jlong ctx) { + zng_stream* stream = (zng_stream*) ctx; + int ret = zng_deflateReset(stream); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); + } +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_releaseCtx + (JNIEnv* env, jclass cla, jlong ctx) { zng_stream* stream = (zng_stream*) ctx; int ret = zng_deflateReset(stream); if (ret != Z_OK) { @@ -69,21 +87,37 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati } } -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_input(JNIEnv* env, jobject obj, jlong srcAddr, jint srcLen) { +__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDeflate + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - stream->next_in = (unsigned char*) srcAddr; - stream->avail_in = srcLen; -} + int ret = zng_deflateReset(stream); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); + return false; + } -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_output(JNIEnv* env, jobject obj, jlong dstAddr, jint dstLen) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcAddr; stream->next_out = (unsigned char*) dstAddr; - stream->avail_out = dstLen; + stream->avail_out = dstSize; + + ret = zng_deflate(stream, Z_FINISH); + if (ret == Z_STREAM_END) { + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); + return true; + } else if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); + } + + return false; } -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_deflate(JNIEnv* env, jobject obj, jboolean finish) { +/* +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_deflate(JNIEnv* env, jobject obj, jboolean finish) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); jint avail_in = stream->avail_in; @@ -101,16 +135,4 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_nati env->SetIntField(obj, readBytesID, (avail_in - stream->avail_in)); env->SetIntField(obj, writtenBytesID, (avail_out - stream->avail_out)); } - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_reset(JNIEnv* env, jobject obj) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - int ret = zng_deflateReset(stream); - - if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); - } - - env->SetIntField(obj, readBytesID, 0); - env->SetIntField(obj, writtenBytesID, 0); - env->SetBooleanField(obj, finishedID, (jboolean) 0); -} +*/ diff --git a/compression/zlib/src/main/native/common/inflater.cpp b/compression/zlib/src/main/native/common/inflater.cpp deleted file mode 100644 index d92aa0cbc..000000000 --- a/compression/zlib/src/main/native/common/inflater.cpp +++ /dev/null @@ -1,115 +0,0 @@ -#include -#include "net_daporkchop_lib_natives_zlib_NativeInflater.h" - -#include - -#include -#include - -static jfieldID ctxID; -static jfieldID readBytesID; -static jfieldID writtenBytesID; -static jfieldID finishedID; - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_load(JNIEnv* env, jclass cla) { - ctxID = env->GetFieldID(cla, "ctx", "J"); - readBytesID = env->GetFieldID(cla, "readBytes", "I"); - writtenBytesID = env->GetFieldID(cla, "writtenBytes", "I"); - finishedID = env->GetFieldID(cla, "finished", "Z"); -} - -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_init(JNIEnv* env, jclass cla, jint mode) { - int windowBits; - if (mode == 0) { //zlib - windowBits = 0; - } else if (mode == 1) { //gzip - windowBits = 16; - } else if (mode == 2) { //auto-detect zlib or gzip - windowBits = 32; - } else if (mode == 3) { //raw deflate - windowBits = -15; - } else { - throwException(env, "Invalid inflater mode!", mode); - return 0; - } - - zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); - memset(stream, 0, sizeof(zng_stream)); - - int ret = zng_inflateInit2(stream, windowBits); - - if (ret != Z_OK) { - const char* msg = stream->msg; - free(stream); - throwException(env, msg == nullptr ? "Couldn't init inflater!" : msg, ret); - } - - return (jlong) stream; -} - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_end(JNIEnv* env, jclass cla, jlong ctx) { - zng_stream* stream = (zng_stream*) ctx; - int ret = zng_inflateReset(stream); - if (ret != Z_OK) { - const char* msg = stream->msg; - free(stream); - throwException(env, msg == nullptr ? "Couldn't reset inflater!" : msg, ret); - return; - } - - ret = zng_inflateEnd(stream); - const char* msg = stream->msg; - free(stream); - - if (ret != Z_OK) { - throwException(env, msg == nullptr ? "Couldn't end inflater!" : msg, ret); - } -} - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_input(JNIEnv* env, jobject obj, jlong srcAddr, jint srcLen) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - - stream->next_in = (unsigned char*) srcAddr; - stream->avail_in = srcLen; -} - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_output(JNIEnv* env, jobject obj, jlong dstAddr, jint dstLen) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - - stream->next_out = (unsigned char*) dstAddr; - stream->avail_out = dstLen; -} - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_inflate(JNIEnv* env, jobject obj) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - - jint avail_in = stream->avail_in; - jint avail_out = stream->avail_out; - - //don't actually run inflate with the flush flag if the entire data isn't going to be able to be read this invocation - //of course this doesn't mean it'll be buffering 4GB of data, it just means that it won't begin flushing the data until it decides to - int ret = zng_inflate(stream, Z_SYNC_FLUSH); - if (ret == Z_STREAM_END) { - env->SetBooleanField(obj, finishedID, (jboolean) 1); - } else if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); - return; - } - - env->SetIntField(obj, readBytesID, avail_in - stream->avail_in); - env->SetIntField(obj, writtenBytesID, avail_out - stream->avail_out); -} - -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_reset(JNIEnv* env, jobject obj) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - - int ret = zng_inflateReset(stream); - - if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Couldn't reset inflater!" : stream->msg, ret); - } - - env->SetIntField(obj, readBytesID, 0); - env->SetIntField(obj, writtenBytesID, 0); - env->SetBooleanField(obj, finishedID, (jboolean) 0); -} diff --git a/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h b/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h deleted file mode 100644 index 33b03eb4b..000000000 --- a/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeDeflater.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class net_daporkchop_lib_natives_zlib_NativeDeflater */ - -#ifndef _Included_net_daporkchop_lib_natives_zlib_NativeDeflater -#define _Included_net_daporkchop_lib_natives_zlib_NativeDeflater -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: load - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_load - (JNIEnv *, jclass); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: init - * Signature: (II)J - */ -JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_init - (JNIEnv *, jclass, jint, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: end - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_end - (JNIEnv *, jclass, jlong); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: input - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_input - (JNIEnv *, jobject, jlong, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: output - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_output - (JNIEnv *, jobject, jlong, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: deflate - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_deflate - (JNIEnv *, jobject, jboolean); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeDeflater - * Method: reset - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeDeflater_reset - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h b/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h deleted file mode 100644 index d6a8bd8aa..000000000 --- a/compression/zlib/src/main/native/common/net_daporkchop_lib_natives_zlib_NativeInflater.h +++ /dev/null @@ -1,69 +0,0 @@ -/* DO NOT EDIT THIS FILE - it is machine generated */ -#include -/* Header for class net_daporkchop_lib_natives_zlib_NativeInflater */ - -#ifndef _Included_net_daporkchop_lib_natives_zlib_NativeInflater -#define _Included_net_daporkchop_lib_natives_zlib_NativeInflater -#ifdef __cplusplus -extern "C" { -#endif -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: load - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_load - (JNIEnv *, jclass); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: init - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_init - (JNIEnv *, jclass, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: end - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_end - (JNIEnv *, jclass, jlong); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: input - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_input - (JNIEnv *, jobject, jlong, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: output - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_output - (JNIEnv *, jobject, jlong, jint); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: inflate - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_inflate - (JNIEnv *, jobject); - -/* - * Class: net_daporkchop_lib_natives_zlib_NativeInflater - * Method: reset - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_natives_zlib_NativeInflater_reset - (JNIEnv *, jobject); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java b/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java index 51bd524c0..eeb7ce11a 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java @@ -56,6 +56,9 @@ public static void loadNativeLibrary(@NonNull String name) { case x86: LIB_ARCH = "x86-linux-gnu"; break; + case AARCH64: + LIB_ARCH = "aarch64-linux-gnu"; + break; } break; case Windows: @@ -166,7 +169,7 @@ public static abstract class NativeImpl extends Impl { * Whether or not native libraries are available. */ public static final boolean AVAILABLE = - ((PlatformInfo.ARCHITECTURE == Architecture.x86 || PlatformInfo.ARCHITECTURE == Architecture.x86_64) && PlatformInfo.OPERATING_SYSTEM == OperatingSystem.Linux) + ((PlatformInfo.ARCHITECTURE == Architecture.x86_64 || PlatformInfo.ARCHITECTURE == Architecture.AARCH64) && PlatformInfo.OPERATING_SYSTEM == OperatingSystem.Linux) || (PlatformInfo.ARCHITECTURE == Architecture.x86_64 && PlatformInfo.OPERATING_SYSTEM == OperatingSystem.Windows); @Override diff --git a/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java b/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java new file mode 100644 index 000000000..d4dbe6bb0 --- /dev/null +++ b/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java @@ -0,0 +1,47 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.unsafe.util; + +import net.daporkchop.lib.unsafe.PUnsafe; +import net.daporkchop.lib.unsafe.capability.Releasable; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * An abstract implementation of {@link Releasable}. + * + * @author DaPorkchop_ + */ +public abstract class AbstractReleasable implements Releasable { + private static final long RELEASED_OFFSET = PUnsafe.pork_getOffset(AbstractReleasable.class, "released"); + + private volatile int released = 0; + + @Override + public void release() throws AlreadyReleasedException { + if (!PUnsafe.compareAndSwapInt(this, RELEASED_OFFSET, 0, 1)) { + throw new AlreadyReleasedException(); + } + + this.doRelease(); + } + + /** + * Actually releases this instance's resources. + *

+ * Will only be called once. + */ + protected abstract void doRelease(); +} From 203fba04d8c609e44ea32d4641179a71dde4899f Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Thu, 30 Jan 2020 20:34:05 +0100 Subject: [PATCH 10/36] try to figure out why this is segfaulting --- .../zlib/src/example/java/ZlibTest.java | 39 +++++++++++++++++++ .../daporkchop/lib/compression/zlib/Zlib.java | 4 ++ .../compression/zlib/natives/NativeZlib.java | 5 ++- .../zlib/natives/NativeZlibDeflater.java | 22 ++++++++--- .../main/native/common/NativeZlibDeflater.h | 30 ++------------ .../zlib/src/main/native/common/deflater.cpp | 1 + 6 files changed, 68 insertions(+), 33 deletions(-) create mode 100644 compression/zlib/src/example/java/ZlibTest.java diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java new file mode 100644 index 000000000..df9817e2f --- /dev/null +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -0,0 +1,39 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.zlib.Zlib; + +/** + * @author DaPorkchop_ + */ +public class ZlibTest { + private static final int SIZE = 1 << 26; // 64 MiB + + public static void main(String... args) { + ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); + ByteBuf compressedNative = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE); + + try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { + if (!deflater.deflate(original, compressedNative)) { + throw new IllegalStateException("Couldn't deflate data!"); + } + } + + System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java index dccc28273..15f1b1ca5 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java @@ -16,12 +16,16 @@ package net.daporkchop.lib.compression.zlib; import lombok.experimental.UtilityClass; +import net.daporkchop.lib.compression.zlib.natives.NativeZlib; +import net.daporkchop.lib.natives.NativeCode; /** * @author DaPorkchop_ */ @UtilityClass public class Zlib { + public final NativeCode PROVIDER = new NativeCode<>(NativeZlib::new); + public final int LEVEL_NONE = 0; //no compression at all public final int LEVEL_FASTEST = 1; //fastest compression, worst ratio public final int LEVEL_BEST = 9; //best ratio, slowest compression diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 3bc6e19e5..2b4b83189 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.compression.zlib.natives; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.zlib.Zlib; import net.daporkchop.lib.compression.zlib.ZlibProvider; import net.daporkchop.lib.natives.NativeCode; @@ -27,7 +28,7 @@ public final class NativeZlib extends NativeCode.NativeImpl implem if (NativeCode.NativeImpl.AVAILABLE) { NativeCode.loadNativeLibrary("zlib"); - //NativeZlibDeflater.load(); + NativeZlibDeflater.load(); //NativeZlibInflater.load(); } } @@ -39,6 +40,6 @@ protected ZlibProvider _get() { @Override public PDeflater deflater(int level, int strategy) { - return null; + return new NativeZlibDeflater(level, strategy, Zlib.MODE_ZLIB); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index cf76e4787..06c55e632 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -22,7 +22,6 @@ import net.daporkchop.lib.compression.util.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; -import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; /** * @author DaPorkchop_ @@ -46,14 +45,27 @@ public final class NativeZlibDeflater extends AbstractReleasable implements PDef private int readBytes; private int writtenBytes; - public NativeZlibDeflater(int level, int strategy, int mode) { + public NativeZlibDeflater(int level, int strategy, int mode) { this.ctx = allocateCtx(level, strategy, mode); this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); } @Override public boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - return false; + long srcAddr = src.memoryAddress() + src.readerIndex(); + int srcSize = src.readableBytes(); + + long dstAddr = dst.memoryAddress() + dst.writerIndex(); + int dstSize = dst.writableBytes(); + + if (this.doDeflate(srcAddr, srcSize, dstAddr, dstSize)) { + //increase indices if successful + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); + return true; + } else { + return false; + } } private native boolean doDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); @@ -72,7 +84,7 @@ public PDeflater reset() { @Override public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { - if (!src.hasMemoryAddress()) { + if (!src.hasMemoryAddress()) { throw new InvalidBufferTypeException(true); } this.src = src; @@ -81,7 +93,7 @@ public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { @Override public PDeflater dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException { - if (!dst.hasMemoryAddress()) { + if (!dst.hasMemoryAddress()) { throw new InvalidBufferTypeException(true); } this.dst = dst; diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h index 609ab16bb..6df97ba6f 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -2,13 +2,14 @@ //actually it's not, it was initially though //easier to make this by hand lol #include -/* Header for class net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater */ #ifndef _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater #define _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + #ifdef __cplusplus extern "C" { #endif + /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater * Method: load @@ -49,31 +50,8 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZl JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDeflate (JNIEnv *, jobject, jlong, jint, jlong, jint); -/* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater - * Method: output - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_output - (JNIEnv *, jobject, jlong, jint); - -/* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater - * Method: deflate - * Signature: (Z)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_deflate - (JNIEnv *, jobject, jboolean); - -/* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater - * Method: reset - * Signature: ()V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_reset - (JNIEnv *, jobject); - #ifdef __cplusplus } #endif -#endif + +#endif //_Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater diff --git a/compression/zlib/src/main/native/common/deflater.cpp b/compression/zlib/src/main/native/common/deflater.cpp index 7ba5a9d7b..7c7e92d1f 100644 --- a/compression/zlib/src/main/native/common/deflater.cpp +++ b/compression/zlib/src/main/native/common/deflater.cpp @@ -54,6 +54,7 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com const char* msg = stream->msg; free(stream); throwException(env, msg == nullptr ? "Couldn't init deflater!" : msg, ret); + return 0; } return (jlong) stream; From e3c425e34e35b8d340a83cbba22cd2149c5a90e3 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Fri, 31 Jan 2020 17:04:12 +0100 Subject: [PATCH 11/36] fix segfaults --- compression/zlib/Makefile | 3 +- .../zlib/src/example/java/ZlibTest.java | 30 +++++++++++++++++-- .../zlib/src/main/native/common/deflater.cpp | 2 +- natives/compile.sh | 1 + 4 files changed, 32 insertions(+), 4 deletions(-) diff --git a/compression/zlib/Makefile b/compression/zlib/Makefile index 5065dfe16..988affef6 100644 --- a/compression/zlib/Makefile +++ b/compression/zlib/Makefile @@ -49,7 +49,8 @@ $(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz @[ ! -d lib-zlib ] || rm -rf lib-zlib/ @tar zxf $(TOPDIR)/zlib-ng-1.2.11.tar.gz @mv zlib-ng-1.2.11/ lib-zlib/ - @cd lib-zlib/ && CFLAGS="-fPIC -fvisibility=hidden -ffunction-sections -fdata-sections" ./configure --static --with-gzfileops && cd .. + @cd lib-zlib/ && ./configure --static && cd .. +# @cd lib-zlib/ && ./configure --static --with-gzfileops && cd .. @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a FORCE: diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index df9817e2f..a507c0748 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -18,15 +18,23 @@ import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.zlib.Zlib; +import java.util.concurrent.ThreadLocalRandom; +import java.util.zip.DataFormatException; +import java.util.zip.Inflater; + /** * @author DaPorkchop_ */ public class ZlibTest { private static final int SIZE = 1 << 26; // 64 MiB - public static void main(String... args) { + public static void main(String... args) throws DataFormatException { ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); - ByteBuf compressedNative = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE); + for (int i = 0; i < 512; i += 8) { + original.setLongLE(i, ThreadLocalRandom.current().nextLong()); + } + + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { if (!deflater.deflate(original, compressedNative)) { @@ -35,5 +43,23 @@ public static void main(String... args) { } System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + + byte[] compressedHeap = new byte[compressedNative.readableBytes()]; + compressedNative.readBytes(compressedHeap); + + byte[] uncompressedHeap = new byte[SIZE]; + + Inflater inflater = new Inflater(); + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + } + + for (int i = 0; i < SIZE; i++) { + if (original.getByte(i) != uncompressedHeap[i]) { + throw new IllegalStateException(); + } + } } } diff --git a/compression/zlib/src/main/native/common/deflater.cpp b/compression/zlib/src/main/native/common/deflater.cpp index 7c7e92d1f..f0491cb6b 100644 --- a/compression/zlib/src/main/native/common/deflater.cpp +++ b/compression/zlib/src/main/native/common/deflater.cpp @@ -100,7 +100,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ //set stream buffers stream->next_in = (unsigned char*) srcAddr; - stream->avail_in = srcAddr; + stream->avail_in = srcSize; stream->next_out = (unsigned char*) dstAddr; stream->avail_out = dstSize; diff --git a/natives/compile.sh b/natives/compile.sh index 17203fb4c..876593fdf 100644 --- a/natives/compile.sh +++ b/natives/compile.sh @@ -2,4 +2,5 @@ #i use this script simply so that i can add the natives compilation as a run configuration in intellij +#make clean && \ make -j$( nproc ) From a6f74aaaa5ab851b68b42d5e31bdb47ee289214a Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Fri, 31 Jan 2020 20:42:53 +0100 Subject: [PATCH 12/36] get deflater more or less usable, then begin working on streaming api --- .../daporkchop/lib/compression/Context.java | 32 ++++++++++++-- .../daporkchop/lib/compression/PDeflater.java | 11 ++++- .../daporkchop/lib/compression/PInflater.java | 2 +- .../exception/ContextFinishedException.java | 24 ++++++++++ .../InvalidBufferTypeException.java | 4 +- .../zlib/src/example/java/ZlibTest.java | 2 +- .../zlib/natives/NativeZlibDeflater.java | 44 ++++++++++++++----- .../{deflater.cpp => NativeZlibDeflater.cpp} | 35 +++++++-------- .../main/native/common/NativeZlibDeflater.h | 20 ++++----- 9 files changed, 125 insertions(+), 49 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java rename compression/src/main/java/net/daporkchop/lib/compression/util/{ => exception}/InvalidBufferTypeException.java (92%) rename compression/zlib/src/main/native/common/{deflater.cpp => NativeZlibDeflater.cpp} (90%) diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index 974f5f628..e16c67c02 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -17,7 +17,8 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.capability.Releasable; /** @@ -41,7 +42,7 @@ interface Context> extends Releasable { * Sets the context's current source buffer when processing data in streaming mode. * * @param src the {@link ByteBuf} to read data from - * @return this + * @return this context */ I src(@NonNull ByteBuf src) throws InvalidBufferTypeException; @@ -49,16 +50,39 @@ interface Context> extends Releasable { * Sets the context's current destination buffer when processing data in streaming mode. * * @param dst the {@link ByteBuf} to write data to - * @return this + * @return this context */ I dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException; + /** + * Updates this context, processing as much data as possible. + *

+ * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up. + *

+ * Implementations may buffer any amount of data internally. + * + * @return this context + * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + */ + I update() throws ContextFinishedException; + + /** + * Finishes this context. + *

+ * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up, and then + * attempt to flush any internally buffered data and finish the (de)compression process. + * + * @return whether or not the context could be completed. If {@code false}, there is not enough space in the destination buffer for the context to finish + * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + */ + boolean finish() throws ContextFinishedException; + /** * Resets this context. *

* This will erase any internal buffers and reset the source and destination buffers to {@code null}. * - * @return this + * @return this context */ I reset(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java index 54ea73314..45b8c2855 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -17,7 +17,8 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; /** * Deflates (compresses) data. @@ -37,5 +38,11 @@ public interface PDeflater extends Context { * @param dst the {@link ByteBuf} to write data to * @return whether or not there was enough space in the destination buffer for the compressed data */ - boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + + @Override + PDeflater update() throws ContextFinishedException; + + @Override + boolean finish() throws ContextFinishedException; } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java index 6fac84d88..64ff69861 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -17,7 +17,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; /** * Inflates (decompresses) data. diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java new file mode 100644 index 000000000..eabecc111 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java @@ -0,0 +1,24 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util.exception; + +/** + * Thrown when a {@link net.daporkchop.lib.compression.Context} is used that is already finished, and was not reset. + * + * @author DaPorkchop_ + */ +public final class ContextFinishedException extends RuntimeException { +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java similarity index 92% rename from compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java rename to compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java index 2e634fd82..0f18483ac 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/InvalidBufferTypeException.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java @@ -13,7 +13,7 @@ * */ -package net.daporkchop.lib.compression.util; +package net.daporkchop.lib.compression.util.exception; /** * Thrown when a {@link io.netty.buffer.ByteBuf} argument to a {@link net.daporkchop.lib.compression.PInflater} or {@link net.daporkchop.lib.compression.PDeflater} @@ -21,7 +21,7 @@ * * @author DaPorkchop_ */ -public class InvalidBufferTypeException extends IllegalArgumentException { +public final class InvalidBufferTypeException extends IllegalArgumentException { public InvalidBufferTypeException(boolean direct) { super(direct ? "direct buffer expected!" : "heap buffer expected!"); } diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index a507c0748..9865fbb71 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -37,7 +37,7 @@ public static void main(String... args) throws DataFormatException { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { - if (!deflater.deflate(original, compressedNative)) { + if (!deflater.fullDeflate(original, compressedNative)) { throw new IllegalStateException("Couldn't deflate data!"); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 06c55e632..3c866a634 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -19,7 +19,8 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import net.daporkchop.lib.compression.PDeflater; -import net.daporkchop.lib.compression.util.InvalidBufferTypeException; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -31,8 +32,6 @@ public final class NativeZlibDeflater extends AbstractReleasable implements PDef private static native long allocateCtx(int level, int strategy, int mode); - private static native void resetCtx(long ctx); - private static native void releaseCtx(long ctx); private final long ctx; @@ -45,20 +44,25 @@ public final class NativeZlibDeflater extends AbstractReleasable implements PDef private int readBytes; private int writtenBytes; + private boolean reset; + public NativeZlibDeflater(int level, int strategy, int mode) { this.ctx = allocateCtx(level, strategy, mode); this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + this.reset = true; } @Override - public boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + this.reset(); //this will do nothing if we're already reset + long srcAddr = src.memoryAddress() + src.readerIndex(); int srcSize = src.readableBytes(); long dstAddr = dst.memoryAddress() + dst.writerIndex(); int dstSize = dst.writableBytes(); - if (this.doDeflate(srcAddr, srcSize, dstAddr, dstSize)) { + if (this.doFullDeflate(srcAddr, srcSize, dstAddr, dstSize)) { //increase indices if successful src.skipBytes(this.readBytes); dst.writerIndex(dst.writerIndex() + this.writtenBytes); @@ -68,20 +72,38 @@ public boolean deflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Invali } } - private native boolean doDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); + private native boolean doFullDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public PDeflater update() throws ContextFinishedException { + return this; + } + + private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public boolean finish() throws ContextFinishedException { + return false; + } + + private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize); @Override public PDeflater reset() { - this.src = null; - this.dst = null; + if (!this.reset) { + this.src = null; + this.dst = null; - this.readBytes = 0; - this.writtenBytes = 0; + this.readBytes = 0; + this.writtenBytes = 0; - resetCtx(this.ctx); + this.doReset(); + } return this; } + private native void doReset(); + @Override public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { diff --git a/compression/zlib/src/main/native/common/deflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp similarity index 90% rename from compression/zlib/src/main/native/common/deflater.cpp rename to compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index f0491cb6b..ff3aa157f 100644 --- a/compression/zlib/src/main/native/common/deflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -11,12 +11,14 @@ static jfieldID ctxID; static jfieldID readBytesID; static jfieldID writtenBytesID; +static jfieldID resetID; __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_load (JNIEnv* env, jclass cla) { ctxID = env->GetFieldID(cla, "ctx", "J"); readBytesID = env->GetFieldID(cla, "readBytes", "I"); writtenBytesID = env->GetFieldID(cla, "writtenBytes", "I"); + resetID = env->GetFieldID(cla, "reset", "Z"); } __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_allocateCtx @@ -60,16 +62,6 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com return (jlong) stream; } -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_resetCtx - (JNIEnv* env, jclass cla, jlong ctx) { - zng_stream* stream = (zng_stream*) ctx; - int ret = zng_deflateReset(stream); - - if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); - } -} - __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_releaseCtx (JNIEnv* env, jclass cla, jlong ctx) { zng_stream* stream = (zng_stream*) ctx; @@ -88,16 +80,10 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } } -__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDeflate +__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doFullDeflate (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - int ret = zng_deflateReset(stream); - if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); - return false; - } - //set stream buffers stream->next_in = (unsigned char*) srcAddr; stream->avail_in = srcSize; @@ -105,7 +91,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ stream->next_out = (unsigned char*) dstAddr; stream->avail_out = dstSize; - ret = zng_deflate(stream, Z_FINISH); + int ret = zng_deflate(stream, Z_FINISH); if (ret == Z_STREAM_END) { env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); @@ -117,6 +103,19 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ return false; } +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doReset + (JNIEnv* env, jobject obj) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + int ret = zng_deflateReset(stream); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); + return; + } + + env->SetBooleanField(obj, resetID, true); +} + /* __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_deflate(JNIEnv* env, jobject obj, jboolean finish) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h index 6df97ba6f..8aabf424b 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -26,14 +26,6 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZl JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_allocateCtx (JNIEnv *, jclass, jint, jint, jint); -/* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater - * Method: resetCtx - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_resetCtx - (JNIEnv *, jclass, jlong); - /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater * Method: releaseCtx @@ -44,12 +36,20 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZl /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater - * Method: doDeflate + * Method: doFullDeflate * Signature: (JIJI)Z */ -JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDeflate +JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doFullDeflate (JNIEnv *, jobject, jlong, jint, jlong, jint); +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: doReset + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doReset + (JNIEnv *, jobject); + #ifdef __cplusplus } #endif From c9aed1b22f34c00887eadb4087fb36949ca596ef Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 00:36:49 +0100 Subject: [PATCH 13/36] theoretically implement streaming compression --- .../daporkchop/lib/compression/Context.java | 9 ++-- .../exception/ContextFinishedException.java | 5 +- .../exception/ContextFinishingException.java | 24 +++++++++ .../zlib/natives/NativeZlibDeflater.java | 44 +++++++++++++---- .../main/native/common/NativeZlibDeflater.cpp | 49 +++++++++++++++++++ .../main/native/common/NativeZlibDeflater.h | 16 ++++++ 6 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index e16c67c02..f475ec40c 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.capability.Releasable; @@ -43,8 +44,9 @@ interface Context> extends Releasable { * * @param src the {@link ByteBuf} to read data from * @return this context + * @throws ContextFinishingException if this context is already being finished, and as such the source buffer may not be updated any more */ - I src(@NonNull ByteBuf src) throws InvalidBufferTypeException; + I src(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContextFinishingException; /** * Sets the context's current destination buffer when processing data in streaming mode. @@ -62,9 +64,10 @@ interface Context> extends Releasable { * Implementations may buffer any amount of data internally. * * @return this context - * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + * @throws ContextFinishingException if this context is already being finished (but is not yet completely finished) */ - I update() throws ContextFinishedException; + I update() throws ContextFinishedException, ContextFinishingException; /** * Finishes this context. diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java index eabecc111..066ebb5e2 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishedException.java @@ -15,10 +15,13 @@ package net.daporkchop.lib.compression.util.exception; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; + /** * Thrown when a {@link net.daporkchop.lib.compression.Context} is used that is already finished, and was not reset. * * @author DaPorkchop_ */ -public final class ContextFinishedException extends RuntimeException { +public class ContextFinishedException extends RuntimeException { } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java new file mode 100644 index 000000000..a177d7e90 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java @@ -0,0 +1,24 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util.exception; + +/** + * Thrown when a {@link net.daporkchop.lib.compression.Context} is updated that is already being finished (but was not completely finished), and was not reset. + * + * @author DaPorkchop_ + */ +public final class ContextFinishingException extends ContextFinishedException { +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 3c866a634..38240fae9 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -20,6 +20,7 @@ import lombok.RequiredArgsConstructor; import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -45,6 +46,8 @@ public final class NativeZlibDeflater extends AbstractReleasable implements PDef private int writtenBytes; private boolean reset; + private boolean finishing; + private boolean finished; public NativeZlibDeflater(int level, int strategy, int mode) { this.ctx = allocateCtx(level, strategy, mode); @@ -56,13 +59,8 @@ public NativeZlibDeflater(int level, int strategy, int mode) { public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { this.reset(); //this will do nothing if we're already reset - long srcAddr = src.memoryAddress() + src.readerIndex(); - int srcSize = src.readableBytes(); - - long dstAddr = dst.memoryAddress() + dst.writerIndex(); - int dstSize = dst.writableBytes(); - - if (this.doFullDeflate(srcAddr, srcSize, dstAddr, dstSize)) { + if (this.doFullDeflate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { //increase indices if successful src.skipBytes(this.readBytes); dst.writerIndex(dst.writerIndex() + this.writtenBytes); @@ -75,15 +73,40 @@ public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws In private native boolean doFullDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); @Override - public PDeflater update() throws ContextFinishedException { + public PDeflater update() throws ContextFinishedException, ContextFinishingException { + this.update(this.src, this.dst); return this; } + private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst) { + if (this.finished) { + throw new ContextFinishedException(); + } else if (this.finishing) { + throw new ContextFinishingException(); + } + + this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); + } + private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize); @Override public boolean finish() throws ContextFinishedException { - return false; + if (this.finished) { + throw new ContextFinishedException(); + } + return this.finish(this.src, this.dst); + } + + private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { + if (this.finished) { + throw new ContextFinishedException(); + } + this.finishing = true; + + return this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); } private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize); @@ -97,6 +120,9 @@ public PDeflater reset() { this.readBytes = 0; this.writtenBytes = 0; + this.finishing = false; + this.finished = false; + this.doReset(); } return this; diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index ff3aa157f..9645ec1ea 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -12,6 +12,7 @@ static jfieldID ctxID; static jfieldID readBytesID; static jfieldID writtenBytesID; static jfieldID resetID; +static jfieldID finishedID; __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_load (JNIEnv* env, jclass cla) { @@ -19,6 +20,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp readBytesID = env->GetFieldID(cla, "readBytes", "I"); writtenBytesID = env->GetFieldID(cla, "writtenBytes", "I"); resetID = env->GetFieldID(cla, "reset", "Z"); + finishedID = env->GetFieldID(cla, "finished", "Z"); } __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_allocateCtx @@ -103,6 +105,53 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ return false; } +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doUpdate + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcSize; + + stream->next_out = (unsigned char*) dstAddr; + stream->avail_out = dstSize; + + int ret = zng_deflate(stream, Z_NO_FLUSH); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); + } + + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); +} + +__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doFinish + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcSize; + + stream->next_out = (unsigned char*) dstAddr; + stream->avail_out = dstSize; + + int ret = zng_deflate(stream, Z_FINISH); + if (ret != Z_STREAM_END && ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); + } + + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); + + if (ret == Z_STREAM_END) { + env->SetBooleanField(obj, finishedID, true); + return true; + } else { + return false; + } +} + __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doReset (JNIEnv* env, jobject obj) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h index 8aabf424b..77f92759b 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -42,6 +42,22 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZl JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doFullDeflate (JNIEnv *, jobject, jlong, jint, jlong, jint); +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: doUpdate + * Signature: (JIJI)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doUpdate + (JNIEnv *, jobject, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: doFinish + * Signature: (JIJI)Z + */ +JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doFinish + (JNIEnv *, jobject, jlong, jint, jlong, jint); + /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater * Method: doReset From caebaf3f9d2fdba126a6ca059d5904f3b2eefb21 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 01:11:31 +0100 Subject: [PATCH 14/36] fix streaming compression, and add the ability to flush the compression buffer while streaming --- .../daporkchop/lib/compression/Context.java | 4 +- .../daporkchop/lib/compression/PDeflater.java | 3 +- .../zlib/src/example/java/ZlibTest.java | 79 +++++++++++++++---- .../zlib/natives/NativeZlibDeflater.java | 29 ++++--- .../main/native/common/NativeZlibDeflater.cpp | 4 +- .../main/native/common/NativeZlibDeflater.h | 4 +- 6 files changed, 91 insertions(+), 32 deletions(-) diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index f475ec40c..9801dd19e 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -63,11 +63,13 @@ interface Context> extends Releasable { *

* Implementations may buffer any amount of data internally. * + * @param flush whether or not the internal buffer should be flushed. If {@code true}, an attempt will be made to flush as much buffered data as possible. Note + * that this can cause a negative impact on the compression ratio. * @return this context * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again * @throws ContextFinishingException if this context is already being finished (but is not yet completely finished) */ - I update() throws ContextFinishedException, ContextFinishingException; + I update(boolean flush) throws ContextFinishedException, ContextFinishingException; /** * Finishes this context. diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java index 45b8c2855..6f2712576 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; /** @@ -41,7 +42,7 @@ public interface PDeflater extends Context { boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; @Override - PDeflater update() throws ContextFinishedException; + PDeflater update(boolean flush) throws ContextFinishedException, ContextFinishingException; @Override boolean finish() throws ContextFinishedException; diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 9865fbb71..70f1c6ff4 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -15,6 +15,7 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import lombok.NonNull; import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.zlib.Zlib; @@ -30,34 +31,80 @@ public class ZlibTest { public static void main(String... args) throws DataFormatException { ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); - for (int i = 0; i < 512; i += 8) { + for (int i = 0; i < SIZE; i++) { + original.setByte(i, i & 0xFF); + } + for (int i = 0; i < 512; i += 8) { original.setLongLE(i, ThreadLocalRandom.current().nextLong()); } - ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); + { + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); + + try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { + if (!deflater.fullDeflate(original, compressedNative)) { + throw new IllegalStateException("Couldn't deflate data!"); + } + } + + System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + + byte[] compressedHeap = new byte[compressedNative.readableBytes()]; + compressedNative.readBytes(compressedHeap); + compressedNative.release(); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { - if (!deflater.fullDeflate(original, compressedNative)) { - throw new IllegalStateException("Couldn't deflate data!"); + byte[] uncompressedHeap = new byte[SIZE]; + + Inflater inflater = new Inflater(); + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); } + + validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); } - System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + { + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); - byte[] compressedHeap = new byte[compressedNative.readableBytes()]; - compressedNative.readBytes(compressedHeap); + try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { + deflater.dst(compressedNative); + for (int i = 0; i < (1 << 4); i++) { + ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); + deflater.src(src).update(true); + if (src.isReadable()) { + throw new IllegalStateException(); + } + } - byte[] uncompressedHeap = new byte[SIZE]; + if (!deflater.finish()) { + throw new IllegalStateException("Couldn't deflate data!"); + } + } + + System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + + byte[] compressedHeap = new byte[compressedNative.readableBytes()]; + compressedNative.readBytes(compressedHeap); + compressedNative.release(); + + byte[] uncompressedHeap = new byte[SIZE]; - Inflater inflater = new Inflater(); - inflater.setInput(compressedHeap); - int cnt = inflater.inflate(uncompressedHeap); - if (cnt != SIZE) { - throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + Inflater inflater = new Inflater(); + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + } + + validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); } + } - for (int i = 0; i < SIZE; i++) { - if (original.getByte(i) != uncompressedHeap[i]) { + private static void validateEqual(@NonNull ByteBuf a, @NonNull ByteBuf b, int start, int size) { + for (int i = 0; i < size; i++) { + if (a.getByte(start + i) != b.getByte(start + i)) { throw new IllegalStateException(); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 38240fae9..d4419d345 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -73,12 +73,12 @@ public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws In private native boolean doFullDeflate(long srcAddr, int srcSize, long dstAddr, int dstSize); @Override - public PDeflater update() throws ContextFinishedException, ContextFinishingException { - this.update(this.src, this.dst); + public PDeflater update(boolean flush) throws ContextFinishedException, ContextFinishingException { + this.update(this.src, this.dst, flush); return this; } - private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst) { + private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { if (this.finished) { throw new ContextFinishedException(); } else if (this.finishing) { @@ -86,16 +86,18 @@ private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst) { } this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + flush); + + //increase indices + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); } - private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize); + private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize, boolean flush); @Override public boolean finish() throws ContextFinishedException { - if (this.finished) { - throw new ContextFinishedException(); - } return this.finish(this.src, this.dst); } @@ -105,8 +107,15 @@ private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { } this.finishing = true; - return this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); + if (this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { + //increase indices if successful + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); + return true; + } else { + return false; + } } private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize); diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index 9645ec1ea..2fdcc7275 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -106,7 +106,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doUpdate - (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jboolean flush) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); //set stream buffers @@ -116,7 +116,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp stream->next_out = (unsigned char*) dstAddr; stream->avail_out = dstSize; - int ret = zng_deflate(stream, Z_NO_FLUSH); + int ret = zng_deflate(stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); } diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h index 77f92759b..adcc624b2 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -45,10 +45,10 @@ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_Nati /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater * Method: doUpdate - * Signature: (JIJI)V + * Signature: (JIJIZ)V */ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doUpdate - (JNIEnv *, jobject, jlong, jint, jlong, jint); + (JNIEnv *, jobject, jlong, jint, jlong, jint, jboolean); /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater From 74cc88a2e6660a9358ce71ccdfa50ba51660c084 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 01:19:02 +0100 Subject: [PATCH 15/36] add helper methods for gzip --- .../zlib/src/example/java/ZlibTest.java | 4 +- .../lib/compression/zlib/ZlibProvider.java | 64 ++++++++++++++++++- .../compression/zlib/natives/NativeZlib.java | 4 +- 3 files changed, 67 insertions(+), 5 deletions(-) diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 70f1c6ff4..92ac8ea50 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -41,7 +41,7 @@ public static void main(String... args) throws DataFormatException { { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { + try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { if (!deflater.fullDeflate(original, compressedNative)) { throw new IllegalStateException("Couldn't deflate data!"); } @@ -68,7 +68,7 @@ public static void main(String... args) throws DataFormatException { { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT)) { + try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { deflater.dst(compressedNative); for (int i = 0; i < (1 << 4); i++) { ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 2f367bb9a..4540c3a85 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -23,6 +23,55 @@ * @author DaPorkchop_ */ public interface ZlibProvider { + /** + * Creates a new {@link PDeflater}. + * + * @return a new {@link PDeflater} + */ + default PDeflater deflater() { + return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); + } + + /** + * Creates a new {@link PDeflater}. + * + * @param level the {@link Zlib} level to use + * @return a new {@link PDeflater} with the given level + */ + default PDeflater deflater(int level) { + return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); + } + + /** + * Creates a new {@link PDeflater}. + * + * @param level the {@link Zlib} level to use + * @param strategy the {@link Zlib} strategy to use + * @return a new {@link PDeflater} with the given level and strategy + */ + default PDeflater deflater(int level, int strategy) { + return this.deflater(level, strategy, Zlib.MODE_ZLIB); + } + + /** + * Creates a new {@link PDeflater}. + * + * @return a new {@link PDeflater} + */ + default PDeflater deflaterGzip() { + return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); + } + + /** + * Creates a new {@link PDeflater}. + * + * @param level the {@link Zlib} level to use + * @return a new {@link PDeflater} with the given level + */ + default PDeflater deflaterGzip(int level) { + return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); + } + /** * Creates a new {@link PDeflater}. * @@ -30,5 +79,18 @@ public interface ZlibProvider { * @param strategy the {@link Zlib} strategy to use * @return a new {@link PDeflater} with the given level and strategy */ - PDeflater deflater(int level, int strategy); + default PDeflater deflaterGzip(int level, int strategy) { + return this.deflater(level, strategy, Zlib.MODE_GZIP); + } + + /** + * Creates a new {@link PDeflater}. + * + * @param level the {@link Zlib} level to use. Must be in range {@link Zlib#LEVEL_NONE} to {@link Zlib#LEVEL_BEST} (inclusive), or {@link Zlib#LEVEL_DEFAULT} + * @param strategy the {@link Zlib} strategy to use. Must be one of {@link Zlib#STRATEGY_DEFAULT}, {@link Zlib#STRATEGY_FILTERED}, {@link Zlib#STRATEGY_HUFFMAN}, + * {@link Zlib#STRATEGY_RLE} or {@link Zlib#STRATEGY_FIXED} + * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP} or {@link Zlib#MODE_RAW} + * @return a new {@link PDeflater} with the given level and strategy + */ + PDeflater deflater(int level, int strategy, int mode); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 2b4b83189..ffc07823a 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -39,7 +39,7 @@ protected ZlibProvider _get() { } @Override - public PDeflater deflater(int level, int strategy) { - return new NativeZlibDeflater(level, strategy, Zlib.MODE_ZLIB); + public PDeflater deflater(int level, int strategy, int mode) { + return new NativeZlibDeflater(level, strategy, mode); } } From 8dfa907b436e5411d818ad5574cdec83ae630d3c Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 01:41:48 +0100 Subject: [PATCH 16/36] implement native zlib inflater as well --- .../daporkchop/lib/compression/PInflater.java | 10 +- .../zlib/src/example/java/ZlibTest.java | 55 ++++-- .../lib/compression/zlib/ZlibProvider.java | 42 +++- .../compression/zlib/natives/NativeZlib.java | 8 +- .../zlib/natives/NativeZlibDeflater.java | 4 + .../zlib/natives/NativeZlibInflater.java | 184 ++++++++++++++++++ .../main/native/common/NativeZlibDeflater.cpp | 28 +-- .../main/native/common/NativeZlibInflater.cpp | 156 +++++++++++++++ .../main/native/common/NativeZlibInflater.h | 73 +++++++ 9 files changed, 512 insertions(+), 48 deletions(-) create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java create mode 100644 compression/zlib/src/main/native/common/NativeZlibInflater.cpp create mode 100644 compression/zlib/src/main/native/common/NativeZlibInflater.h diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java index 64ff69861..9eaca3076 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -17,6 +17,8 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; /** @@ -37,5 +39,11 @@ public interface PInflater extends Context { * @param dst the {@link ByteBuf} to write data to * @return whether or not there was enough space in the destination buffer for the decompressed data */ - boolean inflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + + @Override + PInflater update(boolean flush) throws ContextFinishedException, ContextFinishingException; + + @Override + boolean finish() throws ContextFinishedException; } diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 92ac8ea50..1bd7f3184 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -17,6 +17,7 @@ import io.netty.buffer.Unpooled; import lombok.NonNull; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.PInflater; import net.daporkchop.lib.compression.zlib.Zlib; import java.util.concurrent.ThreadLocalRandom; @@ -39,7 +40,7 @@ public static void main(String... args) throws DataFormatException { } { - ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { if (!deflater.fullDeflate(original, compressedNative)) { @@ -50,23 +51,34 @@ public static void main(String... args) throws DataFormatException { System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); byte[] compressedHeap = new byte[compressedNative.readableBytes()]; - compressedNative.readBytes(compressedHeap); - compressedNative.release(); + compressedNative.getBytes(0, compressedHeap); byte[] uncompressedHeap = new byte[SIZE]; - Inflater inflater = new Inflater(); - inflater.setInput(compressedHeap); - int cnt = inflater.inflate(uncompressedHeap); - if (cnt != SIZE) { - throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + { + Inflater inflater = new Inflater(); + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + } + inflater.end(); } validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); + + ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); + try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + throw new IllegalStateException("Couldn't inflate data!"); + } + } + + validateEqual(original, uncompressedNative, 0, SIZE); } { - ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4).clear().ensureWritable(SIZE >>> 4); + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { deflater.dst(compressedNative); @@ -86,19 +98,30 @@ public static void main(String... args) throws DataFormatException { System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); byte[] compressedHeap = new byte[compressedNative.readableBytes()]; - compressedNative.readBytes(compressedHeap); - compressedNative.release(); + compressedNative.getBytes(0, compressedHeap); byte[] uncompressedHeap = new byte[SIZE]; - Inflater inflater = new Inflater(); - inflater.setInput(compressedHeap); - int cnt = inflater.inflate(uncompressedHeap); - if (cnt != SIZE) { - throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + { + Inflater inflater = new Inflater(); + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + } + inflater.end(); } validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); + + ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); + try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + throw new IllegalStateException("Couldn't inflate data!"); + } + } + + validateEqual(original, uncompressedNative, 0, SIZE); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 4540c3a85..5e0fe3534 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.compression.zlib; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.PInflater; /** * A wrapper around a Zlib implementation. @@ -54,7 +55,7 @@ default PDeflater deflater(int level, int strategy) { } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link PDeflater} that will use Gzip headers. * * @return a new {@link PDeflater} */ @@ -63,7 +64,7 @@ default PDeflater deflaterGzip() { } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link PDeflater} that will use Gzip headers. * * @param level the {@link Zlib} level to use * @return a new {@link PDeflater} with the given level @@ -73,7 +74,7 @@ default PDeflater deflaterGzip(int level) { } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link PDeflater} that will use Gzip headers. * * @param level the {@link Zlib} level to use * @param strategy the {@link Zlib} strategy to use @@ -93,4 +94,39 @@ default PDeflater deflaterGzip(int level, int strategy) { * @return a new {@link PDeflater} with the given level and strategy */ PDeflater deflater(int level, int strategy, int mode); + + /** + * Creates a new {@link PInflater}. + * + * @return a new {@link PInflater} + */ + default PInflater inflater() { + return this.inflater(Zlib.MODE_ZLIB); + } + + /** + * Creates a new {@link PInflater} that will use Gzip headers. + * + * @return a new {@link PInflater} + */ + default PInflater inflaterGzip() { + return this.inflater(Zlib.MODE_GZIP); + } + + /** + * Creates a new {@link PInflater} that will automatically detect whether the compressed data is in Zlib or Gzip format. + * + * @return a new {@link PInflater} + */ + default PInflater inflaterAuto() { + return this.inflater(Zlib.MODE_AUTO); + } + + /** + * Creates a new {@link PInflater}. + * + * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP}, {@link Zlib#MODE_RAW} or {@link Zlib#MODE_AUTO} + * @return a new {@link PInflater} + */ + PInflater inflater(int mode); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index ffc07823a..1709dea4e 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.compression.zlib.natives; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.PInflater; import net.daporkchop.lib.compression.zlib.Zlib; import net.daporkchop.lib.compression.zlib.ZlibProvider; import net.daporkchop.lib.natives.NativeCode; @@ -29,7 +30,7 @@ public final class NativeZlib extends NativeCode.NativeImpl implem NativeCode.loadNativeLibrary("zlib"); NativeZlibDeflater.load(); - //NativeZlibInflater.load(); + NativeZlibInflater.load(); } } @@ -42,4 +43,9 @@ protected ZlibProvider _get() { public PDeflater deflater(int level, int strategy, int mode) { return new NativeZlibDeflater(level, strategy, mode); } + + @Override + public PInflater inflater(int mode) { + return new NativeZlibInflater(mode); + } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index d4419d345..3469a1fe0 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -57,6 +57,10 @@ public NativeZlibDeflater(int level, int strategy, int mode) { @Override public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + if (!src.hasMemoryAddress() || !dst.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + this.reset(); //this will do nothing if we're already reset if (this.doFullDeflate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java new file mode 100644 index 000000000..64a175d01 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -0,0 +1,184 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib.natives; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; + +/** + * @author DaPorkchop_ + */ +public final class NativeZlibInflater extends AbstractReleasable implements PInflater { + static native void load(); + + private static native long allocateCtx(int mode); + + private static native void releaseCtx(long ctx); + + private final long ctx; + + private final PCleaner cleaner; + + private ByteBuf src; + private ByteBuf dst; + + private int readBytes; + private int writtenBytes; + + private boolean reset; + private boolean finishing; + private boolean finished; + + public NativeZlibInflater(int mode) { + this.ctx = allocateCtx(mode); + this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + this.reset = true; + } + + @Override + public boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + if (!src.hasMemoryAddress() || !dst.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + + this.reset(); //this will do nothing if we're already reset + + if (this.doFullInflate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { + //increase indices if successful + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); + return true; + } else { + return false; + } + } + + private native boolean doFullInflate(long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public PInflater update(boolean flush) throws ContextFinishedException, ContextFinishingException { + this.update(this.src, this.dst, flush); + return this; + } + + private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { + if (this.finished) { + throw new ContextFinishedException(); + } else if (this.finishing) { + throw new ContextFinishingException(); + } + + this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + flush); + + //increase indices + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); + } + + private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize, boolean flush); + + @Override + public boolean finish() throws ContextFinishedException { + return this.finish(this.src, this.dst); + } + + private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { + if (this.finished) { + throw new ContextFinishedException(); + } + this.finishing = true; + + if (this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { + //increase indices if successful + src.skipBytes(this.readBytes); + dst.writerIndex(dst.writerIndex() + this.writtenBytes); + return true; + } else { + return false; + } + } + + private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public PInflater reset() { + if (!this.reset) { + this.src = null; + this.dst = null; + + this.readBytes = 0; + this.writtenBytes = 0; + + this.finishing = false; + this.finished = false; + + this.doReset(); + } + return this; + } + + private native void doReset(); + + @Override + public PInflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { + if (!src.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + this.src = src; + return this; + } + + @Override + public PInflater dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException { + if (!dst.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } + this.dst = dst; + return this; + } + + @Override + public boolean direct() { + return true; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long ctx; + + @Override + public void run() { + releaseCtx(this.ctx); + } + } +} diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index 2fdcc7275..ba3f6bea9 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -67,13 +67,8 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_releaseCtx (JNIEnv* env, jclass cla, jlong ctx) { zng_stream* stream = (zng_stream*) ctx; - int ret = zng_deflateReset(stream); - if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); - return; - } - ret = zng_deflateEnd(stream); + int ret = zng_deflateEnd(stream); const char* msg = stream->msg; free(stream); @@ -164,24 +159,3 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp env->SetBooleanField(obj, resetID, true); } - -/* -__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_deflate(JNIEnv* env, jobject obj, jboolean finish) { - zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); - - jint avail_in = stream->avail_in; - jint avail_out = stream->avail_out; - - //even if finish is set to true, don't actually run deflate with the finish flag if the entire data isn't going to be able to be read this invocation - int ret = zng_deflate(stream, finish ? Z_FINISH : Z_NO_FLUSH); - if (ret == Z_STREAM_END) { - env->SetBooleanField(obj, finishedID, (jboolean) 1); - } else if (ret != Z_OK) { - throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); - return; - } - - env->SetIntField(obj, readBytesID, (avail_in - stream->avail_in)); - env->SetIntField(obj, writtenBytesID, (avail_out - stream->avail_out)); -} -*/ diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp new file mode 100644 index 000000000..9a8b12412 --- /dev/null +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp @@ -0,0 +1,156 @@ +#include +#include "NativeZlibInflater.h" + +#include + +#include +#include + +#include + +static jfieldID ctxID; +static jfieldID readBytesID; +static jfieldID writtenBytesID; +static jfieldID resetID; +static jfieldID finishedID; + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_load + (JNIEnv* env, jclass cla) { + ctxID = env->GetFieldID(cla, "ctx", "J"); + readBytesID = env->GetFieldID(cla, "readBytes", "I"); + writtenBytesID = env->GetFieldID(cla, "writtenBytes", "I"); + resetID = env->GetFieldID(cla, "reset", "Z"); + finishedID = env->GetFieldID(cla, "finished", "Z"); +} + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_allocateCtx + (JNIEnv* env, jclass cla, jint mode) { + int windowBits; + switch (mode) { + case 0: //zlib + windowBits = 15; + break; + case 1: //gzip + windowBits = 15 + 16; + break; + case 2: //raw + windowBits = -15; + break; + case 3: //auto + windowBits = 15 + 32; + break; + default: + throwException(env, "Invalid inflater mode!", mode); + return 0; + } + + zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); + memset(stream, 0, sizeof(zng_stream)); + + int ret = zng_inflateInit2(stream, windowBits); + + if (ret != Z_OK) { + const char* msg = stream->msg; + free(stream); + throwException(env, msg == nullptr ? "Couldn't init inflater!" : msg, ret); + return 0; + } + + return (jlong) stream; +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_releaseCtx + (JNIEnv* env, jclass cla, jlong ctx) { + zng_stream* stream = (zng_stream*) ctx; + + int ret = zng_inflateEnd(stream); + const char* msg = stream->msg; + free(stream); + + if (ret != Z_OK) { + throwException(env, msg == nullptr ? "Couldn't end inflater!" : msg, ret); + } +} + +__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFullInflate + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcSize; + + stream->next_out = (unsigned char*) dstAddr; + stream->avail_out = dstSize; + + int ret = zng_inflate(stream, Z_FINISH); + if (ret == Z_STREAM_END) { + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); + return true; + } else if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); + } + + return false; +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doUpdate + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jboolean flush) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcSize; + + stream->next_out = (unsigned char*) dstAddr; + stream->avail_out = dstSize; + + int ret = zng_inflate(stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); + } + + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); +} + +__attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFinish + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + + //set stream buffers + stream->next_in = (unsigned char*) srcAddr; + stream->avail_in = srcSize; + + stream->next_out = (unsigned char*) dstAddr; + stream->avail_out = dstSize; + + int ret = zng_inflate(stream, Z_FINISH); + if (ret != Z_STREAM_END && ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); + } + + env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); + env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); + + if (ret == Z_STREAM_END) { + env->SetBooleanField(obj, finishedID, true); + return true; + } else { + return false; + } +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doReset + (JNIEnv* env, jobject obj) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + int ret = zng_inflateReset(stream); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); + return; + } + + env->SetBooleanField(obj, resetID, true); +} diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.h b/compression/zlib/src/main/native/common/NativeZlibInflater.h new file mode 100644 index 000000000..a8feb8102 --- /dev/null +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.h @@ -0,0 +1,73 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater +#define _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: load + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_load + (JNIEnv *, jclass); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: allocateCtx + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_allocateCtx + (JNIEnv *, jclass, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: releaseCtx + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_releaseCtx + (JNIEnv *, jclass, jlong); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: doFullInflate + * Signature: (JIJI)Z + */ +JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFullInflate + (JNIEnv *, jobject, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: doUpdate + * Signature: (JIJIZ)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doUpdate + (JNIEnv *, jobject, jlong, jint, jlong, jint, jboolean); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: doFinish + * Signature: (JIJI)Z + */ +JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFinish + (JNIEnv *, jobject, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: doReset + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doReset + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater From 80b816fed536861910da189996ae17a91503478e Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 02:19:52 +0100 Subject: [PATCH 17/36] begin trying to implement dictionary compression --- .../daporkchop/lib/compression/Context.java | 21 +++++ .../zlib/src/example/java/ZlibTest.java | 76 +++++++++++++++++-- .../lib/compression/zlib/ZlibDeflater.java | 36 +++++++++ .../lib/compression/zlib/ZlibInflater.java | 36 +++++++++ .../lib/compression/zlib/ZlibProvider.java | 68 ++++++++--------- .../compression/zlib/natives/NativeZlib.java | 6 +- .../zlib/natives/NativeZlibDeflater.java | 25 +++++- .../zlib/natives/NativeZlibInflater.java | 25 +++++- .../main/native/common/NativeZlibDeflater.cpp | 11 +++ .../main/native/common/NativeZlibDeflater.h | 8 ++ .../main/native/common/NativeZlibInflater.cpp | 12 +++ .../main/native/common/NativeZlibInflater.h | 8 ++ 12 files changed, 286 insertions(+), 46 deletions(-) create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index 9801dd19e..f5e32b6b0 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -90,4 +90,25 @@ interface Context> extends Releasable { * @return this context */ I reset(); + + /** + * @return whether or not this implementation allows use of a dictionary + */ + default boolean hasDict() { + return false; + } + + /** + * Sets the dictionary to be used by this context. + *

+ * Must be called immediately after being initialized or reset. + * + * @param dict the new dictionary to use. This method will cause all the bytes in this {@link ByteBuf} to be read. + * @return this context + * @throws UnsupportedOperationException if this context does not allow use of a dictionary + * @see #hasDict() + */ + default I dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { + throw new UnsupportedOperationException(); + } } diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 1bd7f3184..4aef017be 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -28,11 +28,12 @@ * @author DaPorkchop_ */ public class ZlibTest { - private static final int SIZE = 1 << 26; // 64 MiB + private static final int SIZE = 1 << 26; // 64 MiB + private static final int DICT_SIZE = 32768; public static void main(String... args) throws DataFormatException { ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); - for (int i = 0; i < SIZE; i++) { + for (int i = 0; i < SIZE; i++) { original.setByte(i, i & 0xFF); } for (int i = 0; i < 512; i += 8) { @@ -68,8 +69,8 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); - try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { - if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } } @@ -77,6 +78,67 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, uncompressedNative, 0, SIZE); } + { + ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); + + try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { + deflater.dict(original.slice(0, DICT_SIZE)); + deflater.dst(compressedNative); + for (int i = 0; i < (1 << 4); i++) { + ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); + deflater.src(src).update(false); + if (src.isReadable()) { + throw new IllegalStateException(); + } + } + + if (!deflater.finish()) { + throw new IllegalStateException("Couldn't deflate data!"); + } + } + + System.out.printf("original: %d, compressed: %d\n", SIZE, compressedNative.readableBytes()); + + byte[] compressedHeap = new byte[compressedNative.readableBytes()]; + compressedNative.getBytes(0, compressedHeap); + + byte[] uncompressedHeap = new byte[SIZE]; + + if (false) { + Inflater inflater = new Inflater(); + + inflater.setInput(compressedHeap); + int cnt = inflater.inflate(uncompressedHeap); + if (cnt != 0) { + throw new IllegalStateException(String.format("Inflated %d bytes without asking for a dictionary?!?", cnt)); + } else if (!inflater.needsDictionary()) { + throw new IllegalStateException("Not requiring dictionary!"); + } + + byte[] dict = new byte[DICT_SIZE]; + original.getBytes(0, dict); + inflater.setDictionary(dict); + + cnt = inflater.inflate(uncompressedHeap); + if (cnt != SIZE) { + throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); + } + inflater.end(); + + validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); + } + + ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); + try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + throw new IllegalStateException("Couldn't inflate data!"); + } + } + //.dict(original.slice(0, DICT_SIZE)) + + validateEqual(original, uncompressedNative, 0, SIZE); + } + { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); @@ -85,7 +147,7 @@ public static void main(String... args) throws DataFormatException { for (int i = 0; i < (1 << 4); i++) { ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); deflater.src(src).update(true); - if (src.isReadable()) { + if (src.isReadable()) { throw new IllegalStateException(); } } @@ -115,8 +177,8 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); - try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { - if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java new file mode 100644 index 000000000..f515aa4f1 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java @@ -0,0 +1,36 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; + +/** + * Extension of {@link PDeflater} for {@link Zlib}. + * + * @author DaPorkchop_ + */ +public interface ZlibDeflater extends PDeflater { + @Override + default boolean hasDict() { + return true; + } + + @Override + PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java new file mode 100644 index 000000000..17eca9044 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java @@ -0,0 +1,36 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; + +/** + * Extension of {@link PInflater} for {@link Zlib}. + * + * @author DaPorkchop_ + */ +public interface ZlibInflater extends PInflater { + @Override + default boolean hasDict() { + return true; + } + + @Override + PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 5e0fe3534..5350898d9 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -15,8 +15,6 @@ package net.daporkchop.lib.compression.zlib; -import net.daporkchop.lib.compression.PDeflater; -import net.daporkchop.lib.compression.PInflater; /** * A wrapper around a Zlib implementation. @@ -25,108 +23,108 @@ */ public interface ZlibProvider { /** - * Creates a new {@link PDeflater}. + * Creates a new {@link ZlibDeflater}. * - * @return a new {@link PDeflater} + * @return a new {@link ZlibDeflater} */ - default PDeflater deflater() { + default ZlibDeflater deflater() { return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link ZlibDeflater}. * * @param level the {@link Zlib} level to use - * @return a new {@link PDeflater} with the given level + * @return a new {@link ZlibDeflater} with the given level */ - default PDeflater deflater(int level) { + default ZlibDeflater deflater(int level) { return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link ZlibDeflater}. * * @param level the {@link Zlib} level to use * @param strategy the {@link Zlib} strategy to use - * @return a new {@link PDeflater} with the given level and strategy + * @return a new {@link ZlibDeflater} with the given level and strategy */ - default PDeflater deflater(int level, int strategy) { + default ZlibDeflater deflater(int level, int strategy) { return this.deflater(level, strategy, Zlib.MODE_ZLIB); } /** - * Creates a new {@link PDeflater} that will use Gzip headers. + * Creates a new {@link ZlibDeflater} that will use Gzip headers. * - * @return a new {@link PDeflater} + * @return a new {@link ZlibDeflater} */ - default PDeflater deflaterGzip() { + default ZlibDeflater deflaterGzip() { return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); } /** - * Creates a new {@link PDeflater} that will use Gzip headers. + * Creates a new {@link ZlibDeflater} that will use Gzip headers. * * @param level the {@link Zlib} level to use - * @return a new {@link PDeflater} with the given level + * @return a new {@link ZlibDeflater} with the given level */ - default PDeflater deflaterGzip(int level) { + default ZlibDeflater deflaterGzip(int level) { return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); } /** - * Creates a new {@link PDeflater} that will use Gzip headers. + * Creates a new {@link ZlibDeflater} that will use Gzip headers. * * @param level the {@link Zlib} level to use * @param strategy the {@link Zlib} strategy to use - * @return a new {@link PDeflater} with the given level and strategy + * @return a new {@link ZlibDeflater} with the given level and strategy */ - default PDeflater deflaterGzip(int level, int strategy) { + default ZlibDeflater deflaterGzip(int level, int strategy) { return this.deflater(level, strategy, Zlib.MODE_GZIP); } /** - * Creates a new {@link PDeflater}. + * Creates a new {@link ZlibDeflater}. * * @param level the {@link Zlib} level to use. Must be in range {@link Zlib#LEVEL_NONE} to {@link Zlib#LEVEL_BEST} (inclusive), or {@link Zlib#LEVEL_DEFAULT} * @param strategy the {@link Zlib} strategy to use. Must be one of {@link Zlib#STRATEGY_DEFAULT}, {@link Zlib#STRATEGY_FILTERED}, {@link Zlib#STRATEGY_HUFFMAN}, * {@link Zlib#STRATEGY_RLE} or {@link Zlib#STRATEGY_FIXED} * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP} or {@link Zlib#MODE_RAW} - * @return a new {@link PDeflater} with the given level and strategy + * @return a new {@link ZlibDeflater} with the given level and strategy */ - PDeflater deflater(int level, int strategy, int mode); + ZlibDeflater deflater(int level, int strategy, int mode); /** - * Creates a new {@link PInflater}. + * Creates a new {@link ZlibInflater}. * - * @return a new {@link PInflater} + * @return a new {@link ZlibInflater} */ - default PInflater inflater() { + default ZlibInflater inflater() { return this.inflater(Zlib.MODE_ZLIB); } /** - * Creates a new {@link PInflater} that will use Gzip headers. + * Creates a new {@link ZlibInflater} that will use Gzip headers. * - * @return a new {@link PInflater} + * @return a new {@link ZlibInflater} */ - default PInflater inflaterGzip() { + default ZlibInflater inflaterGzip() { return this.inflater(Zlib.MODE_GZIP); } /** - * Creates a new {@link PInflater} that will automatically detect whether the compressed data is in Zlib or Gzip format. + * Creates a new {@link ZlibInflater} that will automatically detect whether the compressed data is in Zlib or Gzip format. * - * @return a new {@link PInflater} + * @return a new {@link ZlibInflater} */ - default PInflater inflaterAuto() { + default ZlibInflater inflaterAuto() { return this.inflater(Zlib.MODE_AUTO); } /** - * Creates a new {@link PInflater}. + * Creates a new {@link ZlibInflater}. * * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP}, {@link Zlib#MODE_RAW} or {@link Zlib#MODE_AUTO} - * @return a new {@link PInflater} + * @return a new {@link ZlibInflater} */ - PInflater inflater(int mode); + ZlibInflater inflater(int mode); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 1709dea4e..c71273186 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -18,6 +18,8 @@ import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.PInflater; import net.daporkchop.lib.compression.zlib.Zlib; +import net.daporkchop.lib.compression.zlib.ZlibDeflater; +import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; import net.daporkchop.lib.natives.NativeCode; @@ -40,12 +42,12 @@ protected ZlibProvider _get() { } @Override - public PDeflater deflater(int level, int strategy, int mode) { + public ZlibDeflater deflater(int level, int strategy, int mode) { return new NativeZlibDeflater(level, strategy, mode); } @Override - public PInflater inflater(int mode) { + public ZlibInflater inflater(int mode) { return new NativeZlibInflater(mode); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 3469a1fe0..da29bacf7 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -22,13 +22,14 @@ import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; /** * @author DaPorkchop_ */ -public final class NativeZlibDeflater extends AbstractReleasable implements PDeflater { +public final class NativeZlibDeflater extends AbstractReleasable implements ZlibDeflater { static native void load(); private static native long allocateCtx(int level, int strategy, int mode); @@ -46,6 +47,7 @@ public final class NativeZlibDeflater extends AbstractReleasable implements PDef private int writtenBytes; private boolean reset; + private boolean started; private boolean finishing; private boolean finished; @@ -89,6 +91,8 @@ private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { throw new ContextFinishingException(); } + this.started = true; + this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), flush); @@ -109,6 +113,8 @@ private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { if (this.finished) { throw new ContextFinishedException(); } + + this.started = true; this.finishing = true; if (this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), @@ -133,6 +139,7 @@ public PDeflater reset() { this.readBytes = 0; this.writtenBytes = 0; + this.started = false; this.finishing = false; this.finished = false; @@ -143,6 +150,22 @@ public PDeflater reset() { private native void doReset(); + @Override + public PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + if (!dict.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } else if (this.started) { + throw new IllegalStateException("Cannot set dictionary after compression has started!"); + } + + this.doDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes()); + dict.skipBytes(dict.readableBytes()); + + return this; + } + + private native void doDict(long dictAddr, int dictSize); + @Override public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java index 64a175d01..a8caa3381 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -23,13 +23,14 @@ import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; /** * @author DaPorkchop_ */ -public final class NativeZlibInflater extends AbstractReleasable implements PInflater { +public final class NativeZlibInflater extends AbstractReleasable implements ZlibInflater { static native void load(); private static native long allocateCtx(int mode); @@ -47,6 +48,7 @@ public final class NativeZlibInflater extends AbstractReleasable implements PInf private int writtenBytes; private boolean reset; + private boolean started; private boolean finishing; private boolean finished; @@ -90,6 +92,8 @@ private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { throw new ContextFinishingException(); } + this.started = true; + this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), flush); @@ -110,6 +114,8 @@ private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { if (this.finished) { throw new ContextFinishedException(); } + + this.started = true; this.finishing = true; if (this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), @@ -134,6 +140,7 @@ public PInflater reset() { this.readBytes = 0; this.writtenBytes = 0; + this.started = false; this.finishing = false; this.finished = false; @@ -144,6 +151,22 @@ public PInflater reset() { private native void doReset(); + @Override + public PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + if (!dict.hasMemoryAddress()) { + throw new InvalidBufferTypeException(true); + } else if (this.started) { + throw new IllegalStateException("Cannot set dictionary after decompression has started!"); + } + + this.doDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes()); + dict.skipBytes(dict.readableBytes()); + + return this; + } + + private native void doDict(long dictAddr, int dictSize); + @Override public PInflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index ba3f6bea9..843fbddd8 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -159,3 +159,14 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp env->SetBooleanField(obj, resetID, true); } + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDict + (JNIEnv* env, jobject obj, jlong dictAddr, jint dictSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + int ret = zng_deflateSetDictionary(stream, (unsigned char*) dictAddr, dictSize); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't set deflater dictionary!" : stream->msg, ret); + return; + } +} diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.h b/compression/zlib/src/main/native/common/NativeZlibDeflater.h index adcc624b2..7718d4327 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.h @@ -66,6 +66,14 @@ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_Nati JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doReset (JNIEnv *, jobject); +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: doDict + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_doDict + (JNIEnv *, jobject, jlong, jint); + #ifdef __cplusplus } #endif diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp index 9a8b12412..8b38f1949 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp @@ -154,3 +154,15 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp env->SetBooleanField(obj, resetID, true); } + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doDict + (JNIEnv* env, jobject obj, jlong dictAddr, jint dictSize) { + zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); + int ret = zng_inflateSetDictionary(stream, (unsigned char*) dictAddr, dictSize); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't set inflater dictionary!" : stream->msg, ret); + return; + } +} + diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.h b/compression/zlib/src/main/native/common/NativeZlibInflater.h index a8feb8102..59ff6afd5 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.h @@ -66,6 +66,14 @@ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_Nati JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doReset (JNIEnv *, jobject); +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater + * Method: doDict + * Signature: (JI)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doDict + (JNIEnv *, jobject, jlong, jint); + #ifdef __cplusplus } #endif From f6b05d4cf6b1be06724be1564b4744ae85226f7e Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 03:07:38 +0100 Subject: [PATCH 18/36] implement dictionary compression --- .../daporkchop/lib/compression/Context.java | 4 +- .../zlib/src/example/java/ZlibTest.java | 86 +++++++++++++------ .../zlib/natives/NativeZlibDeflater.java | 14 ++- .../zlib/natives/NativeZlibInflater.java | 39 ++++++--- .../main/native/common/NativeZlibDeflater.cpp | 2 + .../main/native/common/NativeZlibInflater.cpp | 64 +++++++++++++- .../main/native/common/NativeZlibInflater.h | 20 ++--- 7 files changed, 170 insertions(+), 59 deletions(-) diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index f5e32b6b0..a2cd25446 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -102,8 +102,10 @@ default boolean hasDict() { * Sets the dictionary to be used by this context. *

* Must be called immediately after being initialized or reset. + *

+ * The dictionary will remain referenced until the context is reset. * - * @param dict the new dictionary to use. This method will cause all the bytes in this {@link ByteBuf} to be read. + * @param dict the new dictionary to use. The currently readable region of the buffer will be used as the dictionary. * @return this context * @throws UnsupportedOperationException if this context does not allow use of a dictionary * @see #hasDict() diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 4aef017be..04fa38d39 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -29,14 +29,14 @@ */ public class ZlibTest { private static final int SIZE = 1 << 26; // 64 MiB - private static final int DICT_SIZE = 32768; + private static final int DICT_SIZE = 256 * 8;//32768; public static void main(String... args) throws DataFormatException { ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); for (int i = 0; i < SIZE; i++) { original.setByte(i, i & 0xFF); } - for (int i = 0; i < 512; i += 8) { + for (int i = 0; i < 256; i += 8) { original.setLongLE(i, ThreadLocalRandom.current().nextLong()); } @@ -44,7 +44,7 @@ public static void main(String... args) throws DataFormatException { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { - if (!deflater.fullDeflate(original, compressedNative)) { + if (!deflater.fullDeflate(original.slice(), compressedNative)) { throw new IllegalStateException("Couldn't deflate data!"); } } @@ -73,9 +73,19 @@ public static void main(String... args) throws DataFormatException { if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } + validateEqual(original, uncompressedNative, 0, SIZE); + + uncompressedNative.clear(); + inflater.reset().src(compressedNative.resetReaderIndex()); + for (int i = 0; i < 16; i++) { + ByteBuf dst = uncompressedNative.slice((SIZE >>> 4) * i, SIZE >>> 4).clear(); + inflater.dst(dst).update(false); + if (dst.isWritable()) { + throw new IllegalStateException(); + } + } + validateEqual(original, uncompressedNative, 0, SIZE); } - - validateEqual(original, uncompressedNative, 0, SIZE); } { @@ -83,17 +93,23 @@ public static void main(String... args) throws DataFormatException { try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { deflater.dict(original.slice(0, DICT_SIZE)); - deflater.dst(compressedNative); - for (int i = 0; i < (1 << 4); i++) { - ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); - deflater.src(src).update(false); - if (src.isReadable()) { - throw new IllegalStateException(); + if (false) { + deflater.dst(compressedNative); + for (int i = 0; i < 16; i++) { + ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); + deflater.src(src).update(false); + if (src.isReadable()) { + throw new IllegalStateException(); + } } - } - if (!deflater.finish()) { - throw new IllegalStateException("Couldn't deflate data!"); + if (!deflater.finish()) { + throw new IllegalStateException("Couldn't deflate data!"); + } + } else { + if (!deflater.fullDeflate(original.slice(), compressedNative)) { + throw new IllegalStateException("Couldn't deflate data!"); + } } } @@ -104,7 +120,7 @@ public static void main(String... args) throws DataFormatException { byte[] uncompressedHeap = new byte[SIZE]; - if (false) { + { Inflater inflater = new Inflater(); inflater.setInput(compressedHeap); @@ -124,19 +140,31 @@ public static void main(String... args) throws DataFormatException { throw new IllegalStateException(String.format("Only inflated %d/%d bytes!", cnt, SIZE)); } inflater.end(); - - validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); } + validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); + ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { - if (!inflater.fullInflate(compressedNative, uncompressedNative)) { + if (!inflater.dict(original.slice(0, DICT_SIZE)) + .fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } + validateEqual(original, uncompressedNative, 0, SIZE); + + uncompressedNative.clear(); + inflater.reset() + .dict(original.slice(0, DICT_SIZE)) + .src(compressedNative.resetReaderIndex()); + for (int i = 0; i < 16; i++) { + ByteBuf dst = uncompressedNative.slice((SIZE >>> 4) * i, SIZE >>> 4).clear(); + inflater.dst(dst).update(false); + if (dst.isWritable()) { + throw new IllegalStateException(); + } + } + validateEqual(original, uncompressedNative, 0, SIZE); } - //.dict(original.slice(0, DICT_SIZE)) - - validateEqual(original, uncompressedNative, 0, SIZE); } { @@ -144,7 +172,7 @@ public static void main(String... args) throws DataFormatException { try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { deflater.dst(compressedNative); - for (int i = 0; i < (1 << 4); i++) { + for (int i = 0; i < 16; i++) { ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); deflater.src(src).update(true); if (src.isReadable()) { @@ -181,9 +209,19 @@ public static void main(String... args) throws DataFormatException { if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } + validateEqual(original, uncompressedNative, 0, SIZE); + + uncompressedNative.clear(); + inflater.reset().src(compressedNative.resetReaderIndex()); + for (int i = 0; i < 16; i++) { + ByteBuf dst = uncompressedNative.slice((SIZE >>> 4) * i, SIZE >>> 4).clear(); + inflater.dst(dst).update(false); + if (dst.isWritable()) { + throw new IllegalStateException(); + } + } + validateEqual(original, uncompressedNative, 0, SIZE); } - - validateEqual(original, uncompressedNative, 0, SIZE); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index da29bacf7..521190213 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -42,6 +42,7 @@ public final class NativeZlibDeflater extends AbstractReleasable implements Zlib private ByteBuf src; private ByteBuf dst; + private ByteBuf dict; private int readBytes; private int writtenBytes; @@ -64,6 +65,7 @@ public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws In } this.reset(); //this will do nothing if we're already reset + this.reset = false; if (this.doFullDeflate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { @@ -91,6 +93,7 @@ private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { throw new ContextFinishingException(); } + this.reset = false; this.started = true; this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), @@ -114,6 +117,7 @@ private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { throw new ContextFinishedException(); } + this.reset = false; this.started = true; this.finishing = true; @@ -135,6 +139,10 @@ public PDeflater reset() { if (!this.reset) { this.src = null; this.dst = null; + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } this.readBytes = 0; this.writtenBytes = 0; @@ -156,10 +164,12 @@ public PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { throw new InvalidBufferTypeException(true); } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after compression has started!"); + } else if (this.dict != null) { + throw new IllegalStateException("Dictionary has already been set!"); } - this.doDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes()); - dict.skipBytes(dict.readableBytes()); + this.dict = dict = dict.retainedSlice(); + this.doDict(dict.memoryAddress(), dict.readableBytes()); return this; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java index a8caa3381..4d431c8eb 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -43,6 +43,7 @@ public final class NativeZlibInflater extends AbstractReleasable implements Zlib private ByteBuf src; private ByteBuf dst; + private ByteBuf dict; private int readBytes; private int writtenBytes; @@ -65,9 +66,12 @@ public boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws In } this.reset(); //this will do nothing if we're already reset + this.reset = false; + ByteBuf dict = this.dict; if (this.doFullInflate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + dict == null ? 0L : dict.memoryAddress(), dict == null ? 0 : dict.readableBytes())) { //increase indices if successful src.skipBytes(this.readBytes); dst.writerIndex(dst.writerIndex() + this.writtenBytes); @@ -77,25 +81,27 @@ public boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws In } } - private native boolean doFullInflate(long srcAddr, int srcSize, long dstAddr, int dstSize); + private native boolean doFullInflate(long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); @Override public PInflater update(boolean flush) throws ContextFinishedException, ContextFinishingException { - this.update(this.src, this.dst, flush); + this.update(this.src, this.dst, this.dict, flush); return this; } - private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { + private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict, boolean flush) { if (this.finished) { throw new ContextFinishedException(); } else if (this.finishing) { throw new ContextFinishingException(); } + this.reset = false; this.started = true; this.doUpdate(src.memoryAddress() + src.readerIndex(), src.readableBytes(), dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + dict == null ? 0L : dict.memoryAddress(), dict == null ? 0 : dict.readableBytes(), flush); //increase indices @@ -103,23 +109,25 @@ private void update(@NonNull ByteBuf src, @NonNull ByteBuf dst, boolean flush) { dst.writerIndex(dst.writerIndex() + this.writtenBytes); } - private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize, boolean flush); + private native void doUpdate(long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize, boolean flush); @Override public boolean finish() throws ContextFinishedException { - return this.finish(this.src, this.dst); + return this.finish(this.src, this.dst, this.dict); } - private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { + private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) { if (this.finished) { - throw new ContextFinishedException(); + return true; } + this.reset = false; this.started = true; this.finishing = true; if (this.doFinish(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes())) { + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + dict == null ? 0L : dict.memoryAddress(), dict == null ? 0 : dict.readableBytes())) { //increase indices if successful src.skipBytes(this.readBytes); dst.writerIndex(dst.writerIndex() + this.writtenBytes); @@ -129,13 +137,17 @@ private boolean finish(@NonNull ByteBuf src, @NonNull ByteBuf dst) { } } - private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize); + private native boolean doFinish(long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); @Override public PInflater reset() { if (!this.reset) { this.src = null; this.dst = null; + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } this.readBytes = 0; this.writtenBytes = 0; @@ -157,16 +169,15 @@ public PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { throw new InvalidBufferTypeException(true); } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after decompression has started!"); + } else if (this.dict != null) { + throw new IllegalStateException("Dictionary has already been set!"); } - this.doDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes()); - dict.skipBytes(dict.readableBytes()); + this.dict = dict.retainedSlice(); return this; } - private native void doDict(long dictAddr, int dictSize); - @Override public PInflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index 843fbddd8..b3e66db82 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -114,6 +114,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp int ret = zng_deflate(stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); + return; } env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); @@ -134,6 +135,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ int ret = zng_deflate(stream, Z_FINISH); if (ret != Z_STREAM_END && ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Invalid return value from deflate()!" : stream->msg, ret); + return false; } env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp index 8b38f1949..14a304e24 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp @@ -73,7 +73,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFullInflate - (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); //set stream buffers @@ -84,6 +84,23 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ stream->avail_out = dstSize; int ret = zng_inflate(stream, Z_FINISH); + if (ret == Z_NEED_DICT) { + if (dictAddr) { + //set dictionary + ret = zng_inflateSetDictionary(stream, (unsigned char*) dictAddr, dictSize); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't set inflater dictionary!" : stream->msg, ret); + return false; + } + + //try again + ret = zng_inflate(stream, Z_FINISH); + } else { + throwException(env, "Dictionary needed, but none was given!", ret); + return false; + } + } + if (ret == Z_STREAM_END) { env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); env->SetIntField(obj, writtenBytesID, dstSize - stream->avail_out); @@ -96,7 +113,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ } __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doUpdate - (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jboolean flush) { + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize, jboolean flush) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); //set stream buffers @@ -107,8 +124,29 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp stream->avail_out = dstSize; int ret = zng_inflate(stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); - if (ret != Z_OK) { + if (ret == Z_NEED_DICT) { + if (dictAddr) { + //set dictionary + ret = zng_inflateSetDictionary(stream, (unsigned char*) dictAddr, dictSize); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't set inflater dictionary!" : stream->msg, ret); + return; + } + + //try again + ret = zng_inflate(stream, flush ? Z_SYNC_FLUSH : Z_NO_FLUSH); + } else { + printf("not setting dict\n"); + throwException(env, "Dictionary needed, but none was given!", ret); + return; + } + } + + if (ret == Z_STREAM_END) { + env->SetBooleanField(obj, finishedID, true); + } else if (ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); + return; } env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); @@ -116,7 +154,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFinish - (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize) { zng_stream* stream = (zng_stream*) env->GetLongField(obj, ctxID); //set stream buffers @@ -127,8 +165,26 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ stream->avail_out = dstSize; int ret = zng_inflate(stream, Z_FINISH); + if (ret == Z_NEED_DICT) { + if (dictAddr) { + //set dictionary + ret = zng_inflateSetDictionary(stream, (unsigned char*) dictAddr, dictSize); + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't set inflater dictionary!" : stream->msg, ret); + return false; + } + + //try again + ret = zng_inflate(stream, Z_FINISH); + } else { + throwException(env, "Dictionary needed, but none was given!", ret); + return false; + } + } + if (ret != Z_STREAM_END && ret != Z_OK) { throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); + return false; } env->SetIntField(obj, readBytesID, srcSize - stream->avail_in); diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.h b/compression/zlib/src/main/native/common/NativeZlibInflater.h index 59ff6afd5..9a251fd39 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.h +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.h @@ -37,26 +37,26 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZl /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater * Method: doFullInflate - * Signature: (JIJI)Z + * Signature: (JIJIJI)Z */ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFullInflate - (JNIEnv *, jobject, jlong, jint, jlong, jint); + (JNIEnv *, jobject, jlong, jint, jlong, jint, jlong, jint); /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater * Method: doUpdate - * Signature: (JIJIZ)V + * Signature: (JIJIJIZ)V */ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doUpdate - (JNIEnv *, jobject, jlong, jint, jlong, jint, jboolean); + (JNIEnv *, jobject, jlong, jint, jlong, jint, jlong, jint, jboolean); /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater * Method: doFinish - * Signature: (JIJI)Z + * Signature: (JIJIJI)Z */ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doFinish - (JNIEnv *, jobject, jlong, jint, jlong, jint); + (JNIEnv *, jobject, jlong, jint, jlong, jint, jlong, jint); /* * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater @@ -66,14 +66,6 @@ JNIEXPORT jboolean JNICALL Java_net_daporkchop_lib_compression_zlib_natives_Nati JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doReset (JNIEnv *, jobject); -/* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater - * Method: doDict - * Signature: (JI)V - */ -JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibInflater_doDict - (JNIEnv *, jobject, jlong, jint); - #ifdef __cplusplus } #endif From bf52378e5d994d48b95fa244fcbf3cf00262c619 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 10:13:16 +0100 Subject: [PATCH 19/36] add stub java zlib deflater, and delete all old zlib stuff --- .../daporkchop/lib/compression/PDeflater.java | 22 ++++ .../daporkchop/lib/compression/PInflater.java | 22 ++++ .../zlib/src/example/java/ZlibTest.java | 4 +- .../daporkchop/lib/compression/zlib/Zlib.java | 9 +- .../lib/compression/zlib/java}/JavaZlib.java | 20 +-- .../main/native/common/NativeZlibDeflater.cpp | 8 +- .../main/native/common/NativeZlibInflater.cpp | 2 +- minecraft/build.gradle | 11 +- .../world/format/anvil/AnvilWorldManager.java | 18 +-- .../world/impl/section/DirectSectionImpl.java | 9 +- natives/src/example/java/NativeTests.java | 68 ---------- .../net/daporkchop/lib/natives/PNatives.java | 31 ----- .../lib/natives/zlib/JavaDeflater.java | 119 ----------------- .../lib/natives/zlib/JavaInflater.java | 120 ------------------ .../lib/natives/zlib/NativeDeflater.java | 73 ----------- .../lib/natives/zlib/NativeInflater.java | 73 ----------- .../lib/natives/zlib/NativeZlib.java | 50 -------- .../lib/natives/zlib/PDeflater.java | 113 ----------------- .../lib/natives/zlib/PInflater.java | 107 ---------------- .../net/daporkchop/lib/natives/zlib/Zlib.java | 87 ------------- .../daporkchop/lib/natives/zlib/ZlibMode.java | 44 ------- .../lib/unsafe/util/AbstractReleasable.java | 11 ++ 22 files changed, 99 insertions(+), 922 deletions(-) rename {natives/src/main/java/net/daporkchop/lib/natives/zlib => compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java}/JavaZlib.java (73%) delete mode 100644 natives/src/example/java/NativeTests.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/PNatives.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/PDeflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/PInflater.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java index 6f2712576..fcff5c6a5 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -41,6 +41,28 @@ public interface PDeflater extends Context { */ boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + /** + * Deflates the given source data into the given destination buffer. + *

+ * This will continually grow the destination buffer until there is enough space for deflation to be finished successfully. + *

+ * This method will implicitly reset the context before the actual compression. Any previous state will be ignored. + * + * @param src the {@link ByteBuf} to read data from + * @param dst the {@link ByteBuf} to write data to + */ + default void fullDeflateGrowing(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + this.reset().src(src).dst(dst); + + do { + this.update(false); + } while (src.isReadable() && dst.ensureWritable(8192).isWritable()); + + while (!this.finish()) { + dst.ensureWritable(8192); + } + } + @Override PDeflater update(boolean flush) throws ContextFinishedException, ContextFinishingException; diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java index 9eaca3076..b68b16b74 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -41,6 +41,28 @@ public interface PInflater extends Context { */ boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + /** + * Inflates the given source data into the given destination buffer. + *

+ * This will continually grow the destination buffer until there is enough space for inflation to be finished successfully. + *

+ * This method will implicitly reset the context before the actual decompression. Any previous state will be ignored. + * + * @param src the {@link ByteBuf} to read data from + * @param dst the {@link ByteBuf} to write data to + */ + default void fullInflateGrowing(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + this.reset().src(src).dst(dst); + + do { + this.update(true); + } while (src.isReadable() && dst.ensureWritable(8192).isWritable()); + + if (!this.finish()) { + throw new IllegalStateException(); + } + } + @Override PInflater update(boolean flush) throws ContextFinishedException, ContextFinishingException; diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index 04fa38d39..df65f4e94 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -89,7 +89,7 @@ public static void main(String... args) throws DataFormatException { } { - ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); + ByteBuf compressedNative = Unpooled.directBuffer(16, SIZE >>> 4); try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { deflater.dict(original.slice(0, DICT_SIZE)); @@ -106,6 +106,8 @@ public static void main(String... args) throws DataFormatException { if (!deflater.finish()) { throw new IllegalStateException("Couldn't deflate data!"); } + } else if (true) { + deflater.fullDeflateGrowing(original.slice(), compressedNative); } else { if (!deflater.fullDeflate(original.slice(), compressedNative)) { throw new IllegalStateException("Couldn't deflate data!"); diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java index 15f1b1ca5..f7710e64e 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.compression.zlib; import lombok.experimental.UtilityClass; +import net.daporkchop.lib.compression.zlib.java.JavaZlib; import net.daporkchop.lib.compression.zlib.natives.NativeZlib; import net.daporkchop.lib.natives.NativeCode; @@ -24,18 +25,18 @@ */ @UtilityClass public class Zlib { - public final NativeCode PROVIDER = new NativeCode<>(NativeZlib::new); + public final NativeCode PROVIDER = new NativeCode<>(NativeZlib::new, JavaZlib::new); public final int LEVEL_NONE = 0; //no compression at all public final int LEVEL_FASTEST = 1; //fastest compression, worst ratio public final int LEVEL_BEST = 9; //best ratio, slowest compression public final int LEVEL_DEFAULT = -1; //uses the library default level + public final int STRATEGY_DEFAULT = 0; public final int STRATEGY_FILTERED = 1; public final int STRATEGY_HUFFMAN = 2; - public final int STRATEGY_RLE = 3; - public final int STRATEGY_FIXED = 4; - public final int STRATEGY_DEFAULT = 0; + public final int STRATEGY_RLE = 3; //only supported by native impl + public final int STRATEGY_FIXED = 4; //only supported by native impl public final int MODE_ZLIB = 0; //DEFLATE with zlib headers public final int MODE_GZIP = 1; //DEFLATE with gzip headers diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java similarity index 73% rename from natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java rename to compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java index 4cbe83810..606489836 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java @@ -13,19 +13,19 @@ * */ -package net.daporkchop.lib.natives.zlib; +package net.daporkchop.lib.compression.zlib.java; -import lombok.NonNull; +import net.daporkchop.lib.compression.zlib.ZlibDeflater; +import net.daporkchop.lib.compression.zlib.ZlibInflater; +import net.daporkchop.lib.compression.zlib.ZlibProvider; import net.daporkchop.lib.natives.NativeCode; /** - * Pure Java implementation of {@link Zlib}. - * * @author DaPorkchop_ */ -public final class JavaZlib extends NativeCode.Impl implements Zlib { +public final class JavaZlib extends NativeCode.Impl implements ZlibProvider { @Override - protected Zlib _get() { + protected ZlibProvider _get() { return this; } @@ -35,12 +35,12 @@ protected boolean _available() { } @Override - public PDeflater deflater(int level, @NonNull ZlibMode mode) { - return new JavaDeflater(level, mode); + public ZlibDeflater deflater(int level, int strategy, int mode) { + throw new UnsupportedOperationException(); //TODO } @Override - public PInflater inflater(@NonNull ZlibMode mode) { - return new JavaInflater(mode); + public ZlibInflater inflater(int mode) { + throw new UnsupportedOperationException(); //TODO } } diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index b3e66db82..94a015445 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -67,8 +67,14 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_releaseCtx (JNIEnv* env, jclass cla, jlong ctx) { zng_stream* stream = (zng_stream*) ctx; + int ret = zng_deflateReset(stream); + + if (ret != Z_OK) { + throwException(env, stream->msg == nullptr ? "Couldn't reset deflater!" : stream->msg, ret); + return; + } - int ret = zng_deflateEnd(stream); + ret = zng_deflateEnd(stream); const char* msg = stream->msg; free(stream); diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp index 14a304e24..14d767889 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp @@ -182,7 +182,7 @@ __attribute__((visibility("default"))) jboolean JNICALL Java_net_daporkchop_lib_ } } - if (ret != Z_STREAM_END && ret != Z_OK) { + if (ret != Z_STREAM_END && ret != Z_OK && ret != Z_BUF_ERROR) { throwException(env, stream->msg == nullptr ? "Invalid return value from inflate()!" : stream->msg, ret); return false; } diff --git a/minecraft/build.gradle b/minecraft/build.gradle index dff67b94e..b3e40cf4a 100644 --- a/minecraft/build.gradle +++ b/minecraft/build.gradle @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -13,19 +13,12 @@ * */ -repositories { - maven { - name = "SpigotMC Snapshots" - url = "https://hub.spigotmc.org/nexus/content/repositories/sonatype-nexus-snapshots/" - } -} - dependencies { compile project(":binary") + compile project(":compression:compression-zlib") compile project(":encoding") compile project(":encoding:nbt") compile project(":minecraft:minecraft-text") - compile project(":natives") compile project(":primitive") compile "com.google.guava:guava:$guavaVersion" diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java index 10a9b216a..d2857e16b 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java @@ -28,6 +28,8 @@ import net.daporkchop.lib.common.cache.Cache; import net.daporkchop.lib.common.cache.ThreadCache; import net.daporkchop.lib.common.misc.file.PFiles; +import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.zlib.Zlib; import net.daporkchop.lib.math.vector.i.Vec2i; import net.daporkchop.lib.minecraft.registry.ResourceLocation; import net.daporkchop.lib.minecraft.tileentity.TileEntity; @@ -41,9 +43,6 @@ import net.daporkchop.lib.minecraft.world.impl.section.DirectSectionImpl; import net.daporkchop.lib.minecraft.world.impl.section.HeapSectionImpl; import net.daporkchop.lib.minecraft.world.impl.vanilla.VanillaChunkImpl; -import net.daporkchop.lib.natives.PNatives; -import net.daporkchop.lib.natives.zlib.PInflater; -import net.daporkchop.lib.natives.zlib.Zlib; import net.daporkchop.lib.nbt.NBTInputStream; import net.daporkchop.lib.nbt.alloc.NBTArrayAllocator; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; @@ -68,7 +67,7 @@ public class AnvilWorldManager implements WorldManager { protected static final Cache CHUNK_CACHE = ThreadCache.soft(() -> new HeapSectionImpl(-1, null)); protected static final Pattern REGION_PATTERN = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); - protected static final Cache INFLATER_CACHE = ThreadCache.soft(() -> PNatives.ZLIB.get().inflater(Zlib.ZLIB_MODE_AUTO)); + protected static final Cache INFLATER_CACHE = ThreadCache.soft(() -> Zlib.PROVIDER.get().inflater(Zlib.MODE_AUTO)); protected final AnvilSaveFormat format; protected final File root; @@ -145,7 +144,7 @@ public void loadColumn(Chunk chunk) { PInflater inflater = INFLATER_CACHE.get(); ByteBuf uncompressed = PooledByteBufAllocator.DEFAULT.directBuffer(); try { - inflater.inflate(compressed, uncompressed); + inflater.fullInflateGrowing(compressed, uncompressed); try (NBTInputStream in = new NBTInputStream(DataIn.wrap(uncompressed), this.arrayAllocator)) { rootTag = in.readTag().getCompound("Level"); } @@ -245,26 +244,27 @@ private void loadSection(@NonNull HeapSectionImpl impl, @NonNull CompoundTag tag } private void loadSection(@NonNull DirectSectionImpl impl, @NonNull CompoundTag tag) { - final long addr = impl.memoryAddress(); + final Object ref = impl.memoryRef(); + final long addr = impl.memoryOff(); PUnsafe.copyMemory( tag.getByteArray("Data"), PUnsafe.ARRAY_BYTE_BASE_OFFSET, - null, + ref, addr + DirectSectionImpl.OFFSET_META, DirectSectionImpl.SIZE_NIBBLE_LAYER ); PUnsafe.copyMemory( tag.getByteArray("BlockLight"), PUnsafe.ARRAY_BYTE_BASE_OFFSET, - null, + ref, addr + DirectSectionImpl.OFFSET_BLOCK_LIGHT, DirectSectionImpl.SIZE_NIBBLE_LAYER ); PUnsafe.copyMemory( tag.getByteArray("SkyLight"), PUnsafe.ARRAY_BYTE_BASE_OFFSET, - null, + ref, addr + DirectSectionImpl.OFFSET_SKY_LIGHT, DirectSectionImpl.SIZE_NIBBLE_LAYER ); diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/impl/section/DirectSectionImpl.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/impl/section/DirectSectionImpl.java index 87f051309..231f0cf91 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/impl/section/DirectSectionImpl.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/impl/section/DirectSectionImpl.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -121,7 +121,12 @@ public void release() throws AlreadyReleasedException { } @Override - public long memoryAddress() throws AlreadyReleasedException { + public Object memoryRef() { + return null; + } + + @Override + public long memoryOff() throws AlreadyReleasedException { return this.addr; } diff --git a/natives/src/example/java/NativeTests.java b/natives/src/example/java/NativeTests.java deleted file mode 100644 index 956766140..000000000 --- a/natives/src/example/java/NativeTests.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import net.daporkchop.lib.common.util.PorkUtil; -import net.daporkchop.lib.natives.PNatives; -import net.daporkchop.lib.natives.zlib.PDeflater; -import net.daporkchop.lib.natives.zlib.PInflater; -import net.daporkchop.lib.natives.zlib.Zlib; - -import java.io.IOException; -import java.util.concurrent.ThreadLocalRandom; - -/** - * @author DaPorkchop_ - */ -public class NativeTests { - private static final int SIZE = 67108864; //64 MiB - - public static void main(String... args) throws IOException { - ByteBuf orig = Unpooled.directBuffer(SIZE).writerIndex(SIZE); - for (int i = 0; i < SIZE; i++) { - orig.setByte(i, ThreadLocalRandom.current().nextInt(8)); - } - ByteBuf compressed = Unpooled.directBuffer(SIZE >>> 3, SIZE).clear(); - ByteBuf decompressed = Unpooled.directBuffer(SIZE, SIZE); - - long startTime = System.currentTimeMillis(); - for (int pass = 0; pass < 3; pass++) { - orig.resetReaderIndex(); - compressed.clear(); - decompressed.clear(); - - try (PDeflater deflater = PNatives.ZLIB.get().deflater(Zlib.ZLIB_LEVEL_BEST)) { - System.out.printf("Deflating with %s...\nFinished: %b\n", PorkUtil.className(deflater), deflater.finished()); - deflater.deflate(orig, compressed); - System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", deflater.readBytes(), deflater.writtenBytes(), deflater.finished()); - } - - try (PInflater inflater = PNatives.ZLIB.get().inflater()) { - System.out.printf("Inflating with %s...\nFinished: %b\n", PorkUtil.className(inflater), inflater.finished()); - inflater.inflate(compressed, decompressed); - System.out.printf("Read: %d\nWritten: %d\nFinished: %b\n", inflater.readBytes(), inflater.writtenBytes(), inflater.finished()); - } - - for (int i = 0; i < SIZE; i++) { - if (orig.getByte(i) != decompressed.getByte(i)) { - throw new IllegalStateException(); - } - } - } - - System.out.printf("Took %.2fs!\n", (System.currentTimeMillis() - startTime) / 1000.0d); - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/PNatives.java b/natives/src/main/java/net/daporkchop/lib/natives/PNatives.java deleted file mode 100644 index 98bf44cd4..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/PNatives.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives; - -import lombok.experimental.UtilityClass; -import net.daporkchop.lib.natives.zlib.JavaZlib; -import net.daporkchop.lib.natives.zlib.NativeZlib; -import net.daporkchop.lib.natives.zlib.Zlib; - -/** - * Utility class, has static references to {@link NativeCode} for all implemented features. - * - * @author DaPorkchop_ - */ -@UtilityClass -public class PNatives { - public static final NativeCode ZLIB = new NativeCode<>(NativeZlib::new, JavaZlib::new); -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java deleted file mode 100644 index 3cc76170c..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaDeflater.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.Accessors; -import net.daporkchop.lib.unsafe.PUnsafe; -import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; - -import java.util.zip.Deflater; - -/** - * Implementation of {@link PDeflater} in pure Java. - * - * @author DaPorkchop_ - */ -@Accessors(fluent = true) -public final class JavaDeflater implements PDeflater { - private long inputAddr; - private long outputAddr; - - private final Deflater deflater; - private byte[] inputBuffer = new byte[8192]; - private byte[] outputBuffer = new byte[8192]; - - @Getter - private int readBytes; - @Getter - private int writtenBytes; - - private int inputSize; - private int outputSize; - - public JavaDeflater(int level, @NonNull ZlibMode mode) { - switch (mode) { - case ZLIB: - this.deflater = new Deflater(level, false); - break; - case RAW: - this.deflater = new Deflater(level, true); - break; - case AUTO: - case GZIP: - throw new IllegalArgumentException("Pure Java deflater doesn't support Gzip!"); - default: - throw new IllegalArgumentException("Invalid mode: " + mode); - } - } - - @Override - public void input(long addr, int size) { - this.inputAddr = addr; - this.inputSize = size; - } - - @Override - public void output(long addr, int size) { - this.outputAddr = addr; - this.outputSize = size; - } - - @Override - public void deflate(boolean finish) { - if (finish && this.inputSize <= this.inputBuffer.length) { - this.deflater.finish(); - } - - long prevBytesRead = this.deflater.getBytesRead(); - int inputCount = Math.min(this.inputSize, this.inputBuffer.length); - if (inputCount > 0) { - PUnsafe.copyMemory(null, this.inputAddr, this.inputBuffer, PUnsafe.ARRAY_BYTE_BASE_OFFSET, inputCount); - } - this.deflater.setInput(this.inputBuffer, 0, inputCount); - int written = this.deflater.deflate(this.outputBuffer, 0, Math.min(this.outputSize, this.outputBuffer.length)); - if (written > 0) { - PUnsafe.copyMemory(this.outputBuffer, PUnsafe.ARRAY_BYTE_BASE_OFFSET, null, this.outputAddr, written); - } - this.readBytes = (int) (this.deflater.getBytesRead() - prevBytesRead); - this.writtenBytes = written; - - this.inputAddr += this.readBytes; - this.inputSize -= this.readBytes; - this.outputAddr += written; - this.outputAddr -= written; - } - - @Override - public boolean finished() { - return this.deflater.finished(); - } - - @Override - public void reset() { - this.deflater.reset(); - this.inputAddr = this.outputAddr = 0L; - this.inputSize = this.outputSize = 0; - this.readBytes = this.writtenBytes = 0; - } - - @Override - public void release() throws AlreadyReleasedException { - this.deflater.end(); - this.inputBuffer = this.outputBuffer = null; - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java deleted file mode 100644 index 99d5c04f9..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/JavaInflater.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.Accessors; -import net.daporkchop.lib.unsafe.PUnsafe; -import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; - -import java.util.zip.DataFormatException; -import java.util.zip.Inflater; - -/** - * Implementation of {@link PInflater} in pure Java. - * - * @author DaPorkchop_ - */ -@Accessors(fluent = true) -public final class JavaInflater implements PInflater { - private long inputAddr; - private long outputAddr; - - private final Inflater inflater; - private byte[] inputBuffer = new byte[8192]; - private byte[] outputBuffer = new byte[8192]; - - @Getter - private int readBytes; - @Getter - private int writtenBytes; - - private int inputSize; - private int outputSize; - - public JavaInflater(@NonNull ZlibMode mode) { - switch (mode) { - case ZLIB: - this.inflater = new Inflater(false); - break; - case RAW: - this.inflater = new Inflater(true); - break; - case AUTO: - case GZIP: - throw new IllegalArgumentException("Pure Java inflater doesn't support Gzip!"); - default: - throw new IllegalArgumentException("Invalid mode: " + mode); - } - } - - @Override - public void input(long addr, int size) { - this.inputAddr = addr; - this.inputSize = size; - } - - @Override - public void output(long addr, int size) { - this.outputAddr = addr; - this.outputSize = size; - } - - @Override - public void inflate() { - long prevBytesRead = this.inflater.getBytesRead(); - int inputCount = Math.min(this.inputSize, this.inputBuffer.length); - if (inputCount > 0) { - PUnsafe.copyMemory(null, this.inputAddr, this.inputBuffer, PUnsafe.ARRAY_BYTE_BASE_OFFSET, inputCount); - } - this.inflater.setInput(this.inputBuffer, 0, inputCount); - try { - int written = this.inflater.inflate(this.outputBuffer, 0, Math.min(this.outputSize, this.outputBuffer.length)); - if (written > 0) { - PUnsafe.copyMemory(this.outputBuffer, PUnsafe.ARRAY_BYTE_BASE_OFFSET, null, this.outputAddr, written); - } - this.readBytes = (int) (this.inflater.getBytesRead() - prevBytesRead); - this.writtenBytes = written; - - this.inputAddr += this.readBytes; - this.inputSize -= this.readBytes; - this.outputAddr += written; - this.outputAddr -= written; - } catch (DataFormatException e) { - throw new RuntimeException(e); - } - } - - @Override - public boolean finished() { - return this.inflater.finished(); - } - - @Override - public void reset() { - this.inflater.reset(); - this.inputAddr = this.outputAddr = 0L; - this.inputSize = this.outputSize = 0; - this.readBytes = this.writtenBytes = 0; - } - - @Override - public void release() throws AlreadyReleasedException { - this.inflater.end(); - this.inputBuffer = this.outputBuffer = null; - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java deleted file mode 100644 index 0252dacec..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeDeflater.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.Accessors; -import net.daporkchop.lib.unsafe.PCleaner; -import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; - -/** - * Implementation of {@link PDeflater} using native code. - * - * @author DaPorkchop_ - */ -@Getter -@Accessors(fluent = true) -public final class NativeDeflater implements PDeflater { - static native void load(); - - private static native long init(int level, int mode); - - private static native void end(long ctx); - - @Getter(AccessLevel.NONE) - private final long ctx; - - @Getter(AccessLevel.NONE) - private final PCleaner cleaner; - - private int readBytes; - private int writtenBytes; - - private boolean finished; - - NativeDeflater(int level, @NonNull ZlibMode mode) { - long ctx = this.ctx = init(level, mode.ordinal()); - this.cleaner = PCleaner.cleaner(this, () -> end(ctx)); - } - - @Override - public native void input(long addr, int size); - - @Override - public native void output(long addr, int size); - - @Override - public native void deflate(boolean finish); - - @Override - public native void reset(); - - @Override - public void release() throws AlreadyReleasedException { - if (!this.cleaner.tryClean()) { - throw new AlreadyReleasedException(); - } - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java deleted file mode 100644 index 2eb8b9fcc..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeInflater.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.AccessLevel; -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.Accessors; -import net.daporkchop.lib.unsafe.PCleaner; -import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; - -/** - * Implementation of {@link PInflater} using native code. - * - * @author DaPorkchop_ - */ -@Getter -@Accessors(fluent = true) -public final class NativeInflater implements PInflater { - static native void load(); - - private static native long init(int mode); - - private static native void end(long ctx); - - @Getter(AccessLevel.NONE) - private final long ctx; - - @Getter(AccessLevel.NONE) - private final PCleaner cleaner; - - private int readBytes; - private int writtenBytes; - - private boolean finished; - - NativeInflater(@NonNull ZlibMode mode) { - long ctx = this.ctx = init(mode.ordinal()); - this.cleaner = PCleaner.cleaner(this, () -> end(ctx)); - } - - @Override - public native void input(long addr, int size); - - @Override - public native void output(long addr, int size); - - @Override - public native void inflate(); - - @Override - public native void reset(); - - @Override - public void release() throws AlreadyReleasedException { - if (!this.cleaner.tryClean()) { - throw new AlreadyReleasedException(); - } - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java deleted file mode 100644 index c0ee20af8..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/NativeZlib.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.NonNull; -import net.daporkchop.lib.natives.NativeCode; - -/** - * Native code implementation of {@link Zlib}. - * - * @author DaPorkchop_ - */ -public final class NativeZlib extends NativeCode.NativeImpl implements Zlib { - static { - if (NativeCode.NativeImpl.AVAILABLE) { - NativeCode.loadNativeLibrary("zlib"); - - NativeDeflater.load(); - NativeInflater.load(); - } - } - - @Override - protected Zlib _get() { - return this; - } - - @Override - public PDeflater deflater(int level, @NonNull ZlibMode mode) { - return new NativeDeflater(level, mode); - } - - @Override - public PInflater inflater(@NonNull ZlibMode mode) { - return new NativeInflater(mode); - } -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/PDeflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/PDeflater.java deleted file mode 100644 index 7a160dc04..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/PDeflater.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import io.netty.buffer.ByteBuf; -import lombok.NonNull; -import net.daporkchop.lib.unsafe.capability.Releasable; - -/** - * Used for creating a Zlib-compressed data stream. - * - * @author DaPorkchop_ - */ -public interface PDeflater extends Releasable { - /** - * Does the entire compression process in one go. - *

- * This method ignores (and overwrites) any values set by {@link #input(long, int)} or {@link #output(long, int)}. - *

- * Calling this method will update the values of {@link #readBytes()} and {@link #writtenBytes()}, however the values will (probably) be garbage. - *

- * Attempting to use this method in combination with any of the following methods between resets may result in undefined behavior: - * - {@link #deflate(boolean)} - * - {@link #finished()} - * - * @param input a {@link ByteBuf} containing the input data to be compressed - * @param output a {@link ByteBuf} that the output data will be written to - */ - default void deflate(@NonNull ByteBuf input, @NonNull ByteBuf output) { - if (!input.isReadable()) { - throw new IllegalStateException("Input not readable!"); - } - this.input(input.memoryAddress() + input.readerIndex(), input.readableBytes()); //we don't need to set this in a loop - - do { - //System.out.printf("readable: %d, writable: %d\n", input.readableBytes(), output.writableBytes()); - this.output(output.memoryAddress() + output.writerIndex(), output.writableBytes()); - - this.deflate(true); - - input.skipBytes(this.readBytes()); - output.writerIndex(output.writerIndex() + this.writtenBytes()); - } while (!this.finished() && output.ensureWritable(8192).isWritable()); - - //System.out.printf("Done! readable: %d, writable: %d\n", input.readableBytes(), output.writableBytes()); - } - - /** - * Sets the input (source) data to be compressed. - * - * @param addr the base address of the data to be compressed - * @param size the size of the data to be compressed - */ - void input(long addr, int size); - - /** - * Sets the output (destination) where compressed data will be written to. - * - * @param addr the base address of the destination - * @param size the maximum size of the output data - */ - void output(long addr, int size); - - /** - * Does the actual data compression, blocking until either the input buffer is empty or the output buffer is full. - *

- * This method requires {@link #input(long, int)} and {@link #output(long, int)} to be set. - *

- * Calling this method will update the values of {@link #readBytes()} and {@link #writtenBytes()}. - *

- * Attempting to use this method in combination with {@link #deflate(ByteBuf, ByteBuf)} between resets may result in undefined behavior. - * - * @param finish if {@code true}, this will attempt to read all bytes from the input buffer and then finish the compression process. Even if this - * parameter is set, {@link #finished()} will not be set to {@code true} if the output buffer fills up. - */ - void deflate(boolean finish); - - /** - * @return whether or not the current deflation process is complete - */ - boolean finished(); - - /** - * @return the number of bytes read from the input buffer during the last invocation of {@link #deflate(boolean)} - */ - int readBytes(); - - /** - * @return the number of bytes written to the output buffer during the last invocation of {@link #deflate(boolean)} - */ - int writtenBytes(); - - /** - * Resets this {@link PDeflater} instance. - *

- * This must be called after the compression process is completed if this instance should be re-used (but doesn't have to be, it can also be immediately - * released or left to be garbage collected). - */ - void reset(); -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/PInflater.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/PInflater.java deleted file mode 100644 index dc9d61ee8..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/PInflater.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import io.netty.buffer.ByteBuf; -import lombok.NonNull; -import net.daporkchop.lib.unsafe.capability.Releasable; - -/** - * Used for inflating a Zlib-compressed data stream. - * - * @author DaPorkchop_ - */ -public interface PInflater extends Releasable { - /** - * Does the entire decompression process in one go. - *

- * This method ignores (and overwrites) any values set by {@link #input(long, int)} or {@link #output(long, int)}. - *

- * Calling this method will update the values of {@link #readBytes()} and {@link #writtenBytes()}, however the values will (probably) be garbage. - *

- * Attempting to use this method in combination with any of the following methods between resets may result in undefined behavior: - * - {@link #inflate()} - * - {@link #finished()} - * - * @param input a {@link ByteBuf} containing the input data to be decompressed - * @param output a {@link ByteBuf} that the output data will be written to - */ - default void inflate(@NonNull ByteBuf input, @NonNull ByteBuf output) { - if (!input.isReadable()) { - throw new IllegalStateException("Input not readable!"); - } - this.input(input.memoryAddress() + input.readerIndex(), input.readableBytes()); //we don't need to set this in a loop - - do { - this.output(output.memoryAddress() + output.writerIndex(), output.writableBytes()); - - this.inflate(); - - input.skipBytes(this.readBytes()); - output.writerIndex(output.writerIndex() + this.writtenBytes()); - } while (!this.finished() && output.ensureWritable(8192).isWritable()); - } - - /** - * Sets the input (source) data to be decompressed. - * - * @param addr the base address of the data to be decompressed - * @param size the size of the data to be decompressed - */ - void input(long addr, int size); - - /** - * Sets the output (destination) where decompressed data will be written to. - * - * @param addr the base address of the destination - * @param size the maximum size of the output data - */ - void output(long addr, int size); - - /** - * Does the actual data decompression, blocking until either the input buffer is empty or the output buffer is full. - *

- * This method requires {@link #input(long, int)} and {@link #output(long, int)} to be set. - *

- * Calling this method will update the values of {@link #readBytes()} and {@link #writtenBytes()}. - *

- * Attempting to use this method in combination with {@link #inflate(ByteBuf, ByteBuf)} between resets may result in undefined behavior. - */ - void inflate(); - - /** - * @return whether or not the current deflation process is complete - */ - boolean finished(); - - /** - * @return the number of bytes read from the input buffer during the last invocation of {@link #inflate()} - */ - int readBytes(); - - /** - * @return the number of bytes written to the output buffer during the last invocation of {@link #inflate()} - */ - int writtenBytes(); - - /** - * Resets this {@link PInflater} instance. - *

- * This must be called after the decompression process is completed if this instance should be re-used (but doesn't have to be, it can also be immediately - * released or left to be garbage collected). - */ - void reset(); -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java deleted file mode 100644 index 8ce408554..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/Zlib.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -import lombok.NonNull; - -/** - * Base representation of the Zlib algorithm. - * - * @author DaPorkchop_ - */ -public interface Zlib { - /** - * No compression will be applied. - */ - int ZLIB_LEVEL_NONE = 0; - - /** - * Poorest compression ratio in exchange for fastest speeds. - */ - int ZLIB_LEVEL_FASTEST = 1; - - /** - * Best compression ratio in exchange for lowest speeds. - */ - int ZLIB_LEVEL_BEST = 9; - - /** - * Allows the zlib library to choose a default compression level. - */ - int ZLIB_LEVEL_DEFAULT = -1; - - /** - * Creates a new {@link PDeflater}. - *

- * The returned {@link PDeflater} will use {@link ZlibMode#ZLIB}. - * - * @param level the Deflate compression level to use. Must be in range 0-9 (inclusive), or {@link #ZLIB_LEVEL_DEFAULT} to use the library default - * @return a new {@link PDeflater} instance - * @see #deflater(int, ZlibMode) - */ - default PDeflater deflater(int level) { - return this.deflater(level, ZlibMode.ZLIB); - } - - /** - * Creates a new {@link PDeflater}. - * - * @param level the Deflate compression level to use. Must be in range 0-9 (inclusive), or {@link #ZLIB_LEVEL_DEFAULT} to use the library default - * @param mode the zlib wrapping mode to use - * @return a new {@link PDeflater} instance - */ - PDeflater deflater(int level, @NonNull ZlibMode mode); - - /** - * Creates a new {@link PInflater}. - *

- * The returned {@link PInflater} will use {@link ZlibMode#ZLIB}. - * - * @return a new {@link PInflater} instance - * @see #inflater(ZlibMode) - */ - default PInflater inflater() { - return this.inflater(ZlibMode.ZLIB); - } - - /** - * Creates a new {@link PDeflater}. - * - * @param mode the zlib wrapping mode to use - * @return a new {@link PInflater} instance - */ - PInflater inflater(@NonNull ZlibMode mode); -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java b/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java deleted file mode 100644 index e276bf131..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/zlib/ZlibMode.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.zlib; - -/** - * The different modes supported by Zlib. - * - * @author DaPorkchop_ - */ -public enum ZlibMode { - /** - * Zlib wrapping mode, uses a 6-byte header with an Adler32 checksum. - *

- * This is the default mode. - */ - ZLIB, - /** - * Gzip wrapping mode, uses an (at least) 18-byte header with a CRC32 checksum. - */ - GZIP, - /** - * Only for use by {@link PInflater}, automatically detects whether the input data is in the Zlib or Gzip format. - *

- * Note that this doesn't work for data encoded in the {@link #ZLIB_MODE_RAW} format. - */ - AUTO, - /** - * "Raw" Deflate mode, no wrapping is applied to the compressed data. - */ - RAW; -} diff --git a/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java b/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java index d4dbe6bb0..aa96ba65e 100644 --- a/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java +++ b/unsafe/src/main/java/net/daporkchop/lib/unsafe/util/AbstractReleasable.java @@ -44,4 +44,15 @@ public void release() throws AlreadyReleasedException { * Will only be called once. */ protected abstract void doRelease(); + + /** + * Asserts that this instance has not been released. + * + * @throws AlreadyReleasedException if this instance has been released + */ + protected final void assertNotReleased() throws AlreadyReleasedException { + if (this.released != 0) { + throw new AlreadyReleasedException(); + } + } } From f3666f1697b316bc49f4b6e7e06d181264d38b34 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 10:21:19 +0100 Subject: [PATCH 20/36] remove old compression things from `:encoding` --- encoding/build.gradle | 5 +- .../java/net/daporkchop/lib/nbt/NBTIO.java | 11 +- .../daporkchop/lib/nbt/NBTInputStream.java | 30 +-- .../daporkchop/lib/nbt/NBTOutputStream.java | 16 +- encoding/nbt/src/test/java/NBTTest.java | 11 +- .../lib/encoding/compression/Compression.java | 254 ------------------ .../compression/CompressionHelper.java | 186 ------------- .../test/java/encoding/CompressionTest.java | 67 ----- .../world/format/anvil/AnvilSaveFormat.java | 10 +- .../format/anvil/region/RegionConstants.java | 59 +--- .../world/format/anvil/region/RegionFile.java | 88 ------ 11 files changed, 24 insertions(+), 713 deletions(-) delete mode 100644 encoding/src/main/java/net/daporkchop/lib/encoding/compression/Compression.java delete mode 100644 encoding/src/main/java/net/daporkchop/lib/encoding/compression/CompressionHelper.java delete mode 100644 encoding/src/test/java/encoding/CompressionTest.java diff --git a/encoding/build.gradle b/encoding/build.gradle index 9f1c551df..030ac658a 100644 --- a/encoding/build.gradle +++ b/encoding/build.gradle @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -16,7 +16,4 @@ dependencies { compile project(":binary") compile project(":math") - - compile "org.tukaani:xz:$xzVersion" - compile "org.apache.commons:commons-compress:$apacheCommonsCompressVersion" } diff --git a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTIO.java b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTIO.java index 916d4aaa9..a81c99311 100644 --- a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTIO.java +++ b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTIO.java @@ -17,7 +17,6 @@ import lombok.NonNull; import lombok.experimental.UtilityClass; -import net.daporkchop.lib.encoding.compression.Compression; import net.daporkchop.lib.nbt.tag.TagRegistry; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; @@ -29,6 +28,8 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.zip.GZIPInputStream; +import java.util.zip.GZIPOutputStream; /** * Helper class for reading and writing NBT tags. @@ -76,7 +77,7 @@ public CompoundTag readGzipCompressed(@NonNull InputStream inputStream) throws I } public CompoundTag readGzipCompressed(@NonNull InputStream inputStream, @NonNull TagRegistry registry) throws IOException { - return new NBTInputStream(inputStream, Compression.GZIP_NORMAL).readTag(registry); + return new NBTInputStream(new GZIPInputStream(inputStream)).readTag(registry); } public CompoundTag readGzipCompressed(@NonNull File file) throws IOException { @@ -85,7 +86,7 @@ public CompoundTag readGzipCompressed(@NonNull File file) throws IOException { public CompoundTag readGzipCompressed(@NonNull File file, @NonNull TagRegistry registry) throws IOException { verifyFileExists(file, false); - try (NBTInputStream in = new NBTInputStream(new BufferedInputStream(new FileInputStream(file)), Compression.GZIP_NORMAL)) { + try (NBTInputStream in = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) { return in.readTag(registry); } } @@ -115,7 +116,7 @@ public void writeGzipCompressed(@NonNull OutputStream out, @NonNull CompoundTag } public void writeGzipCompressed(@NonNull OutputStream out, @NonNull CompoundTag tag, @NonNull TagRegistry registry) throws IOException { - NBTOutputStream nbtOut = new NBTOutputStream(out, Compression.GZIP_NORMAL); + NBTOutputStream nbtOut = new NBTOutputStream(new GZIPOutputStream(out)); nbtOut.writeTag(tag, registry); } @@ -125,7 +126,7 @@ public void writeGzipCompressed(@NonNull File file, @NonNull CompoundTag tag) th public void writeGzipCompressed(@NonNull File file, @NonNull CompoundTag tag, @NonNull TagRegistry registry) throws IOException { verifyFileExists(file, true); - try (NBTOutputStream out = new NBTOutputStream(new BufferedOutputStream(new FileOutputStream(file)), Compression.GZIP_NORMAL)) { + try (NBTOutputStream out = new NBTOutputStream(new GZIPOutputStream(new FileOutputStream(file)))) { out.writeTag(tag, registry); } } diff --git a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java index d8785e88b..bf9a02a54 100644 --- a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java +++ b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -19,18 +19,14 @@ import lombok.NonNull; import lombok.experimental.Accessors; import net.daporkchop.lib.binary.stream.DataIn; -import net.daporkchop.lib.encoding.compression.Compression; -import net.daporkchop.lib.encoding.compression.CompressionHelper; import net.daporkchop.lib.nbt.alloc.DefaultNBTArrayAllocator; import net.daporkchop.lib.nbt.alloc.NBTArrayAllocator; -import net.daporkchop.lib.nbt.tag.Tag; import net.daporkchop.lib.nbt.tag.TagRegistry; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; -import java.util.Stack; import java.util.function.Function; /** @@ -47,35 +43,19 @@ public final class NBTInputStream extends DataIn { protected final NBTArrayAllocator alloc; public NBTInputStream(@NonNull InputStream in) throws IOException { - this(in, Compression.NONE, TagRegistry.NOTCHIAN, DefaultNBTArrayAllocator.INSTANCE); - } - - public NBTInputStream(@NonNull InputStream in, @NonNull CompressionHelper compression) throws IOException { - this(in, compression, TagRegistry.NOTCHIAN, DefaultNBTArrayAllocator.INSTANCE); + this(in, TagRegistry.NOTCHIAN, DefaultNBTArrayAllocator.INSTANCE); } public NBTInputStream(@NonNull InputStream in, @NonNull TagRegistry registry) throws IOException { - this(in, Compression.NONE, registry, DefaultNBTArrayAllocator.INSTANCE); - } - - public NBTInputStream(@NonNull InputStream in, @NonNull CompressionHelper compression, @NonNull TagRegistry registry) throws IOException { - this(in, compression, registry, DefaultNBTArrayAllocator.INSTANCE); + this(in, registry, DefaultNBTArrayAllocator.INSTANCE); } public NBTInputStream(@NonNull InputStream in, @NonNull NBTArrayAllocator alloc) throws IOException { - this(in, Compression.NONE, TagRegistry.NOTCHIAN, alloc); - } - - public NBTInputStream(@NonNull InputStream in, @NonNull CompressionHelper compression, @NonNull NBTArrayAllocator alloc) throws IOException { - this(in, compression, TagRegistry.NOTCHIAN, alloc); + this(in, TagRegistry.NOTCHIAN, alloc); } public NBTInputStream(@NonNull InputStream in, @NonNull TagRegistry registry, @NonNull NBTArrayAllocator alloc) throws IOException { - this(in, Compression.NONE, registry, alloc); - } - - public NBTInputStream(@NonNull InputStream in, @NonNull CompressionHelper compression, @NonNull TagRegistry registry, @NonNull NBTArrayAllocator alloc) throws IOException { - this.in = DataIn.wrap(compression.inflate(in)); + this.in = DataIn.wrap(in); this.defaultRegistry = registry; this.alloc = alloc; } diff --git a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTOutputStream.java b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTOutputStream.java index 57dfa9558..f8d007753 100644 --- a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTOutputStream.java +++ b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTOutputStream.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -17,8 +17,6 @@ import lombok.NonNull; import net.daporkchop.lib.binary.stream.DataOut; -import net.daporkchop.lib.encoding.compression.Compression; -import net.daporkchop.lib.encoding.compression.CompressionHelper; import net.daporkchop.lib.nbt.tag.TagRegistry; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; @@ -34,19 +32,11 @@ public final class NBTOutputStream extends DataOut { private final TagRegistry defaultRegistry; public NBTOutputStream(@NonNull OutputStream out) throws IOException { - this(out, Compression.NONE, TagRegistry.NOTCHIAN); - } - - public NBTOutputStream(@NonNull OutputStream out, @NonNull CompressionHelper compression) throws IOException { - this(out, compression, TagRegistry.NOTCHIAN); + this(out, TagRegistry.NOTCHIAN); } public NBTOutputStream(@NonNull OutputStream out, @NonNull TagRegistry registry) throws IOException { - this(out, Compression.NONE, registry); - } - - public NBTOutputStream(@NonNull OutputStream out, @NonNull CompressionHelper compression, @NonNull TagRegistry registry) throws IOException { - this.out = DataOut.wrap(compression.deflate(out)); + this.out = DataOut.wrap(out); this.defaultRegistry = registry; } diff --git a/encoding/nbt/src/test/java/NBTTest.java b/encoding/nbt/src/test/java/NBTTest.java index e1d615841..27a4c46f1 100644 --- a/encoding/nbt/src/test/java/NBTTest.java +++ b/encoding/nbt/src/test/java/NBTTest.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -14,7 +14,6 @@ */ import lombok.NonNull; -import net.daporkchop.lib.encoding.compression.Compression; import net.daporkchop.lib.nbt.NBTInputStream; import net.daporkchop.lib.nbt.NBTOutputStream; import net.daporkchop.lib.nbt.tag.Tag; @@ -30,6 +29,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.util.zip.GZIPInputStream; /** * @author DaPorkchop_ @@ -60,9 +60,8 @@ public static String space(int count) { @Test public void testWriting() throws IOException { byte[] original_uncompressed; - try (InputStream is = NBTTest.class.getResourceAsStream("bigtest.nbt")) { - byte[] b = IOUtils.toByteArray(is); - original_uncompressed = Compression.GZIP_NORMAL.inflate(b); + try (InputStream is = new GZIPInputStream(NBTTest.class.getResourceAsStream("bigtest.nbt"))) { + original_uncompressed = IOUtils.toByteArray(is); } CompoundTag tag; try (NBTInputStream in = new NBTInputStream(new ByteArrayInputStream(original_uncompressed))) { @@ -103,7 +102,7 @@ public void testHelloWorld() throws IOException { @Test public void testBig() throws IOException { - try (NBTInputStream in = new NBTInputStream(NBTTest.class.getResourceAsStream("bigtest.nbt"), Compression.GZIP_NORMAL)) { + try (NBTInputStream in = new NBTInputStream(new GZIPInputStream(NBTTest.class.getResourceAsStream("bigtest.nbt")))) { CompoundTag tag = in.readTag(); printTagRecursive(tag, 0); } diff --git a/encoding/src/main/java/net/daporkchop/lib/encoding/compression/Compression.java b/encoding/src/main/java/net/daporkchop/lib/encoding/compression/Compression.java deleted file mode 100644 index c65afdd61..000000000 --- a/encoding/src/main/java/net/daporkchop/lib/encoding/compression/Compression.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.encoding.compression; - -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.experimental.UtilityClass; -import org.apache.commons.compress.compressors.bzip2.BZip2CompressorInputStream; -import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream; -import org.apache.commons.compress.compressors.deflate.DeflateCompressorInputStream; -import org.apache.commons.compress.compressors.deflate.DeflateCompressorOutputStream; -import org.apache.commons.compress.compressors.deflate.DeflateParameters; -import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream; -import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream; -import org.apache.commons.compress.compressors.gzip.GzipParameters; -import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorInputStream; -import org.apache.commons.compress.compressors.lz4.BlockLZ4CompressorOutputStream; -import org.apache.commons.compress.compressors.lz4.FramedLZ4CompressorOutputStream; -import org.tukaani.xz.LZMA2Options; -import org.tukaani.xz.LZMAInputStream; -import org.tukaani.xz.LZMAOutputStream; -import org.tukaani.xz.XZInputStream; -import org.tukaani.xz.XZOutputStream; - -import java.io.IOException; -import java.io.OutputStream; -import java.lang.reflect.Field; - -/** - * Contains static references to a number of standard compression algorithms. - * - * @author DaPorkchop_ - */ -//TODO: strip some dependencies off of this -@UtilityClass -public class Compression { - public static final CompressionHelper NONE = CompressionHelper.builder("Uncompressed") - .setInputStreamWrapperSimple(in -> in) - .setOutputStreamWrapperSimple(out -> out) - .build(); - - public static final CompressionHelper GZIP_LOW = CompressionHelper.builder("GZip", "Low") - .setParams(new GzipParameters() { - { - this.setCompressionLevel(0); - } - }) - .setInputStreamWrapperSimple(GzipCompressorInputStream::new) - .setOutputStreamWrapper(GzipCompressorOutputStream::new) - .build(); - - public static final CompressionHelper GZIP_NORMAL = CompressionHelper.builder("GZip", "Normal") - .setParams(new GzipParameters() { - { - this.setCompressionLevel(4); - } - }) - .setInputStreamWrapperSimple(GzipCompressorInputStream::new) - .setOutputStreamWrapper(GzipCompressorOutputStream::new) - .build(); - - public static final CompressionHelper GZIP_HIGH = CompressionHelper.builder("GZip", "High") - .setParams(new GzipParameters() { - { - this.setCompressionLevel(8); - } - }) - .setInputStreamWrapperSimple(GzipCompressorInputStream::new) - .setOutputStreamWrapper(GzipCompressorOutputStream::new) - .build(); - - public static final CompressionHelper BZIP2_LOW = CompressionHelper.builder("BZip2", "Low") - .setParams(1) - .setInputStreamWrapperSimple(BZip2CompressorInputStream::new) - .setOutputStreamWrapper(BZip2CompressorOutputStream::new) - .build(); - - public static final CompressionHelper BZIP2_NORMAL = CompressionHelper.builder("BZip2", "Normal") - .setParams(1) - .setInputStreamWrapperSimple(BZip2CompressorInputStream::new) - .setOutputStreamWrapper(BZip2CompressorOutputStream::new) - .build(); - - public static final CompressionHelper BZIP2_HIGH = CompressionHelper.builder("BZip2", "High") - .setParams(1) - .setInputStreamWrapperSimple(BZip2CompressorInputStream::new) - .setOutputStreamWrapper(BZip2CompressorOutputStream::new) - .build(); - - public static final CompressionHelper DEFLATE_LOW = CompressionHelper.builder("Deflate", "Low") - .setParams(new DeflateParameters() { - { - this.setCompressionLevel(0); - } - }) - .setInputStreamWrapper(DeflateCompressorInputStream::new) - .setOutputStreamWrapper(DeflateCompressorOutputStream::new) - .build(); - - public static final CompressionHelper DEFLATE_NORMAL = CompressionHelper.builder("Deflate", "Normal") - .setParams(new DeflateParameters() { - { - this.setCompressionLevel(4); - } - }) - .setInputStreamWrapper(DeflateCompressorInputStream::new) - .setOutputStreamWrapper(DeflateCompressorOutputStream::new) - .build(); - - public static final CompressionHelper DEFLATE_HIGH = CompressionHelper.builder("Deflate", "High") - .setParams(new DeflateParameters() { - { - this.setCompressionLevel(8); - } - }) - .setInputStreamWrapper(DeflateCompressorInputStream::new) - .setOutputStreamWrapper(DeflateCompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZ4_BLOCK = CompressionHelper.builder("LZ4", "Block") - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZ4_FRAMED_64KB = CompressionHelper.builder("LZ4", "Framed - 64KB") - .setParams(new FramedLZ4CompressorOutputStream.Parameters(FramedLZ4CompressorOutputStream.BlockSize.K64)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZ4_FRAMED_256KB = CompressionHelper.builder("LZ4", "Framed - 256KB") - .setParams(new FramedLZ4CompressorOutputStream.Parameters(FramedLZ4CompressorOutputStream.BlockSize.K256)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZ4_FRAMED_1MB = CompressionHelper.builder("LZ4", "Framed - 1MB") - .setParams(new FramedLZ4CompressorOutputStream.Parameters(FramedLZ4CompressorOutputStream.BlockSize.M1)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZ4_FRAMED_4MB = CompressionHelper.builder("LZ4", "Framed - 4MB") - .setParams(new FramedLZ4CompressorOutputStream.Parameters(FramedLZ4CompressorOutputStream.BlockSize.M4)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - /*public static final CompressionHelper LZMA2_LOW = CompressionHelper.builder("LZMA2", "Low") - .setParamsFunc(() -> new LZMA2Options(0)) - .setInputStreamWrapperSimple(in -> new LZMA2InputStream(in, -1)) - .setOutputStreamWrapper(LZMA2OutputStream::new) - .build(); - - public static final CompressionHelper LZMA2_NORMAL = CompressionHelper.builder("LZMA2", "Normal") - .setParamsFunc(() -> new LZMA2Options(0)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build(); - - public static final CompressionHelper LZMA2_HIGH = CompressionHelper.builder("LZMA2", "High") - .setParamsFunc(() -> new LZMA2Options(0)) - .setInputStreamWrapperSimple(BlockLZ4CompressorInputStream::new) - .setOutputStreamWrapperSimple(BlockLZ4CompressorOutputStream::new) - .build();*/ - - public static final CompressionHelper LZMA_LOW = CompressionHelper.builder("LZMA", "Low") - .setParamsFunc(() -> new LZMA2Options(0)) - .setInputStreamWrapperSimple(LZMAInputStream::new) - .setOutputStreamWrapper((out, params) -> new LZMAWrapperOut(new LZMAOutputStream(out, params, -1L))) - .build(); - - public static final CompressionHelper LZMA_NORMAL = CompressionHelper.builder("LZMA", "Normal") - .setParamsFunc(() -> new LZMA2Options(6)) - .setInputStreamWrapperSimple(LZMAInputStream::new) - .setOutputStreamWrapper((out, params) -> new LZMAWrapperOut(new LZMAOutputStream(out, params, -1L))) - .build(); - - public static final CompressionHelper LZMA_HIGH = CompressionHelper.builder("LZMA", "High") - .setParamsFunc(() -> new LZMA2Options(9)) - .setInputStreamWrapperSimple(LZMAInputStream::new) - .setOutputStreamWrapper((out, params) -> new LZMAWrapperOut(new LZMAOutputStream(out, params, -1L))) - .build(); - - public static final CompressionHelper XZ_LOW = CompressionHelper.builder("XZ", "Low") - .setParamsFunc(() -> new LZMA2Options(0)) - .setInputStreamWrapperSimple(XZInputStream::new) - .setOutputStreamWrapper(XZOutputStream::new) - .build(); - - public static final CompressionHelper XZ_NORMAL = CompressionHelper.builder("XZ", "Normal") - .setParamsFunc(() -> new LZMA2Options(6)) - .setInputStreamWrapperSimple(XZInputStream::new) - .setOutputStreamWrapper(XZOutputStream::new) - .build(); - - public static final CompressionHelper XZ_HIGH = CompressionHelper.builder("XZ", "High") - .setParamsFunc(() -> new LZMA2Options(9)) - .setInputStreamWrapperSimple(XZInputStream::new) - .setOutputStreamWrapper(XZOutputStream::new) - .build(); - - static { - try { - for (Field field : Compression.class.getDeclaredFields()) { - if (field.getType() == CompressionHelper.class) { - //System.out.printf("Found compression algorithm: %s\n", field.getName()); - CompressionHelper.registerCompressionType(field.getName(), (CompressionHelper) field.get(null)); - } - } - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - @RequiredArgsConstructor - private static class LZMAWrapperOut extends OutputStream { - @NonNull - private final LZMAOutputStream out; - - @Override - public void write(int b) throws IOException { - this.out.write(b); - } - - /*@Override - public void write(byte[] b) throws IOException { - this.out.write(b); - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - this.out.write(b, off, len); - }*/ - - @Override - public void close() throws IOException { - this.out.close(); - } - } -} diff --git a/encoding/src/main/java/net/daporkchop/lib/encoding/compression/CompressionHelper.java b/encoding/src/main/java/net/daporkchop/lib/encoding/compression/CompressionHelper.java deleted file mode 100644 index 3dd8d8dc2..000000000 --- a/encoding/src/main/java/net/daporkchop/lib/encoding/compression/CompressionHelper.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.encoding.compression; - -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NonNull; -import lombok.RequiredArgsConstructor; -import lombok.Setter; -import lombok.experimental.Accessors; -import net.daporkchop.lib.common.function.ThrowingSupplier; -import net.daporkchop.lib.common.function.io.IOBiFunction; -import net.daporkchop.lib.common.function.io.IOFunction; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Collections; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.IdentityHashMap; -import java.util.Map; -import java.util.function.BiConsumer; -import java.util.stream.Stream; - -/** - * Utility to store initialization functions for various compression algorithms - * - * @author DaPorkchop_ - */ -@AllArgsConstructor(access = AccessLevel.PRIVATE) -public class CompressionHelper { - static final Map nameLookup = Collections.synchronizedMap(new Hashtable<>()); - static final Map reverseNameLookup = Collections.synchronizedMap(new IdentityHashMap<>()); - - static boolean registerCompressionType(@NonNull String name, @NonNull CompressionHelper helper) { - return nameLookup.putIfAbsent(name, helper) == null && reverseNameLookup.put(helper, name) == null; - } - - public static CompressionHelper forName(@NonNull String name) { - return nameLookup.get(name); - } - - public static String getName(@NonNull CompressionHelper name) { - return reverseNameLookup.get(name); - } - - public static void forAllRegisteredAlgs(@NonNull BiConsumer consumer) { - forAllRegisteredAlgs(consumer, false); - } - - public static void forAllRegisteredAlgs(@NonNull BiConsumer consumer, boolean parallel) { - Stream> stream = nameLookup.entrySet().stream(); - if (parallel) { - stream = stream.parallel(); - } else { - stream = stream.sorted(Comparator.comparing(Map.Entry::getKey, Comparator.naturalOrder())); - } - stream.forEach(e -> consumer.accept(e.getKey(), e.getValue())); - } - - public static Builder builder(@NonNull String name) { - return new Builder<>(name); - } - - public static Builder builder(@NonNull String name, @NonNull String level) { - return new Builder<>(name, level); - } - @NonNull - @Getter - private final String name; - @NonNull - @Getter - private final String level; - private final ParamType params; - @NonNull - private final IOBiFunction inputStreamWrapper; - @NonNull - private final IOBiFunction outputStreamWrapper; - - public InputStream inflate(@NonNull InputStream in) throws IOException { - return this.inputStreamWrapper.applyThrowing(in, this.params); - } - - public OutputStream deflate(@NonNull OutputStream out) throws IOException { - return this.outputStreamWrapper.applyThrowing(out, this.params); - } - - public byte[] inflate(@NonNull byte[] compressed) { - try (InputStream in = this.inflate(new ByteArrayInputStream(compressed))) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - int i; - while ((i = in.read()) != -1) { - baos.write(i); - } - return baos.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - public byte[] deflate(@NonNull byte[] original) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try (InputStream in = new ByteArrayInputStream(original); - OutputStream out = this.deflate(baos)) { - int i; - while ((i = in.read()) != -1) { - out.write(i); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - return baos.toByteArray(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (obj instanceof CompressionHelper) { - CompressionHelper compressionHelper = (CompressionHelper) obj; - return this.name.equals(compressionHelper.name) && this.level.equals(compressionHelper.level); - } else { - return false; - } - } - - @Override - public String toString() { - return String.format("%s (%s)", this.name, this.level); - } - - @Getter - @Setter - @Accessors(chain = true) - @RequiredArgsConstructor(access = AccessLevel.PRIVATE) - public static class Builder { - @NonNull - private final String name; - @NonNull - private final String level; - - private ParamType params; - private IOBiFunction inputStreamWrapper; - private IOBiFunction outputStreamWrapper; - - private Builder(@NonNull String name) { - this(name, "Default"); - } - - public Builder setParamsFunc(@NonNull ThrowingSupplier supplier) { - this.params = supplier.get(); - return this; - } - - public Builder setInputStreamWrapperSimple(@NonNull IOFunction inputStreamWrapper) { - this.inputStreamWrapper = (in, params) -> inputStreamWrapper.applyThrowing(in); - return this; - } - - public Builder setOutputStreamWrapperSimple(@NonNull IOFunction outputStreamWrapper) { - this.outputStreamWrapper = (out, params) -> outputStreamWrapper.applyThrowing(out); - return this; - } - - public CompressionHelper build() { - return new CompressionHelper<>(this.name, this.level, this.params, this.inputStreamWrapper, this.outputStreamWrapper); - } - } -} diff --git a/encoding/src/test/java/encoding/CompressionTest.java b/encoding/src/test/java/encoding/CompressionTest.java deleted file mode 100644 index 84d1169b6..000000000 --- a/encoding/src/test/java/encoding/CompressionTest.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package encoding; - -import net.daporkchop.lib.common.misc.TestRandomData; -import net.daporkchop.lib.encoding.compression.Compression; -import net.daporkchop.lib.encoding.compression.CompressionHelper; -import org.junit.Test; - -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.Hashtable; -import java.util.Map; - -/** - * @author DaPorkchop_ - */ -public class CompressionTest { - @Test - public void test() { - Compression.BZIP2_HIGH.toString(); - Map ratios = Collections.synchronizedMap(new Hashtable<>()); - Map times = Collections.synchronizedMap(new Hashtable<>()); - CompressionHelper.forAllRegisteredAlgs((name, helper) -> { - System.out.printf("Testing compression: %s\n", helper); - int inputSize = 0; - int outputSize = 0; - long time = System.currentTimeMillis(); - for (byte[] orig : TestRandomData.randomBytes) { - inputSize += orig.length; - byte[] compressed = helper.deflate(orig); - outputSize += compressed.length; - byte[] inflated = helper.inflate(compressed); - if (!Arrays.equals(orig, inflated)) { - throw new IllegalStateException(String.format("Inflated data was not the same as original data on %s", helper)); - } - } - ratios.put(helper.toString(), ((double) inputSize / (double) outputSize) * 100.0d); - times.put(helper.toString(), System.currentTimeMillis() - time); - }, true); - System.out.println(); - System.out.println("Compression ratios:"); - ratios.entrySet().stream() - .sorted(Comparator.comparing(Map.Entry::getValue, Double::compare)) - .forEachOrdered(e -> System.out.printf(" %.3f%% for %s\n", e.getValue(), e.getKey())); - - System.out.println(); - System.out.println("Compression times:"); - times.entrySet().stream() - .sorted(Comparator.comparing(Map.Entry::getValue, Long::compare)) - .forEachOrdered(e -> System.out.printf(" %05dms for %s\n", e.getValue(), e.getKey())); - } -} diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilSaveFormat.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilSaveFormat.java index 00b6e00d2..b9badeb7d 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilSaveFormat.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilSaveFormat.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -17,8 +17,6 @@ import lombok.Getter; import lombok.NonNull; -import net.daporkchop.lib.common.misc.Tuple; -import net.daporkchop.lib.encoding.compression.Compression; import net.daporkchop.lib.minecraft.registry.IDRegistry; import net.daporkchop.lib.minecraft.registry.IDRegistryBuilder; import net.daporkchop.lib.minecraft.registry.ResourceLocation; @@ -29,18 +27,16 @@ import net.daporkchop.lib.minecraft.world.format.WorldManager; import net.daporkchop.lib.nbt.NBTInputStream; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; -import net.daporkchop.lib.nbt.tag.notch.IntTag; import net.daporkchop.lib.nbt.tag.notch.ListTag; -import net.daporkchop.lib.nbt.tag.notch.StringTag; import net.daporkchop.lib.primitive.function.biconsumer.IntObjBiConsumer; import java.io.File; import java.io.FileInputStream; import java.io.IOException; -import java.util.Arrays; import java.util.function.BiConsumer; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.zip.GZIPInputStream; /** * @author DaPorkchop_ @@ -80,7 +76,7 @@ public void init(@NonNull MinecraftSave save) throws IOException { } else { throw new UnsupportedOperationException("create world"); } - try (NBTInputStream is = new NBTInputStream(new FileInputStream(levelDat_file), Compression.GZIP_NORMAL)) { + try (NBTInputStream is = new NBTInputStream(new GZIPInputStream(new FileInputStream(levelDat_file)))) { this.levelDat = is.readTag(); } } diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionConstants.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionConstants.java index ffc23d1c8..7dd18e413 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionConstants.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionConstants.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -16,12 +16,6 @@ package net.daporkchop.lib.minecraft.world.format.anvil.region; import lombok.experimental.UtilityClass; -import net.daporkchop.lib.encoding.compression.Compression; -import net.daporkchop.lib.encoding.compression.CompressionHelper; -import net.daporkchop.lib.primitive.map.ByteObjMap; -import net.daporkchop.lib.primitive.map.ObjByteMap; -import net.daporkchop.lib.primitive.map.hash.open.ByteObjOpenHashMap; -import net.daporkchop.lib.primitive.map.hash.open.ObjByteOpenHashMap; /** * Constants used when interacting with region files. @@ -41,59 +35,8 @@ public class RegionConstants { public static final int VERSION_HEADER_SIZE = 1; public static final int CHUNK_HEADER_SIZE = LENGTH_HEADER_SIZE + VERSION_HEADER_SIZE; - /** - * A bitmask to identify non-official compression versions. - *

- * Any version containing this mask is unofficial, added by me. - */ - public static final byte PORKIAN_ID_MASK = (byte) 0x80; - public static final byte ID_GZIP = 1; //official, no longer used by vanilla public static final byte ID_ZLIB = 2; //official - public static final byte ID_NONE = PORKIAN_ID_MASK | 1; - public static final byte ID_BZIP2 = PORKIAN_ID_MASK | 2; - public static final byte ID_LZ4 = PORKIAN_ID_MASK | 3; - public static final byte ID_LZMA = PORKIAN_ID_MASK | 4; - public static final byte ID_XZ = PORKIAN_ID_MASK | 5; - - public static final ByteObjMap COMPRESSION_IDS = new ByteObjOpenHashMap<>(); - public static final ObjByteMap REVERSE_COMPRESSION_IDS = new ObjByteOpenHashMap<>(); - - public static final boolean DEBUG_SECTORS = false; - - static { - //id => compression algo - COMPRESSION_IDS.put(ID_NONE, Compression.NONE); - COMPRESSION_IDS.put(ID_GZIP, Compression.GZIP_NORMAL); - COMPRESSION_IDS.put(ID_ZLIB, Compression.DEFLATE_NORMAL); - COMPRESSION_IDS.put(ID_BZIP2, Compression.BZIP2_NORMAL); - COMPRESSION_IDS.put(ID_LZ4, Compression.LZ4_BLOCK); - COMPRESSION_IDS.put(ID_LZMA, Compression.LZMA_NORMAL); - COMPRESSION_IDS.put(ID_XZ, Compression.XZ_NORMAL); - - //compression algo => id - REVERSE_COMPRESSION_IDS.put(Compression.NONE, ID_NONE); - REVERSE_COMPRESSION_IDS.put(Compression.GZIP_LOW, ID_GZIP); - REVERSE_COMPRESSION_IDS.put(Compression.GZIP_NORMAL, ID_GZIP); - REVERSE_COMPRESSION_IDS.put(Compression.GZIP_HIGH, ID_GZIP); - REVERSE_COMPRESSION_IDS.put(Compression.DEFLATE_LOW, ID_ZLIB); - REVERSE_COMPRESSION_IDS.put(Compression.DEFLATE_NORMAL, ID_ZLIB); - REVERSE_COMPRESSION_IDS.put(Compression.DEFLATE_HIGH, ID_ZLIB); - REVERSE_COMPRESSION_IDS.put(Compression.BZIP2_LOW, ID_BZIP2); - REVERSE_COMPRESSION_IDS.put(Compression.BZIP2_NORMAL, ID_BZIP2); - REVERSE_COMPRESSION_IDS.put(Compression.BZIP2_HIGH, ID_BZIP2); - REVERSE_COMPRESSION_IDS.put(Compression.LZ4_BLOCK, ID_LZ4); - REVERSE_COMPRESSION_IDS.put(Compression.LZ4_FRAMED_64KB, ID_LZ4); - REVERSE_COMPRESSION_IDS.put(Compression.LZ4_FRAMED_256KB, ID_LZ4); - REVERSE_COMPRESSION_IDS.put(Compression.LZ4_FRAMED_1MB, ID_LZ4); - REVERSE_COMPRESSION_IDS.put(Compression.LZ4_FRAMED_4MB, ID_LZ4); - REVERSE_COMPRESSION_IDS.put(Compression.LZMA_LOW, ID_LZMA); - REVERSE_COMPRESSION_IDS.put(Compression.LZMA_NORMAL, ID_LZMA); - REVERSE_COMPRESSION_IDS.put(Compression.LZMA_HIGH, ID_LZMA); - REVERSE_COMPRESSION_IDS.put(Compression.XZ_LOW, ID_XZ); - REVERSE_COMPRESSION_IDS.put(Compression.XZ_NORMAL, ID_XZ); - REVERSE_COMPRESSION_IDS.put(Compression.XZ_HIGH, ID_XZ); - } public static void assertInBounds(int x, int z) { if (x < 0 || x >= 32 || z < 0 || z >= 32) { diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionFile.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionFile.java index 71b90d5d2..a3cfbe828 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionFile.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/region/RegionFile.java @@ -16,13 +16,7 @@ package net.daporkchop.lib.minecraft.world.format.anvil.region; import io.netty.buffer.ByteBuf; -import io.netty.buffer.PooledByteBufAllocator; import lombok.NonNull; -import net.daporkchop.lib.binary.stream.DataIn; -import net.daporkchop.lib.binary.stream.DataOut; -import net.daporkchop.lib.binary.stream.netty.NettyByteBufOut; -import net.daporkchop.lib.binary.stream.stream.StreamOut; -import net.daporkchop.lib.encoding.compression.CompressionHelper; import net.daporkchop.lib.minecraft.world.format.anvil.region.ex.CorruptedRegionException; import net.daporkchop.lib.minecraft.world.format.anvil.region.ex.ReadOnlyRegionException; import net.daporkchop.lib.minecraft.world.format.anvil.region.impl.BufferedRegionFile; @@ -31,8 +25,6 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; /** @@ -62,25 +54,6 @@ static RegionFile open(@NonNull File file, @NonNull RegionOpenOptions options) t throw new IllegalArgumentException(options.toString()); } - /** - * Gets an {@link InputStream} that can inflate and read the contents of the chunk at the given coordinates (relative to this region). - * - * @param x the chunk's X coordinate - * @param z the chunk's Z coordinate - * @return an {@link InputStream} that can inflate and read the contents of the chunk at the given coordinates, or {@code null} if the chunk is not present - * @throws IOException if an IO exception occurs you dummy - */ - default InputStream read(int x, int z) throws IOException { - ByteBuf buf = this.readDirect(x, z); - if (buf == null) { - return null; - } else { - DataIn in = DataIn.wrap(buf, true); - byte compressionId = buf.readByte(); - return compressionId == RegionConstants.ID_NONE ? in : RegionConstants.COMPRESSION_IDS.get(compressionId).inflate(in); - } - } - /** * Reads the raw contents of the chunk at the given coordinates into a buffer. *

@@ -93,67 +66,6 @@ default InputStream read(int x, int z) throws IOException { */ ByteBuf readDirect(int x, int z) throws IOException; - /** - * Gets a {@link DataOut} that will compress data written to it using the given compression type. The compressed data will be written to disk at the specified - * region-local chunk coordinates when the {@link DataOut} instance is closed (using {@link DataOut#close()}. - * - * @param x the chunk's X coordinate - * @param z the chunk's Z coordinate - * @param compression the type of compression to use - * @return a {@link DataOut} for writing data to the given chunk - * @throws ReadOnlyRegionException if the region is opened in read-only mode - * @throws IOException if an IO exception occurs you dummy - */ - default DataOut write(int x, int z, @NonNull CompressionHelper compression) throws ReadOnlyRegionException, IOException { - byte compressionId = RegionConstants.REVERSE_COMPRESSION_IDS.get(compression); - if (compressionId == -1) { - throw new IllegalArgumentException(String.format("Unregistered compression format: %s", compression)); - } else { - return this.write(x, z, compression, compressionId); - } - } - - /** - * Gets a {@link DataOut} that will compress data written to it using the given compression type. The compressed data will be written to disk at the specified - * region-local chunk coordinates when the {@link DataOut} instance is closed (using {@link DataOut#close()}. - * - * @param x the chunk's X coordinate - * @param z the chunk's Z coordinate - * @param compression the type of compression to use - * @param compressionId the compression's ID, for writing to disk for decompression - * @return a {@link DataOut} for writing data to the given chunk - * @throws ReadOnlyRegionException if the region is opened in read-only mode - * @throws IOException if an IO exception occurs you dummy - */ - default DataOut write(int x, int z, @NonNull CompressionHelper compression, byte compressionId) throws ReadOnlyRegionException, IOException { - RegionConstants.assertInBounds(x, z); - this.assertWritable(); - - ByteBuf buf = PooledByteBufAllocator.DEFAULT.ioBuffer(RegionConstants.SECTOR_BYTES << 2).writeInt(-1).writeByte(compressionId); - - OutputStream out = DataOut.wrap(buf); - OutputStream compressedOut = compression.deflate(out); - - if (out == compressedOut) { - //no compression will be applied, wrap buffer directly - return new NettyByteBufOut(buf) { - @Override - protected boolean handleClose(@NonNull ByteBuf buf) throws IOException { - RegionFile.this.writeDirect(x, z, this.buf.setInt(0, this.buf.readableBytes() - RegionConstants.LENGTH_HEADER_SIZE)); - return false; - } - }; - } else { - return new StreamOut(compressedOut) { - @Override - public void close() throws IOException { - this.out.close(); - RegionFile.this.writeDirect(x, z, buf.setInt(0, buf.readableBytes() - RegionConstants.LENGTH_HEADER_SIZE)); - } - }; - } - } - /** * Writes raw chunk data to the region at the given region-local coordinates. * From a86072f6219c4b4cca6153c8ddce599aa3ef58df Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 10:51:41 +0100 Subject: [PATCH 21/36] make everything build again --- .../daporkchop/lib/binary/oio/StreamUtil.java | 98 +++++++++++++++++++ .../daporkchop/lib/binary/stream/DataIn.java | 66 +++++++------ .../binary/stream/netty/NettyByteBufIn.java | 30 ++++-- .../lib/binary/stream/nio/BufferIn.java | 26 +++-- .../daporkchop/lib/common/util/PorkUtil.java | 4 +- .../daporkchop/lib/nbt/NBTInputStream.java | 12 +-- encoding/nbt/src/test/java/NBTTest.java | 4 +- .../src/example/java/http/TestHTTPGET.java | 3 +- 8 files changed, 187 insertions(+), 56 deletions(-) create mode 100644 binary/src/main/java/net/daporkchop/lib/binary/oio/StreamUtil.java diff --git a/binary/src/main/java/net/daporkchop/lib/binary/oio/StreamUtil.java b/binary/src/main/java/net/daporkchop/lib/binary/oio/StreamUtil.java new file mode 100644 index 000000000..92f2d36aa --- /dev/null +++ b/binary/src/main/java/net/daporkchop/lib/binary/oio/StreamUtil.java @@ -0,0 +1,98 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.binary.oio; + +import lombok.NonNull; +import lombok.experimental.UtilityClass; +import net.daporkchop.lib.binary.stream.DataIn; +import net.daporkchop.lib.common.util.PorkUtil; + +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.Arrays; + +/** + * Helper methods for dealing with OIO {@link InputStream}s and {@link OutputStream}s. + * + * @author DaPorkchop_ + */ +@UtilityClass +public class StreamUtil { + /** + * Reads the entire contents of the given {@link InputStream} into a {@code byte[]}. + * + * @param in the {@link InputStream} to read + * @return the contents of the given {@link InputStream} as a {@code byte[]} + * @throws IOException if an IO exception occurs you dummy + */ + public byte[] toByteArray(@NonNull InputStream in) throws IOException { + if (in instanceof DataIn) { + //DataIn implementations might apply their own optimizations here + return ((DataIn) in).toByteArray(); + } else { + byte[] arr = new byte[4096]; + int pos = 0; + for (int i; (i = in.read(arr, pos, arr.length - pos)) != -1; pos += i) { + if (pos + i == arr.length) { + //grow array + byte[] old = arr; + System.arraycopy(old, 0, arr = new byte[arr.length << 1], 0, old.length); + } + } + return pos == arr.length ? arr : Arrays.copyOf(arr, pos); //don't copy if the size is exactly the size of the array already + } + } + + /** + * Fills the given {@code byte[]} with data read from the given {@link InputStream}. + * + * @param in the {@link InputStream} to read from + * @param dst the {@code byte[]} to read to + * @return the {@link byte[]} + * @throws EOFException if the given {@link InputStream} reaches EOF before the given {@code byte[]} could be filled + * @throws IOException if an IO exception occurs you dummy + */ + public byte[] readFully(@NonNull InputStream in, @NonNull byte[] dst) throws EOFException, IOException { + return readFully(in, dst, 0, dst.length); + } + + /** + * Fills the given region of the given {@code byte[]} with data read from the given {@link InputStream}. + * + * @param in the {@link InputStream} to read from + * @param dst the {@code byte[]} to read to + * @param start the first index (inclusive) in the {@code byte[]} to start writing to + * @param length the number of bytes to read into the {@code byte[]} + * @return the {@link byte[]} + * @throws EOFException if the given {@link InputStream} reaches EOF before the given number of bytes could be read + * @throws IOException if an IO exception occurs you dummy + */ + public byte[] readFully(@NonNull InputStream in, @NonNull byte[] dst, int start, int length) throws EOFException, IOException { + if (in instanceof DataIn) { + //DataIn implementations might apply their own optimizations here + ((DataIn) in).readFully(dst, start, length); + } else { + PorkUtil.assertInRangeLen(dst.length, start, length); + for (int i; length > 0 && (i = in.read(dst, start, length)) != -1; start += i, length -= i) ; + if (length != 0) { + throw new EOFException(); + } + } + return dst; + } +} diff --git a/binary/src/main/java/net/daporkchop/lib/binary/stream/DataIn.java b/binary/src/main/java/net/daporkchop/lib/binary/stream/DataIn.java index 371208aaf..4fb829770 100644 --- a/binary/src/main/java/net/daporkchop/lib/binary/stream/DataIn.java +++ b/binary/src/main/java/net/daporkchop/lib/binary/stream/DataIn.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -20,9 +20,11 @@ import net.daporkchop.lib.binary.stream.netty.NettyByteBufIn; import net.daporkchop.lib.binary.stream.nio.BufferIn; import net.daporkchop.lib.binary.stream.stream.StreamIn; +import net.daporkchop.lib.common.util.PorkUtil; import java.io.BufferedInputStream; import java.io.ByteArrayInputStream; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; @@ -30,6 +32,7 @@ import java.nio.ByteBuffer; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.function.Function; /** @@ -459,48 +462,51 @@ public CharSequence readText(long size, @NonNull Charset charset) throws IOExcep } /** - * Attempts to fill a byte array with data. - *

- * Functionally equivalent to: - * {@code return readFully(b, 0, b.length);} + * Fills the given {@code byte[]} with data. * - * @param b the byte array to read into - * @return the {@code byte[]} that the data was read into - * @throws IOException if end of stream is reached before the required number required bytes are read + * @param dst the {@code byte[]} to read to + * @throws EOFException if EOF is reached before the given {@code byte[]} could be filled + * @throws IOException if an IO exception occurs you dummy */ - public byte[] readFully(@NonNull byte[] b) throws IOException { - return this.readFully(b, 0, b.length); + public byte[] readFully(@NonNull byte[] dst) throws EOFException, IOException { + return this.readFully(dst, 0, dst.length); } /** - * Attempts to fill a given region of a byte array with data. + * Fills the given region of the given {@code byte[]} with data. * - * @param b the byte array to read into - * @param off the offset in the array to write data to - * @param len the number of bytes to read - * @return the {@code byte[]} that the data was read into - * @throws IOException if end of stream is reached before the required number required bytes are read + * @param dst the {@code byte[]} to read to + * @param start the first index (inclusive) in the {@code byte[]} to start writing to + * @param length the number of bytes to read into the {@code byte[]} + * @return the {@code byte[]} + * @throws EOFException if EOF is reached before the given number of bytes could be read + * @throws IOException if an IO exception occurs you dummy */ - public byte[] readFully(@NonNull byte[] b, int off, int len) throws IOException { - int i = 0; - while (len > 0 && (i = this.read(b, off + i, len)) != -1) { - len -= i; - } - if (i == -1) { - throw new IOException("Reached end of stream!"); + public byte[] readFully(@NonNull byte[] dst, int start, int length) throws EOFException, IOException { + PorkUtil.assertInRangeLen(dst.length, start, length); + for (int i; length > 0 && (i = this.read(dst, start, length)) != -1; start += i, length -= i) ; + if (length != 0) { + throw new EOFException(); } - return b; + return dst; } /** - * Reads all available bytes from this stream, as returned by {@link #available()}. + * Reads the entire contents of this {@link DataIn} into a {@code byte[]}. * - * @return all available bytes from this stream + * @return the contents of this {@link DataIn} as a {@code byte[]} */ - public byte[] readAllAvailableBytes() throws IOException { - byte[] b = new byte[this.available()]; - this.readFully(b); - return b; + public byte[] toByteArray() throws IOException { + byte[] arr = new byte[4096]; + int pos = 0; + for (int i; (i = this.read(arr, pos, arr.length - pos)) != -1; pos += i) { + if (pos + i == arr.length) { + //grow array + byte[] old = arr; + System.arraycopy(old, 0, arr = new byte[arr.length << 1], 0, old.length); + } + } + return pos == arr.length ? arr : Arrays.copyOf(arr, pos); //don't copy if the size is exactly the size of the array already } /** diff --git a/binary/src/main/java/net/daporkchop/lib/binary/stream/netty/NettyByteBufIn.java b/binary/src/main/java/net/daporkchop/lib/binary/stream/netty/NettyByteBufIn.java index c4be4afd2..a19016fd4 100644 --- a/binary/src/main/java/net/daporkchop/lib/binary/stream/netty/NettyByteBufIn.java +++ b/binary/src/main/java/net/daporkchop/lib/binary/stream/netty/NettyByteBufIn.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -21,7 +21,9 @@ import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; import net.daporkchop.lib.binary.stream.DataIn; +import net.daporkchop.lib.common.util.PorkUtil; +import java.io.EOFException; import java.io.IOException; import java.nio.charset.Charset; @@ -177,22 +179,34 @@ public double readDoubleLE() throws IOException { @Override public CharSequence readText(long size, @NonNull Charset charset) throws IOException { - if (size > Integer.MAX_VALUE) { + if (size > Integer.MAX_VALUE) { throw new IllegalArgumentException("size parameter too large!"); } return this.buf.readCharSequence((int) size, charset); } @Override - public byte[] readFully(@NonNull byte[] b) throws IOException { - this.buf.readBytes(b); - return b; + public byte[] readFully(@NonNull byte[] dst) throws IOException { + this.buf.readBytes(dst); + return dst; } @Override - public byte[] readFully(@NonNull byte[] b, int off, int len) throws IOException { - this.buf.readBytes(b, off, len); - return b; + public byte[] readFully(@NonNull byte[] dst, int start, int length) throws EOFException, IOException { + PorkUtil.assertInRangeLen(dst.length, start, length); + if (this.buf.isReadable(length)) { + this.buf.readBytes(dst, start, length); + return dst; + } else { + throw new EOFException(); + } + } + + @Override + public byte[] toByteArray() throws IOException { + byte[] arr = new byte[this.buf.readableBytes()]; + this.buf.readBytes(arr); + return arr; } @Override diff --git a/binary/src/main/java/net/daporkchop/lib/binary/stream/nio/BufferIn.java b/binary/src/main/java/net/daporkchop/lib/binary/stream/nio/BufferIn.java index ea415a432..84e187d45 100644 --- a/binary/src/main/java/net/daporkchop/lib/binary/stream/nio/BufferIn.java +++ b/binary/src/main/java/net/daporkchop/lib/binary/stream/nio/BufferIn.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -19,7 +19,9 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; import net.daporkchop.lib.binary.stream.DataIn; +import net.daporkchop.lib.common.util.PorkUtil; +import java.io.EOFException; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -51,9 +53,21 @@ public int read(@NonNull byte[] b, int off, int len) throws IOException { } @Override - public byte[] readFully(@NonNull byte[] b, int off, int len) throws IOException { - this.buffer.get(b, off, len); - return b; + public byte[] readFully(@NonNull byte[] dst, int start, int length) throws EOFException, IOException { + PorkUtil.assertInRangeLen(dst.length, start, length); + if (this.buffer.remaining() >= length) { + this.buffer.get(dst, start, length); + return dst; + } else { + throw new EOFException(); + } + } + + @Override + public byte[] toByteArray() throws IOException { + byte[] arr = new byte[this.buffer.remaining()]; + this.buffer.get(arr); + return arr; } @Override @@ -76,12 +90,12 @@ public long skip(long cnt) throws IOException { } @Override - public synchronized void mark(int readlimit) { + public void mark(int readlimit) { this.buffer.mark(); } @Override - public synchronized void reset() throws IOException { + public void reset() throws IOException { this.buffer.reset(); } diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java index 763cb7987..122db7ee1 100644 --- a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java +++ b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java @@ -338,7 +338,7 @@ public void assertInRange(int size, int start, int end) throws IndexOutOfBoundsE } } - public void assertInRangeLen(int size, int start, int len) throws IndexOutOfBoundsException { - assertInRange(size, start, start + len); + public void assertInRangeLen(int size, int start, int length) throws IndexOutOfBoundsException { + assertInRange(size, start, start + length); } } diff --git a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java index bf9a02a54..4627c05f1 100644 --- a/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java +++ b/encoding/nbt/src/main/java/net/daporkchop/lib/nbt/NBTInputStream.java @@ -246,18 +246,18 @@ public long readVarLong() throws IOException { } @Override - public byte[] readFully(@NonNull byte[] b) throws IOException { - return this.in.readFully(b); + public byte[] readFully(@NonNull byte[] dst) throws IOException { + return this.in.readFully(dst); } @Override - public byte[] readFully(@NonNull byte[] b, int off, int len) throws IOException { - return this.in.readFully(b, off, len); + public byte[] readFully(@NonNull byte[] dst, int start, int length) throws IOException { + return this.in.readFully(dst, start, length); } @Override - public byte[] readAllAvailableBytes() throws IOException { - return this.in.readAllAvailableBytes(); + public byte[] toByteArray() throws IOException { + return this.in.toByteArray(); } @Override diff --git a/encoding/nbt/src/test/java/NBTTest.java b/encoding/nbt/src/test/java/NBTTest.java index 27a4c46f1..8be825d69 100644 --- a/encoding/nbt/src/test/java/NBTTest.java +++ b/encoding/nbt/src/test/java/NBTTest.java @@ -14,12 +14,12 @@ */ import lombok.NonNull; +import net.daporkchop.lib.binary.oio.StreamUtil; import net.daporkchop.lib.nbt.NBTInputStream; import net.daporkchop.lib.nbt.NBTOutputStream; import net.daporkchop.lib.nbt.tag.Tag; import net.daporkchop.lib.nbt.tag.notch.CompoundTag; import net.daporkchop.lib.nbt.tag.notch.ListTag; -import org.apache.commons.compress.utils.IOUtils; import org.junit.Test; import java.io.BufferedOutputStream; @@ -61,7 +61,7 @@ public static String space(int count) { public void testWriting() throws IOException { byte[] original_uncompressed; try (InputStream is = new GZIPInputStream(NBTTest.class.getResourceAsStream("bigtest.nbt"))) { - original_uncompressed = IOUtils.toByteArray(is); + original_uncompressed = StreamUtil.toByteArray(is); } CompoundTag tag; try (NBTInputStream in = new NBTInputStream(new ByteArrayInputStream(original_uncompressed))) { diff --git a/network/tcp/src/example/java/http/TestHTTPGET.java b/network/tcp/src/example/java/http/TestHTTPGET.java index dd24f091e..4e5fa9192 100644 --- a/network/tcp/src/example/java/http/TestHTTPGET.java +++ b/network/tcp/src/example/java/http/TestHTTPGET.java @@ -22,7 +22,6 @@ import lombok.NonNull; import net.daporkchop.lib.binary.stream.DataIn; import net.daporkchop.lib.logging.LogAmount; -import net.daporkchop.lib.logging.Logging; import net.daporkchop.lib.network.endpoint.PClient; import net.daporkchop.lib.network.endpoint.builder.ClientBuilder; import net.daporkchop.lib.network.netty.LoopPool; @@ -85,7 +84,7 @@ public void onReceive(@NonNull DataIn in, @NonNull PacketMetadata metadata) thro if (this.headers != null) { throw new IllegalStateException("Headers already read!"); } else { - this.headers = Arrays.stream(new String(in.readAllAvailableBytes(), StandardCharsets.UTF_8).split("\r\n")) + this.headers = Arrays.stream(new String(in.toByteArray(), StandardCharsets.UTF_8).split("\r\n")) .map(s -> s.split(": ", 2)) .filter(a -> a.length == 2) .collect(Collectors.toMap(a -> a[0], a -> a[1])); From 45dfb99aa6b75733dfa9024679ff869eca29a7bf Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 12:20:00 +0100 Subject: [PATCH 22/36] begin work on zstd implementation --- build.gradle | 5 -- .../daporkchop/lib/compression/Context.java | 12 +-- .../lib/compression/util/BufferTyped.java | 34 +++++++++ compression/zlib/Makefile | 6 +- .../lib/compression/zlib/ZlibProvider.java | 6 +- .../lib/compression/zlib/java/JavaZlib.java | 5 ++ .../compression/zlib/natives/NativeZlib.java | 5 ++ .../main/native => compression}/zstd/Makefile | 33 +++++---- .../zstd/src/example/java/ZstdTest.java | 25 +++++++ .../daporkchop/lib/compression/zstd/Zstd.java | 32 ++++++++ .../lib/compression/zstd/ZstdProvider.java | 74 +++++++++++++++++++ .../compression/zstd/natives/NativeZstd.java | 69 +++++++++++++++++ .../ContentSizeUnknownException.java | 27 +++++++ .../src/main/native/common/NativeZstd.cpp | 17 +++++ .../zstd/src/main/native/common/NativeZstd.h | 25 +++++++ minecraft/build.gradle | 1 + natives/Makefile | 5 +- 17 files changed, 341 insertions(+), 40 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java rename {natives/src/main/native => compression}/zstd/Makefile (54%) create mode 100644 compression/zstd/src/example/java/ZstdTest.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java create mode 100644 compression/zstd/src/main/native/common/NativeZstd.cpp create mode 100644 compression/zstd/src/main/native/common/NativeZstd.h diff --git a/build.gradle b/build.gradle index 472ee6c93..e284add9b 100644 --- a/build.gradle +++ b/build.gradle @@ -29,19 +29,14 @@ allprojects { porklibVersion = "0.5.1-SNAPSHOT" //dependency things - apacheCommonsCompressVersion = "1.16.1" bouncycastleVersion = "1.59" florianingerlRegexVersion = "1.1.9" - googleHttpClientVersion = "1.23.0" gsonVersion = "2.8.5" guavaVersion = "27.0-jre" - jnaVersion = "5.5.0" junitVersion = "4.12" lombokVersion = "1.16.20" nettyVersion = "4.1.36.Final" raknetVersion = "1.4.0" - sparseBitSetVersion = "1.1" - xzVersion = "1.8" } group "net.daporkchop" diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index a2cd25446..3c90d058c 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -17,6 +17,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; +import net.daporkchop.lib.compression.util.BufferTyped; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; @@ -29,16 +30,7 @@ * * @author DaPorkchop_ */ -interface Context> extends Releasable { - /** - * Checks whether this context uses direct or heap memory. - *

- * {@link io.netty.buffer.ByteBuf}s of the wrong type will not be accepted by any methods, and will cause an {@link InvalidBufferTypeException} to be thrown. - * - * @return whether this context uses direct or heap memory - */ - boolean direct(); - +interface Context> extends Releasable, BufferTyped { /** * Sets the context's current source buffer when processing data in streaming mode. * diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java b/compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java new file mode 100644 index 000000000..df7d29293 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java @@ -0,0 +1,34 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util; + +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; + +/** + * A type that accepts {@link io.netty.buffer.ByteBuf}s, but only of a certain type (either direct or heap). + * + * @author DaPorkchop_ + */ +public interface BufferTyped { + /** + * Checks whether this implementation uses direct or heap memory. + *

+ * {@link io.netty.buffer.ByteBuf}s of the wrong type will not be accepted by any methods, and will cause an {@link InvalidBufferTypeException} to be thrown. + * + * @return whether this implementation uses direct or heap memory + */ + boolean direct(); +} diff --git a/compression/zlib/Makefile b/compression/zlib/Makefile index 988affef6..172803472 100644 --- a/compression/zlib/Makefile +++ b/compression/zlib/Makefile @@ -13,15 +13,13 @@ $(BUILD): @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) build else -.PHONY: build .FORCE +.PHONY: build include $(TOOLCHAINS)/$(BUILD) SOURCES := $(PROJDIR)/src/main/native/common $(PROJDIR)/src/main/native/$(BUILD) $(COMMONSRC)/common $(COMMONSRC)/$(BUILD) SOURCES := $(abspath $(SOURCES)) -#CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) -#CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c)) CPPFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.cpp)) OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) @@ -53,6 +51,4 @@ $(CURDIR)/lib-zlib/libz-ng.a: $(TOPDIR)/zlib-ng-1.2.11.tar.gz # @cd lib-zlib/ && ./configure --static --with-gzfileops && cd .. @$(MAKE) -C $(CURDIR)/lib-zlib/ -f $(CURDIR)/lib-zlib/Makefile libz-ng.a -FORCE: - endif diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 5350898d9..868588f86 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,12 +16,14 @@ package net.daporkchop.lib.compression.zlib; +import net.daporkchop.lib.compression.util.BufferTyped; + /** - * A wrapper around a Zlib implementation. + * Representation of a Zlib implementation. * * @author DaPorkchop_ */ -public interface ZlibProvider { +public interface ZlibProvider extends BufferTyped { /** * Creates a new {@link ZlibDeflater}. * diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java index 606489836..0c1799554 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java @@ -34,6 +34,11 @@ protected boolean _available() { return true; } + @Override + public boolean direct() { + return false; + } + @Override public ZlibDeflater deflater(int level, int strategy, int mode) { throw new UnsupportedOperationException(); //TODO diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index c71273186..5325c595c 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -41,6 +41,11 @@ protected ZlibProvider _get() { return this; } + @Override + public boolean direct() { + return true; + } + @Override public ZlibDeflater deflater(int level, int strategy, int mode) { return new NativeZlibDeflater(level, strategy, mode); diff --git a/natives/src/main/native/zstd/Makefile b/compression/zstd/Makefile similarity index 54% rename from natives/src/main/native/zstd/Makefile rename to compression/zstd/Makefile index d7d1e461d..6cf8ee267 100644 --- a/natives/src/main/native/zstd/Makefile +++ b/compression/zstd/Makefile @@ -1,44 +1,47 @@ -BUILDDIR := build/$(BUILD) +OUTDIR := $(PROJDIR)/src/main/resources ifneq ($(BUILD),$(notdir $(CURDIR))) .PHONY: $(BUILD) clean +BUILDDIR := build/$(BUILD) + clean: - @rm -rf build/ tmp/ + @rm -rf build/ $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) $(BUILD): @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) - @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) zstd-$(BUILD) + @$(MAKE) --no-print-directory -C $(BUILDDIR) -f $(CURDIR)/Makefile BUILD=$(BUILD) build else -.PHONY: zstd-$(BUILD) lib-zstd +.PHONY: build -include $(TOPDIR)/toolchain/$(BUILD) +include $(TOOLCHAINS)/$(BUILD) -SOURCES := $(SOURCES) $(PROJDIR)/source +SOURCES := $(PROJDIR)/src/main/native/common $(PROJDIR)/src/main/native/$(BUILD) $(COMMONSRC)/common $(COMMONSRC)/$(BUILD) +SOURCES := $(abspath $(SOURCES)) -CFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.c')) -CPPFILES := $(foreach dir,$(SOURCES),$(shell find -L $(dir) -maxdepth 1 -type f -name '*.cpp')) +CFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.c)) +CPPFILES := $(foreach dir,$(SOURCES),$(wildcard $(dir)/*.cpp)) OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) -INCLUDE := $(foreach dir,$(INCLUDES),-I$(dir)) -I$(PROJDIR)/include -I$(CURDIR) +INCLUDE := $(addprefix -I,$(INCLUDES) $(CURDIR)) -zstd-$(BUILD): $(OUTDIR)/$(BUILD)/libzstd.$(EXT) +build: $(OUTDIR)/$(BUILD)/libzstd.$(EXT) -$(OUTDIR)/$(BUILD)/libzstd.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a +$(OUTDIR)/$(BUILD)/libzstd.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) @echo "Linking $@..." @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @echo "Stripping $@..." - @strip $@ + @$(STRIP) $@ -%.c.o: $(CFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a +%.c.o: $(CFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @echo "Building $(subst .o,,$(subst __,/,$@))..." @$(CC) $(CFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ -%.cpp.o: $(CPPFILES) $(TOPDIR)/Makefile $(PROJDIR)/Makefile $(CURDIR)/lib-zstd/lib/libzstd.a +%.cpp.o: $(CPPFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @echo "Building $(subst .o,,$(subst __,/,$@))..." - @$(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ + $(CXX) $(CXXFLAGS) $(INCLUDE) -c $(subst .o,,$(subst __,/,$@)) -o $@ $(CURDIR)/lib-zstd/lib/libzstd.a: $(TOPDIR)/zstd-1.4.4.tar.gz @[ ! -d lib-zstd ] || rm -rf lib-zstd/ diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java new file mode 100644 index 000000000..8daf4ee1a --- /dev/null +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -0,0 +1,25 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +import net.daporkchop.lib.compression.zstd.Zstd; + +/** + * @author DaPorkchop_ + */ +public class ZstdTest { + public static void main(String... args) { + System.out.printf("original: %d, worst-case compressed: %d\n", 1 << 16L, Zstd.PROVIDER.get().compressBound(1 << 16L)); + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java new file mode 100644 index 000000000..a8b234031 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java @@ -0,0 +1,32 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import lombok.experimental.UtilityClass; +import net.daporkchop.lib.compression.zstd.natives.NativeZstd; +import net.daporkchop.lib.natives.NativeCode; + +/** + * @author DaPorkchop_ + */ +@UtilityClass +public class Zstd { + public final NativeCode PROVIDER = new NativeCode<>(NativeZstd::new); + + public final int LEVEL_DEFAULT = 3; + public final int LEVEL_MIN = -999; + public final int LEVEL_MAX = 22; +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java new file mode 100644 index 000000000..13de4ae7a --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -0,0 +1,74 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.BufferTyped; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; + +/** + * Representation of a Zstd implementation. + * + * @author DaPorkchop_ + */ +public interface ZstdProvider extends BufferTyped { + @Override + boolean direct(); + + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer. + *

+ * If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read source data from + * @param dst the {@link ByteBuf} to write compressed data to + * @param compressionLevel the Zstd level to compress at + * @return whether or not compression was successful. If {@code false}, the destination buffer was too small for the compressed data + */ + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException; + + /** + * Decompresses the given Zstd-compressed into the given destination buffer. + *

+ * If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read compressed data from + * @param dst the {@link ByteBuf} to write decompressed data to + * @return whether or not decompression was successful. If {@code false}, the destination buffer was too small for the decompressed data + */ + boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + + /** + * Gets the decompressed size of the given Zstd-compressed data. + * + * @param src the {@link ByteBuf} containing the compressed data. This {@link ByteBuf}'s indices will not be modified by this method + * @return the size (in bytes) of the decompressed data + * @throws ContentSizeUnknownException if the decompressed size cannot be determined + */ + long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException; + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length. + * + * @param srcSize the size (in bytes) of the source data + * @return the worst-case size of the compressed data + */ + long compressBound(long srcSize); +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java new file mode 100644 index 000000000..b62964c92 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -0,0 +1,69 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.compression.zstd.ZstdProvider; +import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; +import net.daporkchop.lib.natives.NativeCode; + +/** + * @author DaPorkchop_ + */ +public final class NativeZstd extends NativeCode.NativeImpl implements ZstdProvider { + static { + if (NativeCode.NativeImpl.AVAILABLE) { + NativeCode.loadNativeLibrary("zstd"); + } + } + + @Override + protected ZstdProvider _get() { + return this; + } + + @Override + public boolean direct() { + return true; + } + + @Override + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { + return false; + } + + @Override + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return false; + } + + @Override + public long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException { + return 0; + } + + @Override + public long compressBound(long srcSize) { + if (srcSize < 0L) { + throw new IllegalArgumentException(String.valueOf(srcSize)); + } + return this.doCompressBound(srcSize); + } + + private native long doCompressBound(long srcSize); +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java new file mode 100644 index 000000000..536d2bd19 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java @@ -0,0 +1,27 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.util.exception; + +import io.netty.buffer.ByteBuf; +import net.daporkchop.lib.compression.zstd.ZstdProvider; + +/** + * Thrown when {@link ZstdProvider#frameContentSize(ByteBuf)} cannot identify the content size of the given frame. + * + * @author DaPorkchop_ + */ +public final class ContentSizeUnknownException extends RuntimeException { +} diff --git a/compression/zstd/src/main/native/common/NativeZstd.cpp b/compression/zstd/src/main/native/common/NativeZstd.cpp new file mode 100644 index 000000000..0624ca2e2 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstd.cpp @@ -0,0 +1,17 @@ +#include +#include "NativeZstd.h" + +#include + +#include +#include + +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound + (JNIEnv* env, jobject obj, jlong srcSize) { + + printf("min: %d, max: %d\n", ZSTD_minCLevel(), ZSTD_maxCLevel()); + + return ZSTD_compressBound(srcSize); +} diff --git a/compression/zstd/src/main/native/common/NativeZstd.h b/compression/zstd/src/main/native/common/NativeZstd.h new file mode 100644 index 000000000..ee6a7dcd7 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstd.h @@ -0,0 +1,25 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd +#define _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstd + * Method: doCompressBound + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound + (JNIEnv *, jobject, jlong); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd diff --git a/minecraft/build.gradle b/minecraft/build.gradle index b3e40cf4a..415be7707 100644 --- a/minecraft/build.gradle +++ b/minecraft/build.gradle @@ -21,5 +21,6 @@ dependencies { compile project(":minecraft:minecraft-text") compile project(":primitive") + //TODO: i'm only using LoadingCache, figure out a way to not have to pull in all of guava for that one feature compile "com.google.guava:guava:$guavaVersion" } diff --git a/natives/Makefile b/natives/Makefile index 2d7c66697..286598c4e 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -17,8 +17,7 @@ export ARCHS := aarch64-linux-gnu x86_64-linux-gnu x86_64-w64-mingw32 #export ARCHS := $(foreach arch,$(ARCHS),$(if $(shell which $(arch)-g++),$(arch))) export ARCH_TASKS := $(foreach arch,$(ARCHS),build.$(arch)) -export MODULES := ../compression/zlib -#export MODULES := ../compression/zlib ../compression/zstd +export MODULES := ../compression/zlib ../compression/zstd export LIBDIR := $(TOPDIR)/src/main/native/lib export LIB_URL_BASE := https://cloud.daporkchop.net/programs/source/ @@ -34,7 +33,7 @@ build.%: .FORCE $(foreach module,$(MODULES),%,$(module).lib) %.lib: .FORCE $(LIBS) @_PRJ_NAME=$(shell echo "$@" | perl -n -e '/,(.*?)\.lib$$/ && print $$1') && \ _ARCH=$(shell echo "$@" | perl -n -e '/^([^,]*?),.*?\.lib$$/ && print $$1') && \ - $(MAKE) -C $(TOPDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(TOPDIR)/$$_PRJ_NAME $$_ARCH && \ + $(MAKE) --no-print-directory -C $(TOPDIR)/$$_PRJ_NAME BUILD=$$_ARCH PROJDIR=$(TOPDIR)/$$_PRJ_NAME $$_ARCH && \ echo Built $$_PRJ_NAME for target $$_ARCH! #echo "arg = $@" && echo "prj_name = $$_PRJ_NAME" && echo "arch = $$_ARCH" && \ From 0689bf304fcb3254dfdf604f94c8335f97988edd Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 15:28:35 +0100 Subject: [PATCH 23/36] try to clean up `:natives` module --- .../daporkchop/lib/common/util/PorkUtil.java | 18 ++ compression/build.gradle | 2 + .../daporkchop/lib/compression/Context.java | 4 +- .../daporkchop/lib/compression/PDeflater.java | 2 +- .../daporkchop/lib/compression/PInflater.java | 2 +- .../zlib/src/example/java/ZlibTest.java | 12 +- .../daporkchop/lib/compression/zlib/Zlib.java | 7 +- .../lib/compression/zlib/ZlibDeflater.java | 2 +- .../lib/compression/zlib/ZlibInflater.java | 2 +- .../lib/compression/zlib/ZlibProvider.java | 5 +- .../lib/compression/zlib/java/JavaZlib.java | 17 +- .../compression/zlib/natives/NativeZlib.java | 22 +-- .../zlib/natives/NativeZlibDeflater.java | 12 +- .../zlib/natives/NativeZlibInflater.java | 13 +- .../zstd/src/example/java/ZstdTest.java | 2 +- .../daporkchop/lib/compression/zstd/Zstd.java | 6 +- .../lib/compression/zstd/ZstdProvider.java | 9 +- .../compression/zstd/natives/NativeZstd.java | 20 +- .../world/format/anvil/AnvilWorldManager.java | 2 +- .../lib/natives/FeatureBuilder.java | 84 ++++++++ .../daporkchop/lib/natives/NativeCode.java | 180 ------------------ .../daporkchop/lib/natives/impl/Feature.java | 16 +- .../lib/natives/impl/Implementation.java | 10 +- .../lib/natives/impl/NativeFeature.java | 101 ++++++++++ .../lib/natives/util/BufferTyped.java | 64 +++++++ .../exception/InvalidBufferTypeException.java | 51 +++++ 26 files changed, 384 insertions(+), 281 deletions(-) create mode 100644 natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java rename compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java => natives/src/main/java/net/daporkchop/lib/natives/impl/Feature.java (69%) rename compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java => natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java (75%) create mode 100644 natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java create mode 100644 natives/src/main/java/net/daporkchop/lib/natives/util/BufferTyped.java create mode 100644 natives/src/main/java/net/daporkchop/lib/natives/util/exception/InvalidBufferTypeException.java diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java index 122db7ee1..63942beda 100644 --- a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java +++ b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java @@ -222,6 +222,24 @@ public Class classForName(@NonNull String name) { } } + @SuppressWarnings("unchecked") + public Class uninitializedClassForName(@NonNull String name) { + try { + return (Class) Class.forName(name, false, null); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + + @SuppressWarnings("unchecked") + public Class uninitializedClassForName(@NonNull String name, ClassLoader loader) { + try { + return (Class) Class.forName(name, false, loader); + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } + } + public boolean classExistsWithName(@NonNull String name) { try { Class.forName(name); diff --git a/compression/build.gradle b/compression/build.gradle index 3788af6ff..4171ad4a9 100644 --- a/compression/build.gradle +++ b/compression/build.gradle @@ -14,5 +14,7 @@ */ dependencies { + compile project(":natives") + compile "io.netty:netty-buffer:$nettyVersion" } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index 3c90d058c..95111351d 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -17,10 +17,10 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.BufferTyped; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.capability.Releasable; /** diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java index fcff5c6a5..addec968a 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -19,7 +19,7 @@ import lombok.NonNull; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * Deflates (compresses) data. diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java index b68b16b74..5a698e9dd 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -19,7 +19,7 @@ import lombok.NonNull; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * Inflates (decompresses) data. diff --git a/compression/zlib/src/example/java/ZlibTest.java b/compression/zlib/src/example/java/ZlibTest.java index df65f4e94..c283dbc9f 100644 --- a/compression/zlib/src/example/java/ZlibTest.java +++ b/compression/zlib/src/example/java/ZlibTest.java @@ -43,7 +43,7 @@ public static void main(String... args) throws DataFormatException { { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { + try (PDeflater deflater = Zlib.PROVIDER.deflater()) { if (!deflater.fullDeflate(original.slice(), compressedNative)) { throw new IllegalStateException("Couldn't deflate data!"); } @@ -69,7 +69,7 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); - try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + try (PInflater inflater = Zlib.PROVIDER.inflater()) { if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } @@ -91,7 +91,7 @@ public static void main(String... args) throws DataFormatException { { ByteBuf compressedNative = Unpooled.directBuffer(16, SIZE >>> 4); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { + try (PDeflater deflater = Zlib.PROVIDER.deflater()) { deflater.dict(original.slice(0, DICT_SIZE)); if (false) { deflater.dst(compressedNative); @@ -147,7 +147,7 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); - try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + try (PInflater inflater = Zlib.PROVIDER.inflater()) { if (!inflater.dict(original.slice(0, DICT_SIZE)) .fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); @@ -172,7 +172,7 @@ public static void main(String... args) throws DataFormatException { { ByteBuf compressedNative = Unpooled.directBuffer(SIZE >>> 4, SIZE >>> 4); - try (PDeflater deflater = Zlib.PROVIDER.get().deflater()) { + try (PDeflater deflater = Zlib.PROVIDER.deflater()) { deflater.dst(compressedNative); for (int i = 0; i < 16; i++) { ByteBuf src = original.slice((SIZE >>> 4) * i, SIZE >>> 4); @@ -207,7 +207,7 @@ public static void main(String... args) throws DataFormatException { validateEqual(original, Unpooled.wrappedBuffer(uncompressedHeap), 0, SIZE); ByteBuf uncompressedNative = Unpooled.directBuffer(SIZE, SIZE); - try (PInflater inflater = Zlib.PROVIDER.get().inflater()) { + try (PInflater inflater = Zlib.PROVIDER.inflater()) { if (!inflater.fullInflate(compressedNative, uncompressedNative)) { throw new IllegalStateException("Couldn't inflate data!"); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java index f7710e64e..b468ad7ad 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/Zlib.java @@ -18,14 +18,17 @@ import lombok.experimental.UtilityClass; import net.daporkchop.lib.compression.zlib.java.JavaZlib; import net.daporkchop.lib.compression.zlib.natives.NativeZlib; -import net.daporkchop.lib.natives.NativeCode; +import net.daporkchop.lib.natives.FeatureBuilder; /** * @author DaPorkchop_ */ @UtilityClass public class Zlib { - public final NativeCode PROVIDER = new NativeCode<>(NativeZlib::new, JavaZlib::new); + public final ZlibProvider PROVIDER = FeatureBuilder.create(Zlib.class) + .addNative("net.daporkchop.lib.compression.zlib.natives.NativeZlib", "zlib") + .addJava("net.daporkchop.lib.compression.zlib.java.JavaZlib") + .build(); public final int LEVEL_NONE = 0; //no compression at all public final int LEVEL_FASTEST = 1; //fastest compression, worst ratio diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java index f515aa4f1..b423473c6 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDeflater.java @@ -18,7 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.compression.PDeflater; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * Extension of {@link PDeflater} for {@link Zlib}. diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java index 17eca9044..993e7a76a 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibInflater.java @@ -18,7 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.compression.PInflater; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * Extension of {@link PInflater} for {@link Zlib}. diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 868588f86..c8c5183a9 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,14 +16,15 @@ package net.daporkchop.lib.compression.zlib; -import net.daporkchop.lib.compression.util.BufferTyped; +import net.daporkchop.lib.natives.impl.Feature; +import net.daporkchop.lib.natives.util.BufferTyped; /** * Representation of a Zlib implementation. * * @author DaPorkchop_ */ -public interface ZlibProvider extends BufferTyped { +public interface ZlibProvider extends BufferTyped, Feature { /** * Creates a new {@link ZlibDeflater}. * diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java index 0c1799554..c9b3b3388 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java @@ -18,24 +18,15 @@ import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; -import net.daporkchop.lib.natives.NativeCode; +import net.daporkchop.lib.natives.FeatureBuilder; +import net.daporkchop.lib.natives.impl.NativeFeature; /** * @author DaPorkchop_ */ -public final class JavaZlib extends NativeCode.Impl implements ZlibProvider { +public final class JavaZlib extends NativeFeature implements ZlibProvider { @Override - protected ZlibProvider _get() { - return this; - } - - @Override - protected boolean _available() { - return true; - } - - @Override - public boolean direct() { + public boolean directAccepted() { return false; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 5325c595c..f2b9774ee 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -15,34 +15,22 @@ package net.daporkchop.lib.compression.zlib.natives; -import net.daporkchop.lib.compression.PDeflater; -import net.daporkchop.lib.compression.PInflater; -import net.daporkchop.lib.compression.zlib.Zlib; import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; -import net.daporkchop.lib.natives.NativeCode; +import net.daporkchop.lib.natives.impl.NativeFeature; /** * @author DaPorkchop_ */ -public final class NativeZlib extends NativeCode.NativeImpl implements ZlibProvider { +public final class NativeZlib extends NativeFeature implements ZlibProvider { static { - if (NativeCode.NativeImpl.AVAILABLE) { - NativeCode.loadNativeLibrary("zlib"); - - NativeZlibDeflater.load(); - NativeZlibInflater.load(); - } - } - - @Override - protected ZlibProvider _get() { - return this; + NativeZlibDeflater.load(); + NativeZlibInflater.load(); } @Override - public boolean direct() { + public boolean directAccepted() { return true; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 521190213..1492be46c 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -21,7 +21,7 @@ import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -61,7 +61,7 @@ public NativeZlibDeflater(int level, int strategy, int mode) { @Override public boolean fullDeflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { if (!src.hasMemoryAddress() || !dst.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.reset(); //this will do nothing if we're already reset @@ -161,7 +161,7 @@ public PDeflater reset() { @Override public PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { if (!dict.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after compression has started!"); } else if (this.dict != null) { @@ -179,7 +179,7 @@ public PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { @Override public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.src = src; return this; @@ -188,14 +188,14 @@ public PDeflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { @Override public PDeflater dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException { if (!dst.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.dst = dst; return this; } @Override - public boolean direct() { + public boolean directAccepted() { return true; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java index 4d431c8eb..6973e2943 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -18,11 +18,10 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import lombok.RequiredArgsConstructor; -import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.PInflater; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -62,7 +61,7 @@ public NativeZlibInflater(int mode) { @Override public boolean fullInflate(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { if (!src.hasMemoryAddress() || !dst.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.reset(); //this will do nothing if we're already reset @@ -166,7 +165,7 @@ public PInflater reset() { @Override public PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { if (!dict.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after decompression has started!"); } else if (this.dict != null) { @@ -181,7 +180,7 @@ public PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { @Override public PInflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { if (!src.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.src = src; return this; @@ -190,14 +189,14 @@ public PInflater src(@NonNull ByteBuf src) throws InvalidBufferTypeException { @Override public PInflater dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException { if (!dst.hasMemoryAddress()) { - throw new InvalidBufferTypeException(true); + throw InvalidBufferTypeException.direct(); } this.dst = dst; return this; } @Override - public boolean direct() { + public boolean directAccepted() { return true; } diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java index 8daf4ee1a..002d12593 100644 --- a/compression/zstd/src/example/java/ZstdTest.java +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -20,6 +20,6 @@ */ public class ZstdTest { public static void main(String... args) { - System.out.printf("original: %d, worst-case compressed: %d\n", 1 << 16L, Zstd.PROVIDER.get().compressBound(1 << 16L)); + System.out.printf("original: %d, worst-case compressed: %d\n", 1 << 16L, Zstd.PROVIDER.compressBound(1 << 16L)); } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java index a8b234031..0c0dacc68 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/Zstd.java @@ -17,14 +17,16 @@ import lombok.experimental.UtilityClass; import net.daporkchop.lib.compression.zstd.natives.NativeZstd; -import net.daporkchop.lib.natives.NativeCode; +import net.daporkchop.lib.natives.FeatureBuilder; /** * @author DaPorkchop_ */ @UtilityClass public class Zstd { - public final NativeCode PROVIDER = new NativeCode<>(NativeZstd::new); + public final ZstdProvider PROVIDER = FeatureBuilder.create(Zstd.class) + .addNative("net.daporkchop.lib.compression.zstd.natives.NativeZstd", "zstd") + .build(); public final int LEVEL_DEFAULT = 3; public final int LEVEL_MIN = -999; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index 13de4ae7a..27cf7cff7 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -17,8 +17,9 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.BufferTyped; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.impl.Feature; +import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; /** @@ -26,9 +27,9 @@ * * @author DaPorkchop_ */ -public interface ZstdProvider extends BufferTyped { +public interface ZstdProvider extends BufferTyped, Feature { @Override - boolean direct(); + boolean directAccepted(); /** * Compresses the given source data into a single Zstd frame into the given destination buffer. diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index b62964c92..50a791a6c 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -17,28 +17,18 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.natives.impl.NativeFeature; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zstd.ZstdProvider; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; -import net.daporkchop.lib.natives.NativeCode; +import net.daporkchop.lib.natives.FeatureBuilder; /** * @author DaPorkchop_ */ -public final class NativeZstd extends NativeCode.NativeImpl implements ZstdProvider { - static { - if (NativeCode.NativeImpl.AVAILABLE) { - NativeCode.loadNativeLibrary("zstd"); - } - } - - @Override - protected ZstdProvider _get() { - return this; - } - +public final class NativeZstd extends NativeFeature implements ZstdProvider { @Override - public boolean direct() { + public boolean directAccepted() { return true; } diff --git a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java index d2857e16b..8d2c46953 100644 --- a/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java +++ b/minecraft/src/main/java/net/daporkchop/lib/minecraft/world/format/anvil/AnvilWorldManager.java @@ -67,7 +67,7 @@ public class AnvilWorldManager implements WorldManager { protected static final Cache CHUNK_CACHE = ThreadCache.soft(() -> new HeapSectionImpl(-1, null)); protected static final Pattern REGION_PATTERN = Pattern.compile("^r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.mca$"); - protected static final Cache INFLATER_CACHE = ThreadCache.soft(() -> Zlib.PROVIDER.get().inflater(Zlib.MODE_AUTO)); + protected static final Cache INFLATER_CACHE = ThreadCache.soft(() -> Zlib.PROVIDER.inflater(Zlib.MODE_AUTO)); protected final AnvilSaveFormat format; protected final File root; diff --git a/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java b/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java new file mode 100644 index 000000000..f85842edb --- /dev/null +++ b/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java @@ -0,0 +1,84 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.natives; + +import lombok.AccessLevel; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.common.util.PorkUtil; +import net.daporkchop.lib.natives.impl.Feature; +import net.daporkchop.lib.natives.impl.Implementation; +import net.daporkchop.lib.natives.impl.NativeFeature; +import net.daporkchop.lib.unsafe.PUnsafe; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.function.Supplier; + +/** + * A container around multiple {@link Implementation}s of a {@link Feature}. + *

+ * Serves mainly to automatically choose the best {@link Implementation} to use, and to avoid unnecessary loading of {@link Implementation} classes that won't + * actually end up being used. + * + * @param the type of the {@link Feature} to be implemented + * @author DaPorkchop_ + */ +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +public final class FeatureBuilder> { + public static > FeatureBuilder create(@NonNull Class currentClass) { + return new FeatureBuilder<>(currentClass); + } + + private final Collection> implementations = new ArrayList<>(); + + @NonNull + private final Class currentClass; + + public FeatureBuilder addNative(@NonNull String className, @NonNull String libName) { + return this.addNative(className, libName, this.currentClass.getClassLoader()); + } + + public FeatureBuilder addNative(@NonNull String className, @NonNull String libName, @NonNull Class currentClass) { + return this.addNative(className, libName, currentClass.getClassLoader()); + } + + public FeatureBuilder addNative(@NonNull String className, @NonNull String libName, @NonNull ClassLoader loader) { + if (NativeFeature.AVAILABLE) { + this.implementations.add(() -> { + Class clazz = PorkUtil.uninitializedClassForName(className, loader); + return NativeFeature.loadNativeLibrary(libName, clazz) ? PUnsafe.allocateInstance(clazz) : null; + }); + } + return this; + } + + public FeatureBuilder addJava(@NonNull String className) { + this.implementations.add(() -> PUnsafe.allocateInstance(PorkUtil.uninitializedClassForName(className))); + return this; + } + + public F build() { + for (Supplier implementation : this.implementations) { + F value = implementation.get(); + if (value != null) { + return value; + } + } + + throw new IllegalStateException("No implementations could be loaded!"); + } +} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java b/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java deleted file mode 100644 index eeb7ce11a..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/NativeCode.java +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives; - -import lombok.Getter; -import lombok.NonNull; -import lombok.experimental.Accessors; -import net.daporkchop.lib.common.system.Architecture; -import net.daporkchop.lib.common.system.OperatingSystem; -import net.daporkchop.lib.common.system.PlatformInfo; -import net.daporkchop.lib.common.util.PorkUtil; -import net.daporkchop.lib.unsafe.PUnsafe; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.function.Supplier; - -/** - * A wrapper around multiple distinct implementations of something. - * - * @param the type of the feature to be implemented - * @author DaPorkchop_ - */ -public final class NativeCode implements Supplier { - private static String LIB_ARCH; - private static String LIB_EXT; - - public static void loadNativeLibrary(@NonNull String name) { - if (!NativeImpl.AVAILABLE) { - throw new UnsupportedOperationException("native libraries are not available!"); - } else if (LIB_ARCH == null) { - synchronized (NativeCode.class) { - if (LIB_ARCH == null) { - switch (PlatformInfo.OPERATING_SYSTEM) { - case Linux: - LIB_EXT = "so"; - switch (PlatformInfo.ARCHITECTURE) { - case x86_64: - LIB_ARCH = "x86_64-linux-gnu"; - break; - case x86: - LIB_ARCH = "x86-linux-gnu"; - break; - case AARCH64: - LIB_ARCH = "aarch64-linux-gnu"; - break; - } - break; - case Windows: - if (PlatformInfo.ARCHITECTURE == Architecture.x86_64) { - LIB_EXT = "dll"; - LIB_ARCH = "x86_64-w64-mingw32"; - } - break; - } - if (LIB_ARCH == null || LIB_EXT == null) { - throw new IllegalStateException(); - } - } - } - } - - StackTraceElement[] elements = Thread.getAllStackTraces().get(Thread.currentThread()); - Class clazz; - if (elements == null) { - //cannot get stack trace? - clazz = NativeCode.class; - } else { - //get class that called this method - int i = 0; - while ((clazz = PorkUtil.classForName(elements[i++].getClassName())) != NativeCode.class && i < elements.length); - if (clazz != NativeCode.class) { - throw new IllegalStateException(); - } - clazz = PorkUtil.classForName(elements[i].getClassName()); - } - - try { - File file = File.createTempFile(String.format("%s-%s-", name, LIB_ARCH), String.format(".%s", LIB_EXT)); - file.deleteOnExit(); - try (InputStream is = clazz.getResourceAsStream(String.format("/%s/lib%s.%s", LIB_ARCH, name, LIB_EXT)); - OutputStream os = new FileOutputStream(file)) { - byte[] arr = new byte[PUnsafe.pageSize()]; - for (int b; (b = is.read(arr)) >= 0; os.write(arr, 0, b)); - } - System.load(file.getAbsolutePath()); - } catch (Exception e) { - throw new RuntimeException(String.format("Unable to load library \"%s\"", name), e); - } - } - - private final Impl implementation; - - @SafeVarargs - public NativeCode(@NonNull Supplier>... implementationFactories) { - for (Supplier> implementationFactory : implementationFactories) { - Impl implementation = implementationFactory.get(); - if (implementation.available()) { - this.implementation = implementation; - return; - } - } - - throw new IllegalStateException("No implementations found!"); - } - - @Override - public T get() { - return this.implementation.get(); - } - - /** - * @return whether or not the currently used implementation is based on native code - */ - public boolean isNative() { - return this.implementation instanceof NativeImpl; - } - - /** - * An implementation for use by {@link NativeCode}. - * - * @param the type of the feature to be implemented - * @author DaPorkchop_ - */ - @Getter - @Accessors(fluent = true) - public static abstract class Impl implements Supplier { - protected final boolean available = this._available(); - - @Override - public T get() { - if (this.available) { - return this._get(); - } else { - throw new IllegalStateException("Not available!"); - } - } - - protected abstract T _get(); - - protected abstract boolean _available(); - } - - /** - * Extension of {@link Impl} for use by implementations that actually use native code. - *

- * Eliminates the boilerplate of checking if the current system is supported. - * - * @param the type of the feature to be implemented - * @author DaPorkchop_ - */ - public static abstract class NativeImpl extends Impl { - /** - * Whether or not native libraries are available. - */ - public static final boolean AVAILABLE = - ((PlatformInfo.ARCHITECTURE == Architecture.x86_64 || PlatformInfo.ARCHITECTURE == Architecture.AARCH64) && PlatformInfo.OPERATING_SYSTEM == OperatingSystem.Linux) - || (PlatformInfo.ARCHITECTURE == Architecture.x86_64 && PlatformInfo.OPERATING_SYSTEM == OperatingSystem.Windows); - - @Override - protected boolean _available() { - return AVAILABLE; - } - } -} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java b/natives/src/main/java/net/daporkchop/lib/natives/impl/Feature.java similarity index 69% rename from compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java rename to natives/src/main/java/net/daporkchop/lib/natives/impl/Feature.java index df7d29293..6a9cb0226 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/BufferTyped.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/impl/Feature.java @@ -13,22 +13,14 @@ * */ -package net.daporkchop.lib.compression.util; - -import net.daporkchop.lib.compression.util.exception.InvalidBufferTypeException; +package net.daporkchop.lib.natives.impl; /** - * A type that accepts {@link io.netty.buffer.ByteBuf}s, but only of a certain type (either direct or heap). - * * @author DaPorkchop_ */ -public interface BufferTyped { +public interface Feature> { /** - * Checks whether this implementation uses direct or heap memory. - *

- * {@link io.netty.buffer.ByteBuf}s of the wrong type will not be accepted by any methods, and will cause an {@link InvalidBufferTypeException} to be thrown. - * - * @return whether this implementation uses direct or heap memory + * @return whether or not this feature implementation is native */ - boolean direct(); + boolean isNative(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java b/natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java similarity index 75% rename from compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java rename to natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java index 0f18483ac..f08c93609 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidBufferTypeException.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java @@ -13,16 +13,12 @@ * */ -package net.daporkchop.lib.compression.util.exception; +package net.daporkchop.lib.natives.impl; /** - * Thrown when a {@link io.netty.buffer.ByteBuf} argument to a {@link net.daporkchop.lib.compression.PInflater} or {@link net.daporkchop.lib.compression.PDeflater} - * is of the wrong type. + * Base representation of an implementation of a {@link Feature}. * * @author DaPorkchop_ */ -public final class InvalidBufferTypeException extends IllegalArgumentException { - public InvalidBufferTypeException(boolean direct) { - super(direct ? "direct buffer expected!" : "heap buffer expected!"); - } +public interface Implementation & Feature, F extends Feature> { } diff --git a/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java b/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java new file mode 100644 index 000000000..4d6ff45b9 --- /dev/null +++ b/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java @@ -0,0 +1,101 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.natives.impl; + +import lombok.NonNull; +import net.daporkchop.lib.common.system.PlatformInfo; +import net.daporkchop.lib.common.util.PorkUtil; +import net.daporkchop.lib.unsafe.PUnsafe; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Abstraction of an {@link Implementation} of a {@link Feature} using native code. + * + * @author DaPorkchop_ + */ +public abstract class NativeFeature, F extends Feature> implements Feature, Implementation { + private static final String LIB_FMT; + private static final String LIB_EXT; + + public static final boolean AVAILABLE; + + static { + //these are the platforms that we compile native libraries for + switch (PlatformInfo.OPERATING_SYSTEM) { + case Linux: + switch (PlatformInfo.ARCHITECTURE) { + case AARCH64: + LIB_FMT = "/aarch64-linux-gnu/lib"; + break; + case x86_64: + LIB_FMT = "/x86_64-linux-gnu/lib"; + break; + default: + LIB_FMT = null; + } + LIB_EXT = LIB_FMT == null ? null : ".so"; + break; + case Windows: + switch (PlatformInfo.ARCHITECTURE) { + case x86_64: + LIB_FMT = "/x86_64-w64-mingw32/lib"; + break; + default: + LIB_FMT = null; + } + LIB_EXT = LIB_FMT == null ? null : ".dll"; + break; + default: + LIB_EXT = LIB_FMT = null; + } + + AVAILABLE = LIB_FMT != null; + } + + public static boolean loadNativeLibrary(@NonNull String name, @NonNull Class clazz) { + if (!NativeFeature.AVAILABLE) { + return false; + } + + try (InputStream is = clazz.getResourceAsStream(LIB_FMT + name + LIB_EXT)) { + if (is == null) { + //library doesn't exist + return false; + } + + File file = File.createTempFile(name, LIB_EXT); + file.deleteOnExit(); + try (OutputStream os = new FileOutputStream(file)) { + byte[] arr = new byte[PUnsafe.pageSize()]; + for (int b; (b = is.read(arr)) >= 0; os.write(arr, 0, b)) ; + } + System.load(file.getAbsolutePath()); + } catch (Exception e) { + throw new RuntimeException(String.format("Unable to load library \"%s\"", name), e); + } + + return true; + } + + @Override + public boolean isNative() { + return true; + } +} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/util/BufferTyped.java b/natives/src/main/java/net/daporkchop/lib/natives/util/BufferTyped.java new file mode 100644 index 000000000..fbf4e91b4 --- /dev/null +++ b/natives/src/main/java/net/daporkchop/lib/natives/util/BufferTyped.java @@ -0,0 +1,64 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.natives.util; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; + +/** + * A type with method(s) that accept {@link ByteBuf}(s) as parameters, but are restricted to either direct buffers only or heap buffers only. Attempting to + * pass a {@link ByteBuf} of an unsupported type to any superclass methods will result in an {@link InvalidBufferTypeException}. + * + * @author DaPorkchop_ + */ +public interface BufferTyped { + /** + * @return whether this implementation accepts direct buffers + */ + boolean directAccepted(); + + /** + * @return whether this implementation accepts heap buffers + */ + default boolean heapAccepted() { + return !this.directAccepted(); + } + + /** + * Checks whether the given {@link ByteBuf} is accepted by this implementation. + * + * @param buf the {@link ByteBuf} to check + * @return whether or not the given {@link ByteBuf} is accepted + */ + default boolean isAcceptable(@NonNull ByteBuf buf) { + return (this.directAccepted() && buf.hasMemoryAddress()) || (this.heapAccepted() && buf.hasArray()); + } + + /** + * Ensures that the given {@link ByteBuf} will be accepted by this implementation. + * + * @param buf the {@link ByteBuf} to check + * @return the {@link ByteBuf} + * @throws InvalidBufferTypeException if the given {@link ByteBuf} is not acceptable + */ + default ByteBuf assertAcceptable(@NonNull ByteBuf buf) throws InvalidBufferTypeException { + if (!this.isAcceptable(buf)) { + throw InvalidBufferTypeException.of(this.directAccepted(), this.heapAccepted()); + } + return buf; + } +} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/util/exception/InvalidBufferTypeException.java b/natives/src/main/java/net/daporkchop/lib/natives/util/exception/InvalidBufferTypeException.java new file mode 100644 index 000000000..289290bd3 --- /dev/null +++ b/natives/src/main/java/net/daporkchop/lib/natives/util/exception/InvalidBufferTypeException.java @@ -0,0 +1,51 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.natives.util.exception; + +/** + * Thrown when a {@link io.netty.buffer.ByteBuf} argument to an implementation of {@link net.daporkchop.lib.natives.util.BufferTyped} is of the wrong type. + * + * @author DaPorkchop_ + */ +public final class InvalidBufferTypeException extends IllegalArgumentException { + public static InvalidBufferTypeException direct() { + return new InvalidBufferTypeException("direct buffer expected!"); + } + + public static InvalidBufferTypeException heap() { + return new InvalidBufferTypeException("heap buffer expected!"); + } + + public static InvalidBufferTypeException any() { + return new InvalidBufferTypeException("either direct or heap buffer expected!"); + } + + public static InvalidBufferTypeException of(boolean directAccepted, boolean heapAccepted) { + if (directAccepted && heapAccepted) { + return any(); + } else if (directAccepted) { + return direct(); + } else if (heapAccepted) { + return heap(); + } else { + throw new IllegalArgumentException("neither direct nor heap buffers are accepted?!?"); + } + } + + private InvalidBufferTypeException(String s) { + super(s); + } +} From 6232fc9fa6f0ee2dc7fd40908cb6bfcd2baa0bfe Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 16:26:45 +0100 Subject: [PATCH 24/36] basic usable zstd implementation only implements the "Simple API" atm --- .../lib/common/util/PValidation.java | 80 +++++++++++++++++++ .../lib/compression/zlib/java/JavaZlib.java | 2 +- .../compression/zlib/natives/NativeZlib.java | 2 +- .../zstd/src/example/java/ZstdTest.java | 38 +++++++++ .../compression/zstd/natives/NativeZstd.java | 55 ++++++++++--- .../src/main/native/common/NativeZstd.cpp | 48 ++++++++++- .../zstd/src/main/native/common/NativeZstd.h | 24 ++++++ natives/Makefile | 2 + natives/compile.sh | 2 +- .../lib/natives/FeatureBuilder.java | 7 +- .../lib/natives/impl/Implementation.java | 24 ------ .../lib/natives/impl/NativeFeature.java | 4 +- natives/toolchain/aarch64-linux-gnu | 6 +- natives/toolchain/x86_64-linux-gnu | 6 +- 14 files changed, 247 insertions(+), 53 deletions(-) create mode 100644 common/src/main/java/net/daporkchop/lib/common/util/PValidation.java delete mode 100644 natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java new file mode 100644 index 000000000..403070e3b --- /dev/null +++ b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java @@ -0,0 +1,80 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.common.util; + +import lombok.experimental.UtilityClass; + +/** + * @author DaPorkchop_ + */ +@UtilityClass +public class PValidation { + public long ensureNonNegative(long value) { + if (value < 0L) { + throw new IllegalArgumentException(value + " < 0"); + } + return value; + } + + public int ensureNonNegative(int value) { + if (value < 0) { + throw new IllegalArgumentException(value + " < 0"); + } + return value; + } + + public long ensureNonPositive(long value) { + if (value > 0L) { + throw new IllegalArgumentException(value + " > 0"); + } + return value; + } + + public int ensureNonPositive(int value) { + if (value > 0) { + throw new IllegalArgumentException(value + " > 0"); + } + return value; + } + + public long ensurePositive(long value) { + if (value <= 0L) { + throw new IllegalArgumentException(value + " <= 0"); + } + return value; + } + + public int ensurePositive(int value) { + if (value <= 0) { + throw new IllegalArgumentException(value + " <= 0"); + } + return value; + } + + public long ensureNegative(long value) { + if (value >= 0L) { + throw new IllegalArgumentException(value + " >= 0"); + } + return value; + } + + public int ensureNegative(int value) { + if (value >= 0) { + throw new IllegalArgumentException(value + " >= 0"); + } + return value; + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java index c9b3b3388..92024b893 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java @@ -24,7 +24,7 @@ /** * @author DaPorkchop_ */ -public final class JavaZlib extends NativeFeature implements ZlibProvider { +public final class JavaZlib extends NativeFeature implements ZlibProvider { @Override public boolean directAccepted() { return false; diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index f2b9774ee..da0f8630d 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -23,7 +23,7 @@ /** * @author DaPorkchop_ */ -public final class NativeZlib extends NativeFeature implements ZlibProvider { +public final class NativeZlib extends NativeFeature implements ZlibProvider { static { NativeZlibDeflater.load(); NativeZlibInflater.load(); diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java index 002d12593..c928cbf83 100644 --- a/compression/zstd/src/example/java/ZstdTest.java +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -13,13 +13,51 @@ * */ +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import lombok.NonNull; import net.daporkchop.lib.compression.zstd.Zstd; +import java.util.concurrent.ThreadLocalRandom; + /** * @author DaPorkchop_ */ public class ZstdTest { + private static final int SIZE = 1 << 26; // 64 MiB + + private static final int BOUND_SIZE = (int) Zstd.PROVIDER.compressBound(SIZE); + public static void main(String... args) { System.out.printf("original: %d, worst-case compressed: %d\n", 1 << 16L, Zstd.PROVIDER.compressBound(1 << 16L)); + + ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); + for (int i = 0; i < SIZE; i++) { + original.setByte(i, i & 0xFF); + } + for (int i = 0; i < 256; i += 8) { + original.setLongLE(i, ThreadLocalRandom.current().nextLong()); + } + + ByteBuf compressed = Unpooled.directBuffer(BOUND_SIZE, BOUND_SIZE); + + Zstd.PROVIDER.compress(original.slice(), compressed, Zstd.LEVEL_DEFAULT); + System.out.printf("original: %d, compressed: %d\n", original.readableBytes(), compressed.readableBytes()); + + int uncompressedSize = (int) Zstd.PROVIDER.frameContentSize(compressed); + System.out.printf("original size: %d, frame content size: %d\n", SIZE, uncompressedSize); + ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); + + Zstd.PROVIDER.decompress(compressed, uncompressed); + + validateEqual(original, uncompressed, 0, SIZE); + } + + private static void validateEqual(@NonNull ByteBuf a, @NonNull ByteBuf b, int start, int size) { + for (int i = 0; i < size; i++) { + if (a.getByte(start + i) != b.getByte(start + i)) { + throw new IllegalStateException(); + } + } } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 50a791a6c..3d4605e08 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -17,16 +17,16 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.natives.impl.NativeFeature; -import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.compression.zstd.ZstdProvider; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; -import net.daporkchop.lib.natives.FeatureBuilder; +import net.daporkchop.lib.natives.impl.NativeFeature; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * @author DaPorkchop_ */ -public final class NativeZstd extends NativeFeature implements ZstdProvider { +public final class NativeZstd extends NativeFeature implements ZstdProvider { @Override public boolean directAccepted() { return true; @@ -34,25 +34,58 @@ public boolean directAccepted() { @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { - return false; + this.assertAcceptable(src); + this.assertAcceptable(dst); + + int val = this.doCompress(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + compressionLevel); + + if (val >= 0) { + src.skipBytes(src.readableBytes()); + dst.writerIndex(dst.writerIndex() + val); + return true; + } else { + return false; + } } + private native int doCompress(long srcAddr, int srcSize, long dstAddr, int dstSize, int compressionLevel); + @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - return false; + this.assertAcceptable(src); + this.assertAcceptable(dst); + + int val = this.doDecompress(src.memoryAddress() + src.readerIndex(), src.readableBytes(), + dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); + + if (val >= 0) { + src.skipBytes(src.readableBytes()); + dst.writerIndex(dst.writerIndex() + val); + return true; + } else { + return false; + } } + private native int doDecompress(long srcAddr, int srcSize, long dstAddr, int dstSize); + @Override public long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException { - return 0; + long size = this.doFrameContentSize(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes()); + if (size >= 0L) { + return size; + } else { + throw new ContentSizeUnknownException(); + } } + private native long doFrameContentSize(long srcAddr, int srcSize); + @Override public long compressBound(long srcSize) { - if (srcSize < 0L) { - throw new IllegalArgumentException(String.valueOf(srcSize)); - } - return this.doCompressBound(srcSize); + return this.doCompressBound(PValidation.ensureNonNegative(srcSize)); } private native long doCompressBound(long srcSize); diff --git a/compression/zstd/src/main/native/common/NativeZstd.cpp b/compression/zstd/src/main/native/common/NativeZstd.cpp index 0624ca2e2..5cedb4fc0 100644 --- a/compression/zstd/src/main/native/common/NativeZstd.cpp +++ b/compression/zstd/src/main/native/common/NativeZstd.cpp @@ -2,16 +2,58 @@ #include "NativeZstd.h" #include +#include #include #include #include -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound - (JNIEnv* env, jobject obj, jlong srcSize) { +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompress + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jint compressionLevel) { + auto ret = ZSTD_compress((void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doDecompress + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + auto ret = ZSTD_decompress((void*) dstAddr, dstSize, (void*) srcAddr, srcSize); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } - printf("min: %d, max: %d\n", ZSTD_minCLevel(), ZSTD_maxCLevel()); + return (jint) ret; +} + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSize + (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize) { + auto contentSize = ZSTD_getFrameContentSize((void*) srcAddr, srcSize); + if (contentSize == ZSTD_CONTENTSIZE_ERROR) { + throwException(env, "ZSTD_CONTENTSIZE_ERROR", (int) ZSTD_CONTENTSIZE_ERROR); + return 0; + } + + return contentSize; +} + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound + (JNIEnv* env, jobject obj, jlong srcSize) { return ZSTD_compressBound(srcSize); } diff --git a/compression/zstd/src/main/native/common/NativeZstd.h b/compression/zstd/src/main/native/common/NativeZstd.h index ee6a7dcd7..7b99ba044 100644 --- a/compression/zstd/src/main/native/common/NativeZstd.h +++ b/compression/zstd/src/main/native/common/NativeZstd.h @@ -10,6 +10,30 @@ extern "C" { #endif +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstd + * Method: doCompress + * Signature: (JIJII)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompress + (JNIEnv *, jobject, jlong, jint, jlong, jint, jint); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstd + * Method: doDecompress + * Signature: (JIJI)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doDecompress + (JNIEnv *, jobject, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstd + * Method: doFrameContentSize + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSize + (JNIEnv *, jobject, jlong, jint); + /* * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstd * Method: doCompressBound diff --git a/natives/Makefile b/natives/Makefile index 286598c4e..3bd001bb5 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -1,5 +1,7 @@ export SHELL := /bin/bash +export NPROC := $(shell nproc) + export TARGET := $(shell basename $(CURDIR)) export TOPDIR := $(CURDIR) export TOOLCHAINS := $(CURDIR)/toolchain diff --git a/natives/compile.sh b/natives/compile.sh index 876593fdf..23a203d85 100644 --- a/natives/compile.sh +++ b/natives/compile.sh @@ -3,4 +3,4 @@ #i use this script simply so that i can add the natives compilation as a run configuration in intellij #make clean && \ -make -j$( nproc ) +make -j$( nproc ) build.x86_64-linux-gnu diff --git a/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java b/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java index f85842edb..3561cd0c8 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/FeatureBuilder.java @@ -20,7 +20,6 @@ import lombok.RequiredArgsConstructor; import net.daporkchop.lib.common.util.PorkUtil; import net.daporkchop.lib.natives.impl.Feature; -import net.daporkchop.lib.natives.impl.Implementation; import net.daporkchop.lib.natives.impl.NativeFeature; import net.daporkchop.lib.unsafe.PUnsafe; @@ -29,10 +28,10 @@ import java.util.function.Supplier; /** - * A container around multiple {@link Implementation}s of a {@link Feature}. + * A container around multiple implementations of a {@link Feature}. *

- * Serves mainly to automatically choose the best {@link Implementation} to use, and to avoid unnecessary loading of {@link Implementation} classes that won't - * actually end up being used. + * Serves mainly to automatically choose the best implementation to use, and to avoid unnecessary loading of implementation classes that won't actually end + * up being used. * * @param the type of the {@link Feature} to be implemented * @author DaPorkchop_ diff --git a/natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java b/natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java deleted file mode 100644 index f08c93609..000000000 --- a/natives/src/main/java/net/daporkchop/lib/natives/impl/Implementation.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Adapted from the Wizardry License - * - * Copyright (c) 2018-2020 DaPorkchop_ and contributors - * - * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. - * - * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. - * - * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - */ - -package net.daporkchop.lib.natives.impl; - -/** - * Base representation of an implementation of a {@link Feature}. - * - * @author DaPorkchop_ - */ -public interface Implementation & Feature, F extends Feature> { -} diff --git a/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java b/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java index 4d6ff45b9..22432706c 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/impl/NativeFeature.java @@ -26,11 +26,11 @@ import java.io.OutputStream; /** - * Abstraction of an {@link Implementation} of a {@link Feature} using native code. + * Abstraction of an implementation of a {@link Feature} using native code. * * @author DaPorkchop_ */ -public abstract class NativeFeature, F extends Feature> implements Feature, Implementation { +public abstract class NativeFeature> implements Feature { private static final String LIB_FMT; private static final String LIB_EXT; diff --git a/natives/toolchain/aarch64-linux-gnu b/natives/toolchain/aarch64-linux-gnu index dac4e21a5..73e5dca80 100644 --- a/natives/toolchain/aarch64-linux-gnu +++ b/natives/toolchain/aarch64-linux-gnu @@ -1,6 +1,6 @@ -export CFLAGS := $(CFLAGS) -flto=auto -fno-fat-lto-objects -export CXXFLAGS := $(CXXFLAGS) -flto=auto -fno-fat-lto-objects -export LDFLAGS := $(LDFLAGS) -flto=auto -fno-fat-lto-objects +export CFLAGS := $(CFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +export CXXFLAGS := $(CXXFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +export LDFLAGS := $(LDFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export CC := aarch64-linux-gnu-gcc export CXX := aarch64-linux-gnu-g++ diff --git a/natives/toolchain/x86_64-linux-gnu b/natives/toolchain/x86_64-linux-gnu index c5dee7ce7..6f0664194 100644 --- a/natives/toolchain/x86_64-linux-gnu +++ b/natives/toolchain/x86_64-linux-gnu @@ -1,6 +1,6 @@ -export CFLAGS := $(CFLAGS) -flto=auto -fno-fat-lto-objects -export CXXFLAGS := $(CXXFLAGS) -flto=auto -fno-fat-lto-objects -export LDFLAGS := $(LDFLAGS) -flto=auto -fno-fat-lto-objects +export CFLAGS := $(CFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +export CXXFLAGS := $(CXXFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +export LDFLAGS := $(LDFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export CC := x86_64-linux-gnu-gcc export CXX := x86_64-linux-gnu-g++ From 95aad4bafd88374a00d2b8ac0175f5fb151b8304 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sun, 9 Feb 2020 17:27:39 +0100 Subject: [PATCH 25/36] implement zstd compression context --- .../lib/common/util/PValidation.java | 76 ++++++++++++++----- .../zstd/src/example/java/ZstdTest.java | 38 +++++++--- .../lib/compression/zstd/ZstdCCtx.java | 53 +++++++++++++ .../lib/compression/zstd/ZstdProvider.java | 16 +++- .../compression/zstd/natives/NativeZstd.java | 13 ++-- .../zstd/natives/NativeZstdCCtx.java | 76 +++++++++++++++++++ .../src/main/native/common/NativeZstdCCtx.cpp | 41 ++++++++++ .../src/main/native/common/NativeZstdCCtx.h | 41 ++++++++++ 8 files changed, 320 insertions(+), 34 deletions(-) create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java create mode 100644 compression/zstd/src/main/native/common/NativeZstdCCtx.cpp create mode 100644 compression/zstd/src/main/native/common/NativeZstdCCtx.h diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java index 403070e3b..70849b354 100644 --- a/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java +++ b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java @@ -22,16 +22,16 @@ */ @UtilityClass public class PValidation { - public long ensureNonNegative(long value) { - if (value < 0L) { - throw new IllegalArgumentException(value + " < 0"); + public long ensurePositive(long value) { + if (value <= 0L) { + throw new IllegalArgumentException(value + " <= 0"); } return value; } - public int ensureNonNegative(int value) { - if (value < 0) { - throw new IllegalArgumentException(value + " < 0"); + public int ensurePositive(int value) { + if (value <= 0) { + throw new IllegalArgumentException(value + " <= 0"); } return value; } @@ -50,31 +50,71 @@ public int ensureNonPositive(int value) { return value; } - public long ensurePositive(long value) { - if (value <= 0L) { - throw new IllegalArgumentException(value + " <= 0"); + public long ensureNegative(long value) { + if (value >= 0L) { + throw new IllegalArgumentException(value + " >= 0"); } return value; } - public int ensurePositive(int value) { - if (value <= 0) { - throw new IllegalArgumentException(value + " <= 0"); + public int ensureNegative(int value) { + if (value >= 0) { + throw new IllegalArgumentException(value + " >= 0"); } return value; } - public long ensureNegative(long value) { - if (value >= 0L) { - throw new IllegalArgumentException(value + " >= 0"); + public long ensureNonNegative(long value) { + if (value < 0L) { + throw new IllegalArgumentException(value + " < 0"); } return value; } - public int ensureNegative(int value) { - if (value >= 0) { - throw new IllegalArgumentException(value + " >= 0"); + public int ensureNonNegative(int value) { + if (value < 0) { + throw new IllegalArgumentException(value + " < 0"); } return value; } + + public int toIntSafe(long value) { + int i = (int) value; + if (i != value) { + throw new IllegalArgumentException(value + " cannot fit in an int!"); + } + return i; + } + + public int toPositiveIntSafe(long value) { + int i = (int) ensurePositive(value); + if (i != value) { + throw new IllegalArgumentException(value + " cannot fit in an int!"); + } + return i; + } + + public int toNonPositiveIntSafe(long value) { + int i = (int) ensureNonPositive(value); + if (i != value) { + throw new IllegalArgumentException(value + " cannot fit in an int!"); + } + return i; + } + + public int toNegativeIntSafe(long value) { + int i = (int) ensureNegative(value); + if (i != value) { + throw new IllegalArgumentException(value + " cannot fit in an int!"); + } + return i; + } + + public int toNonNegativeIntSafe(long value) { + int i = (int) ensureNonNegative(value); + if (i != value) { + throw new IllegalArgumentException(value + " cannot fit in an int!"); + } + return i; + } } diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java index c928cbf83..a5e83cf20 100644 --- a/compression/zstd/src/example/java/ZstdTest.java +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -16,7 +16,9 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import lombok.NonNull; +import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.compression.zstd.Zstd; +import net.daporkchop.lib.compression.zstd.ZstdCCtx; import java.util.concurrent.ThreadLocalRandom; @@ -24,14 +26,14 @@ * @author DaPorkchop_ */ public class ZstdTest { - private static final int SIZE = 1 << 26; // 64 MiB + private static final int SIZE = 1 << 26; // 64 MiB - private static final int BOUND_SIZE = (int) Zstd.PROVIDER.compressBound(SIZE); + private static final int BOUND_SIZE = PValidation.toPositiveIntSafe(Zstd.PROVIDER.compressBound(SIZE)); public static void main(String... args) { System.out.printf("original: %d, worst-case compressed: %d\n", 1 << 16L, Zstd.PROVIDER.compressBound(1 << 16L)); - ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE); + ByteBuf original = Unpooled.directBuffer(SIZE, SIZE).clear().ensureWritable(SIZE).writerIndex(SIZE).markWriterIndex(); for (int i = 0; i < SIZE; i++) { original.setByte(i, i & 0xFF); } @@ -41,16 +43,32 @@ public static void main(String... args) { ByteBuf compressed = Unpooled.directBuffer(BOUND_SIZE, BOUND_SIZE); - Zstd.PROVIDER.compress(original.slice(), compressed, Zstd.LEVEL_DEFAULT); - System.out.printf("original: %d, compressed: %d\n", original.readableBytes(), compressed.readableBytes()); + if (true) { //benchmark simple vs context compression + long start = System.currentTimeMillis(); + for (int i = 0; i < 256; i++) { + Zstd.PROVIDER.compress(original.clear().resetWriterIndex(), compressed.clear(), Zstd.LEVEL_MAX); + } + System.out.printf("simple: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); + + start = System.currentTimeMillis(); + try (ZstdCCtx ctx = Zstd.PROVIDER.compressionContext()) { + for (int i = 0; i < 256; i++) { + ctx.compress(original.clear().resetWriterIndex(), compressed.clear(), Zstd.LEVEL_MAX); + } + } + System.out.printf("context: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); + } else if (false) { + Zstd.PROVIDER.compress(original.slice(), compressed, Zstd.LEVEL_DEFAULT); + System.out.printf("original: %d, compressed: %d\n", original.readableBytes(), compressed.readableBytes()); - int uncompressedSize = (int) Zstd.PROVIDER.frameContentSize(compressed); - System.out.printf("original size: %d, frame content size: %d\n", SIZE, uncompressedSize); - ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); + int uncompressedSize = PValidation.toPositiveIntSafe(Zstd.PROVIDER.frameContentSize(compressed)); + System.out.printf("original size: %d, frame content size: %d\n", SIZE, uncompressedSize); + ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); - Zstd.PROVIDER.decompress(compressed, uncompressed); + Zstd.PROVIDER.decompress(compressed, uncompressed); - validateEqual(original, uncompressed, 0, SIZE); + validateEqual(original, uncompressed, 0, SIZE); + } } private static void validateEqual(@NonNull ByteBuf a, @NonNull ByteBuf b, int start, int size) { diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java new file mode 100644 index 000000000..080ff30c4 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java @@ -0,0 +1,53 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.capability.Releasable; + +/** + * Compression context for {@link Zstd}. + *

+ * Not thread-safe. + * + * @author DaPorkchop_ + */ +public interface ZstdCCtx extends BufferTyped, Releasable { + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer at the default compression level. + * + * @see #compress(ByteBuf, ByteBuf, int) + */ + default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return this.compress(src, dst, Zstd.LEVEL_DEFAULT); + } + + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer. + *

+ * If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read source data from + * @param dst the {@link ByteBuf} to write compressed data to + * @param compressionLevel the Zstd level to compress at + * @return whether or not compression was successful. If {@code false}, the destination buffer was too small for the compressed data + */ + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException; +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index 27cf7cff7..f886b592a 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -17,10 +17,10 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; +import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.Feature; import net.daporkchop.lib.natives.util.BufferTyped; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; -import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; /** * Representation of a Zstd implementation. @@ -31,6 +31,15 @@ public interface ZstdProvider extends BufferTyped, Feature { @Override boolean directAccepted(); + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer at the default compression level. + * + * @see #compress(ByteBuf, ByteBuf, int) + */ + default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return this.compress(src, dst, Zstd.LEVEL_DEFAULT); + } + /** * Compresses the given source data into a single Zstd frame into the given destination buffer. *

@@ -72,4 +81,9 @@ public interface ZstdProvider extends BufferTyped, Feature { * @return the worst-case size of the compressed data */ long compressBound(long srcSize); + + /** + * @return a re-usable context for simple compression + */ + ZstdCCtx compressionContext(); } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 3d4605e08..23e1cd631 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.compression.zstd.ZstdProvider; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.NativeFeature; @@ -34,11 +35,8 @@ public boolean directAccepted() { @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { - this.assertAcceptable(src); - this.assertAcceptable(dst); - - int val = this.doCompress(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes(), + int val = this.doCompress(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), compressionLevel); if (val >= 0) { @@ -89,4 +87,9 @@ public long compressBound(long srcSize) { } private native long doCompressBound(long srcSize); + + @Override + public ZstdCCtx compressionContext() { + return new NativeZstdCCtx(); + } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java new file mode 100644 index 000000000..d70ec568e --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java @@ -0,0 +1,76 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; + +/** + * Native implementation of {@link ZstdCCtx}. + * + * @author DaPorkchop_ + */ +final class NativeZstdCCtx extends AbstractReleasable implements ZstdCCtx { + private static native long allocateCtx(); + + private static native void releaseCtx(long ctx); + + private final long ctx = allocateCtx(); + private final PCleaner cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + + @Override + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { + int val = this.doCompress(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + compressionLevel); + + if (val >= 0) { + src.skipBytes(src.readableBytes()); + dst.writerIndex(dst.writerIndex() + val); + return true; + } else { + return false; + } + } + + private native int doCompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, int compressionLevel); + + @Override + public boolean directAccepted() { + return true; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long ctx; + + @Override + public void run() { + releaseCtx(this.ctx); + } + } +} diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp new file mode 100644 index 000000000..93c74cf48 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp @@ -0,0 +1,41 @@ +#include +#include "NativeZstdCCtx.h" + +#include +#include + +#include +#include + +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_allocateCtx + (JNIEnv* env, jclass cla) { + return (jlong) ZSTD_createCCtx(); +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_releaseCtx + (JNIEnv* env, jclass cla, jlong ctx) { + auto ret = ZSTD_freeCCtx((ZSTD_CCtx*) ctx); + + if (ZSTD_isError(ret)) { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return; + } +} + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jint compressionLevel) { + auto ret = ZSTD_compressCCtx((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.h b/compression/zstd/src/main/native/common/NativeZstdCCtx.h new file mode 100644 index 000000000..ffa7a5937 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.h @@ -0,0 +1,41 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx +#define _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + * Method: allocateCtx + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_allocateCtx + (JNIEnv *, jclass); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + * Method: releaseCtx + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_releaseCtx + (JNIEnv *, jclass, jlong); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + * Method: doCompress + * Signature: (JJIJII)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jint); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd From aa8a997b167384f729e1b3b03309340df5162be0 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Mon, 10 Feb 2020 17:44:34 +0100 Subject: [PATCH 26/36] decompression context as well --- .../zstd/src/example/java/ZstdTest.java | 42 +++++++++- .../lib/compression/zstd/ZstdDCtx.java | 43 +++++++++++ .../lib/compression/zstd/ZstdProvider.java | 5 ++ .../compression/zstd/natives/NativeZstd.java | 6 ++ .../zstd/natives/NativeZstdDCtx.java | 76 +++++++++++++++++++ .../src/main/native/common/NativeZstdDCtx.cpp | 41 ++++++++++ .../src/main/native/common/NativeZstdDCtx.h | 41 ++++++++++ 7 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java create mode 100644 compression/zstd/src/main/native/common/NativeZstdDCtx.cpp create mode 100644 compression/zstd/src/main/native/common/NativeZstdDCtx.h diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java index a5e83cf20..4e5c7bc03 100644 --- a/compression/zstd/src/example/java/ZstdTest.java +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -19,6 +19,7 @@ import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.compression.zstd.Zstd; import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdDCtx; import java.util.concurrent.ThreadLocalRandom; @@ -43,20 +44,55 @@ public static void main(String... args) { ByteBuf compressed = Unpooled.directBuffer(BOUND_SIZE, BOUND_SIZE); - if (true) { //benchmark simple vs context compression + if (false) { //benchmark simple vs context compression long start = System.currentTimeMillis(); for (int i = 0; i < 256; i++) { - Zstd.PROVIDER.compress(original.clear().resetWriterIndex(), compressed.clear(), Zstd.LEVEL_MAX); + if (!Zstd.PROVIDER.compress(original.clear().writerIndex(SIZE), compressed.clear(), Zstd.LEVEL_MAX)) { + throw new IllegalStateException(); + } } System.out.printf("simple: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); start = System.currentTimeMillis(); try (ZstdCCtx ctx = Zstd.PROVIDER.compressionContext()) { for (int i = 0; i < 256; i++) { - ctx.compress(original.clear().resetWriterIndex(), compressed.clear(), Zstd.LEVEL_MAX); + if (!ctx.compress(original.clear().writerIndex(SIZE), compressed.clear(), Zstd.LEVEL_MAX)) { + throw new IllegalStateException(); + } + } + } + System.out.printf("context: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); + } else if (true) { //benchmark simple vs context decompression + Zstd.PROVIDER.compress(original.clear().writerIndex(SIZE), compressed.clear(), Zstd.LEVEL_MAX); + compressed.markWriterIndex(); + + int uncompressedSize = PValidation.toPositiveIntSafe(Zstd.PROVIDER.frameContentSize(compressed)); + ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); + + long start = System.currentTimeMillis(); + for (int i = 0; i < 256; i++) { + if (!Zstd.PROVIDER.decompress(compressed.clear().resetWriterIndex(), uncompressed.clear())) { + throw new IllegalStateException(); + } + } + System.out.printf("simple: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); + + start = System.currentTimeMillis(); + try (ZstdDCtx ctx = Zstd.PROVIDER.decompressionContext()) { + for (int i = 0; i < 256; i++) { + if (!ctx.decompress(compressed.clear().resetWriterIndex(), uncompressed.clear())) { + throw new IllegalStateException(); + } } } System.out.printf("context: %.2fs\n", (System.currentTimeMillis() - start) / 1000.0d); + + try (ZstdDCtx ctx = Zstd.PROVIDER.decompressionContext()) { + if (!ctx.decompress(compressed.clear().resetWriterIndex(), uncompressed.clear())) { + throw new IllegalStateException(); + } + } + validateEqual(original, uncompressed, 0, SIZE); } else if (false) { Zstd.PROVIDER.compress(original.slice(), compressed, Zstd.LEVEL_DEFAULT); System.out.printf("original: %d, compressed: %d\n", original.readableBytes(), compressed.readableBytes()); diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java new file mode 100644 index 000000000..d2b8029d4 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java @@ -0,0 +1,43 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.capability.Releasable; + +/** + * Deompression context for {@link Zstd}. + *

+ * Not thread-safe. + * + * @author DaPorkchop_ + */ +public interface ZstdDCtx extends BufferTyped, Releasable { + /** + * Decompresses the given Zstd-compressed into the given destination buffer. + *

+ * If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read compressed data from + * @param dst the {@link ByteBuf} to write decompressed data to + * @return whether or not decompression was successful. If {@code false}, the destination buffer was too small for the decompressed data + */ + boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index f886b592a..928c58632 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -86,4 +86,9 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva * @return a re-usable context for simple compression */ ZstdCCtx compressionContext(); + + /** + * @return a re-usable context for simple decompression + */ + ZstdDCtx decompressionContext(); } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 23e1cd631..4f7020d3c 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -19,6 +19,7 @@ import lombok.NonNull; import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdDCtx; import net.daporkchop.lib.compression.zstd.ZstdProvider; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.NativeFeature; @@ -92,4 +93,9 @@ public long compressBound(long srcSize) { public ZstdCCtx compressionContext() { return new NativeZstdCCtx(); } + + @Override + public ZstdDCtx decompressionContext() { + return new NativeZstdDCtx(); + } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java new file mode 100644 index 000000000..50b30d04b --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java @@ -0,0 +1,76 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdDCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; + +/** + * Native implementation of {@link ZstdCCtx}. + * + * @author DaPorkchop_ + */ +final class NativeZstdDCtx extends AbstractReleasable implements ZstdDCtx { + private static native long allocateCtx(); + + private static native void releaseCtx(long ctx); + + private final long ctx = allocateCtx(); + private final PCleaner cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + + @Override + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + int val = this.doDecompress(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes()); + + if (val >= 0) { + src.skipBytes(src.readableBytes()); + dst.writerIndex(dst.writerIndex() + val); + return true; + } else { + return false; + } + } + + private native int doDecompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public boolean directAccepted() { + return true; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long ctx; + + @Override + public void run() { + releaseCtx(this.ctx); + } + } +} diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp new file mode 100644 index 000000000..3f33d9f67 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp @@ -0,0 +1,41 @@ +#include +#include "NativeZstdDCtx.h" + +#include +#include + +#include +#include + +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_allocateCtx + (JNIEnv* env, jclass cla) { + return (jlong) ZSTD_createDCtx(); +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_releaseCtx + (JNIEnv* env, jclass cla, jlong ctx) { + auto ret = ZSTD_freeDCtx((ZSTD_DCtx*) ctx); + + if (ZSTD_isError(ret)) { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return; + } +} + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + auto ret = ZSTD_decompressDCtx((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.h b/compression/zstd/src/main/native/common/NativeZstdDCtx.h new file mode 100644 index 000000000..ec3a53846 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.h @@ -0,0 +1,41 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx +#define _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + * Method: allocateCtx + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_allocateCtx + (JNIEnv *, jclass); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + * Method: releaseCtx + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_releaseCtx + (JNIEnv *, jclass, jlong); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + * Method: doDecompress + * Signature: (JJIJI)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd From fc5a1e7957bf55b2125c9f4e1cd83b22b4f9744d Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Tue, 11 Feb 2020 14:55:53 +0100 Subject: [PATCH 27/36] some random cleanup that really shouldn't be on this branch, but whatever --- .../lib/compression/CompressionProvider.java | 24 +++++++++++++ .../daporkchop/lib/encoding/Hexadecimal.java | 5 +-- .../http/impl/netty/util/NettyHttpUtil.java | 9 +++-- .../daporkchop/lib/http/util/URLEncoding.java | 34 +++++++++++-------- .../lib/primitive/generator/Generator.java | 8 ++--- 5 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java new file mode 100644 index 000000000..6566556e1 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java @@ -0,0 +1,24 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +/** + * An implementation of a compression algorithm. + * + * @author DaPorkchop_ + */ +public interface CompressionProvider { +} diff --git a/encoding/src/main/java/net/daporkchop/lib/encoding/Hexadecimal.java b/encoding/src/main/java/net/daporkchop/lib/encoding/Hexadecimal.java index b111c6592..e40303eac 100644 --- a/encoding/src/main/java/net/daporkchop/lib/encoding/Hexadecimal.java +++ b/encoding/src/main/java/net/daporkchop/lib/encoding/Hexadecimal.java @@ -32,12 +32,13 @@ @UtilityClass public class Hexadecimal { private final char[] ALPHABET = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; - private final byte[] INDEX = new byte['f' + 1]; + private final byte[] INDEX = new byte[128]; static { Arrays.fill(INDEX, (byte) -1); for (byte i = 0; i < ALPHABET.length; i++) { - INDEX[ALPHABET[i]] = i; + INDEX[Character.toLowerCase(ALPHABET[i])] = i; + INDEX[Character.toUpperCase(ALPHABET[i])] = i; } } diff --git a/http/http-netty/src/main/java/net/daporkchop/lib/http/impl/netty/util/NettyHttpUtil.java b/http/http-netty/src/main/java/net/daporkchop/lib/http/impl/netty/util/NettyHttpUtil.java index 1511f3830..69bbd57ac 100644 --- a/http/http-netty/src/main/java/net/daporkchop/lib/http/impl/netty/util/NettyHttpUtil.java +++ b/http/http-netty/src/main/java/net/daporkchop/lib/http/impl/netty/util/NettyHttpUtil.java @@ -49,12 +49,17 @@ public class NettyHttpUtil { //protected final Pattern _BASE_URL_PATTERN = Pattern.compile("^((?:[\\/A-Za-z+*\\-._]|%(?:[a-zA-Z0-9]{2})+)+)(\\?(?:(?1)(?:=(?1)+)?&)*(?:(?1)+(?:=(?1)+)?))?(?:#((?1)*))?$"); + //protected final String _URL_CHARS = "[A-Za-z0-9-._~:\\/?#[\\]@!\\$&'\\(\\)\\*\\+,;=]"; + protected final String _URL_CHARS = "[A-Za-z0-9-._~:\\/\\[\\]@!\\$&'\\(\\)\\*\\+,;=]"; + protected final String _PARAMS_CHARS = "[A-Za-z0-9-._~:\\/\\[\\]@!\\$&'\\(\\)\\*\\+,;]"; + //formatting for regex101: //^(?((?:[\/A-Za-z0-9+*\-._]|%(?:[a-fA-F0-9]{2})+)+))(?>\?(?(?>(?2)(?>=(?2))?)(?>&(?¶ms))?)?)?(?>#(?(?2)*))?$ - protected final Pattern _URL_PATTERN = Pattern.compile("^(?((?:[\\/A-Za-z0-9+*\\-._]|%(?:[a-fA-F0-9]{2})+)+))(?>\\?(?(?>(?2)(?>=(?2))?)(?>&(?'params'))?)?)?(?>#(?(?2)*))?$"); + protected final Pattern _URL_PATTERN = Pattern.compile("^(?((?:" + _URL_CHARS + "|%(?:[a-fA-F0-9]{2})+)+))(?>\\?(?(?>(?2)(?>=(?2))?)(?>&(?'params'))?)?)?(?>#(?(?2)*))?$"); - protected final Pattern _PARAMS_PATTERN = Pattern.compile("(?>^|&)(?((?>[\\/A-Za-z0-9+*\\-._]|%(?:[a-fA-F0-9]{2})+)+))(?>=(?(?2)))?"); + protected final Pattern _PARAMS_PATTERN = Pattern.compile("(?>^|&)(?((?>" + _PARAMS_CHARS + "|%(?:[a-fA-F0-9]{2})+)+))(?>=(?(?2)))?"); + //TODO: this still doesn't work correctly... public Query parseQuery(@NonNull HttpMethod method, @NonNull CharSequence query) throws HttpException { Matcher urlMatcher = _URL_PATTERN.matcher(query); if (!urlMatcher.find()) { diff --git a/http/src/main/java/net/daporkchop/lib/http/util/URLEncoding.java b/http/src/main/java/net/daporkchop/lib/http/util/URLEncoding.java index fd552ce77..a6bcff07c 100644 --- a/http/src/main/java/net/daporkchop/lib/http/util/URLEncoding.java +++ b/http/src/main/java/net/daporkchop/lib/http/util/URLEncoding.java @@ -93,27 +93,26 @@ public void encode(@NonNull Appendable dst, @NonNull CharSequence text, boolean } else if (c == ' ') { dst.append('+'); } else { - dst.append('%'); if (c < 0x80) { - Hexadecimal.encode(dst, (byte) c); + Hexadecimal.encode(dst.append('%'), (byte) c); } else if (c < 0x800) { - Hexadecimal.encode(dst, (byte) (0xC0 | (c >> 6))); - Hexadecimal.encode(dst, (byte) (0x80 | (c & 0x3F))); + Hexadecimal.encode(dst.append('%'), (byte) (0xC0 | (c >> 6))); + Hexadecimal.encode(dst.append('%'), (byte) (0x80 | (c & 0x3F))); } else if (StringUtil.isSurrogate(c)) { if (Character.isHighSurrogate(c) && ++i < length) { char c2 = arr != null ? arr[i] : text.charAt(i); if (Character.isLowSurrogate(c2)) { int codePoint = Character.toCodePoint(c, c2); - Hexadecimal.encode(dst, (byte) (0xF0 | (codePoint >> 18))); - Hexadecimal.encode(dst, (byte) (0x80 | ((codePoint >> 12) & 0x3F))); - Hexadecimal.encode(dst, (byte) (0x80 | ((codePoint >> 6) & 0x3F))); - Hexadecimal.encode(dst, (byte) (0x80 | (codePoint & 0x3F))); + Hexadecimal.encode(dst.append('%'), (byte) (0xF0 | (codePoint >> 18))); + Hexadecimal.encode(dst.append('%'), (byte) (0x80 | ((codePoint >> 12) & 0x3F))); + Hexadecimal.encode(dst.append('%'), (byte) (0x80 | ((codePoint >> 6) & 0x3F))); + Hexadecimal.encode(dst.append('%'), (byte) (0x80 | (codePoint & 0x3F))); } else { - Hexadecimal.encode(dst, (byte) '?'); + Hexadecimal.encode(dst.append('%'), (byte) '?'); i--; } } else { - Hexadecimal.encode(dst, (byte) '?'); + Hexadecimal.encode(dst.append('%'), (byte) '?'); } } } @@ -149,18 +148,23 @@ public void decode(@NonNull StringBuilder to, @NonNull CharSequence text) throws throw StatusCodes.BAD_REQUEST.exception(); } if ((b & 0xE0) == 0xC0) { - i += 2; + i += 3; int b2; - if (i >= length || (b2 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 1] : text.charAt(i - 1), arr != null ? arr[i] : text.charAt(i))) < 0) { + if (i >= length + || (arr != null ? arr[i - 2] : text.charAt(i - 2)) != '%' + || (b2 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 1] : text.charAt(i - 1), arr != null ? arr[i] : text.charAt(i))) < 0) { throw StatusCodes.BAD_REQUEST.exception(); } to.append((char) (((b & 0x1F) << 6) | (b2 & 0x3F))); } else if ((b & 0xF0) == 0xF0) { - i += 6; + i += 9; int b2, b3, b4; if (i >= length - || (b2 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 5] : text.charAt(i - 5), arr != null ? arr[i - 4] : text.charAt(i - 4))) < 0 - || (b3 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 3] : text.charAt(i - 3), arr != null ? arr[i - 2] : text.charAt(i - 2))) < 0 + || (arr != null ? arr[i - 8] : text.charAt(i - 8)) != '%' + || (b2 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 7] : text.charAt(i - 7), arr != null ? arr[i - 6] : text.charAt(i - 6))) < 0 + || (arr != null ? arr[i - 5] : text.charAt(i - 5)) != '%' + || (b3 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 4] : text.charAt(i - 4), arr != null ? arr[i - 3] : text.charAt(i - 3))) < 0 + || (arr != null ? arr[i - 2] : text.charAt(i - 2)) != '%' || (b4 = Hexadecimal.decodeUnsigned(arr != null ? arr[i - 1] : text.charAt(i - 1), arr != null ? arr[i] : text.charAt(i))) < 0) { throw StatusCodes.BAD_REQUEST.exception(); } diff --git a/primitive/generator/src/main/java/net/daporkchop/lib/primitive/generator/Generator.java b/primitive/generator/src/main/java/net/daporkchop/lib/primitive/generator/Generator.java index bccc2d074..544170d3b 100644 --- a/primitive/generator/src/main/java/net/daporkchop/lib/primitive/generator/Generator.java +++ b/primitive/generator/src/main/java/net/daporkchop/lib/primitive/generator/Generator.java @@ -21,10 +21,10 @@ import com.google.gson.JsonParser; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import net.daporkchop.lib.binary.oio.StreamUtil; import net.daporkchop.lib.common.misc.file.PFiles; import net.daporkchop.lib.common.misc.InstancePool; import net.daporkchop.lib.logging.Logging; -import sun.misc.IOUtils; import java.io.File; import java.io.FileInputStream; @@ -174,7 +174,7 @@ public class Generator { try (InputStream is = new FileInputStream(new File(".", "../../LICENSE"))) { LICENSE = String.format("/*\n * %s\n */", - new String(IOUtils.readFully(is, -1, false)) + new String(StreamUtil.toByteArray(is)) .replace("$today.year", String.valueOf(Calendar.getInstance().get(Calendar.YEAR))) /*.trim()*/.replaceAll("\n", "\n * ")); } catch (IOException e) { @@ -309,7 +309,7 @@ public void generate(@NonNull File file, @NonNull File out) { File f = files[i]; lastModified = max(lastModified, f.lastModified()); try (InputStream is = new FileInputStream(f)) { - methods[i] = new String(IOUtils.readFully(is, -1, false)); + methods[i] = new String(StreamUtil.toByteArray(is)); } catch (IOException e) { throw new RuntimeException(e); } @@ -328,7 +328,7 @@ public void generate(@NonNull File file, @NonNull File out) { } String content; try (InputStream is = new FileInputStream(file)) { - content = new String(IOUtils.readFully(is, -1, false)); + content = new String(StreamUtil.toByteArray(is)); } catch (IOException e) { throw new RuntimeException(e); } From bad22930f2372376aad40f28a5d7df49161d3e9d Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Thu, 13 Feb 2020 18:25:06 +0100 Subject: [PATCH 28/36] make one-shot compression and decompression contexts not be specific to zstd --- .../daporkchop/lib/common/util/PorkUtil.java | 2 +- .../net/daporkchop/lib/compression/CCtx.java | 54 ++++++++++++ .../lib/compression/CompressionProvider.java | 45 +++++++++- .../daporkchop/lib/compression/Context.java | 48 +---------- .../net/daporkchop/lib/compression/DCtx.java | 40 +++++++++ .../daporkchop/lib/compression/PDeflater.java | 2 +- .../daporkchop/lib/compression/PInflater.java | 2 +- .../lib/compression/StreamingContext.java | 83 +++++++++++++++++++ .../InvalidCompressionLevelException.java | 38 +++++++++ .../lib/compression/zstd/ZstdCCtx.java | 22 ++--- .../lib/compression/zstd/ZstdDCtx.java | 14 +--- .../lib/compression/zstd/ZstdProvider.java | 16 ++-- 12 files changed, 287 insertions(+), 79 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/CCtx.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/DCtx.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java index 63942beda..d342dc580 100644 --- a/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java +++ b/common/src/main/java/net/daporkchop/lib/common/util/PorkUtil.java @@ -75,7 +75,7 @@ public class PorkUtil { ); public final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); - public final String PORKLIB_VERSION = "0.5.0-SNAPSHOT"; + public final String PORKLIB_VERSION = "0.5.1-SNAPSHOT"; public final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); static { diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java new file mode 100644 index 000000000..bc5978123 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java @@ -0,0 +1,54 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; + +/** + * A context for doing repeated one-shot compression operations. + * + * @author DaPorkchop_ + */ +public interface CCtx extends Context { + /** + * Compresses the given source data into the given destination buffer at the currently configured compression level. + *

+ * If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read source data from + * @param dst the {@link ByteBuf} to write compressed data to + * @return whether or not compression was successful. If {@code false}, the destination buffer was too small for the compressed data + */ + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + + /** + * @return the currently configured compression level + */ + int level(); + + /** + * Updates this context's compression level. + * + * @param level the new compression level to use + * @return this context + * @throws InvalidCompressionLevelException if the given compression level is invalid + */ + CCtx level(int level) throws InvalidCompressionLevelException; +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java index 6566556e1..8d2f0fe3a 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java @@ -15,10 +15,53 @@ package net.daporkchop.lib.compression; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.BufferTyped; + /** * An implementation of a compression algorithm. * * @author DaPorkchop_ */ -public interface CompressionProvider { +public interface CompressionProvider extends BufferTyped { + @Override + boolean directAccepted(); + + /** + * @return the compression level with the worst compression ratio in exchange for the shortest compression times + */ + int levelFast(); + + /** + * @return the compression level used by default + */ + int levelDefault(); + + /** + * @return the compression level with the best compression ratio in exchange for the longest compression times + */ + int levelBest(); + + /** + * Creates a new {@link CCtx} with the default compression level. + * + * @see #compressionContext(int) + */ + default CCtx compressionContext() { + return this.compressionContext(this.levelDefault()); + } + + /** + * Creates a new {@link CCtx} with the given compression level. + * + * @param level the compression level to use + * @return a new {@link CCtx} with the given compression level + * @throws InvalidCompressionLevelException if the given compression level is invalid + */ + CCtx compressionContext(int level) throws InvalidCompressionLevelException; + + /** + * @return a new {@link DCtx} + */ + DCtx decompressionContext(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index 95111351d..d6a729057 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -17,14 +17,12 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.exception.ContextFinishedException; -import net.daporkchop.lib.compression.util.exception.ContextFinishingException; import net.daporkchop.lib.natives.util.BufferTyped; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.capability.Releasable; /** - * Base interface for deflaters and inflaters. + * Base interface for {@link PDeflater} and {@link PDeflater}. *

* Unless explicitly specified, implementations of this class are not safe for use on multiple threads. * @@ -32,52 +30,14 @@ */ interface Context> extends Releasable, BufferTyped { /** - * Sets the context's current source buffer when processing data in streaming mode. - * - * @param src the {@link ByteBuf} to read data from - * @return this context - * @throws ContextFinishingException if this context is already being finished, and as such the source buffer may not be updated any more - */ - I src(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContextFinishingException; - - /** - * Sets the context's current destination buffer when processing data in streaming mode. - * - * @param dst the {@link ByteBuf} to write data to - * @return this context - */ - I dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException; - - /** - * Updates this context, processing as much data as possible. - *

- * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up. - *

- * Implementations may buffer any amount of data internally. - * - * @param flush whether or not the internal buffer should be flushed. If {@code true}, an attempt will be made to flush as much buffered data as possible. Note - * that this can cause a negative impact on the compression ratio. - * @return this context - * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again - * @throws ContextFinishingException if this context is already being finished (but is not yet completely finished) - */ - I update(boolean flush) throws ContextFinishedException, ContextFinishingException; - - /** - * Finishes this context. - *

- * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up, and then - * attempt to flush any internally buffered data and finish the (de)compression process. - * - * @return whether or not the context could be completed. If {@code false}, there is not enough space in the destination buffer for the context to finish - * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + * @return the {@link CompressionProvider} that created this context */ - boolean finish() throws ContextFinishedException; + CompressionProvider provider(); /** * Resets this context. *

- * This will erase any internal buffers and reset the source and destination buffers to {@code null}. + * This will reset the dictionary buffer to {@code null}. * * @return this context */ diff --git a/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java new file mode 100644 index 000000000..c8ec85850 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java @@ -0,0 +1,40 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; + +/** + * A context for doing repeated one-shot compression operations. + * + * @author DaPorkchop_ + */ +public interface DCtx extends Context { + /** + * Decompresses the given compressed data into the given destination buffer. + *

+ * If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain + * unchanged, however the destination buffer's contents may be modified. + * + * @param src the {@link ByteBuf} to read compressed data from + * @param dst the {@link ByteBuf} to write decompressed data to + * @return whether or not decompression was successful. If {@code false}, the destination buffer was too small for the decompressed data + */ + boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java index addec968a..8091ca98c 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PDeflater.java @@ -26,7 +26,7 @@ * * @author DaPorkchop_ */ -public interface PDeflater extends Context { +public interface PDeflater extends StreamingContext { /** * Deflates the given source data into the given destination buffer. *

diff --git a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java index 5a698e9dd..70ec49e17 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/PInflater.java @@ -26,7 +26,7 @@ * * @author DaPorkchop_ */ -public interface PInflater extends Context { +public interface PInflater extends StreamingContext { /** * Inflates the given source data into the given destination buffer. *

diff --git a/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java b/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java new file mode 100644 index 000000000..5cc99622b --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java @@ -0,0 +1,83 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import io.netty.buffer.ByteBuf; +import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.ContextFinishedException; +import net.daporkchop.lib.compression.util.exception.ContextFinishingException; +import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.capability.Releasable; + +/** + * Base interface for {@link PDeflater} and {@link PDeflater}. + * @author DaPorkchop_ + */ +interface StreamingContext> extends Context { + /** + * Sets the context's current source buffer when processing data in streaming mode. + * + * @param src the {@link ByteBuf} to read data from + * @return this context + * @throws ContextFinishingException if this context is already being finished, and as such the source buffer may not be updated any more + */ + I src(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContextFinishingException; + + /** + * Sets the context's current destination buffer when processing data in streaming mode. + * + * @param dst the {@link ByteBuf} to write data to + * @return this context + */ + I dst(@NonNull ByteBuf dst) throws InvalidBufferTypeException; + + /** + * Updates this context, processing as much data as possible. + *

+ * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up. + *

+ * Implementations may buffer any amount of data internally. + * + * @param flush whether or not the internal buffer should be flushed. If {@code true}, an attempt will be made to flush as much buffered data as possible. Note + * that this can cause a negative impact on the compression ratio. + * @return this context + * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + * @throws ContextFinishingException if this context is already being finished (but is not yet completely finished) + */ + I update(boolean flush) throws ContextFinishedException, ContextFinishingException; + + /** + * Finishes this context. + *

+ * This will read from the source buffer and write to the destination buffer until the source buffer runs dry or the destination buffer fills up, and then + * attempt to flush any internally buffered data and finish the (de)compression process. + * + * @return whether or not the context could be completed. If {@code false}, there is not enough space in the destination buffer for the context to finish + * @throws ContextFinishedException if this context is already finished and needs to be reset before being used again + */ + boolean finish() throws ContextFinishedException; + + /** + * Resets this context. + *

+ * This will erase any internal buffers and reset the source, destination and dictionary buffers to {@code null}. + * + * @return this context + */ + @Override + I reset(); +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java new file mode 100644 index 000000000..cc570d0d5 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java @@ -0,0 +1,38 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util.exception; + +import lombok.NonNull; +import net.daporkchop.lib.compression.CompressionProvider; + +/** + * Thrown when an invalid compression level is given. + * + * @author DaPorkchop_ + */ +public final class InvalidCompressionLevelException extends IllegalArgumentException { + public static int validate(int level, @NonNull CompressionProvider provider) throws InvalidCompressionLevelException { + if (level < provider.levelFast() || level > provider.levelBest()) { + throw new InvalidCompressionLevelException(level, provider); + } + + return level; + } + + public InvalidCompressionLevelException(int level, @NonNull CompressionProvider provider) { + super(String.format("Invalid level %d (must be in range %d-%d)", level, provider.levelFast(), provider.levelBest())); + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java index 080ff30c4..78de134cf 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java @@ -17,9 +17,8 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; -import net.daporkchop.lib.unsafe.capability.Releasable; /** * Compression context for {@link Zstd}. @@ -28,26 +27,23 @@ * * @author DaPorkchop_ */ -public interface ZstdCCtx extends BufferTyped, Releasable { +public interface ZstdCCtx extends CCtx { /** - * Compresses the given source data into a single Zstd frame into the given destination buffer at the default compression level. + * Compresses the given source data into the given destination buffer at the currently configured compression level. * - * @see #compress(ByteBuf, ByteBuf, int) + * @see CCtx#compress(ByteBuf, ByteBuf) */ + @Override default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - return this.compress(src, dst, Zstd.LEVEL_DEFAULT); + return this.compress(src, dst, this.level()); } /** - * Compresses the given source data into a single Zstd frame into the given destination buffer. + * Compresses the given source data into a single Zstd frame into the given destination buffer at the given Zstd level. *

- * If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain - * unchanged, however the destination buffer's contents may be modified. + * This is possible because Zstd allows using the same context for any compression level without having to reallocate it. * - * @param src the {@link ByteBuf} to read source data from - * @param dst the {@link ByteBuf} to write compressed data to - * @param compressionLevel the Zstd level to compress at - * @return whether or not compression was successful. If {@code false}, the destination buffer was too small for the compressed data + * @see #compress(ByteBuf, ByteBuf) */ boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java index d2b8029d4..e2ed2a31c 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java @@ -17,9 +17,8 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.compression.DCtx; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; -import net.daporkchop.lib.unsafe.capability.Releasable; /** * Deompression context for {@link Zstd}. @@ -28,16 +27,11 @@ * * @author DaPorkchop_ */ -public interface ZstdDCtx extends BufferTyped, Releasable { +public interface ZstdDCtx extends DCtx { /** - * Decompresses the given Zstd-compressed into the given destination buffer. - *

- * If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain - * unchanged, however the destination buffer's contents may be modified. + * Decompresses the given Zstd-compressed data into the given destination buffer. * - * @param src the {@link ByteBuf} to read compressed data from - * @param dst the {@link ByteBuf} to write decompressed data to - * @return whether or not decompression was successful. If {@code false}, the destination buffer was too small for the decompressed data + * @see DCtx#decompress(ByteBuf, ByteBuf) */ boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index 928c58632..0450fe19a 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -17,6 +17,10 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; +import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.DCtx; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.Feature; import net.daporkchop.lib.natives.util.BufferTyped; @@ -27,7 +31,7 @@ * * @author DaPorkchop_ */ -public interface ZstdProvider extends BufferTyped, Feature { +public interface ZstdProvider extends CompressionProvider, Feature { @Override boolean directAccepted(); @@ -82,13 +86,9 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva */ long compressBound(long srcSize); - /** - * @return a re-usable context for simple compression - */ - ZstdCCtx compressionContext(); + @Override + ZstdCCtx compressionContext(int level) throws InvalidCompressionLevelException; - /** - * @return a re-usable context for simple decompression - */ + @Override ZstdDCtx decompressionContext(); } From 1d174ced7541f3b21253ed52c18dad20b1449110 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Fri, 14 Feb 2020 17:10:16 +0100 Subject: [PATCH 29/36] implement CCtx and DCtx for zlib --- .../net/daporkchop/lib/compression/CCtx.java | 2 + .../lib/compression/CompressionProvider.java | 23 +++ .../net/daporkchop/lib/compression/DCtx.java | 3 +- .../util/StreamingWrapperCCtx.java | 132 ++++++++++++++++++ .../util/StreamingWrapperDCtx.java | 117 ++++++++++++++++ .../lib/compression/zlib/ZlibProvider.java | 21 ++- .../compression/zlib/natives/NativeZlib.java | 19 ++- .../zlib/natives/NativeZlibDeflater.java | 19 ++- .../zlib/natives/NativeZlibInflater.java | 19 ++- 9 files changed, 339 insertions(+), 16 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java index bc5978123..c97ac3cde 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java @@ -31,6 +31,8 @@ public interface CCtx extends Context { *

* If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain * unchanged, however the destination buffer's contents may be modified. + *

+ * The currently configured dictionary will always remain unaffected by this method. * * @param src the {@link ByteBuf} to read source data from * @param dst the {@link ByteBuf} to write compressed data to diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java index 8d2f0fe3a..1d45d6722 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java @@ -42,6 +42,29 @@ public interface CompressionProvider extends BufferTyped { */ int levelBest(); + /** + * Creates a new {@link PDeflater} with the default compression level. + * + * @see #deflater(int) + */ + default PDeflater deflater() { + return this.deflater(this.levelDefault()); + } + + /** + * Creates a new {@link PDeflater} with the given compression level. + * + * @param level the compression level to use + * @return a new {@link PDeflater} with the given compression level + * @throws InvalidCompressionLevelException if the given compression level is invalid + */ + PDeflater deflater(int level) throws InvalidCompressionLevelException; + + /** + * @return a new {@link PInflater} + */ + PInflater inflater(); + /** * Creates a new {@link CCtx} with the default compression level. * diff --git a/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java index c8ec85850..ff8f83eb4 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java @@ -17,7 +17,6 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** @@ -31,6 +30,8 @@ public interface DCtx extends Context { *

* If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain * unchanged, however the destination buffer's contents may be modified. + *

+ * The currently configured dictionary will always remain unaffected by this method. * * @param src the {@link ByteBuf} to read compressed data from * @param dst the {@link ByteBuf} to write decompressed data to diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java new file mode 100644 index 000000000..85c98972d --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java @@ -0,0 +1,132 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util; + +import io.netty.buffer.ByteBuf; +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; + +/** + * An implementation of {@link CCtx} that wraps a {@link PDeflater}. + * + * @author DaPorkchop_ + */ +@Accessors(fluent = true) +public class StreamingWrapperCCtx extends AbstractReleasable implements CCtx { + @Getter + protected final CompressionProvider provider; + + protected PDeflater deflater; + protected ByteBuf dict; + @Getter + protected int level; + + public StreamingWrapperCCtx(@NonNull CompressionProvider provider, int level) { + this(provider, provider.deflater(level), level); + } + + protected StreamingWrapperCCtx(@NonNull CompressionProvider provider, @NonNull PDeflater deflater, int level) { + this.provider = provider; + this.deflater = deflater; + this.level = level; + } + + @Override + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + this.deflater.reset(); + if (this.dict != null) { + //set dictionary if needed + this.deflater.dict(this.dict); + } + return this.deflater.fullDeflate(src, dst); + } + + @Override + public CCtx level(int level) throws InvalidCompressionLevelException { + if (level != this.level) { + InvalidCompressionLevelException.validate(level, this.provider); + + //release deflater with old level and create new one with the new level + this.deflater.release(); + this.deflater = this.provider.deflater(this.level = level); + } + return this; + } + + @Override + public CCtx reset() { + this.deflater.reset(); + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + return this; + } + + @Override + public boolean hasDict() { + return this.deflater.hasDict(); + } + + @Override + public CCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { + if (!this.deflater.hasDict()) { + throw new UnsupportedOperationException(); + } + + //release old dictionary + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + + this.dict = this.deflater.assertAcceptable(dict).retainedSlice(); + return this; + } + + @Override + public boolean directAccepted() { + return this.deflater.directAccepted(); + } + + @Override + public boolean heapAccepted() { + return this.deflater.heapAccepted(); + } + + @Override + public boolean isAcceptable(@NonNull ByteBuf buf) { + return this.deflater.isAcceptable(buf); + } + + @Override + public ByteBuf assertAcceptable(@NonNull ByteBuf buf) throws InvalidBufferTypeException { + return this.deflater.assertAcceptable(buf); + } + + @Override + protected void doRelease() { + this.deflater.release(); + this.deflater = null; + } +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java new file mode 100644 index 000000000..da2a126f0 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java @@ -0,0 +1,117 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util; + +import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.DCtx; +import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; +import net.daporkchop.lib.unsafe.util.AbstractReleasable; + +/** + * An implementation of {@link DCtx} that wraps a {@link PInflater}. + * + * @author DaPorkchop_ + */ +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) +@Accessors(fluent = true) +public class StreamingWrapperDCtx extends AbstractReleasable implements DCtx { + @Getter + protected final CompressionProvider provider; + + @NonNull + protected PInflater inflater; + protected ByteBuf dict; + + public StreamingWrapperDCtx(@NonNull CompressionProvider provider) { + this(provider, provider.inflater()); + } + + @Override + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + this.inflater.reset(); + if (this.dict != null) { + //set dictionary if needed + this.inflater.dict(this.dict); + } + return this.inflater.fullInflate(src, dst); + } + + @Override + public DCtx reset() { + this.inflater.reset(); + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + return this; + } + + @Override + public boolean hasDict() { + return this.inflater.hasDict(); + } + + @Override + public DCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { + if (!this.inflater.hasDict()) { + throw new UnsupportedOperationException(); + } + + //release old dictionary + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + + this.dict = this.inflater.assertAcceptable(dict).retainedSlice(); + return this; + } + + @Override + public boolean directAccepted() { + return this.inflater.directAccepted(); + } + + @Override + public boolean heapAccepted() { + return this.inflater.heapAccepted(); + } + + @Override + public boolean isAcceptable(@NonNull ByteBuf buf) { + return this.inflater.isAcceptable(buf); + } + + @Override + public ByteBuf assertAcceptable(@NonNull ByteBuf buf) throws InvalidBufferTypeException { + return this.inflater.assertAcceptable(buf); + } + + @Override + protected void doRelease() { + this.inflater.release(); + this.inflater = null; + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index c8c5183a9..ed1132b27 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.compression.zlib; +import net.daporkchop.lib.compression.CompressionProvider; import net.daporkchop.lib.natives.impl.Feature; import net.daporkchop.lib.natives.util.BufferTyped; @@ -24,12 +25,28 @@ * * @author DaPorkchop_ */ -public interface ZlibProvider extends BufferTyped, Feature { +public interface ZlibProvider extends CompressionProvider, Feature { + @Override + default int levelFast() { + return Zlib.LEVEL_FASTEST; + } + + @Override + default int levelDefault() { + return Zlib.LEVEL_DEFAULT; + } + + @Override + default int levelBest() { + return Zlib.LEVEL_BEST; + } + /** * Creates a new {@link ZlibDeflater}. * * @return a new {@link ZlibDeflater} */ + @Override default ZlibDeflater deflater() { return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); } @@ -40,6 +57,7 @@ default ZlibDeflater deflater() { * @param level the {@link Zlib} level to use * @return a new {@link ZlibDeflater} with the given level */ + @Override default ZlibDeflater deflater(int level) { return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); } @@ -101,6 +119,7 @@ default ZlibDeflater deflaterGzip(int level, int strategy) { * * @return a new {@link ZlibInflater} */ + @Override default ZlibInflater inflater() { return this.inflater(Zlib.MODE_ZLIB); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index da0f8630d..87fd1e0c4 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -15,6 +15,11 @@ package net.daporkchop.lib.compression.zlib.natives; +import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.DCtx; +import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; +import net.daporkchop.lib.compression.util.StreamingWrapperDCtx; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; @@ -34,13 +39,23 @@ public boolean directAccepted() { return true; } + @Override + public CCtx compressionContext(int level) throws InvalidCompressionLevelException { + return new StreamingWrapperCCtx(this, level); + } + + @Override + public DCtx decompressionContext() { + return new StreamingWrapperDCtx(this); + } + @Override public ZlibDeflater deflater(int level, int strategy, int mode) { - return new NativeZlibDeflater(level, strategy, mode); + return new NativeZlibDeflater(this, level, strategy, mode); } @Override public ZlibInflater inflater(int mode) { - return new NativeZlibInflater(mode); + return new NativeZlibInflater(this, mode); } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index 1492be46c..fe59a68e2 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -16,19 +16,22 @@ package net.daporkchop.lib.compression.zlib.natives; import io.netty.buffer.ByteBuf; +import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; import net.daporkchop.lib.compression.PDeflater; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zlib.ZlibDeflater; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; /** * @author DaPorkchop_ */ +@Accessors(fluent = true) public final class NativeZlibDeflater extends AbstractReleasable implements ZlibDeflater { static native void load(); @@ -38,7 +41,9 @@ public final class NativeZlibDeflater extends AbstractReleasable implements Zlib private final long ctx; - private final PCleaner cleaner; + @Getter + private final NativeZlib provider; + private final PCleaner cleaner; private ByteBuf src; private ByteBuf dst; @@ -52,7 +57,9 @@ public final class NativeZlibDeflater extends AbstractReleasable implements Zlib private boolean finishing; private boolean finished; - public NativeZlibDeflater(int level, int strategy, int mode) { + NativeZlibDeflater(@NonNull NativeZlib provider, int level, int strategy, int mode) { + this.provider = provider; + this.ctx = allocateCtx(level, strategy, mode); this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); this.reset = true; @@ -139,7 +146,7 @@ public PDeflater reset() { if (!this.reset) { this.src = null; this.dst = null; - if (this.dict != null) { + if (this.dict != null) { this.dict.release(); this.dict = null; } @@ -162,9 +169,9 @@ public PDeflater reset() { public PDeflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { if (!dict.hasMemoryAddress()) { throw InvalidBufferTypeException.direct(); - } else if (this.started) { + } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after compression has started!"); - } else if (this.dict != null) { + } else if (this.dict != null) { throw new IllegalStateException("Dictionary has already been set!"); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java index 6973e2943..551e5808f 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -16,19 +16,22 @@ package net.daporkchop.lib.compression.zlib.natives; import io.netty.buffer.ByteBuf; +import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; import net.daporkchop.lib.compression.PInflater; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.compression.zlib.ZlibInflater; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; /** * @author DaPorkchop_ */ +@Accessors(fluent = true) public final class NativeZlibInflater extends AbstractReleasable implements ZlibInflater { static native void load(); @@ -38,7 +41,9 @@ public final class NativeZlibInflater extends AbstractReleasable implements Zlib private final long ctx; - private final PCleaner cleaner; + @Getter + private final NativeZlib provider; + private final PCleaner cleaner; private ByteBuf src; private ByteBuf dst; @@ -52,7 +57,9 @@ public final class NativeZlibInflater extends AbstractReleasable implements Zlib private boolean finishing; private boolean finished; - public NativeZlibInflater(int mode) { + NativeZlibInflater(@NonNull NativeZlib provider, int mode) { + this.provider = provider; + this.ctx = allocateCtx(mode); this.cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); this.reset = true; @@ -143,7 +150,7 @@ public PInflater reset() { if (!this.reset) { this.src = null; this.dst = null; - if (this.dict != null) { + if (this.dict != null) { this.dict.release(); this.dict = null; } @@ -166,9 +173,9 @@ public PInflater reset() { public PInflater dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { if (!dict.hasMemoryAddress()) { throw InvalidBufferTypeException.direct(); - } else if (this.started) { + } else if (this.started) { throw new IllegalStateException("Cannot set dictionary after decompression has started!"); - } else if (this.dict != null) { + } else if (this.dict != null) { throw new IllegalStateException("Dictionary has already been set!"); } From 0b81d4d3de462d860b2c8e35d19259fb2bc76604 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Fri, 14 Feb 2020 17:36:01 +0100 Subject: [PATCH 30/36] give zlib separate sub-interfaces of CCtx and DCtx --- .../net/daporkchop/lib/compression/CCtx.java | 13 +- .../util/StreamingWrapperCCtx.java | 19 +-- .../lib/compression/zlib/ZlibCCtx.java | 35 ++++++ .../lib/compression/zlib/ZlibDCtx.java | 31 +++++ .../lib/compression/zlib/ZlibProvider.java | 118 ++++++++++++++---- .../compression/zlib/natives/NativeZlib.java | 15 +-- .../zlib/natives/NativeZlibCCtx.java | 39 ++++++ .../zlib/natives/NativeZlibDCtx.java | 39 ++++++ .../zlib/natives/NativeZlibDeflater.java | 2 +- .../zlib/natives/NativeZlibInflater.java | 2 +- 10 files changed, 252 insertions(+), 61 deletions(-) create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java create mode 100644 compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java index c97ac3cde..fe6e2e16b 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java @@ -27,7 +27,7 @@ */ public interface CCtx extends Context { /** - * Compresses the given source data into the given destination buffer at the currently configured compression level. + * Compresses the given source data into the given destination buffer at the configured compression level. *

* If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain * unchanged, however the destination buffer's contents may be modified. @@ -41,16 +41,7 @@ public interface CCtx extends Context { boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; /** - * @return the currently configured compression level + * @return the configured compression level */ int level(); - - /** - * Updates this context's compression level. - * - * @param level the new compression level to use - * @return this context - * @throws InvalidCompressionLevelException if the given compression level is invalid - */ - CCtx level(int level) throws InvalidCompressionLevelException; } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java index 85c98972d..3a505dcfd 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java @@ -36,13 +36,13 @@ public class StreamingWrapperCCtx extends AbstractReleasable implements CCtx { @Getter protected final CompressionProvider provider; - protected PDeflater deflater; + protected final PDeflater deflater; protected ByteBuf dict; @Getter - protected int level; + protected final int level; public StreamingWrapperCCtx(@NonNull CompressionProvider provider, int level) { - this(provider, provider.deflater(level), level); + this(provider, null, level); } protected StreamingWrapperCCtx(@NonNull CompressionProvider provider, @NonNull PDeflater deflater, int level) { @@ -61,18 +61,6 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inval return this.deflater.fullDeflate(src, dst); } - @Override - public CCtx level(int level) throws InvalidCompressionLevelException { - if (level != this.level) { - InvalidCompressionLevelException.validate(level, this.provider); - - //release deflater with old level and create new one with the new level - this.deflater.release(); - this.deflater = this.provider.deflater(this.level = level); - } - return this; - } - @Override public CCtx reset() { this.deflater.reset(); @@ -127,6 +115,5 @@ public ByteBuf assertAcceptable(@NonNull ByteBuf buf) throws InvalidBufferTypeEx @Override protected void doRelease() { this.deflater.release(); - this.deflater = null; } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java new file mode 100644 index 000000000..75a6ea4fa --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java @@ -0,0 +1,35 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import net.daporkchop.lib.compression.CCtx; + +/** + * An extension of {@link CCtx} for {@link Zlib}. + * + * @author DaPorkchop_ + */ +public interface ZlibCCtx extends CCtx { + /** + * @return the configured strategy + */ + int strategy(); + + /** + * @return the configured wrapping mode + */ + int mode(); +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java new file mode 100644 index 000000000..bd9e99d03 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java @@ -0,0 +1,31 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib; + +import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.DCtx; + +/** + * An extension of {@link DCtx} for {@link Zlib}. + * + * @author DaPorkchop_ + */ +public interface ZlibDCtx extends DCtx { + /** + * @return the configured wrapping mode + */ + int mode(); +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index ed1132b27..bce2924cd 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,7 +16,10 @@ package net.daporkchop.lib.compression.zlib; +import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.DCtx; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.impl.Feature; import net.daporkchop.lib.natives.util.BufferTyped; @@ -42,8 +45,6 @@ default int levelBest() { } /** - * Creates a new {@link ZlibDeflater}. - * * @return a new {@link ZlibDeflater} */ @Override @@ -58,7 +59,7 @@ default ZlibDeflater deflater() { * @return a new {@link ZlibDeflater} with the given level */ @Override - default ZlibDeflater deflater(int level) { + default ZlibDeflater deflater(int level) throws InvalidCompressionLevelException { return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); } @@ -69,37 +70,35 @@ default ZlibDeflater deflater(int level) { * @param strategy the {@link Zlib} strategy to use * @return a new {@link ZlibDeflater} with the given level and strategy */ - default ZlibDeflater deflater(int level, int strategy) { + default ZlibDeflater deflater(int level, int strategy) throws InvalidCompressionLevelException { return this.deflater(level, strategy, Zlib.MODE_ZLIB); } /** - * Creates a new {@link ZlibDeflater} that will use Gzip headers. - * - * @return a new {@link ZlibDeflater} + * @return a new {@link ZlibDeflater} using the Gzip format */ default ZlibDeflater deflaterGzip() { return this.deflater(Zlib.LEVEL_DEFAULT, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); } /** - * Creates a new {@link ZlibDeflater} that will use Gzip headers. + * Creates a new {@link ZlibDeflater} using the Gzip format. * * @param level the {@link Zlib} level to use - * @return a new {@link ZlibDeflater} with the given level + * @return a new {@link ZlibDeflater} using the Gzip format with the given level */ - default ZlibDeflater deflaterGzip(int level) { + default ZlibDeflater deflaterGzip(int level) throws InvalidCompressionLevelException { return this.deflater(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); } /** - * Creates a new {@link ZlibDeflater} that will use Gzip headers. + * Creates a new {@link ZlibDeflater} using the Gzip format. * * @param level the {@link Zlib} level to use * @param strategy the {@link Zlib} strategy to use - * @return a new {@link ZlibDeflater} with the given level and strategy + * @return a new {@link ZlibDeflater} using the Gzip format with the given level and strategy */ - default ZlibDeflater deflaterGzip(int level, int strategy) { + default ZlibDeflater deflaterGzip(int level, int strategy) throws InvalidCompressionLevelException { return this.deflater(level, strategy, Zlib.MODE_GZIP); } @@ -110,13 +109,12 @@ default ZlibDeflater deflaterGzip(int level, int strategy) { * @param strategy the {@link Zlib} strategy to use. Must be one of {@link Zlib#STRATEGY_DEFAULT}, {@link Zlib#STRATEGY_FILTERED}, {@link Zlib#STRATEGY_HUFFMAN}, * {@link Zlib#STRATEGY_RLE} or {@link Zlib#STRATEGY_FIXED} * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP} or {@link Zlib#MODE_RAW} - * @return a new {@link ZlibDeflater} with the given level and strategy + * @return a new {@link ZlibDeflater} with the given level, strategy and mode + * @throws InvalidCompressionLevelException if the given compression level is invalid */ - ZlibDeflater deflater(int level, int strategy, int mode); + ZlibDeflater deflater(int level, int strategy, int mode) throws InvalidCompressionLevelException; /** - * Creates a new {@link ZlibInflater}. - * * @return a new {@link ZlibInflater} */ @Override @@ -125,18 +123,14 @@ default ZlibInflater inflater() { } /** - * Creates a new {@link ZlibInflater} that will use Gzip headers. - * - * @return a new {@link ZlibInflater} + * @return a new {@link ZlibInflater} using the Gzip format */ default ZlibInflater inflaterGzip() { return this.inflater(Zlib.MODE_GZIP); } /** - * Creates a new {@link ZlibInflater} that will automatically detect whether the compressed data is in Zlib or Gzip format. - * - * @return a new {@link ZlibInflater} + * @return a new {@link ZlibInflater} that will automatically detect whether the compressed data is in Zlib or Gzip format */ default ZlibInflater inflaterAuto() { return this.inflater(Zlib.MODE_AUTO); @@ -149,4 +143,82 @@ default ZlibInflater inflaterAuto() { * @return a new {@link ZlibInflater} */ ZlibInflater inflater(int mode); + + /** + * @return a new {@link ZlibCCtx} + */ + @Override + default ZlibCCtx compressionContext() { + return this.compressionContext(Zlib.LEVEL_BEST, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); + } + + /** + * @return a new {@link ZlibCCtx} with the given level + */ + @Override + default ZlibCCtx compressionContext(int level) throws InvalidCompressionLevelException { + return this.compressionContext(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_ZLIB); + } + + /** + * @return a new {@link ZlibCCtx} with the given level and strategy + */ + default ZlibCCtx compressionContext(int level, int strategy) throws InvalidCompressionLevelException { + return this.compressionContext(level, strategy, Zlib.MODE_ZLIB); + } + + /** + * @return a new {@link ZlibCCtx} using the Gzip format + */ + default ZlibCCtx compressionContextGzip() { + return this.compressionContext(Zlib.LEVEL_BEST, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); + } + + /** + * @return a new {@link ZlibCCtx} using the Gzip format with the given level + */ + default ZlibCCtx compressionContextGzip(int level) throws InvalidCompressionLevelException { + return this.compressionContext(level, Zlib.STRATEGY_DEFAULT, Zlib.MODE_GZIP); + } + + /** + * @return a new {@link ZlibCCtx} using the Gzip format with the given level and strategy + */ + default ZlibCCtx compressionContextGzip(int level, int strategy) throws InvalidCompressionLevelException { + return this.compressionContext(level, strategy, Zlib.MODE_GZIP); + } + + /** + * @return a new {@link ZlibCCtx} with the given level, strategy and mode + * @see #deflater(int, int, int) + */ + ZlibCCtx compressionContext(int level, int strategy, int mode); + + /** + * @return a new {@link ZlibDCtx} + */ + @Override + default ZlibDCtx decompressionContext() { + return this.decompressionContext(Zlib.MODE_ZLIB); + } + + /** + * @return a new {@link ZlibDCtx} using the Gzip format + */ + default ZlibDCtx decompressionContextGzip() { + return this.decompressionContext(Zlib.MODE_GZIP); + } + + /** + * @return a new {@link ZlibDCtx} that will automatically detect whether the compressed data is in Zlib or Gzip format + */ + default ZlibDCtx decompressionContextAuto() { + return this.decompressionContext(Zlib.MODE_AUTO); + } + + /** + * @return a new {@link ZlibDCtx} with the given mode + * @see #inflater(int) + */ + ZlibDCtx decompressionContext(int mode); } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 87fd1e0c4..97d7819b5 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -15,11 +15,8 @@ package net.daporkchop.lib.compression.zlib.natives; -import net.daporkchop.lib.compression.CCtx; -import net.daporkchop.lib.compression.DCtx; -import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; -import net.daporkchop.lib.compression.util.StreamingWrapperDCtx; -import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.compression.zlib.ZlibCCtx; +import net.daporkchop.lib.compression.zlib.ZlibDCtx; import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; @@ -40,13 +37,13 @@ public boolean directAccepted() { } @Override - public CCtx compressionContext(int level) throws InvalidCompressionLevelException { - return new StreamingWrapperCCtx(this, level); + public ZlibCCtx compressionContext(int level, int strategy, int mode) { + return new NativeZlibCCtx(this, level, strategy, mode); } @Override - public DCtx decompressionContext() { - return new StreamingWrapperDCtx(this); + public ZlibDCtx decompressionContext(int mode) { + return new NativeZlibDCtx(this, mode); } @Override diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java new file mode 100644 index 000000000..0fa7b7e37 --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java @@ -0,0 +1,39 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib.natives; + +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; +import net.daporkchop.lib.compression.zlib.ZlibCCtx; + +/** + * @author DaPorkchop_ + */ +@Getter +@Accessors(fluent = true) +final class NativeZlibCCtx extends StreamingWrapperCCtx implements ZlibCCtx { + private final int strategy; + private final int mode; + + NativeZlibCCtx(@NonNull NativeZlib provider, int level, int strategy, int mode) { + super(provider, provider.deflater(level, strategy, mode), level); + + this.strategy = strategy; + this.mode = mode; + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java new file mode 100644 index 000000000..8c280ef5b --- /dev/null +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java @@ -0,0 +1,39 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zlib.natives; + +import lombok.Getter; +import lombok.NonNull; +import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; +import net.daporkchop.lib.compression.util.StreamingWrapperDCtx; +import net.daporkchop.lib.compression.zlib.ZlibDCtx; + +/** + * @author DaPorkchop_ + */ +@Getter +@Accessors(fluent = true) +final class NativeZlibDCtx extends StreamingWrapperDCtx implements ZlibDCtx { + private final int mode; + + NativeZlibDCtx(@NonNull NativeZlib provider, int mode) { + super(provider, provider.inflater(mode)); + + this.mode = mode; + } +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java index fe59a68e2..b946b530f 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDeflater.java @@ -32,7 +32,7 @@ * @author DaPorkchop_ */ @Accessors(fluent = true) -public final class NativeZlibDeflater extends AbstractReleasable implements ZlibDeflater { +final class NativeZlibDeflater extends AbstractReleasable implements ZlibDeflater { static native void load(); private static native long allocateCtx(int level, int strategy, int mode); diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java index 551e5808f..474365c3d 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibInflater.java @@ -32,7 +32,7 @@ * @author DaPorkchop_ */ @Accessors(fluent = true) -public final class NativeZlibInflater extends AbstractReleasable implements ZlibInflater { +final class NativeZlibInflater extends AbstractReleasable implements ZlibInflater { static native void load(); private static native long allocateCtx(int mode); From c96e50d846b981e2156dcf0bee7c281ad2f76f5f Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Fri, 14 Feb 2020 18:38:44 +0100 Subject: [PATCH 31/36] clean up implementations of CCtx and DCtx a bit more --- .../lib/compression/zlib/ZlibCCtx.java | 14 +++++++ .../lib/compression/zlib/ZlibDCtx.java | 14 +++++++ .../zlib/natives/NativeZlibCCtx.java | 15 +++++++ .../zlib/natives/NativeZlibDCtx.java | 14 +++++++ .../lib/compression/zstd/ZstdCCtx.java | 11 ++++++ .../lib/compression/zstd/ZstdDCtx.java | 11 ++++++ .../compression/zstd/natives/NativeZstd.java | 35 +++++++++++++++-- .../zstd/natives/NativeZstdCCtx.java | 39 ++++++++++++++++++- .../zstd/natives/NativeZstdDCtx.java | 32 +++++++++++++-- .../src/main/native/common/NativeZstdCCtx.cpp | 6 ++- .../src/main/native/common/NativeZstdCCtx.h | 4 +- .../src/main/native/common/NativeZstdDCtx.cpp | 6 ++- .../src/main/native/common/NativeZstdDCtx.h | 4 +- 13 files changed, 189 insertions(+), 16 deletions(-) diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java index 75a6ea4fa..b2d1f4fc6 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java @@ -15,7 +15,10 @@ package net.daporkchop.lib.compression.zlib; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * An extension of {@link CCtx} for {@link Zlib}. @@ -32,4 +35,15 @@ public interface ZlibCCtx extends CCtx { * @return the configured wrapping mode */ int mode(); + + @Override + ZlibCCtx reset(); + + @Override + default boolean hasDict() { + return true; + } + + @Override + ZlibCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java index bd9e99d03..2d2a47a6b 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java @@ -15,8 +15,11 @@ package net.daporkchop.lib.compression.zlib; +import io.netty.buffer.ByteBuf; +import lombok.NonNull; import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.DCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * An extension of {@link DCtx} for {@link Zlib}. @@ -28,4 +31,15 @@ public interface ZlibDCtx extends DCtx { * @return the configured wrapping mode */ int mode(); + + @Override + ZlibDCtx reset(); + + @Override + default boolean hasDict() { + return true; + } + + @Override + ZlibDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java index 0fa7b7e37..c0590242c 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java @@ -15,11 +15,14 @@ package net.daporkchop.lib.compression.zlib.natives; +import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.NonNull; import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; import net.daporkchop.lib.compression.zlib.ZlibCCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * @author DaPorkchop_ @@ -36,4 +39,16 @@ final class NativeZlibCCtx extends StreamingWrapperCCtx implements ZlibCCtx { this.strategy = strategy; this.mode = mode; } + + @Override + public ZlibCCtx reset() { + super.reset(); + return this; + } + + @Override + public ZlibCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + super.dict(dict); + return this; + } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java index 8c280ef5b..70e4ef1be 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java @@ -15,6 +15,7 @@ package net.daporkchop.lib.compression.zlib.natives; +import io.netty.buffer.ByteBuf; import lombok.Getter; import lombok.NonNull; import lombok.experimental.Accessors; @@ -22,6 +23,7 @@ import net.daporkchop.lib.compression.util.StreamingWrapperCCtx; import net.daporkchop.lib.compression.util.StreamingWrapperDCtx; import net.daporkchop.lib.compression.zlib.ZlibDCtx; +import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** * @author DaPorkchop_ @@ -36,4 +38,16 @@ final class NativeZlibDCtx extends StreamingWrapperDCtx implements ZlibDCtx { this.mode = mode; } + + @Override + public ZlibDCtx reset() { + super.reset(); + return this; + } + + @Override + public ZlibDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + super.dict(dict); + return this; + } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java index 78de134cf..73a3671cf 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java @@ -46,4 +46,15 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva * @see #compress(ByteBuf, ByteBuf) */ boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException; + + @Override + ZstdCCtx reset(); + + @Override + default boolean hasDict() { + return true; + } + + @Override + ZstdCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java index e2ed2a31c..d698611e2 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java @@ -34,4 +34,15 @@ public interface ZstdDCtx extends DCtx { * @see DCtx#decompress(ByteBuf, ByteBuf) */ boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + + @Override + ZstdDCtx reset(); + + @Override + default boolean hasDict() { + return true; + } + + @Override + ZstdDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 4f7020d3c..844860ad9 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -18,6 +18,10 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.compression.zstd.Zstd; import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.compression.zstd.ZstdDCtx; import net.daporkchop.lib.compression.zstd.ZstdProvider; @@ -34,6 +38,21 @@ public boolean directAccepted() { return true; } + @Override + public int levelFast() { + return Zstd.LEVEL_MIN; + } + + @Override + public int levelDefault() { + return Zstd.LEVEL_DEFAULT; + } + + @Override + public int levelBest() { + return Zstd.LEVEL_MAX; + } + @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { int val = this.doCompress(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), @@ -90,12 +109,22 @@ public long compressBound(long srcSize) { private native long doCompressBound(long srcSize); @Override - public ZstdCCtx compressionContext() { - return new NativeZstdCCtx(); + public PDeflater deflater(int level) throws InvalidCompressionLevelException { + throw new UnsupportedOperationException(); + } + + @Override + public PInflater inflater() { + throw new UnsupportedOperationException(); + } + + @Override + public ZstdCCtx compressionContext(int level) throws InvalidCompressionLevelException { + return new NativeZstdCCtx(this, level); } @Override public ZstdDCtx decompressionContext() { - return new NativeZstdDCtx(); + return new NativeZstdDCtx(this); } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java index d70ec568e..983f0521e 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java @@ -16,8 +16,13 @@ package net.daporkchop.lib.compression.zstd.natives; import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; @@ -28,6 +33,7 @@ * * @author DaPorkchop_ */ +@Accessors(fluent = true) final class NativeZstdCCtx extends AbstractReleasable implements ZstdCCtx { private static native long allocateCtx(); @@ -36,14 +42,27 @@ final class NativeZstdCCtx extends AbstractReleasable implements ZstdCCtx { private final long ctx = allocateCtx(); private final PCleaner cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + @Getter + private final NativeZstd provider; + private ByteBuf dict; + + @Getter + private int level; + + NativeZstdCCtx(@NonNull NativeZstd provider, int level) { + this.provider = provider; + this.level = level; + } + @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { int val = this.doCompress(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + this.dict != null ? this.dict.memoryAddress() : 0L, this.dict != null ? this.dict.readableBytes() : 0, compressionLevel); - if (val >= 0) { + if (val >= 0) { src.skipBytes(src.readableBytes()); dst.writerIndex(dst.writerIndex() + val); return true; @@ -52,7 +71,7 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compress } } - private native int doCompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, int compressionLevel); + private native int doCompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize, int compressionLevel); @Override public boolean directAccepted() { @@ -61,9 +80,25 @@ public boolean directAccepted() { @Override protected void doRelease() { + this.reset(); this.cleaner.clean(); } + @Override + public ZstdCCtx reset() { + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + return this; + } + + @Override + public ZstdCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + this.dict = this.reset().assertAcceptable(dict).retainedSlice(); + return this; + } + @RequiredArgsConstructor private static final class Releaser implements Runnable { private final long ctx; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java index 50b30d04b..3a4a97151 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java @@ -16,8 +16,11 @@ package net.daporkchop.lib.compression.zstd.natives; import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; +import lombok.Getter; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.compression.zstd.ZstdDCtx; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; @@ -29,6 +32,8 @@ * * @author DaPorkchop_ */ +@RequiredArgsConstructor(access = AccessLevel.PACKAGE) +@Accessors(fluent = true) final class NativeZstdDCtx extends AbstractReleasable implements ZstdDCtx { private static native long allocateCtx(); @@ -37,13 +42,18 @@ final class NativeZstdDCtx extends AbstractReleasable implements ZstdDCtx { private final long ctx = allocateCtx(); private final PCleaner cleaner = PCleaner.cleaner(this, new Releaser(this.ctx)); + @Getter + private final NativeZstd provider; + private ByteBuf dict; + @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { int val = this.doDecompress(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), - this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes()); + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + this.dict != null ? this.dict.memoryAddress() : 0L, this.dict != null ? this.dict.readableBytes() : 0); - if (val >= 0) { + if (val >= 0) { src.skipBytes(src.readableBytes()); dst.writerIndex(dst.writerIndex() + val); return true; @@ -52,7 +62,7 @@ public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inv } } - private native int doDecompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize); + private native int doDecompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); @Override public boolean directAccepted() { @@ -61,9 +71,25 @@ public boolean directAccepted() { @Override protected void doRelease() { + this.reset(); this.cleaner.clean(); } + @Override + public ZstdDCtx reset() { + if (this.dict != null) { + this.dict.release(); + this.dict = null; + } + return this; + } + + @Override + public ZstdDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + this.dict = this.reset().assertAcceptable(dict).retainedSlice(); + return this; + } + @RequiredArgsConstructor private static final class Releaser implements Runnable { private final long ctx; diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp index 93c74cf48..b3dd176a3 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp @@ -25,8 +25,10 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress - (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jint compressionLevel) { - auto ret = ZSTD_compressCCtx((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize, jint compressionLevel) { + auto ret = dictAddr + ? ZSTD_compress_usingDict((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize, compressionLevel) + : ZSTD_compressCCtx((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.h b/compression/zstd/src/main/native/common/NativeZstdCCtx.h index ffa7a5937..0e8145c4a 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.h @@ -29,10 +29,10 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs /* * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx * Method: doCompress - * Signature: (JJIJII)I + * Signature: (JJIJIJII)I */ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress - (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jint); + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint, jint); #ifdef __cplusplus } diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp index 3f33d9f67..305a5e39d 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp @@ -25,8 +25,10 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress - (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { - auto ret = ZSTD_decompressDCtx((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize); + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize) { + auto ret = dictAddr + ? ZSTD_decompress_usingDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize) + : ZSTD_decompressDCtx((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.h b/compression/zstd/src/main/native/common/NativeZstdDCtx.h index ec3a53846..38c8fac55 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.h @@ -29,10 +29,10 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs /* * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx * Method: doDecompress - * Signature: (JJIJI)I + * Signature: (JJIJIJI)I */ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress - (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint); + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint); #ifdef __cplusplus } From 8ab69843944d4887c7573e73f6429927297fb334 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sat, 15 Feb 2020 16:29:33 +0100 Subject: [PATCH 32/36] make debug builds a lot faster, and other various cleanup --- .../lib/common/util/PValidation.java | 70 ++++++++----------- .../exception/ValueCannotFitException.java | 43 ++++++++++++ .../exception/ValueOutOfBoundsException.java | 55 +++++++++++++++ .../net/daporkchop/lib/compression/CCtx.java | 23 ++++-- .../lib/compression/CompressionProvider.java | 18 +++++ .../daporkchop/lib/compression/Context.java | 31 +------- .../net/daporkchop/lib/compression/DCtx.java | 17 ++++- .../lib/compression/StreamingContext.java | 24 +++++-- .../util/StreamingWrapperCCtx.java | 58 +++++---------- .../util/StreamingWrapperDCtx.java | 42 +++-------- .../exception/ContextFinishingException.java | 2 +- .../DictionaryNotAllowedException.java | 24 +++++++ .../InvalidCompressionLevelException.java | 2 +- compression/zlib/Makefile | 16 +++-- .../lib/compression/zlib/ZlibCCtx.java | 6 -- .../lib/compression/zlib/ZlibDCtx.java | 6 -- .../lib/compression/zlib/ZlibProvider.java | 54 +++++++++++++- .../lib/compression/zlib/java/JavaZlib.java | 31 ++++++++ .../compression/zlib/natives/NativeZlib.java | 5 ++ .../zlib/natives/NativeZlibCCtx.java | 11 +-- .../zlib/natives/NativeZlibDCtx.java | 11 +-- .../src/main/native/common/NativeZlib.cpp | 23 ++++++ .../zlib/src/main/native/common/NativeZlib.h | 25 +++++++ .../main/native/common/NativeZlibDeflater.cpp | 15 ++-- .../main/native/common/NativeZlibInflater.cpp | 12 +--- compression/zstd/Makefile | 16 +++-- .../zstd/src/example/java/ZstdTest.java | 4 +- .../lib/compression/zstd/ZstdCCtx.java | 25 +++++-- .../lib/compression/zstd/ZstdDCtx.java | 13 ---- .../lib/compression/zstd/ZstdProvider.java | 26 ++++--- .../compression/zstd/natives/NativeZstd.java | 35 +++------- .../zstd/natives/NativeZstdCCtx.java | 49 ++++++------- .../zstd/natives/NativeZstdDCtx.java | 49 ++++++------- .../zstd/natives/NativeZstdHelper.java | 37 ++++++++++ .../ContentSizeUnknownException.java | 2 +- .../src/main/native/common/NativeZstd.cpp | 9 +-- .../zstd/src/main/native/common/NativeZstd.h | 4 +- .../src/main/native/common/NativeZstdCCtx.cpp | 27 ++++--- .../src/main/native/common/NativeZstdCCtx.h | 12 +++- .../src/main/native/common/NativeZstdDCtx.cpp | 27 ++++--- .../src/main/native/common/NativeZstdDCtx.h | 12 +++- natives/Makefile | 9 +++ natives/compile.sh | 3 + ...odeException.java => NativeException.java} | 23 ++++-- natives/src/main/native/common/common.cpp | 25 ++++++- natives/src/main/native/include/common.h | 14 +++- natives/toolchain/aarch64-linux-gnu | 8 +++ natives/toolchain/x86_64-linux-gnu | 8 +++ 48 files changed, 682 insertions(+), 379 deletions(-) create mode 100644 common/src/main/java/net/daporkchop/lib/common/util/exception/ValueCannotFitException.java create mode 100644 common/src/main/java/net/daporkchop/lib/common/util/exception/ValueOutOfBoundsException.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/util/exception/DictionaryNotAllowedException.java create mode 100644 compression/zlib/src/main/native/common/NativeZlib.cpp create mode 100644 compression/zlib/src/main/native/common/NativeZlib.h create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdHelper.java rename natives/src/main/java/net/daporkchop/lib/natives/{NativeCodeException.java => NativeException.java} (72%) diff --git a/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java index 70849b354..5de721498 100644 --- a/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java +++ b/common/src/main/java/net/daporkchop/lib/common/util/PValidation.java @@ -16,105 +16,91 @@ package net.daporkchop.lib.common.util; import lombok.experimental.UtilityClass; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; +import net.daporkchop.lib.common.util.exception.ValueOutOfBoundsException; /** * @author DaPorkchop_ */ @UtilityClass public class PValidation { - public long ensurePositive(long value) { + public long ensurePositive(long value) throws ValueOutOfBoundsException { if (value <= 0L) { - throw new IllegalArgumentException(value + " <= 0"); + throw new ValueOutOfBoundsException(value + " <= 0"); } return value; } - public int ensurePositive(int value) { + public int ensurePositive(int value) throws ValueOutOfBoundsException { if (value <= 0) { - throw new IllegalArgumentException(value + " <= 0"); + throw new ValueOutOfBoundsException(value + " <= 0"); } return value; } - public long ensureNonPositive(long value) { + public long ensureNonPositive(long value) throws ValueOutOfBoundsException { if (value > 0L) { - throw new IllegalArgumentException(value + " > 0"); + throw new ValueOutOfBoundsException(value + " > 0"); } return value; } - public int ensureNonPositive(int value) { + public int ensureNonPositive(int value) throws ValueOutOfBoundsException { if (value > 0) { - throw new IllegalArgumentException(value + " > 0"); + throw new ValueOutOfBoundsException(value + " > 0"); } return value; } - public long ensureNegative(long value) { + public long ensureNegative(long value) throws ValueOutOfBoundsException { if (value >= 0L) { - throw new IllegalArgumentException(value + " >= 0"); + throw new ValueOutOfBoundsException(value + " >= 0"); } return value; } - public int ensureNegative(int value) { + public int ensureNegative(int value) throws ValueOutOfBoundsException { if (value >= 0) { - throw new IllegalArgumentException(value + " >= 0"); + throw new ValueOutOfBoundsException(value + " >= 0"); } return value; } - public long ensureNonNegative(long value) { + public long ensureNonNegative(long value) throws ValueOutOfBoundsException { if (value < 0L) { - throw new IllegalArgumentException(value + " < 0"); + throw new ValueOutOfBoundsException(value + " < 0"); } return value; } - public int ensureNonNegative(int value) { + public int ensureNonNegative(int value) throws ValueOutOfBoundsException { if (value < 0) { - throw new IllegalArgumentException(value + " < 0"); + throw new ValueOutOfBoundsException(value + " < 0"); } return value; } - public int toIntSafe(long value) { + public int toInt(long value) throws ValueCannotFitException { int i = (int) value; if (i != value) { - throw new IllegalArgumentException(value + " cannot fit in an int!"); + throw new ValueCannotFitException(value, 0); } return i; } - public int toPositiveIntSafe(long value) { - int i = (int) ensurePositive(value); - if (i != value) { - throw new IllegalArgumentException(value + " cannot fit in an int!"); - } - return i; + public int toPositiveIntSafe(long value) throws ValueCannotFitException, ValueOutOfBoundsException { + return ensurePositive(toInt(value)); } - public int toNonPositiveIntSafe(long value) { - int i = (int) ensureNonPositive(value); - if (i != value) { - throw new IllegalArgumentException(value + " cannot fit in an int!"); - } - return i; + public int toNonPositiveIntSafe(long value) throws ValueCannotFitException, ValueOutOfBoundsException { + return ensureNonPositive(toInt(value)); } - public int toNegativeIntSafe(long value) { - int i = (int) ensureNegative(value); - if (i != value) { - throw new IllegalArgumentException(value + " cannot fit in an int!"); - } - return i; + public int toNegativeIntSafe(long value) throws ValueCannotFitException, ValueOutOfBoundsException { + return ensureNegative(toInt(value)); } - public int toNonNegativeIntSafe(long value) { - int i = (int) ensureNonNegative(value); - if (i != value) { - throw new IllegalArgumentException(value + " cannot fit in an int!"); - } - return i; + public int toNonNegativeIntSafe(long value) throws ValueCannotFitException, ValueOutOfBoundsException { + return ensureNonNegative(toInt(value)); } } diff --git a/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueCannotFitException.java b/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueCannotFitException.java new file mode 100644 index 000000000..d92f20b49 --- /dev/null +++ b/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueCannotFitException.java @@ -0,0 +1,43 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.common.util.exception; + +/** + * Thrown when a value is too large to fit within some smaller data type. + * + * @author DaPorkchop_ + */ +public class ValueCannotFitException extends ValueOutOfBoundsException { + public ValueCannotFitException(String s) { + super(s); + } + + public ValueCannotFitException(long value, byte overload) { + super(value + " cannot fit in a byte"); + } + + public ValueCannotFitException(long value, char overload) { + super(value + " cannot fit in a char"); + } + + public ValueCannotFitException(long value, short overload) { + super(value + " cannot fit in a short"); + } + + public ValueCannotFitException(long value, int overload) { + super(value + " cannot fit in an int"); + } +} diff --git a/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueOutOfBoundsException.java b/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueOutOfBoundsException.java new file mode 100644 index 000000000..87adaffc6 --- /dev/null +++ b/common/src/main/java/net/daporkchop/lib/common/util/exception/ValueOutOfBoundsException.java @@ -0,0 +1,55 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.common.util.exception; + +/** + * Thrown when a value is too large to fit within some smaller data type. + * + * @author DaPorkchop_ + */ +public class ValueOutOfBoundsException extends IllegalArgumentException { + public ValueOutOfBoundsException(String s) { + super(s); + } + + public ValueOutOfBoundsException(byte value, byte expectedMin, byte expectedMax) { + super(String.format("%d is not within expected bounds (min: %d, max: %d)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(short value, short expectedMin, short expectedMax) { + super(String.format("%d is not within expected bounds (min: %d, max: %d)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(char value, char expectedMin, char expectedMax) { + super(String.format("%d is not within expected bounds (min: %d, max: %d)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(int value, int expectedMin, int expectedMax) { + super(String.format("%d is not within expected bounds (min: %d, max: %d)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(long value, long expectedMin, long expectedMax) { + super(String.format("%d is not within expected bounds (min: %d, max: %d)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(float value, float expectedMin, float expectedMax) { + super(String.format("%f is not within expected bounds (min: %f, max: %f)", value, expectedMin, expectedMax)); + } + + public ValueOutOfBoundsException(double value, double expectedMin, double expectedMax) { + super(String.format("%f is not within expected bounds (min: %f, max: %f)", value, expectedMin, expectedMax)); + } +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java index fe6e2e16b..7ab36a959 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CCtx.java @@ -17,7 +17,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** @@ -25,20 +25,31 @@ * * @author DaPorkchop_ */ -public interface CCtx extends Context { +public interface CCtx extends Context { + /** + * Convenience method, equivalent to {@code compress(src, dst, null);}. + * + * @see #compress(ByteBuf, ByteBuf, ByteBuf) + */ + default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return this.compress(src, dst, null); + } + /** * Compresses the given source data into the given destination buffer at the configured compression level. *

* If the destination buffer does not have enough space writable for the compressed data, the operation will fail and both buffer's indices will remain * unchanged, however the destination buffer's contents may be modified. *

- * The currently configured dictionary will always remain unaffected by this method. + * In either case, the indices of the dictionary buffer remain unaffected. * - * @param src the {@link ByteBuf} to read source data from - * @param dst the {@link ByteBuf} to write compressed data to + * @param src the {@link ByteBuf} to read source data from + * @param dst the {@link ByteBuf} to write compressed data to + * @param dict the (possibly {@code null}) {@link ByteBuf} containing the dictionary to be used for compression * @return whether or not compression was successful. If {@code false}, the destination buffer was too small for the compressed data + * @throws DictionaryNotAllowedException if the dictionary buffer is not {@code null} and this context does not allow use of a dictionary */ - boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException; /** * @return the configured compression level diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java index 1d45d6722..c938a77c0 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java @@ -15,6 +15,8 @@ package net.daporkchop.lib.compression; +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.BufferTyped; @@ -42,6 +44,22 @@ public interface CompressionProvider extends BufferTyped { */ int levelBest(); + /** + * @see #compressBoundLong(long) + * @throws ValueCannotFitException if the returned value is too large to fit in an {@code int} + */ + default int compressBound(int srcSize) throws ValueCannotFitException { + return PValidation.toInt(this.compressBoundLong(srcSize)); + } + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length. + * + * @param srcSize the size (in bytes) of the source data + * @return the worst-case size of the compressed data + */ + long compressBoundLong(long srcSize); + /** * Creates a new {@link PDeflater} with the default compression level. * diff --git a/compression/src/main/java/net/daporkchop/lib/compression/Context.java b/compression/src/main/java/net/daporkchop/lib/compression/Context.java index d6a729057..375e0a364 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/Context.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/Context.java @@ -28,41 +28,14 @@ * * @author DaPorkchop_ */ -interface Context> extends Releasable, BufferTyped { +interface Context extends Releasable, BufferTyped { /** * @return the {@link CompressionProvider} that created this context */ CompressionProvider provider(); - /** - * Resets this context. - *

- * This will reset the dictionary buffer to {@code null}. - * - * @return this context - */ - I reset(); - /** * @return whether or not this implementation allows use of a dictionary */ - default boolean hasDict() { - return false; - } - - /** - * Sets the dictionary to be used by this context. - *

- * Must be called immediately after being initialized or reset. - *

- * The dictionary will remain referenced until the context is reset. - * - * @param dict the new dictionary to use. The currently readable region of the buffer will be used as the dictionary. - * @return this context - * @throws UnsupportedOperationException if this context does not allow use of a dictionary - * @see #hasDict() - */ - default I dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { - throw new UnsupportedOperationException(); - } + boolean hasDict(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java index ff8f83eb4..f6aee89b4 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/DCtx.java @@ -17,6 +17,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** @@ -24,18 +25,28 @@ * * @author DaPorkchop_ */ -public interface DCtx extends Context { +public interface DCtx extends Context { + /** + * Convenience method, equivalent to {@code decompress(src, dst, null);}. + * + * @see #decompress(ByteBuf, ByteBuf, ByteBuf) + */ + default boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { + return this.decompress(src, dst, null); + } + /** * Decompresses the given compressed data into the given destination buffer. *

* If the destination buffer does not have enough space writable for the decompressed data, the operation will fail and both buffer's indices will remain * unchanged, however the destination buffer's contents may be modified. *

- * The currently configured dictionary will always remain unaffected by this method. + * In either case, the indices of the dictionary buffer remain unaffected. * * @param src the {@link ByteBuf} to read compressed data from * @param dst the {@link ByteBuf} to write decompressed data to + * @param dict the (possibly {@code null}) {@link ByteBuf} containing the dictionary to be used for decompression * @return whether or not decompression was successful. If {@code false}, the destination buffer was too small for the decompressed data */ - boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException; } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java b/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java index 5cc99622b..953769003 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/StreamingContext.java @@ -19,15 +19,14 @@ import lombok.NonNull; import net.daporkchop.lib.compression.util.exception.ContextFinishedException; import net.daporkchop.lib.compression.util.exception.ContextFinishingException; -import net.daporkchop.lib.natives.util.BufferTyped; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; -import net.daporkchop.lib.unsafe.capability.Releasable; /** * Base interface for {@link PDeflater} and {@link PDeflater}. * @author DaPorkchop_ */ -interface StreamingContext> extends Context { +interface StreamingContext> extends Context { /** * Sets the context's current source buffer when processing data in streaming mode. * @@ -74,10 +73,25 @@ interface StreamingContext> extends Context { /** * Resets this context. *

- * This will erase any internal buffers and reset the source, destination and dictionary buffers to {@code null}. + * This will discard any internal buffers and reset the source, destination and dictionary buffers to {@code null}. * * @return this context */ - @Override I reset(); + + /** + * Sets the dictionary to be used by this context. + *

+ * Must be called immediately after being initialized or reset. + *

+ * The dictionary will remain referenced until the context is reset. + * + * @param dict the new dictionary to use. The currently readable region of the buffer will be used as the dictionary. + * @return this context + * @throws DictionaryNotAllowedException if this context does not allow use of a dictionary + * @see #hasDict() + */ + default I dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException { + throw new DictionaryNotAllowedException(); + } } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java index 3a505dcfd..b7e422d0c 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java @@ -16,12 +16,15 @@ package net.daporkchop.lib.compression.util; import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; import lombok.Getter; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.CompressionProvider; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -31,44 +34,37 @@ * * @author DaPorkchop_ */ +@RequiredArgsConstructor(access = AccessLevel.PROTECTED) @Accessors(fluent = true) public class StreamingWrapperCCtx extends AbstractReleasable implements CCtx { @Getter + @NonNull protected final CompressionProvider provider; - - protected final PDeflater deflater; - protected ByteBuf dict; + @NonNull + protected final PDeflater deflater; @Getter - protected final int level; - - public StreamingWrapperCCtx(@NonNull CompressionProvider provider, int level) { - this(provider, null, level); - } + protected final int level; - protected StreamingWrapperCCtx(@NonNull CompressionProvider provider, @NonNull PDeflater deflater, int level) { - this.provider = provider; - this.deflater = deflater; - this.level = level; + public StreamingWrapperCCtx(@NonNull CompressionProvider provider, int level) throws InvalidCompressionLevelException { + this(provider, provider.deflater(level), level); } @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - this.deflater.reset(); - if (this.dict != null) { - //set dictionary if needed - this.deflater.dict(this.dict); - } - return this.deflater.fullDeflate(src, dst); + return this.deflater.reset().fullDeflate(src, dst); } @Override - public CCtx reset() { + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException { + if (dict != null && !this.hasDict()) { + throw new DictionaryNotAllowedException(); + } + this.deflater.reset(); - if (this.dict != null) { - this.dict.release(); - this.dict = null; + if (dict != null) { + this.deflater.dict(dict); } - return this; + return this.deflater.fullDeflate(src, dst); } @Override @@ -76,22 +72,6 @@ public boolean hasDict() { return this.deflater.hasDict(); } - @Override - public CCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { - if (!this.deflater.hasDict()) { - throw new UnsupportedOperationException(); - } - - //release old dictionary - if (this.dict != null) { - this.dict.release(); - this.dict = null; - } - - this.dict = this.deflater.assertAcceptable(dict).retainedSlice(); - return this; - } - @Override public boolean directAccepted() { return this.deflater.directAccepted(); diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java index da2a126f0..f0a0ed206 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java @@ -25,6 +25,7 @@ import net.daporkchop.lib.compression.CompressionProvider; import net.daporkchop.lib.compression.DCtx; import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -39,10 +40,8 @@ public class StreamingWrapperDCtx extends AbstractReleasable implements DCtx { @Getter protected final CompressionProvider provider; - @NonNull - protected PInflater inflater; - protected ByteBuf dict; + protected final PInflater inflater; public StreamingWrapperDCtx(@NonNull CompressionProvider provider) { this(provider, provider.inflater()); @@ -50,22 +49,20 @@ public StreamingWrapperDCtx(@NonNull CompressionProvider provider) { @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - this.inflater.reset(); - if (this.dict != null) { - //set dictionary if needed - this.inflater.dict(this.dict); - } - return this.inflater.fullInflate(src, dst); + return this.inflater.reset().fullInflate(src, dst); } @Override - public DCtx reset() { + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException { + if (dict != null && !this.hasDict()) { + throw new DictionaryNotAllowedException(); + } + this.inflater.reset(); - if (this.dict != null) { - this.dict.release(); - this.dict = null; + if (dict != null) { + this.inflater.dict(dict); } - return this; + return this.inflater.fullInflate(src, dst); } @Override @@ -73,22 +70,6 @@ public boolean hasDict() { return this.inflater.hasDict(); } - @Override - public DCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException, UnsupportedOperationException { - if (!this.inflater.hasDict()) { - throw new UnsupportedOperationException(); - } - - //release old dictionary - if (this.dict != null) { - this.dict.release(); - this.dict = null; - } - - this.dict = this.inflater.assertAcceptable(dict).retainedSlice(); - return this; - } - @Override public boolean directAccepted() { return this.inflater.directAccepted(); @@ -112,6 +93,5 @@ public ByteBuf assertAcceptable(@NonNull ByteBuf buf) throws InvalidBufferTypeEx @Override protected void doRelease() { this.inflater.release(); - this.inflater = null; } } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java index a177d7e90..f9446f053 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/ContextFinishingException.java @@ -20,5 +20,5 @@ * * @author DaPorkchop_ */ -public final class ContextFinishingException extends ContextFinishedException { +public class ContextFinishingException extends ContextFinishedException { } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/DictionaryNotAllowedException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/DictionaryNotAllowedException.java new file mode 100644 index 000000000..ec01af72d --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/DictionaryNotAllowedException.java @@ -0,0 +1,24 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.util.exception; + +/** + * Thrown when a {@link net.daporkchop.lib.compression.Context} that does not allow use of a dictionary is given one anyway. + * + * @author DaPorkchop_ + */ +public class DictionaryNotAllowedException extends UnsupportedOperationException { +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java index cc570d0d5..989adc0e2 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/exception/InvalidCompressionLevelException.java @@ -23,7 +23,7 @@ * * @author DaPorkchop_ */ -public final class InvalidCompressionLevelException extends IllegalArgumentException { +public class InvalidCompressionLevelException extends IllegalArgumentException { public static int validate(int level, @NonNull CompressionProvider provider) throws InvalidCompressionLevelException { if (level < provider.levelFast() || level > provider.levelBest()) { throw new InvalidCompressionLevelException(level, provider); diff --git a/compression/zlib/Makefile b/compression/zlib/Makefile index 172803472..1ae6d5ef6 100644 --- a/compression/zlib/Makefile +++ b/compression/zlib/Makefile @@ -1,12 +1,12 @@ -OUTDIR := $(PROJDIR)/src/main/resources - ifneq ($(BUILD),$(notdir $(CURDIR))) .PHONY: $(BUILD) clean -BUILDDIR := build/$(BUILD) +export OUTDIR := $(CURDIR)/src/main/resources +BUILDDIR := build/native/$(BUILD_TYPE)/$(BUILD) clean: - @rm -rf build/ $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) + @if [ -d build/native/ ]; then rm -rf build/native/; fi + @rm -rf $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) $(BUILD): @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) @@ -26,10 +26,12 @@ OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) INCLUDE := $(addprefix -I,$(INCLUDES) $(CURDIR)) -build: $(OUTDIR)/$(BUILD)/libzlib.$(EXT) - -$(OUTDIR)/$(BUILD)/libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a +build: libzlib.$(EXT) + @echo "Copying libzlib.$(EXT) to $(OUTDIR)/$(BUILD)/..." @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) + @cp libzlib.$(EXT) $(OUTDIR)/$(BUILD)/libzlib.$(EXT) + +libzlib.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Linking $@..." @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zlib/libz-ng.a @echo "Stripping $@..." diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java index b2d1f4fc6..4fd5e3e6d 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibCCtx.java @@ -36,14 +36,8 @@ public interface ZlibCCtx extends CCtx { */ int mode(); - @Override - ZlibCCtx reset(); - @Override default boolean hasDict() { return true; } - - @Override - ZlibCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java index 2d2a47a6b..f692ffe18 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibDCtx.java @@ -32,14 +32,8 @@ public interface ZlibDCtx extends DCtx { */ int mode(); - @Override - ZlibDCtx reset(); - @Override default boolean hasDict() { return true; } - - @Override - ZlibDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index bce2924cd..63ce72c73 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -16,12 +16,11 @@ package net.daporkchop.lib.compression.zlib; -import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; import net.daporkchop.lib.compression.CompressionProvider; -import net.daporkchop.lib.compression.DCtx; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.impl.Feature; -import net.daporkchop.lib.natives.util.BufferTyped; /** * Representation of a Zlib implementation. @@ -44,6 +43,55 @@ default int levelBest() { return Zlib.LEVEL_BEST; } + @Override + default int compressBound(int srcSize) throws ValueCannotFitException { + return PValidation.toInt(this.compressBoundLong(srcSize, Zlib.MODE_ZLIB)); + } + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length using the Gzip format. + * + * @see #compressBound(int) + */ + default int compressBoundGzip(int srcSize) throws ValueCannotFitException { + return PValidation.toInt(this.compressBoundLong(srcSize, Zlib.MODE_GZIP)); + } + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length using the given mode. + * + * @param srcSize the size (in bytes) of the source data + * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP} or {@link Zlib#MODE_RAW} + * @return the worst-case size of the compressed data + * @see #compressBound(int) + */ + default int compressBound(long srcSize, int mode) throws ValueCannotFitException { + return PValidation.toInt(this.compressBoundLong(srcSize, mode)); + } + + @Override + default long compressBoundLong(long srcSize) { + return this.compressBoundLong(srcSize, Zlib.MODE_ZLIB); + } + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length using the Gzip format. + * + * @see #compressBoundLong(long) + */ + default long compressBoundGzipLong(long srcSize) { + return this.compressBoundLong(srcSize, Zlib.MODE_GZIP); + } + + /** + * Gets the maximum (worst-case) compressed size for input data of the given length using the given mode. + * + * @param srcSize the size (in bytes) of the source data + * @param mode the {@link Zlib} mode to use. Must be one of {@link Zlib#MODE_ZLIB}, {@link Zlib#MODE_GZIP} or {@link Zlib#MODE_RAW} + * @return the worst-case size of the compressed data + */ + long compressBoundLong(long srcSize, int mode); + /** * @return a new {@link ZlibDeflater} */ diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java index 92024b893..416de5527 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/java/JavaZlib.java @@ -15,6 +15,10 @@ package net.daporkchop.lib.compression.zlib.java; +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.compression.zlib.Zlib; +import net.daporkchop.lib.compression.zlib.ZlibCCtx; +import net.daporkchop.lib.compression.zlib.ZlibDCtx; import net.daporkchop.lib.compression.zlib.ZlibDeflater; import net.daporkchop.lib.compression.zlib.ZlibInflater; import net.daporkchop.lib.compression.zlib.ZlibProvider; @@ -30,6 +34,23 @@ public boolean directAccepted() { return false; } + @Override + public long compressBoundLong(long srcSize, int mode) { + //extracted from deflate.c, i'm assuming that the java implementation has the same limits + PValidation.ensureNonNegative(srcSize); + long conservativeUpperBound = srcSize + ((srcSize + 7L) >> 3L) + ((srcSize + 63L) >> 6L) + 5L; + switch (mode) { + case Zlib.MODE_ZLIB: + return conservativeUpperBound + 6L + 4L; //additional +4 in case `strstart`? whatever that means + case Zlib.MODE_GZIP: + return conservativeUpperBound + 18L; //assume there is no gzip message + case Zlib.MODE_RAW: + return conservativeUpperBound; + default: + throw new IllegalArgumentException("Invalid Zlib compression mode: " + mode); + } + } + @Override public ZlibDeflater deflater(int level, int strategy, int mode) { throw new UnsupportedOperationException(); //TODO @@ -39,4 +60,14 @@ public ZlibDeflater deflater(int level, int strategy, int mode) { public ZlibInflater inflater(int mode) { throw new UnsupportedOperationException(); //TODO } + + @Override + public ZlibCCtx compressionContext(int level, int strategy, int mode) { + throw new UnsupportedOperationException(); //TODO + } + + @Override + public ZlibDCtx decompressionContext(int mode) { + throw new UnsupportedOperationException(); //TODO + } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java index 97d7819b5..214aed326 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlib.java @@ -15,6 +15,8 @@ package net.daporkchop.lib.compression.zlib.natives; +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.compression.zlib.Zlib; import net.daporkchop.lib.compression.zlib.ZlibCCtx; import net.daporkchop.lib.compression.zlib.ZlibDCtx; import net.daporkchop.lib.compression.zlib.ZlibDeflater; @@ -36,6 +38,9 @@ public boolean directAccepted() { return true; } + @Override + public native long compressBoundLong(long srcSize, int mode); + @Override public ZlibCCtx compressionContext(int level, int strategy, int mode) { return new NativeZlibCCtx(this, level, strategy, mode); diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java index c0590242c..f92995612 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibCCtx.java @@ -41,14 +41,7 @@ final class NativeZlibCCtx extends StreamingWrapperCCtx implements ZlibCCtx { } @Override - public ZlibCCtx reset() { - super.reset(); - return this; - } - - @Override - public ZlibCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { - super.dict(dict); - return this; + public boolean hasDict() { + return true; } } diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java index 70e4ef1be..0a3a9ded0 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/natives/NativeZlibDCtx.java @@ -40,14 +40,7 @@ final class NativeZlibDCtx extends StreamingWrapperDCtx implements ZlibDCtx { } @Override - public ZlibDCtx reset() { - super.reset(); - return this; - } - - @Override - public ZlibDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { - super.dict(dict); - return this; + public boolean hasDict() { + return true; } } diff --git a/compression/zlib/src/main/native/common/NativeZlib.cpp b/compression/zlib/src/main/native/common/NativeZlib.cpp new file mode 100644 index 000000000..822f5c4bf --- /dev/null +++ b/compression/zlib/src/main/native/common/NativeZlib.cpp @@ -0,0 +1,23 @@ +#include +#include "NativeZlib.h" + +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_compressBoundLong + (JNIEnv* env, jobject obj, jlong srcSize, jint mode) { + if (srcSize < 0) { + return throwException(env, "srcSize may not be negative!", srcSize); + } + + long conservativeUpperBound = zng_deflateBound(nullptr, srcSize); + switch (mode) { + case 0: //zlib + return conservativeUpperBound + 6 + 4; //additional +4 in case `strstart`? whatever that means + case 1: //gzip + return conservativeUpperBound + 18; //assume there is no gzip message + case 2: //raw + return conservativeUpperBound; + default: + return throwException(env, "Invalid zlib mode!", mode); + } +} diff --git a/compression/zlib/src/main/native/common/NativeZlib.h b/compression/zlib/src/main/native/common/NativeZlib.h new file mode 100644 index 000000000..f52b07cfe --- /dev/null +++ b/compression/zlib/src/main/native/common/NativeZlib.h @@ -0,0 +1,25 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlib +#define _Included_net_daporkchop_lib_compression_zlib_natives_NativeZlib + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Method: compressBoundLong + * Signature: (JI)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_compressBoundLong + (JNIEnv *, jobject, jlong, jint); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater diff --git a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp index 94a015445..552d4943e 100644 --- a/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibDeflater.cpp @@ -3,11 +3,6 @@ #include -#include -#include - -#include - static jfieldID ctxID; static jfieldID readBytesID; static jfieldID writtenBytesID; @@ -45,18 +40,16 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com windowBits = -15; break; default: - throwException(env, "Invalid deflater mode!", mode); - return 0; + return throwException(env, "Invalid deflater mode!", mode); } - zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); - memset(stream, 0, sizeof(zng_stream)); + zng_stream* stream = (zng_stream*) new char[sizeof(zng_stream)](); int ret = zng_deflateInit2(stream, level, Z_DEFLATED, windowBits, 8, strategy); if (ret != Z_OK) { const char* msg = stream->msg; - free(stream); + delete stream; throwException(env, msg == nullptr ? "Couldn't init deflater!" : msg, ret); return 0; } @@ -76,7 +69,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp ret = zng_deflateEnd(stream); const char* msg = stream->msg; - free(stream); + delete stream; if (ret != Z_OK) { throwException(env, msg == nullptr ? "Couldn't end deflater!" : msg, ret); diff --git a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp index 14d767889..ed736eb6d 100644 --- a/compression/zlib/src/main/native/common/NativeZlibInflater.cpp +++ b/compression/zlib/src/main/native/common/NativeZlibInflater.cpp @@ -3,11 +3,6 @@ #include -#include -#include - -#include - static jfieldID ctxID; static jfieldID readBytesID; static jfieldID writtenBytesID; @@ -44,14 +39,13 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com return 0; } - zng_stream* stream = (zng_stream*) malloc(sizeof(zng_stream)); - memset(stream, 0, sizeof(zng_stream)); + zng_stream* stream = (zng_stream*) new char[sizeof(zng_stream)](); int ret = zng_inflateInit2(stream, windowBits); if (ret != Z_OK) { const char* msg = stream->msg; - free(stream); + delete stream; throwException(env, msg == nullptr ? "Couldn't init inflater!" : msg, ret); return 0; } @@ -65,7 +59,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp int ret = zng_inflateEnd(stream); const char* msg = stream->msg; - free(stream); + delete stream; if (ret != Z_OK) { throwException(env, msg == nullptr ? "Couldn't end inflater!" : msg, ret); diff --git a/compression/zstd/Makefile b/compression/zstd/Makefile index 6cf8ee267..fda022603 100644 --- a/compression/zstd/Makefile +++ b/compression/zstd/Makefile @@ -1,12 +1,12 @@ -OUTDIR := $(PROJDIR)/src/main/resources - ifneq ($(BUILD),$(notdir $(CURDIR))) .PHONY: $(BUILD) clean -BUILDDIR := build/$(BUILD) +export OUTDIR := $(CURDIR)/src/main/resources +BUILDDIR := build/native/$(BUILD_TYPE)/$(BUILD) clean: - @rm -rf build/ $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) + @if [ -d build/native/ ]; then rm -rf build/native/; fi + @rm -rf $(foreach arch,$(ARCHS),$(OUTDIR)/$(arch)) $(BUILD): @[ -d $(BUILDDIR) ] || mkdir -p $(BUILDDIR) @@ -26,10 +26,12 @@ OFILES := $(addsuffix .o,$(subst /,__,$(CFILES)) $(subst /,__,$(CPPFILES))) INCLUDE := $(addprefix -I,$(INCLUDES) $(CURDIR)) -build: $(OUTDIR)/$(BUILD)/libzstd.$(EXT) - -$(OUTDIR)/$(BUILD)/libzstd.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a +build: libzstd.$(EXT) + @echo "Copying libzstd.$(EXT) to $(OUTDIR)/$(BUILD)/..." @[ -d $(OUTDIR)/$(BUILD) ] || mkdir -p $(OUTDIR)/$(BUILD) + @cp libzstd.$(EXT) $(OUTDIR)/$(BUILD)/libzstd.$(EXT) + +libzstd.$(EXT): $(CFILES) $(CPPFILES) $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @echo "Linking $@..." @$(LD) $(LDFLAGS) $(INCLUDE) -o $@ $(OFILES) $(CURDIR)/lib-zstd/lib/libzstd.a @echo "Stripping $@..." diff --git a/compression/zstd/src/example/java/ZstdTest.java b/compression/zstd/src/example/java/ZstdTest.java index 4e5c7bc03..6fe9a15e7 100644 --- a/compression/zstd/src/example/java/ZstdTest.java +++ b/compression/zstd/src/example/java/ZstdTest.java @@ -66,7 +66,7 @@ public static void main(String... args) { Zstd.PROVIDER.compress(original.clear().writerIndex(SIZE), compressed.clear(), Zstd.LEVEL_MAX); compressed.markWriterIndex(); - int uncompressedSize = PValidation.toPositiveIntSafe(Zstd.PROVIDER.frameContentSize(compressed)); + int uncompressedSize = Zstd.PROVIDER.frameContentSize(compressed); ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); long start = System.currentTimeMillis(); @@ -97,7 +97,7 @@ public static void main(String... args) { Zstd.PROVIDER.compress(original.slice(), compressed, Zstd.LEVEL_DEFAULT); System.out.printf("original: %d, compressed: %d\n", original.readableBytes(), compressed.readableBytes()); - int uncompressedSize = PValidation.toPositiveIntSafe(Zstd.PROVIDER.frameContentSize(compressed)); + int uncompressedSize = PValidation.toPositiveIntSafe(Zstd.PROVIDER.frameContentSizeLong(compressed)); System.out.printf("original size: %d, frame content size: %d\n", SIZE, uncompressedSize); ByteBuf uncompressed = Unpooled.directBuffer(uncompressedSize, uncompressedSize); diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java index 73a3671cf..2a0691f3b 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java @@ -18,6 +18,7 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** @@ -29,7 +30,7 @@ */ public interface ZstdCCtx extends CCtx { /** - * Compresses the given source data into the given destination buffer at the currently configured compression level. + * Compresses the given source data into the given destination buffer at the configured Zstd level. * * @see CCtx#compress(ByteBuf, ByteBuf) */ @@ -47,14 +48,28 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva */ boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException; + /** + * Compresses the given source data into the given destination buffer at the configured Zstd level using the given dictionary. + * + * @see CCtx#compress(ByteBuf, ByteBuf, ByteBuf) + */ @Override - ZstdCCtx reset(); + default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException, DictionaryNotAllowedException { + return this.compress(src, dst, dict, this.level()); + } + + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer at the given Zstd level using the given dictionary. + *

+ * This is possible because Zstd allows using the same context for any compression level without having to reallocate it. + * + * @see #compress(ByteBuf, ByteBuf, int) + * @see #compress(ByteBuf, ByteBuf, ByteBuf) + */ + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict, int compressionLevel) throws InvalidBufferTypeException; @Override default boolean hasDict() { return true; } - - @Override - ZstdCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java index d698611e2..299219f90 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java @@ -28,21 +28,8 @@ * @author DaPorkchop_ */ public interface ZstdDCtx extends DCtx { - /** - * Decompresses the given Zstd-compressed data into the given destination buffer. - * - * @see DCtx#decompress(ByteBuf, ByteBuf) - */ - boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; - - @Override - ZstdDCtx reset(); - @Override default boolean hasDict() { return true; } - - @Override - ZstdDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException; } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index 0450fe19a..5441be142 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -17,13 +17,12 @@ import io.netty.buffer.ByteBuf; import lombok.NonNull; -import net.daporkchop.lib.compression.CCtx; +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; import net.daporkchop.lib.compression.CompressionProvider; -import net.daporkchop.lib.compression.DCtx; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.Feature; -import net.daporkchop.lib.natives.util.BufferTyped; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; /** @@ -69,6 +68,14 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva */ boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; + /** + * @see #frameContentSizeLong(ByteBuf) + * @throws ValueCannotFitException if the returned value is too large to fit in an {@code int} + */ + default int frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException, ValueCannotFitException { + return PValidation.toInt(this.frameContentSizeLong(src)); + } + /** * Gets the decompressed size of the given Zstd-compressed data. * @@ -76,15 +83,12 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva * @return the size (in bytes) of the decompressed data * @throws ContentSizeUnknownException if the decompressed size cannot be determined */ - long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException; + long frameContentSizeLong(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException; - /** - * Gets the maximum (worst-case) compressed size for input data of the given length. - * - * @param srcSize the size (in bytes) of the source data - * @return the worst-case size of the compressed data - */ - long compressBound(long srcSize); + @Override + default ZstdCCtx compressionContext() { + return this.compressionContext(Zstd.LEVEL_DEFAULT); + } @Override ZstdCCtx compressionContext(int level) throws InvalidCompressionLevelException; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 844860ad9..674e63617 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -59,39 +59,24 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compress this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), compressionLevel); - if (val >= 0) { - src.skipBytes(src.readableBytes()); - dst.writerIndex(dst.writerIndex() + val); - return true; - } else { - return false; - } + return NativeZstdHelper.finalizeOneShot(src, dst, val); } private native int doCompress(long srcAddr, int srcSize, long dstAddr, int dstSize, int compressionLevel); @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - this.assertAcceptable(src); - this.assertAcceptable(dst); - - int val = this.doDecompress(src.memoryAddress() + src.readerIndex(), src.readableBytes(), - dst.memoryAddress() + dst.writerIndex(), dst.writableBytes()); + int val = this.doDecompress(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes()); - if (val >= 0) { - src.skipBytes(src.readableBytes()); - dst.writerIndex(dst.writerIndex() + val); - return true; - } else { - return false; - } + return NativeZstdHelper.finalizeOneShot(src, dst, val); } private native int doDecompress(long srcAddr, int srcSize, long dstAddr, int dstSize); @Override - public long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException { - long size = this.doFrameContentSize(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes()); + public long frameContentSizeLong(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException { + long size = this.doFrameContentSizeLong(this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes()); if (size >= 0L) { return size; } else { @@ -99,14 +84,14 @@ public long frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeExcep } } - private native long doFrameContentSize(long srcAddr, int srcSize); + private native long doFrameContentSizeLong(long srcAddr, int srcSize); @Override - public long compressBound(long srcSize) { - return this.doCompressBound(PValidation.ensureNonNegative(srcSize)); + public long compressBoundLong(long srcSize) { + return this.doCompressBoundLong(PValidation.ensureNonNegative(srcSize)); } - private native long doCompressBound(long srcSize); + private native long doCompressBoundLong(long srcSize); @Override public PDeflater deflater(int level) throws InvalidCompressionLevelException { diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java index 983f0521e..76137dc27 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java @@ -16,13 +16,10 @@ package net.daporkchop.lib.compression.zstd.natives; import io.netty.buffer.ByteBuf; -import lombok.AccessLevel; import lombok.Getter; -import lombok.NoArgsConstructor; import lombok.NonNull; import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; -import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; @@ -44,7 +41,6 @@ final class NativeZstdCCtx extends AbstractReleasable implements ZstdCCtx { @Getter private final NativeZstd provider; - private ByteBuf dict; @Getter private int level; @@ -56,22 +52,33 @@ final class NativeZstdCCtx extends AbstractReleasable implements ZstdCCtx { @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, int compressionLevel) throws InvalidBufferTypeException { - int val = this.doCompress(this.ctx, + int val = this.doCompressNoDict(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), - this.dict != null ? this.dict.memoryAddress() : 0L, this.dict != null ? this.dict.readableBytes() : 0, compressionLevel); - if (val >= 0) { - src.skipBytes(src.readableBytes()); - dst.writerIndex(dst.writerIndex() + val); - return true; - } else { - return false; + return NativeZstdHelper.finalizeOneShot(src, dst, val); + } + + private native int doCompressNoDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, int compressionLevel); + + @Override + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict, int compressionLevel) throws InvalidBufferTypeException { + if (dict == null) { + //compress without dictionary + return this.compress(src, dst, compressionLevel); } + + int val = this.doCompressRawDict(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + this.assertAcceptable(dict).memoryAddress() + dict.readerIndex(), dict.readableBytes(), + compressionLevel); + + return NativeZstdHelper.finalizeOneShot(src, dst, val); } - private native int doCompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize, int compressionLevel); + private native int doCompressRawDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize, int compressionLevel); @Override public boolean directAccepted() { @@ -80,25 +87,9 @@ public boolean directAccepted() { @Override protected void doRelease() { - this.reset(); this.cleaner.clean(); } - @Override - public ZstdCCtx reset() { - if (this.dict != null) { - this.dict.release(); - this.dict = null; - } - return this; - } - - @Override - public ZstdCCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { - this.dict = this.reset().assertAcceptable(dict).retainedSlice(); - return this; - } - @RequiredArgsConstructor private static final class Releaser implements Runnable { private final long ctx; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java index 3a4a97151..34772fb86 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java @@ -44,25 +44,34 @@ final class NativeZstdDCtx extends AbstractReleasable implements ZstdDCtx { @Getter private final NativeZstd provider; - private ByteBuf dict; @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException { - int val = this.doDecompress(this.ctx, + int val = this.doDecompressNoDict(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), - this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), - this.dict != null ? this.dict.memoryAddress() : 0L, this.dict != null ? this.dict.readableBytes() : 0); - - if (val >= 0) { - src.skipBytes(src.readableBytes()); - dst.writerIndex(dst.writerIndex() + val); - return true; - } else { - return false; + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes()); + + return NativeZstdHelper.finalizeOneShot(src, dst, val); + } + + private native int doDecompressNoDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize); + + @Override + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict) throws InvalidBufferTypeException { + if (dict == null) { + //decompress without dictionary + return this.decompress(src, dst); } + + int val = this.doDecompressRawDict(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + this.assertAcceptable(dict).memoryAddress() + dict.readerIndex(), dict.readableBytes()); + + return NativeZstdHelper.finalizeOneShot(src, dst, val); } - private native int doDecompress(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); + private native int doDecompressRawDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); @Override public boolean directAccepted() { @@ -71,25 +80,9 @@ public boolean directAccepted() { @Override protected void doRelease() { - this.reset(); this.cleaner.clean(); } - @Override - public ZstdDCtx reset() { - if (this.dict != null) { - this.dict.release(); - this.dict = null; - } - return this; - } - - @Override - public ZstdDCtx dict(@NonNull ByteBuf dict) throws InvalidBufferTypeException { - this.dict = this.reset().assertAcceptable(dict).retainedSlice(); - return this; - } - @RequiredArgsConstructor private static final class Releaser implements Runnable { private final long ctx; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdHelper.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdHelper.java new file mode 100644 index 000000000..6c6eb1d6b --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdHelper.java @@ -0,0 +1,37 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.experimental.UtilityClass; + +/** + * Helper methods used by various native Zstd implementations. + * + * @author DaPorkchop_ + */ +@UtilityClass +class NativeZstdHelper { + public static boolean finalizeOneShot(ByteBuf src, ByteBuf dst, int val) { + if (val >= 0) { + src.skipBytes(src.readableBytes()); + dst.writerIndex(dst.writerIndex() + val); + return true; + } else { + return false; + } + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java index 536d2bd19..dbbc8135c 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/util/exception/ContentSizeUnknownException.java @@ -19,7 +19,7 @@ import net.daporkchop.lib.compression.zstd.ZstdProvider; /** - * Thrown when {@link ZstdProvider#frameContentSize(ByteBuf)} cannot identify the content size of the given frame. + * Thrown when {@link ZstdProvider#frameContentSizeLong(ByteBuf)} cannot identify the content size of the given frame. * * @author DaPorkchop_ */ diff --git a/compression/zstd/src/main/native/common/NativeZstd.cpp b/compression/zstd/src/main/native/common/NativeZstd.cpp index 5cedb4fc0..8e1ce6e47 100644 --- a/compression/zstd/src/main/native/common/NativeZstd.cpp +++ b/compression/zstd/src/main/native/common/NativeZstd.cpp @@ -4,11 +4,6 @@ #include #include -#include -#include - -#include - __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompress (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jint compressionLevel) { auto ret = ZSTD_compress((void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); @@ -41,7 +36,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp return (jint) ret; } -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSize +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSizeLong (JNIEnv* env, jobject obj, jlong srcAddr, jint srcSize) { auto contentSize = ZSTD_getFrameContentSize((void*) srcAddr, srcSize); @@ -53,7 +48,7 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com return contentSize; } -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBoundLong (JNIEnv* env, jobject obj, jlong srcSize) { return ZSTD_compressBound(srcSize); } diff --git a/compression/zstd/src/main/native/common/NativeZstd.h b/compression/zstd/src/main/native/common/NativeZstd.h index 7b99ba044..93695a0ea 100644 --- a/compression/zstd/src/main/native/common/NativeZstd.h +++ b/compression/zstd/src/main/native/common/NativeZstd.h @@ -31,7 +31,7 @@ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs * Method: doFrameContentSize * Signature: (JI)J */ -JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSize +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doFrameContentSizeLong (JNIEnv *, jobject, jlong, jint); /* @@ -39,7 +39,7 @@ JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZ * Method: doCompressBound * Signature: (J)J */ -JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBound +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstd_doCompressBoundLong (JNIEnv *, jobject, jlong); #ifdef __cplusplus diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp index b3dd176a3..aa916f2c8 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp @@ -4,11 +4,6 @@ #include #include -#include -#include - -#include - __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_allocateCtx (JNIEnv* env, jclass cla) { return (jlong) ZSTD_createCCtx(); @@ -24,11 +19,25 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } } -__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressNoDict + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jint compressionLevel) { + auto ret = ZSTD_compressCCtx((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressRawDict (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize, jint compressionLevel) { - auto ret = dictAddr - ? ZSTD_compress_usingDict((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize, compressionLevel) - : ZSTD_compressCCtx((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, compressionLevel); + auto ret = ZSTD_compress_usingDict((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize, compressionLevel); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.h b/compression/zstd/src/main/native/common/NativeZstdCCtx.h index 0e8145c4a..9dd701e84 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.h @@ -28,10 +28,18 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs /* * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx - * Method: doCompress + * Method: doCompressNoDict + * Signature: (JJIJII)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressNoDict + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jint); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + * Method: doCompressRawDict * Signature: (JJIJIJII)I */ -JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompress +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressRawDict (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint, jint); #ifdef __cplusplus diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp index 305a5e39d..32f0af1e9 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp @@ -4,11 +4,6 @@ #include #include -#include -#include - -#include - __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_allocateCtx (JNIEnv* env, jclass cla) { return (jlong) ZSTD_createDCtx(); @@ -24,11 +19,25 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp } } -__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressNoDict + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize) { + auto ret = ZSTD_decompressDCtx((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressRawDict (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr, jint dictSize) { - auto ret = dictAddr - ? ZSTD_decompress_usingDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize) - : ZSTD_decompressDCtx((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize); + auto ret = ZSTD_decompress_usingDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr, dictSize); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.h b/compression/zstd/src/main/native/common/NativeZstdDCtx.h index 38c8fac55..b1e805dc9 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.h @@ -28,10 +28,18 @@ JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs /* * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx - * Method: doDecompress + * Method: doDecompressNoDict + * Signature: (JJIJI)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressNoDict + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + * Method: doDecompressRawDict * Signature: (JJIJIJI)I */ -JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompress +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressRawDict (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint); #ifdef __cplusplus diff --git a/natives/Makefile b/natives/Makefile index 3bd001bb5..1b478084f 100644 --- a/natives/Makefile +++ b/natives/Makefile @@ -11,6 +11,15 @@ export CFLAGS := -shared -Ofast -ffast-math -fPIC -ffunction-sections -fdata-se export CXXFLAGS := $(CFLAGS) export LDFLAGS := $(CFLAGS) -Wl,--gc-sections +ifndef PORKLIB_NATIVES_DEBUG +export CFLAGS := $(CFLAGS) +export BUILD_TYPE := release +else +export CFLAGS := $(CFLAGS) -DPORKLIB_NATIVES_DEBUG +export BUILD_TYPE := debug +endif +$(info natives: building for $(BUILD_TYPE)) + export SOURCES := export INCLUDES := $(COMMONSRC)/include $(JAVA_HOME)include $(JAVA_HOME)include/linux diff --git a/natives/compile.sh b/natives/compile.sh index 23a203d85..ea1919380 100644 --- a/natives/compile.sh +++ b/natives/compile.sh @@ -2,5 +2,8 @@ #i use this script simply so that i can add the natives compilation as a run configuration in intellij +export PORKLIB_NATIVES_DEBUG="true" + #make clean && \ +#make -j$( nproc ) make -j$( nproc ) build.x86_64-linux-gnu diff --git a/natives/src/main/java/net/daporkchop/lib/natives/NativeCodeException.java b/natives/src/main/java/net/daporkchop/lib/natives/NativeException.java similarity index 72% rename from natives/src/main/java/net/daporkchop/lib/natives/NativeCodeException.java rename to natives/src/main/java/net/daporkchop/lib/natives/NativeException.java index 7ba563a87..64656b9be 100644 --- a/natives/src/main/java/net/daporkchop/lib/natives/NativeCodeException.java +++ b/natives/src/main/java/net/daporkchop/lib/natives/NativeException.java @@ -1,7 +1,7 @@ /* * Adapted from the Wizardry License * - * Copyright (c) 2018-2019 DaPorkchop_ and contributors + * Copyright (c) 2018-2020 DaPorkchop_ and contributors * * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. * @@ -19,23 +19,32 @@ import lombok.experimental.Accessors; /** - * Thrown by native libraries when an exception occurs. + * Thrown when an exception occurs in native code. * * @author DaPorkchop_ */ @Getter @Accessors(fluent = true) -public final class NativeCodeException extends RuntimeException { - protected final int err; +public class NativeException extends RuntimeException { + protected final long code; - public NativeCodeException(String message, int err) { + public NativeException(String message) { + this(message, 0L); + } + + public NativeException(String message, int code) { + this(message, (long) code); + } + + public NativeException(String message, long code) { super(message); - this.err = err; + this.code = code; } @Override public String getMessage() { - return String.format("%d: %s", this.err, super.getMessage()); + String message = super.getMessage(); + return message == null ? String.valueOf(this.code) : this.code + ": " + message; } } diff --git a/natives/src/main/native/common/common.cpp b/natives/src/main/native/common/common.cpp index 6959ca7fe..91b36a083 100644 --- a/natives/src/main/native/common/common.cpp +++ b/natives/src/main/native/common/common.cpp @@ -1,7 +1,17 @@ #include -jint throwException(JNIEnv* env, const char* msg, int err) { - jclass clazz = env->FindClass("net/daporkchop/lib/natives/NativeCodeException"); +jint throwException(JNIEnv* env, const char* msg) { + jclass clazz = env->FindClass("net/daporkchop/lib/natives/NativeException"); + + return env->Throw((jthrowable) env->NewObject( + clazz, + env->GetMethodID(clazz, "", "(Ljava/lang/String;)V"), + env->NewStringUTF(msg) + )); +} + +jint throwException(JNIEnv* env, const char* msg, jint err) { + jclass clazz = env->FindClass("net/daporkchop/lib/natives/NativeException"); return env->Throw((jthrowable) env->NewObject( clazz, @@ -11,6 +21,17 @@ jint throwException(JNIEnv* env, const char* msg, int err) { )); } +jint throwException(JNIEnv* env, const char* msg, jlong err) { + jclass clazz = env->FindClass("net/daporkchop/lib/natives/NativeException"); + + return env->Throw((jthrowable) env->NewObject( + clazz, + env->GetMethodID(clazz, "", "(Ljava/lang/String;J)V"), + env->NewStringUTF(msg), + err + )); +} + jlong max_l(jlong a, jlong b) { return a > b ? a : b; } diff --git a/natives/src/main/native/include/common.h b/natives/src/main/native/include/common.h index 9aaf51f64..f251390f5 100644 --- a/natives/src/main/native/include/common.h +++ b/natives/src/main/native/include/common.h @@ -1,6 +1,18 @@ #include -jint throwException(JNIEnv* env, const char* msg, int err); +#ifdef PORKLIB_NATIVES_DEBUG +//include some extra headers that might be useful while debugging +#include +#include + +#include +#endif + +jint throwException(JNIEnv* env, const char* msg); + +jint throwException(JNIEnv* env, const char* msg, jint err); + +jint throwException(JNIEnv* env, const char* msg, jlong err); jlong max_l(jlong a, jlong b); diff --git a/natives/toolchain/aarch64-linux-gnu b/natives/toolchain/aarch64-linux-gnu index 73e5dca80..ea7f23ea8 100644 --- a/natives/toolchain/aarch64-linux-gnu +++ b/natives/toolchain/aarch64-linux-gnu @@ -1,6 +1,14 @@ +ifndef PORKLIB_NATIVES_DEBUG +# release mode export CFLAGS := $(CFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export CXXFLAGS := $(CXXFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export LDFLAGS := $(LDFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +else +# debug mode +export CFLAGS := $(CFLAGS) +export CXXFLAGS := $(CXXFLAGS) +export LDFLAGS := $(LDFLAGS) +endif export CC := aarch64-linux-gnu-gcc export CXX := aarch64-linux-gnu-g++ diff --git a/natives/toolchain/x86_64-linux-gnu b/natives/toolchain/x86_64-linux-gnu index 6f0664194..6a5a5c917 100644 --- a/natives/toolchain/x86_64-linux-gnu +++ b/natives/toolchain/x86_64-linux-gnu @@ -1,6 +1,14 @@ +ifndef PORKLIB_NATIVES_DEBUG +# release mode export CFLAGS := $(CFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export CXXFLAGS := $(CXXFLAGS) -flto=$(NPROC) -fno-fat-lto-objects export LDFLAGS := $(LDFLAGS) -flto=$(NPROC) -fno-fat-lto-objects +else +# debug mode +export CFLAGS := $(CFLAGS) +export CXXFLAGS := $(CXXFLAGS) +export LDFLAGS := $(LDFLAGS) +endif export CC := x86_64-linux-gnu-gcc export CXX := x86_64-linux-gnu-g++ From 0aa2cf60acc75b0feb457085de81c3ad27ec5e46 Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sat, 15 Feb 2020 17:30:35 +0100 Subject: [PATCH 33/36] begin implementing pre-digested zstd dictionaries --- .../lib/compression/zstd/ZstdCCtx.java | 13 +++ .../lib/compression/zstd/ZstdCDict.java | 42 ++++++++++ .../lib/compression/zstd/ZstdDCtx.java | 13 +++ .../lib/compression/zstd/ZstdDDict.java | 35 ++++++++ .../zstd/natives/NativeZStdCDict.java | 81 +++++++++++++++++++ .../zstd/natives/NativeZStdDDict.java | 78 ++++++++++++++++++ .../zstd/natives/NativeZstdCCtx.java | 22 +++++ .../zstd/natives/NativeZstdDCtx.java | 22 +++++ .../src/main/native/common/NativeZstdCCtx.cpp | 16 ++++ .../src/main/native/common/NativeZstdCCtx.h | 8 ++ .../src/main/native/common/NativeZstdDCtx.cpp | 16 ++++ .../src/main/native/common/NativeZstdDCtx.h | 8 ++ 12 files changed, 354 insertions(+) create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCDict.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDDict.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java create mode 100644 compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java index 2a0691f3b..5ed6c8a00 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCCtx.java @@ -29,6 +29,9 @@ * @author DaPorkchop_ */ public interface ZstdCCtx extends CCtx { + @Override + ZstdProvider provider(); + /** * Compresses the given source data into the given destination buffer at the configured Zstd level. * @@ -68,6 +71,16 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dic */ boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict, int compressionLevel) throws InvalidBufferTypeException; + /** + * Compresses the given source data into a single Zstd frame into the given destination buffer using the given dictionary. + *

+ * As the dictionary has already been digested, this is far faster than the other dictionary compression methods. + * + * @param dictionary the dictionary to use + * @see #compress(ByteBuf, ByteBuf) + */ + boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdCDict dictionary) throws InvalidBufferTypeException; + @Override default boolean hasDict() { return true; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCDict.java new file mode 100644 index 000000000..87a20609f --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdCDict.java @@ -0,0 +1,42 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import io.netty.util.ReferenceCounted; +import net.daporkchop.lib.common.misc.refcount.RefCounted; +import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.unsafe.capability.Releasable; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * A digested dictionary used by {@link Zstd} compression. + * + * @author DaPorkchop_ + */ +public interface ZstdCDict extends RefCounted { + /** + * @return the {@link CompressionProvider} that created this context + */ + ZstdProvider provider(); + + /** + * @return the compression level that the dictionary will use + */ + int level(); + + @Override + ZstdCDict retain() throws AlreadyReleasedException; +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java index 299219f90..9ed90baba 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDCtx.java @@ -28,6 +28,19 @@ * @author DaPorkchop_ */ public interface ZstdDCtx extends DCtx { + @Override + ZstdProvider provider(); + + /** + * Decompresses the given compressed data into the given destination buffer using the given dictionary. + *

+ * As the dictionary has already been digested, this is far faster than {@link #decompress(ByteBuf, ByteBuf, ByteBuf)}. + * + * @param dictionary the dictionary to use + * @see #decompress(ByteBuf, ByteBuf) + */ + boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdDDict dictionary) throws InvalidBufferTypeException; + @Override default boolean hasDict() { return true; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDDict.java new file mode 100644 index 000000000..299ab4e5f --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdDDict.java @@ -0,0 +1,35 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd; + +import net.daporkchop.lib.common.misc.refcount.RefCounted; +import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * A digested dictionary used by {@link Zstd} decompression. + * + * @author DaPorkchop_ + */ +public interface ZstdDDict extends RefCounted { + /** + * @return the {@link CompressionProvider} that created this context + */ + ZstdProvider provider(); + + @Override + ZstdDDict retain() throws AlreadyReleasedException; +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java new file mode 100644 index 000000000..c77c19028 --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java @@ -0,0 +1,81 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import net.daporkchop.lib.common.misc.refcount.AbstractRefCounted; +import net.daporkchop.lib.compression.zstd.ZstdCDict; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * @author DaPorkchop_ + */ +@Getter +@Accessors(fluent = true) +final class NativeZStdCDict extends AbstractRefCounted implements ZstdCDict { + private static native long createCDict(long dictAddr, int dictSize, int compressionLevel, boolean copy); + + private static native void releaseCDict(long dict); + + @Getter(AccessLevel.PACKAGE) + private final long dict; + + @Getter(AccessLevel.NONE) + private final PCleaner cleaner; + + private final NativeZstd provider; + private final int level; + + NativeZStdCDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, int level, boolean copy) { + this.provider = provider; + this.level = level; + + this.dict = createCDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes(), level, copy); + + this.cleaner = PCleaner.cleaner(this, new Releaser(this.dict, copy ? dict : null)); + } + + @Override + public ZstdCDict retain() throws AlreadyReleasedException { + super.retain(); + return this; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long dict; + private final ByteBuf data; + + @Override + public void run() { + releaseCDict(this.dict); + if (this.data != null) { + this.data.release(); + } + } + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java new file mode 100644 index 000000000..2b8d022fc --- /dev/null +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java @@ -0,0 +1,78 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression.zstd.natives; + +import io.netty.buffer.ByteBuf; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.experimental.Accessors; +import net.daporkchop.lib.common.misc.refcount.AbstractRefCounted; +import net.daporkchop.lib.compression.zstd.ZstdDDict; +import net.daporkchop.lib.unsafe.PCleaner; +import net.daporkchop.lib.unsafe.util.exception.AlreadyReleasedException; + +/** + * @author DaPorkchop_ + */ +@Accessors(fluent = true) +final class NativeZStdDDict extends AbstractRefCounted implements ZstdDDict { + private static native long createDDict(long dictAddr, int dictSize, boolean copy); + + private static native void releaseDDict(long dict); + + @Getter(AccessLevel.PACKAGE) + private final long dict; + + private final PCleaner cleaner; + + @Getter + private final NativeZstd provider; + + NativeZStdDDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, boolean copy) { + this.provider = provider; + + this.dict = createDDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes(), copy); + + this.cleaner = PCleaner.cleaner(this, new Releaser(this.dict, copy ? dict : null)); + } + + @Override + public ZstdDDict retain() throws AlreadyReleasedException { + super.retain(); + return this; + } + + @Override + protected void doRelease() { + this.cleaner.clean(); + } + + @RequiredArgsConstructor + private static final class Releaser implements Runnable { + private final long dict; + private final ByteBuf data; + + @Override + public void run() { + releaseDDict(this.dict); + if (this.data != null) { + this.data.release(); + } + } + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java index 76137dc27..59065a271 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java @@ -21,6 +21,7 @@ import lombok.RequiredArgsConstructor; import lombok.experimental.Accessors; import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdCDict; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -80,6 +81,27 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict private native int doCompressRawDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize, int compressionLevel); + @Override + public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdCDict dictionary) throws InvalidBufferTypeException { + if (!(dictionary instanceof NativeZStdCDict)) { + throw new IllegalArgumentException(dictionary.getClass().getCanonicalName()); + } + + dictionary.retain(); + try { + int val = this.doCompressCDict(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + ((NativeZStdCDict) dictionary).dict()); + + return NativeZstdHelper.finalizeOneShot(src, dst, val); + } finally { + dictionary.release(); + } + } + + private native int doCompressCDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr); + @Override public boolean directAccepted() { return true; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java index 34772fb86..3f8197731 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java @@ -23,6 +23,7 @@ import lombok.experimental.Accessors; import net.daporkchop.lib.compression.zstd.ZstdCCtx; import net.daporkchop.lib.compression.zstd.ZstdDCtx; +import net.daporkchop.lib.compression.zstd.ZstdDDict; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; import net.daporkchop.lib.unsafe.PCleaner; import net.daporkchop.lib.unsafe.util.AbstractReleasable; @@ -73,6 +74,27 @@ public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf di private native int doDecompressRawDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr, int dictSize); + @Override + public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdDDict dictionary) throws InvalidBufferTypeException { + if (!(dictionary instanceof NativeZStdDDict)) { + throw new IllegalArgumentException(dictionary.getClass().getCanonicalName()); + } + + dictionary.retain(); + try { + int val = this.doDecompressCDict(this.ctx, + this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), + this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), + ((NativeZStdDDict) dictionary).dict()); + + return NativeZstdHelper.finalizeOneShot(src, dst, val); + } finally { + dictionary.release(); + } + } + + private native int doDecompressCDict(long ctx, long srcAddr, int srcSize, long dstAddr, int dstSize, long dictAddr); + @Override public boolean directAccepted() { return true; diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp index aa916f2c8..e7b0d94c4 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp @@ -50,3 +50,19 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp return (jint) ret; } + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressCDict + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr) { + auto ret = ZSTD_compress_usingCDict((ZSTD_CCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (ZSTD_CDict*) dictAddr); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.h b/compression/zstd/src/main/native/common/NativeZstdCCtx.h index 9dd701e84..3fb026341 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.h @@ -42,6 +42,14 @@ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressRawDict (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint, jint); +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx + * Method: doCompressCDict + * Signature: (JJIJIJII)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx_doCompressCDict + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong); + #ifdef __cplusplus } #endif diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp index 32f0af1e9..19a7424fb 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp @@ -50,3 +50,19 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp return (jint) ret; } + +__attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressCDict + (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr) { + auto ret = ZSTD_decompress_usingDDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr); + + if (ZSTD_isError(ret)) { + if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { + return -1; + } else { + throwException(env, ZSTD_getErrorName(ret), (int) ret); + return 0; + } + } + + return (jint) ret; +} diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.h b/compression/zstd/src/main/native/common/NativeZstdDCtx.h index b1e805dc9..2654d15f7 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.h @@ -42,6 +42,14 @@ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressRawDict (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong, jint); +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx + * Method: doDecompressCDict + * Signature: (JJIJIJ)I + */ +JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressCDict + (JNIEnv *, jobject, jlong, jlong, jint, jlong, jint, jlong); + #ifdef __cplusplus } #endif From a37b19c0d95fc4876b9e5cf0c545b19a9398662a Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sat, 15 Feb 2020 18:30:04 +0100 Subject: [PATCH 34/36] actually implement native zstd dictionaries --- .../src/main/native/common/NativeZlib.cpp | 2 +- .../zlib/src/main/native/common/NativeZlib.h | 6 +- compression/zstd/build.gradle | 2 + .../zstd/src/example/java/DictionaryTest.java | 101 ++++++++++++++++++ .../lib/compression/zstd/ZstdProvider.java | 32 +++++- .../compression/zstd/natives/NativeZstd.java | 12 +++ .../zstd/natives/NativeZstdCCtx.java | 4 +- ...iveZStdCDict.java => NativeZstdCDict.java} | 4 +- .../zstd/natives/NativeZstdDCtx.java | 4 +- ...iveZStdDDict.java => NativeZstdDDict.java} | 4 +- .../src/main/native/common/NativeZstd.cpp | 6 +- .../src/main/native/common/NativeZstdCCtx.cpp | 8 +- .../src/main/native/common/NativeZstdCCtx.h | 2 +- .../main/native/common/NativeZstdCDict.cpp | 22 ++++ .../src/main/native/common/NativeZstdCDict.h | 33 ++++++ .../src/main/native/common/NativeZstdDCtx.cpp | 10 +- .../src/main/native/common/NativeZstdDCtx.h | 2 +- .../main/native/common/NativeZstdDDict.cpp | 22 ++++ .../src/main/native/common/NativeZstdDDict.h | 33 ++++++ 19 files changed, 281 insertions(+), 28 deletions(-) create mode 100644 compression/zstd/src/example/java/DictionaryTest.java rename compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/{NativeZStdCDict.java => NativeZstdCDict.java} (96%) rename compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/{NativeZStdDDict.java => NativeZstdDDict.java} (95%) create mode 100644 compression/zstd/src/main/native/common/NativeZstdCDict.cpp create mode 100644 compression/zstd/src/main/native/common/NativeZstdCDict.h create mode 100644 compression/zstd/src/main/native/common/NativeZstdDDict.cpp create mode 100644 compression/zstd/src/main/native/common/NativeZstdDDict.h diff --git a/compression/zlib/src/main/native/common/NativeZlib.cpp b/compression/zlib/src/main/native/common/NativeZlib.cpp index 822f5c4bf..c32032e84 100644 --- a/compression/zlib/src/main/native/common/NativeZlib.cpp +++ b/compression/zlib/src/main/native/common/NativeZlib.cpp @@ -3,7 +3,7 @@ #include -__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_compressBoundLong +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlib_compressBoundLong (JNIEnv* env, jobject obj, jlong srcSize, jint mode) { if (srcSize < 0) { return throwException(env, "srcSize may not be negative!", srcSize); diff --git a/compression/zlib/src/main/native/common/NativeZlib.h b/compression/zlib/src/main/native/common/NativeZlib.h index f52b07cfe..1bec65b3e 100644 --- a/compression/zlib/src/main/native/common/NativeZlib.h +++ b/compression/zlib/src/main/native/common/NativeZlib.h @@ -11,15 +11,15 @@ extern "C" { #endif /* - * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater + * Class: net_daporkchop_lib_compression_zlib_natives_NativeZlib * Method: compressBoundLong * Signature: (JI)J */ -JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater_compressBoundLong +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zlib_natives_NativeZlib_compressBoundLong (JNIEnv *, jobject, jlong, jint); #ifdef __cplusplus } #endif -#endif //_Included_net_daporkchop_lib_compression_zlib_natives_NativeZlibDeflater +#endif //_Included_net_daporkchop_lib_compression_zlib_natives_NativeZlib diff --git a/compression/zstd/build.gradle b/compression/zstd/build.gradle index 5f38939a3..6d64c9271 100644 --- a/compression/zstd/build.gradle +++ b/compression/zstd/build.gradle @@ -16,4 +16,6 @@ dependencies { compile project(":compression") compile project(":natives") + + exampleCompile project(":binary") } diff --git a/compression/zstd/src/example/java/DictionaryTest.java b/compression/zstd/src/example/java/DictionaryTest.java new file mode 100644 index 000000000..bbe9c4900 --- /dev/null +++ b/compression/zstd/src/example/java/DictionaryTest.java @@ -0,0 +1,101 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +import io.netty.buffer.ByteBuf; +import io.netty.buffer.PooledByteBufAllocator; +import net.daporkchop.lib.binary.netty.PUnpooled; +import net.daporkchop.lib.common.misc.file.PFiles; +import net.daporkchop.lib.compression.zstd.Zstd; +import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdCDict; + +import java.io.File; +import java.io.IOException; +import java.nio.channels.FileChannel; +import java.nio.file.StandardOpenOption; + +/** + * @author DaPorkchop_ + */ +public class DictionaryTest { + public static final File RAW_DIR = new File("/home/daporkchop/Desktop/raw"); + public static final File OUT_DIR_NORMAL = new File("/home/daporkchop/Desktop/compressed-normal"); + public static final File OUT_DIR_DICT = new File("/home/daporkchop/Desktop/compressed-dict"); + public static final File DICT_FILE = new File("/home/daporkchop/Desktop/dict"); + + public static void main(String... args) throws IOException { + PFiles.rm(OUT_DIR_NORMAL); + PFiles.rm(OUT_DIR_DICT); + + ByteBuf rawDict; + try (FileChannel channel = FileChannel.open(DICT_FILE.toPath(), StandardOpenOption.READ)) { + rawDict = PUnpooled.wrap(channel.map(FileChannel.MapMode.READ_ONLY, 0L, channel.size()), true); + } + + long normalSize = 0L; + long dictSize = 0L; + + try (ZstdCCtx cCtx = Zstd.PROVIDER.compressionContext(); + ZstdCDict cDict = Zstd.PROVIDER.compressionDictionary(rawDict, Zstd.LEVEL_MAX)) { + for (File srcFile : RAW_DIR.listFiles()) { + ByteBuf src; + try (FileChannel channel = FileChannel.open(srcFile.toPath(), StandardOpenOption.READ)) { + src = PUnpooled.wrap(channel.map(FileChannel.MapMode.READ_ONLY, 0L, channel.size()), true); + } + ByteBuf compressed = PooledByteBufAllocator.DEFAULT.directBuffer(Zstd.PROVIDER.compressBound(src.readableBytes()), Zstd.PROVIDER.compressBound(src.readableBytes())); + try { + if (!cCtx.compress(src, compressed, Zstd.LEVEL_MAX)) { + throw new IllegalStateException(); + } + normalSize += compressed.readableBytes(); + if (true) { + continue; + } + try (FileChannel channel = FileChannel.open(PFiles.ensureFileExists(new File(OUT_DIR_NORMAL, srcFile.getName())).toPath(), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { + compressed.readBytes(channel, compressed.readableBytes()); + } + } finally { + src.release(); + compressed.release(); + } + } + + for (File srcFile : RAW_DIR.listFiles()) { + ByteBuf src; + try (FileChannel channel = FileChannel.open(srcFile.toPath(), StandardOpenOption.READ)) { + src = PUnpooled.wrap(channel.map(FileChannel.MapMode.READ_ONLY, 0L, channel.size()), true); + } + ByteBuf compressed = PooledByteBufAllocator.DEFAULT.directBuffer(Zstd.PROVIDER.compressBound(src.readableBytes()), Zstd.PROVIDER.compressBound(src.readableBytes())); + try { + if (!cCtx.compress(src, compressed, cDict)) { + throw new IllegalStateException(); + } + dictSize += compressed.readableBytes(); + if (true) { + continue; + } + try (FileChannel channel = FileChannel.open(PFiles.ensureFileExists(new File(OUT_DIR_DICT, srcFile.getName())).toPath(), StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING)) { + compressed.readBytes(channel, compressed.readableBytes()); + } + } finally { + src.release(); + compressed.release(); + } + } + } + + System.out.printf("Normal: %.2f\nDictionary: %.2f\n", normalSize / (1024.0d * 1024.0d), dictSize / (1024.0d * 1024.0d)); + } +} diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index 5441be142..c4698b6dd 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -69,10 +69,10 @@ default boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws Inva boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst) throws InvalidBufferTypeException; /** - * @see #frameContentSizeLong(ByteBuf) * @throws ValueCannotFitException if the returned value is too large to fit in an {@code int} + * @see #frameContentSizeLong(ByteBuf) */ - default int frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException, ValueCannotFitException { + default int frameContentSize(@NonNull ByteBuf src) throws InvalidBufferTypeException, ContentSizeUnknownException, ValueCannotFitException { return PValidation.toInt(this.frameContentSizeLong(src)); } @@ -95,4 +95,32 @@ default ZstdCCtx compressionContext() { @Override ZstdDCtx decompressionContext(); + + /** + * Digests a Zstd dictionary for compression at the default level. + * + * @param dict the {@link ByteBuf} containing the dictionary + * @return the digested dictionary + */ + default ZstdCDict compressionDictionary(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + return this.compressionDictionary(dict, Zstd.LEVEL_DEFAULT); + } + + /** + * Digests a Zstd dictionary for compression at the given level. + * + * @param dict the {@link ByteBuf} containing the dictionary + * @param level the compression level to use + * @return the digested dictionary + */ + ZstdCDict compressionDictionary(@NonNull ByteBuf dict, int level) throws InvalidBufferTypeException; + + /** + * Digests a Zstd dictionary for decompression. + * + * @param dict the {@link ByteBuf} containing the dictionary + * @return the digested dictionary + */ + ZstdDDict decompressionDictionary(@NonNull ByteBuf dict) throws InvalidBufferTypeException; + } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 674e63617..0be5bdb09 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -23,7 +23,9 @@ import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.compression.zstd.Zstd; import net.daporkchop.lib.compression.zstd.ZstdCCtx; +import net.daporkchop.lib.compression.zstd.ZstdCDict; import net.daporkchop.lib.compression.zstd.ZstdDCtx; +import net.daporkchop.lib.compression.zstd.ZstdDDict; import net.daporkchop.lib.compression.zstd.ZstdProvider; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.NativeFeature; @@ -112,4 +114,14 @@ public ZstdCCtx compressionContext(int level) throws InvalidCompressionLevelExce public ZstdDCtx decompressionContext() { return new NativeZstdDCtx(this); } + + @Override + public ZstdCDict compressionDictionary(@NonNull ByteBuf dict, int level) throws InvalidBufferTypeException { + return new NativeZstdCDict(this, dict, level, true); + } + + @Override + public ZstdDDict decompressionDictionary(@NonNull ByteBuf dict) throws InvalidBufferTypeException { + return new NativeZstdDDict(this, dict, true); + } } diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java index 59065a271..63122ae40 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCCtx.java @@ -83,7 +83,7 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf dict @Override public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdCDict dictionary) throws InvalidBufferTypeException { - if (!(dictionary instanceof NativeZStdCDict)) { + if (!(dictionary instanceof NativeZstdCDict)) { throw new IllegalArgumentException(dictionary.getClass().getCanonicalName()); } @@ -92,7 +92,7 @@ public boolean compress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull Zst int val = this.doCompressCDict(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), - ((NativeZStdCDict) dictionary).dict()); + ((NativeZstdCDict) dictionary).dict()); return NativeZstdHelper.finalizeOneShot(src, dst, val); } finally { diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCDict.java similarity index 96% rename from compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java rename to compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCDict.java index c77c19028..e99a72822 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdCDict.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdCDict.java @@ -31,7 +31,7 @@ */ @Getter @Accessors(fluent = true) -final class NativeZStdCDict extends AbstractRefCounted implements ZstdCDict { +final class NativeZstdCDict extends AbstractRefCounted implements ZstdCDict { private static native long createCDict(long dictAddr, int dictSize, int compressionLevel, boolean copy); private static native void releaseCDict(long dict); @@ -45,7 +45,7 @@ final class NativeZStdCDict extends AbstractRefCounted implements ZstdCDict { private final NativeZstd provider; private final int level; - NativeZStdCDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, int level, boolean copy) { + NativeZstdCDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, int level, boolean copy) { this.provider = provider; this.level = level; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java index 3f8197731..8fc343b07 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDCtx.java @@ -76,7 +76,7 @@ public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, ByteBuf di @Override public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull ZstdDDict dictionary) throws InvalidBufferTypeException { - if (!(dictionary instanceof NativeZStdDDict)) { + if (!(dictionary instanceof NativeZstdDDict)) { throw new IllegalArgumentException(dictionary.getClass().getCanonicalName()); } @@ -85,7 +85,7 @@ public boolean decompress(@NonNull ByteBuf src, @NonNull ByteBuf dst, @NonNull Z int val = this.doDecompressCDict(this.ctx, this.assertAcceptable(src).memoryAddress() + src.readerIndex(), src.readableBytes(), this.assertAcceptable(dst).memoryAddress() + dst.writerIndex(), dst.writableBytes(), - ((NativeZStdDDict) dictionary).dict()); + ((NativeZstdDDict) dictionary).dict()); return NativeZstdHelper.finalizeOneShot(src, dst, val); } finally { diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDDict.java similarity index 95% rename from compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java rename to compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDDict.java index 2b8d022fc..7f1195997 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZStdDDict.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstdDDict.java @@ -30,7 +30,7 @@ * @author DaPorkchop_ */ @Accessors(fluent = true) -final class NativeZStdDDict extends AbstractRefCounted implements ZstdDDict { +final class NativeZstdDDict extends AbstractRefCounted implements ZstdDDict { private static native long createDDict(long dictAddr, int dictSize, boolean copy); private static native void releaseDDict(long dict); @@ -43,7 +43,7 @@ final class NativeZStdDDict extends AbstractRefCounted implements ZstdDDict { @Getter private final NativeZstd provider; - NativeZStdDDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, boolean copy) { + NativeZstdDDict(@NonNull NativeZstd provider, @NonNull ByteBuf dict, boolean copy) { this.provider = provider; this.dict = createDDict(dict.memoryAddress() + dict.readerIndex(), dict.readableBytes(), copy); diff --git a/compression/zstd/src/main/native/common/NativeZstd.cpp b/compression/zstd/src/main/native/common/NativeZstd.cpp index 8e1ce6e47..f0781dfe4 100644 --- a/compression/zstd/src/main/native/common/NativeZstd.cpp +++ b/compression/zstd/src/main/native/common/NativeZstd.cpp @@ -12,7 +12,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -28,7 +28,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -41,7 +41,7 @@ __attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_com auto contentSize = ZSTD_getFrameContentSize((void*) srcAddr, srcSize); if (contentSize == ZSTD_CONTENTSIZE_ERROR) { - throwException(env, "ZSTD_CONTENTSIZE_ERROR", (int) ZSTD_CONTENTSIZE_ERROR); + throwException(env, "ZSTD_CONTENTSIZE_ERROR", (jlong) ZSTD_CONTENTSIZE_ERROR); return 0; } diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp index e7b0d94c4..e4803516c 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.cpp @@ -14,7 +14,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp auto ret = ZSTD_freeCCtx((ZSTD_CCtx*) ctx); if (ZSTD_isError(ret)) { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return; } } @@ -27,7 +27,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -43,7 +43,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -59,7 +59,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } diff --git a/compression/zstd/src/main/native/common/NativeZstdCCtx.h b/compression/zstd/src/main/native/common/NativeZstdCCtx.h index 3fb026341..c38c7c8a4 100644 --- a/compression/zstd/src/main/native/common/NativeZstdCCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdCCtx.h @@ -54,4 +54,4 @@ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs } #endif -#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCCtx diff --git a/compression/zstd/src/main/native/common/NativeZstdCDict.cpp b/compression/zstd/src/main/native/common/NativeZstdCDict.cpp new file mode 100644 index 000000000..1ded3b423 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdCDict.cpp @@ -0,0 +1,22 @@ +#include +#include "NativeZstdCDict.h" + +#include +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict_createCDict + (JNIEnv* env, jclass cla, jlong dictAddr, jint dictSize, jint compressionLevel, jboolean copy) { + return copy + ? (jlong) ZSTD_createCDict((void*) dictAddr, dictSize, compressionLevel) + : 0;//: (jlong) ZSTD_createCDict_byReference((void*) dictAddr, dictSize, compressionLevel); +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict_releaseCDict + (JNIEnv* env, jclass cla, jlong ctx) { + auto ret = ZSTD_freeCDict((ZSTD_CDict*) ctx); + + if (ZSTD_isError(ret)) { + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); + return; + } +} diff --git a/compression/zstd/src/main/native/common/NativeZstdCDict.h b/compression/zstd/src/main/native/common/NativeZstdCDict.h new file mode 100644 index 000000000..460fb49c7 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdCDict.h @@ -0,0 +1,33 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict +#define _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict + * Method: createCDict + * Signature: (JIIZ)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict_createCDict + (JNIEnv *, jclass, jlong, jint, jint, jboolean); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict + * Method: releaseCDict + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict_releaseCDict + (JNIEnv *, jclass, jlong); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdCDict diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp index 19a7424fb..c7d95bf97 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.cpp @@ -14,7 +14,7 @@ __attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_comp auto ret = ZSTD_freeDCtx((ZSTD_DCtx*) ctx); if (ZSTD_isError(ret)) { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return; } } @@ -27,7 +27,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -43,7 +43,7 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } @@ -53,13 +53,13 @@ __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_comp __attribute__((visibility("default"))) jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx_doDecompressCDict (JNIEnv* env, jobject obj, jlong ctx, jlong srcAddr, jint srcSize, jlong dstAddr, jint dstSize, jlong dictAddr) { - auto ret = ZSTD_decompress_usingDDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (void*) dictAddr); + auto ret = ZSTD_decompress_usingDDict((ZSTD_DCtx*) ctx, (void*) dstAddr, dstSize, (void*) srcAddr, srcSize, (ZSTD_DDict*) dictAddr); if (ZSTD_isError(ret)) { if (ZSTD_getErrorCode(ret) == ZSTD_error_dstSize_tooSmall) { return -1; } else { - throwException(env, ZSTD_getErrorName(ret), (int) ret); + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); return 0; } } diff --git a/compression/zstd/src/main/native/common/NativeZstdDCtx.h b/compression/zstd/src/main/native/common/NativeZstdDCtx.h index 2654d15f7..34ed26cfb 100644 --- a/compression/zstd/src/main/native/common/NativeZstdDCtx.h +++ b/compression/zstd/src/main/native/common/NativeZstdDCtx.h @@ -54,4 +54,4 @@ JNIEXPORT jint JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZs } #endif -#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstd +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDCtx diff --git a/compression/zstd/src/main/native/common/NativeZstdDDict.cpp b/compression/zstd/src/main/native/common/NativeZstdDDict.cpp new file mode 100644 index 000000000..7e17eaf1e --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdDDict.cpp @@ -0,0 +1,22 @@ +#include +#include "NativeZstdDDict.h" + +#include +#include + +__attribute__((visibility("default"))) jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict_createDDict + (JNIEnv* env, jclass cla, jlong dictAddr, jint dictSize, jboolean copy) { + return copy + ? (jlong) ZSTD_createDDict((void*) dictAddr, dictSize) + : 0;//: (jlong) ZSTD_createDDict_byReference((void*) dictAddr, dictSize); +} + +__attribute__((visibility("default"))) void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict_releaseDDict + (JNIEnv* env, jclass cla, jlong ctx) { + auto ret = ZSTD_freeDDict((ZSTD_DDict*) ctx); + + if (ZSTD_isError(ret)) { + throwException(env, ZSTD_getErrorName(ret), (jlong) ret); + return; + } +} diff --git a/compression/zstd/src/main/native/common/NativeZstdDDict.h b/compression/zstd/src/main/native/common/NativeZstdDDict.h new file mode 100644 index 000000000..620de5052 --- /dev/null +++ b/compression/zstd/src/main/native/common/NativeZstdDDict.h @@ -0,0 +1,33 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +//actually it's not, it was initially though +//easier to make this by hand lol +#include + +#ifndef _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict +#define _Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict + * Method: createDDict + * Signature: (JIZ)J + */ +JNIEXPORT jlong JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict_createDDict + (JNIEnv *, jclass, jlong, jint, jboolean); + +/* + * Class: net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict + * Method: releaseDDict + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict_releaseDDict + (JNIEnv *, jclass, jlong); + +#ifdef __cplusplus +} +#endif + +#endif //_Included_net_daporkchop_lib_compression_zstd_natives_NativeZstdDDict From bb44265d0e8ac3955689d5b80364668b2489b4dd Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sat, 15 Feb 2020 18:35:18 +0100 Subject: [PATCH 35/36] split CompressionProvider into separate interfaces for streaming and one-shot compression --- .../lib/compression/CompressionProvider.java | 46 ----------------- .../OneShotCompressionProvider.java | 51 +++++++++++++++++++ .../StreamingCompressionProvider.java | 51 +++++++++++++++++++ .../lib/compression/zlib/ZlibProvider.java | 4 +- .../lib/compression/zstd/ZstdProvider.java | 6 +-- 5 files changed, 107 insertions(+), 51 deletions(-) create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/OneShotCompressionProvider.java create mode 100644 compression/src/main/java/net/daporkchop/lib/compression/StreamingCompressionProvider.java diff --git a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java index c938a77c0..4c00db3c1 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/CompressionProvider.java @@ -59,50 +59,4 @@ default int compressBound(int srcSize) throws ValueCannotFitException { * @return the worst-case size of the compressed data */ long compressBoundLong(long srcSize); - - /** - * Creates a new {@link PDeflater} with the default compression level. - * - * @see #deflater(int) - */ - default PDeflater deflater() { - return this.deflater(this.levelDefault()); - } - - /** - * Creates a new {@link PDeflater} with the given compression level. - * - * @param level the compression level to use - * @return a new {@link PDeflater} with the given compression level - * @throws InvalidCompressionLevelException if the given compression level is invalid - */ - PDeflater deflater(int level) throws InvalidCompressionLevelException; - - /** - * @return a new {@link PInflater} - */ - PInflater inflater(); - - /** - * Creates a new {@link CCtx} with the default compression level. - * - * @see #compressionContext(int) - */ - default CCtx compressionContext() { - return this.compressionContext(this.levelDefault()); - } - - /** - * Creates a new {@link CCtx} with the given compression level. - * - * @param level the compression level to use - * @return a new {@link CCtx} with the given compression level - * @throws InvalidCompressionLevelException if the given compression level is invalid - */ - CCtx compressionContext(int level) throws InvalidCompressionLevelException; - - /** - * @return a new {@link DCtx} - */ - DCtx decompressionContext(); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/OneShotCompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/OneShotCompressionProvider.java new file mode 100644 index 000000000..a23e05592 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/OneShotCompressionProvider.java @@ -0,0 +1,51 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.BufferTyped; + +/** + * An implementation of a compression algorithm that supports one-shot compression via {@link CCtx} and {@link DCtx}. + * + * @author DaPorkchop_ + */ +public interface OneShotCompressionProvider extends CompressionProvider { + /** + * Creates a new {@link CCtx} with the default compression level. + * + * @see #compressionContext(int) + */ + default CCtx compressionContext() { + return this.compressionContext(this.levelDefault()); + } + + /** + * Creates a new {@link CCtx} with the given compression level. + * + * @param level the compression level to use + * @return a new {@link CCtx} with the given compression level + * @throws InvalidCompressionLevelException if the given compression level is invalid + */ + CCtx compressionContext(int level) throws InvalidCompressionLevelException; + + /** + * @return a new {@link DCtx} + */ + DCtx decompressionContext(); +} diff --git a/compression/src/main/java/net/daporkchop/lib/compression/StreamingCompressionProvider.java b/compression/src/main/java/net/daporkchop/lib/compression/StreamingCompressionProvider.java new file mode 100644 index 000000000..63cbd7902 --- /dev/null +++ b/compression/src/main/java/net/daporkchop/lib/compression/StreamingCompressionProvider.java @@ -0,0 +1,51 @@ +/* + * Adapted from the Wizardry License + * + * Copyright (c) 2018-2020 DaPorkchop_ and contributors + * + * Permission is hereby granted to any persons and/or organizations using this software to copy, modify, merge, publish, and distribute it. Said persons and/or organizations are not allowed to use the software or any derivatives of the work for commercial use or any other means to generate income, nor are they allowed to claim this software as their own. + * + * The persons and/or organizations are also disallowed from sub-licensing and/or trademarking this software without explicit permission from DaPorkchop_. + * + * Any persons and/or organizations using this software must disclose their source code and have it publicly available, include this license, provide sufficient credit to the original authors of the project (IE: DaPorkchop_), as well as provide a link to the original project. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + */ + +package net.daporkchop.lib.compression; + +import net.daporkchop.lib.common.util.PValidation; +import net.daporkchop.lib.common.util.exception.ValueCannotFitException; +import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; +import net.daporkchop.lib.natives.util.BufferTyped; + +/** + * An implementation of a compression algorithm that supports streaming compression via {@link PDeflater} and {@link PInflater}. + * + * @author DaPorkchop_ + */ +public interface StreamingCompressionProvider extends CompressionProvider { + /** + * Creates a new {@link PDeflater} with the default compression level. + * + * @see #deflater(int) + */ + default PDeflater deflater() { + return this.deflater(this.levelDefault()); + } + + /** + * Creates a new {@link PDeflater} with the given compression level. + * + * @param level the compression level to use + * @return a new {@link PDeflater} with the given compression level + * @throws InvalidCompressionLevelException if the given compression level is invalid + */ + PDeflater deflater(int level) throws InvalidCompressionLevelException; + + /** + * @return a new {@link PInflater} + */ + PInflater inflater(); +} diff --git a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java index 63ce72c73..f0735c3b4 100644 --- a/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java +++ b/compression/zlib/src/main/java/net/daporkchop/lib/compression/zlib/ZlibProvider.java @@ -19,6 +19,8 @@ import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.common.util.exception.ValueCannotFitException; import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.OneShotCompressionProvider; +import net.daporkchop.lib.compression.StreamingCompressionProvider; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.impl.Feature; @@ -27,7 +29,7 @@ * * @author DaPorkchop_ */ -public interface ZlibProvider extends CompressionProvider, Feature { +public interface ZlibProvider extends StreamingCompressionProvider, OneShotCompressionProvider, Feature { @Override default int levelFast() { return Zlib.LEVEL_FASTEST; diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java index c4698b6dd..d01275fb1 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/ZstdProvider.java @@ -20,6 +20,7 @@ import net.daporkchop.lib.common.util.PValidation; import net.daporkchop.lib.common.util.exception.ValueCannotFitException; import net.daporkchop.lib.compression.CompressionProvider; +import net.daporkchop.lib.compression.OneShotCompressionProvider; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.compression.zstd.util.exception.ContentSizeUnknownException; import net.daporkchop.lib.natives.impl.Feature; @@ -30,10 +31,7 @@ * * @author DaPorkchop_ */ -public interface ZstdProvider extends CompressionProvider, Feature { - @Override - boolean directAccepted(); - +public interface ZstdProvider extends OneShotCompressionProvider, Feature { /** * Compresses the given source data into a single Zstd frame into the given destination buffer at the default compression level. * From 830f9364a19e9eb8f2a3d3c7353c5bf4d4cdf00b Mon Sep 17 00:00:00 2001 From: DaMatrix Date: Sat, 15 Feb 2020 18:52:24 +0100 Subject: [PATCH 36/36] don't build zstd legacy stuff and make all the tests run correctly --- .../lib/compression/util/StreamingWrapperCCtx.java | 5 +++-- .../lib/compression/util/StreamingWrapperDCtx.java | 5 +++-- compression/zstd/Makefile | 2 +- .../lib/compression/zstd/natives/NativeZstd.java | 10 ---------- .../java/net/daporkchop/lib/crypto/EncryptionTest.java | 3 ++- http/src/test/java/http/HttpTest.java | 4 +++- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java index b7e422d0c..171d9408f 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperCCtx.java @@ -24,6 +24,7 @@ import net.daporkchop.lib.compression.CCtx; import net.daporkchop.lib.compression.CompressionProvider; import net.daporkchop.lib.compression.PDeflater; +import net.daporkchop.lib.compression.StreamingCompressionProvider; import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; @@ -39,13 +40,13 @@ public class StreamingWrapperCCtx extends AbstractReleasable implements CCtx { @Getter @NonNull - protected final CompressionProvider provider; + protected final StreamingCompressionProvider provider; @NonNull protected final PDeflater deflater; @Getter protected final int level; - public StreamingWrapperCCtx(@NonNull CompressionProvider provider, int level) throws InvalidCompressionLevelException { + public StreamingWrapperCCtx(@NonNull StreamingCompressionProvider provider, int level) throws InvalidCompressionLevelException { this(provider, provider.deflater(level), level); } diff --git a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java index f0a0ed206..cf49d4e64 100644 --- a/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java +++ b/compression/src/main/java/net/daporkchop/lib/compression/util/StreamingWrapperDCtx.java @@ -25,6 +25,7 @@ import net.daporkchop.lib.compression.CompressionProvider; import net.daporkchop.lib.compression.DCtx; import net.daporkchop.lib.compression.PInflater; +import net.daporkchop.lib.compression.StreamingCompressionProvider; import net.daporkchop.lib.compression.util.exception.DictionaryNotAllowedException; import net.daporkchop.lib.compression.util.exception.InvalidCompressionLevelException; import net.daporkchop.lib.natives.util.exception.InvalidBufferTypeException; @@ -39,11 +40,11 @@ @Accessors(fluent = true) public class StreamingWrapperDCtx extends AbstractReleasable implements DCtx { @Getter - protected final CompressionProvider provider; + protected final StreamingCompressionProvider provider; @NonNull protected final PInflater inflater; - public StreamingWrapperDCtx(@NonNull CompressionProvider provider) { + public StreamingWrapperDCtx(@NonNull StreamingCompressionProvider provider) { this(provider, provider.inflater()); } diff --git a/compression/zstd/Makefile b/compression/zstd/Makefile index fda022603..dae8f2b37 100644 --- a/compression/zstd/Makefile +++ b/compression/zstd/Makefile @@ -49,6 +49,6 @@ $(CURDIR)/lib-zstd/lib/libzstd.a: $(TOPDIR)/zstd-1.4.4.tar.gz @[ ! -d lib-zstd ] || rm -rf lib-zstd/ @tar zxf $(TOPDIR)/zstd-1.4.4.tar.gz @mv zstd-1.4.4/ lib-zstd/ - @$(MAKE) -C $(CURDIR)/lib-zstd/ -f $(CURDIR)/lib-zstd/Makefile lib-release + @$(MAKE) -C $(CURDIR)/lib-zstd/ -f $(CURDIR)/lib-zstd/Makefile ZSTD_LEGACY_SUPPORT=0 ZSTD_LEGACY_MULTITHREADED_API=0 lib-release endif diff --git a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java index 0be5bdb09..293332c28 100644 --- a/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java +++ b/compression/zstd/src/main/java/net/daporkchop/lib/compression/zstd/natives/NativeZstd.java @@ -95,16 +95,6 @@ public long compressBoundLong(long srcSize) { private native long doCompressBoundLong(long srcSize); - @Override - public PDeflater deflater(int level) throws InvalidCompressionLevelException { - throw new UnsupportedOperationException(); - } - - @Override - public PInflater inflater() { - throw new UnsupportedOperationException(); - } - @Override public ZstdCCtx compressionContext(int level) throws InvalidCompressionLevelException { return new NativeZstdCCtx(this, level); diff --git a/crypto/src/test/java/net/daporkchop/lib/crypto/EncryptionTest.java b/crypto/src/test/java/net/daporkchop/lib/crypto/EncryptionTest.java index efe9aeb73..36997e4fe 100644 --- a/crypto/src/test/java/net/daporkchop/lib/crypto/EncryptionTest.java +++ b/crypto/src/test/java/net/daporkchop/lib/crypto/EncryptionTest.java @@ -16,6 +16,7 @@ package net.daporkchop.lib.crypto; import lombok.NonNull; +import net.daporkchop.lib.binary.oio.StreamUtil; import net.daporkchop.lib.common.function.io.IOConsumer; import net.daporkchop.lib.common.misc.TestRandomData; import net.daporkchop.lib.crypto.cipher.Cipher; @@ -304,7 +305,7 @@ private void testSeekable(@NonNull Function keyGenerator, @No byte[] encrypted = baos.toByteArray(); byte[] decrypted; try (InputStream in = cipher2.decrypt(new ByteArrayInputStream(encrypted), offset, b.length)) { - decrypted = IOUtils.readFully(in, -1, false); + decrypted = StreamUtil.toByteArray(in); } if (isInvalid(b, decrypted)) { throw new IllegalStateException("Decrypted data isn't the same!"); diff --git a/http/src/test/java/http/HttpTest.java b/http/src/test/java/http/HttpTest.java index 0a1a63acc..a23804da6 100644 --- a/http/src/test/java/http/HttpTest.java +++ b/http/src/test/java/http/HttpTest.java @@ -55,7 +55,9 @@ public void test2() throws IOException { @Test public void testGET() throws IOException { String text = Base58.encodeBase58(TestRandomData.getRandomBytes(64, 128)); - String response = new JsonParser().parse(Http.getString(String.format("http://httpbin.org/get?data=%s", text))).getAsJsonObject().get("args").getAsJsonObject().get("keys").getAsString(); + String response = new JsonParser().parse(Http.getString(String.format("http://httpbin.org/get?data=%s", text))).getAsJsonObject() + .get("args").getAsJsonObject() + .get("data").getAsString(); if (!text.equals(response)) { throw new IllegalStateException(String.format("Data not identical! Sent=%s Received=%s", text, response)); }