From a2f70306dff7fce1be79059713cfbd21c1720ed6 Mon Sep 17 00:00:00 2001
From: fibersel <0583463@gmail.com>
Date: Thu, 6 May 2021 15:55:03 +0300
Subject: [PATCH] add contribs
---
contrib/density/.gitignore | 2 +
contrib/density/.gitmodules | 6 +
contrib/density/.travis.yml | 272 +++
contrib/density/CHANGELOG.md | 168 ++
contrib/density/LICENSE.md | 28 +
contrib/density/README.md | 261 +++
contrib/density/appveyor.yml | 37 +
contrib/density/benchmark/src/benchmark.c | 345 ++++
contrib/density/benchmark/src/benchmark.h | 129 ++
contrib/density/msvc/Density.sln | 21 +
contrib/density/msvc/benchmark.vcxproj | 78 +
.../density/msvc/benchmark.vcxproj.filters | 63 +
contrib/density/msvc/density.vcxproj | 93 +
contrib/density/msvc/density.vcxproj.filters | 135 ++
contrib/density/src/algorithms/algorithms.c | 43 +
contrib/density/src/algorithms/algorithms.h | 78 +
.../src/algorithms/chameleon/chameleon.h | 70 +
.../chameleon/core/chameleon_decode.c | 254 +++
.../chameleon/core/chameleon_decode.h | 53 +
.../chameleon/core/chameleon_encode.c | 179 ++
.../chameleon/core/chameleon_encode.h | 53 +
.../dictionary/chameleon_dictionary.h | 63 +
.../density/src/algorithms/cheetah/cheetah.h | 73 +
.../algorithms/cheetah/core/cheetah_decode.c | 266 +++
.../algorithms/cheetah/core/cheetah_decode.h | 54 +
.../algorithms/cheetah/core/cheetah_encode.c | 202 +++
.../algorithms/cheetah/core/cheetah_encode.h | 54 +
.../cheetah/dictionary/cheetah_dictionary.h | 70 +
contrib/density/src/algorithms/dictionaries.c | 48 +
contrib/density/src/algorithms/dictionaries.h | 45 +
.../src/algorithms/lion/core/lion_decode.c | 327 ++++
.../src/algorithms/lion/core/lion_decode.h | 54 +
.../src/algorithms/lion/core/lion_encode.c | 298 ++++
.../src/algorithms/lion/core/lion_encode.h | 54 +
.../lion/dictionary/lion_dictionary.h | 73 +
.../algorithms/lion/forms/lion_form_model.c | 153 ++
.../algorithms/lion/forms/lion_form_model.h | 96 +
contrib/density/src/algorithms/lion/lion.h | 94 +
contrib/density/src/buffers/buffer.c | 220 +++
contrib/density/src/buffers/buffer.h | 58 +
contrib/density/src/density_api.h | 220 +++
contrib/density/src/globals.c | 47 +
contrib/density/src/globals.h | 232 +++
contrib/density/src/structure/header.c | 57 +
contrib/density/src/structure/header.h | 58 +
contrib/lizard/.gitattributes | 21 +
contrib/lizard/.gitignore | 37 +
contrib/lizard/.travis.yml | 268 +++
contrib/lizard/LICENSE | 15 +
contrib/lizard/NEWS | 41 +
contrib/lizard/README.md | 95 +
contrib/lizard/appveyor.yml | 143 ++
contrib/lizard/contrib/djgpp/LICENSE | 24 +
contrib/lizard/contrib/djgpp/README.MD | 21 +
contrib/lizard/doc/lizard_Block_format.md | 181 ++
contrib/lizard/doc/lizard_Frame_format.md | 312 ++++
contrib/lizard/examples/.gitignore | 8 +
.../lizard/examples/HCStreaming_ringBuffer.c | 241 +++
contrib/lizard/examples/README.md | 8 +
.../examples/blockStreaming_doubleBuffer.c | 203 +++
.../examples/blockStreaming_doubleBuffer.md | 100 ++
.../examples/blockStreaming_lineByLine.c | 210 +++
.../examples/blockStreaming_lineByLine.md | 122 ++
.../examples/blockStreaming_ringBuffer.c | 202 +++
contrib/lizard/examples/compress_functions.c | 303 ++++
contrib/lizard/examples/frameCompress.c | 169 ++
contrib/lizard/examples/printVersion.c | 13 +
contrib/lizard/examples/simple_buffer.c | 91 +
.../lizard/examples/streaming_api_basics.md | 87 +
contrib/lizard/lib/.gitignore | 3 +
contrib/lizard/lib/LICENSE | 25 +
contrib/lizard/lib/README.md | 76 +
contrib/lizard/lib/dll/liblizard.def | 19 +
contrib/lizard/lib/entropy/README.md | 38 +
contrib/lizard/lib/entropy/bitstream.h | 414 +++++
contrib/lizard/lib/entropy/entropy_common.c | 231 +++
contrib/lizard/lib/entropy/error_private.h | 115 ++
contrib/lizard/lib/entropy/error_public.h | 64 +
contrib/lizard/lib/entropy/fse.h | 694 ++++++++
contrib/lizard/lib/entropy/fse_compress.c | 848 +++++++++
contrib/lizard/lib/entropy/fse_decompress.c | 329 ++++
contrib/lizard/lib/entropy/huf.h | 250 +++
contrib/lizard/lib/entropy/huf_compress.c | 612 +++++++
contrib/lizard/lib/entropy/huf_decompress.c | 885 ++++++++++
contrib/lizard/lib/entropy/mem.h | 372 ++++
contrib/lizard/lib/liblizard.pc.in | 15 +
contrib/lizard/lib/lizard_common.h | 504 ++++++
contrib/lizard/lib/lizard_compress.c | 630 +++++++
contrib/lizard/lib/lizard_compress.h | 208 +++
contrib/lizard/lib/lizard_compress_liz.h | 301 ++++
contrib/lizard/lib/lizard_compress_lz4.h | 162 ++
contrib/lizard/lib/lizard_decompress.c | 372 ++++
contrib/lizard/lib/lizard_decompress.h | 152 ++
contrib/lizard/lib/lizard_decompress_liz.h | 220 +++
contrib/lizard/lib/lizard_decompress_lz4.h | 163 ++
contrib/lizard/lib/lizard_frame.c | 1362 ++++++++++++++
contrib/lizard/lib/lizard_frame.h | 303 ++++
contrib/lizard/lib/lizard_frame_static.h | 81 +
contrib/lizard/lib/lizard_parser_fast.h | 196 +++
contrib/lizard/lib/lizard_parser_fastbig.h | 175 ++
contrib/lizard/lib/lizard_parser_fastsmall.h | 189 ++
contrib/lizard/lib/lizard_parser_hashchain.h | 369 ++++
.../lizard/lib/lizard_parser_lowestprice.h | 376 ++++
contrib/lizard/lib/lizard_parser_nochain.h | 318 ++++
contrib/lizard/lib/lizard_parser_optimal.h | 679 +++++++
contrib/lizard/lib/lizard_parser_pricefast.h | 250 +++
contrib/lizard/lib/xxhash/xxhash.c | 888 ++++++++++
contrib/lizard/lib/xxhash/xxhash.h | 293 +++
contrib/lizard/programs/.gitignore | 15 +
contrib/lizard/programs/COPYING | 339 ++++
contrib/lizard/programs/README.md | 73 +
contrib/lizard/programs/bench.c | 502 ++++++
contrib/lizard/programs/bench.h | 37 +
contrib/lizard/programs/datagen.c | 188 ++
contrib/lizard/programs/datagen.h | 39 +
contrib/lizard/programs/lizard.1 | 229 +++
contrib/lizard/programs/lizardcli.c | 581 ++++++
contrib/lizard/programs/lizardio.c | 896 ++++++++++
contrib/lizard/programs/lizardio.h | 101 ++
contrib/lizard/programs/platform.h | 145 ++
contrib/lizard/programs/util.h | 497 ++++++
contrib/lizard/tests/.gitignore | 13 +
contrib/lizard/tests/COPYING | 339 ++++
contrib/lizard/tests/README.md | 15 +
contrib/lizard/tests/datagencli.c | 192 ++
contrib/lizard/tests/frametest.c | 866 +++++++++
contrib/lizard/tests/fullbench.c | 732 ++++++++
contrib/lizard/tests/fuzzer.c | 1086 ++++++++++++
contrib/lizard/visual/.gitignore | 11 +
contrib/lizard/visual/README.md | 53 +
.../visual/VS2010/datagen/datagen.vcxproj | 165 ++
.../visual/VS2010/frametest/frametest.vcxproj | 177 ++
.../visual/VS2010/fullbench/fullbench.vcxproj | 175 ++
.../visual/VS2010/fuzzer/fuzzer.vcxproj | 174 ++
.../VS2010/liblizard-dll/liblizard-dll.rc | 51 +
.../liblizard-dll/liblizard-dll.vcxproj | 179 ++
.../visual/VS2010/liblizard/liblizard.vcxproj | 176 ++
contrib/lizard/visual/VS2010/lizard.sln | 86 +
contrib/lizard/visual/VS2010/lizard/lizard.rc | 51 +
.../visual/VS2010/lizard/lizard.vcxproj | 190 ++
contrib/lzsse/.gitignore | 4 +
contrib/lzsse/.travis.yml | 185 ++
contrib/lzsse/LICENSE | 23 +
contrib/lzsse/README.md | 15 +
contrib/lzsse/example/main.cpp | 389 ++++
contrib/lzsse/lzsse2/lzsse2.cpp | 1080 ++++++++++++
contrib/lzsse/lzsse2/lzsse2.h | 90 +
contrib/lzsse/lzsse2/lzsse2_platform.h | 73 +
contrib/lzsse/lzsse4/lzsse4.cpp | 1499 ++++++++++++++++
contrib/lzsse/lzsse4/lzsse4.h | 117 ++
contrib/lzsse/lzsse4/lzsse4_platform.h | 73 +
contrib/lzsse/lzsse8/lzsse8.cpp | 1568 +++++++++++++++++
contrib/lzsse/lzsse8/lzsse8.h | 117 ++
contrib/lzsse/lzsse8/lzsse8_platform.h | 73 +
contrib/lzsse/premake4.exe | Bin 0 -> 518144 bytes
contrib/lzsse/premake4.lua | 26 +
156 files changed, 35085 insertions(+)
create mode 100644 contrib/density/.gitignore
create mode 100644 contrib/density/.gitmodules
create mode 100644 contrib/density/.travis.yml
create mode 100644 contrib/density/CHANGELOG.md
create mode 100644 contrib/density/LICENSE.md
create mode 100644 contrib/density/README.md
create mode 100644 contrib/density/appveyor.yml
create mode 100644 contrib/density/benchmark/src/benchmark.c
create mode 100644 contrib/density/benchmark/src/benchmark.h
create mode 100644 contrib/density/msvc/Density.sln
create mode 100644 contrib/density/msvc/benchmark.vcxproj
create mode 100644 contrib/density/msvc/benchmark.vcxproj.filters
create mode 100644 contrib/density/msvc/density.vcxproj
create mode 100644 contrib/density/msvc/density.vcxproj.filters
create mode 100644 contrib/density/src/algorithms/algorithms.c
create mode 100644 contrib/density/src/algorithms/algorithms.h
create mode 100644 contrib/density/src/algorithms/chameleon/chameleon.h
create mode 100644 contrib/density/src/algorithms/chameleon/core/chameleon_decode.c
create mode 100644 contrib/density/src/algorithms/chameleon/core/chameleon_decode.h
create mode 100644 contrib/density/src/algorithms/chameleon/core/chameleon_encode.c
create mode 100644 contrib/density/src/algorithms/chameleon/core/chameleon_encode.h
create mode 100644 contrib/density/src/algorithms/chameleon/dictionary/chameleon_dictionary.h
create mode 100644 contrib/density/src/algorithms/cheetah/cheetah.h
create mode 100644 contrib/density/src/algorithms/cheetah/core/cheetah_decode.c
create mode 100644 contrib/density/src/algorithms/cheetah/core/cheetah_decode.h
create mode 100644 contrib/density/src/algorithms/cheetah/core/cheetah_encode.c
create mode 100644 contrib/density/src/algorithms/cheetah/core/cheetah_encode.h
create mode 100644 contrib/density/src/algorithms/cheetah/dictionary/cheetah_dictionary.h
create mode 100644 contrib/density/src/algorithms/dictionaries.c
create mode 100644 contrib/density/src/algorithms/dictionaries.h
create mode 100644 contrib/density/src/algorithms/lion/core/lion_decode.c
create mode 100644 contrib/density/src/algorithms/lion/core/lion_decode.h
create mode 100644 contrib/density/src/algorithms/lion/core/lion_encode.c
create mode 100644 contrib/density/src/algorithms/lion/core/lion_encode.h
create mode 100644 contrib/density/src/algorithms/lion/dictionary/lion_dictionary.h
create mode 100644 contrib/density/src/algorithms/lion/forms/lion_form_model.c
create mode 100644 contrib/density/src/algorithms/lion/forms/lion_form_model.h
create mode 100644 contrib/density/src/algorithms/lion/lion.h
create mode 100644 contrib/density/src/buffers/buffer.c
create mode 100644 contrib/density/src/buffers/buffer.h
create mode 100644 contrib/density/src/density_api.h
create mode 100644 contrib/density/src/globals.c
create mode 100644 contrib/density/src/globals.h
create mode 100644 contrib/density/src/structure/header.c
create mode 100644 contrib/density/src/structure/header.h
create mode 100644 contrib/lizard/.gitattributes
create mode 100644 contrib/lizard/.gitignore
create mode 100644 contrib/lizard/.travis.yml
create mode 100644 contrib/lizard/LICENSE
create mode 100644 contrib/lizard/NEWS
create mode 100644 contrib/lizard/README.md
create mode 100644 contrib/lizard/appveyor.yml
create mode 100644 contrib/lizard/contrib/djgpp/LICENSE
create mode 100644 contrib/lizard/contrib/djgpp/README.MD
create mode 100644 contrib/lizard/doc/lizard_Block_format.md
create mode 100644 contrib/lizard/doc/lizard_Frame_format.md
create mode 100644 contrib/lizard/examples/.gitignore
create mode 100644 contrib/lizard/examples/HCStreaming_ringBuffer.c
create mode 100644 contrib/lizard/examples/README.md
create mode 100644 contrib/lizard/examples/blockStreaming_doubleBuffer.c
create mode 100644 contrib/lizard/examples/blockStreaming_doubleBuffer.md
create mode 100644 contrib/lizard/examples/blockStreaming_lineByLine.c
create mode 100644 contrib/lizard/examples/blockStreaming_lineByLine.md
create mode 100644 contrib/lizard/examples/blockStreaming_ringBuffer.c
create mode 100644 contrib/lizard/examples/compress_functions.c
create mode 100644 contrib/lizard/examples/frameCompress.c
create mode 100644 contrib/lizard/examples/printVersion.c
create mode 100644 contrib/lizard/examples/simple_buffer.c
create mode 100644 contrib/lizard/examples/streaming_api_basics.md
create mode 100644 contrib/lizard/lib/.gitignore
create mode 100644 contrib/lizard/lib/LICENSE
create mode 100644 contrib/lizard/lib/README.md
create mode 100644 contrib/lizard/lib/dll/liblizard.def
create mode 100644 contrib/lizard/lib/entropy/README.md
create mode 100644 contrib/lizard/lib/entropy/bitstream.h
create mode 100644 contrib/lizard/lib/entropy/entropy_common.c
create mode 100644 contrib/lizard/lib/entropy/error_private.h
create mode 100644 contrib/lizard/lib/entropy/error_public.h
create mode 100644 contrib/lizard/lib/entropy/fse.h
create mode 100644 contrib/lizard/lib/entropy/fse_compress.c
create mode 100644 contrib/lizard/lib/entropy/fse_decompress.c
create mode 100644 contrib/lizard/lib/entropy/huf.h
create mode 100644 contrib/lizard/lib/entropy/huf_compress.c
create mode 100644 contrib/lizard/lib/entropy/huf_decompress.c
create mode 100644 contrib/lizard/lib/entropy/mem.h
create mode 100644 contrib/lizard/lib/liblizard.pc.in
create mode 100644 contrib/lizard/lib/lizard_common.h
create mode 100644 contrib/lizard/lib/lizard_compress.c
create mode 100644 contrib/lizard/lib/lizard_compress.h
create mode 100644 contrib/lizard/lib/lizard_compress_liz.h
create mode 100644 contrib/lizard/lib/lizard_compress_lz4.h
create mode 100644 contrib/lizard/lib/lizard_decompress.c
create mode 100644 contrib/lizard/lib/lizard_decompress.h
create mode 100644 contrib/lizard/lib/lizard_decompress_liz.h
create mode 100644 contrib/lizard/lib/lizard_decompress_lz4.h
create mode 100644 contrib/lizard/lib/lizard_frame.c
create mode 100644 contrib/lizard/lib/lizard_frame.h
create mode 100644 contrib/lizard/lib/lizard_frame_static.h
create mode 100644 contrib/lizard/lib/lizard_parser_fast.h
create mode 100644 contrib/lizard/lib/lizard_parser_fastbig.h
create mode 100644 contrib/lizard/lib/lizard_parser_fastsmall.h
create mode 100644 contrib/lizard/lib/lizard_parser_hashchain.h
create mode 100644 contrib/lizard/lib/lizard_parser_lowestprice.h
create mode 100644 contrib/lizard/lib/lizard_parser_nochain.h
create mode 100644 contrib/lizard/lib/lizard_parser_optimal.h
create mode 100644 contrib/lizard/lib/lizard_parser_pricefast.h
create mode 100644 contrib/lizard/lib/xxhash/xxhash.c
create mode 100644 contrib/lizard/lib/xxhash/xxhash.h
create mode 100644 contrib/lizard/programs/.gitignore
create mode 100644 contrib/lizard/programs/COPYING
create mode 100644 contrib/lizard/programs/README.md
create mode 100644 contrib/lizard/programs/bench.c
create mode 100644 contrib/lizard/programs/bench.h
create mode 100644 contrib/lizard/programs/datagen.c
create mode 100644 contrib/lizard/programs/datagen.h
create mode 100644 contrib/lizard/programs/lizard.1
create mode 100644 contrib/lizard/programs/lizardcli.c
create mode 100644 contrib/lizard/programs/lizardio.c
create mode 100644 contrib/lizard/programs/lizardio.h
create mode 100644 contrib/lizard/programs/platform.h
create mode 100644 contrib/lizard/programs/util.h
create mode 100644 contrib/lizard/tests/.gitignore
create mode 100644 contrib/lizard/tests/COPYING
create mode 100644 contrib/lizard/tests/README.md
create mode 100644 contrib/lizard/tests/datagencli.c
create mode 100644 contrib/lizard/tests/frametest.c
create mode 100644 contrib/lizard/tests/fullbench.c
create mode 100644 contrib/lizard/tests/fuzzer.c
create mode 100644 contrib/lizard/visual/.gitignore
create mode 100644 contrib/lizard/visual/README.md
create mode 100644 contrib/lizard/visual/VS2010/datagen/datagen.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/frametest/frametest.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/fullbench/fullbench.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/fuzzer/fuzzer.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/liblizard-dll/liblizard-dll.rc
create mode 100644 contrib/lizard/visual/VS2010/liblizard-dll/liblizard-dll.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/liblizard/liblizard.vcxproj
create mode 100644 contrib/lizard/visual/VS2010/lizard.sln
create mode 100644 contrib/lizard/visual/VS2010/lizard/lizard.rc
create mode 100644 contrib/lizard/visual/VS2010/lizard/lizard.vcxproj
create mode 100644 contrib/lzsse/.gitignore
create mode 100644 contrib/lzsse/.travis.yml
create mode 100644 contrib/lzsse/LICENSE
create mode 100644 contrib/lzsse/README.md
create mode 100644 contrib/lzsse/example/main.cpp
create mode 100644 contrib/lzsse/lzsse2/lzsse2.cpp
create mode 100644 contrib/lzsse/lzsse2/lzsse2.h
create mode 100644 contrib/lzsse/lzsse2/lzsse2_platform.h
create mode 100644 contrib/lzsse/lzsse4/lzsse4.cpp
create mode 100644 contrib/lzsse/lzsse4/lzsse4.h
create mode 100644 contrib/lzsse/lzsse4/lzsse4_platform.h
create mode 100644 contrib/lzsse/lzsse8/lzsse8.cpp
create mode 100644 contrib/lzsse/lzsse8/lzsse8.h
create mode 100644 contrib/lzsse/lzsse8/lzsse8_platform.h
create mode 100644 contrib/lzsse/premake4.exe
create mode 100644 contrib/lzsse/premake4.lua
diff --git a/contrib/density/.gitignore b/contrib/density/.gitignore
new file mode 100644
index 00000000000..5192545dd3f
--- /dev/null
+++ b/contrib/density/.gitignore
@@ -0,0 +1,2 @@
+build/
+benchmark/build
diff --git a/contrib/density/.gitmodules b/contrib/density/.gitmodules
new file mode 100644
index 00000000000..91eee619841
--- /dev/null
+++ b/contrib/density/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "benchmark/libs/cputime"]
+ path = benchmark/libs/cputime
+ url = https://github.com/k0dai/cputime.git
+[submodule "benchmark/libs/spookyhash"]
+ path = benchmark/libs/spookyhash
+ url = https://github.com/k0dai/spookyhash.git
diff --git a/contrib/density/.travis.yml b/contrib/density/.travis.yml
new file mode 100644
index 00000000000..62e7655a4cb
--- /dev/null
+++ b/contrib/density/.travis.yml
@@ -0,0 +1,272 @@
+language: c
+matrix:
+ fast_finish: true
+ include:
+ - os: osx
+ env:
+ - C_COMPILER=clang
+
+ - os: osx
+ env:
+ - C_COMPILER=gcc
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-arm
+ - qemu-user-static
+ - gcc-aarch64-linux-gnu
+ - g++-aarch64-linux-gnu
+ env:
+ - C_COMPILER=aarch64-linux-gnu-gcc MAKE_OPTIONS="AR=gcc-ar NATIVE=off" QEMU_INTERPRETER=qemu-aarch64-static PRE_SCRIPT="export QEMU_LD_PREFIX=/usr/aarch64-linux-gnu/"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-arm
+ - qemu-user-static
+ - gcc-arm-linux-gnueabi
+ - g++-arm-linux-gnueabi
+ env:
+ - C_COMPILER=arm-linux-gnueabi-gcc MAKE_OPTIONS="AR=gcc-ar NATIVE=off" QEMU_INTERPRETER=qemu-arm-static PRE_SCRIPT="export QEMU_LD_PREFIX=/usr/arm-linux-gnueabi/"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-ppc
+ - qemu-user-static
+ - gcc-powerpc-linux-gnu
+ - g++-powerpc-linux-gnu
+ env:
+ - C_COMPILER=powerpc-linux-gnu-gcc MAKE_OPTIONS="AR=gcc-ar ARCH=64" QEMU_INTERPRETER="qemu-ppc64-static" PRE_SCRIPT="export QEMU_LD_PREFIX=/usr/powerpc-linux-gnu/"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-ppc
+ - qemu-user-static
+ - gcc-powerpc-linux-gnu
+ - g++-powerpc-linux-gnu
+ env:
+ - C_COMPILER=powerpc-linux-gnu-gcc MAKE_OPTIONS="AR=gcc-ar NATIVE=off" QEMU_INTERPRETER="qemu-ppc-static" PRE_SCRIPT="export QEMU_LD_PREFIX=/usr/powerpc-linux-gnu/"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.8
+ env:
+ - C_COMPILER=gcc-4.8 MAKE_OPTIONS="AR=gcc-ar"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.8
+ - gcc-4.8-multilib
+ env:
+ - C_COMPILER=gcc-4.8 MAKE_OPTIONS="AR=gcc-ar ARCH=32"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.9
+ env:
+ - C_COMPILER=gcc-4.9 MAKE_OPTIONS="AR=gcc-ar"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-4.9
+ - gcc-4.9-multilib
+ env:
+ - C_COMPILER=gcc-4.9 MAKE_OPTIONS="AR=gcc-ar ARCH=32"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-5
+ env:
+ - C_COMPILER=gcc-5 MAKE_OPTIONS="AR=gcc-ar-5"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-5
+ - gcc-5-multilib
+ env:
+ - C_COMPILER=gcc-5 MAKE_OPTIONS="AR=gcc-ar-5 ARCH=32"
+
+# - dist: trusty
+# sudo: required
+# addons:
+# apt:
+# sources:
+# - ubuntu-toolchain-r-test
+# packages:
+# - gcc-6
+# env:
+# - C_COMPILER=gcc-6 MAKE_OPTIONS="AR=gcc-ar-6"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-6
+ - gcc-6-multilib
+ env:
+ - C_COMPILER=gcc-6 MAKE_OPTIONS="AR=gcc-ar-6 ARCH=32"
+
+# - dist: trusty
+# sudo: required
+# addons:
+# apt:
+# sources:
+# - ubuntu-toolchain-r-test
+# packages:
+# - gcc-7
+# env:
+# - C_COMPILER=gcc-7 MAKE_OPTIONS="AR=gcc-ar-7"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-7
+ - gcc-7-multilib
+ env:
+ - C_COMPILER=gcc-7 MAKE_OPTIONS="AR=gcc-ar-7 ARCH=32"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-3.5
+ packages:
+ - clang-3.5
+ - llvm-3.5-dev
+ env:
+ - C_COMPILER=clang-3.5 MAKE_OPTIONS="AR=llvm-ar-3.5" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-3.6
+ packages:
+ - clang-3.6
+ - llvm-3.6-dev
+ env:
+ - C_COMPILER=clang-3.6 MAKE_OPTIONS="AR=llvm-ar-3.6" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+# - dist: precise
+# sudo: required
+# addons:
+# apt:
+# sources:
+# - ubuntu-toolchain-r-test
+# - llvm-toolchain-precise-3.7
+# packages:
+# - clang-3.7
+# - llvm-3.7-dev
+# env:
+# - C_COMPILER=clang-3.7 MAKE_OPTIONS="AR=llvm-ar-3.7" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+# - dist: precise
+# sudo: required
+# addons:
+# apt:
+# sources:
+# - ubuntu-toolchain-r-test
+# - llvm-toolchain-precise-3.8
+# packages:
+# - clang-3.8
+# - llvm-3.8-dev
+# env:
+# - C_COMPILER=clang-3.8 MAKE_OPTIONS="AR=llvm-ar-3.8" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-3.9
+ packages:
+ - clang-3.9
+ - llvm-3.9-dev
+ env:
+ - C_COMPILER=clang-3.9 MAKE_OPTIONS="AR=llvm-ar-3.9" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+ - dist: trusty
+ sudo: required
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-4.0
+ packages:
+ - clang-4.0
+ - llvm-4.0-dev
+ env:
+ - C_COMPILER=clang-4.0 MAKE_OPTIONS="AR=llvm-ar-4.0" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+# - dist: trusty
+# sudo: required
+# addons:
+# apt:
+# sources:
+# - ubuntu-toolchain-r-test
+# - llvm-toolchain-trusty-5.0
+# packages:
+# - clang-5.0
+# - llvm-5.0-dev
+# env:
+# - C_COMPILER=clang-5.0 MAKE_OPTIONS="AR=llvm-ar-5.0" PRE_SCRIPT="sudo ln -sf ld.gold /usr/bin/ld"
+
+script:
+ - ${PRE_SCRIPT}
+ - $C_COMPILER -v
+ - make CC=$C_COMPILER $MAKE_OPTIONS
+ - file ./build/*
+ - $QEMU_INTERPRETER ./build/benchmark -h -f
diff --git a/contrib/density/CHANGELOG.md b/contrib/density/CHANGELOG.md
new file mode 100644
index 00000000000..6d5535bcc7c
--- /dev/null
+++ b/contrib/density/CHANGELOG.md
@@ -0,0 +1,168 @@
+0.14.2
+------
+*February 12, 2018*
+* Improved chameleon decode speed
+* Added data hash checks and display option in benchmark
+* Now using makefiles as build system
+* Big endian support correctly implemented and tested
+* Improved continuous integration tests
+
+0.14.1
+------
+*January 20, 2018*
+* Added MSVC support
+* Added continuous integration on travis and appveyor
+* Premake script improvement
+* Various codebase improvements
+
+0.14.0
+------
+*January 16, 2018*
+* First stable version of DENSITY
+* Complete project reorganization and API rewrite
+* Many stability fixes and improvements
+* Fast revert to conditional copy for incompressible input
+* Custom dictionaries in API
+* Improvements in compression ratio and speed
+
+0.12.5 beta
+-----------
+*June 20, 2015*
+
+* Added conditional main footer read/write
+* Improved teleport staging buffer management
+* Regression - a minimum buffer output size has to be ensured to avoid signature loss
+* Modified the minimum lookahead and the resulting minimum buffer size in the API
+* Lion : corrected a signature interception problem due to an increase in process unit size
+* Lion : corrected chunk count conditions for new block / mode marker detection
+* Lion : modified end of stream marker conditions
+* Stability fixes and improvements
+
+0.12.4 beta
+-----------
+*May 25, 2015*
+
+* Removed remaining undefined behavior potential occurences
+* Implemented parallelizable decompressible output block header reads/writes (disabled by default)
+
+0.12.3 beta
+-----------
+*May 20, 2015*
+
+* New lion algorithm, faster and more efficient
+* Compiler specific optimizations
+* Switched to premake 5 to benefit from link time optimizations
+* Various fixes and improvements
+
+0.12.2 beta
+-----------
+*May 4, 2015*
+
+* Added an integrated in-memory benchmark
+* Better Windows compatibility
+* Fixed misaligned load/stores
+* Switched to the premake build system
+* Performance optimizations (pointers, branches, loops ...)
+* Various fixes and improvements
+
+0.12.1 beta
+-----------
+*April 3, 2015*
+
+* Better unrolling readability and efficiency
+* Improved read speed of dictionary/predictions entries
+* Implemented case generators in cheetah to speed up decoding by using less branches
+* Added signatures interception in lion to cancel the need for large output buffers
+* Improved lion decode speed with specific form data access and use of ctz in form read
+* Enabled decompression to exact-sized buffer for all algorithms
+* Various fixes and improvements
+
+0.12.0 beta
+-----------
+*March 24, 2015*
+
+* Added new lion kernel
+* Renamed kernel mandala to cheetah
+* Kernel chameleon and cheetah improvements in encoding/decoding speeds
+* Generic function macros to avoid code rewrite
+* Improved memory teleport IO flexibility and speed, bytes issued by memory teleport can now be partially read
+* Various fixes and improvements
+
+0.11.3 beta
+-----------
+*February 5, 2015*
+
+* Added integrity check system
+* Corrected pointer usage and update on footer read/writes
+* Now freeing kernel state memory only when compression mode is not copy
+* Updated Makefiles
+* Improved memory teleport
+* Fixed sequencing problem after kernels request a new block
+
+0.11.2 beta
+-----------
+*February 3, 2015*
+
+* Added an algorithms overview in README
+* Removed ssc references
+* Now initializing last hash to zero on mandala kernel inits
+* Reimplemented the buffer API
+* Various corrections and improvements
+
+0.11.1 beta
+-----------
+*January 19, 2015*
+
+* Added a sharc benchmark in README
+* Stateless memory teleport
+* Improved event management and dispatching
+* Improved compression/decompression finishes
+* Improved streams API
+* Various bug fixes, robustness improvements
+
+0.10.2 beta
+-----------
+*January 7, 2015*
+
+* Improved organization of compile-time switches and run-time options in the API
+* Removed method density_stream_decompress_utilities_get_header from the API, header info is now returned in the density_stream_decompress_init function
+* Corrected readme to reflect API changes
+
+0.10.1 beta
+-----------
+*January 5, 2015*
+
+* Re-added mandala kernel
+* Corrected available bytes adjustment problem
+* Added missing restrict keywords
+* Cleaned unnecessary defines
+
+0.10.0 beta
+-----------
+*January 2, 2015*
+
+* Complete stream API redesign to greatly improve flexibility
+* Only one supported algorithm for now : Chameleon
+
+0.9.12 beta
+-----------
+*December 2, 2013*
+
+* Mandala kernel addition, replacing dual pass chameleon
+* Simplified, faster hash function
+* Fixed memory freeing issue during main encoding/decoding finish
+* Implemented no footer encode output type
+* Namespace migration, kernel structure reorganization
+* Corrected copy mode problem
+* Implemented efficiency checks and mode reversions
+* Corrected lack of main header parameters retrieval
+* Fixed stream not being properly ended when mode reversion occurred
+* Updated metadata computations
+
+0.9.11 beta
+-----------
+*November 2, 2013*
+
+* First beta release of DENSITY, including all the compression code from SHARC in a standalone, BSD licensed library
+* Added copy mode (useful for enhancing data security via the density block checksums for example)
+* Makefile produces static and dynamic libraries
diff --git a/contrib/density/LICENSE.md b/contrib/density/LICENSE.md
new file mode 100644
index 00000000000..c2b699c9b83
--- /dev/null
+++ b/contrib/density/LICENSE.md
@@ -0,0 +1,28 @@
+Copyright (c) 2013, Guillaume Voirin
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/contrib/density/README.md b/contrib/density/README.md
new file mode 100644
index 00000000000..6c660dea1f5
--- /dev/null
+++ b/contrib/density/README.md
@@ -0,0 +1,261 @@
+DENSITY
+========
+Superfast compression library
+
+DENSITY is a free C99, open-source, BSD licensed compression library.
+
+It is focused on high-speed compression, at the best ratio possible. **All three** of DENSITY's algorithms are currently at the **pareto frontier** of compression speed vs ratio (cf. [here](https://github.com/inikep/lzbench/blob/master/lzbench18_sorted.md) for an independent benchmark).
+
+DENSITY features a simple API to enable quick integration in any project.
+
+Branch|Linux & MacOS|Windows
+--- | --- | ---
+master|[![Build Status](https://travis-ci.org/k0dai/density.svg?branch=master)](https://travis-ci.org/k0dai/density)|[![Build status](https://ci.appveyor.com/api/projects/status/rf7x3x829il72cii/branch/master?svg=true)](https://ci.appveyor.com/project/gpnuma/density/branch/master)
+dev|[![Build Status](https://travis-ci.org/k0dai/density.svg?branch=dev)](https://travis-ci.org/k0dai/density)|[![Build status](https://ci.appveyor.com/api/projects/status/rf7x3x829il72cii/branch/dev?svg=true)](https://ci.appveyor.com/project/gpnuma/density/branch/dev)
+
+Why is it so fast ?
+-------------------
+
+One of the biggest assets of DENSITY is that its work unit is **not a byte** like other libraries, but **a group of 4 bytes**.
+
+When other libraries consume one byte of data and then apply an algorithmic processing to it, DENSITY consumes 4 bytes and then applies its algorithmic processing.
+
+That's why DENSITY's algorithms were designed from scratch. They have to alleviate for 4-byte work units and still provide interesting compression ratios.
+
+**Speed pedigree traits**
+
+* 4-byte work units
+* heavy use of registers as opposed to memory for processing
+* avoidance of or use of minimal branching when possible
+* use of low memory data structures to favor processor cache Lx accesses
+* library wide inlining
+* specific unrollings
+* prefetching and branching hints
+* restricted pointers to maximize compiler optimizations
+
+A "blowup protection" is provided, dramatically increasing the processing speed of incompressible input data. Also, the output, compressed data size will **never exceed** the original uncompressed data size by more than 1% in case of incompressible, reasonably-sized inputs.
+
+Benchmarks
+----------
+
+**Quick benchmark**
+
+DENSITY features an **integrated in-memory benchmark**. After building the project (see [build](#build)), a *benchmark* executable will be present in the build directory. If run without arguments, usage help will be displayed.
+
+File used : enwik8 (100 MB)
+
+Platform : MacBook Pro, MacOS 10.13.3, 2.3 GHz Intel Core i7, 8Gb 1600 MHz DDR, SSD, compiling with Clang/LLVM 9.0.0
+
+Timing : using the *time* function, and taking the best *user* output after multiple runs. In the case of density, the in-memory integrated benchmark's best value (which uses the same usermode CPU timing) is used.
+
+Library|Algorithm|Compress|Decompress|Size|Ratio|Round trip
+---|---|---|---|---|---|---
+**density** 0.14.2|Chameleon|0.092s (1085 MB/s)|0.059s (1684 MB/s)|61 524 084|61,52%|0.151s
+lz4 r129|-1|0.468s (214 MB/s)|0.115s (870 MB/s)|57 285 990|57,29%|0.583s
+lzo 2.08|-1|0.367s (272 MB/s)|0.309s (324 MB/s)|56 709 096|56,71%|0.676s
+**density** 0.14.2|Cheetah|0.170s (587 MB/s)|0.126s (796 MB/s)|53 156 668|53,16%|0.296s
+**density** 0.14.2|Lion|0.303s (330 MB/s)|0.288s (347 MB/s)|47 817 692|47,82%|0.591s
+lz4 r129|-3|1.685s (59 MB/s)|0.118s (847 MB/s)|44 539 940|44,54%|1.803s
+lzo 2.08|-7|9.562s (10 MB/s)|0.319s (313 MB/s)|41 720 721|41,72%|9.881s
+
+**Other benchmarks**
+
+Here are a few other benchmarks featuring DENSITY (non exhaustive list) :
+
+* [**squash**](https://github.com/quixdb/squash) is an abstraction layer for compression algorithms, and has an extremely exhaustive set of benchmark results, including density's, [available here](https://quixdb.github.io/squash-benchmark/?dataset=dickens&machine=s-desktop).
+
+* [**lzbench**](https://github.com/inikep/lzbench) is an in-memory benchmark of open-source LZ77/LZSS/LZMA compressors.
+
+* [**fsbench**](https://github.com/gpnuma/fsbench-density) is a command line utility that enables real-time testing of compression algorithms, but also hashes and much more. A fork with density releases is [available here](https://github.com/gpnuma/fsbench-density) for easy access.
+The original author's repository [can be found here](https://chiselapp.com/user/Justin_be_my_guide/repository/fsbench/).
+
+Build
+-----
+DENSITY can be built on a number of platforms, via the provided makefiles.
+
+It was developed and optimized against Clang/LLVM which makes it the preferred compiler, but GCC and MSVC are also supported. Please use the latest compiler versions for best performance.
+
+**MacOS**
+
+On MacOS, Clang/LLVM is the default compiler, which makes things simpler.
+
+1) Get the source code :
+
+```
+ git clone https://github.com/k0dai/density.git
+ cd density
+```
+
+2) Build and test :
+
+```
+ make
+ build/benchmark -f
+```
+
+Alternatively, thanks to the [Homebrew project](https://brew.sh), DENSITY can also be installed with a single command on MacOS:
+
+```
+ brew install density
+```
+
+**Linux**
+
+On Linux, Clang/LLVM is not always available by default, but can be easily added thanks to the provided package managers.
+The following example assumes a Debian or Ubuntu distribution with *apt-get*.
+
+1) From the command line, install Clang/LLVM (*optional*, GCC is also supported if Clang/LLVM can't be used) and other prerequisites.
+
+```
+ sudo apt-get install clang git
+```
+
+2) Get the source code :
+
+```
+ git clone https://github.com/k0dai/density.git
+ cd density
+```
+
+3) Build and test :
+
+```
+ make
+```
+or
+```
+ make CC=gcc-... AR=gcc-ar-...
+```
+or
+```
+ make CC=clang-... AR=llvm-ar-...
+```
+to choose alternative compilers. For a quick test of resulting binaries, run
+```
+ build/benchmark -f
+```
+
+**Windows**
+
+Please install [git for Windows](https://git-scm.com/download/win) to begin with.
+
+On Windows, density can be built in different ways.
+The **first method** is to use mingw's gcc compiler; for that it is necessary to download and install [mingw-w64](https://sourceforge.net/projects/mingw-w64/).
+
+1) Once mingw-w64 is installed, get the source :
+
+```
+ git clone https://github.com/k0dai/density.git
+ cd density
+```
+
+2) Build and test :
+
+```
+ mingw32-make.exe
+ build/benchmark.exe -f
+```
+
+As an alternative, [MSYS2](http://www.msys2.org/) also offers a linux-like environment for Windows.
+
+The **second method** is to download and install Microsoft's [Visual Studio IDE community edition](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community). It comes with Microsoft's own compilers and is free.
+
+1) Once Visual Studio is installed, open a [developer command prompt](https://docs.microsoft.com/en-us/dotnet/framework/tools/developer-command-prompt-for-vs) and type :
+
+```
+ git clone https://github.com/k0dai/density.git
+ cd density\msvc
+```
+
+2) Build and test :
+
+```
+ msbuild Density.sln
+ bin\Release\benchmark.exe -f
+```
+
+An extra **recommended step** would be to install *Clang/LLVM* for Windows. It is downloadable from [this link](http://releases.llvm.org/5.0.1/LLVM-5.0.1-win64.exe). Once installed, open the Visual Studio IDE by double-clicking on *Density.sln*, then right-click on project names and change the platform toolsets to *LLVM*. Rebuild the solution to generate binaries with Clang/LLVM.
+
+Output format
+-------------
+DENSITY outputs compressed data in a simple format, which enables file storage and optional parallelization for both compression and decompression.
+
+A very short header holding vital informations (like DENSITY version and algorithm used) precedes the binary compressed data.
+
+APIs
+----
+DENSITY features a straightforward *API*, simple yet powerful enough to keep users' creativity unleashed.
+
+For advanced developers, it allows use of custom dictionaries and exportation of generated dictionaries after a compression session. Although using the default, blank dictionary is perfectly fine in most cases, setting up your own, tailored dictionaries could somewhat improve compression ratio especially for low sized input datum.
+
+Please see the [*quick start*](#quick-start-a-simple-example-using-the-api) at the bottom of this page.
+
+About the algorithms
+--------------------
+
+**Chameleon** ( *DENSITY_ALGORITHM_CHAMELEON* )
+
+Chameleon is a dictionary lookup based compression algorithm. It is designed for absolute speed and usually reaches a 60% compression ratio on compressible data.
+Decompression is just as fast. This algorithm is a great choice when main concern is speed.
+
+**Cheetah** ( *DENSITY_ALGORITHM_CHEETAH* )
+
+Cheetah was developed with inputs from [Piotr Tarsa](https://github.com/tarsa).
+It is derived from chameleon and uses swapped double dictionary lookups and predictions. It can be extremely good with highly compressible data (ratio reaching 10% or less).
+On typical compressible data compression ratio is about 50% or less. It is still extremely fast for both compression and decompression and is a great, efficient all-rounder algorithm.
+
+**Lion** ( *DENSITY_ALGORITHM_LION* )
+
+Lion is a multiform compression algorithm derived from cheetah. It goes further in the areas of dynamic adaptation and fine-grained analysis.
+It uses multiple swapped dictionary lookups and predictions, and forms rank entropy coding.
+Lion provides the best compression ratio of all three algorithms under any circumstance, and is still very fast.
+
+Quick start (a simple example using the API)
+--------------------------------------------
+Using DENSITY in your application couldn't be any simpler.
+
+First you need to include this file in your project :
+
+* density_api.h
+
+When this is done you can start using the **DENSITY API** :
+
+```C
+ #include
+ #include "density_api.h"
+
+ char* text = "This is a simple example on how to use the simple Density API. This is a simple example on how to use the simple Density API.";
+ uint64_t text_length = (uint64_t)strlen(text);
+
+ // Determine safe buffer sizes
+ uint_fast64_t compress_safe_size = density_compress_safe_size(text_length);
+ uint_fast64_t decompress_safe_size = density_decompress_safe_size(text_length);
+
+ // Allocate required memory
+ uint8_t *outCompressed = malloc(compress_safe_size * sizeof(char));
+ uint8_t *outDecompressed = malloc(decompress_safe_size * sizeof(char));
+ density_processing_result result;
+
+ // Compress
+ result = density_compress(text, text_length, outCompressed, compress_safe_size, DENSITY_COMPRESSION_MODE_CHAMELEON_ALGORITHM);
+ if(!result.state)
+ printf("Compressed %llu bytes to %llu bytes\n", result.bytesRead, result.bytesWritten);
+
+ // Decompress
+ result = density_decompress(outCompressed, result.bytesWritten, outDecompressed, decompress_safe_size);
+ if(!result.state)
+ printf("Decompressed %llu bytes to %llu bytes\n", result.bytesRead, result.bytesWritten);
+
+ // Free memory_allocated
+ free(outCompressed);
+ free(outDecompressed);
+```
+
+And that's it ! We've done a compression/decompression round trip with a few lines !
+
+Related projects
+----------------
+
+* **SHARC** (archiver using density algorithms) [https://github.com/gpnuma/sharc](https://github.com/gpnuma/sharc)
+* **fsbench-density** (in-memory transformations benchmark) [https://github.com/gpnuma/fsbench-density](https://github.com/gpnuma/fsbench-density)
+* **densityxx** (c++ port of density) [https://github.com/charlesw1234/densityxx](https://github.com/charlesw1234/densityxx)
diff --git a/contrib/density/appveyor.yml b/contrib/density/appveyor.yml
new file mode 100644
index 00000000000..0aabedebc8b
--- /dev/null
+++ b/contrib/density/appveyor.yml
@@ -0,0 +1,37 @@
+version: 0.14.2.{build}
+image: Visual Studio 2015
+init:
+- cmd:
+environment:
+ matrix:
+ - EXTRA_PATH: C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin\
+ LAUNCH_BUILD: mingw32-make CC=gcc AR=gcc-ar
+ LAUNCH_PATH: build\
+ - EXTRA_PATH: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1\mingw32\bin\
+ LAUNCH_BUILD: mingw32-make CC=gcc AR=gcc-ar
+ LAUNCH_PATH: build\
+ - EXTRA_PATH: C:\mingw-w64\x86_64-6.3.0-posix-seh-rt_v5-rev1\mingw64\bin\
+ LAUNCH_BUILD: mingw32-make CC=gcc AR=gcc-ar
+ LAUNCH_PATH: build\
+ - EXTRA_PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin\
+ LAUNCH_BUILD: mingw32-make CC=gcc AR=gcc-ar
+ LAUNCH_PATH: build\
+ - EXTRA_PATH: '%programfiles(x86)%\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\amd64\'
+ LAUNCH_BUILD: cd msvc && msbuild.exe Density.sln
+ EXTRA_GIT: git submodule update --init --recursive
+ LAUNCH_PATH: bin\Release\
+install:
+- cmd:
+build_script:
+- cmd: >-
+ %EXTRA_GIT%
+
+ set PATH=%EXTRA_PATH%;%PATH%
+
+ %LAUNCH_BUILD%
+
+ file %LAUNCH_PATH:\=/%*
+
+ %LAUNCH_PATH%benchmark.exe -h -f
+test_script:
+- cmd:
diff --git a/contrib/density/benchmark/src/benchmark.c b/contrib/density/benchmark/src/benchmark.c
new file mode 100644
index 00000000000..9781ef361c6
--- /dev/null
+++ b/contrib/density/benchmark/src/benchmark.c
@@ -0,0 +1,345 @@
+/*
+ * Density benchmark
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * 5/04/15 19:30
+ */
+
+#include "benchmark.h"
+
+void density_benchmark_version() {
+ printf("\nSingle threaded ");
+ DENSITY_BENCHMARK_BOLD(printf("in-memory benchmark"));
+ printf(" powered by ");
+ DENSITY_BENCHMARK_BOLD(printf("Density %i.%i.%i\n", density_version_major(), density_version_minor(), density_version_revision()));
+ printf("Copyright (C) 2015 Guillaume Voirin\n");
+ printf("Built for %s (%s endian system, %u bits) using " DENSITY_BENCHMARK_COMPILER ", %s %s\n", DENSITY_BENCHMARK_PLATFORM_STRING, DENSITY_BENCHMARK_ENDIAN_STRING, (unsigned int) (8 * sizeof(void *)), DENSITY_BENCHMARK_COMPILER_VERSION, __DATE__, __TIME__);
+}
+
+void density_benchmark_client_usage() {
+ printf("\n");
+ DENSITY_BENCHMARK_BOLD(printf("Usage :\n"));
+ printf(" benchmark [OPTIONS ?]... [FILE ?]\n\n");
+ DENSITY_BENCHMARK_BOLD(printf("Available options :\n"));
+ printf(" -[LEVEL] Test file using only the specified compression LEVEL\n");
+ printf(" If unspecified, all algorithms are tested (default).\n");
+ printf(" LEVEL can have the following values (as values become higher,\n");
+ printf(" compression ratio increases and speed diminishes) :\n");
+ printf(" 0 = Copy (no compression)\n");
+ printf(" 1 = Chameleon algorithm\n");
+ printf(" 2 = Cheetah algorithm\n");
+ printf(" 3 = Lion algorithm\n");
+ printf(" -c Compress only\n");
+ printf(" -f Activate fuzzer mode (pseudorandom generated data)\n");
+ printf(" -h Print data hashing informations\n\n");
+ exit(EXIT_SUCCESS);
+}
+
+void density_benchmark_format_decimal(uint64_t number) {
+ if (number < 1000) {
+ printf("%"PRIu64, number);
+ return;
+ }
+ density_benchmark_format_decimal(number / 1000);
+ printf(",%03"PRIu64, number % 1000);
+}
+
+const char *density_benchmark_convert_state_to_text(DENSITY_STATE state) {
+ switch (state) {
+ case DENSITY_STATE_ERROR_DURING_PROCESSING:
+ return "Error during processing";
+ case DENSITY_STATE_ERROR_INPUT_BUFFER_TOO_SMALL:
+ return "Input buffer is too small";
+ case DENSITY_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL:
+ return "Output buffer is too small";
+ case DENSITY_STATE_ERROR_INVALID_CONTEXT:
+ return "Invalid context";
+ case DENSITY_STATE_ERROR_INVALID_ALGORITHM:
+ return "Invalid algorithm";
+ default:
+ return "Unknown error";
+ }
+}
+
+int main(int argc, char *argv[]) {
+ density_benchmark_version();
+ DENSITY_ALGORITHM start_mode = DENSITY_ALGORITHM_CHAMELEON;
+ DENSITY_ALGORITHM end_mode = DENSITY_ALGORITHM_LION;
+ bool compression_only = false;
+ bool fuzzer = false;
+ bool hash_info = false;
+ char *file_path = NULL;
+
+ if (argc <= 1)
+ density_benchmark_client_usage();
+ for (int count = 1; count < argc; count++) {
+ if (argv[count][0] == '-') {
+ switch (argv[count][1]) {
+ case '1':
+ start_mode = DENSITY_ALGORITHM_CHAMELEON;
+ end_mode = DENSITY_ALGORITHM_CHAMELEON;
+ break;
+ case '2':
+ start_mode = DENSITY_ALGORITHM_CHEETAH;
+ end_mode = DENSITY_ALGORITHM_CHEETAH;
+ break;
+ case '3':
+ start_mode = DENSITY_ALGORITHM_LION;
+ end_mode = DENSITY_ALGORITHM_LION;
+ break;
+ case 'c':
+ compression_only = true;
+ break;
+ case 'f':
+ fuzzer = true;
+ break;
+ case 'h':
+ hash_info = true;
+ break;
+ default:
+ density_benchmark_client_usage();
+ }
+ } else
+ file_path = argv[argc - 1];
+ }
+
+ uint8_t *in;
+ uint8_t *out;
+ uint_fast64_t uncompressed_size;
+ uint_fast64_t memory_allocated;
+ if (fuzzer) {
+ srand((unsigned int) (time(NULL) * 14521937821257379531llu));
+ uncompressed_size = (uint_fast64_t) (((uint64_t) (rand() * 100000000llu)) / RAND_MAX);
+ memory_allocated = density_compress_safe_size(uncompressed_size);
+ in = malloc(memory_allocated * sizeof(uint8_t));
+ uint8_t value = (uint8_t) rand();
+ for (unsigned int count = 0; count < uncompressed_size; count++) {
+ if (!(rand() & 0xf))
+ value += (uint8_t)rand();
+ in[count] = value;
+ }
+ out = malloc(memory_allocated * sizeof(uint8_t));
+ } else {
+ // Open file and get infos
+ FILE *file = fopen(file_path, "rb");
+ if (file == NULL) {
+ DENSITY_BENCHMARK_ERROR(printf("Error opening file %s.", file_path), false);
+ }
+ struct stat file_attributes;
+ stat(file_path, &file_attributes);
+
+ // Allocate memory and copy file to memory
+ uncompressed_size = (uint_fast64_t) file_attributes.st_size;
+ memory_allocated = density_compress_safe_size(uncompressed_size);
+ in = malloc(memory_allocated * sizeof(uint8_t));
+ size_t read = fread(in, sizeof(uint8_t), uncompressed_size, file);
+ if(uncompressed_size != read) {
+ DENSITY_BENCHMARK_ERROR(printf("Error reading file %s.", file_path), false);
+ }
+ fclose(file);
+ out = malloc(memory_allocated * sizeof(uint8_t));
+ }
+
+ printf("Allocated ");
+ density_benchmark_format_decimal(2 * memory_allocated);
+ printf(" bytes of in-memory work space\n");
+
+ uint64_t original_hash_1 = DENSITY_BENCHMARK_HASH_SEED_1;
+ uint64_t original_hash_2 = DENSITY_BENCHMARK_HASH_SEED_2;
+ spookyhash_128(in, uncompressed_size, &original_hash_1, &original_hash_2);
+
+ printf("\n");
+ for (DENSITY_ALGORITHM compression_mode = start_mode; compression_mode <= end_mode; compression_mode++) {
+ // Print algorithm info
+ switch (compression_mode) {
+ case DENSITY_ALGORITHM_CHAMELEON:
+ DENSITY_BENCHMARK_BLUE(DENSITY_BENCHMARK_BOLD(printf("Chameleon algorithm")));
+ DENSITY_BENCHMARK_UNDERLINE(19);
+ break;
+ case DENSITY_ALGORITHM_CHEETAH:
+ DENSITY_BENCHMARK_BLUE(DENSITY_BENCHMARK_BOLD(printf("Cheetah algorithm")));
+ DENSITY_BENCHMARK_UNDERLINE(17);
+ break;
+ case DENSITY_ALGORITHM_LION:
+ DENSITY_BENCHMARK_BLUE(DENSITY_BENCHMARK_BOLD(printf("Lion algorithm")));
+ DENSITY_BENCHMARK_UNDERLINE(14);
+ break;
+ }
+ fflush(stdout);
+
+ // Pre-heat
+ printf("\nUsing ");
+ if (fuzzer) {
+ DENSITY_BENCHMARK_BOLD(printf("generated data"));
+ } else {
+ printf("file ");
+ DENSITY_BENCHMARK_BOLD(printf("%s", file_path));
+ }
+ printf(" copied in memory\n");
+ if(hash_info) {
+ printf("Uncompressed data hash is ");
+ DENSITY_BENCHMARK_BOLD(printf("0x%" PRIx64 "%" PRIx64, original_hash_1, original_hash_2));
+ printf("\n");
+ }
+
+ density_processing_result result = density_compress(in, uncompressed_size, out, memory_allocated, compression_mode);
+ if (result.state) {
+ DENSITY_BENCHMARK_ERROR(printf("During compress API returned error %i (%s).", result.state, density_benchmark_convert_state_to_text(result.state)), true);
+ }
+ const uint_fast64_t compressed_size = result.bytesWritten;
+
+ uint64_t hash_1 = DENSITY_BENCHMARK_HASH_SEED_1;
+ uint64_t hash_2 = DENSITY_BENCHMARK_HASH_SEED_2;
+ if(hash_info) {
+ spookyhash_128(out, compressed_size, &hash_1, &hash_2);
+ printf("Compressed data hash is ");
+ DENSITY_BENCHMARK_BOLD(printf("0x%" PRIx64 "%" PRIx64, hash_1, hash_2));
+ printf("\n");
+ }
+
+ if (!compression_only) {
+ memset(in, 0, memory_allocated);
+ result = density_decompress(out, compressed_size, in, memory_allocated);
+ if (result.state) {
+ DENSITY_BENCHMARK_ERROR(printf("During decompress API returned error %i (%s).", result.state, density_benchmark_convert_state_to_text(result.state)), true);
+ }
+ if (result.bytesWritten != uncompressed_size) {
+ DENSITY_BENCHMARK_ERROR(printf("Round-trip size differs from original size (");
+ density_benchmark_format_decimal(result.bytesWritten);
+ printf(" bytes against ");
+ density_benchmark_format_decimal(uncompressed_size);
+ printf(" bytes).");, true);
+ }
+
+ hash_1 = DENSITY_BENCHMARK_HASH_SEED_1;
+ hash_2 = DENSITY_BENCHMARK_HASH_SEED_2;
+ spookyhash_128(in, uncompressed_size, &hash_1, &hash_2);
+
+ if(hash_info) {
+ printf("Round-trip data hash is ");
+ DENSITY_BENCHMARK_BOLD(printf("0x%" PRIx64 "%" PRIx64, hash_1, hash_2));
+ printf("\n");
+ }
+
+ if(hash_1 != original_hash_1 || hash_2 != original_hash_2) {
+ DENSITY_BENCHMARK_ERROR(printf("Uncompressed and round-trip data hashes do not match (");
+ printf("0x%" PRIx64 "%" PRIx64, hash_1, hash_2);
+ printf(" vs. ");
+ printf("0x%" PRIx64 "%" PRIx64, original_hash_1, original_hash_2);
+ printf(").");, true);
+ }
+
+ printf("Uncompressed and round-trip data hashes match. ");
+ }
+ printf("Starting main bench.\n");
+ if (compression_only)
+ printf("Compressing ");
+ else
+ printf("Round-tripping ");
+ density_benchmark_format_decimal(uncompressed_size);
+ printf(" bytes to ");
+ density_benchmark_format_decimal(compressed_size);
+ printf(" bytes (compression ratio ");
+ DENSITY_BENCHMARK_BOLD(printf("%.2lf%%", (100.0 * compressed_size) / uncompressed_size));
+ printf(" or ");
+ DENSITY_BENCHMARK_BOLD(printf("%.3fx", (1.0 * uncompressed_size) / compressed_size));
+ if (compression_only)
+ printf(")\n");
+ else
+ printf(") and back\n");
+ fflush(stdout);
+
+ // Main benchmark
+ unsigned int iterations = 0;
+ double compress_time_high = 0.0;
+ double compress_time_low = 60.0;
+ double decompress_time_high = 0.0;
+ double decompress_time_low = 60.0;
+ double total_compress_time = 0.0;
+ double total_decompress_time = 0.0;
+ double total_time = 0.0;
+ double decompress_speed = 0.0;
+ double decompress_speed_low = 0.0;
+ double decompress_speed_high = 0.0;
+ double compress_time_elapsed = 0.0;
+ double decompress_time_elapsed = 0.0;
+ cputime_chronometer chrono;
+
+ while (total_time <= 10.0) {
+ ++iterations;
+
+ cputime_chronometer_start(&chrono);
+ density_compress(in, uncompressed_size, out, memory_allocated, compression_mode);
+ compress_time_elapsed = cputime_chronometer_stop(&chrono);
+
+ if (!compression_only) {
+ cputime_chronometer_start(&chrono);
+ density_decompress(out, compressed_size, in, memory_allocated);
+ decompress_time_elapsed = cputime_chronometer_stop(&chrono);
+ }
+
+ total_compress_time += compress_time_elapsed;
+
+ if (compress_time_elapsed < compress_time_low)
+ compress_time_low = compress_time_elapsed;
+ if (compress_time_elapsed > compress_time_high)
+ compress_time_high = compress_time_elapsed;
+
+ double compress_speed = ((1.0 * uncompressed_size * iterations) / (total_compress_time * 1000.0 * 1000.0));
+ double compress_speed_low = ((1.0 * uncompressed_size) / (compress_time_high * 1000.0 * 1000.0));
+ double compress_speed_high = ((1.0 * uncompressed_size) / (compress_time_low * 1000.0 * 1000.0));
+
+ total_time += compress_time_elapsed;
+
+ if (!compression_only) {
+ total_decompress_time += decompress_time_elapsed;
+
+ if (decompress_time_elapsed < decompress_time_low)
+ decompress_time_low = decompress_time_elapsed;
+ if (decompress_time_elapsed > decompress_time_high)
+ decompress_time_high = decompress_time_elapsed;
+
+ decompress_speed = ((1.0 * uncompressed_size * iterations) / (total_decompress_time * 1000.0 * 1000.0));
+ decompress_speed_low = ((1.0 * uncompressed_size) / (decompress_time_high * 1000.0 * 1000.0));
+ decompress_speed_high = ((1.0 * uncompressed_size) / (decompress_time_low * 1000.0 * 1000.0));
+
+ total_time += decompress_time_elapsed;
+ }
+
+ DENSITY_BENCHMARK_BLUE(printf("\rCompress speed ");
+ DENSITY_BENCHMARK_BOLD(printf("%.0lf MB/s", compress_speed)));
+ printf(" (min %.0lf MB/s, max %.0lf MB/s, best %.4lfs) ", compress_speed_low, compress_speed_high, compress_time_low);
+
+ if (!compression_only) {
+ printf("<=> ");
+ DENSITY_BENCHMARK_BLUE(printf("Decompress speed ");
+ DENSITY_BENCHMARK_BOLD(printf("%.0lf MB/s", decompress_speed)));
+ printf(" (min %.0lf MB/s, max %.0lf MB/s, best %.4lfs) ", decompress_speed_low, decompress_speed_high, decompress_time_low);
+ }
+ fflush(stdout);
+ }
+ printf("\nRun time %.3lfs (%i iterations)\n\n", total_time, iterations);
+ }
+
+ free(in);
+ free(out);
+
+ printf("Allocated memory released.\n\n");
+
+ return EXIT_SUCCESS;
+}
diff --git a/contrib/density/benchmark/src/benchmark.h b/contrib/density/benchmark/src/benchmark.h
new file mode 100644
index 00000000000..749e1ccb1d1
--- /dev/null
+++ b/contrib/density/benchmark/src/benchmark.h
@@ -0,0 +1,129 @@
+/*
+ * Density benchmark
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * 6/04/15 0:11
+ */
+
+#ifndef DENSITY_BENCHMARK_H
+#define DENSITY_BENCHMARK_H
+
+#define _CRT_SECURE_NO_DEPRECATE
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "../../src/density_api.h"
+#include "../libs/cputime/src/cputime_api.h"
+#include "../libs/spookyhash/src/spookyhash_api.h"
+
+#if defined(_WIN64) || defined(_WIN32)
+#else
+#define DENSITY_BENCHMARK_ALLOW_ANSI_ESCAPE_SEQUENCES
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define DENSITY_BENCHMARK_ENDIAN_STRING "Little"
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define DENSITY_BENCHMARK_ENDIAN_STRING "Big"
+#endif
+
+#if defined(__clang__)
+#define DENSITY_BENCHMARK_COMPILER "Clang %d.%d.%d"
+#define DENSITY_BENCHMARK_COMPILER_VERSION __clang_major__, __clang_minor__, __clang_patchlevel__
+#elif defined(__GNUC__)
+#define DENSITY_BENCHMARK_COMPILER "GCC %d.%d.%d"
+#define DENSITY_BENCHMARK_COMPILER_VERSION __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__
+#elif defined(_MSC_VER)
+#define DENSITY_BENCHMARK_COMPILER "MSVC"
+#define DENSITY_BENCHMARK_COMPILER_VERSION ""
+#elif defined(__INTEL_COMPILER)
+#define DENSITY_BENCHMARK_COMPILER "ICC"
+#define DENSITY_BENCHMARK_COMPILER_VERSION ""
+#else
+#define DENSITY_BENCHMARK_COMPILER "an unknown compiler"
+#define DENSITY_BENCHMARK_COMPILER_VERSION ""
+#endif
+
+#if defined(_WIN64) || defined(_WIN32)
+#define DENSITY_BENCHMARK_PLATFORM_STRING "Microsoft Windows"
+#elif defined(__APPLE__)
+#include "TargetConditionals.h"
+#if TARGET_IPHONE_SIMULATOR
+#define DENSITY_BENCHMARK_PLATFORM_STRING "iOS Simulator"
+#elif TARGET_OS_IPHONE
+#define DENSITY_BENCHMARK_PLATFORM_STRING "iOS"
+#elif TARGET_OS_MAC
+#define DENSITY_BENCHMARK_PLATFORM_STRING "MacOS"
+#else
+#define DENSITY_BENCHMARK_PLATFORM_STRING "an unknown Apple platform"
+#endif
+#elif defined(__FreeBSD__)
+#define DENSITY_BENCHMARK_PLATFORM_STRING "FreeBSD"
+#elif defined(__linux__)
+#define DENSITY_BENCHMARK_PLATFORM_STRING "GNU/Linux"
+#elif defined(__unix__)
+#define DENSITY_BENCHMARK_PLATFORM_STRING "Unix"
+#elif defined(__posix__)
+#define DENSITY_BENCHMARK_PLATFORM_STRING "Posix"
+#else
+#define DENSITY_BENCHMARK_PLATFORM_STRING "an unknown platform"
+#endif
+
+#define DENSITY_ESCAPE_CHARACTER ((char)27)
+
+#ifdef DENSITY_BENCHMARK_ALLOW_ANSI_ESCAPE_SEQUENCES
+#define DENSITY_BENCHMARK_BOLD(op) printf("%c[1m", DENSITY_ESCAPE_CHARACTER);\
+ op;\
+ printf("%c[0m", DENSITY_ESCAPE_CHARACTER);
+
+#define DENSITY_BENCHMARK_BLUE(op) printf("%c[0;34m", DENSITY_ESCAPE_CHARACTER);\
+ op;\
+ printf("%c[0m", DENSITY_ESCAPE_CHARACTER);
+
+#define DENSITY_BENCHMARK_RED(op) printf("%c[0;31m", DENSITY_ESCAPE_CHARACTER);\
+ op;\
+ printf("%c[0m", DENSITY_ESCAPE_CHARACTER);
+#else
+#define DENSITY_BENCHMARK_BOLD(op) op;
+#define DENSITY_BENCHMARK_BLUE(op) op;
+#define DENSITY_BENCHMARK_RED(op) op;
+#endif
+
+#define DENSITY_BENCHMARK_UNDERLINE(n) printf("\n");\
+ for(int i = 0; i < n; i++) printf("=");
+
+#define DENSITY_BENCHMARK_ERROR(op, issue) DENSITY_BENCHMARK_RED(DENSITY_BENCHMARK_BOLD(printf("\nAn error has occured !\n")));\
+ op;\
+ printf("\n");\
+ if(issue) {\
+ printf("Please open an issue at , with your platform information and any relevant file.\n");\
+ DENSITY_BENCHMARK_BOLD(printf("Thank you !\n"));\
+ }\
+ fflush(stdout);\
+ exit(EXIT_FAILURE);
+
+#endif
+
+#define DENSITY_BENCHMARK_HASH_SEED_1 0x0123456789abcdefllu
+#define DENSITY_BENCHMARK_HASH_SEED_2 0xfedcba9876543210llu
diff --git a/contrib/density/msvc/Density.sln b/contrib/density/msvc/Density.sln
new file mode 100644
index 00000000000..70c25ab3413
--- /dev/null
+++ b/contrib/density/msvc/Density.sln
@@ -0,0 +1,21 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "density", "density.vcxproj", "{65C51F09-D1A4-9EA4-DABC-297B461B0506}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "benchmark", "benchmark.vcxproj", "{7000C5C1-DC6A-7938-25A9-2ADE9152578D}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {65C51F09-D1A4-9EA4-DABC-297B461B0506}.Release|x64.ActiveCfg = Release|x64
+ {65C51F09-D1A4-9EA4-DABC-297B461B0506}.Release|x64.Build.0 = Release|x64
+ {7000C5C1-DC6A-7938-25A9-2ADE9152578D}.Release|x64.ActiveCfg = Release|x64
+ {7000C5C1-DC6A-7938-25A9-2ADE9152578D}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/contrib/density/msvc/benchmark.vcxproj b/contrib/density/msvc/benchmark.vcxproj
new file mode 100644
index 00000000000..ef32bbb5f3c
--- /dev/null
+++ b/contrib/density/msvc/benchmark.vcxproj
@@ -0,0 +1,78 @@
+
+
+
+
+ Release
+ x64
+
+
+
+ {7000C5C1-DC6A-7938-25A9-2ADE9152578D}
+ true
+ Win32Proj
+ benchmark
+
+
+
+ Application
+ false
+ Unicode
+ v140
+ true
+
+
+
+
+
+
+
+
+
+ false
+ bin\Release\
+ obj\Release\benchmark\
+ benchmark
+ .exe
+
+
+
+ NotUsing
+ Level4
+ MaxSpeed
+ true
+ true
+ false
+ true
+ true
+
+
+ Console
+ true
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {65C51F09-D1A4-9EA4-DABC-297B461B0506}
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/density/msvc/benchmark.vcxproj.filters b/contrib/density/msvc/benchmark.vcxproj.filters
new file mode 100644
index 00000000000..26379e28724
--- /dev/null
+++ b/contrib/density/msvc/benchmark.vcxproj.filters
@@ -0,0 +1,63 @@
+
+
+
+
+ {2F149A7C-1B4B-9B0D-C437-8110B04D170F}
+
+
+ {95C9EAC4-812C-7A69-2AB2-B21F16F445EC}
+
+
+ {2C4ACB69-1843-EABB-4175-CF402DCDC9C7}
+
+
+ {C78AF53E-3316-6303-3C27-E6F7A831BF03}
+
+
+ {5E54D780-CAB5-B48E-5323-FB40BF83EB4D}
+
+
+ {2DAB880B-99B4-887C-2230-9F7C8E38947C}
+
+
+
+
+ libs\cputime\src
+
+
+ libs\cputime\src
+
+
+ libs\spookyhash\src
+
+
+ libs\spookyhash\src
+
+
+ libs\spookyhash\src
+
+
+ libs\spookyhash\src
+
+
+ src
+
+
+
+
+ libs\cputime\src
+
+
+ libs\spookyhash\src
+
+
+ libs\spookyhash\src
+
+
+ libs\spookyhash\src
+
+
+ src
+
+
+
\ No newline at end of file
diff --git a/contrib/density/msvc/density.vcxproj b/contrib/density/msvc/density.vcxproj
new file mode 100644
index 00000000000..f1ad77fbc1b
--- /dev/null
+++ b/contrib/density/msvc/density.vcxproj
@@ -0,0 +1,93 @@
+
+
+
+
+ Release
+ x64
+
+
+
+ {65C51F09-D1A4-9EA4-DABC-297B461B0506}
+ true
+ Win32Proj
+ density
+
+
+
+ DynamicLibrary
+ false
+ Unicode
+ v140
+ true
+
+
+
+
+
+
+
+
+
+ false
+ bin\Release\
+ obj\Release\density\
+ density
+ .dll
+
+
+
+ NotUsing
+ Level4
+ MaxSpeed
+ true
+ true
+ false
+ true
+ true
+
+
+ Windows
+ true
+ true
+ bin\Release\density.lib
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/density/msvc/density.vcxproj.filters b/contrib/density/msvc/density.vcxproj.filters
new file mode 100644
index 00000000000..202f2522bbe
--- /dev/null
+++ b/contrib/density/msvc/density.vcxproj.filters
@@ -0,0 +1,135 @@
+
+
+
+
+ {DF10C562-CBC8-06B0-34D0-DF0B20A7A1A0}
+
+
+ {5AB95D49-4648-E712-EF66-FB0DDBD4F7B8}
+
+
+ {1252540B-7E14-8895-C7C4-162233C66073}
+
+
+ {3F6054BC-AB43-63FC-B446-913820A9294D}
+
+
+ {C09C0CB6-AC80-CD0B-15E1-C75E01E4B78D}
+
+
+ {3845B705-A47C-FF9C-AD86-63C0193D2696}
+
+
+ {E597066D-51B0-ED96-1A5D-7D3086348230}
+
+
+ {40FA2C44-AC85-9A08-B596-1DFD21A1F608}
+
+
+ {B8122E82-A4A1-B74B-4DC0-CB46392EC8F1}
+
+
+ {6585C1C9-5195-6D9A-BA4E-D2B8A67D5C33}
+
+
+ {B6B426C8-2221-E2C2-EB14-7A205740042B}
+
+
+ {B2DFE593-1EBF-642F-27D7-EF059335CB90}
+
+
+ {367A73B3-A2E4-272A-EB22-D9CF57CC057F}
+
+
+
+
+ algorithms
+
+
+ algorithms\chameleon
+
+
+ algorithms\chameleon\core
+
+
+ algorithms\chameleon\core
+
+
+ algorithms\chameleon\dictionary
+
+
+ algorithms\cheetah
+
+
+ algorithms\cheetah\core
+
+
+ algorithms\cheetah\core
+
+
+ algorithms\cheetah\dictionary
+
+
+ algorithms
+
+
+ algorithms\lion\core
+
+
+ algorithms\lion\core
+
+
+ algorithms\lion\dictionary
+
+
+ algorithms\lion\forms
+
+
+ algorithms\lion
+
+
+ buffers
+
+
+
+
+ structure
+
+
+
+
+ algorithms
+
+
+ algorithms\chameleon\core
+
+
+ algorithms\chameleon\core
+
+
+ algorithms\cheetah\core
+
+
+ algorithms\cheetah\core
+
+
+ algorithms
+
+
+ algorithms\lion\core
+
+
+ algorithms\lion\core
+
+
+ algorithms\lion\forms
+
+
+ buffers
+
+
+
+ structure
+
+
+
\ No newline at end of file
diff --git a/contrib/density/src/algorithms/algorithms.c b/contrib/density/src/algorithms/algorithms.c
new file mode 100644
index 00000000000..f36e94cd08b
--- /dev/null
+++ b/contrib/density/src/algorithms/algorithms.c
@@ -0,0 +1,43 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 14/10/15 02:06
+ */
+
+#include "algorithms.h"
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_algorithms_prepare_state(density_algorithm_state *const DENSITY_RESTRICT state, void *const DENSITY_RESTRICT dictionary) {
+ state->dictionary = dictionary;
+ state->copy_penalty = 0;
+ state->copy_penalty_start = 1;
+ state->previous_incompressible = false;
+ state->counter = 0;
+}
diff --git a/contrib/density/src/algorithms/algorithms.h b/contrib/density/src/algorithms/algorithms.h
new file mode 100644
index 00000000000..b5e31377004
--- /dev/null
+++ b/contrib/density/src/algorithms/algorithms.h
@@ -0,0 +1,78 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 3/02/15 19:51
+ */
+
+#ifndef DENSITY_ALGORITHMS_H
+#define DENSITY_ALGORITHMS_H
+
+#include "../globals.h"
+
+typedef enum {
+ DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED = 0,
+ DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING,
+ DENSITY_ALGORITHMS_EXIT_STATUS_INPUT_STALL,
+ DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL
+} density_algorithm_exit_status;
+
+typedef struct {
+ void *dictionary;
+ uint_fast8_t copy_penalty;
+ uint_fast8_t copy_penalty_start;
+ bool previous_incompressible;
+ uint_fast64_t counter;
+} density_algorithm_state;
+
+#define DENSITY_ALGORITHM_COPY(work_block_size)\
+ DENSITY_MEMCPY(*out, *in, work_block_size);\
+ *in += work_block_size;\
+ *out += work_block_size;
+
+#define DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START\
+ if(!(--state->copy_penalty))\
+ state->copy_penalty_start++;
+
+#define DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START\
+ if (state->copy_penalty_start & ~0x1)\
+ state->copy_penalty_start >>= 1;
+
+#define DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY(span, work_block_size)\
+ if (DENSITY_UNLIKELY(span & ~(work_block_size - 1))) {\
+ if (state->previous_incompressible)\
+ state->copy_penalty = state->copy_penalty_start;\
+ state->previous_incompressible = true;\
+ } else\
+ state->previous_incompressible = false;
+
+DENSITY_WINDOWS_EXPORT void density_algorithms_prepare_state(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, void *const DENSITY_RESTRICT_DECLARE);
+
+#endif
diff --git a/contrib/density/src/algorithms/chameleon/chameleon.h b/contrib/density/src/algorithms/chameleon/chameleon.h
new file mode 100644
index 00000000000..2054f34cfd8
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/chameleon.h
@@ -0,0 +1,70 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/10/13 11:57
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#ifndef DENSITY_CHAMELEON_H
+#define DENSITY_CHAMELEON_H
+
+#include "../../globals.h"
+
+#define DENSITY_CHAMELEON_HASH_BITS 16
+#define DENSITY_CHAMELEON_HASH_MULTIPLIER (uint32_t)0x9D6EF916lu
+
+#define DENSITY_CHAMELEON_HASH_ALGORITHM(value32) (uint16_t)((value32 * DENSITY_CHAMELEON_HASH_MULTIPLIER) >> (32 - DENSITY_CHAMELEON_HASH_BITS))
+
+typedef enum {
+ DENSITY_CHAMELEON_SIGNATURE_FLAG_CHUNK = 0x0,
+ DENSITY_CHAMELEON_SIGNATURE_FLAG_MAP = 0x1,
+} DENSITY_CHAMELEON_SIGNATURE_FLAG;
+
+typedef uint64_t density_chameleon_signature;
+
+#define DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE (density_bitsizeof(density_chameleon_signature) * sizeof(uint32_t)) // Uncompressed chunks
+#define DENSITY_CHAMELEON_DECOMPRESSED_BODY_SIZE_PER_SIGNATURE (density_bitsizeof(density_chameleon_signature) * sizeof(uint32_t))
+
+#define DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE (sizeof(density_chameleon_signature) + DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE)
+#define DENSITY_CHAMELEON_DECOMPRESSED_UNIT_SIZE (DENSITY_CHAMELEON_DECOMPRESSED_BODY_SIZE_PER_SIGNATURE)
+
+#define DENSITY_CHAMELEON_WORK_BLOCK_SIZE 256
+
+#endif
diff --git a/contrib/density/src/algorithms/chameleon/core/chameleon_decode.c b/contrib/density/src/algorithms/chameleon/core/chameleon_decode.c
new file mode 100644
index 00000000000..240aaba8598
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/core/chameleon_decode.c
@@ -0,0 +1,254 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 22:11
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#include "chameleon_decode.h"
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_process_compressed(const uint16_t hash, uint8_t **DENSITY_RESTRICT out, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ DENSITY_MEMCPY(*out, &dictionary->entries[hash].as_uint32_t, sizeof(uint32_t));
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_process_uncompressed(const uint32_t chunk, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ const uint16_t hash = DENSITY_CHAMELEON_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(chunk));
+ (&dictionary->entries[hash])->as_uint32_t = chunk; // Does not ensure dictionary content consistency between endiannesses
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_kernel(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, const density_bool compressed, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ if (compressed) {
+ uint16_t hash;
+ DENSITY_MEMCPY(&hash, *in, sizeof(uint16_t));
+ density_chameleon_decode_process_compressed(DENSITY_LITTLE_ENDIAN_16(hash), out, dictionary);
+ *in += sizeof(uint16_t);
+ } else {
+ uint32_t unit;
+ DENSITY_MEMCPY(&unit, *in, sizeof(uint32_t));
+ density_chameleon_decode_process_uncompressed(unit, dictionary);
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ *in += sizeof(uint32_t);
+ }
+ *out += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_kernel_dual(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, const density_chameleon_signature signature, const uint_fast8_t shift, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ uint32_t var_32;
+ uint64_t var_64;
+
+ switch((signature >> shift) & 0x3) {
+ case 0x0:
+ DENSITY_MEMCPY(&var_64, *in, sizeof(uint32_t) + sizeof(uint32_t));
+#ifdef DENSITY_LITTLE_ENDIAN
+ density_chameleon_decode_process_uncompressed((uint32_t)(var_64 & 0xffffffff), dictionary);
+#endif
+ density_chameleon_decode_process_uncompressed((uint32_t)(var_64 >> density_bitsizeof(uint32_t)), dictionary);
+#ifdef DENSITY_BIG_ENDIAN
+ density_chameleon_decode_process_uncompressed((uint32_t)(var_64 & 0xffffffff), dictionary);
+#endif
+ DENSITY_MEMCPY(*out, &var_64, sizeof(uint32_t) + sizeof(uint32_t));
+ *in += (sizeof(uint32_t) + sizeof(uint32_t));
+ *out += sizeof(uint64_t);
+ break;
+ case 0x1:
+ DENSITY_MEMCPY(&var_64, *in, sizeof(uint16_t) + sizeof(uint32_t));
+#ifdef DENSITY_LITTLE_ENDIAN
+ density_chameleon_decode_process_compressed((uint16_t)(var_64 & 0xffff), out, dictionary);
+ var_32 = (uint32_t)((var_64 >> density_bitsizeof(uint16_t)) & 0xffffffff);
+ density_chameleon_decode_process_uncompressed(var_32, dictionary);
+ DENSITY_MEMCPY(*out + sizeof(uint32_t), &var_32, sizeof(uint32_t));
+ *out += sizeof(uint64_t);
+#elif defined(DENSITY_BIG_ENDIAN)
+ density_chameleon_decode_process_compressed(DENSITY_LITTLE_ENDIAN_16((uint16_t)((var_64 >> (density_bitsizeof(uint16_t) + density_bitsizeof(uint32_t))) & 0xffff)), out, dictionary);
+ var_32 = (uint32_t)((var_64 >> density_bitsizeof(uint16_t)) & 0xffffffff);
+ density_chameleon_decode_process_uncompressed(var_32, dictionary);
+ DENSITY_MEMCPY(*out + sizeof(uint32_t), &var_32, sizeof(uint32_t));
+ *out += sizeof(uint64_t);
+#else
+#error
+#endif
+ *in += (sizeof(uint16_t) + sizeof(uint32_t));
+ break;
+ case 0x2:
+ DENSITY_MEMCPY(&var_64, *in, sizeof(uint32_t) + sizeof(uint16_t));
+#ifdef DENSITY_LITTLE_ENDIAN
+ var_32 = (uint32_t)(var_64 & 0xffffffff);
+ density_chameleon_decode_process_uncompressed(var_32, dictionary);
+ DENSITY_MEMCPY(*out, &var_32, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ density_chameleon_decode_process_compressed((uint16_t)((var_64 >> density_bitsizeof(uint32_t)) & 0xffff), out, dictionary);
+ *out += sizeof(uint32_t);
+#elif defined(DENSITY_BIG_ENDIAN)
+ var_32 = (uint32_t)((var_64 >> density_bitsizeof(uint32_t)) & 0xffffffff);
+ density_chameleon_decode_process_uncompressed(var_32, dictionary);
+ DENSITY_MEMCPY(*out, &var_32, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ density_chameleon_decode_process_compressed(DENSITY_LITTLE_ENDIAN_16((uint16_t)((var_64 >> density_bitsizeof(uint16_t)) & 0xffff)), out, dictionary);
+ *out += sizeof(uint32_t);
+#else
+#error
+#endif
+ *in += (sizeof(uint32_t) + sizeof(uint16_t));
+ break;
+ case 0x3:
+ DENSITY_MEMCPY(&var_32, *in, sizeof(uint16_t) + sizeof(uint16_t));
+#ifdef DENSITY_LITTLE_ENDIAN
+ density_chameleon_decode_process_compressed((uint16_t)(var_32 & 0xffff), out, dictionary);
+ *out += sizeof(uint32_t);
+#endif
+ density_chameleon_decode_process_compressed(DENSITY_LITTLE_ENDIAN_16((uint16_t)(var_32 >> density_bitsizeof(uint16_t))), out, dictionary);
+ *out += sizeof(uint32_t);
+#ifdef DENSITY_BIG_ENDIAN
+ density_chameleon_decode_process_compressed(DENSITY_LITTLE_ENDIAN_16((uint16_t)(var_32 & 0xffff)), out, dictionary);
+ *out += sizeof(uint32_t);
+#endif
+ *in += (sizeof(uint16_t) + sizeof(uint16_t));
+ break;
+ }
+}
+
+DENSITY_FORCE_INLINE bool density_chameleon_decode_test_compressed(const density_chameleon_signature signature, const uint_fast8_t shift) {
+ return (density_bool const) ((signature >> shift) & DENSITY_CHAMELEON_SIGNATURE_FLAG_MAP);
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, const density_chameleon_signature signature, const uint_fast8_t shift, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ density_chameleon_decode_kernel(in, out, density_chameleon_decode_test_compressed(signature, shift), dictionary);
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_256(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, const density_chameleon_signature signature, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary) {
+ uint_fast8_t count_a = 0;
+ uint_fast8_t count_b = 0;
+
+#if defined(__clang__) || defined(_MSC_VER)
+ do {
+ DENSITY_UNROLL_2(density_chameleon_decode_kernel_dual(in, out, signature, count_a, dictionary); count_a+= 2);
+ } while (++count_b & 0xf);
+#else
+ do {
+ DENSITY_UNROLL_2(density_chameleon_decode_4(in, out, signature, count_a ++, dictionary));
+ } while (++count_b & 0x1f);
+#endif
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_decode_read_signature(const uint8_t **DENSITY_RESTRICT in, density_chameleon_signature *DENSITY_RESTRICT signature) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature, *in, sizeof(density_chameleon_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ density_chameleon_signature endian_signature;
+ DENSITY_MEMCPY(&endian_signature, *in, sizeof(density_chameleon_signature));
+ *signature = DENSITY_LITTLE_ENDIAN_64(endian_signature);
+#else
+#error
+#endif
+ *in += sizeof(density_chameleon_signature);
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_chameleon_decode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_CHAMELEON_DECOMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_chameleon_signature signature;
+ uint_fast8_t shift;
+ uint_fast64_t remaining;
+
+ const uint8_t *start = *in;
+
+ if (in_size < DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE) {
+ goto read_signature;
+ }
+
+ const uint8_t *in_limit = *in + in_size - DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint8_t *out_limit = *out + out_size - DENSITY_CHAMELEON_DECOMPRESSED_UNIT_SIZE;
+
+ while (DENSITY_LIKELY(*in <= in_limit && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0xf))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_CHAMELEON_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *in_start = *in;
+ density_chameleon_decode_read_signature(in, &signature);
+ density_chameleon_decode_256(in, out, signature, (density_chameleon_dictionary *const) state->dictionary);
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*in - in_start), DENSITY_CHAMELEON_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ read_signature:
+ if (in_size - (*in - start) < sizeof(density_chameleon_signature))
+ return DENSITY_ALGORITHMS_EXIT_STATUS_INPUT_STALL;
+ shift = 0;
+ density_chameleon_decode_read_signature(in, &signature);
+ read_and_decode_4:
+ switch (in_size - (*in - start)) {
+ case 0:
+ case 1:
+ if (density_chameleon_decode_test_compressed(signature, shift))
+ return DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING;
+ else // End marker
+ goto process_remaining_bytes;
+ case 2:
+ case 3:
+ if (density_chameleon_decode_test_compressed(signature, shift++))
+ density_chameleon_decode_kernel(in, out, true, (density_chameleon_dictionary *const) state->dictionary);
+ else // End marker
+ goto process_remaining_bytes;
+ break;
+ default:
+ density_chameleon_decode_4(in, out, signature, shift++, (density_chameleon_dictionary *const) state->dictionary);
+ break;
+ }
+
+ if (DENSITY_UNLIKELY(shift == density_bitsizeof(density_chameleon_signature)))
+ goto read_signature;
+ else
+ goto read_and_decode_4;
+
+ process_remaining_bytes:
+ remaining = in_size - (*in - start);
+ DENSITY_ALGORITHM_COPY(remaining);
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/chameleon/core/chameleon_decode.h b/contrib/density/src/algorithms/chameleon/core/chameleon_decode.h
new file mode 100644
index 00000000000..cbf06e26a44
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/core/chameleon_decode.h
@@ -0,0 +1,53 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 21:49
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#ifndef DENSITY_CHAMELEON_DECODE_H
+#define DENSITY_CHAMELEON_DECODE_H
+
+#include "../dictionary/chameleon_dictionary.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_chameleon_decode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/chameleon/core/chameleon_encode.c b/contrib/density/src/algorithms/chameleon/core/chameleon_encode.c
new file mode 100644
index 00000000000..2090cb99173
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/core/chameleon_encode.c
@@ -0,0 +1,179 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 22:02
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#include "chameleon_encode.h"
+
+DENSITY_FORCE_INLINE void density_chameleon_encode_prepare_signature(uint8_t **DENSITY_RESTRICT out, density_chameleon_signature **DENSITY_RESTRICT signature_pointer, density_chameleon_signature *const DENSITY_RESTRICT signature) {
+ *signature = 0;
+ *signature_pointer = (density_chameleon_signature *) *out;
+ *out += sizeof(density_chameleon_signature);
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_encode_kernel(uint8_t **DENSITY_RESTRICT out, const uint16_t hash, const uint_fast8_t shift, density_chameleon_signature *const DENSITY_RESTRICT signature, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ density_chameleon_dictionary_entry *const found = &dictionary->entries[hash];
+
+ switch (*unit ^ found->as_uint32_t) {
+ case 0:
+ *signature |= ((uint64_t) DENSITY_CHAMELEON_SIGNATURE_FLAG_MAP << shift);
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ break;
+ default:
+ found->as_uint32_t = *unit; // Does not ensure dictionary content consistency between endiannesses
+ DENSITY_MEMCPY(*out, unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ break;
+ }
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_encode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, const uint_fast8_t shift, density_chameleon_signature *const DENSITY_RESTRICT signature, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ DENSITY_MEMCPY(unit, *in, sizeof(uint32_t));
+ density_chameleon_encode_kernel(out, DENSITY_CHAMELEON_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(*unit)), shift, signature, dictionary, unit);
+ *in += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE void density_chameleon_encode_256(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, density_chameleon_signature *const DENSITY_RESTRICT signature, density_chameleon_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ uint_fast8_t count = 0;
+
+#ifdef __clang__
+ for (uint_fast8_t count_b = 0; count_b < 32; count_b++) {
+ DENSITY_UNROLL_2(density_chameleon_encode_4(in, out, count++, signature, dictionary, unit));
+ }
+#else
+ for (uint_fast8_t count_b = 0; count_b < 16; count_b++) {
+ DENSITY_UNROLL_4(density_chameleon_encode_4(in, out, count++, signature, dictionary, unit));
+ }
+#endif
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_chameleon_encode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_chameleon_signature signature;
+ density_chameleon_signature *signature_pointer;
+ uint32_t unit;
+
+ uint8_t *out_limit = *out + out_size - DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint_fast64_t limit_256 = (in_size >> 8);
+
+ while (DENSITY_LIKELY(limit_256-- && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0xf))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_CHAMELEON_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *out_start = *out;
+ density_chameleon_encode_prepare_signature(out, &signature_pointer, &signature);
+ DENSITY_PREFETCH(*in + DENSITY_CHAMELEON_WORK_BLOCK_SIZE);
+ density_chameleon_encode_256(in, out, &signature, (density_chameleon_dictionary *const) state->dictionary, &unit);
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_chameleon_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_chameleon_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_chameleon_signature));
+#else
+#error
+#endif
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*out - out_start), DENSITY_CHAMELEON_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ uint_fast64_t remaining;
+
+ switch (in_size & 0xff) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ density_chameleon_encode_prepare_signature(out, &signature_pointer, &signature);
+ signature = ((uint64_t) DENSITY_CHAMELEON_SIGNATURE_FLAG_CHUNK); // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_chameleon_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_chameleon_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_chameleon_signature));
+#else
+#error
+#endif
+ goto process_remaining_bytes;
+ default:
+ break;
+ }
+
+ const uint_fast64_t limit_4 = (in_size & 0xff) >> 2;
+ density_chameleon_encode_prepare_signature(out, &signature_pointer, &signature);
+ for (uint_fast8_t shift = 0; shift != limit_4; shift++)
+ density_chameleon_encode_4(in, out, shift, &signature, (density_chameleon_dictionary *const) state->dictionary, &unit);
+
+ signature |= ((uint64_t) DENSITY_CHAMELEON_SIGNATURE_FLAG_CHUNK << limit_4); // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_chameleon_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_chameleon_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_chameleon_signature));
+#else
+#error
+#endif
+
+ process_remaining_bytes:
+ remaining = in_size & 0x3;
+ if (remaining)
+ DENSITY_ALGORITHM_COPY(remaining);
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/chameleon/core/chameleon_encode.h b/contrib/density/src/algorithms/chameleon/core/chameleon_encode.h
new file mode 100644
index 00000000000..f71fc23fbc0
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/core/chameleon_encode.h
@@ -0,0 +1,53 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 21:51
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#ifndef DENSITY_CHAMELEON_ENCODE_H
+#define DENSITY_CHAMELEON_ENCODE_H
+
+#include "../dictionary/chameleon_dictionary.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_chameleon_encode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/chameleon/dictionary/chameleon_dictionary.h b/contrib/density/src/algorithms/chameleon/dictionary/chameleon_dictionary.h
new file mode 100644
index 00000000000..1f584a5936e
--- /dev/null
+++ b/contrib/density/src/algorithms/chameleon/dictionary/chameleon_dictionary.h
@@ -0,0 +1,63 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/10/13 12:05
+ *
+ * -------------------
+ * Chameleon algorithm
+ * -------------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Hash based superfast kernel
+ */
+
+#ifndef DENSITY_CHAMELEON_DICTIONARY_H
+#define DENSITY_CHAMELEON_DICTIONARY_H
+
+#include "../chameleon.h"
+
+#include
+
+#pragma pack(push)
+#pragma pack(4)
+typedef struct {
+ uint32_t as_uint32_t;
+} density_chameleon_dictionary_entry;
+
+typedef struct {
+ density_chameleon_dictionary_entry entries[1 << DENSITY_CHAMELEON_HASH_BITS];
+} density_chameleon_dictionary;
+#pragma pack(pop)
+
+#endif
diff --git a/contrib/density/src/algorithms/cheetah/cheetah.h b/contrib/density/src/algorithms/cheetah/cheetah.h
new file mode 100644
index 00000000000..0d47d0ab502
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/cheetah.h
@@ -0,0 +1,73 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 06/12/13 20:10
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#ifndef DENSITY_CHEETAH_H
+#define DENSITY_CHEETAH_H
+
+#include "../../globals.h"
+
+#define DENSITY_CHEETAH_HASH_BITS 16
+#define DENSITY_CHEETAH_HASH_MULTIPLIER (uint32_t)0x9D6EF916lu
+
+#define DENSITY_CHEETAH_HASH_ALGORITHM(value32) (uint16_t)(value32 * DENSITY_CHEETAH_HASH_MULTIPLIER >> (32 - DENSITY_CHEETAH_HASH_BITS))
+
+typedef enum {
+ DENSITY_CHEETAH_SIGNATURE_FLAG_PREDICTED = 0x0,
+ DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_A = 0x1,
+ DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_B = 0x2,
+ DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK = 0x3,
+} DENSITY_CHEETAH_SIGNATURE_FLAG;
+
+typedef uint64_t density_cheetah_signature;
+
+#define DENSITY_CHEETAH_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE ((density_bitsizeof(density_cheetah_signature) >> 1) * sizeof(uint32_t)) // Uncompressed chunks
+#define DENSITY_CHEETAH_DECOMPRESSED_BODY_SIZE_PER_SIGNATURE ((density_bitsizeof(density_cheetah_signature) >> 1) * sizeof(uint32_t))
+
+#define DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE (sizeof(density_cheetah_signature) + DENSITY_CHEETAH_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE)
+#define DENSITY_CHEETAH_DECOMPRESSED_UNIT_SIZE (DENSITY_CHEETAH_DECOMPRESSED_BODY_SIZE_PER_SIGNATURE)
+
+#define DENSITY_CHEETAH_WORK_BLOCK_SIZE 128
+
+#endif
\ No newline at end of file
diff --git a/contrib/density/src/algorithms/cheetah/core/cheetah_decode.c b/contrib/density/src/algorithms/cheetah/core/cheetah_decode.c
new file mode 100644
index 00000000000..4928938b41e
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/core/cheetah_decode.c
@@ -0,0 +1,266 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 0:32
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#include "cheetah_decode.h"
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_process_predicted(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+ const uint32_t unit = dictionary->prediction_entries[*last_hash].next_chunk_prediction;
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ *last_hash = DENSITY_CHEETAH_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(unit));
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_process_compressed_a(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, const uint16_t hash) {
+ DENSITY_PREFETCH(&dictionary->prediction_entries[hash]);
+ const uint32_t unit = dictionary->entries[hash].chunk_a;
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ dictionary->prediction_entries[*last_hash].next_chunk_prediction = unit;
+ *last_hash = hash;
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_process_compressed_b(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, const uint16_t hash) {
+ DENSITY_PREFETCH(&dictionary->prediction_entries[hash]);
+ density_cheetah_dictionary_entry *const entry = &dictionary->entries[hash];
+ const uint32_t unit = entry->chunk_b;
+ entry->chunk_b = entry->chunk_a;
+ entry->chunk_a = unit; // Does not ensure dictionary content consistency between endiannesses
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ dictionary->prediction_entries[*last_hash].next_chunk_prediction = unit;
+ *last_hash = hash;
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_process_uncompressed(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, const uint32_t unit) {
+ const uint16_t hash = DENSITY_CHEETAH_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(unit));
+ DENSITY_PREFETCH(&dictionary->prediction_entries[hash]);
+ density_cheetah_dictionary_entry *const entry = &dictionary->entries[hash];
+ entry->chunk_b = entry->chunk_a;
+ entry->chunk_a = unit; // Does not ensure dictionary content consistency between endiannesses
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ dictionary->prediction_entries[*last_hash].next_chunk_prediction = unit; // Does not ensure dictionary content consistency between endiannesses
+ *last_hash = hash;
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_kernel_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const uint8_t flag, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+ uint16_t hash;
+ uint32_t unit;
+
+ switch (flag) {
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_PREDICTED:
+ density_cheetah_decode_process_predicted(out, last_hash, dictionary);
+ break;
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_A:
+ DENSITY_MEMCPY(&hash, *in, sizeof(uint16_t));
+ density_cheetah_decode_process_compressed_a(out, last_hash, dictionary, DENSITY_LITTLE_ENDIAN_16(hash));
+ *in += sizeof(uint16_t);
+ break;
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_B:
+ DENSITY_MEMCPY(&hash, *in, sizeof(uint16_t));
+ density_cheetah_decode_process_compressed_b(out, last_hash, dictionary, DENSITY_LITTLE_ENDIAN_16(hash));
+ *in += sizeof(uint16_t);
+ break;
+ default: // DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK
+ DENSITY_MEMCPY(&unit, *in, sizeof(uint32_t));
+ density_cheetah_decode_process_uncompressed(out, last_hash, dictionary, unit);
+ *in += sizeof(uint32_t);
+ break;
+ }
+
+ *out += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_kernel_16(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const uint8_t flags, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+ uint16_t hash;
+ uint32_t unit;
+
+ switch (flags) {
+ DENSITY_CASE_GENERATOR_4_4_COMBINED(\
+ density_cheetah_decode_process_predicted(out, last_hash, dictionary);, \
+ DENSITY_CHEETAH_SIGNATURE_FLAG_PREDICTED, \
+ DENSITY_MEMCPY(&hash, *in, sizeof(uint16_t)); \
+ density_cheetah_decode_process_compressed_a(out, last_hash, dictionary, DENSITY_LITTLE_ENDIAN_16(hash));\
+ *in += sizeof(uint16_t);, \
+ DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_A, \
+ DENSITY_MEMCPY(&hash, *in, sizeof(uint16_t)); \
+ density_cheetah_decode_process_compressed_b(out, last_hash, dictionary, DENSITY_LITTLE_ENDIAN_16(hash));\
+ *in += sizeof(uint16_t);, \
+ DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_B, \
+ DENSITY_MEMCPY(&unit, *in, sizeof(uint32_t)); \
+ density_cheetah_decode_process_uncompressed(out, last_hash, dictionary, unit);\
+ *in += sizeof(uint32_t);, \
+ DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK, \
+ *out += sizeof(uint32_t);, \
+ 2\
+ );
+ default:
+ break;
+ }
+
+ *out += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE uint8_t density_cheetah_decode_read_flag(const density_cheetah_signature signature, const uint_fast8_t shift) {
+ return (uint8_t const) ((signature >> shift) & 0x3);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const density_cheetah_signature signature, const uint_fast8_t shift, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+ density_cheetah_decode_kernel_4(in, out, last_hash, density_cheetah_decode_read_flag(signature, shift), dictionary);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_16(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const density_cheetah_signature signature, const uint_fast8_t shift, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+ density_cheetah_decode_kernel_16(in, out, last_hash, (uint8_t const) ((signature >> shift) & 0xff), dictionary);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_128(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const density_cheetah_signature signature, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary) {
+#ifdef __clang__
+ uint_fast8_t count = 0;
+ for (uint_fast8_t count_b = 0; count_b < 8; count_b ++) {
+ density_cheetah_decode_16(in, out, last_hash, signature, count, dictionary);
+ count += 8;
+ }
+#else
+ for (uint_fast8_t count_b = 0; count_b < density_bitsizeof(density_cheetah_signature); count_b += 8)
+ density_cheetah_decode_16(in, out, last_hash, signature, count_b, dictionary);
+#endif
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_decode_read_signature(const uint8_t **DENSITY_RESTRICT in, density_cheetah_signature *DENSITY_RESTRICT signature) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature, *in, sizeof(density_cheetah_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ density_cheetah_signature endian_signature;
+ DENSITY_MEMCPY(&endian_signature, *in, sizeof(density_cheetah_signature));
+ *signature = DENSITY_LITTLE_ENDIAN_64(endian_signature);
+#else
+#error
+#endif
+ *in += sizeof(density_cheetah_signature);
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_cheetah_decode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_CHEETAH_DECOMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_cheetah_signature signature;
+ uint_fast8_t shift;
+ uint_fast64_t remaining;
+ uint_fast16_t last_hash = 0;
+ uint8_t flag;
+
+ const uint8_t *start = *in;
+
+ if (in_size < DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE) {
+ goto read_signature;
+ }
+
+ const uint8_t *in_limit = *in + in_size - DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint8_t *out_limit = *out + out_size - DENSITY_CHEETAH_DECOMPRESSED_UNIT_SIZE;
+
+ while (DENSITY_LIKELY(*in <= in_limit && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0x1f))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_CHEETAH_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *in_start = *in;
+ density_cheetah_decode_read_signature(in, &signature);
+ density_cheetah_decode_128(in, out, &last_hash, signature, (density_cheetah_dictionary *const) state->dictionary);
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*in - in_start), DENSITY_CHEETAH_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ read_signature:
+ if (in_size - (*in - start) < sizeof(density_cheetah_signature))
+ return DENSITY_ALGORITHMS_EXIT_STATUS_INPUT_STALL;
+ shift = 0;
+ density_cheetah_decode_read_signature(in, &signature);
+ read_and_decode_4:
+ switch (in_size - (*in - start)) {
+ case 0:
+ case 1:
+ switch (density_cheetah_decode_read_flag(signature, shift)) {
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK:
+ goto process_remaining_bytes; // End marker
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_PREDICTED:
+ density_cheetah_decode_kernel_4(in, out, &last_hash, DENSITY_CHEETAH_SIGNATURE_FLAG_PREDICTED, (density_cheetah_dictionary *const) state->dictionary);
+ shift += 2;
+ break;
+ default:
+ return DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING;
+ }
+ break;
+ case 2:
+ case 3:
+ flag = density_cheetah_decode_read_flag(signature, shift);
+ switch (flag) {
+ case DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK:
+ goto process_remaining_bytes; // End marker
+ default:
+ density_cheetah_decode_kernel_4(in, out, &last_hash, flag, (density_cheetah_dictionary *const) state->dictionary);
+ shift += 2;
+ break;
+ }
+ break;
+ default:
+ density_cheetah_decode_4(in, out, &last_hash, signature, shift, (density_cheetah_dictionary *const) state->dictionary);
+ shift += 2;
+ break;
+ }
+
+ if (DENSITY_UNLIKELY(shift == density_bitsizeof(density_cheetah_signature)))
+ goto read_signature;
+ else
+ goto read_and_decode_4;
+
+ process_remaining_bytes:
+ remaining = in_size - (*in - start);
+ DENSITY_ALGORITHM_COPY(remaining);
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/cheetah/core/cheetah_decode.h b/contrib/density/src/algorithms/cheetah/core/cheetah_decode.h
new file mode 100644
index 00000000000..278368e7938
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/core/cheetah_decode.h
@@ -0,0 +1,54 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 0:31
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#ifndef DENSITY_CHEETAH_DECODE_H
+#define DENSITY_CHEETAH_DECODE_H
+
+#include "../dictionary/cheetah_dictionary.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_cheetah_decode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/cheetah/core/cheetah_encode.c b/contrib/density/src/algorithms/cheetah/core/cheetah_encode.c
new file mode 100644
index 00000000000..6cec16f4bf0
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/core/cheetah_encode.c
@@ -0,0 +1,202 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 23:29
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#include "cheetah_encode.h"
+
+DENSITY_FORCE_INLINE void density_cheetah_encode_prepare_signature(uint8_t **DENSITY_RESTRICT out, density_cheetah_signature **DENSITY_RESTRICT signature_pointer, density_cheetah_signature *const DENSITY_RESTRICT signature) {
+ *signature = 0;
+ *signature_pointer = (density_cheetah_signature *) *out;
+ *out += sizeof(density_cheetah_signature);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_encode_kernel(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const uint_fast16_t hash, const uint_fast8_t shift, density_cheetah_signature *const DENSITY_RESTRICT signature, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ uint32_t *predictedChunk = (uint32_t*) &dictionary->prediction_entries[*last_hash];
+
+ if (*predictedChunk ^ *unit) {
+ density_cheetah_dictionary_entry *found = &dictionary->entries[hash];
+ uint32_t *found_a = &found->chunk_a;
+ if (*found_a ^ *unit) {
+ uint32_t *found_b = &found->chunk_b;
+ if (*found_b ^ *unit) {
+ *signature |= ((uint64_t) DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK << shift);
+ DENSITY_MEMCPY(*out, unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ } else {
+ *signature |= ((uint64_t) DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_B << shift);
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ *found_b = *found_a;
+ *found_a = *unit; // Does not ensure dictionary content consistency between endiannesses
+ } else {
+ *signature |= ((uint64_t) DENSITY_CHEETAH_SIGNATURE_FLAG_MAP_A << shift);
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ *predictedChunk = *unit; // Does not ensure dictionary content consistency between endiannesses
+ }
+ *last_hash = hash;
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_encode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, const uint_fast8_t shift, density_cheetah_signature *const DENSITY_RESTRICT signature, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ DENSITY_MEMCPY(unit, *in, sizeof(uint32_t));
+ *in += sizeof(uint32_t);
+ density_cheetah_encode_kernel(out, last_hash, DENSITY_CHEETAH_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(*unit)), shift, signature, dictionary, unit);
+}
+
+DENSITY_FORCE_INLINE void density_cheetah_encode_128(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_cheetah_signature *const DENSITY_RESTRICT signature, density_cheetah_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT unit) {
+ uint_fast8_t count = 0;
+
+#ifdef __clang__
+ for(; count < density_bitsizeof(density_cheetah_signature); count += 2) {
+ density_cheetah_encode_4(in, out, last_hash, count, signature, dictionary, unit);
+ }
+#else
+ for (uint_fast8_t count_b = 0; count_b < 16; count_b++) {
+ DENSITY_UNROLL_2(\
+ density_cheetah_encode_4(in, out, last_hash, count, signature, dictionary, unit);\
+ count += 2);
+ }
+#endif
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_cheetah_encode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_cheetah_signature signature;
+ density_cheetah_signature *signature_pointer;
+ uint_fast16_t last_hash = 0;
+ uint32_t unit;
+
+ uint8_t *out_limit = *out + out_size - DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint_fast64_t limit_128 = (in_size >> 7);
+
+ while (DENSITY_LIKELY(limit_128-- && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0x1f))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_CHEETAH_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *out_start = *out;
+ density_cheetah_encode_prepare_signature(out, &signature_pointer, &signature);
+ DENSITY_PREFETCH(*in + DENSITY_CHEETAH_WORK_BLOCK_SIZE);
+ density_cheetah_encode_128(in, out, &last_hash, &signature, (density_cheetah_dictionary *const) state->dictionary, &unit);
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_cheetah_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_cheetah_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_cheetah_signature));
+#else
+#error
+#endif
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*out - out_start), DENSITY_CHEETAH_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ uint_fast64_t remaining;
+
+ switch (in_size & 0x7f) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ density_cheetah_encode_prepare_signature(out, &signature_pointer, &signature);
+ signature = (uint64_t) DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK; // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_cheetah_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_cheetah_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_cheetah_signature));
+#else
+#error
+#endif
+ goto process_remaining_bytes;
+ default:
+ break;
+ }
+
+ const uint_fast64_t limit_4 = ((in_size & 0x7f) >> 2) << 1; // 4-byte units times number of signature flag bits
+ density_cheetah_encode_prepare_signature(out, &signature_pointer, &signature);
+ for (uint_fast8_t shift = 0; shift != limit_4; shift += 2)
+ density_cheetah_encode_4(in, out, &last_hash, shift, &signature, (density_cheetah_dictionary *const) state->dictionary, &unit);
+
+ signature |= ((uint64_t) DENSITY_CHEETAH_SIGNATURE_FLAG_CHUNK << limit_4); // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_cheetah_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_cheetah_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_cheetah_signature));
+#else
+#error
+#endif
+
+ process_remaining_bytes:
+ remaining = in_size & 0x3;
+ if (remaining)
+ DENSITY_ALGORITHM_COPY(remaining);
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/cheetah/core/cheetah_encode.h b/contrib/density/src/algorithms/cheetah/core/cheetah_encode.h
new file mode 100644
index 00000000000..9f67e5bad9d
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/core/cheetah_encode.h
@@ -0,0 +1,54 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 23/06/15 23:29
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#ifndef DENSITY_CHEETAH_ENCODE_H
+#define DENSITY_CHEETAH_ENCODE_H
+
+#include "../dictionary/cheetah_dictionary.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_cheetah_encode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/cheetah/dictionary/cheetah_dictionary.h b/contrib/density/src/algorithms/cheetah/dictionary/cheetah_dictionary.h
new file mode 100644
index 00000000000..5223d843574
--- /dev/null
+++ b/contrib/density/src/algorithms/cheetah/dictionary/cheetah_dictionary.h
@@ -0,0 +1,70 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 06/12/13 20:20
+ *
+ * -----------------
+ * Cheetah algorithm
+ * -----------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ * Piotr Tarsa (https://github.com/tarsa)
+ *
+ * Description
+ * Very fast two level dictionary hash algorithm derived from Chameleon, with predictions lookup
+ */
+
+#ifndef DENSITY_CHEETAH_DICTIONARY_H
+#define DENSITY_CHEETAH_DICTIONARY_H
+
+#include "../cheetah.h"
+
+#include
+
+#pragma pack(push)
+#pragma pack(4)
+typedef struct {
+ uint32_t chunk_a;
+ uint32_t chunk_b;
+} density_cheetah_dictionary_entry;
+
+typedef struct {
+ uint32_t next_chunk_prediction;
+} density_cheetah_dictionary_prediction_entry;
+
+typedef struct {
+ density_cheetah_dictionary_entry entries[1 << DENSITY_CHEETAH_HASH_BITS];
+ density_cheetah_dictionary_prediction_entry prediction_entries[1 << DENSITY_CHEETAH_HASH_BITS];
+} density_cheetah_dictionary;
+#pragma pack(pop)
+
+#endif
diff --git a/contrib/density/src/algorithms/dictionaries.c b/contrib/density/src/algorithms/dictionaries.c
new file mode 100644
index 00000000000..1e8d5466014
--- /dev/null
+++ b/contrib/density/src/algorithms/dictionaries.c
@@ -0,0 +1,48 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2018, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 13/01/18 17:31
+ */
+
+#include "dictionaries.h"
+
+DENSITY_WINDOWS_EXPORT size_t density_get_dictionary_size(DENSITY_ALGORITHM algorithm) {
+ switch(algorithm) {
+ case DENSITY_ALGORITHM_CHAMELEON:
+ return sizeof(density_chameleon_dictionary);
+ case DENSITY_ALGORITHM_CHEETAH:
+ return sizeof(density_cheetah_dictionary);
+ case DENSITY_ALGORITHM_LION:
+ return sizeof(density_lion_dictionary);
+ default:
+ return 0;
+ }
+}
diff --git a/contrib/density/src/algorithms/dictionaries.h b/contrib/density/src/algorithms/dictionaries.h
new file mode 100644
index 00000000000..291c361963e
--- /dev/null
+++ b/contrib/density/src/algorithms/dictionaries.h
@@ -0,0 +1,45 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2018, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 13/01/18 17:26
+ */
+
+#ifndef DENSITY_DICTIONARIES_H
+#define DENSITY_DICTIONARIES_H
+
+#include "../globals.h"
+#include "../algorithms/chameleon/dictionary/chameleon_dictionary.h"
+#include "../algorithms/cheetah/dictionary/cheetah_dictionary.h"
+#include "../algorithms/lion/dictionary/lion_dictionary.h"
+
+DENSITY_WINDOWS_EXPORT size_t density_get_dictionary_size(DENSITY_ALGORITHM);
+
+#endif
diff --git a/contrib/density/src/algorithms/lion/core/lion_decode.c b/contrib/density/src/algorithms/lion/core/lion_decode.c
new file mode 100644
index 00000000000..c84262c0d50
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/core/lion_decode.c
@@ -0,0 +1,327 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 20:55
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#include "lion_decode.h"
+
+DENSITY_FORCE_INLINE void density_lion_decode_read_signature(const uint8_t **DENSITY_RESTRICT in, uint_fast64_t *const DENSITY_RESTRICT signature) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature, *in, sizeof(density_lion_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ density_lion_signature endian_signature;
+ DENSITY_MEMCPY(&endian_signature, *in, sizeof(density_lion_signature));
+ *signature = DENSITY_LITTLE_ENDIAN_64(endian_signature);
+#else
+#error
+#endif
+ *in += sizeof(density_lion_signature);
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_update_predictions_model(density_lion_dictionary_chunk_prediction_entry *const DENSITY_RESTRICT predictions, const uint32_t chunk) {
+ DENSITY_MEMMOVE((uint32_t *) predictions + 1, predictions, 2 * sizeof(uint32_t));
+ *(uint32_t *) predictions = chunk; // Move chunk to the top of the predictions list, does not ensure dictionary content consistency between endiannesses
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_update_dictionary_model(density_lion_dictionary_chunk_entry *const DENSITY_RESTRICT entry, const uint32_t chunk) {
+ DENSITY_MEMMOVE((uint32_t *) entry + 1, entry, 3 * sizeof(uint32_t));
+ *(uint32_t *) entry = chunk; // Does not ensure dictionary content consistency between endiannesses
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_read_hash(const uint8_t **DENSITY_RESTRICT in, uint16_t *DENSITY_RESTRICT const hash) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(hash, *in, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ uint16_t endian_hash;
+ DENSITY_MEMCPY(&endian_hash, *in, sizeof(uint16_t));
+ *hash = DENSITY_LITTLE_ENDIAN_16(endian_hash);
+#else
+#error
+#endif
+ *in += sizeof(uint16_t);
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_prediction_generic(uint8_t **DENSITY_RESTRICT out, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ *hash = DENSITY_LION_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(*unit));
+ DENSITY_MEMCPY(*out, unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_dictionary_generic(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint32_t *DENSITY_RESTRICT const unit) {
+ DENSITY_MEMCPY(*out, unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ density_lion_dictionary_chunk_prediction_entry *prediction = &(dictionary->predictions[*last_hash]);
+ density_lion_decode_update_predictions_model(prediction, *unit);
+}
+
+void density_lion_decode_prediction_a(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ (void)in;
+ *unit = dictionary->predictions[*last_hash].next_chunk_a;
+ density_lion_decode_prediction_generic(out, hash, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_prediction_b(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ (void)in;
+ density_lion_dictionary_chunk_prediction_entry *const prediction = &dictionary->predictions[*last_hash];
+ *unit = prediction->next_chunk_b;
+ density_lion_decode_update_predictions_model(prediction, *unit);
+ density_lion_decode_prediction_generic(out, hash, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_prediction_c(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ (void)in;
+ density_lion_dictionary_chunk_prediction_entry *const prediction = &dictionary->predictions[*last_hash];
+ *unit = prediction->next_chunk_c;
+ density_lion_decode_update_predictions_model(prediction, *unit);
+ density_lion_decode_prediction_generic(out, hash, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_dictionary_a(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ density_lion_decode_read_hash(in, hash);
+ DENSITY_PREFETCH(&dictionary->predictions[*hash]);
+ *unit = dictionary->chunks[*hash].chunk_a;
+ density_lion_decode_dictionary_generic(out, last_hash, dictionary, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_dictionary_b(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ density_lion_decode_read_hash(in, hash);
+ DENSITY_PREFETCH(&dictionary->predictions[*hash]);
+ density_lion_dictionary_chunk_entry *entry = &dictionary->chunks[*hash];
+ *unit = entry->chunk_b;
+ density_lion_decode_update_dictionary_model(entry, *unit);
+ density_lion_decode_dictionary_generic(out, last_hash, dictionary, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_dictionary_c(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ density_lion_decode_read_hash(in, hash);
+ DENSITY_PREFETCH(&dictionary->predictions[*hash]);
+ density_lion_dictionary_chunk_entry *entry = &dictionary->chunks[*hash];
+ *unit = entry->chunk_c;
+ density_lion_decode_update_dictionary_model(entry, *unit);
+ density_lion_decode_dictionary_generic(out, last_hash, dictionary, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_dictionary_d(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ density_lion_decode_read_hash(in, hash);
+ DENSITY_PREFETCH(&dictionary->predictions[*hash]);
+ density_lion_dictionary_chunk_entry *entry = &dictionary->chunks[*hash];
+ *unit = entry->chunk_d;
+ density_lion_decode_update_dictionary_model(entry, *unit);
+ density_lion_decode_dictionary_generic(out, last_hash, dictionary, unit);
+
+ *last_hash = *hash;
+}
+
+void density_lion_decode_plain(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, uint16_t *DENSITY_RESTRICT const hash, uint32_t *DENSITY_RESTRICT const unit) {
+ DENSITY_MEMCPY(unit, *in, sizeof(uint32_t));
+ *in += sizeof(uint32_t);
+ *hash = DENSITY_LION_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(*unit));
+ density_lion_dictionary_chunk_entry *entry = &dictionary->chunks[*hash];
+ density_lion_decode_update_dictionary_model(entry, *unit);
+ DENSITY_MEMCPY(*out, unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ density_lion_dictionary_chunk_prediction_entry *prediction = &(dictionary->predictions[*last_hash]);
+ density_lion_decode_update_predictions_model(prediction, *unit);
+
+ *last_hash = *hash;
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const data, const DENSITY_LION_FORM form) {
+ uint16_t hash;
+ uint32_t unit;
+
+ data->attachments[form](in, out, last_hash, dictionary, &hash, &unit);
+}
+
+DENSITY_FORCE_INLINE DENSITY_LION_FORM density_lion_decode_read_form(const uint8_t **DENSITY_RESTRICT in, uint_fast64_t *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_form_data *const form_data) {
+ const uint_fast8_t trailing_zeroes = DENSITY_CTZ(0x80 | (*signature >> *shift));
+ if (DENSITY_LIKELY(!trailing_zeroes)) {
+ *shift = (uint_fast8_t)((*shift + 1) & 0x3f);
+ return density_lion_form_model_increment_usage(form_data, (density_lion_form_node *) form_data->formsPool);
+ } else if (DENSITY_LIKELY(trailing_zeroes <= 6)) {
+ *shift = (uint_fast8_t)((*shift + (trailing_zeroes + 1)) & 0x3f);
+ return density_lion_form_model_increment_usage(form_data, (density_lion_form_node *) form_data->formsPool + trailing_zeroes);
+ } else {
+ if (DENSITY_LIKELY(*shift <= (density_bitsizeof(density_lion_signature) - 7))) {
+ *shift = (uint_fast8_t)((*shift + 7) & 0x3f);
+ return density_lion_form_model_increment_usage(form_data, (density_lion_form_node *) form_data->formsPool + 7);
+ } else {
+ density_lion_decode_read_signature(in, signature);
+ const uint_fast8_t primary_trailing_zeroes = (uint_fast8_t)(density_bitsizeof(density_lion_signature) - *shift);
+ const uint_fast8_t ctz_barrier_shift = (uint_fast8_t)(7 - primary_trailing_zeroes);
+ const uint_fast8_t secondary_trailing_zeroes = DENSITY_CTZ(((uint64_t)1 << ctz_barrier_shift) | *signature);
+ if (DENSITY_LIKELY(secondary_trailing_zeroes != ctz_barrier_shift))
+ *shift = (uint_fast8_t)(secondary_trailing_zeroes + 1);
+ else
+ *shift = secondary_trailing_zeroes;
+ return density_lion_form_model_increment_usage(form_data, (density_lion_form_node *) form_data->formsPool + primary_trailing_zeroes + secondary_trailing_zeroes);
+ }
+ }
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_process_form(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const form_data, uint_fast64_t *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift) {
+ if (DENSITY_UNLIKELY(!*shift))
+ density_lion_decode_read_signature(in, signature);
+
+ switch ((*signature >> *shift) & 0x1) {
+ case 0:
+ density_lion_decode_4(in, out, last_hash, dictionary, form_data, density_lion_decode_read_form(in, signature, shift, form_data));
+ break;
+ default:
+ density_lion_decode_4(in, out, last_hash, dictionary, form_data, density_lion_form_model_increment_usage(form_data, (density_lion_form_node *) form_data->formsPool));
+ *shift = (uint_fast8_t)((*shift + 1) & 0x3f);
+ break;
+ }
+}
+
+DENSITY_FORCE_INLINE void density_lion_decode_256(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const form_data, uint_fast64_t *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift) {
+#ifdef __clang__
+ for (uint_fast8_t count = 0; count < (DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_BIG >> 2); count++) {
+ DENSITY_UNROLL_4(density_lion_decode_process_form(in, out, last_hash, dictionary, form_data, signature, shift));
+ }
+#else
+ for (uint_fast8_t count = 0; count < (DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_BIG >> 2); count++) {
+ DENSITY_UNROLL_4(density_lion_decode_process_form(in, out, last_hash, dictionary, form_data, signature, shift));
+ }
+#endif
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_lion_decode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_LION_MAXIMUM_DECOMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_lion_signature signature = 0;
+ density_lion_form_data data;
+ density_lion_form_model_init(&data);
+ void (*attachments[DENSITY_LION_NUMBER_OF_FORMS])(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const) = {(void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_prediction_a, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_prediction_b, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_prediction_c, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_dictionary_a, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_dictionary_b, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_dictionary_c, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_dictionary_d, (void (*)(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) &density_lion_decode_plain};
+ density_lion_form_model_attach(&data, attachments);
+ uint_fast8_t shift = 0;
+ uint_fast64_t remaining;
+ uint_fast16_t last_hash = 0;
+ DENSITY_LION_FORM form;
+
+ const uint8_t *start = *in;
+
+ if (in_size < DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE) {
+ goto read_and_decode_4;
+ }
+
+ const uint8_t *in_limit = *in + in_size - DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint8_t *out_limit = *out + out_size - DENSITY_LION_MAXIMUM_DECOMPRESSED_UNIT_SIZE;
+
+ while (DENSITY_LIKELY(*in <= in_limit && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0xf))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_LION_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *in_start = *in;
+ density_lion_decode_256(in, out, &last_hash, (density_lion_dictionary *const) state->dictionary, &data, &signature, &shift);
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*in - in_start), DENSITY_LION_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ read_and_decode_4:
+ if (DENSITY_UNLIKELY(!shift)) {
+ if (in_size - (*in - start) < sizeof(density_lion_signature))
+ return DENSITY_ALGORITHMS_EXIT_STATUS_INPUT_STALL;
+
+ density_lion_decode_read_signature(in, &signature);
+ }
+ form = density_lion_decode_read_form(in, &signature, &shift, &data);
+ switch (in_size - (*in - start)) {
+ case 0:
+ case 1:
+ switch (form) {
+ case DENSITY_LION_FORM_PLAIN:
+ goto process_remaining_bytes; // End marker
+ case DENSITY_LION_FORM_PREDICTIONS_A:
+ case DENSITY_LION_FORM_PREDICTIONS_B:
+ case DENSITY_LION_FORM_PREDICTIONS_C:
+ density_lion_decode_4(in, out, &last_hash, (density_lion_dictionary *const) state->dictionary, &data, form);
+ break;
+ default:
+ return DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING; // Not enough bytes to read a hash
+ }
+ break;
+ case 2:
+ case 3:
+ switch (form) {
+ case DENSITY_LION_FORM_PLAIN:
+ goto process_remaining_bytes; // End marker
+ default:
+ density_lion_decode_4(in, out, &last_hash, (density_lion_dictionary *const) state->dictionary, &data, form);
+ break;
+ }
+ break;
+ default:
+ density_lion_decode_4(in, out, &last_hash, (density_lion_dictionary *const) state->dictionary, &data, form);
+ break;
+ }
+ goto read_and_decode_4;
+
+ process_remaining_bytes:
+ remaining = in_size - (*in - start);
+ DENSITY_MEMCPY(*out, *in, remaining);
+ *in += remaining;
+ *out += remaining;
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/lion/core/lion_decode.h b/contrib/density/src/algorithms/lion/core/lion_decode.h
new file mode 100644
index 00000000000..9972f0be388
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/core/lion_decode.h
@@ -0,0 +1,54 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 20:55
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#ifndef DENSITY_LION_DECODE_H
+#define DENSITY_LION_DECODE_H
+
+#include "../dictionary/lion_dictionary.h"
+#include "../forms/lion_form_model.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_lion_decode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/lion/core/lion_encode.c b/contrib/density/src/algorithms/lion/core/lion_encode.c
new file mode 100644
index 00000000000..7cff2f3dda7
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/core/lion_encode.c
@@ -0,0 +1,298 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 18:57
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#include "lion_encode.h"
+
+DENSITY_FORCE_INLINE void density_lion_encode_prepare_signature(uint8_t **DENSITY_RESTRICT out, uint_fast64_t **DENSITY_RESTRICT signature_pointer, uint_fast64_t *const DENSITY_RESTRICT signature) {
+ *signature = 0;
+ *signature_pointer = (density_lion_signature *) *out;
+ *out += sizeof(density_lion_signature);
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_push_to_proximity_signature(uint_fast64_t *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, const uint64_t content, const uint_fast8_t bits) {
+ *signature |= (content << *shift);
+ *shift += bits;
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_push_to_signature(uint8_t **DENSITY_RESTRICT out, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, const uint64_t content, const uint_fast8_t bits) {
+ if (DENSITY_LIKELY(*shift)) {
+ density_lion_encode_push_to_proximity_signature(signature, shift, content, bits);
+
+ if (DENSITY_UNLIKELY(*shift >= density_bitsizeof(density_lion_signature))) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*signature_pointer, signature, sizeof(density_lion_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_lion_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(*signature);
+ DENSITY_MEMCPY(*signature_pointer, &endian_signature, sizeof(density_lion_signature));
+#else
+#error
+#endif
+
+ const uint_fast8_t remainder = (uint_fast8_t)(*shift & 0x3f);
+ *shift = 0;
+ if (remainder) {
+ density_lion_encode_prepare_signature(out, signature_pointer, signature);
+ density_lion_encode_push_to_proximity_signature(signature, shift, content >> (bits - remainder), remainder);
+ }
+ }
+ } else {
+ density_lion_encode_prepare_signature(out, signature_pointer, signature);
+ density_lion_encode_push_to_proximity_signature(signature, shift, content, bits);
+ }
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_push_zero_to_signature(uint8_t **DENSITY_RESTRICT out, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, const uint_fast8_t bits) {
+ if (DENSITY_LIKELY(*shift)) {
+ *shift += bits;
+
+ if (DENSITY_UNLIKELY(*shift >= density_bitsizeof(density_lion_signature))) {
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*signature_pointer, signature, sizeof(density_lion_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_lion_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(*signature);
+ DENSITY_MEMCPY(*signature_pointer, &endian_signature, sizeof(density_lion_signature));
+#else
+#error
+#endif
+
+ const uint_fast8_t remainder = (uint_fast8_t)(*shift & 0x3f);
+ if (remainder) {
+ density_lion_encode_prepare_signature(out, signature_pointer, signature);
+ *shift = remainder;
+ } else
+ *shift = 0;
+ }
+ } else {
+ density_lion_encode_prepare_signature(out, signature_pointer, signature);
+ *shift = bits;
+ }
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_push_code_to_signature(uint8_t **DENSITY_RESTRICT out, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, const density_lion_entropy_code code) {
+ density_lion_encode_push_to_signature(out, signature_pointer, signature, shift, code.value, code.bitLength);
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_kernel_4(uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_dictionary *const DENSITY_RESTRICT dictionary, const uint16_t hash, density_lion_form_data *const data, const uint32_t unit) {
+ density_lion_dictionary_chunk_prediction_entry *const predictions = &dictionary->predictions[*last_hash];
+ DENSITY_PREFETCH(&dictionary->predictions[hash]);
+
+ if (*(uint32_t *) predictions ^ unit) {
+ if (*((uint32_t *) predictions + 1) ^ unit) {
+ if (*((uint32_t *) predictions + 2) ^ unit) {
+ density_lion_dictionary_chunk_entry *const in_dictionary = &dictionary->chunks[hash];
+ if (*(uint32_t *) in_dictionary ^ unit) {
+ if (*((uint32_t *) in_dictionary + 1) ^ unit) {
+ if (*((uint32_t *) in_dictionary + 2) ^ unit) {
+ if (*((uint32_t *) in_dictionary + 3) ^ unit) {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_PLAIN));
+ DENSITY_MEMCPY(*out, &unit, sizeof(uint32_t));
+ *out += sizeof(uint32_t);
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_DICTIONARY_D));
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_DICTIONARY_C));
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_DICTIONARY_B));
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ DENSITY_MEMMOVE((uint32_t *) in_dictionary + 1, in_dictionary, 3 * sizeof(uint32_t));
+ *(uint32_t *) in_dictionary = unit; // Does not ensure dictionary content consistency between endiannesses
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_DICTIONARY_A));
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(*out, &hash, sizeof(uint16_t));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const uint16_t endian_hash = DENSITY_LITTLE_ENDIAN_16(hash);
+ DENSITY_MEMCPY(*out, &endian_hash, sizeof(uint16_t));
+#else
+#error
+#endif
+ *out += sizeof(uint16_t);
+ }
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_PREDICTIONS_C));
+ }
+ } else {
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_PREDICTIONS_B));
+ }
+ DENSITY_MEMMOVE((uint32_t *) predictions + 1, predictions, 2 * sizeof(uint32_t));
+ *(uint32_t *) predictions = unit; // Does not ensure dictionary content consistency between endiannesses
+ } else
+ density_lion_encode_push_code_to_signature(out, signature_pointer, signature, shift, density_lion_form_model_get_encoding(data, DENSITY_LION_FORM_PREDICTIONS_A));
+ *last_hash = hash;
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_4(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const data, uint32_t *DENSITY_RESTRICT unit) {
+ DENSITY_MEMCPY(unit, *in, sizeof(uint32_t));
+ density_lion_encode_kernel_4(out, last_hash, signature_pointer, signature, shift, dictionary, DENSITY_LION_HASH_ALGORITHM(DENSITY_LITTLE_ENDIAN_32(*unit)), data, *unit);
+ *in += sizeof(uint32_t);
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_generic(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_dictionary *const DENSITY_RESTRICT dictionary, const uint_fast8_t chunks_per_process_unit, density_lion_form_data *const data, uint32_t *DENSITY_RESTRICT unit) {
+#ifdef __clang__
+ for (uint_fast8_t count = 0; count < (chunks_per_process_unit >> 2); count++) {
+ DENSITY_UNROLL_4(density_lion_encode_4(in, out, last_hash, signature_pointer, signature, shift, dictionary, data, unit));
+ }
+#else
+ for (uint_fast8_t count = 0; count < (chunks_per_process_unit >> 1); count++) {
+ DENSITY_UNROLL_2(density_lion_encode_4(in, out, last_hash, signature_pointer, signature, shift, dictionary, data, unit));
+ }
+#endif
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_32(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const data, uint32_t *DENSITY_RESTRICT unit) {
+ density_lion_encode_generic(in, out, last_hash, signature_pointer, signature, shift, dictionary, DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_SMALL, data, unit);
+}
+
+DENSITY_FORCE_INLINE void density_lion_encode_256(const uint8_t **DENSITY_RESTRICT in, uint8_t **DENSITY_RESTRICT out, uint_fast16_t *DENSITY_RESTRICT last_hash, density_lion_signature **DENSITY_RESTRICT signature_pointer, density_lion_signature *const DENSITY_RESTRICT signature, uint_fast8_t *const DENSITY_RESTRICT shift, density_lion_dictionary *const DENSITY_RESTRICT dictionary, density_lion_form_data *const data, uint32_t *DENSITY_RESTRICT unit) {
+ density_lion_encode_generic(in, out, last_hash, signature_pointer, signature, shift, dictionary, DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_BIG, data, unit);
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_algorithm_exit_status density_lion_encode(density_algorithm_state *const DENSITY_RESTRICT state, const uint8_t **DENSITY_RESTRICT in, const uint_fast64_t in_size, uint8_t **DENSITY_RESTRICT out, const uint_fast64_t out_size) {
+ if (out_size < DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ density_lion_signature signature = 0;
+ density_lion_signature *signature_pointer = NULL;
+ uint_fast8_t shift = 0;
+ density_lion_form_data data;
+ density_lion_form_model_init(&data);
+ uint_fast16_t last_hash = 0;
+ uint32_t unit;
+
+ uint8_t *out_limit = *out + out_size - DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE;
+ uint_fast64_t limit_256 = (in_size >> 8);
+
+ while (DENSITY_LIKELY(limit_256-- && *out <= out_limit)) {
+ if (DENSITY_UNLIKELY(!(state->counter & 0xf))) {
+ DENSITY_ALGORITHM_REDUCE_COPY_PENALTY_START;
+ }
+ state->counter++;
+ if (DENSITY_UNLIKELY(state->copy_penalty)) {
+ DENSITY_ALGORITHM_COPY(DENSITY_LION_WORK_BLOCK_SIZE);
+ DENSITY_ALGORITHM_INCREASE_COPY_PENALTY_START;
+ } else {
+ const uint8_t *out_start = *out;
+ DENSITY_PREFETCH(*in + DENSITY_LION_WORK_BLOCK_SIZE);
+ density_lion_encode_256(in, out, &last_hash, &signature_pointer, &signature, &shift, (density_lion_dictionary *const) state->dictionary, &data, &unit);
+ DENSITY_ALGORITHM_TEST_INCOMPRESSIBILITY((*out - out_start), DENSITY_LION_WORK_BLOCK_SIZE);
+ }
+ }
+
+ if (*out > out_limit)
+ return DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL;
+
+ uint_fast64_t remaining;
+
+ switch (in_size & 0xff) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ density_lion_encode_push_code_to_signature(out, &signature_pointer, &signature, &shift, density_lion_form_model_get_encoding(&data, DENSITY_LION_FORM_PLAIN)); // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_lion_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_lion_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_lion_signature));
+#else
+#error
+#endif
+ goto process_remaining_bytes;
+ default:
+ break;
+ }
+
+ uint_fast64_t limit_4 = (in_size & 0xff) >> 2;
+ while (limit_4--)
+ density_lion_encode_4(in, out, &last_hash, &signature_pointer, &signature, &shift, (density_lion_dictionary *const) state->dictionary, &data, &unit);
+
+ density_lion_encode_push_code_to_signature(out, &signature_pointer, &signature, &shift, density_lion_form_model_get_encoding(&data, DENSITY_LION_FORM_PLAIN)); // End marker
+#ifdef DENSITY_LITTLE_ENDIAN
+ DENSITY_MEMCPY(signature_pointer, &signature, sizeof(density_lion_signature));
+#elif defined(DENSITY_BIG_ENDIAN)
+ const density_lion_signature endian_signature = DENSITY_LITTLE_ENDIAN_64(signature);
+ DENSITY_MEMCPY(signature_pointer, &endian_signature, sizeof(density_lion_signature));
+#else
+#error
+#endif
+
+ process_remaining_bytes:
+ remaining = in_size & 0x3;
+ if (remaining) {
+ DENSITY_MEMCPY(*out, *in, remaining);
+ *in += remaining;
+ *out += remaining;
+ }
+
+ return DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED;
+}
diff --git a/contrib/density/src/algorithms/lion/core/lion_encode.h b/contrib/density/src/algorithms/lion/core/lion_encode.h
new file mode 100644
index 00000000000..71cd2cad4cf
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/core/lion_encode.h
@@ -0,0 +1,54 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 24/06/15 18:56
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#ifndef DENSITY_LION_ENCODE_H
+#define DENSITY_LION_ENCODE_H
+
+#include "../dictionary/lion_dictionary.h"
+#include "../forms/lion_form_model.h"
+#include "../../algorithms.h"
+
+DENSITY_WINDOWS_EXPORT density_algorithm_exit_status density_lion_encode(density_algorithm_state *const DENSITY_RESTRICT_DECLARE, const uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t, uint8_t **DENSITY_RESTRICT_DECLARE, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/algorithms/lion/dictionary/lion_dictionary.h b/contrib/density/src/algorithms/lion/dictionary/lion_dictionary.h
new file mode 100644
index 00000000000..68f71da6373
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/dictionary/lion_dictionary.h
@@ -0,0 +1,73 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 12/02/15 23:09
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#ifndef DENSITY_LION_DICTIONARY_H
+#define DENSITY_LION_DICTIONARY_H
+
+#include "../lion.h"
+
+#pragma pack(push)
+#pragma pack(4)
+
+typedef struct {
+ uint32_t chunk_a;
+ uint32_t chunk_b;
+ uint32_t chunk_c;
+ uint32_t chunk_d;
+ uint32_t chunk_e;
+} density_lion_dictionary_chunk_entry;
+
+typedef struct {
+ uint32_t next_chunk_a;
+ uint32_t next_chunk_b;
+ uint32_t next_chunk_c;
+} density_lion_dictionary_chunk_prediction_entry;
+
+typedef struct {
+ density_lion_dictionary_chunk_entry chunks[1 << DENSITY_LION_CHUNK_HASH_BITS];
+ density_lion_dictionary_chunk_prediction_entry predictions[1 << DENSITY_LION_CHUNK_HASH_BITS];
+} density_lion_dictionary;
+#pragma pack(pop)
+
+#endif
diff --git a/contrib/density/src/algorithms/lion/forms/lion_form_model.c b/contrib/density/src/algorithms/lion/forms/lion_form_model.c
new file mode 100644
index 00000000000..21dfc23e3c9
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/forms/lion_form_model.c
@@ -0,0 +1,153 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 9/03/15 11:19
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#include "lion_form_model.h"
+
+const density_lion_entropy_code density_lion_form_entropy_codes[DENSITY_LION_NUMBER_OF_FORMS] = DENSITY_LION_FORM_MODEL_ENTROPY_CODES;
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_lion_form_model_init(density_lion_form_data *const data) {
+ density_lion_form_node *rank_0 = &data->formsPool[0];
+ rank_0->form = DENSITY_LION_FORM_PLAIN;
+ rank_0->rank = 0;
+ rank_0->previousForm = NULL;
+ data->formsIndex[DENSITY_LION_FORM_PLAIN] = rank_0;
+
+ density_lion_form_node *rank_1 = &data->formsPool[1];
+ rank_1->form = DENSITY_LION_FORM_DICTIONARY_A;
+ rank_1->rank = 1;
+ rank_1->previousForm = rank_0;
+ data->formsIndex[DENSITY_LION_FORM_DICTIONARY_A] = rank_1;
+
+ density_lion_form_node *rank_2 = &data->formsPool[2];
+ rank_2->form = DENSITY_LION_FORM_DICTIONARY_B;
+ rank_2->rank = 2;
+ rank_2->previousForm = rank_1;
+ data->formsIndex[DENSITY_LION_FORM_DICTIONARY_B] = rank_2;
+
+ density_lion_form_node *rank_3 = &data->formsPool[3];
+ rank_3->form = DENSITY_LION_FORM_PREDICTIONS_A;
+ rank_3->rank = 3;
+ rank_3->previousForm = rank_2;
+ data->formsIndex[DENSITY_LION_FORM_PREDICTIONS_A] = rank_3;
+
+ density_lion_form_node *rank_4 = &data->formsPool[4];
+ rank_4->form = DENSITY_LION_FORM_PREDICTIONS_B;
+ rank_4->rank = 4;
+ rank_4->previousForm = rank_3;
+ data->formsIndex[DENSITY_LION_FORM_PREDICTIONS_B] = rank_4;
+
+ density_lion_form_node *rank_5 = &data->formsPool[5];
+ rank_5->form = DENSITY_LION_FORM_DICTIONARY_C;
+ rank_5->rank = 5;
+ rank_5->previousForm = rank_4;
+ data->formsIndex[DENSITY_LION_FORM_DICTIONARY_C] = rank_5;
+
+ density_lion_form_node *rank_6 = &data->formsPool[6];
+ rank_6->form = DENSITY_LION_FORM_PREDICTIONS_C;
+ rank_6->rank = 6;
+ rank_6->previousForm = rank_5;
+ data->formsIndex[DENSITY_LION_FORM_PREDICTIONS_C] = rank_6;
+
+ density_lion_form_node *rank_7 = &data->formsPool[7];
+ rank_7->form = DENSITY_LION_FORM_DICTIONARY_D;
+ rank_7->rank = 7;
+ rank_7->previousForm = rank_6;
+ data->formsIndex[DENSITY_LION_FORM_DICTIONARY_D] = rank_7;
+
+ data->usages.usages_as_uint64_t = 0;
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_lion_form_model_attach(density_lion_form_data *const data, void (*attachments[DENSITY_LION_NUMBER_OF_FORMS])(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const)) {
+ for(uint_fast8_t count = 0; count < DENSITY_LION_NUMBER_OF_FORMS; count ++)
+ data->attachments[count] = attachments[count];
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_lion_form_model_update(density_lion_form_data *const DENSITY_RESTRICT data, density_lion_form_node *const DENSITY_RESTRICT form, const uint8_t usage, density_lion_form_node *const DENSITY_RESTRICT previous_form, const uint8_t previous_usage) {
+ if (DENSITY_UNLIKELY(previous_usage < usage)) { // Relative stability is assumed
+ const DENSITY_LION_FORM form_value = form->form;
+ const DENSITY_LION_FORM previous_form_value = previous_form->form;
+
+ previous_form->form = form_value;
+ form->form = previous_form_value;
+
+ data->formsIndex[form_value] = previous_form;
+ data->formsIndex[previous_form_value] = form;
+ }
+}
+
+DENSITY_FORCE_INLINE void density_lion_form_model_flatten(density_lion_form_data *const data, const uint8_t usage) {
+ if (DENSITY_UNLIKELY(usage & 0x80))
+ data->usages.usages_as_uint64_t = (data->usages.usages_as_uint64_t >> 1) & 0x7f7f7f7f7f7f7f7fllu; // Flatten usage values
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE DENSITY_LION_FORM density_lion_form_model_increment_usage(density_lion_form_data *const data, density_lion_form_node *const DENSITY_RESTRICT form) {
+ const DENSITY_LION_FORM form_value = form->form;
+ const uint8_t usage = ++data->usages.usages_as_uint8_t[form_value];
+
+ density_lion_form_node *const previous_form = form->previousForm;
+
+ if (previous_form)
+ density_lion_form_model_update(data, form, usage, previous_form, data->usages.usages_as_uint8_t[previous_form->form]);
+ else
+ density_lion_form_model_flatten(data, usage);
+
+ return form_value;
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE density_lion_entropy_code density_lion_form_model_get_encoding(density_lion_form_data *const data, const DENSITY_LION_FORM form) {
+ const uint8_t usage = ++data->usages.usages_as_uint8_t[form];
+
+ density_lion_form_node *const form_found = data->formsIndex[form];
+ density_lion_form_node *const previous_form = form_found->previousForm;
+
+ if (previous_form) {
+ density_lion_form_model_update(data, form_found, usage, previous_form, data->usages.usages_as_uint8_t[previous_form->form]);
+
+ return density_lion_form_entropy_codes[form_found->rank];
+ } else {
+ density_lion_form_model_flatten(data, usage);
+
+ return density_lion_form_entropy_codes[0];
+ }
+}
diff --git a/contrib/density/src/algorithms/lion/forms/lion_form_model.h b/contrib/density/src/algorithms/lion/forms/lion_form_model.h
new file mode 100644
index 00000000000..90164d94c78
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/forms/lion_form_model.h
@@ -0,0 +1,96 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 9/03/15 12:04
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#ifndef DENSITY_LION_FORM_MODEL_H
+#define DENSITY_LION_FORM_MODEL_H
+
+#include "../../../globals.h"
+#include "../lion.h"
+
+#define DENSITY_LION_NUMBER_OF_FORMS 8
+
+// Unary codes (reversed) except the last one
+#define DENSITY_LION_FORM_MODEL_ENTROPY_CODES {\
+ {DENSITY_BINARY_TO_UINT(1), 1},\
+ {DENSITY_BINARY_TO_UINT(10), 2},\
+ {DENSITY_BINARY_TO_UINT(100), 3},\
+ {DENSITY_BINARY_TO_UINT(1000), 4},\
+ {DENSITY_BINARY_TO_UINT(10000), 5},\
+ {DENSITY_BINARY_TO_UINT(100000), 6},\
+ {DENSITY_BINARY_TO_UINT(1000000), 7},\
+ {DENSITY_BINARY_TO_UINT(0000000), 7},\
+}
+
+#pragma pack(push)
+#pragma pack(4)
+typedef struct {
+ void* previousForm;
+ DENSITY_LION_FORM form;
+ uint8_t rank;
+} density_lion_form_node;
+
+typedef struct {
+ union {
+ uint8_t usages_as_uint8_t[DENSITY_LION_NUMBER_OF_FORMS];
+ uint64_t usages_as_uint64_t;
+ } usages;
+
+ void (*attachments[DENSITY_LION_NUMBER_OF_FORMS])(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const);
+ density_lion_form_node formsPool[DENSITY_LION_NUMBER_OF_FORMS];
+ density_lion_form_node *formsIndex[DENSITY_LION_NUMBER_OF_FORMS];
+ uint8_t nextAvailableForm;
+} density_lion_form_data;
+#pragma pack(pop)
+
+DENSITY_WINDOWS_EXPORT void density_lion_form_model_init(density_lion_form_data *const);
+
+DENSITY_WINDOWS_EXPORT void density_lion_form_model_attach(density_lion_form_data *const, void (*[DENSITY_LION_NUMBER_OF_FORMS])(const uint8_t **, uint8_t **, uint_fast16_t *, void *const, uint16_t *const, uint32_t *const));
+
+DENSITY_WINDOWS_EXPORT void density_lion_form_model_update(density_lion_form_data *const DENSITY_RESTRICT_DECLARE, density_lion_form_node *const DENSITY_RESTRICT_DECLARE, const uint8_t, density_lion_form_node *const DENSITY_RESTRICT_DECLARE, const uint8_t);
+
+DENSITY_WINDOWS_EXPORT DENSITY_LION_FORM density_lion_form_model_increment_usage(density_lion_form_data *const, density_lion_form_node *const DENSITY_RESTRICT_DECLARE);
+
+DENSITY_WINDOWS_EXPORT density_lion_entropy_code density_lion_form_model_get_encoding(density_lion_form_data *const, const DENSITY_LION_FORM);
+
+#endif
diff --git a/contrib/density/src/algorithms/lion/lion.h b/contrib/density/src/algorithms/lion/lion.h
new file mode 100644
index 00000000000..30b40f8d92b
--- /dev/null
+++ b/contrib/density/src/algorithms/lion/lion.h
@@ -0,0 +1,94 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 5/02/15 20:57
+ *
+ * --------------
+ * Lion algorithm
+ * --------------
+ *
+ * Author(s)
+ * Guillaume Voirin (https://github.com/gpnuma)
+ *
+ * Description
+ * Multiform compression algorithm
+ */
+
+#ifndef DENSITY_LION_H
+#define DENSITY_LION_H
+
+#include "../../globals.h"
+
+#define DENSITY_LION_HASH32_MULTIPLIER (uint32_t)0x9D6EF916lu
+#define DENSITY_LION_CHUNK_HASH_BITS 16
+
+#define DENSITY_LION_HASH_ALGORITHM(value32) (uint16_t)(value32 * DENSITY_LION_HASH32_MULTIPLIER >> (32 - DENSITY_LION_CHUNK_HASH_BITS))
+
+typedef enum {
+ DENSITY_LION_FORM_PREDICTIONS_A = 0,
+ DENSITY_LION_FORM_PREDICTIONS_B,
+ DENSITY_LION_FORM_PREDICTIONS_C,
+ DENSITY_LION_FORM_DICTIONARY_A,
+ DENSITY_LION_FORM_DICTIONARY_B,
+ DENSITY_LION_FORM_DICTIONARY_C,
+ DENSITY_LION_FORM_DICTIONARY_D,
+ DENSITY_LION_FORM_PLAIN,
+} DENSITY_LION_FORM;
+
+typedef enum {
+ DENSITY_LION_PREDICTIONS_SIGNATURE_FLAG_A = 0x0,
+ DENSITY_LION_PREDICTIONS_SIGNATURE_FLAG_B = 0x1,
+} DENSITY_LION_PREDICTIONS_SIGNATURE_FLAG;
+
+#pragma pack(push)
+#pragma pack(4)
+typedef struct {
+ uint_fast8_t value;
+ uint_fast8_t bitLength;
+} density_lion_entropy_code;
+#pragma pack(pop)
+
+typedef uint64_t density_lion_signature;
+
+#define DENSITY_LION_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE (density_bitsizeof(density_lion_signature) * sizeof(uint32_t)) // Plain writes
+#define DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE (sizeof(density_lion_signature) + DENSITY_LION_MAXIMUM_COMPRESSED_BODY_SIZE_PER_SIGNATURE)
+
+#define DENSITY_LION_MAXIMUM_DECOMPRESSED_UNIT_SIZE (density_bitsizeof(density_lion_signature) * sizeof(uint32_t)) // Smallest form size times work unit size
+
+#define DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_SMALL 8
+#define DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_BIG 64
+#define DENSITY_LION_PROCESS_UNIT_SIZE_SMALL (DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_SMALL * sizeof(uint32_t))
+#define DENSITY_LION_PROCESS_UNIT_SIZE_BIG (DENSITY_LION_CHUNKS_PER_PROCESS_UNIT_BIG * sizeof(uint32_t))
+
+#define DENSITY_LION_WORK_BLOCK_SIZE 256
+#define DENSITY_LION_COPY_PENALTY 2
+
+#endif
diff --git a/contrib/density/src/buffers/buffer.c b/contrib/density/src/buffers/buffer.c
new file mode 100644
index 00000000000..d3e9943c599
--- /dev/null
+++ b/contrib/density/src/buffers/buffer.c
@@ -0,0 +1,220 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 3/02/15 19:53
+ */
+
+#include "buffer.h"
+
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_compress_safe_size(const uint_fast64_t input_size) {
+ const uint_fast64_t slack = DENSITY_MAX_3(DENSITY_CHAMELEON_MAXIMUM_COMPRESSED_UNIT_SIZE, DENSITY_CHEETAH_MAXIMUM_COMPRESSED_UNIT_SIZE, DENSITY_LION_MAXIMUM_COMPRESSED_UNIT_SIZE);
+
+ // Chameleon longest output
+ uint_fast64_t chameleon_longest_output_size = 0;
+ chameleon_longest_output_size += sizeof(density_header);
+ chameleon_longest_output_size += sizeof(density_chameleon_signature) * (1 + (input_size >> (5 + 3))); // Signature space (1 bit <=> 4 bytes)
+ chameleon_longest_output_size += sizeof(density_chameleon_signature); // Eventual supplementary signature for end marker
+ chameleon_longest_output_size += input_size; // Everything encoded as plain data
+
+ // Cheetah longest output
+ uint_fast64_t cheetah_longest_output_size = 0;
+ cheetah_longest_output_size += sizeof(density_header);
+ cheetah_longest_output_size += sizeof(density_cheetah_signature) * (1 + (input_size >> (4 + 3))); // Signature space (2 bits <=> 4 bytes)
+ cheetah_longest_output_size += sizeof(density_cheetah_signature); // Eventual supplementary signature for end marker
+ cheetah_longest_output_size += input_size; // Everything encoded as plain data
+
+ // Lion longest output
+ uint_fast64_t lion_longest_output_size = 0;
+ lion_longest_output_size += sizeof(density_header);
+ lion_longest_output_size += sizeof(density_lion_signature) * (1 + ((input_size * 7) >> (5 + 3))); // Signature space (7 bits <=> 4 bytes), although this size is technically impossible
+ lion_longest_output_size += sizeof(density_lion_signature); // Eventual supplementary signature for end marker
+ lion_longest_output_size += input_size; // Everything encoded as plain data
+
+ return DENSITY_MAX_3(chameleon_longest_output_size, cheetah_longest_output_size, lion_longest_output_size) + slack;
+}
+
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_decompress_safe_size(const uint_fast64_t expected_decompressed_output_size) {
+ const uint_fast64_t slack = DENSITY_MAX_3(DENSITY_CHAMELEON_DECOMPRESSED_UNIT_SIZE, DENSITY_CHEETAH_DECOMPRESSED_UNIT_SIZE, DENSITY_LION_MAXIMUM_DECOMPRESSED_UNIT_SIZE);
+
+ return expected_decompressed_output_size + slack;
+}
+
+DENSITY_FORCE_INLINE DENSITY_STATE density_convert_algorithm_exit_status(const density_algorithm_exit_status status) {
+ switch (status) {
+ case DENSITY_ALGORITHMS_EXIT_STATUS_FINISHED:
+ return DENSITY_STATE_OK;
+ case DENSITY_ALGORITHMS_EXIT_STATUS_INPUT_STALL:
+ return DENSITY_STATE_ERROR_INPUT_BUFFER_TOO_SMALL;
+ case DENSITY_ALGORITHMS_EXIT_STATUS_OUTPUT_STALL:
+ return DENSITY_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL;
+ default:
+ return DENSITY_STATE_ERROR_DURING_PROCESSING;
+ }
+}
+
+DENSITY_FORCE_INLINE density_processing_result density_make_result(const DENSITY_STATE state, const uint_fast64_t read, const uint_fast64_t written, density_context *const context) {
+ density_processing_result result;
+ result.state = state;
+ result.bytesRead = read;
+ result.bytesWritten = written;
+ result.context = context;
+ return result;
+}
+
+DENSITY_FORCE_INLINE density_context* density_allocate_context(const DENSITY_ALGORITHM algorithm, const bool custom_dictionary, void *(*mem_alloc)(size_t)) {
+ density_context* context = mem_alloc(sizeof(density_context));
+ context->algorithm = algorithm;
+ context->dictionary_size = density_get_dictionary_size(context->algorithm);
+ context->dictionary_type = custom_dictionary;
+ if(!context->dictionary_type) {
+ context->dictionary = mem_alloc(context->dictionary_size);
+ DENSITY_MEMSET(context->dictionary, 0, context->dictionary_size);
+ }
+ return context;
+}
+
+DENSITY_WINDOWS_EXPORT void density_free_context(density_context *const context, void (*mem_free)(void *)) {
+ if(mem_free == NULL)
+ mem_free = free;
+ if(!context->dictionary_type)
+ mem_free(context->dictionary);
+ mem_free(context);
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_prepare_context(const DENSITY_ALGORITHM algorithm, const bool custom_dictionary, void *(*mem_alloc)(size_t)) {
+ if(mem_alloc == NULL)
+ mem_alloc = malloc;
+
+ return density_make_result(DENSITY_STATE_OK, 0, 0, density_allocate_context(algorithm, custom_dictionary, mem_alloc));
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_with_context(const uint8_t * input_buffer, const uint_fast64_t input_size, uint8_t * output_buffer, const uint_fast64_t output_size, density_context *const context) {
+ if (output_size < sizeof(density_header))
+ return density_make_result(DENSITY_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL, 0, 0, context);
+ if(context == NULL)
+ return density_make_result(DENSITY_STATE_ERROR_INVALID_CONTEXT, 0, 0, context);
+
+ // Variables setup
+ const uint8_t *in = input_buffer;
+ uint8_t *out = output_buffer;
+ density_algorithm_state state;
+ density_algorithm_exit_status status = DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING;
+
+ // Header
+ density_header_write(&out, context->algorithm);
+
+ // Compression
+ density_algorithms_prepare_state(&state, context->dictionary);
+ switch (context->algorithm) {
+ case DENSITY_ALGORITHM_CHAMELEON:
+ status = density_chameleon_encode(&state, &in, input_size, &out, output_size);
+ break;
+ case DENSITY_ALGORITHM_CHEETAH:
+ status = density_cheetah_encode(&state, &in, input_size, &out, output_size);
+ break;
+ case DENSITY_ALGORITHM_LION:
+ status = density_lion_encode(&state, &in, input_size, &out, output_size);
+ break;
+ }
+
+ // Result
+ return density_make_result(density_convert_algorithm_exit_status(status), in - input_buffer, out - output_buffer, context);
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_prepare_context(const uint8_t *input_buffer, const uint_fast64_t input_size, const bool custom_dictionary, void *(*mem_alloc)(size_t)) {
+ if (input_size < sizeof(density_header))
+ return density_make_result(DENSITY_STATE_ERROR_INPUT_BUFFER_TOO_SMALL, 0, 0, NULL);
+
+ // Variables setup
+ const uint8_t* in = input_buffer;
+ if(mem_alloc == NULL)
+ mem_alloc = malloc;
+
+ // Read header
+ density_header main_header;
+ density_header_read(&in, &main_header);
+
+ // Setup context
+ density_context *const context = density_allocate_context(main_header.algorithm, custom_dictionary, mem_alloc);
+ return density_make_result(DENSITY_STATE_OK, in - input_buffer, 0, context);
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_with_context(const uint8_t * input_buffer, const uint_fast64_t input_size, uint8_t * output_buffer, const uint_fast64_t output_size, density_context *const context) {
+ if(context == NULL)
+ return density_make_result(DENSITY_STATE_ERROR_INVALID_CONTEXT, 0, 0, context);
+
+ // Variables setup
+ const uint8_t *in = input_buffer;
+ uint8_t *out = output_buffer;
+ density_algorithm_state state;
+ density_algorithm_exit_status status = DENSITY_ALGORITHMS_EXIT_STATUS_ERROR_DURING_PROCESSING;
+
+ // Decompression
+ density_algorithms_prepare_state(&state, context->dictionary);
+ switch (context->algorithm) {
+ case DENSITY_ALGORITHM_CHAMELEON:
+ status = density_chameleon_decode(&state, &in, input_size, &out, output_size);
+ break;
+ case DENSITY_ALGORITHM_CHEETAH:
+ status = density_cheetah_decode(&state, &in, input_size, &out, output_size);
+ break;
+ case DENSITY_ALGORITHM_LION:
+ status = density_lion_decode(&state, &in, input_size, &out, output_size);
+ break;
+ }
+
+ // Result
+ return density_make_result(density_convert_algorithm_exit_status(status), in - input_buffer, out - output_buffer, context);
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress(const uint8_t *input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size, const DENSITY_ALGORITHM algorithm) {
+ density_processing_result result = density_compress_prepare_context(algorithm, false, malloc);
+ if(result.state) {
+ density_free_context(result.context, free);
+ return result;
+ }
+
+ result = density_compress_with_context(input_buffer, input_size, output_buffer, output_size, result.context);
+ density_free_context(result.context, free);
+ return result;
+}
+
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress(const uint8_t *input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size) {
+ density_processing_result result = density_decompress_prepare_context(input_buffer, input_size, false, malloc);
+ if(result.state) {
+ density_free_context(result.context, free);
+ return result;
+ }
+
+ result = density_decompress_with_context(input_buffer + result.bytesRead, input_size - result.bytesRead, output_buffer, output_size, result.context);
+ density_free_context(result.context, free);
+ return result;
+}
diff --git a/contrib/density/src/buffers/buffer.h b/contrib/density/src/buffers/buffer.h
new file mode 100644
index 00000000000..f34ab5458d2
--- /dev/null
+++ b/contrib/density/src/buffers/buffer.h
@@ -0,0 +1,58 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2015, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 3/02/15 19:51
+ */
+
+#ifndef DENSITY_BUFFER_H
+#define DENSITY_BUFFER_H
+
+#include "../globals.h"
+#include "../density_api.h"
+#include "../structure/header.h"
+#include "../algorithms/chameleon/core/chameleon_encode.h"
+#include "../algorithms/chameleon/core/chameleon_decode.h"
+#include "../algorithms/cheetah/core/cheetah_encode.h"
+#include "../algorithms/cheetah/core/cheetah_decode.h"
+#include "../algorithms/lion/core/lion_encode.h"
+#include "../algorithms/lion/core/lion_decode.h"
+
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_compress_safe_size(const uint_fast64_t);
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_decompress_safe_size(const uint_fast64_t);
+DENSITY_WINDOWS_EXPORT void density_free_context(density_context *const, void (*)(void *));
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_prepare_context(const DENSITY_ALGORITHM, const bool, void *(*)(size_t));
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_with_context(const uint8_t *, const uint_fast64_t, uint8_t *, const uint_fast64_t, density_context *const);
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress(const uint8_t *, const uint_fast64_t, uint8_t *, const uint_fast64_t, const DENSITY_ALGORITHM);
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_prepare_context(const uint8_t *, const uint_fast64_t, const bool, void *(*)(size_t));
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_with_context(const uint8_t *, const uint_fast64_t, uint8_t *, const uint_fast64_t, density_context *const);
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress(const uint8_t *, const uint_fast64_t, uint8_t *, const uint_fast64_t);
+
+#endif
diff --git a/contrib/density/src/density_api.h b/contrib/density/src/density_api.h
new file mode 100644
index 00000000000..385e24e609a
--- /dev/null
+++ b/contrib/density/src/density_api.h
@@ -0,0 +1,220 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 18/10/13 22:41
+ */
+
+#ifndef DENSITY_API_H
+#define DENSITY_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include
+#include
+#include
+
+#if defined(_WIN64) || defined(_WIN32)
+#define DENSITY_WINDOWS_EXPORT __declspec(dllexport)
+#else
+#define DENSITY_WINDOWS_EXPORT
+#endif
+
+
+/***********************************************************************************************************************
+ * *
+ * API data structures *
+ * *
+ ***********************************************************************************************************************/
+
+typedef uint8_t density_byte;
+typedef bool density_bool;
+
+typedef enum {
+ DENSITY_ALGORITHM_CHAMELEON = 1,
+ DENSITY_ALGORITHM_CHEETAH = 2,
+ DENSITY_ALGORITHM_LION = 3,
+} DENSITY_ALGORITHM;
+
+typedef enum {
+ DENSITY_STATE_OK = 0, // Everything went alright
+ DENSITY_STATE_ERROR_INPUT_BUFFER_TOO_SMALL, // Input buffer size is too small
+ DENSITY_STATE_ERROR_OUTPUT_BUFFER_TOO_SMALL, // Output buffer size is too small
+ DENSITY_STATE_ERROR_DURING_PROCESSING, // Error during processing
+ DENSITY_STATE_ERROR_INVALID_CONTEXT, // Invalid context
+ DENSITY_STATE_ERROR_INVALID_ALGORITHM, // Invalid algorithm
+} DENSITY_STATE;
+
+typedef struct {
+ DENSITY_ALGORITHM algorithm;
+ bool dictionary_type;
+ size_t dictionary_size;
+ void* dictionary;
+} density_context;
+
+typedef struct {
+ DENSITY_STATE state;
+ uint_fast64_t bytesRead;
+ uint_fast64_t bytesWritten;
+ density_context* context;
+} density_processing_result;
+
+
+
+/***********************************************************************************************************************
+ * *
+ * Density version information *
+ * *
+ ***********************************************************************************************************************/
+
+/*
+ * Returns the major density version
+ */
+DENSITY_WINDOWS_EXPORT uint8_t density_version_major(void);
+
+/*
+ * Returns the minor density version
+ */
+DENSITY_WINDOWS_EXPORT uint8_t density_version_minor(void);
+
+/*
+ * Returns the density revision
+ */
+DENSITY_WINDOWS_EXPORT uint8_t density_version_revision(void);
+
+
+
+/***********************************************************************************************************************
+ * *
+ * Density API functions *
+ * *
+ ***********************************************************************************************************************/
+
+/*
+ * Return the required size of an algorithm's dictionary
+ *
+ * @param algorithm the algorithm to use this dictionary for
+ */
+DENSITY_WINDOWS_EXPORT size_t density_get_dictionary_size(DENSITY_ALGORITHM algorithm);
+
+/*
+ * Return an output buffer byte size which guarantees enough space for encoding input_size bytes
+ *
+ * @param input_size the size of the input data which is about to be compressed
+ */
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_compress_safe_size(const uint_fast64_t input_size);
+
+/*
+ * Return an output buffer byte size which, if expected_decompressed_output_size is correct, will enable density to decompress properly
+ *
+ * @param expected_decompressed_output_size the expected (original) size of the decompressed data
+ */
+DENSITY_WINDOWS_EXPORT uint_fast64_t density_decompress_safe_size(const uint_fast64_t expected_decompressed_output_size);
+
+/*
+ * Releases a context from memory.
+ *
+ * @param context the context to free
+ * @param mem_free the memory freeing function. If set to NULL, free() is used
+ */
+DENSITY_WINDOWS_EXPORT void density_free_context(density_context *const context, void (*mem_free)(void *));
+
+/*
+ * Allocate a context in memory using the provided function and optional dictionary
+ *
+ * @param algorithm the required algorithm
+ * @param custom_dictionary use an eventual custom dictionary ? If set to true the context's dictionary will have to be allocated
+ * @param mem_alloc the memory allocation function. If set to NULL, malloc() is used
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_prepare_context(const DENSITY_ALGORITHM algorithm, const bool custom_dictionary, void *(*mem_alloc)(size_t));
+
+/*
+ * Compress an input_buffer of input_size bytes and store the result in output_buffer, using the provided context.
+ * Important note * this function could be unsafe memory-wise if not used properly.
+ *
+ * @param input_buffer a buffer of bytes
+ * @param input_size the size in bytes of input_buffer
+ * @param output_buffer a buffer of bytes
+ * @param output_size the size of output_buffer, must be at least DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE
+ * @param context a pointer to a context structure
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress_with_context(const uint8_t *input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size, density_context *const context);
+
+/*
+ * Compress an input_buffer of input_size bytes and store the result in output_buffer.
+ *
+ * @param input_buffer a buffer of bytes
+ * @param input_size the size in bytes of input_buffer
+ * @param output_buffer a buffer of bytes
+ * @param output_size the size of output_buffer, must be at least DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE
+ * @param algorithm the algorithm to use
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_compress(const uint8_t *input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size, const DENSITY_ALGORITHM algorithm);
+
+/*
+ * Reads the compressed data's header and creates an adequate decompression context.
+ *
+ * @param input_buffer a buffer of bytes
+ * @param input_size the size in bytes of input_buffer
+ * @param custom_dictionary use a custom dictionary ? If set to true the context's dictionary will have to be allocated
+ * @param mem_alloc the memory allocation function. If set to NULL, malloc() is used
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_prepare_context(const uint8_t *input_buffer, const uint_fast64_t input_size, const bool custom_dictionary, void *(*mem_alloc)(size_t));
+
+/*
+ * Decompress an input_buffer of input_size bytes and store the result in output_buffer, using the provided dictionary.
+ * Important notes * You must know in advance the algorithm used for compression to provide the proper dictionary.
+ * * This function could be unsafe memory-wise if not used properly.
+ *
+ * @param input_buffer a buffer of bytes
+ * @param input_size the size in bytes of input_buffer
+ * @param output_buffer a buffer of bytes
+ * @param output_size the size of output_buffer, must be at least DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE
+ * @param dictionaries a pointer to a dictionary
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress_with_context(const uint8_t * input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size, density_context *const context);
+
+/*
+ * Decompress an input_buffer of input_size bytes and store the result in output_buffer.
+ *
+ * @param input_buffer a buffer of bytes
+ * @param input_size the size in bytes of input_buffer
+ * @param output_buffer a buffer of bytes
+ * @param output_size the size of output_buffer, must be at least DENSITY_MINIMUM_OUTPUT_BUFFER_SIZE
+ */
+DENSITY_WINDOWS_EXPORT density_processing_result density_decompress(const uint8_t *input_buffer, const uint_fast64_t input_size, uint8_t *output_buffer, const uint_fast64_t output_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/contrib/density/src/globals.c b/contrib/density/src/globals.c
new file mode 100644
index 00000000000..4c58cd6f067
--- /dev/null
+++ b/contrib/density/src/globals.c
@@ -0,0 +1,47 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 01/11/13 13:39
+ */
+
+#include "globals.h"
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_major() {
+ return DENSITY_MAJOR_VERSION;
+}
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_minor() {
+ return DENSITY_MINOR_VERSION;
+}
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_revision() {
+ return DENSITY_REVISION;
+}
diff --git a/contrib/density/src/globals.h b/contrib/density/src/globals.h
new file mode 100644
index 00000000000..eb44a52a673
--- /dev/null
+++ b/contrib/density/src/globals.h
@@ -0,0 +1,232 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 11/10/13 02:01
+ */
+
+#ifndef DENSITY_GLOBALS_H
+#define DENSITY_GLOBALS_H
+
+#include
+#include
+#include
+#include
+
+#include "density_api.h"
+
+#if defined(__clang__) || defined(__GNUC__)
+#define DENSITY_FORCE_INLINE inline __attribute__((always_inline))
+#define DENSITY_RESTRICT restrict
+#define DENSITY_RESTRICT_DECLARE
+#define DENSITY_MEMCPY __builtin_memcpy
+#define DENSITY_MEMMOVE __builtin_memmove
+#define DENSITY_MEMSET __builtin_memset
+#define DENSITY_LIKELY(x) __builtin_expect(!!(x), 1)
+#define DENSITY_UNLIKELY(x) __builtin_expect(!!(x), 0)
+#define DENSITY_PREFETCH(x) __builtin_prefetch(x)
+#define DENSITY_CTZ(x) __builtin_ctz(x)
+
+#if defined(__BYTE_ORDER__)
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define DENSITY_LITTLE_ENDIAN
+#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+#define DENSITY_BIG_ENDIAN
+#else
+#error Unsupported endianness
+#endif
+#else
+#error Unkwnown endianness
+#endif
+
+#elif defined(_MSC_VER)
+#include
+#include
+
+#define DENSITY_FORCE_INLINE __forceinline
+#define DENSITY_RESTRICT __restrict
+#define DENSITY_RESTRICT_DECLARE __restrict
+#define DENSITY_MEMCPY memcpy
+#define DENSITY_MEMMOVE memmove
+#define DENSITY_MEMSET memset
+#define DENSITY_LIKELY(x) (x)
+#define DENSITY_UNLIKELY(x) (x)
+#define DENSITY_PREFETCH(x) ((void)(x))
+
+DENSITY_FORCE_INLINE uint_fast8_t density_msvc_ctz(uint64_t value) {
+ unsigned long trailing_zero = 0;
+ if (_BitScanForward(&trailing_zero, (unsigned long)value))
+ return (uint_fast8_t)trailing_zero;
+ else
+ return 0;
+}
+#define DENSITY_CTZ(x) density_msvc_ctz(x)
+
+#define DENSITY_LITTLE_ENDIAN // Little endian by default on Windows
+
+#else
+#error Unsupported compiler
+#endif
+
+#ifdef DENSITY_LITTLE_ENDIAN
+#define DENSITY_LITTLE_ENDIAN_64(b) ((uint64_t)b)
+#define DENSITY_LITTLE_ENDIAN_32(b) ((uint32_t)b)
+#define DENSITY_LITTLE_ENDIAN_16(b) ((uint16_t)b)
+#elif defined(DENSITY_BIG_ENDIAN)
+#if __GNUC__ * 100 + __GNUC_MINOR__ >= 403
+#define DENSITY_LITTLE_ENDIAN_64(b) __builtin_bswap64(b)
+#define DENSITY_LITTLE_ENDIAN_32(b) __builtin_bswap32(b)
+#define DENSITY_LITTLE_ENDIAN_16(b) __builtin_bswap16(b)
+#else
+#warning Using bulk byte swap routines. Expect performance issues.
+#define DENSITY_LITTLE_ENDIAN_64(b) ((((b) & 0xFF00000000000000ull) >> 56) | (((b) & 0x00FF000000000000ull) >> 40) | (((b) & 0x0000FF0000000000ull) >> 24) | (((b) & 0x000000FF00000000ull) >> 8) | (((b) & 0x00000000FF000000ull) << 8) | (((b) & 0x0000000000FF0000ull) << 24ull) | (((b) & 0x000000000000FF00ull) << 40) | (((b) & 0x00000000000000FFull) << 56))
+#define DENSITY_LITTLE_ENDIAN_32(b) ((((b) & 0xFF000000) >> 24) | (((b) & 0x00FF0000) >> 8) | (((b) & 0x0000FF00) << 8) | (((b) & 0x000000FF) << 24))
+#define DENSITY_LITTLE_ENDIAN_16(b) ((((b) & 0xFF00) >> 8) | (((b) & 0x00FF) << 8))
+#endif
+#else
+#error Unsupported endianness
+#endif
+
+#define DENSITY_MAX_2(a, b) (((a)>(b))?(a):(b))
+#define DENSITY_MAX_3(a, b, c) (DENSITY_MAX_2(DENSITY_MAX_2(a, b), c))
+
+#define DENSITY_FORMAT(v) 0##v##llu
+
+#define DENSITY_ISOLATE(b, p) ((DENSITY_FORMAT(b) / p) & 0x1)
+
+#define DENSITY_BINARY_TO_UINT(b) ((DENSITY_ISOLATE(b, 1llu) ? 0x1 : 0)\
+ + (DENSITY_ISOLATE(b, 8llu) ? 0x2 : 0)\
+ + (DENSITY_ISOLATE(b, 64llu) ? 0x4 : 0)\
+ + (DENSITY_ISOLATE(b, 512llu) ? 0x8 : 0)\
+ + (DENSITY_ISOLATE(b, 4096llu) ? 0x10 : 0)\
+ + (DENSITY_ISOLATE(b, 32768llu) ? 0x20 : 0)\
+ + (DENSITY_ISOLATE(b, 262144llu) ? 0x40 : 0)\
+ + (DENSITY_ISOLATE(b, 2097152llu) ? 0x80 : 0)\
+ + (DENSITY_ISOLATE(b, 16777216llu) ? 0x100 : 0)\
+ + (DENSITY_ISOLATE(b, 134217728llu) ? 0x200 : 0)\
+ + (DENSITY_ISOLATE(b, 1073741824llu) ? 0x400 : 0)\
+ + (DENSITY_ISOLATE(b, 8589934592llu) ? 0x800 : 0)\
+ + (DENSITY_ISOLATE(b, 68719476736llu) ? 0x1000 : 0)\
+ + (DENSITY_ISOLATE(b, 549755813888llu) ? 0x2000 : 0)\
+ + (DENSITY_ISOLATE(b, 4398046511104llu) ? 0x4000 : 0)\
+ + (DENSITY_ISOLATE(b, 35184372088832llu) ? 0x8000 : 0)\
+ + (DENSITY_ISOLATE(b, 281474976710656llu) ? 0x10000 : 0)\
+ + (DENSITY_ISOLATE(b, 2251799813685248llu) ? 0x20000 : 0))
+
+#define DENSITY_UNROLL_2(op) op; op
+#define DENSITY_UNROLL_4(op) DENSITY_UNROLL_2(op); DENSITY_UNROLL_2(op)
+#define DENSITY_UNROLL_8(op) DENSITY_UNROLL_4(op); DENSITY_UNROLL_4(op)
+#define DENSITY_UNROLL_16(op) DENSITY_UNROLL_8(op); DENSITY_UNROLL_8(op)
+#define DENSITY_UNROLL_32(op) DENSITY_UNROLL_16(op); DENSITY_UNROLL_16(op)
+#define DENSITY_UNROLL_64(op) DENSITY_UNROLL_32(op); DENSITY_UNROLL_32(op)
+
+#define DENSITY_CASE_GENERATOR_2(op_a, flag_a, op_b, flag_b, op_mid, shift)\
+ case ((flag_b << shift) | flag_a):\
+ op_a;\
+ op_mid;\
+ op_b;\
+ break;
+
+#define DENSITY_CASE_GENERATOR_4(op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ case ((flag_d << (shift * 3)) | (flag_c << (shift * 2)) | (flag_b << shift) | flag_a):\
+ op_a;\
+ op_mid;\
+ op_b;\
+ op_mid;\
+ op_c;\
+ op_mid;\
+ op_d;\
+ break;
+
+#define DENSITY_CASE_GENERATOR_4_2_LAST_1_COMBINED(op_1, flag_1, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_2(op_1, flag_1, op_a, flag_a, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_2(op_1, flag_1, op_b, flag_b, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_2(op_1, flag_1, op_c, flag_c, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_2(op_1, flag_1, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_CASE_GENERATOR_4_2_COMBINED(op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_4_2_LAST_1_COMBINED(op_a, flag_a, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_2_LAST_1_COMBINED(op_b, flag_b, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_2_LAST_1_COMBINED(op_c, flag_c, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_2_LAST_1_COMBINED(op_d, flag_d, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_CASE_GENERATOR_4_4_LAST_1_COMBINED(op_1, flag_1, op_2, flag_2, op_3, flag_3, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_4(op_1, flag_1, op_2, flag_2, op_3, flag_3, op_a, flag_a, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4(op_1, flag_1, op_2, flag_2, op_3, flag_3, op_b, flag_b, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4(op_1, flag_1, op_2, flag_2, op_3, flag_3, op_c, flag_c, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4(op_1, flag_1, op_2, flag_2, op_3, flag_3, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_CASE_GENERATOR_4_4_LAST_2_COMBINED(op_1, flag_1, op_2, flag_2, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_4_4_LAST_1_COMBINED(op_1, flag_1, op_2, flag_2, op_a, flag_a, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_1_COMBINED(op_1, flag_1, op_2, flag_2, op_b, flag_b, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_1_COMBINED(op_1, flag_1, op_2, flag_2, op_c, flag_c, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_1_COMBINED(op_1, flag_1, op_2, flag_2, op_d, flag_d, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_CASE_GENERATOR_4_4_LAST_3_COMBINED(op_1, flag_1, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_4_4_LAST_2_COMBINED(op_1, flag_1, op_a, flag_a, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_2_COMBINED(op_1, flag_1, op_b, flag_b, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_2_COMBINED(op_1, flag_1, op_c, flag_c, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_2_COMBINED(op_1, flag_1, op_d, flag_d, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_CASE_GENERATOR_4_4_COMBINED(op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift)\
+ DENSITY_CASE_GENERATOR_4_4_LAST_3_COMBINED(op_a, flag_a, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_3_COMBINED(op_b, flag_b, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_3_COMBINED(op_c, flag_c, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);\
+ DENSITY_CASE_GENERATOR_4_4_LAST_3_COMBINED(op_d, flag_d, op_a, flag_a, op_b, flag_b, op_c, flag_c, op_d, flag_d, op_mid, shift);
+
+#define DENSITY_DICTIONARY_PREFERRED_RESET_CYCLE_SHIFT 6
+#define DENSITY_DICTIONARY_PREFERRED_RESET_CYCLE (1 << DENSITY_DICTIONARY_PREFERRED_RESET_CYCLE_SHIFT)
+
+
+#define density_bitsizeof(x) (8 * sizeof(x))
+
+#define DENSITY_SPOOKYHASH_SEED_1 (0xabc)
+#define DENSITY_SPOOKYHASH_SEED_2 (0xdef)
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_major();
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_minor();
+
+DENSITY_WINDOWS_EXPORT uint8_t density_version_revision();
+
+
+/**********************************************************************************************************************
+ * *
+ * Global compile-time switches *
+ * *
+ **********************************************************************************************************************/
+
+#define DENSITY_MAJOR_VERSION 0
+#define DENSITY_MINOR_VERSION 14
+#define DENSITY_REVISION 2
+
+
+
+#endif
diff --git a/contrib/density/src/structure/header.c b/contrib/density/src/structure/header.c
new file mode 100644
index 00000000000..4306a5962cf
--- /dev/null
+++ b/contrib/density/src/structure/header.c
@@ -0,0 +1,57 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 11/10/13 17:56
+ */
+
+#include "header.h"
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_header_read(const uint8_t **DENSITY_RESTRICT in, density_header *DENSITY_RESTRICT header) {
+ header->version[0] = *(*in);
+ header->version[1] = *(*in + 1);
+ header->version[2] = *(*in + 2);
+ header->algorithm = *(*in + 3);
+
+ *in += sizeof(density_header);
+}
+
+DENSITY_WINDOWS_EXPORT DENSITY_FORCE_INLINE void density_header_write(uint8_t **DENSITY_RESTRICT out, const DENSITY_ALGORITHM algorithm) {
+ *(*out) = DENSITY_MAJOR_VERSION;
+ *(*out + 1) = DENSITY_MINOR_VERSION;
+ *(*out + 2) = DENSITY_REVISION;
+ *(*out + 3) = algorithm;
+ *(*out + 4) = 0;
+ *(*out + 5) = 0;
+ *(*out + 6) = 0;
+ *(*out + 7) = 0;
+
+ *out += sizeof(density_header);
+}
diff --git a/contrib/density/src/structure/header.h b/contrib/density/src/structure/header.h
new file mode 100644
index 00000000000..d4065b5600c
--- /dev/null
+++ b/contrib/density/src/structure/header.h
@@ -0,0 +1,58 @@
+/*
+ * Density
+ *
+ * Copyright (c) 2013, Guillaume Voirin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * 11/10/13 02:06
+ */
+
+#ifndef DENSITY_FILE_HEADER_H
+#define DENSITY_FILE_HEADER_H
+
+#include
+#include
+
+#include "../globals.h"
+#include "../density_api.h"
+
+#pragma pack(push)
+#pragma pack(4)
+
+typedef struct {
+ density_byte version[3];
+ density_byte algorithm;
+ density_byte reserved[4];
+} density_header;
+
+#pragma pack(pop)
+
+DENSITY_WINDOWS_EXPORT void density_header_read(const uint8_t ** DENSITY_RESTRICT_DECLARE, density_header * DENSITY_RESTRICT_DECLARE);
+DENSITY_WINDOWS_EXPORT void density_header_write(uint8_t ** DENSITY_RESTRICT_DECLARE, const DENSITY_ALGORITHM);
+
+#endif
diff --git a/contrib/lizard/.gitattributes b/contrib/lizard/.gitattributes
new file mode 100644
index 00000000000..6212bd405b4
--- /dev/null
+++ b/contrib/lizard/.gitattributes
@@ -0,0 +1,21 @@
+# Set the default behavior
+* text eol=lf
+
+# Explicitly declare source files
+*.c text eol=lf
+*.h text eol=lf
+
+# Denote files that should not be modified.
+*.odt binary
+*.png binary
+
+# Visual Studio
+*.sln text eol=crlf
+*.vcxproj* text eol=crlf
+*.vcproj* text eol=crlf
+*.suo binary
+*.rc text eol=crlf
+
+# Windows
+*.bat text eol=crlf
+*.cmd text eol=crlf
diff --git a/contrib/lizard/.gitignore b/contrib/lizard/.gitignore
new file mode 100644
index 00000000000..dc30b0e5504
--- /dev/null
+++ b/contrib/lizard/.gitignore
@@ -0,0 +1,37 @@
+# Object files
+*.o
+*.ko
+
+# Libraries
+*.lib
+*.a
+
+# Shared objects (inc. Windows DLLs)
+*.dll
+*.so
+*.so.*
+*.dylib
+
+# Executables
+*.exe
+*.out
+*.app
+
+# IDE / editors files
+*.suo
+*.user
+.clang_complete
+
+# Directories
+_lizardbench/
+_visual/
+_codelite/
+_backup/
+_codelite_lz4/
+
+# Archives
+*.zip
+*.liz
+
+*.txt
+*.bat
\ No newline at end of file
diff --git a/contrib/lizard/.travis.yml b/contrib/lizard/.travis.yml
new file mode 100644
index 00000000000..29f75591a31
--- /dev/null
+++ b/contrib/lizard/.travis.yml
@@ -0,0 +1,268 @@
+language: c
+matrix:
+ fast_finish: true
+ include:
+ - name: macOS
+ os: osx
+ env: Ubu=OS_X_Mavericks Cmd='make -C tests test-lizard CC=clang MOREFLAGS="-Werror -Wconversion -Wno-sign-conversion"' COMPILER=clang
+
+
+ # Ubuntu 18.04
+ - name: Ubuntu 18.04, gcc-9, 64-bit and 32-bit tests
+ dist: bionic
+ script:
+ - CC=gcc-9; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-9; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ before_install:
+ - sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
+ - sudo apt-get -q update
+ - sudo apt-get --no-install-suggests --no-install-recommends -yq install gcc-multilib gcc-9 gcc-9-multilib
+
+ - name: Ubuntu 18.04, clang-9, 64-bit tests
+ dist: bionic
+ script:
+ - CC=clang-9; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - sourceline: 'deb https://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+ packages:
+ - clang-9
+
+
+
+ # Ubuntu 16.04 gcc
+ - name: Ubuntu 16.04, gcc-9, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-9; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-9; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-multilib
+ - gcc-9
+ - gcc-9-multilib
+
+ - name: Ubuntu 16.04, gcc-8, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-8; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-8; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-multilib
+ - gcc-8
+ - gcc-8-multilib
+
+ - name: Ubuntu 16.04, gcc-7, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-7; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-7; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-multilib
+ - gcc-7
+ - gcc-7-multilib
+
+ - name: Ubuntu 16.04, gcc-6, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-6; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-6; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-multilib
+ - gcc-6
+ - gcc-6-multilib
+
+ - name: Ubuntu 16.04, gcc-5, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-5; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-5; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ packages:
+ - gcc-multilib
+ - gcc-5
+ - gcc-5-multilib
+
+ - name: Ubuntu 16.04, gcc-4.8, 64-bit and 32-bit tests
+ dist: xenial
+ script:
+ - CC=gcc-4.8; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ - CC=gcc-4.8; $CC -v; make -C tests test-lizardc32 test-fullbench32 test-frametest32 test-fuzzer32 MOREFLAGS=-Werror
+ addons:
+ apt:
+ packages:
+ - gcc-multilib
+ - gcc-4.8
+ - gcc-4.8-multilib
+
+
+
+ # Ubuntu 16.04 clang
+ - name: Ubuntu 16.04, clang-9, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-9; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main'
+ key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'
+ packages:
+ - clang-9
+
+ - name: Ubuntu 16.04, clang-8, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-8; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-xenial-8
+ packages:
+ - clang-8
+
+ - name: Ubuntu 16.04, clang-7, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-7; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-xenial-7
+ packages:
+ - clang-7
+
+ - name: Ubuntu 16.04, clang-6.0, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-6.0; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-xenial-6.0
+ packages:
+ - clang-6.0
+
+ - name: Ubuntu 16.04, clang-5.0, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-5.0; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-xenial-5.0
+ packages:
+ - clang-5.0
+
+ - name: Ubuntu 16.04, clang-4.0, 64-bit tests
+ dist: xenial
+ script:
+ - CC=clang-4.0; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-xenial-4.0
+ packages:
+ - clang-4.0
+
+ - name: Ubuntu 14.04, clang-3.8, 64-bit tests
+ dist: trusty
+ script:
+ - CC=clang-3.8; $CC -v; make -C tests test-lizard test-fullbench test-frametest test-fuzzer MOREFLAGS=-Werror
+ addons:
+ apt:
+ sources:
+ - ubuntu-toolchain-r-test
+ - llvm-toolchain-trusty-3.8
+ packages:
+ - clang-3.8
+
+
+
+ - name: Ubuntu 16.04, misc tests
+ env: Cmd="make c_standards && make gpptest-native && make clean && make examples && make clean && make cmake && make clean && make travis-install && make clean && make clangtest-native" COMPILER=cc
+ dist: xenial
+
+ - name: Ubuntu 14.04, arm and aarch64
+ env: Cmd='make platformTest CC=arm-linux-gnueabi-gcc QEMU_SYS=qemu-arm-static && make platformTest CC=aarch64-linux-gnu-gcc QEMU_SYS=qemu-aarch64-static' COMPILER=arm-linux-gnueabi-gcc
+ dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-arm
+ - qemu-user-static
+ - gcc-arm-linux-gnueabi
+ - libc6-dev-armel-cross
+ - gcc-aarch64-linux-gnu
+ - libc6-dev-arm64-cross
+
+ - name: Ubuntu 14.04, powerpc and ppc64
+ env: Cmd='make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc-static && make platformTest CC=powerpc-linux-gnu-gcc QEMU_SYS=qemu-ppc64-static MOREFLAGS=-m64' COMPILER=powerpc-linux-gnu-gcc
+ dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - qemu-system-ppc
+ - qemu-user-static
+ - gcc-powerpc-linux-gnu
+
+ - name: Ubuntu 14.04, valgrind
+ env: Cmd='make -C tests test-mem MOREFLAGS=-DLIZARD_RESET_MEM' COMPILER=cc
+ dist: trusty
+ sudo: required
+ addons:
+ apt:
+ packages:
+ - valgrind
+
+
+ #- env: Ubu=14.04 Cmd='make sanitize' COMPILER=clang
+ # dist: trusty
+ # sudo: required
+ # addons:
+ # apt:
+ # packages:
+ # - valgrind
+
+ #- env: Ubu=14.04 Cmd='make staticAnalyze' COMPILER=clang
+ # dist: trusty
+ # sudo: required
+ # addons:
+ # apt:
+ # packages:
+ # - clang
+
+
+script:
+ - echo Cmd=$Cmd
+ - $COMPILER -v
+ - sh -c "$Cmd"
diff --git a/contrib/lizard/LICENSE b/contrib/lizard/LICENSE
new file mode 100644
index 00000000000..df1edbca85e
--- /dev/null
+++ b/contrib/lizard/LICENSE
@@ -0,0 +1,15 @@
+This repository uses 2 different licenses :
+- all files in the `lib` directory use a BSD 2-Clause license
+- all other files use a GPLv2 license, unless explicitly stated otherwise
+
+Relevant license is reminded at the top of each source file,
+and with the presence of COPYING or LICENSE file.
+
+This model emphasizes the fact that
+only files in the `lib` directory are designed to be included into 3rd party projects.
+
+Other files, such as those from `programs` or `examples` directory,
+are not intended to be compiled outside of their context.
+They can serve as source of inspiration,
+but they should not be copy/pasted into 3rd party projects,
+as this scenario is not supported.
diff --git a/contrib/lizard/NEWS b/contrib/lizard/NEWS
new file mode 100644
index 00000000000..05d424656e9
--- /dev/null
+++ b/contrib/lizard/NEWS
@@ -0,0 +1,41 @@
+Lizard v1.0
+- LZ5 v2.0 was renamed to Lizard v1.0
+- improved compression speed with many small files
+
+LZ5 v2.0
+- this version is optimized for decompression speed (instead of ratio for previous versions)
+- LZ5 v2.0 contains 4 compression methods:
+ fastLZ4 : compression levels -10...-19 are designed to give better decompression speed than LZ4 i.e. over 2000 MB/s
+ LIZv1 : compression levels -20...-29 are designed to give better ratio than LZ4 keeping 75% decompression speed
+ fastLZ4 + Huffman : compression levels -30...-39 add Huffman coding to fastLZ4
+ LIZv1 + Huffman : compression levels -40...-49 give the best ratio (comparable to zlib and low levels of zstd/brotli) at decompression speed of 1000 MB/s
+
+LZ5 v1.5
+- introduced compatibility with Visual C++ 2010 and newer
+- attached Visual Studio 2010 project
+- thoroughly tested with 21 Travis CI and 7 AppVeyor CI tests
+- fixed bug with reusing a context in lizard_frame.c (LizardF_compressBegin and Lizard_compress_HC_continue)
+- fixed rare bug in match finder (concerns levels 4 - 15)
+
+LZ5 v1.4.1
+- fixed bug with a backward match extension (level 11 and 12)
+
+LZ5 v1.4
+- improved: levels from 13 to 15 (maximum compression ratio)
+- added a new parser: LizardHC_optimal_price_bt
+- updated documentation: lizard_Block_format.md and lizard_Frame_format.md
+- changed lizard.exe: the "-B" option with block size [1-7] = 64KB, 256KB, 1MB, 4MB, 16MB, 64MB, 256MB (default : 4 = 4MB)
+
+LZ5 v1.3.3
+- added: new levels from 11 to 18 (maximum compression ratio)
+- added: a new parser: LizardHC_optimal_price
+- fixed: buffer-overflow during decompression (thanks to m^2)
+
+LZ5 r132
+- improved compression ratio
+- added: new parsers: LizardHC_fast, LizardHC_price_fast, LizardHC_lowest_price
+- added: a special 1-byte codeword for the last occured offset
+- added: support for 3-byte long matches (MINMATCH = 3)
+
+LZ5 r131
+The first release based on LZ4 r132 dev
diff --git a/contrib/lizard/README.md b/contrib/lizard/README.md
new file mode 100644
index 00000000000..50dd737fb8d
--- /dev/null
+++ b/contrib/lizard/README.md
@@ -0,0 +1,95 @@
+Lizard - efficient compression with very fast decompression
+--------------------------------------------------------
+
+Lizard (formerly LZ5) is a lossless compression algorithm which contains 4 compression methods:
+- fastLZ4 : compression levels -10...-19 are designed to give better decompression speed than [LZ4] i.e. over 2000 MB/s
+- LIZv1 : compression levels -20...-29 are designed to give better ratio than [LZ4] keeping 75% decompression speed
+- fastLZ4 + Huffman : compression levels -30...-39 add Huffman coding to fastLZ4
+- LIZv1 + Huffman : compression levels -40...-49 give the best ratio (comparable to [zlib] and low levels of [zstd]/[brotli]) at decompression speed of 1000 MB/s
+
+Lizard library is based on frequently used [LZ4] library by Yann Collet but the Lizard compression format is not compatible with LZ4.
+Lizard library is provided as open-source software using BSD 2-Clause license.
+The high compression/decompression speed is achieved without any SSE and AVX extensions.
+
+
+|Branch |Status |
+|------------|---------|
+|lz5_v1.5 | [![Build Status][travis15Badge]][travisLink] [![Build status][Appveyor15Badge]][AppveyorLink] |
+|lizard | [![Build Status][travis20Badge]][travisLink] [![Build status][Appveyor20Badge]][AppveyorLink] |
+
+[travis15Badge]: https://travis-ci.org/inikep/lizard.svg?branch=lz5_v1.5 "Continuous Integration test suite"
+[travis20Badge]: https://travis-ci.org/inikep/lizard.svg?branch=lizard "Continuous Integration test suite"
+[travisLink]: https://travis-ci.org/inikep/lizard
+[Appveyor15Badge]: https://ci.appveyor.com/api/projects/status/cqw7emcuqge369p0/branch/lz5_v1.5?svg=true "Visual test suite"
+[Appveyor20Badge]: https://ci.appveyor.com/api/projects/status/cqw7emcuqge369p0/branch/lizard?svg=true "Visual test suite"
+[AppveyorLink]: https://ci.appveyor.com/project/inikep/lizard
+[LZ4]: https://github.com/lz4/lz4
+[zlib]: https://github.com/madler/zlib
+[zstd]: https://github.com/facebook/zstd
+[brotli]: https://github.com/google/brotli
+
+
+Benchmarks
+-------------------------
+
+The following results are obtained with [lzbench](https://github.com/inikep/lzbench) and `-t16,16`
+using 1 core of Intel Core i5-4300U, Windows 10 64-bit (MinGW-w64 compilation under gcc 6.2.0)
+with [silesia.tar] which contains tarred files from [Silesia compression corpus](http://sun.aei.polsl.pl/~sdeor/index.php?page=silesia).
+
+| Compressor name | Compression| Decompress.| Compr. size | Ratio |
+| --------------- | -----------| -----------| ----------- | ----- |
+| memcpy | 7332 MB/s | 8719 MB/s | 211947520 |100.00 |
+| lz4 1.7.3 | 440 MB/s | 2318 MB/s | 100880800 | 47.60 |
+| lz4hc 1.7.3 -1 | 98 MB/s | 2121 MB/s | 87591763 | 41.33 |
+| lz4hc 1.7.3 -4 | 55 MB/s | 2259 MB/s | 79807909 | 37.65 |
+| lz4hc 1.7.3 -9 | 22 MB/s | 2315 MB/s | 77892285 | 36.75 |
+| lz4hc 1.7.3 -12 | 17 MB/s | 2323 MB/s | 77849762 | 36.73 |
+| lz4hc 1.7.3 -16 | 10 MB/s | 2323 MB/s | 77841782 | 36.73 |
+| lizard 1.0 -10 | 346 MB/s | 2610 MB/s | 103402971 | 48.79 |
+| lizard 1.0 -12 | 103 MB/s | 2458 MB/s | 86232422 | 40.69 |
+| lizard 1.0 -15 | 50 MB/s | 2552 MB/s | 81187330 | 38.31 |
+| lizard 1.0 -19 | 3.04 MB/s | 2497 MB/s | 77416400 | 36.53 |
+| lizard 1.0 -21 | 157 MB/s | 1795 MB/s | 89239174 | 42.10 |
+| lizard 1.0 -23 | 30 MB/s | 1778 MB/s | 81097176 | 38.26 |
+| lizard 1.0 -26 | 6.63 MB/s | 1734 MB/s | 74503695 | 35.15 |
+| lizard 1.0 -29 | 1.37 MB/s | 1634 MB/s | 68694227 | 32.41 |
+| lizard 1.0 -30 | 246 MB/s | 909 MB/s | 85727429 | 40.45 |
+| lizard 1.0 -32 | 94 MB/s | 1244 MB/s | 76929454 | 36.30 |
+| lizard 1.0 -35 | 47 MB/s | 1435 MB/s | 73850400 | 34.84 |
+| lizard 1.0 -39 | 2.94 MB/s | 1502 MB/s | 69807522 | 32.94 |
+| lizard 1.0 -41 | 126 MB/s | 961 MB/s | 76100661 | 35.91 |
+| lizard 1.0 -43 | 28 MB/s | 1101 MB/s | 70955653 | 33.48 |
+| lizard 1.0 -46 | 6.25 MB/s | 1073 MB/s | 65413061 | 30.86 |
+| lizard 1.0 -49 | 1.27 MB/s | 1064 MB/s | 60679215 | 28.63 |
+| zlib 1.2.8 -1 | 66 MB/s | 244 MB/s | 77259029 | 36.45 |
+| zlib 1.2.8 -6 | 20 MB/s | 263 MB/s | 68228431 | 32.19 |
+| zlib 1.2.8 -9 | 8.37 MB/s | 266 MB/s | 67644548 | 31.92 |
+| zstd 1.1.1 -1 | 235 MB/s | 645 MB/s | 73659468 | 34.75 |
+| zstd 1.1.1 -2 | 181 MB/s | 600 MB/s | 70168955 | 33.11 |
+| zstd 1.1.1 -5 | 88 MB/s | 565 MB/s | 65002208 | 30.67 |
+| zstd 1.1.1 -8 | 31 MB/s | 619 MB/s | 61026497 | 28.79 |
+| zstd 1.1.1 -11 | 16 MB/s | 613 MB/s | 59523167 | 28.08 |
+| zstd 1.1.1 -15 | 4.97 MB/s | 639 MB/s | 58007773 | 27.37 |
+| zstd 1.1.1 -18 | 2.87 MB/s | 583 MB/s | 55294241 | 26.09 |
+| zstd 1.1.1 -22 | 1.44 MB/s | 505 MB/s | 52731930 | 24.88 |
+| brotli 0.5.2 -0 | 217 MB/s | 244 MB/s | 78226979 | 36.91 |
+| brotli 0.5.2 -2 | 96 MB/s | 283 MB/s | 68066621 | 32.11 |
+| brotli 0.5.2 -5 | 24 MB/s | 312 MB/s | 60801716 | 28.69 |
+| brotli 0.5.2 -8 | 5.56 MB/s | 324 MB/s | 57382470 | 27.07 |
+| brotli 0.5.2 -11 | 0.39 MB/s | 266 MB/s | 51138054 | 24.13 |
+
+[silesia.tar]: https://drive.google.com/file/d/0BwX7dtyRLxThenZpYU9zLTZhR1k/view?usp=sharing
+
+
+Documentation
+-------------------------
+
+The raw Lizard block compression format is detailed within [lizard_Block_format].
+
+To compress an arbitrarily long file or data stream, multiple blocks are required.
+Organizing these blocks and providing a common header format to handle their content
+is the purpose of the Frame format, defined into [lizard_Frame_format].
+Interoperable versions of Lizard must respect this frame format.
+
+[lizard_Block_format]: doc/lizard_Block_format.md
+[lizard_Frame_format]: doc/lizard_Frame_format.md
diff --git a/contrib/lizard/appveyor.yml b/contrib/lizard/appveyor.yml
new file mode 100644
index 00000000000..d5863f7c06b
--- /dev/null
+++ b/contrib/lizard/appveyor.yml
@@ -0,0 +1,143 @@
+version: 1.0.{build}
+environment:
+ matrix:
+ - COMPILER: "visual"
+ CONFIGURATION: "Debug"
+ PLATFORM: "x64"
+ - COMPILER: "visual"
+ CONFIGURATION: "Debug"
+ PLATFORM: "Win32"
+ - COMPILER: "visual"
+ CONFIGURATION: "Release"
+ PLATFORM: "x64"
+ - COMPILER: "visual"
+ CONFIGURATION: "Release"
+ PLATFORM: "Win32"
+ - COMPILER: "gcc"
+ PLATFORM: "mingw64"
+ - COMPILER: "gcc"
+ PLATFORM: "mingw32"
+ - COMPILER: "gcc"
+ PLATFORM: "clang"
+
+install:
+ - ECHO Installing %COMPILER% %PLATFORM% %CONFIGURATION%
+ - MKDIR bin
+ - if [%COMPILER%]==[gcc] SET PATH_ORIGINAL=%PATH%
+ - if [%COMPILER%]==[gcc] (
+ SET "PATH_MINGW32=c:\MinGW\bin;c:\MinGW\usr\bin" &&
+ SET "PATH_MINGW64=c:\msys64\mingw64\bin;c:\msys64\usr\bin" &&
+ COPY C:\MinGW\bin\mingw32-make.exe C:\MinGW\bin\make.exe &&
+ COPY C:\MinGW\bin\gcc.exe C:\MinGW\bin\cc.exe
+ ) else (
+ IF [%PLATFORM%]==[x64] (SET ADDITIONALPARAM=/p:LibraryPath="C:\Program Files\Microsoft SDKs\Windows\v7.1\lib\x64;c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\amd64;C:\Program Files (x86)\Microsoft Visual Studio 10.0\;C:\Program Files (x86)\Microsoft Visual Studio 10.0\lib\amd64;")
+ )
+
+build_script:
+ - if [%PLATFORM%]==[mingw32] SET PATH=%PATH_MINGW32%;%PATH_ORIGINAL%
+ - if [%PLATFORM%]==[mingw64] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL%
+ - if [%PLATFORM%]==[clang] SET PATH=%PATH_MINGW64%;%PATH_ORIGINAL%
+ - ECHO *** &&
+ ECHO Building %COMPILER% %PLATFORM% %CONFIGURATION% &&
+ ECHO ***
+ - if [%PLATFORM%]==[clang] (clang -v)
+ - if [%COMPILER%]==[gcc] (gcc -v)
+ - if [%COMPILER%]==[gcc] (
+ echo ----- &&
+ make -v &&
+ echo ----- &&
+ if not [%PLATFORM%]==[clang] (
+ make -C programs lizard && make -C tests fullbench && make -C lib lib
+ ) ELSE (
+ make -C programs lizard CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" &&
+ make -C tests fullbench CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion" &&
+ make -C lib lib CC=clang MOREFLAGS="--target=x86_64-w64-mingw32 -Werror -Wconversion -Wno-sign-conversion"
+ )
+ )
+ - if [%COMPILER%]==[gccX] if not [%PLATFORM%]==[clang] (
+ MKDIR bin\dll bin\static bin\example bin\include &&
+ COPY tests\fullbench.c bin\example\ &&
+ COPY lib\xxhash.c bin\example\ &&
+ COPY lib\xxhash.h bin\example\ &&
+ COPY lib\lizard.h bin\include\ &&
+ COPY lib\lizardhc.h bin\include\ &&
+ COPY lib\lizard_frame.h bin\include\ &&
+ COPY lib\liblizard.a bin\static\liblizard_static.lib &&
+ COPY lib\dll\liblizard.* bin\dll\ &&
+ COPY lib\dll\example\Makefile bin\example\ &&
+ COPY lib\dll\example\fullbench-dll.* bin\example\ &&
+ COPY lib\dll\example\README.md bin\ &&
+ COPY programs\lizard.exe bin\lizard.exe
+ )
+ - if [%COMPILER%]==[gccX] if [%PLATFORM%]==[mingw64] (
+ 7z.exe a bin\lizard_x64.zip NEWS .\bin\lizard.exe .\bin\README.md .\bin\example .\bin\dll .\bin\static .\bin\include &&
+ appveyor PushArtifact bin\lizard_x64.zip
+ )
+ - if [%COMPILER%]==[gccX] if [%PLATFORM%]==[mingw32] (
+ 7z.exe a bin\lizard_x86.zip NEWS .\bin\lizard.exe .\bin\README.md .\bin\example .\bin\dll .\bin\static .\bin\include &&
+ appveyor PushArtifact bin\lizard_x86.zip
+ )
+ - if [%COMPILER%]==[gcc] (COPY tests\fullbench.exe programs\)
+ - if [%COMPILER%]==[visual] (
+ ECHO *** &&
+ ECHO *** Building Visual Studio 2010 %PLATFORM%\%CONFIGURATION% &&
+ ECHO *** &&
+ msbuild "visual\VS2010\lizard.sln" %ADDITIONALPARAM% /m /verbosity:minimal /property:PlatformToolset=v100 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ ECHO *** &&
+ ECHO *** Building Visual Studio 2012 %PLATFORM%\%CONFIGURATION% &&
+ ECHO *** &&
+ msbuild "visual\VS2010\lizard.sln" /m /verbosity:minimal /property:PlatformToolset=v110 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ ECHO *** &&
+ ECHO *** Building Visual Studio 2013 %PLATFORM%\%CONFIGURATION% &&
+ ECHO *** &&
+ msbuild "visual\VS2010\lizard.sln" /m /verbosity:minimal /property:PlatformToolset=v120 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ ECHO *** &&
+ ECHO *** Building Visual Studio 2015 %PLATFORM%\%CONFIGURATION% &&
+ ECHO *** &&
+ msbuild "visual\VS2010\lizard.sln" /m /verbosity:minimal /property:PlatformToolset=v140 /t:Clean,Build /p:Platform=%PLATFORM% /p:Configuration=%CONFIGURATION% /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" &&
+ COPY visual\VS2010\bin\%PLATFORM%_%CONFIGURATION%\*.exe programs\
+ )
+
+test_script:
+ - ECHO *** &&
+ ECHO Testing %COMPILER% %PLATFORM% %CONFIGURATION% &&
+ ECHO ***
+ - if not [%COMPILER%]==[unknown] (
+ CD programs &&
+ lizard -h &&
+ lizard -i1b lizard.exe &&
+ lizard -i1b5 lizard.exe &&
+ lizard -i1b10 lizard.exe &&
+ lizard -i1b15 lizard.exe &&
+ echo ------- lizard tested ------- &&
+ fullbench.exe -i1 fullbench.exe
+ )
+
+artifacts:
+ - path: bin\lizard_x64.zip
+ - path: bin\lizard_x86.zip
+
+deploy:
+- provider: GitHub
+ artifact: bin\lizard_x64.zip
+ auth_token:
+ secure: LgJo8emYc3sFnlNWkGl4/VYK3nk/8+RagcsqDlAi3xeqNGNutnKjcftjg84uJoT4
+ force_update: true
+ prerelease: true
+ on:
+ COMPILER: gcc
+ PLATFORM: "mingw64"
+ appveyor_repo_tag: true
+ branch: autobuild
+
+- provider: GitHub
+ artifact: bin\lizard_x86.zip
+ auth_token:
+ secure: LgJo8emYc3sFnlNWkGl4/VYK3nk/8+RagcsqDlAi3xeqNGNutnKjcftjg84uJoT4
+ force_update: true
+ prerelease: true
+ on:
+ COMPILER: gcc
+ PLATFORM: "mingw32"
+ appveyor_repo_tag: true
+ branch: autobuild
diff --git a/contrib/lizard/contrib/djgpp/LICENSE b/contrib/lizard/contrib/djgpp/LICENSE
new file mode 100644
index 00000000000..fee0d3b3e23
--- /dev/null
+++ b/contrib/lizard/contrib/djgpp/LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2014, lpsantil
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/contrib/lizard/contrib/djgpp/README.MD b/contrib/lizard/contrib/djgpp/README.MD
new file mode 100644
index 00000000000..8dfc3a838c4
--- /dev/null
+++ b/contrib/lizard/contrib/djgpp/README.MD
@@ -0,0 +1,21 @@
+# lizard for DOS/djgpp
+This file details on how to compile lizard.exe, and liblizard.a for use on DOS/djgpp using
+Andrew Wu's build-djgpp cross compilers ([GH][0], [Binaries][1]) on OSX, Linux.
+
+## Setup
+* Download a djgpp tarball [binaries][1] for your platform.
+* Extract and install it (`tar jxvf djgpp-linux64-gcc492.tar.bz2`). Note the path. We'll assume `/home/user/djgpp`.
+* Add the `bin` folder to your `PATH`. In bash, do `export PATH=/home/user/djgpp/bin:$PATH`.
+* The `Makefile` in `contrib/djgpp/` sets up `CC`, `AR`, `LD` for you. So, `CC=i586-pc-msdosdjgpp-gcc`, `AR=i586-pc-msdosdjgpp-ar`, `LD=i586-pc-msdosdjgpp-gcc`.
+
+## Building Lizard for DOS
+In the base dir of lizard and with `contrib/djgpp/Makefile`, try:
+Try:
+* `make -f contrib/djgpp/Makefile`
+* `make -f contrib/djgpp/Makefile liblizard.a`
+* `make -f contrib/djgpp/Makefile lizard.exe`
+* `make -f contrib/djgpp/Makefile DESTDIR=/home/user/dos install`, however it doesn't make much sense on a \*nix.
+* You can also do `make -f contrib/djgpp/Makefile uninstall`
+
+[0]: https://github.com/andrewwutw/build-djgpp
+[1]: https://github.com/andrewwutw/build-djgpp/releases
diff --git a/contrib/lizard/doc/lizard_Block_format.md b/contrib/lizard/doc/lizard_Block_format.md
new file mode 100644
index 00000000000..45307a1fce5
--- /dev/null
+++ b/contrib/lizard/doc/lizard_Block_format.md
@@ -0,0 +1,181 @@
+Lizard v1.x Block Format Description
+============================
+Last revised: 2016-10-08
+Authors : Yann Collet, Przemyslaw Skibinski
+
+
+This specification is intended for developers
+willing to produce Lizard-compatible compressed data blocks
+using any programming language.
+
+Lizard is an LZ77-type compressor with a fixed, byte-oriented encoding.
+There is no framing layer as it is assumed to be handled by other parts of the system (see [Lizard Frame format]).
+This design is assumed to favor simplicity and speed.
+It helps later on for optimizations, compactness, and features.
+
+This document describes only the block format,
+not how the compressor nor decompressor actually work.
+The correctness of the decompressor should not depend
+on implementation details of the compressor, and vice versa.
+
+[Lizard Frame format]: lizard_Frame_format.md
+
+
+Division into blocks
+--------------------
+
+The input data is divided into blocks of maximum size LIZARD_BLOCK_SIZE (which is 128 KB). The subsequent blocks use the same sliding window and are dependent on previous blocks.
+Our impementation of Lizard compressor divides input data into blocks of size of LIZARD_BLOCK_SIZE except the last one which usually will be smaller.
+The output data is a single byte 'Compression_Level' and one or more blocks in the format described below.
+
+
+Block header format
+-----------------------
+
+The block header is a single byte `Header_Byte` that is combination of following flags:
+
+| Name | Value |
+| --------------------- | --- |
+| LIZARD_FLAG_LITERALS | 1 |
+| LIZARD_FLAG_FLAGS | 2 |
+| LIZARD_FLAG_OFF16LEN | 4 |
+| LIZARD_FLAG_OFF24LEN | 8 |
+| LIZARD_FLAG_LEN | 16 |
+| LIZARD_FLAG_UNCOMPRESSED | 128 |
+
+When `Header_Byte & LIZARD_FLAG_UNCOMPRESSED` is true then the block is followed by 3-byte `Uncompressed_length` and uncompressed data of given size.
+
+
+Compressed block content
+------------------------
+
+When `Header_Byte & LIZARD_FLAG_UNCOMPRESSED` is false then compressed block contains of 5 streams:
+- `Lengths_Stream` (compressed with Huffman if LIZARD_FLAG_LEN is set)
+- `16-bit_Offsets_Stream` (compressed with Huffman if LIZARD_FLAG_OFF16LEN is set)
+- `24-bit_Offsets_Stream` (compressed with Huffman if LIZARD_FLAG_OFF24LEN is set)
+- `Tokens_Stream` (compressed with Huffman if LIZARD_FLAG_FLAGS is set)
+- `Literals_Stream` (compressed with Huffman if LIZARD_FLAG_LITERALS is set)
+
+
+Stream format
+-------------
+The single stream is either:
+- if LIZARD_FLAG_XXX is not set: 3 byte `Stream_Length` followed by a given number bytes
+- if LIZARD_FLAG_XXX is set: 3 byte `Original_Stream_Length`, 3 byte `Compressed_Stream_Length`, followed by a given number of Huffman compressed bytes
+
+
+Lizard block decompression
+-----------------------
+At the beginning we have 5 streams and their sizes.
+Decompressor should iterate through `Tokens_Stream`. Each token is 1-byte long and describes how to get data from other streams.
+If token points a stream that is already empty it means that data is corrupted.
+
+
+Lizard token decompression
+-----------------------
+The token is a one byte. Token decribes:
+- how many literals should be copied from `Literals_Stream`
+- if offset should be read from `16-bit_Offsets_Stream` or `24-bit_Offsets_Stream`
+- how many bytes are part of a match and should be copied from a sliding window
+
+Lizard uses 4 types of tokens:
+- [0_MMMM_LLL] - 3-bit literal length (0-7+), use offset from `16-bit_Offsets_Stream`, 4-bit match length (4-15+)
+- [1_MMMM_LLL] - 3-bit literal length (0-7+), use last offset, 4-bit match length (0-15+)
+- token 31 - no literal length, use offset from `24-bit_Offsets_Stream`, match length (47+)
+- token 0-30 - no literal length, use offset from `24-bit_Offsets_Stream`, 31 match lengths (16-46)
+
+Lizard uses different output codewords and is not compatible with LZ4. LZ4 output codewords are 3 byte long (24-bit) and look as follows:
+- LLLL_MMMM OOOOOOOO OOOOOOOO - 16-bit offset, 4-bit match length, 4-bit literal length
+
+
+The format of `Lengths_Stream`
+------------------------------
+`Lengths_Stream` contains lenghts in the the following format:
+- when 'First_Byte' is < 254 then lenght is equal 'First_Byte'
+- when 'First_Byte' is 254 then lenght is equal to value of 2-bytes after 'First_Byte' i.e. 0-65536
+- when 'First_Byte' is 255 then lenght is equal to value of 3-bytes after 'First_Byte' i.e. 0-16777215
+
+
+[0_MMMM_LLL] and [1_MMMM_LLL] tokens
+---------------------------------------
+The length of literals to be copied from `Literals_Stream` depends on the literal length field (LLL) that uses 3 bits of the token.
+Therefore each field ranges from 0 to 7.
+If the value is 7, then the lenght is increased with a length taken from `Lengths_Stream`.
+
+Example 1 : A literal length of 48 will be represented as :
+
+ - 7 : value for the 3-bits LLL field
+ - 41 : (=48-7) remaining length to reach 48 (in `Lengths_Stream`)
+
+Example 2 : A literal length of 280 for will be represented as :
+
+ - 7 : value for the 3-bits LLL field
+ - 254 : informs that remaining length (=280-7) must be represented as 2-bytes (in `Lengths_Stream`)
+ - 273 : (=280-7) encoded as 2-bytes (in `Lengths_Stream`)
+
+Example 3 : A literal length of 7 for will be represented as :
+
+ - 7 : value for the 3-bits LLL field
+ - 0 : (=7-7) yes, the zero must be output (in `Lengths_Stream`)
+
+After copying 0 or more literals from `Literals_Stream` we can prepare the match copy operation which depends on a offset and a match length.
+The flag "0" informs that decoder should use the last encoded offset.
+The flag "1" informs that the offset is a 2 bytes value (16-bit), in little endian format and should be taken from `16-bit_Offsets_Stream`.
+
+The match length depends on the match length field (MMMM) that uses 4 bits of the token.
+Therefore each field ranges from 0 to 15. Values from 0-3 are forbidden with offset taken from `16-bit_Offsets_Stream`.
+If the value is 15, then the lenght is increased with a length taken from `Lengths_Stream`.
+
+With the offset and the match length,
+the decoder can now proceed to copy the data from the already decoded buffer.
+
+
+Lizard block epilogue
+------------------
+When all tokens are read from `Tokens_Stream` and interpreted all remaining streams should also be empty.
+Otherwise, it means that the data is corrupted. The only exception is `Literals_Stream` that should have at least 16 remaining literals what
+allows fast memory copy operations. The remaining literals up to the end of `Literals_Stream` should be appended to the output data.
+
+
+Tokens 0-31
+-----------
+The offset is a 3 bytes value (24-bit), in little endian format and should be taken from `24-bit_Offsets_Stream`.
+The offset represents the position of the match to be copied from.
+1 means "current position - 1 byte".
+The maximum offset value is (1<<24)-1, 1<<24 cannot be coded.
+Note that 0 is an invalid value, not used.
+
+The 'Token_Value' ranges from 0 to 31.
+The match length is equal to 'Token_Value + 16 that is from 16 to 47.
+If match length is 47, the lenght is increased with a length taken from `Lengths_Stream`.
+
+
+Parsing restrictions
+-----------------------
+There are specific parsing rules to respect in order to remain compatible
+with assumptions made by the decoder :
+
+1. The last 16 bytes are always literals what allows fast memory copy operations.
+2. The last match must start at least 20 bytes before end of block.
+ Consequently, a block with less than 20 bytes cannot be compressed.
+
+These rules are in place to ensure that the decoder
+will never read beyond the input buffer, nor write beyond the output buffer.
+
+Note that the last sequence is also incomplete,
+and stops right after literals.
+
+
+Additional notes
+-----------------------
+There is no assumption nor limits to the way the compressor
+searches and selects matches within the source data block.
+It could be a fast scan, a multi-probe, a full search using BST,
+standard hash chains or MMC, well whatever.
+
+Advanced parsing strategies can also be implemented, such as lazy match,
+or full optimal parsing.
+
+All these trade-off offer distinctive speed/memory/compression advantages.
+Whatever the method used by the compressor, its result will be decodable
+by any Lizard decoder if it follows the format specification described above.
diff --git a/contrib/lizard/doc/lizard_Frame_format.md b/contrib/lizard/doc/lizard_Frame_format.md
new file mode 100644
index 00000000000..ce24b0e23e2
--- /dev/null
+++ b/contrib/lizard/doc/lizard_Frame_format.md
@@ -0,0 +1,312 @@
+Lizard v1.x Frame Format Description
+=================================
+
+###Notices
+
+Copyright (c) 2013-2015 Yann Collet
+
+Copyright (c) 2016 Przemyslaw Skibinski
+
+Permission is granted to copy and distribute this document
+for any purpose and without charge,
+including translations into other languages
+and incorporation into compilations,
+provided that the copyright notice and this notice are preserved,
+and that any substantive changes or deletions from the original
+are clearly marked.
+Distribution of this document is unlimited.
+
+###Version
+
+1.0 (8-10-2016)
+
+
+Introduction
+------------
+
+The purpose of this document is to define a lossless compressed data format,
+that is independent of CPU type, operating system,
+file system and character set, suitable for
+File compression, Pipe and streaming compression
+using the Lizard algorithm.
+
+The data can be produced or consumed,
+even for an arbitrarily long sequentially presented input data stream,
+using only an a priori bounded amount of intermediate storage,
+and hence can be used in data communications.
+The format uses the Lizard compression method,
+and optional [xxHash-32 checksum method](https://github.com/Cyan4973/xxHash),
+for detection of data corruption.
+
+The data format defined by this specification
+does not attempt to allow random access to compressed data.
+
+This specification is intended for use by implementers of software
+to compress data into Lizard format and/or decompress data from Lizard format.
+The text of the specification assumes a basic background in programming
+at the level of bits and other primitive data representations.
+
+Unless otherwise indicated below,
+a compliant compressor must produce data sets
+that conform to the specifications presented here.
+It doesn’t need to support all options though.
+
+A compliant decompressor must be able to decompress
+at least one working set of parameters
+that conforms to the specifications presented here.
+It may also ignore checksums.
+Whenever it does not support a specific parameter within the compressed stream,
+it must produce a non-ambiguous error code
+and associated error message explaining which parameter is unsupported.
+
+
+General Structure of Lizard Frame format
+-------------------------------------
+
+| MagicNb | F. Descriptor | Block | (...) | EndMark | C. Checksum |
+|:-------:|:-------------:| ----- | ----- | ------- | ----------- |
+| 4 bytes | 3-11 bytes | | | 4 bytes | 0-4 bytes |
+
+__Magic Number__
+
+4 Bytes, Little endian format.
+Value : 0x184D2206 (it was 0x184D2204 for LZ4 and 0x184D2205 for LZ5 v1.x)
+
+__Frame Descriptor__
+
+3 to 11 Bytes, to be detailed in the next part.
+Most important part of the spec.
+
+__Data Blocks__
+
+To be detailed later on.
+That’s where compressed data is stored.
+
+__EndMark__
+
+The flow of blocks ends when the last data block has a size of “0”.
+The size is expressed as a 32-bits value.
+
+__Content Checksum__
+
+Content Checksum verify that the full content has been decoded correctly.
+The content checksum is the result
+of [xxh32() hash function](https://github.com/Cyan4973/xxHash)
+digesting the original (decoded) data as input, and a seed of zero.
+Content checksum is only present when its associated flag
+is set in the frame descriptor.
+Content Checksum validates the result,
+that all blocks were fully transmitted in the correct order and without error,
+and also that the encoding/decoding process itself generated no distortion.
+Its usage is recommended.
+
+__Frame Concatenation__
+
+In some circumstances, it may be preferable to append multiple frames,
+for example in order to add new data to an existing compressed file
+without re-framing it.
+
+In such case, each frame has its own set of descriptor flags.
+Each frame is considered independent.
+The only relation between frames is their sequential order.
+
+The ability to decode multiple concatenated frames
+within a single stream or file
+is left outside of this specification.
+As an example, the reference lizard command line utility behavior is
+to decode all concatenated frames in their sequential order.
+
+
+Frame Descriptor
+----------------
+
+| FLG | BD | (Content Size) | HC |
+| ------- | ------- |:--------------:| ------- |
+| 1 byte | 1 byte | 0 - 8 bytes | 1 byte |
+
+The descriptor uses a minimum of 3 bytes,
+and up to 11 bytes depending on optional parameters.
+
+__FLG byte__
+
+| BitNb | 7-6 | 5 | 4 | 3 | 2 | 1-0 |
+| ------- | ------- | ------- | --------- | ------- | --------- | -------- |
+|FieldName| Version | B.Indep | B.Checksum| C.Size | C.Checksum|*Reserved*|
+
+
+__BD byte__
+
+| BitNb | 7 | 6-5-4 | 3-2-1-0 |
+| ------- | -------- | ------------ | -------- |
+|FieldName|*Reserved*| Block MaxSize|*Reserved*|
+
+In the tables, bit 7 is highest bit, while bit 0 is lowest.
+
+__Version Number__
+
+2-bits field, must be set to “01”.
+Any other value cannot be decoded by this version of the specification.
+Other version numbers will use different flag layouts.
+
+__Block Independence flag__
+
+If this flag is set to “1”, blocks are independent.
+If this flag is set to “0”, each block depends on previous ones
+(up to Lizard window size, which is 16 MB).
+In such case, it’s necessary to decode all blocks in sequence.
+
+Block dependency improves compression ratio, especially for small blocks.
+On the other hand, it makes direct jumps or multi-threaded decoding impossible.
+
+__Block checksum flag__
+
+If this flag is set, each data block will be followed by a 4-bytes checksum,
+calculated by using the xxHash-32 algorithm on the raw (compressed) data block.
+The intention is to detect data corruption (storage or transmission errors)
+immediately, before decoding.
+Block checksum usage is optional.
+
+__Content Size flag__
+
+If this flag is set, the uncompressed size of data included within the frame
+will be present as an 8 bytes unsigned little endian value, after the flags.
+Content Size usage is optional.
+
+__Content checksum flag__
+
+If this flag is set, a content checksum will be appended after the EndMark.
+
+Recommended value : “1” (content checksum is present)
+
+__Block Maximum Size__
+
+This information is intended to help the decoder allocate memory.
+Size here refers to the original (uncompressed) data size.
+Block Maximum Size is one value among the following table :
+
+| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
+| --- | ------ | ------ | ---- | ---- | ----- | ----- | ------ |
+| N/A | 128 KB | 256 KB | 1 MB | 4 MB | 16 MB | 64 MB | 256 MB |
+
+
+The decoder may refuse to allocate block sizes above a (system-specific) size.
+Unused values may be used in a future revision of the spec.
+A decoder conformant to the current version of the spec
+is only able to decode blocksizes defined in this spec.
+
+__Reserved bits__
+
+Value of reserved bits **must** be 0 (zero).
+Reserved bit might be used in a future version of the specification,
+typically enabling new optional features.
+If this happens, a decoder respecting the current version of the specification
+shall not be able to decode such a frame.
+
+__Content Size__
+
+This is the original (uncompressed) size.
+This information is optional, and only present if the associated flag is set.
+Content size is provided using unsigned 8 Bytes, for a maximum of 16 HexaBytes.
+Format is Little endian.
+This value is informational, typically for display or memory allocation.
+It can be skipped by a decoder, or used to validate content correctness.
+
+__Header Checksum__
+
+One-byte checksum of combined descriptor fields, including optional ones.
+The value is the second byte of xxh32() : ` (xxh32()>>8) & 0xFF `
+using zero as a seed,
+and the full Frame Descriptor as an input
+(including optional fields when they are present).
+A wrong checksum indicates an error in the descriptor.
+Header checksum is informational and can be skipped.
+
+
+Data Blocks
+-----------
+
+| Block Size | data | (Block Checksum) |
+|:----------:| ------ |:----------------:|
+| 4 bytes | | 0 - 4 bytes |
+
+
+__Block Size__
+
+This field uses 4-bytes, format is little-endian.
+
+The highest bit is “1” if data in the block is uncompressed.
+
+The highest bit is “0” if data in the block is compressed by Lizard.
+
+All other bits give the size, in bytes, of the following data block
+(the size does not include the block checksum if present).
+
+Block Size shall never be larger than Block Maximum Size.
+Such a thing could happen for incompressible source data.
+In such case, such a data block shall be passed in uncompressed format.
+
+__Data__
+
+Where the actual data to decode stands.
+It might be compressed or not, depending on previous field indications.
+Uncompressed size of Data can be any size, up to “block maximum size”.
+Note that data block is not necessarily full :
+an arbitrary “flush” may happen anytime. Any block can be “partially filled”.
+
+__Block checksum__
+
+Only present if the associated flag is set.
+This is a 4-bytes checksum value, in little endian format,
+calculated by using the xxHash-32 algorithm on the raw (undecoded) data block,
+and a seed of zero.
+The intention is to detect data corruption (storage or transmission errors)
+before decoding.
+
+Block checksum is cumulative with Content checksum.
+
+
+Skippable Frames
+----------------
+
+| Magic Number | Frame Size | User Data |
+|:------------:|:----------:| --------- |
+| 4 bytes | 4 bytes | |
+
+Skippable frames allow the integration of user-defined data
+into a flow of concatenated frames.
+Its design is pretty straightforward,
+with the sole objective to allow the decoder to quickly skip
+over user-defined data and continue decoding.
+
+For the purpose of facilitating identification,
+it is discouraged to start a flow of concatenated frames with a skippable frame.
+If there is a need to start such a flow with some user data
+encapsulated into a skippable frame,
+it’s recommended to start with a zero-byte Lizard frame
+followed by a skippable frame.
+This will make it easier for file type identifiers.
+
+
+__Magic Number__
+
+4 Bytes, Little endian format.
+Value : 0x184D2A5X, which means any value from 0x184D2A50 to 0x184D2A5F.
+All 16 values are valid to identify a skippable frame.
+
+__Frame Size__
+
+This is the size, in bytes, of the following User Data
+(without including the magic number nor the size field itself).
+4 Bytes, Little endian format, unsigned 32-bits.
+This means User Data can’t be bigger than (2^32-1) Bytes.
+
+__User Data__
+
+User Data can be anything. Data will just be skipped by the decoder.
+
+
+
+Version changes
+---------------
+
+1.0 : based on LZ4 Frame Format Description 1.5.1 (31/03/2015)
diff --git a/contrib/lizard/examples/.gitignore b/contrib/lizard/examples/.gitignore
new file mode 100644
index 00000000000..f6f8bbcca09
--- /dev/null
+++ b/contrib/lizard/examples/.gitignore
@@ -0,0 +1,8 @@
+/Makefile.liz*
+/printVersion
+/doubleBuffer
+/ringBuffer
+/ringBufferHC
+/lineCompress
+/frameCompress
+/*.exe
diff --git a/contrib/lizard/examples/HCStreaming_ringBuffer.c b/contrib/lizard/examples/HCStreaming_ringBuffer.c
new file mode 100644
index 00000000000..3e4d75a5d78
--- /dev/null
+++ b/contrib/lizard/examples/HCStreaming_ringBuffer.c
@@ -0,0 +1,241 @@
+// Lizard streaming API example : ring buffer
+// Based on previous work from Takayuki Matsuoka
+
+
+/**************************************
+ * Compiler Options
+ **************************************/
+#ifdef _MSC_VER /* Visual Studio */
+# define _CRT_SECURE_NO_WARNINGS // for MSVC
+# define snprintf sprintf_s
+#endif
+
+#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
+#endif
+
+
+/**************************************
+ * Includes
+ **************************************/
+#include "lizard_compress.h"
+#include "lizard_decompress.h"
+#include "lizard_common.h"
+
+#include
+#include
+#include
+#include
+
+enum {
+ MESSAGE_MAX_BYTES = 1024,
+ RING_BUFFER_BYTES = 1024 * 8 + MESSAGE_MAX_BYTES,
+ DEC_BUFFER_BYTES = RING_BUFFER_BYTES + MESSAGE_MAX_BYTES // Intentionally larger to test unsynchronized ring buffers
+};
+
+
+size_t write_int32(FILE* fp, int32_t i) {
+ return fwrite(&i, sizeof(i), 1, fp);
+}
+
+size_t write_bin(FILE* fp, const void* array, int arrayBytes) {
+ return fwrite(array, 1, arrayBytes, fp);
+}
+
+size_t read_int32(FILE* fp, int32_t* i) {
+ return fread(i, sizeof(*i), 1, fp);
+}
+
+size_t read_bin(FILE* fp, void* array, int arrayBytes) {
+ return fread(array, 1, arrayBytes, fp);
+}
+
+
+void test_compress(FILE* outFp, FILE* inpFp)
+{
+ Lizard_stream_t* lizardStream = Lizard_createStream(0);
+ static char inpBuf[RING_BUFFER_BYTES];
+ int inpOffset = 0;
+
+ if (!lizardStream) return;
+
+ for(;;)
+ {
+ // Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer.
+ char* const inpPtr = &inpBuf[inpOffset];
+ const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1;
+ const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength);
+ if (0 == inpBytes) break;
+
+ {
+ char cmpBuf[LIZARD_COMPRESSBOUND(MESSAGE_MAX_BYTES)];
+ const int cmpBytes = Lizard_compress_continue(lizardStream, inpPtr, cmpBuf, inpBytes, Lizard_compressBound(inpBytes));
+
+ if(cmpBytes <= 0) break;
+ write_int32(outFp, cmpBytes);
+ write_bin(outFp, cmpBuf, cmpBytes);
+
+ inpOffset += inpBytes;
+
+ // Wraparound the ringbuffer offset
+ if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES)
+ inpOffset = 0;
+ }
+ }
+
+ write_int32(outFp, 0);
+ Lizard_freeStream(lizardStream);
+}
+
+
+void test_decompress(FILE* outFp, FILE* inpFp)
+{
+ static char decBuf[DEC_BUFFER_BYTES];
+ int decOffset = 0;
+ Lizard_streamDecode_t lizardStreamDecode_body = { 0 };
+ Lizard_streamDecode_t* lizardStreamDecode = &lizardStreamDecode_body;
+
+ for(;;)
+ {
+ int cmpBytes = 0;
+ char cmpBuf[LIZARD_COMPRESSBOUND(MESSAGE_MAX_BYTES)];
+
+ {
+ const size_t r0 = read_int32(inpFp, &cmpBytes);
+ size_t r1;
+ if(r0 != 1 || cmpBytes <= 0)
+ break;
+
+ r1 = read_bin(inpFp, cmpBuf, cmpBytes);
+ if(r1 != (size_t) cmpBytes)
+ break;
+ }
+
+ {
+ char* const decPtr = &decBuf[decOffset];
+ const int decBytes = Lizard_decompress_safe_continue(
+ lizardStreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES);
+ if(decBytes <= 0)
+ break;
+
+ decOffset += decBytes;
+ write_bin(outFp, decPtr, decBytes);
+
+ // Wraparound the ringbuffer offset
+ if(decOffset >= DEC_BUFFER_BYTES - MESSAGE_MAX_BYTES)
+ decOffset = 0;
+ }
+ }
+}
+
+
+// Compare 2 files content
+// return 0 if identical
+// return ByteNb>0 if different
+size_t compare(FILE* f0, FILE* f1)
+{
+ size_t result = 1;
+
+ for (;;)
+ {
+ char b0[65536];
+ char b1[65536];
+ const size_t r0 = fread(b0, 1, sizeof(b0), f0);
+ const size_t r1 = fread(b1, 1, sizeof(b1), f1);
+
+ if ((r0==0) && (r1==0)) return 0; // success
+
+ if (r0 != r1)
+ {
+ size_t smallest = r0;
+ if (r1
+#include
+#include
+#include
+
+enum {
+ BLOCK_BYTES = 1024 * 8,
+// BLOCK_BYTES = 1024 * 64,
+};
+
+
+size_t write_int(FILE* fp, int i) {
+ return fwrite(&i, sizeof(i), 1, fp);
+}
+
+size_t write_bin(FILE* fp, const void* array, size_t arrayBytes) {
+ return fwrite(array, 1, arrayBytes, fp);
+}
+
+size_t read_int(FILE* fp, int* i) {
+ return fread(i, sizeof(*i), 1, fp);
+}
+
+size_t read_bin(FILE* fp, void* array, size_t arrayBytes) {
+ return fread(array, 1, arrayBytes, fp);
+}
+
+
+void test_compress(FILE* outFp, FILE* inpFp)
+{
+ Lizard_stream_t* lizardStream = Lizard_createStream_MinLevel();
+ char inpBuf[2][BLOCK_BYTES];
+ int inpBufIndex = 0;
+
+ if (!lizardStream) return;
+ lizardStream = Lizard_resetStream_MinLevel(lizardStream);
+ if (!lizardStream) return;
+
+ for(;;) {
+ char* const inpPtr = inpBuf[inpBufIndex];
+ const int inpBytes = (int) read_bin(inpFp, inpPtr, BLOCK_BYTES);
+ if(0 == inpBytes) {
+ break;
+ }
+
+ {
+ char cmpBuf[LIZARD_COMPRESSBOUND(BLOCK_BYTES)];
+ const int cmpBytes = Lizard_compress_continue(lizardStream, inpPtr, cmpBuf, inpBytes, sizeof(cmpBuf));
+ if(cmpBytes <= 0) {
+ break;
+ }
+ write_int(outFp, cmpBytes);
+ write_bin(outFp, cmpBuf, (size_t) cmpBytes);
+ }
+
+ inpBufIndex = (inpBufIndex + 1) % 2;
+ }
+
+ write_int(outFp, 0);
+ Lizard_freeStream(lizardStream);
+}
+
+
+void test_decompress(FILE* outFp, FILE* inpFp)
+{
+ Lizard_streamDecode_t lizardStreamDecode_body;
+ Lizard_streamDecode_t* lizardStreamDecode = &lizardStreamDecode_body;
+
+ char decBuf[2][BLOCK_BYTES];
+ int decBufIndex = 0;
+
+ Lizard_setStreamDecode(lizardStreamDecode, NULL, 0);
+
+ for(;;) {
+ char cmpBuf[LIZARD_COMPRESSBOUND(BLOCK_BYTES)];
+ int cmpBytes = 0;
+
+ {
+ const size_t readCount0 = read_int(inpFp, &cmpBytes);
+ if(readCount0 != 1 || cmpBytes <= 0) {
+ break;
+ }
+
+ const size_t readCount1 = read_bin(inpFp, cmpBuf, (size_t) cmpBytes);
+ if(readCount1 != (size_t) cmpBytes) {
+ break;
+ }
+ }
+
+ {
+ char* const decPtr = decBuf[decBufIndex];
+ const int decBytes = Lizard_decompress_safe_continue(
+ lizardStreamDecode, cmpBuf, decPtr, cmpBytes, BLOCK_BYTES);
+ if(decBytes <= 0) {
+ break;
+ }
+ write_bin(outFp, decPtr, (size_t) decBytes);
+ }
+
+ decBufIndex = (decBufIndex + 1) % 2;
+ }
+}
+
+
+int compare(FILE* fp0, FILE* fp1)
+{
+ int result = 0;
+
+ while(0 == result) {
+ char b0[65536];
+ char b1[65536];
+ const size_t r0 = read_bin(fp0, b0, sizeof(b0));
+ const size_t r1 = read_bin(fp1, b1, sizeof(b1));
+
+ result = (int) r0 - (int) r1;
+
+ if(0 == r0 || 0 == r1) {
+ break;
+ }
+ if(0 == result) {
+ result = memcmp(b0, b1, r0);
+ }
+ }
+
+ return result;
+}
+
+
+int main(int argc, char* argv[])
+{
+ char inpFilename[256] = { 0 };
+ char lizardFilename[256] = { 0 };
+ char decFilename[256] = { 0 };
+
+ if(argc < 2) {
+ printf("Please specify input filename\n");
+ return 0;
+ }
+
+ snprintf(inpFilename, 256, "%s", argv[1]);
+ snprintf(lizardFilename, 256, "%s.lizs-%d", argv[1], BLOCK_BYTES);
+ snprintf(decFilename, 256, "%s.lizs-%d.dec", argv[1], BLOCK_BYTES);
+
+ printf("inp = [%s]\n", inpFilename);
+ printf("lizard = [%s]\n", lizardFilename);
+ printf("dec = [%s]\n", decFilename);
+
+ // compress
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* outFp = fopen(lizardFilename, "wb");
+
+ printf("compress : %s -> %s\n", inpFilename, lizardFilename);
+ test_compress(outFp, inpFp);
+ printf("compress : done\n");
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // decompress
+ {
+ FILE* inpFp = fopen(lizardFilename, "rb");
+ FILE* outFp = fopen(decFilename, "wb");
+
+ printf("decompress : %s -> %s\n", lizardFilename, decFilename);
+ test_decompress(outFp, inpFp);
+ printf("decompress : done\n");
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // verify
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* decFp = fopen(decFilename, "rb");
+
+ printf("verify : %s <-> %s\n", inpFilename, decFilename);
+ const int cmp = compare(inpFp, decFp);
+ if(0 == cmp) {
+ printf("verify : OK\n");
+ } else {
+ printf("verify : NG\n");
+ }
+
+ fclose(decFp);
+ fclose(inpFp);
+ }
+
+ return 0;
+}
diff --git a/contrib/lizard/examples/blockStreaming_doubleBuffer.md b/contrib/lizard/examples/blockStreaming_doubleBuffer.md
new file mode 100644
index 00000000000..c27afcfb98c
--- /dev/null
+++ b/contrib/lizard/examples/blockStreaming_doubleBuffer.md
@@ -0,0 +1,100 @@
+# Lizard streaming API Example : Double Buffer
+by *Takayuki Matsuoka*
+
+`blockStreaming_doubleBuffer.c` is Lizard Straming API example which implements double buffer (de)compression.
+
+Please note :
+
+ - Firstly, read "Lizard Streaming API Basics".
+ - This is relatively advanced application example.
+ - Output file is not compatible with lizard_frame and platform dependent.
+
+
+## What's the point of this example ?
+
+ - Handle huge file in small amount of memory
+ - Always better compression ratio than Block API
+ - Uniform block size
+
+
+## How the compression works
+
+First of all, allocate "Double Buffer" for input and Lizard compressed data buffer for output.
+Double buffer has two pages, "first" page (Page#1) and "second" page (Page#2).
+
+```
+ Double Buffer
+
+ Page#1 Page#2
+ +---------+---------+
+ | Block#1 | |
+ +----+----+---------+
+ |
+ v
+ {Out#1}
+
+
+ Prefix Dependency
+ +---------+
+ | |
+ v |
+ +---------+----+----+
+ | Block#1 | Block#2 |
+ +---------+----+----+
+ |
+ v
+ {Out#2}
+
+
+ External Dictionary Mode
+ +---------+
+ | |
+ | v
+ +----+----+---------+
+ | Block#3 | Block#2 |
+ +----+----+---------+
+ |
+ v
+ {Out#3}
+
+
+ Prefix Dependency
+ +---------+
+ | |
+ v |
+ +---------+----+----+
+ | Block#3 | Block#4 |
+ +---------+----+----+
+ |
+ v
+ {Out#4}
+```
+
+Next, read first block to double buffer's first page. And compress it by `Lizard_compress_continue()`.
+For the first time, Lizard doesn't know any previous dependencies,
+so it just compress the line without dependencies and generates compressed block {Out#1} to Lizard compressed data buffer.
+After that, write {Out#1} to the file.
+
+Next, read second block to double buffer's second page. And compress it.
+In this time, Lizard can use dependency to Block#1 to improve compression ratio.
+This dependency is called "Prefix mode".
+
+Next, read third block to double buffer's *first* page. And compress it.
+Also this time, Lizard can use dependency to Block#2.
+This dependency is called "External Dictonaly mode".
+
+Continue these procedure to the end of the file.
+
+
+## How the decompression works
+
+Decompression will do reverse order.
+
+ - Read first compressed block.
+ - Decompress it to the first page and write that page to the file.
+ - Read second compressed block.
+ - Decompress it to the second page and write that page to the file.
+ - Read third compressed block.
+ - Decompress it to the *first* page and write that page to the file.
+
+Continue these procedure to the end of the compressed file.
diff --git a/contrib/lizard/examples/blockStreaming_lineByLine.c b/contrib/lizard/examples/blockStreaming_lineByLine.c
new file mode 100644
index 00000000000..9d239533501
--- /dev/null
+++ b/contrib/lizard/examples/blockStreaming_lineByLine.c
@@ -0,0 +1,210 @@
+// Lizard streaming API example : line-by-line logfile compression
+// Copyright : Takayuki Matsuoka
+
+
+#ifdef _MSC_VER /* Visual Studio */
+# define _CRT_SECURE_NO_WARNINGS
+# define snprintf sprintf_s
+#endif
+#include "lizard_common.h"
+#include "lizard_decompress.h"
+#include
+#include
+#include
+#include
+
+static size_t write_uint16(FILE* fp, uint16_t i)
+{
+ return fwrite(&i, sizeof(i), 1, fp);
+}
+
+static size_t write_bin(FILE* fp, const void* array, int arrayBytes)
+{
+ return fwrite(array, 1, arrayBytes, fp);
+}
+
+static size_t read_uint16(FILE* fp, uint16_t* i)
+{
+ return fread(i, sizeof(*i), 1, fp);
+}
+
+static size_t read_bin(FILE* fp, void* array, int arrayBytes)
+{
+ return fread(array, 1, arrayBytes, fp);
+}
+
+
+static void test_compress(
+ FILE* outFp,
+ FILE* inpFp,
+ size_t messageMaxBytes,
+ size_t ringBufferBytes)
+{
+ Lizard_stream_t* const lizardStream = Lizard_createStream_MinLevel();
+ const size_t cmpBufBytes = LIZARD_COMPRESSBOUND(messageMaxBytes);
+ char* const cmpBuf = (char*) malloc(cmpBufBytes);
+ char* const inpBuf = (char*) malloc(ringBufferBytes);
+ int inpOffset = 0;
+
+ for ( ; ; )
+ {
+ char* const inpPtr = &inpBuf[inpOffset];
+
+#if 0
+ // Read random length data to the ring buffer.
+ const int randomLength = (rand() % messageMaxBytes) + 1;
+ const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength);
+ if (0 == inpBytes) break;
+#else
+ // Read line to the ring buffer.
+ int inpBytes = 0;
+ if (!fgets(inpPtr, (int) messageMaxBytes, inpFp))
+ break;
+ inpBytes = (int) strlen(inpPtr);
+#endif
+
+ {
+ const int cmpBytes = Lizard_compress_continue(lizardStream, inpPtr, cmpBuf, inpBytes, cmpBufBytes);
+ if (cmpBytes <= 0) break;
+ write_uint16(outFp, (uint16_t) cmpBytes);
+ write_bin(outFp, cmpBuf, cmpBytes);
+
+ // Add and wraparound the ringbuffer offset
+ inpOffset += inpBytes;
+ if ((size_t)inpOffset >= ringBufferBytes - messageMaxBytes) inpOffset = 0;
+ }
+ }
+ write_uint16(outFp, 0);
+
+ free(inpBuf);
+ free(cmpBuf);
+ Lizard_freeStream(lizardStream);
+}
+
+
+static void test_decompress(
+ FILE* outFp,
+ FILE* inpFp,
+ size_t messageMaxBytes,
+ size_t ringBufferBytes)
+{
+ Lizard_streamDecode_t* const lizardStreamDecode = Lizard_createStreamDecode();
+ char* const cmpBuf = (char*) malloc(LIZARD_COMPRESSBOUND(messageMaxBytes));
+ char* const decBuf = (char*) malloc(ringBufferBytes);
+ int decOffset = 0;
+
+ for ( ; ; )
+ {
+ uint16_t cmpBytes = 0;
+
+ if (read_uint16(inpFp, &cmpBytes) != 1) break;
+ if (cmpBytes <= 0) break;
+ if (read_bin(inpFp, cmpBuf, cmpBytes) != cmpBytes) break;
+
+ {
+ char* const decPtr = &decBuf[decOffset];
+ const int decBytes = Lizard_decompress_safe_continue(
+ lizardStreamDecode, cmpBuf, decPtr, cmpBytes, (int) messageMaxBytes);
+ if (decBytes <= 0) break;
+ write_bin(outFp, decPtr, decBytes);
+
+ // Add and wraparound the ringbuffer offset
+ decOffset += decBytes;
+ if ((size_t)decOffset >= ringBufferBytes - messageMaxBytes) decOffset = 0;
+ }
+ }
+
+ free(decBuf);
+ free(cmpBuf);
+ Lizard_freeStreamDecode(lizardStreamDecode);
+}
+
+
+static int compare(FILE* f0, FILE* f1)
+{
+ int result = 0;
+ const size_t tempBufferBytes = 65536;
+ char* const b0 = (char*) malloc(tempBufferBytes);
+ char* const b1 = (char*) malloc(tempBufferBytes);
+
+ while(0 == result)
+ {
+ const size_t r0 = fread(b0, 1, tempBufferBytes, f0);
+ const size_t r1 = fread(b1, 1, tempBufferBytes, f1);
+
+ result = (int) r0 - (int) r1;
+
+ if (0 == r0 || 0 == r1) break;
+ if (0 == result) result = memcmp(b0, b1, r0);
+ }
+
+ free(b1);
+ free(b0);
+ return result;
+}
+
+
+int main(int argc, char* argv[])
+{
+ enum {
+ MESSAGE_MAX_BYTES = 1024,
+ RING_BUFFER_BYTES = 1024 * 256 + MESSAGE_MAX_BYTES,
+ };
+
+ char inpFilename[256] = { 0 };
+ char lizardFilename[256] = { 0 };
+ char decFilename[256] = { 0 };
+
+ if (argc < 2)
+ {
+ printf("Please specify input filename\n");
+ return 0;
+ }
+
+ snprintf(inpFilename, 256, "%s", argv[1]);
+ snprintf(lizardFilename, 256, "%s.lizs", argv[1]);
+ snprintf(decFilename, 256, "%s.lizs.dec", argv[1]);
+
+ printf("inp = [%s]\n", inpFilename);
+ printf("lizard = [%s]\n", lizardFilename);
+ printf("dec = [%s]\n", decFilename);
+
+ // compress
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* outFp = fopen(lizardFilename, "wb");
+
+ test_compress(outFp, inpFp, MESSAGE_MAX_BYTES, RING_BUFFER_BYTES);
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // decompress
+ {
+ FILE* inpFp = fopen(lizardFilename, "rb");
+ FILE* outFp = fopen(decFilename, "wb");
+
+ test_decompress(outFp, inpFp, MESSAGE_MAX_BYTES, RING_BUFFER_BYTES);
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // verify
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* decFp = fopen(decFilename, "rb");
+
+ const int cmp = compare(inpFp, decFp);
+ if (0 == cmp)
+ printf("Verify : OK\n");
+ else
+ printf("Verify : NG\n");
+
+ fclose(decFp);
+ fclose(inpFp);
+ }
+
+ return 0;
+}
diff --git a/contrib/lizard/examples/blockStreaming_lineByLine.md b/contrib/lizard/examples/blockStreaming_lineByLine.md
new file mode 100644
index 00000000000..ac56b879c90
--- /dev/null
+++ b/contrib/lizard/examples/blockStreaming_lineByLine.md
@@ -0,0 +1,122 @@
+# Lizard streaming API Example : Line by Line Text Compression
+by *Takayuki Matsuoka*
+
+`blockStreaming_lineByLine.c` is Lizard Straming API example which implements line by line incremental (de)compression.
+
+Please note the following restrictions :
+
+ - Firstly, read "Lizard Streaming API Basics".
+ - This is relatively advanced application example.
+ - Output file is not compatible with lizard_frame and platform dependent.
+
+
+## What's the point of this example ?
+
+ - Line by line incremental (de)compression.
+ - Handle huge file in small amount of memory
+ - Generally better compression ratio than Block API
+ - Non-uniform block size
+
+
+## How the compression works
+
+First of all, allocate "Ring Buffer" for input and Lizard compressed data buffer for output.
+
+```
+(1)
+ Ring Buffer
+
+ +--------+
+ | Line#1 |
+ +---+----+
+ |
+ v
+ {Out#1}
+
+
+(2)
+ Prefix Mode Dependency
+ +----+
+ | |
+ v |
+ +--------+-+------+
+ | Line#1 | Line#2 |
+ +--------+---+----+
+ |
+ v
+ {Out#2}
+
+
+(3)
+ Prefix Prefix
+ +----+ +----+
+ | | | |
+ v | v |
+ +--------+-+------+-+------+
+ | Line#1 | Line#2 | Line#3 |
+ +--------+--------+---+----+
+ |
+ v
+ {Out#3}
+
+
+(4)
+ External Dictionary Mode
+ +----+ +----+
+ | | | |
+ v | v |
+ ------+--------+-+------+-+--------+
+ | .... | Line#X | Line#X+1 |
+ ------+--------+--------+-----+----+
+ ^ |
+ | v
+ | {Out#X+1}
+ |
+ Reset
+
+
+(5)
+ Prefix
+ +-----+
+ | |
+ v |
+ ------+--------+--------+----------+--+-------+
+ | .... | Line#X | Line#X+1 | Line#X+2 |
+ ------+--------+--------+----------+-----+----+
+ ^ |
+ | v
+ | {Out#X+2}
+ |
+ Reset
+```
+
+Next (see (1)), read first line to ringbuffer and compress it by `Lizard_compress_continue()`.
+For the first time, Lizard doesn't know any previous dependencies,
+so it just compress the line without dependencies and generates compressed line {Out#1} to Lizard compressed data buffer.
+After that, write {Out#1} to the file and forward ringbuffer offset.
+
+Do the same things to second line (see (2)).
+But in this time, Lizard can use dependency to Line#1 to improve compression ratio.
+This dependency is called "Prefix mode".
+
+Eventually, we'll reach end of ringbuffer at Line#X (see (4)).
+This time, we should reset ringbuffer offset.
+After resetting, at Line#X+1 pointer is not adjacent, but Lizard still maintain its memory.
+This is called "External Dictionary Mode".
+
+In Line#X+2 (see (5)), finally Lizard forget almost all memories but still remains Line#X+1.
+This is the same situation as Line#2.
+
+Continue these procedure to the end of text file.
+
+
+## How the decompression works
+
+Decompression will do reverse order.
+
+ - Read compressed line from the file to buffer.
+ - Decompress it to the ringbuffer.
+ - Output decompressed plain text line to the file.
+ - Forward ringbuffer offset. If offset exceedes end of the ringbuffer, reset it.
+
+Continue these procedure to the end of the compressed file.
diff --git a/contrib/lizard/examples/blockStreaming_ringBuffer.c b/contrib/lizard/examples/blockStreaming_ringBuffer.c
new file mode 100644
index 00000000000..011cd8b665b
--- /dev/null
+++ b/contrib/lizard/examples/blockStreaming_ringBuffer.c
@@ -0,0 +1,202 @@
+// Lizard streaming API example : ring buffer
+// Based on sample code from Takayuki Matsuoka
+
+
+/**************************************
+ * Compiler Options
+ **************************************/
+#ifdef _MSC_VER /* Visual Studio */
+# define _CRT_SECURE_NO_WARNINGS // for MSVC
+# define snprintf sprintf_s
+#endif
+#ifdef __GNUC__
+# pragma GCC diagnostic ignored "-Wmissing-braces" /* GCC bug 53119 : doesn't accept { 0 } as initializer (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119) */
+#endif
+
+
+/**************************************
+ * Includes
+ **************************************/
+#include
+#include
+#include
+#include
+#include "lizard_common.h"
+#include "lizard_decompress.h"
+
+
+enum {
+ MESSAGE_MAX_BYTES = 1024,
+ RING_BUFFER_BYTES = 1024 * 8 + MESSAGE_MAX_BYTES,
+ DECODE_RING_BUFFER = RING_BUFFER_BYTES + MESSAGE_MAX_BYTES // Intentionally larger, to test unsynchronized ring buffers
+};
+
+
+size_t write_int32(FILE* fp, int32_t i) {
+ return fwrite(&i, sizeof(i), 1, fp);
+}
+
+size_t write_bin(FILE* fp, const void* array, int arrayBytes) {
+ return fwrite(array, 1, arrayBytes, fp);
+}
+
+size_t read_int32(FILE* fp, int32_t* i) {
+ return fread(i, sizeof(*i), 1, fp);
+}
+
+size_t read_bin(FILE* fp, void* array, int arrayBytes) {
+ return fread(array, 1, arrayBytes, fp);
+}
+
+
+void test_compress(FILE* outFp, FILE* inpFp)
+{
+ Lizard_stream_t* lizardStream = Lizard_createStream_MinLevel();
+ if (!lizardStream) return;
+
+ static char inpBuf[RING_BUFFER_BYTES];
+ int inpOffset = 0;
+
+ for(;;) {
+ // Read random length ([1,MESSAGE_MAX_BYTES]) data to the ring buffer.
+ char* const inpPtr = &inpBuf[inpOffset];
+ const int randomLength = (rand() % MESSAGE_MAX_BYTES) + 1;
+ const int inpBytes = (int) read_bin(inpFp, inpPtr, randomLength);
+ if (0 == inpBytes) break;
+
+ {
+ char cmpBuf[LIZARD_COMPRESSBOUND(MESSAGE_MAX_BYTES)];
+ const int cmpBytes = Lizard_compress_continue(lizardStream, inpPtr, cmpBuf, inpBytes, Lizard_compressBound(inpBytes));
+ if(cmpBytes <= 0) break;
+ write_int32(outFp, cmpBytes);
+ write_bin(outFp, cmpBuf, cmpBytes);
+
+ inpOffset += inpBytes;
+
+ // Wraparound the ringbuffer offset
+ if(inpOffset >= RING_BUFFER_BYTES - MESSAGE_MAX_BYTES) inpOffset = 0;
+ }
+ }
+
+ write_int32(outFp, 0);
+ Lizard_freeStream(lizardStream);
+}
+
+
+void test_decompress(FILE* outFp, FILE* inpFp)
+{
+ static char decBuf[DECODE_RING_BUFFER];
+ int decOffset = 0;
+ Lizard_streamDecode_t lizardStreamDecode_body = { 0 };
+ Lizard_streamDecode_t* lizardStreamDecode = &lizardStreamDecode_body;
+
+ for(;;) {
+ int cmpBytes = 0;
+ char cmpBuf[LIZARD_COMPRESSBOUND(MESSAGE_MAX_BYTES)];
+
+ {
+ const size_t r0 = read_int32(inpFp, &cmpBytes);
+ if(r0 != 1 || cmpBytes <= 0) break;
+
+ const size_t r1 = read_bin(inpFp, cmpBuf, cmpBytes);
+ if(r1 != (size_t) cmpBytes) break;
+ }
+
+ {
+ char* const decPtr = &decBuf[decOffset];
+ const int decBytes = Lizard_decompress_safe_continue(
+ lizardStreamDecode, cmpBuf, decPtr, cmpBytes, MESSAGE_MAX_BYTES);
+ if(decBytes <= 0) break;
+ decOffset += decBytes;
+ write_bin(outFp, decPtr, decBytes);
+
+ // Wraparound the ringbuffer offset
+ if(decOffset >= DECODE_RING_BUFFER - MESSAGE_MAX_BYTES) decOffset = 0;
+ }
+ }
+}
+
+
+int compare(FILE* f0, FILE* f1)
+{
+ int result = 0;
+
+ while(0 == result) {
+ char b0[65536];
+ char b1[65536];
+ const size_t r0 = fread(b0, 1, sizeof(b0), f0);
+ const size_t r1 = fread(b1, 1, sizeof(b1), f1);
+
+ result = (int) r0 - (int) r1;
+
+ if(0 == r0 || 0 == r1) {
+ break;
+ }
+ if(0 == result) {
+ result = memcmp(b0, b1, r0);
+ }
+ }
+
+ return result;
+}
+
+
+int main(int argc, char** argv)
+{
+ char inpFilename[256] = { 0 };
+ char lizardFilename[256] = { 0 };
+ char decFilename[256] = { 0 };
+
+ if(argc < 2) {
+ printf("Please specify input filename\n");
+ return 0;
+ }
+
+ snprintf(inpFilename, 256, "%s", argv[1]);
+ snprintf(lizardFilename, 256, "%s.lizs-%d", argv[1], 0);
+ snprintf(decFilename, 256, "%s.lizs-%d.dec", argv[1], 0);
+
+ printf("inp = [%s]\n", inpFilename);
+ printf("lizard = [%s]\n", lizardFilename);
+ printf("dec = [%s]\n", decFilename);
+
+ // compress
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* outFp = fopen(lizardFilename, "wb");
+
+ test_compress(outFp, inpFp);
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // decompress
+ {
+ FILE* inpFp = fopen(lizardFilename, "rb");
+ FILE* outFp = fopen(decFilename, "wb");
+
+ test_decompress(outFp, inpFp);
+
+ fclose(outFp);
+ fclose(inpFp);
+ }
+
+ // verify
+ {
+ FILE* inpFp = fopen(inpFilename, "rb");
+ FILE* decFp = fopen(decFilename, "rb");
+
+ const int cmp = compare(inpFp, decFp);
+ if(0 == cmp) {
+ printf("Verify : OK\n");
+ } else {
+ printf("Verify : NG\n");
+ }
+
+ fclose(decFp);
+ fclose(inpFp);
+ }
+
+ return 0;
+}
diff --git a/contrib/lizard/examples/compress_functions.c b/contrib/lizard/examples/compress_functions.c
new file mode 100644
index 00000000000..36bc40e691a
--- /dev/null
+++ b/contrib/lizard/examples/compress_functions.c
@@ -0,0 +1,303 @@
+/*
+ * compress_functions.c
+ * Copyright : Kyle Harper
+ * License : Follows same licensing as the lizard_compress.c/lizard_compress.h program at any given time. Currently, BSD 2.
+ * Description: A program to demonstrate the various compression functions involved in when using Lizard_compress_MinLevel(). The idea
+ * is to show how each step in the call stack can be used directly, if desired. There is also some benchmarking for
+ * each function to demonstrate the (probably lack of) performance difference when jumping the stack.
+ * (If you're new to lizard, please read simple_buffer.c to understand the fundamentals)
+ *
+ * The call stack (before theoretical compiler optimizations) for Lizard_compress_MinLevel is as follows:
+ * Lizard_compress_MinLevel
+ * Lizard_compress_fast
+ * Lizard_compress_extState_MinLevel
+ * Lizard_compress_generic
+ *
+ * Lizard_compress_MinLevel()
+ * This is the recommended function for compressing data. It will serve as the baseline for comparison.
+ * Lizard_compress_fast()
+ * Despite its name, it's not a "fast" version of compression. It simply decides if HEAPMODE is set and either
+ * allocates memory on the heap for a struct or creates the struct directly on the stack. Stack access is generally
+ * faster but this function itself isn't giving that advantage, it's just some logic for compile time.
+ * Lizard_compress_extState_MinLevel()
+ * This simply accepts all the pointers and values collected thus far and adds logic to determine how
+ * Lizard_compress_generic should be invoked; specifically: can the source fit into a single pass as determined by
+ * Lizard_64Klimit.
+ * Lizard_compress_generic()
+ * As the name suggests, this is the generic function that ultimately does most of the heavy lifting. Calling this
+ * directly can help avoid some test cases and branching which might be useful in some implementation-specific
+ * situations, but you really need to know what you're doing AND what you're asking lizard to do! You also need a
+ * wrapper function because this function isn't exposed with lizard_compress.h.
+ *
+ * The call stack for decompression functions is shallow. There are 2 options:
+ * Lizard_decompress_safe || Lizard_decompress_fast
+ * Lizard_decompress_generic
+ *
+ * Lizard_decompress_safe
+ * This is the recommended function for decompressing data. It is considered safe because the caller specifies
+ * both the size of the compresssed buffer to read as well as the maximum size of the output (decompressed) buffer
+ * instead of just the latter.
+ * Lizard_decompress_generic
+ * This is the generic function that both of the Lizard_decompress_* functions above end up calling. Calling this
+ * directly is not advised, period. Furthermore, it is a static inline function in lizard_compress.c, so there isn't a symbol
+ * exposed for anyone using lizard_compress.h to utilize.
+ *
+ * Special Note About Decompression:
+ * Using the Lizard_decompress_safe() function protects against malicious (user) input.
+ */
+
+/* Since lizard compiles with c99 and not gnu/std99 we need to enable POSIX linking for time.h structs and functions. */
+#if __STDC_VERSION__ >= 199901L
+#define _XOPEN_SOURCE 600
+#else
+#define _XOPEN_SOURCE 500
+#endif
+#define _POSIX_C_SOURCE 199309L
+
+/* Includes, for Power! */
+#include "lizard_compress.h"
+#include "lizard_decompress.h"
+#include /* for printf() */
+#include /* for exit() */
+#include /* for atoi() memcmp() */
+#include /* for uint_types */
+#include /* for PRIu64 */
+#include /* for clock_gettime() */
+#include /* for setlocale() */
+
+/* We need to know what one billion is for clock timing. */
+#define BILLION 1000000000L
+
+/* Create a crude set of test IDs so we can switch on them later (Can't switch() on a char[] or char*). */
+#define ID__LIZARD_COMPRESS_DEFAULT 1
+#define ID__LIZARD_COMPRESS_GENERIC 4
+#define ID__LIZARD_DECOMPRESS_SAFE 5
+
+
+
+/*
+ * Easy show-error-and-bail function.
+ */
+void run_screaming(const char *message, const int code) {
+ printf("%s\n", message);
+ exit(code);
+ return;
+}
+
+
+/*
+ * Centralize the usage function to keep main cleaner.
+ */
+void usage(const char *message) {
+ printf("Usage: ./argPerformanceTesting \n");
+ run_screaming(message, 1);
+ return;
+}
+
+
+
+/*
+ * Runs the benchmark for Lizard_compress_* based on function_id.
+ */
+uint64_t bench(
+ const char *known_good_dst,
+ const int function_id,
+ const int iterations,
+ const char *src,
+ char *dst,
+ const size_t src_size,
+ const size_t max_dst_size,
+ const size_t comp_size
+ ) {
+ uint64_t time_taken = 0;
+ int rv = 0;
+ const int warm_up = 5000;
+ struct timespec start, end;
+ Lizard_stream_t* state = Lizard_createStream_MinLevel();
+ if (!state) return;
+
+ // Select the right function to perform the benchmark on. We perform 5000 initial loops to warm the cache and ensure that dst
+ // remains matching to known_good_dst between successive calls.
+ switch(function_id) {
+ case ID__LIZARD_COMPRESS_DEFAULT:
+ printf("Starting benchmark for function: Lizard_compress_MinLevel()\n");
+ for(int junk=0; junk 1)
+ iterations = atoi(argv[1]);
+ if (iterations < 1)
+ usage("Argument 1 (iterations) must be > 0.");
+
+ // First we will create 2 sources (char *) of 2000 bytes each. One normal text, the other highly-compressible text.
+ const char *src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed luctus purus et risus vulputate, et mollis orci ullamcorper. Nulla facilisi. Fusce in ligula sed purus varius aliquet interdum vitae justo. Proin quis diam velit. Nulla varius iaculis auctor. Cras volutpat, justo eu dictum pulvinar, elit sem porttitor metus, et imperdiet metus sapien et ante. Nullam nisi nulla, ornare eu tristique eu, dignissim vitae diam. Nulla sagittis porta libero, a accumsan felis sagittis scelerisque. Integer laoreet eleifend congue. Etiam rhoncus leo vel dolor fermentum, quis luctus nisl iaculis. Praesent a erat sapien. Aliquam semper mi in lorem ultrices ultricies. Lorem ipsum dolor sit amet, consectetur adipiscing elit. In feugiat risus sed enim ultrices, at sodales nulla tristique. Maecenas eget pellentesque justo, sed pellentesque lectus. Fusce sagittis sit amet elit vel varius. Donec sed ligula nec ligula vulputate rutrum sed ut lectus. Etiam congue pharetra leo vitae cursus. Morbi enim ante, porttitor ut varius vel, tincidunt quis justo. Nunc iaculis, risus id ultrices semper, metus est efficitur ligula, vel posuere risus nunc eget purus. Ut lorem turpis, condimentum at sem sed, porta aliquam turpis. In ut sapien a nulla dictum tincidunt quis sit amet lorem. Fusce at est egestas, luctus neque eu, consectetur tortor. Phasellus eleifend ultricies nulla ac lobortis. Morbi maximus quam cursus vehicula iaculis. Maecenas cursus vel justo ut rutrum. Curabitur magna orci, dignissim eget dapibus vitae, finibus id lacus. Praesent rhoncus mattis augue vitae bibendum. Praesent porta mauris non ultrices fermentum. Quisque vulputate ipsum in sodales pulvinar. Aliquam nec mollis felis. Donec vitae augue pulvinar, congue nisl sed, pretium purus. Fusce lobortis mi ac neque scelerisque semper. Pellentesque vel est vitae magna aliquet aliquet. Nam non dolor. Nulla facilisi. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi ac lacinia felis metus.";
+ const char *hc_src = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
+ // Set and derive sizes. Since we're using strings, use strlen() + 1 for \0.
+ const size_t src_size = strlen(src) + 1;
+ const size_t max_dst_size = Lizard_compressBound(src_size);
+ int bytes_returned = 0;
+ // Now build allocations for the data we'll be playing with.
+ char *dst = calloc(1, max_dst_size);
+ char *known_good_dst = calloc(1, max_dst_size);
+ char *known_good_hc_dst = calloc(1, max_dst_size);
+ if (dst == NULL || known_good_dst == NULL || known_good_hc_dst == NULL)
+ run_screaming("Couldn't allocate memory for the destination buffers. Sad :(", 1);
+
+ // Create known-good buffers to verify our tests with other functions will produce the same results.
+ bytes_returned = Lizard_compress_MinLevel(src, known_good_dst, src_size, max_dst_size);
+ if (bytes_returned < 1)
+ run_screaming("Couldn't create a known-good destination buffer for comparison... this is bad.", 1);
+ const size_t src_comp_size = bytes_returned;
+ bytes_returned = Lizard_compress_MinLevel(hc_src, known_good_hc_dst, src_size, max_dst_size);
+ if (bytes_returned < 1)
+ run_screaming("Couldn't create a known-good (highly compressible) destination buffer for comparison... this is bad.", 1);
+ const size_t hc_src_comp_size = bytes_returned;
+
+
+ /* Lizard_compress_MinLevel() */
+ // This is the default function so we don't need to demonstrate how to use it. See basics.c if you need more basal information.
+
+ /* Lizard_compress_extState_MinLevel() */
+ // Using this function directly requires that we build an Lizard_stream_t struct ourselves. We do NOT have to reset it ourselves.
+ memset(dst, 0, max_dst_size);
+ Lizard_stream_t* state = Lizard_createStream_MinLevel();
+ if (!state) return;
+ bytes_returned = Lizard_compress_extState_MinLevel(state, src, dst, src_size, max_dst_size, 1);
+ if (bytes_returned < 1)
+ run_screaming("Failed to compress src using Lizard_compress_extState_MinLevel. echo $? for return code.", bytes_returned);
+ if (memcmp(dst, known_good_dst, bytes_returned) != 0)
+ run_screaming("According to memcmp(), the value we got in dst from Lizard_compress_extState_MinLevel doesn't match the known-good value. This is bad.", 1);
+
+ /* Lizard_compress_generic */
+ // When you can exactly control the inputs and options of your Lizard needs, you can use Lizard_compress_generic and fixed (const)
+ // values for the enum types such as dictionary and limitations. Any other direct-use is probably a bad idea.
+ //
+ // That said, the Lizard_compress_generic() function is 'static inline' and does not have a prototype in lizard_compress.h to expose a symbol
+ // for it. In other words: we can't access it directly. I don't want to submit a PR that modifies lizard_compress.c/h. Yann and others can
+ // do that if they feel it's worth expanding this example.
+ //
+ // I will, however, leave a skeleton of what would be required to use it directly:
+ /*
+ memset(dst, 0, max_dst_size);
+ // Lizard_stream_t state: is already declared above. We can reuse it BUT we have to reset the stream ourselves between each call.
+ Lizard_resetStream_MinLevel((Lizard_stream_t *)state);
+ // Since src size is small we know the following enums will be used: notLimited (0), byU16 (2), noDict (0), noDictIssue (0).
+ bytes_returned = Lizard_compress_generic(state, src, dst, src_size, max_dst_size, notLimited, byU16, noDict, noDictIssue, 1);
+ if (bytes_returned < 1)
+ run_screaming("Failed to compress src using Lizard_compress_generic. echo $? for return code.", bytes_returned);
+ if (memcmp(dst, known_good_dst, bytes_returned) != 0)
+ run_screaming("According to memcmp(), the value we got in dst from Lizard_compress_generic doesn't match the known-good value. This is bad.", 1);
+ */
+ Lizard_freeStream(state);
+
+
+ /* Benchmarking */
+ /* Now we'll run a few rudimentary benchmarks with each function to demonstrate differences in speed based on the function used.
+ * Remember, we cannot call Lizard_compress_generic() directly (yet) so it's disabled.
+ */
+ // Suite A - Normal Compressibility
+ char *dst_d = calloc(1, src_size);
+ memset(dst, 0, max_dst_size);
+ printf("\nStarting suite A: Normal compressible text.\n");
+ uint64_t time_taken__default = bench(known_good_dst, ID__LIZARD_COMPRESS_DEFAULT, iterations, src, dst, src_size, max_dst_size, src_comp_size);
+ //uint64_t time_taken__generic = bench(known_good_dst, ID__LIZARD_COMPRESS_GENERIC, iterations, src, dst, src_size, max_dst_size, src_comp_size);
+ uint64_t time_taken__decomp_safe = bench(src, ID__LIZARD_DECOMPRESS_SAFE, iterations, known_good_dst, dst_d, src_size, max_dst_size, src_comp_size);
+ // Suite B - Highly Compressible
+ memset(dst, 0, max_dst_size);
+ printf("\nStarting suite B: Highly compressible text.\n");
+ uint64_t time_taken_hc__default = bench(known_good_hc_dst, ID__LIZARD_COMPRESS_DEFAULT, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size);
+ //uint64_t time_taken_hc__generic = bench(known_good_hc_dst, ID__LIZARD_COMPRESS_GENERIC, iterations, hc_src, dst, src_size, max_dst_size, hc_src_comp_size);
+ uint64_t time_taken_hc__decomp_safe = bench(hc_src, ID__LIZARD_DECOMPRESS_SAFE, iterations, known_good_hc_dst, dst_d, src_size, max_dst_size, hc_src_comp_size);
+
+ // Report and leave.
+ setlocale(LC_ALL, "");
+ const char *format = "|%-14s|%-30s|%'14.9f|%'16d|%'14d|%'13.2f%%|\n";
+ const char *header_format = "|%-14s|%-30s|%14s|%16s|%14s|%14s|\n";
+ const char *separator = "+--------------+------------------------------+--------------+----------------+--------------+--------------+\n";
+ printf("\n");
+ printf("%s", separator);
+ printf(header_format, "Source", "Function Benchmarked", "Total Seconds", "Iterations/sec", "ns/Iteration", "% of default");
+ printf("%s", separator);
+ printf(format, "Normal Text", "Lizard_compress_MinLevel()", (double)time_taken__default / BILLION, (int)(iterations / ((double)time_taken__default /BILLION)), time_taken__default / iterations, (double)time_taken__default * 100 / time_taken__default);
+ printf(format, "Normal Text", "Lizard_compress_fast()", (double)time_taken__fast / BILLION, (int)(iterations / ((double)time_taken__fast /BILLION)), time_taken__fast / iterations, (double)time_taken__fast * 100 / time_taken__default);
+ printf(format, "Normal Text", "Lizard_compress_extState_MinLevel()", (double)time_taken__fast_extstate / BILLION, (int)(iterations / ((double)time_taken__fast_extstate /BILLION)), time_taken__fast_extstate / iterations, (double)time_taken__fast_extstate * 100 / time_taken__default);
+ //printf(format, "Normal Text", "Lizard_compress_generic()", (double)time_taken__generic / BILLION, (int)(iterations / ((double)time_taken__generic /BILLION)), time_taken__generic / iterations, (double)time_taken__generic * 100 / time_taken__default);
+ printf(format, "Normal Text", "Lizard_decompress_safe()", (double)time_taken__decomp_safe / BILLION, (int)(iterations / ((double)time_taken__decomp_safe /BILLION)), time_taken__decomp_safe / iterations, (double)time_taken__decomp_safe * 100 / time_taken__default);
+ printf(header_format, "", "", "", "", "", "");
+ printf(format, "Compressible", "Lizard_compress_MinLevel()", (double)time_taken_hc__default / BILLION, (int)(iterations / ((double)time_taken_hc__default /BILLION)), time_taken_hc__default / iterations, (double)time_taken_hc__default * 100 / time_taken_hc__default);
+ printf(format, "Compressible", "Lizard_compress_fast()", (double)time_taken_hc__fast / BILLION, (int)(iterations / ((double)time_taken_hc__fast /BILLION)), time_taken_hc__fast / iterations, (double)time_taken_hc__fast * 100 / time_taken_hc__default);
+ printf(format, "Compressible", "Lizard_compress_extState_MinLevel()", (double)time_taken_hc__fast_extstate / BILLION, (int)(iterations / ((double)time_taken_hc__fast_extstate /BILLION)), time_taken_hc__fast_extstate / iterations, (double)time_taken_hc__fast_extstate * 100 / time_taken_hc__default);
+ //printf(format, "Compressible", "Lizard_compress_generic()", (double)time_taken_hc__generic / BILLION, (int)(iterations / ((double)time_taken_hc__generic /BILLION)), time_taken_hc__generic / iterations, (double)time_taken_hc__generic * 100 / time_taken_hc__default);
+ printf(format, "Compressible", "Lizard_decompress_safe()", (double)time_taken_hc__decomp_safe / BILLION, (int)(iterations / ((double)time_taken_hc__decomp_safe /BILLION)), time_taken_hc__decomp_safe / iterations, (double)time_taken_hc__decomp_safe * 100 / time_taken_hc__default);
+ printf("%s", separator);
+ printf("\n");
+ printf("All done, ran %d iterations per test.\n", iterations);
+ return 0;
+}
diff --git a/contrib/lizard/examples/frameCompress.c b/contrib/lizard/examples/frameCompress.c
new file mode 100644
index 00000000000..37ea0aa4fa8
--- /dev/null
+++ b/contrib/lizard/examples/frameCompress.c
@@ -0,0 +1,169 @@
+// Lizardframe API example : compress a file
+// Based on sample code from Zbigniew Jędrzejewski-Szmek
+
+#include
+#include
+#include
+#include
+
+#include
+
+#define BUF_SIZE (16*1024)
+#define LIZARD_HEADER_SIZE 19
+#define LIZARD_FOOTER_SIZE 4
+
+static const LizardF_preferences_t lizard_preferences = {
+ { LizardF_max256KB, LizardF_blockLinked, LizardF_noContentChecksum, LizardF_frame, 0, { 0, 0 } },
+ 0, /* compression level */
+ 0, /* autoflush */
+ { 0, 0, 0, 0 }, /* reserved, must be set to 0 */
+};
+
+static int compress_file(FILE *in, FILE *out, size_t *size_in, size_t *size_out) {
+ LizardF_errorCode_t r;
+ LizardF_compressionContext_t ctx;
+ char *src, *buf = NULL;
+ size_t size, n, k, count_in = 0, count_out, offset = 0, frame_size;
+
+ r = LizardF_createCompressionContext(&ctx, LIZARDF_VERSION);
+ if (LizardF_isError(r)) {
+ printf("Failed to create context: error %zu", r);
+ return 1;
+ }
+ r = 1;
+
+ src = malloc(BUF_SIZE);
+ if (!src) {
+ printf("Not enough memory");
+ goto cleanup;
+ }
+
+ frame_size = LizardF_compressBound(BUF_SIZE, &lizard_preferences);
+ size = frame_size + LIZARD_HEADER_SIZE + LIZARD_FOOTER_SIZE;
+ buf = malloc(size);
+ if (!buf) {
+ printf("Not enough memory");
+ goto cleanup;
+ }
+
+ n = offset = count_out = LizardF_compressBegin(ctx, buf, size, &lizard_preferences);
+ if (LizardF_isError(n)) {
+ printf("Failed to start compression: error %zu", n);
+ goto cleanup;
+ }
+
+ printf("Buffer size is %zu bytes, header size %zu bytes\n", size, n);
+
+ for (;;) {
+ k = fread(src, 1, BUF_SIZE, in);
+ if (k == 0)
+ break;
+ count_in += k;
+
+ n = LizardF_compressUpdate(ctx, buf + offset, size - offset, src, k, NULL);
+ if (LizardF_isError(n)) {
+ printf("Compression failed: error %zu", n);
+ goto cleanup;
+ }
+
+ offset += n;
+ count_out += n;
+ if (size - offset < frame_size + LIZARD_FOOTER_SIZE) {
+ printf("Writing %zu bytes\n", offset);
+
+ k = fwrite(buf, 1, offset, out);
+ if (k < offset) {
+ if (ferror(out))
+ printf("Write failed");
+ else
+ printf("Short write");
+ goto cleanup;
+ }
+
+ offset = 0;
+ }
+ }
+
+ n = LizardF_compressEnd(ctx, buf + offset, size - offset, NULL);
+ if (LizardF_isError(n)) {
+ printf("Failed to end compression: error %zu", n);
+ goto cleanup;
+ }
+
+ offset += n;
+ count_out += n;
+ printf("Writing %zu bytes\n", offset);
+
+ k = fwrite(buf, 1, offset, out);
+ if (k < offset) {
+ if (ferror(out))
+ printf("Write failed");
+ else
+ printf("Short write");
+ goto cleanup;
+ }
+
+ *size_in = count_in;
+ *size_out = count_out;
+ r = 0;
+ cleanup:
+ if (ctx)
+ LizardF_freeCompressionContext(ctx);
+ free(src);
+ free(buf);
+ return r;
+}
+
+static int compress(const char *input, const char *output) {
+ char *tmp = NULL;
+ FILE *in = NULL, *out = NULL;
+ size_t size_in = 0, size_out = 0;
+ int r = 1;
+
+ if (!output) {
+ size_t len = strlen(input);
+
+ output = tmp = malloc(len + 5);
+ if (!tmp) {
+ printf("Not enough memory");
+ return 1;
+ }
+ strcpy(tmp, input);
+ strcpy(tmp + len, ".liz");
+ }
+
+ in = fopen(input, "rb");
+ if (!in) {
+ fprintf(stderr, "Failed to open input file %s: %s\n", input, strerror(errno));
+ goto cleanup;
+ }
+
+ out = fopen(output, "wb");
+ if (!out) {
+ fprintf(stderr, "Failed to open output file %s: %s\n", output, strerror(errno));
+ goto cleanup;
+ }
+
+ r = compress_file(in, out, &size_in, &size_out);
+ if (r == 0)
+ printf("%s: %zu → %zu bytes, %.1f%%\n",
+ input, size_in, size_out,
+ (double)size_out / size_in * 100);
+ cleanup:
+ if (in)
+ fclose(in);
+ if (out)
+ fclose(out);
+ free(tmp);
+ return r;
+}
+
+
+int main(int argc, char **argv) {
+ if (argc < 2 || argc > 3) {
+ fprintf(stderr, "Syntax: %s